All of lore.kernel.org
 help / color / mirror / Atom feed
From: "John W. Linville" <linville@tuxdriver.com>
To: netdev@vger.kernel.org
Subject: What's new in wireless-dev?
Date: Mon, 4 Sep 2006 20:02:12 -0400	[thread overview]
Message-ID: <20060905000212.GB8927@tuxdriver.com> (raw)

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

             reply	other threads:[~2006-09-05  0:02 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-09-05  0:02 John W. Linville [this message]
  -- strict thread matches above, loose matches on Subject: below --
2006-09-05  0:10 What's new in wireless-dev? John W. Linville
2006-09-04 23:53 John W. Linville
2006-08-24 19:08 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060905000212.GB8927@tuxdriver.com \
    --to=linville@tuxdriver.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.