Upgrade rt2x00 to a more recent snapshot, master mode now working, thanks to Daniel...
authorFlorian Fainelli <florian@openwrt.org>
Tue, 7 Aug 2007 09:12:49 +0000 (09:12 +0000)
committerFlorian Fainelli <florian@openwrt.org>
Tue, 7 Aug 2007 09:12:49 +0000 (09:12 +0000)
SVN-Revision: 8367

29 files changed:
package/rt2x00/Makefile
package/rt2x00/src/COPYING [new file with mode: 0644]
package/rt2x00/src/Makefile
package/rt2x00/src/README [new file with mode: 0644]
package/rt2x00/src/THANKS [new file with mode: 0644]
package/rt2x00/src/config [new file with mode: 0644]
package/rt2x00/src/rt2400pci.c
package/rt2x00/src/rt2400pci.h
package/rt2x00/src/rt2500pci.c
package/rt2x00/src/rt2500pci.h
package/rt2x00/src/rt2500usb.c
package/rt2x00/src/rt2500usb.h
package/rt2x00/src/rt2x00.h
package/rt2x00/src/rt2x00_compat.h
package/rt2x00/src/rt2x00_config.h
package/rt2x00/src/rt2x00debug.c
package/rt2x00/src/rt2x00debug.h
package/rt2x00/src/rt2x00dev.c
package/rt2x00/src/rt2x00firmware.c
package/rt2x00/src/rt2x00lib.h
package/rt2x00/src/rt2x00mac.c
package/rt2x00/src/rt2x00pci.c
package/rt2x00/src/rt2x00pci.h
package/rt2x00/src/rt2x00rfkill.c
package/rt2x00/src/rt2x00usb.c
package/rt2x00/src/rt61pci.c
package/rt2x00/src/rt61pci.h
package/rt2x00/src/rt73usb.c
package/rt2x00/src/rt73usb.h

index 4ab5a12..1759f82 100644 (file)
@@ -10,8 +10,7 @@ include $(TOPDIR)/rules.mk
 include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=rt2x00
-#PKG_VERSION:=cvs-20070725
-PKG_VERSION:=git-200706018
+PKG_VERSION:=cvs-20070712
 
 include $(INCLUDE_DIR)/package.mk
 
