netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* What's new in wireless-dev?
@ 2006-06-15 21:10 John W. Linville
  0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-06-15 21:10 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: text/plain, Size: 3196 bytes --]

The following changes since commit bff7c0afa5a40acf518ae9fbf67e5f93ff9107bc:
  John W. Linville:
        Merge branch 'from-linus'

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git

Jiri Benc:
      d80211: deinit sysfs in case of an error
      d80211: better sysfs registration of symlinks to wiphy
      d80211: separate allocation of ieee80211_local
      d80211: fix Oops when writing to add_ and remove_iface
      d80211: wiphy sysfs attributes
      d80211: network interface sysfs attributes
      d80211: rename sta_info_relase to sta_info_put
      d80211: sysfs attributes for associated stations
      d80211: remove useless parameters
      d80211: rate_control sysfs attributes
      d80211: encryption keys sysfs attributes
      d80211: remove procfs files

John W. Linville:
      Merge git://git.kernel.org/.../jbenc/dscape

Michael Buesch:
      bcm43xx: Port new locking scheme to d80211
      bcm43xx: Port preemptible-periodic-work to d80211
      bcm43xx: Port suspend-mac-in-long-pwork from d80211
      bcm43xx: Port PIO fixes to d80211

 drivers/net/wireless/d80211/bcm43xx/bcm43xx.h      |  102 ++-
 .../net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c  |   33 +
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.h  |    8 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c |    4 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c |  287 +++++--
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c  |    9 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c  |  154 +++-
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.h  |   32 +
 .../net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c    |   38 -
 include/linux/netdevice.h                          |    1 
 net/d80211/Makefile                                |    2 
 net/d80211/ieee80211.c                             |  206 +++--
 net/d80211/ieee80211_dev.c                         |   17 
 net/d80211/ieee80211_i.h                           |   45 +
 net/d80211/ieee80211_iface.c                       |   43 +
 net/d80211/ieee80211_ioctl.c                       |  213 +++---
 net/d80211/ieee80211_key.h                         |    2 
 net/d80211/ieee80211_proc.c                        |  771 --------------------
 net/d80211/ieee80211_proc.h                        |   45 -
 net/d80211/ieee80211_scan.c                        |   10 
 net/d80211/ieee80211_sta.c                         |   68 +-
 net/d80211/ieee80211_sysfs.c                       |  706 +++++++++++++++++-
 net/d80211/ieee80211_sysfs_sta.c                   |  434 +++++++++++
 net/d80211/rate_control.c                          |   55 +
 net/d80211/rate_control.h                          |   57 +
 net/d80211/sta_info.c                              |  132 ++-
 net/d80211/sta_info.h                              |   16 
 net/d80211/wme.c                                   |   26 -
 28 files changed, 2110 insertions(+), 1406 deletions(-)
 delete mode 100644 net/d80211/ieee80211_proc.c
 delete mode 100644 net/d80211/ieee80211_proc.h
 create mode 100644 net/d80211/ieee80211_sysfs_sta.c

Patch included as attachment due to size concerns.
-- 
John W. Linville
linville@tuxdriver.com

