* What's new in wireless-dev?
@ 2006-06-15 21:10 John W. Linville
0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-06-15 21:10 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 3196 bytes --]
The following changes since commit bff7c0afa5a40acf518ae9fbf67e5f93ff9107bc:
John W. Linville:
Merge branch 'from-linus'
are found in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git
Jiri Benc:
d80211: deinit sysfs in case of an error
d80211: better sysfs registration of symlinks to wiphy
d80211: separate allocation of ieee80211_local
d80211: fix Oops when writing to add_ and remove_iface
d80211: wiphy sysfs attributes
d80211: network interface sysfs attributes
d80211: rename sta_info_relase to sta_info_put
d80211: sysfs attributes for associated stations
d80211: remove useless parameters
d80211: rate_control sysfs attributes
d80211: encryption keys sysfs attributes
d80211: remove procfs files
John W. Linville:
Merge git://git.kernel.org/.../jbenc/dscape
Michael Buesch:
bcm43xx: Port new locking scheme to d80211
bcm43xx: Port preemptible-periodic-work to d80211
bcm43xx: Port suspend-mac-in-long-pwork from d80211
bcm43xx: Port PIO fixes to d80211
drivers/net/wireless/d80211/bcm43xx/bcm43xx.h | 102 ++-
.../net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c | 33 +
drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.h | 8
drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c | 4
drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c | 287 +++++--
drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c | 9
drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c | 154 +++-
drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.h | 32 +
.../net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c | 38 -
include/linux/netdevice.h | 1
net/d80211/Makefile | 2
net/d80211/ieee80211.c | 206 +++--
net/d80211/ieee80211_dev.c | 17
net/d80211/ieee80211_i.h | 45 +
net/d80211/ieee80211_iface.c | 43 +
net/d80211/ieee80211_ioctl.c | 213 +++---
net/d80211/ieee80211_key.h | 2
net/d80211/ieee80211_proc.c | 771 --------------------
net/d80211/ieee80211_proc.h | 45 -
net/d80211/ieee80211_scan.c | 10
net/d80211/ieee80211_sta.c | 68 +-
net/d80211/ieee80211_sysfs.c | 706 +++++++++++++++++-
net/d80211/ieee80211_sysfs_sta.c | 434 +++++++++++
net/d80211/rate_control.c | 55 +
net/d80211/rate_control.h | 57 +
net/d80211/sta_info.c | 132 ++-
net/d80211/sta_info.h | 16
net/d80211/wme.c | 26 -
28 files changed, 2110 insertions(+), 1406 deletions(-)
delete mode 100644 net/d80211/ieee80211_proc.c
delete mode 100644 net/d80211/ieee80211_proc.h
create mode 100644 net/d80211/ieee80211_sysfs_sta.c
Patch included as attachment due to size concerns.
--
John W. Linville
linville@tuxdriver.com
[-- Attachment #2: wireless-dev.patch.bz2 --]
[-- Type: application/x-bzip2, Size: 33583 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
* What's new in wireless-dev?
@ 2006-07-11 20:45 John W. Linville
2006-07-12 9:48 ` Jiri Benc
0 siblings, 1 reply; 11+ messages in thread
From: John W. Linville @ 2006-07-11 20:45 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 3344 bytes --]
I apologize for the delay. Between the 2.6.18 merge window and things
heating up at the paying job, I've been a bit behind.
Along w/ pulling some updates from Jiri and some random bug fixes,
this includes the new d80211-based adm8211 driver from Michael Wu.
I'm sure he would love for anyone equipped with that hardware to beat
the crap out of his driver. :-)
Happy hacking!
John
---
The following changes since commit 46226c37e4764103719005eb363b3bc53216caea:
John W. Linville:
Merge branch 'from-linus'
are found in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git
Alexander Tsvyashchenko:
bcm43xx-d80211: AccessPoint mode related fixes
Gertjan van Wingerde:
d80211: Take lowlevel driver's channel change time into account during scanning.
Ivo van Doorn:
rt2x00: per-queue TX flow control
Jiri Benc:
d80211: update tx.skb after TX handler calls
d80211: per-queue TX flow control
d80211: handle full queue when sending fragments
d80211: add first_fragment flag to ieee80211_tx_control
bcm43xx-d80211: fix sending of fragments
bcm43xx-d80211: per-queue TX flow control
John W. Linville:
Merge branch 'master' of git://git.kernel.org/.../jbenc/dscape
d80211: use netif_tx_lock API
bcm43xx-d80211: fixup UTS_RELEASE build break
Michael Buesch:
d80211: allow NULL for control in beacon_get
bcm43xx-d80211: fix mac_suspend refcount
Michael Wu:
add adm8211 driver
drivers/net/wireless/d80211/Kconfig | 1
drivers/net/wireless/d80211/Makefile | 1
drivers/net/wireless/d80211/adm8211/Kconfig | 24
drivers/net/wireless/d80211/adm8211/Makefile | 1
drivers/net/wireless/d80211/adm8211/adm8211.c | 2202 ++++++++++++++++++++
drivers/net/wireless/d80211/adm8211/adm8211.h | 631 ++++++
drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c | 8
.../net/wireless/d80211/bcm43xx/bcm43xx_ethtool.c | 1
drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c | 482 +++-
drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h | 24
drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c | 2
drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c | 18
drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.h | 3
drivers/net/wireless/d80211/rt2x00/rt2400pci.c | 41
drivers/net/wireless/d80211/rt2x00/rt2500pci.c | 41
drivers/net/wireless/d80211/rt2x00/rt2500usb.c | 40
drivers/net/wireless/d80211/rt2x00/rt61pci.c | 41
drivers/net/wireless/d80211/rt2x00/rt73usb.c | 40
include/net/d80211.h | 32
net/d80211/ieee80211.c | 293 ++-
net/d80211/ieee80211_i.h | 20
net/d80211/ieee80211_sta.c | 4
net/d80211/wme.c | 9
23 files changed, 3723 insertions(+), 236 deletions(-)
create mode 100644 drivers/net/wireless/d80211/adm8211/Kconfig
create mode 100644 drivers/net/wireless/d80211/adm8211/Makefile
create mode 100644 drivers/net/wireless/d80211/adm8211/adm8211.c
create mode 100644 drivers/net/wireless/d80211/adm8211/adm8211.h
Full diff attached as wireless-dev.patch.bz2
--
John W. Linville
linville@tuxdriver.com
[-- Attachment #2: wireless-dev.patch.bz2 --]
[-- Type: application/x-bzip2, Size: 30407 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: What's new in wireless-dev?
2006-07-11 20:45 John W. Linville
@ 2006-07-12 9:48 ` Jiri Benc
2006-07-12 12:48 ` John W. Linville
0 siblings, 1 reply; 11+ messages in thread
From: Jiri Benc @ 2006-07-12 9:48 UTC (permalink / raw)
To: John W. Linville; +Cc: netdev
On Tue, 11 Jul 2006 16:45:58 -0400, John W. Linville wrote:
> John W. Linville:
> d80211: use netif_tx_lock API
> --- a/net/d80211/ieee80211.c
> +++ b/net/d80211/ieee80211.c
> @@ -1338,7 +1338,7 @@ static void ieee80211_tx_pending(unsigne
> struct ieee80211_txrx_data tx;
> int i, ret, reschedule = 0;
>
> - spin_lock_bh(&dev->xmit_lock);
> + netif_tx_lock_bh(dev);
> dev->xmit_lock_owner = smp_processor_id();
Those dev->xmit_lock_owner assignments are done in netif_tx_[un]lock_bh,
so they should go away as well.
Jiri
--
Jiri Benc
SUSE Labs
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: What's new in wireless-dev?
2006-07-12 9:48 ` Jiri Benc
@ 2006-07-12 12:48 ` John W. Linville
2006-07-13 2:30 ` John W. Linville
0 siblings, 1 reply; 11+ messages in thread
From: John W. Linville @ 2006-07-12 12:48 UTC (permalink / raw)
To: Jiri Benc; +Cc: netdev
On Wed, Jul 12, 2006 at 11:48:32AM +0200, Jiri Benc wrote:
> On Tue, 11 Jul 2006 16:45:58 -0400, John W. Linville wrote:
> > John W. Linville:
> > d80211: use netif_tx_lock API
>
> > --- a/net/d80211/ieee80211.c
> > +++ b/net/d80211/ieee80211.c
> > @@ -1338,7 +1338,7 @@ static void ieee80211_tx_pending(unsigne
> > struct ieee80211_txrx_data tx;
> > int i, ret, reschedule = 0;
> >
> > - spin_lock_bh(&dev->xmit_lock);
> > + netif_tx_lock_bh(dev);
> > dev->xmit_lock_owner = smp_processor_id();
>
> Those dev->xmit_lock_owner assignments are done in netif_tx_[un]lock_bh,
> so they should go away as well.
Doh! I missed that...thanks for the heads-up!
John
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: What's new in wireless-dev?
2006-07-12 12:48 ` John W. Linville
@ 2006-07-13 2:30 ` John W. Linville
0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-07-13 2:30 UTC (permalink / raw)
To: Jiri Benc; +Cc: netdev
On Wed, Jul 12, 2006 at 08:48:32AM -0400, John W. Linville wrote:
> On Wed, Jul 12, 2006 at 11:48:32AM +0200, Jiri Benc wrote:
> > On Tue, 11 Jul 2006 16:45:58 -0400, John W. Linville wrote:
> > > John W. Linville:
> > > d80211: use netif_tx_lock API
> >
> > > --- a/net/d80211/ieee80211.c
> > > +++ b/net/d80211/ieee80211.c
> > > @@ -1338,7 +1338,7 @@ static void ieee80211_tx_pending(unsigne
> > > struct ieee80211_txrx_data tx;
> > > int i, ret, reschedule = 0;
> > >
> > > - spin_lock_bh(&dev->xmit_lock);
> > > + netif_tx_lock_bh(dev);
> > > dev->xmit_lock_owner = smp_processor_id();
> >
> > Those dev->xmit_lock_owner assignments are done in netif_tx_[un]lock_bh,
> > so they should go away as well.
>
> Doh! I missed that...thanks for the heads-up!
[PATCH] d80211: remove referencess to xmit_lock_owner
Clean-up sloppy attempt at moving to netif_tx_lock API. When using that
API, direct manipulation of xmit_lock_owner is unnecessary and
inappropriate.
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
net/d80211/ieee80211.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
a5b83f260b3cbe9ed161313e620c66b76e0218cf
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 542fec9..7ceef10 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -1339,7 +1339,6 @@ static void ieee80211_tx_pending(unsigne
int i, ret, reschedule = 0;
netif_tx_lock_bh(dev);
- dev->xmit_lock_owner = smp_processor_id();
for (i = 0; i < local->hw->queues; i++) {
if (__ieee80211_queue_stopped(local, i))
continue;
@@ -1364,7 +1363,6 @@ static void ieee80211_tx_pending(unsigne
reschedule = 1;
}
}
- dev->xmit_lock_owner = -1;
netif_tx_unlock_bh(dev);
if (reschedule)
netif_schedule(dev);
--
1.3.1
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply related [flat|nested] 11+ messages in thread
* What's new in wireless-dev?
@ 2006-07-30 1:30 John W. Linville
0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-07-30 1:30 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 1649 bytes --]
Lots of patches lately, and I got a bit behind w/ travel to Ottawa
and some "real job" stuff too... :-(
I've still got a bunch of rt2x00 patches from Ivo, and a few other
patches as well. Coming soon...
John
---
The following changes since commit 44ba187488edb4e567a0163d334f2bc0318dc392:
John W. Linville:
Merge branch 'from-linus'
are found in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git
Ivo van Doorn:
rt2x00 makefile
Jiri Benc:
d80211: do not receive through master interface when not scanning
d80211: host_gen_beacon_template flag
d80211: better deallocation of mdev
d80211: fix receiving through virtual interfaces
d80211: fix defragmentation
d80211: optimize defragmentation
d80211: SET_NETDEV_DEV for non-master devices
bcm43xx-d80211: use host_gen_beacon_template
bcm43xx-d80211: use SET_NETDEV_DEV
John W. Linville:
Merge branch 'up' of git://git.kernel.org/.../jbenc/dscape
Merge branch 'bcm43xx' of git://git.kernel.org/.../jbenc/dscape
Larry Finger:
bcm43xx: remove unused routines
Michael Buesch:
bcm43xx-d80211: Lower mac_suspend timeout
bcm43xx-d80211: opencoded locking
bcm43xx-d80211: init routine rewrite
Michael Wu:
d80211: Replace rc4 code with crypto api arc4
d80211: Add sparse bitwise annotations
adm8211: Properly initialize priv->mode in adm8211_probe
adm8211: Restore frame header after TX
adm8211: Add MAINTAINERS entry
Consolidate patch attached as wireless-dev.patch.bz2.
--
John W. Linville
linville@tuxdriver.com
[-- Attachment #2: wireless-dev.patch.bz2 --]
[-- Type: application/x-bzip2, Size: 31657 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
* What's new in wireless-dev?
@ 2006-08-08 23:41 John W. Linville
0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-08-08 23:41 UTC (permalink / raw)
To: netdev
The following changes since commit d2970f6c700f2291c1a80b061ebcd6041d2f3f1e:
John W. Linville:
Merge branch 'from-linus'
are found in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git
Ivo van Doorn:
rt2x00 - pci request/release regions
rt2x00 - ieee80211_hw->config no longer requires scheduling
rt2x00 - optimize MAC reading & initialize perm_addr
rt2x00 - txpower limits
rt2x00 - misc fixes
rt2x00 - scan handlers
rfkill - Add rfkill driver to misc input devices
rfkill - rt2x00 should use rfkill
Jiri Benc:
d80211: fix wrong logical operations
d80211: more correct WE support on master interface
Jouni Malinen:
d80211: Fix RTS threshold use
d80211: Fix PS-Poll frame dropping
d80211: Fix PLCP header length comment
d80211: Send Layer 2 Update frames in kernel
d80211: Fix ieee80211_remove_tx_extra() if key not configured
d80211: Fix TKIP replay protection
Michael Wu:
d80211: Fix issues with QOS bitwise ops
adm8211: Use ieee80211_*_queue functions
d80211 drivers: Use IRQF_SHARED instead of SA_SHIRQ
drivers/input/misc/Kconfig | 15 +
drivers/input/misc/Makefile | 1
drivers/input/misc/rfkill.c | 210 ++++++++++++++++++++
drivers/net/wireless/d80211/adm8211/adm8211.c | 18 +-
drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c | 2
drivers/net/wireless/d80211/rt2x00/Kconfig | 24 +-
drivers/net/wireless/d80211/rt2x00/rt2400pci.c | 193 +++++++++---------
drivers/net/wireless/d80211/rt2x00/rt2400pci.h | 4
drivers/net/wireless/d80211/rt2x00/rt2500pci.c | 197 ++++++++++---------
drivers/net/wireless/d80211/rt2x00/rt2500pci.h | 4
drivers/net/wireless/d80211/rt2x00/rt2500usb.c | 99 +++------
drivers/net/wireless/d80211/rt2x00/rt2500usb.h | 4
drivers/net/wireless/d80211/rt2x00/rt2x00.h | 62 +++++-
drivers/net/wireless/d80211/rt2x00/rt2x00pci.h | 111 -----------
drivers/net/wireless/d80211/rt2x00/rt61pci.c | 200 +++++++++----------
drivers/net/wireless/d80211/rt2x00/rt61pci.h | 4
drivers/net/wireless/d80211/rt2x00/rt73usb.c | 92 +++------
drivers/net/wireless/d80211/rt2x00/rt73usb.h | 4
include/linux/input.h | 1
include/linux/rfkill.h | 98 +++++++++
net/d80211/ieee80211.c | 26 +-
net/d80211/ieee80211_i.h | 1
net/d80211/ieee80211_ioctl.c | 87 ++++++++
net/d80211/tkip.c | 1
net/d80211/wme.c | 4
net/d80211/wpa.c | 2
26 files changed, 868 insertions(+), 596 deletions(-)
create mode 100644 drivers/input/misc/rfkill.c
create mode 100644 include/linux/rfkill.h
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index a6dfc74..ac10c02 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -79,4 +79,19 @@ config HP_SDC_RTC
Say Y here if you want to support the built-in real time clock
of the HP SDC controller.
+config RFKILL
+ tristate "RF button support"
+ help
+ If you say yes here, the rfkill driver will be build
+ which allowed network devices to register their hardware
+ RF button which controls the radio state. This driver
+ will then create an input device for it.
+
+ When the input device is not used, the rfkill driver
+ will make sure that when the RF button is pressed the radio
+ is enabled or disabled accordingly. When the input device
+ has been opened by the user this radio control will be left
+ to the user, and rfkill will only send the RF button status
+ change to userspace.
+
endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 415c491..e788a1b 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_INPUT_UINPUT) += uinput.o
obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o
obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
+obj-$(CONFIG_RFKILL) += rfkill.o
diff --git a/drivers/input/misc/rfkill.c b/drivers/input/misc/rfkill.c
new file mode 100644
index 0000000..7b78053
--- /dev/null
+++ b/drivers/input/misc/rfkill.c
@@ -0,0 +1,210 @@
+/*
+ Copyright (C) 2006 Ivo van Doorn
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/timer.h>
+#include <linux/rfkill.h>
+
+#include <asm/atomic.h>
+
+MODULE_AUTHOR("Ivo van Doorn <IvDoorn@gmail.com>");
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("RF button support");
+MODULE_LICENSE("GPL");
+
+/*
+ * List of all registered buttons.
+ */
+static struct list_head rfkill_list;
+static spinlock_t rfkill_list_lock;
+
+/*
+ * Polling timer, poll_delay and use count.
+ */
+static struct timer_list poll_timer;
+static atomic_t poll_required;
+
+static void rfkill_toggle_radio(int new_status)
+{
+ struct list_head *entry;
+ struct rfkill *rfkill;
+
+ /*
+ * Go through the list of all radio's to toggle the radio state.
+ */
+ list_for_each(entry, &rfkill_list) {
+ rfkill = list_entry(entry, struct rfkill, entry);
+
+ rfkill->current_status = new_status;
+
+ /*
+ * If the input_device has been opened
+ * all radio events should be send to user space.
+ */
+ if (rfkill->input_dev->users) {
+ input_report_key(rfkill->input_dev,
+ KEY_RFKILL, new_status);
+ input_sync(rfkill->input_dev);
+ continue;
+ }
+
+ /*
+ * If the hardware does not toggle the radio status automaticly,
+ * we should take care of it.
+ */
+ if (new_status && rfkill->enable_radio)
+ rfkill->enable_radio(rfkill->data);
+ else if (!new_status && rfkill->disable_radio)
+ rfkill->disable_radio(rfkill->data);
+ }
+}
+
+static void rfkill_poll_button(unsigned long data)
+{
+ struct list_head *entry;
+ struct rfkill *rfkill;
+ int status;
+
+ spin_lock(&rfkill_list_lock);
+
+ list_for_each(entry, &rfkill_list) {
+ rfkill = list_entry(entry, struct rfkill, entry);
+
+ if (!rfkill->poll)
+ continue;
+
+ status = !!rfkill->poll(rfkill->data);
+
+ if (status != rfkill->current_status) {
+ rfkill_toggle_radio(status);
+ break;
+ }
+ }
+
+ spin_unlock(&rfkill_list_lock);
+
+ /*
+ * Check if polling is still required.
+ */
+ if (atomic_read(&poll_required)) {
+ poll_timer.expires = jiffies + RFKILL_POLL_DELAY;
+ add_timer(&poll_timer);
+ }
+}
+
+void rfkill_button_event(struct rfkill *rfkill, int status)
+{
+ if (status != rfkill->current_status) {
+ spin_lock(&rfkill_list_lock);
+ rfkill_toggle_radio(status);
+ spin_unlock(&rfkill_list_lock);
+ }
+}
+EXPORT_SYMBOL(rfkill_button_event);
+
+int rfkill_add_device(struct rfkill *rfkill)
+{
+ int status;
+
+ /*
+ * Allocate, initialize and register input device.
+ */
+ rfkill->input_dev = input_allocate_device();
+ if (!rfkill->input_dev) {
+ printk(KERN_ERR "Failed to allocate input device %s.\n",
+ rfkill->dev_name);
+ return -ENOMEM;
+ }
+
+ rfkill->input_dev->name = "Radio button";
+ rfkill->input_dev->phys = rfkill->dev_name;
+ rfkill->input_dev->id.bustype = BUS_HOST;
+ set_bit(KEY_RFKILL, rfkill->input_dev->keybit);
+
+ status = input_register_device(rfkill->input_dev);
+ if (status) {
+ printk(KERN_ERR "Failed to register input device %s.\n",
+ rfkill->dev_name);
+ input_free_device(rfkill->input_dev);
+ return status;
+ }
+
+ INIT_LIST_HEAD(&rfkill->entry);
+
+ spin_lock(&rfkill_list_lock);
+ list_add(&rfkill->entry, &rfkill_list);
+ spin_unlock(&rfkill_list_lock);
+
+ /*
+ * If polling is required the poll_required counter should be
+ * increased. If it was previously 0 we should start the polling timer.
+ */
+ if (rfkill->poll) {
+ if (!atomic_read(&poll_required)) {
+ poll_timer.expires = jiffies + RFKILL_POLL_DELAY;
+ add_timer(&poll_timer);
+ }
+ atomic_inc(&poll_required);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(rfkill_add_device);
+
+void rfkill_del_device(struct rfkill *rfkill)
+{
+ spin_lock(&rfkill_list_lock);
+
+ /*
+ * Check if this button required polling and if this
+ * was the last button that required polling.
+ */
+ if (rfkill->poll && atomic_dec_and_test(&poll_required))
+ del_timer(&poll_timer);
+
+ list_del(&rfkill->entry);
+
+ spin_unlock(&rfkill_list_lock);
+}
+EXPORT_SYMBOL(rfkill_del_device);
+
+static int __init radiobtn_init(void)
+{
+ printk(KERN_INFO "Loading rfkill driver.\n");
+
+ INIT_LIST_HEAD(&rfkill_list);
+ spin_lock_init(&rfkill_list_lock);
+
+ init_timer(&poll_timer);
+ poll_timer.function = rfkill_poll_button;
+ poll_timer.data = 0;
+ atomic_set(&poll_required, 0);
+
+ return 0;
+}
+
+static void __exit radiobtn_exit(void)
+{
+ printk(KERN_INFO "Unloading rfkill driver.\n");
+}
+
+module_init(radiobtn_init);
+module_exit(radiobtn_exit);
diff --git a/drivers/net/wireless/d80211/adm8211/adm8211.c b/drivers/net/wireless/d80211/adm8211/adm8211.c
index 748eb26..dcabeab 100644
--- a/drivers/net/wireless/d80211/adm8211/adm8211.c
+++ b/drivers/net/wireless/d80211/adm8211/adm8211.c
@@ -452,7 +452,7 @@ static void adm8211_interrupt_tci(struct
}
if (priv->cur_tx - dirty_tx < priv->tx_ring_size - 2)
- netif_wake_queue(dev);
+ ieee80211_wake_queue(dev, 0);
priv->dirty_tx = dirty_tx;
spin_unlock(&priv->lock);
@@ -1627,7 +1627,7 @@ static int adm8211_open(struct net_devic
adm8211_rf_set_channel(dev, priv->channel);
retval = request_irq(dev->irq, &adm8211_interrupt,
- SA_SHIRQ, dev->name, dev);
+ IRQF_SHARED, dev->name, dev);
if (retval) {
printk(KERN_ERR "%s: failed to register IRQ handler\n",
dev->name);
@@ -1765,17 +1765,13 @@ static void adm8211_tx_raw(struct net_de
spin_lock_irqsave(&priv->lock, flags);
- if (priv->cur_tx - priv->dirty_tx < priv->tx_ring_size / 2)
+ if (priv->cur_tx - priv->dirty_tx == priv->tx_ring_size / 2)
flag = TDES1_CONTROL_IC | TDES1_CONTROL_LS | TDES1_CONTROL_FS;
- else if (priv->cur_tx - priv->dirty_tx == priv->tx_ring_size / 2)
- flag = TDES1_CONTROL_IC | TDES1_CONTROL_LS | TDES1_CONTROL_FS;
- else if (priv->cur_tx - priv->dirty_tx < priv->tx_ring_size - 2)
+ else
flag = TDES1_CONTROL_LS | TDES1_CONTROL_FS;
- else {
- flag = TDES1_CONTROL_IC | TDES1_CONTROL_LS | TDES1_CONTROL_FS;
- printk(KERN_DEBUG "%s: Yikes, this shouldn't happen!\n", dev->name);
- netif_stop_queue(dev);
- }
+
+ if (priv->cur_tx - priv->dirty_tx == priv->tx_ring_size - 2)
+ ieee80211_stop_queue(dev, 0);
entry = priv->cur_tx % priv->tx_ring_size;
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
index 59d137b..6366020 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -2295,7 +2295,7 @@ #ifdef CONFIG_BCM947XX
}
#endif
err = request_irq(bcm->irq, bcm43xx_interrupt_handler,
- SA_SHIRQ, KBUILD_MODNAME, bcm);
+ IRQF_SHARED, KBUILD_MODNAME, bcm);
if (err)
printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq);
diff --git a/drivers/net/wireless/d80211/rt2x00/Kconfig b/drivers/net/wireless/d80211/rt2x00/Kconfig
index d9b97f1..9e91fd6 100644
--- a/drivers/net/wireless/d80211/rt2x00/Kconfig
+++ b/drivers/net/wireless/d80211/rt2x00/Kconfig
@@ -17,12 +17,12 @@ config RT2400PCI
config RT2400PCI_BUTTON
bool "Ralink rt2400 hardware button support"
- depends on RT2400PCI && X86
+ depends on RT2400PCI && RFKILL
---help---
In some notebooks the rt2400 chipset is integrated in the machine,
- with this option enabled the device will periodically poll the
- the status of this button and will send and ACPI event when
- the button has been pressed.
+ with this option enabled the driver will register itself to the
+ rfkill driver for periodical polling of the hardware button
+ status, and the correct handling of button press events.
config RT2400PCI_DEBUG
bool "Ralink rt2400 debug output"
@@ -40,12 +40,12 @@ config RT2500PCI
config RT2500PCI_BUTTON
bool "Ralink rt2500 hardware button support"
- depends on RT2500PCI && X86
+ depends on RT2500PCI && RFKILL
---help---
In some notebooks the rt2500 chipset is integrated in the machine,
- with this option enabled the device will periodically poll the
- the status of this button and will send and ACPI event when
- the button has been pressed.
+ with this option enabled the driver will register itself to the
+ rfkill driver for periodical polling of the hardware button
+ status, and the correct handling of button press events.
config RT2500PCI_DEBUG
bool "Ralink rt2500 debug output"
@@ -63,12 +63,12 @@ config RT61PCI
config RT61PCI_BUTTON
bool "Ralink rt61 hardware button support"
- depends on RT61PCI && X86
+ depends on RT61PCI && RFKILL
---help---
In some notebooks the rt61 chipset is integrated in the machine,
- with this option enabled the device will periodically poll the
- the status of this button and will send and ACPI event when
- the button has been pressed.
+ with this option enabled the driver will register itself to the
+ rfkill driver for periodical polling of the hardware button
+ status, and the correct handling of button press events.
config RT61PCI_DEBUG
bool "Ralink rt61 debug output"
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
index 709cdbf..96bcdf4 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
@@ -346,23 +346,6 @@ static void rt2x00_eeprom_multiread(cons
rt2x00_eeprom_read(rt2x00dev, word + i, data++);
}
-#ifdef CONFIG_RT2400PCI_BUTTON
-/*
- * Hardware button poll handler.
- */
-static void rt2400pci_button_poll(unsigned long data)
-{
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
- u32 reg;
-
- rt2x00_register_read(rt2x00dev, GPIOCSR, ®);
- rt2x00pci_button_status(
- rt2x00dev, rt2x00_get_field32(reg, GPIOCSR_BIT0));
-}
-#else /* CONFIG_RT2400PCI_BUTTON */
-static void rt2400pci_button_poll(unsigned long data){}
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
/*
* Ethtool handlers.
*/
@@ -434,8 +417,63 @@ #endif /* CONFIG_RT2400PCI_DEBUG */
.get_link = ethtool_op_get_link,
.get_eeprom_len = rt2400pci_get_eeprom_len,
.get_eeprom = rt2400pci_get_eeprom,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
+#ifdef CONFIG_RT2400PCI_BUTTON
+static int rt2400pci_button_poll(unsigned long data)
+{
+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
+ u32 reg;
+
+ rt2x00_register_read(rt2x00dev, GPIOCSR, ®);
+ return rt2x00_get_field32(reg, GPIOCSR_BIT0);
+}
+
+static void rt2400pci_button_enable_radio(unsigned long data)
+{
+ rt2400pci_enable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt2400pci_button_disable_radio(unsigned long data)
+{
+ rt2400pci_disable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt2400pci_button_start(struct rt2x00_dev *rt2x00dev)
+{
+ struct rfkill *rfkill = &rt2x00dev->rfkill;
+
+ /*
+ * Only start the button polling when
+ * the hardware button is present.
+ */
+ if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+ return;
+
+ rfkill->dev_name = "rt2400pci";
+ rfkill->data = (unsigned long)rt2x00dev;
+ rfkill->poll = rt2400pci_button_poll;
+ rfkill->enable_radio = rt2400pci_button_enable_radio;
+ rfkill->disable_radio = rt2400pci_button_disable_radio;
+ rfkill->current_status = !!rt2400pci_button_poll(rfkill->data);
+
+ if (rfkill_add_device(rfkill))
+ ERROR("Failed to register button handler.\n");
+}
+
+static void rt2400pci_button_stop(struct rt2x00_dev *rt2x00dev)
+{
+ if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+ return;
+
+ rfkill_del_device(&rt2x00dev->rfkill);
+}
+#else /* CONFIG_RT2400PCI_BUTTON */
+static void rt2400pci_button_start(struct rt2x00_dev *rt2x00dev){}
+static void rt2400pci_button_stop(struct rt2x00_dev *rt2x00dev){}
+#endif /* CONFIG_RT2400PCI_BUTTON */
+
/*
* Configuration handlers.
*/
@@ -1356,7 +1394,7 @@ static int rt2400pci_initialize(struct r
* Register interrupt handler.
*/
if (request_irq(rt2x00dev_pci(rt2x00dev)->irq, rt2400pci_interrupt,
- SA_SHIRQ, net_dev->name, rt2x00dev)) {
+ IRQF_SHARED, net_dev->name, rt2x00dev)) {
ERROR("IRQ %d allocation failed.\n",
rt2x00dev_pci(rt2x00dev)->irq);
goto exit_fail;
@@ -1380,10 +1418,8 @@ static void rt2400pci_uninitialize(struc
/*
* Cancel scanning.
*/
- if (rt2x00dev->scan) {
- rt2x00dev->scan->status = SCANNING_CANCELLED;
- complete_all(&rt2x00dev->scan->completion);
- }
+ if (rt2x00dev->scan)
+ rt2x00_signal_scan(rt2x00dev->scan, SCANNING_CANCELLED);
/*
* Flush out all pending work.
@@ -1801,10 +1837,8 @@ static void rt2400pci_txdone(void *data)
if (rt2x00dev->scan &&
rt2x00_ring_empty(&rt2x00dev->ring[RING_TX]) &&
rt2x00_ring_empty(&rt2x00dev->ring[RING_ATIM]) &&
- rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO])) {
- rt2x00dev->scan->status = SCANNING_READY;
- complete(&rt2x00dev->scan->completion);
- }
+ rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO]))
+ rt2x00_signal_scan(rt2x00dev->scan, SCANNING_READY);
/*
* If the data ring was full before the txdone handler
@@ -2050,11 +2084,10 @@ static void rt2400pci_remove_interface(s
rt2400pci_disable_radio(rt2x00dev);
}
-static void rt2400pci_config_update(void *data)
+static int rt2400pci_config(struct net_device *net_dev,
+ struct ieee80211_conf *conf)
{
- struct rt2x00_dev *rt2x00dev = data;
- struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
- struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+ struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
u32 reg;
/*
@@ -2085,21 +2118,10 @@ static void rt2400pci_config_update(void
rt2x00_register_read(rt2x00dev, RXCSR0, ®);
rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0);
rt2x00_register_write(rt2x00dev, RXCSR0, reg);
- } else if (conf->radio_enabled) {
- if (rt2400pci_enable_radio(rt2x00dev))
- return;
- }
-}
-
-static int rt2400pci_config(struct net_device *net_dev,
- struct ieee80211_conf *conf)
-{
- struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+ } else if (conf->radio_enabled)
+ return rt2400pci_enable_radio(rt2x00dev);
- /*
- * Queue work.
- */
- return !queue_work(rt2x00dev->workqueue, &rt2x00dev->config_work);
+ return 0;
}
static int rt2400pci_config_interface(struct net_device *net_dev, int if_id,
@@ -2164,14 +2186,7 @@ static void rt2400pci_scan(void *data)
* we need to wait untill all TX rings are empty to
* guarentee that all frames are send on the correct channel.
*/
- if (rt2x00dev->scan->status != SCANNING_READY)
- wait_for_completion(&rt2x00dev->scan->completion);
-
- /*
- * Check if this scan has been cancelled while
- * work was still scheduled.
- */
- if (rt2x00dev->scan->status == SCANNING_CANCELLED)
+ if (rt2x00_wait_scan(rt2x00dev->scan))
goto exit;
/*
@@ -2243,13 +2258,7 @@ static int rt2400pci_passive_scan(struct
/*
* Initialize Scanning structure.
*/
- init_completion(&rt2x00dev->scan->completion);
-
- memcpy(&rt2x00dev->scan->conf, conf, sizeof(*conf));
-
- rt2x00dev->scan->state = state;
-
- rt2x00dev->scan->status = 0;
+ rt2x00_start_scan(rt2x00dev->scan, conf, state);
/*
* Queue work.
@@ -2521,25 +2530,29 @@ static int rt2400pci_init_eeprom(struct
static int rt2400pci_init_mac(struct rt2x00_dev *rt2x00dev)
{
struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
- u32 reg[2] = { 0, 0 };
+ u8 reg[8];
if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
return 0;
- rt2x00_register_multiread(rt2x00dev, CSR3, ®[0], sizeof(reg));
+ /*
+ * Read MAC address from MAC register.
+ */
+ rt2x00_register_multiread(rt2x00dev, CSR3, (u32*)®[0], 6);
- net_dev->dev_addr[0] = rt2x00_get_field32(reg[0], CSR3_BYTE0);
- net_dev->dev_addr[1] = rt2x00_get_field32(reg[0], CSR3_BYTE1);
- net_dev->dev_addr[2] = rt2x00_get_field32(reg[0], CSR3_BYTE2);
- net_dev->dev_addr[3] = rt2x00_get_field32(reg[0], CSR3_BYTE3);
- net_dev->dev_addr[4] = rt2x00_get_field32(reg[1], CSR4_BYTE4);
- net_dev->dev_addr[5] = rt2x00_get_field32(reg[1], CSR4_BYTE5);
+ /*
+ * Check if a valid MAC address has been read.
+ */
+ if (!is_valid_ether_addr(®[0]))
+ return -EINVAL;
+ /*
+ * Copy to netdevice structure.
+ */
+ memcpy(&net_dev->dev_addr[0], ®[0], 6);
+ memcpy(&net_dev->perm_addr[0], ®[0], 6);
net_dev->addr_len = 6;
- if (!is_valid_ether_addr(&net_dev->dev_addr[0]))
- return -EINVAL;
-
SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
return 0;
}
@@ -2738,7 +2751,7 @@ static void rt2400pci_free_dev(struct ne
/*
* Shutdown poll_timer for hardware button.
*/
- rt2x00pci_button_stop(rt2x00dev);
+ rt2400pci_button_stop(rt2x00dev);
/*
* Free ring structures.
@@ -2798,11 +2811,6 @@ static int rt2400pci_alloc_dev(struct pc
goto exit;
/*
- * Initialize cofniguration work.
- */
- INIT_WORK(&rt2x00dev->config_work, rt2400pci_config_update, rt2x00dev);
-
- /*
* Reset current working type.
*/
rt2x00dev->interface.type = -EINVAL;
@@ -2832,7 +2840,7 @@ static int rt2400pci_alloc_dev(struct pc
/*
* If required start hardware button polling.
*/
- rt2x00pci_button_start(rt2x00dev, rt2400pci_button_poll);
+ rt2400pci_button_start(rt2x00dev);
return 0;
@@ -2851,10 +2859,16 @@ static int rt2400pci_probe(struct pci_de
struct net_device *net_dev;
int status;
+ status = pci_request_regions(pci_dev, pci_name(pci_dev));
+ if (status) {
+ ERROR("PCI request regions failed.\n");
+ return status;
+ }
+
status = pci_enable_device(pci_dev);
if (status) {
ERROR("Enable device failed.\n");
- return status;
+ goto exit_release_regions;
}
pci_set_master(pci_dev);
@@ -2869,17 +2883,11 @@ static int rt2400pci_probe(struct pci_de
goto exit_disable_device;
}
- status = pci_request_regions(pci_dev, pci_name(pci_dev));
- if (status) {
- ERROR("PCI request regions failed.\n");
- goto exit_disable_device;
- }
-
net_dev = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), NULL);
if (!net_dev) {
ERROR("Failed to allocate hardware.\n");
status = -ENOMEM;
- goto exit_release_regions;
+ goto exit_disable_device;
}
SET_ETHTOOL_OPS(net_dev, &rt2400pci_ethtool_ops);
@@ -2898,13 +2906,13 @@ static int rt2400pci_probe(struct pci_de
exit_free_device:
ieee80211_free_hw(net_dev);
-exit_release_regions:
- pci_release_regions(pci_dev);
-
exit_disable_device:
if (status != -EBUSY)
pci_disable_device(pci_dev);
+exit_release_regions:
+ pci_release_regions(pci_dev);
+
pci_set_drvdata(pci_dev, NULL);
return status;
@@ -2927,9 +2935,9 @@ static void rt2400pci_remove(struct pci_
pci_set_drvdata(pci_dev, NULL);
- pci_release_regions(pci_dev);
-
pci_disable_device(pci_dev);
+
+ pci_release_regions(pci_dev);
}
#ifdef CONFIG_PM
@@ -3024,11 +3032,6 @@ module_param_named(debug, rt2x00_debug_l
MODULE_PARM_DESC(debug, "Set this parameter to 1 to enable debug output.");
#endif /* CONFIG_RT2400PCI_DEBUG */
-#ifdef CONFIG_RT2400PCI_BUTTON
-module_param_named(poll_delay, rt2x00_poll_delay, short, S_IRUGO);
-MODULE_PARM_DESC(debug, "Delay between WiFi button pollings (in 100ms).");
-#endif /* CONFIG_RT2400PCI_BUTTON */
-
static struct pci_driver rt2400pci_driver = {
.name = DRV_NAME,
.id_table = rt2400pci_device_table,
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.h b/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
index b592eef..ae0ea54 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.h
@@ -881,8 +881,8 @@ #define TXPOWER_FROM_DEV(__txpower) \
#define TXPOWER_TO_DEV(__txpower) \
({ \
(__txpower) += MIN_TXPOWER; \
- ((__txpower) < MIN_TXPOWER) ? MAX_TXPOWER : \
- (((__txpower) > MAX_TXPOWER) ? MIN_TXPOWER : \
+ ((__txpower) <= MIN_TXPOWER) ? MAX_TXPOWER : \
+ (((__txpower) >= MAX_TXPOWER) ? MIN_TXPOWER : \
(MAX_TXPOWER - ((__txpower) - MIN_TXPOWER))); \
})
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
index 8a22968..20095aa 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.c
@@ -346,23 +346,6 @@ static void rt2x00_eeprom_multiread(cons
rt2x00_eeprom_read(rt2x00dev, word + i, data++);
}
-#ifdef CONFIG_RT2500PCI_BUTTON
-/*
- * Hardware button poll handler.
- */
-static void rt2500pci_button_poll(unsigned long data)
-{
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
- u32 reg;
-
- rt2x00_register_read(rt2x00dev, GPIOCSR, ®);
- rt2x00pci_button_status(
- rt2x00dev, rt2x00_get_field32(reg, GPIOCSR_BIT0));
-}
-#else /* CONFIG_RT2500PCI_BUTTON */
-static void rt2500pci_button_poll(unsigned long data){}
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
/*
* Ethtool handlers.
*/
@@ -434,8 +417,63 @@ #endif /* CONFIG_RT2500PCI_DEBUG */
.get_link = ethtool_op_get_link,
.get_eeprom_len = rt2500pci_get_eeprom_len,
.get_eeprom = rt2500pci_get_eeprom,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
+#ifdef CONFIG_RT2500PCI_BUTTON
+static int rt2500pci_button_poll(unsigned long data)
+{
+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
+ u32 reg;
+
+ rt2x00_register_read(rt2x00dev, GPIOCSR, ®);
+ return rt2x00_get_field32(reg, GPIOCSR_BIT0);
+}
+
+static void rt2500pci_button_enable_radio(unsigned long data)
+{
+ rt2500pci_enable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt2500pci_button_disable_radio(unsigned long data)
+{
+ rt2500pci_disable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt2500pci_button_start(struct rt2x00_dev *rt2x00dev)
+{
+ struct rfkill *rfkill = &rt2x00dev->rfkill;
+
+ /*
+ * Only start the button polling when
+ * the hardware button is present.
+ */
+ if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+ return;
+
+ rfkill->dev_name = "rt2500pci";
+ rfkill->data = (unsigned long)rt2x00dev;
+ rfkill->poll = rt2500pci_button_poll;
+ rfkill->enable_radio = rt2500pci_button_enable_radio;
+ rfkill->disable_radio = rt2500pci_button_disable_radio;
+ rfkill->current_status = !!rt2500pci_button_poll(rfkill->data);
+
+ if (rfkill_add_device(rfkill))
+ ERROR("Failed to register button handler.\n");
+}
+
+static void rt2500pci_button_stop(struct rt2x00_dev *rt2x00dev)
+{
+ if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+ return;
+
+ rfkill_del_device(&rt2x00dev->rfkill);
+}
+#else /* CONFIG_RT2500PCI_BUTTON */
+static void rt2500pci_button_start(struct rt2x00_dev *rt2x00dev){}
+static void rt2500pci_button_stop(struct rt2x00_dev *rt2x00dev){}
+#endif /* CONFIG_RT2500PCI_BUTTON */
+
/*
* Configuration handlers.
*/
@@ -1476,7 +1514,7 @@ static int rt2500pci_initialize(struct r
* Register interrupt handler.
*/
if (request_irq(rt2x00dev_pci(rt2x00dev)->irq, rt2500pci_interrupt,
- SA_SHIRQ, net_dev->name, rt2x00dev)) {
+ IRQF_SHARED, net_dev->name, rt2x00dev)) {
ERROR("IRQ %d allocation failed.\n",
rt2x00dev_pci(rt2x00dev)->irq);
goto exit_fail;
@@ -1500,10 +1538,8 @@ static void rt2500pci_uninitialize(struc
/*
* Cancel scanning.
*/
- if (rt2x00dev->scan) {
- rt2x00dev->scan->status = SCANNING_CANCELLED;
- complete_all(&rt2x00dev->scan->completion);
- }
+ if (rt2x00dev->scan)
+ rt2x00_signal_scan(rt2x00dev->scan, SCANNING_CANCELLED);
/*
* Flush out all pending work.
@@ -1948,10 +1984,8 @@ static void rt2500pci_txdone(void *data)
if (rt2x00dev->scan &&
rt2x00_ring_empty(&rt2x00dev->ring[RING_TX]) &&
rt2x00_ring_empty(&rt2x00dev->ring[RING_ATIM]) &&
- rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO])) {
- rt2x00dev->scan->status = SCANNING_READY;
- complete(&rt2x00dev->scan->completion);
- }
+ rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO]))
+ rt2x00_signal_scan(rt2x00dev->scan, SCANNING_READY);
/*
* If the data ring was full before the txdone handler
@@ -2197,11 +2231,10 @@ static void rt2500pci_remove_interface(s
rt2500pci_disable_radio(rt2x00dev);
}
-static void rt2500pci_config_update(void *data)
+static int rt2500pci_config(struct net_device *net_dev,
+ struct ieee80211_conf *conf)
{
- struct rt2x00_dev *rt2x00dev = data;
- struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
- struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+ struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
u32 reg;
/*
@@ -2233,21 +2266,10 @@ static void rt2500pci_config_update(void
rt2x00_register_read(rt2x00dev, RXCSR0, ®);
rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0);
rt2x00_register_write(rt2x00dev, RXCSR0, reg);
- } else if (conf->radio_enabled) {
- if (rt2500pci_enable_radio(rt2x00dev))
- return;
- }
-}
-
-static int rt2500pci_config(struct net_device *net_dev,
- struct ieee80211_conf *conf)
-{
- struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+ } else if (conf->radio_enabled)
+ return rt2500pci_enable_radio(rt2x00dev);
- /*
- * Queue work.
- */
- return !queue_work(rt2x00dev->workqueue, &rt2x00dev->config_work);
+ return 0;
}
static int rt2500pci_config_interface(struct net_device *net_dev, int if_id,
@@ -2312,14 +2334,7 @@ static void rt2500pci_scan(void *data)
* we need to wait untill all TX rings are empty to
* guarentee that all frames are send on the correct channel.
*/
- if (rt2x00dev->scan->status != SCANNING_READY)
- wait_for_completion(&rt2x00dev->scan->completion);
-
- /*
- * Check if this scan has been cancelled while
- * work was still scheduled.
- */
- if (rt2x00dev->scan->status == SCANNING_CANCELLED)
+ if (rt2x00_wait_scan(rt2x00dev->scan))
goto exit;
/*
@@ -2337,7 +2352,7 @@ static void rt2500pci_scan(void *data)
} else {
rt2500pci_config_phymode(rt2x00dev,
rt2x00dev->scan->conf.running_phymode);
-
+
rt2500pci_config_channel(rt2x00dev,
rt2x00dev->scan->conf.running_channel_val,
rt2x00dev->scan->conf.running_channel,
@@ -2387,13 +2402,7 @@ static int rt2500pci_passive_scan(struct
/*
* Initialize Scanning structure.
*/
- init_completion(&rt2x00dev->scan->completion);
-
- memcpy(&rt2x00dev->scan->conf, conf, sizeof(*conf));
-
- rt2x00dev->scan->state = state;
-
- rt2x00dev->scan->status = 0;
+ rt2x00_start_scan(rt2x00dev->scan, conf, state);
/*
* Queue work.
@@ -2673,25 +2682,29 @@ static int rt2500pci_init_eeprom(struct
static int rt2500pci_init_mac(struct rt2x00_dev *rt2x00dev)
{
struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
- u32 reg[2] = { 0, 0 };
+ u8 reg[8];
if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
return 0;
- rt2x00_register_multiread(rt2x00dev, CSR3, ®[0], sizeof(reg));
+ /*
+ * Read MAC address from MAC register.
+ */
+ rt2x00_register_multiread(rt2x00dev, CSR3, (u32*)®[0], 6);
- net_dev->dev_addr[0] = rt2x00_get_field32(reg[0], CSR3_BYTE0);
- net_dev->dev_addr[1] = rt2x00_get_field32(reg[0], CSR3_BYTE1);
- net_dev->dev_addr[2] = rt2x00_get_field32(reg[0], CSR3_BYTE2);
- net_dev->dev_addr[3] = rt2x00_get_field32(reg[0], CSR3_BYTE3);
- net_dev->dev_addr[4] = rt2x00_get_field32(reg[1], CSR4_BYTE4);
- net_dev->dev_addr[5] = rt2x00_get_field32(reg[1], CSR4_BYTE5);
+ /*
+ * Check if a valid MAC address has been read.
+ */
+ if (!is_valid_ether_addr(®[0]))
+ return -EINVAL;
+ /*
+ * Copy to netdevice structure.
+ */
+ memcpy(&net_dev->dev_addr[0], ®[0], 6);
+ memcpy(&net_dev->perm_addr[0], ®[0], 6);
net_dev->addr_len = 6;
- if (!is_valid_ether_addr(&net_dev->dev_addr[0]))
- return -EINVAL;
-
SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
return 0;
}
@@ -2866,7 +2879,7 @@ static void rt2500pci_init_hw_channels(s
};
struct ieee80211_channel *chan = channels + 14;
-
+
for (i = 0; i < ARRAY_SIZE(vals); i++)
(chan++)->val = cpu_to_le32(vals[i]);
}
@@ -3021,7 +3034,7 @@ static void rt2500pci_free_dev(struct ne
/*
* Shutdown poll_timer for hardware button.
*/
- rt2x00pci_button_stop(rt2x00dev);
+ rt2500pci_button_stop(rt2x00dev);
/*
* Free ring structures.
@@ -3081,11 +3094,6 @@ static int rt2500pci_alloc_dev(struct pc
goto exit;
/*
- * Initialize cofniguration work.
- */
- INIT_WORK(&rt2x00dev->config_work, rt2500pci_config_update, rt2x00dev);
-
- /*
* Reset current working type.
*/
rt2x00dev->interface.type = -EINVAL;
@@ -3115,7 +3123,7 @@ static int rt2500pci_alloc_dev(struct pc
/*
* If required start hardware button polling.
*/
- rt2x00pci_button_start(rt2x00dev, rt2500pci_button_poll);
+ rt2500pci_button_start(rt2x00dev);
return 0;
@@ -3134,10 +3142,16 @@ static int rt2500pci_probe(struct pci_de
struct net_device *net_dev;
int status;
+ status = pci_request_regions(pci_dev, pci_name(pci_dev));
+ if (status) {
+ ERROR("PCI request regions failed.\n");
+ return status;
+ }
+
status = pci_enable_device(pci_dev);
if (status) {
ERROR("Enable device failed.\n");
- return status;
+ goto exit_release_regions;
}
pci_set_master(pci_dev);
@@ -3152,17 +3166,11 @@ static int rt2500pci_probe(struct pci_de
goto exit_disable_device;
}
- status = pci_request_regions(pci_dev, pci_name(pci_dev));
- if (status) {
- ERROR("PCI request regions failed.\n");
- goto exit_disable_device;
- }
-
net_dev = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), NULL);
if (!net_dev) {
ERROR("Failed to allocate hardware.\n");
status = -ENOMEM;
- goto exit_release_regions;
+ goto exit_disable_device;
}
SET_ETHTOOL_OPS(net_dev, &rt2500pci_ethtool_ops);
@@ -3181,13 +3189,13 @@ static int rt2500pci_probe(struct pci_de
exit_free_device:
ieee80211_free_hw(net_dev);
-exit_release_regions:
- pci_release_regions(pci_dev);
-
exit_disable_device:
if (status != -EBUSY)
pci_disable_device(pci_dev);
+exit_release_regions:
+ pci_release_regions(pci_dev);
+
pci_set_drvdata(pci_dev, NULL);
return status;
@@ -3210,9 +3218,9 @@ static void rt2500pci_remove(struct pci_
pci_set_drvdata(pci_dev, NULL);
- pci_release_regions(pci_dev);
-
pci_disable_device(pci_dev);
+
+ pci_release_regions(pci_dev);
}
#ifdef CONFIG_PM
@@ -3307,11 +3315,6 @@ module_param_named(debug, rt2x00_debug_l
MODULE_PARM_DESC(debug, "Set this parameter to 1 to enable debug output.");
#endif /* CONFIG_RT2500PCI_DEBUG */
-#ifdef CONFIG_RT2500PCI_BUTTON
-module_param_named(poll_delay, rt2x00_poll_delay, short, S_IRUGO);
-MODULE_PARM_DESC(debug, "Delay between WiFi button pollings (in 100ms).");
-#endif /* CONFIG_RT2500PCI_BUTTON */
-
static struct pci_driver rt2500pci_driver = {
.name = DRV_NAME,
.id_table = rt2500pci_device_table,
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500pci.h b/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
index 671265b..8ef5ae5 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500pci.h
@@ -1142,8 +1142,8 @@ #define TXPOWER_FROM_DEV(__txpower) \
#define TXPOWER_TO_DEV(__txpower) \
({ \
- ((__txpower) < MIN_TXPOWER) ? MIN_TXPOWER : \
- (((__txpower) > MAX_TXPOWER) ? MAX_TXPOWER : \
+ ((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
+ (((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
(__txpower)); \
})
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
index d15a33e..383f4a9 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500usb.c
@@ -170,7 +170,8 @@ static void rt2x00_bbp_read(const struct
*value = 0xff;
}
-static void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev, const u32 value)
+static void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev,
+ const u32 value)
{
u16 reg;
unsigned int i;
@@ -284,6 +285,7 @@ #endif /* CONFIG_RT2500USB_DEBUG */
.get_link = ethtool_op_get_link,
.get_eeprom_len = rt2500usb_get_eeprom_len,
.get_eeprom = rt2500usb_get_eeprom,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
/*
@@ -1263,10 +1265,8 @@ static void rt2500usb_uninitialize(struc
/*
* Cancel scanning.
*/
- if (rt2x00dev->scan) {
- rt2x00dev->scan->status = SCANNING_CANCELLED;
- complete_all(&rt2x00dev->scan->completion);
- }
+ if (rt2x00dev->scan)
+ rt2x00_signal_scan(rt2x00dev->scan, SCANNING_CANCELLED);
/*
* Flush out all pending work.
@@ -1482,7 +1482,7 @@ static void rt2500usb_write_tx_desc(stru
else
rt2x00_set_field32(&txd->word0, TXD_W0_MORE_FRAG, 0);
- if ((ieee80211hdr->seq_ctrl & IEEE80211_SCTL_FRAG) == 0)
+ if ((le16_to_cpu(ieee80211hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) == 0)
rt2x00_set_field32(&txd->word0, TXD_W0_NEW_SEQ, 1);
else
rt2x00_set_field32(&txd->word0, TXD_W0_NEW_SEQ, 0);
@@ -1712,10 +1712,8 @@ static void rt2500usb_txdone(void *data)
if (rt2x00dev->scan &&
rt2x00_ring_empty(&rt2x00dev->ring[RING_TX]) &&
rt2x00_ring_empty(&rt2x00dev->ring[RING_ATIM]) &&
- rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO])) {
- rt2x00dev->scan->status = SCANNING_READY;
- complete(&rt2x00dev->scan->completion);
- }
+ rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO]))
+ rt2x00_signal_scan(rt2x00dev->scan, SCANNING_READY);
/*
* If the data ring was full before the txdone handler
@@ -1912,12 +1910,10 @@ static void rt2500usb_remove_interface(s
rt2500usb_disable_radio(rt2x00dev);
}
-static void rt2500usb_config_update(void *data)
+static int rt2500usb_config(struct net_device *net_dev,
+ struct ieee80211_conf *conf)
{
- struct rt2x00_dev *rt2x00dev = data;
- struct net_device *net_dev =
- usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
- struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+ struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
u16 reg;
/*
@@ -1949,21 +1945,10 @@ static void rt2500usb_config_update(void
rt2x00_register_read(rt2x00dev, TXRX_CSR2, ®);
rt2x00_set_field16_nb(®, TXRX_CSR2_DISABLE_RX, 0);
rt2x00_register_write(rt2x00dev, TXRX_CSR2, reg);
- } else if (conf->radio_enabled) {
- if (rt2500usb_enable_radio(rt2x00dev))
- return;
- }
-}
-
-static int rt2500usb_config(struct net_device *net_dev,
- struct ieee80211_conf *conf)
-{
- struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+ } else if (conf->radio_enabled)
+ return rt2500usb_enable_radio(rt2x00dev);
- /*
- * Queue work.
- */
- return !queue_work(rt2x00dev->workqueue, &rt2x00dev->config_work);
+ return 0;
}
static void rt2500usb_interface_update(void *data)
@@ -2038,14 +2023,7 @@ static void rt2500usb_scan(void *data)
* we need to wait untill all TX rings are empty to
* guarentee that all frames are send on the correct channel.
*/
- if (rt2x00dev->scan->status != SCANNING_READY)
- wait_for_completion(&rt2x00dev->scan->completion);
-
- /*
- * Check if this scan has been cancelled while
- * work was still scheduled.
- */
- if (rt2x00dev->scan->status == SCANNING_CANCELLED)
+ if (rt2x00_wait_scan(rt2x00dev->scan))
goto exit;
/*
@@ -2054,7 +2032,7 @@ static void rt2500usb_scan(void *data)
if (rt2x00dev->scan->state == IEEE80211_SCAN_START) {
rt2500usb_config_phymode(rt2x00dev,
rt2x00dev->scan->conf.scan_phymode);
-
+
rt2500usb_config_channel(rt2x00dev,
rt2x00dev->scan->conf.scan_channel_val,
rt2x00dev->scan->conf.scan_channel,
@@ -2063,7 +2041,7 @@ static void rt2500usb_scan(void *data)
} else {
rt2500usb_config_phymode(rt2x00dev,
rt2x00dev->scan->conf.running_phymode);
-
+
rt2500usb_config_channel(rt2x00dev,
rt2x00dev->scan->conf.running_channel_val,
rt2x00dev->scan->conf.running_channel,
@@ -2113,13 +2091,7 @@ static int rt2500usb_passive_scan(struct
/*
* Initialize Scanning structure.
*/
- init_completion(&rt2x00dev->scan->completion);
-
- memcpy(&rt2x00dev->scan->conf, conf, sizeof(*conf));
-
- rt2x00dev->scan->state = state;
-
- rt2x00dev->scan->status = 0;
+ rt2x00_start_scan(rt2x00dev->scan, conf, state);
/*
* Queue work.
@@ -2345,7 +2317,7 @@ static int rt2500usb_init_mac(struct rt2
{
struct net_device *net_dev =
usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
- u16 eeprom[3] = { 0, 0, 0 };
+ u8 eeprom[6];
if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
return 0;
@@ -2353,26 +2325,22 @@ static int rt2500usb_init_mac(struct rt2
/*
* Read MAC address from EEPROM.
*/
- rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR, &eeprom[0], 6);
-
- net_dev->dev_addr[0] = rt2x00_get_field16(eeprom[0],
- EEPROM_MAC_ADDR_BYTE0);
- net_dev->dev_addr[1] = rt2x00_get_field16(eeprom[0],
- EEPROM_MAC_ADDR_BYTE1);
- net_dev->dev_addr[2] = rt2x00_get_field16(eeprom[1],
- EEPROM_MAC_ADDR_BYTE2);
- net_dev->dev_addr[3] = rt2x00_get_field16(eeprom[1],
- EEPROM_MAC_ADDR_BYTE3);
- net_dev->dev_addr[4] = rt2x00_get_field16(eeprom[2],
- EEPROM_MAC_ADDR_BYTE4);
- net_dev->dev_addr[5] = rt2x00_get_field16(eeprom[2],
- EEPROM_MAC_ADDR_BYTE5);
-
- net_dev->addr_len = 6;
+ rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
+ (u16*)&eeprom[0], 6);
- if (!is_valid_ether_addr(&net_dev->dev_addr[0]))
+ /*
+ * Check if a valid MAC address has been read.
+ */
+ if (!is_valid_ether_addr(&eeprom[0]))
return -EINVAL;
+ /*
+ * Copy to netdevice structure.
+ */
+ memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
+ memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+ net_dev->addr_len = 6;
+
SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
return 0;
}
@@ -2738,9 +2706,8 @@ static int rt2500usb_alloc_dev(struct us
return -ENODEV;
/*
- * Initialize cofniguration work.
+ * Initialize configuration work.
*/
- INIT_WORK(&rt2x00dev->config_work, rt2500usb_config_update, rt2x00dev);
INIT_WORK(&rt2x00dev->interface.work,
rt2500usb_interface_update, rt2x00dev);
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2500usb.h b/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
index 42d44aa..917ba4c 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2500usb.h
@@ -679,8 +679,8 @@ #define TXPOWER_FROM_DEV(__txpower) \
#define TXPOWER_TO_DEV(__txpower) \
({ \
- ((__txpower) < MIN_TXPOWER) ? MIN_TXPOWER : \
- (((__txpower) > MAX_TXPOWER) ? MAX_TXPOWER : \
+ ((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
+ (((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
(__txpower)); \
})
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2x00.h b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
index 06fa2be..eb56aea 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2x00.h
@@ -82,6 +82,16 @@ #define DEBUG(__message, __args...) \
__FUNCTION__, ##__args);
/*
+ * Hardware button support (through radiobtn)
+ * The delay between each poll can be set by the user
+ * using the module parameter. Default value is 0,
+ * which means polling is disabled.
+ */
+#ifdef CONFIG_RT2X00_BUTTON
+#include <linux/rfkill.h>
+#endif /* CONFIG_RT2X00_BUTTON */
+
+/*
* Ring sizes.
* Ralink PCI devices demand the Frame size to be a multiple of 128 bytes.
* DATA_FRAME_SIZE is used for TX, RX, ATIM and PRIO rings.
@@ -734,7 +744,8 @@ struct scanning {
* Flag to see if this scan has been cancelled.
*/
short status;
-#define SCANNING_READY 0x0001
+#define SCANNING_READY 0x0000
+#define SCANNING_WAITING 0x0001
#define SCANNING_CANCELLED 0x0002
/*
@@ -743,6 +754,48 @@ #define SCANNING_CANCELLED 0x0002
struct work_struct work;
};
+static inline void rt2x00_start_scan(struct scanning *scan,
+ struct ieee80211_scan_conf *conf, int state)
+{
+ init_completion(&scan->completion);
+
+ memcpy(&scan->conf, conf, sizeof(*conf));
+
+ scan->state = state;
+
+ /*
+ * Set initial status to SCANNING_WAITING to prevent scanning
+ * to begin while there are still TX packets queued.
+ */
+ scan->status = SCANNING_WAITING;
+}
+
+static inline void rt2x00_signal_scan(struct scanning *scan, short status)
+{
+ scan->status = status;
+
+ complete_all(&scan->completion);
+}
+
+static inline int rt2x00_wait_scan(struct scanning *scan)
+{
+ /*
+ * Only wait for completion when the status
+ * indicates we should. The SCANNING_READY
+ * and SCANNING_CANCELLED are both states
+ * which indicate complete_all has already
+ * been called.
+ */
+ if (scan->status == SCANNING_WAITING)
+ wait_for_completion(&scan->completion);
+
+ /*
+ * Status field will have been updated by the handler
+ * that has called complete_all() on our complete structure.
+ */
+ return scan->status;
+}
+
/*
* rt2x00 device structure.
*/
@@ -751,7 +804,7 @@ struct rt2x00_dev {
* Device structure.
* The structure stored in here depends on the
* system bus (PCI or USB).
- * When accessing this variable, the rt2x00{pci,usb}_dev
+ * When accessing this variable, the rt2x00dev_{pci,usb}
* macro's should be used for correct typecasting.
*/
void *dev;
@@ -873,11 +926,6 @@ #endif /* CONFIG_RT2X00_BUTTON */
struct ieee80211_rx_status rx_params;
/*
- * work structure for configuration changes.
- */
- struct work_struct config_work;
-
- /*
* Scanning structure.
*/
struct scanning *scan;
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h b/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
index fe6f833..bd39395 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt2x00pci.h
@@ -44,115 +44,4 @@ #define EEPROM_WIDTH_93C66 8
#define EEPROM_WRITE_OPCODE 0x05
#define EEPROM_READ_OPCODE 0x06
-/*
- * HW button structure.
- */
-#ifdef CONFIG_RT2X00_BUTTON
-#include <acpi/acpi_bus.h>
-
-struct rt2x00_button {
- /*
- * ACPI device for generation of ACPI events.
- */
- struct acpi_device acpi_dev;
-
- /*
- * Timer for register polling.
- */
- struct timer_list poll_timer;
-
- /*
- * Timer delay.
- */
- short poll_delay;
-
- /*
- * Current status of button.
- */
- short button_status:1;
- short active_poll:1;
- short __pad:14;
-};
-#endif /* CONFIG_RT2X00_BUTTON */
-
-/*
- * HW button variables & functions.
- * The delay between each poll is set by the module parameter.
- */
-#ifdef CONFIG_RT2X00_BUTTON
-/*
- * Module parameter.
- */
-static short rt2x00_poll_delay = 0;
-
-static inline void rt2x00pci_button_status(struct rt2x00_dev *rt2x00dev,
- char status)
-{
- struct rt2x00_button *button = &rt2x00dev->button;
-
- if (!button->active_poll)
- return;
-
- if (status != button->button_status) {
- button->button_status = status;
- acpi_bus_generate_event(
- &button->acpi_dev, ACPI_TYPE_EVENT, status);
- }
-
- button->poll_timer.expires = jiffies + button->poll_delay;
-
- if (button->active_poll)
- add_timer(&button->poll_timer);
-}
-
-static inline void rt2x00pci_button_start(struct rt2x00_dev *rt2x00dev,
- void (*handler)(unsigned long data))
-{
- struct rt2x00_button *button = &rt2x00dev->button;
-
- /*
- * Only enable polling when the user has
- * set the poll delay module parameter,
- * and the device contains a hardware button.
- */
- if(!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON) ||
- !rt2x00_poll_delay)
- return;
-
- strcpy(acpi_device_class(&button->acpi_dev), DRV_NAME "_button");
- strcpy(acpi_device_bid(&button->acpi_dev), DRV_NAME);
- strcpy(acpi_device_name(&button->acpi_dev), DRV_NAME);
-
- init_timer(&button->poll_timer);
-
- button->poll_delay = rt2x00_poll_delay * (HZ / 10);
- button->button_status = 0;
- button->active_poll = 1;
-
- button->poll_timer.function = handler;
- button->poll_timer.data = (unsigned long)rt2x00dev;
- button->poll_timer.expires = jiffies + button->poll_delay;
-
- add_timer(&button->poll_timer);
-}
-
-static inline void rt2x00pci_button_stop(struct rt2x00_dev *rt2x00dev)
-{
- /*
- * Shutdown poll_timer for hardware button,
- * make sure only to disable polling when
- * it was enabled in the first place.
- */
- if(!rt2x00dev->button.active_poll)
- return;
-
- rt2x00dev->button.active_poll = 0;
- del_timer_sync(&rt2x00dev->button.poll_timer);
-}
-#else /* CONFIG_RT2X00_BUTTON */
-static inline void rt2x00pci_button_start(struct rt2x00_dev *rt2x00dev,
- void (*handler)(unsigned long data)){}
-static inline void rt2x00pci_button_stop(struct rt2x00_dev *rt2x00dev){}
-#endif /* CONFIG_RT2X00_BUTTON */
-
#endif /* RT2X00PCI_H */
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.c b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
index 8bb9de9..cc6789e 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.c
@@ -377,23 +377,6 @@ static void rt2x00_eeprom_multiread(cons
rt2x00_eeprom_read(rt2x00dev, word + i, data++);
}
-#ifdef CONFIG_RT61PCI_BUTTON
-/*
- * Hardware button poll handler.
- */
-static void rt61pci_button_poll(unsigned long data)
-{
- struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
- u32 reg;
-
- rt2x00_register_read(rt2x00dev, MAC_CSR13, ®);
- rt2x00pci_button_status(
- rt2x00dev, rt2x00_get_field32(reg, MAC_CSR13_BIT5));
-}
-#else /* CONFIG_RT61PCI_BUTTON */
-static void rt61pci_button_poll(unsigned long data){}
-#endif /* CONFIG_RT61PCI_BUTTON */
-
/*
* Ethtool handlers.
*/
@@ -465,8 +448,63 @@ #endif /* CONFIG_RT61PCI_DEBUG */
.get_link = ethtool_op_get_link,
.get_eeprom_len = rt61pci_get_eeprom_len,
.get_eeprom = rt61pci_get_eeprom,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
+#ifdef CONFIG_RT61PCI_BUTTON
+static int rt61pci_button_poll(unsigned long data)
+{
+ struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev*)data;
+ u32 reg;
+
+ rt2x00_register_read(rt2x00dev, MAC_CSR13, ®);
+ return rt2x00_get_field32(reg, MAC_CSR13_BIT5);
+}
+
+static void rt61pci_button_enable_radio(unsigned long data)
+{
+ rt61pci_enable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt61pci_button_disable_radio(unsigned long data)
+{
+ rt61pci_disable_radio((struct rt2x00_dev*)data);
+}
+
+static void rt61pci_button_start(struct rt2x00_dev *rt2x00dev)
+{
+ struct rfkill *rfkill = &rt2x00dev->rfkill;
+
+ /*
+ * Only start the button polling when
+ * the hardware button is present.
+ */
+ if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+ return;
+
+ rfkill->dev_name = "rt61pci";
+ rfkill->data = (unsigned long)rt2x00dev;
+ rfkill->poll = rt61pci_button_poll;
+ rfkill->enable_radio = rt61pci_button_enable_radio;
+ rfkill->disable_radio = rt61pci_button_disable_radio;
+ rfkill->current_status = !!rt61pci_button_poll(rfkill->data);
+
+ if (rfkill_add_device(rfkill))
+ ERROR("Failed to register button handler.\n");
+}
+
+static void rt61pci_button_stop(struct rt2x00_dev *rt2x00dev)
+{
+ if (!GET_FLAG(rt2x00dev, DEVICE_SUPPORT_HW_BUTTON))
+ return;
+
+ rfkill_del_device(&rt2x00dev->rfkill);
+}
+#else /* CONFIG_RT61PCI_BUTTON */
+static void rt61pci_button_start(struct rt2x00_dev *rt2x00dev){}
+static void rt61pci_button_stop(struct rt2x00_dev *rt2x00dev){}
+#endif /* CONFIG_RT61PCI_BUTTON */
+
/*
* Configuration handlers.
*/
@@ -1902,7 +1940,7 @@ static int rt61pci_initialize(struct rt2
* Register interrupt handler.
*/
if (request_irq(rt2x00dev_pci(rt2x00dev)->irq, rt61pci_interrupt,
- SA_SHIRQ, net_dev->name, rt2x00dev)) {
+ IRQF_SHARED, net_dev->name, rt2x00dev)) {
ERROR("IRQ %d allocation failed.\n",
rt2x00dev_pci(rt2x00dev)->irq);
goto exit_fail;
@@ -1926,10 +1964,8 @@ static void rt61pci_uninitialize(struct
/*
* Cancel scanning.
*/
- if (rt2x00dev->scan) {
- rt2x00dev->scan->status = SCANNING_CANCELLED;
- complete_all(&rt2x00dev->scan->completion);
- }
+ if (rt2x00dev->scan)
+ rt2x00_signal_scan(rt2x00dev->scan, SCANNING_CANCELLED);
/*
* Flush out all pending work.
@@ -2448,10 +2484,8 @@ static void rt61pci_txdone(void *data)
rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_BE]) &&
rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_VI]) &&
rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_VO]) &&
- rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO])) {
- rt2x00dev->scan->status = SCANNING_READY;
- complete(&rt2x00dev->scan->completion);
- }
+ rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO]))
+ rt2x00_signal_scan(rt2x00dev->scan, SCANNING_READY);
}
static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance,
@@ -2675,11 +2709,10 @@ static void rt61pci_remove_interface(str
rt61pci_disable_radio(rt2x00dev);
}
-static void rt61pci_config_update(void *data)
+static int rt61pci_config(struct net_device *net_dev,
+ struct ieee80211_conf *conf)
{
- struct rt2x00_dev *rt2x00dev = data;
- struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
- struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+ struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
u32 reg;
/*
@@ -2711,21 +2744,10 @@ static void rt61pci_config_update(void *
rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®);
rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0);
rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg);
- } else if (conf->radio_enabled) {
- if (rt61pci_enable_radio(rt2x00dev))
- return;
- }
-}
-
-static int rt61pci_config(struct net_device *net_dev,
- struct ieee80211_conf *conf)
-{
- struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+ } else if (conf->radio_enabled)
+ return rt61pci_enable_radio(rt2x00dev);
- /*
- * Queue work.
- */
- return !queue_work(rt2x00dev->workqueue, &rt2x00dev->config_work);
+ return 0;
}
static int rt61pci_config_interface(struct net_device *net_dev, int if_id,
@@ -2790,14 +2812,7 @@ static void rt61pci_scan(void *data)
* we need to wait untill all TX rings are empty to
* guarentee that all frames are send on the correct channel.
*/
- if (rt2x00dev->scan->status != SCANNING_READY)
- wait_for_completion(&rt2x00dev->scan->completion);
-
- /*
- * Check if this scan has been cancelled while
- * work was still scheduled.
- */
- if (rt2x00dev->scan->status == SCANNING_CANCELLED)
+ if (rt2x00_wait_scan(rt2x00dev->scan))
goto exit;
/*
@@ -2865,13 +2880,7 @@ static int rt61pci_passive_scan(struct n
/*
* Initialize Scanning structure.
*/
- init_completion(&rt2x00dev->scan->completion);
-
- memcpy(&rt2x00dev->scan->conf, conf, sizeof(*conf));
-
- rt2x00dev->scan->state = state;
-
- rt2x00dev->scan->status = 0;
+ rt2x00_start_scan(rt2x00dev->scan, conf, state);
/*
* Queue work.
@@ -3198,7 +3207,7 @@ static int rt61pci_init_eeprom(struct rt
static int rt61pci_init_mac(struct rt2x00_dev *rt2x00dev)
{
struct net_device *net_dev = pci_get_drvdata(rt2x00dev_pci(rt2x00dev));
- u16 eeprom[3] = { 0, 0, 0 };
+ u8 eeprom[6];
if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
return 0;
@@ -3206,26 +3215,22 @@ static int rt61pci_init_mac(struct rt2x0
/*
* Read MAC address from EEPROM.
*/
- rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR, &eeprom[0], 6);
-
- net_dev->dev_addr[0] = rt2x00_get_field16(eeprom[0],
- EEPROM_MAC_ADDR_BYTE0);
- net_dev->dev_addr[1] = rt2x00_get_field16(eeprom[0],
- EEPROM_MAC_ADDR_BYTE1);
- net_dev->dev_addr[2] = rt2x00_get_field16(eeprom[1],
- EEPROM_MAC_ADDR_BYTE2);
- net_dev->dev_addr[3] = rt2x00_get_field16(eeprom[1],
- EEPROM_MAC_ADDR_BYTE3);
- net_dev->dev_addr[4] = rt2x00_get_field16(eeprom[2],
- EEPROM_MAC_ADDR_BYTE4);
- net_dev->dev_addr[5] = rt2x00_get_field16(eeprom[2],
- EEPROM_MAC_ADDR_BYTE5);
+ rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
+ (u16*)&eeprom[0], 6);
- net_dev->addr_len = 6;
-
- if (!is_valid_ether_addr(&net_dev->dev_addr[0]))
+ /*
+ * Check if a valid MAC address has been read.
+ */
+ if (!is_valid_ether_addr(&eeprom[0]))
return -EINVAL;
+ /*
+ * Copy to netdevice structure.
+ */
+ memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
+ memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+ net_dev->addr_len = 6;
+
SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
return 0;
}
@@ -3491,7 +3496,6 @@ static int rt61pci_init_hw_modes(struct
hw->modes[0].num_channels = 14;
hw->modes[0].num_rates = 12;
-
/*
* Intitialize 802.11b
* Rates: CCK.
@@ -3547,7 +3551,7 @@ static void rt61pci_free_dev(struct net_
/*
* Shutdown poll_timer for hardware button.
*/
- rt2x00pci_button_stop(rt2x00dev);
+ rt61pci_button_stop(rt2x00dev);
/*
* Free ring structures.
@@ -3607,11 +3611,6 @@ static int rt61pci_alloc_dev(struct pci_
goto exit;
/*
- * Initialize configuration work.
- */
- INIT_WORK(&rt2x00dev->config_work, rt61pci_config_update, rt2x00dev);
-
- /*
* Reset current working type.
*/
rt2x00dev->interface.type = -EINVAL;
@@ -3646,7 +3645,7 @@ static int rt61pci_alloc_dev(struct pci_
/*
* If required start hardware button polling.
*/
- rt2x00pci_button_start(rt2x00dev, rt61pci_button_poll);
+ rt61pci_button_start(rt2x00dev);
return 0;
@@ -3665,10 +3664,16 @@ static int rt61pci_probe(struct pci_dev
struct net_device *net_dev;
int status;
+ status = pci_request_regions(pci_dev, pci_name(pci_dev));
+ if (status) {
+ ERROR("PCI request regions failed.\n");
+ return status;
+ }
+
status = pci_enable_device(pci_dev);
if (status) {
ERROR("Enable device failed.\n");
- return status;
+ goto exit_release_regions;
}
pci_set_master(pci_dev);
@@ -3683,17 +3688,11 @@ static int rt61pci_probe(struct pci_dev
goto exit_disable_device;
}
- status = pci_request_regions(pci_dev, pci_name(pci_dev));
- if (status) {
- ERROR("PCI request regions failed.\n");
- goto exit_disable_device;
- }
-
net_dev = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), NULL);
if (!net_dev) {
ERROR("Failed to allocate hardware.\n");
status = -ENOMEM;
- goto exit_release_regions;
+ goto exit_disable_device;
}
SET_ETHTOOL_OPS(net_dev, &rt61pci_ethtool_ops);
@@ -3712,13 +3711,13 @@ static int rt61pci_probe(struct pci_dev
exit_free_device:
ieee80211_free_hw(net_dev);
-exit_release_regions:
- pci_release_regions(pci_dev);
-
exit_disable_device:
if (status != -EBUSY)
pci_disable_device(pci_dev);
+exit_release_regions:
+ pci_release_regions(pci_dev);
+
pci_set_drvdata(pci_dev, NULL);
return status;
@@ -3741,9 +3740,9 @@ static void rt61pci_remove(struct pci_de
pci_set_drvdata(pci_dev, NULL);
- pci_release_regions(pci_dev);
-
pci_disable_device(pci_dev);
+
+ pci_release_regions(pci_dev);
}
#ifdef CONFIG_PM
@@ -3844,11 +3843,6 @@ module_param_named(debug, rt2x00_debug_l
MODULE_PARM_DESC(debug, "Set this parameter to 1 to enable debug output.");
#endif /* CONFIG_RT61PCI_DEBUG */
-#ifdef CONFIG_RT61PCI_BUTTON
-module_param_named(poll_delay, rt2x00_poll_delay, short, S_IRUGO);
-MODULE_PARM_DESC(debug, "Delay between WiFi button pollings (in 100ms).");
-#endif /* CONFIG_RT61PCI_BUTTON */
-
static struct pci_driver rt61pci_driver = {
.name = DRV_NAME,
.id_table = rt61pci_device_table,
diff --git a/drivers/net/wireless/d80211/rt2x00/rt61pci.h b/drivers/net/wireless/d80211/rt2x00/rt61pci.h
index d334390..2c5065b 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt61pci.h
@@ -1360,8 +1360,8 @@ #define TXPOWER_FROM_DEV(__txpower) \
#define TXPOWER_TO_DEV(__txpower) \
({ \
- ((__txpower) < MIN_TXPOWER) ? MIN_TXPOWER : \
- (((__txpower) > MAX_TXPOWER) ? MAX_TXPOWER : \
+ ((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
+ (((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
(__txpower)); \
})
diff --git a/drivers/net/wireless/d80211/rt2x00/rt73usb.c b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
index acc5357..682d078 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt73usb.c
@@ -286,6 +286,7 @@ #endif /* CONFIG_RT2500USB_DEBUG */
.get_link = ethtool_op_get_link,
.get_eeprom_len = rt73usb_get_eeprom_len,
.get_eeprom = rt73usb_get_eeprom,
+ .get_perm_addr = ethtool_op_get_perm_addr,
};
/*
@@ -1524,10 +1525,8 @@ static void rt73usb_uninitialize(struct
/*
* Cancel scanning.
*/
- if (rt2x00dev->scan) {
- rt2x00dev->scan->status = SCANNING_CANCELLED;
- complete_all(&rt2x00dev->scan->completion);
- }
+ if (rt2x00dev->scan)
+ rt2x00_signal_scan(rt2x00dev->scan, SCANNING_CANCELLED);
/*
* Flush out all pending work.
@@ -1999,10 +1998,8 @@ static void rt73usb_txdone(void *data)
rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_BE]) &&
rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_VI]) &&
rt2x00_ring_empty(&rt2x00dev->ring[RING_AC_VO]) &&
- rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO])) {
- rt2x00dev->scan->status = SCANNING_READY;
- complete(&rt2x00dev->scan->completion);
- }
+ rt2x00_ring_empty(&rt2x00dev->ring[RING_PRIO]))
+ rt2x00_signal_scan(rt2x00dev->scan, SCANNING_READY);
/*
* If the data ring was full before the txdone handler
@@ -2127,6 +2124,7 @@ static int rt73usb_tx(struct net_device
static int rt73usb_reset(struct net_device *net_dev)
{
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+
rt73usb_disable_radio(rt2x00dev);
return rt73usb_enable_radio(rt2x00dev);
}
@@ -2195,12 +2193,10 @@ static void rt73usb_remove_interface(str
rt73usb_disable_radio(rt2x00dev);
}
-static void rt73usb_config_update(void *data)
+static int rt73usb_config(struct net_device *net_dev,
+ struct ieee80211_conf *conf)
{
- struct rt2x00_dev *rt2x00dev = data;
- struct net_device *net_dev =
- usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
- struct ieee80211_conf *conf = ieee80211_get_hw_conf(net_dev);
+ struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
u32 reg;
/*
@@ -2232,21 +2228,10 @@ static void rt73usb_config_update(void *
rt2x00_register_read(rt2x00dev, TXRX_CSR0, ®);
rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0);
rt2x00_register_write(rt2x00dev, TXRX_CSR0, reg);
- } else if (conf->radio_enabled) {
- if (rt73usb_enable_radio(rt2x00dev))
- return;
- }
-}
-
-static int rt73usb_config(struct net_device *net_dev,
- struct ieee80211_conf *conf)
-{
- struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
+ } else if (conf->radio_enabled)
+ return rt73usb_enable_radio(rt2x00dev);
- /*
- * Queue work.
- */
- return !queue_work(rt2x00dev->workqueue, &rt2x00dev->config_work);
+ return 0;
}
static void rt73usb_interface_update(void *data)
@@ -2321,14 +2306,7 @@ static void rt73usb_scan(void *data)
* we need to wait untill all TX rings are empty to
* guarentee that all frames are send on the correct channel.
*/
- if (rt2x00dev->scan->status != SCANNING_READY)
- wait_for_completion(&rt2x00dev->scan->completion);
-
- /*
- * Check if this scan has been cancelled while
- * work was still scheduled.
- */
- if (rt2x00dev->scan->status == SCANNING_CANCELLED)
+ if (rt2x00_wait_scan(rt2x00dev->scan))
goto exit;
/*
@@ -2396,13 +2374,7 @@ static int rt73usb_passive_scan(struct n
/*
* Initialize Scanning structure.
*/
- init_completion(&rt2x00dev->scan->completion);
-
- memcpy(&rt2x00dev->scan->conf, conf, sizeof(*conf));
-
- rt2x00dev->scan->state = state;
-
- rt2x00dev->scan->status = 0;
+ rt2x00_start_scan(rt2x00dev->scan, conf, state);
/*
* Queue work.
@@ -2710,7 +2682,7 @@ static int rt73usb_init_mac(struct rt2x0
{
struct net_device *net_dev =
usb_get_intfdata(rt2x00dev_usb(rt2x00dev));
- u16 eeprom[3] = { 0, 0, 0 };
+ u8 eeprom[6];
if (GET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC))
return 0;
@@ -2718,26 +2690,22 @@ static int rt73usb_init_mac(struct rt2x0
/*
* Read MAC address from EEPROM.
*/
- rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR, &eeprom[0], 6);
-
- net_dev->dev_addr[0] = rt2x00_get_field16(eeprom[0],
- EEPROM_MAC_ADDR_BYTE0);
- net_dev->dev_addr[1] = rt2x00_get_field16(eeprom[0],
- EEPROM_MAC_ADDR_BYTE1);
- net_dev->dev_addr[2] = rt2x00_get_field16(eeprom[1],
- EEPROM_MAC_ADDR_BYTE2);
- net_dev->dev_addr[3] = rt2x00_get_field16(eeprom[1],
- EEPROM_MAC_ADDR_BYTE3);
- net_dev->dev_addr[4] = rt2x00_get_field16(eeprom[2],
- EEPROM_MAC_ADDR_BYTE4);
- net_dev->dev_addr[5] = rt2x00_get_field16(eeprom[2],
- EEPROM_MAC_ADDR_BYTE5);
+ rt2x00_eeprom_multiread(rt2x00dev, EEPROM_MAC_ADDR,
+ (u16*)&eeprom[0], 6);
- net_dev->addr_len = 6;
-
- if (!is_valid_ether_addr(&net_dev->dev_addr[0]))
+ /*
+ * Check if a valid MAC address has been read.
+ */
+ if (!is_valid_ether_addr(&eeprom[0]))
return -EINVAL;
+ /*
+ * Copy to netdevice structure.
+ */
+ memcpy(&net_dev->dev_addr[0], &eeprom[0], 6);
+ memcpy(&net_dev->perm_addr[0], &eeprom[0], 6);
+ net_dev->addr_len = 6;
+
SET_FLAG(rt2x00dev, DEVICE_INITIALIZED_MAC);
return 0;
}
@@ -3000,7 +2968,6 @@ static int rt73usb_init_hw_modes(struct
hw->modes[0].num_channels = 14;
hw->modes[0].num_rates = 12;
-
/*
* Intitialize 802.11b
* Rates: CCK.
@@ -3095,9 +3062,8 @@ static int rt73usb_alloc_dev(struct usb_
return -ENODEV;
/*
- * Initialize cofniguration work.
+ * Initialize configuration work.
*/
- INIT_WORK(&rt2x00dev->config_work, rt73usb_config_update, rt2x00dev);
INIT_WORK(&rt2x00dev->interface.work,
rt73usb_interface_update, rt2x00dev);
diff --git a/drivers/net/wireless/d80211/rt2x00/rt73usb.h b/drivers/net/wireless/d80211/rt2x00/rt73usb.h
index 662ca30..5be5e14 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/d80211/rt2x00/rt73usb.h
@@ -939,8 +939,8 @@ #define TXPOWER_FROM_DEV(__txpower) \
#define TXPOWER_TO_DEV(__txpower) \
({ \
- ((__txpower) < MIN_TXPOWER) ? MIN_TXPOWER : \
- (((__txpower) > MAX_TXPOWER) ? MAX_TXPOWER : \
+ ((__txpower) <= MIN_TXPOWER) ? MIN_TXPOWER : \
+ (((__txpower) >= MAX_TXPOWER) ? MAX_TXPOWER : \
(__txpower)); \
})
diff --git a/include/linux/input.h b/include/linux/input.h
index b3253ab..f16da66 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -488,6 +488,7 @@ #define KEY_PREVIOUS 0x19c
#define KEY_DIGITS 0x19d
#define KEY_TEEN 0x19e
#define KEY_TWEN 0x19f
+#define KEY_RFKILL 0x1a0
#define KEY_DEL_EOL 0x1c0
#define KEY_DEL_EOS 0x1c1
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
new file mode 100644
index 0000000..2e1c740
--- /dev/null
+++ b/include/linux/rfkill.h
@@ -0,0 +1,98 @@
+/*
+ Copyright (C) 2006 Ivo van Doorn
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ RF button support
+ Laptops are quite often equiped with a RF button to enable or
+ disable the radio of the network device attached to that button.
+ This network device usually is an integrated wireless network device,
+ or bluetooth device.
+ Some of these devices will disable the radio automaticly when the
+ RF button has been pressed, while other devices need to be polled
+ for the RF button status.
+ But in all cases the only interface that will have its radio disabled
+ will be the device that has the RF button attached to it. But it could
+ be desired that userspace performs this disabling of all radios in case
+ there are also interfaces without a RF button that need to be disabled.
+
+ The rfkill driver will contain a list of all devices with a RF button,
+ hardware drivers need to register their hardware to teh rfkill
+ interface it can take care of everything. If the RF button requires
+ polling to obtain the status this will be handled by rfkill as well.
+ Once the status of the button has changed and the hardware does not
+ automaticly enable or disable the radio rfkill provides with the
+ interface to do this correctly.
+
+ For each registered hardware button an input device will be created.
+ If this input device has been opened by the user, rfkill will send a
+ signal to userspace instead of the hardware about the new button
+ status. This will allow userpace to perform the correct steps
+ in order to bring down all interfaces.
+ */
+
+#ifndef RFKILL_H
+#define RFKILL_H
+
+#include <linux/list.h>
+#include <linux/input.h>
+
+#define RFKILL_POLL_DELAY ( HZ / 10 ) /* 100 ms */
+
+/**
+ * struct rfkill - rfkill button control structure.
+ * @dev_name: Name of the interface. This will become the name
+ * of the input device which will be created for this button.
+ * @data: Private data which will be passed along with the radio and polling
+ * handlers.
+ * @poll(unsigned long data): Optional handler which will frequently be
+ * called to determine the current status of the RF button.
+ * @enable_radio(unsigned long data): Optional handler to enable the radio
+ * once the RF button has been pressed and the hardware does enable
+ * the radio automaticly.
+ * @disable_radio(unsigned long data): Optional handler to disable the radio
+ * once the RF button has been pressed and the hardware does disable
+ * the radio automaticly.
+ * @current_status: Contains the current status of the radio as it was
+ * previously indicated by the radio. This field may only be changed
+ * by the driver at initialization time.
+ */
+struct rfkill {
+ const char *dev_name;
+
+ unsigned long data;
+
+ int (*poll)(unsigned long data);
+ void (*enable_radio)(unsigned long data);
+ void (*disable_radio)(unsigned long data);
+
+ unsigned int current_status;
+
+ /*
+ * These fields are private to rfkill, and
+ * should not be used by the RF button driver.
+ */
+ struct list_head entry;
+ struct input_dev *input_dev;
+};
+
+void rfkill_button_event(struct rfkill *rfkill, int status);
+int rfkill_add_device(struct rfkill *rfkill);
+void rfkill_del_device(struct rfkill *rfkill);
+
+#endif /* RFKILL_H */
diff --git a/net/d80211/ieee80211.c b/net/d80211/ieee80211.c
index 60eca90..11804d5 100644
--- a/net/d80211/ieee80211.c
+++ b/net/d80211/ieee80211.c
@@ -250,7 +250,7 @@ int ieee80211_get_hdrlen(u16 fc)
case IEEE80211_FTYPE_DATA:
if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))
hdrlen = 30; /* Addr4 */
- if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_QOS_DATA)
+ if (fc & IEEE80211_STYPE_QOS_DATA)
hdrlen += 2; /* QoS Control Field */
break;
case IEEE80211_FTYPE_CTL:
@@ -637,7 +637,7 @@ static int ieee80211_frame_duration(stru
* 802.11 (DS): 15.3.3, 802.11b: 18.3.4
* aSIFSTime = 10 usec
* aPreambleLength = 144 usec or 72 usec with short preamble
- * aPLCPHeaderLength = 48 ms or 24 ms with short preamble
+ * aPLCPHeaderLength = 48 usec or 24 usec with short preamble
*/
dur = 10; /* aSIFSTime = 10 usec */
dur += short_preamble ? (72 + 24) : (144 + 48);
@@ -762,7 +762,7 @@ ieee80211_tx_h_misc(struct ieee80211_txr
struct ieee80211_tx_control *control = tx->u.tx.control;
if (!is_multicast_ether_addr(hdr->addr1)) {
- if (tx->skb->len >= tx->local->rts_threshold &&
+ if (tx->skb->len + FCS_LEN > tx->local->rts_threshold &&
tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD) {
control->use_rts_cts = 1;
control->retry_limit =
@@ -1519,7 +1519,7 @@ static int ieee80211_subif_start_xmit(st
sta = sta_info_get(local, hdr.addr1);
if (sta) {
if (sta->flags & WLAN_STA_WME) {
- fc |= IEEE80211_STYPE_QOS_DATA << 4;
+ fc |= IEEE80211_STYPE_QOS_DATA;
hdrlen += 2;
}
sta_info_put(sta);
@@ -3074,8 +3074,9 @@ ieee80211_rx_h_check(struct ieee80211_tx
rx->sdata->type != IEEE80211_IF_TYPE_IBSS &&
(!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) {
if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
- !(rx->fc & IEEE80211_FCTL_TODS)) ||
- !rx->u.rx.ra_match) {
+ !(rx->fc & IEEE80211_FCTL_TODS) &&
+ (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)
+ || !rx->u.rx.ra_match) {
/* Drop IBSS frames and frames for other hosts
* silently. */
return TXRX_DROP;
@@ -3976,11 +3977,11 @@ static void ieee80211_remove_tx_extra(st
pkt_data->requeue = control->requeue;
pkt_data->queue = control->queue;
- if (key == NULL)
- return;
-
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+ if (key == NULL)
+ goto no_key;
+
switch (key->alg) {
case ALG_WEP:
iv_len = WEP_IV_LEN;
@@ -3995,7 +3996,7 @@ static void ieee80211_remove_tx_extra(st
mic_len = CCMP_MIC_LEN;
break;
default:
- return;
+ goto no_key;
}
if (skb->len >= mic_len && key->force_sw_encrypt)
@@ -4005,11 +4006,12 @@ static void ieee80211_remove_tx_extra(st
skb_pull(skb, iv_len);
}
+no_key:
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
u16 fc = le16_to_cpu(hdr->frame_control);
if ((fc & 0x8C) == 0x88) /* QoS Control Field */ {
- fc &= ~(IEEE80211_STYPE_QOS_DATA << 4);
+ fc &= ~IEEE80211_STYPE_QOS_DATA;
hdr->frame_control = cpu_to_le16(fc);
memmove(skb->data + 2, skb->data, hdrlen - 2);
skb_pull(skb, 2);
@@ -4379,7 +4381,7 @@ struct net_device *ieee80211_alloc_hw(si
mdev->hard_start_xmit = ieee80211_master_start_xmit;
mdev->wireless_handlers =
- (struct iw_handler_def *) &ieee80211_iw_handler_def;
+ (struct iw_handler_def *) &ieee80211_iw_master_handler_def;
mdev->do_ioctl = ieee80211_ioctl;
mdev->change_mtu = ieee80211_change_mtu;
mdev->tx_timeout = ieee80211_tx_timeout;
diff --git a/net/d80211/ieee80211_i.h b/net/d80211/ieee80211_i.h
index 7e021ec..bdaaf5e 100644
--- a/net/d80211/ieee80211_i.h
+++ b/net/d80211/ieee80211_i.h
@@ -569,6 +569,7 @@ void ieee80211_if_mgmt_setup(struct net_
/* ieee80211_ioctl.c */
int ieee80211_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
extern const struct iw_handler_def ieee80211_iw_handler_def;
+extern const struct iw_handler_def ieee80211_iw_master_handler_def;
/* Set hw encryption from ieee80211 */
int ieee80211_set_hw_encryption(struct net_device *dev,
diff --git a/net/d80211/ieee80211_ioctl.c b/net/d80211/ieee80211_ioctl.c
index dd52555..b983716 100644
--- a/net/d80211/ieee80211_ioctl.c
+++ b/net/d80211/ieee80211_ioctl.c
@@ -15,6 +15,7 @@ #include <linux/netdevice.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
#include <linux/if_arp.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
@@ -215,6 +216,52 @@ static int ieee80211_ioctl_flush(struct
}
+/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
+struct iapp_layer2_update {
+ u8 da[ETH_ALEN]; /* broadcast */
+ u8 sa[ETH_ALEN]; /* STA addr */
+ u16 len; /* 6 */
+ u8 dsap; /* 0 */
+ u8 ssap; /* 0 */
+ u8 control;
+ u8 xid_info[3];
+} __attribute__ ((packed));
+
+static void ieee80211_send_layer2_update(struct net_device *dev,
+ const u8 *addr)
+{
+ struct iapp_layer2_update *msg;
+ struct sk_buff *skb;
+
+ /* Send Level 2 Update Frame to update forwarding tables in layer 2
+ * bridge devices */
+
+ skb = dev_alloc_skb(sizeof(*msg));
+ if (skb == NULL)
+ return;
+ msg = (struct iapp_layer2_update *) skb_put(skb, sizeof(*msg));
+
+ /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
+ * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
+
+ memset(msg->da, 0xff, ETH_ALEN);
+ memcpy(msg->sa, addr, ETH_ALEN);
+ msg->len = htons(6);
+ msg->dsap = 0;
+ msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */
+ msg->control = 0xaf; /* XID response lsb.1111F101.
+ * F=0 (no poll command; unsolicited frame) */
+ msg->xid_info[0] = 0x81; /* XID format identifier */
+ msg->xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
+ msg->xid_info[2] = 0; /* XID sender's receive window size (RW) */
+
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ netif_rx(skb);
+}
+
+
static int ieee80211_ioctl_add_sta(struct net_device *dev,
struct prism2_hostapd_param *param)
{
@@ -296,6 +343,10 @@ static int ieee80211_ioctl_add_sta(struc
sta_info_put(sta);
+ if (sdata->type == IEEE80211_IF_TYPE_AP ||
+ sdata->type == IEEE80211_IF_TYPE_VLAN)
+ ieee80211_send_layer2_update(dev, param->sta_addr);
+
return 0;
}
@@ -1168,6 +1219,10 @@ #if 0
dev->name, MAC_ARG(param->sta_addr),
new_vlan_dev->name);
#endif
+ if (sta->dev != new_vlan_dev) {
+ ieee80211_send_layer2_update(new_vlan_dev,
+ sta->addr);
+ }
sta->dev = new_vlan_dev;
sta->vlan_id = param->u.set_sta_vlan.vlan_id;
dev_put(new_vlan_dev);
@@ -2500,7 +2555,7 @@ static int ieee80211_ioctl_prism2_param(
break;
case PRISM2_PARAM_MIXED_CELL:
- if (sdata->type != IEEE80211_IF_TYPE_STA ||
+ if (sdata->type != IEEE80211_IF_TYPE_STA &&
sdata->type != IEEE80211_IF_TYPE_IBSS)
ret = -EINVAL;
else
@@ -2525,7 +2580,7 @@ static int ieee80211_ioctl_prism2_param(
sdata->u.sta.create_ibss = !!value;
break;
case PRISM2_PARAM_WMM_ENABLED:
- if (sdata->type != IEEE80211_IF_TYPE_STA ||
+ if (sdata->type != IEEE80211_IF_TYPE_STA &&
sdata->type != IEEE80211_IF_TYPE_IBSS)
ret = -EINVAL;
else
@@ -2712,7 +2767,7 @@ static int ieee80211_ioctl_get_prism2_pa
break;
case PRISM2_PARAM_MIXED_CELL:
- if (sdata->type != IEEE80211_IF_TYPE_STA ||
+ if (sdata->type != IEEE80211_IF_TYPE_STA &&
sdata->type != IEEE80211_IF_TYPE_IBSS)
ret = -EINVAL;
else
@@ -2726,7 +2781,7 @@ static int ieee80211_ioctl_get_prism2_pa
*param = sdata->u.sta.key_mgmt;
break;
case PRISM2_PARAM_WMM_ENABLED:
- if (sdata->type != IEEE80211_IF_TYPE_STA ||
+ if (sdata->type != IEEE80211_IF_TYPE_STA &&
sdata->type != IEEE80211_IF_TYPE_IBSS)
ret = -EINVAL;
else
@@ -2778,7 +2833,7 @@ static int ieee80211_ioctl_siwmlme(struc
struct iw_mlme *mlme = (struct iw_mlme *) extra;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (sdata->type != IEEE80211_IF_TYPE_STA ||
+ if (sdata->type != IEEE80211_IF_TYPE_STA &&
sdata->type != IEEE80211_IF_TYPE_IBSS)
return -EINVAL;
@@ -3129,3 +3184,25 @@ const struct iw_handler_def ieee80211_iw
.private = (iw_handler *) ieee80211_private_handler,
.private_args = (struct iw_priv_args *) ieee80211_ioctl_priv,
};
+
+/* Wireless handlers for master interface */
+
+static const iw_handler ieee80211_master_handler[] =
+{
+ [SIOCGIWNAME - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwname,
+ [SIOCSIWFREQ - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwfreq,
+ [SIOCGIWFREQ - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwfreq,
+ [SIOCGIWRANGE - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwrange,
+ [SIOCSIWRTS - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwrts,
+ [SIOCGIWRTS - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwrts,
+ [SIOCSIWFRAG - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwfrag,
+ [SIOCGIWFRAG - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwfrag,
+ [SIOCSIWRETRY - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_siwretry,
+ [SIOCGIWRETRY - SIOCIWFIRST] = (iw_handler) ieee80211_ioctl_giwretry,
+};
+
+const struct iw_handler_def ieee80211_iw_master_handler_def =
+{
+ .num_standard = sizeof(ieee80211_master_handler) / sizeof(iw_handler),
+ .standard = ieee80211_master_handler,
+};
diff --git a/net/d80211/tkip.c b/net/d80211/tkip.c
index 3f0cf57..c27a7fe 100644
--- a/net/d80211/tkip.c
+++ b/net/d80211/tkip.c
@@ -286,6 +286,7 @@ #endif /* CONFIG_TKIP_DEBUG */
if (only_iv) {
res = TKIP_DECRYPT_OK;
+ key->u.tkip.rx_initialized[queue] = 1;
goto done;
}
diff --git a/net/d80211/wme.c b/net/d80211/wme.c
index c3c961d..fc2a113 100644
--- a/net/d80211/wme.c
+++ b/net/d80211/wme.c
@@ -76,7 +76,7 @@ ieee80211_rx_h_remove_qos_control(struct
memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2);
hdr = (struct ieee80211_hdr *) skb_pull(rx->skb, 2);
/* change frame type to non QOS */
- rx->fc = fc &= ~(IEEE80211_STYPE_QOS_DATA << 4);
+ rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA;
hdr->frame_control = cpu_to_le16(fc);
return TXRX_CONTINUE;
@@ -199,7 +199,7 @@ static inline int classify80211(struct s
}
/* is this a QoS frame? */
- qos = fc & (IEEE80211_STYPE_QOS_DATA << 4);
+ qos = fc & IEEE80211_STYPE_QOS_DATA;
if (!qos) {
skb->priority = 0; /* required for correct WPA/11i MIC */
diff --git a/net/d80211/wpa.c b/net/d80211/wpa.c
index 7919620..fe5861f 100644
--- a/net/d80211/wpa.c
+++ b/net/d80211/wpa.c
@@ -70,7 +70,7 @@ int ieee80211_get_hdr_info(const struct
a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
- (fc & IEEE80211_FCTL_STYPE) & IEEE80211_STYPE_QOS_DATA) {
+ fc & IEEE80211_STYPE_QOS_DATA) {
pos = (u8 *) &hdr->addr4;
if (a4_included)
pos += 6;
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply related [flat|nested] 11+ messages in thread
* What's new in wireless-dev?
@ 2006-08-24 19:08 John W. Linville
0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-08-24 19:08 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 4503 bytes --]
The following changes since commit f4a4ffcd3f5013bfb0cf7da41a5acfd7f8a5f1f3:
John W. Linville:
Merge branch 'from-linus'
are found in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git
David Kimdon:
d80211: allow for large scan results
d80211: fix multiple device support
d80211: fix interface removal
Jiri Benc:
d80211: remove useless and wrong check for interface type
Johannes Berg:
d80211: relax sysfs permissions
d80211: master link
d80211: pointers as extended booleans
d80211: use kzalloc()
d80211: get rid of WME bitfield
d80211: get rid of sta_aid in favour of keeping track of TIM
d80211: clean up exports
d80211: clean up includes
d80211: fix some sparse warnings
d80211: make lowlevel TX framedump option visible
d80211: surface IBSS debug
d80211: get rid of MICHAEL_MIC_HWACCEL define
d80211: surface powersave debug switch
d80211: fix some documentation
Michael Buesch:
d80211: add ieee80211_stop_queues()
bcm43xx-d80211: Init, shutdown and restart fixes
bcm43xx-d80211: New DMA engine code
bcm43xx-d80211: return correct hard_start_xmit error code
Add Sonics Silicon Backplane driver
bcm43xx: convert driver to use ssb
Michael Wu:
d80211: switch status codes, reason codes, and EIDs to enums
d80211: Group EIDs by standard, add remaining 802.11d EIDs
drivers/misc/Kconfig | 4
drivers/misc/Makefile | 5
drivers/misc/ssb.c | 1015 ++++++++++++++++
drivers/net/wireless/d80211/bcm43xx/Kconfig | 1
drivers/net/wireless/d80211/bcm43xx/bcm43xx.h | 306 +----
.../net/wireless/d80211/bcm43xx/bcm43xx_debugfs.c | 61 -
.../net/wireless/d80211/bcm43xx/bcm43xx_debugfs.h | 1
drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.c | 835 +++++++++----
drivers/net/wireless/d80211/bcm43xx/bcm43xx_dma.h | 297 +++--
.../net/wireless/d80211/bcm43xx/bcm43xx_ethtool.c | 2
drivers/net/wireless/d80211/bcm43xx/bcm43xx_leds.c | 8
drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c | 1282 ++++++--------------
drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.h | 5
drivers/net/wireless/d80211/bcm43xx/bcm43xx_phy.c | 66 +
drivers/net/wireless/d80211/bcm43xx/bcm43xx_pio.c | 9
.../net/wireless/d80211/bcm43xx/bcm43xx_power.c | 104 +-
.../net/wireless/d80211/bcm43xx/bcm43xx_radio.c | 10
.../net/wireless/d80211/bcm43xx/bcm43xx_sysfs.c | 112 --
drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.c | 9
drivers/net/wireless/d80211/bcm43xx/bcm43xx_xmit.h | 5
include/linux/ssb.h | 577 +++++++++
include/net/d80211.h | 144 +-
include/net/d80211_mgmt.h | 158 +-
net/d80211/Kconfig | 26
net/d80211/aes_ccm.c | 3
net/d80211/aes_ccm.h | 2
net/d80211/fifo_qdisc.c | 5
net/d80211/ieee80211.c | 276 ++--
net/d80211/ieee80211_i.h | 68 +
net/d80211/ieee80211_iface.c | 8
net/d80211/ieee80211_ioctl.c | 79 +
net/d80211/ieee80211_key.h | 7
net/d80211/ieee80211_scan.c | 12
net/d80211/ieee80211_sta.c | 113 +-
net/d80211/ieee80211_sysfs.c | 6
net/d80211/rate_control.c | 18
net/d80211/rate_control.h | 2
net/d80211/sta_info.c | 31
net/d80211/sta_info.h | 14
net/d80211/tkip.c | 15
net/d80211/tkip.h | 1
net/d80211/wep.c | 14
net/d80211/wme.c | 24
net/d80211/wme.h | 25
net/d80211/wpa.c | 17
45 files changed, 3475 insertions(+), 2307 deletions(-)
create mode 100644 drivers/misc/ssb.c
create mode 100644 include/linux/ssb.h
Omnibus patch attached as wireless-dev.patch.bz2.
--
John W. Linville
linville@tuxdriver.com
[-- Attachment #2: wireless-dev.patch.bz2 --]
[-- Type: application/x-bzip2, Size: 62392 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
* What's new in wireless-dev?
@ 2006-09-04 23:53 John W. Linville
0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-09-04 23:53 UTC (permalink / raw)
To: netdev
I apologize for the announcement delay -- I had a hiccup w/ my mail
server this weekend...
---
The following changes since commit a7bcae7c095077d89899b2bf0b8d81b8997f340f:
John W. Linville:
Merge branch 'from-linus'
are found in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git
David Kimdon:
d80211: fix crash in ieee80211_rx_michael_mic_report()
Ivo van Doorn:
rt2x00: Add register revision and firmware version to ethtool
rt2x00: basic rate mask
rt2x00: Mac address reading optimization
rt2x00: add/remove interface fix
rt2x00: Register initialization fixes
rt2x00: Respect return values
rt2x00: Add ieee80211_netif_oper() calls
rt2x00: change variable name
rt2x00: TXD/RTS fixes
rt2x00: Misc fixes
Michael Buesch:
ssb: minor fixes and cleanups
ssb: add MAINTAINERS entry
bcm43xx-d80211: add support for 4312
ssb: fix core CC and REV reading
bcm43xx-d80211: 4311 support
MAINTAINERS | 6 +
drivers/misc/ssb.c | 23 ++-
drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c | 13 ++
.../net/wireless/d80211/bcm43xx/bcm43xx_power.c | 27 +++--
drivers/net/wireless/d80211/rt2x00/rt2400pci.c | 119 +++++++++++++-----
drivers/net/wireless/d80211/rt2x00/rt2400pci.h | 15 ++
drivers/net/wireless/d80211/rt2x00/rt2500pci.c | 129 ++++++++++++++------
drivers/net/wireless/d80211/rt2x00/rt2500pci.h | 17 ++-
drivers/net/wireless/d80211/rt2x00/rt2500usb.c | 127 +++++++++++++------
drivers/net/wireless/d80211/rt2x00/rt2500usb.h | 6 +
drivers/net/wireless/d80211/rt2x00/rt2x00.h | 60 +++++++++
drivers/net/wireless/d80211/rt2x00/rt61pci.c | 132 ++++++++++++++------
drivers/net/wireless/d80211/rt2x00/rt61pci.h | 6 +
drivers/net/wireless/d80211/rt2x00/rt73usb.c | 113 +++++++++++++----
drivers/net/wireless/d80211/rt2x00/rt73usb.h | 6 +
include/linux/ssb.h | 46 ++++++-
net/d80211/ieee80211.c | 7 +
17 files changed, 632 insertions(+), 220 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 8a88b78..783c1ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2650,6 +2650,12 @@ M: tsbogend@alpha.franken.de
L: netdev@vger.kernel.org
S: Maintained
+SONICS SILICON BACKPLANE DRIVER (SSB)
+P: Michael Buesch
+M: mb@bu3sch.de
+L: netdev@vger.kernel.org
+S: Maintained
+
SONY VAIO CONTROL DEVICE DRIVER
P: Stelian Pop
M: stelian@popies.net
diff --git a/drivers/misc/ssb.c b/drivers/misc/ssb.c
index 55e1447..44ab647 100644
--- a/drivers/misc/ssb.c
+++ b/drivers/misc/ssb.c
@@ -518,7 +518,8 @@ int ssb_init(struct ssb *ssb,
{
int err;
- if (!ssb || !pci_dev || !device_suspend || !device_resume)
+ if (!ssb || !pci_dev || !mmio ||
+ !device_suspend || !device_resume)
return -EINVAL;
memset(ssb, 0, sizeof(*ssb));
@@ -551,9 +552,9 @@ void ssb_exit(struct ssb *ssb)
list_del(&ssb->list);
mutex_unlock(&ssb_list_mutex);
+ mutex_destroy(&ssb->suspend_mutex);
+ mutex_destroy(&ssb->mutex);
kfree(ssb->cores);
- if (SSB_DEBUG)
- memset(ssb, 0x5B, sizeof(*ssb));
}
EXPORT_SYMBOL_GPL(ssb_exit);
@@ -592,8 +593,8 @@ error:
return -ENODEV;
}
-int ssb_switch_core_locked(struct ssb *ssb,
- struct ssb_core *new_core)
+static int ssb_switch_core_locked(struct ssb *ssb,
+ struct ssb_core *new_core)
{
int err = 0;
@@ -642,8 +643,9 @@ int ssb_probe_cores(struct ssb *ssb,
goto error;
idhi = ssb_read32(ssb, SSB_IDHIGH);
- cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
- rev = (idhi & SSB_IDHIGH_RC_MASK);
+ cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+ rev = (idhi & SSB_IDHIGH_RCLO);
+ rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
ssb->chipcommon_capabilities = 0;
ssb->nr_cores = 0;
@@ -715,9 +717,10 @@ int ssb_probe_cores(struct ssb *ssb,
core = &(ssb->cores[i]);
idhi = ssb_read32(ssb, SSB_IDHIGH);
- core->cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
- core->rev = (idhi & SSB_IDHIGH_RC_MASK);
- core->vendor = (idhi & SSB_IDHIGH_VC_MASK) >> SSB_IDHIGH_VC_SHIFT;
+ core->cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+ core->rev = (idhi & SSB_IDHIGH_RCLO);
+ core->rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
+ core->vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
core->index = i;
dprintk(KERN_DEBUG PFX "Core %d found: "
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
index b47f006..d71d797 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -129,6 +129,10 @@ static struct pci_device_id bcm43xx_pci_
{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4307 802.11b */
{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4311 802.11a/b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4312 802.11a/b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4318 802.11b/g */
{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4319 802.11b/g */
@@ -2299,7 +2303,9 @@ static int bcm43xx_wireless_core_init(st
u32 sbimconfiglow;
u8 limit;
- if (bcm->ssb.chip_rev < 5) {
+ assert(bcm->core_pci);
+ if (bcm->core_pci->cc == SSB_CC_PCI &&
+ bcm->core_pci->rev <= 5) {
sbimconfiglow = bcm43xx_read32(bcm, SSB_IMCFGLO);
sbimconfiglow &= ~SSB_IMCFGLO_REQTO;
sbimconfiglow &= ~SSB_IMCFGLO_SERTO;
@@ -2710,6 +2716,7 @@ #endif
switch (core->cc) {
case SSB_CC_PCI:
+ case SSB_CC_PCIE:
if (bcm->core_pci) {
printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
break;
@@ -2742,7 +2749,7 @@ #endif
switch (core->rev) {
case 2: case 4: case 5: case 6:
- case 7: case 9:
+ case 7: case 9: case 10:
break;
default:
printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
@@ -3247,7 +3254,7 @@ static int bcm43xx_read_phyinfo(struct b
phy_rev_ok = 0;
break;
case BCM43xx_PHYTYPE_G:
- if (phy_rev > 7)
+ if (phy_rev > 8)
phy_rev_ok = 0;
break;
default:
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
index 6aa2a33..702af69 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
@@ -153,8 +153,6 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
int err, maxfreq;
struct ssb_core *old_core;
- if (!(bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL))
- return 0;
if (!bcm->core_chipcommon)
return 0;
@@ -163,11 +161,26 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
if (err)
goto out;
- maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
- bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
- (maxfreq * 150 + 999999) / 1000000);
- bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
- (maxfreq * 15 + 999999) / 1000000);
+ if (bcm->ssb.chip_id == 0x4321) {
+ if (bcm->ssb.chip_rev == 0)
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x03A4);
+ else if (bcm->ssb.chip_rev == 1)
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x00A4);
+ }
+ if (bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL) {
+ if (bcm->core_chipcommon->rev >= 10) {
+ /* Set Idle Power clock rate to 1Mhz */
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_SYSCLKCTL,
+ (bcm43xx_read32(bcm, SSB_CHIPCOMMON_SYSCLKCTL) &
+ 0x0000FFFF) | 0x00040000);
+ } else {
+ maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
+ (maxfreq * 150 + 999999) / 1000000);
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
+ (maxfreq * 15 + 999999) / 1000000);
+ }
+ }
err = ssb_switch_core(&bcm->ssb, old_core);
assert(err == 0);
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
index 00f3a66..59163bf 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
@@ -373,6 +373,7 @@ static void rt2400pci_get_drvinfo(struct
strcpy(drvinfo->driver, DRV_NAME);
strcpy(drvinfo->version, DRV_VERSION);
+ strcpy(drvinfo->fw_version, "N/A");
strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
drvinfo->eedump_len = EEPROM_SIZE;
drvinfo->regdump_len = CSR_REG_SIZE;
@@ -389,7 +390,7 @@ static void rt2400pci_get_regs(struct ne
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
- regs->version = *((u32*)data);
+ regs->version = rt2x00_rev(&rt2x00dev->chip);
regs->len = CSR_REG_SIZE;
}
@@ -751,7 +752,12 @@ static void rt2400pci_config_rate(struct
preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
? SHORT_PREAMBLE : PREAMBLE;
- reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+ /*
+ * Extract the allowed ratemask from the device specific rate value,
+ * We need to set ARCSR1 to the basic rate mask so we need to mask
+ * off the non-basic rates.
+ */
+ reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
rt2x00_register_write(rt2x00dev, ARCSR1, cpu_to_le32(reg[0]));
@@ -767,12 +773,12 @@ static void rt2400pci_config_rate(struct
rt2x00_set_field32(®[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);
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply related [flat|nested] 11+ messages in thread
* What's new in wireless-dev?
@ 2006-09-05 0:02 John W. Linville
0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-09-05 0:02 UTC (permalink / raw)
To: netdev
I apologize for the announcement delay -- I had a hiccup w/ my mail
server this weekend...
(Sorry if you get this twice, vger's new bogofilter doesn't seem to
be playing nice...)
---
The following changes since commit a7bcae7c095077d89899b2bf0b8d81b8997f340f:
John W. Linville:
Merge branch 'from-linus'
are found in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git
David Kimdon:
d80211: fix crash in ieee80211_rx_michael_mic_report()
Ivo van Doorn:
rt2x00: Add register revision and firmware version to ethtool
rt2x00: basic rate mask
rt2x00: Mac address reading optimization
rt2x00: add/remove interface fix
rt2x00: Register initialization fixes
rt2x00: Respect return values
rt2x00: Add ieee80211_netif_oper() calls
rt2x00: change variable name
rt2x00: TXD/RTS fixes
rt2x00: Misc fixes
Michael Buesch:
ssb: minor fixes and cleanups
ssb: add MAINTAINERS entry
bcm43xx-d80211: add support for 4312
ssb: fix core CC and REV reading
bcm43xx-d80211: 4311 support
MAINTAINERS | 6 +
drivers/misc/ssb.c | 23 ++-
drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c | 13 ++
.../net/wireless/d80211/bcm43xx/bcm43xx_power.c | 27 +++--
drivers/net/wireless/d80211/rt2x00/rt2400pci.c | 119 +++++++++++++-----
drivers/net/wireless/d80211/rt2x00/rt2400pci.h | 15 ++
drivers/net/wireless/d80211/rt2x00/rt2500pci.c | 129 ++++++++++++++------
drivers/net/wireless/d80211/rt2x00/rt2500pci.h | 17 ++-
drivers/net/wireless/d80211/rt2x00/rt2500usb.c | 127 +++++++++++++------
drivers/net/wireless/d80211/rt2x00/rt2500usb.h | 6 +
drivers/net/wireless/d80211/rt2x00/rt2x00.h | 60 +++++++++
drivers/net/wireless/d80211/rt2x00/rt61pci.c | 132 ++++++++++++++------
drivers/net/wireless/d80211/rt2x00/rt61pci.h | 6 +
drivers/net/wireless/d80211/rt2x00/rt73usb.c | 113 +++++++++++++----
drivers/net/wireless/d80211/rt2x00/rt73usb.h | 6 +
include/linux/ssb.h | 46 ++++++-
net/d80211/ieee80211.c | 7 +
17 files changed, 632 insertions(+), 220 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 8a88b78..783c1ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2650,6 +2650,12 @@ M: tsbogend@alpha.franken.de
L: netdev@vger.kernel.org
S: Maintained
+SONICS SILICON BACKPLANE DRIVER (SSB)
+P: Michael Buesch
+M: mb@bu3sch.de
+L: netdev@vger.kernel.org
+S: Maintained
+
SONY VAIO CONTROL DEVICE DRIVER
P: Stelian Pop
M: stelian@popies.net
diff --git a/drivers/misc/ssb.c b/drivers/misc/ssb.c
index 55e1447..44ab647 100644
--- a/drivers/misc/ssb.c
+++ b/drivers/misc/ssb.c
@@ -518,7 +518,8 @@ int ssb_init(struct ssb *ssb,
{
int err;
- if (!ssb || !pci_dev || !device_suspend || !device_resume)
+ if (!ssb || !pci_dev || !mmio ||
+ !device_suspend || !device_resume)
return -EINVAL;
memset(ssb, 0, sizeof(*ssb));
@@ -551,9 +552,9 @@ void ssb_exit(struct ssb *ssb)
list_del(&ssb->list);
mutex_unlock(&ssb_list_mutex);
+ mutex_destroy(&ssb->suspend_mutex);
+ mutex_destroy(&ssb->mutex);
kfree(ssb->cores);
- if (SSB_DEBUG)
- memset(ssb, 0x5B, sizeof(*ssb));
}
EXPORT_SYMBOL_GPL(ssb_exit);
@@ -592,8 +593,8 @@ error:
return -ENODEV;
}
-int ssb_switch_core_locked(struct ssb *ssb,
- struct ssb_core *new_core)
+static int ssb_switch_core_locked(struct ssb *ssb,
+ struct ssb_core *new_core)
{
int err = 0;
@@ -642,8 +643,9 @@ int ssb_probe_cores(struct ssb *ssb,
goto error;
idhi = ssb_read32(ssb, SSB_IDHIGH);
- cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
- rev = (idhi & SSB_IDHIGH_RC_MASK);
+ cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+ rev = (idhi & SSB_IDHIGH_RCLO);
+ rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
ssb->chipcommon_capabilities = 0;
ssb->nr_cores = 0;
@@ -715,9 +717,10 @@ int ssb_probe_cores(struct ssb *ssb,
core = &(ssb->cores[i]);
idhi = ssb_read32(ssb, SSB_IDHIGH);
- core->cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
- core->rev = (idhi & SSB_IDHIGH_RC_MASK);
- core->vendor = (idhi & SSB_IDHIGH_VC_MASK) >> SSB_IDHIGH_VC_SHIFT;
+ core->cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+ core->rev = (idhi & SSB_IDHIGH_RCLO);
+ core->rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
+ core->vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
core->index = i;
dprintk(KERN_DEBUG PFX "Core %d found: "
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
index b47f006..d71d797 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -129,6 +129,10 @@ static struct pci_device_id bcm43xx_pci_
{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4307 802.11b */
{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4311 802.11a/b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4312 802.11a/b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4318 802.11b/g */
{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4319 802.11b/g */
@@ -2299,7 +2303,9 @@ static int bcm43xx_wireless_core_init(st
u32 sbimconfiglow;
u8 limit;
- if (bcm->ssb.chip_rev < 5) {
+ assert(bcm->core_pci);
+ if (bcm->core_pci->cc == SSB_CC_PCI &&
+ bcm->core_pci->rev <= 5) {
sbimconfiglow = bcm43xx_read32(bcm, SSB_IMCFGLO);
sbimconfiglow &= ~SSB_IMCFGLO_REQTO;
sbimconfiglow &= ~SSB_IMCFGLO_SERTO;
@@ -2710,6 +2716,7 @@ #endif
switch (core->cc) {
case SSB_CC_PCI:
+ case SSB_CC_PCIE:
if (bcm->core_pci) {
printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
break;
@@ -2742,7 +2749,7 @@ #endif
switch (core->rev) {
case 2: case 4: case 5: case 6:
- case 7: case 9:
+ case 7: case 9: case 10:
break;
default:
printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
@@ -3247,7 +3254,7 @@ static int bcm43xx_read_phyinfo(struct b
phy_rev_ok = 0;
break;
case BCM43xx_PHYTYPE_G:
- if (phy_rev > 7)
+ if (phy_rev > 8)
phy_rev_ok = 0;
break;
default:
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
index 6aa2a33..702af69 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
@@ -153,8 +153,6 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
int err, maxfreq;
struct ssb_core *old_core;
- if (!(bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL))
- return 0;
if (!bcm->core_chipcommon)
return 0;
@@ -163,11 +161,26 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
if (err)
goto out;
- maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
- bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
- (maxfreq * 150 + 999999) / 1000000);
- bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
- (maxfreq * 15 + 999999) / 1000000);
+ if (bcm->ssb.chip_id == 0x4321) {
+ if (bcm->ssb.chip_rev == 0)
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x03A4);
+ else if (bcm->ssb.chip_rev == 1)
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x00A4);
+ }
+ if (bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL) {
+ if (bcm->core_chipcommon->rev >= 10) {
+ /* Set Idle Power clock rate to 1Mhz */
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_SYSCLKCTL,
+ (bcm43xx_read32(bcm, SSB_CHIPCOMMON_SYSCLKCTL) &
+ 0x0000FFFF) | 0x00040000);
+ } else {
+ maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
+ (maxfreq * 150 + 999999) / 1000000);
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
+ (maxfreq * 15 + 999999) / 1000000);
+ }
+ }
err = ssb_switch_core(&bcm->ssb, old_core);
assert(err == 0);
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
index 00f3a66..59163bf 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
@@ -373,6 +373,7 @@ static void rt2400pci_get_drvinfo(struct
strcpy(drvinfo->driver, DRV_NAME);
strcpy(drvinfo->version, DRV_VERSION);
+ strcpy(drvinfo->fw_version, "N/A");
strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
drvinfo->eedump_len = EEPROM_SIZE;
drvinfo->regdump_len = CSR_REG_SIZE;
@@ -389,7 +390,7 @@ static void rt2400pci_get_regs(struct ne
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
- regs->version = *((u32*)data);
+ regs->version = rt2x00_rev(&rt2x00dev->chip);
regs->len = CSR_REG_SIZE;
}
@@ -751,7 +752,12 @@ static void rt2400pci_config_rate(struct
preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
? SHORT_PREAMBLE : PREAMBLE;
- reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+ /*
+ * Extract the allowed ratemask from the device specific rate value,
+ * We need to set ARCSR1 to the basic rate mask so we need to mask
+ * off the non-basic rates.
+ */
+ reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
rt2x00_register_write(rt2x00dev, ARCSR1, cpu_to_le32(reg[0]));
@@ -767,12 +773,12 @@ static void rt2400pci_config_rate(struct
rt2x00_set_field32(®[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);
--
John W. Linville
linville@tuxdriver.com
^ permalink raw reply related [flat|nested] 11+ messages in thread
* What's new in wireless-dev?
@ 2006-09-05 0:10 John W. Linville
0 siblings, 0 replies; 11+ messages in thread
From: John W. Linville @ 2006-09-05 0:10 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 366 bytes --]
(Third attempt -- vger's new bogofilter seems a bit over-zealous...)
New stuff in wireless-dev since Saturday or so. I apologize for the delayed announcement, but I was having some local IT problems...
I'm going to try attaching the rest -- bogofilter seems to think I'm sending spam...wtf???
I hope this works!
John
--
John W. Linville
linville@tuxdriver.com
[-- Attachment #2: wireless-dev.txt --]
[-- Type: text/plain, Size: 74382 bytes --]
The following changes since commit a7bcae7c095077d89899b2bf0b8d81b8997f340f:
John W. Linville:
Merge branch 'from-linus'
are found in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-dev.git
David Kimdon:
d80211: fix crash in ieee80211_rx_michael_mic_report()
Ivo van Doorn:
rt2x00: Add register revision and firmware version to ethtool
rt2x00: basic rate mask
rt2x00: Mac address reading optimization
rt2x00: add/remove interface fix
rt2x00: Register initialization fixes
rt2x00: Respect return values
rt2x00: Add ieee80211_netif_oper() calls
rt2x00: change variable name
rt2x00: TXD/RTS fixes
rt2x00: Misc fixes
Michael Buesch:
ssb: minor fixes and cleanups
ssb: add MAINTAINERS entry
bcm43xx-d80211: add support for 4312
ssb: fix core CC and REV reading
bcm43xx-d80211: 4311 support
MAINTAINERS | 6 +
drivers/misc/ssb.c | 23 ++-
drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c | 13 ++
.../net/wireless/d80211/bcm43xx/bcm43xx_power.c | 27 +++--
drivers/net/wireless/d80211/rt2x00/rt2400pci.c | 119 +++++++++++++-----
drivers/net/wireless/d80211/rt2x00/rt2400pci.h | 15 ++
drivers/net/wireless/d80211/rt2x00/rt2500pci.c | 129 ++++++++++++++------
drivers/net/wireless/d80211/rt2x00/rt2500pci.h | 17 ++-
drivers/net/wireless/d80211/rt2x00/rt2500usb.c | 127 +++++++++++++------
drivers/net/wireless/d80211/rt2x00/rt2500usb.h | 6 +
drivers/net/wireless/d80211/rt2x00/rt2x00.h | 60 +++++++++
drivers/net/wireless/d80211/rt2x00/rt61pci.c | 132 ++++++++++++++------
drivers/net/wireless/d80211/rt2x00/rt61pci.h | 6 +
drivers/net/wireless/d80211/rt2x00/rt73usb.c | 113 +++++++++++++----
drivers/net/wireless/d80211/rt2x00/rt73usb.h | 6 +
include/linux/ssb.h | 46 ++++++-
net/d80211/ieee80211.c | 7 +
17 files changed, 632 insertions(+), 220 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 8a88b78..783c1ad 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2650,6 +2650,12 @@ M: tsbogend@alpha.franken.de
L: netdev@vger.kernel.org
S: Maintained
+SONICS SILICON BACKPLANE DRIVER (SSB)
+P: Michael Buesch
+M: mb@bu3sch.de
+L: netdev@vger.kernel.org
+S: Maintained
+
SONY VAIO CONTROL DEVICE DRIVER
P: Stelian Pop
M: stelian@popies.net
diff --git a/drivers/misc/ssb.c b/drivers/misc/ssb.c
index 55e1447..44ab647 100644
--- a/drivers/misc/ssb.c
+++ b/drivers/misc/ssb.c
@@ -518,7 +518,8 @@ int ssb_init(struct ssb *ssb,
{
int err;
- if (!ssb || !pci_dev || !device_suspend || !device_resume)
+ if (!ssb || !pci_dev || !mmio ||
+ !device_suspend || !device_resume)
return -EINVAL;
memset(ssb, 0, sizeof(*ssb));
@@ -551,9 +552,9 @@ void ssb_exit(struct ssb *ssb)
list_del(&ssb->list);
mutex_unlock(&ssb_list_mutex);
+ mutex_destroy(&ssb->suspend_mutex);
+ mutex_destroy(&ssb->mutex);
kfree(ssb->cores);
- if (SSB_DEBUG)
- memset(ssb, 0x5B, sizeof(*ssb));
}
EXPORT_SYMBOL_GPL(ssb_exit);
@@ -592,8 +593,8 @@ error:
return -ENODEV;
}
-int ssb_switch_core_locked(struct ssb *ssb,
- struct ssb_core *new_core)
+static int ssb_switch_core_locked(struct ssb *ssb,
+ struct ssb_core *new_core)
{
int err = 0;
@@ -642,8 +643,9 @@ int ssb_probe_cores(struct ssb *ssb,
goto error;
idhi = ssb_read32(ssb, SSB_IDHIGH);
- cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
- rev = (idhi & SSB_IDHIGH_RC_MASK);
+ cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+ rev = (idhi & SSB_IDHIGH_RCLO);
+ rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
ssb->chipcommon_capabilities = 0;
ssb->nr_cores = 0;
@@ -715,9 +717,10 @@ int ssb_probe_cores(struct ssb *ssb,
core = &(ssb->cores[i]);
idhi = ssb_read32(ssb, SSB_IDHIGH);
- core->cc = (idhi & SSB_IDHIGH_CC_MASK) >> SSB_IDHIGH_CC_SHIFT;
- core->rev = (idhi & SSB_IDHIGH_RC_MASK);
- core->vendor = (idhi & SSB_IDHIGH_VC_MASK) >> SSB_IDHIGH_VC_SHIFT;
+ core->cc = (idhi & SSB_IDHIGH_CC) >> SSB_IDHIGH_CC_SHIFT;
+ core->rev = (idhi & SSB_IDHIGH_RCLO);
+ core->rev |= (idhi & SSB_IDHIGH_RCHI) >> SSB_IDHIGH_RCHI_SHIFT;
+ core->vendor = (idhi & SSB_IDHIGH_VC) >> SSB_IDHIGH_VC_SHIFT;
core->index = i;
dprintk(KERN_DEBUG PFX "Core %d found: "
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
index b47f006..d71d797 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_main.c
@@ -129,6 +129,10 @@ static struct pci_device_id bcm43xx_pci_
{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4307 802.11b */
{ PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4311 802.11a/b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ /* Broadcom 4312 802.11a/b/g */
+ { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4318 802.11b/g */
{ PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4319 802.11b/g */
@@ -2299,7 +2303,9 @@ static int bcm43xx_wireless_core_init(st
u32 sbimconfiglow;
u8 limit;
- if (bcm->ssb.chip_rev < 5) {
+ assert(bcm->core_pci);
+ if (bcm->core_pci->cc == SSB_CC_PCI &&
+ bcm->core_pci->rev <= 5) {
sbimconfiglow = bcm43xx_read32(bcm, SSB_IMCFGLO);
sbimconfiglow &= ~SSB_IMCFGLO_REQTO;
sbimconfiglow &= ~SSB_IMCFGLO_SERTO;
@@ -2710,6 +2716,7 @@ #endif
switch (core->cc) {
case SSB_CC_PCI:
+ case SSB_CC_PCIE:
if (bcm->core_pci) {
printk(KERN_WARNING PFX "Multiple PCI cores found.\n");
break;
@@ -2742,7 +2749,7 @@ #endif
switch (core->rev) {
case 2: case 4: case 5: case 6:
- case 7: case 9:
+ case 7: case 9: case 10:
break;
default:
printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n",
@@ -3247,7 +3254,7 @@ static int bcm43xx_read_phyinfo(struct b
phy_rev_ok = 0;
break;
case BCM43xx_PHYTYPE_G:
- if (phy_rev > 7)
+ if (phy_rev > 8)
phy_rev_ok = 0;
break;
default:
diff --git a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
index 6aa2a33..702af69 100644
--- a/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
+++ b/drivers/net/wireless/d80211/bcm43xx/bcm43xx_power.c
@@ -153,8 +153,6 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
int err, maxfreq;
struct ssb_core *old_core;
- if (!(bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL))
- return 0;
if (!bcm->core_chipcommon)
return 0;
@@ -163,11 +161,26 @@ int bcm43xx_pctl_init(struct bcm43xx_pri
if (err)
goto out;
- maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
- bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
- (maxfreq * 150 + 999999) / 1000000);
- bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
- (maxfreq * 15 + 999999) / 1000000);
+ if (bcm->ssb.chip_id == 0x4321) {
+ if (bcm->ssb.chip_rev == 0)
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x03A4);
+ else if (bcm->ssb.chip_rev == 1)
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_CHIPCTL, 0x00A4);
+ }
+ if (bcm->ssb.chipcommon_capabilities & SSB_CHIPCOMMON_CAP_PCTL) {
+ if (bcm->core_chipcommon->rev >= 10) {
+ /* Set Idle Power clock rate to 1Mhz */
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_SYSCLKCTL,
+ (bcm43xx_read32(bcm, SSB_CHIPCOMMON_SYSCLKCTL) &
+ 0x0000FFFF) | 0x00040000);
+ } else {
+ maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1);
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_PLLONDELAY,
+ (maxfreq * 150 + 999999) / 1000000);
+ bcm43xx_write32(bcm, SSB_CHIPCOMMON_FREFSELDELAY,
+ (maxfreq * 15 + 999999) / 1000000);
+ }
+ }
err = ssb_switch_core(&bcm->ssb, old_core);
assert(err == 0);
diff --git a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
index 00f3a66..59163bf 100644
--- a/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/d80211/rt2x00/rt2400pci.c
@@ -373,6 +373,7 @@ static void rt2400pci_get_drvinfo(struct
strcpy(drvinfo->driver, DRV_NAME);
strcpy(drvinfo->version, DRV_VERSION);
+ strcpy(drvinfo->fw_version, "N/A");
strcpy(drvinfo->bus_info, pci_name(rt2x00dev_pci(rt2x00dev)));
drvinfo->eedump_len = EEPROM_SIZE;
drvinfo->regdump_len = CSR_REG_SIZE;
@@ -389,7 +390,7 @@ static void rt2400pci_get_regs(struct ne
struct rt2x00_dev *rt2x00dev = ieee80211_dev_hw_data(net_dev);
rt2x00_register_multiread(rt2x00dev, CSR_REG_BASE, data, CSR_REG_SIZE);
- regs->version = *((u32*)data);
+ regs->version = rt2x00_rev(&rt2x00dev->chip);
regs->len = CSR_REG_SIZE;
}
@@ -751,7 +752,12 @@ static void rt2400pci_config_rate(struct
preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE)
? SHORT_PREAMBLE : PREAMBLE;
- reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK);
+ /*
+ * Extract the allowed ratemask from the device specific rate value,
+ * We need to set ARCSR1 to the basic rate mask so we need to mask
+ * off the non-basic rates.
+ */
+ reg[0] = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE;
rt2x00_register_write(rt2x00dev, ARCSR1, cpu_to_le32(reg[0]));
@@ -767,12 +773,12 @@ static void rt2400pci_config_rate(struct
rt2x00_set_field32(®[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);
^ permalink raw reply related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2006-09-05 7:22 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-24 19:08 What's new in wireless-dev? John W. Linville
-- strict thread matches above, loose matches on Subject: below --
2006-09-05 0:10 John W. Linville
2006-09-05 0:02 John W. Linville
2006-09-04 23:53 John W. Linville
2006-08-08 23:41 John W. Linville
2006-07-30 1:30 John W. Linville
2006-07-11 20:45 John W. Linville
2006-07-12 9:48 ` Jiri Benc
2006-07-12 12:48 ` John W. Linville
2006-07-13 2:30 ` John W. Linville
2006-06-15 21:10 John W. Linville
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).