Browse Source

Fix rt2x00 compilation and upgrade to the current mainline version (2.6.24)

SVN-Revision: 10573
Florian Fainelli 18 years ago
parent
commit
fef15a956c

+ 2 - 1
package/rt2x00/Makefile

@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
 include $(INCLUDE_DIR)/kernel.mk
 
 PKG_NAME:=rt2x00
-PKG_VERSION:=cvs-20070712
+PKG_VERSION:=$(KERNEL_VERSION)
 
 include $(INCLUDE_DIR)/package.mk
 
@@ -109,6 +109,7 @@ PKG_EXTRA_KCONFIG:= \
 	CONFIG_MAC80211=y \
 	CONFIG_RT2X00=y \
 	CONFIG_RT2X00_DEBUG=y \
+	CONFIG_RT2X00_LIB_FIRMWARE=y \
 
 ifneq ($(CONFIG_PACKAGE_kmod-rt2x00-pci),)
   PKG_EXTRA_KCONFIG+= CONFIG_RT2X00PCI=y

+ 6 - 6
package/rt2x00/src/Makefile

@@ -62,7 +62,7 @@ ifeq ($(CONFIG_RT2400PCI),y)
 	obj-m += rt2400pci.o
 ifeq ($(CONFIG_RT2400PCI_RFKILL),y)
 	rt2x00lib-objs += rt2x00rfkill.o
-	CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
+	EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
 endif
 endif
 
@@ -70,7 +70,7 @@ ifeq ($(CONFIG_RT2500PCI),y)
 	obj-m += rt2500pci.o
 ifeq ($(CONFIG_RT2500PCI_RFKILL),y)
 	rt2x00lib-objs += rt2x00rfkill.o
-	CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
+	EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
 endif
 endif
 
@@ -79,17 +79,17 @@ ifeq ($(CONFIG_RT2500USB),y)
 endif
 
 ifeq ($(CONFIG_RT61PCI),y)
-	CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
+	EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
 	rt2x00lib-objs += rt2x00firmware.o
 	obj-m += rt61pci.o
 ifeq ($(CONFIG_RT61PCI_RFKILL),y)
 	rt2x00lib-objs += rt2x00rfkill.o
-	CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
+	EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_RFKILL
 endif
 endif
 
 ifeq ($(CONFIG_RT73USB),y)
-	CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
+	EXTRA_CFLAGS += -DCONFIG_RT2X00_LIB_FIRMWARE
 	rt2x00lib-objs += rt2x00firmware.o
 	obj-m += rt73usb.o
 endif
@@ -97,7 +97,7 @@ endif
 endif
 
 MAKEFLAGS += --no-print-directory
-CFLAGS := -include $(SUBDIRS)/rt2x00_compat.h $(CFLAGS)
+EXTRA_CFLAGS := -include $(SUBDIRS)/rt2x00_compat.h $(CFLAGS)
 
 all: default
 

File diff suppressed because it is too large
+ 267 - 334
package/rt2x00/src/rt2400pci.c


+ 27 - 18
package/rt2x00/src/rt2400pci.h

@@ -35,9 +35,10 @@
 
 /*
  * Signal information.
+ * Defaul offset is required for RSSI <-> dBm conversion.
  */
+#define MAX_SIGNAL			100
 #define MAX_RX_SSI			-1
-#define MAX_RX_NOISE			-110
 #define DEFAULT_RSSI_OFFSET		100
 
 /*
@@ -48,6 +49,7 @@
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x0100
 #define BBP_SIZE			0x0020
+#define RF_SIZE				0x0010
 
 /*
  * Control/Status Registers(CSR).
@@ -544,7 +546,6 @@
  */
 #define MACCSR0				0x00e0
 
-
 /*
  * MACCSR1: MAC configuration register 1.
  * KICK_RX: Kick one-shot rx in one-shot rx mode.
@@ -716,10 +717,33 @@
 #define ARCSR5_SERVICE			FIELD32(0x0000ff00)
 #define ARCSR5_LENGTH			FIELD32(0xffff0000)
 
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * R1: TX antenna control
+ */
+#define BBP_R1_TX_ANTENNA		FIELD8(0x03)
+
+/*
+ * R4: RX antenna control
+ */
+#define BBP_R4_RX_ANTENNA		FIELD8(0x06)
+
 /*
  * RF registers
  */
+
+/*
+ * RF 1
+ */
 #define RF1_TUNER			FIELD32(0x00020000)
+
+/*
+ * RF 3
+ */
 #define RF3_TUNER			FIELD32(0x00000100)
 #define RF3_TXPOWER			FIELD32(0x00003e00)
 
@@ -776,21 +800,6 @@
 #define EEPROM_TXPOWER_1		FIELD16(0x00ff)
 #define EEPROM_TXPOWER_2		FIELD16(0xff00)
 
-/*
- * BBP content.
- * The wordsize of the BBP is 8 bits.
- */
-
-/*
- * BBP_R1: TX antenna control
- */
-#define BBP_R1_TX_ANTENNA		FIELD8(0x03)
-
-/*
- * BBP_R4: RX antenna control
- */
-#define BBP_R4_RX_ANTENNA		FIELD8(0x06)
-
 /*
  * DMA descriptor defines.
  */
@@ -867,7 +876,7 @@
 #define RXD_W0_MULTICAST		FIELD32(0x00000004)
 #define RXD_W0_BROADCAST		FIELD32(0x00000008)
 #define RXD_W0_MY_BSS			FIELD32(0x00000010)
-#define RXD_W0_CRC			FIELD32(0x00000020)
+#define RXD_W0_CRC_ERROR		FIELD32(0x00000020)
 #define RXD_W0_PHYSICAL_ERROR		FIELD32(0x00000080)
 #define RXD_W0_DATABYTE_COUNT		FIELD32(0xffff0000)
 

File diff suppressed because it is too large
+ 295 - 368
package/rt2x00/src/rt2500pci.c


+ 63 - 35
package/rt2x00/src/rt2500pci.h

@@ -46,9 +46,10 @@
 
 /*
  * Signal information.
+ * Defaul offset is required for RSSI <-> dBm conversion.
  */
+#define MAX_SIGNAL			100
 #define MAX_RX_SSI			-1
-#define MAX_RX_NOISE			-110
 #define DEFAULT_RSSI_OFFSET		121
 
 /*
@@ -59,6 +60,7 @@
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x0200
 #define BBP_SIZE			0x0040
+#define RF_SIZE				0x0014
 
 /*
  * Control/Status Registers(CSR).
@@ -438,16 +440,16 @@
 
 /*
  * TXCSR8: CCK Tx BBP register.
- * CCK_SIGNAL: BBP rate field address for CCK.
- * CCK_SERVICE: BBP service field address for CCK.
- * CCK_LENGTH_LOW: BBP length low byte address for CCK.
- * CCK_LENGTH_HIGH: BBP length high byte address for CCK.
  */
 #define TXCSR8				0x0098
-#define TXCSR8_CCK_SIGNAL		FIELD32(0x000000ff)
-#define TXCSR8_CCK_SERVICE		FIELD32(0x0000ff00)
-#define TXCSR8_CCK_LENGTH_LOW		FIELD32(0x00ff0000)
-#define TXCSR8_CCK_LENGTH_HIGH		FIELD32(0xff000000)
+#define TXCSR8_BBP_ID0			FIELD32(0x0000007f)
+#define TXCSR8_BBP_ID0_VALID		FIELD32(0x00000080)
+#define TXCSR8_BBP_ID1			FIELD32(0x00007f00)
+#define TXCSR8_BBP_ID1_VALID		FIELD32(0x00008000)
+#define TXCSR8_BBP_ID2			FIELD32(0x007f0000)
+#define TXCSR8_BBP_ID2_VALID		FIELD32(0x00800000)
+#define TXCSR8_BBP_ID3			FIELD32(0x7f000000)
+#define TXCSR8_BBP_ID3_VALID		FIELD32(0x80000000)
 
 /*
  * TXCSR9: OFDM TX BBP registers
@@ -862,14 +864,32 @@
 #define ARCSR5_LENGTH			FIELD32(0xffff0000)
 
 /*
- * ACK/CTS payload consumed time registers.
  * ARTCSR0: CCK ACK/CTS payload consumed time for 1/2/5.5/11 mbps.
- * ARTCSR1: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
- * ARTCSR2: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
  */
 #define ARTCSR0				0x014c
+#define ARTCSR0_ACK_CTS_11MBS		FIELD32(0x000000ff)
+#define ARTCSR0_ACK_CTS_5_5MBS		FIELD32(0x0000ff00)
+#define ARTCSR0_ACK_CTS_2MBS		FIELD32(0x00ff0000)
+#define ARTCSR0_ACK_CTS_1MBS		FIELD32(0xff000000)
+
+
+/*
+ * ARTCSR1: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
+ */
 #define ARTCSR1				0x0150
+#define ARTCSR1_ACK_CTS_6MBS		FIELD32(0x000000ff)
+#define ARTCSR1_ACK_CTS_9MBS		FIELD32(0x0000ff00)
+#define ARTCSR1_ACK_CTS_12MBS		FIELD32(0x00ff0000)
+#define ARTCSR1_ACK_CTS_18MBS		FIELD32(0xff000000)
+
+/*
+ * ARTCSR2: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
+ */
 #define ARTCSR2				0x0154
+#define ARTCSR2_ACK_CTS_24MBS		FIELD32(0x000000ff)
+#define ARTCSR2_ACK_CTS_36MBS		FIELD32(0x0000ff00)
+#define ARTCSR2_ACK_CTS_48MBS		FIELD32(0x00ff0000)
+#define ARTCSR2_ACK_CTS_54MBS		FIELD32(0xff000000)
 
 /*
  * SECCSR1_RT2509: WEP control register.
@@ -945,10 +965,40 @@
 #define UART2CSR3			0x0198
 #define UART2CSR4			0x019c
 
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * R2: TX antenna control
+ */
+#define BBP_R2_TX_ANTENNA		FIELD8(0x03)
+#define BBP_R2_TX_IQ_FLIP		FIELD8(0x04)
+
+/*
+ * R14: RX antenna control
+ */
+#define BBP_R14_RX_ANTENNA		FIELD8(0x03)
+#define BBP_R14_RX_IQ_FLIP		FIELD8(0x04)
+
+/*
+ * BBP_R70
+ */
+#define BBP_R70_JAPAN_FILTER		FIELD8(0x08)
+
 /*
  * RF registers
  */
+
+/*
+ * RF 1
+ */
 #define RF1_TUNER			FIELD32(0x00020000)
+
+/*
+ * RF 3
+ */
 #define RF3_TUNER			FIELD32(0x00000100)
 #define RF3_TXPOWER			FIELD32(0x00003e00)
 
@@ -1029,28 +1079,6 @@
 #define EEPROM_CALIBRATE_OFFSET		0x3e
 #define EEPROM_CALIBRATE_OFFSET_RSSI	FIELD16(0x00ff)
 
-/*
- * BBP content.
- * The wordsize of the BBP is 8 bits.
- */
-
-/*
- * BBP_R2: TX antenna control
- */
-#define BBP_R2_TX_ANTENNA		FIELD8(0x03)
-#define BBP_R2_TX_IQ_FLIP		FIELD8(0x04)
-
-/*
- * BBP_R14: RX antenna control
- */
-#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.
  */
@@ -1135,7 +1163,7 @@
 #define RXD_W0_MULTICAST		FIELD32(0x00000004)
 #define RXD_W0_BROADCAST		FIELD32(0x00000008)
 #define RXD_W0_MY_BSS			FIELD32(0x00000010)
-#define RXD_W0_CRC			FIELD32(0x00000020)
+#define RXD_W0_CRC_ERROR		FIELD32(0x00000020)
 #define RXD_W0_OFDM			FIELD32(0x00000040)
 #define RXD_W0_PHYSICAL_ERROR		FIELD32(0x00000080)
 #define RXD_W0_CIPHER_OWNER		FIELD32(0x00000100)

File diff suppressed because it is too large
+ 305 - 347
package/rt2x00/src/rt2500usb.c


+ 90 - 32
package/rt2x00/src/rt2500usb.h

@@ -46,9 +46,10 @@
 
 /*
  * Signal information.
+ * Defaul offset is required for RSSI <-> dBm conversion.
  */
+#define MAX_SIGNAL			100
 #define MAX_RX_SSI			-1
-#define MAX_RX_NOISE			-110
 #define DEFAULT_RSSI_OFFSET		120
 
 /*
@@ -59,6 +60,7 @@
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x006a
 #define BBP_SIZE			0x0060
+#define RF_SIZE				0x0014
 
 /*
  * Control/Status Registers(CSR).
@@ -72,8 +74,14 @@
 
 /*
  * MAC_CSR1: System control.
+ * SOFT_RESET: Software reset, 1: reset, 0: normal.
+ * BBP_RESET: Hardware reset, 1: reset, 0, release.
+ * HOST_READY: Host ready after initialization.
  */
 #define MAC_CSR1			0x0402
+#define MAC_CSR1_SOFT_RESET		FIELD16(0x00000001)
+#define MAC_CSR1_BBP_RESET		FIELD16(0x00000002)
+#define MAC_CSR1_HOST_READY		FIELD16(0x00000004)
 
 /*
  * MAC_CSR2: STA MAC register 0.
@@ -246,8 +254,8 @@
 #define TXRX_CSR2_DROP_NOT_TO_ME	FIELD16(0x0010)
 #define TXRX_CSR2_DROP_TODS		FIELD16(0x0020)
 #define TXRX_CSR2_DROP_VERSION_ERROR	FIELD16(0x0040)
-#define TXRX_CSR2_DROP_MCAST		FIELD16(0x0200)
-#define TXRX_CSR2_DROP_BCAST		FIELD16(0x0400)
+#define TXRX_CSR2_DROP_MULTICAST	FIELD16(0x0200)
+#define TXRX_CSR2_DROP_BROADCAST	FIELD16(0x0400)
 
 /*
  * RX BBP ID registers
@@ -258,16 +266,40 @@
 #define TXRX_CSR4			0x0448
 
 /*
- * TX BBP ID registers
  * TXRX_CSR5: CCK TX BBP ID0.
- * TXRX_CSR5: CCK TX BBP ID1.
- * TXRX_CSR5: OFDM TX BBP ID0.
- * TXRX_CSR5: OFDM TX BBP ID1.
  */
 #define TXRX_CSR5			0x044a
+#define TXRX_CSR5_BBP_ID0		FIELD16(0x007f)
+#define TXRX_CSR5_BBP_ID0_VALID		FIELD16(0x0080)
+#define TXRX_CSR5_BBP_ID1		FIELD16(0x7f00)
+#define TXRX_CSR5_BBP_ID1_VALID		FIELD16(0x8000)
+
+/*
+ * TXRX_CSR6: CCK TX BBP ID1.
+ */
 #define TXRX_CSR6			0x044c
+#define TXRX_CSR6_BBP_ID0		FIELD16(0x007f)
+#define TXRX_CSR6_BBP_ID0_VALID		FIELD16(0x0080)
+#define TXRX_CSR6_BBP_ID1		FIELD16(0x7f00)
+#define TXRX_CSR6_BBP_ID1_VALID		FIELD16(0x8000)
+
+/*
+ * TXRX_CSR7: OFDM TX BBP ID0.
+ */
 #define TXRX_CSR7			0x044e
+#define TXRX_CSR7_BBP_ID0		FIELD16(0x007f)
+#define TXRX_CSR7_BBP_ID0_VALID		FIELD16(0x0080)
+#define TXRX_CSR7_BBP_ID1		FIELD16(0x7f00)
+#define TXRX_CSR7_BBP_ID1_VALID		FIELD16(0x8000)
+
+/*
+ * TXRX_CSR5: OFDM TX BBP ID1.
+ */
 #define TXRX_CSR8			0x0450
+#define TXRX_CSR8_BBP_ID0		FIELD16(0x007f)
+#define TXRX_CSR8_BBP_ID0_VALID		FIELD16(0x0080)
+#define TXRX_CSR8_BBP_ID1		FIELD16(0x7f00)
+#define TXRX_CSR8_BBP_ID1_VALID		FIELD16(0x8000)
 
 /*
  * TXRX_CSR9: TX ACK time-out.
@@ -408,6 +440,7 @@
  * PHY_CSR4: Interface configuration.
  */
 #define PHY_CSR4			0x04c8
+#define PHY_CSR4_LOW_RF_LE		FIELD16(0x0001)
 
 /*
  * BBP pre-TX registers.
@@ -473,28 +506,70 @@
 #define STA_CSR0_FCS_ERROR		FIELD16(0xffff)
 
 /*
- * Statistic Register.
- * STA_CSR1: PLCP error.
- * STA_CSR2: LONG error.
- * STA_CSR3: CCA false alarm.
- * STA_CSR4: RX FIFO overflow.
- * STA_CSR5: Beacon sent counter.
+ * STA_CSR1: PLCP error count.
  */
 #define STA_CSR1			0x04e2
+
+/*
+ * STA_CSR2: LONG error count.
+ */
 #define STA_CSR2			0x04e4
+
+/*
+ * STA_CSR3: CCA false alarm.
+ * FALSE_CCA_ERROR: False CCA error count, cleared when read.
+ */
 #define STA_CSR3			0x04e6
+#define STA_CSR3_FALSE_CCA_ERROR	FIELD16(0xffff)
+
+/*
+ * STA_CSR4: RX FIFO overflow.
+ */
 #define STA_CSR4			0x04e8
+
+/*
+ * STA_CSR5: Beacon sent counter.
+ */
 #define STA_CSR5			0x04ea
+
+/*
+ *  Statistics registers
+ */
 #define STA_CSR6			0x04ec
 #define STA_CSR7			0x04ee
 #define STA_CSR8			0x04f0
 #define STA_CSR9			0x04f2
 #define STA_CSR10			0x04f4
 
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * R2: TX antenna control
+ */
+#define BBP_R2_TX_ANTENNA		FIELD8(0x03)
+#define BBP_R2_TX_IQ_FLIP		FIELD8(0x04)
+
+/*
+ * R14: RX antenna control
+ */
+#define BBP_R14_RX_ANTENNA		FIELD8(0x03)
+#define BBP_R14_RX_IQ_FLIP		FIELD8(0x04)
+
 /*
  * RF registers.
  */
+
+/*
+ * RF 1
+ */
 #define RF1_TUNER			FIELD32(0x00020000)
+
+/*
+ * RF 3
+ */
 #define RF3_TUNER			FIELD32(0x00000100)
 #define RF3_TXPOWER			FIELD32(0x00003e00)
 
@@ -614,23 +689,6 @@
 #define EEPROM_CALIBRATE_OFFSET		0x0036
 #define EEPROM_CALIBRATE_OFFSET_RSSI	FIELD16(0x00ff)
 
-/*
- * BBP content.
- * The wordsize of the BBP is 8 bits.
- */
-
-/*
- * BBP_R2: TX antenna control
- */
-#define BBP_R2_TX_ANTENNA		FIELD8(0x03)
-#define BBP_R2_TX_IQ_FLIP		FIELD8(0x04)
-
-/*
- * BBP_R14: RX antenna control
- */
-#define BBP_R14_RX_ANTENNA		FIELD8(0x03)
-#define BBP_R14_RX_IQ_FLIP		FIELD8(0x04)
-
 /*
  * DMA descriptor defines.
  */
@@ -693,11 +751,11 @@
 #define RXD_W0_MULTICAST		FIELD32(0x00000004)
 #define RXD_W0_BROADCAST		FIELD32(0x00000008)
 #define RXD_W0_MY_BSS			FIELD32(0x00000010)