[-- Attachment #2: wireless-dev.patch.bz2 --]
[-- Type: application/x-bzip2, Size: 33583 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* What's new in wireless-dev?
@ 2006-07-11 20:45 John W. Linville
  2006-07-12  9:48 ` Jiri Benc
  0 siblings, 1 reply; 11+ messages in thread
From: John W. Linville @ 2006-07-11 20:45 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: text/plain, Size: 3344 bytes --]

I apologize for the delay.  Between the 2.6.18 merge window and things
heating up at the paying job, I've been a bit behind.

Along w/ pulling some updates from Jiri and some random bug fixes,
this includes the new d80211-based adm8211 driver from Michael Wu.
I'm sure he would love for anyone equipped with that hardware to beat
the crap out of his driver. :-)

Happy hacking!

John

---

The following changes since commit 46226c37e4764103719005eb363b3bc53216caea:
  John W. Linville:
        Merge branch 'from-linus'

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git

Alexander Tsvyashchenko:
      bcm43xx-d80211: AccessPoint mode related fixes

Gertjan van Wingerde:
      d80211: Take lowlevel driver's channel change time into account during scanning.

Ivo van Doorn:
      rt2x00: per-queue TX flow control

Jiri Benc:
      d80211: update tx.skb after TX handler calls
      d80211: per-queue TX flow control
      d80211: handle full queue when sending fragments
      d80211: add first_fragment flag to ieee80211_tx_control
      bcm43xx-d80211: fix sending of fragments
      bcm43xx-d80211: per-queue TX flow control

John W. Linville:
      Merge branch 'master' of git://git.kernel.org/.../jbenc/dscape
      d80211: use netif_tx_lock API
      bcm43xx-d80211: fixup UTS_RELEASE build break

Michael Buesch:
      d80211: allow NULL for control in beacon_get
      bcm43xx-d80211: fix mac_suspend refcount

Michael Wu:
      add adm8211 driver

 drivers/net/wireless/d80211/Kconfig                |    1 
 drivers/net/wireless/d80211/Makefile               |    1 
 drivers/net/wireless/d80211/adm8211/Kconfig        |   24 
 drivers/net/wireless/d80211/adm8211/Makefile       |    1 
 drivers/net/wireless/d80211/adm8211/adm8211.c      | 2202 ++++++++++++++++++++
 drivers/net/wireless/d80211/adm8211/adm8211.h      |  631 ++++++
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c  |    8 
 .../net/wireless/d80211/bcm43xx/bcm43xx_ethtool.c  |    1 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c |  482 +++-
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h |   24 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c  |    2 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c |   18 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.h |    3 
 drivers/net/wireless/d80211/rt2x00/rt2400pci.c     |   41 
 drivers/net/wireless/d80211/rt2x00/rt2500pci.c     |   41 
 drivers/net/wireless/d80211/rt2x00/rt2500usb.c     |   40 
 drivers/net/wireless/d80211/rt2x00/rt61pci.c       |   41 
 drivers/net/wireless/d80211/rt2x00/rt73usb.c       |   40 
 include/net/d80211.h                               |   32 
 net/d80211/ieee80211.c                             |  293 ++-
 net/d80211/ieee80211_i.h                           |   20 
 net/d80211/ieee80211_sta.c                         |    4 
 net/d80211/wme.c                                   |    9 
 23 files changed, 3723 insertions(+), 236 deletions(-)
 create mode 100644 drivers/net/wireless/d80211/adm8211/Kconfig
 create mode 100644 drivers/net/wireless/d80211/adm8211/Makefile
 create mode 100644 drivers/net/wireless/d80211/adm8211/adm8211.c
 create mode 100644 drivers/net/wireless/d80211/adm8211/adm8211.h

Full diff attached as wireless-dev.patch.bz2

-- 
John W. Linville
linville@tuxdriver.com

[-- Attachment #2: wireless-dev.patch.bz2 --]
[-- Type: application/x-bzip2, Size: 30407 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: What's new in wireless-dev?
  2006-07-11 20:45 John W. Linville
@ 2006-07-12  9:48 ` Jiri Benc
  2006-07-12 12:48   ` John W. Linville
  0 siblings, 1 reply; 11+ messages in thread
From: Jiri Benc @ 2006-07-12  9:48 UTC (permalink / raw)
  To: John W. Linville; +Cc: netdev

On Tue, 11 Jul 2006 16:45:58 -0400, John W. Linville wrote:
> John W. Linville:
>       d80211: use netif_tx_lock API

> --- a/net/d80211/ieee80211.c
> +++ b/net/d80211/ieee80211.c
> @@ -1338,7 +1338,7 @@ static void ieee80211_tx_pending(unsigne
>  	struct ieee80211_txrx_data tx;
>  	int i, ret, reschedule = 0;
>  
> -	spin_lock_bh(&dev->xmit_lock);
> +	netif_tx_lock_bh(dev);
>  	dev->xmit_lock_owner = smp_processor_id();

Those dev->xmit_lock_owner assignments are done in netif_tx_[un]lock_bh,
so they should go away as well.

 Jiri

-- 
Jiri Benc
SUSE Labs

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: What's new in wireless-dev?
  2006-07-12  9:48 ` Jiri Benc
@ 2006-07-12 12:48   ` John W. Linville
  2006-07-13  2:30     ` John W. Linville
  0 siblings, 1 reply; 11+ messages in thread
From: John W. Linville @ 2006-07-12 12:48 UTC (permalink / raw)
  To: Jiri Benc; +Cc: netdev

On Wed, Jul 12, 2006 at 11:48:32AM +0200, Jiri Benc wrote:
> On Tue, 11 Jul 2006 16:45:58 -0400, John W. Linville wrote:
> > John W. Linville:
> >       d80211: use netif_tx_lock API
> 
> > --- a/net/d80211/ieee80211.c
> > +++ b/net/d80211/ieee80211.c
> > @@ -1338,7 +1338,7 @@ static void ieee80211_tx_pending(unsigne
> >  	struct ieee80211_txrx_data tx;
> >  	int i, ret, reschedule = 0;
> >  
> > -	spin_lock_bh(&dev->xmit_lock);
> > +	netif_tx_lock_bh(dev);
> >  	dev->xmit_lock_owner = smp_processor_id();
> 
> Those dev->xmit_lock_owner assignments are done in netif_tx_[un]lock_bh,
> so they should go away as well.

Doh!  I missed that...thanks for the heads-up!

John
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: What's new in wireless-dev?
  2006-07-12 12:48   ` John W. Linville
@ 2006-07-13  2:30     ` John W. Linville
  0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-07-13  2:30 UTC (permalink / raw)
  To: Jiri Benc; +Cc: netdev

On Wed, Jul 12, 2006 at 08:48:32AM -0400, John W. Linville wrote:
> On Wed, Jul 12, 2006 at 11:48:32AM +0200, Jiri Benc wrote:
> > On Tue, 11 Jul 2006 16:45:58 -0400, John W. Linville wrote:
> > > John W. Linville:
> > >       d80211: use netif_tx_lock API
> > 
> > > --- a/net/d80211/ieee80211.c
> > > +++ b/net/d80211/ieee80211.c
> > > @@ -1338,7 +1338,7 @@ static void ieee80211_tx_pending(unsigne
> > >  	struct ieee80211_txrx_data tx;
> > >  	int i, ret, reschedule = 0;
> > >  
> > > -	spin_lock_bh(&dev->xmit_lock);
> > > +	netif_tx_lock_bh(dev);
> > >  	dev->xmit_lock_owner = smp_processor_id();
> > 
> > Those dev->xmit_lock_owner assignments are done in netif_tx_[un]lock_bh,
> > so they should go away as well.
> 
> Doh!  I missed that...thanks for the heads-up!

[PATCH] d80211: remove referencess to xmit_lock_owner

Clean-up sloppy attempt at moving to netif_tx_lock API.  When using that
API, direct manipulation of xmit_lock_owner is unnecessary and
inappropriate.

Signed-off-by: John W. Linville <linville@tuxdriver.com>

---

 net/d80211/ieee80211.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

a5b83f260b3cbe9ed161313e620c66b76e0218cf
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 542fec9..7ceef10 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1339,7 +1339,6 @@ static void ieee80211_tx_pending(unsigne
 	int i, ret, reschedule = 0;
 
 	netif_tx_lock_bh(dev);
-	dev->xmit_lock_owner = smp_processor_id();
 	for (i = 0; i < local->hw->queues; i++) {
 		if (__ieee80211_queue_stopped(local, i))
 			continue;
@@ -1364,7 +1363,6 @@ static void ieee80211_tx_pending(unsigne
 			reschedule = 1;
 		}
 	}
-	dev->xmit_lock_owner = -1;
 	netif_tx_unlock_bh(dev);
 	if (reschedule)
 		netif_schedule(dev);
-- 
1.3.1

-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* What's new in wireless-dev?
@ 2006-07-30  1:30 John W. Linville
  0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-07-30  1:30 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: text/plain, Size: 1649 bytes --]

Lots of patches lately, and I got a bit behind w/ travel to Ottawa
and some "real job" stuff too... :-(

I've still got a bunch of rt2x00 patches from Ivo, and a few other
patches as well.  Coming soon...

John

---

The following changes since commit 44ba187488edb4e567a0163d334f2bc0318dc392:
  John W. Linville:
        Merge branch 'from-linus'

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git

Ivo van Doorn:
      rt2x00 makefile

Jiri Benc:
      d80211: do not receive through master interface when not scanning
      d80211: host_gen_beacon_template flag
      d80211: better deallocation of mdev
      d80211: fix receiving through virtual interfaces
      d80211: fix defragmentation
      d80211: optimize defragmentation
      d80211: SET_NETDEV_DEV for non-master devices
      bcm43xx-d80211: use host_gen_beacon_template
      bcm43xx-d80211: use SET_NETDEV_DEV

John W. Linville:
      Merge branch 'up' of git://git.kernel.org/.../jbenc/dscape
      Merge branch 'bcm43xx' of git://git.kernel.org/.../jbenc/dscape

Larry Finger:
      bcm43xx: remove unused routines

Michael Buesch:
      bcm43xx-d80211: Lower mac_suspend timeout
      bcm43xx-d80211: opencoded locking
      bcm43xx-d80211: init routine rewrite

Michael Wu:
      d80211: Replace rc4 code with crypto api arc4
      d80211: Add sparse bitwise annotations
      adm8211: Properly initialize priv->mode in adm8211_probe
      adm8211: Restore frame header after TX
      adm8211: Add MAINTAINERS entry

Consolidate patch attached as wireless-dev.patch.bz2.
-- 
John W. Linville
linville@tuxdriver.com

[-- Attachment #2: wireless-dev.patch.bz2 --]
[-- Type: application/x-bzip2, Size: 31657 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* What's new in wireless-dev?
@ 2006-08-08 23:41 John W. Linville
  0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-08-08 23:41 UTC (permalink / raw)
  To: netdev

The following changes since commit d2970f6c700f2291c1a80b061ebcd6041d2f3f1e:
  John W. Linville:
        Merge branch 'from-linus'

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git

Ivo van Doorn:
      rt2x00 - pci request/release regions
      rt2x00 - ieee80211_hw->config no longer requires scheduling
      rt2x00 - optimize MAC reading & initialize perm_addr
      rt2x00 - txpower limits
      rt2x00 - misc fixes
      rt2x00 - scan handlers
      rfkill - Add rfkill driver to misc input devices
      rfkill - rt2x00 should use rfkill

Jiri Benc:
      d80211: fix wrong logical operations
      d80211: more correct WE support on master interface

Jouni Malinen:
      d80211: Fix RTS threshold use
      d80211: Fix PS-Poll frame dropping
      d80211: Fix PLCP header length comment
      d80211: Send Layer 2 Update frames in kernel
      d80211: Fix ieee80211_remove_tx_extra() if key not configured
      d80211: Fix TKIP replay protection

Michael Wu:
      d80211: Fix issues with QOS bitwise ops
      adm8211: Use ieee80211_*_queue functions
      d80211 drivers: Use IRQF_SHARED instead of SA_SHIRQ

 drivers/input/misc/Kconfig                         |   15 +
 drivers/input/misc/Makefile                        |    1 
 drivers/input/misc/rfkill.c                        |  210 ++++++++++++++++++++
 drivers/net/wireless/d80211/adm8211/adm8211.c      |   18 +-
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c |    2 
 drivers/net/wireless/d80211/rt2x00/Kconfig         |   24 +-
 drivers/net/wireless/d80211/rt2x00/rt2400pci.c     |  193 +++++++++---------
 drivers/net/wireless/d80211/rt2x00/rt2400pci.h     |    4 
 drivers/net/wireless/d80211/rt2x00/rt2500pci.c     |  197 ++++++++++---------
 drivers/net/wireless/d80211/rt2x00/rt2500pci.h     |    4 
 drivers/net/wireless/d80211/rt2x00/rt2500usb.c     |   99 +++------
 drivers/net/wireless/d80211/rt2x00/rt2500usb.h     |    4 
 drivers/net/wireless/d80211/rt2x00/rt2x00.h        |   62 +++++-
 drivers/net/wireless/d80211/rt2x00/rt2x00pci.h     |  111 -----------
 drivers/net/wireless/d80211/rt2x00/rt61pci.c       |  200 +++++++++----------
 drivers/net/wireless/d80211/rt2x00/rt61pci.h       |    4 
 drivers/net/wireless/d80211/rt2x00/rt73usb.c       |   92 +++------
 drivers/net/wireless/d80211/rt2x00/rt73usb.h       |    4 
 include/linux/input.h                              |    1 
 include/linux/rfkill.h                             |   98 +++++++++
 net/d80211/ieee80211.c                             |   26 +-
 net/d80211/ieee80211_i.h                           |    1 
 net/d80211/ieee80211_ioctl.c                       |   87 ++++++++
 net/d80211/tkip.c                                  |    1 
 net/d80211/wme.c                                   |    4 
 net/d80211/wpa.c                                   |    2 
 26 files changed, 868 insertions(+), 596 deletions(-)
 create mode 100644 drivers/input/misc/rfkill.c
 create mode 100644 include/linux/rfkill.h

diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index a6dfc74..ac10c02 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -79,4 +79,19 @@ config HP_SDC_RTC
 	  Say Y here if you want to support the built-in real time clock
 	  of the HP SDC controller.
 
+config RFKILL
+	tristate "RF button support"
+	help
+	  If you say yes here, the rfkill driver will be build
+	  which allowed network devices to register their hardware
+	  RF button which controls the radio state. This driver
+	  will then create an input device for it.
+
+	  When the input device is not used, the rfkill driver
+	  will make sure that when the RF button is pressed the radio
+	  is enabled or disabled accordingly. When the input device
+	  has been opened by the user this radio control will be left
+	  to the user, and rfkill will only send the RF button status
+	  change to userspace.
+
 endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 415c491..e788a1b 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
+obj-$(CONFIG_RFKILL)			+= rfkill.o
diff --git a/drivers/input/misc/rfkill.c b/drivers/input/misc/rfkill.c
new file mode 100644
index 0000000..7b78053
--- /dev/null
+++ b/drivers/input/misc/rfkill.c
@@ -0,0 +1,210 @@
+/*
+	Copyright (C) 2006 Ivo van Doorn
+
+	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 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the
+	Free Software Foundation, Inc.,
+	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/rfkill.h>
+
+#include <asm/atomic.h>
+
+MODULE_AUTHOR("Ivo van Doorn <IvDoorn@gmail.com>");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("RF button support");
+MODULE_LICENSE("GPL");
+
+/*
+ * List of all registered buttons.
+ */
+static struct list_head rfkill_list;
+static spinlock_t rfkill_list_lock;
+
+/*
+ * Polling timer, poll_delay and use count.
+ */
+static struct timer_list poll_timer;
+static atomic_t poll_required;
+
+static void rfkill_toggle_radio(int new_status)
+{
+	struct list_head *entry;
+	struct rfkill *rfkill;
+
+	/*
+	 * Go through the list of all radio's to toggle the radio state.
+	 */
+	list_for_each(entry, &rfkill_list) {
+		rfkill =  list_entry(entry, struct rfkill, entry);
+
+		rfkill->current_status = new_status;
+
+		/*
+		 * If the input_device has been opened
+		 * all radio events should be send to user space.
+		 */
+		if (rfkill->input_dev->users) {
+			input_report_key(rfkill->input_dev,
+				KEY_RFKILL, new_status);
+			input_sync(rfkill->input_dev);
+			continue;
+		}
+
+		/*
+		 * If the hardware does not toggle the radio status automaticly,
+		 * we should take care of it.
+		 */
+		if (new_status && rfkill->enable_radio)
+			rfkill->enable_radio(rfkill->data);
+		else if (!new_status && rfkill->disable_radio)
+			rfkill->disable_radio(rfkill->data);
+	}
+}
+
+static void rfkill_poll_button(unsigned long data)
+{
+	struct list_head *entry;
+	struct rfkill *rfkill;
+	int status;
+
+	spin_lock(&rfkill_list_lock);
+
+	list_for_each(entry, &rfkill_list) {
+		rfkill =  list_entry(entry, struct rfkill, entry);
+
+		if (!rfkill->poll)
+			continue;
+
+		status = !!rfkill->poll(rfkill->data);
+
+		if (status != rfkill->current_status) {
+			rfkill_toggle_radio(status);
+			break;
+		}
+	}
+
+	spin_unlock(&rfkill_list_lock);
+
+	/*
+	 * Check if polling is still required.
+	 */
+	if (atomic_read(&poll_required)) {
+		poll_timer.expires = jiffies + RFKILL_POLL_DELAY;
+		add_timer(&poll_timer);
+	}
+}
+
+void rfkill_button_event(struct rfkill *rfkill, int status)
+{
+	if (status != rfkill->current_status) {
+		spin_lock(&rfkill_list_lock);
+		rfkill_toggle_radio(status);
+		spin_unlock(&rfkill_list_lock);
+	}
+}
+EXPORT_SYMBOL(rfkill_button_event);
+
+int rfkill_add_device(struct rfkill *rfkill)
+{
+	int status;
+
+	/*
+	 * Allocate, initialize and register input device.
+	 */
+	rfkill->input_dev = input_allocate_device();
+	if (!rfkill->input_dev) {
+		printk(KERN_ERR "Failed to allocate input device %s.\n",
+			rfkill->dev_name);
+		return -ENOMEM;
+	}
+
+	rfkill->input_dev->name = "Radio button";
+	rfkill->input_dev->phys = rfkill->dev_name;
+	rfkill->input_dev->id.bustype = BUS_HOST;
+	set_bit(KEY_RFKILL, rfkill->input_dev->keybit);
+
+	status = input_register_device(rfkill->input_dev);
+	if (status) {
+		printk(KERN_ERR "Failed to register input device %s.\n",
+			rfkill->dev_name);
+		input_free_device(rfkill->input_dev);
+		return status;
+	}
+
+	INIT_LIST_HEAD(&rfkill->entry);
+
+	spin_lock(&rfkill_list_lock);
+	list_add(&rfkill->entry, &rfkill_list);
+	spin_unlock(&rfkill_list_lock);
+
+	/*
+	 * If polling is required the poll_required counter should be
+	 * increased. If it was previously 0 we should start the polling timer.
+	 */
+	if (rfkill->poll) {
+		if (!atomic_read(&poll_required)) {
+			poll_timer.expires = jiffies + RFKILL_POLL_DELAY;
+			add_timer(&poll_timer);
+		}
+		atomic_inc(&poll_required);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(rfkill_add_device);
+
+void rfkill_del_device(struct rfkill *rfkill)
+{
+	spin_lock(&rfkill_list_lock);
+
+	/*
+	 * Check if this button required polling and if this
+	 * was the last button that required polling.
+	 */
+	if (rfkill->poll && atomic_dec_and_test(&poll_required))
+		del_timer(&poll_timer);
+
+	list_del(&rfkill->entry);
+
+	spin_unlock(&rfkill_list_lock);
+}
+EXPORT_SYMBOL(rfkill_del_device);
+
+static int __init radiobtn_init(void)
+{
+	printk(KERN_INFO "Loading rfkill driver.\n");
+
+	INIT_LIST_HEAD(&rfkill_list);
+	spin_lock_init(&rfkill_list_lock);
+
+	init_timer(&poll_timer);
+	poll_timer.function = rfkill_poll_button;
+	poll_timer.data = 0;
+	atomic_set(&poll_required, 0);
+
+	return 0;
+}
+
+static void __exit radiobtn_exit(void)
+{
+	printk(KERN_INFO "Unloading rfkill driver.\n");
+}
+
+module_init(radiobtn_init);
+module_exit(radiobtn_exit);
diff --git a/drivers/net/wireless/d80211/adm8211/adm8211.c b/drivers/net/wireless/d80211/adm8211/adm8211.c
index 748eb26..dcabeab 100644
--- a/drivers/net/wireless/d80211/adm8211/adm8211.c
+++ b/drivers/net/wireless/d80211/adm8211/adm8211.c
@@ -452,7 +452,7 @@ static void adm8211_interrupt_tci(struct
 	}
 
 	if (priv->cur_tx - dirty_tx < priv->tx_ring_size - 2)
-		netif_wake_queue(dev);
+		ieee80211_wake_queue(dev, 0);
 
 	priv->dirty_tx = dirty_tx;
 	spin_unlock(&priv->lock);
@@ -1627,7 +1627,7 @@ static int adm8211_open(struct net_devic
 	adm8211_rf_set_channel(dev, priv->channel);
 
 	retval = request_irq(dev->irq, &adm8211_interrupt,
-			     SA_SHIRQ, dev->name, dev);
+			     IRQF_SHARED, dev->name, dev);
 	if (retval) {
 		printk(KERN_ERR "%s: failed to register IRQ handler\n",
 		       dev->name);
@@ -1765,17 +1765,13 @@ static void adm8211_tx_raw(struct net_de
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	if (priv->cur_tx - priv->dirty_tx < priv->tx_ring_size / 2)
+	if (priv->cur_tx - priv->dirty_tx == priv->tx_ring_size / 2)
 		flag = TDES1_CONTROL_IC | TDES1_CONTROL_LS | TDES1_CONTROL_FS;
-	else if (priv->cur_tx - priv->dirty_tx == priv->tx_ring_size / 2)
-		flag = TDES1_CONTROL_IC | TDES1_CONTROL_LS | TDES1_CONTROL_FS;
-	else if (priv->cur_tx - priv->dirty_tx < priv->tx_ring_size - 2)
+	else
 		flag = TDES1_CONTROL_LS | TDES1_CONTROL_FS;
-	else {
-		flag = TDES1_CONTROL_IC | TDES1_CONTROL_LS | TDES1_CONTROL_FS;
-		printk(KERN_DEBUG "%s: Yikes, this shouldn't happen!\n", dev->name);
-		netif_stop_queue(dev);
-	}
+
+	if (priv->cur_tx - priv->dirty_tx == priv->tx_ring_size - 2)
+		ieee80211_stop_queue(dev, 0);
 
 	entry = priv->cur_tx % priv->tx_ring_size;
 
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
index 59d137b..6366020 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -2295,7 +2295,7 @@ #ifdef CONFIG_BCM947XX
 	}
 #endif
 	err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
-			  SA_SHIRQ, KBUILD_MODNAME, bcm);
+			  IRQF_SHARED, KBUILD_MODNAME, bcm);
 	if (err)
 		printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
 
diff --git a/drivers/net/wireless/d80211/rt2x00/Kconfig b/drivers/net/wireless/d80211/rt2x00/Kconfig
index d9b97f1..9e91fd6 100644
--- a/drivers/net/wireless/d80211/rt2x00/Kconfig
+++ b/drivers/net/wireless/d80211/rt2x00/Kconfig
@@ -17,12 +17,12 @@ config RT2400PCI
 
 config RT2400PCI_BUTTON
 	bool "Ralink rt2400 hardware button support"
-	depends on RT2400PCI && X86
+	depends on RT2400PCI && RFKILL
 	---help---
 	In some notebooks the rt2400 chipset is integrated in the machine,
-	with this option enabled the device will periodically poll the
-	the status of this button and will send and ACPI event when
-	the button has been pressed.
+	with this option enabled the driver will register itself to the
+	rfkill driver for periodical polling of the hardware button
+	status, and the correct handling of button press events.
 
 config RT2400PCI_DEBUG
 	bool "Ralink rt2400 debug output"
@@ -40,12 +40,12 @@ config RT2500PCI
 
 config RT2500PCI_BUTTON
 	bool "Ralink rt2500 hardware button support"
-	depends on RT2500PCI && X86
+	depends on RT2500PCI && RFKILL
 	---help---
 	In some notebooks the rt2500 chipset is integrated in the machine,
-	with this option enabled the device will periodically poll the
-	the status of this button and will send and ACPI event when
-	the button has been pressed.
+	with this option enabled the driver will register itself to the
+	rfkill driver for periodical polling of the hardware button
+	status, and the correct handling of button press events.
 
 config RT2500PCI_DEBUG
 	bool "Ralink rt2500 debug output"
@@ -63,12 +63,12 @@ config RT61PCI
 
 config RT61PCI_BUTTON
 	bool "Ralink rt61 hardware button support"
-	depends on RT61PCI && X86
+	depends on RT61PCI && RFKILL
 	---help---
 	In some notebooks the rt61 chipset is integrated in the machine,
-	with this option enabled the device will periodically poll the
-	the status of this button and will send and ACPI event when
-	the button has been pressed.
+	with this option enabled the driver will register itself to the
+	rfkill driver for periodical polling of the hardware button
+	status, and the correct handling of button press events.
 
 config RT61PCI_DEBUG
 	bool "Ralink rt61 debug output"
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
index 709cdbf..96bcdf4 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
@@ -346,23 +346,6 @@ static void rt2x00_eeprom_multiread(cons
 		rt2x00_eeprom_read(rt2x00dev, word + i, data++);
 }
 
-#ifdef CONFIG_RT2400PCI_BUTTON
-/*
- * Hardware button poll handler.
- */
-static void rt2400pci_button_poll(unsigned long data)
-{
-	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
-	u32 reg;
-
-	rt2x00_register_read(rt2x00dev, GPIOCSR, &reg);
-	rt2x00pci_button_status(
-		rt2x00dev, rt2x00_get_field32(reg, GPIOCSR_BIT0));
-}
-#else /* CONFIG_RT2400PCI_BUTTON */
-static void rt2400pci_button_poll(unsigned long data){}
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
 /*
  * Ethtool handlers.
  */
@@ -434,8 +417,63 @@ #endif /* CONFIG_RT2400PCI_DEBUG */
 	.get_link	= ethtool_op_get_link,
 	.get_eeprom_len	= rt2400pci_get_eeprom_len,
 	.get_eeprom	= rt2400pci_get_eeprom,
+	.get_perm_addr	= ethtool_op_get_perm_addr,
 };
 
+#ifdef CONFIG_RT2400PCI_BUTTON
+static int rt2400pci_button_poll(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
+	u32 reg;
+
+	rt2x00_register_read(rt2x00dev, GPIOCSR, &reg);
+	return rt2x00_get_field32(reg, GPIOCSR_BIT0);
+}
+
+static void rt2400pci_button_enable_radio(unsigned long data)
+{
+	rt2400pci_enable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt2400pci_button_disable_radio(unsigned long data)
+{
+	rt2400pci_disable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt2400pci_button_start(struct rt2x00_dev *rt2x00dev)
+{
+	struct rfkill *rfkill = &rt2x00dev->rfkill;
+
+	/*
+	 * Only start the button polling when
+	 * the hardware button is present.
+	 */
+	if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+		return;
+
+	rfkill->dev_name	= "rt2400pci";
+	rfkill->data		= (unsigned long)rt2x00dev;
+	rfkill->poll		= rt2400pci_button_poll;
+	rfkill->enable_radio	= rt2400pci_button_enable_radio;
+	rfkill->disable_radio	= rt2400pci_button_disable_radio;
+	rfkill->current_status	= !!rt2400pci_button_poll(rfkill->data);
+
+	if (rfkill_add_device(rfkill))
+		ERROR("Failed to register button handler.\n");
+}
+
+static void rt2400pci_button_stop(struct rt2x00_dev *rt2x00dev)
+{
+	if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+		return;
+
+	rfkill_del_device(&rt2x00dev->rfkill);
+}
+#else /* CONFIG_RT2400PCI_BUTTON */
+static void rt2400pci_button_start(struct rt2x00_dev *rt2x00dev){}
+static void rt2400pci_button_stop(struct rt2x00_dev *rt2x00dev){}
+#endif /* CONFIG_RT2400PCI_BUTTON */
+
 /*
  * Configuration handlers.
  */
@@ -1356,7 +1394,7 @@ static int rt2400pci_initialize(struct r
 	 * Register interrupt handler.
 	 */
 	if (request_irq(rt2x00dev_pci(rt2x00dev)->irq, rt2400pci_interrupt,
-		SA_SHIRQ, net_dev->name, rt2x00dev)) {
+		IRQF_SHARED, net_dev->name, rt2x00dev)) {
 		ERROR("IRQ %d allocation failed.\n",
 			rt2x00dev_pci(rt2x00dev)->irq);
 		goto exit_fail;
@@ -1380,10 +1418,8 @@ static void rt2400pci_uninitialize(struc
 	/*
 	 * Cancel scanning.
 	 */
-	if (rt2x00dev->scan) {
-		rt2x00dev->scan->status = SCANNING_CANCELLED;
-		complete_all(&rt2x00dev->scan->completion);
-	}
+	if (rt2x00dev->scan)
+		rt2x00_signal_scan(rt2x00dev->scan, SCANNING_CANCELLED);
 
 	/*
 	 * Flush out all pending work.
@@ -1801,10 +1837,8 @@ static void rt2400pci_txdone(void *data)
 	if (rt2x00dev->scan &&
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_TX]) &&
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_ATIM]) &&
-	    rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO])) {
-		rt2x00dev->scan->status = SCANNING_READY;
-		complete(&rt2x00dev->scan->completion);
-	}
+	    rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO]))
+		rt2x00_signal_scan(rt2x00dev->scan, SCANNING_READY);
 
 	/*
 	 * If the data ring was full before the txdone handler
@@ -2050,11 +2084,10 @@ static void rt2400pci_remove_interface(s
 		rt2400pci_disable_radio(rt2x00dev);
 }
 
-static void rt2400pci_config_update(void *data)
+static int rt2400pci_config(struct net_device *net_dev,
+	struct ieee80211_conf *conf)
 {
-	struct rt2x00_dev *rt2x00dev = data;
-	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 	u32 reg;
 
 	/*
@@ -2085,21 +2118,10 @@ static void rt2400pci_config_update(void
 		rt2x00_register_read(rt2x00dev, RXCSR0, &reg);
 		rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
 		rt2x00_register_write(rt2x00dev, RXCSR0, reg);
-	} else if (conf->radio_enabled) {
-		if (rt2400pci_enable_radio(rt2x00dev))
-			return;
-	}
-}
-
-static int rt2400pci_config(struct net_device *net_dev,
-	struct ieee80211_conf *conf)
-{
-	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	} else if (conf->radio_enabled)
+		return rt2400pci_enable_radio(rt2x00dev);
 
-	/*
-	 * Queue work.
-	 */
-	return !queue_work(rt2x00dev->workqueue, &rt2x00dev->config_work);
+	return 0;
 }
 
 static int rt2400pci_config_interface(struct net_device *net_dev, int if_id,
@@ -2164,14 +2186,7 @@ static void rt2400pci_scan(void *data)
 	 * we need to wait untill all TX rings are empty to
 	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00dev->scan->status != SCANNING_READY)
-		wait_for_completion(&rt2x00dev->scan->completion);
-
-	/*
-	 * Check if this scan has been cancelled while
-	 * work was still scheduled.
-	 */
-	if (rt2x00dev->scan->status == SCANNING_CANCELLED)
+	if (rt2x00_wait_scan(rt2x00dev->scan))
 		goto exit;
 
 	/*
@@ -2243,13 +2258,7 @@ static int rt2400pci_passive_scan(struct
 	/*
 	 * Initialize Scanning structure.
 	 */
-	init_completion(&rt2x00dev->scan->completion);
-
-	memcpy(&rt2x00dev->scan->conf, conf, sizeof(*conf));
-
-	rt2x00dev->scan->state = state;
-
-	rt2x00dev->scan->status = 0;
+	rt2x00_start_scan(rt2x00dev->scan, conf, state);
 
 	/*
 	 * Queue work.
@@ -2521,25 +2530,29 @@ static int rt2400pci_init_eeprom(struct 
 static int rt2400pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u32 reg[2] = { 0, 0 };
+	u8 reg[8];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
-	rt2x00_register_multiread(rt2x00dev, CSR3, &reg[0], sizeof(reg));
+	/*
+	 * Read MAC address from MAC register.
+	 */
+	rt2x00_register_multiread(rt2x00dev, CSR3, (u32*)&reg[0], 6);
 
-	net_dev->dev_addr[0] = rt2x00_get_field32(reg[0], CSR3_BYTE0);
-	net_dev->dev_addr[1] = rt2x00_get_field32(reg[0], CSR3_BYTE1);
-	net_dev->dev_addr[2] = rt2x00_get_field32(reg[0], CSR3_BYTE2);
-	net_dev->dev_addr[3] = rt2x00_get_field32(reg[0], CSR3_BYTE3);
-	net_dev->dev_addr[4] = rt2x00_get_field32(reg[1], CSR4_BYTE4);
-	net_dev->dev_addr[5] = rt2x00_get_field32(reg[1], CSR4_BYTE5);
+	/*
+	 * Check if a valid MAC address has been read.
+	 */
+	if (!is_valid_ether_addr(&reg[0]))
+		return -EINVAL;
 
+	/*
+	 * Copy to netdevice structure.
+	 */
+	memcpy(&net_dev->dev_addr[0], &reg[0], 6);
+	memcpy(&net_dev->perm_addr[0], &reg[0], 6);
 	net_dev->addr_len = 6;
 
-	if (!is_valid_ether_addr(&net_dev->dev_addr[0]))
-		return -EINVAL;
-
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -2738,7 +2751,7 @@ static void rt2400pci_free_dev(struct ne
 	/*
 	 * Shutdown poll_timer for hardware button.
 	 */
-	rt2x00pci_button_stop(rt2x00dev);
+	rt2400pci_button_stop(rt2x00dev);
 
 	/*
 	 * Free ring structures.
@@ -2798,11 +2811,6 @@ static int rt2400pci_alloc_dev(struct pc
 		goto exit;
 
 	/*
-	 * Initialize cofniguration work.
-	 */
-	INIT_WORK(&rt2x00dev->config_work, rt2400pci_config_update, rt2x00dev);
-
-	/*
 	 * Reset current working type.
 	 */
 	rt2x00dev->interface.type = -EINVAL;
@@ -2832,7 +2840,7 @@ static int rt2400pci_alloc_dev(struct pc
 	/*
 	 * If required start hardware button polling.
 	 */
-	rt2x00pci_button_start(rt2x00dev, rt2400pci_button_poll);
+	rt2400pci_button_start(rt2x00dev);
 
 	return 0;
 
@@ -2851,10 +2859,16 @@ static int rt2400pci_probe(struct pci_de
 	struct net_device *net_dev;
 	int status;
 
+	status = pci_request_regions(pci_dev, pci_name(pci_dev));
+	if (status) {
+		ERROR("PCI request regions failed.\n");
+		return status;
+	}
+
 	status = pci_enable_device(pci_dev);
 	if (status) {
 		ERROR("Enable device failed.\n");
-		return status;
+		goto exit_release_regions;
 	}
 
 	pci_set_master(pci_dev);
@@ -2869,17 +2883,11 @@ static int rt2400pci_probe(struct pci_de
 		goto exit_disable_device;
 	}
 
-	status = pci_request_regions(pci_dev, pci_name(pci_dev));
-	if (status) {
-		ERROR("PCI request regions failed.\n");
-		goto exit_disable_device;
-	}
-
 	net_dev = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), NULL);
 	if (!net_dev) {
 		ERROR("Failed to allocate hardware.\n");
 		status = -ENOMEM;
-		goto exit_release_regions;
+		goto exit_disable_device;
 	}
 
 	SET_ETHTOOL_OPS(net_dev, &rt2400pci_ethtool_ops);
@@ -2898,13 +2906,13 @@ static int rt2400pci_probe(struct pci_de
 exit_free_device:
 	ieee80211_free_hw(net_dev);
 
-exit_release_regions:
-	pci_release_regions(pci_dev);
-
 exit_disable_device:
 	if (status != -EBUSY)
 		pci_disable_device(pci_dev);
 
+exit_release_regions:
+	pci_release_regions(pci_dev);
+
 	pci_set_drvdata(pci_dev, NULL);
 
 	return status;
@@ -2927,9 +2935,9 @@ static void rt2400pci_remove(struct pci_
 
 	pci_set_drvdata(pci_dev, NULL);
 
-	pci_release_regions(pci_dev);
-
 	pci_disable_device(pci_dev);
+
+	pci_release_regions(pci_dev);
 }
 
 #ifdef CONFIG_PM
@@ -3024,11 +3032,6 @@ module_param_named(debug, rt2x00_debug_l
 MODULE_PARM_DESC(debug, "Set this parameter to 1 to enable debug output.");
 #endif /* CONFIG_RT2400PCI_DEBUG */
 
-#ifdef CONFIG_RT2400PCI_BUTTON
-module_param_named(poll_delay, rt2x00_poll_delay, short, S_IRUGO);
-MODULE_PARM_DESC(debug, "Delay between WiFi button pollings (in 100ms).");
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
 static struct pci_driver rt2400pci_driver = {
 	.name		= DRV_NAME,
 	.id_table	= rt2400pci_device_table,
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.h b/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
index b592eef..ae0ea54 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
@@ -881,8 +881,8 @@ #define TXPOWER_FROM_DEV(__txpower) \
 #define TXPOWER_TO_DEV(__txpower) \
 	({ \
 		(__txpower) += MIN_TXPOWER; \
-		((__txpower) < MIN_TXPOWER) ? MAX_TXPOWER : \
-		(((__txpower) > MAX_TXPOWER) ? MIN_TXPOWER : \
+		((__txpower) <= MIN_TXPOWER) ? MAX_TXPOWER : \
+		(((__txpower) >= MAX_TXPOWER) ? MIN_TXPOWER : \
 		(MAX_TXPOWER - ((__txpower) - MIN_TXPOWER))); \
 	})
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
index 8a22968..20095aa 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
@@ -346,23 +346,6 @@ static void rt2x00_eeprom_multiread(cons
 		rt2x00_eeprom_read(rt2x00dev, word + i, data++);
 }
 
-#ifdef CONFIG_RT2500PCI_BUTTON
-/*
- * Hardware button poll handler.
- */
-static void rt2500pci_button_poll(unsigned long data)
-{
-	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
-	u32 reg;
-
-	rt2x00_register_read(rt2x00dev, GPIOCSR, &reg);
-	rt2x00pci_button_status(
-		rt2x00dev, rt2x00_get_field32(reg, GPIOCSR_BIT0));
-}
-#else /* CONFIG_RT2500PCI_BUTTON */
-static void rt2500pci_button_poll(unsigned long data){}
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
 /*
  * Ethtool handlers.
  */
@@ -434,8 +417,63 @@ #endif /* CONFIG_RT2500PCI_DEBUG */
 	.get_link	= ethtool_op_get_link,
 	.get_eeprom_len	= rt2500pci_get_eeprom_len,
 	.get_eeprom	= rt2500pci_get_eeprom,
+	.get_perm_addr	= ethtool_op_get_perm_addr,
 };
 
+#ifdef CONFIG_RT2500PCI_BUTTON
+static int rt2500pci_button_poll(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
+	u32 reg;
+
+	rt2x00_register_read(rt2x00dev, GPIOCSR, &reg);
+	return rt2x00_get_field32(reg, GPIOCSR_BIT0);
+}
+
+static void rt2500pci_button_enable_radio(unsigned long data)
+{
+	rt2500pci_enable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt2500pci_button_disable_radio(unsigned long data)
+{
+	rt2500pci_disable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt2500pci_button_start(struct rt2x00_dev *rt2x00dev)
+{
+	struct rfkill *rfkill = &rt2x00dev->rfkill;
+
+	/*
+	 * Only start the button polling when
+	 * the hardware button is present.
+	 */
+	if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+		return;
+
+	rfkill->dev_name	= "rt2500pci";
+	rfkill->data		= (unsigned long)rt2x00dev;
+	rfkill->poll		= rt2500pci_button_poll;
+	rfkill->enable_radio	= rt2500pci_button_enable_radio;
+	rfkill->disable_radio	= rt2500pci_button_disable_radio;
+	rfkill->current_status	= !!rt2500pci_button_poll(rfkill->data);
+
+	if (rfkill_add_device(rfkill))
+		ERROR("Failed to register button handler.\n");
+}
+
+static void rt2500pci_button_stop(struct rt2x00_dev *rt2x00dev)
+{
+	if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+		return;
+
+	rfkill_del_device(&rt2x00dev->rfkill);
+}
+#else /* CONFIG_RT2500PCI_BUTTON */
+static void rt2500pci_button_start(struct rt2x00_dev *rt2x00dev){}
+static void rt2500pci_button_stop(struct rt2x00_dev *rt2x00dev){}
+#endif /* CONFIG_RT2500PCI_BUTTON */
+
 /*
  * Configuration handlers.
  */
@@ -1476,7 +1514,7 @@ static int rt2500pci_initialize(struct r
 	 * Register interrupt handler.
 	 */
 	if (request_irq(rt2x00dev_pci(rt2x00dev)->irq, rt2500pci_interrupt,
-		SA_SHIRQ, net_dev->name, rt2x00dev)) {
+		IRQF_SHARED, net_dev->name, rt2x00dev)) {
 		ERROR("IRQ %d allocation failed.\n",
 			rt2x00dev_pci(rt2x00dev)->irq);
 		goto exit_fail;
@@ -1500,10 +1538,8 @@ static void rt2500pci_uninitialize(struc
 	/*
 	 * Cancel scanning.
 	 */
-	if (rt2x00dev->scan) {
-		rt2x00dev->scan->status = SCANNING_CANCELLED;
-		complete_all(&rt2x00dev->scan->completion);
-	}
+	if (rt2x00dev->scan)
+		rt2x00_signal_scan(rt2x00dev->scan, SCANNING_CANCELLED);
 
 	/*
 	 * Flush out all pending work.
@@ -1948,10 +1984,8 @@ static void rt2500pci_txdone(void *data)
 	if (rt2x00dev->scan &&
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_TX]) &&
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_ATIM]) &&
-	    rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO])) {
-		rt2x00dev->scan->status = SCANNING_READY;
-		complete(&rt2x00dev->scan->completion);
-	}
+	    rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO]))
+		rt2x00_signal_scan(rt2x00dev->scan, SCANNING_READY);
 
 	/*
 	 * If the data ring was full before the txdone handler
@@ -2197,11 +2231,10 @@ static void rt2500pci_remove_interface(s
 		rt2500pci_disable_radio(rt2x00dev);
 }
 
-static void rt2500pci_config_update(void *data)
+static int rt2500pci_config(struct net_device *net_dev,
+	struct ieee80211_conf *conf)
 {
-	struct rt2x00_dev *rt2x00dev = data;
-	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 	u32 reg;
 
 	/*
@@ -2233,21 +2266,10 @@ static void rt2500pci_config_update(void
 		rt2x00_register_read(rt2x00dev, RXCSR0, &reg);
 		rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
 		rt2x00_register_write(rt2x00dev, RXCSR0, reg);
-	} else if (conf->radio_enabled) {
-		if (rt2500pci_enable_radio(rt2x00dev))
-			return;
-	}
-}
-
-static int rt2500pci_config(struct net_device *net_dev,
-	struct ieee80211_conf *conf)
-{
-	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	} else if (conf->radio_enabled)
+		return rt2500pci_enable_radio(rt2x00dev);
 
-	/*
-	 * Queue work.
-	 */
-	return !queue_work(rt2x00dev->workqueue, &rt2x00dev->config_work);
+	return 0;
 }
 
 static int rt2500pci_config_interface(struct net_device *net_dev, int if_id,
@@ -2312,14 +2334,7 @@ static void rt2500pci_scan(void *data)
 	 * we need to wait untill all TX rings are empty to
 	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00dev->scan->status != SCANNING_READY)
-		wait_for_completion(&rt2x00dev->scan->completion);
-
-	/*
-	 * Check if this scan has been cancelled while
-	 * work was still scheduled.
-	 */
-	if (rt2x00dev->scan->status == SCANNING_CANCELLED)
+	if (rt2x00_wait_scan(rt2x00dev->scan))
 		goto exit;
 
 	/*
@@ -2337,7 +2352,7 @@ static void rt2500pci_scan(void *data)
 	} else {
 		rt2500pci_config_phymode(rt2x00dev,
 			rt2x00dev->scan->conf.running_phymode);
-	
+
 		rt2500pci_config_channel(rt2x00dev,
 			rt2x00dev->scan->conf.running_channel_val,
 			rt2x00dev->scan->conf.running_channel,
@@ -2387,13 +2402,7 @@ static int rt2500pci_passive_scan(struct
 	/*
 	 * Initialize Scanning structure.
 	 */
-	init_completion(&rt2x00dev->scan->completion);
-
-	memcpy(&rt2x00dev->scan->conf, conf, sizeof(*conf));
-
-	rt2x00dev->scan->state = state;
-
-	rt2x00dev->scan->status = 0;
+	rt2x00_start_scan(rt2x00dev->scan, conf, state);
 
 	/*
 	 * Queue work.
@@ -2673,25 +2682,29 @@ static int rt2500pci_init_eeprom(struct 
 static int rt2500pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u32 reg[2] = { 0, 0 };
+	u8 reg[8];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
-	rt2x00_register_multiread(rt2x00dev, CSR3, &reg[0], sizeof(reg));
+	/*
+	 * Read MAC address from MAC register.
+	 */
+	rt2x00_register_multiread(rt2x00dev, CSR3, (u32*)&reg[0], 6);
 
-	net_dev->dev_addr[0] = rt2x00_get_field32(reg[0], CSR3_BYTE0);
-	net_dev->dev_addr[1] = rt2x00_get_field32(reg[0], CSR3_BYTE1);
-	net_dev->dev_addr[2] = rt2x00_get_field32(reg[0], CSR3_BYTE2);
-	net_dev->dev_addr[3] = rt2x00_get_field32(reg[0], CSR3_BYTE3);
-	net_dev->dev_addr[4] = rt2x00_get_field32(reg[1], CSR4_BYTE4);
-	net_dev->dev_addr[5] = rt2x00_get_field32(reg[1], CSR4_BYTE5);
+	/*
+	 * Check if a valid MAC address has been read.
+	 */
+	if (!is_valid_ether_addr(&reg[0]))
+		return -EINVAL;
 
+	/*
+	 * Copy to netdevice structure.
+	 */
+	memcpy(&net_dev->dev_addr[0], &reg[0], 6);
+	memcpy(&net_dev->perm_addr[0], &reg[0], 6);
 	net_dev->addr_len = 6;
 
-	if (!is_valid_ether_addr(&net_dev->dev_addr[0]))
-		return -EINVAL;
-
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -2866,7 +2879,7 @@ static void rt2500pci_init_hw_channels(s
 		};
 
 		struct ieee80211_channel *chan = channels + 14;
-	
+
 		for (i = 0; i < ARRAY_SIZE(vals); i++)
 			(chan++)->val = cpu_to_le32(vals[i]);
 	}
@@ -3021,7 +3034,7 @@ static void rt2500pci_free_dev(struct ne
 	/*
 	 * Shutdown poll_timer for hardware button.
 	 */
-	rt2x00pci_button_stop(rt2x00dev);
+	rt2500pci_button_stop(rt2x00dev);
 
 	/*
 	 * Free ring structures.
@@ -3081,11 +3094,6 @@ static int rt2500pci_alloc_dev(struct pc
 		goto exit;
 
 	/*
-	 * Initialize cofniguration work.
-	 */
-	INIT_WORK(&rt2x00dev->config_work, rt2500pci_config_update, rt2x00dev);
-
-	/*
 	 * Reset current working type.
 	 */
 	rt2x00dev->interface.type = -EINVAL;
@@ -3115,7 +3123,7 @@ static int rt2500pci_alloc_dev(struct pc
 	/*
 	 * If required start hardware button polling.
 	 */
-	rt2x00pci_button_start(rt2x00dev, rt2500pci_button_poll);
+	rt2500pci_button_start(rt2x00dev);
 
 	return 0;
 
@@ -3134,10 +3142,16 @@ static int rt2500pci_probe(struct pci_de
 	struct net_device *net_dev;
 	int status;
 
+	status = pci_request_regions(pci_dev, pci_name(pci_dev));
+	if (status) {
+		ERROR("PCI request regions failed.\n");
+		return status;
+	}
+
 	status = pci_enable_device(pci_dev);
 	if (status) {
 		ERROR("Enable device failed.\n");
-		return status;
+		goto exit_release_regions;
 	}
 
 	pci_set_master(pci_dev);
@@ -3152,17 +3166,11 @@ static int rt2500pci_probe(struct pci_de
 		goto exit_disable_device;
 	}
 
-	status = pci_request_regions(pci_dev, pci_name(pci_dev));
-	if (status) {
-		ERROR("PCI request regions failed.\n");
-		goto exit_disable_device;
-	}
-
 	net_dev = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), NULL);
 	if (!net_dev) {
 		ERROR("Failed to allocate hardware.\n");
 		status = -ENOMEM;
-		goto exit_release_regions;
+		goto exit_disable_device;
 	}
 
 	SET_ETHTOOL_OPS(net_dev, &rt2500pci_ethtool_ops);
@@ -3181,13 +3189,13 @@ static int rt2500pci_probe(struct pci_de
 exit_free_device:
 	ieee80211_free_hw(net_dev);
 
-exit_release_regions:
-	pci_release_regions(pci_dev);
-
 exit_disable_device:
 	if (status != -EBUSY)
 		pci_disable_device(pci_dev);
 
+exit_release_regions:
+	pci_release_regions(pci_dev);
+
 	pci_set_drvdata(pci_dev, NULL);
 
 	return status;
@@ -3210,9 +3218,9 @@ static void rt2500pci_remove(struct pci_
 
 	pci_set_drvdata(pci_dev, NULL);
 
-	pci_release_regions(pci_dev);
-
 	pci_disable_device(pci_dev);
+
+	pci_release_regions(pci_dev);
 }
 
 #ifdef CONFIG_PM
@@ -3307,11 +3315,6 @@ module_param_named(debug, rt2x00_debug_l
 MODULE_PARM_DESC(debug, "Set this parameter to 1 to enable debug output.");
 #endif /* CONFIG_RT2500PCI_DEBUG */
 
-#ifdef CONFIG_RT2500PCI_BUTTON
-module_param_named(poll_delay, rt2x00_poll_delay, short, S_IRUGO);
-MODULE_PARM_DESC(debug, "Delay between WiFi button pollings (in 100ms).");
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
 static struct pci_driver rt2500pci_driver = {
 	.name		= DRV_NAME,
 	.id_table	= rt2500pci_device_table,
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.h b/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
index 671265b..8ef5ae5 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
@@ -1142,8 +1142,8 @@ #define TXPOWER_FROM_DEV(__txpower) \
 
 #define TXPOWER_TO_DEV(__txpower) \
 	({ \
-		((__txpower) < MIN_TXPOWER) ? MIN_TXPOWER : \
-		(((__txpower) > MAX_TXPOWER) ? MAX_TXPOWER : \
+		((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
+		(((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
 		(__txpower)); \
 	})
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
index d15a33e..383f4a9 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
@@ -170,7 +170,8 @@ static void rt2x00_bbp_read(const struct
 	*value = 0xff;
 }
 
-static void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev, const u32 value)
+static void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev,
+	const u32 value)
 {
 	u16 reg;
 	unsigned int i;
@@ -284,6 +285,7 @@ #endif /* CONFIG_RT2500USB_DEBUG */
 	.get_link	= ethtool_op_get_link,
 	.get_eeprom_len	= rt2500usb_get_eeprom_len,
 	.get_eeprom	= rt2500usb_get_eeprom,
+	.get_perm_addr	= ethtool_op_get_perm_addr,
 };
 
 /*
@@ -1263,10 +1265,8 @@ static void rt2500usb_uninitialize(struc
 	/*
 	 * Cancel scanning.
 	 */
-	if (rt2x00dev->scan) {
-		rt2x00dev->scan->status = SCANNING_CANCELLED;
-		complete_all(&rt2x00dev->scan->completion);
-	}
+	if (rt2x00dev->scan)
+		rt2x00_signal_scan(rt2x00dev->scan, SCANNING_CANCELLED);
 
 	/*
 	 * Flush out all pending work.
@@ -1482,7 +1482,7 @@ static void rt2500usb_write_tx_desc(stru
 	else
 		rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 0);
 
-	if ((ieee80211hdr->seq_ctrl & IEEE80211_SCTL_FRAG) == 0)
+	if ((le16_to_cpu(ieee80211hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) == 0)
 		rt2x00_set_field32(&txd->word0, TXD_W0_NEW_SEQ, 1);
 	else
 		rt2x00_set_field32(&txd->word0, TXD_W0_NEW_SEQ, 0);
@@ -1712,10 +1712,8 @@ static void rt2500usb_txdone(void *data)
 	if (rt2x00dev->scan &&
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_TX]) &&
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_ATIM]) &&
-	    rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO])) {
-		rt2x00dev->scan->status = SCANNING_READY;
-		complete(&rt2x00dev->scan->completion);
-	}
+	    rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO]))
+		rt2x00_signal_scan(rt2x00dev->scan, SCANNING_READY);
 
 	/*
 	 * If the data ring was full before the txdone handler
@@ -1912,12 +1910,10 @@ static void rt2500usb_remove_interface(s
 		rt2500usb_disable_radio(rt2x00dev);
 }
 
-static void rt2500usb_config_update(void *data)
+static int rt2500usb_config(struct net_device *net_dev,
+	struct ieee80211_conf *conf)
 {
-	struct rt2x00_dev *rt2x00dev = data;
-	struct net_device *net_dev =
-		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
-	struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 	u16 reg;
 
 	/*
@@ -1949,21 +1945,10 @@ static void rt2500usb_config_update(void
 		rt2x00_register_read(rt2x00dev, TXRX_CSR2, &reg);
 		rt2x00_set_field16_nb(&reg, TXRX_CSR2_DISABLE_RX, 0);
 		rt2x00_register_write(rt2x00dev, TXRX_CSR2, reg);
-	} else if (conf->radio_enabled) {
-		if (rt2500usb_enable_radio(rt2x00dev))
-			return;
-	}
-}
-
-static int rt2500usb_config(struct net_device *net_dev,
-	struct ieee80211_conf *conf)
-{
-	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	} else if (conf->radio_enabled)
+		return rt2500usb_enable_radio(rt2x00dev);
 
-	/*
-	 * Queue work.
-	 */
-	return !queue_work(rt2x00dev->workqueue, &rt2x00dev->config_work);
+	return 0;
 }
 
 static void rt2500usb_interface_update(void *data)
@@ -2038,14 +2023,7 @@ static void rt2500usb_scan(void *data)
 	 * we need to wait untill all TX rings are empty to
 	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00dev->scan->status != SCANNING_READY)
-		wait_for_completion(&rt2x00dev->scan->completion);
-
-	/*
-	 * Check if this scan has been cancelled while
-	 * work was still scheduled.
-	 */
-	if (rt2x00dev->scan->status == SCANNING_CANCELLED)
+	if (rt2x00_wait_scan(rt2x00dev->scan))
 		goto exit;
 
 	/*
@@ -2054,7 +2032,7 @@ static void rt2500usb_scan(void *data)
 	if (rt2x00dev->scan->state == IEEE80211_SCAN_START) {
 		rt2500usb_config_phymode(rt2x00dev,
 			rt2x00dev->scan->conf.scan_phymode);
-	
+
 		rt2500usb_config_channel(rt2x00dev,
 			rt2x00dev->scan->conf.scan_channel_val,
 			rt2x00dev->scan->conf.scan_channel,
@@ -2063,7 +2041,7 @@ static void rt2500usb_scan(void *data)
 	} else {
 		rt2500usb_config_phymode(rt2x00dev,
 			rt2x00dev->scan->conf.running_phymode);
-	
+
 		rt2500usb_config_channel(rt2x00dev,
 			rt2x00dev->scan->conf.running_channel_val,
 			rt2x00dev->scan->conf.running_channel,
@@ -2113,13 +2091,7 @@ static int rt2500usb_passive_scan(struct
 	/*
 	 * Initialize Scanning structure.
 	 */
-	init_completion(&rt2x00dev->scan->completion);
-
-	memcpy(&rt2x00dev->scan->conf, conf, sizeof(*conf));
-
-	rt2x00dev->scan->state = state;
-
-	rt2x00dev->scan->status = 0;
+	rt2x00_start_scan(rt2x00dev->scan, conf, state);
 
 	/*
 	 * Queue work.
@@ -2345,7 +2317,7 @@ static int rt2500usb_init_mac(struct rt2
 {
 	struct net_device *net_dev =
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
-	u16 eeprom[3] = { 0, 0, 0 };
+	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
@@ -2353,26 +2325,22 @@ static int rt2500usb_init_mac(struct rt2
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR, &eeprom[0], 6);
-
-	net_dev->dev_addr[0] = rt2x00_get_field16(eeprom[0],
-					EEPROM_MAC_ADDR_BYTE0);
-	net_dev->dev_addr[1] = rt2x00_get_field16(eeprom[0],
-					EEPROM_MAC_ADDR_BYTE1);
-	net_dev->dev_addr[2] = rt2x00_get_field16(eeprom[1],
-					EEPROM_MAC_ADDR_BYTE2);
-	net_dev->dev_addr[3] = rt2x00_get_field16(eeprom[1],
-					EEPROM_MAC_ADDR_BYTE3);
-	net_dev->dev_addr[4] = rt2x00_get_field16(eeprom[2],
-					EEPROM_MAC_ADDR_BYTE4);
-	net_dev->dev_addr[5] = rt2x00_get_field16(eeprom[2],
-					EEPROM_MAC_ADDR_BYTE5);
-
-	net_dev->addr_len = 6;
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
+		(u16*)&eeprom[0], 6);
 
-	if (!is_valid_ether_addr(&net_dev->dev_addr[0]))
+	/*
+	 * Check if a valid MAC address has been read.
+	 */
+	if (!is_valid_ether_addr(&eeprom[0]))
 		return -EINVAL;
 
+	/*
+	 * Copy to netdevice structure.
+	 */
+	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	net_dev->addr_len = 6;
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -2738,9 +2706,8 @@ static int rt2500usb_alloc_dev(struct us
 		return -ENODEV;
 
 	/*
-	 * Initialize cofniguration work.
+	 * Initialize configuration work.
 	 */
-	INIT_WORK(&rt2x00dev->config_work, rt2500usb_config_update, rt2x00dev);
 	INIT_WORK(&rt2x00dev->interface.work,
 		rt2500usb_interface_update, rt2x00dev);
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500usb.h b/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
index 42d44aa..917ba4c 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
@@ -679,8 +679,8 @@ #define TXPOWER_FROM_DEV(__txpower) \
 
 #define TXPOWER_TO_DEV(__txpower) \
 	({ \
-		((__txpower) < MIN_TXPOWER) ? MIN_TXPOWER : \
-		(((__txpower) > MAX_TXPOWER) ? MAX_TXPOWER : \
+		((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
+		(((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
 		(__txpower)); \
 	})
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2x00.h b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
index 06fa2be..eb56aea 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
@@ -82,6 +82,16 @@ #define DEBUG(__message, __args...) \
 		__FUNCTION__, ##__args);
 
 /*
+ * Hardware button support (through radiobtn)
+ * The delay between each poll can be set by the user
+ * using the module parameter. Default value is 0,
+ * which means polling is disabled.
+ */
+#ifdef CONFIG_RT2X00_BUTTON
+#include <linux/rfkill.h>
+#endif /* CONFIG_RT2X00_BUTTON */
+
+/*
  * Ring sizes.
  * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes.
  * DATA_FRAME_SIZE is used for TX, RX, ATIM and PRIO rings.
@@ -734,7 +744,8 @@ struct scanning {
 	 * Flag to see if this scan has been cancelled.
 	 */
 	short status;
-#define SCANNING_READY		0x0001
+#define SCANNING_READY		0x0000
+#define SCANNING_WAITING	0x0001
 #define SCANNING_CANCELLED	0x0002
 
 	/*
@@ -743,6 +754,48 @@ #define SCANNING_CANCELLED	0x0002
 	struct work_struct work;
 };
 
+static inline void rt2x00_start_scan(struct scanning *scan,
+	struct ieee80211_scan_conf *conf, int state)
+{
+	init_completion(&scan->completion);
+
+	memcpy(&scan->conf, conf, sizeof(*conf));
+
+	scan->state = state;
+
+	/*
+	 * Set initial status to SCANNING_WAITING to prevent scanning
+	 * to begin while there are still TX packets queued.
+	 */
+	scan->status = SCANNING_WAITING;
+}
+
+static inline void rt2x00_signal_scan(struct scanning *scan, short status)
+{
+	scan->status = status;
+
+	complete_all(&scan->completion);
+}
+
+static inline int rt2x00_wait_scan(struct scanning *scan)
+{
+	/*
+	 * Only wait for completion when the status
+	 * indicates we should. The SCANNING_READY
+	 * and SCANNING_CANCELLED are both states
+	 * which indicate complete_all has already
+	 * been called.
+	 */
+	if (scan->status == SCANNING_WAITING)
+		wait_for_completion(&scan->completion);
+
+	/*
+	 * Status field will have been updated by the handler
+	 * that has called complete_all() on our complete structure.
+	 */
+	return scan->status;
+}
+
 /*
  * rt2x00 device structure.
  */
@@ -751,7 +804,7 @@ struct rt2x00_dev {
 	 * Device structure.
 	 * The structure stored in here depends on the
 	 * system bus (PCI or USB).
-	 * When accessing this variable, the rt2x00{pci,usb}_dev
+	 * When accessing this variable, the rt2x00dev_{pci,usb}
 	 * macro's should be used for correct typecasting.
 	 */
 	void *dev;
@@ -873,11 +926,6 @@ #endif /* CONFIG_RT2X00_BUTTON */
 	struct ieee80211_rx_status rx_params;
 
 	/*
-	 * work structure for configuration changes.
-	 */
-	struct work_struct config_work;
-
-	/*
 	 * Scanning structure.
 	 */
 	struct scanning *scan;
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h b/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
index fe6f833..bd39395 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
@@ -44,115 +44,4 @@ #define EEPROM_WIDTH_93C66	8
 #define EEPROM_WRITE_OPCODE	0x05
 #define EEPROM_READ_OPCODE	0x06
 
-/*
- * HW button structure.
- */
-#ifdef CONFIG_RT2X00_BUTTON
-#include <acpi/acpi_bus.h>
-
-struct rt2x00_button {
-	/*
-	 * ACPI device for generation of ACPI events.
-	 */
-	struct acpi_device acpi_dev;
-
-	/*
-	 * Timer for register polling.
-	 */
-	struct timer_list poll_timer;
-
-	/*
-	 * Timer delay.
-	 */
-	short poll_delay;
-
-	/*
-	 * Current status of button.
-	 */
-	short button_status:1;
-	short active_poll:1;
-	short __pad:14;
-};
-#endif /* CONFIG_RT2X00_BUTTON */
-
-/*
- * HW button variables & functions.
- * The delay between each poll is set by the module parameter.
- */
-#ifdef CONFIG_RT2X00_BUTTON
-/*
- * Module parameter.
- */
-static short rt2x00_poll_delay = 0;
-
-static inline void rt2x00pci_button_status(struct rt2x00_dev *rt2x00dev,
-	char status)
-{
-	struct rt2x00_button *button = &rt2x00dev->button;
-
-	if (!button->active_poll)
-		return;
-
-	if (status != button->button_status) {
-		button->button_status = status;
-		acpi_bus_generate_event(
-			&button->acpi_dev, ACPI_TYPE_EVENT, status);
-	}
-
-	button->poll_timer.expires = jiffies + button->poll_delay;
-
-	if (button->active_poll)
-		add_timer(&button->poll_timer);
-}
-
-static inline void rt2x00pci_button_start(struct rt2x00_dev *rt2x00dev,
-	void (*handler)(unsigned long data))
-{
-	struct rt2x00_button *button = &rt2x00dev->button;
-
-	/*
-	 * Only enable polling when the user has
-	 * set the poll delay module parameter,
-	 * and the device contains a hardware button.
-	 */
-	if(!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON) ||
-	   !rt2x00_poll_delay)
-		return;
-
-	strcpy(acpi_device_class(&button->acpi_dev), DRV_NAME "_button");
-	strcpy(acpi_device_bid(&button->acpi_dev), DRV_NAME);
-	strcpy(acpi_device_name(&button->acpi_dev), DRV_NAME);
-
-	init_timer(&button->poll_timer);
-
-	button->poll_delay = rt2x00_poll_delay * (HZ / 10);
-	button->button_status = 0;
-	button->active_poll = 1;
-
-	button->poll_timer.function = handler;
-	button->poll_timer.data = (unsigned long)rt2x00dev;
-	button->poll_timer.expires = jiffies + button->poll_delay;
-
-	add_timer(&button->poll_timer);
-}
-
-static inline void rt2x00pci_button_stop(struct rt2x00_dev *rt2x00dev)
-{
-	/*
-	 * Shutdown poll_timer for hardware button,
-	 * make sure only to disable polling when
-	 * it was enabled in the first place.
-	 */
-	if(!rt2x00dev->button.active_poll)
-		return;
-
-	rt2x00dev->button.active_poll = 0;
-	del_timer_sync(&rt2x00dev->button.poll_timer);
-}
-#else /* CONFIG_RT2X00_BUTTON */
-static inline void rt2x00pci_button_start(struct rt2x00_dev *rt2x00dev,
-	void (*handler)(unsigned long data)){}
-static inline void rt2x00pci_button_stop(struct rt2x00_dev *rt2x00dev){}
-#endif /* CONFIG_RT2X00_BUTTON */
-
 #endif /* RT2X00PCI_H */
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.c b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
index 8bb9de9..cc6789e 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
@@ -377,23 +377,6 @@ static void rt2x00_eeprom_multiread(cons
 		rt2x00_eeprom_read(rt2x00dev, word + i, data++);
 }
 
-#ifdef CONFIG_RT61PCI_BUTTON
-/*
- * Hardware button poll handler.
- */
-static void rt61pci_button_poll(unsigned long data)
-{
-	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
-	u32 reg;
-
-	rt2x00_register_read(rt2x00dev, MAC_CSR13, &reg);
-	rt2x00pci_button_status(
-		rt2x00dev, rt2x00_get_field32(reg, MAC_CSR13_BIT5));
-}
-#else /* CONFIG_RT61PCI_BUTTON */
-static void rt61pci_button_poll(unsigned long data){}
-#endif /* CONFIG_RT61PCI_BUTTON */
-
 /*
  * Ethtool handlers.
  */
@@ -465,8 +448,63 @@ #endif /* CONFIG_RT61PCI_DEBUG */
 	.get_link	= ethtool_op_get_link,
 	.get_eeprom_len	= rt61pci_get_eeprom_len,
 	.get_eeprom	= rt61pci_get_eeprom,
+	.get_perm_addr	= ethtool_op_get_perm_addr,
 };
 
+#ifdef CONFIG_RT61PCI_BUTTON
+static int rt61pci_button_poll(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
+	u32 reg;
+
+	rt2x00_register_read(rt2x00dev, MAC_CSR13, &reg);
+	return rt2x00_get_field32(reg, MAC_CSR13_BIT5);
+}
+
+static void rt61pci_button_enable_radio(unsigned long data)
+{
+	rt61pci_enable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt61pci_button_disable_radio(unsigned long data)
+{
+	rt61pci_disable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt61pci_button_start(struct rt2x00_dev *rt2x00dev)
+{
+	struct rfkill *rfkill = &rt2x00dev->rfkill;
+
+	/*
+	 * Only start the button polling when
+	 * the hardware button is present.
+	 */
+	if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+		return;
+
+	rfkill->dev_name	= "rt61pci";
+	rfkill->data		= (unsigned long)rt2x00dev;
+	rfkill->poll		= rt61pci_button_poll;
+	rfkill->enable_radio	= rt61pci_button_enable_radio;
+	rfkill->disable_radio	= rt61pci_button_disable_radio;
+	rfkill->current_status	= !!rt61pci_button_poll(rfkill->data);
+
+	if (rfkill_add_device(rfkill))
+		ERROR("Failed to register button handler.\n");
+}
+
+static void rt61pci_button_stop(struct rt2x00_dev *rt2x00dev)
+{
+	if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+		return;
+
+	rfkill_del_device(&rt2x00dev->rfkill);
+}
+#else /* CONFIG_RT61PCI_BUTTON */
+static void rt61pci_button_start(struct rt2x00_dev *rt2x00dev){}
+static void rt61pci_button_stop(struct rt2x00_dev *rt2x00dev){}
+#endif /* CONFIG_RT61PCI_BUTTON */
+
 /*
  * Configuration handlers.
  */
@@ -1902,7 +1940,7 @@ static int rt61pci_initialize(struct rt2
 	 * Register interrupt handler.
 	 */
 	if (request_irq(rt2x00dev_pci(rt2x00dev)->irq, rt61pci_interrupt,
-		SA_SHIRQ, net_dev->name, rt2x00dev)) {
+		IRQF_SHARED, net_dev->name, rt2x00dev)) {
 		ERROR("IRQ %d allocation failed.\n",
 			rt2x00dev_pci(rt2x00dev)->irq);
 		goto exit_fail;
@@ -1926,10 +1964,8 @@ static void rt61pci_uninitialize(struct 
 	/*
 	 * Cancel scanning.
 	 */
-	if (rt2x00dev->scan) {
-		rt2x00dev->scan->status = SCANNING_CANCELLED;
-		complete_all(&rt2x00dev->scan->completion);
-	}
+	if (rt2x00dev->scan)
+		rt2x00_signal_scan(rt2x00dev->scan, SCANNING_CANCELLED);
 
 	/*
 	 * Flush out all pending work.
@@ -2448,10 +2484,8 @@ static void rt61pci_txdone(void *data)
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_BE]) &&
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_VI]) &&
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_VO]) &&
-	    rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO])) {
-		rt2x00dev->scan->status = SCANNING_READY;
-		complete(&rt2x00dev->scan->completion);
-	}
+	    rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO]))
+		rt2x00_signal_scan(rt2x00dev->scan, SCANNING_READY);
 }
 
 static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance,
@@ -2675,11 +2709,10 @@ static void rt61pci_remove_interface(str
 		rt61pci_disable_radio(rt2x00dev);
 }
 
-static void rt61pci_config_update(void *data)
+static int rt61pci_config(struct net_device *net_dev,
+	struct ieee80211_conf *conf)
 {
-	struct rt2x00_dev *rt2x00dev = data;
-	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 	u32 reg;
 
 	/*
@@ -2711,21 +2744,10 @@ static void rt61pci_config_update(void *
 		rt2x00_register_read(rt2x00dev, TXRX_CSR0, &reg);
 		rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
 		rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg);
-	} else if (conf->radio_enabled) {
-		if (rt61pci_enable_radio(rt2x00dev))
-			return;
-	}
-}
-
-static int rt61pci_config(struct net_device *net_dev,
-	struct ieee80211_conf *conf)
-{
-	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	} else if (conf->radio_enabled)
+		return rt61pci_enable_radio(rt2x00dev);
 
-	/*
-	 * Queue work.
-	 */
-	return !queue_work(rt2x00dev->workqueue, &rt2x00dev->config_work);
+	return 0;
 }
 
 static int rt61pci_config_interface(struct net_device *net_dev, int if_id,
@@ -2790,14 +2812,7 @@ static void rt61pci_scan(void *data)
 	 * we need to wait untill all TX rings are empty to
 	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00dev->scan->status != SCANNING_READY)
-		wait_for_completion(&rt2x00dev->scan->completion);
-
-	/*
-	 * Check if this scan has been cancelled while
-	 * work was still scheduled.
-	 */
-	if (rt2x00dev->scan->status == SCANNING_CANCELLED)
+	if (rt2x00_wait_scan(rt2x00dev->scan))
 		goto exit;
 
 	/*
@@ -2865,13 +2880,7 @@ static int rt61pci_passive_scan(struct n
 	/*
 	 * Initialize Scanning structure.
 	 */
-	init_completion(&rt2x00dev->scan->completion);
-
-	memcpy(&rt2x00dev->scan->conf, conf, sizeof(*conf));
-
-	rt2x00dev->scan->state = state;
-
-	rt2x00dev->scan->status = 0;
+	rt2x00_start_scan(rt2x00dev->scan, conf, state);
 
 	/*
 	 * Queue work.
@@ -3198,7 +3207,7 @@ static int rt61pci_init_eeprom(struct rt
 static int rt61pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u16 eeprom[3] = { 0, 0, 0 };
+	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
@@ -3206,26 +3215,22 @@ static int rt61pci_init_mac(struct rt2x0
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR, &eeprom[0], 6);
-
-	net_dev->dev_addr[0] = rt2x00_get_field16(eeprom[0],
-					EEPROM_MAC_ADDR_BYTE0);
-	net_dev->dev_addr[1] = rt2x00_get_field16(eeprom[0],
-					EEPROM_MAC_ADDR_BYTE1);
-	net_dev->dev_addr[2] = rt2x00_get_field16(eeprom[1],
-					EEPROM_MAC_ADDR_BYTE2);
-	net_dev->dev_addr[3] = rt2x00_get_field16(eeprom[1],
-					EEPROM_MAC_ADDR_BYTE3);
-	net_dev->dev_addr[4] = rt2x00_get_field16(eeprom[2],
-					EEPROM_MAC_ADDR_BYTE4);
-	net_dev->dev_addr[5] = rt2x00_get_field16(eeprom[2],
-					EEPROM_MAC_ADDR_BYTE5);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
+		(u16*)&eeprom[0], 6);
 
-	net_dev->addr_len = 6;
-
-	if (!is_valid_ether_addr(&net_dev->dev_addr[0]))
+	/*
+	 * Check if a valid MAC address has been read.
+	 */
+	if (!is_valid_ether_addr(&eeprom[0]))
 		return -EINVAL;
 
+	/*
+	 * Copy to netdevice structure.
+	 */
+	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	net_dev->addr_len = 6;
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -3491,7 +3496,6 @@ static int rt61pci_init_hw_modes(struct 
 	hw->modes[0].num_channels = 14;
 	hw->modes[0].num_rates = 12;
 
-
 	/*
 	 * Intitialize 802.11b
 	 * Rates: CCK.
@@ -3547,7 +3551,7 @@ static void rt61pci_free_dev(struct net_
 	/*
 	 * Shutdown poll_timer for hardware button.
 	 */
-	rt2x00pci_button_stop(rt2x00dev);
+	rt61pci_button_stop(rt2x00dev);
 
 	/*
 	 * Free ring structures.
@@ -3607,11 +3611,6 @@ static int rt61pci_alloc_dev(struct pci_
 		goto exit;
 
 	/*
-	 * Initialize configuration work.
-	 */
-	INIT_WORK(&rt2x00dev->config_work, rt61pci_config_update, rt2x00dev);
-
-	/*
 	 * Reset current working type.
 	 */
 	rt2x00dev->interface.type = -EINVAL;
@@ -3646,7 +3645,7 @@ static int rt61pci_alloc_dev(struct pci_
 	/*
 	 * If required start hardware button polling.
 	 */
-	rt2x00pci_button_start(rt2x00dev, rt61pci_button_poll);
+	rt61pci_button_start(rt2x00dev);
 
 	return 0;
 
@@ -3665,10 +3664,16 @@ static int rt61pci_probe(struct pci_dev 
 	struct net_device *net_dev;
 	int status;
 
+	status = pci_request_regions(pci_dev, pci_name(pci_dev));
+	if (status) {
+		ERROR("PCI request regions failed.\n");
+		return status;
+	}
+
 	status = pci_enable_device(pci_dev);
 	if (status) {
 		ERROR("Enable device failed.\n");
-		return status;
+		goto exit_release_regions;
 	}
 
 	pci_set_master(pci_dev);
@@ -3683,17 +3688,11 @@ static int rt61pci_probe(struct pci_dev 
 		goto exit_disable_device;
 	}
 
-	status = pci_request_regions(pci_dev, pci_name(pci_dev));
-	if (status) {
-		ERROR("PCI request regions failed.\n");
-		goto exit_disable_device;
-	}
-
 	net_dev = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), NULL);
 	if (!net_dev) {
 		ERROR("Failed to allocate hardware.\n");
 		status = -ENOMEM;
-		goto exit_release_regions;
+		goto exit_disable_device;
 	}
 
 	SET_ETHTOOL_OPS(net_dev, &rt61pci_ethtool_ops);
@@ -3712,13 +3711,13 @@ static int rt61pci_probe(struct pci_dev 
 exit_free_device:
 	ieee80211_free_hw(net_dev);
 
-exit_release_regions:
-	pci_release_regions(pci_dev);
-
 exit_disable_device:
 	if (status != -EBUSY)
 		pci_disable_device(pci_dev);
 
+exit_release_regions:
+	pci_release_regions(pci_dev);
+
 	pci_set_drvdata(pci_dev, NULL);
 
 	return status;
@@ -3741,9 +3740,9 @@ static void rt61pci_remove(struct pci_de
 
 	pci_set_drvdata(pci_dev, NULL);
 
-	pci_release_regions(pci_dev);
-
 	pci_disable_device(pci_dev);
+
+	pci_release_regions(pci_dev);
 }
 
 #ifdef CONFIG_PM
@@ -3844,11 +3843,6 @@ module_param_named(debug, rt2x00_debug_l
 MODULE_PARM_DESC(debug, "Set this parameter to 1 to enable debug output.");
 #endif /* CONFIG_RT61PCI_DEBUG */
 
-#ifdef CONFIG_RT61PCI_BUTTON
-module_param_named(poll_delay, rt2x00_poll_delay, short, S_IRUGO);
-MODULE_PARM_DESC(debug, "Delay between WiFi button pollings (in 100ms).");
-#endif /* CONFIG_RT61PCI_BUTTON */
-
 static struct pci_driver rt61pci_driver = {
 	.name		= DRV_NAME,
 	.id_table	= rt61pci_device_table,
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.h b/drivers/net/wireless/d80211/rt2x00/rt61pci.h
index d334390..2c5065b 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.h
@@ -1360,8 +1360,8 @@ #define TXPOWER_FROM_DEV(__txpower) \
 
 #define TXPOWER_TO_DEV(__txpower) \
 	({ \
-		((__txpower) < MIN_TXPOWER) ? MIN_TXPOWER : \
-		(((__txpower) > MAX_TXPOWER) ? MAX_TXPOWER : \
+		((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
+		(((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
 		(__txpower)); \
 	})
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt73usb.c b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
index acc5357..682d078 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
@@ -286,6 +286,7 @@ #endif /* CONFIG_RT2500USB_DEBUG */
 	.get_link	= ethtool_op_get_link,
 	.get_eeprom_len	= rt73usb_get_eeprom_len,
 	.get_eeprom	= rt73usb_get_eeprom,
+	.get_perm_addr	= ethtool_op_get_perm_addr,
 };
 
 /*
@@ -1524,10 +1525,8 @@ static void rt73usb_uninitialize(struct 
 	/*
 	 * Cancel scanning.
 	 */
-	if (rt2x00dev->scan) {
-		rt2x00dev->scan->status = SCANNING_CANCELLED;
-		complete_all(&rt2x00dev->scan->completion);
-	}
+	if (rt2x00dev->scan)
+		rt2x00_signal_scan(rt2x00dev->scan, SCANNING_CANCELLED);
 
 	/*
 	 * Flush out all pending work.
@@ -1999,10 +1998,8 @@ static void rt73usb_txdone(void *data)
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_BE]) &&
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_VI]) &&
 	    rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_VO]) &&
-	    rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO])) {
-		rt2x00dev->scan->status = SCANNING_READY;
-		complete(&rt2x00dev->scan->completion);
-	}
+	    rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO]))
+		rt2x00_signal_scan(rt2x00dev->scan, SCANNING_READY);
 
 	/*
 	 * If the data ring was full before the txdone handler
@@ -2127,6 +2124,7 @@ static int rt73usb_tx(struct net_device 
 static int rt73usb_reset(struct net_device *net_dev)
 {
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+
 	rt73usb_disable_radio(rt2x00dev);
 	return rt73usb_enable_radio(rt2x00dev);
 }
@@ -2195,12 +2193,10 @@ static void rt73usb_remove_interface(str
 		rt73usb_disable_radio(rt2x00dev);
 }
 
-static void rt73usb_config_update(void *data)
+static int rt73usb_config(struct net_device *net_dev,
+	struct ieee80211_conf *conf)
 {
-	struct rt2x00_dev *rt2x00dev = data;
-	struct net_device *net_dev =
-		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
-	struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 	u32 reg;
 
 	/*
@@ -2232,21 +2228,10 @@ static void rt73usb_config_update(void *
 		rt2x00_register_read(rt2x00dev, TXRX_CSR0, &reg);
 		rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
 		rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg);
-	} else if (conf->radio_enabled) {
-		if (rt73usb_enable_radio(rt2x00dev))
-			return;
-	}
-}
-
-static int rt73usb_config(struct net_device *net_dev,
-	struct ieee80211_conf *conf)
-{
-	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	} else if (conf->radio_enabled)
+		return rt73usb_enable_radio(rt2x00dev);
 
-	/*
-	 * Queue work.
-	 */
-	return !queue_work(rt2x00dev->workqueue, &rt2x00dev->config_work);
+	return 0;
 }
 
 static void rt73usb_interface_update(void *data)
@@ -2321,14 +2306,7 @@ static void rt73usb_scan(void *data)
 	 * we need to wait untill all TX rings are empty to
 	 * guarentee that all frames are send on the correct channel.
 	 */
-	if (rt2x00dev->scan->status != SCANNING_READY)
-		wait_for_completion(&rt2x00dev->scan->completion);
-
-	/*
-	 * Check if this scan has been cancelled while
-	 * work was still scheduled.
-	 */
-	if (rt2x00dev->scan->status == SCANNING_CANCELLED)
+	if (rt2x00_wait_scan(rt2x00dev->scan))
 		goto exit;
 
 	/*
@@ -2396,13 +2374,7 @@ static int rt73usb_passive_scan(struct n
 	/*
 	 * Initialize Scanning structure.
 	 */
-	init_completion(&rt2x00dev->scan->completion);
-
-	memcpy(&rt2x00dev->scan->conf, conf, sizeof(*conf));
-
-	rt2x00dev->scan->state = state;
-
-	rt2x00dev->scan->status = 0;
+	rt2x00_start_scan(rt2x00dev->scan, conf, state);
 
 	/*
 	 * Queue work.
@@ -2710,7 +2682,7 @@ static int rt73usb_init_mac(struct rt2x0
 {
 	struct net_device *net_dev =
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
-	u16 eeprom[3] = { 0, 0, 0 };
+	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
@@ -2718,26 +2690,22 @@ static int rt73usb_init_mac(struct rt2x0
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR, &eeprom[0], 6);
-
-	net_dev->dev_addr[0] = rt2x00_get_field16(eeprom[0],
-					EEPROM_MAC_ADDR_BYTE0);
-	net_dev->dev_addr[1] = rt2x00_get_field16(eeprom[0],
-					EEPROM_MAC_ADDR_BYTE1);
-	net_dev->dev_addr[2] = rt2x00_get_field16(eeprom[1],
-					EEPROM_MAC_ADDR_BYTE2);
-	net_dev->dev_addr[3] = rt2x00_get_field16(eeprom[1],
-					EEPROM_MAC_ADDR_BYTE3);
-	net_dev->dev_addr[4] = rt2x00_get_field16(eeprom[2],
-					EEPROM_MAC_ADDR_BYTE4);
-	net_dev->dev_addr[5] = rt2x00_get_field16(eeprom[2],
-					EEPROM_MAC_ADDR_BYTE5);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
+		(u16*)&eeprom[0], 6);
 
-	net_dev->addr_len = 6;
-
-	if (!is_valid_ether_addr(&net_dev->dev_addr[0]))
+	/*
+	 * Check if a valid MAC address has been read.
+	 */
+	if (!is_valid_ether_addr(&eeprom[0]))
 		return -EINVAL;
 
+	/*
+	 * Copy to netdevice structure.
+	 */
+	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	net_dev->addr_len = 6;
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -3000,7 +2968,6 @@ static int rt73usb_init_hw_modes(struct 
 	hw->modes[0].num_channels = 14;
 	hw->modes[0].num_rates = 12;
 
-
 	/*
 	 * Intitialize 802.11b
 	 * Rates: CCK.
@@ -3095,9 +3062,8 @@ static int rt73usb_alloc_dev(struct usb_
 		return -ENODEV;
 
 	/*
-	 * Initialize cofniguration work.
+	 * Initialize configuration work.
 	 */
-	INIT_WORK(&rt2x00dev->config_work, rt73usb_config_update, rt2x00dev);
 	INIT_WORK(&rt2x00dev->interface.work,
 		rt73usb_interface_update, rt2x00dev);
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt73usb.h b/drivers/net/wireless/d80211/rt2x00/rt73usb.h
index 662ca30..5be5e14 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt73usb.h
@@ -939,8 +939,8 @@ #define TXPOWER_FROM_DEV(__txpower) \
 
 #define TXPOWER_TO_DEV(__txpower) \
 	({ \
-		((__txpower) < MIN_TXPOWER) ? MIN_TXPOWER : \
-		(((__txpower) > MAX_TXPOWER) ? MAX_TXPOWER : \
+		((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
+		(((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
 		(__txpower)); \
 	})
 
diff --git a/include/linux/input.h b/include/linux/input.h
index b3253ab..f16da66 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -488,6 +488,7 @@ #define KEY_PREVIOUS		0x19c
 #define KEY_DIGITS		0x19d
 #define KEY_TEEN		0x19e
 #define KEY_TWEN		0x19f
+#define KEY_RFKILL		0x1a0
 
 #define KEY_DEL_EOL		0x1c0
 #define KEY_DEL_EOS		0x1c1
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
new file mode 100644
index 0000000..2e1c740
--- /dev/null
+++ b/include/linux/rfkill.h
@@ -0,0 +1,98 @@
+/*
+	Copyright (C) 2006 Ivo van Doorn
+
+	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 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the
+	Free Software Foundation, Inc.,
+	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+	RF button support
+	Laptops are quite often equiped with a RF button to enable or
+	disable the radio of the network device attached to that button.
+	This network device usually is an integrated wireless network device,
+	or bluetooth device.
+	Some of these devices will disable the radio automaticly when the
+	RF button has been pressed, while other devices need to be polled
+	for the RF button status.
+	But in all cases the only interface that will have its radio disabled
+	will be the device that has the RF button attached to it. But it could
+	be desired that userspace performs this disabling of all radios in case
+	there are also interfaces without a RF button that need to be disabled.
+
+	The rfkill driver will contain a list of all devices with a RF button,
+	hardware drivers need to register their hardware to teh rfkill
+	interface it can take care of everything. If the RF button requires
+	polling to obtain the status this will be handled by rfkill as well.
+	Once the status of the button has changed and the hardware does not
+	automaticly enable or disable the radio rfkill provides with the
+	interface to do this correctly.
+
+	For each registered hardware button an input device will be created.
+	If this input device has been opened by the user, rfkill will send a
+	signal to userspace instead of the hardware about the new button
+	status. This will allow userpace to perform the correct steps
+	in order to bring down all interfaces.
+ */
+
+#ifndef RFKILL_H
+#define RFKILL_H
+
+#include <linux/list.h>
+#include <linux/input.h>
+
+#define RFKILL_POLL_DELAY	( HZ / 10 ) /* 100 ms */
+
+/**
+ * struct rfkill - rfkill button control structure.
+ * @dev_name: Name of the interface. This will become the name
+ * 	of the input device which will be created for this button.
+ * @data: Private data which will be passed along with the radio and polling
+ * 	handlers.
+ * @poll(unsigned long data): Optional handler which will frequently be
+ * 	called to determine the current status of the RF button.
+ * @enable_radio(unsigned long data): Optional handler to enable the radio
+ * 	once the RF button has been pressed and the hardware does enable
+ * 	the radio automaticly.
+ * @disable_radio(unsigned long data): Optional handler to disable the radio
+ * 	once the RF button has been pressed and the hardware does disable
+ * 	the radio automaticly.
+ * @current_status: Contains the current status of the radio as it was
+ * 	previously indicated by the radio. This field may only be changed
+ * 	by the driver at initialization time.
+ */
+struct rfkill {
+	const char *dev_name;
+
+	unsigned long data;
+
+	int (*poll)(unsigned long data);
+	void (*enable_radio)(unsigned long data);
+	void (*disable_radio)(unsigned long data);
+
+	unsigned int current_status;
+
+	/*
+	 * These fields are private to rfkill, and
+	 * should not be used by the RF button driver.
+	 */
+	struct list_head entry;
+	struct input_dev *input_dev;
+};
+
+void rfkill_button_event(struct rfkill *rfkill, int status);
+int rfkill_add_device(struct rfkill *rfkill);
+void rfkill_del_device(struct rfkill *rfkill);
+
+#endif /* RFKILL_H */
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 60eca90..11804d5 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -250,7 +250,7 @@ int ieee80211_get_hdrlen(u16 fc)
 	case IEEE80211_FTYPE_DATA:
 		if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
 			hdrlen = 30; /* Addr4 */
-		if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_QOS_DATA)
+		if (fc & IEEE80211_STYPE_QOS_DATA)
 			hdrlen += 2; /* QoS Control Field */
 		break;
 	case IEEE80211_FTYPE_CTL:
@@ -637,7 +637,7 @@ static int ieee80211_frame_duration(stru
 		 * 802.11 (DS): 15.3.3, 802.11b: 18.3.4
 		 * aSIFSTime = 10 usec
 		 * aPreambleLength = 144 usec or 72 usec with short preamble
-		 * aPLCPHeaderLength = 48 ms or 24 ms with short preamble
+		 * aPLCPHeaderLength = 48 usec or 24 usec with short preamble
 		 */
 		dur = 10; /* aSIFSTime = 10 usec */
 		dur += short_preamble ? (72 + 24) : (144 + 48);
@@ -762,7 +762,7 @@ ieee80211_tx_h_misc(struct ieee80211_txr
 	struct ieee80211_tx_control *control = tx->u.tx.control;
 
 	if (!is_multicast_ether_addr(hdr->addr1)) {
-		if (tx->skb->len >= tx->local->rts_threshold &&
+		if (tx->skb->len + FCS_LEN > tx->local->rts_threshold &&
 		    tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD) {
 			control->use_rts_cts = 1;
 			control->retry_limit =
@@ -1519,7 +1519,7 @@ static int ieee80211_subif_start_xmit(st
 	sta = sta_info_get(local, hdr.addr1);
 	if (sta) {
 		if (sta->flags & WLAN_STA_WME) {
-			fc |= IEEE80211_STYPE_QOS_DATA << 4;
+			fc |= IEEE80211_STYPE_QOS_DATA;
 			hdrlen += 2;
 		}
 		sta_info_put(sta);
@@ -3074,8 +3074,9 @@ ieee80211_rx_h_check(struct ieee80211_tx
 		     rx->sdata->type != IEEE80211_IF_TYPE_IBSS &&
 		     (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) {
 		if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
-		     !(rx->fc & IEEE80211_FCTL_TODS)) ||
-		    !rx->u.rx.ra_match) {
+		     !(rx->fc & IEEE80211_FCTL_TODS) &&
+		     (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
+		    || !rx->u.rx.ra_match) {
 			/* Drop IBSS frames and frames for other hosts
 			 * silently. */
 			return TXRX_DROP;
@@ -3976,11 +3977,11 @@ static void ieee80211_remove_tx_extra(st
 	pkt_data->requeue = control->requeue;
 	pkt_data->queue = control->queue;
 
-	if (key == NULL)
-		return;
-
 	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
 
+	if (key == NULL)
+		goto no_key;
+
 	switch (key->alg) {
 	case ALG_WEP:
 		iv_len = WEP_IV_LEN;
@@ -3995,7 +3996,7 @@ static void ieee80211_remove_tx_extra(st
 		mic_len = CCMP_MIC_LEN;
 		break;
 	default:
-		return;
+		goto no_key;
 	}
 
 	if (skb->len >= mic_len && key->force_sw_encrypt)
@@ -4005,11 +4006,12 @@ static void ieee80211_remove_tx_extra(st
 		skb_pull(skb, iv_len);
 	}
 
+no_key:
 	{
 		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 		u16 fc = le16_to_cpu(hdr->frame_control);
 		if ((fc & 0x8C) == 0x88) /* QoS Control Field */ {
-			fc &= ~(IEEE80211_STYPE_QOS_DATA << 4);
+			fc &= ~IEEE80211_STYPE_QOS_DATA;
 			hdr->frame_control = cpu_to_le16(fc);
 			memmove(skb->data + 2, skb->data, hdrlen - 2);
 			skb_pull(skb, 2);
@@ -4379,7 +4381,7 @@ struct net_device *ieee80211_alloc_hw(si
 
 	mdev->hard_start_xmit = ieee80211_master_start_xmit;
 	mdev->wireless_handlers =
-		(struct iw_handler_def *) &ieee80211_iw_handler_def;
+		(struct iw_handler_def *) &ieee80211_iw_master_handler_def;
         mdev->do_ioctl = ieee80211_ioctl;
 	mdev->change_mtu = ieee80211_change_mtu;
         mdev->tx_timeout = ieee80211_tx_timeout;
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 7e021ec..bdaaf5e 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -569,6 +569,7 @@ void ieee80211_if_mgmt_setup(struct net_
 /* ieee80211_ioctl.c */
 int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 extern const struct iw_handler_def ieee80211_iw_handler_def;
+extern const struct iw_handler_def ieee80211_iw_master_handler_def;
 
 /* Set hw encryption from ieee80211 */
 int ieee80211_set_hw_encryption(struct net_device *dev,
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index dd52555..b983716 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -15,6 +15,7 @@ #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/skbuff.h>
+#include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 #include <linux/wireless.h>
 #include <net/iw_handler.h>
@@ -215,6 +216,52 @@ static int ieee80211_ioctl_flush(struct 
 }
 
 
+/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
+struct iapp_layer2_update {
+	u8 da[ETH_ALEN]; /* broadcast */
+	u8 sa[ETH_ALEN]; /* STA addr */
+	u16 len; /* 6 */
+	u8 dsap; /* 0 */
+	u8 ssap; /* 0 */
+	u8 control;
+	u8 xid_info[3];
+} __attribute__ ((packed));
+
+static void ieee80211_send_layer2_update(struct net_device *dev,
+					 const u8 *addr)
+{
+	struct iapp_layer2_update *msg;
+	struct sk_buff *skb;
+
+	/* Send Level 2 Update Frame to update forwarding tables in layer 2
+	 * bridge devices */
+
+	skb = dev_alloc_skb(sizeof(*msg));
+	if (skb == NULL)
+		return;
+	msg = (struct iapp_layer2_update *) skb_put(skb, sizeof(*msg));
+
+	/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
+	 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
+
+	memset(msg->da, 0xff, ETH_ALEN);
+	memcpy(msg->sa, addr, ETH_ALEN);
+	msg->len = htons(6);
+	msg->dsap = 0;
+	msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */
+	msg->control = 0xaf; /* XID response lsb.1111F101.
+			      * F=0 (no poll command; unsolicited frame) */
+	msg->xid_info[0] = 0x81; /* XID format identifier */
+	msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
+	msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */
+
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+	memset(skb->cb, 0, sizeof(skb->cb));
+	netif_rx(skb);
+}
+
+
 static int ieee80211_ioctl_add_sta(struct net_device *dev,
 				   struct prism2_hostapd_param *param)
 {
@@ -296,6 +343,10 @@ static int ieee80211_ioctl_add_sta(struc
 
 	sta_info_put(sta);
 
+	if (sdata->type == IEEE80211_IF_TYPE_AP ||
+	    sdata->type == IEEE80211_IF_TYPE_VLAN)
+		ieee80211_send_layer2_update(dev, param->sta_addr);
+
 	return 0;
 }
 
@@ -1168,6 +1219,10 @@ #if 0
 			       dev->name, MAC_ARG(param->sta_addr),
                                new_vlan_dev->name);
 #endif
+			if (sta->dev != new_vlan_dev) {
+				ieee80211_send_layer2_update(new_vlan_dev,
+							     sta->addr);
+			}
                         sta->dev = new_vlan_dev;
 			sta->vlan_id = param->u.set_sta_vlan.vlan_id;
                         dev_put(new_vlan_dev);
@@ -2500,7 +2555,7 @@ static int ieee80211_ioctl_prism2_param(
 		break;
 
 	case PRISM2_PARAM_MIXED_CELL:
-		if (sdata->type != IEEE80211_IF_TYPE_STA ||
+		if (sdata->type != IEEE80211_IF_TYPE_STA &&
 		    sdata->type != IEEE80211_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
@@ -2525,7 +2580,7 @@ static int ieee80211_ioctl_prism2_param(
 			sdata->u.sta.create_ibss = !!value;
 		break;
 	case PRISM2_PARAM_WMM_ENABLED:
-		if (sdata->type != IEEE80211_IF_TYPE_STA ||
+		if (sdata->type != IEEE80211_IF_TYPE_STA &&
 		    sdata->type != IEEE80211_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
@@ -2712,7 +2767,7 @@ static int ieee80211_ioctl_get_prism2_pa
 		break;
 
 	case PRISM2_PARAM_MIXED_CELL:
-		if (sdata->type != IEEE80211_IF_TYPE_STA ||
+		if (sdata->type != IEEE80211_IF_TYPE_STA &&
 		    sdata->type != IEEE80211_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
@@ -2726,7 +2781,7 @@ static int ieee80211_ioctl_get_prism2_pa
 			*param = sdata->u.sta.key_mgmt;
 		break;
 	case PRISM2_PARAM_WMM_ENABLED:
-		if (sdata->type != IEEE80211_IF_TYPE_STA ||
+		if (sdata->type != IEEE80211_IF_TYPE_STA &&
 		    sdata->type != IEEE80211_IF_TYPE_IBSS)
 			ret = -EINVAL;
 		else
@@ -2778,7 +2833,7 @@ static int ieee80211_ioctl_siwmlme(struc
 	struct iw_mlme *mlme = (struct iw_mlme *) extra;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_IF_TYPE_STA ||
+	if (sdata->type != IEEE80211_IF_TYPE_STA &&
 	    sdata->type != IEEE80211_IF_TYPE_IBSS)
 		return -EINVAL;
 
@@ -3129,3 +3184,25 @@ const struct iw_handler_def ieee80211_iw
 	.private	= (iw_handler *) ieee80211_private_handler,
 	.private_args	= (struct iw_priv_args *) ieee80211_ioctl_priv,
 };
+
+/* Wireless handlers for master interface */
+
+static const iw_handler ieee80211_master_handler[] =
+{
+	[SIOCGIWNAME  - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwname,
+	[SIOCSIWFREQ  - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwfreq,
+	[SIOCGIWFREQ  - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwfreq,
+	[SIOCGIWRANGE - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwrange,
+	[SIOCSIWRTS   - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwrts,
+	[SIOCGIWRTS   - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwrts,
+	[SIOCSIWFRAG  - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwfrag,
+	[SIOCGIWFRAG  - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwfrag,
+	[SIOCSIWRETRY - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwretry,
+	[SIOCGIWRETRY - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwretry,
+};
+
+const struct iw_handler_def ieee80211_iw_master_handler_def =
+{
+	.num_standard	= sizeof(ieee80211_master_handler) / sizeof(iw_handler),
+	.standard	= ieee80211_master_handler,
+};
diff --git a/net/d80211/tkip.c b/net/d80211/tkip.c
index 3f0cf57..c27a7fe 100644
--- a/net/d80211/tkip.c
+++ b/net/d80211/tkip.c
@@ -286,6 +286,7 @@ #endif /* CONFIG_TKIP_DEBUG */
 
 	if (only_iv) {
 		res = TKIP_DECRYPT_OK;
+		key->u.tkip.rx_initialized[queue] = 1;
 		goto done;
 	}
 
diff --git a/net/d80211/wme.c b/net/d80211/wme.c
index c3c961d..fc2a113 100644
--- a/net/d80211/wme.c
+++ b/net/d80211/wme.c
@@ -76,7 +76,7 @@ ieee80211_rx_h_remove_qos_control(struct
 	memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2);
 	hdr = (struct ieee80211_hdr *) skb_pull(rx->skb, 2);
 	/* change frame type to non QOS */
-	rx->fc = fc &= ~(IEEE80211_STYPE_QOS_DATA << 4);
+	rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA;
 	hdr->frame_control = cpu_to_le16(fc);
 
 	return TXRX_CONTINUE;
@@ -199,7 +199,7 @@ static inline int classify80211(struct s
 	}
 
 	/* is this a QoS frame? */
-	qos = fc & (IEEE80211_STYPE_QOS_DATA << 4);
+	qos = fc & IEEE80211_STYPE_QOS_DATA;
 
 	if (!qos) {
 		skb->priority = 0; /* required for correct WPA/11i MIC */
diff --git a/net/d80211/wpa.c b/net/d80211/wpa.c
index 7919620..fe5861f 100644
--- a/net/d80211/wpa.c
+++ b/net/d80211/wpa.c
@@ -70,7 +70,7 @@ int ieee80211_get_hdr_info(const struct 
 	a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
 		(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
 	if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
-	    (fc & IEEE80211_FCTL_STYPE) & IEEE80211_STYPE_QOS_DATA) {
+	    fc & IEEE80211_STYPE_QOS_DATA) {
 		pos = (u8 *) &hdr->addr4;
 		if (a4_included)
 			pos += 6;
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* What's new in wireless-dev?
@ 2006-08-24 19:08 John W. Linville
  0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-08-24 19:08 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: text/plain, Size: 4503 bytes --]

The following changes since commit f4a4ffcd3f5013bfb0cf7da41a5acfd7f8a5f1f3:
  John W. Linville:
        Merge branch 'from-linus'

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git

David Kimdon:
      d80211: allow for large scan results
      d80211: fix multiple device support
      d80211: fix interface removal

Jiri Benc:
      d80211: remove useless and wrong check for interface type

Johannes Berg:
      d80211: relax sysfs permissions
      d80211: master link
      d80211: pointers as extended booleans
      d80211: use kzalloc()
      d80211: get rid of WME bitfield
      d80211: get rid of sta_aid in favour of keeping track of TIM
      d80211: clean up exports
      d80211: clean up includes
      d80211: fix some sparse warnings
      d80211: make lowlevel TX framedump option visible
      d80211: surface IBSS debug
      d80211: get rid of MICHAEL_MIC_HWACCEL define
      d80211: surface powersave debug switch
      d80211: fix some documentation

Michael Buesch:
      d80211: add ieee80211_stop_queues()
      bcm43xx-d80211: Init, shutdown and restart fixes
      bcm43xx-d80211: New DMA engine code
      bcm43xx-d80211: return correct hard_start_xmit error code
      Add Sonics Silicon Backplane driver
      bcm43xx: convert driver to use ssb

Michael Wu:
      d80211: switch status codes, reason codes, and EIDs to enums
      d80211: Group EIDs by standard, add remaining 802.11d EIDs

 drivers/misc/Kconfig                               |    4 
 drivers/misc/Makefile                              |    5 
 drivers/misc/ssb.c                                 | 1015 ++++++++++++++++
 drivers/net/wireless/d80211/bcm43xx/Kconfig        |    1 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx.h      |  306 +----
 .../net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c  |   61 -
 .../net/wireless/d80211/bcm43xx/bcm43xx_debugfs.h  |    1 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c  |  835 +++++++++----
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.h  |  297 +++--
 .../net/wireless/d80211/bcm43xx/bcm43xx_ethtool.c  |    2 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c |    8 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c | 1282 ++++++--------------
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h |    5 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c  |   66 +
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c  |    9 
 .../net/wireless/d80211/bcm43xx/bcm43xx_power.c    |  104 +-
 .../net/wireless/d80211/bcm43xx/bcm43xx_radio.c    |   10 
 .../net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c    |  112 --
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c |    9 
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.h |    5 
 include/linux/ssb.h                                |  577 +++++++++
 include/net/d80211.h                               |  144 +-
 include/net/d80211_mgmt.h                          |  158 +-
 net/d80211/Kconfig                                 |   26 
 net/d80211/aes_ccm.c                               |    3 
 net/d80211/aes_ccm.h                               |    2 
 net/d80211/fifo_qdisc.c                            |    5 
 net/d80211/ieee80211.c                             |  276 ++--
 net/d80211/ieee80211_i.h                           |   68 +
 net/d80211/ieee80211_iface.c                       |    8 
 net/d80211/ieee80211_ioctl.c                       |   79 +
 net/d80211/ieee80211_key.h                         |    7 
 net/d80211/ieee80211_scan.c                        |   12 
 net/d80211/ieee80211_sta.c                         |  113 +-
 net/d80211/ieee80211_sysfs.c                       |    6 
 net/d80211/rate_control.c                          |   18 
 net/d80211/rate_control.h                          |    2 
 net/d80211/sta_info.c                              |   31 
 net/d80211/sta_info.h                              |   14 
 net/d80211/tkip.c                                  |   15 
 net/d80211/tkip.h                                  |    1 
 net/d80211/wep.c                                   |   14 
 net/d80211/wme.c                                   |   24 
 net/d80211/wme.h                                   |   25 
 net/d80211/wpa.c                                   |   17 
 45 files changed, 3475 insertions(+), 2307 deletions(-)
 create mode 100644 drivers/misc/ssb.c
 create mode 100644 include/linux/ssb.h

Omnibus patch attached as wireless-dev.patch.bz2.
-- 
John W. Linville
linville@tuxdriver.com

[-- Attachment #2: wireless-dev.patch.bz2 --]
[-- Type: application/x-bzip2, Size: 62392 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* What's new in wireless-dev?
@ 2006-09-04 23:53 John W. Linville
  0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-09-04 23:53 UTC (permalink / raw)
  To: netdev

I apologize for the announcement delay -- I had a hiccup w/ my mail
server this weekend...

---

The following changes since commit a7bcae7c095077d89899b2bf0b8d81b8997f340f:
  John W. Linville:
        Merge branch 'from-linus'

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git

David Kimdon:
      d80211: fix crash in ieee80211_rx_michael_mic_report()

Ivo van Doorn:
      rt2x00: Add register revision and firmware version to ethtool
      rt2x00: basic rate mask
      rt2x00: Mac address reading optimization
      rt2x00: add/remove interface fix
      rt2x00: Register initialization fixes
      rt2x00: Respect return values
      rt2x00: Add ieee80211_netif_oper() calls
      rt2x00: change variable name
      rt2x00: TXD/RTS fixes
      rt2x00: Misc fixes

Michael Buesch:
      ssb: minor fixes and cleanups
      ssb: add MAINTAINERS entry
      bcm43xx-d80211: add support for 4312
      ssb: fix core CC and REV reading
      bcm43xx-d80211: 4311 support

 MAINTAINERS                                        |    6 +
 drivers/misc/ssb.c                                 |   23 ++-
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c |   13 ++
 .../net/wireless/d80211/bcm43xx/bcm43xx_power.c    |   27 +++--
 drivers/net/wireless/d80211/rt2x00/rt2400pci.c     |  119 +++++++++++++-----
 drivers/net/wireless/d80211/rt2x00/rt2400pci.h     |   15 ++
 drivers/net/wireless/d80211/rt2x00/rt2500pci.c     |  129 ++++++++++++++------
 drivers/net/wireless/d80211/rt2x00/rt2500pci.h     |   17 ++-
 drivers/net/wireless/d80211/rt2x00/rt2500usb.c     |  127 +++++++++++++------
 drivers/net/wireless/d80211/rt2x00/rt2500usb.h     |    6 +
 drivers/net/wireless/d80211/rt2x00/rt2x00.h        |   60 +++++++++
 drivers/net/wireless/d80211/rt2x00/rt61pci.c       |  132 ++++++++++++++------
 drivers/net/wireless/d80211/rt2x00/rt61pci.h       |    6 +
 drivers/net/wireless/d80211/rt2x00/rt73usb.c       |  113 +++++++++++++----
 drivers/net/wireless/d80211/rt2x00/rt73usb.h       |    6 +
 include/linux/ssb.h                                |   46 ++++++-
 net/d80211/ieee80211.c                             |    7 +
 17 files changed, 632 insertions(+), 220 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8a88b78..783c1ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2650,6 +2650,12 @@ M:	tsbogend@alpha.franken.de
 L:	netdev@vger.kernel.org
 S:	Maintained
 
+SONICS SILICON BACKPLANE DRIVER (SSB)
+P:	Michael Buesch
+M:	mb@bu3sch.de
+L:	netdev@vger.kernel.org
+S:	Maintained
+
 SONY VAIO CONTROL DEVICE DRIVER
 P:	Stelian Pop
 M:	stelian@popies.net
diff --git a/drivers/misc/ssb.c b/drivers/misc/ssb.c
index 55e1447..44ab647 100644
--- a/drivers/misc/ssb.c
+++ b/drivers/misc/ssb.c
@@ -518,7 +518,8 @@ int ssb_init(struct ssb *ssb,
 {
 	int err;
 
-	if (!ssb || !pci_dev || !device_suspend || !device_resume)
+	if (!ssb || !pci_dev || !mmio ||
+	    !device_suspend || !device_resume)
 		return -EINVAL;
 
 	memset(ssb, 0, sizeof(*ssb));
@@ -551,9 +552,9 @@ void ssb_exit(struct ssb *ssb)
 	list_del(&ssb->list);
 	mutex_unlock(&ssb_list_mutex);
 
+	mutex_destroy(&ssb->suspend_mutex);
+	mutex_destroy(&ssb->mutex);
 	kfree(ssb->cores);
-	if (SSB_DEBUG)
-		memset(ssb, 0x5B, sizeof(*ssb));
 }
 EXPORT_SYMBOL_GPL(ssb_exit);
 
@@ -592,8 +593,8 @@ error:
 	return -ENODEV;
 }
 
-int ssb_switch_core_locked(struct ssb *ssb,
-			   struct ssb_core *new_core)
+static int ssb_switch_core_locked(struct ssb *ssb,
+				  struct ssb_core *new_core)
 {
 	int err = 0;
 
@@ -642,8 +643,9 @@ int ssb_probe_cores(struct ssb *ssb,
 		goto error;
 
 	idhi = ssb_read32(ssb, SSB_IDHIGH);
-	cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
-	rev = (idhi & SSB_IDHIGH_RC_MASK);
+	cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+	rev = (idhi & SSB_IDHIGH_RCLO);
+	rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
 
 	ssb->chipcommon_capabilities = 0;
 	ssb->nr_cores = 0;
@@ -715,9 +717,10 @@ int ssb_probe_cores(struct ssb *ssb,
 		core = &(ssb->cores[i]);
 
 		idhi = ssb_read32(ssb, SSB_IDHIGH);
-		core->cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
-		core->rev = (idhi & SSB_IDHIGH_RC_MASK);
-		core->vendor = (idhi & SSB_IDHIGH_VC_MASK) >> SSB_IDHIGH_VC_SHIFT;
+		core->cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+		core->rev = (idhi & SSB_IDHIGH_RCLO);
+		core->rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
+		core->vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
 		core->index = i;
 
 		dprintk(KERN_DEBUG PFX "Core %d found: "
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
index b47f006..d71d797 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -129,6 +129,10 @@ static struct pci_device_id bcm43xx_pci_
 	{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4307 802.11b */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 4311 802.11a/b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 4312 802.11a/b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4318 802.11b/g */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4319 802.11b/g */
@@ -2299,7 +2303,9 @@ static int bcm43xx_wireless_core_init(st
 	u32 sbimconfiglow;
 	u8 limit;
 
-	if (bcm->ssb.chip_rev < 5) {
+	assert(bcm->core_pci);
+	if (bcm->core_pci->cc == SSB_CC_PCI &&
+	    bcm->core_pci->rev <= 5) {
 		sbimconfiglow = bcm43xx_read32(bcm, SSB_IMCFGLO);
 		sbimconfiglow &= ~SSB_IMCFGLO_REQTO;
 		sbimconfiglow &= ~SSB_IMCFGLO_SERTO;
@@ -2710,6 +2716,7 @@ #endif
 
 		switch (core->cc) {
 		case SSB_CC_PCI:
+		case SSB_CC_PCIE:
 			if (bcm->core_pci) {
 				printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
 				break;
@@ -2742,7 +2749,7 @@ #endif
 
 			switch (core->rev) {
 			case 2: case 4: case 5: case 6:
-			case 7: case 9:
+			case 7: case 9: case 10:
 				break;
 			default:
 				printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
@@ -3247,7 +3254,7 @@ static int bcm43xx_read_phyinfo(struct b
 			phy_rev_ok = 0;
 		break;
 	case BCM43xx_PHYTYPE_G:
-		if (phy_rev > 7)
+		if (phy_rev > 8)
 			phy_rev_ok = 0;
 		break;
 	default:
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
index 6aa2a33..702af69 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
@@ -153,8 +153,6 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
 	int err, maxfreq;
 	struct ssb_core *old_core;
 
-	if (!(bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL))
-		return 0;
 	if (!bcm->core_chipcommon)
 		return 0;
 
@@ -163,11 +161,26 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
 	if (err)
 		goto out;
 
-	maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
-	bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
-			(maxfreq * 150 + 999999) / 1000000);
-	bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
-			(maxfreq * 15 + 999999) / 1000000);
+	if (bcm->ssb.chip_id == 0x4321) {
+		if (bcm->ssb.chip_rev == 0)
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x03A4);
+		else if (bcm->ssb.chip_rev == 1)
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x00A4);
+	}
+	if (bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL) {
+		if (bcm->core_chipcommon->rev >= 10) {
+			/* Set Idle Power clock rate to 1Mhz */
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_SYSCLKCTL,
+					(bcm43xx_read32(bcm, SSB_CHIPCOMMON_SYSCLKCTL) &
+					 0x0000FFFF) | 0x00040000);
+		} else {
+			maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
+					(maxfreq * 150 + 999999) / 1000000);
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
+					(maxfreq * 15 + 999999) / 1000000);
+		}
+	}
 
 	err = ssb_switch_core(&bcm->ssb, old_core);
 	assert(err == 0);
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
index 00f3a66..59163bf 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
@@ -373,6 +373,7 @@ static void rt2400pci_get_drvinfo(struct
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, "N/A");
 	strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -389,7 +390,7 @@ static void rt2400pci_get_regs(struct ne
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -751,7 +752,12 @@ static void rt2400pci_config_rate(struct
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set ARCSR1 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, ARCSR1, cpu_to_le32(reg[0]));
 
@@ -767,12 +773,12 @@ static void rt2400pci_config_rate(struct
 	rt2x00_set_field32(&reg[0], TXCSR1_ACK_CONSUME_TIME, value);
 	rt2x00_register_write(rt2x00dev, TXCSR1, reg[0]);
 
-	value = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
+	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
 
-	reg[0] = cpu_to_le32(0x00700400 | value);	/* ARCSR2 */
-	reg[1] = cpu_to_le32(0x00380401 | value);	/* ARCSR3 */
-	reg[2] = cpu_to_le32(0x00150402 | value);	/* ARCSR4 */
-	reg[3] = cpu_to_le32(0x000b8403 | value);	/* ARCSR5 */
+	reg[0] = cpu_to_le32(0x00700400 | preamble);	/* ARCSR2 */
+	reg[1] = cpu_to_le32(0x00380401 | preamble);	/* ARCSR3 */
+	reg[2] = cpu_to_le32(0x00150402 | preamble);	/* ARCSR4 */
+	reg[3] = cpu_to_le32(0x000b8403 | preamble);	/* ARCSR5 */
 
 	rt2x00_register_multiwrite(rt2x00dev, ARCSR2, &reg[0], sizeof(reg));
 }
@@ -1186,11 +1192,7 @@ static int rt2400pci_init_registers(stru
 	rt2x00_register_write(rt2x00dev, RXCSR0, reg);
 
 	rt2x00_register_write(rt2x00dev, MACCSR0, cpu_to_le32(0x00217223));
-
-	rt2x00_register_read(rt2x00dev, MACCSR1, &reg);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_TXBBP, 1);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_RXBBP, 1);
-	rt2x00_register_write(rt2x00dev, MACCSR1, reg);
+	rt2x00_register_write(rt2x00dev, MACCSR1, cpu_to_le32(0x00235518));
 
 	rt2x00_register_read(rt2x00dev, MACCSR2, &reg);
 	rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
@@ -1463,17 +1465,22 @@ static int rt2400pci_enable_radio(struct
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
 	u32 reg;
 
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1760,6 +1767,7 @@ static void rt2400pci_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * The TXD_W0_RESULT field will only be set when
@@ -1769,12 +1777,13 @@ static void rt2400pci_txdone(void *data)
 		 */
 		tx_status = rt2x00_get_field32(txd->word0, TXD_W0_RESULT);
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (tx_status == TX_SUCCESS ||
 		    tx_status == TX_SUCCESS_RETRY))
 			entry->tx_status.ack = 1;
 		else if (ack && tx_status == TX_FAIL_RETRY) {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 32,
@@ -1788,6 +1797,7 @@ static void rt2400pci_txdone(void *data)
 				entry->skb, &entry->tx_status);
 
 		rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(ring);
@@ -1954,7 +1964,8 @@ static int rt2400pci_tx(struct net_devic
 	memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
 	rt2400pci_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -1995,10 +2006,6 @@ static int rt2400pci_add_interface(struc
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2014,6 +2021,19 @@ static int rt2400pci_add_interface(struc
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2035,15 +2055,25 @@ static void rt2400pci_remove_interface(s
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt2400pci_disable_radio(rt2x00dev);
 }
 
@@ -2450,7 +2480,8 @@ static int rt2400pci_init_eeprom(struct 
 	 * 3 - Identify RF chipset.
 	 */
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, RT2460, value);
+	rt2x00_register_read(rt2x00dev, CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT2460, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2420) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2421))
@@ -2493,29 +2524,36 @@ static int rt2400pci_init_eeprom(struct 
 static int rt2400pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u8 reg[8];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
-	 * Read MAC address from MAC register.
+	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_register_multiread(rt2x00dev, CSR3, (u32*)&reg[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&reg[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &reg[0], 6);
-	memcpy(&net_dev->perm_addr[0], &reg[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt2400pci_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -2864,6 +2902,8 @@ static int rt2400pci_probe(struct pci_de
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -2888,6 +2928,8 @@ static void rt2400pci_remove(struct pci_
 
 	rt2400pci_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt2400pci_uninitialize(rt2x00dev);
 
 	rt2400pci_free_dev(net_dev);
@@ -2908,6 +2950,7 @@ static int rt2400pci_suspend(struct pci_
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -2915,12 +2958,14 @@ static int rt2400pci_suspend(struct pci_
 	 * Disable the radio.
 	 */
 	rt2400pci_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt2400pci_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt2400pci_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -2944,6 +2989,7 @@ static int rt2400pci_resume(struct pci_d
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -2960,15 +3006,22 @@ static int rt2400pci_resume(struct pci_d
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt2400pci_alloc_dev(pci_dev, net_dev)) {
+	status = rt2400pci_alloc_dev(pci_dev, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt2400pci_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt2400pci_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.h b/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
index ae0ea54..a991b59 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
@@ -44,7 +44,7 @@ #define RF2421				0x0001
 #define CSR_REG_BASE			0x0000
 #define CSR_REG_SIZE			0x014c
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x00ff
+#define EEPROM_SIZE			0x0100
 
 /*
  * Control/Status Registers(CSR).
@@ -705,6 +705,19 @@ #define RF3_TXPOWER			FIELD32(0x00003e00
  */
 
 /*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0		0x0002
+#define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0003
+#define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0004
+#define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
+
+/*
  * EEPROM antenna.
  * ANTENNA_NUM: Number of antenna's.
  * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
index 3f6dd94..651fbec 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
@@ -373,6 +373,7 @@ static void rt2500pci_get_drvinfo(struct
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, "N/A");
 	strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -389,7 +390,7 @@ static void rt2500pci_get_regs(struct ne
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -817,7 +818,12 @@ static void rt2500pci_config_rate(struct
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set ARCSR1 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, ARCSR1, cpu_to_le32(reg[0]));
 
@@ -833,12 +839,12 @@ static void rt2500pci_config_rate(struct
 	rt2x00_set_field32(&reg[0], TXCSR1_ACK_CONSUME_TIME, value);
 	rt2x00_register_write(rt2x00dev, TXCSR1, reg[0]);
 
-	value = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
+	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
 
-	reg[0] = cpu_to_le32(0x00700400 | value);	/* ARCSR2 */
-	reg[1] = cpu_to_le32(0x00380401 | value);	/* ARCSR3 */
-	reg[2] = cpu_to_le32(0x00150402 | value);	/* ARCSR4 */
-	reg[3] = cpu_to_le32(0x000b8403 | value);	/* ARCSR5 */
+	reg[0] = cpu_to_le32(0x00700400 | preamble);	/* ARCSR2 */
+	reg[1] = cpu_to_le32(0x00380401 | preamble);	/* ARCSR3 */
+	reg[2] = cpu_to_le32(0x00150402 | preamble);	/* ARCSR4 */
+	reg[3] = cpu_to_le32(0x000b8403 | preamble);	/* ARCSR5 */
 
 	rt2x00_register_multiwrite(rt2x00dev, ARCSR2, &reg[0], sizeof(reg));
 }
@@ -1243,6 +1249,7 @@ static int rt2500pci_init_registers(stru
 		return -EBUSY;
 
 	rt2x00_register_write(rt2x00dev, PWRCSR0, cpu_to_le32(0x3f3b3100));
+	rt2x00_register_write(rt2x00dev, PCICSR, cpu_to_le32(0x000003b8));
 
 	rt2x00_register_write(rt2x00dev, PSCSR0, cpu_to_le32(0x00020002));
 	rt2x00_register_write(rt2x00dev, PSCSR1, cpu_to_le32(0x00000002));
@@ -1266,12 +1273,11 @@ static int rt2500pci_init_registers(stru
 	rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
 	rt2x00_register_write(rt2x00dev, RXCSR0, reg);
 
-	rt2x00_register_write(rt2x00dev, MACCSR0, cpu_to_le32(0x00213223));
+	rt2x00_register_write(rt2x00dev, GPIOCSR, cpu_to_le32(0x0000ff00));
+	rt2x00_register_write(rt2x00dev, TESTCSR, cpu_to_le32(0x000000f0));
 
-	rt2x00_register_read(rt2x00dev, MACCSR1, &reg);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_TXBBP, 1);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_RXBBP, 1);
-	rt2x00_register_write(rt2x00dev, MACCSR1, reg);
+	rt2x00_register_write(rt2x00dev, MACCSR0, cpu_to_le32(0x00213223));
+	rt2x00_register_write(rt2x00dev, MACCSR1, cpu_to_le32(0x00235518));
 
 	rt2x00_register_read(rt2x00dev, MACCSR2, &reg);
 	rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
@@ -1583,17 +1589,22 @@ static int rt2500pci_enable_radio(struct
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
 	u32 reg;
 
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1739,11 +1750,9 @@ static void rt2500pci_write_tx_desc(stru
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 		residual = 0;
 
@@ -1907,6 +1916,7 @@ static void rt2500pci_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * The TXD_W0_RESULT field will only be set when
@@ -1916,12 +1926,13 @@ static void rt2500pci_txdone(void *data)
 		 */
 		tx_status = rt2x00_get_field32(txd->word0, TXD_W0_RESULT);
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (tx_status == TX_SUCCESS ||
 		    tx_status == TX_SUCCESS_RETRY))
 			entry->tx_status.ack = 1;
 		else if (ack && tx_status == TX_FAIL_RETRY) {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 32,
@@ -1935,6 +1946,7 @@ static void rt2500pci_txdone(void *data)
 				entry->skb, &entry->tx_status);
 
 		rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(ring);
@@ -2101,7 +2113,8 @@ static int rt2500pci_tx(struct net_devic
 	memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
 	rt2500pci_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -2142,10 +2155,6 @@ static int rt2500pci_add_interface(struc
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2161,6 +2170,19 @@ static int rt2500pci_add_interface(struc
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2182,15 +2204,25 @@ static void rt2500pci_remove_interface(s
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt2500pci_disable_radio(rt2x00dev);
 }
 
@@ -2589,7 +2621,8 @@ static int rt2500pci_init_eeprom(struct 
 	 * 3 - Identify RF chipset.
 	 */
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, RT2560, value);
+	rt2x00_register_read(rt2x00dev, CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT2560, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2523) &&
@@ -2645,29 +2678,36 @@ static int rt2500pci_init_eeprom(struct 
 static int rt2500pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u8 reg[8];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
-	 * Read MAC address from MAC register.
+	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_register_multiread(rt2x00dev, CSR3, (u32*)&reg[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&reg[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &reg[0], 6);
-	memcpy(&net_dev->perm_addr[0], &reg[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt2500pci_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -3147,6 +3187,8 @@ static int rt2500pci_probe(struct pci_de
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -3171,6 +3213,8 @@ static void rt2500pci_remove(struct pci_
 
 	rt2500pci_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt2500pci_uninitialize(rt2x00dev);
 
 	rt2500pci_free_dev(net_dev);
@@ -3191,6 +3235,7 @@ static int rt2500pci_suspend(struct pci_
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -3198,12 +3243,14 @@ static int rt2500pci_suspend(struct pci_
 	 * Disable the radio.
 	 */
 	rt2500pci_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt2500pci_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt2500pci_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -3227,6 +3274,7 @@ static int rt2500pci_resume(struct pci_d
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -3243,15 +3291,22 @@ static int rt2500pci_resume(struct pci_d
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt2500pci_alloc_dev(pci_dev, net_dev)) {
+	status = rt2500pci_alloc_dev(pci_dev, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt2500pci_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt2500pci_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.h b/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
index 8ef5ae5..fb44881 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
@@ -55,7 +55,7 @@ #define RT2560_VERSION_D		4
 #define CSR_REG_BASE			0x0000
 #define CSR_REG_SIZE			0x0174
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x01ff
+#define EEPROM_SIZE			0x0200
 
 /*
  * Control/Status Registers(CSR).
@@ -542,7 +542,7 @@ #define ARCSR1_AR_BBP_ID3		FIELD32(0xff0
  */
 
 /*
- * PCISR: PCI control register.
+ * PCICSR: PCI control register.
  * BIG_ENDIAN: 1: big endian, 0: little endian.
  * RX_TRESHOLD: Rx threshold in dw to start pci access
  * 0: 16dw (default), 1: 8dw, 2: 4dw, 3: 32dw.
@@ -935,6 +935,19 @@ #define RF3_TXPOWER			FIELD32(0x00003e00
  */
 
 /*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0		0x0002
+#define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0003
+#define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0004
+#define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
+
+/*
  * EEPROM antenna.
  * ANTENNA_NUM: Number of antenna's.
  * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
index 383f4a9..5d119cd 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
@@ -224,6 +224,7 @@ static void rt2500usb_get_drvinfo(struct
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, "N/A");
 	strcpy(drvinfo->bus_info, rt2x00dev_usb(rt2x00dev)->dev.bus_id);
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -240,7 +241,7 @@ static void rt2500usb_get_regs(struct ne
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u16*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -269,7 +270,7 @@ static int rt2500usb_get_eeprom(struct n
 	eeprom->magic = 0xbad;
 
 	rt2x00_eeprom_multiread(rt2x00dev,
-		eeprom->offset / sizeof(u16), (void*)data, eeprom->len);
+		eeprom->offset, (void*)data, eeprom->len);
 
 	return 0;
 }
@@ -629,15 +630,9 @@ static void rt2500usb_config_antenna(str
 static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
 	int short_slot_time)
 {
-	u16 reg;
-
 	short_slot_time = short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME;
 
 	rt2x00_register_write(rt2x00dev, MAC_CSR10, (u16)short_slot_time);
-
-	rt2x00_register_read(rt2x00dev, TXRX_CSR1, &reg);
-	rt2x00_set_field16_nb(&reg, TXRX_CSR1_TSF_OFFSET, IEEE80211_HEADER);
-	rt2x00_register_write(rt2x00dev, TXRX_CSR1, reg);
 }
 
 static void rt2500usb_config_rate(struct rt2x00_dev *rt2x00dev, const int rate)
@@ -651,7 +646,12 @@ static void rt2500usb_config_rate(struct
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set TXRX_CSR11 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR11, reg);
 
@@ -844,7 +844,7 @@ static int rt2500usb_set_state(struct rt
 
 	put_to_sleep = (state != STATE_AWAKE);
 
-	rt2x00_register_read(rt2x00dev, MAC_CSR17, &reg);
+	reg = 0;
 	rt2x00_set_field16_nb(&reg, MAC_CSR17_BBP_DESIRE_STATE, state);
 	rt2x00_set_field16_nb(&reg, MAC_CSR17_RF_DESIRE_STATE, state);
 	rt2x00_set_field16_nb(&reg, MAC_CSR17_PUT_TO_SLEEP, put_to_sleep);
@@ -866,7 +866,7 @@ static int rt2500usb_set_state(struct rt
 		if (bbp_state == state && rf_state == state)
 			return 0;
 		rt2x00_register_write(rt2x00dev, MAC_CSR17, reg);
-		msleep(10);
+		msleep(30);
 	}
 
 	NOTICE("Device failed to enter state %d, "
@@ -1092,7 +1092,7 @@ static int rt2500usb_init_registers(stru
 	}
 	rt2x00_register_write(rt2x00dev, PHY_CSR2, reg);
 
-	rt2x00_register_write(rt2x00dev, MAC_CSR11, 0x0002);
+	rt2x00_register_write(rt2x00dev, MAC_CSR11, 0x0005);
 	rt2x00_register_write(rt2x00dev, MAC_CSR22, 0x0053);
 	rt2x00_register_write(rt2x00dev, MAC_CSR15, 0x01ee);
 	rt2x00_register_write(rt2x00dev, MAC_CSR16, 0x0000);
@@ -1335,12 +1335,15 @@ static int rt2500usb_enable_radio(struct
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev =
+		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
 	struct data_ring *ring;
 	u16 reg;
 	unsigned int i;
@@ -1348,6 +1351,9 @@ static void rt2500usb_disable_radio(stru
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1499,11 +1505,9 @@ static void rt2500usb_write_tx_desc(stru
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 		residual = 0;
 
@@ -1679,6 +1683,7 @@ static void rt2500usb_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = entry->ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * Check if we have received an
@@ -1686,11 +1691,12 @@ static void rt2500usb_txdone(void *data)
 		 * was succesfull.
 		 */
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (urb->status == TX_SUCCESS))
 			entry->tx_status.ack = 1;
 		else if (ack && urb->status == TX_FAIL_OTHER) {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 0,
@@ -1700,6 +1706,7 @@ static void rt2500usb_txdone(void *data)
 			ieee80211_tx_status(ring->net_dev,
 				entry->skb, &entry->tx_status);
 
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(entry->ring);
@@ -1815,7 +1822,8 @@ static int rt2500usb_tx(struct net_devic
 	memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
 	rt2500usb_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -1858,10 +1866,6 @@ static int rt2500usb_add_interface(struc
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -1877,6 +1881,19 @@ static int rt2500usb_add_interface(struc
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -1898,15 +1915,25 @@ static void rt2500usb_remove_interface(s
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt2500usb_disable_radio(rt2x00dev);
 }
 
@@ -2255,6 +2282,8 @@ static int rt2500usb_init_eeprom(struct 
 {
 	struct ieee80211_conf *conf = ieee80211_get_hw_conf(
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev)));
+	u16 reg;
+	u16 value;
 	u16 eeprom;
 
 	/*
@@ -2265,8 +2294,9 @@ static int rt2500usb_init_eeprom(struct 
 	/*
 	 * 2 - Identify RF chipset.
 	 */
-	rt2x00_set_chip(&rt2x00dev->chip, RT2570,
-		rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE));
+	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
+	rt2x00_register_read(rt2x00dev, MAC_CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT2570, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2523) &&
@@ -2317,30 +2347,36 @@ static int rt2500usb_init_mac(struct rt2
 {
 	struct net_device *net_dev =
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
-	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
-		(u16*)&eeprom[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&eeprom[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
-	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt2500usb_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -2776,6 +2812,8 @@ static int rt2500usb_probe(struct usb_in
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -2794,6 +2832,8 @@ static void rt2500usb_disconnect(struct 
 
 	rt2500usb_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt2500usb_uninitialize(rt2x00dev);
 
 	rt2500usb_free_dev(net_dev);
@@ -2813,6 +2853,7 @@ static int rt2500usb_suspend(struct usb_
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -2820,12 +2861,14 @@ static int rt2500usb_suspend(struct usb_
 	 * Disable the radio.
 	 */
 	rt2500usb_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt2500usb_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt2500usb_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -2849,6 +2892,7 @@ static int rt2500usb_resume(struct usb_i
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -2860,15 +2904,22 @@ static int rt2500usb_resume(struct usb_i
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt2500usb_alloc_dev(usb_intf, net_dev)) {
+	status = rt2500usb_alloc_dev(usb_intf, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt2500usb_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt2500usb_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500usb.h b/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
index 917ba4c..7babcb6 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
@@ -46,7 +46,7 @@ #define RF5222				0x0010
  * Register layout information.
  */
 #define CSR_REG_BASE			0x0400
-#define CSR_REG_SIZE			0x00ff
+#define CSR_REG_SIZE			0x0100
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x006a
 
@@ -492,11 +492,13 @@ #define RF3_TXPOWER			FIELD32(0x00003e00
 /*
  * HW MAC address.
  */
-#define EEPROM_MAC_ADDR			0x0004
+#define EEPROM_MAC_ADDR_0		0x0004
 #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0006
 #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0008
 #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2x00.h b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
index 89eee23..e0ae5fe 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
@@ -117,7 +117,7 @@ #define SIFS			10
 #define PREAMBLE		144
 #define SHORT_PREAMBLE		72
 #define SLOT_TIME		20
-#define SHORT_SLOT_TIME		7
+#define SHORT_SLOT_TIME		9
 
 /*
  * TX result flags.
@@ -433,18 +433,32 @@ static inline u16 rt2x00_get_field16_nb(
 struct rt2x00_chip {
 	u16 rt;
 	u16 rf;
+	u16 rev;
+	u8 fw_h;
+	u8 fw_l;
 };
 
 /*
  * Set chipset data.
  */
 static inline void rt2x00_set_chip(struct rt2x00_chip *chipset,
-	const u16 rt, const u16 rf)
+	const u16 rt, const u16 rf, const u16 rev)
 {
-	INFO("Chipset detected - rt: %04x, rf: %04x.\n", rt, rf);
+	INFO("Chipset detected - rt: %04x, rf: %04x, rev: %04x.\n",
+		rt, rf, rev);
 
 	chipset->rt = rt;
 	chipset->rf = rf;
+	chipset->rev = rev;
+}
+
+static inline void rt2x00_set_chip_fw(struct rt2x00_chip *chipset,
+	const u8 fw_h, const u8 fw_l)
+{
+	INFO("Firmware detected - version: %d.%d.\n", fw_h, fw_l);
+
+	chipset->fw_h = fw_h;
+	chipset->fw_l = fw_l;
 }
 
 static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip)
@@ -457,6 +471,16 @@ static inline char rt2x00_rf(const struc
 	return (chipset->rf == chip);
 }
 
+static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset)
+{
+	return chipset->rev;
+}
+
+static inline char* rt2x00_fw(const struct rt2x00_chip *chipset)
+{
+	return chipset->fw_h + "." + chipset->fw_l;
+}
+
 /*
  * data_entry
  * The data ring is a list of data entries.
@@ -984,6 +1008,36 @@ #define DEV_RATEMASK	FIELD32(0x00fff000)
 #define DEV_PLCP	FIELD32(0xff000000)
 
 /*
+ * Bitmask for MASK_RATE
+ */
+#define DEV_RATE_1MB	0x00000001
+#define DEV_RATE_2MB	0x00000002
+#define DEV_RATE_5_5MB	0x00000004
+#define DEV_RATE_11MB	0x00000008
+#define DEV_RATE_6MB	0x00000010
+#define DEV_RATE_9MB	0x00000020
+#define DEV_RATE_12MB	0x00000040
+#define DEV_RATE_18MB	0x00000080
+#define DEV_RATE_24MB	0x00000100
+#define DEV_RATE_36MB	0x00000200
+#define DEV_RATE_48MB	0x00000400
+#define DEV_RATE_54MB	0x00000800
+
+/*
+ * Bitmask groups of bitrates
+ */
+#define DEV_BASIC_RATE \
+	( DEV_RATE_1MB | DEV_RATE_2MB | DEV_RATE_5_5MB | DEV_RATE_11MB | \
+	  DEV_RATE_6MB | DEV_RATE_12MB | DEV_RATE_24MB )
+
+#define DEV_CCK_RATE \
+	( DEV_RATE_1MB | DEV_RATE_2MB | DEV_RATE_5_5MB | DEV_RATE_11MB )
+
+#define DEV_OFDM_RATE \
+	( DEV_RATE_6MB | DEV_RATE_9MB | DEV_RATE_12MB | DEV_RATE_18MB | \
+	  DEV_RATE_24MB | DEV_RATE_36MB | DEV_RATE_48MB | DEV_RATE_54MB )
+
+/*
  * Macro's to set and get specific fields from the device specific val and val2
  * fields inside the ieee80211_rate entry.
  */
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.c b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
index 2157ba2..9a0462a 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
@@ -404,6 +404,7 @@ static void rt61pci_get_drvinfo(struct n
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, rt2x00_fw(&rt2x00dev->chip));
 	strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -420,7 +421,7 @@ static void rt61pci_get_regs(struct net_
 	struct rt2x00_dev	*rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -1042,7 +1043,12 @@ static void rt61pci_config_rate(struct r
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set TXRX_CSR5 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR5, cpu_to_le32(reg));
 
@@ -1359,7 +1365,7 @@ static void rt61pci_init_firmware_cont(c
 		goto exit;
 	}
 
-	DEBUG("Loading Firmware version: %d.%d.\n",
+	rt2x00_set_chip_fw(&rt2x00dev->chip,
 		fw->data[fw->size - 4], fw->data[fw->size - 3]);
 
 	/*
@@ -1691,7 +1697,6 @@ static int rt61pci_init_registers(struct
 
 	rt2x00_register_write(rt2x00dev, MAC_CSR10, cpu_to_le32(0x00000718));
 
-	rt2x00_register_write(rt2x00dev, RX_CNTL_CSR, cpu_to_le32(0x00000001));
 	rt2x00_register_write(rt2x00dev, TXRX_CSR0, cpu_to_le32(0x025eb032));
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR1, cpu_to_le32(0x9eb39eb3));
@@ -1734,7 +1739,7 @@ static int rt61pci_init_registers(struct
 	rt2x00_register_write(rt2x00dev, PHY_CSR6, cpu_to_le32(0x00080606));
 	rt2x00_register_write(rt2x00dev, PHY_CSR7, cpu_to_le32(0x00000a08));
 
-	rt2x00_register_write(rt2x00dev, PCI_CFG_CSR, cpu_to_le32(0x3cca4808));
+	rt2x00_register_write(rt2x00dev, PCI_CFG_CSR, cpu_to_le32(0x28ca4404));
 
 	rt2x00_register_write(rt2x00dev, TEST_MODE_CSR,
 		cpu_to_le32(0x00000200));
@@ -1989,10 +1994,9 @@ static int rt61pci_enable_radio(struct r
 	/*
 	 * Enable interrupts.
 	 */
-	rt2x00_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, 0);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, 0);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, 0);
+	reg = 0;
+	rt2x00_set_field32(&reg, INT_MASK_CSR_TX_ABORT_DONE, 1);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
 	rt2x00_register_write(rt2x00dev, INT_MASK_CSR, reg);
 
 	rt2x00_register_write(rt2x00dev, MCU_INT_MASK_CSR, 0x00000000);
@@ -2000,6 +2004,7 @@ static int rt61pci_enable_radio(struct r
 	/*
 	 * Enable RX.
 	 */
+	rt2x00_register_write(rt2x00dev, RX_CNTL_CSR, cpu_to_le32(0x00000001));
 	rt2x00_register_read(rt2x00dev, TXRX_CSR0, &reg);
 	rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
 	rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg);
@@ -2012,17 +2017,22 @@ static int rt61pci_enable_radio(struct r
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
 	u32 reg;
 
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -2055,10 +2065,8 @@ static void rt61pci_disable_radio(struct
 	/*
 	 * Disable interrupts.
 	 */
-	rt2x00_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE,1);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, 1);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, 1);
+	reg = 0xffffffff;
+	rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, 0);
 	rt2x00_register_write(rt2x00dev, INT_MASK_CSR, reg);
 
 	rt2x00_register_write(rt2x00dev, MCU_INT_MASK_CSR, 0xffffffff);
@@ -2186,11 +2194,9 @@ static void rt61pci_write_tx_desc(struct
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 
 		/*
@@ -2346,6 +2352,7 @@ static void rt61pci_txdone_entry(struct 
 	entry->tx_status.tx_filtered = 0;
 
 	entry->tx_status.queue_length = entry->ring->stats.limit;
+	entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 	/*
 	 * The TXD_W0_RESULT field will only be set when
@@ -2355,12 +2362,13 @@ static void rt61pci_txdone_entry(struct 
 	 */
 	tx_status = rt2x00_get_field32(sta_csr4, STA_CSR4_TX_RESULT);
 	entry->tx_status.ack = 0;
+	entry->tx_status.excessive_retries = 0;
 	if (ack && (tx_status == TX_SUCCESS ||
 	    tx_status == TX_SUCCESS_RETRY))
 		entry->tx_status.ack = 1;
 	else if (ack && tx_status == TX_FAIL_RETRY) {
 		rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-		entry->tx_status.excessive_retries++;
+		entry->tx_status.excessive_retries = 1;
 	}
 
 	rt2x00_bbp_read(rt2x00dev, 32,
@@ -2374,6 +2382,7 @@ static void rt61pci_txdone_entry(struct 
 			entry->skb, &entry->tx_status);
 
 	rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+	CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = NULL;
 
 	/*
@@ -2575,7 +2584,8 @@ static int rt61pci_tx(struct net_device 
 	memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
 	rt61pci_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -2620,10 +2630,6 @@ static int rt61pci_add_interface(struct 
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2639,6 +2645,19 @@ static int rt61pci_add_interface(struct 
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2660,15 +2679,25 @@ static void rt61pci_remove_interface(str
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt61pci_disable_radio(rt2x00dev);
 }
 
@@ -3057,11 +3086,11 @@ static int rt61pci_init_eeprom(struct rt
 	 * To determine the RT chip we have to read the
 	 * PCI header of the device.
 	 */
-	pci_read_config_word(
-		rt2x00dev_pci(rt2x00dev), PCI_CONFIG_HEADER_DEVICE, &device);
-
+	pci_read_config_word(rt2x00dev_pci(rt2x00dev),
+		PCI_CONFIG_HEADER_DEVICE, &device);
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, device, value);
+	rt2x00_register_read(rt2x00dev, MAC_CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, device, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF5325) &&
@@ -3170,30 +3199,36 @@ static int rt61pci_init_eeprom(struct rt
 static int rt61pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
-		(u16*)&eeprom[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&eeprom[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
-	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt61pci_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -3669,6 +3704,8 @@ static int rt61pci_probe(struct pci_dev 
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -3693,6 +3730,8 @@ static void rt61pci_remove(struct pci_de
 
 	rt61pci_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt61pci_uninitialize(rt2x00dev);
 
 	rt61pci_free_dev(net_dev);
@@ -3713,6 +3752,7 @@ static int rt61pci_suspend(struct pci_de
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -3720,12 +3760,14 @@ static int rt61pci_suspend(struct pci_de
 	 * Disable the radio.
 	 */
 	rt61pci_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt61pci_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt61pci_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -3749,6 +3791,7 @@ static int rt61pci_resume(struct pci_dev
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -3765,15 +3808,22 @@ static int rt61pci_resume(struct pci_dev
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt61pci_alloc_dev(pci_dev, net_dev)) {
+	status = rt61pci_alloc_dev(pci_dev, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt61pci_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt61pci_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.h b/drivers/net/wireless/d80211/rt2x00/rt61pci.h
index 2c5065b..77b867d 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.h
@@ -48,7 +48,7 @@ #define RF2529				0x0004
 #define CSR_REG_BASE			0x3000
 #define CSR_REG_SIZE			0x04b0
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x00ff
+#define EEPROM_SIZE			0x0100
 
 /*
  * PCI registers.
@@ -991,11 +991,13 @@ #define RF4_FREQ_OFFSET			FIELD32(0x0003
 /*
  * HW MAC address.
  */
-#define EEPROM_MAC_ADDR			0x0002
+#define EEPROM_MAC_ADDR_0		0x0002
 #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0004
 #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0006
 #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt73usb.c b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
index 682d078..a3b0996 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
@@ -225,6 +225,7 @@ static void rt73usb_get_drvinfo(struct n
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, rt2x00_fw(&rt2x00dev->chip));
 	strcpy(drvinfo->bus_info, rt2x00dev_usb(rt2x00dev)->dev.bus_id);
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -241,7 +242,7 @@ static void rt73usb_get_regs(struct net_
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -270,7 +271,7 @@ static int rt73usb_get_eeprom(struct net
 	eeprom->magic = 0xbad;
 
 	rt2x00_eeprom_multiread(rt2x00dev,
-		eeprom->offset / sizeof(u16), (void*)data, eeprom->len);
+		eeprom->offset, (void*)data, eeprom->len);
 
 	return 0;
 }
@@ -759,7 +760,12 @@ static void rt73usb_config_rate(struct r
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set TXRX_CSR5 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR5, cpu_to_le32(reg));
 
@@ -1070,7 +1076,7 @@ static void rt73usb_init_firmware_cont(c
 		goto exit;
 	}
 
-	DEBUG("Loading Firmware version: %d.%d.\n",
+	rt2x00_set_chip_fw(&rt2x00dev->chip,
 		fw->data[fw->size - 4], fw->data[fw->size - 3]);
 
 	/*
@@ -1594,12 +1600,15 @@ static int rt73usb_enable_radio(struct r
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev =
+		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
 	struct data_ring *ring;
 	u32 reg;
 	unsigned int i;
@@ -1607,6 +1616,9 @@ static void rt73usb_disable_radio(struct
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1781,11 +1793,9 @@ static void rt73usb_write_tx_desc(struct
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 
 		/*
@@ -1963,6 +1973,7 @@ static void rt73usb_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = entry->ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * Check if we have received an
@@ -1970,11 +1981,12 @@ static void rt73usb_txdone(void *data)
 		 * was succesfull.
 		 */
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (urb->status == TX_SUCCESS))
 			entry->tx_status.ack = 1;
 		else {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 32,
@@ -1984,6 +1996,7 @@ static void rt73usb_txdone(void *data)
 			ieee80211_tx_status(ring->net_dev,
 				entry->skb, &entry->tx_status);
 
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(entry->ring);
@@ -2098,7 +2111,8 @@ static int rt73usb_tx(struct net_device 
 	memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
 	rt73usb_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -2141,10 +2155,6 @@ static int rt73usb_add_interface(struct 
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2160,6 +2170,19 @@ static int rt73usb_add_interface(struct 
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2181,15 +2204,25 @@ static void rt73usb_remove_interface(str
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt73usb_disable_radio(rt2x00dev);
 }
 
@@ -2577,6 +2610,7 @@ static int rt73usb_init_eeprom(struct rt
 {
 	struct ieee80211_conf *conf = ieee80211_get_hw_conf(
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev)));
+	u32 reg;
 	u16 value;
 	u16 eeprom;
 
@@ -2589,7 +2623,8 @@ static int rt73usb_init_eeprom(struct rt
 	 * 2 - Identify RF chipset.
 	 */
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, RT73, value);
+	rt2x00_register_read(rt2x00dev, MAC_CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT73, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF5226) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2528) &&
@@ -2682,30 +2717,36 @@ static int rt73usb_init_mac(struct rt2x0
 {
 	struct net_device *net_dev =
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
-	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
-		(u16*)&eeprom[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&eeprom[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
-	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt73usb_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -3137,6 +3178,8 @@ static int rt73usb_probe(struct usb_inte
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -3155,6 +3198,8 @@ static void rt73usb_disconnect(struct us
 
 	rt73usb_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt73usb_uninitialize(rt2x00dev);
 
 	rt73usb_free_dev(net_dev);
@@ -3173,6 +3218,7 @@ static int rt73usb_suspend(struct usb_in
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -3180,12 +3226,14 @@ static int rt73usb_suspend(struct usb_in
 	 * Disable the radio.
 	 */
 	rt73usb_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt73usb_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt73usb_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -3209,6 +3257,7 @@ static int rt73usb_resume(struct usb_int
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -3220,15 +3269,21 @@ static int rt73usb_resume(struct usb_int
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt73usb_alloc_dev(usb_intf, net_dev)) {
+	status = rt73usb_alloc_dev(usb_intf, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt73usb_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt73usb_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt73usb.h b/drivers/net/wireless/d80211/rt2x00/rt73usb.h
index 5be5e14..cc1013c 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt73usb.h
@@ -46,7 +46,7 @@ #define RF2527				0x0004
 #define CSR_REG_BASE			0x3000
 #define CSR_REG_SIZE			0x04b0
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x00ff
+#define EEPROM_SIZE			0x0100
 
 /*
  * USB registers.
@@ -643,11 +643,13 @@ #define RF4_FREQ_OFFSET			FIELD32(0x0003
 /*
  * HW MAC address.
  */
-#define EEPROM_MAC_ADDR			0x0004
+#define EEPROM_MAC_ADDR_0		0x0004
 #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0006
 #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0008
 #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
 
diff --git a/include/linux/ssb.h b/include/linux/ssb.h
index 0673b02..a36dd75 100644
--- a/include/linux/ssb.h
+++ b/include/linux/ssb.h
@@ -100,10 +100,12 @@ #define  SSB_IDLOW_SSBREV	0xF0000000 /* 
 #define  SSB_IDLOW_SSBREV_22	0x00000000 /* <= 2.2 */
 #define  SSB_IDLOW_SSBREV_23	0x10000000 /* 2.3 */
 #define SSB_IDHIGH		0x0FFC     /* SB Identification High */
-#define  SSB_IDHIGH_RC_MASK	0x0000000f /* Revision Code */
-#define  SSB_IDHIGH_CC_MASK	0x0000fff0 /* Core Code */
+#define  SSB_IDHIGH_RCLO	0x0000000F /* Revision Code (low part) */
+#define  SSB_IDHIGH_CC		0x00008FF0 /* Core Code */
 #define  SSB_IDHIGH_CC_SHIFT	4
-#define  SSB_IDHIGH_VC_MASK	0xffff0000 /* Vendor Code */
+#define  SSB_IDHIGH_RCHI	0x00007000 /* Revision Code (high part) */
+#define  SSB_IDHIGH_RCHI_SHIFT	8	   /* yes, shift 8 is right */
+#define  SSB_IDHIGH_VC		0xFFFF0000 /* Vendor Code */
 #define  SSB_IDHIGH_VC_SHIFT	16
 
 /* SPROM shadow area. If not otherwise noted, fields are
@@ -170,7 +172,7 @@ #define SSB_SPROM1_OEM			0x1076	/* 8 byt
 #define SSB_SPROM2_BFLHI		0x1038	/* Boardflags (high 16 bits) */
 #define SSB_SPROM2_MAXP_A		0x103A	/* A-PHY Max Power */
 #define  SSB_SPROM2_MAXP_A_HI		0x00FF	/* Max Power High */
-#define  SSB_SPROM2_MAXP_A_LO		0x1100	/* Max Power Low */
+#define  SSB_SPROM2_MAXP_A_LO		0xFF00	/* Max Power Low */
 #define  SSB_SPROM2_MAXP_A_LO_SHIFT	8
 #define SSB_SPROM2_PA1LOB0		0x103C	/* A-PHY PowerAmplifier Low Settings */
 #define SSB_SPROM2_PA1LOB1		0x103E	/* A-PHY PowerAmplifier Low Settings */
@@ -277,12 +279,40 @@ #define  SSB_CHIPCOMMON_CAP_BROM	0x00800
 #define  SSB_CHIPCOMMON_CAP_64BIT	0x08000000	/* 64-bit Backplane */
 #define SSB_CHIPCOMMON_CORECTL		0x0008
 #define SSB_CHIPCOMMON_BIST		0x000C
+#define SSB_CHIPCOMMON_OTPSTAT		0x0010
+#define SSB_CHIPCOMMON_OTPCTL		0x0014
+#define SSB_CHIPCOMMON_OTPPRG		0x0018
+#define SSB_CHIPCOMMON_IRQSTAT		0x0020
+#define SSB_CHIPCOMMON_IRQMASK		0x0024
+#define SSB_CHIPCOMMON_CHIPCTL		0x0028	/* Rev >= 11 only */
+#define SSB_CHIPCOMMON_CHIPSTAT		0x002C	/* Rev >= 11 only */
+#define SSB_CHIPCOMMON_JTAGCMD		0x0030	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_JTAGIR		0x0034	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_JTAGDR		0x0038	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_JTAGCTL		0x003C	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_FLASHCTL		0x0040
+#define SSB_CHIPCOMMON_FLASHADDR	0x0044
+#define SSB_CHIPCOMMON_FLASHDATA	0x0048
 #define SSB_CHIPCOMMON_BCAST_ADDR	0x0050
 #define SSB_CHIPCOMMON_BCAST_DATA	0x0054
-#define SSB_CHIPCOMMON_PLLONDELAY	0x00B0
-#define SSB_CHIPCOMMON_FREFSELDELAY	0x00B4
-#define SSB_CHIPCOMMON_SLOWCLKCTL	0x00B8
-#define SSB_CHIPCOMMON_SYSCLKCTL	0x00C0
+#define SSB_CHIPCOMMON_GPIOIN		0x0060
+#define SSB_CHIPCOMMON_GPIOOUT		0x0064
+#define SSB_CHIPCOMMON_GPIOOUTEN	0x0068
+#define SSB_CHIPCOMMON_GPIOCTL		0x006C
+#define SSB_CHIPCOMMON_GPIOPOL		0x0070
+#define SSB_CHIPCOMMON_GPIOIRQ		0x0074
+#define SSB_CHIPCOMMON_WATCHDOG		0x0080
+#define SSB_CHIPCOMMON_CLOCK_N		0x0090
+#define SSB_CHIPCOMMON_CLOCK_SB		0x0094
+#define SSB_CHIPCOMMON_CLOCK_PCI	0x0098
+#define SSB_CHIPCOMMON_CLOCK_M2		0x009C
+#define SSB_CHIPCOMMON_CLOCK_MIPS	0x00A0
+#define SSB_CHIPCOMMON_UARTCLKDIV	0x00A4	/* Rev >= 3 only */
+#define SSB_CHIPCOMMON_PLLONDELAY	0x00B0	/* Rev >= 4 only */
+#define SSB_CHIPCOMMON_FREFSELDELAY	0x00B4	/* Rev >= 4 only */
+#define SSB_CHIPCOMMON_SLOWCLKCTL	0x00B8	/* 6 <= Rev <= 9 only */
+#define SSB_CHIPCOMMON_SYSCLKCTL	0x00C0	/* Rev >= 3 only */
+#define SSB_CHIPCOMMON_CLKSTSTR		0x00C4	/* Rev >= 3 only */
 
 /* PCI core registers. */
 #define SSB_PCICORE_CTL		0x0000	/* PCI Control */
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index e72721f..320272c 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -3582,6 +3582,11 @@ void __ieee80211_rx(struct net_device *d
 	else
 		sta = rx.sta = NULL;
 
+	if (sta) {
+		rx.dev = sta->dev;
+		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
+	}
+
         if ((status->flag & RX_FLAG_MMIC_ERROR)) {
 		ieee80211_rx_michael_mic_report(dev, hdr, sta, &rx);
 		goto end;
@@ -3597,8 +3602,6 @@ void __ieee80211_rx(struct net_device *d
 
 	if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
 	    !local->iff_promiscs && !multicast) {
-		rx.dev = sta->dev;
-		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
 		rx.u.rx.ra_match = 1;
 		ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
 					     sta);
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* What's new in wireless-dev?
@ 2006-09-05  0:02 John W. Linville
  0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-09-05  0:02 UTC (permalink / raw)
  To: netdev

I apologize for the announcement delay -- I had a hiccup w/ my mail
server this weekend...

(Sorry if you get this twice, vger's new bogofilter doesn't seem to
be playing nice...)
---

The following changes since commit a7bcae7c095077d89899b2bf0b8d81b8997f340f:
  John W. Linville:
        Merge branch 'from-linus'

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git

David Kimdon:
      d80211: fix crash in ieee80211_rx_michael_mic_report()

Ivo van Doorn:
      rt2x00: Add register revision and firmware version to ethtool
      rt2x00: basic rate mask
      rt2x00: Mac address reading optimization
      rt2x00: add/remove interface fix
      rt2x00: Register initialization fixes
      rt2x00: Respect return values
      rt2x00: Add ieee80211_netif_oper() calls
      rt2x00: change variable name
      rt2x00: TXD/RTS fixes
      rt2x00: Misc fixes

Michael Buesch:
      ssb: minor fixes and cleanups
      ssb: add MAINTAINERS entry
      bcm43xx-d80211: add support for 4312
      ssb: fix core CC and REV reading
      bcm43xx-d80211: 4311 support

 MAINTAINERS                                        |    6 +
 drivers/misc/ssb.c                                 |   23 ++-
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c |   13 ++
 .../net/wireless/d80211/bcm43xx/bcm43xx_power.c    |   27 +++--
 drivers/net/wireless/d80211/rt2x00/rt2400pci.c     |  119 +++++++++++++-----
 drivers/net/wireless/d80211/rt2x00/rt2400pci.h     |   15 ++
 drivers/net/wireless/d80211/rt2x00/rt2500pci.c     |  129 ++++++++++++++------
 drivers/net/wireless/d80211/rt2x00/rt2500pci.h     |   17 ++-
 drivers/net/wireless/d80211/rt2x00/rt2500usb.c     |  127 +++++++++++++------
 drivers/net/wireless/d80211/rt2x00/rt2500usb.h     |    6 +
 drivers/net/wireless/d80211/rt2x00/rt2x00.h        |   60 +++++++++
 drivers/net/wireless/d80211/rt2x00/rt61pci.c       |  132 ++++++++++++++------
 drivers/net/wireless/d80211/rt2x00/rt61pci.h       |    6 +
 drivers/net/wireless/d80211/rt2x00/rt73usb.c       |  113 +++++++++++++----
 drivers/net/wireless/d80211/rt2x00/rt73usb.h       |    6 +
 include/linux/ssb.h                                |   46 ++++++-
 net/d80211/ieee80211.c                             |    7 +
 17 files changed, 632 insertions(+), 220 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8a88b78..783c1ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2650,6 +2650,12 @@ M:	tsbogend@alpha.franken.de
 L:	netdev@vger.kernel.org
 S:	Maintained
 
+SONICS SILICON BACKPLANE DRIVER (SSB)
+P:	Michael Buesch
+M:	mb@bu3sch.de
+L:	netdev@vger.kernel.org
+S:	Maintained
+
 SONY VAIO CONTROL DEVICE DRIVER
 P:	Stelian Pop
 M:	stelian@popies.net
diff --git a/drivers/misc/ssb.c b/drivers/misc/ssb.c
index 55e1447..44ab647 100644
--- a/drivers/misc/ssb.c
+++ b/drivers/misc/ssb.c
@@ -518,7 +518,8 @@ int ssb_init(struct ssb *ssb,
 {
 	int err;
 
-	if (!ssb || !pci_dev || !device_suspend || !device_resume)
+	if (!ssb || !pci_dev || !mmio ||
+	    !device_suspend || !device_resume)
 		return -EINVAL;
 
 	memset(ssb, 0, sizeof(*ssb));
@@ -551,9 +552,9 @@ void ssb_exit(struct ssb *ssb)
 	list_del(&ssb->list);
 	mutex_unlock(&ssb_list_mutex);
 
+	mutex_destroy(&ssb->suspend_mutex);
+	mutex_destroy(&ssb->mutex);
 	kfree(ssb->cores);
-	if (SSB_DEBUG)
-		memset(ssb, 0x5B, sizeof(*ssb));
 }
 EXPORT_SYMBOL_GPL(ssb_exit);
 
@@ -592,8 +593,8 @@ error:
 	return -ENODEV;
 }
 
-int ssb_switch_core_locked(struct ssb *ssb,
-			   struct ssb_core *new_core)
+static int ssb_switch_core_locked(struct ssb *ssb,
+				  struct ssb_core *new_core)
 {
 	int err = 0;
 
@@ -642,8 +643,9 @@ int ssb_probe_cores(struct ssb *ssb,
 		goto error;
 
 	idhi = ssb_read32(ssb, SSB_IDHIGH);
-	cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
-	rev = (idhi & SSB_IDHIGH_RC_MASK);
+	cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+	rev = (idhi & SSB_IDHIGH_RCLO);
+	rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
 
 	ssb->chipcommon_capabilities = 0;
 	ssb->nr_cores = 0;
@@ -715,9 +717,10 @@ int ssb_probe_cores(struct ssb *ssb,
 		core = &(ssb->cores[i]);
 
 		idhi = ssb_read32(ssb, SSB_IDHIGH);
-		core->cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
-		core->rev = (idhi & SSB_IDHIGH_RC_MASK);
-		core->vendor = (idhi & SSB_IDHIGH_VC_MASK) >> SSB_IDHIGH_VC_SHIFT;
+		core->cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+		core->rev = (idhi & SSB_IDHIGH_RCLO);
+		core->rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
+		core->vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
 		core->index = i;
 
 		dprintk(KERN_DEBUG PFX "Core %d found: "
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
index b47f006..d71d797 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -129,6 +129,10 @@ static struct pci_device_id bcm43xx_pci_
 	{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4307 802.11b */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 4311 802.11a/b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 4312 802.11a/b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4318 802.11b/g */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4319 802.11b/g */
@@ -2299,7 +2303,9 @@ static int bcm43xx_wireless_core_init(st
 	u32 sbimconfiglow;
 	u8 limit;
 
-	if (bcm->ssb.chip_rev < 5) {
+	assert(bcm->core_pci);
+	if (bcm->core_pci->cc == SSB_CC_PCI &&
+	    bcm->core_pci->rev <= 5) {
 		sbimconfiglow = bcm43xx_read32(bcm, SSB_IMCFGLO);
 		sbimconfiglow &= ~SSB_IMCFGLO_REQTO;
 		sbimconfiglow &= ~SSB_IMCFGLO_SERTO;
@@ -2710,6 +2716,7 @@ #endif
 
 		switch (core->cc) {
 		case SSB_CC_PCI:
+		case SSB_CC_PCIE:
 			if (bcm->core_pci) {
 				printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
 				break;
@@ -2742,7 +2749,7 @@ #endif
 
 			switch (core->rev) {
 			case 2: case 4: case 5: case 6:
-			case 7: case 9:
+			case 7: case 9: case 10:
 				break;
 			default:
 				printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
@@ -3247,7 +3254,7 @@ static int bcm43xx_read_phyinfo(struct b
 			phy_rev_ok = 0;
 		break;
 	case BCM43xx_PHYTYPE_G:
-		if (phy_rev > 7)
+		if (phy_rev > 8)
 			phy_rev_ok = 0;
 		break;
 	default:
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
index 6aa2a33..702af69 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
@@ -153,8 +153,6 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
 	int err, maxfreq;
 	struct ssb_core *old_core;
 
-	if (!(bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL))
-		return 0;
 	if (!bcm->core_chipcommon)
 		return 0;
 
@@ -163,11 +161,26 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
 	if (err)
 		goto out;
 
-	maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
-	bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
-			(maxfreq * 150 + 999999) / 1000000);
-	bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
-			(maxfreq * 15 + 999999) / 1000000);
+	if (bcm->ssb.chip_id == 0x4321) {
+		if (bcm->ssb.chip_rev == 0)
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x03A4);
+		else if (bcm->ssb.chip_rev == 1)
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x00A4);
+	}
+	if (bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL) {
+		if (bcm->core_chipcommon->rev >= 10) {
+			/* Set Idle Power clock rate to 1Mhz */
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_SYSCLKCTL,
+					(bcm43xx_read32(bcm, SSB_CHIPCOMMON_SYSCLKCTL) &
+					 0x0000FFFF) | 0x00040000);
+		} else {
+			maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
+					(maxfreq * 150 + 999999) / 1000000);
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
+					(maxfreq * 15 + 999999) / 1000000);
+		}
+	}
 
 	err = ssb_switch_core(&bcm->ssb, old_core);
 	assert(err == 0);
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
index 00f3a66..59163bf 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
@@ -373,6 +373,7 @@ static void rt2400pci_get_drvinfo(struct
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, "N/A");
 	strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -389,7 +390,7 @@ static void rt2400pci_get_regs(struct ne
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -751,7 +752,12 @@ static void rt2400pci_config_rate(struct
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set ARCSR1 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, ARCSR1, cpu_to_le32(reg[0]));
 
@@ -767,12 +773,12 @@ static void rt2400pci_config_rate(struct
 	rt2x00_set_field32(&reg[0], TXCSR1_ACK_CONSUME_TIME, value);
 	rt2x00_register_write(rt2x00dev, TXCSR1, reg[0]);
 
-	value = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
+	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
 
-	reg[0] = cpu_to_le32(0x00700400 | value);	/* ARCSR2 */
-	reg[1] = cpu_to_le32(0x00380401 | value);	/* ARCSR3 */
-	reg[2] = cpu_to_le32(0x00150402 | value);	/* ARCSR4 */
-	reg[3] = cpu_to_le32(0x000b8403 | value);	/* ARCSR5 */
+	reg[0] = cpu_to_le32(0x00700400 | preamble);	/* ARCSR2 */
+	reg[1] = cpu_to_le32(0x00380401 | preamble);	/* ARCSR3 */
+	reg[2] = cpu_to_le32(0x00150402 | preamble);	/* ARCSR4 */
+	reg[3] = cpu_to_le32(0x000b8403 | preamble);	/* ARCSR5 */
 
 	rt2x00_register_multiwrite(rt2x00dev, ARCSR2, &reg[0], sizeof(reg));
 }
@@ -1186,11 +1192,7 @@ static int rt2400pci_init_registers(stru
 	rt2x00_register_write(rt2x00dev, RXCSR0, reg);
 
 	rt2x00_register_write(rt2x00dev, MACCSR0, cpu_to_le32(0x00217223));
-
-	rt2x00_register_read(rt2x00dev, MACCSR1, &reg);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_TXBBP, 1);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_RXBBP, 1);
-	rt2x00_register_write(rt2x00dev, MACCSR1, reg);
+	rt2x00_register_write(rt2x00dev, MACCSR1, cpu_to_le32(0x00235518));
 
 	rt2x00_register_read(rt2x00dev, MACCSR2, &reg);
 	rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
@@ -1463,17 +1465,22 @@ static int rt2400pci_enable_radio(struct
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
 	u32 reg;
 
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1760,6 +1767,7 @@ static void rt2400pci_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * The TXD_W0_RESULT field will only be set when
@@ -1769,12 +1777,13 @@ static void rt2400pci_txdone(void *data)
 		 */
 		tx_status = rt2x00_get_field32(txd->word0, TXD_W0_RESULT);
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (tx_status == TX_SUCCESS ||
 		    tx_status == TX_SUCCESS_RETRY))
 			entry->tx_status.ack = 1;
 		else if (ack && tx_status == TX_FAIL_RETRY) {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 32,
@@ -1788,6 +1797,7 @@ static void rt2400pci_txdone(void *data)
 				entry->skb, &entry->tx_status);
 
 		rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(ring);
@@ -1954,7 +1964,8 @@ static int rt2400pci_tx(struct net_devic
 	memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
 	rt2400pci_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -1995,10 +2006,6 @@ static int rt2400pci_add_interface(struc
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2014,6 +2021,19 @@ static int rt2400pci_add_interface(struc
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2035,15 +2055,25 @@ static void rt2400pci_remove_interface(s
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt2400pci_disable_radio(rt2x00dev);
 }
 
@@ -2450,7 +2480,8 @@ static int rt2400pci_init_eeprom(struct 
 	 * 3 - Identify RF chipset.
 	 */
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, RT2460, value);
+	rt2x00_register_read(rt2x00dev, CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT2460, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2420) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2421))
@@ -2493,29 +2524,36 @@ static int rt2400pci_init_eeprom(struct 
 static int rt2400pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u8 reg[8];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
-	 * Read MAC address from MAC register.
+	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_register_multiread(rt2x00dev, CSR3, (u32*)&reg[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&reg[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &reg[0], 6);
-	memcpy(&net_dev->perm_addr[0], &reg[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt2400pci_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -2864,6 +2902,8 @@ static int rt2400pci_probe(struct pci_de
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -2888,6 +2928,8 @@ static void rt2400pci_remove(struct pci_
 
 	rt2400pci_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt2400pci_uninitialize(rt2x00dev);
 
 	rt2400pci_free_dev(net_dev);
@@ -2908,6 +2950,7 @@ static int rt2400pci_suspend(struct pci_
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -2915,12 +2958,14 @@ static int rt2400pci_suspend(struct pci_
 	 * Disable the radio.
 	 */
 	rt2400pci_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt2400pci_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt2400pci_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -2944,6 +2989,7 @@ static int rt2400pci_resume(struct pci_d
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -2960,15 +3006,22 @@ static int rt2400pci_resume(struct pci_d
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt2400pci_alloc_dev(pci_dev, net_dev)) {
+	status = rt2400pci_alloc_dev(pci_dev, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt2400pci_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt2400pci_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.h b/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
index ae0ea54..a991b59 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
@@ -44,7 +44,7 @@ #define RF2421				0x0001
 #define CSR_REG_BASE			0x0000
 #define CSR_REG_SIZE			0x014c
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x00ff
+#define EEPROM_SIZE			0x0100
 
 /*
  * Control/Status Registers(CSR).
@@ -705,6 +705,19 @@ #define RF3_TXPOWER			FIELD32(0x00003e00
  */
 
 /*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0		0x0002
+#define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0003
+#define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0004
+#define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
+
+/*
  * EEPROM antenna.
  * ANTENNA_NUM: Number of antenna's.
  * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
index 3f6dd94..651fbec 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
@@ -373,6 +373,7 @@ static void rt2500pci_get_drvinfo(struct
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, "N/A");
 	strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -389,7 +390,7 @@ static void rt2500pci_get_regs(struct ne
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -817,7 +818,12 @@ static void rt2500pci_config_rate(struct
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set ARCSR1 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, ARCSR1, cpu_to_le32(reg[0]));
 
@@ -833,12 +839,12 @@ static void rt2500pci_config_rate(struct
 	rt2x00_set_field32(&reg[0], TXCSR1_ACK_CONSUME_TIME, value);
 	rt2x00_register_write(rt2x00dev, TXCSR1, reg[0]);
 
-	value = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
+	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
 
-	reg[0] = cpu_to_le32(0x00700400 | value);	/* ARCSR2 */
-	reg[1] = cpu_to_le32(0x00380401 | value);	/* ARCSR3 */
-	reg[2] = cpu_to_le32(0x00150402 | value);	/* ARCSR4 */
-	reg[3] = cpu_to_le32(0x000b8403 | value);	/* ARCSR5 */
+	reg[0] = cpu_to_le32(0x00700400 | preamble);	/* ARCSR2 */
+	reg[1] = cpu_to_le32(0x00380401 | preamble);	/* ARCSR3 */
+	reg[2] = cpu_to_le32(0x00150402 | preamble);	/* ARCSR4 */
+	reg[3] = cpu_to_le32(0x000b8403 | preamble);	/* ARCSR5 */
 
 	rt2x00_register_multiwrite(rt2x00dev, ARCSR2, &reg[0], sizeof(reg));
 }
@@ -1243,6 +1249,7 @@ static int rt2500pci_init_registers(stru
 		return -EBUSY;
 
 	rt2x00_register_write(rt2x00dev, PWRCSR0, cpu_to_le32(0x3f3b3100));
+	rt2x00_register_write(rt2x00dev, PCICSR, cpu_to_le32(0x000003b8));
 
 	rt2x00_register_write(rt2x00dev, PSCSR0, cpu_to_le32(0x00020002));
 	rt2x00_register_write(rt2x00dev, PSCSR1, cpu_to_le32(0x00000002));
@@ -1266,12 +1273,11 @@ static int rt2500pci_init_registers(stru
 	rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
 	rt2x00_register_write(rt2x00dev, RXCSR0, reg);
 
-	rt2x00_register_write(rt2x00dev, MACCSR0, cpu_to_le32(0x00213223));
+	rt2x00_register_write(rt2x00dev, GPIOCSR, cpu_to_le32(0x0000ff00));
+	rt2x00_register_write(rt2x00dev, TESTCSR, cpu_to_le32(0x000000f0));
 
-	rt2x00_register_read(rt2x00dev, MACCSR1, &reg);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_TXBBP, 1);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_RXBBP, 1);
-	rt2x00_register_write(rt2x00dev, MACCSR1, reg);
+	rt2x00_register_write(rt2x00dev, MACCSR0, cpu_to_le32(0x00213223));
+	rt2x00_register_write(rt2x00dev, MACCSR1, cpu_to_le32(0x00235518));
 
 	rt2x00_register_read(rt2x00dev, MACCSR2, &reg);
 	rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
@@ -1583,17 +1589,22 @@ static int rt2500pci_enable_radio(struct
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
 	u32 reg;
 
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1739,11 +1750,9 @@ static void rt2500pci_write_tx_desc(stru
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 		residual = 0;
 
@@ -1907,6 +1916,7 @@ static void rt2500pci_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * The TXD_W0_RESULT field will only be set when
@@ -1916,12 +1926,13 @@ static void rt2500pci_txdone(void *data)
 		 */
 		tx_status = rt2x00_get_field32(txd->word0, TXD_W0_RESULT);
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (tx_status == TX_SUCCESS ||
 		    tx_status == TX_SUCCESS_RETRY))
 			entry->tx_status.ack = 1;
 		else if (ack && tx_status == TX_FAIL_RETRY) {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 32,
@@ -1935,6 +1946,7 @@ static void rt2500pci_txdone(void *data)
 				entry->skb, &entry->tx_status);
 
 		rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(ring);
@@ -2101,7 +2113,8 @@ static int rt2500pci_tx(struct net_devic
 	memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
 	rt2500pci_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -2142,10 +2155,6 @@ static int rt2500pci_add_interface(struc
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2161,6 +2170,19 @@ static int rt2500pci_add_interface(struc
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2182,15 +2204,25 @@ static void rt2500pci_remove_interface(s
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt2500pci_disable_radio(rt2x00dev);
 }
 
@@ -2589,7 +2621,8 @@ static int rt2500pci_init_eeprom(struct 
 	 * 3 - Identify RF chipset.
 	 */
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, RT2560, value);
+	rt2x00_register_read(rt2x00dev, CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT2560, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2523) &&
@@ -2645,29 +2678,36 @@ static int rt2500pci_init_eeprom(struct 
 static int rt2500pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u8 reg[8];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
-	 * Read MAC address from MAC register.
+	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_register_multiread(rt2x00dev, CSR3, (u32*)&reg[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&reg[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &reg[0], 6);
-	memcpy(&net_dev->perm_addr[0], &reg[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt2500pci_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -3147,6 +3187,8 @@ static int rt2500pci_probe(struct pci_de
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -3171,6 +3213,8 @@ static void rt2500pci_remove(struct pci_
 
 	rt2500pci_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt2500pci_uninitialize(rt2x00dev);
 
 	rt2500pci_free_dev(net_dev);
@@ -3191,6 +3235,7 @@ static int rt2500pci_suspend(struct pci_
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -3198,12 +3243,14 @@ static int rt2500pci_suspend(struct pci_
 	 * Disable the radio.
 	 */
 	rt2500pci_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt2500pci_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt2500pci_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -3227,6 +3274,7 @@ static int rt2500pci_resume(struct pci_d
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -3243,15 +3291,22 @@ static int rt2500pci_resume(struct pci_d
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt2500pci_alloc_dev(pci_dev, net_dev)) {
+	status = rt2500pci_alloc_dev(pci_dev, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt2500pci_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt2500pci_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.h b/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
index 8ef5ae5..fb44881 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
@@ -55,7 +55,7 @@ #define RT2560_VERSION_D		4
 #define CSR_REG_BASE			0x0000
 #define CSR_REG_SIZE			0x0174
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x01ff
+#define EEPROM_SIZE			0x0200
 
 /*
  * Control/Status Registers(CSR).
@@ -542,7 +542,7 @@ #define ARCSR1_AR_BBP_ID3		FIELD32(0xff0
  */
 
 /*
- * PCISR: PCI control register.
+ * PCICSR: PCI control register.
  * BIG_ENDIAN: 1: big endian, 0: little endian.
  * RX_TRESHOLD: Rx threshold in dw to start pci access
  * 0: 16dw (default), 1: 8dw, 2: 4dw, 3: 32dw.
@@ -935,6 +935,19 @@ #define RF3_TXPOWER			FIELD32(0x00003e00
  */
 
 /*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0		0x0002
+#define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0003
+#define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0004
+#define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
+
+/*
  * EEPROM antenna.
  * ANTENNA_NUM: Number of antenna's.
  * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
index 383f4a9..5d119cd 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
@@ -224,6 +224,7 @@ static void rt2500usb_get_drvinfo(struct
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, "N/A");
 	strcpy(drvinfo->bus_info, rt2x00dev_usb(rt2x00dev)->dev.bus_id);
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -240,7 +241,7 @@ static void rt2500usb_get_regs(struct ne
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u16*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -269,7 +270,7 @@ static int rt2500usb_get_eeprom(struct n
 	eeprom->magic = 0xbad;
 
 	rt2x00_eeprom_multiread(rt2x00dev,
-		eeprom->offset / sizeof(u16), (void*)data, eeprom->len);
+		eeprom->offset, (void*)data, eeprom->len);
 
 	return 0;
 }
@@ -629,15 +630,9 @@ static void rt2500usb_config_antenna(str
 static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
 	int short_slot_time)
 {
-	u16 reg;
-
 	short_slot_time = short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME;
 
 	rt2x00_register_write(rt2x00dev, MAC_CSR10, (u16)short_slot_time);
-
-	rt2x00_register_read(rt2x00dev, TXRX_CSR1, &reg);
-	rt2x00_set_field16_nb(&reg, TXRX_CSR1_TSF_OFFSET, IEEE80211_HEADER);
-	rt2x00_register_write(rt2x00dev, TXRX_CSR1, reg);
 }
 
 static void rt2500usb_config_rate(struct rt2x00_dev *rt2x00dev, const int rate)
@@ -651,7 +646,12 @@ static void rt2500usb_config_rate(struct
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set TXRX_CSR11 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR11, reg);
 
@@ -844,7 +844,7 @@ static int rt2500usb_set_state(struct rt
 
 	put_to_sleep = (state != STATE_AWAKE);
 
-	rt2x00_register_read(rt2x00dev, MAC_CSR17, &reg);
+	reg = 0;
 	rt2x00_set_field16_nb(&reg, MAC_CSR17_BBP_DESIRE_STATE, state);
 	rt2x00_set_field16_nb(&reg, MAC_CSR17_RF_DESIRE_STATE, state);
 	rt2x00_set_field16_nb(&reg, MAC_CSR17_PUT_TO_SLEEP, put_to_sleep);
@@ -866,7 +866,7 @@ static int rt2500usb_set_state(struct rt
 		if (bbp_state == state && rf_state == state)
 			return 0;
 		rt2x00_register_write(rt2x00dev, MAC_CSR17, reg);
-		msleep(10);
+		msleep(30);
 	}
 
 	NOTICE("Device failed to enter state %d, "
@@ -1092,7 +1092,7 @@ static int rt2500usb_init_registers(stru
 	}
 	rt2x00_register_write(rt2x00dev, PHY_CSR2, reg);
 
-	rt2x00_register_write(rt2x00dev, MAC_CSR11, 0x0002);
+	rt2x00_register_write(rt2x00dev, MAC_CSR11, 0x0005);
 	rt2x00_register_write(rt2x00dev, MAC_CSR22, 0x0053);
 	rt2x00_register_write(rt2x00dev, MAC_CSR15, 0x01ee);
 	rt2x00_register_write(rt2x00dev, MAC_CSR16, 0x0000);
@@ -1335,12 +1335,15 @@ static int rt2500usb_enable_radio(struct
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev =
+		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
 	struct data_ring *ring;
 	u16 reg;
 	unsigned int i;
@@ -1348,6 +1351,9 @@ static void rt2500usb_disable_radio(stru
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1499,11 +1505,9 @@ static void rt2500usb_write_tx_desc(stru
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 		residual = 0;
 
@@ -1679,6 +1683,7 @@ static void rt2500usb_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = entry->ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * Check if we have received an
@@ -1686,11 +1691,12 @@ static void rt2500usb_txdone(void *data)
 		 * was succesfull.
 		 */
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (urb->status == TX_SUCCESS))
 			entry->tx_status.ack = 1;
 		else if (ack && urb->status == TX_FAIL_OTHER) {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 0,
@@ -1700,6 +1706,7 @@ static void rt2500usb_txdone(void *data)
 			ieee80211_tx_status(ring->net_dev,
 				entry->skb, &entry->tx_status);
 
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(entry->ring);
@@ -1815,7 +1822,8 @@ static int rt2500usb_tx(struct net_devic
 	memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
 	rt2500usb_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -1858,10 +1866,6 @@ static int rt2500usb_add_interface(struc
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -1877,6 +1881,19 @@ static int rt2500usb_add_interface(struc
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -1898,15 +1915,25 @@ static void rt2500usb_remove_interface(s
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt2500usb_disable_radio(rt2x00dev);
 }
 
@@ -2255,6 +2282,8 @@ static int rt2500usb_init_eeprom(struct 
 {
 	struct ieee80211_conf *conf = ieee80211_get_hw_conf(
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev)));
+	u16 reg;
+	u16 value;
 	u16 eeprom;
 
 	/*
@@ -2265,8 +2294,9 @@ static int rt2500usb_init_eeprom(struct 
 	/*
 	 * 2 - Identify RF chipset.
 	 */
-	rt2x00_set_chip(&rt2x00dev->chip, RT2570,
-		rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE));
+	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
+	rt2x00_register_read(rt2x00dev, MAC_CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT2570, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2523) &&
@@ -2317,30 +2347,36 @@ static int rt2500usb_init_mac(struct rt2
 {
 	struct net_device *net_dev =
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
-	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
-		(u16*)&eeprom[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&eeprom[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
-	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt2500usb_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -2776,6 +2812,8 @@ static int rt2500usb_probe(struct usb_in
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -2794,6 +2832,8 @@ static void rt2500usb_disconnect(struct 
 
 	rt2500usb_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt2500usb_uninitialize(rt2x00dev);
 
 	rt2500usb_free_dev(net_dev);
@@ -2813,6 +2853,7 @@ static int rt2500usb_suspend(struct usb_
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -2820,12 +2861,14 @@ static int rt2500usb_suspend(struct usb_
 	 * Disable the radio.
 	 */
 	rt2500usb_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt2500usb_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt2500usb_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -2849,6 +2892,7 @@ static int rt2500usb_resume(struct usb_i
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -2860,15 +2904,22 @@ static int rt2500usb_resume(struct usb_i
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt2500usb_alloc_dev(usb_intf, net_dev)) {
+	status = rt2500usb_alloc_dev(usb_intf, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt2500usb_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt2500usb_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500usb.h b/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
index 917ba4c..7babcb6 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
@@ -46,7 +46,7 @@ #define RF5222				0x0010
  * Register layout information.
  */
 #define CSR_REG_BASE			0x0400
-#define CSR_REG_SIZE			0x00ff
+#define CSR_REG_SIZE			0x0100
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x006a
 
@@ -492,11 +492,13 @@ #define RF3_TXPOWER			FIELD32(0x00003e00
 /*
  * HW MAC address.
  */
-#define EEPROM_MAC_ADDR			0x0004
+#define EEPROM_MAC_ADDR_0		0x0004
 #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0006
 #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0008
 #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2x00.h b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
index 89eee23..e0ae5fe 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
@@ -117,7 +117,7 @@ #define SIFS			10
 #define PREAMBLE		144
 #define SHORT_PREAMBLE		72
 #define SLOT_TIME		20
-#define SHORT_SLOT_TIME		7
+#define SHORT_SLOT_TIME		9
 
 /*
  * TX result flags.
@@ -433,18 +433,32 @@ static inline u16 rt2x00_get_field16_nb(
 struct rt2x00_chip {
 	u16 rt;
 	u16 rf;
+	u16 rev;
+	u8 fw_h;
+	u8 fw_l;
 };
 
 /*
  * Set chipset data.
  */
 static inline void rt2x00_set_chip(struct rt2x00_chip *chipset,
-	const u16 rt, const u16 rf)
+	const u16 rt, const u16 rf, const u16 rev)
 {
-	INFO("Chipset detected - rt: %04x, rf: %04x.\n", rt, rf);
+	INFO("Chipset detected - rt: %04x, rf: %04x, rev: %04x.\n",
+		rt, rf, rev);
 
 	chipset->rt = rt;
 	chipset->rf = rf;
+	chipset->rev = rev;
+}
+
+static inline void rt2x00_set_chip_fw(struct rt2x00_chip *chipset,
+	const u8 fw_h, const u8 fw_l)
+{
+	INFO("Firmware detected - version: %d.%d.\n", fw_h, fw_l);
+
+	chipset->fw_h = fw_h;
+	chipset->fw_l = fw_l;
 }
 
 static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip)
@@ -457,6 +471,16 @@ static inline char rt2x00_rf(const struc
 	return (chipset->rf == chip);
 }
 
+static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset)
+{
+	return chipset->rev;
+}
+
+static inline char* rt2x00_fw(const struct rt2x00_chip *chipset)
+{
+	return chipset->fw_h + "." + chipset->fw_l;
+}
+
 /*
  * data_entry
  * The data ring is a list of data entries.
@@ -984,6 +1008,36 @@ #define DEV_RATEMASK	FIELD32(0x00fff000)
 #define DEV_PLCP	FIELD32(0xff000000)
 
 /*
+ * Bitmask for MASK_RATE
+ */
+#define DEV_RATE_1MB	0x00000001
+#define DEV_RATE_2MB	0x00000002
+#define DEV_RATE_5_5MB	0x00000004
+#define DEV_RATE_11MB	0x00000008
+#define DEV_RATE_6MB	0x00000010
+#define DEV_RATE_9MB	0x00000020
+#define DEV_RATE_12MB	0x00000040
+#define DEV_RATE_18MB	0x00000080
+#define DEV_RATE_24MB	0x00000100
+#define DEV_RATE_36MB	0x00000200
+#define DEV_RATE_48MB	0x00000400
+#define DEV_RATE_54MB	0x00000800
+
+/*
+ * Bitmask groups of bitrates
+ */
+#define DEV_BASIC_RATE \
+	( DEV_RATE_1MB | DEV_RATE_2MB | DEV_RATE_5_5MB | DEV_RATE_11MB | \
+	  DEV_RATE_6MB | DEV_RATE_12MB | DEV_RATE_24MB )
+
+#define DEV_CCK_RATE \
+	( DEV_RATE_1MB | DEV_RATE_2MB | DEV_RATE_5_5MB | DEV_RATE_11MB )
+
+#define DEV_OFDM_RATE \
+	( DEV_RATE_6MB | DEV_RATE_9MB | DEV_RATE_12MB | DEV_RATE_18MB | \
+	  DEV_RATE_24MB | DEV_RATE_36MB | DEV_RATE_48MB | DEV_RATE_54MB )
+
+/*
  * Macro's to set and get specific fields from the device specific val and val2
  * fields inside the ieee80211_rate entry.
  */
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.c b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
index 2157ba2..9a0462a 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
@@ -404,6 +404,7 @@ static void rt61pci_get_drvinfo(struct n
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, rt2x00_fw(&rt2x00dev->chip));
 	strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -420,7 +421,7 @@ static void rt61pci_get_regs(struct net_
 	struct rt2x00_dev	*rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -1042,7 +1043,12 @@ static void rt61pci_config_rate(struct r
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set TXRX_CSR5 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR5, cpu_to_le32(reg));
 
@@ -1359,7 +1365,7 @@ static void rt61pci_init_firmware_cont(c
 		goto exit;
 	}
 
-	DEBUG("Loading Firmware version: %d.%d.\n",
+	rt2x00_set_chip_fw(&rt2x00dev->chip,
 		fw->data[fw->size - 4], fw->data[fw->size - 3]);
 
 	/*
@@ -1691,7 +1697,6 @@ static int rt61pci_init_registers(struct
 
 	rt2x00_register_write(rt2x00dev, MAC_CSR10, cpu_to_le32(0x00000718));
 
-	rt2x00_register_write(rt2x00dev, RX_CNTL_CSR, cpu_to_le32(0x00000001));
 	rt2x00_register_write(rt2x00dev, TXRX_CSR0, cpu_to_le32(0x025eb032));
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR1, cpu_to_le32(0x9eb39eb3));
@@ -1734,7 +1739,7 @@ static int rt61pci_init_registers(struct
 	rt2x00_register_write(rt2x00dev, PHY_CSR6, cpu_to_le32(0x00080606));
 	rt2x00_register_write(rt2x00dev, PHY_CSR7, cpu_to_le32(0x00000a08));
 
-	rt2x00_register_write(rt2x00dev, PCI_CFG_CSR, cpu_to_le32(0x3cca4808));
+	rt2x00_register_write(rt2x00dev, PCI_CFG_CSR, cpu_to_le32(0x28ca4404));
 
 	rt2x00_register_write(rt2x00dev, TEST_MODE_CSR,
 		cpu_to_le32(0x00000200));
@@ -1989,10 +1994,9 @@ static int rt61pci_enable_radio(struct r
 	/*
 	 * Enable interrupts.
 	 */
-	rt2x00_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, 0);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, 0);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, 0);
+	reg = 0;
+	rt2x00_set_field32(&reg, INT_MASK_CSR_TX_ABORT_DONE, 1);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
 	rt2x00_register_write(rt2x00dev, INT_MASK_CSR, reg);
 
 	rt2x00_register_write(rt2x00dev, MCU_INT_MASK_CSR, 0x00000000);
@@ -2000,6 +2004,7 @@ static int rt61pci_enable_radio(struct r
 	/*
 	 * Enable RX.
 	 */
+	rt2x00_register_write(rt2x00dev, RX_CNTL_CSR, cpu_to_le32(0x00000001));
 	rt2x00_register_read(rt2x00dev, TXRX_CSR0, &reg);
 	rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
 	rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg);
@@ -2012,17 +2017,22 @@ static int rt61pci_enable_radio(struct r
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
 	u32 reg;
 
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -2055,10 +2065,8 @@ static void rt61pci_disable_radio(struct
 	/*
 	 * Disable interrupts.
 	 */
-	rt2x00_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE,1);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, 1);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, 1);
+	reg = 0xffffffff;
+	rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, 0);
 	rt2x00_register_write(rt2x00dev, INT_MASK_CSR, reg);
 
 	rt2x00_register_write(rt2x00dev, MCU_INT_MASK_CSR, 0xffffffff);
@@ -2186,11 +2194,9 @@ static void rt61pci_write_tx_desc(struct
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 
 		/*
@@ -2346,6 +2352,7 @@ static void rt61pci_txdone_entry(struct 
 	entry->tx_status.tx_filtered = 0;
 
 	entry->tx_status.queue_length = entry->ring->stats.limit;
+	entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 	/*
 	 * The TXD_W0_RESULT field will only be set when
@@ -2355,12 +2362,13 @@ static void rt61pci_txdone_entry(struct 
 	 */
 	tx_status = rt2x00_get_field32(sta_csr4, STA_CSR4_TX_RESULT);
 	entry->tx_status.ack = 0;
+	entry->tx_status.excessive_retries = 0;
 	if (ack && (tx_status == TX_SUCCESS ||
 	    tx_status == TX_SUCCESS_RETRY))
 		entry->tx_status.ack = 1;
 	else if (ack && tx_status == TX_FAIL_RETRY) {
 		rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-		entry->tx_status.excessive_retries++;
+		entry->tx_status.excessive_retries = 1;
 	}
 
 	rt2x00_bbp_read(rt2x00dev, 32,
@@ -2374,6 +2382,7 @@ static void rt61pci_txdone_entry(struct 
 			entry->skb, &entry->tx_status);
 
 	rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+	CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = NULL;
 
 	/*
@@ -2575,7 +2584,8 @@ static int rt61pci_tx(struct net_device 
 	memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
 	rt61pci_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -2620,10 +2630,6 @@ static int rt61pci_add_interface(struct 
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2639,6 +2645,19 @@ static int rt61pci_add_interface(struct 
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2660,15 +2679,25 @@ static void rt61pci_remove_interface(str
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt61pci_disable_radio(rt2x00dev);
 }
 
@@ -3057,11 +3086,11 @@ static int rt61pci_init_eeprom(struct rt
 	 * To determine the RT chip we have to read the
 	 * PCI header of the device.
 	 */
-	pci_read_config_word(
-		rt2x00dev_pci(rt2x00dev), PCI_CONFIG_HEADER_DEVICE, &device);
-
+	pci_read_config_word(rt2x00dev_pci(rt2x00dev),
+		PCI_CONFIG_HEADER_DEVICE, &device);
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, device, value);
+	rt2x00_register_read(rt2x00dev, MAC_CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, device, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF5325) &&
@@ -3170,30 +3199,36 @@ static int rt61pci_init_eeprom(struct rt
 static int rt61pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
-		(u16*)&eeprom[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&eeprom[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
-	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt61pci_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -3669,6 +3704,8 @@ static int rt61pci_probe(struct pci_dev 
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -3693,6 +3730,8 @@ static void rt61pci_remove(struct pci_de
 
 	rt61pci_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt61pci_uninitialize(rt2x00dev);
 
 	rt61pci_free_dev(net_dev);
@@ -3713,6 +3752,7 @@ static int rt61pci_suspend(struct pci_de
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -3720,12 +3760,14 @@ static int rt61pci_suspend(struct pci_de
 	 * Disable the radio.
 	 */
 	rt61pci_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt61pci_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt61pci_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -3749,6 +3791,7 @@ static int rt61pci_resume(struct pci_dev
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -3765,15 +3808,22 @@ static int rt61pci_resume(struct pci_dev
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt61pci_alloc_dev(pci_dev, net_dev)) {
+	status = rt61pci_alloc_dev(pci_dev, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt61pci_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt61pci_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.h b/drivers/net/wireless/d80211/rt2x00/rt61pci.h
index 2c5065b..77b867d 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.h
@@ -48,7 +48,7 @@ #define RF2529				0x0004
 #define CSR_REG_BASE			0x3000
 #define CSR_REG_SIZE			0x04b0
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x00ff
+#define EEPROM_SIZE			0x0100
 
 /*
  * PCI registers.
@@ -991,11 +991,13 @@ #define RF4_FREQ_OFFSET			FIELD32(0x0003
 /*
  * HW MAC address.
  */
-#define EEPROM_MAC_ADDR			0x0002
+#define EEPROM_MAC_ADDR_0		0x0002
 #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0004
 #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0006
 #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt73usb.c b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
index 682d078..a3b0996 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
@@ -225,6 +225,7 @@ static void rt73usb_get_drvinfo(struct n
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, rt2x00_fw(&rt2x00dev->chip));
 	strcpy(drvinfo->bus_info, rt2x00dev_usb(rt2x00dev)->dev.bus_id);
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -241,7 +242,7 @@ static void rt73usb_get_regs(struct net_
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -270,7 +271,7 @@ static int rt73usb_get_eeprom(struct net
 	eeprom->magic = 0xbad;
 
 	rt2x00_eeprom_multiread(rt2x00dev,
-		eeprom->offset / sizeof(u16), (void*)data, eeprom->len);
+		eeprom->offset, (void*)data, eeprom->len);
 
 	return 0;
 }
@@ -759,7 +760,12 @@ static void rt73usb_config_rate(struct r
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set TXRX_CSR5 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR5, cpu_to_le32(reg));
 
@@ -1070,7 +1076,7 @@ static void rt73usb_init_firmware_cont(c
 		goto exit;
 	}
 
-	DEBUG("Loading Firmware version: %d.%d.\n",
+	rt2x00_set_chip_fw(&rt2x00dev->chip,
 		fw->data[fw->size - 4], fw->data[fw->size - 3]);
 
 	/*
@@ -1594,12 +1600,15 @@ static int rt73usb_enable_radio(struct r
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev =
+		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
 	struct data_ring *ring;
 	u32 reg;
 	unsigned int i;
@@ -1607,6 +1616,9 @@ static void rt73usb_disable_radio(struct
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1781,11 +1793,9 @@ static void rt73usb_write_tx_desc(struct
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 
 		/*
@@ -1963,6 +1973,7 @@ static void rt73usb_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = entry->ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * Check if we have received an
@@ -1970,11 +1981,12 @@ static void rt73usb_txdone(void *data)
 		 * was succesfull.
 		 */
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (urb->status == TX_SUCCESS))
 			entry->tx_status.ack = 1;
 		else {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 32,
@@ -1984,6 +1996,7 @@ static void rt73usb_txdone(void *data)
 			ieee80211_tx_status(ring->net_dev,
 				entry->skb, &entry->tx_status);
 
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(entry->ring);
@@ -2098,7 +2111,8 @@ static int rt73usb_tx(struct net_device 
 	memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
 	rt73usb_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -2141,10 +2155,6 @@ static int rt73usb_add_interface(struct 
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2160,6 +2170,19 @@ static int rt73usb_add_interface(struct 
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2181,15 +2204,25 @@ static void rt73usb_remove_interface(str
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt73usb_disable_radio(rt2x00dev);
 }
 
@@ -2577,6 +2610,7 @@ static int rt73usb_init_eeprom(struct rt
 {
 	struct ieee80211_conf *conf = ieee80211_get_hw_conf(
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev)));
+	u32 reg;
 	u16 value;
 	u16 eeprom;
 
@@ -2589,7 +2623,8 @@ static int rt73usb_init_eeprom(struct rt
 	 * 2 - Identify RF chipset.
 	 */
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, RT73, value);
+	rt2x00_register_read(rt2x00dev, MAC_CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT73, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF5226) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2528) &&
@@ -2682,30 +2717,36 @@ static int rt73usb_init_mac(struct rt2x0
 {
 	struct net_device *net_dev =
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
-	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
-		(u16*)&eeprom[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&eeprom[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
-	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt73usb_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -3137,6 +3178,8 @@ static int rt73usb_probe(struct usb_inte
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -3155,6 +3198,8 @@ static void rt73usb_disconnect(struct us
 
 	rt73usb_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt73usb_uninitialize(rt2x00dev);
 
 	rt73usb_free_dev(net_dev);
@@ -3173,6 +3218,7 @@ static int rt73usb_suspend(struct usb_in
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -3180,12 +3226,14 @@ static int rt73usb_suspend(struct usb_in
 	 * Disable the radio.
 	 */
 	rt73usb_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt73usb_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt73usb_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -3209,6 +3257,7 @@ static int rt73usb_resume(struct usb_int
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -3220,15 +3269,21 @@ static int rt73usb_resume(struct usb_int
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt73usb_alloc_dev(usb_intf, net_dev)) {
+	status = rt73usb_alloc_dev(usb_intf, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt73usb_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt73usb_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt73usb.h b/drivers/net/wireless/d80211/rt2x00/rt73usb.h
index 5be5e14..cc1013c 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt73usb.h
@@ -46,7 +46,7 @@ #define RF2527				0x0004
 #define CSR_REG_BASE			0x3000
 #define CSR_REG_SIZE			0x04b0
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x00ff
+#define EEPROM_SIZE			0x0100
 
 /*
  * USB registers.
@@ -643,11 +643,13 @@ #define RF4_FREQ_OFFSET			FIELD32(0x0003
 /*
  * HW MAC address.
  */
-#define EEPROM_MAC_ADDR			0x0004
+#define EEPROM_MAC_ADDR_0		0x0004
 #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0006
 #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0008
 #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
 
diff --git a/include/linux/ssb.h b/include/linux/ssb.h
index 0673b02..a36dd75 100644
--- a/include/linux/ssb.h
+++ b/include/linux/ssb.h
@@ -100,10 +100,12 @@ #define  SSB_IDLOW_SSBREV	0xF0000000 /* 
 #define  SSB_IDLOW_SSBREV_22	0x00000000 /* <= 2.2 */
 #define  SSB_IDLOW_SSBREV_23	0x10000000 /* 2.3 */
 #define SSB_IDHIGH		0x0FFC     /* SB Identification High */
-#define  SSB_IDHIGH_RC_MASK	0x0000000f /* Revision Code */
-#define  SSB_IDHIGH_CC_MASK	0x0000fff0 /* Core Code */
+#define  SSB_IDHIGH_RCLO	0x0000000F /* Revision Code (low part) */
+#define  SSB_IDHIGH_CC		0x00008FF0 /* Core Code */
 #define  SSB_IDHIGH_CC_SHIFT	4
-#define  SSB_IDHIGH_VC_MASK	0xffff0000 /* Vendor Code */
+#define  SSB_IDHIGH_RCHI	0x00007000 /* Revision Code (high part) */
+#define  SSB_IDHIGH_RCHI_SHIFT	8	   /* yes, shift 8 is right */
+#define  SSB_IDHIGH_VC		0xFFFF0000 /* Vendor Code */
 #define  SSB_IDHIGH_VC_SHIFT	16
 
 /* SPROM shadow area. If not otherwise noted, fields are
@@ -170,7 +172,7 @@ #define SSB_SPROM1_OEM			0x1076	/* 8 byt
 #define SSB_SPROM2_BFLHI		0x1038	/* Boardflags (high 16 bits) */
 #define SSB_SPROM2_MAXP_A		0x103A	/* A-PHY Max Power */
 #define  SSB_SPROM2_MAXP_A_HI		0x00FF	/* Max Power High */
-#define  SSB_SPROM2_MAXP_A_LO		0x1100	/* Max Power Low */
+#define  SSB_SPROM2_MAXP_A_LO		0xFF00	/* Max Power Low */
 #define  SSB_SPROM2_MAXP_A_LO_SHIFT	8
 #define SSB_SPROM2_PA1LOB0		0x103C	/* A-PHY PowerAmplifier Low Settings */
 #define SSB_SPROM2_PA1LOB1		0x103E	/* A-PHY PowerAmplifier Low Settings */
@@ -277,12 +279,40 @@ #define  SSB_CHIPCOMMON_CAP_BROM	0x00800
 #define  SSB_CHIPCOMMON_CAP_64BIT	0x08000000	/* 64-bit Backplane */
 #define SSB_CHIPCOMMON_CORECTL		0x0008
 #define SSB_CHIPCOMMON_BIST		0x000C
+#define SSB_CHIPCOMMON_OTPSTAT		0x0010
+#define SSB_CHIPCOMMON_OTPCTL		0x0014
+#define SSB_CHIPCOMMON_OTPPRG		0x0018
+#define SSB_CHIPCOMMON_IRQSTAT		0x0020
+#define SSB_CHIPCOMMON_IRQMASK		0x0024
+#define SSB_CHIPCOMMON_CHIPCTL		0x0028	/* Rev >= 11 only */
+#define SSB_CHIPCOMMON_CHIPSTAT		0x002C	/* Rev >= 11 only */
+#define SSB_CHIPCOMMON_JTAGCMD		0x0030	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_JTAGIR		0x0034	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_JTAGDR		0x0038	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_JTAGCTL		0x003C	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_FLASHCTL		0x0040
+#define SSB_CHIPCOMMON_FLASHADDR	0x0044
+#define SSB_CHIPCOMMON_FLASHDATA	0x0048
 #define SSB_CHIPCOMMON_BCAST_ADDR	0x0050
 #define SSB_CHIPCOMMON_BCAST_DATA	0x0054
-#define SSB_CHIPCOMMON_PLLONDELAY	0x00B0
-#define SSB_CHIPCOMMON_FREFSELDELAY	0x00B4
-#define SSB_CHIPCOMMON_SLOWCLKCTL	0x00B8
-#define SSB_CHIPCOMMON_SYSCLKCTL	0x00C0
+#define SSB_CHIPCOMMON_GPIOIN		0x0060
+#define SSB_CHIPCOMMON_GPIOOUT		0x0064
+#define SSB_CHIPCOMMON_GPIOOUTEN	0x0068
+#define SSB_CHIPCOMMON_GPIOCTL		0x006C
+#define SSB_CHIPCOMMON_GPIOPOL		0x0070
+#define SSB_CHIPCOMMON_GPIOIRQ		0x0074
+#define SSB_CHIPCOMMON_WATCHDOG		0x0080
+#define SSB_CHIPCOMMON_CLOCK_N		0x0090
+#define SSB_CHIPCOMMON_CLOCK_SB		0x0094
+#define SSB_CHIPCOMMON_CLOCK_PCI	0x0098
+#define SSB_CHIPCOMMON_CLOCK_M2		0x009C
+#define SSB_CHIPCOMMON_CLOCK_MIPS	0x00A0
+#define SSB_CHIPCOMMON_UARTCLKDIV	0x00A4	/* Rev >= 3 only */
+#define SSB_CHIPCOMMON_PLLONDELAY	0x00B0	/* Rev >= 4 only */
+#define SSB_CHIPCOMMON_FREFSELDELAY	0x00B4	/* Rev >= 4 only */
+#define SSB_CHIPCOMMON_SLOWCLKCTL	0x00B8	/* 6 <= Rev <= 9 only */
+#define SSB_CHIPCOMMON_SYSCLKCTL	0x00C0	/* Rev >= 3 only */
+#define SSB_CHIPCOMMON_CLKSTSTR		0x00C4	/* Rev >= 3 only */
 
 /* PCI core registers. */
 #define SSB_PCICORE_CTL		0x0000	/* PCI Control */
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index e72721f..320272c 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -3582,6 +3582,11 @@ void __ieee80211_rx(struct net_device *d
 	else
 		sta = rx.sta = NULL;
 
+	if (sta) {
+		rx.dev = sta->dev;
+		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
+	}
+
         if ((status->flag & RX_FLAG_MMIC_ERROR)) {
 		ieee80211_rx_michael_mic_report(dev, hdr, sta, &rx);
 		goto end;
@@ -3597,8 +3602,6 @@ void __ieee80211_rx(struct net_device *d
 
 	if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
 	    !local->iff_promiscs && !multicast) {
-		rx.dev = sta->dev;
-		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
 		rx.u.rx.ra_match = 1;
 		ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
 					     sta);
-- 
John W. Linville
linville@tuxdriver.com

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* What's new in wireless-dev?
@ 2006-09-05  0:10 John W. Linville
  0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-09-05  0:10 UTC (permalink / raw)
  To: netdev

[-- Attachment #1: Type: text/plain, Size: 366 bytes --]

(Third attempt -- vger's new bogofilter seems a bit over-zealous...)

New stuff in wireless-dev since Saturday or so.  I apologize for the delayed announcement, but I was having some local IT problems...

I'm going to try attaching the rest -- bogofilter seems to think I'm sending spam...wtf???

I hope this works!

John
-- 
John W. Linville
linville@tuxdriver.com

[-- Attachment #2: wireless-dev.txt --]
[-- Type: text/plain, Size: 74382 bytes --]

The following changes since commit a7bcae7c095077d89899b2bf0b8d81b8997f340f:
  John W. Linville:
        Merge branch 'from-linus'

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git

David Kimdon:
      d80211: fix crash in ieee80211_rx_michael_mic_report()

Ivo van Doorn:
      rt2x00: Add register revision and firmware version to ethtool
      rt2x00: basic rate mask
      rt2x00: Mac address reading optimization
      rt2x00: add/remove interface fix
      rt2x00: Register initialization fixes
      rt2x00: Respect return values
      rt2x00: Add ieee80211_netif_oper() calls
      rt2x00: change variable name
      rt2x00: TXD/RTS fixes
      rt2x00: Misc fixes

Michael Buesch:
      ssb: minor fixes and cleanups
      ssb: add MAINTAINERS entry
      bcm43xx-d80211: add support for 4312
      ssb: fix core CC and REV reading
      bcm43xx-d80211: 4311 support

 MAINTAINERS                                        |    6 +
 drivers/misc/ssb.c                                 |   23 ++-
 drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c |   13 ++
 .../net/wireless/d80211/bcm43xx/bcm43xx_power.c    |   27 +++--
 drivers/net/wireless/d80211/rt2x00/rt2400pci.c     |  119 +++++++++++++-----
 drivers/net/wireless/d80211/rt2x00/rt2400pci.h     |   15 ++
 drivers/net/wireless/d80211/rt2x00/rt2500pci.c     |  129 ++++++++++++++------
 drivers/net/wireless/d80211/rt2x00/rt2500pci.h     |   17 ++-
 drivers/net/wireless/d80211/rt2x00/rt2500usb.c     |  127 +++++++++++++------
 drivers/net/wireless/d80211/rt2x00/rt2500usb.h     |    6 +
 drivers/net/wireless/d80211/rt2x00/rt2x00.h        |   60 +++++++++
 drivers/net/wireless/d80211/rt2x00/rt61pci.c       |  132 ++++++++++++++------
 drivers/net/wireless/d80211/rt2x00/rt61pci.h       |    6 +
 drivers/net/wireless/d80211/rt2x00/rt73usb.c       |  113 +++++++++++++----
 drivers/net/wireless/d80211/rt2x00/rt73usb.h       |    6 +
 include/linux/ssb.h                                |   46 ++++++-
 net/d80211/ieee80211.c                             |    7 +
 17 files changed, 632 insertions(+), 220 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 8a88b78..783c1ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2650,6 +2650,12 @@ M:	tsbogend@alpha.franken.de
 L:	netdev@vger.kernel.org
 S:	Maintained
 
+SONICS SILICON BACKPLANE DRIVER (SSB)
+P:	Michael Buesch
+M:	mb@bu3sch.de
+L:	netdev@vger.kernel.org
+S:	Maintained
+
 SONY VAIO CONTROL DEVICE DRIVER
 P:	Stelian Pop
 M:	stelian@popies.net
diff --git a/drivers/misc/ssb.c b/drivers/misc/ssb.c
index 55e1447..44ab647 100644
--- a/drivers/misc/ssb.c
+++ b/drivers/misc/ssb.c
@@ -518,7 +518,8 @@ int ssb_init(struct ssb *ssb,
 {
 	int err;
 
-	if (!ssb || !pci_dev || !device_suspend || !device_resume)
+	if (!ssb || !pci_dev || !mmio ||
+	    !device_suspend || !device_resume)
 		return -EINVAL;
 
 	memset(ssb, 0, sizeof(*ssb));
@@ -551,9 +552,9 @@ void ssb_exit(struct ssb *ssb)
 	list_del(&ssb->list);
 	mutex_unlock(&ssb_list_mutex);
 
+	mutex_destroy(&ssb->suspend_mutex);
+	mutex_destroy(&ssb->mutex);
 	kfree(ssb->cores);
-	if (SSB_DEBUG)
-		memset(ssb, 0x5B, sizeof(*ssb));
 }
 EXPORT_SYMBOL_GPL(ssb_exit);
 
@@ -592,8 +593,8 @@ error:
 	return -ENODEV;
 }
 
-int ssb_switch_core_locked(struct ssb *ssb,
-			   struct ssb_core *new_core)
+static int ssb_switch_core_locked(struct ssb *ssb,
+				  struct ssb_core *new_core)
 {
 	int err = 0;
 
@@ -642,8 +643,9 @@ int ssb_probe_cores(struct ssb *ssb,
 		goto error;
 
 	idhi = ssb_read32(ssb, SSB_IDHIGH);
-	cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
-	rev = (idhi & SSB_IDHIGH_RC_MASK);
+	cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+	rev = (idhi & SSB_IDHIGH_RCLO);
+	rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
 
 	ssb->chipcommon_capabilities = 0;
 	ssb->nr_cores = 0;
@@ -715,9 +717,10 @@ int ssb_probe_cores(struct ssb *ssb,
 		core = &(ssb->cores[i]);
 
 		idhi = ssb_read32(ssb, SSB_IDHIGH);
-		core->cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
-		core->rev = (idhi & SSB_IDHIGH_RC_MASK);
-		core->vendor = (idhi & SSB_IDHIGH_VC_MASK) >> SSB_IDHIGH_VC_SHIFT;
+		core->cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+		core->rev = (idhi & SSB_IDHIGH_RCLO);
+		core->rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
+		core->vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
 		core->index = i;
 
 		dprintk(KERN_DEBUG PFX "Core %d found: "
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
index b47f006..d71d797 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -129,6 +129,10 @@ static struct pci_device_id bcm43xx_pci_
 	{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4307 802.11b */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 4311 802.11a/b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	/* Broadcom 4312 802.11a/b/g */
+	{ PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4318 802.11b/g */
 	{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	/* Broadcom 4319 802.11b/g */
@@ -2299,7 +2303,9 @@ static int bcm43xx_wireless_core_init(st
 	u32 sbimconfiglow;
 	u8 limit;
 
-	if (bcm->ssb.chip_rev < 5) {
+	assert(bcm->core_pci);
+	if (bcm->core_pci->cc == SSB_CC_PCI &&
+	    bcm->core_pci->rev <= 5) {
 		sbimconfiglow = bcm43xx_read32(bcm, SSB_IMCFGLO);
 		sbimconfiglow &= ~SSB_IMCFGLO_REQTO;
 		sbimconfiglow &= ~SSB_IMCFGLO_SERTO;
@@ -2710,6 +2716,7 @@ #endif
 
 		switch (core->cc) {
 		case SSB_CC_PCI:
+		case SSB_CC_PCIE:
 			if (bcm->core_pci) {
 				printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
 				break;
@@ -2742,7 +2749,7 @@ #endif
 
 			switch (core->rev) {
 			case 2: case 4: case 5: case 6:
-			case 7: case 9:
+			case 7: case 9: case 10:
 				break;
 			default:
 				printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
@@ -3247,7 +3254,7 @@ static int bcm43xx_read_phyinfo(struct b
 			phy_rev_ok = 0;
 		break;
 	case BCM43xx_PHYTYPE_G:
-		if (phy_rev > 7)
+		if (phy_rev > 8)
 			phy_rev_ok = 0;
 		break;
 	default:
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
index 6aa2a33..702af69 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
@@ -153,8 +153,6 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
 	int err, maxfreq;
 	struct ssb_core *old_core;
 
-	if (!(bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL))
-		return 0;
 	if (!bcm->core_chipcommon)
 		return 0;
 
@@ -163,11 +161,26 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
 	if (err)
 		goto out;
 
-	maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
-	bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
-			(maxfreq * 150 + 999999) / 1000000);
-	bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
-			(maxfreq * 15 + 999999) / 1000000);
+	if (bcm->ssb.chip_id == 0x4321) {
+		if (bcm->ssb.chip_rev == 0)
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x03A4);
+		else if (bcm->ssb.chip_rev == 1)
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x00A4);
+	}
+	if (bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL) {
+		if (bcm->core_chipcommon->rev >= 10) {
+			/* Set Idle Power clock rate to 1Mhz */
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_SYSCLKCTL,
+					(bcm43xx_read32(bcm, SSB_CHIPCOMMON_SYSCLKCTL) &
+					 0x0000FFFF) | 0x00040000);
+		} else {
+			maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
+					(maxfreq * 150 + 999999) / 1000000);
+			bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
+					(maxfreq * 15 + 999999) / 1000000);
+		}
+	}
 
 	err = ssb_switch_core(&bcm->ssb, old_core);
 	assert(err == 0);
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
index 00f3a66..59163bf 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
@@ -373,6 +373,7 @@ static void rt2400pci_get_drvinfo(struct
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, "N/A");
 	strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -389,7 +390,7 @@ static void rt2400pci_get_regs(struct ne
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -751,7 +752,12 @@ static void rt2400pci_config_rate(struct
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set ARCSR1 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, ARCSR1, cpu_to_le32(reg[0]));
 
@@ -767,12 +773,12 @@ static void rt2400pci_config_rate(struct
 	rt2x00_set_field32(&reg[0], TXCSR1_ACK_CONSUME_TIME, value);
 	rt2x00_register_write(rt2x00dev, TXCSR1, reg[0]);
 
-	value = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
+	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
 
-	reg[0] = cpu_to_le32(0x00700400 | value);	/* ARCSR2 */
-	reg[1] = cpu_to_le32(0x00380401 | value);	/* ARCSR3 */
-	reg[2] = cpu_to_le32(0x00150402 | value);	/* ARCSR4 */
-	reg[3] = cpu_to_le32(0x000b8403 | value);	/* ARCSR5 */
+	reg[0] = cpu_to_le32(0x00700400 | preamble);	/* ARCSR2 */
+	reg[1] = cpu_to_le32(0x00380401 | preamble);	/* ARCSR3 */
+	reg[2] = cpu_to_le32(0x00150402 | preamble);	/* ARCSR4 */
+	reg[3] = cpu_to_le32(0x000b8403 | preamble);	/* ARCSR5 */
 
 	rt2x00_register_multiwrite(rt2x00dev, ARCSR2, &reg[0], sizeof(reg));
 }
@@ -1186,11 +1192,7 @@ static int rt2400pci_init_registers(stru
 	rt2x00_register_write(rt2x00dev, RXCSR0, reg);
 
 	rt2x00_register_write(rt2x00dev, MACCSR0, cpu_to_le32(0x00217223));
-
-	rt2x00_register_read(rt2x00dev, MACCSR1, &reg);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_TXBBP, 1);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_RXBBP, 1);
-	rt2x00_register_write(rt2x00dev, MACCSR1, reg);
+	rt2x00_register_write(rt2x00dev, MACCSR1, cpu_to_le32(0x00235518));
 
 	rt2x00_register_read(rt2x00dev, MACCSR2, &reg);
 	rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
@@ -1463,17 +1465,22 @@ static int rt2400pci_enable_radio(struct
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
 	u32 reg;
 
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1760,6 +1767,7 @@ static void rt2400pci_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * The TXD_W0_RESULT field will only be set when
@@ -1769,12 +1777,13 @@ static void rt2400pci_txdone(void *data)
 		 */
 		tx_status = rt2x00_get_field32(txd->word0, TXD_W0_RESULT);
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (tx_status == TX_SUCCESS ||
 		    tx_status == TX_SUCCESS_RETRY))
 			entry->tx_status.ack = 1;
 		else if (ack && tx_status == TX_FAIL_RETRY) {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 32,
@@ -1788,6 +1797,7 @@ static void rt2400pci_txdone(void *data)
 				entry->skb, &entry->tx_status);
 
 		rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(ring);
@@ -1954,7 +1964,8 @@ static int rt2400pci_tx(struct net_devic
 	memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
 	rt2400pci_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -1995,10 +2006,6 @@ static int rt2400pci_add_interface(struc
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2014,6 +2021,19 @@ static int rt2400pci_add_interface(struc
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2035,15 +2055,25 @@ static void rt2400pci_remove_interface(s
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt2400pci_disable_radio(rt2x00dev);
 }
 
@@ -2450,7 +2480,8 @@ static int rt2400pci_init_eeprom(struct 
 	 * 3 - Identify RF chipset.
 	 */
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, RT2460, value);
+	rt2x00_register_read(rt2x00dev, CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT2460, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2420) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2421))
@@ -2493,29 +2524,36 @@ static int rt2400pci_init_eeprom(struct 
 static int rt2400pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u8 reg[8];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
-	 * Read MAC address from MAC register.
+	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_register_multiread(rt2x00dev, CSR3, (u32*)&reg[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&reg[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &reg[0], 6);
-	memcpy(&net_dev->perm_addr[0], &reg[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt2400pci_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -2864,6 +2902,8 @@ static int rt2400pci_probe(struct pci_de
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -2888,6 +2928,8 @@ static void rt2400pci_remove(struct pci_
 
 	rt2400pci_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt2400pci_uninitialize(rt2x00dev);
 
 	rt2400pci_free_dev(net_dev);
@@ -2908,6 +2950,7 @@ static int rt2400pci_suspend(struct pci_
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -2915,12 +2958,14 @@ static int rt2400pci_suspend(struct pci_
 	 * Disable the radio.
 	 */
 	rt2400pci_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt2400pci_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt2400pci_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -2944,6 +2989,7 @@ static int rt2400pci_resume(struct pci_d
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -2960,15 +3006,22 @@ static int rt2400pci_resume(struct pci_d
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt2400pci_alloc_dev(pci_dev, net_dev)) {
+	status = rt2400pci_alloc_dev(pci_dev, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt2400pci_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt2400pci_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.h b/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
index ae0ea54..a991b59 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
@@ -44,7 +44,7 @@ #define RF2421				0x0001
 #define CSR_REG_BASE			0x0000
 #define CSR_REG_SIZE			0x014c
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x00ff
+#define EEPROM_SIZE			0x0100
 
 /*
  * Control/Status Registers(CSR).
@@ -705,6 +705,19 @@ #define RF3_TXPOWER			FIELD32(0x00003e00
  */
 
 /*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0		0x0002
+#define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0003
+#define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0004
+#define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
+
+/*
  * EEPROM antenna.
  * ANTENNA_NUM: Number of antenna's.
  * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
index 3f6dd94..651fbec 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
@@ -373,6 +373,7 @@ static void rt2500pci_get_drvinfo(struct
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, "N/A");
 	strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -389,7 +390,7 @@ static void rt2500pci_get_regs(struct ne
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -817,7 +818,12 @@ static void rt2500pci_config_rate(struct
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set ARCSR1 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, ARCSR1, cpu_to_le32(reg[0]));
 
@@ -833,12 +839,12 @@ static void rt2500pci_config_rate(struct
 	rt2x00_set_field32(&reg[0], TXCSR1_ACK_CONSUME_TIME, value);
 	rt2x00_register_write(rt2x00dev, TXCSR1, reg[0]);
 
-	value = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
+	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 8 : 0;
 
-	reg[0] = cpu_to_le32(0x00700400 | value);	/* ARCSR2 */
-	reg[1] = cpu_to_le32(0x00380401 | value);	/* ARCSR3 */
-	reg[2] = cpu_to_le32(0x00150402 | value);	/* ARCSR4 */
-	reg[3] = cpu_to_le32(0x000b8403 | value);	/* ARCSR5 */
+	reg[0] = cpu_to_le32(0x00700400 | preamble);	/* ARCSR2 */
+	reg[1] = cpu_to_le32(0x00380401 | preamble);	/* ARCSR3 */
+	reg[2] = cpu_to_le32(0x00150402 | preamble);	/* ARCSR4 */
+	reg[3] = cpu_to_le32(0x000b8403 | preamble);	/* ARCSR5 */
 
 	rt2x00_register_multiwrite(rt2x00dev, ARCSR2, &reg[0], sizeof(reg));
 }
@@ -1243,6 +1249,7 @@ static int rt2500pci_init_registers(stru
 		return -EBUSY;
 
 	rt2x00_register_write(rt2x00dev, PWRCSR0, cpu_to_le32(0x3f3b3100));
+	rt2x00_register_write(rt2x00dev, PCICSR, cpu_to_le32(0x000003b8));
 
 	rt2x00_register_write(rt2x00dev, PSCSR0, cpu_to_le32(0x00020002));
 	rt2x00_register_write(rt2x00dev, PSCSR1, cpu_to_le32(0x00000002));
@@ -1266,12 +1273,11 @@ static int rt2500pci_init_registers(stru
 	rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
 	rt2x00_register_write(rt2x00dev, RXCSR0, reg);
 
-	rt2x00_register_write(rt2x00dev, MACCSR0, cpu_to_le32(0x00213223));
+	rt2x00_register_write(rt2x00dev, GPIOCSR, cpu_to_le32(0x0000ff00));
+	rt2x00_register_write(rt2x00dev, TESTCSR, cpu_to_le32(0x000000f0));
 
-	rt2x00_register_read(rt2x00dev, MACCSR1, &reg);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_TXBBP, 1);
-	rt2x00_set_field32(&reg, MACCSR1_AUTO_RXBBP, 1);
-	rt2x00_register_write(rt2x00dev, MACCSR1, reg);
+	rt2x00_register_write(rt2x00dev, MACCSR0, cpu_to_le32(0x00213223));
+	rt2x00_register_write(rt2x00dev, MACCSR1, cpu_to_le32(0x00235518));
 
 	rt2x00_register_read(rt2x00dev, MACCSR2, &reg);
 	rt2x00_set_field32(&reg, MACCSR2_DELAY, 64);
@@ -1583,17 +1589,22 @@ static int rt2500pci_enable_radio(struct
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
 	u32 reg;
 
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1739,11 +1750,9 @@ static void rt2500pci_write_tx_desc(stru
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 		residual = 0;
 
@@ -1907,6 +1916,7 @@ static void rt2500pci_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * The TXD_W0_RESULT field will only be set when
@@ -1916,12 +1926,13 @@ static void rt2500pci_txdone(void *data)
 		 */
 		tx_status = rt2x00_get_field32(txd->word0, TXD_W0_RESULT);
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (tx_status == TX_SUCCESS ||
 		    tx_status == TX_SUCCESS_RETRY))
 			entry->tx_status.ack = 1;
 		else if (ack && tx_status == TX_FAIL_RETRY) {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 32,
@@ -1935,6 +1946,7 @@ static void rt2500pci_txdone(void *data)
 				entry->skb, &entry->tx_status);
 
 		rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(ring);
@@ -2101,7 +2113,8 @@ static int rt2500pci_tx(struct net_devic
 	memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
 	rt2500pci_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -2142,10 +2155,6 @@ static int rt2500pci_add_interface(struc
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2161,6 +2170,19 @@ static int rt2500pci_add_interface(struc
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2182,15 +2204,25 @@ static void rt2500pci_remove_interface(s
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt2500pci_disable_radio(rt2x00dev);
 }
 
@@ -2589,7 +2621,8 @@ static int rt2500pci_init_eeprom(struct 
 	 * 3 - Identify RF chipset.
 	 */
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, RT2560, value);
+	rt2x00_register_read(rt2x00dev, CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT2560, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2523) &&
@@ -2645,29 +2678,36 @@ static int rt2500pci_init_eeprom(struct 
 static int rt2500pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u8 reg[8];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
-	 * Read MAC address from MAC register.
+	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_register_multiread(rt2x00dev, CSR3, (u32*)&reg[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&reg[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &reg[0], 6);
-	memcpy(&net_dev->perm_addr[0], &reg[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt2500pci_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -3147,6 +3187,8 @@ static int rt2500pci_probe(struct pci_de
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -3171,6 +3213,8 @@ static void rt2500pci_remove(struct pci_
 
 	rt2500pci_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt2500pci_uninitialize(rt2x00dev);
 
 	rt2500pci_free_dev(net_dev);
@@ -3191,6 +3235,7 @@ static int rt2500pci_suspend(struct pci_
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -3198,12 +3243,14 @@ static int rt2500pci_suspend(struct pci_
 	 * Disable the radio.
 	 */
 	rt2500pci_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt2500pci_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt2500pci_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -3227,6 +3274,7 @@ static int rt2500pci_resume(struct pci_d
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -3243,15 +3291,22 @@ static int rt2500pci_resume(struct pci_d
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt2500pci_alloc_dev(pci_dev, net_dev)) {
+	status = rt2500pci_alloc_dev(pci_dev, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt2500pci_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt2500pci_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.h b/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
index 8ef5ae5..fb44881 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
@@ -55,7 +55,7 @@ #define RT2560_VERSION_D		4
 #define CSR_REG_BASE			0x0000
 #define CSR_REG_SIZE			0x0174
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x01ff
+#define EEPROM_SIZE			0x0200
 
 /*
  * Control/Status Registers(CSR).
@@ -542,7 +542,7 @@ #define ARCSR1_AR_BBP_ID3		FIELD32(0xff0
  */
 
 /*
- * PCISR: PCI control register.
+ * PCICSR: PCI control register.
  * BIG_ENDIAN: 1: big endian, 0: little endian.
  * RX_TRESHOLD: Rx threshold in dw to start pci access
  * 0: 16dw (default), 1: 8dw, 2: 4dw, 3: 32dw.
@@ -935,6 +935,19 @@ #define RF3_TXPOWER			FIELD32(0x00003e00
  */
 
 /*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0		0x0002
+#define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0003
+#define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0004
+#define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
+
+/*
  * EEPROM antenna.
  * ANTENNA_NUM: Number of antenna's.
  * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B.
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
index 383f4a9..5d119cd 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
@@ -224,6 +224,7 @@ static void rt2500usb_get_drvinfo(struct
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, "N/A");
 	strcpy(drvinfo->bus_info, rt2x00dev_usb(rt2x00dev)->dev.bus_id);
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -240,7 +241,7 @@ static void rt2500usb_get_regs(struct ne
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u16*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -269,7 +270,7 @@ static int rt2500usb_get_eeprom(struct n
 	eeprom->magic = 0xbad;
 
 	rt2x00_eeprom_multiread(rt2x00dev,
-		eeprom->offset / sizeof(u16), (void*)data, eeprom->len);
+		eeprom->offset, (void*)data, eeprom->len);
 
 	return 0;
 }
@@ -629,15 +630,9 @@ static void rt2500usb_config_antenna(str
 static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
 	int short_slot_time)
 {
-	u16 reg;
-
 	short_slot_time = short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME;
 
 	rt2x00_register_write(rt2x00dev, MAC_CSR10, (u16)short_slot_time);
-
-	rt2x00_register_read(rt2x00dev, TXRX_CSR1, &reg);
-	rt2x00_set_field16_nb(&reg, TXRX_CSR1_TSF_OFFSET, IEEE80211_HEADER);
-	rt2x00_register_write(rt2x00dev, TXRX_CSR1, reg);
 }
 
 static void rt2500usb_config_rate(struct rt2x00_dev *rt2x00dev, const int rate)
@@ -651,7 +646,12 @@ static void rt2500usb_config_rate(struct
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set TXRX_CSR11 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR11, reg);
 
@@ -844,7 +844,7 @@ static int rt2500usb_set_state(struct rt
 
 	put_to_sleep = (state != STATE_AWAKE);
 
-	rt2x00_register_read(rt2x00dev, MAC_CSR17, &reg);
+	reg = 0;
 	rt2x00_set_field16_nb(&reg, MAC_CSR17_BBP_DESIRE_STATE, state);
 	rt2x00_set_field16_nb(&reg, MAC_CSR17_RF_DESIRE_STATE, state);
 	rt2x00_set_field16_nb(&reg, MAC_CSR17_PUT_TO_SLEEP, put_to_sleep);
@@ -866,7 +866,7 @@ static int rt2500usb_set_state(struct rt
 		if (bbp_state == state && rf_state == state)
 			return 0;
 		rt2x00_register_write(rt2x00dev, MAC_CSR17, reg);
-		msleep(10);
+		msleep(30);
 	}
 
 	NOTICE("Device failed to enter state %d, "
@@ -1092,7 +1092,7 @@ static int rt2500usb_init_registers(stru
 	}
 	rt2x00_register_write(rt2x00dev, PHY_CSR2, reg);
 
-	rt2x00_register_write(rt2x00dev, MAC_CSR11, 0x0002);
+	rt2x00_register_write(rt2x00dev, MAC_CSR11, 0x0005);
 	rt2x00_register_write(rt2x00dev, MAC_CSR22, 0x0053);
 	rt2x00_register_write(rt2x00dev, MAC_CSR15, 0x01ee);
 	rt2x00_register_write(rt2x00dev, MAC_CSR16, 0x0000);
@@ -1335,12 +1335,15 @@ static int rt2500usb_enable_radio(struct
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev =
+		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
 	struct data_ring *ring;
 	u16 reg;
 	unsigned int i;
@@ -1348,6 +1351,9 @@ static void rt2500usb_disable_radio(stru
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1499,11 +1505,9 @@ static void rt2500usb_write_tx_desc(stru
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 		residual = 0;
 
@@ -1679,6 +1683,7 @@ static void rt2500usb_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = entry->ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * Check if we have received an
@@ -1686,11 +1691,12 @@ static void rt2500usb_txdone(void *data)
 		 * was succesfull.
 		 */
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (urb->status == TX_SUCCESS))
 			entry->tx_status.ack = 1;
 		else if (ack && urb->status == TX_FAIL_OTHER) {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 0,
@@ -1700,6 +1706,7 @@ static void rt2500usb_txdone(void *data)
 			ieee80211_tx_status(ring->net_dev,
 				entry->skb, &entry->tx_status);
 
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(entry->ring);
@@ -1815,7 +1822,8 @@ static int rt2500usb_tx(struct net_devic
 	memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
 	rt2500usb_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -1858,10 +1866,6 @@ static int rt2500usb_add_interface(struc
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -1877,6 +1881,19 @@ static int rt2500usb_add_interface(struc
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -1898,15 +1915,25 @@ static void rt2500usb_remove_interface(s
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt2500usb_disable_radio(rt2x00dev);
 }
 
@@ -2255,6 +2282,8 @@ static int rt2500usb_init_eeprom(struct 
 {
 	struct ieee80211_conf *conf = ieee80211_get_hw_conf(
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev)));
+	u16 reg;
+	u16 value;
 	u16 eeprom;
 
 	/*
@@ -2265,8 +2294,9 @@ static int rt2500usb_init_eeprom(struct 
 	/*
 	 * 2 - Identify RF chipset.
 	 */
-	rt2x00_set_chip(&rt2x00dev->chip, RT2570,
-		rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE));
+	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
+	rt2x00_register_read(rt2x00dev, MAC_CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT2570, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2523) &&
@@ -2317,30 +2347,36 @@ static int rt2500usb_init_mac(struct rt2
 {
 	struct net_device *net_dev =
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
-	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
-		(u16*)&eeprom[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&eeprom[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
-	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt2500usb_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -2776,6 +2812,8 @@ static int rt2500usb_probe(struct usb_in
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -2794,6 +2832,8 @@ static void rt2500usb_disconnect(struct 
 
 	rt2500usb_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt2500usb_uninitialize(rt2x00dev);
 
 	rt2500usb_free_dev(net_dev);
@@ -2813,6 +2853,7 @@ static int rt2500usb_suspend(struct usb_
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -2820,12 +2861,14 @@ static int rt2500usb_suspend(struct usb_
 	 * Disable the radio.
 	 */
 	rt2500usb_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt2500usb_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt2500usb_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -2849,6 +2892,7 @@ static int rt2500usb_resume(struct usb_i
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -2860,15 +2904,22 @@ static int rt2500usb_resume(struct usb_i
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt2500usb_alloc_dev(usb_intf, net_dev)) {
+	status = rt2500usb_alloc_dev(usb_intf, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt2500usb_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt2500usb_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500usb.h b/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
index 917ba4c..7babcb6 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
@@ -46,7 +46,7 @@ #define RF5222				0x0010
  * Register layout information.
  */
 #define CSR_REG_BASE			0x0400
-#define CSR_REG_SIZE			0x00ff
+#define CSR_REG_SIZE			0x0100
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x006a
 
@@ -492,11 +492,13 @@ #define RF3_TXPOWER			FIELD32(0x00003e00
 /*
  * HW MAC address.
  */
-#define EEPROM_MAC_ADDR			0x0004
+#define EEPROM_MAC_ADDR_0		0x0004
 #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0006
 #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0008
 #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2x00.h b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
index 89eee23..e0ae5fe 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
@@ -117,7 +117,7 @@ #define SIFS			10
 #define PREAMBLE		144
 #define SHORT_PREAMBLE		72
 #define SLOT_TIME		20
-#define SHORT_SLOT_TIME		7
+#define SHORT_SLOT_TIME		9
 
 /*
  * TX result flags.
@@ -433,18 +433,32 @@ static inline u16 rt2x00_get_field16_nb(
 struct rt2x00_chip {
 	u16 rt;
 	u16 rf;
+	u16 rev;
+	u8 fw_h;
+	u8 fw_l;
 };
 
 /*
  * Set chipset data.
  */
 static inline void rt2x00_set_chip(struct rt2x00_chip *chipset,
-	const u16 rt, const u16 rf)
+	const u16 rt, const u16 rf, const u16 rev)
 {
-	INFO("Chipset detected - rt: %04x, rf: %04x.\n", rt, rf);
+	INFO("Chipset detected - rt: %04x, rf: %04x, rev: %04x.\n",
+		rt, rf, rev);
 
 	chipset->rt = rt;
 	chipset->rf = rf;
+	chipset->rev = rev;
+}
+
+static inline void rt2x00_set_chip_fw(struct rt2x00_chip *chipset,
+	const u8 fw_h, const u8 fw_l)
+{
+	INFO("Firmware detected - version: %d.%d.\n", fw_h, fw_l);
+
+	chipset->fw_h = fw_h;
+	chipset->fw_l = fw_l;
 }
 
 static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip)
@@ -457,6 +471,16 @@ static inline char rt2x00_rf(const struc
 	return (chipset->rf == chip);
 }
 
+static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset)
+{
+	return chipset->rev;
+}
+
+static inline char* rt2x00_fw(const struct rt2x00_chip *chipset)
+{
+	return chipset->fw_h + "." + chipset->fw_l;
+}
+
 /*
  * data_entry
  * The data ring is a list of data entries.
@@ -984,6 +1008,36 @@ #define DEV_RATEMASK	FIELD32(0x00fff000)
 #define DEV_PLCP	FIELD32(0xff000000)
 
 /*
+ * Bitmask for MASK_RATE
+ */
+#define DEV_RATE_1MB	0x00000001
+#define DEV_RATE_2MB	0x00000002
+#define DEV_RATE_5_5MB	0x00000004
+#define DEV_RATE_11MB	0x00000008
+#define DEV_RATE_6MB	0x00000010
+#define DEV_RATE_9MB	0x00000020
+#define DEV_RATE_12MB	0x00000040
+#define DEV_RATE_18MB	0x00000080
+#define DEV_RATE_24MB	0x00000100
+#define DEV_RATE_36MB	0x00000200
+#define DEV_RATE_48MB	0x00000400
+#define DEV_RATE_54MB	0x00000800
+
+/*
+ * Bitmask groups of bitrates
+ */
+#define DEV_BASIC_RATE \
+	( DEV_RATE_1MB | DEV_RATE_2MB | DEV_RATE_5_5MB | DEV_RATE_11MB | \
+	  DEV_RATE_6MB | DEV_RATE_12MB | DEV_RATE_24MB )
+
+#define DEV_CCK_RATE \
+	( DEV_RATE_1MB | DEV_RATE_2MB | DEV_RATE_5_5MB | DEV_RATE_11MB )
+
+#define DEV_OFDM_RATE \
+	( DEV_RATE_6MB | DEV_RATE_9MB | DEV_RATE_12MB | DEV_RATE_18MB | \
+	  DEV_RATE_24MB | DEV_RATE_36MB | DEV_RATE_48MB | DEV_RATE_54MB )
+
+/*
  * Macro's to set and get specific fields from the device specific val and val2
  * fields inside the ieee80211_rate entry.
  */
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.c b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
index 2157ba2..9a0462a 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
@@ -404,6 +404,7 @@ static void rt61pci_get_drvinfo(struct n
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, rt2x00_fw(&rt2x00dev->chip));
 	strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -420,7 +421,7 @@ static void rt61pci_get_regs(struct net_
 	struct rt2x00_dev	*rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -1042,7 +1043,12 @@ static void rt61pci_config_rate(struct r
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set TXRX_CSR5 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR5, cpu_to_le32(reg));
 
@@ -1359,7 +1365,7 @@ static void rt61pci_init_firmware_cont(c
 		goto exit;
 	}
 
-	DEBUG("Loading Firmware version: %d.%d.\n",
+	rt2x00_set_chip_fw(&rt2x00dev->chip,
 		fw->data[fw->size - 4], fw->data[fw->size - 3]);
 
 	/*
@@ -1691,7 +1697,6 @@ static int rt61pci_init_registers(struct
 
 	rt2x00_register_write(rt2x00dev, MAC_CSR10, cpu_to_le32(0x00000718));
 
-	rt2x00_register_write(rt2x00dev, RX_CNTL_CSR, cpu_to_le32(0x00000001));
 	rt2x00_register_write(rt2x00dev, TXRX_CSR0, cpu_to_le32(0x025eb032));
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR1, cpu_to_le32(0x9eb39eb3));
@@ -1734,7 +1739,7 @@ static int rt61pci_init_registers(struct
 	rt2x00_register_write(rt2x00dev, PHY_CSR6, cpu_to_le32(0x00080606));
 	rt2x00_register_write(rt2x00dev, PHY_CSR7, cpu_to_le32(0x00000a08));
 
-	rt2x00_register_write(rt2x00dev, PCI_CFG_CSR, cpu_to_le32(0x3cca4808));
+	rt2x00_register_write(rt2x00dev, PCI_CFG_CSR, cpu_to_le32(0x28ca4404));
 
 	rt2x00_register_write(rt2x00dev, TEST_MODE_CSR,
 		cpu_to_le32(0x00000200));
@@ -1989,10 +1994,9 @@ static int rt61pci_enable_radio(struct r
 	/*
 	 * Enable interrupts.
 	 */
-	rt2x00_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, 0);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, 0);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, 0);
+	reg = 0;
+	rt2x00_set_field32(&reg, INT_MASK_CSR_TX_ABORT_DONE, 1);
+	rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
 	rt2x00_register_write(rt2x00dev, INT_MASK_CSR, reg);
 
 	rt2x00_register_write(rt2x00dev, MCU_INT_MASK_CSR, 0x00000000);
@@ -2000,6 +2004,7 @@ static int rt61pci_enable_radio(struct r
 	/*
 	 * Enable RX.
 	 */
+	rt2x00_register_write(rt2x00dev, RX_CNTL_CSR, cpu_to_le32(0x00000001));
 	rt2x00_register_read(rt2x00dev, TXRX_CSR0, &reg);
 	rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
 	rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg);
@@ -2012,17 +2017,22 @@ static int rt61pci_enable_radio(struct r
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
 	u32 reg;
 
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -2055,10 +2065,8 @@ static void rt61pci_disable_radio(struct
 	/*
 	 * Disable interrupts.
 	 */
-	rt2x00_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE,1);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, 1);
-	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, 1);
+	reg = 0xffffffff;
+	rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, 0);
 	rt2x00_register_write(rt2x00dev, INT_MASK_CSR, reg);
 
 	rt2x00_register_write(rt2x00dev, MCU_INT_MASK_CSR, 0xffffffff);
@@ -2186,11 +2194,9 @@ static void rt61pci_write_tx_desc(struct
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 
 		/*
@@ -2346,6 +2352,7 @@ static void rt61pci_txdone_entry(struct 
 	entry->tx_status.tx_filtered = 0;
 
 	entry->tx_status.queue_length = entry->ring->stats.limit;
+	entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 	/*
 	 * The TXD_W0_RESULT field will only be set when
@@ -2355,12 +2362,13 @@ static void rt61pci_txdone_entry(struct 
 	 */
 	tx_status = rt2x00_get_field32(sta_csr4, STA_CSR4_TX_RESULT);
 	entry->tx_status.ack = 0;
+	entry->tx_status.excessive_retries = 0;
 	if (ack && (tx_status == TX_SUCCESS ||
 	    tx_status == TX_SUCCESS_RETRY))
 		entry->tx_status.ack = 1;
 	else if (ack && tx_status == TX_FAIL_RETRY) {
 		rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-		entry->tx_status.excessive_retries++;
+		entry->tx_status.excessive_retries = 1;
 	}
 
 	rt2x00_bbp_read(rt2x00dev, 32,
@@ -2374,6 +2382,7 @@ static void rt61pci_txdone_entry(struct 
 			entry->skb, &entry->tx_status);
 
 	rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);
+	CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = NULL;
 
 	/*
@@ -2575,7 +2584,8 @@ static int rt61pci_tx(struct net_device 
 	memcpy(rt2x00pci_data_addr(entry), skb->data, skb->len);
 	rt61pci_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -2620,10 +2630,6 @@ static int rt61pci_add_interface(struct 
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2639,6 +2645,19 @@ static int rt61pci_add_interface(struct 
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2660,15 +2679,25 @@ static void rt61pci_remove_interface(str
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt61pci_disable_radio(rt2x00dev);
 }
 
@@ -3057,11 +3086,11 @@ static int rt61pci_init_eeprom(struct rt
 	 * To determine the RT chip we have to read the
 	 * PCI header of the device.
 	 */
-	pci_read_config_word(
-		rt2x00dev_pci(rt2x00dev), PCI_CONFIG_HEADER_DEVICE, &device);
-
+	pci_read_config_word(rt2x00dev_pci(rt2x00dev),
+		PCI_CONFIG_HEADER_DEVICE, &device);
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, device, value);
+	rt2x00_register_read(rt2x00dev, MAC_CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, device, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF5325) &&
@@ -3170,30 +3199,36 @@ static int rt61pci_init_eeprom(struct rt
 static int rt61pci_init_mac(struct rt2x00_dev *rt2x00dev)
 {
 	struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
-	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
-		(u16*)&eeprom[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&eeprom[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
-	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt61pci_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -3669,6 +3704,8 @@ static int rt61pci_probe(struct pci_dev 
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -3693,6 +3730,8 @@ static void rt61pci_remove(struct pci_de
 
 	rt61pci_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt61pci_uninitialize(rt2x00dev);
 
 	rt61pci_free_dev(net_dev);
@@ -3713,6 +3752,7 @@ static int rt61pci_suspend(struct pci_de
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -3720,12 +3760,14 @@ static int rt61pci_suspend(struct pci_de
 	 * Disable the radio.
 	 */
 	rt61pci_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt61pci_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt61pci_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -3749,6 +3791,7 @@ static int rt61pci_resume(struct pci_dev
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -3765,15 +3808,22 @@ static int rt61pci_resume(struct pci_dev
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt61pci_alloc_dev(pci_dev, net_dev)) {
+	status = rt61pci_alloc_dev(pci_dev, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt61pci_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt61pci_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.h b/drivers/net/wireless/d80211/rt2x00/rt61pci.h
index 2c5065b..77b867d 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.h
@@ -48,7 +48,7 @@ #define RF2529				0x0004
 #define CSR_REG_BASE			0x3000
 #define CSR_REG_SIZE			0x04b0
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x00ff
+#define EEPROM_SIZE			0x0100
 
 /*
  * PCI registers.
@@ -991,11 +991,13 @@ #define RF4_FREQ_OFFSET			FIELD32(0x0003
 /*
  * HW MAC address.
  */
-#define EEPROM_MAC_ADDR			0x0002
+#define EEPROM_MAC_ADDR_0		0x0002
 #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0004
 #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0006
 #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt73usb.c b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
index 682d078..a3b0996 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
@@ -225,6 +225,7 @@ static void rt73usb_get_drvinfo(struct n
 
 	strcpy(drvinfo->driver, DRV_NAME);
 	strcpy(drvinfo->version, DRV_VERSION);
+	strcpy(drvinfo->fw_version, rt2x00_fw(&rt2x00dev->chip));
 	strcpy(drvinfo->bus_info, rt2x00dev_usb(rt2x00dev)->dev.bus_id);
 	drvinfo->eedump_len = EEPROM_SIZE;
 	drvinfo->regdump_len = CSR_REG_SIZE;
@@ -241,7 +242,7 @@ static void rt73usb_get_regs(struct net_
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
 
 	rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
-	regs->version = *((u32*)data);
+	regs->version = rt2x00_rev(&rt2x00dev->chip);
 	regs->len = CSR_REG_SIZE;
 }
 
@@ -270,7 +271,7 @@ static int rt73usb_get_eeprom(struct net
 	eeprom->magic = 0xbad;
 
 	rt2x00_eeprom_multiread(rt2x00dev,
-		eeprom->offset / sizeof(u16), (void*)data, eeprom->len);
+		eeprom->offset, (void*)data, eeprom->len);
 
 	return 0;
 }
@@ -759,7 +760,12 @@ static void rt73usb_config_rate(struct r
 	preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
 		? SHORT_PREAMBLE : PREAMBLE;
 
-	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+	/*
+	 * Extract the allowed ratemask from the device specific rate value,
+	 * We need to set TXRX_CSR5 to the basic rate mask so we need to mask
+	 * off the non-basic rates.
+	 */
+	reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
 
 	rt2x00_register_write(rt2x00dev, TXRX_CSR5, cpu_to_le32(reg));
 
@@ -1070,7 +1076,7 @@ static void rt73usb_init_firmware_cont(c
 		goto exit;
 	}
 
-	DEBUG("Loading Firmware version: %d.%d.\n",
+	rt2x00_set_chip_fw(&rt2x00dev->chip,
 		fw->data[fw->size - 4], fw->data[fw->size - 3]);
 
 	/*
@@ -1594,12 +1600,15 @@ static int rt73usb_enable_radio(struct r
 	SET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO);
 
 	ieee80211_start_queues(net_dev);
+	ieee80211_netif_oper(net_dev, NETIF_WAKE);
 
 	return 0;
 }
 
 static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
+	struct net_device *net_dev =
+		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
 	struct data_ring *ring;
 	u32 reg;
 	unsigned int i;
@@ -1607,6 +1616,9 @@ static void rt73usb_disable_radio(struct
 	if (!GET_FLAG(rt2x00dev, DEVICE_ENABLED_RADIO))
 		return;
 
+	ieee80211_netif_oper(net_dev, NETIF_STOP);
+	ieee80211_stop_queues(net_dev);
+
 	/*
 	 * Disable LED
 	 */
@@ -1781,11 +1793,9 @@ static void rt73usb_write_tx_desc(struct
 	length = skb->len + 4;
 
 	/*
-	 * Check if we are working with an OFDM rate,
-	 * this can be done by checking if bit 4 or higher
-	 * is set in the ratemask.
+	 * Check if we are working with an OFDM rate.
 	 */
-	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & 0x0ff0) {
+	if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) {
 		rt2x00_set_field32(&txd->word0, TXD_W0_OFDM, 1);
 
 		/*
@@ -1963,6 +1973,7 @@ static void rt73usb_txdone(void *data)
 		entry->tx_status.tx_filtered = 0;
 
 		entry->tx_status.queue_length = entry->ring->stats.limit;
+		entry->tx_status.queue_number = entry->tx_status.control.queue;
 
 		/*
 		 * Check if we have received an
@@ -1970,11 +1981,12 @@ static void rt73usb_txdone(void *data)
 		 * was succesfull.
 		 */
 		entry->tx_status.ack = 0;
+		entry->tx_status.excessive_retries = 0;
 		if (ack && (urb->status == TX_SUCCESS))
 			entry->tx_status.ack = 1;
 		else {
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
-			entry->tx_status.excessive_retries++;
+			entry->tx_status.excessive_retries = 1;
 		}
 
 		rt2x00_bbp_read(rt2x00dev, 32,
@@ -1984,6 +1996,7 @@ static void rt73usb_txdone(void *data)
 			ieee80211_tx_status(ring->net_dev,
 				entry->skb, &entry->tx_status);
 
+		CLEAR_FLAG(entry, ENTRY_RTS_FRAME);
 		entry->skb = NULL;
 
 		rt2x00_ring_index_done_inc(entry->ring);
@@ -2098,7 +2111,8 @@ static int rt73usb_tx(struct net_device 
 	memcpy(rt2x00usb_txdata_addr(entry), skb->data, skb->len);
 	rt73usb_write_tx_desc(rt2x00dev, txd, skb, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
-	if ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)
+	if (((frame_control & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+	    ((frame_control & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS))
 		SET_FLAG(entry, ENTRY_RTS_FRAME);
 	entry->skb = skb;
 
@@ -2141,10 +2155,6 @@ static int rt73usb_add_interface(struct 
 	    GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return -ENOBUFS;
 
-	SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
-
-	rt2x00_add_interface(&rt2x00dev->interface, conf);
-
 	/*
 	 * Enable configuration.
 	 */
@@ -2160,6 +2170,19 @@ static int rt73usb_add_interface(struct 
 	}
 
 	/*
+	 * Add the new interface.
+	 */
+	rt2x00_add_interface(&rt2x00dev->interface, conf);
+
+	/*
+	 * When this is a non-monitor mode,
+	 * set the INTERFACE_INITIALIZED FLAG to prevent
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		SET_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+
+	/*
 	 * Enable radio when this is the first
 	 * interface that is brought up.
 	 */
@@ -2181,15 +2204,25 @@ static void rt73usb_remove_interface(str
 	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		return;
 
+	/*
+	 * Remove the interface.
+	 */
 	rt2x00_remove_interface(&rt2x00dev->interface, conf);
 
-	CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
+	/*
+	 * When this is a non-monitor mode,
+	 * clear the INTERFACE_INITIALIZED FLAG to allow
+	 * new non-monitor interfaces to be added.
+	 */
+	if (conf->type != IEEE80211_IF_TYPE_MNTR)
+		CLEAR_FLAG(rt2x00dev, INTERFACE_INITIALIZED);
 
 	/*
 	 * Disable radio if this was the last interface
 	 * that was working with this device.
 	 */
-	if (!rt2x00dev->interface.monitor_count)
+	if (!rt2x00dev->interface.monitor_count &&
+	    !GET_FLAG(rt2x00dev, INTERFACE_INITIALIZED))
 		rt73usb_disable_radio(rt2x00dev);
 }
 
@@ -2577,6 +2610,7 @@ static int rt73usb_init_eeprom(struct rt
 {
 	struct ieee80211_conf *conf = ieee80211_get_hw_conf(
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev)));
+	u32 reg;
 	u16 value;
 	u16 eeprom;
 
@@ -2589,7 +2623,8 @@ static int rt73usb_init_eeprom(struct rt
 	 * 2 - Identify RF chipset.
 	 */
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2x00_set_chip(&rt2x00dev->chip, RT73, value);
+	rt2x00_register_read(rt2x00dev, MAC_CSR0, &reg);
+	rt2x00_set_chip(&rt2x00dev->chip, RT73, value, reg);
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF5226) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2528) &&
@@ -2682,30 +2717,36 @@ static int rt73usb_init_mac(struct rt2x0
 {
 	struct net_device *net_dev =
 		usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
-	u8 eeprom[6];
 
 	if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
 		return 0;
 
+	memset(&net_dev->perm_addr[0], 0, sizeof(net_dev->perm_addr));
+
 	/*
 	 * Read MAC address from EEPROM.
 	 */
-	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
-		(u16*)&eeprom[0], 6);
+	rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR_0,
+		(u16*)&net_dev->perm_addr[0], 6);
 
 	/*
 	 * Check if a valid MAC address has been read.
 	 */
-	if (!is_valid_ether_addr(&eeprom[0]))
+	if (!is_valid_ether_addr(&net_dev->perm_addr[0]))
 		return -EINVAL;
 
 	/*
-	 * Copy to netdevice structure.
+	 * Copy to perm_addr to dev_addr structure.
 	 */
-	memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
-	memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+	memcpy(&net_dev->dev_addr[0], &net_dev->perm_addr[0],
+		sizeof(net_dev->perm_addr));
 	net_dev->addr_len = 6;
 
+	/*
+	 * Write MAC address to register.
+	 */
+	rt73usb_config_mac_address(rt2x00dev, &net_dev->perm_addr[0]);
+
 	SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
 	return 0;
 }
@@ -3137,6 +3178,8 @@ static int rt73usb_probe(struct usb_inte
 		goto exit_free_device;
 	}
 
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+
 	return 0;
 
 exit_free_device:
@@ -3155,6 +3198,8 @@ static void rt73usb_disconnect(struct us
 
 	rt73usb_disable_radio(rt2x00dev);
 
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
+
 	rt73usb_uninitialize(rt2x00dev);
 
 	rt73usb_free_dev(net_dev);
@@ -3173,6 +3218,7 @@ static int rt73usb_suspend(struct usb_in
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Going to sleep.\n");
 
@@ -3180,12 +3226,14 @@ static int rt73usb_suspend(struct usb_in
 	 * Disable the radio.
 	 */
 	rt73usb_disable_radio(rt2x00dev);
+	ieee80211_netif_oper(net_dev, NETIF_DETACH);
 
 	/*
 	 * Set device mode to sleep for power management.
 	 */
-	if (rt73usb_set_state(rt2x00dev, STATE_SLEEP))
-		return -EBUSY;
+	status = rt73usb_set_state(rt2x00dev, STATE_SLEEP);
+	if (status)
+		return status;
 
 	/*
 	 * Uninitialize device.
@@ -3209,6 +3257,7 @@ static int rt73usb_resume(struct usb_int
 {
 	struct net_device *net_dev = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+	int status;
 
 	NOTICE("Waking up.\n");
 
@@ -3220,15 +3269,21 @@ static int rt73usb_resume(struct usb_int
 	/*
 	 * Initialize hardware.
 	 */
-	if (rt73usb_alloc_dev(usb_intf, net_dev)) {
+	status = rt73usb_alloc_dev(usb_intf, net_dev);
+	if (status) {
 		ERROR("Failed to allocate device.\n");
-		return -ENOMEM;
+		return status;
 	}
 
 	/*
 	 * Set device mode to awake for power management.
 	 */
-	return rt73usb_set_state(rt2x00dev, STATE_AWAKE);
+	status = rt73usb_set_state(rt2x00dev, STATE_AWAKE);
+	if (status)
+		return status;
+
+	ieee80211_netif_oper(net_dev, NETIF_ATTACH);
+	return 0;
 }
 #endif /* CONFIG_PM */
 
diff --git a/drivers/net/wireless/d80211/rt2x00/rt73usb.h b/drivers/net/wireless/d80211/rt2x00/rt73usb.h
index 5be5e14..cc1013c 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt73usb.h
@@ -46,7 +46,7 @@ #define RF2527				0x0004
 #define CSR_REG_BASE			0x3000
 #define CSR_REG_SIZE			0x04b0
 #define EEPROM_BASE			0x0000
-#define EEPROM_SIZE			0x00ff
+#define EEPROM_SIZE			0x0100
 
 /*
  * USB registers.
@@ -643,11 +643,13 @@ #define RF4_FREQ_OFFSET			FIELD32(0x0003
 /*
  * HW MAC address.
  */
-#define EEPROM_MAC_ADDR			0x0004
+#define EEPROM_MAC_ADDR_0		0x0004
 #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR1		0x0006
 #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2		0x0008
 #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)
 #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)
 
diff --git a/include/linux/ssb.h b/include/linux/ssb.h
index 0673b02..a36dd75 100644
--- a/include/linux/ssb.h
+++ b/include/linux/ssb.h
@@ -100,10 +100,12 @@ #define  SSB_IDLOW_SSBREV	0xF0000000 /* 
 #define  SSB_IDLOW_SSBREV_22	0x00000000 /* <= 2.2 */
 #define  SSB_IDLOW_SSBREV_23	0x10000000 /* 2.3 */
 #define SSB_IDHIGH		0x0FFC     /* SB Identification High */
-#define  SSB_IDHIGH_RC_MASK	0x0000000f /* Revision Code */
-#define  SSB_IDHIGH_CC_MASK	0x0000fff0 /* Core Code */
+#define  SSB_IDHIGH_RCLO	0x0000000F /* Revision Code (low part) */
+#define  SSB_IDHIGH_CC		0x00008FF0 /* Core Code */
 #define  SSB_IDHIGH_CC_SHIFT	4
-#define  SSB_IDHIGH_VC_MASK	0xffff0000 /* Vendor Code */
+#define  SSB_IDHIGH_RCHI	0x00007000 /* Revision Code (high part) */
+#define  SSB_IDHIGH_RCHI_SHIFT	8	   /* yes, shift 8 is right */
+#define  SSB_IDHIGH_VC		0xFFFF0000 /* Vendor Code */
 #define  SSB_IDHIGH_VC_SHIFT	16
 
 /* SPROM shadow area. If not otherwise noted, fields are
@@ -170,7 +172,7 @@ #define SSB_SPROM1_OEM			0x1076	/* 8 byt
 #define SSB_SPROM2_BFLHI		0x1038	/* Boardflags (high 16 bits) */
 #define SSB_SPROM2_MAXP_A		0x103A	/* A-PHY Max Power */
 #define  SSB_SPROM2_MAXP_A_HI		0x00FF	/* Max Power High */
-#define  SSB_SPROM2_MAXP_A_LO		0x1100	/* Max Power Low */
+#define  SSB_SPROM2_MAXP_A_LO		0xFF00	/* Max Power Low */
 #define  SSB_SPROM2_MAXP_A_LO_SHIFT	8
 #define SSB_SPROM2_PA1LOB0		0x103C	/* A-PHY PowerAmplifier Low Settings */
 #define SSB_SPROM2_PA1LOB1		0x103E	/* A-PHY PowerAmplifier Low Settings */
@@ -277,12 +279,40 @@ #define  SSB_CHIPCOMMON_CAP_BROM	0x00800
 #define  SSB_CHIPCOMMON_CAP_64BIT	0x08000000	/* 64-bit Backplane */
 #define SSB_CHIPCOMMON_CORECTL		0x0008
 #define SSB_CHIPCOMMON_BIST		0x000C
+#define SSB_CHIPCOMMON_OTPSTAT		0x0010
+#define SSB_CHIPCOMMON_OTPCTL		0x0014
+#define SSB_CHIPCOMMON_OTPPRG		0x0018
+#define SSB_CHIPCOMMON_IRQSTAT		0x0020
+#define SSB_CHIPCOMMON_IRQMASK		0x0024
+#define SSB_CHIPCOMMON_CHIPCTL		0x0028	/* Rev >= 11 only */
+#define SSB_CHIPCOMMON_CHIPSTAT		0x002C	/* Rev >= 11 only */
+#define SSB_CHIPCOMMON_JTAGCMD		0x0030	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_JTAGIR		0x0034	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_JTAGDR		0x0038	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_JTAGCTL		0x003C	/* Rev >= 10 only */
+#define SSB_CHIPCOMMON_FLASHCTL		0x0040
+#define SSB_CHIPCOMMON_FLASHADDR	0x0044
+#define SSB_CHIPCOMMON_FLASHDATA	0x0048
 #define SSB_CHIPCOMMON_BCAST_ADDR	0x0050
 #define SSB_CHIPCOMMON_BCAST_DATA	0x0054
-#define SSB_CHIPCOMMON_PLLONDELAY	0x00B0
-#define SSB_CHIPCOMMON_FREFSELDELAY	0x00B4
-#define SSB_CHIPCOMMON_SLOWCLKCTL	0x00B8
-#define SSB_CHIPCOMMON_SYSCLKCTL	0x00C0
+#define SSB_CHIPCOMMON_GPIOIN		0x0060
+#define SSB_CHIPCOMMON_GPIOOUT		0x0064
+#define SSB_CHIPCOMMON_GPIOOUTEN	0x0068
+#define SSB_CHIPCOMMON_GPIOCTL		0x006C
+#define SSB_CHIPCOMMON_GPIOPOL		0x0070
+#define SSB_CHIPCOMMON_GPIOIRQ		0x0074
+#define SSB_CHIPCOMMON_WATCHDOG		0x0080
+#define SSB_CHIPCOMMON_CLOCK_N		0x0090
+#define SSB_CHIPCOMMON_CLOCK_SB		0x0094
+#define SSB_CHIPCOMMON_CLOCK_PCI	0x0098
+#define SSB_CHIPCOMMON_CLOCK_M2		0x009C
+#define SSB_CHIPCOMMON_CLOCK_MIPS	0x00A0
+#define SSB_CHIPCOMMON_UARTCLKDIV	0x00A4	/* Rev >= 3 only */
+#define SSB_CHIPCOMMON_PLLONDELAY	0x00B0	/* Rev >= 4 only */
+#define SSB_CHIPCOMMON_FREFSELDELAY	0x00B4	/* Rev >= 4 only */
+#define SSB_CHIPCOMMON_SLOWCLKCTL	0x00B8	/* 6 <= Rev <= 9 only */
+#define SSB_CHIPCOMMON_SYSCLKCTL	0x00C0	/* Rev >= 3 only */
+#define SSB_CHIPCOMMON_CLKSTSTR		0x00C4	/* Rev >= 3 only */
 
 /* PCI core registers. */
 #define SSB_PCICORE_CTL		0x0000	/* PCI Control */
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index e72721f..320272c 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -3582,6 +3582,11 @@ void __ieee80211_rx(struct net_device *d
 	else
 		sta = rx.sta = NULL;
 
+	if (sta) {
+		rx.dev = sta->dev;
+		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
+	}
+
         if ((status->flag & RX_FLAG_MMIC_ERROR)) {
 		ieee80211_rx_michael_mic_report(dev, hdr, sta, &rx);
 		goto end;
@@ -3597,8 +3602,6 @@ void __ieee80211_rx(struct net_device *d
 
 	if (sta && !sta->assoc_ap && !(sta->flags & WLAN_STA_WDS) &&
 	    !local->iff_promiscs && !multicast) {
-		rx.dev = sta->dev;
-		rx.sdata = IEEE80211_DEV_TO_SUB_IF(rx.dev);
 		rx.u.rx.ra_match = 1;
 		ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
 					     sta);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2006-09-05  7:22 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-24 19:08 What's new in wireless-dev? John W. Linville
  -- strict thread matches above, loose matches on Subject: below --
2006-09-05  0:10 John W. Linville
2006-09-05  0:02 John W. Linville
2006-09-04 23:53 John W. Linville
2006-08-08 23:41 John W. Linville
2006-07-30  1:30 John W. Linville
2006-07-11 20:45 John W. Linville
2006-07-12  9:48 ` Jiri Benc
2006-07-12 12:48   ` John W. Linville
2006-07-13  2:30     ` John W. Linville
2006-06-15 21:10 John W. Linville

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).