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:10:00 -0400 [thread overview]
Message-ID: <20060905000955.GD8927@tuxdriver.com> (raw)
[-- 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(®[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, ®[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, ®);
- rt2x00_set_field32(®, MACCSR1_AUTO_TXBBP, 1);
- rt2x00_set_field32(®, MACCSR1_AUTO_RXBBP, 1);
- rt2x00_register_write(rt2x00dev, MACCSR1, reg);
+ rt2x00_register_write(rt2x00dev, MACCSR1, cpu_to_le32(0x00235518));
rt2x00_register_read(rt2x00dev, MACCSR2, ®);
rt2x00_set_field32(®, 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, ®);
+ 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*)®[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(®[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], ®[0], 6);
- memcpy(&net_dev->perm_addr[0], ®[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(®[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, ®[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(®, 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, ®);
- rt2x00_set_field32(®, MACCSR1_AUTO_TXBBP, 1);
- rt2x00_set_field32(®, 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, ®);
rt2x00_set_field32(®, 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, ®);
+ 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*)®[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(®[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], ®[0], 6);
- memcpy(&net_dev->perm_addr[0], ®[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, ®);
- rt2x00_set_field16_nb(®, 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 = 0;
rt2x00_set_field16_nb(®, MAC_CSR17_BBP_DESIRE_STATE, state);
rt2x00_set_field16_nb(®, MAC_CSR17_RF_DESIRE_STATE, state);
rt2x00_set_field16_nb(®, 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, ®);
+ 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, ®);
- rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, 0);
- rt2x00_set_field32(®, INT_MASK_CSR_BEACON_DONE, 0);
- rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, 0);
+ reg = 0;
+ rt2x00_set_field32(®, INT_MASK_CSR_TX_ABORT_DONE, 1);
+ rt2x00_set_field32(®, 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, ®);
rt2x00_set_field32(®, 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, ®);
- rt2x00_set_field32(®, INT_MASK_CSR_RXDONE,1);
- rt2x00_set_field32(®, INT_MASK_CSR_BEACON_DONE, 1);
- rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, 1);
+ reg = 0xffffffff;
+ rt2x00_set_field32(®, 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, ®);
+ 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, ®);
+ 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);
next reply other threads:[~2006-09-05 7:22 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-09-05 0:10 John W. Linville [this message]
-- strict thread matches above, loose matches on Subject: below --
2006-09-05 0:02 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=20060905000955.GD8927@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.