-#define RXD_W0_CRC			FIELD32(0x00000020)
+#define RXD_W0_CRC_ERROR		FIELD32(0x00000020)
 #define RXD_W0_OFDM			FIELD32(0x00000040)
 #define RXD_W0_PHYSICAL_ERROR		FIELD32(0x00000080)
 #define RXD_W0_CIPHER			FIELD32(0x00000100)
-#define RXD_W0_CI_ERROR			FIELD32(0x00000200)
+#define RXD_W0_CIPHER_ERROR		FIELD32(0x00000200)
 #define RXD_W0_DATABYTE_COUNT		FIELD32(0x0fff0000)
 
 /*

File diff suppressed because it is too large
+ 265 - 529
package/rt2x00/src/rt2x00.h


+ 205 - 0
package/rt2x00/src/rt2x00config.c

@@ -0,0 +1,205 @@
+/*
+	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.
+ */
+
+/*
+	Module: rt2x00lib
+	Abstract: rt2x00 generic configuration routines.
+ */
+
+/*
+ * Set enviroment defines for rt2x00.h
+ */
+#define DRV_NAME "rt2x00lib"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+#include "rt2x00lib.h"
+
+
+/*
+ * The MAC and BSSID addressess are simple array of bytes,
+ * these arrays are little endian, so when sending the addressess
+ * to the drivers, copy the it into a endian-signed variable.
+ *
+ * Note that all devices (except rt2500usb) have 32 bits
+ * register word sizes. This means that whatever variable we
+ * pass _must_ be a multiple of 32 bits. Otherwise the device
+ * might not accept what we are sending to it.
+ * This will also make it easier for the driver to write
+ * the data to the device.
+ *
+ * Also note that when NULL is passed as address the
+ * we will send 00:00:00:00:00 to the device to clear the address.
+ * This will prevent the device being confused when it wants
+ * to ACK frames or consideres itself associated.
+ */
+void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac)
+{
+	__le32 reg[2];
+
+	memset(&reg, 0, sizeof(reg));
+	if (mac)
+		memcpy(&reg, mac, ETH_ALEN);
+
+	rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, &reg[0]);
+}
+
+void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid)
+{
+	__le32 reg[2];
+
+	memset(&reg, 0, sizeof(reg));
+	if (bssid)
+		memcpy(&reg, bssid, ETH_ALEN);
+
+	rt2x00dev->ops->lib->config_bssid(rt2x00dev, &reg[0]);
+}
+
+void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type)
+{
+	int tsf_sync;
+
+	switch (type) {
+	case IEEE80211_IF_TYPE_IBSS:
+	case IEEE80211_IF_TYPE_AP:
+		tsf_sync = TSF_SYNC_BEACON;
+		break;
+	case IEEE80211_IF_TYPE_STA:
+		tsf_sync = TSF_SYNC_INFRA;
+		break;
+	default:
+		tsf_sync = TSF_SYNC_NONE;
+		break;
+	}
+
+	rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync);
+}
+
+void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
+		      struct ieee80211_conf *conf, const int force_config)
+{
+	struct rt2x00lib_conf libconf;
+	struct ieee80211_hw_mode *mode;
+	struct ieee80211_rate *rate;
+	int flags = 0;
+	int short_slot_time;
+
+	/*
+	 * In some situations we want to force all configurations
+	 * to be reloaded (When resuming for instance).
+	 */
+	if (force_config) {
+		flags = CONFIG_UPDATE_ALL;
+		goto config;
+	}
+
+	/*
+	 * Check which configuration options have been
+	 * updated and should be send to the device.
+	 */
+	if (rt2x00dev->rx_status.phymode != conf->phymode)
+		flags |= CONFIG_UPDATE_PHYMODE;
+	if (rt2x00dev->rx_status.channel != conf->channel)
+		flags |= CONFIG_UPDATE_CHANNEL;
+	if (rt2x00dev->tx_power != conf->power_level)
+		flags |= CONFIG_UPDATE_TXPOWER;
+	if (rt2x00dev->rx_status.antenna == conf->antenna_sel_rx)
+		flags |= CONFIG_UPDATE_ANTENNA;
+
+	/*
+	 * The following configuration options are never
+	 * stored anywhere and will always be updated.
+	 */
+	flags |= CONFIG_UPDATE_SLOT_TIME;
+	flags |= CONFIG_UPDATE_BEACON_INT;
+
+	/*
+	 * We have determined what options should be updated,
+	 * now precalculate device configuration values depending
+	 * on what configuration options need to be updated.
+	 */
+config:
+	memset(&libconf, 0, sizeof(libconf));
+
+	if (flags & CONFIG_UPDATE_PHYMODE) {
+		switch (conf->phymode) {
+		case MODE_IEEE80211A:
+			libconf.phymode = HWMODE_A;
+			break;
+		case MODE_IEEE80211B:
+			libconf.phymode = HWMODE_B;
+			break;
+		case MODE_IEEE80211G:
+			libconf.phymode = HWMODE_G;
+			break;
+		default:
+			ERROR(rt2x00dev,
+			      "Attempt to configure unsupported mode (%d)"
+			      "Defaulting to 802.11b", conf->phymode);
+			libconf.phymode = HWMODE_B;
+		}
+
+		mode = &rt2x00dev->hwmodes[libconf.phymode];
+		rate = &mode->rates[mode->num_rates - 1];
+
+		libconf.basic_rates =
+		    DEVICE_GET_RATE_FIELD(rate->val, RATEMASK) & DEV_BASIC_RATEMASK;
+	}
+
+	if (flags & CONFIG_UPDATE_CHANNEL) {
+		memcpy(&libconf.rf,
+		       &rt2x00dev->spec.channels[conf->channel_val],
+		       sizeof(libconf.rf));
+	}
+
+	if (flags & CONFIG_UPDATE_SLOT_TIME) {
+		short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
+
+		libconf.slot_time =
+		    short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME;
+		libconf.sifs = SIFS;
+		libconf.pifs = short_slot_time ? SHORT_PIFS : PIFS;
+		libconf.difs = short_slot_time ? SHORT_DIFS : DIFS;
+		libconf.eifs = EIFS;
+	}
+
+	libconf.conf = conf;
+
+	/*
+	 * Start configuration.
+	 */
+	rt2x00dev->ops->lib->config(rt2x00dev, flags, &libconf);
+
+	/*
+	 * Some configuration changes affect the link quality
+	 * which means we need to reset the link tuner.
+	 */
+	if (flags & (CONFIG_UPDATE_CHANNEL | CONFIG_UPDATE_ANTENNA))
+		rt2x00lib_reset_link_tuner(rt2x00dev);
+
+	rt2x00dev->curr_hwmode = libconf.phymode;
+	rt2x00dev->rx_status.phymode = conf->phymode;
+	rt2x00dev->rx_status.freq = conf->freq;
+	rt2x00dev->rx_status.channel = conf->channel;
+	rt2x00dev->tx_power = conf->power_level;
+	rt2x00dev->rx_status.antenna = conf->antenna_sel_rx;
+}

+ 165 - 158
package/rt2x00/src/rt2x00debug.c

@@ -21,22 +21,22 @@
 /*
 	Module: rt2x00lib
 	Abstract: rt2x00 debugfs specific routines.
-	Supported chipsets: RT2460, RT2560, RT2570,
-	rt2561, rt2561s, rt2661, rt2571W & rt2671.
  */
 
-#include <linux/debugfs.h>
+/*
+ * Set enviroment defines for rt2x00.h
+ */
+#define DRV_NAME "rt2x00lib"
 
-#include <asm/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
 
 #include "rt2x00.h"
-#include "rt2x00debug.h"
+#include "rt2x00lib.h"
 
-#define PRINT_REG8_STR		( "0x%.2x\n" )
-#define PRINT_REG16_STR		( "0x%.4x\n" )
-#define PRINT_REG32_STR		( "0x%.8x\n" )
-#define PRINT_REG_LEN_MAX	( 16 )
-#define PRINT_LINE_LEN_MAX	( 32 )
+#define PRINT_LINE_LEN_MAX 32
 
 struct rt2x00debug_intf {
 	/*
@@ -57,19 +57,24 @@ struct rt2x00debug_intf {
 	 * - driver folder
 	 * - driver file
 	 * - chipset file
+	 * - device flags file
 	 * - register offset/value files
 	 * - eeprom offset/value files
 	 * - bbp offset/value files
+	 * - rf offset/value files
 	 */
 	struct dentry *driver_folder;
 	struct dentry *driver_entry;
 	struct dentry *chipset_entry;
+	struct dentry *dev_flags;
 	struct dentry *csr_off_entry;
 	struct dentry *csr_val_entry;
 	struct dentry *eeprom_off_entry;
 	struct dentry *eeprom_val_entry;
 	struct dentry *bbp_off_entry;
 	struct dentry *bbp_val_entry;
+	struct dentry *rf_off_entry;
+	struct dentry *rf_val_entry;
 
 	/*
 	 * Driver and chipset files will use a data buffer
@@ -85,6 +90,7 @@ struct rt2x00debug_intf {
 	unsigned int offset_csr;
 	unsigned int offset_eeprom;
 	unsigned int offset_bbp;
+	unsigned int offset_rf;
 };
 
 static int rt2x00debug_file_open(struct inode *inode, struct file *file)
@@ -108,127 +114,120 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file)
 	return 0;
 }
 
-static ssize_t rt2x00debug_file_read(void *device, char __user *buf,
-	loff_t *offset, unsigned int word, const struct rt2x00debug_reg *reg)
-{
-	unsigned long value;
-	unsigned int size;
-	char *line;
-
-	if (*offset)
-		return 0;
-
-	line = kzalloc(PRINT_REG_LEN_MAX, GFP_KERNEL);
-	if (!line)
-		return -ENOMEM;
-
-	reg->read(device, word, &value);
-
-	if (reg->word_size == sizeof(u8))
-		size = sprintf(line, PRINT_REG8_STR, (u8)value);
-	else if (reg->word_size == sizeof(u16))
-		size = sprintf(line, PRINT_REG16_STR, (u16)value);
-	else
-		size = sprintf(line, PRINT_REG32_STR, (u32)value);
-
-	if (copy_to_user(buf, line, size))
-		goto exit;
-
-	kfree(line);
-
-	*offset += size;
-	return size;
-
-exit:
-	kfree(line);
+#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type)	\
+static ssize_t rt2x00debug_read_##__name(struct file *file,	\
+					 char __user *buf,	\
+					 size_t length,		\
+					 loff_t *offset)	\
+{								\
+	struct rt2x00debug_intf *intf =	file->private_data;	\
+	const struct rt2x00debug *debug = intf->debug;		\
+	char line[16];						\
+	size_t size;						\
+	__type value;						\
+								\
+	if (*offset)						\
+		return 0;					\
+								\
+	if (intf->offset_##__name >= debug->__name.word_count)	\
+		return -EINVAL;					\
+								\
+	debug->__name.read(intf->rt2x00dev,			\
+			   intf->offset_##__name, &value);	\
+								\
+	size = sprintf(line, __format, value);			\
+								\
+	if (copy_to_user(buf, line, size))			\
+		return -EFAULT;					\
+								\
+	*offset += size;					\
+	return size;						\
+}
 
-	return -EFAULT;
+#define RT2X00DEBUGFS_OPS_WRITE(__name, __type)			\
+static ssize_t rt2x00debug_write_##__name(struct file *file,	\
+					  const char __user *buf,\
+					  size_t length,	\
+					  loff_t *offset)	\
+{								\
+	struct rt2x00debug_intf *intf =	file->private_data;	\
+	const struct rt2x00debug *debug = intf->debug;		\
+	char line[16];						\
+	size_t size;						\
+	__type value;						\
+								\
+	if (*offset)						\
+		return 0;					\
+								\
+	if (!capable(CAP_NET_ADMIN))				\
+		return -EPERM;					\
+								\
+	if (intf->offset_##__name >= debug->__name.word_count)	\
+		return -EINVAL;					\
+								\
+	if (copy_from_user(line, buf, length))			\
+		return -EFAULT;					\
+								\
+	size = strlen(line);					\
+	value = simple_strtoul(line, NULL, 0);			\
+								\
+	debug->__name.write(intf->rt2x00dev,			\
+			    intf->offset_##__name, value);	\
+								\
+	*offset += size;					\
+	return size;						\
 }
 
-static ssize_t rt2x00debug_file_write(void *device, const char __user *buf,
-	loff_t *offset, unsigned int word, unsigned int length,
-	const struct rt2x00debug_reg *reg)
-{
-	unsigned long value;
-	int size;
-	char *line;
+#define RT2X00DEBUGFS_OPS(__name, __format, __type)		\
+RT2X00DEBUGFS_OPS_READ(__name, __format, __type);		\
+RT2X00DEBUGFS_OPS_WRITE(__name, __type);			\
+								\
+static const struct file_operations rt2x00debug_fop_##__name = {\
+	.owner		= THIS_MODULE,				\
+	.read		= rt2x00debug_read_##__name,		\
+	.write		= rt2x00debug_write_##__name,		\
+	.open		= rt2x00debug_file_open,		\
+	.release	= rt2x00debug_file_release,		\
+};
 
-	line = kzalloc(length, GFP_KERNEL);
-	if (!line)
-		return -ENOMEM;
+RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32);
+RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16);
+RT2X00DEBUGFS_OPS(bbp, "0x%.2x\n", u8);
+RT2X00DEBUGFS_OPS(rf, "0x%.8x\n", u32);
 
-	if (copy_from_user(line, buf, length))
-		goto exit;
+static ssize_t rt2x00debug_read_dev_flags(struct file *file,
+					  char __user *buf,
+					  size_t length,
+					  loff_t *offset)
+{
+	struct rt2x00debug_intf *intf =	file->private_data;
+	char line[16];
+	size_t size;
 
-	size = strlen(line);
-	value = simple_strtoul(line, NULL, 0);
+	if (*offset)
+		return 0;
 
-	reg->write(device, word, &value);
+	size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->flags);
 
-	kfree(line);
+	if (copy_to_user(buf, line, size))
+		return -EFAULT;
 
 	*offset += size;
 	return size;
-
-exit:
-	kfree(line);
-
-	return -EFAULT;
 }
 
-#define RT2X00DEBUGFS_OPS_READ(__name)					\
-	static ssize_t rt2x00debug_read_##__name(struct file *file,	\
-		char __user *buf, size_t length, loff_t *offset)	\
-	{								\
-		struct rt2x00debug_intf *intf =	file->private_data;	\
-		const struct rt2x00debug *debug = intf->debug;		\
-		const struct rt2x00debug_reg *reg = &debug->reg_##__name;\
-									\
-		if (intf->offset_##__name > reg->word_count)		\
-			return -EINVAL;					\
-									\
-		return rt2x00debug_file_read(intf->rt2x00dev, buf,	\
-			offset, intf->offset_##__name, reg);		\
-	}
-
-RT2X00DEBUGFS_OPS_READ(csr);
-RT2X00DEBUGFS_OPS_READ(eeprom);
-RT2X00DEBUGFS_OPS_READ(bbp);
-
-#define RT2X00DEBUGFS_OPS_WRITE(__name)					\
-	static ssize_t rt2x00debug_write_##__name(struct file *file,	\
-		const char __user *buf, size_t length, loff_t *offset)	\
-	{								\
-		struct rt2x00debug_intf *intf =	file->private_data;	\
-		const struct rt2x00debug *debug = intf->debug;		\
-		const struct rt2x00debug_reg *reg = &debug->reg_##__name;\
-									\
-		if (intf->offset_##__name > reg->word_count)		\
-			return -EINVAL;					\
-									\
-		return rt2x00debug_file_write(intf->rt2x00dev, buf,	\
-			offset, intf->offset_##__name, length, reg);	\
-	}
-
-RT2X00DEBUGFS_OPS_WRITE(csr);
-RT2X00DEBUGFS_OPS_WRITE(eeprom);
-RT2X00DEBUGFS_OPS_WRITE(bbp);
-
-#define RT2X00DEBUGFS_OPS(__name)					\
-	static const struct file_operations rt2x00debug_fop_##__name = {\
-		.owner		= THIS_MODULE,				\
-		.read		= rt2x00debug_read_##__name,		\
-		.write		= rt2x00debug_write_##__name,		\
-		.open		= rt2x00debug_file_open,		\
-		.release	= rt2x00debug_file_release,		\
-	};
-
-RT2X00DEBUGFS_OPS(csr);
-RT2X00DEBUGFS_OPS(eeprom);
-RT2X00DEBUGFS_OPS(bbp);
+static const struct file_operations rt2x00debug_fop_dev_flags = {
+	.owner		= THIS_MODULE,
+	.read		= rt2x00debug_read_dev_flags,
+	.open		= rt2x00debug_file_open,
+	.release	= rt2x00debug_file_release,
+};
 
 static struct dentry *rt2x00debug_create_file_driver(const char *name,
-	struct rt2x00debug_intf *intf, struct debugfs_blob_wrapper *blob)
+						     struct rt2x00debug_intf
+						     *intf,
+						     struct debugfs_blob_wrapper
+						     *blob)
 {
 	char *data;
 
@@ -246,20 +245,24 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name,
 }
 
 static struct dentry *rt2x00debug_create_file_chipset(const char *name,
-	struct rt2x00debug_intf *intf, struct debugfs_blob_wrapper *blob)
+						      struct rt2x00debug_intf
+						      *intf,
+						      struct
+						      debugfs_blob_wrapper
+						      *blob)
 {
 	const struct rt2x00debug *debug = intf->debug;
 	char *data;
 
-	data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
+	data = kzalloc(4 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
 	if (!data)
 		return NULL;
 
 	blob->data = data;
-	data += sprintf(data, "csr length: %d\n", debug->reg_csr.word_count);
-	data += sprintf(data, "eeprom length: %d\n",
-		debug->reg_eeprom.word_count);
-	data += sprintf(data, "bbp length: %d\n", debug->reg_bbp.word_count);
+	data += sprintf(data, "csr length: %d\n", debug->csr.word_count);
+	data += sprintf(data, "eeprom length: %d\n", debug->eeprom.word_count);
+	data += sprintf(data, "bbp length: %d\n", debug->bbp.word_count);
+	data += sprintf(data, "rf length: %d\n", debug->rf.word_count);
 	blob->size = strlen(blob->data);
 
 	return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);
@@ -280,53 +283,54 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
 	intf->rt2x00dev = rt2x00dev;
 	rt2x00dev->debugfs_intf = intf;
 
-	intf->driver_folder = debugfs_create_dir(intf->rt2x00dev->ops->name,
-		rt2x00dev->hw->wiphy->debugfsdir);
+	intf->driver_folder =
+	    debugfs_create_dir(intf->rt2x00dev->ops->name,
+			       rt2x00dev->hw->wiphy->debugfsdir);
 	if (IS_ERR(intf->driver_folder))
 		goto exit;
 
-	intf->driver_entry = rt2x00debug_create_file_driver("driver",
-		intf, &intf->driver_blob);
+	intf->driver_entry =
+	    rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
 	if (IS_ERR(intf->driver_entry))
 		goto exit;
 
-	intf->chipset_entry = rt2x00debug_create_file_chipset("chipset",
-		intf, &intf->chipset_blob);
+	intf->chipset_entry =
+	    rt2x00debug_create_file_chipset("chipset",
+					    intf, &intf->chipset_blob);
 	if (IS_ERR(intf->chipset_entry))
 		goto exit;
 
-	intf->csr_off_entry = debugfs_create_u32("csr_offset",
-		S_IRUGO | S_IWUSR, intf->driver_folder, &intf->offset_csr);
-	if (IS_ERR(intf->csr_off_entry))
-		goto exit;
-
-	intf->csr_val_entry = debugfs_create_file("csr_value",
-		S_IRUGO | S_IWUSR, intf->driver_folder, intf,
-		&rt2x00debug_fop_csr);
-	if (IS_ERR(intf->csr_val_entry))
-		goto exit;
-
-	intf->eeprom_off_entry = debugfs_create_u32("eeprom_offset",
-		S_IRUGO | S_IWUSR, intf->driver_folder, &intf->offset_eeprom);
-	if (IS_ERR(intf->eeprom_off_entry))
-		goto exit;
-
-	intf->eeprom_val_entry = debugfs_create_file("eeprom_value",
-		S_IRUGO | S_IWUSR, intf->driver_folder, intf,
-		&rt2x00debug_fop_eeprom);
-	if (IS_ERR(intf->eeprom_val_entry))
+	intf->dev_flags = debugfs_create_file("dev_flags", S_IRUGO,
+					      intf->driver_folder, intf,
+					      &rt2x00debug_fop_dev_flags);
+	if (IS_ERR(intf->dev_flags))
 		goto exit;
 
-	intf->bbp_off_entry = debugfs_create_u32("bbp_offset",
-		S_IRUGO | S_IWUSR, intf->driver_folder, &intf->offset_bbp);
-	if (IS_ERR(intf->bbp_off_entry))
-		goto exit;
-
-	intf->bbp_val_entry = debugfs_create_file("bbp_value",
-		S_IRUGO | S_IWUSR, intf->driver_folder, intf,
-		&rt2x00debug_fop_bbp);
-	if (IS_ERR(intf->bbp_val_entry))
-		goto exit;
+#define RT2X00DEBUGFS_CREATE_ENTRY(__intf, __name)		\
+({								\
+	(__intf)->__name##_off_entry =				\
+	    debugfs_create_u32(__stringify(__name) "_offset",	\
+			       S_IRUGO | S_IWUSR,		\
+			       (__intf)->driver_folder,		\
+			       &(__intf)->offset_##__name);	\
+	if (IS_ERR((__intf)->__name##_off_entry))		\
+		goto exit;					\
+								\
+	(__intf)->__name##_val_entry =				\
+	    debugfs_create_file(__stringify(__name) "_value",	\
+				S_IRUGO | S_IWUSR,		\
+				(__intf)->driver_folder,	\
+				(__intf), &rt2x00debug_fop_##__name);\
+	if (IS_ERR((__intf)->__name##_val_entry))		\
+		goto exit;					\
+})
+
+	RT2X00DEBUGFS_CREATE_ENTRY(intf, csr);
+	RT2X00DEBUGFS_CREATE_ENTRY(intf, eeprom);
+	RT2X00DEBUGFS_CREATE_ENTRY(intf, bbp);
+	RT2X00DEBUGFS_CREATE_ENTRY(intf, rf);
+
+#undef RT2X00DEBUGFS_CREATE_ENTRY
 
 	return;
 
@@ -344,12 +348,15 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
 	if (unlikely(!intf))
 		return;
 
+	debugfs_remove(intf->rf_val_entry);
+	debugfs_remove(intf->rf_off_entry);
 	debugfs_remove(intf->bbp_val_entry);
 	debugfs_remove(intf->bbp_off_entry);
 	debugfs_remove(intf->eeprom_val_entry);
 	debugfs_remove(intf->eeprom_off_entry);
 	debugfs_remove(intf->csr_val_entry);
 	debugfs_remove(intf->csr_off_entry);
+	debugfs_remove(intf->dev_flags);
 	debugfs_remove(intf->chipset_entry);
 	debugfs_remove(intf->driver_entry);
 	debugfs_remove(intf->driver_folder);

+ 16 - 23
package/rt2x00/src/rt2x00debug.h

@@ -21,23 +21,23 @@
 /*
 	Module: rt2x00debug
 	Abstract: Data structures for the rt2x00debug.
-	Supported chipsets: RT2460, RT2560, RT2570,
-	rt2561, rt2561s, rt2661, rt2571W & rt2671.
  */
 
 #ifndef RT2X00DEBUG_H
 #define RT2X00DEBUG_H
 
-typedef void (debug_access_t)(struct rt2x00_dev *rt2x00dev,
-	const unsigned long word, void *data);
+struct rt2x00_dev;
 
-struct rt2x00debug_reg {
-	debug_access_t *read;
-	debug_access_t *write;
-
-	unsigned int word_size;
-	unsigned int word_count;
-};
+#define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type)		\
+struct reg##__name {						\
+	void (*read)(const struct rt2x00_dev *rt2x00dev,	\
+		     const unsigned int word, __type *data);	\
+	void (*write)(const struct rt2x00_dev *rt2x00dev,	\
+		      const unsigned int word, __type data);	\
+								\
+	unsigned int word_size;					\
+	unsigned int word_count;				\
+} __name
 
 struct rt2x00debug {
 	/*
@@ -46,19 +46,12 @@ struct rt2x00debug {
 	struct module *owner;
 
 	/*
-	 * Register access information.
+	 * Register access entries.
 	 */
-	struct rt2x00debug_reg reg_csr;
-	struct rt2x00debug_reg reg_eeprom;
-	struct rt2x00debug_reg reg_bbp;
+	RT2X00DEBUGFS_REGISTER_ENTRY(csr, u32);
+	RT2X00DEBUGFS_REGISTER_ENTRY(eeprom, u16);
+	RT2X00DEBUGFS_REGISTER_ENTRY(bbp, u8);
+	RT2X00DEBUGFS_REGISTER_ENTRY(rf, u32);
 };
 
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
-void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
-#else /* CONFIG_RT2X00_LIB_DEBUGFS */
-static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev){}
-static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev){}
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
 #endif /* RT2X00DEBUG_H */