@@ -107,18 +106,20 @@ endef
 define Build/Prepare
        $(call Build/Prepare/Default)
        $(CP) -r src/* $(PKG_BUILD_DIR)/
-       sed 's/\$$$$(CONFIG_RT.*)/m\t\t/g' src/Makefile > $(PKG_BUILD_DIR)/Makefile
+       wget -N -P $(DL_DIR) http://www.ralinktech.com.tw/data/RT61_Firmware_V1.2.zip
+       wget -N -P $(DL_DIR) http://www.ralinktech.com.tw/data/RT71W_Firmware_V1.8.zip
+       unzip -jod $(PKG_BUILD_DIR) $(DL_DIR)/RT61_Firmware_V1.2.zip
+       unzip -jod $(PKG_BUILD_DIR) $(DL_DIR)/RT71W_Firmware_V1.8.zip
 endef
 
 define Build/Compile
-#      $(MAKE) -C "$(PKG_BUILD_DIR)" config_header
+       $(MAKE) -C "$(PKG_BUILD_DIR)" config_header
        $(MAKE) -C "$(LINUX_DIR)" \
                CROSS_COMPILE="$(TARGET_CROSS)" \
                ARCH="$(LINUX_KARCH)" V="$(V)" \
                SUBDIRS="$(PKG_BUILD_DIR)" \
                KERNELVERSION="$(KERNEL)" \
                KERNEL_SOURCE="$(LINUX_DIR)" \
-               CFLAGS_MODULE="-DMODULE -include $(PKG_BUILD_DIR)/rt2x00_compat.h" \
                KDIR="$(LINUX_DIR)"
 endef
 
diff --git a/package/rt2x00/src/COPYING b/package/rt2x00/src/COPYING
new file mode 100644 (file)
index 0000000..5b6e7c6
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
index 0ed8321..84352c3 100644 (file)
-rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00firmware.o
+#      Copyright (C) 2004 - 2007 rt2x00 SourceForge Project
+#      <http://rt2x00.serialmonkey.com>
+#
+#      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.
 
-EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
+#      Module: Makefile
+#      Abstract: Makefile for rt2x00 kernel module
 
-obj-m                          += rt2x00lib.o rt2x00pci.o rt2x00usb.o
+#
+# Set the enviroment variables.
+#
+ifndef SUBDIRS
+       SUBDIRS=$(shell pwd)
+endif
 
-obj-$(CONFIG_RT2400PCI)                += rt2400pci.o
-obj-$(CONFIG_RT2500PCI)                += rt2500pci.o
-obj-$(CONFIG_RT61PCI)          += rt61pci.o
-obj-$(CONFIG_RT2500USB)                += rt2500usb.o
-obj-$(CONFIG_RT73USB)          += rt73usb.o
+ifdef KERNDIR
+       KERNEL_SOURCES := $(KERNDIR)
+else
+       KERNEL_SOURCES := /lib/modules/$(shell uname -r)/build
+endif
+
+ifdef KERNOUT
+       KERNEL_OUTPUT := KBUILD_OUTPUT=$(KERNOUT)
+else
+       KERNEL_OUTPUT :=
+endif
+
+#
+# Include kernel and rt2x00 config.
+#
+include $(KERNEL_SOURCES)/.config
+include $(SUBDIRS)/config
+
+#
+# Determine if and with what options the rt2x00 drivers should be build
+#
+rt2x00lib-objs := rt2x00dev.o rt2x00mac.o
+
+ifeq ($(CONFIG_RT2X00),y)
+
+ifeq ($(CONFIG_RT2X00_LIB_DEBUGFS),y)
+       rt2x00lib-objs += rt2x00debug.o
+endif
+
+ifeq ($(CONFIG_RT2400PCI),y)
+       obj-m += rt2400pci.o rt2x00pci.o rt2x00lib.o
+ifeq ($(CONFIG_RT2400PCI_RFKILL),y)
+       rt2x00lib-objs += rt2x00rfkill.o
+       CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
+endif
+endif
+
+ifeq ($(CONFIG_RT2500PCI),y)
+       obj-m += rt2500pci.o rt2x00pci.o rt2x00lib.o
+ifeq ($(CONFIG_RT2500PCI_RFKILL),y)
+       rt2x00lib-objs += rt2x00rfkill.o
+       CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
+endif
+endif
+
+ifeq ($(CONFIG_RT2500USB),y)
+       obj-m += rt2500usb.o rt2x00usb.o rt2x00lib.o
+endif
+
+ifeq ($(CONFIG_RT61PCI),y)
+       CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
+       rt2x00lib-objs += rt2x00firmware.o
+       obj-m += rt61pci.o rt2x00pci.o rt2x00lib.o
+ifeq ($(CONFIG_RT61PCI_RFKILL),y)
+       rt2x00lib-objs += rt2x00rfkill.o
+       CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
+endif
+endif
+
+ifeq ($(CONFIG_RT73USB),y)
+       CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
+       rt2x00lib-objs += rt2x00firmware.o
+       obj-m += rt73usb.o rt2x00usb.o rt2x00lib.o
+endif
+
+endif
+
+MAKEFLAGS += --no-print-directory
+CFLAGS := -include $(SUBDIRS)/rt2x00_compat.h $(CFLAGS)
+
+all: default
+
+config_header:
+       @if [ ! -f "rt2x00_config.h" ] || [ "rt2x00_config.h" -ot "config" ]; \
+       then \
+               awk -F = > rt2x00_config.h < config '/^CONFIG.*$\/ \
+               { \
+                       if($$2 == "y") { \
+                               print "#ifndef " $$1; \
+                               print "#define " $$1; \
+                               print "#endif"; \
+                               print "" \
+                       } else { \
+                               print "#undef " $$1; \
+                               print ""; \
+                       } \
+               }'; \
+       fi
+
+default: config_header
+       @$(MAKE) -C $(KERNEL_SOURCES) SUBDIRS=$(SUBDIRS) $(KERNEL_OUTPUT) \
+               modules
+
+sparse: config_header
+       @$(MAKE) -C $(KERNEL_SOURCES) SUBDIRS=$(SUBDIRS) $(KERNEL_OUTPUT) \
+               modules C=1 CF=-D__CHECK_ENDIAN__
+
+install: config_header
+       @$(MAKE) -C $(KERNEL_SOURCES) SUBDIRS=$(SUBDIRS) $(KERNEL_OUTPUT) \
+               INSTALL_MOD_DIR=rt2x00 $(KERNEL_OUTPUT) modules_install
+       /sbin/depmod -a
+
+clean:
+       @rm -f rt2x00_config.h
+       @rm -f Modules.symvers Module.symvers
+       @for folder in $(EXTMODDIRS); \
+       do \
+               rm -f $${folder}/*.o \
+               rm -f $${folder}/*.ko \
+               rm -f $${folder}/*.s \
+               rm -f $${folder}/*.mod.c \
+               rm -f $${folder}/.*.cmd \
+               rm -f $${folder}/.*.flags \
+               rm -f $${folder}/.*.o.d \
+               rm -f $${folder}/.*.s.d \
+               rm -f $${folder}/.#* \
+               rm -f $${folder}/*~ \
+               rm -fr $${folder}/.tmp_versions; \
+       done
diff --git a/package/rt2x00/src/README b/package/rt2x00/src/README
new file mode 100644 (file)
index 0000000..7f3f448
--- /dev/null
@@ -0,0 +1,548 @@
+===============================================================================
+ Installation and configuration instructions for the rt2x00 Modules
+===============================================================================
+
+===============================================================================
+ Table of contents:
+========================
+
+ - 1: Minimal requirements
+   - 1.1: kernel
+   - 1.2: gcc
+   - 1.3: make
+ - 2: Hardware
+   - 2.1: Chipsets
+   - 2.2: RF button
+ -  3: Module building & Installation
+   - 3.1: Introduction
+   - 3.2: Configure
+   - 3.3: Build
+   - 3.4: Installation
+ - 4: Firmware
+   - 4.1: Firmware files
+   - 4.2: Firmware installation
+   - 4.3: Firmware requirements
+ - 5: Module loading
+   - 5.1: Module load order
+   - 5.2: Module load options
+ - 6: Interfaces
+   - 6.1: Wireless interfaces
+   - 6.2: Input interface
+ - 7: Interface configuration
+   - 7.1: Minimal configuration
+   - 7.2: Configuration tools
+ - 8: Distribution specific notes
+   - 8.1: Debian & derivatives
+   - 8.2: Fedora
+   - 8.3: Gentoo
+   - 8.4: Mandriva
+ - 9: Problems & Troubleshooting
+   - 9.1: Debug information
+   - 9.2: Debugfs
+   - 9.3: Bug reporting
+ - 10: Problems & Workarounds
+   - 10.1: udev interface naming
+   - 10.2: BUG - ifdown & ifup radio failure
+ - 11: TODO list
+ - 12: Contact us
+
+
+===============================================================================
+ 1: Minimal requirements:
+=======================================
+
+===================
+ 1.1: kernel
+=========
+
+ - The minimal required kernel version is 2.6.22-rc1
+
+ - It is important that the installed kernel sources match
+   the running kernel. Unless you are crosscompiling and you
+   know what you are doing.
+
+ - Depending on what rt2x00 components will be built,
+   some kernel configuration options are mandatory.
+   It does however not matter if these options are compiled
+   into the kernel or compiled as module.
+
+       Kernel config option    Required for component
+       ------------------------------------------------------------------
+       # CONFIG_NET_RADIO      all
+       # CONFIG_MAC80211       all
+       # CONFIG_WLAN_80211     all
+       # CONFIG_PCI            rt2400pci, rt2500pci, rt61pci
+       # CONFIG_USB            rt2500usb, rt73usb
+       # CONFIG_HOTPLUG        rt61pci, rt73usb
+       # CONFIG_FW_LOADER      rt61pci, rt73usb
+       # CONFIG_CRC_ITU_T      rt61pci, rt73usb
+       # CONFIG_DEBUG_FS       rt2x00 (optional, only for debug)
+       # CONFIG_RFKILL         rt2400pci, rt2500pci, rt61pci (optional,
+                                                       only for button support)
+
+===================
+ 1.2: GCC
+=========
+
+ - For building the rt2x00 components the same gcc version is required
+   as was used to build your target kernel.
+
+===================
+ 1.3: make
+=========
+
+ - The program 'make' needs to be installed on the system. There are no
+   further special requirements for this program.
+
+===============================================================================
+ 2: Hardware
+=======================================
+
+===================
+ 2.1: Chipsets
+=========
+
+ Support for each Ralink wireless chipset has been split into separate drivers.
+
+       # rt2400pci
+               - chipset: rt2400
+               - supports: rt2460
+               - bus type: PCI/PCMCIA/miniPCI
+       # rt2500pci
+               - chipset: rt2500
+               - supports: rt2560
+               - bus type: PCI/PCMCIA/miniPCI
+       # rt2500usb
+               - chipset: rt2570
+               - supports: rt2570
+               - bus type: USB
+       # rt61pci
+               - chipset: rt61 (or rt2600)
+               - supports: rt2561, rt2561s, rt2661
+               - bus type: PCI/PCMCIA/miniPCI
+       # rt73usb
+               - chipset: rt73
+               - supports: rt2571(w), rt2573, rt2671
+               - bus type: USB
+
+===================
+ 2.2: RF button
+=========
+
+ On some occasions the Ralink chipset has been built into a laptop.
+ If that is the case, there usually is a hardware button that controls the
+ radio of the wireless interface.
+ If you have such a hardware device, make sure you enable hardware button
+ support for your device in the configuration before building the rt2x00
+ components.
+ Note: This feature requires the enabling of the rfkill driver in the kernel.
+
+===============================================================================
+ 3: Module building & Installation
+=======================================
+
+===================
+ 3.1: Introduction
+=========
+
+ The following steps in this chapter concerning module building and
+ installation need to be performed for each kernel. This means that
+ after each kernel upgrade the modules need to be rebuild and
+ reinstalled in order to make them work with the new kernel.
+
+===================
+ 3.2: Configure
+=========
+
+ Before starting to build the rt2x00 components it is recommended to look into
+ the 'config' file first. In this file you can configure which components of
+ rt2x00 should be built. And even more importantly, you can configure with
+ what options the components will be built.
+ To build all the rt2x00 drivers (with debug capabilities enabled) no changes
+ in the configuration file are required. For most users this would be
+ sufficient to start working with rt2x00.
+
+===================
+ 3.3: Build
+=========
+
+ To build all rt2x00 components which were enabled in the configuration file
+ simply run (root privileges not required):
+
+       # $ make
+
+ All modules (.ko files) will be created in the current directory.
+
+===================
+ 3.4: Installation
+=========
+
+ All rt2x00 modules can be installed by doing (with root privileges):
+
+        # $ make install
+
+ With this command all rt2x00 modules (including rfkill and d80211) will be
+ created in a newly created folder named 'rt2x00' inside the kernel modules
+ directory (usually '/lib/modules/$(uname -r)/').
+
+
+==============================================================================
+ 4: Firmware
+=======================================
+
+===================
+ 4.1: Firmware files
+=========
+
+ rt61pci and rt73usb require firmware to be available while loading the module.
+ The following firmware files are available for each driver:
+
+       # rt61pci
+               - rt2561.bin
+               - rt2561s.bin
+               - rt2661.bin
+
+       # rt73usb
+               - rt73.bin
+
+===================
+ 4.2: Firmware installation
+=========
+
+ The latest firmware files are available in a separate .zip archive and can be
+ downloaded from the support page on the Ralink website at
+ http://www.ralinktech.com.
+ Note that by a high level of logic, Ralink has named their firmware for rt73
+ chipsets "rt71W" with a comment that it is for the rt2571W and rt2671 devices.
+ For rt61pci 3 seperate firmware files are available, which one is used depends
+ on which RT chip is on the device. Usually it is best to install all files.
+ To install the firmware the firmware files need to be manually copied to the
+ systems firmware folder (usually '/lib/firmware/') the exact folder depends
+ on the distribution. When in doubt consult the distributions documentation.
+
+===================
+ 4.3: Firmware requirements
+=========
+
+ To load firmware when the module is loaded the hotplug daemon should be
+ running. Make sure you either enable hotplugging manually before loading the
+ module, or make sure hotplugging is enabled during the system boot process.
+
+
+==============================================================================
+ 5: Module loading
+=======================================
+
+===================
+ 5.1: Module load order
+=========
+
+ When the modules have been properly installed by following the installation
+ instructions from the previous section, the module handlers (i.e. modprobe)
+ will automaticly resolve all module dependencies when loading the device
+ specific driver.
+
+ When loading the modules manually with insmod, you should load them in the
+ following order:
+
+       # eeprom_93cx6.ko (optional, only required for pci devices)
+       # rt2x00lib.ko
+       # rt2x00pci.ko (optional, only required for pci devices)
+       # rt2x00usb.ko (optional, only required for usb devices)
+       # rt2400pci.ko (optional, only required for rt2400 support)
+       # rt2500pci.ko (optional, only required for rt2500 support)
+       # rt2500usb.ko (optional, only required for rt2570 support)
+       # rt61pci.ko (optional, only required for rt61 support)
+       # rt73usb.ko (optional, only required for rt73 support)
+
+===================
+ 5.2: Module load options
+=========
+
+ None.
+
+
+==============================================================================
+ 6: Interfaces
+=======================================
+
+===================
+ 6.1: Wireless interfaces
+=========
+
+ After loading the modules two interfaces will now be visible in ifconfig and
+ iwconfig, namely wmaster0 and wlan0. The first device is the so called master
+ device which is can be used by some userspace tools, but normally can be
+ ignored by the user. The second interface wlan0 is the client interface which
+ the user can configure.
+ With rt2x00 it is possible to run multiple client interfaces with
+ only a single device. 1 client interface can run in adhoc, managed or master
+ mode while a second interface can run in monitor mode at the same time.
+ More client interfaces can be added by issuing the following command
+ (with root privileges):
+
+       # $ echo -n <name> > /sys/class/ieee80211/<dev>/add_iface
+
+ where the variable <name> is the name of the client interface that should be
+ added (i.e. wlan1), and <dev> is the physical device where the new client
+ interface should be attached to (i.e. phy0).
+
+===================
+ 6.2: Input interface
+=========
+
+ When the rfkill driver is being used a new input device with the name of the
+ device specific module where the button belongs to will have been created.
+ Whenever the user presses the hardware button the rfkill driver will
+ automatically make sure the hardware radio is being disabled or enabled
+ accordingly. When the user has opened the input device the radio will
+ not be automatically controlled, but instead the input device will
+ report all button events (KEY_RFKILL) to userspace where the user
+ could have setup script to do all the work that has to be executed.
+ This means that while the input device is opened, the user is responsible
+ for the correct behaviour.
+
+
+==============================================================================
+ 7: Interface configuration
+=======================================
+
+===================
+ 7.1: Minimal configuration
+=========
+
+ - After loading the modules the interface should be configured to start
+   an association or work in monitor mode. The following steps are required
+   for a minimal configuration to associate with a non-encrypted access point.
+
+ - Before bringing the client interface up, the working mode should be set:
+
+       # $ iwconfig wlan0 mode managed
+
+ - Configuration parts like essid and channel can be set before or after the
+   client interface has been brought up.
+
+ - It is usually a good idea to set the essid:
+
+       # $ iwconfig wlan0 essid myessid
+
+ - In some situations the device also requires the channel to be manually set:
+
+       # $ iwconfig wlan0 channel mychannel
+
+ - To bring the client interface up:
+
+       # $ ifconfig wlan0 up
+
+ - After the client interface has been brought up, scanning can be performed
+   to check if the desired AP is being detected.
+
+       # $ iwlist wlan0 scan
+
+ - To start an association attempt, the AP address should be set:
+
+       # $ iwconfig wlan0 ap mybssid
+
+===================
+ 7.2: Configuration tools
+=========
+
+ To configure the interface several tools are possible, the most basic tools
+ are the wireless-tools that provide the iwconfig, iwpriv and iwlist commands.
+ For WPA connections the wireless-tools are not sufficient, to configure the
+ interface for WPA wireless network wpa_supplicant is required.
+ For master mode functionality it is possible to only use the wireless-tools,
+ but it is recommended to use hostapd instead. This tool offers the best
+ functionality.
+ For all configuration tools (wireless-tools, wpa_supplicant and hostapd) are
+ manuals and howto's present in the manpages or on the internet. It is adviced
+ to have at least read the manpages before using the tools for a better
+ understanding on configuring the interface.
+
+
+==============================================================================
+ 8: Distribution specific notes
+=======================================
+
+===================
+ 8.1: Debian & derivatives
+=========
+
+ In some instances installing the rt2x00 drivers on debian will result
+ in the problem that the files are being copied into the wrong folder,
+ which results in the fact that the driver cannot be loaded.
+ Installing the drivers should be done manually in this case,
+ please refer to the distributions documentation regarding the proper
+ location of the kernel modules.
+
+===================
+ 8.2: Fedora
+=========
+
+ Although rt2x00 contains many backward compatibility fixes to ensure
+ that all rt2x00 components will be able to compile and run on all
+ systems that meet the minimal requirements, this does not work in all
+ situations when the Fedora kernels are being used.
+ The problem lies in the fact that Fedora (like most other distributions)
+ heavily patch their kernel for better stability and more features.
+ Unlike the other distributions however, Fedora does not pay attention to
+ compatibility for external kernel drivers. This means that compiling rt2x00
+ while using a Fedora kernel will result in compile errors regarding unknown
+ fields in structures or problems with function arguments.
+ For rt2x00 it is impossible to make all checks to support all Fedora kernel
+ releases. This means that when rt2x00 compilation is failing while using a
+ Fedora kernel we cannot give support for the compilation steps.
+ We recommend the user to complain to the Fedora developers when this problem
+ occurs.
+ If the user has managed to compile rt2x00 for a Fedora kernel we will
+ give support for possible problems while working with rt2x00. So the only
+ part we do not support is the building of rt2x00.
+ Please note that when you have edited the rt2x00 code to make it compile,
+ it is advised to state those changes in bugreports while reporting other
+ problems with rt2x00.
+
+===================
+ 8.3: Gentoo
+=========
+
+ rt2x00 can also be found in portage, both the beta releases and the cvs tree.
+ Because rt2x00 is still experimental these ebuild are still masked, this means
+ that before you can emerge them they first have to be unmasked.
+ Gentoo provides various instructions on how this can be done on their website.
+
+===================
+ 8.4: Mandriva
+=========
+
+ In some instances installing the rt2x00 drivers on Mandriva will result
+ in the problem that the files are being copied into the wrong folder,
+ which results in the fact that the driver cannot be loaded.
+ Installing the drivers should be done manually in this case,
+ please refer to the distributions documentation regarding the proper
+ location of the kernel modules.
+
+
+==============================================================================
+ 9: Problems & Troubleshooting
+=======================================
+
+===================
+ 9.1: Debug information
+=========
+
+ When reporting problems make sure the driver has been compiled with debug
+ enabled.
+ If you have done so, the debug output can be found in the output
+ of 'dmesg' and also in /var/log/messages and /var/log/syslog.
+
+===================
+ 9.2: Debugfs
+=========
+
+ rt2x00 provides several debugfs entries which can be used to help
+ provide more information about the interface.
+ To see the rt2x00 debugfs entries, debugfs should first be mounted,
+ to do this you should issue the following command:
+
+        # $ mount -t debugfs none /debug
+
+ Where /debug is the directy on which the debugfs entries should appear,
+ make sure this directory exists when mounting debugfs.
+ With the debugfs folder, the rt2x00 folder with the rt2x00 debugfs entries
+ will be created. Within the rt2x00 folder, each physical device will be
+ represented by a folder named after the interface which belongs to this
+ device. Within the folder the following files can be found:
+
+       # register
+               - This file contains the register contents of the interface.
+       # eeprom
+               - This file contains the eeprom contents of the interface.
+
+===================
+ 9.3: Bug reporting
+=========
+
+ When reporting a bug or problem with the rt2x00 module,
+ make sure you report the following information:
+       # How to reproduce
+       # RT2x00 debug output, usually found in /var/log/messages
+       # Module version
+       # Wireless card chipset, model and manufacturer
+       # Kernel version (i.e. 2.6.17)
+       # Hardware architecture (i.e. x86, AMD64, Sparc)
+       # rt2x00 code changes done by the user
+       # Anything else you may think will help us resolve the issue
+
+
+==============================================================================
+ 10: Problems & Workarounds
+=======================================
+
+===================
+ 10.1: udev interface naming
+=========
+
+ In some cases when loading the rt2x00 drivers the interface names are
+ different from the names used in this README. This is usually caused by the
+ udev handler who has set some rules regarding the interface. These rules
+ are usually set up by the distribution and have been created especially for
+ for the legacy driver and their strange behavior.
+ To change the rules udev applies to your interface you should edit the udev
+ rules stored in /etc/udev/rules.d/ (exact location might be different
+ depending on distribution).
+ When editing this file, search for the line that contains something like this:
+
+       # ACTION=="add", SUBSYSTEM=="net", DRIVERS=="?*",
+       #       SYSFS{address}=="<mac address>", NAME="<interface>"
+       (line has been wrapped due to max line length limit)
+
+ Where <mac address> is the hardware address of your wireless networkcard,
+ and <interface> is the interface name the interface takes as soon as the
+ rt2x00 modules are loaded.
+ This line should be changed to look like:
+
+       # ACTION=="add", SUBSYSTEM=="net", DRIVERS=="?*",
+       #       SYSFS{address}=="<mac address>", SYSFS{type}=="801",
+       #       NAME="wmaster0"
+       # ACTION=="add", SUBSYSTEM=="net", DRIVERS=="?*",
+       #       SYSFS{address}=="<mac address>", NAME="wlan0"
+       (the 2 lines have been wrapped due to max line length limit)
+
+ Where <mac address> is the hardware address of your wireless networkcard,
+ and thus should be the same as on the original line.
+
+===================
+ 10.2: BUG - ifdown & ifup radio failure
+=========
+
+ It is a known issue (and BUG) that the driver will fail to correctly resume
+ its radio operations after the interface has been brought down and up again.
+ It is still unknown what the cause for this issue could be, besides the fact
+ that for some reason the device's registers have been incorrectly initialized.
+ This issue also has impact on the device status after a suspend/resume
+ operation. There is no known workaround for this yet.
+
+
+==============================================================================
+ 11: TODO list
+=======================================
+ See http://rt2x00.serialmonkey.com/wiki/index.php/Rt2x00_beta
+
+==============================================================================
+ 12: Contact us
+=======================================
+
+ - Website
+       # http://rt2x00.serialmonkey.com/
+       # http://rt2x00.serialmonkey.com/wiki/index.php/Rt2x00_beta
+
+ - Forums:
+       # http://rt2x00.serialmonkey.com/phpBB2/
+
+ - Mailing list:
+       # general: rt2400-general@lists.sourceforge.net
+       # developers: rt2400-devel@lists.sourceforge.net
+
+ - Sourceforge:
+       # http://sourceforge.net/projects/rt2400
+
diff --git a/package/rt2x00/src/THANKS b/package/rt2x00/src/THANKS
new file mode 100644 (file)
index 0000000..81b88d2
--- /dev/null
@@ -0,0 +1,54 @@
+A big thanks to all the developers, testers and supporters of
+the rt2x00 Linux source code.
+
+Thanks to the projects main developers:
+* Mark Wallis - mwallis@serialmonkey.com
+* Ivo van Doorn - IvDoorn@gmail.com
+* Luis Correia - lfcorreia@users.sf.net
+* Robin Cornelius - robin.cornelius@gmail.com
+* Gertjan van Wingerde - gwingerde@kpnplanet.nl
+* Romain - spy84464@hotmail.com
+
+Special thanks to the contributors of this project:
+* Adisorn Ermongkonchai - moo7822-wlan@yahoo.com
+* Amir Shalem - amir@boom.org.il
+* Bernd Petrovitsch - bernd@firmix.at
+* Bruno - bruno123@users.sf.net
+* Chris Houston - chris.houston@atterotech.com
+* Defekt - defekt@liquid-nexus.net
+* Edvard - eaglenest@users.sourceforge.net
+* Flavio Stanchina - flavio@stanchina.net
+* Gregor Glomm - gg@seh.de
+* Heikki Pernu - heikki.pernu@nekonet.fi
+* Jerzy Kozera - nordom@tlen.pl
+* Joachim Glei├čner - jg@suse.de
+* John Coppens - john@jcoppens.com
+* Jonathan Hudson
+* KrissN - krissn@op.pl
+* Luca Tettamanti - kronos.it@gmail.com
+* Magnus Damm - magnus.damm@gmail.com
+* Mags
+* Mathias Klien - ma_klein@gmx.de
+* Meelis Roos - mroos@linux.ee
+* Michal Ludvig - michal@logix.cz
+* Miguel - miguel.marte2@verizon.net
+* Mike Skinner
+* Olivier Cornu - o.cornu@gmail.com
+* Paul Hampson - Paul.Hampson@anu.edu.au
+* Philippe Rousselot - amazilia@users.sourceforge.net
+* Remco - remco@d-compu.dyndns.org
+* Sergey Vlasov - vsu@altlinux.ru
+* Stephen Warren - SWarren@nvidia.com
+* Stuart Rackham - srackham@methods.co.nz
+* Thor Harald Johansen - thorhajo@gmail.com
+* Tor Petterson - 2r@manowar.dk
+
+Special thanks:
+* Ralink - http://www.ralinktech.com.tw
+  For releasing their rt2400/rt2500/rt2570 drivers under the GPL,
+  and their assistance in providing documentation to help development.
+* Minitar - www.minitar.com
+  For working together with Ralink on releasing the
+  rt2400/rt2500/rt2570 drivers under the GPL.
+* All the people that have assisted with the rt2400/rt2500/rt2570 source
+  and hence progressed the rt2x00 along the way.
diff --git a/package/rt2x00/src/config b/package/rt2x00/src/config
new file mode 100644 (file)
index 0000000..8a09911
--- /dev/null
@@ -0,0 +1,41 @@
+# rt2x00 configuration
+# All configuration options can be enabled
+# by setting the value to 'y'. To disable
+# the option it should be set to 'n'.
+
+#
+# RT2X00 generic support
+#
+
+# Enable rt2x00 support
+CONFIG_RT2X00=y
+# Enable rt2x00 debug output
+CONFIG_RT2X00_DEBUG=y
+# Enable rt2x00 debugfs support
+CONFIG_RT2X00_DEBUGFS=n
+# Enable rt2x00 asm file creation
+CONFIG_RT2X00_ASM=n
+
+#
+# RT2X00 driver support
+#
+# Enable rt2400pci support
+CONFIG_RT2400PCI=y
+# Enable rt2400pci hardware button support (requires rfkill)
+CONFIG_RT2400PCI_BUTTON=n
+
+# Enable rt2500pci support
+CONFIG_RT2500PCI=y
+# Enable rt2500pci hardware button support (requires rfkill)
+CONFIG_RT2500PCI_BUTTON=n
+
+# Enable rt2500usb support
+CONFIG_RT2500USB=y
+
+# Enable rt61pci support
+CONFIG_RT61PCI=y
+# Enable rt61pci hardware button support (requires rfkill)
+CONFIG_RT61PCI_BUTTON=n
+
+# Enable rt73usb support
+CONFIG_RT73USB=y
index aaed3b4..824c823 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/io.h>
 
 #include "rt2x00.h"
+#include "rt2x00lib.h"
 #include "rt2x00pci.h"
 #include "rt2400pci.h"
 
@@ -614,7 +615,7 @@ static void rt2400pci_disable_led(struct rt2x00_dev *rt2x00dev)
 /*
  * Link tuning
  */