File diff suppressed because it is too large
+ 541 - 196
package/rt2x00/src/rt2x00dev.c


+ 53 - 60
package/rt2x00/src/rt2x00firmware.c

@@ -20,8 +20,7 @@
 
 /*
 	Module: rt2x00lib
-	Abstract: rt2x00 firmware loading specific routines.
-	Supported chipsets: rt2561, rt2561s, rt2661, rt2571W & rt2671.
+	Abstract: rt2x00 firmware loading routines.
  */
 
 /*
@@ -29,24 +28,44 @@
  */
 #define DRV_NAME "rt2x00lib"
 
-#include <linux/delay.h>
 #include <linux/crc-itu-t.h>
-#include <linux/firmware.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 
 #include "rt2x00.h"
 #include "rt2x00lib.h"
-#include "rt2x00firmware.h"
 
-static void rt2x00lib_load_firmware_continued(const struct firmware *fw,
-	void *context)
+static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)
 {
-	struct rt2x00_dev *rt2x00dev = context;
+	struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
+	const struct firmware *fw;
+	char *fw_name;
+	int retval;
 	u16 crc;
 	u16 tmp;
 
+	/*
+	 * Read correct firmware from harddisk.
+	 */
+	fw_name = rt2x00dev->ops->lib->get_firmware_name(rt2x00dev);
+	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);
+
+	retval = request_firmware(&fw, fw_name, device);
+	if (retval) {
+		ERROR(rt2x00dev, "Failed to request Firmware.\n");
+		return retval;
+	}
+
 	if (!fw || !fw->size || !fw->data) {
 		ERROR(rt2x00dev, "Failed to read Firmware.\n");
-		goto exit_failed;
+		return -ENOENT;
 	}
 
 	/*
@@ -57,75 +76,49 @@ static void rt2x00lib_load_firmware_continued(const struct firmware *fw,
 	 */
 	tmp = 0;
 	crc = crc_itu_t(0, fw->data, fw->size - 2);
-	crc = crc_itu_t(crc, (u8*)&tmp, 2);
+	crc = crc_itu_t(crc, (u8 *)&tmp, 2);
 
 	if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) {
 		ERROR(rt2x00dev, "Firmware CRC error.\n");
-		goto exit_failed;
+		retval = -ENOENT;
+		goto exit;
 	}
 
-	/*
-	 * Send firmware to the device.
-	 */
-	if (rt2x00dev->ops->lib->load_firmware(rt2x00dev, fw->data, fw->size))
-		goto exit_failed;
-
 	INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n",
-		fw->data[fw->size - 4], fw->data[fw->size - 3]);
+	     fw->data[fw->size - 4], fw->data[fw->size - 3]);
 
-	__set_bit(FIRMWARE_LOADED, &rt2x00dev->flags);
+	rt2x00dev->fw = fw;
 
-	return;
+	return 0;
 
-exit_failed:
-	rt2x00debug_deregister(rt2x00dev);
+exit:
+	release_firmware(fw);
 
-	__set_bit(FIRMWARE_FAILED, &rt2x00dev->flags);
+	return retval;
 }
 
 int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
 {
-	char *fw_name;
-	int status = -EINVAL;
+	int retval;
 
-	/*
-	 * Read correct firmware from harddisk.
-	 */
-	fw_name = rt2x00dev->ops->lib->get_fw_name(rt2x00dev);
-	if (!fw_name) {
-		ERROR(rt2x00dev,
-			"Invalid firmware filename.\n"
-			"Please file bug report to %s.\n", DRV_PROJECT);
-		return -EINVAL;
+	if (!rt2x00dev->fw) {
+		retval = rt2x00lib_request_firmware(rt2x00dev);
+		if (retval)
+			return retval;
 	}
 
-	INFO(rt2x00dev, "Loading firmware file '%s'.\n", fw_name);
-
-	status = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
-		fw_name, wiphy_dev(rt2x00dev->hw->wiphy), rt2x00dev,
-		&rt2x00lib_load_firmware_continued);
-
-	if (status)
-		ERROR(rt2x00dev, "Failed to request Firmware.\n");
-
-	return status;
+	/*
+	 * Send firmware to the device.
+	 */
+	retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev,
+						    rt2x00dev->fw->data,
+						    rt2x00dev->fw->size);
+	return retval;
 }
 
-int rt2x00lib_load_firmware_wait(struct rt2x00_dev *rt2x00dev)
+void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
 {
-	unsigned int i;
-
-	if (!test_bit(FIRMWARE_REQUIRED, &rt2x00dev->flags))
-		return 0;
-
-	for (i = 0; i < 150; i++) {
-		if (test_bit(FIRMWARE_FAILED, &rt2x00dev->flags))
-			return -EIO;
-		if (test_bit(FIRMWARE_LOADED, &rt2x00dev->flags))
-			return 0;
-		msleep(20);
-	}
-
-	ERROR(rt2x00dev, "Firmware loading timed out.\n");
-	return -ETIMEDOUT;
+	release_firmware(rt2x00dev->fw);
+	rt2x00dev->fw = NULL;
 }
+

+ 76 - 38
package/rt2x00/src/rt2x00lib.h

@@ -20,62 +20,100 @@
 
 /*
 	Module: rt2x00lib
-	Abstract: Data structures for the rt2x00lib module.
-	Supported chipsets: RT2460, RT2560, RT2570,
-	rt2561, rt2561s, rt2661, rt2571W & rt2671.
+	Abstract: Data structures and definitions for the rt2x00lib module.
  */
 
 #ifndef RT2X00LIB_H
 #define RT2X00LIB_H
 
 /*
- * Driver allocation handlers.
+ * Interval defines
+ * Both the link tuner as the rfkill will be called once per second.
  */
-int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev);
-void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev);
+#define LINK_TUNE_INTERVAL	( round_jiffies_relative(HZ) )
+#define RFKILL_POLL_INTERVAL	( 1000 )
 
 /*
- * Driver status handlers.
+ * Radio control handlers.
  */
-int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state);
-int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev);
+int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state);
+void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev);
 
 /*
- * Interrupt context handlers.
+ * Initialization handlers.
  */
-void rt2x00lib_txdone(struct data_entry *entry,
-	const int status, const int retry);
-void rt2x00lib_rxdone(struct data_entry *entry, char *data,
-	const int size, const int signal, const int rssi, const int ofdm);
+int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev);
 
 /*
- * TX descriptor initializer
+ * Configuration handlers.
  */
-void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
-	struct data_entry *entry, struct data_desc *txd,
-	struct ieee80211_hdr *ieee80211hdr, unsigned int length,
-	struct ieee80211_tx_control *control);
+void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac);
+void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid);
+void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type);
+void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
+		      struct ieee80211_conf *conf, const int force_config);
 
 /*
- * mac80211 handlers.
+ * Firmware handlers.
  */
-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_add_interface(struct ieee80211_hw *hw,
-	struct ieee80211_if_init_conf *conf);
-void rt2x00lib_remove_interface(struct ieee80211_hw *hw,
-	struct ieee80211_if_init_conf *conf);
-int rt2x00lib_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
-int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id,
-	struct ieee80211_if_conf *conf);
-void rt2x00lib_set_multicast_list(struct ieee80211_hw *hw,
-	unsigned short flags, int mc_count);
-int rt2x00lib_get_tx_stats(struct ieee80211_hw *hw,
-	struct ieee80211_tx_queue_stats *stats);
-int rt2x00lib_conf_tx(struct ieee80211_hw *hw, int queue,
-	const struct ieee80211_tx_queue_params *params);
-
-#include "rt2x00debug.h"
+#ifdef CONFIG_RT2X00_LIB_FIRMWARE
+int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev);
+#else
+static inline int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
+{
+	return 0;
+}
+static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
+{
+}
+#endif /* CONFIG_RT2X00_LIB_FIRMWARE */
+
+/*
+ * Debugfs handlers.
+ */
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
+void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
+#else
+static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
+{
+}
+
+static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
+{
+}
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+/*
+ * RFkill handlers.
+ */
+#ifdef CONFIG_RT2X00_LIB_RFKILL
+int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev);
+void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev);
+int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev);
+void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev);
+#else
+static inline int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
+{
+	return 0;
+}
+
+static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
+{
+}
+
+static inline int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
+{
+	return 0;
+}
+
+static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
+{
+}
+#endif /* CONFIG_RT2X00_LIB_RFKILL */
 
 #endif /* RT2X00LIB_H */

+ 208 - 169
package/rt2x00/src/rt2x00mac.c

@@ -19,10 +19,8 @@
  */
 
 /*
-	Module: rt2x00lib
+	Module: rt2x00mac
 	Abstract: rt2x00 generic mac80211 routines.
-	Supported chipsets: RT2460, RT2560, RT2570,
-	rt2561, rt2561s, rt2661, rt2571W & rt2671.
  */
 
 /*
@@ -30,15 +28,16 @@
  */
 #define DRV_NAME "rt2x00lib"
 
-#include <linux/netdevice.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 
 #include "rt2x00.h"
 #include "rt2x00lib.h"
-#include "rt2x00dev.h"
 
-static int rt2x00_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
-	struct data_ring *ring, struct sk_buff *frag_skb,
-	struct ieee80211_tx_control *control)
+static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
+				struct data_ring *ring,
+				struct sk_buff *frag_skb,
+				struct ieee80211_tx_control *control)
 {
 	struct sk_buff *skb;
 	int size;
@@ -58,13 +57,13 @@ static int rt2x00_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
 	skb_put(skb, size);
 
 	if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
-		ieee80211_ctstoself_get(rt2x00dev->hw,
-			frag_skb->data, frag_skb->len, control,
-			(struct ieee80211_cts*)(skb->data));
+		ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id,
+					frag_skb->data, frag_skb->len, control,
+					(struct ieee80211_cts *)(skb->data));
 	else
-		ieee80211_rts_get(rt2x00dev->hw,
-			frag_skb->data, frag_skb->len, control,
-			(struct ieee80211_rts*)(skb->data));
+		ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id,
+				  frag_skb->data, frag_skb->len, control,
+				  (struct ieee80211_rts *)(skb->data));
 
 	if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
 		WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
@@ -74,23 +73,34 @@ static int rt2x00_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
 	return NETDEV_TX_OK;
 }
 
-int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
-	struct ieee80211_tx_control *control)
+int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+		 struct ieee80211_tx_control *control)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
-	struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+	struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
 	struct data_ring *ring;
 	u16 frame_control;
 
+	/*
+	 * Mac80211 might be calling this function while we are trying
+	 * to remove the device or perhaps suspending it.
+	 * Note that we can only stop the TX queues inside the TX path
+	 * due to possible race conditions in mac80211.
+	 */
+	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) {
+		ieee80211_stop_queues(hw);
+		return 0;
+	}
+
 	/*
 	 * Determine which ring to put packet on.
 	 */
-	ring = rt2x00_get_ring(rt2x00dev, control->queue);
+	ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
 	if (unlikely(!ring)) {
 		ERROR(rt2x00dev,
-			"Attempt to send packet over invalid queue %d.\n"
-			"Please file bug report to %s.\n",
-			control->queue, DRV_PROJECT);
+		      "Attempt to send packet over invalid queue %d.\n"
+		      "Please file bug report to %s.\n",
+		      control->queue, DRV_PROJECT);
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
 	}
@@ -102,12 +112,13 @@ int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 	 * frame as well as the data frame.
 	 */
 	frame_control = le16_to_cpu(ieee80211hdr->frame_control);
-	if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS &&
-	    !is_cts_frame(frame_control) && !is_rts_frame(frame_control)) {
+	if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) &&
+	    (control->flags & (IEEE80211_TXCTL_USE_RTS_CTS |
+			       IEEE80211_TXCTL_USE_CTS_PROTECT))) {
 		if (rt2x00_ring_free(ring) <= 1)
 			return NETDEV_TX_BUSY;
 
-		if (rt2x00_tx_rts_cts(rt2x00dev, ring, skb, control))
+		if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control))
 			return NETDEV_TX_BUSY;
 	}
 
@@ -119,130 +130,148 @@ int rt2x00lib_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
 
 	return NETDEV_TX_OK;
 }
-EXPORT_SYMBOL_GPL(rt2x00lib_tx);
+EXPORT_SYMBOL_GPL(rt2x00mac_tx);
 
-int rt2x00lib_reset(struct ieee80211_hw *hw)
+int rt2x00mac_start(struct ieee80211_hw *hw)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
+	int status;
+
+	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
+	    test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+		return 0;
+
+	/*
+	 * If this is the first interface which is added,
+	 * we should load the firmware now.
+	 */
+	if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
+		status = rt2x00lib_load_firmware(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;
+	}
+
+	__set_bit(DEVICE_STARTED, &rt2x00dev->flags);
 
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_start);
+
+void rt2x00mac_stop(struct ieee80211_hw *hw)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+
+	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
+		return;
+
+	/*
+	 * Perhaps we can add something smarter here,
+	 * but for now just disabling the radio should do.
+	 */
 	rt2x00lib_disable_radio(rt2x00dev);
-	return rt2x00lib_enable_radio(rt2x00dev);
+
+	__clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
 }
-EXPORT_SYMBOL_GPL(rt2x00lib_reset);
+EXPORT_SYMBOL_GPL(rt2x00mac_stop);
 
-int rt2x00lib_add_interface(struct ieee80211_hw *hw,
-	struct ieee80211_if_init_conf *conf)
+int rt2x00mac_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;
+
+	/* FIXME: Beaconing is broken in rt2x00. */
+	if (conf->type == IEEE80211_IF_TYPE_IBSS ||
+	    conf->type == IEEE80211_IF_TYPE_AP) {
+		ERROR(rt2x00dev,
+		      "rt2x00 does not support Adhoc or Master mode");
+		return -EOPNOTSUPP;
+	}
 
 	/*
-	 * We only support 1 non-monitor interface.
+	 * Don't allow interfaces to be added while
+	 * either the device has disappeared or when
+	 * another interface is already present.
 	 */
-	if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
 	    is_interface_present(intf))
 		return -ENOBUFS;
 
-	/*
-	 * We support muliple monitor mode interfaces.
-	 * All we need to do is increase the monitor_count.
-	 */
-	if (conf->type == IEEE80211_IF_TYPE_MNTR) {
-		intf->monitor_count++;
-	} else {
-		intf->id = conf->if_id;
-		intf->type = conf->type;
-		if (conf->type == IEEE80211_IF_TYPE_AP)
-			memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
-		intf->promisc = 0;
-	}
+	intf->id = conf->if_id;
+	intf->type = conf->type;
+	if (conf->type == IEEE80211_IF_TYPE_AP)
+		memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
+	memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
 
 	/*
-	 * Initialize interface, and enable the radio when this
-	 * is the first interface that is brought up.
+	 * The MAC adddress must be configured after the device
+	 * has been initialized. Otherwise the device can reset
+	 * the MAC registers.
 	 */
-	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;
-	}
+	rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
+	rt2x00lib_config_type(rt2x00dev, conf->type);
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(rt2x00lib_add_interface);
+EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);
 
-void rt2x00lib_remove_interface(struct ieee80211_hw *hw,
-	struct ieee80211_if_init_conf *conf)
+void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
+				struct ieee80211_if_init_conf *conf)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct interface *intf = &rt2x00dev->interface;
 
 	/*
-	 * We only support 1 non-monitor interface.
+	 * Don't allow interfaces to be remove while
+	 * either the device has disappeared or when
+	 * no interface is present.
 	 */
-	if (conf->type != IEEE80211_IF_TYPE_MNTR &&
+	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
 	    !is_interface_present(intf))
 		return;
 
-	/*
-	 * 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--;
-	} else if (intf->type == conf->type) {
-		intf->id = 0;
-		intf->type = -EINVAL;
-		memset(&intf->bssid, 0x00, ETH_ALEN);
-		intf->promisc = 0;
-	}
+	intf->id = 0;
+	intf->type = INVALID_INTERFACE;
+	memset(&intf->bssid, 0x00, ETH_ALEN);
+	memset(&intf->mac, 0x00, ETH_ALEN);
 
 	/*
-	 * 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.
+	 * Make sure the bssid and mac address registers
+	 * are cleared to prevent false ACKing of frames.
 	 */
-	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);
+	rt2x00lib_config_mac_addr(rt2x00dev, intf->mac);
+	rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
+	rt2x00lib_config_type(rt2x00dev, intf->type);
 }
-EXPORT_SYMBOL_GPL(rt2x00lib_remove_interface);
+EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
 
-int rt2x00lib_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 
+	/*
+	 * Mac80211 might be calling this function while we are trying
+	 * to remove the device or perhaps suspending it.
+	 */
+	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
+		return 0;
+
 	/*
 	 * Check if we need to disable the radio,
 	 * if this is not the case, at least the RX must be disabled.
@@ -251,46 +280,42 @@ int rt2x00lib_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
 		if (!conf->radio_enabled)
 			rt2x00lib_disable_radio(rt2x00dev);
 		else
-			rt2x00lib_toggle_rx(rt2x00dev, 0);
+			rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
 	}
 
-	rt2x00lib_config_phymode(rt2x00dev, conf->phymode);
-	rt2x00lib_config_channel(rt2x00dev, conf->channel_val,
-		conf->channel, conf->freq, conf->power_level);
-	rt2x00lib_config_txpower(rt2x00dev, conf->power_level);
-	rt2x00lib_config_antenna(rt2x00dev,
-		conf->antenna_sel_tx, conf->antenna_sel_rx);
-	rt2x00dev->ops->lib->config_duration(rt2x00dev,
-		(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME),
-		conf->beacon_int);
+	rt2x00lib_config(rt2x00dev, conf, 0);
 
 	/*
 	 * Reenable RX only if the radio should be on.
 	 */
 	if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
-		rt2x00lib_toggle_rx(rt2x00dev, 1);
+		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
 	else if (conf->radio_enabled)
 		return rt2x00lib_enable_radio(rt2x00dev);
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(rt2x00lib_config);
+EXPORT_SYMBOL_GPL(rt2x00mac_config);
 
-int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id,
-	struct ieee80211_if_conf *conf)
+int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id,
+			       struct ieee80211_if_conf *conf)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct interface *intf = &rt2x00dev->interface;
 	int status;
 
 	/*
-	 * Monitor mode does not need configuring.
+	 * Mac80211 might be calling this function while we are trying
+	 * to remove the device or perhaps suspending it.
+	 */
+	if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
+		return 0;
+
+	/*
 	 * If the given type does not match the configured type,
 	 * there has been a problem.
 	 */
-	if (conf->type == IEEE80211_IF_TYPE_MNTR)
-		return 0;
-	else if (conf->type != intf->type)
+	if (conf->type != intf->type)
 		return -EINVAL;
 
 	/*
@@ -300,14 +325,7 @@ int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id,
 	 */
 	if (conf->type != IEEE80211_IF_TYPE_AP)
 		memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
-
-	/*
-	 * Enable configuration.
-	 * For Monitor mode, promisc mode will be forced on.
-	 */
-	rt2x00lib_config_type(rt2x00dev, conf->type);
-	rt2x00lib_config_promisc(rt2x00dev, rt2x00dev->interface.promisc);
-	rt2x00dev->ops->lib->config_bssid(rt2x00dev, intf->bssid);
+	rt2x00lib_config_bssid(rt2x00dev, intf->bssid);
 
 	/*
 	 * We only need to initialize the beacon when master mode is enabled.
@@ -316,65 +334,86 @@ int rt2x00lib_config_interface(struct ieee80211_hw *hw, int if_id,
 		return 0;
 
 	status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
-		conf->beacon, conf->beacon_control);
+						   conf->beacon,
+						   conf->beacon_control);
 	if (status)
 		dev_kfree_skb(conf->beacon);
 
 	return status;
 }
-EXPORT_SYMBOL_GPL(rt2x00lib_config_interface);
+EXPORT_SYMBOL_GPL(rt2x00mac_config_interface);
 
-void rt2x00lib_set_multicast_list(struct ieee80211_hw *hw,
-	unsigned short flags, int mc_count)
+int rt2x00mac_get_stats(struct ieee80211_hw *hw,
+			struct ieee80211_low_level_stats *stats)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 
 	/*
-	 * Promisc mode is forced on for Monitor interfaces.
+	 * The dot11ACKFailureCount, dot11RTSFailureCount and
+	 * dot11RTSSuccessCount are updated in interrupt time.
+	 * dot11FCSErrorCount is updated in the link tuner.
 	 */
-	if (is_monitor_present(&rt2x00dev->interface))
-		return;
+	memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats));
 
-	/*
-	 * Check if the new state is different then the old state.
-	 */
-	if (test_bit(INTERFACE_ENABLED_PROMISC, &rt2x00dev->flags) ==
-	    !!(flags & IFF_PROMISC))
-		return;
-
-	rt2x00dev->interface.promisc = !!(flags & IFF_PROMISC);
-
-	/*
-	 * Schedule the link tuner if this does not run
-	 * automatically. The link tuner will be automatically
-	 * switched off when it is not required.
-	 */
-	if (!work_pending(&rt2x00dev->link.work.work))
-		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work.work);
+	return 0;
 }
-EXPORT_SYMBOL_GPL(rt2x00lib_set_multicast_list);
+EXPORT_SYMBOL_GPL(rt2x00mac_get_stats);
 
-int rt2x00lib_get_tx_stats(struct ieee80211_hw *hw,
-	struct ieee80211_tx_queue_stats *stats)
+int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
+			   struct ieee80211_tx_queue_stats *stats)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	unsigned int i;
 
 	for (i = 0; i < hw->queues; i++)
 		memcpy(&stats->data[i], &rt2x00dev->tx[i].stats,
-			sizeof(rt2x00dev->tx[i].stats));
+		       sizeof(rt2x00dev->tx[i].stats));
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(rt2x00lib_get_tx_stats);
+EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats);
+
+void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes,
+			      int cts_protection, int preamble)
+{
+	struct rt2x00_dev *rt2x00dev = hw->priv;
+	int short_preamble;
+	int ack_timeout;
+	int ack_consume_time;
+	int difs;
+
+	/*
+	 * We only support changing preamble mode.
+	 */
+	if (!(changes & IEEE80211_ERP_CHANGE_PREAMBLE))
+		return;
+
+	short_preamble = !preamble;
+	preamble = !!(preamble) ? PREAMBLE : SHORT_PREAMBLE;
+
+	difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
+		SHORT_DIFS : DIFS;
+	ack_timeout = difs + PLCP + preamble + get_duration(ACK_SIZE, 10);
+
+	ack_consume_time = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10);
+
+	if (short_preamble)
+		__set_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
+	else
+		__clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
+
+	rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble,
+					     ack_timeout, ack_consume_time);
+}
+EXPORT_SYMBOL_GPL(rt2x00mac_erp_ie_changed);
 
-int rt2x00lib_conf_tx(struct ieee80211_hw *hw, int queue,
-	const struct ieee80211_tx_queue_params *params)
+int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
+		      const struct ieee80211_tx_queue_params *params)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct data_ring *ring;
 
-	ring = rt2x00_get_ring(rt2x00dev, queue);
+	ring = rt2x00lib_get_ring(rt2x00dev, queue);
 	if (unlikely(!ring))
 		return -EINVAL;
 
@@ -398,10 +437,10 @@ int rt2x00lib_conf_tx(struct ieee80211_hw *hw, int queue,
 		ring->tx_params.aifs = 2;
 
 	INFO(rt2x00dev,
-		"Configured TX ring %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
-		queue, ring->tx_params.cw_min, ring->tx_params.cw_max,
-		ring->tx_params.aifs);
+	     "Configured TX ring %d - CWmin: %d, CWmax: %d, Aifs: %d.\n",
+	     queue, ring->tx_params.cw_min, ring->tx_params.cw_max,
+	     ring->tx_params.aifs);
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(rt2x00lib_conf_tx);
+EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx);

+ 125 - 91
package/rt2x00/src/rt2x00pci.c

@@ -21,7 +21,6 @@
 /*
 	Module: rt2x00pci
 	Abstract: rt2x00 generic pci device routines.
-	Supported chipsets: rt2460, rt2560, rt2561, rt2561s & rt2661.
  */
 
 /*
@@ -29,29 +28,27 @@
  */
 #define DRV_NAME "rt2x00pci"
 
+#include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/version.h>
-#include <linux/init.h>
 #include <linux/pci.h>
 
 #include "rt2x00.h"
-#include "rt2x00lib.h"
 #include "rt2x00pci.h"
 
 /*
  * Beacon handlers.
  */
 int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-	struct ieee80211_tx_control *control)
+			    struct ieee80211_tx_control *control)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct data_ring *ring =
-		rt2x00_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
+	    rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
 	struct data_entry *entry = rt2x00_get_data_entry(ring);
 
 	/*
-	 * Just in case the ieee80211 doesn't set this,
+	 * Just in case mac80211 doesn't set this correctly,
 	 * but we need this queue set for the descriptor
 	 * initialization.
 	 */
@@ -61,8 +58,9 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 	 * Update the beacon entry.
 	 */
 	memcpy(entry->data_addr, skb->data, skb->len);
-	rt2x00lib_write_tx_desc(rt2x00dev, entry, entry->priv,
-		(struct ieee80211_hdr*)skb->data, skb->len, control);
+	rt2x00lib_write_tx_desc(rt2x00dev, entry->priv,
+				(struct ieee80211_hdr *)skb->data,
+				skb->len, control);
 
 	/*
 	 * Enable beacon generation.
@@ -73,32 +71,14 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_beacon_update);
 
-void rt2x00pci_beacondone(struct rt2x00_dev *rt2x00dev, const int queue)
-{
-	struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue);
-	struct data_entry *entry = rt2x00_get_data_entry(ring);
-	struct sk_buff *skb;
-
-	skb = ieee80211_beacon_get(rt2x00dev->hw,
-		rt2x00dev->interface.id, &entry->tx_status.control);
-	if (!skb)
-		return;
-
-	rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb,
-		&entry->tx_status.control);
-
-	dev_kfree_skb(skb);
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_beacondone);
-
 /*
  * TX data handlers.
  */
 int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
-	struct data_ring *ring, struct sk_buff *skb,
-	struct ieee80211_tx_control *control)
+			    struct data_ring *ring, struct sk_buff *skb,
+			    struct ieee80211_tx_control *control)
 {
-	struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+	struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
 	struct data_entry *entry = rt2x00_get_data_entry(ring);
 	struct data_desc *txd = entry->priv;
 	u32 word;
@@ -113,9 +93,9 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
 	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",
-			control->queue, DRV_PROJECT);
+		      "Arrived at non-free entry in the non-full queue %d.\n"
+		      "Please file bug report to %s.\n",
+		      control->queue, DRV_PROJECT);
 		ieee80211_stop_queue(rt2x00dev->hw, control->queue);
 		return -EINVAL;
 	}
@@ -123,8 +103,8 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
 	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);
+	rt2x00lib_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
+				skb->len, control);
 
 	rt2x00_ring_index_inc(ring);
 
@@ -143,35 +123,53 @@ 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;
+	struct sk_buff *skb;
+	struct ieee80211_hdr *hdr;
+	struct rxdata_entry_desc desc;
+	int header_size;
+	int align;
+	u32 word;
 
 	while (1) {
 		entry = rt2x00_get_data_entry(ring);
 		rxd = entry->priv;
-		rt2x00_desc_read(rxd, 0, &desc);
+		rt2x00_desc_read(rxd, 0, &word);
 
-		if (rt2x00_get_field32(desc, RXD_ENTRY_OWNER_NIC))
+		if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
 			break;
 
-		size = rt2x00dev->ops->lib->fill_rxdone(
-			entry, &signal, &rssi, &ofdm);
-		if (size < 0)
-			goto skip_entry;
+		memset(&desc, 0x00, sizeof(desc));
+		rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
+
+		hdr = (struct ieee80211_hdr *)entry->data_addr;
+		header_size =
+		    ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+
+		/*
+		 * The data behind the ieee80211 header must be
+		 * aligned on a 4 byte boundary.
+		 */
+		align = header_size % 4;
+
+		/*
+		 * Allocate the sk_buffer, initialize it and copy
+		 * all data into it.
+		 */
+		skb = dev_alloc_skb(desc.size + align);
+		if (!skb)
+			return;
+
+		skb_reserve(skb, align);
+		memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);
 
 		/*
-		 * Send the packet to upper layer.
+		 * Send the frame to rt2x00lib for further processing.
 		 */
-		rt2x00lib_rxdone(entry, entry->data_addr, size,
-			signal, rssi, ofdm);
+		rt2x00lib_rxdone(entry, skb, &desc);
 
-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_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1);
+			rt2x00_desc_write(rxd, 0, word);
 		}
 
 		rt2x00_ring_index_inc(ring);
@@ -189,20 +187,20 @@ EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
 
 #define data_addr_offset(__ring, __i)				\
 ({								\
-	(__ring)->data_addr					\
-		+ ((__ring)->stats.limit * (__ring)->desc_size)	\
-		+ ((__i) * (__ring)->data_size);		\
+	(__ring)->data_addr +					\
+	    ((__ring)->stats.limit * (__ring)->desc_size) +	\
+	    ((__i) * (__ring)->data_size);			\
 })
 
 #define data_dma_offset(__ring, __i)				\
 ({								\
-	(__ring)->data_dma					\
-		+ ((__ring)->stats.limit * (__ring)->desc_size)	\
-		+ ((__i) * (__ring)->data_size);		\
+	(__ring)->data_dma +					\
+	    ((__ring)->stats.limit * (__ring)->desc_size) +	\
+	    ((__i) * (__ring)->data_size);			\
 })
 
-static int rt2x00pci_alloc_ring(struct rt2x00_dev *rt2x00dev,
-	struct data_ring *ring)
+static int rt2x00pci_alloc_dma(struct rt2x00_dev *rt2x00dev,
+			       struct data_ring *ring)
 {
 	unsigned int i;
 
@@ -210,7 +208,8 @@ static int rt2x00pci_alloc_ring(struct rt2x00_dev *rt2x00dev,
 	 * Allocate DMA memory for descriptor and buffer.
 	 */
 	ring->data_addr = pci_alloc_consistent(rt2x00dev_pci(rt2x00dev),
-		rt2x00_get_ring_size(ring), &ring->data_dma);
+					       rt2x00_get_ring_size(ring),
+					       &ring->data_dma);
 	if (!ring->data_addr)
 		return -ENOMEM;
 
@@ -227,6 +226,16 @@ static int rt2x00pci_alloc_ring(struct rt2x00_dev *rt2x00dev,
 	return 0;
 }
 
+static void rt2x00pci_free_dma(struct rt2x00_dev *rt2x00dev,
+			       struct data_ring *ring)
+{
+	if (ring->data_addr)
+		pci_free_consistent(rt2x00dev_pci(rt2x00dev),
+				    rt2x00_get_ring_size(ring),
+				    ring->data_addr, ring->data_dma);
+	ring->data_addr = NULL;
+}
+
 int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
 {
 	struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
@@ -237,7 +246,7 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
 	 * Allocate DMA
 	 */
 	ring_for_each(rt2x00dev, ring) {
-		status = rt2x00pci_alloc_ring(rt2x00dev, ring);
+		status = rt2x00pci_alloc_dma(rt2x00dev, ring);
 		if (status)
 			goto exit;
 	}
@@ -246,10 +255,10 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
 	 * Register interrupt handler.
 	 */
 	status = request_irq(pci_dev->irq, rt2x00dev->ops->lib->irq_handler,
-		IRQF_SHARED, pci_dev->driver->name, rt2x00dev);
+			     IRQF_SHARED, pci_name(pci_dev), rt2x00dev);
 	if (status) {
 		ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
-			pci_dev->irq, status);
+		      pci_dev->irq, status);
 		return status;
 	}
 
@@ -274,43 +283,58 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Free DMA
 	 */
-	ring_for_each(rt2x00dev, ring) {
-		if (ring->data_addr)
-			pci_free_consistent(rt2x00dev_pci(rt2x00dev),
-				rt2x00_get_ring_size(ring),
-				ring->data_addr, ring->data_dma);
-		ring->data_addr = NULL;
-	}
+	ring_for_each(rt2x00dev, ring)
+		rt2x00pci_free_dma(rt2x00dev, ring);
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize);
 
 /*
  * PCI driver handlers.
  */
-static int rt2x00pci_alloc_csr(struct rt2x00_dev *rt2x00dev)
+static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev)
 {
-	rt2x00dev->csr_addr = ioremap(
-		pci_resource_start(rt2x00dev_pci(rt2x00dev), 0),
-		pci_resource_len(rt2x00dev_pci(rt2x00dev), 0));
-	if (!rt2x00dev->csr_addr) {
-		ERROR(rt2x00dev, "Ioremap failed.\n");
-		return -ENOMEM;
-	}
+	kfree(rt2x00dev->rf);
+	rt2x00dev->rf = NULL;
 
-	return 0;
-}
+	kfree(rt2x00dev->eeprom);
+	rt2x00dev->eeprom = NULL;
 