-static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
+static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 {
        u8 reg;
        char false_cca_delta;
@@ -623,7 +624,7 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
         * The link tuner should not run longer then 60 seconds,
         * and should run once every 2 seconds.
         */
-       if (rt2x00dev->link.count > 60 || !(rt2x00dev->link.count % 1))
+       if (rt2x00dev->link.count > 60 || !(rt2x00dev->link.count & 1))
                return;
 
        /*
@@ -649,6 +650,7 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
                reg += 2;
                if (reg < 0x20)
                        rt2400pci_bbp_write(rt2x00dev, 13, reg);
+               rt2x00dev->rx_status.noise = reg;
        }
 }
 
@@ -926,10 +928,34 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
        rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
 }
 
-static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled)
 {
        u32 reg;
 
+       /*
+        * When interrupts are being enabled, the interrupt registers
+        * should clear the register to assure a clean state.
+        */
+       if (enabled) {
+               rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
+               rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+       }
+
+       /*
+        * Only toggle the interrupts bits we are going to use.
+        * Non-checked interrupt bits are disabled by default.
+        */
+       rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+       rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, !enabled);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, !enabled);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, !enabled);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, !enabled);
+       rt2x00_set_field32(&reg, CSR8_RXDONE, !enabled);
+       rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+}
+
+static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
        /*
         * Initialize all registers.
         */
@@ -940,22 +966,10 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
                return -EIO;
        }
 
-       /*
-        * Clear interrupts.
-        */
-       rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
-       rt2x00pci_register_write(rt2x00dev, CSR7, reg);
-
        /*
         * Enable interrupts.
         */
-       rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
-       rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, 0);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
-       rt2x00_set_field32(&reg, CSR8_RXDONE, 0);
-       rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+       rt2400pci_toggle_irq(rt2x00dev, 1);
 
        /*
         * Enable LED
@@ -991,13 +1005,7 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
        /*
         * Disable interrupts.
         */
-       rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
-       rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, 1);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 1);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 1);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 1);
-       rt2x00_set_field32(&reg, CSR8_RXDONE, 1);
-       rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+       rt2400pci_toggle_irq(rt2x00dev, 0);
 }
 
 static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -1163,59 +1171,40 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
 }
 
 /*
- * Interrupt functions.
+ * RX control handlers
  */
-static void rt2400pci_rxdone(struct rt2x00_dev *rt2x00dev)
+static int rt2400pci_fill_rxdone(struct data_entry *entry,
+       int *signal, int *rssi, int *ofdm)
 {
-       struct data_ring *ring = rt2x00dev->rx;
-       struct data_entry *entry;
-       struct data_desc *rxd;
+       struct data_desc *rxd = entry->priv;
        u32 word0;
        u32 word2;
-       int signal;
-       int rssi;
-       u16 size;
-
-       while (1) {
-               entry = rt2x00_get_data_entry(ring);
-               rxd = entry->priv;
-               rt2x00_desc_read(rxd, 0, &word0);
-               rt2x00_desc_read(rxd, 2, &word2);
-
-               if (rt2x00_get_field32(word0, RXD_W0_OWNER_NIC))
-                       break;
-
-               /*
-                * TODO: Don't we need to keep statistics
-                * updated about events like CRC and physical errors?
-                */
-               if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
-                   rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
-                       goto skip_entry;
 
-               /*
-                * Obtain the status about this packet.
-                */
-               size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-               signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
-               rssi = rt2x00_get_field32(word2, RXD_W2_RSSI);
+       rt2x00_desc_read(rxd, 0, &word0);
+       rt2x00_desc_read(rxd, 2, &word2);
 
-               /*
-                * Send the packet to upper layer.
-                */
-               rt2x00lib_rxdone(entry, entry->data_addr, size,
-                       signal, rssi, 0);
+       /*
+        * TODO: Don't we need to keep statistics
+        * updated about these errors?
+        */
+       if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
+           rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+               return -EINVAL;
 
-skip_entry:
-               if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
-                       rt2x00_set_field32(&word0, RXD_W0_OWNER_NIC, 1);
-                       rt2x00_desc_write(rxd, 0, word0);
-               }
+       /*
+        * Obtain the status about this packet.
+        */
+       *signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
+       *rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
+               entry->ring->rt2x00dev->rssi_offset;
+       *ofdm = 0;
 
-               rt2x00_ring_index_inc(ring);
-       }
+       return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 }
 
+/*
+ * Interrupt functions.
+ */
 static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
 {
        struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue);
@@ -1296,7 +1285,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
         * 2 - Rx ring done interrupt.
         */
        if (rt2x00_get_field32(reg, CSR7_RXDONE))
-               rt2400pci_rxdone(rt2x00dev);
+               rt2x00pci_rxdone(rt2x00dev);
 
        /*
         * 3 - Atim ring transmit done interrupt.
@@ -1327,6 +1316,7 @@ static int rt2400pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
        struct eeprom_93cx6 eeprom;
        u32 reg;
        u16 word;
+       u8 *mac;
 
        /*
         * Allocate the eeprom memory, check the eeprom width
@@ -1354,6 +1344,12 @@ static int rt2400pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Start validation of the data that has been read.
         */
+       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+       if (!is_valid_ether_addr(mac)) {
+               random_ether_addr(mac);
+               EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac));
+       }
+
        rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
        if (word == 0xffff) {
                ERROR(rt2x00dev, "Invalid EEPROM data detected.\n");
@@ -1440,16 +1436,16 @@ static void rt2400pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
                IEEE80211_HW_WEP_INCLUDE_IV |
                IEEE80211_HW_DATA_NULLFUNC_ACK |
                IEEE80211_HW_NO_TKIP_WMM_HWACCEL |
-               IEEE80211_HW_MONITOR_DURING_OPER;
+               IEEE80211_HW_MONITOR_DURING_OPER |
+               IEEE80211_HW_NO_PROBE_FILTERING;
        rt2x00dev->hw->extra_tx_headroom = 0;
        rt2x00dev->hw->max_rssi = MAX_RX_SSI;
        rt2x00dev->hw->max_noise = MAX_RX_NOISE;
        rt2x00dev->hw->queues = 2;
 
-       /*
-        * This device supports ATIM
-        */
-       __set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
+       SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
+       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+               rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0));
 
        /*
         * Set device specific, but channel independent RF values.
@@ -1470,7 +1466,6 @@ static void rt2400pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize hw_mode information.
         */
-       spec->mac_addr = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        spec->num_modes = 1;
        spec->num_rates = 4;
        spec->num_channels = 14;
@@ -1501,6 +1496,16 @@ static int rt2400pci_init_hw(struct rt2x00_dev *rt2x00dev)
         */
        rt2400pci_init_hw_mode(rt2x00dev);
 
+       /*
+        * This device supports ATIM
+        */
+       __set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
+
+       /*
+        * Set the rssi offset.
+        */
+       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
+
        return 0;
 }
 
@@ -1599,8 +1604,6 @@ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
 static const struct ieee80211_ops rt2400pci_mac80211_ops = {
        .tx                     = rt2x00lib_tx,
        .reset                  = rt2x00lib_reset,
-       .open                   = rt2x00lib_open,
-       .stop                   = rt2x00lib_stop,
        .add_interface          = rt2x00lib_add_interface,
        .remove_interface       = rt2x00lib_remove_interface,
        .config                 = rt2x00lib_config,
@@ -1629,6 +1632,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
        .write_tx_desc          = rt2400pci_write_tx_desc,
        .write_tx_data          = rt2x00pci_write_tx_data,
        .kick_tx_queue          = rt2400pci_kick_tx_queue,
+       .fill_rxdone            = rt2400pci_fill_rxdone,
        .config_type            = rt2400pci_config_type,
        .config_phymode         = rt2400pci_config_phymode,
        .config_channel         = rt2400pci_config_channel,
@@ -1679,14 +1683,11 @@ static struct pci_driver rt2400pci_driver = {
 
 static int __init rt2400pci_init(void)
 {
-       printk(KERN_INFO "Loading module: %s - %s by %s.\n",
-               DRV_NAME, DRV_VERSION, DRV_PROJECT);
        return pci_register_driver(&rt2400pci_driver);
 }
 
 static void __exit rt2400pci_exit(void)
 {
-       printk(KERN_INFO "Unloading module: %s.\n", DRV_NAME);
        pci_unregister_driver(&rt2400pci_driver);
 }
 
index 097f4c9..10fe488 100644 (file)
 #define RF2421                         0x0001
 
 /*
- * Max RSSI value, required for RSSI <-> dBm conversion.
+ * Signal information.
  */
-#define MAX_RX_SSI                     100
+#define MAX_RX_SSI                     -1
 #define MAX_RX_NOISE                   -110
+#define DEFAULT_RSSI_OFFSET            100
 
 /*
  * Register layout information.
index 61d7e74..d71e3c3 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/io.h>
 
 #include "rt2x00.h"
+#include "rt2x00lib.h"
 #include "rt2x00pci.h"
 #include "rt2500pci.h"
 
@@ -368,6 +369,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
        u32 rf2 = value;
        u32 rf3 = rt2x00dev->rf3;
        u32 rf4 = rt2x00dev->rf4;
+       u8 r70;
 
        if (rt2x00_rf(&rt2x00dev->chip, RF2525) ||
            rt2x00_rf(&rt2x00dev->chip, RF2525E))
@@ -435,7 +437,9 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
        /*
         * Channel 14 requires the Japan filter bit to be set.
         */
-       rt2500pci_bbp_write(rt2x00dev, 70, (channel == 14) ? 0x4e : 0x46);
+       r70 = 0x46;
+       rt2x00_set_field8(&r70, BBP_R70_JAPAN_FILTER, channel == 14);
+       rt2500pci_bbp_write(rt2x00dev, 70, r70);
 
        msleep(1);
 
@@ -692,8 +696,9 @@ static void rt2500pci_disable_led(struct rt2x00_dev *rt2x00dev)
 /*
  * Link tuning
  */
-static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
+static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 {
+       int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
        u32 reg;
        u8 r17;
 
@@ -722,7 +727,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
         */
        if (rssi < -80 && rt2x00dev->link.count > 20) {
                if (r17 >= 0x41) {
-                       r17 = rt2x00dev->link.curr_noise;
+                       r17 = rt2x00dev->rx_status.noise;
                        rt2500pci_bbp_write(rt2x00dev, 17, r17);
                }
                return;
@@ -751,7 +756,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
         * to the dynamic tuning range.
         */
        if (r17 >= 0x41) {
-               rt2500pci_bbp_write(rt2x00dev, 17, rt2x00dev->link.curr_noise);
+               rt2500pci_bbp_write(rt2x00dev, 17, rt2x00dev->rx_status.noise);
                return;
        }
 
@@ -766,10 +771,10 @@ dynamic_cca_tune:
 
        if (rt2x00dev->link.false_cca > 512 && r17 < 0x40) {
                rt2500pci_bbp_write(rt2x00dev, 17, ++r17);
-               rt2x00dev->link.curr_noise = r17;
+               rt2x00dev->rx_status.noise = r17;
        } else if (rt2x00dev->link.false_cca < 100 && r17 > 0x32) {
                rt2500pci_bbp_write(rt2x00dev, 17, --r17);
-               rt2x00dev->link.curr_noise = r17;
+               rt2x00dev->rx_status.noise = r17;
        }
 }
 
@@ -898,7 +903,16 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
                return -EBUSY;
 
        rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100);
-       rt2x00pci_register_write(rt2x00dev, PCICSR, 0x000003b8);
+
+       rt2x00pci_register_read(rt2x00dev, PCICSR, &reg);
+       rt2x00_set_field32(&reg, PCICSR_BIG_ENDIAN, 0);
+       rt2x00_set_field32(&reg, PCICSR_RX_TRESHOLD, 0);
+       rt2x00_set_field32(&reg, PCICSR_TX_TRESHOLD, 3);
+       rt2x00_set_field32(&reg, PCICSR_BURST_LENTH, 1);
+       rt2x00_set_field32(&reg, PCICSR_ENABLE_CLK, 1);
+       rt2x00_set_field32(&reg, PCICSR_READ_MULTIPLE, 1);
+       rt2x00_set_field32(&reg, PCICSR_WRITE_INVALID, 1);
+       rt2x00pci_register_write(rt2x00dev, PCICSR, reg);
 
        rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002);
        rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002);
@@ -1079,10 +1093,34 @@ static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
        rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
 }
 
-static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled)
 {
        u32 reg;
 
+       /*
+        * When interrupts are being enabled, the interrupt registers
+        * should clear the register to assure a clean state.
+        */
+       if (enabled) {
+               rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
+               rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+       }
+
+       /*
+        * Only toggle the interrupts bits we are going to use.
+        * Non-checked interrupt bits are disabled by default.
+        */
+       rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+       rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, !enabled);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, !enabled);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, !enabled);
+       rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, !enabled);
+       rt2x00_set_field32(&reg, CSR8_RXDONE, !enabled);
+       rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+}
+
+static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
        /*
         * Initialize all registers.
         */
@@ -1093,22 +1131,10 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
                return -EIO;
        }
 
-       /*
-        * Clear interrupts.
-        */
-       rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
-       rt2x00pci_register_write(rt2x00dev, CSR7, reg);
-
        /*
         * Enable interrupts.
         */
-       rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
-       rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, 0);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
-       rt2x00_set_field32(&reg, CSR8_RXDONE, 0);
-       rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+       rt2500pci_toggle_irq(rt2x00dev, 1);
 
        /*
         * Enable LED
@@ -1144,13 +1170,7 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)
        /*
         * Disable interrupts.
         */
-       rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
-       rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, 1);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 1);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 1);
-       rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 1);
-       rt2x00_set_field32(&reg, CSR8_RXDONE, 1);
-       rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+       rt2500pci_toggle_irq(rt2x00dev, 0);
 }
 
 static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -1300,61 +1320,37 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
 }
 
 /*
- * Interrupt functions.
+ * RX control handlers
  */
-static void rt2500pci_rxdone(struct rt2x00_dev *rt2x00dev)
+static int rt2500pci_fill_rxdone(struct data_entry *entry,
+       int *signal, int *rssi, int *ofdm)
 {
-       struct data_ring *ring = rt2x00dev->rx;
-       struct data_entry *entry;
-       struct data_desc *rxd;
+       struct data_desc *rxd = entry->priv;
        u32 word0;
        u32 word2;
-       int signal;
-       int rssi;
-       int ofdm;
-       u16 size;
-
-       while (1) {
-               entry = rt2x00_get_data_entry(ring);
-               rxd = entry->priv;
-               rt2x00_desc_read(rxd, 0, &word0);
-               rt2x00_desc_read(rxd, 2, &word2);
-
-               if (rt2x00_get_field32(word0, RXD_W0_OWNER_NIC))
-                       break;
 
-               /*
-                * TODO: Don't we need to keep statistics
-                * updated about events like CRC and physical errors?
-                */
-               if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
-                   rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
-                       goto skip_entry;
+       rt2x00_desc_read(rxd, 0, &word0);
+       rt2x00_desc_read(rxd, 2, &word2);
 
-               /*
-                * Obtain the status about this packet.
-                */
-               size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-               signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
-               rssi = rt2x00_get_field32(word2, RXD_W2_RSSI);
-               ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
-
-               /*
-                * Send the packet to upper layer.
-                */
-               rt2x00lib_rxdone(entry, entry->data_addr, size,
-                       signal, rssi, ofdm);
+       /*
+        * TODO: Don't we need to keep statistics
+        * updated about these errors?
+        */
+       if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
+           rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
+               return -EINVAL;
 
-skip_entry:
-               if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
-                       rt2x00_set_field32(&word0, RXD_W0_OWNER_NIC, 1);
-                       rt2x00_desc_write(rxd, 0, word0);
-               }
+       *signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL);
+       *rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) -
+               entry->ring->rt2x00dev->rssi_offset;
+       *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
 
-               rt2x00_ring_index_inc(ring);
-       }
+       return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 }
 
+/*
+ * Interrupt functions.
+ */
 static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
 {
        struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue);
@@ -1435,7 +1431,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
         * 2 - Rx ring done interrupt.
         */
        if (rt2x00_get_field32(reg, CSR7_RXDONE))
-               rt2500pci_rxdone(rt2x00dev);
+               rt2x00pci_rxdone(rt2x00dev);
 
        /*
         * 3 - Atim ring transmit done interrupt.
@@ -1466,6 +1462,7 @@ static int rt2500pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
        struct eeprom_93cx6 eeprom;
        u32 reg;
        u16 word;
+       u8 *mac;
 
        /*
         * Allocate the eeprom memory, check the eeprom width
@@ -1493,6 +1490,12 @@ static int rt2500pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Start validation of the data that has been read.
         */
+       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+       if (!is_valid_ether_addr(mac)) {
+               random_ether_addr(mac);
+               EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac));
+       }
+
        rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
@@ -1518,7 +1521,7 @@ static int rt2500pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
-                       MAX_RX_SSI);
+                       DEFAULT_RSSI_OFFSET);
                rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
                EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word);
        }
@@ -1586,7 +1589,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * Read the RSSI <-> dBm offset information.
         */
        rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
-       rt2x00dev->hw->max_rssi =
+       rt2x00dev->rssi_offset =
                rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
 
        return 0;
@@ -1660,16 +1663,16 @@ static void rt2500pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
                IEEE80211_HW_WEP_INCLUDE_IV |
                IEEE80211_HW_DATA_NULLFUNC_ACK |
                IEEE80211_HW_NO_TKIP_WMM_HWACCEL |
-               IEEE80211_HW_MONITOR_DURING_OPER;
+               IEEE80211_HW_MONITOR_DURING_OPER |
+               IEEE80211_HW_NO_PROBE_FILTERING;
        rt2x00dev->hw->extra_tx_headroom = 0;
        rt2x00dev->hw->max_rssi = MAX_RX_SSI;
        rt2x00dev->hw->max_noise = MAX_RX_NOISE;
        rt2x00dev->hw->queues = 2;
 
-       /*
-        * This device supports ATIM
-        */
-       __set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
+       SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
+       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+               rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0));
 
        /*
         * Set device specific, but channel independent RF values.
@@ -1692,7 +1695,6 @@ static void rt2500pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize hw_mode information.
         */
-       spec->mac_addr = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        spec->num_modes = 2;
        spec->num_rates = 12;
        spec->num_channels = 14;
@@ -1738,6 +1740,11 @@ static int rt2500pci_init_hw(struct rt2x00_dev *rt2x00dev)
         */
        rt2500pci_init_hw_mode(rt2x00dev);
 
+       /*
+        * This device supports ATIM
+        */
+       __set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
+
        return 0;
 }
 
@@ -1812,8 +1819,6 @@ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
 static const struct ieee80211_ops rt2500pci_mac80211_ops = {
        .tx                     = rt2x00lib_tx,
        .reset                  = rt2x00lib_reset,
-       .open                   = rt2x00lib_open,
-       .stop                   = rt2x00lib_stop,
        .add_interface          = rt2x00lib_add_interface,
        .remove_interface       = rt2x00lib_remove_interface,
        .config                 = rt2x00lib_config,
@@ -1842,6 +1847,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
        .write_tx_desc          = rt2500pci_write_tx_desc,
        .write_tx_data          = rt2x00pci_write_tx_data,
        .kick_tx_queue          = rt2500pci_kick_tx_queue,
+       .fill_rxdone            = rt2500pci_fill_rxdone,
        .config_type            = rt2500pci_config_type,
        .config_phymode         = rt2500pci_config_phymode,
        .config_channel         = rt2500pci_config_channel,
@@ -1892,14 +1898,11 @@ static struct pci_driver rt2500pci_driver = {
 
 static int __init rt2500pci_init(void)
 {
-       printk(KERN_INFO "Loading module: %s - %s by %s.\n",
-               DRV_NAME, DRV_VERSION, DRV_PROJECT);
        return pci_register_driver(&rt2500pci_driver);
 }
 
 static void __exit rt2500pci_exit(void)
 {
-       printk(KERN_INFO "Unloading module: %s.\n", DRV_NAME);
        pci_unregister_driver(&rt2500pci_driver);
 }
 
index e695a57..c70bcb7 100644 (file)
 #define RT2560_VERSION_D               4
 
 /*
- * Max RSSI value, required for RSSI <-> dBm conversion.
+ * Signal information.
  */
-#define MAX_RX_SSI                     121
+#define MAX_RX_SSI                     -1
 #define MAX_RX_NOISE                   -110
+#define DEFAULT_RSSI_OFFSET            121
 
 /*
  * Register layout information.
 #define BBP_R14_RX_ANTENNA             FIELD8(0x03)
 #define BBP_R14_RX_IQ_FLIP             FIELD8(0x04)
 
+/*
+ * BBP_R70
+ */
+#define BBP_R70_JAPAN_FILTER           FIELD8(0x08)
+
 /*
  * DMA descriptor defines.
  */
index c5459b5..3be51f0 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/etherdevice.h>
 
 #include "rt2x00.h"
+#include "rt2x00lib.h"
 #include "rt2x00usb.h"
 #include "rt2500usb.h"
 
@@ -638,8 +639,9 @@ static void rt2500usb_disable_led(struct rt2x00_dev *rt2x00dev)
 /*
  * Link tuning
  */
-static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
+static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
 {
+       int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
        u16 bbp_thresh;
        u16 cca_alarm;
        u16 vgc_bound;
@@ -734,62 +736,19 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
 
        if (r17 > up_bound) {
                rt2500usb_bbp_write(rt2x00dev, 17, up_bound);
-               rt2x00dev->link.curr_noise = up_bound;
+               rt2x00dev->rx_status.noise = up_bound;
        } else if (cca_alarm > 512 && r17 < up_bound) {
                rt2500usb_bbp_write(rt2x00dev, 17, ++r17);
-               rt2x00dev->link.curr_noise = r17;
+               rt2x00dev->rx_status.noise = r17;
        } else if (cca_alarm < 100 && r17 > low_bound) {
                rt2500usb_bbp_write(rt2x00dev, 17, --r17);
-               rt2x00dev->link.curr_noise = r17;
+               rt2x00dev->rx_status.noise = r17;
        }
 }
 
 /*
  * Initialization functions.
  */
-static void rt2500usb_init_rxring(struct rt2x00_dev *rt2x00dev)
-{
-       struct usb_device *usb_dev =
-               interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
-       unsigned int i;
-
-       for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
-               usb_fill_bulk_urb(
-                       rt2x00dev->rx->entry[i].priv,
-                       usb_dev,
-                       usb_rcvbulkpipe(usb_dev, 1),
-                       rt2x00dev->rx->entry[i].skb->data,
-                       rt2x00dev->rx->entry[i].skb->len,
-                       rt2500usb_interrupt_rxdone,
-                       &rt2x00dev->rx->entry[i]);
-       }
-
-       rt2x00_ring_index_clear(rt2x00dev->rx);
-}
-
-static void rt2500usb_init_txring(struct rt2x00_dev *rt2x00dev,
-       const int queue)
-{
-       struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue);
-       unsigned int i;
-
-       for (i = 0; i < ring->stats.limit; i++)
-               ring->entry[i].flags = 0;
-
-       rt2x00_ring_index_clear(ring);
-}
-
-static int rt2500usb_init_rings(struct rt2x00_dev *rt2x00dev)
-{
-       rt2500usb_init_rxring(rt2x00dev);
-       rt2500usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
-       rt2500usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
-       rt2500usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
-       rt2500usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-
-       return 0;
-}
-
 static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
 {
        u16 reg;
@@ -801,7 +760,10 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
                USB_VENDOR_REQUEST_OUT, 0x0308, 0xf0, NULL, 0,
                REGISTER_TIMEOUT);
 
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR2, 0x0001);
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+
        rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x1111);
        rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x1e11);
 
@@ -819,9 +781,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
 
        rt2500usb_register_write(rt2x00dev, MAC_CSR1, 0x0004);
 
-       reg = 0;
-       rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
-       if (reg >= 0x0003) {
+       if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
                rt2500usb_register_read(rt2x00dev, PHY_CSR2, &reg);
                reg &= ~0x0002;
        } else {
@@ -962,8 +922,7 @@ static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize all registers.
         */
-       if (rt2500usb_init_rings(rt2x00dev) ||
-           rt2500usb_init_registers(rt2x00dev) ||
+       if (rt2500usb_init_registers(rt2x00dev) ||
            rt2500usb_init_bbp(rt2x00dev)) {
                ERROR(rt2x00dev, "Register initialization failed.\n");
                return -EIO;
@@ -1107,7 +1066,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_set_field32(&word, TXD_W0_OFDM,
                test_bit(ENTRY_TXD_OFDM_RATE, &entry->flags));
        rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
-               test_bit(ENTRY_TXD_NEW_SEQ, &entry->flags));
+               control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT);
        rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
        rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length);
        rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
@@ -1141,74 +1100,40 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
 }
 
 /*
- * Interrupt functions.
+ * RX control handlers
  */
-static void rt2500usb_interrupt_rxdone(struct urb *urb)
+static int rt2500usb_fill_rxdone(struct data_entry *entry,
+       int *signal, int *rssi, int *ofdm)
 {
-       struct data_entry *entry = (struct data_entry*)urb->context;
-       struct data_ring *ring = entry->ring;
-       struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
-       struct data_desc *rxd = (struct data_desc*)
-               (entry->skb->data + urb->actual_length - ring->desc_size);
+       struct urb *urb = entry->priv;
+       struct data_desc *rxd = (struct data_desc*)(entry->skb->data +
+               (urb->actual_length - entry->ring->desc_size));
        u32 word0;
        u32 word1;
-       int signal;
-       int rssi;
-       int ofdm;
-       u16 size;
-
-       if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
-           !test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
-               return;
-
-       /*
-        * Check if the received data is simply too small
-        * to be actually valid, or if the urb is signaling
-        * a problem.
-        */
-       if (urb->actual_length < entry->ring->desc_size || urb->status)
-               goto skip_entry;
 
        rt2x00_desc_read(rxd, 0, &word0);
        rt2x00_desc_read(rxd, 1, &word1);
 
        /*
         * TODO: Don't we need to keep statistics
-        * updated about events like CRC and physical errors?
+        * updated about these errors?
         */
        if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
            rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
-               goto skip_entry;
+               return -EINVAL;
 
        /*
         * Obtain the status about this packet.
         */
-       size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT) - FCS_LEN;
-       signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-       rssi = rt2x00_get_field32(word1, RXD_W1_RSSI);
-       ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+       *signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+       *rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
+               entry->ring->rt2x00dev->rssi_offset;
+       *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
 
        /*
-        * Trim the skb_buffer to only contain the valid
-        * frame data (so ignore the device's descriptor).
+        * rt2570 includes the FCS, so fix data length accordingly.
         */
-       skb_trim(entry->skb, size);
-
-       /*
-        * Send the packet to upper layer, and update urb.
-        */
-       rt2x00lib_rxdone(entry, NULL, ring->data_size + ring->desc_size,
-               signal, rssi, ofdm);
-       urb->transfer_buffer = entry->skb->data;
-       urb->transfer_buffer_length = entry->skb->len;
-
-skip_entry:
-       if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
-               __set_bit(ENTRY_OWNER_NIC, &entry->flags);
-               usb_submit_urb(urb, GFP_ATOMIC);
-       }
-
-       rt2x00_ring_index_inc(ring);
+       return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT) - FCS_LEN;
 }
 
 /*
@@ -1217,6 +1142,7 @@ skip_entry:
 static int rt2500usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
 {
        u16 word;
+       u8 *mac;
 
        /*
         * Allocate the eeprom memory, check the eeprom width
@@ -1234,6 +1160,12 @@ static int rt2500usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Start validation of the data that has been read.
         */
+       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+       if (!is_valid_ether_addr(mac)) {
+               random_ether_addr(mac);
+               EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac));
+       }
+
        rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
@@ -1259,7 +1191,7 @@ static int rt2500usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
        rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,
-                       MAX_RX_SSI);
+                       DEFAULT_RSSI_OFFSET);
                rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word);
                EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word);
        }
@@ -1366,7 +1298,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
         * Read the RSSI <-> dBm offset information.
         */
        rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom);
-       rt2x00dev->hw->max_rssi =
+       rt2x00dev->rssi_offset =
                rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI);
 
        return 0;
@@ -1443,16 +1375,16 @@ static void rt2500usb_init_hw_mode(struct rt2x00_dev *rt2x00dev)
                IEEE80211_HW_WEP_INCLUDE_IV |
                IEEE80211_HW_DATA_NULLFUNC_ACK |
                IEEE80211_HW_NO_TKIP_WMM_HWACCEL |
-               IEEE80211_HW_MONITOR_DURING_OPER;
+               IEEE80211_HW_MONITOR_DURING_OPER |
+               IEEE80211_HW_NO_PROBE_FILTERING;
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
        rt2x00dev->hw->max_rssi = MAX_RX_SSI;
        rt2x00dev->hw->max_noise = MAX_RX_NOISE;
        rt2x00dev->hw->queues = 2;
 
-       /*
-        * This device supports ATIM
-        */
-       __set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
+       SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
+       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+               rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0));
 
        /*
         * Set device specific, but channel independent RF values.
@@ -1475,7 +1407,6 @@ static void rt2500usb_init_hw_mode(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize hw_mode information.
         */
-       spec->mac_addr = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        spec->num_modes = 2;
        spec->num_rates = 12;
        spec->num_channels = 14;
@@ -1522,6 +1453,11 @@ static int rt2500usb_init_hw(struct rt2x00_dev *rt2x00dev)
         */
        rt2500usb_init_hw_mode(rt2x00dev);
 
+       /*
+        * This device supports ATIM
+        */
+       __set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags);
+
        return 0;
 }
 