-static void rt2x00pci_free_csr(struct rt2x00_dev *rt2x00dev)
-{
 	if (rt2x00dev->csr_addr) {
 		iounmap(rt2x00dev->csr_addr);
 		rt2x00dev->csr_addr = NULL;
 	}
 }
 
+static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev)
+{
+	struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev);
+
+	rt2x00dev->csr_addr = ioremap(pci_resource_start(pci_dev, 0),
+				      pci_resource_len(pci_dev, 0));
+	if (!rt2x00dev->csr_addr)
+		goto exit;
+
+	rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
+	if (!rt2x00dev->eeprom)
+		goto exit;
+
+	rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
+	if (!rt2x00dev->rf)
+		goto exit;
+
+	return 0;
+
+exit:
+	ERROR_PROBE("Failed to allocate registers.\n");
+
+	rt2x00pci_free_reg(rt2x00dev);
+
+	return -ENOMEM;
+}
+
 int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 {
-	struct rt2x00_ops *ops = (struct rt2x00_ops*)id->driver_data;
+	struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data;
 	struct ieee80211_hw *hw;
 	struct rt2x00_dev *rt2x00dev;
 	int retval;
@@ -353,18 +377,18 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 	rt2x00dev->ops = ops;
 	rt2x00dev->hw = hw;
 
-	retval = rt2x00pci_alloc_csr(rt2x00dev);
+	retval = rt2x00pci_alloc_reg(rt2x00dev);
 	if (retval)
 		goto exit_free_device;
 
 	retval = rt2x00lib_probe_dev(rt2x00dev);
 	if (retval)
-		goto exit_free_csr;
+		goto exit_free_reg;
 
 	return 0;
 
-exit_free_csr:
-	rt2x00pci_free_csr(rt2x00dev);
+exit_free_reg:
+	rt2x00pci_free_reg(rt2x00dev);
 
 exit_free_device:
 	ieee80211_free_hw(hw);
@@ -391,6 +415,7 @@ void rt2x00pci_remove(struct pci_dev *pci_dev)
 	 * Free all allocated data.
 	 */
 	rt2x00lib_remove_dev(rt2x00dev);
+	rt2x00pci_free_reg(rt2x00dev);
 	ieee80211_free_hw(hw);
 
 	/*
@@ -413,7 +438,7 @@ int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
 	if (retval)
 		return retval;
 
-	rt2x00pci_free_csr(rt2x00dev);
+	rt2x00pci_free_reg(rt2x00dev);
 
 	pci_save_state(pci_dev);
 	pci_disable_device(pci_dev);
@@ -434,11 +459,20 @@ int rt2x00pci_resume(struct pci_dev *pci_dev)
 		return -EIO;
 	}
 
-	retval = rt2x00pci_alloc_csr(rt2x00dev);
+	retval = rt2x00pci_alloc_reg(rt2x00dev);
 	if (retval)
 		return retval;
 
-	return rt2x00lib_resume(rt2x00dev);
+	retval = rt2x00lib_resume(rt2x00dev);
+	if (retval)
+		goto exit_free_reg;
+
+	return 0;
+
+exit_free_reg:
+	rt2x00pci_free_reg(rt2x00dev);
+
+	return retval;
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_resume);
 #endif /* CONFIG_PM */

+ 25 - 16
package/rt2x00/src/rt2x00pci.h

@@ -21,12 +21,13 @@
 /*
 	Module: rt2x00pci
 	Abstract: Data structures for the rt2x00pci module.
-	Supported chipsets: rt2460, rt2560, rt2561, rt2561s & rt2661.
  */
 
 #ifndef RT2X00PCI_H
 #define RT2X00PCI_H
 
+#include <linux/io.h>
+
 /*
  * This variable should be used with the
  * pci_driver structure initialization.
@@ -35,9 +36,9 @@
 
 /*
  * Register defines.
- * When register access attempts should be repeated
- * only REGISTER_BUSY_COUNT attempts with a delay
- * of REGISTER_BUSY_DELAY us should be taken.
+ * Some registers require multiple attempts before success,
+ * in those cases REGISTER_BUSY_COUNT attempts should be
+ * taken with a REGISTER_BUSY_DELAY interval.
  */
 #define REGISTER_BUSY_COUNT	5
 #define REGISTER_BUSY_DELAY	100
@@ -46,6 +47,8 @@
  * Descriptor availability flags.
  * All PCI device descriptors have these 2 flags
  * with the exact same definition.
+ * By storing them here we can use them inside rt2x00pci
+ * for some simple entry availability checking.
  */
 #define TXD_ENTRY_OWNER_NIC	FIELD32(0x00000001)
 #define TXD_ENTRY_VALID		FIELD32(0x00000002)
@@ -55,27 +58,31 @@
  * Register access.
  */
 static inline void rt2x00pci_register_read(const struct rt2x00_dev *rt2x00dev,
-	const unsigned long offset, u32 *value)
+					   const unsigned long offset,
+					   u32 *value)
 {
 	*value = readl(rt2x00dev->csr_addr + offset);
 }
 
-static inline void rt2x00pci_register_multiread(
-	const struct rt2x00_dev *rt2x00dev,
-	const unsigned long offset, void *value, const u16 length)
+static inline void
+rt2x00pci_register_multiread(const struct rt2x00_dev *rt2x00dev,
+			     const unsigned long offset,
+			     void *value, const u16 length)
 {
 	memcpy_fromio(value, rt2x00dev->csr_addr + offset, length);
 }
 
 static inline void rt2x00pci_register_write(const struct rt2x00_dev *rt2x00dev,
-	const unsigned long offset, u32 value)
+					    const unsigned long offset,
+					    u32 value)
 {
 	writel(value, rt2x00dev->csr_addr + offset);
 }
 
-static inline void rt2x00pci_register_multiwrite(
-	const struct rt2x00_dev *rt2x00dev,
-	const unsigned long offset, void *value, const u16 length)
+static inline void
+rt2x00pci_register_multiwrite(const struct rt2x00_dev *rt2x00dev,
+			      const unsigned long offset,
+			      void *value, const u16 length)
 {
 	memcpy_toio(rt2x00dev->csr_addr + offset, value, length);
 }
@@ -84,15 +91,14 @@ static inline void rt2x00pci_register_multiwrite(
  * Beacon handlers.
  */
 int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-	struct ieee80211_tx_control *control);
-void rt2x00pci_beacondone(struct rt2x00_dev *rt2x00dev, const int queue);
+			    struct ieee80211_tx_control *control);
 
 /*
  * TX data handlers.
  */
 int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
-	struct data_ring *ring, struct sk_buff *skb,
-	struct ieee80211_tx_control *control);
+			    struct data_ring *ring, struct sk_buff *skb,
+			    struct ieee80211_tx_control *control);
 
 /*
  * RX data handlers.
@@ -113,6 +119,9 @@ void rt2x00pci_remove(struct pci_dev *pci_dev);
 #ifdef CONFIG_PM
 int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state);
 int rt2x00pci_resume(struct pci_dev *pci_dev);
+#else
+#define rt2x00pci_suspend	NULL
+#define rt2x00pci_resume	NULL
 #endif /* CONFIG_PM */
 
 #endif /* RT2X00PCI_H */

+ 292 - 0
package/rt2x00/src/rt2x00reg.h

@@ -0,0 +1,292 @@
+/*
+	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.
+ */
+
+/*
+	Module: rt2x00
+	Abstract: rt2x00 generic register information.
+ */
+
+#ifndef RT2X00REG_H
+#define RT2X00REG_H
+
+/*
+ * TX result flags.
+ */
+enum TX_STATUS {
+	TX_SUCCESS = 0,
+	TX_SUCCESS_RETRY = 1,
+	TX_FAIL_RETRY = 2,
+	TX_FAIL_INVALID = 3,
+	TX_FAIL_OTHER = 4,
+};
+
+/*
+ * Antenna values
+ */
+enum antenna {
+	ANTENNA_SW_DIVERSITY = 0,
+	ANTENNA_A = 1,
+	ANTENNA_B = 2,
+	ANTENNA_HW_DIVERSITY = 3,
+};
+
+/*
+ * Led mode values.
+ */
+enum led_mode {
+	LED_MODE_DEFAULT = 0,
+	LED_MODE_TXRX_ACTIVITY = 1,
+	LED_MODE_SIGNAL_STRENGTH = 2,
+	LED_MODE_ASUS = 3,
+	LED_MODE_ALPHA = 4,
+};
+
+/*
+ * TSF sync values
+ */
+enum tsf_sync {
+	TSF_SYNC_NONE = 0,
+	TSF_SYNC_INFRA = 1,
+	TSF_SYNC_BEACON = 2,
+};
+
+/*
+ * Device states
+ */
+enum dev_state {
+	STATE_DEEP_SLEEP = 0,
+	STATE_SLEEP = 1,
+	STATE_STANDBY = 2,
+	STATE_AWAKE = 3,
+
+/*
+ * Additional device states, these values are
+ * not strict since they are not directly passed
+ * into the device.
+ */
+	STATE_RADIO_ON,
+	STATE_RADIO_OFF,
+	STATE_RADIO_RX_ON,
+	STATE_RADIO_RX_OFF,
+	STATE_RADIO_IRQ_ON,
+	STATE_RADIO_IRQ_OFF,
+};
+
+/*
+ * IFS backoff values
+ */
+enum ifs {
+	IFS_BACKOFF = 0,
+	IFS_SIFS = 1,
+	IFS_NEW_BACKOFF = 2,
+	IFS_NONE = 3,
+};
+
+/*
+ * Cipher types for hardware encryption
+ */
+enum cipher {
+	CIPHER_NONE = 0,
+	CIPHER_WEP64 = 1,
+	CIPHER_WEP128 = 2,
+	CIPHER_TKIP = 3,
+	CIPHER_AES = 4,
+/*
+ * The following fields were added by rt61pci and rt73usb.
+ */
+	CIPHER_CKIP64 = 5,
+	CIPHER_CKIP128 = 6,
+	CIPHER_TKIP_NO_MIC = 7,
+};
+
+/*
+ * Register handlers.
+ * We store the position of a register field inside a field structure,
+ * This will simplify the process of setting and reading a certain field
+ * inside the register while making sure the process remains byte order safe.
+ */
+struct rt2x00_field8 {
+	u8 bit_offset;
+	u8 bit_mask;
+};
+
+struct rt2x00_field16 {
+	u16 bit_offset;
+	u16 bit_mask;
+};
+
+struct rt2x00_field32 {
+	u32 bit_offset;
+	u32 bit_mask;
+};
+
+/*
+ * Power of two check, this will check
+ * if the mask that has been given contains
+ * and contiguous set of bits.
+ */
+#define is_power_of_two(x)	( !((x) & ((x)-1)) )
+#define low_bit_mask(x)		( ((x)-1) & ~(x) )
+#define is_valid_mask(x)	is_power_of_two(1 + (x) + low_bit_mask(x))
+
+#define FIELD8(__mask)				\
+({						\
+	BUILD_BUG_ON(!(__mask) ||		\
+		     !is_valid_mask(__mask) ||	\
+		     (__mask) != (u8)(__mask));	\
+	(struct rt2x00_field8) {		\
+		__ffs(__mask), (__mask)		\
+	};					\
+})
+
+#define FIELD16(__mask)				\
+({						\
+	BUILD_BUG_ON(!(__mask) ||		\
+		     !is_valid_mask(__mask) ||	\
+		     (__mask) != (u16)(__mask));\
+	(struct rt2x00_field16) {		\
+		__ffs(__mask), (__mask)		\
+	};					\
+})
+
+#define FIELD32(__mask)				\
+({						\
+	BUILD_BUG_ON(!(__mask) ||		\
+		     !is_valid_mask(__mask) ||	\
+		     (__mask) != (u32)(__mask));\
+	(struct rt2x00_field32) {		\
+		__ffs(__mask), (__mask)		\
+	};					\
+})
+
+static inline void rt2x00_set_field32(u32 *reg,
+				      const struct rt2x00_field32 field,
+				      const u32 value)
+{
+	*reg &= ~(field.bit_mask);
+	*reg |= (value << field.bit_offset) & field.bit_mask;
+}
+
+static inline u32 rt2x00_get_field32(const u32 reg,
+				     const struct rt2x00_field32 field)
+{
+	return (reg & field.bit_mask) >> field.bit_offset;
+}
+
+static inline void rt2x00_set_field16(u16 *reg,
+				      const struct rt2x00_field16 field,
+				      const u16 value)
+{
+	*reg &= ~(field.bit_mask);
+	*reg |= (value << field.bit_offset) & field.bit_mask;
+}
+
+static inline u16 rt2x00_get_field16(const u16 reg,
+				     const struct rt2x00_field16 field)
+{
+	return (reg & field.bit_mask) >> field.bit_offset;
+}
+
+static inline void rt2x00_set_field8(u8 *reg,
+				     const struct rt2x00_field8 field,
+				     const u8 value)
+{
+	*reg &= ~(field.bit_mask);
+	*reg |= (value << field.bit_offset) & field.bit_mask;
+}
+
+static inline u8 rt2x00_get_field8(const u8 reg,
+				   const struct rt2x00_field8 field)
+{
+	return (reg & field.bit_mask) >> field.bit_offset;
+}
+
+/*
+ * Device specific rate value.
+ * We will have to create the device specific rate value
+ * passed to the ieee80211 kernel. We need to make it a consist of
+ * multiple fields because we want to store more then 1 device specific
+ * values inside the value.
+ *	1 - rate, stored as 100 kbit/s.
+ *	2 - preamble, short_preamble enabled flag.
+ *	3 - MASK_RATE, which rates are enabled in this mode, this mask
+ *	corresponds with the TX register format for the current device.
+ *	4 - plcp, 802.11b rates are device specific,
+ *	802.11g rates are set according to the ieee802.11a-1999 p.14.
+ * The bit to enable preamble is set in a seperate define.
+ */
+#define DEV_RATE	FIELD32(0x000007ff)
+#define DEV_PREAMBLE	FIELD32(0x00000800)
+#define DEV_RATEMASK	FIELD32(0x00fff000)
+#define DEV_PLCP	FIELD32(0xff000000)
+
+/*
+ * Bitfields
+ */
+#define DEV_RATEBIT_1MB		( 1 << 0 )
+#define DEV_RATEBIT_2MB		( 1 << 1 )
+#define DEV_RATEBIT_5_5MB	( 1 << 2 )
+#define DEV_RATEBIT_11MB	( 1 << 3 )
+#define DEV_RATEBIT_6MB		( 1 << 4 )
+#define DEV_RATEBIT_9MB		( 1 << 5 )
+#define DEV_RATEBIT_12MB	( 1 << 6 )
+#define DEV_RATEBIT_18MB	( 1 << 7 )
+#define DEV_RATEBIT_24MB	( 1 << 8 )
+#define DEV_RATEBIT_36MB	( 1 << 9 )
+#define DEV_RATEBIT_48MB	( 1 << 10 )
+#define DEV_RATEBIT_54MB	( 1 << 11 )
+
+/*
+ * Bitmasks for DEV_RATEMASK
+ */
+#define DEV_RATEMASK_1MB	( (DEV_RATEBIT_1MB << 1) -1 )
+#define DEV_RATEMASK_2MB	( (DEV_RATEBIT_2MB << 1) -1 )
+#define DEV_RATEMASK_5_5MB	( (DEV_RATEBIT_5_5MB << 1) -1 )
+#define DEV_RATEMASK_11MB	( (DEV_RATEBIT_11MB << 1) -1 )
+#define DEV_RATEMASK_6MB	( (DEV_RATEBIT_6MB << 1) -1 )
+#define DEV_RATEMASK_9MB	( (DEV_RATEBIT_9MB << 1) -1 )
+#define DEV_RATEMASK_12MB	( (DEV_RATEBIT_12MB << 1) -1 )
+#define DEV_RATEMASK_18MB	( (DEV_RATEBIT_18MB << 1) -1 )
+#define DEV_RATEMASK_24MB	( (DEV_RATEBIT_24MB << 1) -1 )
+#define DEV_RATEMASK_36MB	( (DEV_RATEBIT_36MB << 1) -1 )
+#define DEV_RATEMASK_48MB	( (DEV_RATEBIT_48MB << 1) -1 )
+#define DEV_RATEMASK_54MB	( (DEV_RATEBIT_54MB << 1) -1 )
+
+/*
+ * Bitmask groups of bitrates
+ */
+#define DEV_BASIC_RATEMASK \
+	( DEV_RATEMASK_11MB | \
+	  DEV_RATEBIT_6MB | DEV_RATEBIT_12MB | DEV_RATEBIT_24MB )
+
+#define DEV_CCK_RATEMASK	( DEV_RATEMASK_11MB )
+#define DEV_OFDM_RATEMASK	( DEV_RATEMASK_54MB & ~DEV_CCK_RATEMASK )
+
+/*
+ * Macro's to set and get specific fields from the device specific val and val2
+ * fields inside the ieee80211_rate entry.
+ */
+#define DEVICE_SET_RATE_FIELD(__value, __mask) \
+	(int)( ((__value) << DEV_##__mask.bit_offset) & DEV_##__mask.bit_mask )
+
+#define DEVICE_GET_RATE_FIELD(__value, __mask) \
+	(int)( ((__value) & DEV_##__mask.bit_mask) >> DEV_##__mask.bit_offset )
+
+#endif /* RT2X00REG_H */

+ 59 - 42
package/rt2x00/src/rt2x00rfkill.c

@@ -19,9 +19,8 @@
  */
 
 /*
-	Module: rt2x00lib
-	Abstract: rt2x00 rfkill specific routines.
-	Supported chipsets: RT2460, RT2560, rt2561, rt2561s, rt2661.
+	Module: rt2x00rfkill
+	Abstract: rt2x00 rfkill routines.
  */
 
 /*
@@ -29,101 +28,119 @@
  */
 #define DRV_NAME "rt2x00lib"
 
+#include <linux/input-polldev.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/rfkill.h>
 
 #include "rt2x00.h"
+#include "rt2x00lib.h"
 
-static int rt2x00lib_toggle_radio(void *data, enum rfkill_state state)
+static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state)
 {
-	struct rt2x00_dev* rt2x00dev = data;
+	struct rt2x00_dev *rt2x00dev = data;
 	int retval = 0;
 
 	if (unlikely(!rt2x00dev))
 		return 0;
 
 	/*
-	 * Only continue if we have an active interface,
-	 * either monitor or non-monitor should be present.
+	 * Only continue if there are enabled interfaces.
 	 */
-	if (!is_interface_present(&rt2x00dev->interface) &&
-	    !is_monitor_present(&rt2x00dev->interface))
+	if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
 		return 0;
 
 	if (state == RFKILL_STATE_ON) {
 		INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n");
-		__set_bit(DEVICE_ENABLED_RADIO_HW, &rt2x00dev->flags);
+		__clear_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags);
 		retval = rt2x00lib_enable_radio(rt2x00dev);
 	} else if (state == RFKILL_STATE_OFF) {
 		INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n");
-		__clear_bit(DEVICE_ENABLED_RADIO_HW, &rt2x00dev->flags);
+		__set_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags);
 		rt2x00lib_disable_radio(rt2x00dev);
 	}
 
 	return retval;
 }
 
-static void rt2x00lib_rfkill_poll(struct work_struct *work)
+static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev)
 {
-	struct rt2x00_dev *rt2x00dev =
-		container_of(work, struct rt2x00_dev, rfkill_work.work);
+	struct rt2x00_dev *rt2x00dev = poll_dev->private;
+	int state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
 
-	rfkill_switch_all(rt2x00dev->rfkill->type,
-		rt2x00dev->ops->lib->rfkill_poll(rt2x00dev));
-
-	queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->rfkill_work,
-		RFKILL_POLL_INTERVAL);
+	if (rt2x00dev->rfkill->state != state)
+		input_report_key(poll_dev->input, KEY_WLAN, 1);
 }
 