@@ -1551,8 +1487,6 @@ static int rt2500usb_get_stats(struct ieee80211_hw *hw,
 static const struct ieee80211_ops rt2500usb_mac80211_ops = {
        .tx                     = rt2x00lib_tx,
        .reset                  = rt2x00lib_reset,
-       .open                   = rt2x00lib_open,
-       .stop                   = rt2x00lib_stop,
        .add_interface          = rt2x00lib_add_interface,
        .remove_interface       = rt2x00lib_remove_interface,
        .config                 = rt2x00lib_config,
@@ -1573,6 +1507,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
        .write_tx_desc          = rt2500usb_write_tx_desc,
        .write_tx_data          = rt2x00usb_write_tx_data,
        .kick_tx_queue          = rt2500usb_kick_tx_queue,
+       .fill_rxdone            = rt2500usb_fill_rxdone,
        .config_type            = rt2500usb_config_type,
        .config_phymode         = rt2500usb_config_phymode,
        .config_channel         = rt2500usb_config_channel,
@@ -1665,14 +1600,11 @@ static struct usb_driver rt2500usb_driver = {
 
 static int __init rt2500usb_init(void)
 {
-       printk(KERN_INFO "Loading module: %s - %s by %s.\n",
-               DRV_NAME, DRV_VERSION, DRV_PROJECT);
        return usb_register(&rt2500usb_driver);
 }
 
 static void __exit rt2500usb_exit(void)
 {
-       printk(KERN_INFO "Unloading module: %s.\n", DRV_NAME);
        usb_deregister(&rt2500usb_driver);
 }
 
index e756d6e..814bd04 100644 (file)
 #define RF5222                         0x0010
 
 /*
- * Max RSSI value, required for RSSI <-> dBm conversion.
+ * RT2570 version
  */
-#define MAX_RX_SSI                     120
+#define RT2570_VERSION_B               2
+#define RT2570_VERSION_C               3
+#define RT2570_VERSION_D               4
+
+/*
+ * Signal information.
+ */
+#define MAX_RX_SSI                     -1
 #define MAX_RX_NOISE                   -110
+#define DEFAULT_RSSI_OFFSET            120
 
 /*
  * Register layout information.
        (__txpower));                                   \
 })
 
-/*
- * Interrupt functions.
- */
-static void rt2500usb_interrupt_rxdone(struct urb *urb);
-
 #endif /* RT2500USB_H */
index dbea6ac..33b5094 100644 (file)
 #define RT2X00_H
 
 #include <linux/bitops.h>
+#include <linux/prefetch.h>
 #include <linux/skbuff.h>
 #include <linux/workqueue.h>
 
 #include <net/mac80211.h>
 
-#include "rt2x00lib.h"
-#include "rt2x00debug.h"
-
 /*
  * Module information.
+ * DRV_NAME should be set within the individual module source files.
  */
-#ifndef DRV_NAME
-#define DRV_NAME       "rt2x00"
-#endif /* DRV_NAME */
-#define DRV_VERSION    "2.0.1"
+#define DRV_VERSION    "2.0.2"
 #define DRV_PROJECT    "http://rt2x00.serialmonkey.com"
 
 /*
 /*
  * Interval defines
  */
-#define LINK_TUNE_INTERVAL     ( 1 * HZ )
+#define LINK_TUNE_INTERVAL     ( round_jiffies(HZ) )
 #define RFKILL_POLL_INTERVAL   ( HZ / 4 )
 
 /*
@@ -392,7 +388,6 @@ struct data_entry {
 #define ENTRY_TXD_MORE_FRAG    5
 #define ENTRY_TXD_REQ_TIMESTAMP        6
 #define ENTRY_TXD_REQ_ACK      7
-#define ENTRY_TXD_NEW_SEQ      8
 
        /*
         * Ring we belong to.
@@ -569,17 +564,26 @@ struct link {
         */
        u32 count;
 
-       /*
-        * RSSI statistics.
-        */
-       u32 count_rssi;
-       u32 total_rssi;
-
        /*
         * Misc statistics.
+        * For the average RSSI value we use the "Walking average" approach.
+        * When adding RSSI to the average value the following calculation
+        * is needed:
+        *
+        *      avg_rssi = ((avg_rssi * 7) + rssi) / 8;
+        *
+        * The advantage of this approach is that we only need 1 variable
+        * to store the average in (No need for a count and a total).
+        * But more importantly, normal average values will over time
+        * move less and less towards newly added values.
+        * This means that with link tuning, the device can have a very
+        * good RSSI for a few minutes but when the device is moved away
+        * from the AP the average will not decrease fast enough to
+        * compensate. The walking average compensates this and will
+        * move towards the new values correctly.
         */
-       u32 curr_noise;
-       u32 false_cca;
+       int avg_rssi;
+       int false_cca;
 
        /*
         * Work structure for scheduling periodic link tuning.
@@ -636,6 +640,33 @@ static inline int is_monitor_present(struct interface *intf)
        return !!intf->monitor_count;
 }
 
+/*
+ * Details about the supported modes, rates and channels
+ * of a particular chipset. This is used by rt2x00lib
+ * to build the ieee80211_hw_mode array for mac80211.
+ */
+struct hw_mode_spec {
+       /*
+        * Number of modes, rates and channels.
+        */
+       int num_modes;
+       int num_rates;
+       int num_channels;
+
+       /*
+        * txpower values.
+        */
+       const u8 *tx_power_a;
+       const u8 *tx_power_bg;
+       u8 tx_power_default;
+
+       /*
+        * Device/chipset specific value.
+        */
+       const u32 *chan_val_a;
+       const u32 *chan_val_bg;
+};
+
 /*
  * rt2x00lib callback functions.
  */
@@ -665,7 +696,7 @@ struct rt2x00lib_ops {
        int (*set_device_state)(struct rt2x00_dev *rt2x00dev,
                enum dev_state state);
        int (*rfkill_poll)(struct rt2x00_dev *rt2x00dev);
-       void (*link_tuner)(struct rt2x00_dev *rt2x00dev, int rssi);
+       void (*link_tuner)(struct rt2x00_dev *rt2x00dev);
 
        /*
         * TX control handlers
@@ -680,13 +711,19 @@ struct rt2x00lib_ops {
                struct ieee80211_tx_control *control);
        void (*kick_tx_queue)(struct rt2x00_dev *rt2x00dev, int queue);
 
+       /*
+        * RX control handlers
+        */
+       int (*fill_rxdone)(struct data_entry *entry,
+               int *signal, int *rssi, int *ofdm);
+
        /*
         * Configuration handlers.
         */
        void (*config_type)(struct rt2x00_dev *rt2x00dev, const int type);
        void (*config_phymode)(struct rt2x00_dev *rt2x00dev, const int phy);
        void (*config_channel)(struct rt2x00_dev *rt2x00dev, const int value,
-       const int channel, const int txpower);
+               const int channel, const int txpower);
        void (*config_mac_addr)(struct rt2x00_dev *rt2x00dev, u8 *mac);
        void (*config_bssid)(struct rt2x00_dev *rt2x00dev, u8 *bssid);
        void (*config_promisc)(struct rt2x00_dev *rt2x00dev, const int promisc);
@@ -723,7 +760,6 @@ struct rt2x00_dev {
         * macro's should be used for correct typecasting.
         */
        void *dev;
-       struct device *device;
 #define rt2x00dev_pci(__dev)   ( (struct pci_dev*)(__dev)->dev )
 #define rt2x00dev_usb(__dev)   ( (struct usb_interface*)(__dev)->dev )
 
@@ -796,12 +832,9 @@ struct rt2x00_dev {
         * If enabled, the debugfs interface structures
         * required for deregistration of debugfs.
         */
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
        const struct rt2x00debug_intf *debugfs_intf;
-
-       /*
-        * Queue for deferred work.
-        */
-       struct workqueue_struct *workqueue;
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
 
        /*
         * Interface configuration.
@@ -844,9 +877,9 @@ struct rt2x00_dev {
        u8 led_mode;
 
        /*
-        * EEPROM bus width (PCI devices only).
+        * Rssi <-> Dbm offset
         */
-       u8 eeprom_width;
+       u8 rssi_offset;
 
        /*
         * Frequency offset (for rt61pci & rt73usb).
@@ -907,14 +940,22 @@ static inline struct data_ring* rt2x00_get_ring(
  * The 1 + Atim check will assure that the address directly after
  * the ring array is obtained and the for-each loop exits correctly.
  */
-#define ring_for_each(__dev, __entry)          \
-       for ((__entry) = (__dev)->rx;           \
-               (__entry) != &(__dev)->bcn[1 +  \
-                       test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags)]; \
-               (__entry)++)
+#define ring_end(__dev) \
+       &(__dev)->bcn[1 + test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags)]
+
+#define ring_loop(__entry, __start, __end)                     \
+       for ((__entry) = (__start);                             \
+            prefetch(&(__entry)[1]), (__entry) != (__end);     \
+            (__entry) = &(__entry)[1])
+
+#define ring_for_each(__dev, __entry) \
+       ring_loop(__entry, (__dev)->rx, ring_end(__dev))
+
+#define txring_for_each(__dev, __entry) \
+       ring_loop(__entry, (__dev)->tx, (__dev)->bcn)
 
-#define txring_for_each(__dev, __entry)                \
-       for ((__entry) = (__dev)->tx; (__entry) != (__dev)->bcn; (__entry)++)
+#define txringall_for_each(__dev, __entry) \
+       ring_loop(__entry, (__dev)->tx, ring_end(__dev))
 
 /*
  * EEPROM access.
@@ -944,11 +985,10 @@ static inline void rt2x00_eeprom_write(const struct rt2x00_dev *rt2x00dev,
 static inline void rt2x00_start_link_tune(struct rt2x00_dev *rt2x00dev)
 {
        rt2x00dev->link.count = 0;
-       rt2x00dev->link.count_rssi = 0;
-       rt2x00dev->link.total_rssi = 0;
-       rt2x00dev->link.curr_noise = 0;
+       rt2x00dev->link.avg_rssi = 0;
+       rt2x00dev->link.false_cca = 0;
 
-       queue_delayed_work(rt2x00dev->workqueue,
+       queue_delayed_work(rt2x00dev->hw->workqueue,
                &rt2x00dev->link.work, LINK_TUNE_INTERVAL);
 }
 
@@ -956,26 +996,20 @@ static inline void rt2x00_stop_link_tune(struct rt2x00_dev *rt2x00dev)
 {
        if (work_pending(&rt2x00dev->link.work.work))
                cancel_rearming_delayed_workqueue(
-                       rt2x00dev->workqueue, &rt2x00dev->link.work);
+                       rt2x00dev->hw->workqueue, &rt2x00dev->link.work);
 }
 
-static inline void rt2x00_update_link_rssi(struct link *link, u32 rssi)
+static inline void rt2x00_update_link_rssi(struct link *link, int rssi)
 {
-       link->count_rssi++;
-       link->total_rssi += rssi;
+       if (!link->avg_rssi)
+               link->avg_rssi = rssi;
+       else
+               link->avg_rssi = ((link->avg_rssi * 7) + rssi) / 8;
 }
 
-static inline u32 rt2x00_get_link_rssi(struct link *link)
+static inline int rt2x00_get_link_rssi(struct link *link)
 {
-       u32 average = 0;
-
-       if (link->count_rssi && link->total_rssi)
-               average = link->total_rssi / link->count_rssi;
-
-       link->count_rssi = 0;
-       link->total_rssi = 0;
-
-       return average;
+       return link->avg_rssi;
 }
 
 /*
index 111c51e..83d4f99 100644 (file)
 #endif
 #endif
 
+#if (defined(CONFIG_RT2X00_DEBUGFS))
+#if (!defined(CONFIG_MAC80211_DEBUGFS) && !defined(CONFIG_MAC80211_DEBUGFS_MODULE))
+#error mac80211 debugfs support has been disabled in your kernel!
+#endif
+#endif
+
 #if (defined(CONFIG_RT2400PCI_BUTTON) || defined(CONFIG_RT2500PCI_BUTTON) || defined(CONFIG_RT61PCI_BUTTON))
 #if (!defined(CONFIG_RFKILL) && !defined (CONFIG_RFKILL_MODULE))
 #error RFKILL has been disabled in your kernel!
index 5751dd1..e69de29 100644 (file)
@@ -1,44 +0,0 @@
-#ifndef CONFIG_RT2X00
-#define CONFIG_RT2X00
-#endif
-
-#ifndef CONFIG_RT2X00_DEBUG
-#define CONFIG_RT2X00_DEBUG
-#endif
-
-#ifndef CONFIG_RT2X00_DEBUGFS
-#define CONFIG_RT2X00_DEBUGFS
-#endif
-
-#undef CONFIG_RT2X00_ASM
-
-#ifndef CONFIG_RT2X00_LIB_FIRMWARE
-#define CONFIG_RT2X00_LIB_FIRMWARE
-#endif
-
-#ifndef CONFIG_RT2400PCI
-#define CONFIG_RT2400PCI
-#endif
-
-#undef CONFIG_RT2400PCI_BUTTON
-
-#ifndef CONFIG_RT2500PCI
-#define CONFIG_RT2500PCI
-#endif
-
-#undef CONFIG_RT2500PCI_BUTTON
-
-#ifndef CONFIG_RT2500USB
-#define CONFIG_RT2500USB
-#endif
-
-#ifndef CONFIG_RT61PCI
-#define CONFIG_RT61PCI
-#endif
-
-#undef CONFIG_RT61PCI_BUTTON
-
-#ifndef CONFIG_RT73USB
-#define CONFIG_RT73USB
-#endif
-
index cb61870..e2239fa 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/uaccess.h>
 
 #include "rt2x00.h"
+#include "rt2x00debug.h"
 
 #define PRINT_REG8_STR         ( "0x%.2x\n" )
 #define PRINT_REG16_STR                ( "0x%.4x\n" )
index 8c8f5a3..f987bc9 100644 (file)
@@ -28,8 +28,6 @@
 #ifndef RT2X00DEBUG_H
 #define RT2X00DEBUG_H
 
-#include <net/wireless.h>
-
 typedef void (debug_access_t)(struct rt2x00_dev *rt2x00dev,
        const unsigned long word, void *data);
 
index 448f1bc..043af31 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/etherdevice.h>
 
 #include "rt2x00.h"
+#include "rt2x00lib.h"
 #include "rt2x00dev.h"
 
 /*
@@ -67,6 +68,9 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
 
        ieee80211_start_queues(rt2x00dev->hw);
 
+       if (is_interface_present(&rt2x00dev->interface))
+               rt2x00_start_link_tune(rt2x00dev);
+
        return 0;
 }
 
@@ -75,6 +79,8 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
        if (!__test_and_clear_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
                return;
 
+       rt2x00_stop_link_tune(rt2x00dev);
+
        ieee80211_stop_queues(rt2x00dev->hw);
 
        rt2x00lib_toggle_rx(rt2x00dev, 0);
@@ -87,7 +93,7 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, int enable)
        /*
         * When we are disabling the rx, we should also stop the link tuner.
         */
-       if (!enable && work_pending(&rt2x00dev->link.work.work))
+       if (!enable)
                rt2x00_stop_link_tune(rt2x00dev);
 
        rt2x00dev->ops->lib->set_device_state(rt2x00dev,
@@ -96,7 +102,7 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, int enable)
        /*
         * When we are enabling the rx, we should also start the link tuner.
         */
-       if (enable)
+       if (enable && is_interface_present(&rt2x00dev->interface))
                rt2x00_start_link_tune(rt2x00dev);
 }
 
@@ -104,7 +110,6 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
 {
        struct rt2x00_dev *rt2x00dev =
                container_of(work, struct rt2x00_dev, link.work.work);
-       int rssi;
 
        /*
         * Update promisc mode (this function will first check
@@ -119,20 +124,13 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
        if (test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags))
                return;
 
-       /*
-        * Retrieve link quality.
-        * Also convert rssi to dBm using the max_rssi value.
-        */
-       rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
-       rssi -= rt2x00dev->hw->max_rssi;
-
-       rt2x00dev->ops->lib->link_tuner(rt2x00dev, rssi);
+       rt2x00dev->ops->lib->link_tuner(rt2x00dev);
 
        /*
         * Increase tuner counter, and reschedule the next link tuner run.
         */
        rt2x00dev->link.count++;
-       queue_delayed_work(rt2x00dev->workqueue, &rt2x00dev->link.work,
+       queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work,
                LINK_TUNE_INTERVAL);
 }
 
@@ -422,23 +420,6 @@ static int rt2x00lib_init_hw(struct rt2x00_dev *rt2x00dev)
        struct hw_mode_spec *spec = &rt2x00dev->spec;
        int status;
 
-       /*
-        * Initialize device.
-        */
-       SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->device);
-
-       /*
-        * Initialize MAC address.
-        */
-       if (!is_valid_ether_addr(spec->mac_addr)) {
-               ERROR(rt2x00dev, "Invalid MAC addr: " MAC_FMT ".\n",
-                       MAC_ARG(spec->mac_addr));
-               return -EINVAL;
-       }
-
-       rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, spec->mac_addr);
-       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, spec->mac_addr);
-
        /*
         * Initialize HW modes.
         */
@@ -463,7 +444,7 @@ static int rt2x00lib_init_hw(struct rt2x00_dev *rt2x00dev)
 /*
  * Initialization/uninitialization handlers.
  */
-static int rt2x00lib_alloc_ring(struct data_ring *ring,
+static int rt2x00lib_alloc_ring_entries(struct data_ring *ring,
        const u16 max_entries, const u16 data_size, const u16 desc_size)
 {
        struct data_entry *entry;
@@ -491,14 +472,14 @@ static int rt2x00lib_alloc_ring(struct data_ring *ring,
        return 0;
 }
 
-static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev)
+static int rt2x00lib_allocate_ring_entries(struct rt2x00_dev *rt2x00dev)
 {
        struct data_ring *ring;
 
        /*
         * Allocate the RX ring.
         */
-       if (rt2x00lib_alloc_ring(rt2x00dev->rx,
+       if (rt2x00lib_alloc_ring_entries(rt2x00dev->rx,
                RX_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->rxd_size))
                return -ENOMEM;
 
@@ -506,7 +487,7 @@ static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev)
         * First allocate the TX rings.
         */
        txring_for_each(rt2x00dev, ring) {
-               if (rt2x00lib_alloc_ring(ring,
+               if (rt2x00lib_alloc_ring_entries(ring,
                        TX_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->txd_size))
                        return -ENOMEM;
        }
@@ -514,7 +495,7 @@ static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev)
        /*
         * Allocate the BEACON ring.
         */
-       if (rt2x00lib_alloc_ring(&rt2x00dev->bcn[0],
+       if (rt2x00lib_alloc_ring_entries(&rt2x00dev->bcn[0],
                BEACON_ENTRIES, MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size))
                return -ENOMEM;
 
@@ -522,7 +503,7 @@ static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev)
         * Allocate the Atim ring.
         */
        if (test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags)) {
-               if (rt2x00lib_alloc_ring(&rt2x00dev->bcn[1],
+               if (rt2x00lib_alloc_ring_entries(&rt2x00dev->bcn[1],
                        ATIM_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->txd_size))
                        return -ENOMEM;
        }
@@ -530,7 +511,7 @@ static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev)
        return 0;
 }
 
-static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev)
+static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev)
 {
        struct data_ring *ring;
 
@@ -550,7 +531,7 @@ int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
        /*
         * Allocate all data rings.
         */
-       status = rt2x00lib_allocate_rings(rt2x00dev);
+       status = rt2x00lib_allocate_ring_entries(rt2x00dev);
        if (status) {
                ERROR(rt2x00dev, "DMA allocation failed.\n");
                return status;
@@ -578,7 +559,7 @@ exit_unitialize:
        rt2x00lib_uninitialize(rt2x00dev);
 
 exit:
-       rt2x00lib_free_rings(rt2x00dev);
+       rt2x00lib_free_ring_entries(rt2x00dev);
 
        return status;
 }
@@ -588,11 +569,6 @@ void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
        if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
                return;
 
-       /*
-        * Flush out all pending work.
-        */
-       flush_workqueue(rt2x00dev->workqueue);
-
        /*
         * Unregister rfkill.
         */
@@ -606,7 +582,7 @@ void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
        /*
         * Free allocated datarings.
         */
-       rt2x00lib_free_rings(rt2x00dev);
+       rt2x00lib_free_ring_entries(rt2x00dev);
 }
 
 /*
@@ -659,13 +635,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
 {
        int retval = -ENOMEM;
 
-       /*
-        * Create workqueue.
-        */
-       rt2x00dev->workqueue = create_singlethread_workqueue(DRV_NAME);
-       if (!rt2x00dev->workqueue)
-               goto exit;
-
        /*
         * Let the driver probe the device to detect the capabilities.
         */
@@ -763,14 +732,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
         */
        rt2x00lib_deinit_hw(rt2x00dev);
 
-       /*
-        * Free workqueue.
-        */
-       if (likely(rt2x00dev->workqueue)) {
-               destroy_workqueue(rt2x00dev->workqueue);
-               rt2x00dev->workqueue = NULL;
-       }
-
        /*
         * Free ring structures.
         */
@@ -824,13 +785,6 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
                return retval;
        }
 
-       /*
-        * Set device mode to awake for power management.
-        */
-       retval = rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE);
-       if (retval)
-               return retval;
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_resume);
@@ -914,14 +868,14 @@ void rt2x00lib_rxdone(struct data_entry *entry, char *data,
                         */
                        if (signal & 0x08)
                                val = rate->val2;
-                       val = rate->val;
+                       else
+                               val = rate->val;
                        break;
                }
        }
 
        rx_status->rate = val;
        rx_status->ssi = rssi;
-       rx_status->noise = rt2x00dev->link.curr_noise;
        rt2x00_update_link_rssi(&rt2x00dev->link, rssi);
 
        /*
@@ -1001,12 +955,6 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        if (ieee80211_get_morefrag(ieee80211hdr))
                __set_bit(ENTRY_TXD_MORE_FRAG, &entry->flags);
 
-       /*
-        * Check if this is a new sequence
-        */
-       if ((seq_ctrl & IEEE80211_SCTL_FRAG) == 0)
-               __set_bit(ENTRY_TXD_NEW_SEQ, &entry->flags);
-
        /*
         * Beacons and probe responses require the tsf timestamp
         * to be inserted into the frame.
index 3aef107..4c1ce4c 100644 (file)
  */
 #define DRV_NAME "rt2x00lib"
 
+#include <linux/delay.h>
 #include <linux/crc-itu-t.h>
 #include <linux/firmware.h>
 
 #include "rt2x00.h"
+#include "rt2x00lib.h"
 #include "rt2x00firmware.h"
 
 static void rt2x00lib_load_firmware_continued(const struct firmware *fw,
@@ -90,12 +92,17 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
         * Read correct firmware from harddisk.
         */
        fw_name = rt2x00dev->ops->lib->get_fw_name(rt2x00dev);
-       BUG_ON(fw_name == NULL);
+       if (!fw_name) {
+               ERROR(rt2x00dev,
+                       "Invalid firmware filename.\n"
+                       "Please file bug report to %s.\n", DRV_PROJECT);
+               return -EINVAL;
+       }
 
        INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name);
 
        status = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
-               fw_name, rt2x00dev->device, rt2x00dev,
+               fw_name, wiphy_dev(rt2x00dev->hw->wiphy), rt2x00dev,
                &rt2x00lib_load_firmware_continued);
 
        if (status)
index c9b5ee7..461d13d 100644 (file)
 #ifndef RT2X00LIB_H
 #define RT2X00LIB_H
 
-struct rt2x00_dev;
-struct data_desc;
-struct data_entry_desc;
-struct data_entry;
-
-/*
- * Details about the supported modes, rates and channels
- * of a particular chipset. This is used by rt2x00lib
- * to build the ieee80211_hw_mode array for mac80211.
- */
-struct hw_mode_spec {
-       /*
-        * Default mac address.
-        */
-       char *mac_addr;
-
-       /*
-        * Number of modes, rates and channels.
-        */
-       int num_modes;
-       int num_rates;
-       int num_channels;
-
-       /*
-        * txpower values.
-        */
-       const u8 *tx_power_a;
-       const u8 *tx_power_bg;
-       u8 tx_power_default;
-
-       /*
-        * Device/chipset specific value.
-        */
-       const u32 *chan_val_a;
-       const u32 *chan_val_bg;
-};
-
 /*
  * Driver allocation handlers.
  */
@@ -99,8 +62,6 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
        struct ieee80211_tx_control *control);
 int rt2x00lib_reset(struct ieee80211_hw *hw);
-int rt2x00lib_open(struct ieee80211_hw *hw);
-int rt2x00lib_stop(struct ieee80211_hw *hw);
 int rt2x00lib_add_interface(struct ieee80211_hw *hw,
        struct ieee80211_if_init_conf *conf);
 void rt2x00lib_remove_interface(struct ieee80211_hw *hw,
@@ -115,4 +76,6 @@ int rt2x00lib_get_tx_stats(struct ieee80211_hw *hw,
 int rt2x00lib_conf_tx(struct ieee80211_hw *hw, int queue,
        const struct ieee80211_tx_queue_params *params);
 
+#include "rt2x00debug.h"
+
 #endif /* RT2X00LIB_H */
index 349353b..8835df2 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/netdevice.h>
 
 #include "rt2x00.h"
+#include "rt2x00lib.h"
 #include "rt2x00dev.h"
 
 static int rt2x00_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
@@ -129,60 +130,18 @@ int rt2x00lib_reset(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_reset);
 
-int rt2x00lib_open(struct ieee80211_hw *hw)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       int status;
-
-       /*
-        * We must wait on the firmware before
-        * we can safely continue.
-        */
-       status = rt2x00lib_load_firmware_wait(rt2x00dev);
-       if (status)
-               return status;
-
-       /*
-        * Initialize the device.
-        */
-       status = rt2x00lib_initialize(rt2x00dev);
-       if (status)
-               return status;
-
-       /*
-        * Enable radio.
-        */
-       status = rt2x00lib_enable_radio(rt2x00dev);
-       if (status) {
-               rt2x00lib_uninitialize(rt2x00dev);
-               return status;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_open);
-
-int rt2x00lib_stop(struct ieee80211_hw *hw)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-
-       rt2x00lib_disable_radio(rt2x00dev);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00lib_stop);
-
 int rt2x00lib_add_interface(struct ieee80211_hw *hw,
        struct ieee80211_if_init_conf *conf)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
        struct interface *intf = &rt2x00dev->interface;
+       int status;
 
        /*
         * We only support 1 non-monitor interface.
         */
        if (conf->type != IEEE80211_IF_TYPE_MNTR &&
-           is_interface_present(&rt2x00dev->interface))
+           is_interface_present(intf))
                return -ENOBUFS;
 
        /*
@@ -200,17 +159,39 @@ int rt2x00lib_add_interface(struct ieee80211_hw *hw,
        }
 
        /*
-        * If this is the first interface which is being added,
-        * we should write the MAC address to the device.
-        */
-       if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
-               rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, conf->mac_addr);
-
-       /*
-        * Enable periodic link tuning if this is a non-monitor interface.
+        * Initialize interface, and enable the radio when this
+        * is the first interface that is brought up.
         */
-       if (conf->type != IEEE80211_IF_TYPE_MNTR)
-               rt2x00_start_link_tune(rt2x00dev);
+       if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) {
+               /*
+                * We must wait on the firmware before
+                * we can safely continue.
+                */
+               status = rt2x00lib_load_firmware_wait(rt2x00dev);
+               if (status)
+                       return status;
+
+               /*
+                * Before initialization, the mac address should
+                * be configured.
+                */
+               rt2x00dev->ops->lib->config_mac_addr(rt2x00dev,
+                       conf->mac_addr);
+               /*
+                * Initialize the device.
+                */
+               status = rt2x00lib_initialize(rt2x00dev);
+               if (status)
+                       return status;
+
+               /*
+                * Enable radio.
+                */
+               status = rt2x00lib_enable_radio(rt2x00dev);
+               if (status)
+                       return status;
+       }
 
        return 0;
 }
@@ -226,12 +207,12 @@ void rt2x00lib_remove_interface(struct ieee80211_hw *hw,
         * We only support 1 non-monitor interface.
         */
        if (conf->type != IEEE80211_IF_TYPE_MNTR &&
-           !is_interface_present(&rt2x00dev->interface))
+           !is_interface_present(intf))
                return;
 
        /*
-        * We support muliple monitor mode interfaces.
-        * All we need to do is decrease the monitor_count.
+        * When removing an monitor interface, decrease monitor_count.
+        * For non-monitor interfaces, all interface data needs to be reset.
         */
        if (conf->type == IEEE80211_IF_TYPE_MNTR) {
                intf->monitor_count--;
@@ -243,33 +224,18 @@ void rt2x00lib_remove_interface(struct ieee80211_hw *hw,
        }
 
        /*
-        * When this is a non-monitor mode, stop the periodic link tuning.
-        */
-       if (conf->type != IEEE80211_IF_TYPE_MNTR)
-               rt2x00_stop_link_tune(rt2x00dev);
-
-       /*
-        * Check if we still have 1 non-monitor or a monitor
-        * interface enabled. In that case we should update the
-        * registers.
-        */
-       if (is_monitor_present(&rt2x00dev->interface) ^
-           is_interface_present(&rt2x00dev->interface)) {
-               if (is_interface_present(&rt2x00dev->interface))
-                       rt2x00lib_config_type(rt2x00dev,
-                               rt2x00dev->interface.type);
-               else
-                       rt2x00lib_config_type(rt2x00dev,
-                               IEEE80211_IF_TYPE_MNTR);
-       }
-
-       /*
-        * Check which interfaces have been disabled.
+        * If this was the last interface,
+        * this is the time to disable the radio.
+        * If this is not the last interface, then we should
+        * check if we should switch completely to monitor
+        * mode or completely switch to the non-monitor mode.
         */
-       if (!is_interface_present(&rt2x00dev->interface))
-               __clear_bit(INTERFACE_ENABLED, &rt2x00dev->flags);
-       else if (!is_monitor_present(&rt2x00dev->interface))
-               __clear_bit(INTERFACE_ENABLED_MONITOR, &rt2x00dev->flags);
+       if (!is_monitor_present(intf) && !is_interface_present(intf))
+               rt2x00lib_disable_radio(rt2x00dev);
+       else if (is_monitor_present(intf) ^ is_interface_present(intf))
+               rt2x00lib_config_type(rt2x00dev,
+                       is_interface_present(intf) ?
+                               intf->type : IEEE80211_IF_TYPE_MNTR);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_remove_interface);
 
@@ -373,10 +339,10 @@ void rt2x00lib_set_multicast_list(struct ieee80211_hw *hw,
         * Check if the new state is different then the old state.
         */
        if (test_bit(INTERFACE_ENABLED_PROMISC, &rt2x00dev->flags) ==
-           (flags & IFF_PROMISC))
+           !!(flags & IFF_PROMISC))
                return;
 
-       rt2x00dev->interface.promisc = (flags & IFF_PROMISC);
+       rt2x00dev->interface.promisc = !!(flags & IFF_PROMISC);
 
        /*
         * Schedule the link tuner if this does not run
@@ -384,7 +350,7 @@ void rt2x00lib_set_multicast_list(struct ieee80211_hw *hw,
         * switched off when it is not required.
         */
        if (!work_pending(&rt2x00dev->link.work.work))
-               queue_work(rt2x00dev->workqueue, &rt2x00dev->link.work.work);
+               queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work.work);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_set_multicast_list);
 
index 4156ea3..33c724d 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/pci.h>
 
 #include "rt2x00.h"
+#include "rt2x00lib.h"
 #include "rt2x00pci.h"
 
 /*
@@ -109,7 +110,8 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
 
        rt2x00_desc_read(txd, 0, &word);
 
-       if (rt2x00_get_field32(word, TXD_ENTRY_AVAILABLE)) {
+       if (rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) ||
+           rt2x00_get_field32(word, TXD_ENTRY_VALID)) {
                ERROR(rt2x00dev,
                        "Arrived at non-free entry in the non-full queue %d.\n"
                        "Please file bug report to %s.\n",
@@ -118,11 +120,11 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
                return -EINVAL;
        }
 
+       entry->skb = skb;
+       memcpy(&entry->tx_status.control, control, sizeof(*control));
        memcpy(entry->data_addr, skb->data, skb->len);
        rt2x00lib_write_tx_desc(rt2x00dev, entry, txd, ieee80211hdr,
                skb->len, control);
-       memcpy(&entry->tx_status.control, control, sizeof(*control));
-       entry->skb = skb;
 
        rt2x00_ring_index_inc(ring);
 
@@ -133,6 +135,50 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
 
+/*
+ * RX data handlers.
+ */
+void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_ring *ring = rt2x00dev->rx;
+       struct data_entry *entry;
+       struct data_desc *rxd;
+       u32 desc;
+       int signal;
+       int rssi;
+       int ofdm;
+       int size;
+
+       while (1) {
+               entry = rt2x00_get_data_entry(ring);
+               rxd = entry->priv;
+               rt2x00_desc_read(rxd, 0, &desc);
+
+               if (rt2x00_get_field32(desc, RXD_ENTRY_OWNER_NIC))
+                       break;
+
+               size = rt2x00dev->ops->lib->fill_rxdone(
+                       entry, &signal, &rssi, &ofdm);
+               if (size < 0)
+                       goto skip_entry;
+
+               /*
+                * Send the packet to upper layer.
+                */
+               rt2x00lib_rxdone(entry, entry->data_addr, size,
+                       signal, rssi, ofdm);
+
+skip_entry:
+               if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
+                       rt2x00_set_field32(&desc, RXD_ENTRY_OWNER_NIC, 1);
+                       rt2x00_desc_write(rxd, 0, desc);
+               }
+
+               rt2x00_ring_index_inc(ring);
+       }
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
+
 /*
  * Device initialization handlers.
  */
@@ -304,7 +350,6 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 
        rt2x00dev = hw->priv;
        rt2x00dev->dev = pci_dev;
-       rt2x00dev->device = &pci_dev->dev;
        rt2x00dev->ops = ops;
        rt2x00dev->hw = hw;
 
index 291d0c0..8595cbf 100644 (file)
 #define REGISTER_BUSY_DELAY    100
 
 /*
- * TX descriptor available flag.
- * This flag is the combination of the TXD_W0_OWNER_NIC
- * and TXD_W0_VALID flag which have the same value on all
- * PCI drivers.
+ * Descriptor availability flags.
+ * All PCI device descriptors have these 2 flags
+ * with the exact same definition.
  */