-int rt2x00lib_register_rfkill(struct rt2x00_dev *rt2x00dev)
+int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
 {
-	int status = rfkill_register(rt2x00dev->rfkill);
-	if (status) {
+	int retval;
+
+	if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+		return 0;
+
+	retval = rfkill_register(rt2x00dev->rfkill);
+	if (retval) {
 		ERROR(rt2x00dev, "Failed to register rfkill handler.\n");
-		return status;
+		return retval;
 	}
 
-	rt2x00lib_rfkill_poll(&rt2x00dev->rfkill_work.work);
+	retval = input_register_polled_device(rt2x00dev->poll_dev);
+	if (retval) {
+		ERROR(rt2x00dev, "Failed to register polled device.\n");
+		rfkill_unregister(rt2x00dev->rfkill);
+		return retval;
+	}
 
-	return !schedule_delayed_work(&rt2x00dev->rfkill_work,
-		RFKILL_POLL_INTERVAL);
+	return 0;
 }
 
-void rt2x00lib_unregister_rfkill(struct rt2x00_dev *rt2x00dev)
+void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)
 {
-	if (delayed_work_pending(&rt2x00dev->rfkill_work))
-		cancel_rearming_delayed_workqueue(
-			rt2x00dev->hw->workqueue, &rt2x00dev->rfkill_work);
+	if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+		return;
 
+	input_unregister_polled_device(rt2x00dev->poll_dev);
 	rfkill_unregister(rt2x00dev->rfkill);
 }
 
-int rt2x00lib_allocate_rfkill(struct rt2x00_dev *rt2x00dev)
+int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
 {
-	struct rfkill *rfkill;
+	struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
 
-	if (!test_bit(DEVICE_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+	if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
 		return 0;
 
-	rfkill = rfkill_allocate(rt2x00dev->device, RFKILL_TYPE_WLAN);
-	if (!rfkill) {
+	rt2x00dev->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
+	if (!rt2x00dev->rfkill) {
 		ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n");
 		return -ENOMEM;
 	}
 
-	rfkill->name = rt2x00dev->ops->name;
-	rfkill->data = rt2x00dev;
-	rfkill->toggle_radio = rt2x00lib_toggle_radio;
-	rt2x00dev->rfkill = rfkill;
+	rt2x00dev->rfkill->name = rt2x00dev->ops->name;
+	rt2x00dev->rfkill->data = rt2x00dev;
+	rt2x00dev->rfkill->state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
+	rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio;
+
+	rt2x00dev->poll_dev = input_allocate_polled_device();
+	if (!rt2x00dev->poll_dev) {
+		ERROR(rt2x00dev, "Failed to allocate polled device.\n");
+		rfkill_free(rt2x00dev->rfkill);
+		return -ENOMEM;
+	}
 
-	INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00lib_rfkill_poll);
+	rt2x00dev->poll_dev->private = rt2x00dev;
+	rt2x00dev->poll_dev->poll = rt2x00rfkill_poll;
+	rt2x00dev->poll_dev->poll_interval = RFKILL_POLL_INTERVAL;
 
 	return 0;
 }
 
-void rt2x00lib_free_rfkill(struct rt2x00_dev *rt2x00dev)
+void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
 {
-	if (!test_bit(DEVICE_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
+	if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags))
 		return;
 
+	input_free_polled_device(rt2x00dev->poll_dev);
 	rfkill_free(rt2x00dev->rfkill);
 }

+ 268 - 0
package/rt2x00/src/rt2x00ring.h

@@ -0,0 +1,268 @@
+/*
+	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.
+ */
+
+/*
+	Module: rt2x00
+	Abstract: rt2x00 ring datastructures and routines
+ */
+
+#ifndef RT2X00RING_H
+#define RT2X00RING_H
+
+/*
+ * data_desc
+ * Each data entry also contains a descriptor which is used by the
+ * device to determine what should be done with the packet and
+ * what the current status is.
+ * This structure is greatly simplified, but the descriptors
+ * are basically a list of little endian 32 bit values.
+ * Make the array by default 1 word big, this will allow us
+ * to use sizeof() correctly.
+ */
+struct data_desc {
+	__le32 word[1];
+};
+
+/*
+ * rxdata_entry_desc
+ * Summary of information that has been read from the
+ * RX frame descriptor.
+ */
+struct rxdata_entry_desc {
+	int signal;
+	int rssi;
+	int ofdm;
+	int size;
+	int flags;
+};
+
+/*
+ * txdata_entry_desc
+ * Summary of information that should be written into the
+ * descriptor for sending a TX frame.
+ */
+struct txdata_entry_desc {
+	unsigned long flags;
+#define ENTRY_TXDONE		1
+#define ENTRY_TXD_RTS_FRAME	2
+#define ENTRY_TXD_OFDM_RATE	3
+#define ENTRY_TXD_MORE_FRAG	4
+#define ENTRY_TXD_REQ_TIMESTAMP	5
+#define ENTRY_TXD_BURST		6
+
+/*
+ * Queue ID. ID's 0-4 are data TX rings
+ */
+	int queue;
+#define QUEUE_MGMT		13
+#define QUEUE_RX		14
+#define QUEUE_OTHER		15
+
+	/*
+	 * PLCP values.
+	 */
+	u16 length_high;
+	u16 length_low;
+	u16 signal;
+	u16 service;
+
+	/*
+	 * Timing information
+	 */
+	int aifs;
+	int ifs;
+	int cw_min;
+	int cw_max;
+};
+
+/*
+ * data_entry
+ * The data ring is a list of data entries.
+ * Each entry holds a reference to the descriptor
+ * and the data buffer. For TX rings the reference to the
+ * sk_buff of the packet being transmitted is also stored here.
+ */
+struct data_entry {
+	/*
+	 * Status flags
+	 */
+	unsigned long flags;
+#define ENTRY_OWNER_NIC		1
+
+	/*
+	 * Ring we belong to.
+	 */
+	struct data_ring *ring;
+
+	/*
+	 * sk_buff for the packet which is being transmitted
+	 * in this entry (Only used with TX related rings).
+	 */
+	struct sk_buff *skb;
+
+	/*
+	 * Store a ieee80211_tx_status structure in each
+	 * ring entry, this will optimize the txdone
+	 * handler.
+	 */
+	struct ieee80211_tx_status tx_status;
+
+	/*
+	 * private pointer specific to driver.
+	 */
+	void *priv;
+
+	/*
+	 * Data address for this entry.
+	 */
+	void *data_addr;
+	dma_addr_t data_dma;
+};
+
+/*
+ * data_ring
+ * Data rings are used by the device to send and receive packets.
+ * The data_addr is the base address of the data memory.
+ * To determine at which point in the ring we are,
+ * have to use the rt2x00_ring_index_*() functions.
+ */
+struct data_ring {
+	/*
+	 * Pointer to main rt2x00dev structure where this
+	 * ring belongs to.
+	 */
+	struct rt2x00_dev *rt2x00dev;
+
+	/*
+	 * Base address for the device specific data entries.
+	 */
+	struct data_entry *entry;
+
+	/*
+	 * TX queue statistic info.
+	 */
+	struct ieee80211_tx_queue_stats_data stats;
+
+	/*
+	 * TX Queue parameters.
+	 */
+	struct ieee80211_tx_queue_params tx_params;
+
+	/*
+	 * Base address for data ring.
+	 */
+	dma_addr_t data_dma;
+	void *data_addr;
+
+	/*
+	 * Index variables.
+	 */
+	u16 index;
+	u16 index_done;
+
+	/*
+	 * Size of packet and descriptor in bytes.
+	 */
+	u16 data_size;
+	u16 desc_size;
+};
+
+/*
+ * Handlers to determine the address of the current device specific
+ * data entry, where either index or index_done points to.
+ */
+static inline struct data_entry *rt2x00_get_data_entry(struct data_ring *ring)
+{
+	return &ring->entry[ring->index];
+}
+
+static inline struct data_entry *rt2x00_get_data_entry_done(struct data_ring
+							    *ring)
+{
+	return &ring->entry[ring->index_done];
+}
+
+/*
+ * Total ring memory
+ */
+static inline int rt2x00_get_ring_size(struct data_ring *ring)
+{
+	return ring->stats.limit * (ring->desc_size + ring->data_size);
+}
+
+/*
+ * Ring index manipulation functions.
+ */
+static inline void rt2x00_ring_index_inc(struct data_ring *ring)
+{
+	ring->index++;
+	if (ring->index >= ring->stats.limit)
+		ring->index = 0;
+	ring->stats.len++;
+}
+
+static inline void rt2x00_ring_index_done_inc(struct data_ring *ring)
+{
+	ring->index_done++;
+	if (ring->index_done >= ring->stats.limit)
+		ring->index_done = 0;
+	ring->stats.len--;
+	ring->stats.count++;
+}
+
+static inline void rt2x00_ring_index_clear(struct data_ring *ring)
+{
+	ring->index = 0;
+	ring->index_done = 0;
+	ring->stats.len = 0;
+	ring->stats.count = 0;
+}
+
+static inline int rt2x00_ring_empty(struct data_ring *ring)
+{
+	return ring->stats.len == 0;
+}
+
+static inline int rt2x00_ring_full(struct data_ring *ring)
+{
+	return ring->stats.len == ring->stats.limit;
+}
+
+static inline int rt2x00_ring_free(struct data_ring *ring)
+{
+	return ring->stats.limit - ring->stats.len;
+}
+
+/*
+ * TX/RX Descriptor access functions.
+ */
+static inline void rt2x00_desc_read(struct data_desc *desc,
+				    const u8 word, u32 *value)
+{
+	*value = le32_to_cpu(desc->word[word]);
+}
+
+static inline void rt2x00_desc_write(struct data_desc *desc,
+				     const u8 word, const u32 value)
+{
+	desc->word[word] = cpu_to_le32(value);
+}
+
+#endif /* RT2X00RING_H */

+ 219 - 198
package/rt2x00/src/rt2x00usb.c

@@ -21,7 +21,6 @@
 /*
 	Module: rt2x00usb
 	Abstract: rt2x00 generic usb device routines.
-	Supported chipsets: rt2570, rt2571W & rt2671.
  */
 
 /*
@@ -31,169 +30,87 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/version.h>
-#include <linux/init.h>
 #include <linux/usb.h>
 
 #include "rt2x00.h"
-#include "rt2x00lib.h"
 #include "rt2x00usb.h"
 
 /*
  * Interfacing with the HW.
  */
 int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
-	const u8 request, const u8 type, const u16 offset,
-	u32 value, void *buffer, const u16 buffer_length, const u16 timeout)
+			     const u8 request, const u8 requesttype,
+			     const u16 offset, const u16 value,
+			     void *buffer, const u16 buffer_length,
+			     const int timeout)
 {
-	struct usb_device *usb_dev = interface_to_usbdev(
-		rt2x00dev_usb(rt2x00dev));
+	struct usb_device *usb_dev =
+	    interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
 	int status;
 	unsigned int i;
+	unsigned int pipe =
+	    (requesttype == USB_VENDOR_REQUEST_IN) ?
+	    usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
 
 	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
-		status = usb_control_msg(
-			usb_dev,
-			(type == USB_VENDOR_REQUEST_IN) ?
-				usb_rcvctrlpipe(usb_dev, 0) :
-				usb_sndctrlpipe(usb_dev, 0),
-			request, type, value, offset, buffer, buffer_length,
-			timeout);
+		status = usb_control_msg(usb_dev, pipe, request, requesttype,
+					 value, offset, buffer, buffer_length,
+					 timeout);
 		if (status >= 0)
 			return 0;
+
+		/*
+		 * Check for errors
+		 * -ENODEV: Device has disappeared, no point continuing.
+		 * All other errors: Try again.
+		 */
+		else if (status == -ENODEV)
+			break;
 	}
 
-	ERROR(rt2x00dev, "Vendor 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);
 
-/*
- * Beacon handlers.
- */
-int rt2x00usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-	struct ieee80211_tx_control *control)
+int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev,
+				  const u8 request, const u8 requesttype,
+				  const u16 offset, void *buffer,
+				  const u16 buffer_length, const int timeout)
 {
-	struct rt2x00_dev *rt2x00dev = hw->priv;
-	struct usb_device *usb_dev =
-		interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
-	struct data_ring *ring =
-		rt2x00_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-	struct data_entry *beacon;
-	struct data_entry *guardian;
-	int length;
-
-	/*
-	 * Just in case the ieee80211 doesn't set this,
-	 * but we need this queue set for the descriptor
-	 * initialization.
-	 */
-	control->queue = IEEE80211_TX_QUEUE_BEACON;
-
-	/*
-	 * Obtain 2 entries, one for the guardian byte,
-	 * the second for the actual beacon.
-	 */
-	guardian = rt2x00_get_data_entry(ring);
-	rt2x00_ring_index_inc(ring);
-	beacon = rt2x00_get_data_entry(ring);
-
-	/*
-	 * First we create the beacon.
-	 */
-	skb_push(skb, ring->desc_size);
-	rt2x00lib_write_tx_desc(rt2x00dev, beacon,
-		(struct data_desc*)skb->data,
-		(struct ieee80211_hdr*)(skb->data + ring->desc_size),
-		skb->len - ring->desc_size,
-		control);
-
-	/*
-	 * Length passed to usb_fill_urb cannot be an odd number,
-	 * so add 1 byte to make it even.
-	 */
-	length = skb->len;
-	if (length % 2)
-		length++;
-
-	usb_fill_bulk_urb(
-		beacon->priv,
-		usb_dev,
-		usb_sndbulkpipe(usb_dev, 1),
-		skb->data,
-		length,
-		rt2x00usb_beacondone,
-		beacon);
-
-	beacon->skb = skb;
-
-	/*
-	 * Second we need to create the guardian byte.
-	 * We only need a single byte, so lets recycle
-	 * the 'flags' field we are not using for beacons.
-	 */
-	guardian->flags = 0;
-	usb_fill_bulk_urb(
-		guardian->priv,
-		usb_dev,
-		usb_sndbulkpipe(usb_dev, 1),
-		&guardian->flags,
-		1,
-		rt2x00usb_beacondone,
-		guardian);
-
-	/*
-	 * Send out the guardian byte.
-	 */
-	usb_submit_urb(guardian->priv, GFP_ATOMIC);
+	int status;
 
 	/*
-	 * Enable beacon generation.
+	 * Check for Cache availability.
 	 */
-	rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
+	if (unlikely(!rt2x00dev->csr_cache || buffer_length > CSR_CACHE_SIZE)) {
+		ERROR(rt2x00dev, "CSR cache not available.\n");
+		return -ENOMEM;
+	}
 
-	return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_beacon_update);
+	if (requesttype == USB_VENDOR_REQUEST_OUT)
+		memcpy(rt2x00dev->csr_cache, buffer, buffer_length);
 
-void rt2x00usb_beacondone(struct urb *urb)
-{
-	struct data_entry *entry = (struct data_entry*)urb->context;
-	struct data_ring *ring = entry->ring;
+	status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype,
+					  offset, 0, rt2x00dev->csr_cache,
+					  buffer_length, timeout);
 
-	if (!test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags))
-		return;
+	if (!status && requesttype == USB_VENDOR_REQUEST_IN)
+		memcpy(buffer, rt2x00dev->csr_cache, buffer_length);
 
-	/*
-	 * Check if this was the guardian beacon,
-	 * if that was the case we need to send the real beacon now.
-	 * Otherwise we should free the sk_buffer, the device
-	 * should be doing the rest of the work now.
-	 */
-	if (ring->index == 1) {
-		rt2x00_ring_index_done_inc(ring);
-		entry = rt2x00_get_data_entry(ring);
-		usb_submit_urb(entry->priv, GFP_ATOMIC);
-		rt2x00_ring_index_inc(ring);
-	} else if (ring->index_done == 1) {
-		entry = rt2x00_get_data_entry_done(ring);
-		if (entry->skb) {
-			dev_kfree_skb(entry->skb);
-			entry->skb = NULL;
-		}
-		rt2x00_ring_index_done_inc(ring);
-	}
+	return status;
 }
-EXPORT_SYMBOL_GPL(rt2x00usb_beacondone);
+EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
 
 /*
  * TX data handlers.
  */
 static void rt2x00usb_interrupt_txdone(struct urb *urb)
 {
-	struct data_entry *entry = (struct data_entry*)urb->context;
+	struct data_entry *entry = (struct data_entry *)urb->context;
 	struct data_ring *ring = entry->ring;
 	struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
 	struct data_desc *txd = (struct data_desc *)entry->skb->data;
@@ -231,19 +148,18 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
 	 */
 	if (!rt2x00_ring_full(ring))
 		ieee80211_wake_queue(rt2x00dev->hw,
-			entry->tx_status.control.queue);
+				     entry->tx_status.control.queue);
 }
 
 int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
-	struct data_ring *ring, struct sk_buff *skb,
-	struct ieee80211_tx_control *control)
+			    struct data_ring *ring, struct sk_buff *skb,
+			    struct ieee80211_tx_control *control)
 {
 	struct usb_device *usb_dev =
-		interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
-	struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr*)skb->data;
+	    interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
 	struct data_entry *entry = rt2x00_get_data_entry(ring);
-	struct data_desc *txd;
-	u32 length = skb->len;
+	int pipe = usb_sndbulkpipe(usb_dev, 1);
+	u32 length;
 
 	if (rt2x00_ring_full(ring)) {
 		ieee80211_stop_queue(rt2x00dev->hw, control->queue);
@@ -252,37 +168,39 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
 
 	if (test_bit(ENTRY_OWNER_NIC, &entry->flags)) {
 		ERROR(rt2x00dev,
-			"Arrived at non-free entry in the non-full queue %d.\n"
-			"Please file bug report to %s.\n",
-			control->queue, DRV_PROJECT);
-		ieee80211_stop_queue( rt2x00dev->hw, control->queue);
+		      "Arrived at non-free entry in the non-full queue %d.\n"
+		      "Please file bug report to %s.\n",
+		      control->queue, DRV_PROJECT);
+		ieee80211_stop_queue(rt2x00dev->hw, control->queue);
 		return -EINVAL;
 	}
 
-	skb_push(skb, rt2x00dev->hw->extra_tx_headroom);
-	txd = (struct data_desc*)skb->data;
-	rt2x00lib_write_tx_desc(rt2x00dev, entry, txd, ieee80211hdr,
-		length, control);
+	/*
+	 * Add the descriptor in front of the skb.
+	 */
+	skb_push(skb, ring->desc_size);
+	memset(skb->data, 0, ring->desc_size);
+
+	rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data,
+				(struct ieee80211_hdr *)(skb->data +
+							 ring->desc_size),
+				skb->len - ring->desc_size, control);
 	memcpy(&entry->tx_status.control, control, sizeof(*control));
 	entry->skb = skb;
 
 	/*
-	 * Length passed to usb_fill_urb cannot be an odd number,
-	 * so add 1 byte to make it even.
+	 * USB devices cannot blindly pass the skb->len as the
+	 * length of the data to usb_fill_bulk_urb. Pass the skb
+	 * to the driver to determine what the length should be.
 	 */
-	length += rt2x00dev->hw->extra_tx_headroom;
-	if (length % 2)
-		length++;
+	length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, skb);
 
+	/*
+	 * Initialize URB and send the frame to the device.
+	 */
 	__set_bit(ENTRY_OWNER_NIC, &entry->flags);