-#define TXD_ENTRY_AVAILABLE    FIELD32(0x00000003)
+#define TXD_ENTRY_OWNER_NIC    FIELD32(0x00000001)
+#define TXD_ENTRY_VALID                FIELD32(0x00000002)
+#define RXD_ENTRY_OWNER_NIC    FIELD32(0x00000001)
 
 /*
  * Register access.
@@ -93,6 +94,11 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
        struct data_ring *ring, struct sk_buff *skb,
        struct ieee80211_tx_control *control);
 
+/*
+ * RX data handlers.
+ */
+void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
+
 /*
  * Device initialization handlers.
  */
index 63062f1..c08a2aa 100644 (file)
@@ -70,7 +70,7 @@ static void rt2x00lib_rfkill_poll(struct work_struct *work)
        rfkill_switch_all(rt2x00dev->rfkill->type,
                rt2x00dev->ops->lib->rfkill_poll(rt2x00dev));
 
-       queue_delayed_work(rt2x00dev->workqueue, &rt2x00dev->rfkill_work,
+       queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->rfkill_work,
                RFKILL_POLL_INTERVAL);
 }
 
@@ -92,7 +92,7 @@ void rt2x00lib_unregister_rfkill(struct rt2x00_dev *rt2x00dev)
 {
        if (delayed_work_pending(&rt2x00dev->rfkill_work))
                cancel_rearming_delayed_workqueue(
-                       rt2x00dev->workqueue, &rt2x00dev->rfkill_work);
+                       rt2x00dev->hw->workqueue, &rt2x00dev->rfkill_work);
 
        rfkill_unregister(rt2x00dev->rfkill);
 }
index 6b193d0..4175aef 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/usb.h>
 
 #include "rt2x00.h"
+#include "rt2x00lib.h"
 #include "rt2x00usb.h"
 
 /*
@@ -62,48 +63,13 @@ int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
                        return 0;
        }
 
-       ERROR(rt2x00dev, "vendor request error. Request 0x%02x failed "
-               "for offset 0x%04x with error %d.\n", request, offset, status);
+       ERROR(rt2x00dev, "Vendor Request 0x%02x failed for offset 0x%04x"
+               " with error %d.\n", request, offset, status);
 
        return status;
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request);
 
-/*
- * Radio handlers
- */
-void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       unsigned int i;
-
-       /*
-        * Start the RX ring.
-        */
-       for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
-               __set_bit(ENTRY_OWNER_NIC, &rt2x00dev->rx->entry[i].flags);
-               usb_submit_urb(rt2x00dev->rx->entry[i].priv, GFP_ATOMIC);
-       }
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_enable_radio);
-
-void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       struct data_ring *ring;
-       unsigned int i;
-
-       rt2x00usb_vendor_request(rt2x00dev, USB_RX_CONTROL,
-               USB_VENDOR_REQUEST_OUT, 0x00, 0x00, NULL, 0, REGISTER_TIMEOUT);
-
-       /*
-        * Cancel all rings.
-        */
-       ring_for_each(rt2x00dev, ring) {
-               for (i = 0; i < ring->stats.limit; i++)
-                       usb_kill_urb(ring->entry[i].priv);
-       }
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
-
 /*
  * Beacon handlers.
  */
@@ -328,6 +294,120 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
 
+/*
+ * RX data handlers.
+ */
+static void rt2x00usb_interrupt_rxdone(struct urb *urb)
+{
+       struct data_entry *entry = (struct data_entry*)urb->context;
+       struct data_ring *ring = entry->ring;
+       struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
+       int signal;
+       int rssi;
+       int ofdm;
+       int size;
+
+       if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
+           !test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
+               return;
+
+       /*
+        * Check if the received data is simply too small
+        * to be actually valid, or if the urb is signaling
+        * a problem.
+        */
+       if (urb->actual_length < entry->ring->desc_size || urb->status)
+               goto skip_entry;
+
+       size = rt2x00dev->ops->lib->fill_rxdone(entry, &signal, &rssi, &ofdm);
+       if (size < 0)
+               goto skip_entry;
+
+       /*
+        * Trim the skb_buffer to only contain the valid
+        * frame data (so ignore the device's descriptor).
+        */
+       skb_trim(entry->skb, size);
+
+       /*
+        * Send the packet to upper layer, and update urb.
+        */
+       rt2x00lib_rxdone(entry, NULL, ring->data_size + ring->desc_size,
+               signal, rssi, ofdm);
+       urb->transfer_buffer = entry->skb->data;
+       urb->transfer_buffer_length = entry->skb->len;
+
+skip_entry:
+       if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
+               __set_bit(ENTRY_OWNER_NIC, &entry->flags);
+               usb_submit_urb(urb, GFP_ATOMIC);
+       }
+
+       rt2x00_ring_index_inc(ring);
+}
+
+/*
+ * Radio handlers
+ */
+void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       struct usb_device *usb_dev =
+               interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
+       struct data_ring *ring;
+       struct data_entry *entry;
+       unsigned int i;
+
+       /*
+        * Initialize the TX rings
+        */
+       txringall_for_each(rt2x00dev, ring) {
+               for (i = 0; i < ring->stats.limit; i++)
+                       ring->entry[i].flags = 0;
+
+               rt2x00_ring_index_clear(ring);
+       }
+
+       /*
+        * Initialize and start the RX ring.
+        */
+       rt2x00_ring_index_clear(rt2x00dev->rx);
+
+       for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
+               entry = &rt2x00dev->rx->entry[i];
+
+               usb_fill_bulk_urb(
+                       entry->priv,
+                       usb_dev,
+                       usb_rcvbulkpipe(usb_dev, 1),
+                       entry->skb->data,
+                       entry->skb->len,
+                       rt2x00usb_interrupt_rxdone,
+                       entry);
+
+               __set_bit(ENTRY_OWNER_NIC, &entry->flags);
+               usb_submit_urb(entry->priv, GFP_ATOMIC);
+       }
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_enable_radio);
+
+void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_ring *ring;
+       unsigned int i;
+
+       rt2x00usb_vendor_request(rt2x00dev, USB_RX_CONTROL,
+               USB_VENDOR_REQUEST_OUT, 0x00, 0x00, NULL, 0, REGISTER_TIMEOUT);
+
+       /*
+        * Cancel all rings.
+        */
+       ring_for_each(rt2x00dev, ring) {
+               for (i = 0; i < ring->stats.limit; i++)
+                       usb_kill_urb(ring->entry[i].priv);
+       }
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
+
 /*
  * Device initialization handlers.
  */
@@ -433,7 +513,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
 
        rt2x00dev = hw->priv;
        rt2x00dev->dev = usb_intf;
-       rt2x00dev->device = &usb_intf->dev;
        rt2x00dev->ops = ops;
        rt2x00dev->hw = hw;
 
index fe90dd2..6277548 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/io.h>
 
 #include "rt2x00.h"
+#include "rt2x00lib.h"
 #include "rt2x00pci.h"
 #include "rt61pci.h"
 
@@ -891,13 +892,19 @@ static void rt61pci_disable_led(struct rt2x00_dev *rt2x00dev)
        rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
 }
 
-static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, char rssi)
+static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
 {
        u8 led;
 
        if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
                return;
 
+       /*
+        * Led handling requires a positive value for the rssi,
+        * to do that correctly we need to add the correction.
+        */
+       rssi += rt2x00dev->rssi_offset;
+
        if (rssi <= 30)
                led = 0;
        else if (rssi <= 39)
@@ -917,8 +924,9 @@ static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, char rssi)
 /*
  * Link tuning
  */
-static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
+static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
 {
+       int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
        u32 reg;
        u8 r17;
        u8 up_bound;
@@ -1013,10 +1021,12 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
                if (++r17 > up_bound)
                        r17 = up_bound;
                rt61pci_bbp_write(rt2x00dev, 17, r17);
+               rt2x00dev->rx_status.noise = r17;
        } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) {
                if (--r17 < low_bound)
                        r17 = low_bound;
                rt61pci_bbp_write(rt2x00dev, 17, r17);
+               rt2x00dev->rx_status.noise = r17;
        }
 }
 
@@ -1279,7 +1289,12 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
 
        rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
 
-       rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, 0x025eb032);
+       rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
+       rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
 
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR1, 0x9eb39eb3);
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR2, 0x8a8b8c8d);
@@ -1312,10 +1327,6 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
        rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
 
-       rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
-       rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
-
        rt2x00pci_register_write(rt2x00dev, PHY_CSR1, 0x000023b0);
        rt2x00pci_register_write(rt2x00dev, PHY_CSR5, 0x060a100c);
        rt2x00pci_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
@@ -1432,10 +1443,48 @@ static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
        rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
 }
 
-static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled)
 {
        u32 reg;
 
+       /*
+        * When interrupts are being enabled, the interrupt registers
+        * should clear the register to assure a clean state.
+        */
+       if (enabled) {
+               rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+               rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+               rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
+               rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
+       }
+
+       /*
+        * Only toggle the interrupts bits we are going to use.
+        * Non-checked interrupt bits are disabled by default.
+        */
+       rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+       rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, !enabled);
+       rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, !enabled);
+       rt2x00_set_field32(&reg, INT_MASK_CSR_BEACON_DONE, !enabled);
+       rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, !enabled);
+       rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
+       rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+
+       rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_0, !enabled);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_1, !enabled);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_2, !enabled);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_3, !enabled);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_4, !enabled);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_5, !enabled);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_6, !enabled);
+       rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_7, !enabled);
+       rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+}
+
+static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
+{
        /*
         * Initialize all registers.
         */
@@ -1446,24 +1495,10 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
                return -EIO;
        }
 
-       /*
-        * Clear interrupts.
-        */
-       rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
-       rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
-
-       rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
-       rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
-
        /*
         * Enable interrupts.
         */
-       reg = 0;
-       rt2x00_set_field32(&reg, INT_MASK_CSR_TX_ABORT_DONE, 1);
-       rt2x00_set_field32(&reg, INT_MASK_CSR_MITIGATION_PERIOD, 0xff);
-       rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
-
-       rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, 0x00000000);
+       rt61pci_toggle_irq(rt2x00dev, 1);
 
        /*
         * Enable RX.
@@ -1508,11 +1543,7 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)
        /*
         * Disable interrupts.
         */
-       reg = 0xffffffff;
-       rt2x00_set_field32(&reg, INT_MASK_CSR_ENABLE_MITIGATION, 0);
-       rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
-
-       rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, 0xffffffff);
+       rt61pci_toggle_irq(rt2x00dev, 0);
 }
 
 static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -1681,60 +1712,80 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
 }
 
 /*
- * Interrupt functions.
+ * RX control handlers
  */
-static void rt61pci_rxdone(struct rt2x00_dev *rt2x00dev)
+static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
 {
-       struct data_ring *ring = rt2x00dev->rx;
-       struct data_entry *entry;
-       struct data_desc *rxd;
-       u32 word0;
-       u32 word1;
-       int signal;
-       int rssi;
-       int ofdm;
-       u16 size;
+       u16 eeprom;
+       char offset;
+       char lna;
 
-       while (1) {
-               entry = rt2x00_get_data_entry(ring);
-               rxd = entry->priv;
-               rt2x00_desc_read(rxd, 0, &word0);
-               rt2x00_desc_read(rxd, 1, &word1);
+       lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
+       switch (lna) {
+               case 3:
+                       offset = 90;
+               break;
+               case 2:
+                       offset = 74;
+               break;
+               case 1:
+                       offset = 64;
+               break;
+               default:
+                       return 0;
+       }
 
-               if (rt2x00_get_field32(word0, RXD_W0_OWNER_NIC))
-                       break;
+       if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
+               if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+                       offset += 14;
 
-               /*
-                * TODO: Don't we need to keep statistics
-                * updated about events like CRC and physical errors?
-                */
-               if (rt2x00_get_field32(word0, RXD_W0_CRC))
-                       goto skip_entry;
+               if (lna == 3 || lna == 2)
+                       offset += 10;
 
-               /*
-                * Obtain the status about this packet.
-                */
-               size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-               signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-               rssi = rt2x00_get_field32(word1, RXD_W1_RSSI);
-               ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+               offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
+       } else {
+               if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+                       offset += 14;
 
-               /*
-                * Send the packet to upper layer.
-                */
-               rt2x00lib_rxdone(entry, entry->data_addr, size,
-                       signal, rssi, ofdm);
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+               offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
+       }
 
-skip_entry:
-               if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
-                       rt2x00_set_field32(&word0, RXD_W0_OWNER_NIC, 1);
-                       rt2x00_desc_write(rxd, 0, word0);
-               }
+       return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
+}
 
-               rt2x00_ring_index_inc(ring);
-       }
+static int rt61pci_fill_rxdone(struct data_entry *entry,
+       int *signal, int *rssi, int *ofdm)
+{
+       struct data_desc *rxd = entry->priv;
+       u32 word0;
+       u32 word1;
+
+       rt2x00_desc_read(rxd, 0, &word0);
+       rt2x00_desc_read(rxd, 1, &word1);
+
+       /*
+        * TODO: Don't we need to keep statistics
+        * updated about these errors?
+        */
+       if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
+           rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
+               return -EINVAL;
+
+       /*
+        * Obtain the status about this packet.
+        */
+       *signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+       *rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1);
+       *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+
+       return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 }
 
+/*
+ * Interrupt functions.
+ */
 static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
 {
        struct data_ring *ring;
@@ -1840,7 +1891,7 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
         * 2 - Rx ring done interrupt.
         */
        if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE))
-               rt61pci_rxdone(rt2x00dev);
+               rt2x00pci_rxdone(rt2x00dev);
 
        /*
         * 3 - Tx ring done interrupt.
@@ -1859,6 +1910,8 @@ static int rt61pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
        struct eeprom_93cx6 eeprom;
        u32 reg;
        u16 word;
+       u8 *mac;
+       char value;
 
        /*
         * Allocate the eeprom memory, check the eeprom width
@@ -1886,6 +1939,12 @@ static int rt61pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Start validation of the data that has been read.
         */
+       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+       if (!is_valid_ether_addr(mac)) {
+               random_ether_addr(mac);
+               EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac));
+       }
+
        rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
@@ -1927,6 +1986,38 @@ static int rt61pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
                EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
        }
 
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
+               EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+       } else {
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_2);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+               EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+       } else {
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_2);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+       }
+
        return 0;
 }
 
@@ -2086,12 +2177,17 @@ static void rt61pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
                IEEE80211_HW_WEP_INCLUDE_IV |
                IEEE80211_HW_DATA_NULLFUNC_ACK |
                IEEE80211_HW_NO_TKIP_WMM_HWACCEL |
-               IEEE80211_HW_MONITOR_DURING_OPER;
+               IEEE80211_HW_MONITOR_DURING_OPER |
+               IEEE80211_HW_NO_PROBE_FILTERING;
        rt2x00dev->hw->extra_tx_headroom = 0;
        rt2x00dev->hw->max_rssi = MAX_RX_SSI;
        rt2x00dev->hw->max_noise = MAX_RX_NOISE;
        rt2x00dev->hw->queues = 5;
 
+       SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev);
+       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+               rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0));
+
        /*
         * Convert tx_power array in eeprom.
         */
@@ -2102,7 +2198,6 @@ static void rt61pci_init_hw_mode(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize hw_mode information.
         */
-       spec->mac_addr = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        spec->num_modes = 2;
        spec->num_rates = 12;
        spec->num_channels = 14;
@@ -2150,10 +2245,15 @@ static int rt61pci_init_hw(struct rt2x00_dev *rt2x00dev)
        rt61pci_init_hw_mode(rt2x00dev);
 
        /*
-        * rt61pci requires firmware
+        * This device requires firmware
         */
        __set_bit(FIRMWARE_REQUIRED, &rt2x00dev->flags);
 
+       /*
+        * Set the rssi offset.
+        */
+       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
+
        return 0;
 }
 
@@ -2219,8 +2319,6 @@ static void rt61pci_reset_tsf(struct ieee80211_hw *hw)
 static const struct ieee80211_ops rt61pci_mac80211_ops = {
        .tx                     = rt2x00lib_tx,
        .reset                  = rt2x00lib_reset,
-       .open                   = rt2x00lib_open,
-       .stop                   = rt2x00lib_stop,
        .add_interface          = rt2x00lib_add_interface,
        .remove_interface       = rt2x00lib_remove_interface,
        .config                 = rt2x00lib_config,
@@ -2250,6 +2348,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
        .write_tx_desc          = rt61pci_write_tx_desc,
        .write_tx_data          = rt2x00pci_write_tx_data,
        .kick_tx_queue          = rt61pci_kick_tx_queue,
+       .fill_rxdone            = rt61pci_fill_rxdone,
        .config_type            = rt61pci_config_type,
        .config_phymode         = rt61pci_config_phymode,
        .config_channel         = rt61pci_config_channel,
@@ -2309,14 +2408,11 @@ static struct pci_driver rt61pci_driver = {
 
 static int __init rt61pci_init(void)
 {
-       printk(KERN_INFO "Loading module: %s - %s by %s.\n",
-               DRV_NAME, DRV_VERSION, DRV_PROJECT);
        return pci_register_driver(&rt61pci_driver);
 }
 
 static void __exit rt61pci_exit(void)
 {
-       printk(KERN_INFO "Unloading module: %s.\n", DRV_NAME);
        pci_unregister_driver(&rt61pci_driver);
 }
 
index 6834732..9dfd293 100644 (file)
 #define RF2529                         0x0004
 
 /*
- * Max RSSI value, required for RSSI <-> dBm conversion.
+ * Signal information.
  */
-#define MAX_RX_SSI                     120
+#define MAX_RX_SSI                     -1
 #define MAX_RX_NOISE                   -110
+#define DEFAULT_RSSI_OFFSET            120
 
 /*
  * Register layout information.
@@ -1102,6 +1103,20 @@ struct hw_pairwise_ta_entry {
 #define EEPROM_TXPOWER_A_1             FIELD16(0x00ff)
 #define EEPROM_TXPOWER_A_2             FIELD16(0xff00)
 
+/*
+ * EEPROM RSSI offset 802.11BG
+ */
+#define EEPROM_RSSI_OFFSET_BG          0x004d
+#define EEPROM_RSSI_OFFSET_BG_1                FIELD16(0x00ff)
+#define EEPROM_RSSI_OFFSET_BG_2                FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI offset 802.11A
+ */
+#define EEPROM_RSSI_OFFSET_A           0x004e
+#define EEPROM_RSSI_OFFSET_A_1         FIELD16(0x00ff)
+#define EEPROM_RSSI_OFFSET_A_2         FIELD16(0xff00)
+
 /*
  * BBP content.
  * The wordsize of the BBP is 8 bits.
@@ -1285,10 +1300,10 @@ struct hw_pairwise_ta_entry {
 /*
  * Word1
  * SIGNAL: RX raw data rate reported by BBP.
- * RSSI: RSSI reported by BBP.
  */
 #define RXD_W1_SIGNAL                  FIELD32(0x000000ff)
-#define RXD_W1_RSSI                    FIELD32(0x0000ff00)
+#define RXD_W1_RSSI_AGC                        FIELD32(0x00001f00)
+#define RXD_W1_RSSI_LNA                        FIELD32(0x00006000)
 #define RXD_W1_FRAME_OFFSET            FIELD32(0x7f000000)
 
 /*
index 04261fa..c80bee1 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/etherdevice.h>
 
 #include "rt2x00.h"
+#include "rt2x00lib.h"
 #include "rt2x00usb.h"
 #include "rt73usb.h"
 
@@ -745,13 +746,19 @@ static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev)
                0x00, rt2x00dev->led_reg, NULL, 0, REGISTER_TIMEOUT);
 }
 
-static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, char rssi)
+static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
 {
        u32 led;
 
        if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH)
                return;
 
+       /*
+        * Led handling requires a positive value for the rssi,
+        * to do that correctly we need to add the correction.
+        */
+       rssi += rt2x00dev->rssi_offset;
+
        if (rssi <= 30)
                led = 0;
        else if (rssi <= 39)
@@ -773,8 +780,9 @@ static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, char rssi)
 /*
  * Link tuning
  */
-static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
+static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
 {
+       int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
        u32 reg;
        u8 r17;
        u8 up_bound;
@@ -880,11 +888,13 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, int rssi)
                if (r17 > up_bound)
                        r17 = up_bound;
                rt73usb_bbp_write(rt2x00dev, 17, r17);
+               rt2x00dev->rx_status.noise = r17;
        } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) {
                r17 -= 4;
                if (r17 < low_bound)
                        r17 = low_bound;
                rt73usb_bbp_write(rt2x00dev, 17, r17);
+               rt2x00dev->rx_status.noise = r17;
        }
 }
 
@@ -952,51 +962,6 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
        return 0;
 }
 
-static void rt73usb_init_rxring(struct rt2x00_dev *rt2x00dev)
-{
-       struct usb_device *usb_dev =
-               interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
-       unsigned int i;
-
-       for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
-               usb_fill_bulk_urb(
-                       rt2x00dev->rx->entry[i].priv,
-                       usb_dev,
-                       usb_rcvbulkpipe(usb_dev, 1),
-                       rt2x00dev->rx->entry[i].skb->data,
-                       rt2x00dev->rx->entry[i].skb->len,
-                       rt73usb_interrupt_rxdone,
-                       &rt2x00dev->rx->entry[i]);
-       }
-
-       rt2x00_ring_index_clear(rt2x00dev->rx);
-}
-
-static void rt73usb_init_txring(struct rt2x00_dev *rt2x00dev,
-       const int queue)
-{
-       struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue);
-       unsigned int i;
-
-       for (i = 0; i < ring->stats.limit; i++)
-               ring->entry[i].flags = 0;
-
-       rt2x00_ring_index_clear(ring);
-}
-
-static int rt73usb_init_rings(struct rt2x00_dev *rt2x00dev)
-{
-       rt73usb_init_rxring(rt2x00dev);
-       rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
-       rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
-       rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA2);
-       rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA3);
-       rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA4);
-       rt73usb_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-
-       return 0;
-}
-
 static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
@@ -1006,7 +971,12 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
 
        rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
 
-       rt73usb_register_write(rt2x00dev, TXRX_CSR0, 0x025eb032);
+       rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS, 1);
+       rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
+       rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
 
        rt73usb_register_write(rt2x00dev, TXRX_CSR1, 0x9eaa9eaf);
        rt73usb_register_write(rt2x00dev, TXRX_CSR2, 0x8a8b8c8d);
@@ -1049,10 +1019,6 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
        rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
        rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
 
-       rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
-
        /*
         * We must clear the error counters.
         * These registers are cleared on read,
@@ -1164,8 +1130,7 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize all registers.
         */
-       if (rt73usb_init_rings(rt2x00dev) ||
-           rt73usb_init_registers(rt2x00dev) ||
+       if (rt73usb_init_registers(rt2x00dev) ||
            rt73usb_init_bbp(rt2x00dev)) {
                ERROR(rt2x00dev, "Register initialization failed.\n");
                return -EIO;
@@ -1344,74 +1309,84 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue)
 }
 
 /*
- * Interrupt functions.
+ * RX control handlers
  */
-static void rt73usb_interrupt_rxdone(struct urb *urb)
+static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
+{
+       u16 eeprom;
+       char offset;
+       char lna;
+
+       lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA);
+       switch (lna) {
+               case 3:
+                       offset = 90;
+               break;
+               case 2:
+                       offset = 74;
+               break;
+               case 1:
+                       offset = 64;
+               break;
+               default:
+                       return 0;
+       }
+
+       if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) {
+               if (test_bit(CONFIG_EXTERNAL_LNA, &rt2x00dev->flags)) {
+                       if (lna == 3 || lna == 2)
+                               offset += 10;
+               } else {
+                       if (lna == 3)
+                               offset += 6;
+                       else if (lna == 2)
+                               offset += 8;
+               }
+
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+               offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
+       } else {
+               if (test_bit(CONFIG_EXTERNAL_LNA, &rt2x00dev->flags))
+                       offset += 14;
+
+               rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+               offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
+       }
+
+       return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset;
+}
+
+static int rt73usb_fill_rxdone(struct data_entry *entry,
+       int *signal, int *rssi, int *ofdm)
 {
-       struct data_entry *entry = (struct data_entry*)urb->context;
-       struct data_ring *ring = entry->ring;
-       struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
        struct data_desc *rxd = (struct data_desc*)entry->skb->data;
        u32 word0;
        u32 word1;
-       int signal;
-       int rssi;
-       int ofdm;
-       u16 size;
-
-       if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
-           !__test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
-               return;
-
-       /*
-        * Check if the received data is simply too small
-        * to be actually valid, or if the urb is signaling
-        * a problem.
-        */
-       if (urb->actual_length < entry->ring->desc_size || urb->status)
-               goto skip_entry;
 
        rt2x00_desc_read(rxd, 0, &word0);
        rt2x00_desc_read(rxd, 1, &word1);
 
        /*
         * TODO: Don't we need to keep statistics
-        * updated about events like CRC and physical errors?
+        * updated about these errors?
         */
        if (rt2x00_get_field32(word0, RXD_W0_CRC) ||
            rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
-               goto skip_entry;
+               return -EINVAL;
 
        /*
         * Obtain the status about this packet.
         */
-       size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-       signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
-       rssi = rt2x00_get_field32(word1, RXD_W1_RSSI);
-       ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
+       *signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
+       *rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1);
+       *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
 
        /*
-        * Trim the skb_buffer to only contain the valid
-        * frame data (so ignore the device's descriptor).
+        * Pull the skb to clear the descriptor area.
         */
-       skb_pull(entry->skb, ring->desc_size);
-       skb_trim(entry->skb, size);
+       skb_pull(entry->skb, entry->ring->desc_size);
 
-       /*
-        * Send the packet to upper layer, and update urb.
-        */
-       rt2x00lib_rxdone(entry, NULL, ring->data_size + ring->desc_size,
-               signal, rssi, ofdm);
-       urb->transfer_buffer = entry->skb->data;
-       urb->transfer_buffer_length = entry->skb->len;
-
-skip_entry:
-       if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) {
-               __set_bit(ENTRY_OWNER_NIC, &entry->flags);
-               usb_submit_urb(urb, GFP_ATOMIC);
-       }
-
-       rt2x00_ring_index_inc(ring);
+       return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
 }
 
 /*
@@ -1420,6 +1395,8 @@ skip_entry:
 static int rt73usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
 {
        u16 word;
+       u8 *mac;
+       char value;
 
        /*
         * Allocate the eeprom memory, check the eeprom width
@@ -1437,6 +1414,12 @@ static int rt73usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
        /*
         * Start validation of the data that has been read.
         */
+       mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+       if (!is_valid_ether_addr(mac)) {
+               random_ether_addr(mac);
+               EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac));
+       }
+
        rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
        if (word == 0xffff) {
                rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
@@ -1481,6 +1464,38 @@ static int rt73usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev)
                EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
        }
 
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
+               EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+       } else {
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_2);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word);
+       }
+
+       rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word);
+       if (word == 0xffff) {
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+               rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+               EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);
+       } else {
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);
+               value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_2);
+               if (value < -10 || value > 10)
+                       rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);
+               rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word);
+       }
+
        return 0;
 }
 
@@ -1612,12 +1627,17 @@ static void rt73usb_init_hw_mode(struct rt2x00_dev *rt2x00dev)
                IEEE80211_HW_WEP_INCLUDE_IV |
                IEEE80211_HW_DATA_NULLFUNC_ACK |
                IEEE80211_HW_NO_TKIP_WMM_HWACCEL |
-               IEEE80211_HW_MONITOR_DURING_OPER;
+               IEEE80211_HW_MONITOR_DURING_OPER |
+               IEEE80211_HW_NO_PROBE_FILTERING;
        rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
        rt2x00dev->hw->max_rssi = MAX_RX_SSI;
        rt2x00dev->hw->max_noise = MAX_RX_NOISE;
        rt2x00dev->hw->queues = 5;
 
+       SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev);
+       SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+               rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0));
+
        /*
         * Set device specific, but channel independent RF values.
         */
@@ -1638,7 +1658,6 @@ static void rt73usb_init_hw_mode(struct rt2x00_dev *rt2x00dev)
        /*
         * Initialize hw_mode information.
         */
-       spec->mac_addr = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
        spec->num_modes = 2;
        spec->num_rates = 12;
        spec->num_channels = 14;
@@ -1683,10 +1702,15 @@ static int rt73usb_init_hw(struct rt2x00_dev *rt2x00dev)
        rt73usb_init_hw_mode(rt2x00dev);
 
        /*
-        * rt73usb requires firmware
+        * This device requires firmware
         */
        __set_bit(FIRMWARE_REQUIRED, &rt2x00dev->flags);
 
+       /*
+        * Set the rssi offset.
+        */
+       rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET;
+
        return 0;
 }
 
@@ -1752,8 +1776,6 @@ static void rt73usb_reset_tsf(struct ieee80211_hw *hw)
 static const struct ieee80211_ops rt73usb_mac80211_ops = {
        .tx                     = rt2x00lib_tx,
        .reset                  = rt2x00lib_reset,
-       .open                   = rt2x00lib_open,
-       .stop                   = rt2x00lib_stop,
        .add_interface          = rt2x00lib_add_interface,
        .remove_interface       = rt2x00lib_remove_interface,
        .config                 = rt2x00lib_config,
@@ -1779,6 +1801,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
        .write_tx_desc          = rt73usb_write_tx_desc,
        .write_tx_data          = rt2x00usb_write_tx_data,
        .kick_tx_queue          = rt73usb_kick_tx_queue,
+       .fill_rxdone            = rt73usb_fill_rxdone,
        .config_type            = rt73usb_config_type,
        .config_phymode         = rt73usb_config_phymode,
        .config_channel         = rt73usb_config_channel,
@@ -1881,14 +1904,11 @@ static struct usb_driver rt73usb_driver = {
 
 static int __init rt73usb_init(void)
 {
-       printk(KERN_INFO "Loading module: %s - %s by %s.\n",
-               DRV_NAME, DRV_VERSION, DRV_PROJECT);
        return usb_register(&rt73usb_driver);
 }
 
 static void __exit rt73usb_exit(void)
 {
-       printk(KERN_INFO "Unloading module: %s.\n", DRV_NAME);
        usb_deregister(&rt73usb_driver);
 }
 
index 7796656..159240f 100644 (file)
 #define RF2527                         0x0004
 
 /*
- * Max RSSI value, required for RSSI <-> dBm conversion.
+ * Signal information.
  */
-#define MAX_RX_SSI                     120
+#define MAX_RX_SSI                     -1
 #define MAX_RX_NOISE                   -110
+#define DEFAULT_RSSI_OFFSET            120
 
 /*
  * Register layout information.
@@ -748,6 +749,20 @@ struct hw_pairwise_ta_entry {
 #define EEPROM_TXPOWER_A_1             FIELD16(0x00ff)
 #define EEPROM_TXPOWER_A_2             FIELD16(0xff00)
 
+/*
+ * EEPROM RSSI offset 802.11BG
+ */
+#define EEPROM_RSSI_OFFSET_BG          0x004d
+#define EEPROM_RSSI_OFFSET_BG_1                FIELD16(0x00ff)
+#define EEPROM_RSSI_OFFSET_BG_2                FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI offset 802.11A
+ */
+#define EEPROM_RSSI_OFFSET_A           0x004e
+#define EEPROM_RSSI_OFFSET_A_1         FIELD16(0x00ff)
+#define EEPROM_RSSI_OFFSET_A_2         FIELD16(0xff00)
+
 /*
  * BBP content.
  * The wordsize of the BBP is 8 bits.
@@ -886,7 +901,8 @@ struct hw_pairwise_ta_entry {
  * RSSI: RSSI reported by BBP.
  */
 #define RXD_W1_SIGNAL                  FIELD32(0x000000ff)
-#define RXD_W1_RSSI                    FIELD32(0x0000ff00)
+#define RXD_W1_RSSI_AGC                        FIELD32(0x00001f00)
+#define RXD_W1_RSSI_LNA                        FIELD32(0x00006000)
 #define RXD_W1_FRAME_OFFSET            FIELD32(0x7f000000)
 
 /*
@@ -939,9 +955,4 @@ struct hw_pairwise_ta_entry {
        (__txpower));                                   \
 })
 
-/*
- * Interrupt functions.
- */
-static void rt73usb_interrupt_rxdone(struct urb *urb);
-
 #endif /* RT73USB_H */