-	usb_fill_bulk_urb(
-		entry->priv,
-		usb_dev,
-		usb_sndbulkpipe(usb_dev, 1),
-		skb->data,
-		length,
-		rt2x00usb_interrupt_txdone,
-		entry);
+	usb_fill_bulk_urb(entry->priv, usb_dev, pipe,
+			  skb->data, length, rt2x00usb_interrupt_txdone, entry);
 	usb_submit_urb(entry->priv, GFP_ATOMIC);
 
 	rt2x00_ring_index_inc(ring);
@@ -299,13 +217,14 @@ EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
  */
 static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 {
-	struct data_entry *entry = (struct data_entry*)urb->context;
+	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;
+	struct sk_buff *skb;
+	struct ieee80211_hdr *hdr;
+	struct rxdata_entry_desc desc;
+	int header_size;
+	int frame_size;
 
 	if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) ||
 	    !test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags))
@@ -319,21 +238,56 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
 	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)
+	memset(&desc, 0x00, sizeof(desc));
+	rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
+
+	/*
+	 * Allocate a new sk buffer to replace the current one.
+	 * If allocation fails, we should drop the current frame
+	 * so we can recycle the existing sk buffer for the new frame.
+	 * As alignment we use 2 and not NET_IP_ALIGN because we need
+	 * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN
+	 * can be 0 on some hardware). We use these 2 bytes for frame
+	 * alignment later, we assume that the chance that
+	 * header_size % 4 == 2 is bigger then header_size % 2 == 0
+	 * and thus optimize alignment by reserving the 2 bytes in
+	 * advance.
+	 */
+	frame_size = entry->ring->data_size + entry->ring->desc_size;
+	skb = dev_alloc_skb(frame_size + 2);
+	if (!skb)
 		goto skip_entry;
 
+	skb_reserve(skb, 2);
+	skb_put(skb, frame_size);
+
 	/*
-	 * Trim the skb_buffer to only contain the valid
-	 * frame data (so ignore the device's descriptor).
+	 * The data behind the ieee80211 header must be
+	 * aligned on a 4 byte boundary.
+	 * After that trim the entire buffer down to only
+	 * contain the valid frame data excluding the device
+	 * descriptor.
 	 */
-	skb_trim(entry->skb, size);
+	hdr = (struct ieee80211_hdr *)entry->skb->data;
+	header_size =
+	    ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
+
+	if (header_size % 4 == 0) {
+		skb_push(entry->skb, 2);
+		memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
+	}
+	skb_trim(entry->skb, desc.size);
+
+	/*
+	 * Send the frame to rt2x00lib for further processing.
+	 */
+	rt2x00lib_rxdone(entry, entry->skb, &desc);
 
 	/*
-	 * Send the packet to upper layer, and update urb.
+	 * Replace current entry's skb with the newly allocated one,
+	 * and reinitialize the urb.
 	 */
-	rt2x00lib_rxdone(entry, NULL, ring->data_size + ring->desc_size,
-		signal, rssi, ofdm);
+	entry->skb = skb;
 	urb->transfer_buffer = entry->skb->data;
 	urb->transfer_buffer_length = entry->skb->len;
 
@@ -352,7 +306,7 @@ skip_entry:
 void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
 {
 	struct usb_device *usb_dev =
-		interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
+	    interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
 	struct data_ring *ring;
 	struct data_entry *entry;
 	unsigned int i;
@@ -375,14 +329,10 @@ void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
 	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);
+		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);
@@ -395,8 +345,8 @@ 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);
+	rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0x0000, 0x0000,
+				    REGISTER_TIMEOUT);
 
 	/*
 	 * Cancel all rings.
@@ -411,8 +361,8 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
 /*
  * Device initialization handlers.
  */
-static int rt2x00usb_alloc_ring(struct rt2x00_dev *rt2x00dev,
-	struct data_ring *ring)
+static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
+			       struct data_ring *ring)
 {
 	unsigned int i;
 
@@ -428,6 +378,22 @@ static int rt2x00usb_alloc_ring(struct rt2x00_dev *rt2x00dev,
 	return 0;
 }
 
+static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev,
+			       struct data_ring *ring)
+{
+	unsigned int i;
+
+	if (!ring->entry)
+		return;
+
+	for (i = 0; i < ring->stats.limit; i++) {
+		usb_kill_urb(ring->entry[i].priv);
+		usb_free_urb(ring->entry[i].priv);
+		if (ring->entry[i].skb)
+			kfree_skb(ring->entry[i].skb);
+	}
+}
+
 int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
 {
 	struct data_ring *ring;
@@ -440,7 +406,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
 	 * Allocate DMA
 	 */
 	ring_for_each(rt2x00dev, ring) {
-		status = rt2x00usb_alloc_ring(rt2x00dev, ring);
+		status = rt2x00usb_alloc_urb(rt2x00dev, ring);
 		if (status)
 			goto exit;
 	}
@@ -448,7 +414,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * For the RX ring, skb's should be allocated.
 	 */
-	entry_size = ring->data_size + ring->desc_size;
+	entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size;
 	for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
 		skb = dev_alloc_skb(NET_IP_ALIGN + entry_size);
 		if (!skb)
@@ -472,30 +438,56 @@ EXPORT_SYMBOL_GPL(rt2x00usb_initialize);
 void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev)
 {
 	struct data_ring *ring;
-	unsigned int i;
-
-	ring_for_each(rt2x00dev, ring) {
-		if (!ring->entry)
-			continue;
 
-		for (i = 0; i < ring->stats.limit; i++) {
-			usb_kill_urb(ring->entry[i].priv);
-			usb_free_urb(ring->entry[i].priv);
-			if (ring->entry[i].skb)
-				kfree_skb(ring->entry[i].skb);
-		}
-	}
+	ring_for_each(rt2x00dev, ring)
+		rt2x00usb_free_urb(rt2x00dev, ring);
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize);
 
 /*
  * USB driver handlers.
  */
+static void rt2x00usb_free_reg(struct rt2x00_dev *rt2x00dev)
+{
+	kfree(rt2x00dev->rf);
+	rt2x00dev->rf = NULL;
+
+	kfree(rt2x00dev->eeprom);
+	rt2x00dev->eeprom = NULL;
+
+	kfree(rt2x00dev->csr_cache);
+	rt2x00dev->csr_cache = NULL;
+}
+
+static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev)
+{
+	rt2x00dev->csr_cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL);
+	if (!rt2x00dev->csr_cache)
+		goto exit;
+
+	rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
+	if (!rt2x00dev->eeprom)
+		goto exit;
+
+	rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
+	if (!rt2x00dev->rf)
+		goto exit;
+
+	return 0;
+
+exit:
+	ERROR_PROBE("Failed to allocate registers.\n");
+
+	rt2x00usb_free_reg(rt2x00dev);
+
+	return -ENOMEM;
+}
+
 int rt2x00usb_probe(struct usb_interface *usb_intf,
-	const struct usb_device_id *id)
+		    const struct usb_device_id *id)
 {
 	struct usb_device *usb_dev = interface_to_usbdev(usb_intf);
-	struct rt2x00_ops *ops = (struct rt2x00_ops*)id->driver_info;
+	struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info;
 	struct ieee80211_hw *hw;
 	struct rt2x00_dev *rt2x00dev;
 	int retval;
@@ -516,12 +508,24 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
 	rt2x00dev->ops = ops;
 	rt2x00dev->hw = hw;
 
-	retval = rt2x00lib_probe_dev(rt2x00dev);
+	rt2x00dev->usb_maxpacket =
+	    usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1);
+	if (!rt2x00dev->usb_maxpacket)
+		rt2x00dev->usb_maxpacket = 1;
+
+	retval = rt2x00usb_alloc_reg(rt2x00dev);
 	if (retval)
 		goto exit_free_device;
 
+	retval = rt2x00lib_probe_dev(rt2x00dev);
+	if (retval)
+		goto exit_free_reg;
+
 	return 0;
 
+exit_free_reg:
+	rt2x00usb_free_reg(rt2x00dev);
+
 exit_free_device:
 	ieee80211_free_hw(hw);
 
@@ -543,6 +547,7 @@ void rt2x00usb_disconnect(struct usb_interface *usb_intf)
 	 * Free all allocated data.
 	 */
 	rt2x00lib_remove_dev(rt2x00dev);
+	rt2x00usb_free_reg(rt2x00dev);
 	ieee80211_free_hw(hw);
 
 	/*
@@ -564,6 +569,8 @@ int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state)
 	if (retval)
 		return retval;
 
+	rt2x00usb_free_reg(rt2x00dev);
+
 	/*
 	 * Decrease usbdev refcount.
 	 */
@@ -577,10 +584,24 @@ int rt2x00usb_resume(struct usb_interface *usb_intf)
 {
 	struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);
 	struct rt2x00_dev *rt2x00dev = hw->priv;
+	int retval;
 
 	usb_get_dev(interface_to_usbdev(usb_intf));
 
-	return rt2x00lib_resume(rt2x00dev);
+	retval = rt2x00usb_alloc_reg(rt2x00dev);
+	if (retval)
+		return retval;
+
+	retval = rt2x00lib_resume(rt2x00dev);
+	if (retval)
+		goto exit_free_reg;
+
+	return 0;
+
+exit_free_reg:
+	rt2x00usb_free_reg(rt2x00dev);
+
+	return retval;
 }
 EXPORT_SYMBOL_GPL(rt2x00usb_resume);
 #endif /* CONFIG_PM */

+ 71 - 23
package/rt2x00/src/rt2x00usb.h

@@ -21,7 +21,6 @@
 /*
 	Module: rt2x00usb
 	Abstract: Data structures for the rt2x00usb module.
-	Supported chipsets: rt2570, rt2571W & rt2671.
  */
 
 #ifndef RT2X00USB_H
@@ -35,19 +34,25 @@
 
 /*
  * Register defines.
- * When register access attempts should be repeated
- * only REGISTER_BUSY_COUNT attempts with a delay
- * of REGISTER_BUSY_DELAY us should be taken.
+ * Some registers require multiple attempts before success,
+ * in those cases REGISTER_BUSY_COUNT attempts should be
+ * taken with a REGISTER_BUSY_DELAY interval.
  * For USB vendor requests we need to pass a timeout
  * time in ms, for this we use the REGISTER_TIMEOUT,
  * however when loading firmware a higher value is
- * required. For that we use the REGISTER_TIMEOUT_FIRMWARE.
+ * required. In that case we use the REGISTER_TIMEOUT_FIRMWARE.
  */
 #define REGISTER_BUSY_COUNT		5
 #define REGISTER_BUSY_DELAY		100
-#define REGISTER_TIMEOUT		20
+#define REGISTER_TIMEOUT		500
 #define REGISTER_TIMEOUT_FIRMWARE	1000
 
+/*
+ * Cache size
+ */
+#define CSR_CACHE_SIZE			8
+#define CSR_CACHE_SIZE_FIRMWARE		64
+
 /*
  * USB request types.
  */
@@ -80,37 +85,77 @@
 #define USB_MODE_WAKEUP		0x09	/* RT73USB */
 
 /*
- * USB devices need an additional Beacon (guardian beacon) to be generated.
+ * Used to read/write from/to the device.
+ * This is the main function to communicate with the device,
+ * the buffer argument _must_ either be NULL or point to
+ * a buffer allocated by kmalloc. Failure to do so can lead
+ * to unexpected behavior depending on the architecture.
  */
-#undef BEACON_ENTRIES
-#define BEACON_ENTRIES 2
+int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
+			     const u8 request, const u8 requesttype,
+			     const u16 offset, const u16 value,
+			     void *buffer, const u16 buffer_length,
+			     const int timeout);
 
 /*
- * Interfacing with the HW.
+ * Used to read/write from/to the device.
+ * This function will use a previously with kmalloc allocated cache
+ * to communicate with the device. The contents of the buffer pointer
+ * will be copied to this cache when writing, or read from the cache
+ * when reading.
+ * Buffers send to rt2x00usb_vendor_request _must_ be allocated with
+ * kmalloc. Hence the reason for using a previously allocated cache
+ * which has been allocated properly.
  */
-int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
-	const u8 request, const u8 type, const u16 offset,
-	u32 value, void *buffer, const u16 buffer_length, const u16 timeout);
+int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev,
+				  const u8 request, const u8 requesttype,
+				  const u16 offset, void *buffer,
+				  const u16 buffer_length, const int timeout);
 
 /*
- * Radio handlers
+ * Simple wrapper around rt2x00usb_vendor_request to write a single
+ * command to the device. Since we don't use the buffer argument we
+ * don't have to worry about kmalloc here.
  */
-void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev);
-void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
+static inline int rt2x00usb_vendor_request_sw(const struct rt2x00_dev
+					      *rt2x00dev,
+					      const u8 request,
+					      const u16 offset,
+					      const u16 value,
+					      const int timeout)
+{
+	return rt2x00usb_vendor_request(rt2x00dev, request,
+					USB_VENDOR_REQUEST_OUT, offset,
+					value, NULL, 0, timeout);
+}
 
 /*
- * Beacon handlers.
+ * Simple wrapper around rt2x00usb_vendor_request to read the eeprom
+ * from the device. Note that the eeprom argument _must_ be allocated using
+ * kmalloc for correct handling inside the kernel USB layer.
  */
-int rt2x00usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
-	struct ieee80211_tx_control *control);
-void rt2x00usb_beacondone(struct urb *urb);
+static inline int rt2x00usb_eeprom_read(const struct rt2x00_dev *rt2x00dev,
+					 __le16 *eeprom, const u16 lenght)
+{
+	int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16));
+
+	return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
+					USB_VENDOR_REQUEST_IN, 0x0000,
+					0x0000, eeprom, lenght, timeout);
+}
+
+/*
+ * Radio handlers
+ */
+void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev);
+void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
 
 /*
  * TX data handlers.
  */
 int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
-	struct data_ring *ring, struct sk_buff *skb,
-	struct ieee80211_tx_control *control);
+			    struct data_ring *ring, struct sk_buff *skb,
+			    struct ieee80211_tx_control *control);
 
 /*
  * Device initialization handlers.
@@ -122,11 +167,14 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
  * USB driver handlers.
  */
 int rt2x00usb_probe(struct usb_interface *usb_intf,
-	const struct usb_device_id *id);
+		    const struct usb_device_id *id);
 void rt2x00usb_disconnect(struct usb_interface *usb_intf);
 #ifdef CONFIG_PM
 int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state);
 int rt2x00usb_resume(struct usb_interface *usb_intf);
+#else
+#define rt2x00usb_suspend	NULL
+#define rt2x00usb_resume	NULL
 #endif /* CONFIG_PM */
 
 #endif /* RT2X00USB_H */

File diff suppressed because it is too large
+ 371 - 453
package/rt2x00/src/rt61pci.c


+ 119 - 35
package/rt2x00/src/rt61pci.h

@@ -37,9 +37,10 @@
 
 /*
  * Signal information.
+ * Defaul offset is required for RSSI <-> dBm conversion.
  */
+#define MAX_SIGNAL			100
 #define MAX_RX_SSI			-1
-#define MAX_RX_NOISE			-110
 #define DEFAULT_RSSI_OFFSET		120
 
 /*
@@ -50,6 +51,7 @@
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x0100
 #define BBP_SIZE			0x0080
+#define RF_SIZE				0x0014
 
 /*
  * PCI registers.
@@ -260,7 +262,7 @@ struct hw_pairwise_ta_entry {
  * MAC_CSR6: Maximum frame length register.
  */
 #define MAC_CSR6			0x3018
-#define MAC_CSR6_MAX_FRAME_UNIT		FIELD32(0x000007ff)
+#define MAC_CSR6_MAX_FRAME_UNIT		FIELD32(0x00000fff)
 
 /*
  * MAC_CSR7: Reserved
@@ -330,6 +332,11 @@ struct hw_pairwise_ta_entry {
 #define MAC_CSR13_BIT5			FIELD32(0x00000020)
 #define MAC_CSR13_BIT6			FIELD32(0x00000040)
 #define MAC_CSR13_BIT7			FIELD32(0x00000080)
+#define MAC_CSR13_BIT8			FIELD32(0x00000100)
+#define MAC_CSR13_BIT9			FIELD32(0x00000200)
+#define MAC_CSR13_BIT10			FIELD32(0x00000400)
+#define MAC_CSR13_BIT11			FIELD32(0x00000800)
+#define MAC_CSR13_BIT12			FIELD32(0x00001000)
 
 /*
  * MAC_CSR14: LED control register.
@@ -392,16 +399,40 @@ struct hw_pairwise_ta_entry {
  * TXRX_CSR1
  */
 #define TXRX_CSR1			0x3044
+#define TXRX_CSR1_BBP_ID0		FIELD32(0x0000007f)
+#define TXRX_CSR1_BBP_ID0_VALID		FIELD32(0x00000080)
+#define TXRX_CSR1_BBP_ID1		FIELD32(0x00007f00)
+#define TXRX_CSR1_BBP_ID1_VALID		FIELD32(0x00008000)
+#define TXRX_CSR1_BBP_ID2		FIELD32(0x007f0000)
+#define TXRX_CSR1_BBP_ID2_VALID		FIELD32(0x00800000)
+#define TXRX_CSR1_BBP_ID3		FIELD32(0x7f000000)
+#define TXRX_CSR1_BBP_ID3_VALID		FIELD32(0x80000000)
 
 /*
  * TXRX_CSR2
  */
 #define TXRX_CSR2			0x3048
+#define TXRX_CSR2_BBP_ID0		FIELD32(0x0000007f)
+#define TXRX_CSR2_BBP_ID0_VALID		FIELD32(0x00000080)
+#define TXRX_CSR2_BBP_ID1		FIELD32(0x00007f00)
+#define TXRX_CSR2_BBP_ID1_VALID		FIELD32(0x00008000)
+#define TXRX_CSR2_BBP_ID2		FIELD32(0x007f0000)
+#define TXRX_CSR2_BBP_ID2_VALID		FIELD32(0x00800000)
+#define TXRX_CSR2_BBP_ID3		FIELD32(0x7f000000)
+#define TXRX_CSR2_BBP_ID3_VALID		FIELD32(0x80000000)
 
 /*
  * TXRX_CSR3
  */
 #define TXRX_CSR3			0x304c
+#define TXRX_CSR3_BBP_ID0		FIELD32(0x0000007f)
+#define TXRX_CSR3_BBP_ID0_VALID		FIELD32(0x00000080)
+#define TXRX_CSR3_BBP_ID1		FIELD32(0x00007f00)
+#define TXRX_CSR3_BBP_ID1_VALID		FIELD32(0x00008000)
+#define TXRX_CSR3_BBP_ID2		FIELD32(0x007f0000)
+#define TXRX_CSR3_BBP_ID2_VALID		FIELD32(0x00800000)
+#define TXRX_CSR3_BBP_ID3		FIELD32(0x7f000000)
+#define TXRX_CSR3_BBP_ID3_VALID		FIELD32(0x80000000)
 
 /*
  * TXRX_CSR4: Auto-Responder/Tx-retry register.
@@ -428,11 +459,27 @@ struct hw_pairwise_ta_entry {
 #define TXRX_CSR5			0x3054
 
 /*
- * ACK/CTS payload consumed time registers.
+ * TXRX_CSR6: ACK/CTS payload consumed time
  */
 #define TXRX_CSR6			0x3058
+
+/*
+ * TXRX_CSR7: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
+ */
 #define TXRX_CSR7			0x305c
+#define TXRX_CSR7_ACK_CTS_6MBS		FIELD32(0x000000ff)
+#define TXRX_CSR7_ACK_CTS_9MBS		FIELD32(0x0000ff00)
+#define TXRX_CSR7_ACK_CTS_12MBS		FIELD32(0x00ff0000)
+#define TXRX_CSR7_ACK_CTS_18MBS		FIELD32(0xff000000)
+
+/*
+ * TXRX_CSR8: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
+ */
 #define TXRX_CSR8			0x3060
+#define TXRX_CSR8_ACK_CTS_24MBS		FIELD32(0x000000ff)
+#define TXRX_CSR8_ACK_CTS_36MBS		FIELD32(0x0000ff00)
+#define TXRX_CSR8_ACK_CTS_48MBS		FIELD32(0x00ff0000)
+#define TXRX_CSR8_ACK_CTS_54MBS		FIELD32(0xff000000)
 
 /*
  * TXRX_CSR9: Synchronization control register.
@@ -481,7 +528,6 @@ struct hw_pairwise_ta_entry {
  */
 #define TXRX_CSR15			0x307c
 
-
 /*
  * PHY control registers.
  * Some values are set in TU, whereas 1 TU == 1024 us.
@@ -536,11 +582,13 @@ struct hw_pairwise_ta_entry {
  * PHY_CSR5: RX to TX signal switch timing control.
  */
 #define PHY_CSR5			0x3094
+#define PHY_CSR5_IQ_FLIP		FIELD32(0x00000004)
 
 /*
  * PHY_CSR6: TX to RX signal timing control.
  */
 #define PHY_CSR6			0x3098
+#define PHY_CSR6_IQ_FLIP		FIELD32(0x00000004)
 
 /*
  * PHY_CSR7: TX DAC switching timing control.
@@ -555,6 +603,22 @@ struct hw_pairwise_ta_entry {
  * SEC_CSR0: Shared key table control.
  */
 #define SEC_CSR0			0x30a0
+#define SEC_CSR0_BSS0_KEY0_VALID	FIELD32(0x00000001)
+#define SEC_CSR0_BSS0_KEY1_VALID	FIELD32(0x00000002)
+#define SEC_CSR0_BSS0_KEY2_VALID	FIELD32(0x00000004)
+#define SEC_CSR0_BSS0_KEY3_VALID	FIELD32(0x00000008)
+#define SEC_CSR0_BSS1_KEY0_VALID	FIELD32(0x00000010)
+#define SEC_CSR0_BSS1_KEY1_VALID	FIELD32(0x00000020)
+#define SEC_CSR0_BSS1_KEY2_VALID	FIELD32(0x00000040)
+#define SEC_CSR0_BSS1_KEY3_VALID	FIELD32(0x00000080)
+#define SEC_CSR0_BSS2_KEY0_VALID	FIELD32(0x00000100)
+#define SEC_CSR0_BSS2_KEY1_VALID	FIELD32(0x00000200)
+#define SEC_CSR0_BSS2_KEY2_VALID	FIELD32(0x00000400)
+#define SEC_CSR0_BSS2_KEY3_VALID	FIELD32(0x00000800)
+#define SEC_CSR0_BSS3_KEY0_VALID	FIELD32(0x00001000)
+#define SEC_CSR0_BSS3_KEY1_VALID	FIELD32(0x00002000)
+#define SEC_CSR0_BSS3_KEY2_VALID	FIELD32(0x00004000)
+#define SEC_CSR0_BSS3_KEY3_VALID	FIELD32(0x00008000)
 
 /*
  * SEC_CSR1: Shared key table security mode register.
@@ -768,9 +832,15 @@ struct hw_pairwise_ta_entry {
 #define CWMAX_CSR_CWMAX3		FIELD32(0x0000f000)
 
 /*
- * TX_DMA_DST_CSR
+ * TX_DMA_DST_CSR: TX DMA destination
+ * 0: TX ring0, 1: TX ring1, 2: TX ring2 3: invalid
  */
 #define TX_DMA_DST_CSR			0x342c
+#define TX_DMA_DST_CSR_DEST_AC0		FIELD32(0x00000003)
+#define TX_DMA_DST_CSR_DEST_AC1		FIELD32(0x0000000c)
+#define TX_DMA_DST_CSR_DEST_AC2		FIELD32(0x00000030)
+#define TX_DMA_DST_CSR_DEST_AC3		FIELD32(0x000000c0)
+#define TX_DMA_DST_CSR_DEST_MGMT	FIELD32(0x00000300)
 
 /*
  * TX_CNTL_CSR: KICK/Abort TX.
@@ -796,9 +866,14 @@ struct hw_pairwise_ta_entry {
 #define TX_CNTL_CSR_ABORT_TX_MGMT	FIELD32(0x00100000)
 
 /*
- * LOAD_TX_RING_CSR
+ * LOAD_TX_RING_CSR: Load RX de
  */
 #define LOAD_TX_RING_CSR		0x3434
+#define LOAD_TX_RING_CSR_LOAD_TXD_AC0	FIELD32(0x00000001)
+#define LOAD_TX_RING_CSR_LOAD_TXD_AC1	FIELD32(0x00000002)
+#define LOAD_TX_RING_CSR_LOAD_TXD_AC2	FIELD32(0x00000004)
+#define LOAD_TX_RING_CSR_LOAD_TXD_AC3	FIELD32(0x00000008)
+#define LOAD_TX_RING_CSR_LOAD_TXD_MGMT	FIELD32(0x00000010)
 
 /*
  * Several read-only registers, for debugging.
@@ -828,6 +903,8 @@ struct hw_pairwise_ta_entry {
  * RX_CNTL_CSR
  */
 #define RX_CNTL_CSR			0x3458
+#define RX_CNTL_CSR_ENABLE_RX_DMA	FIELD32(0x00000001)
+#define RX_CNTL_CSR_LOAD_RXD		FIELD32(0x00000002)
 
 /*
  * RXPTR_CSR: Read-only, for debugging.
@@ -981,10 +1058,45 @@ struct hw_pairwise_ta_entry {
 #define FIRMWARE_RT2661			"rt2661.bin"
 #define FIRMWARE_IMAGE_BASE		0x4000
 
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * R2
+ */
+#define BBP_R2_BG_MODE			FIELD8(0x20)
+
+/*
+ * R3
+ */
+#define BBP_R3_SMART_MODE		FIELD8(0x01)
+
+/*
+ * R4: RX antenna control
+ * FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
+ */
+#define BBP_R4_RX_ANTENNA		FIELD8(0x03)
+#define BBP_R4_RX_FRAME_END		FIELD8(0x20)
+
+/*
+ * R77
+ */
+#define BBP_R77_PAIR			FIELD8(0x03)
+
 /*
  * RF registers
  */
+
+/*
+ * RF 3
+ */
 #define RF3_TXPOWER			FIELD32(0x00003e00)
+
+/*
+ * RF 4
+ */
 #define RF4_FREQ_OFFSET			FIELD32(0x0003f000)
 
 /*
@@ -1117,34 +1229,6 @@ struct hw_pairwise_ta_entry {
 #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.
- */
-
-/*
- * BBP_R2
- */
-#define BBP_R2_BG_MODE			FIELD8(0x20)
-
-/*
- * BBP_R3
- */
-#define BBP_R3_SMART_MODE		FIELD8(0x01)
-
-/*
- * BBP_R4: RX antenna control
- * FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
- */
-#define BBP_R4_RX_ANTENNA		FIELD8(0x03)
-#define BBP_R4_RX_FRAME_END		FIELD8(0x10)
-#define BBP_R4_RX_BG_MODE		FIELD8(0x20)
-
-/*
- * BBP_R77
- */
-#define BBP_R77_PAIR			FIELD8(0x03)
-
 /*
  * MCU mailbox commands.
  */
@@ -1290,7 +1374,7 @@ struct hw_pairwise_ta_entry {
 #define RXD_W0_MULTICAST		FIELD32(0x00000008)
 #define RXD_W0_BROADCAST		FIELD32(0x00000010)
 #define RXD_W0_MY_BSS			FIELD32(0x00000020)
-#define RXD_W0_CRC			FIELD32(0x00000040)
+#define RXD_W0_CRC_ERROR		FIELD32(0x00000040)
 #define RXD_W0_OFDM			FIELD32(0x00000080)
 #define RXD_W0_CIPHER_ERROR		FIELD32(0x00000300)
 #define RXD_W0_KEY_INDEX		FIELD32(0x0000fc00)

File diff suppressed because it is too large
+ 350 - 447
package/rt2x00/src/rt73usb.c


+ 100 - 34
package/rt2x00/src/rt73usb.h

@@ -37,9 +37,10 @@
 
 /*
  * Signal information.
+ * Defaul offset is required for RSSI <-> dBm conversion.
  */
+#define MAX_SIGNAL			100
 #define MAX_RX_SSI			-1
-#define MAX_RX_NOISE			-110
 #define DEFAULT_RSSI_OFFSET		120
 
 /*
@@ -50,6 +51,7 @@
 #define EEPROM_BASE			0x0000
 #define EEPROM_SIZE			0x0100
 #define BBP_SIZE			0x0080
+#define RF_SIZE				0x0014
 
 /*
  * USB registers.
@@ -172,7 +174,7 @@ struct hw_pairwise_ta_entry {
  * MAC_CSR6: Maximum frame length register.
  */
 #define MAC_CSR6			0x3018
-#define MAC_CSR6_MAX_FRAME_UNIT		FIELD32(0x000007ff)
+#define MAC_CSR6_MAX_FRAME_UNIT		FIELD32(0x00000fff)
 
 /*
  * MAC_CSR7: Reserved
@@ -288,7 +290,7 @@ struct hw_pairwise_ta_entry {
 #define TXRX_CSR0_DROP_TO_DS		FIELD32(0x00200000)
 #define TXRX_CSR0_DROP_VERSION_ERROR	FIELD32(0x00400000)
 #define TXRX_CSR0_DROP_MULTICAST	FIELD32(0x00800000)
-#define TXRX_CSR0_DROP_BORADCAST	FIELD32(0x01000000)
+#define TXRX_CSR0_DROP_BROADCAST	FIELD32(0x01000000)
 #define TXRX_CSR0_DROP_ACK_CTS		FIELD32(0x02000000)
 #define TXRX_CSR0_TX_WITHOUT_WAITING	FIELD32(0x04000000)
 
@@ -296,16 +298,40 @@ struct hw_pairwise_ta_entry {
  * TXRX_CSR1
  */
 #define TXRX_CSR1			0x3044
+#define TXRX_CSR1_BBP_ID0		FIELD32(0x0000007f)
+#define TXRX_CSR1_BBP_ID0_VALID		FIELD32(0x00000080)
+#define TXRX_CSR1_BBP_ID1		FIELD32(0x00007f00)
+#define TXRX_CSR1_BBP_ID1_VALID		FIELD32(0x00008000)
+#define TXRX_CSR1_BBP_ID2		FIELD32(0x007f0000)
+#define TXRX_CSR1_BBP_ID2_VALID		FIELD32(0x00800000)
+#define TXRX_CSR1_BBP_ID3		FIELD32(0x7f000000)
+#define TXRX_CSR1_BBP_ID3_VALID		FIELD32(0x80000000)
 
 /*
  * TXRX_CSR2
  */
 #define TXRX_CSR2			0x3048
+#define TXRX_CSR2_BBP_ID0		FIELD32(0x0000007f)
+#define TXRX_CSR2_BBP_ID0_VALID		FIELD32(0x00000080)
+#define TXRX_CSR2_BBP_ID1		FIELD32(0x00007f00)
+#define TXRX_CSR2_BBP_ID1_VALID		FIELD32(0x00008000)
+#define TXRX_CSR2_BBP_ID2		FIELD32(0x007f0000)
+#define TXRX_CSR2_BBP_ID2_VALID		FIELD32(0x00800000)
+#define TXRX_CSR2_BBP_ID3		FIELD32(0x7f000000)
+#define TXRX_CSR2_BBP_ID3_VALID		FIELD32(0x80000000)
 
 /*
  * TXRX_CSR3
  */
 #define TXRX_CSR3			0x304c
+#define TXRX_CSR3_BBP_ID0		FIELD32(0x0000007f)
+#define TXRX_CSR3_BBP_ID0_VALID		FIELD32(0x00000080)
+#define TXRX_CSR3_BBP_ID1		FIELD32(0x00007f00)
+#define TXRX_CSR3_BBP_ID1_VALID		FIELD32(0x00008000)
+#define TXRX_CSR3_BBP_ID2		FIELD32(0x007f0000)
+#define TXRX_CSR3_BBP_ID2_VALID		FIELD32(0x00800000)
+#define TXRX_CSR3_BBP_ID3		FIELD32(0x7f000000)
+#define TXRX_CSR3_BBP_ID3_VALID		FIELD32(0x80000000)
 
 /*
  * TXRX_CSR4: Auto-Responder/Tx-retry register.
@@ -332,11 +358,27 @@ struct hw_pairwise_ta_entry {
 #define TXRX_CSR5			0x3054
 
 /*
- * ACK/CTS payload consumed time registers.
+ * TXRX_CSR6: ACK/CTS payload consumed time
  */
 #define TXRX_CSR6			0x3058
+
+/*
+ * TXRX_CSR7: OFDM ACK/CTS payload consumed time for 6/9/12/18 mbps.
+ */
 #define TXRX_CSR7			0x305c
+#define TXRX_CSR7_ACK_CTS_6MBS		FIELD32(0x000000ff)
+#define TXRX_CSR7_ACK_CTS_9MBS		FIELD32(0x0000ff00)
+#define TXRX_CSR7_ACK_CTS_12MBS		FIELD32(0x00ff0000)
+#define TXRX_CSR7_ACK_CTS_18MBS		FIELD32(0xff000000)
+
+/*
+ * TXRX_CSR8: OFDM ACK/CTS payload consumed time for 24/36/48/54 mbps.
+ */
 #define TXRX_CSR8			0x3060
+#define TXRX_CSR8_ACK_CTS_24MBS		FIELD32(0x000000ff)
+#define TXRX_CSR8_ACK_CTS_36MBS		FIELD32(0x0000ff00)
+#define TXRX_CSR8_ACK_CTS_48MBS		FIELD32(0x00ff0000)
+#define TXRX_CSR8_ACK_CTS_54MBS		FIELD32(0xff000000)
 
 /*
  * TXRX_CSR9: Synchronization control register.
@@ -403,7 +445,6 @@ struct hw_pairwise_ta_entry {
 #define PHY_CSR1			0x3084
 #define PHY_CSR1_RF_RPI			FIELD32(0x00010000)
 
-
 /*
  * PHY_CSR2: Pre-TX BBP control.
  */
@@ -441,11 +482,13 @@ struct hw_pairwise_ta_entry {
  * PHY_CSR5: RX to TX signal switch timing control.
  */
 #define PHY_CSR5			0x3094
+#define PHY_CSR5_IQ_FLIP		FIELD32(0x00000004)
 
 /*
  * PHY_CSR6: TX to RX signal timing control.
  */
 #define PHY_CSR6			0x3098
+#define PHY_CSR6_IQ_FLIP		FIELD32(0x00000004)
 
 /*
  * PHY_CSR7: TX DAC switching timing control.
@@ -460,6 +503,22 @@ struct hw_pairwise_ta_entry {
  * SEC_CSR0: Shared key table control.
  */
 #define SEC_CSR0			0x30a0
+#define SEC_CSR0_BSS0_KEY0_VALID	FIELD32(0x00000001)
+#define SEC_CSR0_BSS0_KEY1_VALID	FIELD32(0x00000002)
+#define SEC_CSR0_BSS0_KEY2_VALID	FIELD32(0x00000004)
+#define SEC_CSR0_BSS0_KEY3_VALID	FIELD32(0x00000008)
+#define SEC_CSR0_BSS1_KEY0_VALID	FIELD32(0x00000010)
+#define SEC_CSR0_BSS1_KEY1_VALID	FIELD32(0x00000020)
+#define SEC_CSR0_BSS1_KEY2_VALID	FIELD32(0x00000040)
+#define SEC_CSR0_BSS1_KEY3_VALID	FIELD32(0x00000080)
+#define SEC_CSR0_BSS2_KEY0_VALID	FIELD32(0x00000100)
+#define SEC_CSR0_BSS2_KEY1_VALID	FIELD32(0x00000200)
+#define SEC_CSR0_BSS2_KEY2_VALID	FIELD32(0x00000400)
+#define SEC_CSR0_BSS2_KEY3_VALID	FIELD32(0x00000800)
+#define SEC_CSR0_BSS3_KEY0_VALID	FIELD32(0x00001000)
+#define SEC_CSR0_BSS3_KEY1_VALID	FIELD32(0x00002000)
+#define SEC_CSR0_BSS3_KEY2_VALID	FIELD32(0x00004000)
+#define SEC_CSR0_BSS3_KEY3_VALID	FIELD32(0x00008000)
 
 /*
  * SEC_CSR1: Shared key table security mode register.
@@ -635,10 +694,45 @@ struct hw_pairwise_ta_entry {
 #define AC_TXOP_CSR1_AC2_TX_OP		FIELD32(0x0000ffff)
 #define AC_TXOP_CSR1_AC3_TX_OP		FIELD32(0xffff0000)
 
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * R2
+ */
+#define BBP_R2_BG_MODE			FIELD8(0x20)
+
+/*
+ * R3
+ */
+#define BBP_R3_SMART_MODE		FIELD8(0x01)
+
+/*
+ * R4: RX antenna control
+ * FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
+ */
+#define BBP_R4_RX_ANTENNA		FIELD8(0x03)
+#define BBP_R4_RX_FRAME_END		FIELD8(0x20)
+
+/*
+ * R77
+ */
+#define BBP_R77_PAIR			FIELD8(0x03)
+
 /*
  * RF registers
  */
+
+/*
+ * RF 3
+ */
 #define RF3_TXPOWER			FIELD32(0x00003e00)
+
+/*
+ * RF 4
+ */
 #define RF4_FREQ_OFFSET			FIELD32(0x0003f000)
 
 /*
@@ -763,34 +857,6 @@ struct hw_pairwise_ta_entry {
 #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.
- */
-
-/*
- * BBP_R2
- */
-#define BBP_R2_BG_MODE			FIELD8(0x20)
-
-/*
- * BBP_R3
- */
-#define BBP_R3_SMART_MODE		FIELD8(0x01)
-
-/*
- * BBP_R4: RX antenna control
- * FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
- */
-#define BBP_R4_RX_ANTENNA		FIELD8(0x03)
-#define BBP_R4_RX_FRAME_END		FIELD8(0x10)
-#define BBP_R4_RX_BG_MODE		FIELD8(0x20)
-
-/*
- * BBP_R77
- */
-#define BBP_R77_PAIR			FIELD8(0x03)
-
 /*
  * DMA descriptor defines.
  */
@@ -888,7 +954,7 @@ struct hw_pairwise_ta_entry {
 #define RXD_W0_MULTICAST		FIELD32(0x00000008)
 #define RXD_W0_BROADCAST		FIELD32(0x00000010)
 #define RXD_W0_MY_BSS			FIELD32(0x00000020)
-#define RXD_W0_CRC			FIELD32(0x00000040)
+#define RXD_W0_CRC_ERROR		FIELD32(0x00000040)
 #define RXD_W0_OFDM			FIELD32(0x00000080)
 #define RXD_W0_CIPHER_ERROR		FIELD32(0x00000300)
 #define RXD_W0_KEY_INDEX		FIELD32(0x0000fc00)

Some files were not shown because too many files changed in this diff