diff options
author | florian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-03-09 10:55:19 +0000 |
---|---|---|
committer | florian <florian@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-03-09 10:55:19 +0000 |
commit | bffb95528ca22369393a9fc721606caeec785643 (patch) | |
tree | 5c186939d554f7059ba415f8961de8250f4e7282 /package/rt2x00 | |
parent | eccad93958b05e35a0d88555d0ba43463ed9b09f (diff) |
Fix rt2x00 compilation and upgrade to the current mainline version (2.6.24)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10573 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'package/rt2x00')
27 files changed, 6794 insertions, 5095 deletions
diff --git a/package/rt2x00/Makefile b/package/rt2x00/Makefile index 4d63963bc8..0f6e55d236 100644 --- a/package/rt2x00/Makefile +++ b/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 diff --git a/package/rt2x00/src/Makefile b/package/rt2x00/src/Makefile index 97a88311ce..cc4d1dc405 100644 --- a/package/rt2x00/src/Makefile +++ b/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 diff --git a/package/rt2x00/src/rt2400pci.c b/package/rt2x00/src/rt2400pci.c index 824c8233e8..31c1dd2716 100644 --- a/package/rt2x00/src/rt2400pci.c +++ b/package/rt2x00/src/rt2400pci.c @@ -29,20 +29,15 @@ */ #define DRV_NAME "rt2400pci" +#include <linux/delay.h> +#include <linux/etherdevice.h> +#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> -#include <linux/init.h> #include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/delay.h> -#include <linux/etherdevice.h> #include <linux/eeprom_93cx6.h> -#include <asm/io.h> - #include "rt2x00.h" -#include "rt2x00lib.h" #include "rt2x00pci.h" #include "rt2400pci.h" @@ -75,12 +70,12 @@ static u32 rt2400pci_bbp_check(const struct rt2x00_dev *rt2x00dev) } static void rt2400pci_bbp_write(const struct rt2x00_dev *rt2x00dev, - const u8 reg_id, const u8 value) + const unsigned int word, const u8 value) { u32 reg; /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt2400pci_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { @@ -93,7 +88,7 @@ static void rt2400pci_bbp_write(const struct rt2x00_dev *rt2x00dev, */ reg = 0; rt2x00_set_field32(®, BBPCSR_VALUE, value); - rt2x00_set_field32(®, BBPCSR_REGNUM, reg_id); + rt2x00_set_field32(®, BBPCSR_REGNUM, word); rt2x00_set_field32(®, BBPCSR_BUSY, 1); rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); @@ -101,12 +96,12 @@ static void rt2400pci_bbp_write(const struct rt2x00_dev *rt2x00dev, } static void rt2400pci_bbp_read(const struct rt2x00_dev *rt2x00dev, - const u8 reg_id, u8 *value) + const unsigned int word, u8 *value) { u32 reg; /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt2400pci_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { @@ -118,14 +113,14 @@ static void rt2400pci_bbp_read(const struct rt2x00_dev *rt2x00dev, * Write the request into the BBP. */ reg = 0; - rt2x00_set_field32(®, BBPCSR_REGNUM, reg_id); + rt2x00_set_field32(®, BBPCSR_REGNUM, word); rt2x00_set_field32(®, BBPCSR_BUSY, 1); rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt2400pci_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { @@ -138,11 +133,14 @@ static void rt2400pci_bbp_read(const struct rt2x00_dev *rt2x00dev, } static void rt2400pci_rf_write(const struct rt2x00_dev *rt2x00dev, - const u32 value) + const unsigned int word, const u32 value) { u32 reg; unsigned int i; + if (!word) + return; + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2x00pci_register_read(rt2x00dev, RFCSR, ®); if (!rt2x00_get_field32(reg, RFCSR_BUSY)) @@ -161,6 +159,7 @@ rf_write: rt2x00_set_field32(®, RFCSR_BUSY, 1); rt2x00pci_register_write(rt2x00dev, RFCSR, reg); + rt2x00_rf_write(rt2x00dev, word, value); } static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom) @@ -170,14 +169,12 @@ static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom) rt2x00pci_register_read(rt2x00dev, CSR21, ®); - eeprom->reg_data_in = !!rt2x00_get_field32(reg, - CSR21_EEPROM_DATA_IN); - eeprom->reg_data_out = !!rt2x00_get_field32(reg, - CSR21_EEPROM_DATA_OUT); - eeprom->reg_data_clock = !!rt2x00_get_field32(reg, - CSR21_EEPROM_DATA_CLOCK); - eeprom->reg_chip_select = !!rt2x00_get_field32(reg, - CSR21_EEPROM_CHIP_SELECT); + eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN); + eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT); + eeprom->reg_data_clock = + !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_CLOCK); + eeprom->reg_chip_select = + !!rt2x00_get_field32(reg, CSR21_EEPROM_CHIP_SELECT); } static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom) @@ -185,14 +182,12 @@ static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom) struct rt2x00_dev *rt2x00dev = eeprom->data; u32 reg = 0; - rt2x00_set_field32(®, CSR21_EEPROM_DATA_IN, - !!eeprom->reg_data_in); - rt2x00_set_field32(®, CSR21_EEPROM_DATA_OUT, - !!eeprom->reg_data_out); + rt2x00_set_field32(®, CSR21_EEPROM_DATA_IN, !!eeprom->reg_data_in); + rt2x00_set_field32(®, CSR21_EEPROM_DATA_OUT, !!eeprom->reg_data_out); rt2x00_set_field32(®, CSR21_EEPROM_DATA_CLOCK, - !!eeprom->reg_data_clock); + !!eeprom->reg_data_clock); rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT, - !!eeprom->reg_chip_select); + !!eeprom->reg_chip_select); rt2x00pci_register_write(rt2x00dev, CSR21, reg); } @@ -200,62 +195,44 @@ static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom) #ifdef CONFIG_RT2X00_LIB_DEBUGFS #define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) ) -static void rt2400pci_read_csr(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) +static void rt2400pci_read_csr(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 *data) { rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data); } -static void rt2400pci_write_csr(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), *((u32*)data)); -} - -static void rt2400pci_read_eeprom(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2x00_eeprom_read(rt2x00dev, word, data); -} - -static void rt2400pci_write_eeprom(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) +static void rt2400pci_write_csr(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 data) { - rt2x00_eeprom_write(rt2x00dev, word, *((u16*)data)); -} - -static void rt2400pci_read_bbp(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2400pci_bbp_read(rt2x00dev, word, data); -} - -static void rt2400pci_write_bbp(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2400pci_bbp_write(rt2x00dev, word, *((u8*)data)); + rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data); } static const struct rt2x00debug rt2400pci_rt2x00debug = { - .owner = THIS_MODULE, - .reg_csr = { + .owner = THIS_MODULE, + .csr = { .read = rt2400pci_read_csr, .write = rt2400pci_write_csr, .word_size = sizeof(u32), .word_count = CSR_REG_SIZE / sizeof(u32), }, - .reg_eeprom = { - .read = rt2400pci_read_eeprom, - .write = rt2400pci_write_eeprom, + .eeprom = { + .read = rt2x00_eeprom_read, + .write = rt2x00_eeprom_write, .word_size = sizeof(u16), .word_count = EEPROM_SIZE / sizeof(u16), }, - .reg_bbp = { - .read = rt2400pci_read_bbp, - .write = rt2400pci_write_bbp, + .bbp = { + .read = rt2400pci_bbp_read, + .write = rt2400pci_bbp_write, .word_size = sizeof(u8), .word_count = BBP_SIZE / sizeof(u8), }, + .rf = { + .read = rt2x00_rf_read, + .write = rt2400pci_rf_write, + .word_size = sizeof(u32), + .word_count = RF_SIZE / sizeof(u32), + }, }; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ @@ -267,110 +244,114 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); return rt2x00_get_field32(reg, GPIOCSR_BIT0); } +#else +#define rt2400pci_rfkill_poll NULL #endif /* CONFIG_RT2400PCI_RFKILL */ /* * Configuration handlers. */ -static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) +static void rt2400pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, + __le32 *mac) { - u32 reg[2]; - - memset(®, 0, sizeof(reg)); - memcpy(®, bssid, ETH_ALEN); - - /* - * The BSSID is passed to us as an array of bytes, - * that array is little endian, so no need for byte ordering. - */ - rt2x00pci_register_multiwrite(rt2x00dev, CSR5, ®, sizeof(reg)); + rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac, + (2 * sizeof(__le32))); } -static void rt2400pci_config_promisc(struct rt2x00_dev *rt2x00dev, - const int promisc) +static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev, + __le32 *bssid) { - u32 reg; - - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, !promisc); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); + rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid, + (2 * sizeof(__le32))); } -static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, int type) +static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, + const int tsf_sync) { u32 reg; rt2x00pci_register_write(rt2x00dev, CSR14, 0); /* - * Apply hardware packet filter. - */ - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - - if (!is_monitor_present(&rt2x00dev->interface) && - (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA)) - rt2x00_set_field32(®, RXCSR0_DROP_TODS, 1); - else - rt2x00_set_field32(®, RXCSR0_DROP_TODS, 0); - - rt2x00_set_field32(®, RXCSR0_DROP_CRC, 1); - if (is_monitor_present(&rt2x00dev->interface)) { - rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 0); - rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 0); - rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 0); - } else { - rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 1); - rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 1); - rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); - } - - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); - - /* * Enable beacon config */ rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); rt2x00_set_field32(®, BCNCSR1_PRELOAD, - PREAMBLE + get_duration(IEEE80211_HEADER, 2)); + PREAMBLE + get_duration(IEEE80211_HEADER, 20)); rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); /* * Enable synchronisation. */ rt2x00pci_register_read(rt2x00dev, CSR14, ®); - if (is_interface_present(&rt2x00dev->interface)) { - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, 1); - } - + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, 1); rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - if (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_AP) - rt2x00_set_field32(®, CSR14_TSF_SYNC, 2); - else if (type == IEEE80211_IF_TYPE_STA) - rt2x00_set_field32(®, CSR14_TSF_SYNC, 1); - else if (is_monitor_present(&rt2x00dev->interface) && - !is_interface_present(&rt2x00dev->interface)) - rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); - + rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync); rt2x00pci_register_write(rt2x00dev, CSR14, reg); } -static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev, - const int value, const int channel, const int txpower) +static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) +{ + int preamble_mask; + u32 reg; + + /* + * When short preamble is enabled, we should set bit 0x08 + */ + preamble_mask = short_preamble << 3; + + rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); + rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, ack_timeout); + rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, ack_consume_time); + rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); + rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00 | preamble_mask); + rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10)); + rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); + rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); + rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20)); + rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); + rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); + rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55)); + rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); + rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); + rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); + rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); + rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); +} + +static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev, + const int basic_rate_mask) { - u32 rf1 = rt2x00dev->rf1; - u32 rf2 = value; - u32 rf3 = rt2x00dev->rf3; + rt2x00pci_register_write(rt2x00dev, ARCSR1, basic_rate_mask); +} +static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev, + struct rf_channel *rf) +{ /* * Switch on tuning bits. */ - rt2x00_set_field32(&rf1, RF1_TUNER, 1); - rt2x00_set_field32(&rf3, RF3_TUNER, 1); + rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); + rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); - rt2400pci_rf_write(rt2x00dev, rf1); - rt2400pci_rf_write(rt2x00dev, rf2); - rt2400pci_rf_write(rt2x00dev, rf3); + rt2400pci_rf_write(rt2x00dev, 1, rf->rf1); + rt2400pci_rf_write(rt2x00dev, 2, rf->rf2); + rt2400pci_rf_write(rt2x00dev, 3, rf->rf3); /* * RF2420 chipset don't need any additional actions. @@ -383,38 +364,31 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev, * reference clock rate to activate auto_tune. * After that we set the value back to the correct channel. */ - rt2400pci_rf_write(rt2x00dev, rf1); - rt2400pci_rf_write(rt2x00dev, 0x000c2a32); - rt2400pci_rf_write(rt2x00dev, rf3); + rt2400pci_rf_write(rt2x00dev, 1, rf->rf1); + rt2400pci_rf_write(rt2x00dev, 2, 0x000c2a32); + rt2400pci_rf_write(rt2x00dev, 3, rf->rf3); msleep(1); - rt2400pci_rf_write(rt2x00dev, rf1); - rt2400pci_rf_write(rt2x00dev, rf2); - rt2400pci_rf_write(rt2x00dev, rf3); + rt2400pci_rf_write(rt2x00dev, 1, rf->rf1); + rt2400pci_rf_write(rt2x00dev, 2, rf->rf2); + rt2400pci_rf_write(rt2x00dev, 3, rf->rf3); msleep(1); /* * Switch off tuning bits. */ - rt2x00_set_field32(&rf1, RF1_TUNER, 0); - rt2x00_set_field32(&rf3, RF3_TUNER, 0); - - rt2400pci_rf_write(rt2x00dev, rf1); - rt2400pci_rf_write(rt2x00dev, rf3); + rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); + rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0); - /* - * Update rf fields - */ - rt2x00dev->rf1 = rf1; - rt2x00dev->rf2 = rf2; - rt2x00dev->rf3 = rf3; + rt2400pci_rf_write(rt2x00dev, 1, rf->rf1); + rt2400pci_rf_write(rt2x00dev, 3, rf->rf3); /* * Clear false CRC during channel switch. */ - rt2x00pci_register_read(rt2x00dev, CNT0, &rf1); + rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1); } static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower) @@ -423,7 +397,7 @@ static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower) } static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev, - int antenna_tx, int antenna_rx) + int antenna_tx, int antenna_rx) { u8 r1; u8 r4; @@ -434,58 +408,56 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev, /* * Configure the TX antenna. */ - if (antenna_tx == ANTENNA_DIVERSITY) + switch (antenna_tx) { + case ANTENNA_SW_DIVERSITY: + case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1); - else if (antenna_tx == ANTENNA_A) + break; + case ANTENNA_A: rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0); - else if (antenna_tx == ANTENNA_B) + break; + case ANTENNA_B: rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2); + break; + } /* * Configure the RX antenna. */ - if (antenna_rx == ANTENNA_DIVERSITY) + switch (antenna_rx) { + case ANTENNA_SW_DIVERSITY: + case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); - else if (antenna_rx == ANTENNA_A) + break; + case ANTENNA_A: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0); - else if (antenna_rx == ANTENNA_B) + break; + case ANTENNA_B: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); + break; + } rt2400pci_bbp_write(rt2x00dev, 4, r4); rt2400pci_bbp_write(rt2x00dev, 1, r1); } -static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev, - struct ieee80211_tx_queue_params *params) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_CWMIN, params->cw_min); - rt2x00_set_field32(®, CSR11_CWMAX, params->cw_max); - rt2x00pci_register_write(rt2x00dev, CSR11, reg); -} - static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev, - int short_slot_time, int beacon_int) + struct rt2x00lib_conf *libconf) { u32 reg; rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_SLOT_TIME, - short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME); + rt2x00_set_field32(®, CSR11_SLOT_TIME, libconf->slot_time); rt2x00pci_register_write(rt2x00dev, CSR11, reg); rt2x00pci_register_read(rt2x00dev, CSR18, ®); - rt2x00_set_field32(®, CSR18_SIFS, SIFS); - rt2x00_set_field32(®, CSR18_PIFS, - short_slot_time ? SHORT_PIFS : PIFS); + rt2x00_set_field32(®, CSR18_SIFS, libconf->sifs); + rt2x00_set_field32(®, CSR18_PIFS, libconf->pifs); rt2x00pci_register_write(rt2x00dev, CSR18, reg); rt2x00pci_register_read(rt2x00dev, CSR19, ®); - rt2x00_set_field32(®, CSR19_DIFS, - short_slot_time ? SHORT_DIFS : DIFS); - rt2x00_set_field32(®, CSR19_EIFS, EIFS); + rt2x00_set_field32(®, CSR19_DIFS, libconf->difs); + rt2x00_set_field32(®, CSR19_EIFS, libconf->eifs); rt2x00pci_register_write(rt2x00dev, CSR19, reg); rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); @@ -494,86 +466,41 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); rt2x00pci_register_read(rt2x00dev, CSR12, ®); - rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, beacon_int * 16); - rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, beacon_int * 16); + rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, + libconf->conf->beacon_int * 16); + rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, + libconf->conf->beacon_int * 16); rt2x00pci_register_write(rt2x00dev, CSR12, reg); } -static void rt2400pci_config_rate(struct rt2x00_dev *rt2x00dev, const int rate) +static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, + const unsigned int flags, + struct rt2x00lib_conf *libconf) { - struct ieee80211_conf *conf = &rt2x00dev->hw->conf; - u32 reg; - u32 preamble; - u16 value; - - preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) - ? SHORT_PREAMBLE : PREAMBLE; - - reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE; - rt2x00pci_register_write(rt2x00dev, ARCSR1, reg); - - rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ? - SHORT_DIFS : DIFS) + - PLCP + preamble + get_duration(ACK_SIZE, 10); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, value); - value = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10); - rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, value); - rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); - - preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 0x08 : 0x00; - - rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); - rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00 | preamble); - rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10)); - rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); - rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble); - rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20)); - rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); - rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble); - rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55)); - rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); - rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble); - rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); - rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); - rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); + if (flags & CONFIG_UPDATE_PHYMODE) + rt2400pci_config_phymode(rt2x00dev, libconf->basic_rates); + if (flags & CONFIG_UPDATE_CHANNEL) + rt2400pci_config_channel(rt2x00dev, &libconf->rf); + if (flags & CONFIG_UPDATE_TXPOWER) + rt2400pci_config_txpower(rt2x00dev, + libconf->conf->power_level); + if (flags & CONFIG_UPDATE_ANTENNA) + rt2400pci_config_antenna(rt2x00dev, + libconf->conf->antenna_sel_tx, + libconf->conf->antenna_sel_rx); + if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) + rt2400pci_config_duration(rt2x00dev, libconf); } -static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev, - const int phymode) -{ - struct ieee80211_hw_mode *mode; - struct ieee80211_rate *rate; - - rt2x00dev->curr_hwmode = HWMODE_B; - - mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode]; - rate = &mode->rates[mode->num_rates - 1]; - - rt2400pci_config_rate(rt2x00dev, rate->val2); -} - -static void rt2400pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *addr) +static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev, + struct ieee80211_tx_queue_params *params) { - u32 reg[2]; - - memset(®, 0, sizeof(reg)); - memcpy(®, addr, ETH_ALEN); + u32 reg; - /* - * The MAC address is passed to us as an array of bytes, - * that array is little endian, so no need for byte ordering. - */ - rt2x00pci_register_multiwrite(rt2x00dev, CSR3, ®, sizeof(reg)); + rt2x00pci_register_read(rt2x00dev, CSR11, ®); + rt2x00_set_field32(®, CSR11_CWMIN, params->cw_min); + rt2x00_set_field32(®, CSR11_CWMAX, params->cw_max); + rt2x00pci_register_write(rt2x00dev, CSR11, reg); } /* @@ -615,10 +542,33 @@ static void rt2400pci_disable_led(struct rt2x00_dev *rt2x00dev) /* * Link tuning */ +static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + u8 bbp; + + /* + * Update FCS error count from register. + */ + rt2x00pci_register_read(rt2x00dev, CNT0, ®); + rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); + + /* + * Update False CCA count from register. + */ + rt2400pci_bbp_read(rt2x00dev, 39, &bbp); + rt2x00dev->link.false_cca = bbp; +} + +static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev) +{ + rt2400pci_bbp_write(rt2x00dev, 13, 0x08); + rt2x00dev->link.vgc_level = 0x08; +} + static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) { u8 reg; - char false_cca_delta; /* * The link tuner should not run longer then 60 seconds, @@ -628,29 +578,16 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) return; /* - * Read false CCA counter. + * Base r13 link tuning on the false cca count. */ - rt2400pci_bbp_read(rt2x00dev, 39, ®); + rt2400pci_bbp_read(rt2x00dev, 13, ®); - /* - * Determine difference with previous CCA counter. - */ - false_cca_delta = reg - rt2x00dev->link.false_cca; - rt2x00dev->link.false_cca = reg; - - /* - * Check if the difference is higher than the - * threshold and if so, tune the link. - */ - if (false_cca_delta >= 8) { - /* - * Read and update RX AGC VGC. - */ - rt2400pci_bbp_read(rt2x00dev, 13, ®); - reg += 2; - if (reg < 0x20) - rt2400pci_bbp_write(rt2x00dev, 13, reg); - rt2x00dev->rx_status.noise = reg; + if (rt2x00dev->link.false_cca > 512 && reg < 0x20) { + rt2400pci_bbp_write(rt2x00dev, 13, ++reg); + rt2x00dev->link.vgc_level = reg; + } else if (rt2x00dev->link.false_cca < 100 && reg > 0x08) { + rt2400pci_bbp_write(rt2x00dev, 13, --reg); + rt2x00dev->link.vgc_level = reg; } } @@ -659,24 +596,24 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) */ static void rt2400pci_init_rxring(struct rt2x00_dev *rt2x00dev) { + struct data_ring *ring = rt2x00dev->rx; struct data_desc *rxd; unsigned int i; u32 word; - memset(rt2x00dev->rx->data_addr, 0x00, - rt2x00_get_ring_size(rt2x00dev->rx)); + memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring)); - for (i = 0; i < rt2x00dev->rx->stats.limit; i++) { - rxd = rt2x00dev->rx->entry[i].priv; + for (i = 0; i < ring->stats.limit; i++) { + rxd = ring->entry[i].priv; rt2x00_desc_read(rxd, 2, &word); rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, - rt2x00dev->rx->data_size); + ring->data_size); rt2x00_desc_write(rxd, 2, word); rt2x00_desc_read(rxd, 1, &word); rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, - rt2x00dev->rx->entry[i].data_dma); + ring->entry[i].data_dma); rt2x00_desc_write(rxd, 1, word); rt2x00_desc_read(rxd, 0, &word); @@ -687,10 +624,9 @@ static void rt2400pci_init_rxring(struct rt2x00_dev *rt2x00dev) rt2x00_ring_index_clear(rt2x00dev->rx); } -static void rt2400pci_init_txring(struct rt2x00_dev *rt2x00dev, - const int queue) +static void rt2400pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue) { - struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue); + struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); struct data_desc *txd; unsigned int i; u32 word; @@ -702,12 +638,12 @@ static void rt2400pci_init_txring(struct rt2x00_dev *rt2x00dev, rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, - ring->entry[i].data_dma); + ring->entry[i].data_dma); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, - ring->data_size); + ring->data_size); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 0, &word); @@ -737,45 +673,43 @@ static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev) */ rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); rt2x00_set_field32(®, TXCSR2_TXD_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size); rt2x00_set_field32(®, TXCSR2_NUM_TXD, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); rt2x00_set_field32(®, TXCSR2_NUM_ATIM, - rt2x00dev->bcn[1].stats.limit); + rt2x00dev->bcn[1].stats.limit); rt2x00_set_field32(®, TXCSR2_NUM_PRIO, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, - rt2x00dev->bcn[1].data_dma); + rt2x00dev->bcn[1].data_dma); rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, - rt2x00dev->bcn[0].data_dma); + rt2x00dev->bcn[0].data_dma); rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); - rt2x00_set_field32(®, RXCSR1_RXD_SIZE, - rt2x00dev->rx->desc_size); - rt2x00_set_field32(®, RXCSR1_NUM_RXD, - rt2x00dev->rx->stats.limit); + rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); + rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit); rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, - rt2x00dev->rx->data_dma); + rt2x00dev->rx->data_dma); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); return 0; @@ -785,14 +719,9 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; - if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) - return -EBUSY; - - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); - rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002); rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002); - rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00020002); + rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00023f20); rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002); rt2x00pci_register_read(rt2x00dev, TIMECSR, ®); @@ -803,36 +732,39 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00pci_register_read(rt2x00dev, CSR9, ®); rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT, - (rt2x00dev->rx->data_size / 128)); + (rt2x00dev->rx->data_size / 128)); rt2x00pci_register_write(rt2x00dev, CSR9, reg); rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000); - rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00217223); - rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518); - - rt2x00pci_register_read(rt2x00dev, MACCSR2, ®); - rt2x00_set_field32(®, MACCSR2_DELAY, 64); - rt2x00pci_register_write(rt2x00dev, MACCSR2, reg); + rt2x00pci_register_read(rt2x00dev, ARCSR0, ®); + rt2x00_set_field32(®, ARCSR0_AR_BBP_DATA0, 133); + rt2x00_set_field32(®, ARCSR0_AR_BBP_ID0, 134); + rt2x00_set_field32(®, ARCSR0_AR_BBP_DATA1, 136); + rt2x00_set_field32(®, ARCSR0_AR_BBP_ID1, 135); + rt2x00pci_register_write(rt2x00dev, ARCSR0, reg); rt2x00pci_register_read(rt2x00dev, RXCSR3, ®); - /* - * Tx power. - */ - rt2x00_set_field32(®, RXCSR3_BBP_ID0, 3); + rt2x00_set_field32(®, RXCSR3_BBP_ID0, 3); /* Tx power.*/ rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1); - /* - * Signal. - */ - rt2x00_set_field32(®, RXCSR3_BBP_ID1, 32); + rt2x00_set_field32(®, RXCSR3_BBP_ID1, 32); /* Signal */ rt2x00_set_field32(®, RXCSR3_BBP_ID1_VALID, 1); - /* - * Rssi. - */ - rt2x00_set_field32(®, RXCSR3_BBP_ID2, 36); + rt2x00_set_field32(®, RXCSR3_BBP_ID2, 36); /* Rssi */ rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1); rt2x00pci_register_write(rt2x00dev, RXCSR3, reg); + rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); + + if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) + return -EBUSY; + + rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00217223); + rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518); + + rt2x00pci_register_read(rt2x00dev, MACCSR2, ®); + rt2x00_set_field32(®, MACCSR2_DELAY, 64); + rt2x00pci_register_write(rt2x00dev, MACCSR2, reg); + rt2x00pci_register_read(rt2x00dev, RALINKCSR, ®); rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17); rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 154); @@ -885,7 +817,6 @@ continue_csr_init: rt2400pci_bbp_write(rt2x00dev, 3, 0x27); rt2400pci_bbp_write(rt2x00dev, 4, 0x08); rt2400pci_bbp_write(rt2x00dev, 10, 0x0f); - rt2400pci_bbp_write(rt2x00dev, 13, 0x08); rt2400pci_bbp_write(rt2x00dev, 15, 0x72); rt2400pci_bbp_write(rt2x00dev, 16, 0x74); rt2400pci_bbp_write(rt2x00dev, 17, 0x20); @@ -905,7 +836,7 @@ continue_csr_init: reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n", - reg_id, value); + reg_id, value); rt2400pci_bbp_write(rt2x00dev, reg_id, value); } } @@ -918,25 +849,27 @@ continue_csr_init: * Device state switch handlers. */ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { u32 reg; rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - state == STATE_RADIO_RX_OFF); + state == STATE_RADIO_RX_OFF); rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); } -static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled) +static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, + enum dev_state state) { + int mask = (state == STATE_RADIO_IRQ_OFF); u32 reg; /* * When interrupts are being enabled, the interrupt registers * should clear the register to assure a clean state. */ - if (enabled) { + if (state == STATE_RADIO_IRQ_ON) { rt2x00pci_register_read(rt2x00dev, CSR7, ®); rt2x00pci_register_write(rt2x00dev, CSR7, reg); } @@ -946,11 +879,11 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled) * Non-checked interrupt bits are disabled by default. */ rt2x00pci_register_read(rt2x00dev, CSR8, ®); - rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, !enabled); - rt2x00_set_field32(®, CSR8_TXDONE_TXRING, !enabled); - rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, !enabled); - rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, !enabled); - rt2x00_set_field32(®, CSR8_RXDONE, !enabled); + rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); + rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); + rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, mask); + rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); + rt2x00_set_field32(®, CSR8_RXDONE, mask); rt2x00pci_register_write(rt2x00dev, CSR8, reg); } @@ -969,7 +902,7 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Enable interrupts. */ - rt2400pci_toggle_irq(rt2x00dev, 1); + rt2400pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON); /* * Enable LED @@ -1005,11 +938,11 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev) /* * Disable interrupts. */ - rt2400pci_toggle_irq(rt2x00dev, 0); + rt2400pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF); } static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { u32 reg; unsigned int i; @@ -1041,36 +974,36 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, } NOTICE(rt2x00dev, "Device failed to enter state %d, " - "current device state: bbp %d and rf %d.\n", - state, bbp_state, rf_state); + "current device state: bbp %d and rf %d.\n", + state, bbp_state, rf_state); return -EBUSY; } static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { int retval = 0; switch (state) { - case STATE_RADIO_ON: - retval = rt2400pci_enable_radio(rt2x00dev); + case STATE_RADIO_ON: + retval = rt2400pci_enable_radio(rt2x00dev); break; - case STATE_RADIO_OFF: - rt2400pci_disable_radio(rt2x00dev); + case STATE_RADIO_OFF: + rt2400pci_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_OFF: - rt2400pci_toggle_rx(rt2x00dev, state); + case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_OFF: + rt2400pci_toggle_rx(rt2x00dev, state); break; - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: - case STATE_AWAKE: - retval = rt2400pci_set_state(rt2x00dev, state); + case STATE_DEEP_SLEEP: + case STATE_SLEEP: + case STATE_STANDBY: + case STATE_AWAKE: + retval = rt2400pci_set_state(rt2x00dev, state); break; - default: - retval = -ENOTSUPP; + default: + retval = -ENOTSUPP; break; } @@ -1081,9 +1014,11 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, * TX descriptor initialization */ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry, struct data_desc *txd, - struct data_entry_desc *desc, struct ieee80211_hdr *ieee80211hdr, - unsigned int length, struct ieee80211_tx_control *control) + struct data_desc *txd, + struct txdata_entry_desc *desc, + struct ieee80211_hdr *ieee80211hdr, + unsigned int length, + struct ieee80211_tx_control *control) { u32 word; u32 signal = 0; @@ -1132,22 +1067,25 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &entry->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_REQ_ACK, &entry->flags)); + !(control->flags & IEEE80211_TXCTL_NO_ACK)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &entry->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_RTS, - test_bit(ENTRY_TXD_RTS_FRAME, &entry->flags)); + test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); - rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, 0); + rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, + !!(control->flags & + IEEE80211_TXCTL_LONG_RETRY_LIMIT)); rt2x00_desc_write(txd, 0, word); } /* * TX data initialization */ -static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue) +static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, + unsigned int queue) { u32 reg; @@ -1173,8 +1111,8 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue) /* * RX control handlers */ -static int rt2400pci_fill_rxdone(struct data_entry *entry, - int *signal, int *rssi, int *ofdm) +static void rt2400pci_fill_rxdone(struct data_entry *entry, + struct rxdata_entry_desc *desc) { struct data_desc *rxd = entry->priv; u32 word0; @@ -1183,23 +1121,20 @@ static int rt2400pci_fill_rxdone(struct data_entry *entry, rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 2, &word2); - /* - * TODO: Don't we need to keep statistics - * updated about these errors? - */ - if (rt2x00_get_field32(word0, RXD_W0_CRC) || - rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - return -EINVAL; + desc->flags = 0; + if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) + desc->flags |= RX_FLAG_FAILED_FCS_CRC; + if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) + desc->flags |= RX_FLAG_FAILED_PLCP_CRC; /* * Obtain the status about this packet. */ - *signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); - *rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - - entry->ring->rt2x00dev->rssi_offset; - *ofdm = 0; - - return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); + desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - + entry->ring->rt2x00dev->rssi_offset; + desc->ofdm = 0; + desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); } /* @@ -1207,7 +1142,7 @@ static int rt2400pci_fill_rxdone(struct data_entry *entry, */ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) { - struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue); + struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); struct data_entry *entry; struct data_desc *txd; u32 word; @@ -1248,7 +1183,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) entry = ring->entry; if (!rt2x00_ring_full(ring)) ieee80211_wake_queue(rt2x00dev->hw, - entry->tx_status.control.queue); + entry->tx_status.control.queue); } static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) @@ -1279,7 +1214,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) * 1 - Beacon timer expired interrupt. */ if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) - rt2x00pci_beacondone(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt2x00lib_beacondone(rt2x00dev); /* * 2 - Rx ring done interrupt. @@ -1309,45 +1244,39 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) } /* - * Device initialization functions. + * Device probe functions. */ -static int rt2400pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) { struct eeprom_93cx6 eeprom; u32 reg; u16 word; u8 *mac; - /* - * Allocate the eeprom memory, check the eeprom width - * and copy the entire eeprom into this allocated memory. - */ - rt2x00dev->eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); - if (!rt2x00dev->eeprom) - return -ENOMEM; - rt2x00pci_register_read(rt2x00dev, CSR21, ®); eeprom.data = rt2x00dev; eeprom.register_read = rt2400pci_eepromregister_read; eeprom.register_write = rt2400pci_eepromregister_write; eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ? - PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; + PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; eeprom.reg_data_in = 0; eeprom.reg_data_out = 0; eeprom.reg_data_clock = 0; eeprom.reg_chip_select = 0; eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, - EEPROM_SIZE / sizeof(u16)); + EEPROM_SIZE / sizeof(u16)); /* * Start validation of the data that has been read. */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { + DECLARE_MAC_BUF(macbuf); + random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac)); + EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac)); } rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); @@ -1386,22 +1315,24 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Identify default antenna configuration. */ - rt2x00dev->hw->conf.antenna_sel_tx = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_TX_DEFAULT); - rt2x00dev->hw->conf.antenna_sel_rx = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_RX_DEFAULT); + rt2x00dev->hw->conf.antenna_sel_tx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); + rt2x00dev->hw->conf.antenna_sel_rx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); /* * Store led mode, for correct led behaviour. */ - rt2x00dev->led_mode = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_LED_MODE); + rt2x00dev->led_mode = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); /* * Detect if this device has an hardware controlled radio. */ +#ifdef CONFIG_RT2400PCI_RFKILL if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(DEVICE_SUPPORT_HW_BUTTON, &rt2x00dev->flags); + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +#endif /* CONFIG_RT2400PCI_RFKILL */ /* * Check if the BBP tuning should be enabled. @@ -1416,13 +1347,24 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * RF value list for RF2420 & RF2421 * Supports: 2.4 GHz */ -static const u32 rf_vals_bg[] = { - 0x000c1fda, 0x000c1fee, 0x000c2002, 0x000c2016, 0x000c202a, - 0x000c203e, 0x000c2052, 0x000c2066, 0x000c207a, 0x000c208e, - 0x000c20a2, 0x000c20b6, 0x000c20ca, 0x000c20fa +static const struct rf_channel rf_vals_bg[] = { + { 1, 0x00022058, 0x000c1fda, 0x00000101, 0 }, + { 2, 0x00022058, 0x000c1fee, 0x00000101, 0 }, + { 3, 0x00022058, 0x000c2002, 0x00000101, 0 }, + { 4, 0x00022058, 0x000c2016, 0x00000101, 0 }, + { 5, 0x00022058, 0x000c202a, 0x00000101, 0 }, + { 6, 0x00022058, 0x000c203e, 0x00000101, 0 }, + { 7, 0x00022058, 0x000c2052, 0x00000101, 0 }, + { 8, 0x00022058, 0x000c2066, 0x00000101, 0 }, + { 9, 0x00022058, 0x000c207a, 0x00000101, 0 }, + { 10, 0x00022058, 0x000c208e, 0x00000101, 0 }, + { 11, 0x00022058, 0x000c20a2, 0x00000101, 0 }, + { 12, 0x00022058, 0x000c20b6, 0x00000101, 0 }, + { 13, 0x00022058, 0x000c20ca, 0x00000101, 0 }, + { 14, 0x00022058, 0x000c20fa, 0x00000101, 0 }, }; -static void rt2400pci_init_hw_mode(struct rt2x00_dev *rt2x00dev) +static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; u8 *txpower; @@ -1431,30 +1373,16 @@ static void rt2400pci_init_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Initialize all hw fields. */ - rt2x00dev->hw->flags = IEEE80211_HW_HOST_GEN_BEACON | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_WEP_INCLUDE_IV | - IEEE80211_HW_DATA_NULLFUNC_ACK | - IEEE80211_HW_NO_TKIP_WMM_HWACCEL | - IEEE80211_HW_MONITOR_DURING_OPER | - IEEE80211_HW_NO_PROBE_FILTERING; + rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; rt2x00dev->hw->extra_tx_headroom = 0; + rt2x00dev->hw->max_signal = MAX_SIGNAL; rt2x00dev->hw->max_rssi = MAX_RX_SSI; - rt2x00dev->hw->max_noise = MAX_RX_NOISE; rt2x00dev->hw->queues = 2; SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); - - /* - * Set device specific, but channel independent RF values. - */ - rt2x00dev->rf1 = 0x00022058; - if (rt2x00_rf(&rt2x00dev->chip, RF2420)) - rt2x00dev->rf3 = 0x00000111; - else - rt2x00dev->rf3 = 0x00000101; + rt2x00_eeprom_addr(rt2x00dev, + EEPROM_MAC_ADDR_0)); /* * Convert tx_power array in eeprom. @@ -1468,22 +1396,22 @@ static void rt2400pci_init_hw_mode(struct rt2x00_dev *rt2x00dev) */ spec->num_modes = 1; spec->num_rates = 4; - spec->num_channels = 14; spec->tx_power_a = NULL; spec->tx_power_bg = txpower; spec->tx_power_default = DEFAULT_TXPOWER; - spec->chan_val_a = NULL; - spec->chan_val_bg = rf_vals_bg; + + spec->num_channels = ARRAY_SIZE(rf_vals_bg); + spec->channels = rf_vals_bg; } -static int rt2400pci_init_hw(struct rt2x00_dev *rt2x00dev) +static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; /* * Allocate eeprom data. */ - retval = rt2400pci_alloc_eeprom(rt2x00dev); + retval = rt2400pci_validate_eeprom(rt2x00dev); if (retval) return retval; @@ -1494,12 +1422,12 @@ static int rt2400pci_init_hw(struct rt2x00_dev *rt2x00dev) /* * Initialize hw specifications. */ - rt2400pci_init_hw_mode(rt2x00dev); + rt2400pci_probe_hw_mode(rt2x00dev); /* - * This device supports ATIM + * This device requires the beacon ring */ - __set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1512,28 +1440,70 @@ static int rt2400pci_init_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static int rt2400pci_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) +static void rt2400pci_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_addr_list *mc_list) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct interface *intf = &rt2x00dev->interface; u32 reg; /* - * Update FCS error count from register. - * The dot11ACKFailureCount, dot11RTSFailureCount and - * dot11RTSSuccessCount are updated in interrupt time. + * Mask off any flags we are going to ignore from + * the total_flags field. */ - rt2x00pci_register_read(rt2x00dev, CNT0, ®); - rt2x00dev->low_level_stats.dot11FCSErrorCount += - rt2x00_get_field32(reg, CNT0_FCS_ERROR); + *total_flags &= + FIF_ALLMULTI | + FIF_FCSFAIL | + FIF_PLCPFAIL | + FIF_CONTROL | + FIF_OTHER_BSS | + FIF_PROMISC_IN_BSS; + + /* + * Apply some rules to the filters: + * - Some filters imply different filters to be set. + * - Some things we can't filter out at all. + * - Some filters are set based on interface type. + */ + *total_flags |= FIF_ALLMULTI; + if (*total_flags & FIF_OTHER_BSS || + *total_flags & FIF_PROMISC_IN_BSS) + *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; + if (is_interface_type(intf, IEEE80211_IF_TYPE_AP)) + *total_flags |= FIF_PROMISC_IN_BSS; - memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats)); + /* + * Check if there is any work left for us. + */ + if (intf->filter == *total_flags) + return; + intf->filter = *total_flags; - return 0; + /* + * Start configuration steps. + * Note that the version error will always be dropped + * since there is no filter for it at this time. + */ + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DROP_CRC, + !(*total_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, + !(*total_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, + !(*total_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, + !(*total_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_TODS, + !(*total_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); } static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw, - u32 short_retry, u32 long_retry) + u32 short_retry, u32 long_retry) { struct rt2x00_dev *rt2x00dev = hw->priv; u32 reg; @@ -1547,7 +1517,8 @@ static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw, } static int rt2400pci_conf_tx(struct ieee80211_hw *hw, - int queue, const struct ieee80211_tx_queue_params *params) + int queue, + const struct ieee80211_tx_queue_params *params) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -1559,7 +1530,7 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, if (queue != IEEE80211_TX_QUEUE_DATA0) return -EINVAL; - if (rt2x00lib_conf_tx(hw, queue, params)) + if (rt2x00mac_conf_tx(hw, queue, params)) return -EINVAL; /* @@ -1577,7 +1548,7 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw) u32 reg; rt2x00pci_register_read(rt2x00dev, CSR17, ®); - tsf = (u64)rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; + tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; rt2x00pci_register_read(rt2x00dev, CSR16, ®); tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER); @@ -1602,17 +1573,19 @@ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) } static const struct ieee80211_ops rt2400pci_mac80211_ops = { - .tx = rt2x00lib_tx, - .reset = rt2x00lib_reset, - .add_interface = rt2x00lib_add_interface, - .remove_interface = rt2x00lib_remove_interface, - .config = rt2x00lib_config, - .config_interface = rt2x00lib_config_interface, - .set_multicast_list = rt2x00lib_set_multicast_list, - .get_stats = rt2400pci_get_stats, + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, + .remove_interface = rt2x00mac_remove_interface, + .config = rt2x00mac_config, + .config_interface = rt2x00mac_config_interface, + .configure_filter = rt2400pci_configure_filter, + .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt2400pci_set_retry_limit, + .erp_ie_changed = rt2x00mac_erp_ie_changed, .conf_tx = rt2400pci_conf_tx, - .get_tx_stats = rt2x00lib_get_tx_stats, + .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2400pci_get_tsf, .reset_tsf = rt2400pci_reset_tsf, .beacon_update = rt2x00pci_beacon_update, @@ -1621,37 +1594,35 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .irq_handler = rt2400pci_interrupt, - .init_hw = rt2400pci_init_hw, + .probe_hw = rt2400pci_probe_hw, .initialize = rt2x00pci_initialize, .uninitialize = rt2x00pci_uninitialize, .set_device_state = rt2400pci_set_device_state, -#ifdef CONFIG_RT2400PCI_RFKILL .rfkill_poll = rt2400pci_rfkill_poll, -#endif /* CONFIG_RT2400PCI_RFKILL */ + .link_stats = rt2400pci_link_stats, + .reset_tuner = rt2400pci_reset_tuner, .link_tuner = rt2400pci_link_tuner, .write_tx_desc = rt2400pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, - .config_type = rt2400pci_config_type, - .config_phymode = rt2400pci_config_phymode, - .config_channel = rt2400pci_config_channel, .config_mac_addr = rt2400pci_config_mac_addr, .config_bssid = rt2400pci_config_bssid, - .config_promisc = rt2400pci_config_promisc, - .config_txpower = rt2400pci_config_txpower, - .config_antenna = rt2400pci_config_antenna, - .config_duration = rt2400pci_config_duration, + .config_type = rt2400pci_config_type, + .config_preamble = rt2400pci_config_preamble, + .config = rt2400pci_config, }; static const struct rt2x00_ops rt2400pci_ops = { - .name = DRV_NAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, - .lib = &rt2400pci_rt2x00_ops, - .hw = &rt2400pci_mac80211_ops, + .name = DRV_NAME, + .rxd_size = RXD_DESC_SIZE, + .txd_size = TXD_DESC_SIZE, + .eeprom_size = EEPROM_SIZE, + .rf_size = RF_SIZE, + .lib = &rt2400pci_rt2x00_ops, + .hw = &rt2400pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2400pci_rt2x00debug, + .debugfs = &rt2400pci_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; @@ -1675,10 +1646,8 @@ static struct pci_driver rt2400pci_driver = { .id_table = rt2400pci_device_table, .probe = rt2x00pci_probe, .remove = __devexit_p(rt2x00pci_remove), -#ifdef CONFIG_PM .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, -#endif /* CONFIG_PM */ }; static int __init rt2400pci_init(void) diff --git a/package/rt2x00/src/rt2400pci.h b/package/rt2x00/src/rt2400pci.h index 10fe48888b..ae22501f08 100644 --- a/package/rt2x00/src/rt2400pci.h +++ b/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. @@ -717,9 +718,32 @@ #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) @@ -777,21 +801,6 @@ #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. */ #define TXD_DESC_SIZE ( 8 * sizeof(struct data_desc) ) @@ -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) diff --git a/package/rt2x00/src/rt2500pci.c b/package/rt2x00/src/rt2500pci.c index d71e3c32a4..702321c301 100644 --- a/package/rt2x00/src/rt2500pci.c +++ b/package/rt2x00/src/rt2500pci.c @@ -29,20 +29,15 @@ */ #define DRV_NAME "rt2500pci" +#include <linux/delay.h> +#include <linux/etherdevice.h> +#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> -#include <linux/init.h> #include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/delay.h> -#include <linux/etherdevice.h> #include <linux/eeprom_93cx6.h> -#include <asm/io.h> - #include "rt2x00.h" -#include "rt2x00lib.h" #include "rt2x00pci.h" #include "rt2500pci.h" @@ -75,12 +70,12 @@ static u32 rt2500pci_bbp_check(const struct rt2x00_dev *rt2x00dev) } static void rt2500pci_bbp_write(const struct rt2x00_dev *rt2x00dev, - const u8 reg_id, const u8 value) + const unsigned int word, const u8 value) { u32 reg; /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt2500pci_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { @@ -93,7 +88,7 @@ static void rt2500pci_bbp_write(const struct rt2x00_dev *rt2x00dev, */ reg = 0; rt2x00_set_field32(®, BBPCSR_VALUE, value); - rt2x00_set_field32(®, BBPCSR_REGNUM, reg_id); + rt2x00_set_field32(®, BBPCSR_REGNUM, word); rt2x00_set_field32(®, BBPCSR_BUSY, 1); rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); @@ -101,12 +96,12 @@ static void rt2500pci_bbp_write(const struct rt2x00_dev *rt2x00dev, } static void rt2500pci_bbp_read(const struct rt2x00_dev *rt2x00dev, - const u8 reg_id, u8 *value) + const unsigned int word, u8 *value) { u32 reg; /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt2500pci_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { @@ -118,14 +113,14 @@ static void rt2500pci_bbp_read(const struct rt2x00_dev *rt2x00dev, * Write the request into the BBP. */ reg = 0; - rt2x00_set_field32(®, BBPCSR_REGNUM, reg_id); + rt2x00_set_field32(®, BBPCSR_REGNUM, word); rt2x00_set_field32(®, BBPCSR_BUSY, 1); rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt2500pci_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, BBPCSR_BUSY)) { @@ -138,11 +133,14 @@ static void rt2500pci_bbp_read(const struct rt2x00_dev *rt2x00dev, } static void rt2500pci_rf_write(const struct rt2x00_dev *rt2x00dev, - const u32 value) + const unsigned int word, const u32 value) { u32 reg; unsigned int i; + if (!word) + return; + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2x00pci_register_read(rt2x00dev, RFCSR, ®); if (!rt2x00_get_field32(reg, RFCSR_BUSY)) @@ -161,6 +159,7 @@ rf_write: rt2x00_set_field32(®, RFCSR_BUSY, 1); rt2x00pci_register_write(rt2x00dev, RFCSR, reg); + rt2x00_rf_write(rt2x00dev, word, value); } static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom) @@ -170,14 +169,12 @@ static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom) rt2x00pci_register_read(rt2x00dev, CSR21, ®); - eeprom->reg_data_in = !!rt2x00_get_field32(reg, - CSR21_EEPROM_DATA_IN); - eeprom->reg_data_out = !!rt2x00_get_field32(reg, - CSR21_EEPROM_DATA_OUT); - eeprom->reg_data_clock = !!rt2x00_get_field32(reg, - CSR21_EEPROM_DATA_CLOCK); - eeprom->reg_chip_select = !!rt2x00_get_field32(reg, - CSR21_EEPROM_CHIP_SELECT); + eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN); + eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT); + eeprom->reg_data_clock = + !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_CLOCK); + eeprom->reg_chip_select = + !!rt2x00_get_field32(reg, CSR21_EEPROM_CHIP_SELECT); } static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom) @@ -185,14 +182,12 @@ static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom) struct rt2x00_dev *rt2x00dev = eeprom->data; u32 reg = 0; - rt2x00_set_field32(®, CSR21_EEPROM_DATA_IN, - !!eeprom->reg_data_in); - rt2x00_set_field32(®, CSR21_EEPROM_DATA_OUT, - !!eeprom->reg_data_out); + rt2x00_set_field32(®, CSR21_EEPROM_DATA_IN, !!eeprom->reg_data_in); + rt2x00_set_field32(®, CSR21_EEPROM_DATA_OUT, !!eeprom->reg_data_out); rt2x00_set_field32(®, CSR21_EEPROM_DATA_CLOCK, - !!eeprom->reg_data_clock); + !!eeprom->reg_data_clock); rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT, - !!eeprom->reg_chip_select); + !!eeprom->reg_chip_select); rt2x00pci_register_write(rt2x00dev, CSR21, reg); } @@ -200,62 +195,44 @@ static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom) #ifdef CONFIG_RT2X00_LIB_DEBUGFS #define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) ) -static void rt2500pci_read_csr(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) +static void rt2500pci_read_csr(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 *data) { rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data); } -static void rt2500pci_write_csr(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), *((u32*)data)); -} - -static void rt2500pci_read_eeprom(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2x00_eeprom_read(rt2x00dev, word, data); -} - -static void rt2500pci_write_eeprom(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2x00_eeprom_write(rt2x00dev, word, *((u16*)data)); -} - -static void rt2500pci_read_bbp(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) +static void rt2500pci_write_csr(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 data) { - rt2500pci_bbp_read(rt2x00dev, word, data); -} - -static void rt2500pci_write_bbp(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2500pci_bbp_write(rt2x00dev, word, *((u8*)data)); + rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data); } static const struct rt2x00debug rt2500pci_rt2x00debug = { - .owner = THIS_MODULE, - .reg_csr = { + .owner = THIS_MODULE, + .csr = { .read = rt2500pci_read_csr, .write = rt2500pci_write_csr, .word_size = sizeof(u32), .word_count = CSR_REG_SIZE / sizeof(u32), }, - .reg_eeprom = { - .read = rt2500pci_read_eeprom, - .write = rt2500pci_write_eeprom, + .eeprom = { + .read = rt2x00_eeprom_read, + .write = rt2x00_eeprom_write, .word_size = sizeof(u16), .word_count = EEPROM_SIZE / sizeof(u16), }, - .reg_bbp = { - .read = rt2500pci_read_bbp, - .write = rt2500pci_write_bbp, + .bbp = { + .read = rt2500pci_bbp_read, + .write = rt2500pci_bbp_write, .word_size = sizeof(u8), .word_count = BBP_SIZE / sizeof(u8), }, + .rf = { + .read = rt2x00_rf_read, + .write = rt2500pci_rf_write, + .word_size = sizeof(u32), + .word_count = RF_SIZE / sizeof(u32), + }, }; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ @@ -267,148 +244,123 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); return rt2x00_get_field32(reg, GPIOCSR_BIT0); } -#endif /* CONFIG_RT2400PCI_RFKILL */ +#else +#define rt2500pci_rfkill_poll NULL +#endif /* CONFIG_RT2500PCI_RFKILL */ /* * Configuration handlers. */ -static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) +static void rt2500pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, + __le32 *mac) { - u32 reg[2]; - - memset(®, 0, sizeof(reg)); - memcpy(®, bssid, ETH_ALEN); - - /* - * The BSSID is passed to us as an array of bytes, - * that array is little endian, so no need for byte ordering. - */ - rt2x00pci_register_multiwrite(rt2x00dev, CSR5, ®, sizeof(reg)); + rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac, + (2 * sizeof(__le32))); } -static void rt2500pci_config_promisc(struct rt2x00_dev *rt2x00dev, - const int promisc) +static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev, + __le32 *bssid) { - u32 reg; - - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, !promisc); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); + rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid, + (2 * sizeof(__le32))); } -static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, - const int type) +static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, + const int tsf_sync) { u32 reg; rt2x00pci_register_write(rt2x00dev, CSR14, 0); /* - * Apply hardware packet filter. - */ - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - - if (!is_monitor_present(&rt2x00dev->interface) && - (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA)) - rt2x00_set_field32(®, RXCSR0_DROP_TODS, 1); - else - rt2x00_set_field32(®, RXCSR0_DROP_TODS, 0); - - rt2x00_set_field32(®, RXCSR0_DROP_CRC, 1); - if (is_monitor_present(&rt2x00dev->interface)) { - rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 0); - rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 0); - rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 0); - } else { - rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, 1); - rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, 1); - rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); - } - - rt2x00_set_field32(®, RXCSR0_DROP_MCAST, 0); - rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); - - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); - - /* * Enable beacon config */ rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); rt2x00_set_field32(®, BCNCSR1_PRELOAD, - PREAMBLE + get_duration(IEEE80211_HEADER, 2)); + PREAMBLE + get_duration(IEEE80211_HEADER, 20)); rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, - rt2x00_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON) - ->tx_params.cw_min); + rt2x00lib_get_ring(rt2x00dev, + IEEE80211_TX_QUEUE_BEACON) + ->tx_params.cw_min); rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); /* * Enable synchronisation. */ rt2x00pci_register_read(rt2x00dev, CSR14, ®); - if (is_interface_present(&rt2x00dev->interface)) { - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, 1); - } - + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, 1); rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - if (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_AP) - rt2x00_set_field32(®, CSR14_TSF_SYNC, 2); - else if (type == IEEE80211_IF_TYPE_STA) - rt2x00_set_field32(®, CSR14_TSF_SYNC, 1); - else if (is_monitor_present(&rt2x00dev->interface) && - !is_interface_present(&rt2x00dev->interface)) - rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); - + rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync); rt2x00pci_register_write(rt2x00dev, CSR14, reg); } +static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) +{ + int preamble_mask; + u32 reg; + + /* + * When short preamble is enabled, we should set bit 0x08 + */ + preamble_mask = short_preamble << 3; + + rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); + rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, ack_timeout); + rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, ack_consume_time); + rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); + rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00 | preamble_mask); + rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10)); + rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); + rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); + rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20)); + rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); + rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); + rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); + rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55)); + rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); + + rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); + rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); + rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); + rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); + rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); +} + +static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev, + const int basic_rate_mask) +{ + rt2x00pci_register_write(rt2x00dev, ARCSR1, basic_rate_mask); +} + static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, - const int value, const int channel, const int txpower) + struct rf_channel *rf, const int txpower) { - u32 rf1 = rt2x00dev->rf1; - u32 rf2 = value; - u32 rf3 = rt2x00dev->rf3; - u32 rf4 = rt2x00dev->rf4; u8 r70; - if (rt2x00_rf(&rt2x00dev->chip, RF2525) || - rt2x00_rf(&rt2x00dev->chip, RF2525E)) - rf2 |= 0x00080000; - - if (rt2x00_rf(&rt2x00dev->chip, RF2525E) && channel == 14) - rf4 |= 0x00000010; - - if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { - if (channel < 14) { - rf1 = 0x00022020; - rf4 = 0x00000a0b; - } else if (channel == 14) { - rf1 = 0x00022010; - rf4 = 0x00000a1b; - } else if (channel < 64) { - rf1 = 0x00022010; - rf4 = 0x00000a1f; - } else if (channel < 140) { - rf1 = 0x00022010; - rf4 = 0x00000a0f; - } else if (channel < 161) { - rf1 = 0x00022020; - rf4 = 0x00000a07; - } - } - /* * Set TXpower. */ - rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); /* * Switch on tuning bits. * For RT2523 devices we do not need to update the R1 register. */ if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) - rt2x00_set_field32(&rf1, RF1_TUNER, 1); - rt2x00_set_field32(&rf3, RF3_TUNER, 1); + rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); + rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); /* * For RT2525 we should first set the channel to half band higher. @@ -421,24 +373,24 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, 0x00080d2e, 0x00080d3a }; - rt2500pci_rf_write(rt2x00dev, rf1); - rt2500pci_rf_write(rt2x00dev, vals[channel - 1]); - rt2500pci_rf_write(rt2x00dev, rf3); - if (rf4) - rt2500pci_rf_write(rt2x00dev, rf4); + rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); + rt2500pci_rf_write(rt2x00dev, 2, vals[rf->channel - 1]); + rt2500pci_rf_write(rt2x00dev, 3, rf->rf3); + if (rf->rf4) + rt2500pci_rf_write(rt2x00dev, 4, rf->rf4); } - rt2500pci_rf_write(rt2x00dev, rf1); - rt2500pci_rf_write(rt2x00dev, rf2); - rt2500pci_rf_write(rt2x00dev, rf3); - if (rf4) - rt2500pci_rf_write(rt2x00dev, rf4); + rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); + rt2500pci_rf_write(rt2x00dev, 2, rf->rf2); + rt2500pci_rf_write(rt2x00dev, 3, rf->rf3); + if (rf->rf4) + rt2500pci_rf_write(rt2x00dev, 4, rf->rf4); /* * Channel 14 requires the Japan filter bit to be set. */ r70 = 0x46; - rt2x00_set_field8(&r70, BBP_R70_JAPAN_FILTER, channel == 14); + rt2x00_set_field8(&r70, BBP_R70_JAPAN_FILTER, rf->channel == 14); rt2500pci_bbp_write(rt2x00dev, 70, r70); msleep(1); @@ -447,41 +399,32 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, * Switch off tuning bits. * For RT2523 devices we do not need to update the R1 register. */ - rt2x00_set_field32(&rf1, RF1_TUNER, 0); - rt2x00_set_field32(&rf3, RF3_TUNER, 0); - - - if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) - rt2500pci_rf_write(rt2x00dev, rf1); - - rt2500pci_rf_write(rt2x00dev, rf3); + if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) { + rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); + rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); + } - /* - * Update rf fields - */ - rt2x00dev->rf1 = rf1; - rt2x00dev->rf2 = rf2; - rt2x00dev->rf3 = rf3; - rt2x00dev->rf4 = rf4; - rt2x00dev->tx_power = txpower; + rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0); + rt2500pci_rf_write(rt2x00dev, 3, rf->rf3); /* * Clear false CRC during channel switch. */ - rt2x00pci_register_read(rt2x00dev, CNT0, &rf1); + rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1); } static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev, - const int txpower) + const int txpower) { - rt2x00_set_field32(&rt2x00dev->rf3, RF3_TXPOWER, - TXPOWER_TO_DEV(txpower)); - rt2500pci_rf_write(rt2x00dev, rt2x00dev->rf3); + u32 rf3; + rt2x00_rf_read(rt2x00dev, 3, &rf3); + rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); + rt2500pci_rf_write(rt2x00dev, 3, rf3); } static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, - const int antenna_tx, const int antenna_rx) + const int antenna_tx, const int antenna_rx) { u32 reg; u8 r14; @@ -494,29 +437,40 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, /* * Configure the TX antenna. */ - if (antenna_tx == ANTENNA_DIVERSITY) { + switch (antenna_tx) { + case ANTENNA_SW_DIVERSITY: + case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2); rt2x00_set_field32(®, BBPCSR1_CCK, 2); rt2x00_set_field32(®, BBPCSR1_OFDM, 2); - } else if (antenna_tx == ANTENNA_A) { + break; + case ANTENNA_A: rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0); rt2x00_set_field32(®, BBPCSR1_CCK, 0); rt2x00_set_field32(®, BBPCSR1_OFDM, 0); - } else if (antenna_tx == ANTENNA_B) { + break; + case ANTENNA_B: rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2); rt2x00_set_field32(®, BBPCSR1_CCK, 2); rt2x00_set_field32(®, BBPCSR1_OFDM, 2); + break; } /* * Configure the RX antenna. */ - if (antenna_rx == ANTENNA_DIVERSITY) + switch (antenna_rx) { + case ANTENNA_SW_DIVERSITY: + case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2); - else if (antenna_rx == ANTENNA_A) + break; + case ANTENNA_A: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0); - else if (antenna_rx == ANTENNA_B) + break; + case ANTENNA_B: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2); + break; + } /* * RT2525E and RT5222 need to flip TX I/Q @@ -543,25 +497,22 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, } static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev, - const int short_slot_time, const int beacon_int) + struct rt2x00lib_conf *libconf) { u32 reg; rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_SLOT_TIME, - short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME); + rt2x00_set_field32(®, CSR11_SLOT_TIME, libconf->slot_time); rt2x00pci_register_write(rt2x00dev, CSR11, reg); rt2x00pci_register_read(rt2x00dev, CSR18, ®); - rt2x00_set_field32(®, CSR18_SIFS, SIFS); - rt2x00_set_field32(®, CSR18_PIFS, - short_slot_time ? SHORT_PIFS : PIFS); + rt2x00_set_field32(®, CSR18_SIFS, libconf->sifs); + rt2x00_set_field32(®, CSR18_PIFS, libconf->pifs); rt2x00pci_register_write(rt2x00dev, CSR18, reg); rt2x00pci_register_read(rt2x00dev, CSR19, ®); - rt2x00_set_field32(®, CSR19_DIFS, - short_slot_time ? SHORT_DIFS : DIFS); - rt2x00_set_field32(®, CSR19_EIFS, EIFS); + rt2x00_set_field32(®, CSR19_DIFS, libconf->difs); + rt2x00_set_field32(®, CSR19_EIFS, libconf->eifs); rt2x00pci_register_write(rt2x00dev, CSR19, reg); rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); @@ -570,91 +521,31 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); rt2x00pci_register_read(rt2x00dev, CSR12, ®); - rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, beacon_int * 16); - rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, beacon_int * 16); + rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, + libconf->conf->beacon_int * 16); + rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, + libconf->conf->beacon_int * 16); rt2x00pci_register_write(rt2x00dev, CSR12, reg); } -static void rt2500pci_config_rate(struct rt2x00_dev *rt2x00dev, const int rate) +static void rt2500pci_config(struct rt2x00_dev *rt2x00dev, + const unsigned int flags, + struct rt2x00lib_conf *libconf) { - struct ieee80211_conf *conf = &rt2x00dev->hw->conf; - u32 reg; - u32 preamble; - u16 value; - - preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) - ? SHORT_PREAMBLE : PREAMBLE; - - reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE; - rt2x00pci_register_write(rt2x00dev, ARCSR1, reg); - - rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ? - SHORT_DIFS : DIFS) + - PLCP + preamble + get_duration(ACK_SIZE, 10); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, value); - value = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10); - rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, value); - rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); - - preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) ? 0x08 : 0x00; - - rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); - rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00 | preamble); - rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10)); - rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); - rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble); - rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20)); - rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); - rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble); - rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55)); - rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); - rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble); - rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); - rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); - rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); -} - -static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev, - const int phymode) -{ - struct ieee80211_hw_mode *mode; - struct ieee80211_rate *rate; - - if (phymode == MODE_IEEE80211A) - rt2x00dev->curr_hwmode = HWMODE_A; - else if (phymode == MODE_IEEE80211B) - rt2x00dev->curr_hwmode = HWMODE_B; - else - rt2x00dev->curr_hwmode = HWMODE_G; - - mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode]; - rate = &mode->rates[mode->num_rates - 1]; - - rt2500pci_config_rate(rt2x00dev, rate->val2); -} - -static void rt2500pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *addr) -{ - u32 reg[2]; - - memset(®, 0, sizeof(reg)); - memcpy(®, addr, ETH_ALEN); - - /* - * The MAC address is passed to us as an array of bytes, - * that array is little endian, so no need for byte ordering. - */ - rt2x00pci_register_multiwrite(rt2x00dev, CSR3, ®, sizeof(reg)); + if (flags & CONFIG_UPDATE_PHYMODE) + rt2500pci_config_phymode(rt2x00dev, libconf->basic_rates); + if (flags & CONFIG_UPDATE_CHANNEL) + rt2500pci_config_channel(rt2x00dev, &libconf->rf, + libconf->conf->power_level); + if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL)) + rt2500pci_config_txpower(rt2x00dev, + libconf->conf->power_level); + if (flags & CONFIG_UPDATE_ANTENNA) + rt2500pci_config_antenna(rt2x00dev, + libconf->conf->antenna_sel_tx, + libconf->conf->antenna_sel_rx); + if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) + rt2500pci_config_duration(rt2x00dev, libconf); } /* @@ -696,10 +587,32 @@ static void rt2500pci_disable_led(struct rt2x00_dev *rt2x00dev) /* * Link tuning */ +static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + /* + * Update FCS error count from register. + */ + rt2x00pci_register_read(rt2x00dev, CNT0, ®); + rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); + + /* + * Update False CCA count from register. + */ + rt2x00pci_register_read(rt2x00dev, CNT3, ®); + rt2x00dev->link.false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); +} + +static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev) +{ + rt2500pci_bbp_write(rt2x00dev, 17, 0x48); + rt2x00dev->link.vgc_level = 0x48; +} + static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) { int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); - u32 reg; u8 r17; /* @@ -727,7 +640,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) */ if (rssi < -80 && rt2x00dev->link.count > 20) { if (r17 >= 0x41) { - r17 = rt2x00dev->rx_status.noise; + r17 = rt2x00dev->link.vgc_level; rt2500pci_bbp_write(rt2x00dev, 17, r17); } return; @@ -756,7 +669,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) * to the dynamic tuning range. */ if (r17 >= 0x41) { - rt2500pci_bbp_write(rt2x00dev, 17, rt2x00dev->rx_status.noise); + rt2500pci_bbp_write(rt2x00dev, 17, rt2x00dev->link.vgc_level); return; } @@ -766,15 +679,12 @@ dynamic_cca_tune: * R17 is inside the dynamic tuning range, * start tuning the link based on the false cca counter. */ - rt2x00pci_register_read(rt2x00dev, CNT3, ®); - rt2x00dev->link.false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); - if (rt2x00dev->link.false_cca > 512 && r17 < 0x40) { rt2500pci_bbp_write(rt2x00dev, 17, ++r17); - rt2x00dev->rx_status.noise = r17; + rt2x00dev->link.vgc_level = r17; } else if (rt2x00dev->link.false_cca < 100 && r17 > 0x32) { rt2500pci_bbp_write(rt2x00dev, 17, --r17); - rt2x00dev->rx_status.noise = r17; + rt2x00dev->link.vgc_level = r17; } } @@ -783,19 +693,19 @@ dynamic_cca_tune: */ static void rt2500pci_init_rxring(struct rt2x00_dev *rt2x00dev) { + struct data_ring *ring = rt2x00dev->rx; struct data_desc *rxd; unsigned int i; u32 word; - memset(rt2x00dev->rx->data_addr, 0x00, - rt2x00_get_ring_size(rt2x00dev->rx)); + memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring)); - for (i = 0; i < rt2x00dev->rx->stats.limit; i++) { - rxd = rt2x00dev->rx->entry[i].priv; + for (i = 0; i < ring->stats.limit; i++) { + rxd = ring->entry[i].priv; rt2x00_desc_read(rxd, 1, &word); rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, - rt2x00dev->rx->entry[i].data_dma); + ring->entry[i].data_dma); rt2x00_desc_write(rxd, 1, word); rt2x00_desc_read(rxd, 0, &word); @@ -806,10 +716,9 @@ static void rt2500pci_init_rxring(struct rt2x00_dev *rt2x00dev) rt2x00_ring_index_clear(rt2x00dev->rx); } -static void rt2500pci_init_txring(struct rt2x00_dev *rt2x00dev, - const int queue) +static void rt2500pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue) { - struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue); + struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); struct data_desc *txd; unsigned int i; u32 word; @@ -821,7 +730,7 @@ static void rt2500pci_init_txring(struct rt2x00_dev *rt2x00dev, rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, - ring->entry[i].data_dma); + ring->entry[i].data_dma); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 0, &word); @@ -851,45 +760,43 @@ static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev) */ rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); rt2x00_set_field32(®, TXCSR2_TXD_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size); rt2x00_set_field32(®, TXCSR2_NUM_TXD, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); rt2x00_set_field32(®, TXCSR2_NUM_ATIM, - rt2x00dev->bcn[1].stats.limit); + rt2x00dev->bcn[1].stats.limit); rt2x00_set_field32(®, TXCSR2_NUM_PRIO, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, - rt2x00dev->bcn[1].data_dma); + rt2x00dev->bcn[1].data_dma); rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, - rt2x00dev->bcn[0].data_dma); + rt2x00dev->bcn[0].data_dma); rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); - rt2x00_set_field32(®, RXCSR1_RXD_SIZE, - rt2x00dev->rx->desc_size); - rt2x00_set_field32(®, RXCSR1_NUM_RXD, - rt2x00dev->rx->stats.limit); + rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); + rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit); rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, - rt2x00dev->rx->data_dma); + rt2x00dev->rx->data_dma); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); return 0; @@ -899,21 +806,6 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; - if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) - return -EBUSY; - - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); - - rt2x00pci_register_read(rt2x00dev, PCICSR, ®); - rt2x00_set_field32(®, PCICSR_BIG_ENDIAN, 0); - rt2x00_set_field32(®, PCICSR_RX_TRESHOLD, 0); - rt2x00_set_field32(®, PCICSR_TX_TRESHOLD, 3); - rt2x00_set_field32(®, PCICSR_BURST_LENTH, 1); - rt2x00_set_field32(®, PCICSR_ENABLE_CLK, 1); - rt2x00_set_field32(®, PCICSR_READ_MULTIPLE, 1); - rt2x00_set_field32(®, PCICSR_WRITE_INVALID, 1); - rt2x00pci_register_write(rt2x00dev, PCICSR, reg); - rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002); rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002); rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00020002); @@ -927,21 +819,9 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00pci_register_read(rt2x00dev, CSR9, ®); rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT, - rt2x00dev->rx->data_size / 128); + rt2x00dev->rx->data_size / 128); rt2x00pci_register_write(rt2x00dev, CSR9, reg); - rt2x00pci_register_write(rt2x00dev, CNT3, 0); - - rt2x00pci_register_write(rt2x00dev, GPIOCSR, 0x0000ff00); - rt2x00pci_register_write(rt2x00dev, TESTCSR, 0x000000f0); - - rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00213223); - rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518); - - rt2x00pci_register_read(rt2x00dev, MACCSR2, ®); - rt2x00_set_field32(®, MACCSR2_DELAY, 64); - rt2x00pci_register_write(rt2x00dev, MACCSR2, reg); - /* * Always use CWmin and CWmax set in descriptor. */ @@ -949,29 +829,76 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, CSR11_CW_SELECT, 0); rt2x00pci_register_write(rt2x00dev, CSR11, reg); + rt2x00pci_register_write(rt2x00dev, CNT3, 0); + + rt2x00pci_register_read(rt2x00dev, TXCSR8, ®); + rt2x00_set_field32(®, TXCSR8_BBP_ID0, 10); + rt2x00_set_field32(®, TXCSR8_BBP_ID0_VALID, 1); + rt2x00_set_field32(®, TXCSR8_BBP_ID1, 11); + rt2x00_set_field32(®, TXCSR8_BBP_ID1_VALID, 1); + rt2x00_set_field32(®, TXCSR8_BBP_ID2, 13); + rt2x00_set_field32(®, TXCSR8_BBP_ID2_VALID, 1); + rt2x00_set_field32(®, TXCSR8_BBP_ID3, 12); + rt2x00_set_field32(®, TXCSR8_BBP_ID3_VALID, 1); + rt2x00pci_register_write(rt2x00dev, TXCSR8, reg); + + rt2x00pci_register_read(rt2x00dev, ARTCSR0, ®); + rt2x00_set_field32(®, ARTCSR0_ACK_CTS_1MBS, 112); + rt2x00_set_field32(®, ARTCSR0_ACK_CTS_2MBS, 56); + rt2x00_set_field32(®, ARTCSR0_ACK_CTS_5_5MBS, 20); + rt2x00_set_field32(®, ARTCSR0_ACK_CTS_11MBS, 10); + rt2x00pci_register_write(rt2x00dev, ARTCSR0, reg); + + rt2x00pci_register_read(rt2x00dev, ARTCSR1, ®); + rt2x00_set_field32(®, ARTCSR1_ACK_CTS_6MBS, 45); + rt2x00_set_field32(®, ARTCSR1_ACK_CTS_9MBS, 37); + rt2x00_set_field32(®, ARTCSR1_ACK_CTS_12MBS, 33); + rt2x00_set_field32(®, ARTCSR1_ACK_CTS_18MBS, 29); + rt2x00pci_register_write(rt2x00dev, ARTCSR1, reg); + + rt2x00pci_register_read(rt2x00dev, ARTCSR2, ®); + rt2x00_set_field32(®, ARTCSR2_ACK_CTS_24MBS, 29); + rt2x00_set_field32(®, ARTCSR2_ACK_CTS_36MBS, 25); + rt2x00_set_field32(®, ARTCSR2_ACK_CTS_48MBS, 25); + rt2x00_set_field32(®, ARTCSR2_ACK_CTS_54MBS, 25); + rt2x00pci_register_write(rt2x00dev, ARTCSR2, reg); + rt2x00pci_register_read(rt2x00dev, RXCSR3, ®); - /* - * Signal. - */ - rt2x00_set_field32(®, RXCSR3_BBP_ID0, 47); + rt2x00_set_field32(®, RXCSR3_BBP_ID0, 47); /* CCK Signal */ rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1); - /* - * Rssi. - */ - rt2x00_set_field32(®, RXCSR3_BBP_ID1, 51); + rt2x00_set_field32(®, RXCSR3_BBP_ID1, 51); /* Rssi */ rt2x00_set_field32(®, RXCSR3_BBP_ID1_VALID, 1); - /* - * OFDM Rate. - */ - rt2x00_set_field32(®, RXCSR3_BBP_ID2, 42); + rt2x00_set_field32(®, RXCSR3_BBP_ID2, 42); /* OFDM Rate */ rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1); - /* - * OFDM. - */ - rt2x00_set_field32(®, RXCSR3_BBP_ID3, 51); + rt2x00_set_field32(®, RXCSR3_BBP_ID3, 51); /* RSSI */ rt2x00_set_field32(®, RXCSR3_BBP_ID3_VALID, 1); rt2x00pci_register_write(rt2x00dev, RXCSR3, reg); + rt2x00pci_register_read(rt2x00dev, PCICSR, ®); + rt2x00_set_field32(®, PCICSR_BIG_ENDIAN, 0); + rt2x00_set_field32(®, PCICSR_RX_TRESHOLD, 0); + rt2x00_set_field32(®, PCICSR_TX_TRESHOLD, 3); + rt2x00_set_field32(®, PCICSR_BURST_LENTH, 1); + rt2x00_set_field32(®, PCICSR_ENABLE_CLK, 1); + rt2x00_set_field32(®, PCICSR_READ_MULTIPLE, 1); + rt2x00_set_field32(®, PCICSR_WRITE_INVALID, 1); + rt2x00pci_register_write(rt2x00dev, PCICSR, reg); + + rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); + + rt2x00pci_register_write(rt2x00dev, GPIOCSR, 0x0000ff00); + rt2x00pci_register_write(rt2x00dev, TESTCSR, 0x000000f0); + + if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) + return -EBUSY; + + rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00213223); + rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518); + + rt2x00pci_register_read(rt2x00dev, MACCSR2, ®); + rt2x00_set_field32(®, MACCSR2_DELAY, 64); + rt2x00pci_register_write(rt2x00dev, MACCSR2, reg); + rt2x00pci_register_read(rt2x00dev, RALINKCSR, ®); rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17); rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 26); @@ -985,10 +912,6 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00pci_register_write(rt2x00dev, TXACKCSR0, 0x00000020); - rt2x00pci_register_write(rt2x00dev, ARTCSR0, 0x7038140a); - rt2x00pci_register_write(rt2x00dev, ARTCSR1, 0x1d21252d); - rt2x00pci_register_write(rt2x00dev, ARTCSR2, 0x1919191d); - rt2x00pci_register_read(rt2x00dev, CSR1, ®); rt2x00_set_field32(®, CSR1_SOFT_RESET, 1); rt2x00_set_field32(®, CSR1_BBP_RESET, 0); @@ -1035,7 +958,6 @@ continue_csr_init: rt2500pci_bbp_write(rt2x00dev, 14, 0x1c); rt2500pci_bbp_write(rt2x00dev, 15, 0x30); rt2500pci_bbp_write(rt2x00dev, 16, 0xac); - rt2500pci_bbp_write(rt2x00dev, 17, 0x48); rt2500pci_bbp_write(rt2x00dev, 18, 0x18); rt2500pci_bbp_write(rt2x00dev, 19, 0xff); rt2500pci_bbp_write(rt2x00dev, 20, 0x1e); @@ -1070,7 +992,7 @@ continue_csr_init: reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n", - reg_id, value); + reg_id, value); rt2500pci_bbp_write(rt2x00dev, reg_id, value); } } @@ -1083,25 +1005,27 @@ continue_csr_init: * Device state switch handlers. */ static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { u32 reg; rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - state == STATE_RADIO_RX_OFF); + state == STATE_RADIO_RX_OFF); rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); } -static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled) +static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, + enum dev_state state) { + int mask = (state == STATE_RADIO_IRQ_OFF); u32 reg; /* * When interrupts are being enabled, the interrupt registers * should clear the register to assure a clean state. */ - if (enabled) { + if (state == STATE_RADIO_IRQ_ON) { rt2x00pci_register_read(rt2x00dev, CSR7, ®); rt2x00pci_register_write(rt2x00dev, CSR7, reg); } @@ -1111,11 +1035,11 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled) * Non-checked interrupt bits are disabled by default. */ rt2x00pci_register_read(rt2x00dev, CSR8, ®); - rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, !enabled); - rt2x00_set_field32(®, CSR8_TXDONE_TXRING, !enabled); - rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, !enabled); - rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, !enabled); - rt2x00_set_field32(®, CSR8_RXDONE, !enabled); + rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); + rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); + rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, mask); + rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); + rt2x00_set_field32(®, CSR8_RXDONE, mask); rt2x00pci_register_write(rt2x00dev, CSR8, reg); } @@ -1134,7 +1058,7 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Enable interrupts. */ - rt2500pci_toggle_irq(rt2x00dev, 1); + rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON); /* * Enable LED @@ -1170,11 +1094,11 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev) /* * Disable interrupts. */ - rt2500pci_toggle_irq(rt2x00dev, 0); + rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF); } static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { u32 reg; unsigned int i; @@ -1206,36 +1130,36 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, } NOTICE(rt2x00dev, "Device failed to enter state %d, " - "current device state: bbp %d and rf %d.\n", - state, bbp_state, rf_state); + "current device state: bbp %d and rf %d.\n", + state, bbp_state, rf_state); return -EBUSY; } static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { int retval = 0; switch (state) { - case STATE_RADIO_ON: - retval = rt2500pci_enable_radio(rt2x00dev); + case STATE_RADIO_ON: + retval = rt2500pci_enable_radio(rt2x00dev); break; - case STATE_RADIO_OFF: - rt2500pci_disable_radio(rt2x00dev); + case STATE_RADIO_OFF: + rt2500pci_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_OFF: - rt2500pci_toggle_rx(rt2x00dev, state); + case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_OFF: + rt2500pci_toggle_rx(rt2x00dev, state); break; - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: - case STATE_AWAKE: - retval = rt2500pci_set_state(rt2x00dev, state); + case STATE_DEEP_SLEEP: + case STATE_SLEEP: + case STATE_STANDBY: + case STATE_AWAKE: + retval = rt2500pci_set_state(rt2x00dev, state); break; - default: - retval = -ENOTSUPP; + default: + retval = -ENOTSUPP; break; } @@ -1246,9 +1170,11 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, * TX descriptor initialization */ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry, struct data_desc *txd, - struct data_entry_desc *desc, struct ieee80211_hdr *ieee80211hdr, - unsigned int length, struct ieee80211_tx_control *control) + struct data_desc *txd, + struct txdata_entry_desc *desc, + struct ieee80211_hdr *ieee80211hdr, + unsigned int length, + struct ieee80211_tx_control *control) { u32 word; @@ -1257,9 +1183,9 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ rt2x00_desc_read(txd, 2, &word); rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(&word, TXD_W2_AIFS, entry->ring->tx_params.aifs); - rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->ring->tx_params.cw_min); - rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->ring->tx_params.cw_max); + rt2x00_set_field32(&word, TXD_W2_AIFS, desc->aifs); + rt2x00_set_field32(&word, TXD_W2_CWMIN, desc->cw_min); + rt2x00_set_field32(&word, TXD_W2_CWMAX, desc->cw_max); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); @@ -1271,23 +1197,25 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_read(txd, 10, &word); rt2x00_set_field32(&word, TXD_W10_RTS, - test_bit(ENTRY_TXD_RTS_FRAME, &entry->flags)); + test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags)); rt2x00_desc_write(txd, 10, word); rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &entry->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_REQ_ACK, &entry->flags)); + !(control->flags & IEEE80211_TXCTL_NO_ACK)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &entry->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &entry->flags)); + test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1); rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); - rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, 0); + rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, + !!(control->flags & + IEEE80211_TXCTL_LONG_RETRY_LIMIT)); rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); @@ -1296,7 +1224,8 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ -static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue) +static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, + unsigned int queue) { u32 reg; @@ -1322,8 +1251,8 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue) /* * RX control handlers */ -static int rt2500pci_fill_rxdone(struct data_entry *entry, - int *signal, int *rssi, int *ofdm) +static void rt2500pci_fill_rxdone(struct data_entry *entry, + struct rxdata_entry_desc *desc) { struct data_desc *rxd = entry->priv; u32 word0; @@ -1332,20 +1261,17 @@ static int rt2500pci_fill_rxdone(struct data_entry *entry, rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 2, &word2); - /* - * TODO: Don't we need to keep statistics - * updated about these errors? - */ - if (rt2x00_get_field32(word0, RXD_W0_CRC) || - rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - return -EINVAL; - - *signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); - *rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - - entry->ring->rt2x00dev->rssi_offset; - *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); - - return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + desc->flags = 0; + if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) + desc->flags |= RX_FLAG_FAILED_FCS_CRC; + if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) + desc->flags |= RX_FLAG_FAILED_PLCP_CRC; + + desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); + desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - + entry->ring->rt2x00dev->rssi_offset; + desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); } /* @@ -1353,7 +1279,7 @@ static int rt2500pci_fill_rxdone(struct data_entry *entry, */ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) { - struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue); + struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); struct data_entry *entry; struct data_desc *txd; u32 word; @@ -1394,7 +1320,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) entry = ring->entry; if (!rt2x00_ring_full(ring)) ieee80211_wake_queue(rt2x00dev->hw, - entry->tx_status.control.queue); + entry->tx_status.control.queue); } static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) @@ -1425,7 +1351,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) * 1 - Beacon timer expired interrupt. */ if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) - rt2x00pci_beacondone(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt2x00lib_beacondone(rt2x00dev); /* * 2 - Rx ring done interrupt. @@ -1455,45 +1381,40 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) } /* - * Device initialization functions. + * Device probe functions. */ -static int rt2500pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) { struct eeprom_93cx6 eeprom; u32 reg; u16 word; u8 *mac; - /* - * Allocate the eeprom memory, check the eeprom width - * and copy the entire eeprom into this allocated memory. - */ - rt2x00dev->eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); - if (!rt2x00dev->eeprom) - return -ENOMEM; - rt2x00pci_register_read(rt2x00dev, CSR21, ®); eeprom.data = rt2x00dev; eeprom.register_read = rt2500pci_eepromregister_read; eeprom.register_write = rt2500pci_eepromregister_write; eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ? - PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; + PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; eeprom.reg_data_in = 0; eeprom.reg_data_out = 0; eeprom.reg_data_clock = 0; eeprom.reg_chip_select = 0; eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, - EEPROM_SIZE / sizeof(u16)); + EEPROM_SIZE / sizeof(u16)); /* * Start validation of the data that has been read. */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { + DECLARE_MAC_BUF(macbuf); + random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac)); + EEPROM(rt2x00dev, "MAC: %s\n", + print_mac(macbuf, mac)); } rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); @@ -1521,7 +1442,7 @@ static int rt2500pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word); if (word == 0xffff) { rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI, - DEFAULT_RSSI_OFFSET); + DEFAULT_RSSI_OFFSET); rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word); EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word); } @@ -1560,22 +1481,24 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Identify default antenna configuration. */ - rt2x00dev->hw->conf.antenna_sel_tx = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_TX_DEFAULT); - rt2x00dev->hw->conf.antenna_sel_rx = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_RX_DEFAULT); + rt2x00dev->hw->conf.antenna_sel_tx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); + rt2x00dev->hw->conf.antenna_sel_rx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); /* * Store led mode, for correct led behaviour. */ - rt2x00dev->led_mode = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_LED_MODE); + rt2x00dev->led_mode = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); /* * Detect if this device has an hardware controlled radio. */ +#ifdef CONFIG_RT2500PCI_RFKILL if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(DEVICE_SUPPORT_HW_BUTTON, &rt2x00dev->flags); + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +#endif /* CONFIG_RT2500PCI_RFKILL */ /* * Check if the BBP tuning should be enabled. @@ -1590,66 +1513,167 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom); rt2x00dev->rssi_offset = - rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI); + rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI); return 0; } -static const struct { - unsigned int chip; - u32 val[3]; -} rf_vals[] = { - { RF2522, { 0x00002050, 0x00000101, 0x00000000 } }, - { RF2523, { 0x00022010, 0x000e0111, 0x00000a1b } }, - { RF2524, { 0x00032020, 0x00000101, 0x00000a1b } }, - { RF2525, { 0x00022020, 0x00060111, 0x00000a1b } }, - { RF2525E, { 0x00022020, 0x00060111, 0x00000a0b } }, - { RF5222, { 0x00000000, 0x00000101, 0x00000000 } }, +/* + * RF value list for RF2522 + * Supports: 2.4 GHz + */ +static const struct rf_channel rf_vals_bg_2522[] = { + { 1, 0x00002050, 0x000c1fda, 0x00000101, 0 }, + { 2, 0x00002050, 0x000c1fee, 0x00000101, 0 }, + { 3, 0x00002050, 0x000c2002, 0x00000101, 0 }, + { 4, 0x00002050, 0x000c2016, 0x00000101, 0 }, + { 5, 0x00002050, 0x000c202a, 0x00000101, 0 }, + { 6, 0x00002050, 0x000c203e, 0x00000101, 0 }, + { 7, 0x00002050, 0x000c2052, 0x00000101, 0 }, + { 8, 0x00002050, 0x000c2066, 0x00000101, 0 }, + { 9, 0x00002050, 0x000c207a, 0x00000101, 0 }, + { 10, 0x00002050, 0x000c208e, 0x00000101, 0 }, + { 11, 0x00002050, 0x000c20a2, 0x00000101, 0 }, + { 12, 0x00002050, 0x000c20b6, 0x00000101, 0 }, + { 13, 0x00002050, 0x000c20ca, 0x00000101, 0 }, + { 14, 0x00002050, 0x000c20fa, 0x00000101, 0 }, }; /* - * RF value list for RF2522 + * RF value list for RF2523 * Supports: 2.4 GHz */ -static const u32 rf_vals_bg_2522[] = { - 0x000c1fda, 0x000c1fee, 0x000c2002, 0x000c2016, 0x000c202a, - 0x000c203e, 0x000c2052, 0x000c2066, 0x000c207a, 0x000c208e, - 0x000c20a2, 0x000c20b6, 0x000c20ca, 0x000c20fa +static const struct rf_channel rf_vals_bg_2523[] = { + { 1, 0x00022010, 0x00000c9e, 0x000e0111, 0x00000a1b }, + { 2, 0x00022010, 0x00000ca2, 0x000e0111, 0x00000a1b }, + { 3, 0x00022010, 0x00000ca6, 0x000e0111, 0x00000a1b }, + { 4, 0x00022010, 0x00000caa, 0x000e0111, 0x00000a1b }, + { 5, 0x00022010, 0x00000cae, 0x000e0111, 0x00000a1b }, + { 6, 0x00022010, 0x00000cb2, 0x000e0111, 0x00000a1b }, + { 7, 0x00022010, 0x00000cb6, 0x000e0111, 0x00000a1b }, + { 8, 0x00022010, 0x00000cba, 0x000e0111, 0x00000a1b }, + { 9, 0x00022010, 0x00000cbe, 0x000e0111, 0x00000a1b }, + { 10, 0x00022010, 0x00000d02, 0x000e0111, 0x00000a1b }, + { 11, 0x00022010, 0x00000d06, 0x000e0111, 0x00000a1b }, + { 12, 0x00022010, 0x00000d0a, 0x000e0111, 0x00000a1b }, + { 13, 0x00022010, 0x00000d0e, 0x000e0111, 0x00000a1b }, + { 14, 0x00022010, 0x00000d1a, 0x000e0111, 0x00000a03 }, }; /* - * RF value list for RF2523, RF2524 & RF2525 + * RF value list for RF2524 * Supports: 2.4 GHz */ -static const u32 rf_vals_bg_252x[] = { - 0x00000c9e, 0x00000ca2, 0x00000ca6, 0x00000caa, 0x00000cae, - 0x00000cb2, 0x00000cb6, 0x00000cba, 0x00000cbe, 0x00000d02, - 0x00000d06, 0x00000d0a, 0x00000d0e, 0x00000d1a +static const struct rf_channel rf_vals_bg_2524[] = { + { 1, 0x00032020, 0x00000c9e, 0x00000101, 0x00000a1b }, + { 2, 0x00032020, 0x00000ca2, 0x00000101, 0x00000a1b }, + { 3, 0x00032020, 0x00000ca6, 0x00000101, 0x00000a1b }, + { 4, 0x00032020, 0x00000caa, 0x00000101, 0x00000a1b }, + { 5, 0x00032020, 0x00000cae, 0x00000101, 0x00000a1b }, + { 6, 0x00032020, 0x00000cb2, 0x00000101, 0x00000a1b }, + { 7, 0x00032020, 0x00000cb6, 0x00000101, 0x00000a1b }, + { 8, 0x00032020, 0x00000cba, 0x00000101, 0x00000a1b }, + { 9, 0x00032020, 0x00000cbe, 0x00000101, 0x00000a1b }, + { 10, 0x00032020, 0x00000d02, 0x00000101, 0x00000a1b }, + { 11, 0x00032020, 0x00000d06, 0x00000101, 0x00000a1b }, + { 12, 0x00032020, 0x00000d0a, 0x00000101, 0x00000a1b }, + { 13, 0x00032020, 0x00000d0e, 0x00000101, 0x00000a1b }, + { 14, 0x00032020, 0x00000d1a, 0x00000101, 0x00000a03 }, }; /* - * RF value list for RF2525E & RF5222 + * RF value list for RF2525 * Supports: 2.4 GHz */ -static const u32 rf_vals_bg_5x[] = { - 0x00001136, 0x0000113a, 0x0000113e, 0x00001182, 0x00001186, - 0x0000118a, 0x0000118e, 0x00001192, 0x00001196, 0x0000119a, - 0x0000119e, 0x000011a2, 0x000011a6, 0x000011ae +static const struct rf_channel rf_vals_bg_2525[] = { + { 1, 0x00022020, 0x00080c9e, 0x00060111, 0x00000a1b }, + { 2, 0x00022020, 0x00080ca2, 0x00060111, 0x00000a1b }, + { 3, 0x00022020, 0x00080ca6, 0x00060111, 0x00000a1b }, + { 4, 0x00022020, 0x00080caa, 0x00060111, 0x00000a1b }, + { 5, 0x00022020, 0x00080cae, 0x00060111, 0x00000a1b }, + { 6, 0x00022020, 0x00080cb2, 0x00060111, 0x00000a1b }, + { 7, 0x00022020, 0x00080cb6, 0x00060111, 0x00000a1b }, + { 8, 0x00022020, 0x00080cba, 0x00060111, 0x00000a1b }, + { 9, 0x00022020, 0x00080cbe, 0x00060111, 0x00000a1b }, + { 10, 0x00022020, 0x00080d02, 0x00060111, 0x00000a1b }, + { 11, 0x00022020, 0x00080d06, 0x00060111, 0x00000a1b }, + { 12, 0x00022020, 0x00080d0a, 0x00060111, 0x00000a1b }, + { 13, 0x00022020, 0x00080d0e, 0x00060111, 0x00000a1b }, + { 14, 0x00022020, 0x00080d1a, 0x00060111, 0x00000a03 }, }; /* - * RF value list for RF5222 (supplement to rf_vals_bg_5x) - * Supports: 5.2 GHz + * RF value list for RF2525e + * Supports: 2.4 GHz */ -static const u32 rf_vals_a_5x[] = { - 0x00018896, 0x0001889a, 0x0001889e, 0x000188a2, 0x000188a6, - 0x000188aa, 0x000188ae, 0x000188b2, 0x00008802, 0x00008806, - 0x0000880a, 0x0000880e, 0x00008812, 0x00008816, 0x0000881a, - 0x0000881e, 0x00008822, 0x00008826, 0x0000882a, 0x000090a6, - 0x000090ae, 0x000090b6, 0x000090be +static const struct rf_channel rf_vals_bg_2525e[] = { + { 1, 0x00022020, 0x00081136, 0x00060111, 0x00000a0b }, + { 2, 0x00022020, 0x0008113a, 0x00060111, 0x00000a0b }, + { 3, 0x00022020, 0x0008113e, 0x00060111, 0x00000a0b }, + { 4, 0x00022020, 0x00081182, 0x00060111, 0x00000a0b }, + { 5, 0x00022020, 0x00081186, 0x00060111, 0x00000a0b }, + { 6, 0x00022020, 0x0008118a, 0x00060111, 0x00000a0b }, + { 7, 0x00022020, 0x0008118e, 0x00060111, 0x00000a0b }, + { 8, 0x00022020, 0x00081192, 0x00060111, 0x00000a0b }, + { 9, 0x00022020, 0x00081196, 0x00060111, 0x00000a0b }, + { 10, 0x00022020, 0x0008119a, 0x00060111, 0x00000a0b }, + { 11, 0x00022020, 0x0008119e, 0x00060111, 0x00000a0b }, + { 12, 0x00022020, 0x000811a2, 0x00060111, 0x00000a0b }, + { 13, 0x00022020, 0x000811a6, 0x00060111, 0x00000a0b }, + { 14, 0x00022020, 0x000811ae, 0x00060111, 0x00000a1b }, }; -static void rt2500pci_init_hw_mode(struct rt2x00_dev *rt2x00dev) +/* + * RF value list for RF5222 + * Supports: 2.4 GHz & 5.2 GHz + */ +static const struct rf_channel rf_vals_5222[] = { + { 1, 0x00022020, 0x00001136, 0x00000101, 0x00000a0b }, + { 2, 0x00022020, 0x0000113a, 0x00000101, 0x00000a0b }, + { 3, 0x00022020, 0x0000113e, 0x00000101, 0x00000a0b }, + { 4, 0x00022020, 0x00001182, 0x00000101, 0x00000a0b }, + { 5, 0x00022020, 0x00001186, 0x00000101, 0x00000a0b }, + { 6, 0x00022020, 0x0000118a, 0x00000101, 0x00000a0b }, + { 7, 0x00022020, 0x0000118e, 0x00000101, 0x00000a0b }, + { 8, 0x00022020, 0x00001192, 0x00000101, 0x00000a0b }, + { 9, 0x00022020, 0x00001196, 0x00000101, 0x00000a0b }, + { 10, 0x00022020, 0x0000119a, 0x00000101, 0x00000a0b }, + { 11, 0x00022020, 0x0000119e, 0x00000101, 0x00000a0b }, + { 12, 0x00022020, 0x000011a2, 0x00000101, 0x00000a0b }, + { 13, 0x00022020, 0x000011a6, 0x00000101, 0x00000a0b }, + { 14, 0x00022020, 0x000011ae, 0x00000101, 0x00000a1b }, + + /* 802.11 UNI / HyperLan 2 */ + { 36, 0x00022010, 0x00018896, 0x00000101, 0x00000a1f }, + { 40, 0x00022010, 0x0001889a, 0x00000101, 0x00000a1f }, + { 44, 0x00022010, 0x0001889e, 0x00000101, 0x00000a1f }, + { 48, 0x00022010, 0x000188a2, 0x00000101, 0x00000a1f }, + { 52, 0x00022010, 0x000188a6, 0x00000101, 0x00000a1f }, + { 66, 0x00022010, 0x000188aa, 0x00000101, 0x00000a1f }, + { 60, 0x00022010, 0x000188ae, 0x00000101, 0x00000a1f }, + { 64, 0x00022010, 0x000188b2, 0x00000101, 0x00000a1f }, + + /* 802.11 HyperLan 2 */ + { 100, 0x00022010, 0x00008802, 0x00000101, 0x00000a0f }, + { 104, 0x00022010, 0x00008806, 0x00000101, 0x00000a0f }, + { 108, 0x00022010, 0x0000880a, 0x00000101, 0x00000a0f }, + { 112, 0x00022010, 0x0000880e, 0x00000101, 0x00000a0f }, + { 116, 0x00022010, 0x00008812, 0x00000101, 0x00000a0f }, + { 120, 0x00022010, 0x00008816, 0x00000101, 0x00000a0f }, + { 124, 0x00022010, 0x0000881a, 0x00000101, 0x00000a0f }, + { 128, 0x00022010, 0x0000881e, 0x00000101, 0x00000a0f }, + { 132, 0x00022010, 0x00008822, 0x00000101, 0x00000a0f }, + { 136, 0x00022010, 0x00008826, 0x00000101, 0x00000a0f }, + + /* 802.11 UNII */ + { 140, 0x00022010, 0x0000882a, 0x00000101, 0x00000a0f }, + { 149, 0x00022020, 0x000090a6, 0x00000101, 0x00000a07 }, + { 153, 0x00022020, 0x000090ae, 0x00000101, 0x00000a07 }, + { 157, 0x00022020, 0x000090b6, 0x00000101, 0x00000a07 }, + { 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 }, +}; + +static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; u8 *txpower; @@ -1658,32 +1682,16 @@ static void rt2500pci_init_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Initialize all hw fields. */ - rt2x00dev->hw->flags = IEEE80211_HW_HOST_GEN_BEACON | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_WEP_INCLUDE_IV | - IEEE80211_HW_DATA_NULLFUNC_ACK | - IEEE80211_HW_NO_TKIP_WMM_HWACCEL | - IEEE80211_HW_MONITOR_DURING_OPER | - IEEE80211_HW_NO_PROBE_FILTERING; + rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; rt2x00dev->hw->extra_tx_headroom = 0; + rt2x00dev->hw->max_signal = MAX_SIGNAL; rt2x00dev->hw->max_rssi = MAX_RX_SSI; - rt2x00dev->hw->max_noise = MAX_RX_NOISE; rt2x00dev->hw->queues = 2; SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); - - /* - * Set device specific, but channel independent RF values. - */ - for (i = 0; i < ARRAY_SIZE(rf_vals); i++) { - if (rt2x00_rf(&rt2x00dev->chip, rf_vals[i].chip)) { - rt2x00dev->rf1 = rf_vals[i].val[0]; - rt2x00dev->rf3 = rf_vals[i].val[1]; - rt2x00dev->rf4 = rf_vals[i].val[2]; - } - } + rt2x00_eeprom_addr(rt2x00dev, + EEPROM_MAC_ADDR_0)); /* * Convert tx_power array in eeprom. @@ -1697,37 +1705,40 @@ static void rt2500pci_init_hw_mode(struct rt2x00_dev *rt2x00dev) */ spec->num_modes = 2; spec->num_rates = 12; - spec->num_channels = 14; spec->tx_power_a = NULL; spec->tx_power_bg = txpower; spec->tx_power_default = DEFAULT_TXPOWER; - spec->chan_val_a = NULL; - - if (rt2x00_rf(&rt2x00dev->chip, RF2522)) - spec->chan_val_bg = rf_vals_bg_2522; - else if (rt2x00_rf(&rt2x00dev->chip, RF2523) || - rt2x00_rf(&rt2x00dev->chip, RF2524) || - rt2x00_rf(&rt2x00dev->chip, RF2525)) - spec->chan_val_bg = rf_vals_bg_252x; - else if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || - rt2x00_rf(&rt2x00dev->chip, RF5222)) - spec->chan_val_bg = rf_vals_bg_5x; - - if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { + + if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { + spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); + spec->channels = rf_vals_bg_2522; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { + spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); + spec->channels = rf_vals_bg_2523; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { + spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); + spec->channels = rf_vals_bg_2524; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { + spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); + spec->channels = rf_vals_bg_2525; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { + spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); + spec->channels = rf_vals_bg_2525e; + } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { + spec->num_channels = ARRAY_SIZE(rf_vals_5222); + spec->channels = rf_vals_5222; spec->num_modes = 3; - spec->num_channels += 23; - spec->chan_val_a = rf_vals_a_5x; } } -static int rt2500pci_init_hw(struct rt2x00_dev *rt2x00dev) +static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; /* * Allocate eeprom data. */ - retval = rt2500pci_alloc_eeprom(rt2x00dev); + retval = rt2500pci_validate_eeprom(rt2x00dev); if (retval) return retval; @@ -1738,12 +1749,17 @@ static int rt2500pci_init_hw(struct rt2x00_dev *rt2x00dev) /* * Initialize hw specifications. */ - rt2500pci_init_hw_mode(rt2x00dev); + rt2500pci_probe_hw_mode(rt2x00dev); + + /* + * This device requires the beacon ring + */ + __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); /* - * This device supports ATIM + * Set the rssi offset. */ - __set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags); + rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; return 0; } @@ -1751,28 +1767,75 @@ static int rt2500pci_init_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static int rt2500pci_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) +static void rt2500pci_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_addr_list *mc_list) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct interface *intf = &rt2x00dev->interface; u32 reg; /* - * Update FCS error count from register. - * The dot11ACKFailureCount, dot11RTSFailureCount and - * dot11RTSSuccessCount are updated in interrupt time. + * Mask off any flags we are going to ignore from + * the total_flags field. */ - rt2x00pci_register_read(rt2x00dev, CNT0, ®); - rt2x00dev->low_level_stats.dot11FCSErrorCount += - rt2x00_get_field32(reg, CNT0_FCS_ERROR); + *total_flags &= + FIF_ALLMULTI | + FIF_FCSFAIL | + FIF_PLCPFAIL | + FIF_CONTROL | + FIF_OTHER_BSS | + FIF_PROMISC_IN_BSS; - memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats)); + /* + * Apply some rules to the filters: + * - Some filters imply different filters to be set. + * - Some things we can't filter out at all. + * - Some filters are set based on interface type. + */ + if (mc_count) + *total_flags |= FIF_ALLMULTI; + if (*total_flags & FIF_OTHER_BSS || + *total_flags & FIF_PROMISC_IN_BSS) + *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; + if (is_interface_type(intf, IEEE80211_IF_TYPE_AP)) + *total_flags |= FIF_PROMISC_IN_BSS; - return 0; + /* + * Check if there is any work left for us. + */ + if (intf->filter == *total_flags) + return; + intf->filter = *total_flags; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DROP_CRC, + !(*total_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, + !(*total_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, + !(*total_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, + !(*total_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_TODS, + !(*total_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); + rt2x00_set_field32(®, RXCSR0_DROP_MCAST, + !(*total_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); } static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw, - u32 short_retry, u32 long_retry) + u32 short_retry, u32 long_retry) { struct rt2x00_dev *rt2x00dev = hw->priv; u32 reg; @@ -1792,7 +1855,7 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw) u32 reg; rt2x00pci_register_read(rt2x00dev, CSR17, ®); - tsf = (u64)rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; + tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; rt2x00pci_register_read(rt2x00dev, CSR16, ®); tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER); @@ -1817,17 +1880,19 @@ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw) } static const struct ieee80211_ops rt2500pci_mac80211_ops = { - .tx = rt2x00lib_tx, - .reset = rt2x00lib_reset, - .add_interface = rt2x00lib_add_interface, - .remove_interface = rt2x00lib_remove_interface, - .config = rt2x00lib_config, - .config_interface = rt2x00lib_config_interface, - .set_multicast_list = rt2x00lib_set_multicast_list, - .get_stats = rt2500pci_get_stats, + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, + .remove_interface = rt2x00mac_remove_interface, + .config = rt2x00mac_config, + .config_interface = rt2x00mac_config_interface, + .configure_filter = rt2500pci_configure_filter, + .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt2500pci_set_retry_limit, - .conf_tx = rt2x00lib_conf_tx, - .get_tx_stats = rt2x00lib_get_tx_stats, + .erp_ie_changed = rt2x00mac_erp_ie_changed, + .conf_tx = rt2x00mac_conf_tx, + .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2500pci_get_tsf, .reset_tsf = rt2500pci_reset_tsf, .beacon_update = rt2x00pci_beacon_update, @@ -1836,37 +1901,35 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .irq_handler = rt2500pci_interrupt, - .init_hw = rt2500pci_init_hw, + .probe_hw = rt2500pci_probe_hw, .initialize = rt2x00pci_initialize, .uninitialize = rt2x00pci_uninitialize, .set_device_state = rt2500pci_set_device_state, -#ifdef CONFIG_RT2500PCI_RFKILL .rfkill_poll = rt2500pci_rfkill_poll, -#endif /* CONFIG_RT2500PCI_RFKILL */ + .link_stats = rt2500pci_link_stats, + .reset_tuner = rt2500pci_reset_tuner, .link_tuner = rt2500pci_link_tuner, .write_tx_desc = rt2500pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, - .config_type = rt2500pci_config_type, - .config_phymode = rt2500pci_config_phymode, - .config_channel = rt2500pci_config_channel, .config_mac_addr = rt2500pci_config_mac_addr, .config_bssid = rt2500pci_config_bssid, - .config_promisc = rt2500pci_config_promisc, - .config_txpower = rt2500pci_config_txpower, - .config_antenna = rt2500pci_config_antenna, - .config_duration = rt2500pci_config_duration, + .config_type = rt2500pci_config_type, + .config_preamble = rt2500pci_config_preamble, + .config = rt2500pci_config, }; static const struct rt2x00_ops rt2500pci_ops = { - .name = DRV_NAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, - .lib = &rt2500pci_rt2x00_ops, - .hw = &rt2500pci_mac80211_ops, + .name = DRV_NAME, + .rxd_size = RXD_DESC_SIZE, + .txd_size = TXD_DESC_SIZE, + .eeprom_size = EEPROM_SIZE, + .rf_size = RF_SIZE, + .lib = &rt2500pci_rt2x00_ops, + .hw = &rt2500pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2500pci_rt2x00debug, + .debugfs = &rt2500pci_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; @@ -1890,10 +1953,8 @@ static struct pci_driver rt2500pci_driver = { .id_table = rt2500pci_device_table, .probe = rt2x00pci_probe, .remove = __devexit_p(rt2x00pci_remove), -#ifdef CONFIG_PM .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, -#endif /* CONFIG_PM */ }; static int __init rt2500pci_init(void) diff --git a/package/rt2x00/src/rt2500pci.h b/package/rt2x00/src/rt2500pci.h index c70bcb790b..d92aa56b2f 100644 --- a/package/rt2x00/src/rt2500pci.h +++ b/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. @@ -946,9 +966,39 @@ #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) @@ -1030,28 +1080,6 @@ #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. */ #define TXD_DESC_SIZE ( 11 * sizeof(struct data_desc) ) @@ -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) diff --git a/package/rt2x00/src/rt2500usb.c b/package/rt2x00/src/rt2500usb.c index 3be51f0a36..18b1f91453 100644 --- a/package/rt2x00/src/rt2500usb.c +++ b/package/rt2x00/src/rt2500usb.c @@ -29,16 +29,14 @@ */ #define DRV_NAME "rt2500usb" +#include <linux/delay.h> +#include <linux/etherdevice.h> +#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> -#include <linux/init.h> #include <linux/usb.h> -#include <linux/delay.h> -#include <linux/etherdevice.h> #include "rt2x00.h" -#include "rt2x00lib.h" #include "rt2x00usb.h" #include "rt2500usb.h" @@ -55,45 +53,47 @@ * the access attempt is considered to have failed, * and we will print an error. */ -static inline void rt2500usb_register_read( - const struct rt2x00_dev *rt2x00dev, - const u16 offset, u16 *value) +static inline void rt2500usb_register_read(const struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u16 *value) { __le16 reg; - rt2x00usb_vendor_request( - rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, - offset, 0x00, ®, sizeof(u16), REGISTER_TIMEOUT); + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, + USB_VENDOR_REQUEST_IN, offset, + ®, sizeof(u16), REGISTER_TIMEOUT); *value = le16_to_cpu(reg); } -static inline void rt2500usb_register_multiread( - const struct rt2x00_dev *rt2x00dev, - const u16 offset, void *value, const u16 length) +static inline void rt2500usb_register_multiread(const struct rt2x00_dev + *rt2x00dev, + const unsigned int offset, + void *value, const u16 length) { - rt2x00usb_vendor_request( - rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, - offset, 0x00, value, length, - REGISTER_TIMEOUT * (length / sizeof(u16))); + int timeout = REGISTER_TIMEOUT * (length / sizeof(u16)); + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, + USB_VENDOR_REQUEST_IN, offset, + value, length, timeout); } -static inline void rt2500usb_register_write( - const struct rt2x00_dev *rt2x00dev, - const u16 offset, u16 value) +static inline void rt2500usb_register_write(const struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u16 value) { __le16 reg = cpu_to_le16(value); - rt2x00usb_vendor_request( - rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, - offset, 0x00, ®, sizeof(u16), REGISTER_TIMEOUT); + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, offset, + ®, sizeof(u16), REGISTER_TIMEOUT); } -static inline void rt2500usb_register_multiwrite( - const struct rt2x00_dev *rt2x00dev, - const u16 offset, void *value, const u16 length) +static inline void rt2500usb_register_multiwrite(const struct rt2x00_dev + *rt2x00dev, + const unsigned int offset, + void *value, const u16 length) { - rt2x00usb_vendor_request( - rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, - offset, 0x00, value, length, - REGISTER_TIMEOUT * (length / sizeof(u16))); + int timeout = REGISTER_TIMEOUT * (length / sizeof(u16)); + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, offset, + value, length, timeout); } static u16 rt2500usb_bbp_check(const struct rt2x00_dev *rt2x00dev) @@ -112,12 +112,12 @@ static u16 rt2500usb_bbp_check(const struct rt2x00_dev *rt2x00dev) } static void rt2500usb_bbp_write(const struct rt2x00_dev *rt2x00dev, - const u8 reg_id, const u8 value) + const unsigned int word, const u8 value) { u16 reg; /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt2500usb_bbp_check(rt2x00dev); if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { @@ -130,19 +130,19 @@ static void rt2500usb_bbp_write(const struct rt2x00_dev *rt2x00dev, */ reg = 0; rt2x00_set_field16(®, PHY_CSR7_DATA, value); - rt2x00_set_field16(®, PHY_CSR7_REG_ID, reg_id); + rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg); } static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev, - const u8 reg_id, u8 *value) + const unsigned int word, u8 *value) { u16 reg; /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt2500usb_bbp_check(rt2x00dev); if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { @@ -153,14 +153,14 @@ static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev, /* * Write the request into the BBP. */ - reg =0; - rt2x00_set_field16(®, PHY_CSR7_REG_ID, reg_id); + reg = 0; + rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt2500usb_bbp_check(rt2x00dev); if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { @@ -174,11 +174,14 @@ static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev, } static void rt2500usb_rf_write(const struct rt2x00_dev *rt2x00dev, - const u32 value) + const unsigned int word, const u32 value) { u16 reg; unsigned int i; + if (!word) + return; + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2500usb_register_read(rt2x00dev, PHY_CSR10, ®); if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY)) @@ -201,134 +204,83 @@ rf_write: rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); rt2500usb_register_write(rt2x00dev, PHY_CSR10, reg); + rt2x00_rf_write(rt2x00dev, word, value); } #ifdef CONFIG_RT2X00_LIB_DEBUGFS #define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u16)) ) -static void rt2500usb_read_csr(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2500usb_register_read(rt2x00dev, CSR_OFFSET(word), data); -} - -static void rt2500usb_write_csr(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2500usb_register_write(rt2x00dev, CSR_OFFSET(word), *((u16*)data)); -} - -static void rt2500usb_read_eeprom(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2x00_eeprom_read(rt2x00dev, word, data); -} - -static void rt2500usb_write_eeprom(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) +static void rt2500usb_read_csr(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 *data) { - rt2x00_eeprom_write(rt2x00dev, word, *((u16*)data)); + rt2500usb_register_read(rt2x00dev, CSR_OFFSET(word), (u16 *) data); } -static void rt2500usb_read_bbp(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) +static void rt2500usb_write_csr(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 data) { - rt2500usb_bbp_read(rt2x00dev, word, data); -} - -static void rt2500usb_write_bbp(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2500usb_bbp_write(rt2x00dev, word, *((u8*)data)); + rt2500usb_register_write(rt2x00dev, CSR_OFFSET(word), data); } static const struct rt2x00debug rt2500usb_rt2x00debug = { - .owner = THIS_MODULE, - .reg_csr = { + .owner = THIS_MODULE, + .csr = { .read = rt2500usb_read_csr, .write = rt2500usb_write_csr, .word_size = sizeof(u16), .word_count = CSR_REG_SIZE / sizeof(u16), }, - .reg_eeprom = { - .read = rt2500usb_read_eeprom, - .write = rt2500usb_write_eeprom, + .eeprom = { + .read = rt2x00_eeprom_read, + .write = rt2x00_eeprom_write, .word_size = sizeof(u16), .word_count = EEPROM_SIZE / sizeof(u16), }, - .reg_bbp = { - .read = rt2500usb_read_bbp, - .write = rt2500usb_write_bbp, + .bbp = { + .read = rt2500usb_bbp_read, + .write = rt2500usb_bbp_write, .word_size = sizeof(u8), .word_count = BBP_SIZE / sizeof(u8), }, + .rf = { + .read = rt2x00_rf_read, + .write = rt2500usb_rf_write, + .word_size = sizeof(u32), + .word_count = RF_SIZE / sizeof(u32), + }, }; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ /* * Configuration handlers. */ -static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) +static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, + __le32 *mac) { - u16 reg[3]; - - memset(®, 0, sizeof(reg)); - memcpy(®, bssid, ETH_ALEN); - - /* - * The BSSID is passed to us as an array of bytes, - * that array is little endian, so no need for byte ordering. - */ - rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, ®, sizeof(reg)); + rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac, + (3 * sizeof(__le16))); } -static void rt2500usb_config_promisc(struct rt2x00_dev *rt2x00dev, - const int promisc) +static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev, + __le32 *bssid) { - u16 reg; - - rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, !promisc); - rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); + rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, bssid, + (3 * sizeof(__le16))); } -static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, - const int type) +static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type, + const int tsf_sync) { u16 reg; rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); /* - * Apply hardware packet filter. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); - - if (!is_monitor_present(&rt2x00dev->interface) && - (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA)) - rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, 1); - else - rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, 0); - - rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC, 1); - if (is_monitor_present(&rt2x00dev->interface)) { - rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, 0); - rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, 0); - rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 0); - } else { - rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, 1); - rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, 1); - rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); - } - - rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); - - /* * Enable beacon config */ rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); rt2x00_set_field16(®, TXRX_CSR20_OFFSET, - (PREAMBLE + get_duration(IEEE80211_HEADER, 2)) >> 6); + (PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6); if (type == IEEE80211_IF_TYPE_STA) rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 0); else @@ -343,72 +295,61 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - if (is_interface_present(&rt2x00dev->interface)) { - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); - } - + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); - if (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_AP) - rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, 2); - else if (type == IEEE80211_IF_TYPE_STA) - rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, 1); - else if (is_monitor_present(&rt2x00dev->interface) && - !is_interface_present(&rt2x00dev->interface)) - rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, 0); - + rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, tsf_sync); rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); } -static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, - const int value, const int channel, const int txpower) +static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { - u32 rf1 = rt2x00dev->rf1; - u32 rf2 = value; - u32 rf3 = rt2x00dev->rf3; - u32 rf4 = rt2x00dev->rf4; + u16 reg; + + /* + * When in atomic context, reschedule and let rt2x00lib + * call this function again. + */ + if (in_atomic()) { + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work); + return; + } - if (rt2x00_rf(&rt2x00dev->chip, RF2525)) - rf2 |= 0x00080000; + rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); + rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, ack_timeout); + rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg); - if ((rt2x00_rf(&rt2x00dev->chip, RF2523) || - rt2x00_rf(&rt2x00dev->chip, RF2524) || - rt2x00_rf(&rt2x00dev->chip, RF2525)) && - channel == 14) - rf4 &= ~0x00000018; + rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®); + rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, + !!short_preamble); + rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); +} - if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { - if (channel & 0x01) - rf4 = 0x00000e1b; - else - rf4 = 0x00000e07; - if (channel == 14) - rf4 = 0x00000e23; - } +static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev, + const int phymode, + const int basic_rate_mask) +{ + rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask); - if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { - if (channel < 14) { - rf1 = 0x00022020; - rf4 = 0x00000a0b; - } else if (channel == 14) { - rf1 = 0x00022010; - rf4 = 0x00000a1b; - } else if (channel < 64) { - rf1 = 0x00022010; - rf4 = 0x00000a1f; - } else if (channel < 140) { - rf1 = 0x00022010; - rf4 = 0x00000a0f; - } else if (channel < 161) { - rf1 = 0x00022020; - rf4 = 0x00000a07; - } + if (phymode == HWMODE_B) { + rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x000b); + rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x0040); + } else { + rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0005); + rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x016c); } +} +static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, + struct rf_channel *rf, const int txpower) +{ /* * Set TXpower. */ - rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); /* * For RT2525E we should first set the channel to half band higher. @@ -421,37 +362,30 @@ static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, 0x00000902, 0x00000906 }; - rt2500usb_rf_write(rt2x00dev, vals[channel - 1]); - if (rf4) - rt2500usb_rf_write(rt2x00dev, rf4); + rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]); + if (rf->rf4) + rt2500usb_rf_write(rt2x00dev, 4, rf->rf4); } - rt2500usb_rf_write(rt2x00dev, rf1); - rt2500usb_rf_write(rt2x00dev, rf2); - rt2500usb_rf_write(rt2x00dev, rf3); - if (rf4) - rt2500usb_rf_write(rt2x00dev, rf4); - - /* - * Update rf fields - */ - rt2x00dev->rf1 = rf1; - rt2x00dev->rf2 = rf2; - rt2x00dev->rf3 = rf3; - rt2x00dev->rf4 = rf4; - rt2x00dev->tx_power = txpower; + rt2500usb_rf_write(rt2x00dev, 1, rf->rf1); + rt2500usb_rf_write(rt2x00dev, 2, rf->rf2); + rt2500usb_rf_write(rt2x00dev, 3, rf->rf3); + if (rf->rf4) + rt2500usb_rf_write(rt2x00dev, 4, rf->rf4); } static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev, - const int txpower) + const int txpower) { - rt2x00_set_field32(&rt2x00dev->rf3, RF3_TXPOWER, - TXPOWER_TO_DEV(txpower)); - rt2500usb_rf_write(rt2x00dev, rt2x00dev->rf3); + u32 rf3; + + rt2x00_rf_read(rt2x00dev, 3, &rf3); + rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); + rt2500usb_rf_write(rt2x00dev, 3, rf3); } static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, - const int antenna_tx, const int antenna_rx) + const int antenna_tx, const int antenna_rx) { u8 r2; u8 r14; @@ -466,29 +400,40 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, /* * Configure the TX antenna. */ - if (antenna_tx == ANTENNA_DIVERSITY) { + switch (antenna_tx) { + case ANTENNA_SW_DIVERSITY: + case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 1); rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 1); rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 1); - } else if (antenna_tx == ANTENNA_A) { + break; + case ANTENNA_A: rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0); rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0); rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0); - } else if (antenna_tx == ANTENNA_B) { + break; + case ANTENNA_B: rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2); rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2); rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 2); + break; } /* * Configure the RX antenna. */ - if (antenna_rx == ANTENNA_DIVERSITY) + switch (antenna_rx) { + case ANTENNA_SW_DIVERSITY: + case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 1); - else if (antenna_rx == ANTENNA_A) + break; + case ANTENNA_A: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0); - else if (antenna_rx == ANTENNA_B) + break; + case ANTENNA_B: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2); + break; + } /* * RT2525E and RT5222 need to flip TX I/Q @@ -516,86 +461,37 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, } static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev, - const int short_slot_time, const int beacon_int) + struct rt2x00lib_conf *libconf) { u16 reg; - rt2500usb_register_write(rt2x00dev, MAC_CSR10, - short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME); + rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time); rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); - rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, beacon_int * 4); + rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, + libconf->conf->beacon_int * 4); rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); } -static void rt2500usb_config_rate(struct rt2x00_dev *rt2x00dev, const int rate) -{ - struct ieee80211_conf *conf = &rt2x00dev->hw->conf; - u16 reg; - u16 value; - u16 preamble; - - preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) - ? SHORT_PREAMBLE : PREAMBLE; - - reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE; - - rt2500usb_register_write(rt2x00dev, TXRX_CSR11, reg); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); - value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ? - SHORT_DIFS : DIFS) + - PLCP + preamble + get_duration(ACK_SIZE, 10); - rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, value); - rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®); - if (preamble == SHORT_PREAMBLE) - rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, 1); - else - rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); -} - -static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev, - const int phymode) -{ - struct ieee80211_hw_mode *mode; - struct ieee80211_rate *rate; - - if (phymode == MODE_IEEE80211A) - rt2x00dev->curr_hwmode = HWMODE_A; - else if (phymode == MODE_IEEE80211B) - rt2x00dev->curr_hwmode = HWMODE_B; - else - rt2x00dev->curr_hwmode = HWMODE_G; - - mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode]; - rate = &mode->rates[mode->num_rates - 1]; - - rt2500usb_config_rate(rt2x00dev, rate->val2); - - if (phymode == MODE_IEEE80211B) { - rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x000b); - rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x0040); - } else { - rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0005); - rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x016c); - } -} - -static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *addr) +static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, + const unsigned int flags, + struct rt2x00lib_conf *libconf) { - u16 reg[3]; - - memset(®, 0, sizeof(reg)); - memcpy(®, addr, ETH_ALEN); - - /* - * The MAC address is passed to us as an array of bytes, - * that array is little endian, so no need for byte ordering. - */ - rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, ®, sizeof(reg)); + if (flags & CONFIG_UPDATE_PHYMODE) + rt2500usb_config_phymode(rt2x00dev, libconf->phymode, + libconf->basic_rates); + if (flags & CONFIG_UPDATE_CHANNEL) + rt2500usb_config_channel(rt2x00dev, &libconf->rf, + libconf->conf->power_level); + if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL)) + rt2500usb_config_txpower(rt2x00dev, + libconf->conf->power_level); + if (flags & CONFIG_UPDATE_ANTENNA) + rt2500usb_config_antenna(rt2x00dev, + libconf->conf->antenna_sel_tx, + libconf->conf->antenna_sel_rx); + if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) + rt2500usb_config_duration(rt2x00dev, libconf); } /* @@ -639,11 +535,52 @@ static void rt2500usb_disable_led(struct rt2x00_dev *rt2x00dev) /* * Link tuning */ +static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev) +{ + u16 reg; + + /* + * Update FCS error count from register. + */ + rt2500usb_register_read(rt2x00dev, STA_CSR0, ®); + rt2x00dev->link.rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR); + + /* + * Update False CCA count from register. + */ + rt2500usb_register_read(rt2x00dev, STA_CSR3, ®); + rt2x00dev->link.false_cca = + rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR); +} + +static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev) +{ + u16 eeprom; + u16 value; + + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &eeprom); + value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R24_LOW); + rt2500usb_bbp_write(rt2x00dev, 24, value); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &eeprom); + value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R25_LOW); + rt2500usb_bbp_write(rt2x00dev, 25, value); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &eeprom); + value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R61_LOW); + rt2500usb_bbp_write(rt2x00dev, 61, value); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &eeprom); + value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER); + rt2500usb_bbp_write(rt2x00dev, 17, value); + + rt2x00dev->link.vgc_level = value; +} + static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) { int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); u16 bbp_thresh; - u16 cca_alarm; u16 vgc_bound; u16 sens; u16 r24; @@ -721,7 +658,6 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Leave short or middle distance condition, restore r17 * to the dynamic tuning range. */ - rt2500usb_register_read(rt2x00dev, STA_CSR3, &cca_alarm); rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound); vgc_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER); @@ -736,13 +672,13 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) if (r17 > up_bound) { rt2500usb_bbp_write(rt2x00dev, 17, up_bound); - rt2x00dev->rx_status.noise = up_bound; - } else if (cca_alarm > 512 && r17 < up_bound) { + rt2x00dev->link.vgc_level = up_bound; + } else if (rt2x00dev->link.false_cca > 512 && r17 < up_bound) { rt2500usb_bbp_write(rt2x00dev, 17, ++r17); - rt2x00dev->rx_status.noise = r17; - } else if (cca_alarm < 100 && r17 > low_bound) { + rt2x00dev->link.vgc_level = r17; + } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) { rt2500usb_bbp_write(rt2x00dev, 17, --r17); - rt2x00dev->rx_status.noise = r17; + rt2x00dev->link.vgc_level = r17; } } @@ -753,12 +689,10 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) { u16 reg; - rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE, - USB_VENDOR_REQUEST_OUT, 0x0001, USB_MODE_TEST, NULL, 0, - REGISTER_TIMEOUT); - rt2x00usb_vendor_request(rt2x00dev, USB_SINGLE_WRITE, - USB_VENDOR_REQUEST_OUT, 0x0308, 0xf0, NULL, 0, - REGISTER_TIMEOUT); + rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0x0001, + USB_MODE_TEST, REGISTER_TIMEOUT); + rt2x00usb_vendor_request_sw(rt2x00dev, USB_SINGLE_WRITE, 0x0308, + 0x00f0, REGISTER_TIMEOUT); rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 1); @@ -767,19 +701,57 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x1111); rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x1e11); - rt2500usb_register_write(rt2x00dev, MAC_CSR1, 0x0003); - rt2500usb_register_write(rt2x00dev, MAC_CSR1, 0x0000); - rt2500usb_register_write(rt2x00dev, TXRX_CSR5, 0x8c8d); - rt2500usb_register_write(rt2x00dev, TXRX_CSR6, 0x8b8a); - rt2500usb_register_write(rt2x00dev, TXRX_CSR7, 0x8687); - rt2500usb_register_write(rt2x00dev, TXRX_CSR8, 0x0085); + rt2500usb_register_read(rt2x00dev, MAC_CSR1, ®); + rt2x00_set_field16(®, MAC_CSR1_SOFT_RESET, 1); + rt2x00_set_field16(®, MAC_CSR1_BBP_RESET, 1); + rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); + + rt2500usb_register_read(rt2x00dev, MAC_CSR1, ®); + rt2x00_set_field16(®, MAC_CSR1_SOFT_RESET, 0); + rt2x00_set_field16(®, MAC_CSR1_BBP_RESET, 0); + rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); + + rt2500usb_register_read(rt2x00dev, TXRX_CSR5, ®); + rt2x00_set_field16(®, TXRX_CSR5_BBP_ID0, 13); + rt2x00_set_field16(®, TXRX_CSR5_BBP_ID0_VALID, 1); + rt2x00_set_field16(®, TXRX_CSR5_BBP_ID1, 12); + rt2x00_set_field16(®, TXRX_CSR5_BBP_ID1_VALID, 1); + rt2500usb_register_write(rt2x00dev, TXRX_CSR5, reg); + + rt2500usb_register_read(rt2x00dev, TXRX_CSR6, ®); + rt2x00_set_field16(®, TXRX_CSR6_BBP_ID0, 10); + rt2x00_set_field16(®, TXRX_CSR6_BBP_ID0_VALID, 1); + rt2x00_set_field16(®, TXRX_CSR6_BBP_ID1, 11); + rt2x00_set_field16(®, TXRX_CSR6_BBP_ID1_VALID, 1); + rt2500usb_register_write(rt2x00dev, TXRX_CSR6, reg); + + rt2500usb_register_read(rt2x00dev, TXRX_CSR7, ®); + rt2x00_set_field16(®, TXRX_CSR7_BBP_ID0, 7); + rt2x00_set_field16(®, TXRX_CSR7_BBP_ID0_VALID, 1); + rt2x00_set_field16(®, TXRX_CSR7_BBP_ID1, 6); + rt2x00_set_field16(®, TXRX_CSR7_BBP_ID1_VALID, 1); + rt2500usb_register_write(rt2x00dev, TXRX_CSR7, reg); + + rt2500usb_register_read(rt2x00dev, TXRX_CSR8, ®); + rt2x00_set_field16(®, TXRX_CSR8_BBP_ID0, 5); + rt2x00_set_field16(®, TXRX_CSR8_BBP_ID0_VALID, 1); + rt2x00_set_field16(®, TXRX_CSR8_BBP_ID1, 0); + rt2x00_set_field16(®, TXRX_CSR8_BBP_ID1_VALID, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR8, reg); + rt2500usb_register_write(rt2x00dev, TXRX_CSR21, 0xe78f); rt2500usb_register_write(rt2x00dev, MAC_CSR9, 0xff1d); if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) return -EBUSY; - rt2500usb_register_write(rt2x00dev, MAC_CSR1, 0x0004); + rt2500usb_register_read(rt2x00dev, MAC_CSR1, ®); + rt2x00_set_field16(®, MAC_CSR1_SOFT_RESET, 0); + rt2x00_set_field16(®, MAC_CSR1_BBP_RESET, 0); + rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); + rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); @@ -794,27 +766,28 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2500usb_register_write(rt2x00dev, MAC_CSR15, 0x01ee); rt2500usb_register_write(rt2x00dev, MAC_CSR16, 0x0000); + rt2500usb_register_read(rt2x00dev, MAC_CSR8, ®); + rt2x00_set_field16(®, MAC_CSR8_MAX_FRAME_UNIT, + rt2x00dev->rx->data_size); + rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg); + rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field16(®, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER); rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, 0xff); rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg); - rt2500usb_register_read(rt2x00dev, MAC_CSR8, ®); - rt2x00_set_field16(®, MAC_CSR8_MAX_FRAME_UNIT, - rt2x00dev->rx->data_size); - rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg); - rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); - rt2x00_set_field16(®, MAC_CSR18_DELAY_AFTER_BEACON, 0x5a); + rt2x00_set_field16(®, MAC_CSR18_DELAY_AFTER_BEACON, 90); rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); + rt2500usb_register_read(rt2x00dev, PHY_CSR4, ®); + rt2x00_set_field16(®, PHY_CSR4_LOW_RF_LE, 1); + rt2500usb_register_write(rt2x00dev, PHY_CSR4, reg); + rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); rt2x00_set_field16(®, TXRX_CSR1_AUTO_SEQUENCE, 1); rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg); - rt2500usb_register_read(rt2x00dev, PHY_CSR4, ®); - rt2500usb_register_write(rt2x00dev, PHY_CSR4, reg | 0x0001); - return 0; } @@ -842,7 +815,6 @@ continue_csr_init: rt2500usb_bbp_write(rt2x00dev, 14, 0x1c); rt2500usb_bbp_write(rt2x00dev, 15, 0x30); rt2500usb_bbp_write(rt2x00dev, 16, 0xac); - rt2500usb_bbp_write(rt2x00dev, 17, 0x48); rt2500usb_bbp_write(rt2x00dev, 18, 0x18); rt2500usb_bbp_write(rt2x00dev, 19, 0xff); rt2500usb_bbp_write(rt2x00dev, 20, 0x1e); @@ -878,28 +850,12 @@ continue_csr_init: reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n", - reg_id, value); + reg_id, value); rt2500usb_bbp_write(rt2x00dev, reg_id, value); } } DEBUG(rt2x00dev, "...End initialization from EEPROM.\n"); - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &eeprom); - value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R24_LOW); - rt2500usb_bbp_write(rt2x00dev, 24, value); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &eeprom); - value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R25_LOW); - rt2500usb_bbp_write(rt2x00dev, 25, value); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &eeprom); - value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R61_LOW); - rt2500usb_bbp_write(rt2x00dev, 61, value); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &eeprom); - value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER); - rt2500usb_bbp_write(rt2x00dev, 17, value); - return 0; } @@ -907,13 +863,13 @@ continue_csr_init: * Device state switch handlers. */ static void rt2500usb_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { u16 reg; rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, - state == STATE_RADIO_RX_OFF); + state == STATE_RADIO_RX_OFF); rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); } @@ -957,7 +913,7 @@ static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev) } static int rt2500usb_set_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { u16 reg; u16 reg2; @@ -992,36 +948,36 @@ static int rt2500usb_set_state(struct rt2x00_dev *rt2x00dev, } NOTICE(rt2x00dev, "Device failed to enter state %d, " - "current device state: bbp %d and rf %d.\n", - state, bbp_state, rf_state); + "current device state: bbp %d and rf %d.\n", + state, bbp_state, rf_state); return -EBUSY; } static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { int retval = 0; switch (state) { - case STATE_RADIO_ON: - retval = rt2500usb_enable_radio(rt2x00dev); + case STATE_RADIO_ON: + retval = rt2500usb_enable_radio(rt2x00dev); break; - case STATE_RADIO_OFF: - rt2500usb_disable_radio(rt2x00dev); + case STATE_RADIO_OFF: + rt2500usb_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_OFF: - rt2500usb_toggle_rx(rt2x00dev, state); + case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_OFF: + rt2500usb_toggle_rx(rt2x00dev, state); break; - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: - case STATE_AWAKE: - retval = rt2500usb_set_state(rt2x00dev, state); + case STATE_DEEP_SLEEP: + case STATE_SLEEP: + case STATE_STANDBY: + case STATE_AWAKE: + retval = rt2500usb_set_state(rt2x00dev, state); break; - default: - retval = -ENOTSUPP; + default: + retval = -ENOTSUPP; break; } @@ -1032,9 +988,11 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, * TX descriptor initialization */ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry, struct data_desc *txd, - struct data_entry_desc *desc, struct ieee80211_hdr *ieee80211hdr, - unsigned int length, struct ieee80211_tx_control *control) + struct data_desc *txd, + struct txdata_entry_desc *desc, + struct ieee80211_hdr *ieee80211hdr, + unsigned int length, + struct ieee80211_tx_control *control) { u32 word; @@ -1043,9 +1001,9 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(&word, TXD_W1_AIFS, entry->ring->tx_params.aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->ring->tx_params.cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->ring->tx_params.cw_max); + rt2x00_set_field32(&word, TXD_W1_AIFS, desc->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); @@ -1058,25 +1016,41 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, control->retry_limit); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &entry->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_REQ_ACK, &entry->flags)); + !(control->flags & IEEE80211_TXCTL_NO_ACK)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &entry->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &entry->flags)); + test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, - control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT); + !!(control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT)); rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length); rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } +static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb) +{ + int length; + + /* + * The length _must_ be a multiple of 2, + * but it must _not_ be a multiple of the USB packet size. + */ + length = roundup(skb->len, 2); + length += (2 * !(length % rt2x00dev->usb_maxpacket)); + + return length; +} + /* * TX data initialization */ -static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue) +static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, + unsigned int queue) { u16 reg; @@ -1102,68 +1076,88 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue) /* * RX control handlers */ -static int rt2500usb_fill_rxdone(struct data_entry *entry, - int *signal, int *rssi, int *ofdm) +static void rt2500usb_fill_rxdone(struct data_entry *entry, + struct rxdata_entry_desc *desc) { struct urb *urb = entry->priv; - struct data_desc *rxd = (struct data_desc*)(entry->skb->data + - (urb->actual_length - entry->ring->desc_size)); + struct data_desc *rxd = (struct data_desc *)(entry->skb->data + + (urb->actual_length - + entry->ring->desc_size)); u32 word0; u32 word1; rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); - /* - * TODO: Don't we need to keep statistics - * updated about these errors? - */ - if (rt2x00_get_field32(word0, RXD_W0_CRC) || - rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - return -EINVAL; + desc->flags = 0; + if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) + desc->flags |= RX_FLAG_FAILED_FCS_CRC; + if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) + desc->flags |= RX_FLAG_FAILED_PLCP_CRC; /* * Obtain the status about this packet. */ - *signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - *rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - - entry->ring->rt2x00dev->rssi_offset; - *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + desc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - + entry->ring->rt2x00dev->rssi_offset; + desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + + return; +} + +/* + * Interrupt functions. + */ +static void rt2500usb_beacondone(struct urb *urb) +{ + struct data_entry *entry = (struct data_entry *)urb->context; + struct data_ring *ring = entry->ring; + + if (!test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) + return; /* - * rt2570 includes the FCS, so fix data length accordingly. + * 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. */ - return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT) - FCS_LEN; + 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); + } } /* - * Device initialization functions. + * Device probe functions. */ -static int rt2500usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) { u16 word; u8 *mac; - /* - * Allocate the eeprom memory, check the eeprom width - * and copy the entire eeprom into this allocated memory. - */ - rt2x00dev->eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); - if (!rt2x00dev->eeprom) - return -ENOMEM; - - rt2x00usb_vendor_request( - rt2x00dev, USB_EEPROM_READ, USB_VENDOR_REQUEST_IN, - EEPROM_BASE, 0x00, rt2x00dev->eeprom, EEPROM_SIZE, - REGISTER_TIMEOUT * (EEPROM_SIZE / sizeof(u16))); + rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); /* * Start validation of the data that has been read. */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { + DECLARE_MAC_BUF(macbuf); + random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac)); + EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac)); } rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); @@ -1191,7 +1185,7 @@ static int rt2500usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word); if (word == 0xffff) { rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI, - DEFAULT_RSSI_OFFSET); + DEFAULT_RSSI_OFFSET); rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word); EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word); } @@ -1263,6 +1257,11 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2570, value, reg); + if (!rt2x00_check_rev(&rt2x00dev->chip, 0)) { + ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); + return -ENODEV; + } + if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && !rt2x00_rf(&rt2x00dev->chip, RF2523) && !rt2x00_rf(&rt2x00dev->chip, RF2524) && @@ -1276,16 +1275,16 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Identify default antenna configuration. */ - rt2x00dev->hw->conf.antenna_sel_tx = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_TX_DEFAULT); - rt2x00dev->hw->conf.antenna_sel_rx = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_RX_DEFAULT); + rt2x00dev->hw->conf.antenna_sel_tx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); + rt2x00dev->hw->conf.antenna_sel_rx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); /* * Store led mode, for correct led behaviour. */ - rt2x00dev->led_mode = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_LED_MODE); + rt2x00dev->led_mode = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); /* * Check if the BBP tuning should be disabled. @@ -1299,69 +1298,167 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) */ rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom); rt2x00dev->rssi_offset = - rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI); + rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI); return 0; } -static const struct { - unsigned int chip; - u32 val[3]; -} rf_vals[] = { - { RF2522, { 0x00002050, 0x00000101, 0x00000000 } }, - { RF2523, { 0x00022010, 0x000e0111, 0x00000a1b } }, - { RF2524, { 0x00032020, 0x00000101, 0x00000a1b } }, - { RF2525, { 0x00022020, 0x00060111, 0x00000a1b } }, - { RF2525E, { 0x00022010, 0x00060111, 0x00000000 } }, - { RF5222, { 0x00000000, 0x00000101, 0x00000000 } } +/* + * RF value list for RF2522 + * Supports: 2.4 GHz + */ +static const struct rf_channel rf_vals_bg_2522[] = { + { 1, 0x00002050, 0x000c1fda, 0x00000101, 0 }, + { 2, 0x00002050, 0x000c1fee, 0x00000101, 0 }, + { 3, 0x00002050, 0x000c2002, 0x00000101, 0 }, + { 4, 0x00002050, 0x000c2016, 0x00000101, 0 }, + { 5, 0x00002050, 0x000c202a, 0x00000101, 0 }, + { 6, 0x00002050, 0x000c203e, 0x00000101, 0 }, + { 7, 0x00002050, 0x000c2052, 0x00000101, 0 }, + { 8, 0x00002050, 0x000c2066, 0x00000101, 0 }, + { 9, 0x00002050, 0x000c207a, 0x00000101, 0 }, + { 10, 0x00002050, 0x000c208e, 0x00000101, 0 }, + { 11, 0x00002050, 0x000c20a2, 0x00000101, 0 }, + { 12, 0x00002050, 0x000c20b6, 0x00000101, 0 }, + { 13, 0x00002050, 0x000c20ca, 0x00000101, 0 }, + { 14, 0x00002050, 0x000c20fa, 0x00000101, 0 }, }; /* - * RF value list for RF2522 + * RF value list for RF2523 * Supports: 2.4 GHz */ -static const u32 rf_vals_bg_2522[] = { - 0x000c1fda, 0x000c1fee, 0x000c2002, 0x000c2016, 0x000c202a, - 0x000c203e, 0x000c2052, 0x000c2066, 0x000c207a, 0x000c208e, - 0x000c20a2, 0x000c20b6, 0x000c20ca, 0x000c20fa +static const struct rf_channel rf_vals_bg_2523[] = { + { 1, 0x00022010, 0x00000c9e, 0x000e0111, 0x00000a1b }, + { 2, 0x00022010, 0x00000ca2, 0x000e0111, 0x00000a1b }, + { 3, 0x00022010, 0x00000ca6, 0x000e0111, 0x00000a1b }, + { 4, 0x00022010, 0x00000caa, 0x000e0111, 0x00000a1b }, + { 5, 0x00022010, 0x00000cae, 0x000e0111, 0x00000a1b }, + { 6, 0x00022010, 0x00000cb2, 0x000e0111, 0x00000a1b }, + { 7, 0x00022010, 0x00000cb6, 0x000e0111, 0x00000a1b }, + { 8, 0x00022010, 0x00000cba, 0x000e0111, 0x00000a1b }, + { 9, 0x00022010, 0x00000cbe, 0x000e0111, 0x00000a1b }, + { 10, 0x00022010, 0x00000d02, 0x000e0111, 0x00000a1b }, + { 11, 0x00022010, 0x00000d06, 0x000e0111, 0x00000a1b }, + { 12, 0x00022010, 0x00000d0a, 0x000e0111, 0x00000a1b }, + { 13, 0x00022010, 0x00000d0e, 0x000e0111, 0x00000a1b }, + { 14, 0x00022010, 0x00000d1a, 0x000e0111, 0x00000a03 }, }; /* - * RF value list for RF2523, RF2524 & RF2525 + * RF value list for RF2524 * Supports: 2.4 GHz */ -static const u32 rf_vals_bg_252x[] = { - 0x00000c9e, 0x00000ca2, 0x00000ca6, 0x00000caa, 0x00000cae, - 0x00000cb2, 0x00000cb6, 0x00000cba, 0x00000cbe, 0x00000d02, - 0x00000d06, 0x00000d0a, 0x00000d0e, 0x00000d1a +static const struct rf_channel rf_vals_bg_2524[] = { + { 1, 0x00032020, 0x00000c9e, 0x00000101, 0x00000a1b }, + { 2, 0x00032020, 0x00000ca2, 0x00000101, 0x00000a1b }, + { 3, 0x00032020, 0x00000ca6, 0x00000101, 0x00000a1b }, + { 4, 0x00032020, 0x00000caa, 0x00000101, 0x00000a1b }, + { 5, 0x00032020, 0x00000cae, 0x00000101, 0x00000a1b }, + { 6, 0x00032020, 0x00000cb2, 0x00000101, 0x00000a1b }, + { 7, 0x00032020, 0x00000cb6, 0x00000101, 0x00000a1b }, + { 8, 0x00032020, 0x00000cba, 0x00000101, 0x00000a1b }, + { 9, 0x00032020, 0x00000cbe, 0x00000101, 0x00000a1b }, + { 10, 0x00032020, 0x00000d02, 0x00000101, 0x00000a1b }, + { 11, 0x00032020, 0x00000d06, 0x00000101, 0x00000a1b }, + { 12, 0x00032020, 0x00000d0a, 0x00000101, 0x00000a1b }, + { 13, 0x00032020, 0x00000d0e, 0x00000101, 0x00000a1b }, + { 14, 0x00032020, 0x00000d1a, 0x00000101, 0x00000a03 }, }; /* - * RF value list for RF2525E + * RF value list for RF2525 * Supports: 2.4 GHz */ -static const u32 rf_vals_bg_2525e[] = { - 0x0000089a, 0x0000089e, 0x0000089e, 0x000008a2, 0x000008a2, - 0x000008a6, 0x000008a6, 0x000008aa, 0x000008aa, 0x000008ae, - 0x000008ae, 0x000008b2, 0x000008b2, 0x000008b6 +static const struct rf_channel rf_vals_bg_2525[] = { + { 1, 0x00022020, 0x00080c9e, 0x00060111, 0x00000a1b }, + { 2, 0x00022020, 0x00080ca2, 0x00060111, 0x00000a1b }, + { 3, 0x00022020, 0x00080ca6, 0x00060111, 0x00000a1b }, + { 4, 0x00022020, 0x00080caa, 0x00060111, 0x00000a1b }, + { 5, 0x00022020, 0x00080cae, 0x00060111, 0x00000a1b }, + { 6, 0x00022020, 0x00080cb2, 0x00060111, 0x00000a1b }, + { 7, 0x00022020, 0x00080cb6, 0x00060111, 0x00000a1b }, + { 8, 0x00022020, 0x00080cba, 0x00060111, 0x00000a1b }, + { 9, 0x00022020, 0x00080cbe, 0x00060111, 0x00000a1b }, + { 10, 0x00022020, 0x00080d02, 0x00060111, 0x00000a1b }, + { 11, 0x00022020, 0x00080d06, 0x00060111, 0x00000a1b }, + { 12, 0x00022020, 0x00080d0a, 0x00060111, 0x00000a1b }, + { 13, 0x00022020, 0x00080d0e, 0x00060111, 0x00000a1b }, + { 14, 0x00022020, 0x00080d1a, 0x00060111, 0x00000a03 }, +}; + +/* + * RF value list for RF2525e + * Supports: 2.4 GHz + */ +static const struct rf_channel rf_vals_bg_2525e[] = { + { 1, 0x00022010, 0x0000089a, 0x00060111, 0x00000e1b }, + { 2, 0x00022010, 0x0000089e, 0x00060111, 0x00000e07 }, + { 3, 0x00022010, 0x0000089e, 0x00060111, 0x00000e1b }, + { 4, 0x00022010, 0x000008a2, 0x00060111, 0x00000e07 }, + { 5, 0x00022010, 0x000008a2, 0x00060111, 0x00000e1b }, + { 6, 0x00022010, 0x000008a6, 0x00060111, 0x00000e07 }, + { 7, 0x00022010, 0x000008a6, 0x00060111, 0x00000e1b }, + { 8, 0x00022010, 0x000008aa, 0x00060111, 0x00000e07 }, + { 9, 0x00022010, 0x000008aa, 0x00060111, 0x00000e1b }, + { 10, 0x00022010, 0x000008ae, 0x00060111, 0x00000e07 }, + { 11, 0x00022010, 0x000008ae, 0x00060111, 0x00000e1b }, + { 12, 0x00022010, 0x000008b2, 0x00060111, 0x00000e07 }, + { 13, 0x00022010, 0x000008b2, 0x00060111, 0x00000e1b }, + { 14, 0x00022010, 0x000008b6, 0x00060111, 0x00000e23 }, }; /* * RF value list for RF5222 * Supports: 2.4 GHz & 5.2 GHz */ -static const u32 rf_vals_abg_5222[] = { - 0x00001136, 0x0000113a, 0x0000113e, 0x00001182, 0x00001186, - 0x0000118a, 0x0000118e, 0x00001192, 0x00001196, 0x0000119a, - 0x0000119e, 0x000011a2, 0x000011a6, 0x000011ae, 0x0001889a, - 0x0001889a, 0x0001889e, 0x000188a2, 0x000188a6, 0x000188aa, - 0x000188ae, 0x000188b2, 0x00008802, 0x00008806, 0x0000880a, - 0x0000880e, 0x00008812, 0x00008816, 0x0000881a, 0x0000881e, - 0x00008822, 0x00008826, 0x0000882a, 0x000090a6, 0x000090ae, - 0x000090b6, 0x000090be +static const struct rf_channel rf_vals_5222[] = { + { 1, 0x00022020, 0x00001136, 0x00000101, 0x00000a0b }, + { 2, 0x00022020, 0x0000113a, 0x00000101, 0x00000a0b }, + { 3, 0x00022020, 0x0000113e, 0x00000101, 0x00000a0b }, + { 4, 0x00022020, 0x00001182, 0x00000101, 0x00000a0b }, + { 5, 0x00022020, 0x00001186, 0x00000101, 0x00000a0b }, + { 6, 0x00022020, 0x0000118a, 0x00000101, 0x00000a0b }, + { 7, 0x00022020, 0x0000118e, 0x00000101, 0x00000a0b }, + { 8, 0x00022020, 0x00001192, 0x00000101, 0x00000a0b }, + { 9, 0x00022020, 0x00001196, 0x00000101, 0x00000a0b }, + { 10, 0x00022020, 0x0000119a, 0x00000101, 0x00000a0b }, + { 11, 0x00022020, 0x0000119e, 0x00000101, 0x00000a0b }, + { 12, 0x00022020, 0x000011a2, 0x00000101, 0x00000a0b }, + { 13, 0x00022020, 0x000011a6, 0x00000101, 0x00000a0b }, + { 14, 0x00022020, 0x000011ae, 0x00000101, 0x00000a1b }, + + /* 802.11 UNI / HyperLan 2 */ + { 36, 0x00022010, 0x00018896, 0x00000101, 0x00000a1f }, + { 40, 0x00022010, 0x0001889a, 0x00000101, 0x00000a1f }, + { 44, 0x00022010, 0x0001889e, 0x00000101, 0x00000a1f }, + { 48, 0x00022010, 0x000188a2, 0x00000101, 0x00000a1f }, + { 52, 0x00022010, 0x000188a6, 0x00000101, 0x00000a1f }, + { 66, 0x00022010, 0x000188aa, 0x00000101, 0x00000a1f }, + { 60, 0x00022010, 0x000188ae, 0x00000101, 0x00000a1f }, + { 64, 0x00022010, 0x000188b2, 0x00000101, 0x00000a1f }, + + /* 802.11 HyperLan 2 */ + { 100, 0x00022010, 0x00008802, 0x00000101, 0x00000a0f }, + { 104, 0x00022010, 0x00008806, 0x00000101, 0x00000a0f }, + { 108, 0x00022010, 0x0000880a, 0x00000101, 0x00000a0f }, + { 112, 0x00022010, 0x0000880e, 0x00000101, 0x00000a0f }, + { 116, 0x00022010, 0x00008812, 0x00000101, 0x00000a0f }, + { 120, 0x00022010, 0x00008816, 0x00000101, 0x00000a0f }, + { 124, 0x00022010, 0x0000881a, 0x00000101, 0x00000a0f }, + { 128, 0x00022010, 0x0000881e, 0x00000101, 0x00000a0f }, + { 132, 0x00022010, 0x00008822, 0x00000101, 0x00000a0f }, + { 136, 0x00022010, 0x00008826, 0x00000101, 0x00000a0f }, + + /* 802.11 UNII */ + { 140, 0x00022010, 0x0000882a, 0x00000101, 0x00000a0f }, + { 149, 0x00022020, 0x000090a6, 0x00000101, 0x00000a07 }, + { 153, 0x00022020, 0x000090ae, 0x00000101, 0x00000a07 }, + { 157, 0x00022020, 0x000090b6, 0x00000101, 0x00000a07 }, + { 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 }, }; -static void rt2500usb_init_hw_mode(struct rt2x00_dev *rt2x00dev) +static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; u8 *txpower; @@ -1370,32 +1467,19 @@ static void rt2500usb_init_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Initialize all hw fields. */ - rt2x00dev->hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_WEP_INCLUDE_IV | - IEEE80211_HW_DATA_NULLFUNC_ACK | - IEEE80211_HW_NO_TKIP_WMM_HWACCEL | - IEEE80211_HW_MONITOR_DURING_OPER | - IEEE80211_HW_NO_PROBE_FILTERING; + rt2x00dev->hw->flags = + IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | + IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; + rt2x00dev->hw->max_signal = MAX_SIGNAL; rt2x00dev->hw->max_rssi = MAX_RX_SSI; - rt2x00dev->hw->max_noise = MAX_RX_NOISE; rt2x00dev->hw->queues = 2; SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); - - /* - * Set device specific, but channel independent RF values. - */ - for (i = 0; i < ARRAY_SIZE(rf_vals); i++) { - if (rt2x00_rf(&rt2x00dev->chip, rf_vals[i].chip)) { - rt2x00dev->rf1 = rf_vals[i].val[0]; - rt2x00dev->rf3 = rf_vals[i].val[1]; - rt2x00dev->rf4 = rf_vals[i].val[2]; - } - } + rt2x00_eeprom_addr(rt2x00dev, + EEPROM_MAC_ADDR_0)); /* * Convert tx_power array in eeprom. @@ -1409,38 +1493,40 @@ static void rt2500usb_init_hw_mode(struct rt2x00_dev *rt2x00dev) */ spec->num_modes = 2; spec->num_rates = 12; - spec->num_channels = 14; spec->tx_power_a = NULL; spec->tx_power_bg = txpower; spec->tx_power_default = DEFAULT_TXPOWER; - spec->chan_val_a = NULL; - - if (rt2x00_rf(&rt2x00dev->chip, RF2522)) - spec->chan_val_bg = rf_vals_bg_2522; - else if (rt2x00_rf(&rt2x00dev->chip, RF2523) || - rt2x00_rf(&rt2x00dev->chip, RF2524) || - rt2x00_rf(&rt2x00dev->chip, RF2525)) - spec->chan_val_bg = rf_vals_bg_252x; - else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) - spec->chan_val_bg = rf_vals_bg_2525e; - else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) - spec->chan_val_bg = rf_vals_abg_5222; - - if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { + + if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { + spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); + spec->channels = rf_vals_bg_2522; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { + spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); + spec->channels = rf_vals_bg_2523; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { + spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); + spec->channels = rf_vals_bg_2524; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { + spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); + spec->channels = rf_vals_bg_2525; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { + spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); + spec->channels = rf_vals_bg_2525e; + } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { + spec->num_channels = ARRAY_SIZE(rf_vals_5222); + spec->channels = rf_vals_5222; spec->num_modes = 3; - spec->num_channels += 23; - spec->chan_val_a = &rf_vals_abg_5222[14]; } } -static int rt2500usb_init_hw(struct rt2x00_dev *rt2x00dev) +static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; /* * Allocate eeprom data. */ - retval = rt2500usb_alloc_eeprom(rt2x00dev); + retval = rt2500usb_validate_eeprom(rt2x00dev); if (retval) return retval; @@ -1451,12 +1537,17 @@ static int rt2500usb_init_hw(struct rt2x00_dev *rt2x00dev) /* * Initialize hw specifications. */ - rt2500usb_init_hw_mode(rt2x00dev); + rt2500usb_probe_hw_mode(rt2x00dev); /* - * This device supports ATIM + * This device requires the beacon ring */ - __set_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); + + /* + * Set the rssi offset. + */ + rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; return 0; } @@ -1464,69 +1555,197 @@ static int rt2500usb_init_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static int rt2500usb_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) +static void rt2500usb_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_addr_list *mc_list) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct interface *intf = &rt2x00dev->interface; u16 reg; /* - * Update FCS error count from register. - * The dot11ACKFailureCount, dot11RTSFailureCount and - * dot11RTSSuccessCount are updated in interrupt time. + * Mask off any flags we are going to ignore from + * the total_flags field. */ - rt2500usb_register_read(rt2x00dev, STA_CSR0, ®); - rt2x00dev->low_level_stats.dot11FCSErrorCount += - rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR); + *total_flags &= + FIF_ALLMULTI | + FIF_FCSFAIL | + FIF_PLCPFAIL | + FIF_CONTROL | + FIF_OTHER_BSS | + FIF_PROMISC_IN_BSS; + + /* + * Apply some rules to the filters: + * - Some filters imply different filters to be set. + * - Some things we can't filter out at all. + * - Some filters are set based on interface type. + */ + if (mc_count) + *total_flags |= FIF_ALLMULTI; + if (*total_flags & FIF_OTHER_BSS || + *total_flags & FIF_PROMISC_IN_BSS) + *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; + if (is_interface_type(intf, IEEE80211_IF_TYPE_AP)) + *total_flags |= FIF_PROMISC_IN_BSS; + + /* + * Check if there is any work left for us. + */ + if (intf->filter == *total_flags) + return; + intf->filter = *total_flags; + + /* + * When in atomic context, reschedule and let rt2x00lib + * call this function again. + */ + if (in_atomic()) { + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); + return; + } - memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats)); + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC, + !(*total_flags & FIF_FCSFAIL)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, + !(*total_flags & FIF_PLCPFAIL)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, + !(*total_flags & FIF_CONTROL)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, + !(*total_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, + !(*total_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); + rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST, + !(*total_flags & FIF_ALLMULTI)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_BROADCAST, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); +} + +static int rt2500usb_beacon_update(struct ieee80211_hw *hw, + struct sk_buff *skb, + struct ieee80211_tx_control *control) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct usb_device *usb_dev = + interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); + struct data_ring *ring = + rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + struct data_entry *beacon; + struct data_entry *guardian; + int pipe = usb_sndbulkpipe(usb_dev, 1); + 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); + 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); + + length = rt2500usb_get_tx_data_len(rt2x00dev, skb); + + usb_fill_bulk_urb(beacon->priv, usb_dev, pipe, + skb->data, length, rt2500usb_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, pipe, + &guardian->flags, 1, rt2500usb_beacondone, guardian); + + /* + * Send out the guardian byte. + */ + usb_submit_urb(guardian->priv, GFP_ATOMIC); + + /* + * Enable beacon generation. + */ + rt2500usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); return 0; } static const struct ieee80211_ops rt2500usb_mac80211_ops = { - .tx = rt2x00lib_tx, - .reset = rt2x00lib_reset, - .add_interface = rt2x00lib_add_interface, - .remove_interface = rt2x00lib_remove_interface, - .config = rt2x00lib_config, - .config_interface = rt2x00lib_config_interface, - .set_multicast_list = rt2x00lib_set_multicast_list, - .get_stats = rt2500usb_get_stats, - .conf_tx = rt2x00lib_conf_tx, - .get_tx_stats = rt2x00lib_get_tx_stats, - .beacon_update = rt2x00usb_beacon_update, + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, + .remove_interface = rt2x00mac_remove_interface, + .config = rt2x00mac_config, + .config_interface = rt2x00mac_config_interface, + .configure_filter = rt2500usb_configure_filter, + .get_stats = rt2x00mac_get_stats, + .erp_ie_changed = rt2x00mac_erp_ie_changed, + .conf_tx = rt2x00mac_conf_tx, + .get_tx_stats = rt2x00mac_get_tx_stats, + .beacon_update = rt2500usb_beacon_update, }; static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { - .init_hw = rt2500usb_init_hw, + .probe_hw = rt2500usb_probe_hw, .initialize = rt2x00usb_initialize, .uninitialize = rt2x00usb_uninitialize, .set_device_state = rt2500usb_set_device_state, + .link_stats = rt2500usb_link_stats, + .reset_tuner = rt2500usb_reset_tuner, .link_tuner = rt2500usb_link_tuner, .write_tx_desc = rt2500usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, + .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, - .config_type = rt2500usb_config_type, - .config_phymode = rt2500usb_config_phymode, - .config_channel = rt2500usb_config_channel, .config_mac_addr = rt2500usb_config_mac_addr, .config_bssid = rt2500usb_config_bssid, - .config_promisc = rt2500usb_config_promisc, - .config_txpower = rt2500usb_config_txpower, - .config_antenna = rt2500usb_config_antenna, - .config_duration = rt2500usb_config_duration, + .config_type = rt2500usb_config_type, + .config_preamble = rt2500usb_config_preamble, + .config = rt2500usb_config, }; static const struct rt2x00_ops rt2500usb_ops = { - .name = DRV_NAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, - .lib = &rt2500usb_rt2x00_ops, - .hw = &rt2500usb_mac80211_ops, + .name = DRV_NAME, + .rxd_size = RXD_DESC_SIZE, + .txd_size = TXD_DESC_SIZE, + .eeprom_size = EEPROM_SIZE, + .rf_size = RF_SIZE, + .lib = &rt2500usb_rt2x00_ops, + .hw = &rt2500usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2500usb_rt2x00debug, + .debugfs = &rt2500usb_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; @@ -1558,6 +1777,8 @@ static struct usb_device_id rt2500usb_device_table[] = { { USB_DEVICE(0x0411, 0x0066), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0411, 0x0067), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0411, 0x008b), USB_DEVICE_DATA(&rt2500usb_ops) }, + { USB_DEVICE(0x0411, 0x0097), USB_DEVICE_DATA(&rt2500usb_ops) }, + /* MSI */ { USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) }, @@ -1592,10 +1813,8 @@ static struct usb_driver rt2500usb_driver = { .id_table = rt2500usb_device_table, .probe = rt2x00usb_probe, .disconnect = rt2x00usb_disconnect, -#ifdef CONFIG_PM .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, -#endif /* CONFIG_PM */ }; static int __init rt2500usb_init(void) diff --git a/package/rt2x00/src/rt2500usb.h b/package/rt2x00/src/rt2500usb.h index 814bd0452e..b18d56e73c 100644 --- a/package/rt2x00/src/rt2500usb.h +++ b/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,18 +506,35 @@ #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 @@ -492,9 +542,34 @@ #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) @@ -615,23 +690,6 @@ #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. */ #define TXD_DESC_SIZE ( 5 * sizeof(struct data_desc) ) @@ -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) /* diff --git a/package/rt2x00/src/rt2x00.h b/package/rt2x00/src/rt2x00.h index 33b5094358..c8f16f161c 100644 --- a/package/rt2x00/src/rt2x00.h +++ b/package/rt2x00/src/rt2x00.h @@ -21,8 +21,6 @@ /* Module: rt2x00 Abstract: rt2x00 global information. - Supported chipsets: RT2460, RT2560, RT2570, - rt2561, rt2561s, rt2661, rt2571W & rt2671. */ #ifndef RT2X00_H @@ -32,14 +30,19 @@ #include <linux/prefetch.h> #include <linux/skbuff.h> #include <linux/workqueue.h> +#include <linux/firmware.h> #include <net/mac80211.h> +#include "rt2x00debug.h" +#include "rt2x00reg.h" +#include "rt2x00ring.h" + /* * Module information. * DRV_NAME should be set within the individual module source files. */ -#define DRV_VERSION "2.0.2" +#define DRV_VERSION "2.0.10" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" /* @@ -48,18 +51,17 @@ */ #define DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, __args...) \ printk(__kernlvl "%s -> %s: %s - " __msg, \ - wiphy_name(rt2x00dev->hw->wiphy), \ - __FUNCTION__, __lvl, ##__args) + wiphy_name((__dev)->hw->wiphy), __FUNCTION__, __lvl, ##__args) -#define DEBUG_PRINTK_PROBE(__kernlvl, __lvl, __msg, __args...) \ - printk(__kernlvl "%s -> %s: %s - " __msg, \ - DRV_NAME, __FUNCTION__, __lvl, ##__args) +#define DEBUG_PRINTK_PROBE(__kernlvl, __lvl, __msg, __args...) \ + printk(__kernlvl "%s -> %s: %s - " __msg, \ + DRV_NAME, __FUNCTION__, __lvl, ##__args) #ifdef CONFIG_RT2X00_DEBUG -#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ +#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args); -#else /* CONFIG_RT2X00_DEBUG */ -#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ +#else +#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ do { } while (0) #endif /* CONFIG_RT2X00_DEBUG */ @@ -98,14 +100,18 @@ /* * Number of entries in a packet ring. + * PCI devices only need 1 Beacon entry, + * but USB devices require a second because they + * have to send a Guardian byte first. */ #define RX_ENTRIES 12 #define TX_ENTRIES 12 #define ATIM_ENTRIES 1 -#define BEACON_ENTRIES 1 +#define BEACON_ENTRIES 2 /* * Standard timing and size defines. + * These values should follow the ieee80211 specifications. */ #define ACK_SIZE 14 #define IEEE80211_HEADER 24 @@ -125,197 +131,22 @@ /* * IEEE802.11 header defines */ -#define is_rts_frame(__fc) \ - ( !!((((__fc) & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && \ - (((__fc) & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)) ) -#define is_cts_frame(__fc) \ - ( !!((((__fc) & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && \ - (((__fc) & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_CTS)) ) -#define is_probe_resp(__fc) \ - ( !!((((__fc) & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && \ - (((__fc) & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)) ) - -/* - * Interval defines - */ -#define LINK_TUNE_INTERVAL ( round_jiffies(HZ) ) -#define RFKILL_POLL_INTERVAL ( HZ / 4 ) - -/* - * 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_DIVERSITY = 0, - ANTENNA_A = 1, - ANTENNA_B = 2, -}; - -/* - * 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, -}; - -/* - * 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, -}; - -/* - * 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 from Linus Torvalds, - * 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) +static inline int is_rts_frame(u16 fc) { - *reg &= ~(field.bit_mask); - *reg |= (value << field.bit_offset) & field.bit_mask; + return !!(((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS)); } -static inline u16 rt2x00_get_field16(const u16 reg, - const struct rt2x00_field16 field) +static inline int is_cts_frame(u16 fc) { - return (reg & field.bit_mask) >> field.bit_offset; + return !!(((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) && + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_CTS)); } -static inline void rt2x00_set_field8(u8 *reg, - const struct rt2x00_field8 field, const u8 value) +static inline int is_probe_resp(u16 fc) { - *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; + return !!(((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) && + ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP)); } /* @@ -328,8 +159,8 @@ struct rt2x00_chip { #define RT2460 0x0101 #define RT2560 0x0201 #define RT2570 0x1201 -#define RT2561 0x0301 -#define RT2561s 0x0302 +#define RT2561s 0x0301 /* Turbo */ +#define RT2561 0x0302 #define RT2661 0x0401 #define RT2571 0x1300 @@ -338,220 +169,17 @@ struct rt2x00_chip { }; /* - * 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]; -}; - -/* - * data_entry_desc - * Summary of information that should be written into the - * descriptor for sending a TX frame. - */ -struct data_entry_desc { - /* - * PLCP values. - */ - u16 length_high; - u16 length_low; - u16 signal; - u16 service; - - int queue; - int ifs; -}; - -/* - * 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. + * RF register values that belong to a particular channel. */ -struct data_entry { - /* - * Status flags - */ - unsigned long flags; -#define ENTRY_OWNER_NIC 1 -#define ENTRY_TXDONE 2 -#define ENTRY_TXD_RTS_FRAME 3 -#define ENTRY_TXD_OFDM_RATE 4 -#define ENTRY_TXD_MORE_FRAG 5 -#define ENTRY_TXD_REQ_TIMESTAMP 6 -#define ENTRY_TXD_REQ_ACK 7 - - /* - * 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; +struct rf_channel { + int channel; + u32 rf1; + u32 rf2; + u32 rf3; + u32 rf4; }; /* - * 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) -{ - if (ring->index_done >= ring->index) - return ring->index_done - ring->index; - return ring->stats.len - (ring->index - ring->index_done); -} - -/* - * 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); -} - -/* * To optimize the quality of the link we need to store * the quality of received frames and periodically * optimize the link. @@ -565,33 +193,94 @@ struct link { u32 count; /* - * Misc statistics. + * Statistics required for Link tuning. * For the average RSSI value we use the "Walking average" approach. * When adding RSSI to the average value the following calculation * is needed: * - * avg_rssi = ((avg_rssi * 7) + rssi) / 8; + * avg_rssi = ((avg_rssi * 7) + rssi) / 8; * * The advantage of this approach is that we only need 1 variable * to store the average in (No need for a count and a total). * But more importantly, normal average values will over time - * move less and less towards newly added values. - * This means that with link tuning, the device can have a very - * good RSSI for a few minutes but when the device is moved away - * from the AP the average will not decrease fast enough to - * compensate. The walking average compensates this and will - * move towards the new values correctly. + * move less and less towards newly added values this results + * that with link tuning, the device can have a very good RSSI + * for a few minutes but when the device is moved away from the AP + * the average will not decrease fast enough to compensate. + * The walking average compensates this and will move towards + * the new values correctly allowing a effective link tuning. */ int avg_rssi; + int vgc_level; int false_cca; /* + * Statistics required for Signal quality calculation. + * For calculating the Signal quality we have to determine + * the total number of success and failed RX and TX frames. + * After that we also use the average RSSI value to help + * determining the signal quality. + * For the calculation we will use the following algorithm: + * + * rssi_percentage = (avg_rssi * 100) / rssi_offset + * rx_percentage = (rx_success * 100) / rx_total + * tx_percentage = (tx_success * 100) / tx_total + * avg_signal = ((WEIGHT_RSSI * avg_rssi) + + * (WEIGHT_TX * tx_percentage) + + * (WEIGHT_RX * rx_percentage)) / 100 + * + * This value should then be checked to not be greated then 100. + */ + int rx_percentage; + int rx_success; + int rx_failed; + int tx_percentage; + int tx_success; + int tx_failed; +#define WEIGHT_RSSI 20 +#define WEIGHT_RX 40 +#define WEIGHT_TX 40 + + /* * Work structure for scheduling periodic link tuning. */ struct delayed_work work; }; /* + * Clear all counters inside the link structure. + * This can be easiest achieved by memsetting everything + * except for the work structure at the end. + */ +static inline void rt2x00_clear_link(struct link *link) +{ + memset(link, 0x00, sizeof(*link) - sizeof(link->work)); + link->rx_percentage = 50; + link->tx_percentage = 50; +} + +/* + * Update the rssi using the walking average approach. + */ +static inline void rt2x00_update_link_rssi(struct link *link, int rssi) +{ + if (!link->avg_rssi) + link->avg_rssi = rssi; + else + link->avg_rssi = ((link->avg_rssi * 7) + rssi) / 8; +} + +/* + * When the avg_rssi is unset or no frames have been received), + * we need to return the default value which needs to be less + * than -80 so the device will select the maximum sensitivity. + */ +static inline int rt2x00_get_link_rssi(struct link *link) +{ + return (link->avg_rssi && link->rx_success) ? link->avg_rssi : -128; +} + +/* * Interface structure * Configuration details about the current interface. */ @@ -605,29 +294,25 @@ struct interface { /* * Current working type (IEEE80211_IF_TYPE_*). - * This excludes the type IEEE80211_IF_TYPE_MNTR - * since that is counted seperately in the monitor_count - * field. + * When set to INVALID_INTERFACE, no interface is configured. */ int type; +#define INVALID_INTERFACE IEEE80211_IF_TYPE_INVALID /* - * BBSID of the AP to associate with. + * MAC of the device. */ - u8 bssid[ETH_ALEN]; + u8 mac[ETH_ALEN]; /* - * Store the promisc mode for the current interface. - * monitor mode always forces promisc mode to be enabled, - * so we need to store the promisc mode seperately. + * BBSID of the AP to associate with. */ - short promisc; + u8 bssid[ETH_ALEN]; /* - * Monitor mode count, the number of interfaces - * in monitor mode that that have been added. + * Store the packet filter mode for the current interface. */ - short monitor_count; + unsigned int filter; }; static inline int is_interface_present(struct interface *intf) @@ -635,9 +320,9 @@ static inline int is_interface_present(struct interface *intf) return !!intf->id; } -static inline int is_monitor_present(struct interface *intf) +static inline int is_interface_type(struct interface *intf, int type) { - return !!intf->monitor_count; + return intf->type == type; } /* @@ -663,8 +348,29 @@ struct hw_mode_spec { /* * Device/chipset specific value. */ - const u32 *chan_val_a; - const u32 *chan_val_bg; + const struct rf_channel *channels; +}; + +/* + * Configuration structure wrapper around the + * mac80211 configuration structure. + * When mac80211 configures the driver, rt2x00lib + * can precalculate values which are equal for all + * rt2x00 drivers. Those values can be stored in here. + */ +struct rt2x00lib_conf { + struct ieee80211_conf *conf; + struct rf_channel rf; + + int phymode; + + int basic_rates; + int slot_time; + + short sifs; + short pifs; + short difs; + short eifs; }; /* @@ -679,59 +385,70 @@ struct rt2x00lib_ops { /* * Device init handlers. */ - int (*init_hw)(struct rt2x00_dev *rt2x00dev); - char* (*get_fw_name)(struct rt2x00_dev *rt2x00dev); - int (*load_firmware)(struct rt2x00_dev *rt2x00dev, void *data, - const size_t len); + int (*probe_hw) (struct rt2x00_dev *rt2x00dev); + char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev); + int (*load_firmware) (struct rt2x00_dev *rt2x00dev, void *data, + const size_t len); /* * Device initialization/deinitialization handlers. */ - int (*initialize)(struct rt2x00_dev *rt2x00dev); - void (*uninitialize)(struct rt2x00_dev *rt2x00dev); + int (*initialize) (struct rt2x00_dev *rt2x00dev); + void (*uninitialize) (struct rt2x00_dev *rt2x00dev); /* * Radio control handlers. */ - int (*set_device_state)(struct rt2x00_dev *rt2x00dev, - enum dev_state state); - int (*rfkill_poll)(struct rt2x00_dev *rt2x00dev); - void (*link_tuner)(struct rt2x00_dev *rt2x00dev); + int (*set_device_state) (struct rt2x00_dev *rt2x00dev, + enum dev_state state); + int (*rfkill_poll) (struct rt2x00_dev *rt2x00dev); + void (*link_stats) (struct rt2x00_dev *rt2x00dev); + void (*reset_tuner) (struct rt2x00_dev *rt2x00dev); + void (*link_tuner) (struct rt2x00_dev *rt2x00dev); /* * TX control handlers */ - void (*write_tx_desc)(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry, struct data_desc *txd, - struct data_entry_desc *desc, - struct ieee80211_hdr *ieee80211hdr, unsigned int length, - struct ieee80211_tx_control *control); - int (*write_tx_data)(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, struct sk_buff *skb, - struct ieee80211_tx_control *control); - void (*kick_tx_queue)(struct rt2x00_dev *rt2x00dev, int queue); + void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, + struct data_desc *txd, + struct txdata_entry_desc *desc, + struct ieee80211_hdr *ieee80211hdr, + unsigned int length, + struct ieee80211_tx_control *control); + int (*write_tx_data) (struct rt2x00_dev *rt2x00dev, + struct data_ring *ring, struct sk_buff *skb, + struct ieee80211_tx_control *control); + int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb); + void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, + unsigned int queue); /* * RX control handlers */ - int (*fill_rxdone)(struct data_entry *entry, - int *signal, int *rssi, int *ofdm); + void (*fill_rxdone) (struct data_entry *entry, + struct rxdata_entry_desc *desc); /* * Configuration handlers. */ - void (*config_type)(struct rt2x00_dev *rt2x00dev, const int type); - void (*config_phymode)(struct rt2x00_dev *rt2x00dev, const int phy); - void (*config_channel)(struct rt2x00_dev *rt2x00dev, const int value, - const int channel, const int txpower); - void (*config_mac_addr)(struct rt2x00_dev *rt2x00dev, u8 *mac); - void (*config_bssid)(struct rt2x00_dev *rt2x00dev, u8 *bssid); - void (*config_promisc)(struct rt2x00_dev *rt2x00dev, const int promisc); - void (*config_txpower)(struct rt2x00_dev *rt2x00dev, const int txpower); - void (*config_antenna)(struct rt2x00_dev *rt2x00dev, - const int antenna_tx, const int antenna_rx); - void (*config_duration)(struct rt2x00_dev *rt2x00dev, - const int short_slot_time, const int beacon_int); + void (*config_mac_addr) (struct rt2x00_dev *rt2x00dev, __le32 *mac); + void (*config_bssid) (struct rt2x00_dev *rt2x00dev, __le32 *bssid); + void (*config_type) (struct rt2x00_dev *rt2x00dev, const int type, + const int tsf_sync); + void (*config_preamble) (struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time); + void (*config) (struct rt2x00_dev *rt2x00dev, const unsigned int flags, + struct rt2x00lib_conf *libconf); +#define CONFIG_UPDATE_PHYMODE ( 1 << 1 ) +#define CONFIG_UPDATE_CHANNEL ( 1 << 2 ) +#define CONFIG_UPDATE_TXPOWER ( 1 << 3 ) +#define CONFIG_UPDATE_ANTENNA ( 1 << 4 ) +#define CONFIG_UPDATE_SLOT_TIME ( 1 << 5 ) +#define CONFIG_UPDATE_BEACON_INT ( 1 << 6 ) +#define CONFIG_UPDATE_ALL 0xffff }; /* @@ -741,6 +458,8 @@ struct rt2x00_ops { const char *name; const unsigned int rxd_size; const unsigned int txd_size; + const unsigned int eeprom_size; + const unsigned int rf_size; const struct rt2x00lib_ops *lib; const struct ieee80211_ops *hw; #ifdef CONFIG_RT2X00_LIB_DEBUGFS @@ -749,6 +468,40 @@ struct rt2x00_ops { }; /* + * rt2x00 device flags + */ +enum rt2x00_flags { + /* + * Device state flags + */ + DEVICE_PRESENT, + DEVICE_REGISTERED_HW, + DEVICE_INITIALIZED, + DEVICE_STARTED, + DEVICE_STARTED_SUSPEND, + DEVICE_ENABLED_RADIO, + DEVICE_DISABLED_RADIO_HW, + + /* + * Driver features + */ + DRIVER_REQUIRE_FIRMWARE, + DRIVER_REQUIRE_BEACON_RING, + + /* + * Driver configuration + */ + CONFIG_SUPPORT_HW_BUTTON, + CONFIG_FRAME_TYPE, + CONFIG_RF_SEQUENCE, + CONFIG_EXTERNAL_LNA_A, + CONFIG_EXTERNAL_LNA_BG, + CONFIG_DOUBLE_ANTENNA, + CONFIG_DISABLE_LINK_TUNING, + CONFIG_SHORT_PREAMBLE, +}; + +/* * rt2x00 device structure. */ struct rt2x00_dev { @@ -784,34 +537,23 @@ struct rt2x00_dev { */ #ifdef CONFIG_RT2X00_LIB_RFKILL struct rfkill *rfkill; - struct delayed_work rfkill_work; + struct input_polled_dev *poll_dev; #endif /* CONFIG_RT2X00_LIB_RFKILL */ /* + * If enabled, the debugfs interface structures + * required for deregistration of debugfs. + */ +#ifdef CONFIG_RT2X00_LIB_DEBUGFS + const struct rt2x00debug_intf *debugfs_intf; +#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ + + /* * Device flags. * In these flags the current status and some * of the device capabilities are stored. */ unsigned long flags; -#define DEVICE_ENABLED_RADIO 1 -#define DEVICE_ENABLED_RADIO_HW 2 -#define DEVICE_INITIALIZED 3 -#define DEVICE_INITIALIZED_HW 4 -#define FIRMWARE_REQUIRED 5 -#define FIRMWARE_LOADED 6 -#define FIRMWARE_FAILED 7 -#define INTERFACE_ENABLED 8 -#define INTERFACE_ENABLED_MONITOR 9 -#define INTERFACE_ENABLED_PROMISC 10 -#define DEVICE_SUPPORT_ATIM 11 -#define DEVICE_SUPPORT_HW_BUTTON 12 -#define CONFIG_FRAME_TYPE 13 -#define CONFIG_RF_SEQUENCE 14 -#define CONFIG_EXTERNAL_LNA 15 -#define CONFIG_EXTERNAL_LNA_A 16 -#define CONFIG_EXTERNAL_LNA_BG 17 -#define CONFIG_DOUBLE_ANTENNA 18 -#define CONFIG_DISABLE_LINK_TUNING 19 /* * Chipset identification. @@ -824,17 +566,12 @@ struct rt2x00_dev { struct hw_mode_spec spec; /* - * Base address of device registers (PCI devices only). + * Register pointers + * csr_addr: Base register address. (PCI) + * csr_cache: CSR cache for usb_control_msg. (USB) */ void __iomem *csr_addr; - - /* - * If enabled, the debugfs interface structures - * required for deregistration of debugfs. - */ -#ifdef CONFIG_RT2X00_LIB_DEBUGFS - const struct rt2x00debug_intf *debugfs_intf; -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ + void *csr_cache; /* * Interface configuration. @@ -853,13 +590,18 @@ struct rt2x00_dev { /* * Active RF register values. - * These are stored here for easier working - * with the rf registers. + * These are stored here so we don't need + * to read the rf registers and can directly + * use this value instead. + * This field should be accessed by using + * rt2x00_rf_read() and rt2x00_rf_write(). */ - u32 rf1; - u32 rf2; - u32 rf3; - u32 rf4; + u32 *rf; + + /* + * USB Max frame size (for rt2500usb & rt73usb). + */ + u16 usb_maxpacket; /* * Current TX power value. @@ -898,50 +640,44 @@ struct rt2x00_dev { struct ieee80211_rx_status rx_status; /* + * Scheduled work. + */ + struct work_struct beacon_work; + struct work_struct filter_work; + struct work_struct config_work; + + /* * Data ring arrays for RX, TX and Beacon. * The Beacon array also contains the Atim ring * if that is supported by the device. */ + int data_rings; struct data_ring *rx; struct data_ring *tx; struct data_ring *bcn; -}; - -static inline struct data_ring* rt2x00_get_ring( - struct rt2x00_dev *rt2x00dev, const unsigned int queue) -{ - int atim = test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags); /* - * Check if the rings have been allocated. + * Firmware image. */ - if (!rt2x00dev->tx || !rt2x00dev->bcn) - return NULL; - - /* - * Check if we are requesting a reqular TX ring, - * or if we are requesting a Beacon or Atim ring. - * For Atim rings, we should check if it is supported. - */ - if (queue < rt2x00dev->hw->queues) - return &rt2x00dev->tx[queue]; - else if (queue == IEEE80211_TX_QUEUE_BEACON) - return &rt2x00dev->bcn[0]; - else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON && atim) - return &rt2x00dev->bcn[1]; - - return NULL; -} + const struct firmware *fw; +}; /* * For-each loop for the ring array. - * Since the all rings are allocated as a single array, - * we can start at the rx pointer and move forward to the tx rings. - * The 1 + Atim check will assure that the address directly after - * the ring array is obtained and the for-each loop exits correctly. + * All rings have been allocated as a single array, + * this means we can create a very simply loop macro + * that is capable of looping through all rings. + * ring_end(), txring_end() and ring_loop() are helper macro's which + * should not be used directly. Instead the following should be used: + * ring_for_each() - Loops through all rings (RX, TX, Beacon & Atim) + * txring_for_each() - Loops through TX data rings (TX only) + * txringall_for_each() - Loops through all TX rings (TX, Beacon & Atim) */ #define ring_end(__dev) \ - &(__dev)->bcn[1 + test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags)] + &(__dev)->rx[(__dev)->data_rings] + +#define txring_end(__dev) \ + &(__dev)->tx[(__dev)->hw->queues] #define ring_loop(__entry, __start, __end) \ for ((__entry) = (__start); \ @@ -952,75 +688,58 @@ static inline struct data_ring* rt2x00_get_ring( ring_loop(__entry, (__dev)->rx, ring_end(__dev)) #define txring_for_each(__dev, __entry) \ - ring_loop(__entry, (__dev)->tx, (__dev)->bcn) + ring_loop(__entry, (__dev)->tx, txring_end(__dev)) #define txringall_for_each(__dev, __entry) \ ring_loop(__entry, (__dev)->tx, ring_end(__dev)) /* - * EEPROM access. - * The EEPROM is being accessed by word index. + * Generic RF access. + * The RF is being accessed by word index. */ -static inline void* rt2x00_eeprom_addr(const struct rt2x00_dev *rt2x00dev, - const u8 word) +static inline void rt2x00_rf_read(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 *data) { - return (void*)&rt2x00dev->eeprom[word]; + *data = rt2x00dev->rf[word]; } -static inline void rt2x00_eeprom_read(const struct rt2x00_dev *rt2x00dev, - const u8 word, u16 *data) +static inline void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 data) { - *data = le16_to_cpu(rt2x00dev->eeprom[word]); -} - -static inline void rt2x00_eeprom_write(const struct rt2x00_dev *rt2x00dev, - const u8 word, u16 data) -{ - rt2x00dev->eeprom[word] = cpu_to_le16(data); + rt2x00dev->rf[word] = data; } /* - * Link tuning handlers + * Generic EEPROM access. + * The EEPROM is being accessed by word index. */ -static inline void rt2x00_start_link_tune(struct rt2x00_dev *rt2x00dev) +static inline void *rt2x00_eeprom_addr(const struct rt2x00_dev *rt2x00dev, + const unsigned int word) { - rt2x00dev->link.count = 0; - rt2x00dev->link.avg_rssi = 0; - rt2x00dev->link.false_cca = 0; - - queue_delayed_work(rt2x00dev->hw->workqueue, - &rt2x00dev->link.work, LINK_TUNE_INTERVAL); + return (void *)&rt2x00dev->eeprom[word]; } -static inline void rt2x00_stop_link_tune(struct rt2x00_dev *rt2x00dev) -{ - if (work_pending(&rt2x00dev->link.work.work)) - cancel_rearming_delayed_workqueue( - rt2x00dev->hw->workqueue, &rt2x00dev->link.work); -} - -static inline void rt2x00_update_link_rssi(struct link *link, int rssi) +static inline void rt2x00_eeprom_read(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u16 *data) { - if (!link->avg_rssi) - link->avg_rssi = rssi; - else - link->avg_rssi = ((link->avg_rssi * 7) + rssi) / 8; + *data = le16_to_cpu(rt2x00dev->eeprom[word]); } -static inline int rt2x00_get_link_rssi(struct link *link) +static inline void rt2x00_eeprom_write(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u16 data) { - return link->avg_rssi; + rt2x00dev->eeprom[word] = cpu_to_le16(data); } /* * Chipset handlers */ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, - const u16 rt, const u16 rf, const u32 rev) + const u16 rt, const u16 rf, const u32 rev) { INFO(rt2x00dev, - "Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n", - rt, rf, rev); + "Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n", + rt, rf, rev); rt2x00dev->chip.rt = rt; rt2x00dev->chip.rf = rf; @@ -1042,64 +761,12 @@ static inline u16 rt2x00_rev(const struct rt2x00_chip *chipset) return chipset->rev; } -/* - * 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) - -/* - * Bitmask for MASK_RATE - */ -#define DEV_RATE_1MB 0x00000001 -#define DEV_RATE_2MB 0x00000002 -#define DEV_RATE_5_5MB 0x00000004 -#define DEV_RATE_11MB 0x00000008 -#define DEV_RATE_6MB 0x00000010 -#define DEV_RATE_9MB 0x00000020 -#define DEV_RATE_12MB 0x00000040 -#define DEV_RATE_18MB 0x00000080 -#define DEV_RATE_24MB 0x00000100 -#define DEV_RATE_36MB 0x00000200 -#define DEV_RATE_48MB 0x00000400 -#define DEV_RATE_54MB 0x00000800 - -/* - * Bitmask groups of bitrates - */ -#define DEV_BASIC_RATE \ - ( DEV_RATE_1MB | DEV_RATE_2MB | DEV_RATE_5_5MB | DEV_RATE_11MB | \ - DEV_RATE_6MB | DEV_RATE_12MB | DEV_RATE_24MB ) - -#define DEV_CCK_RATE \ - ( DEV_RATE_1MB | DEV_RATE_2MB | DEV_RATE_5_5MB | DEV_RATE_11MB ) - -#define DEV_OFDM_RATE \ - ( DEV_RATE_6MB | DEV_RATE_9MB | DEV_RATE_12MB | DEV_RATE_18MB | \ - DEV_RATE_24MB | DEV_RATE_36MB | DEV_RATE_48MB | DEV_RATE_54MB ) - -/* - * Macro's to set and get specific fields from the device specific val and val2 - * fields inside the ieee80211_rate entry. - */ -#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 ) +static inline u16 rt2x00_check_rev(const struct rt2x00_chip *chipset, + const u32 rev) +{ + return (((chipset->rev & 0xffff0) == rev) && + !!(chipset->rev & 0x0000f)); +} /* * Duration calculations @@ -1118,4 +785,61 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) return ((size * 8 * 10) % rate); } +/* + * Library functions. + */ +struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev, + const unsigned int queue); + +/* + * Interrupt context handlers. + */ +void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); +void rt2x00lib_txdone(struct data_entry *entry, + const int status, const int retry); +void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, + struct rxdata_entry_desc *desc); + +/* + * TX descriptor initializer + */ +void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, + struct data_desc *txd, + struct ieee80211_hdr *ieee80211hdr, + unsigned int length, + struct ieee80211_tx_control *control); + +/* + * mac80211 handlers. + */ +int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ieee80211_tx_control *control); +int rt2x00mac_start(struct ieee80211_hw *hw); +void rt2x00mac_stop(struct ieee80211_hw *hw); +int rt2x00mac_add_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); +int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); +int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id, + struct ieee80211_if_conf *conf); +int rt2x00mac_get_stats(struct ieee80211_hw *hw, + struct ieee80211_low_level_stats *stats); +int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, + struct ieee80211_tx_queue_stats *stats); +void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes, + int cts_protection, int preamble); +int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue, + const struct ieee80211_tx_queue_params *params); + +/* + * Driver allocation handlers. + */ +int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev); +void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev); +#ifdef CONFIG_PM +int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state); +int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev); +#endif /* CONFIG_PM */ + #endif /* RT2X00_H */ diff --git a/package/rt2x00/src/rt2x00config.c b/package/rt2x00/src/rt2x00config.c new file mode 100644 index 0000000000..12914cf715 --- /dev/null +++ b/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(®, 0, sizeof(reg)); + if (mac) + memcpy(®, mac, ETH_ALEN); + + rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, ®[0]); +} + +void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) +{ + __le32 reg[2]; + + memset(®, 0, sizeof(reg)); + if (bssid) + memcpy(®, bssid, ETH_ALEN); + + rt2x00dev->ops->lib->config_bssid(rt2x00dev, ®[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; +} diff --git a/package/rt2x00/src/rt2x00debug.c b/package/rt2x00/src/rt2x00debug.c index e2239fab8d..9275d6f951 100644 --- a/package/rt2x00/src/rt2x00debug.c +++ b/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); diff --git a/package/rt2x00/src/rt2x00debug.h b/package/rt2x00/src/rt2x00debug.h index f987bc91f7..860e8fa3a0 100644 --- a/package/rt2x00/src/rt2x00debug.h +++ b/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 */ diff --git a/package/rt2x00/src/rt2x00dev.c b/package/rt2x00/src/rt2x00dev.c index 043af31561..ff399f8083 100644 --- a/package/rt2x00/src/rt2x00dev.c +++ b/package/rt2x00/src/rt2x00dev.c @@ -21,8 +21,6 @@ /* Module: rt2x00lib Abstract: rt2x00 generic device routines. - Supported chipsets: RT2460, RT2560, RT2570, - rt2561, rt2561s, rt2661, rt2571W & rt2671. */ /* @@ -32,14 +30,67 @@ #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/etherdevice.h> #include "rt2x00.h" #include "rt2x00lib.h" -#include "rt2x00dev.h" + +/* + * Ring handler. + */ +struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev, + const unsigned int queue) +{ + int beacon = test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); + + /* + * Check if we are requesting a reqular TX ring, + * or if we are requesting a Beacon or Atim ring. + * For Atim rings, we should check if it is supported. + */ + if (queue < rt2x00dev->hw->queues && rt2x00dev->tx) + return &rt2x00dev->tx[queue]; + + if (!rt2x00dev->bcn || !beacon) + return NULL; + + if (queue == IEEE80211_TX_QUEUE_BEACON) + return &rt2x00dev->bcn[0]; + else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON) + return &rt2x00dev->bcn[1]; + + return NULL; +} +EXPORT_SYMBOL_GPL(rt2x00lib_get_ring); + +/* + * Link tuning handlers + */ +static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev) +{ + rt2x00_clear_link(&rt2x00dev->link); + + /* + * Reset the link tuner. + */ + rt2x00dev->ops->lib->reset_tuner(rt2x00dev); + + queue_delayed_work(rt2x00dev->hw->workqueue, + &rt2x00dev->link.work, LINK_TUNE_INTERVAL); +} + +static void rt2x00lib_stop_link_tuner(struct rt2x00_dev *rt2x00dev) +{ + cancel_delayed_work_sync(&rt2x00dev->link.work); +} + +void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev) +{ + if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) + return; + + rt2x00lib_stop_link_tuner(rt2x00dev); + rt2x00lib_start_link_tuner(rt2x00dev); +} /* * Radio control handlers. @@ -50,27 +101,32 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Don't enable the radio twice. - * or if the hardware button has been disabled. + * And check if the hardware button has been disabled. */ if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || - (test_bit(DEVICE_SUPPORT_HW_BUTTON, &rt2x00dev->flags) && - !test_bit(DEVICE_ENABLED_RADIO_HW, &rt2x00dev->flags))) + test_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags)) return 0; - status = rt2x00dev->ops->lib->set_device_state( - rt2x00dev, STATE_RADIO_ON); + /* + * Enable radio. + */ + status = rt2x00dev->ops->lib->set_device_state(rt2x00dev, + STATE_RADIO_ON); if (status) return status; __set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags); - rt2x00lib_toggle_rx(rt2x00dev, 1); + /* + * Enable RX. + */ + rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); + /* + * Start the TX queues. + */ ieee80211_start_queues(rt2x00dev->hw); - if (is_interface_present(&rt2x00dev->interface)) - rt2x00_start_link_tune(rt2x00dev); - return 0; } @@ -79,160 +135,447 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) if (!__test_and_clear_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) return; - rt2x00_stop_link_tune(rt2x00dev); + /* + * Stop all scheduled work. + */ + if (work_pending(&rt2x00dev->beacon_work)) + cancel_work_sync(&rt2x00dev->beacon_work); + if (work_pending(&rt2x00dev->filter_work)) + cancel_work_sync(&rt2x00dev->filter_work); + if (work_pending(&rt2x00dev->config_work)) + cancel_work_sync(&rt2x00dev->config_work); + /* + * Stop the TX queues. + */ ieee80211_stop_queues(rt2x00dev->hw); - rt2x00lib_toggle_rx(rt2x00dev, 0); + /* + * Disable RX. + */ + rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); + /* + * Disable radio. + */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF); } -void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, int enable) +void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) { /* - * When we are disabling the rx, we should also stop the link tuner. + * When we are disabling the RX, we should also stop the link tuner. */ - if (!enable) - rt2x00_stop_link_tune(rt2x00dev); + if (state == STATE_RADIO_RX_OFF) + rt2x00lib_stop_link_tuner(rt2x00dev); - rt2x00dev->ops->lib->set_device_state(rt2x00dev, - enable ? STATE_RADIO_RX_ON : STATE_RADIO_RX_OFF); + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); + + /* + * When we are enabling the RX, we should also start the link tuner. + */ + if (state == STATE_RADIO_RX_ON && + is_interface_present(&rt2x00dev->interface)) + rt2x00lib_start_link_tuner(rt2x00dev); +} + +static void rt2x00lib_precalculate_link_signal(struct link *link) +{ + if (link->rx_failed || link->rx_success) + link->rx_percentage = + (link->rx_success * 100) / + (link->rx_failed + link->rx_success); + else + link->rx_percentage = 50; + + if (link->tx_failed || link->tx_success) + link->tx_percentage = + (link->tx_success * 100) / + (link->tx_failed + link->tx_success); + else + link->tx_percentage = 50; + + link->rx_success = 0; + link->rx_failed = 0; + link->tx_success = 0; + link->tx_failed = 0; +} + +static int rt2x00lib_calculate_link_signal(struct rt2x00_dev *rt2x00dev, + int rssi) +{ + int rssi_percentage = 0; + int signal; + + /* + * We need a positive value for the RSSI. + */ + if (rssi < 0) + rssi += rt2x00dev->rssi_offset; + + /* + * Calculate the different percentages, + * which will be used for the signal. + */ + if (rt2x00dev->rssi_offset) + rssi_percentage = (rssi * 100) / rt2x00dev->rssi_offset; /* - * When we are enabling the rx, we should also start the link tuner. + * Add the individual percentages and use the WEIGHT + * defines to calculate the current link signal. */ - if (enable && is_interface_present(&rt2x00dev->interface)) - rt2x00_start_link_tune(rt2x00dev); + signal = ((WEIGHT_RSSI * rssi_percentage) + + (WEIGHT_TX * rt2x00dev->link.tx_percentage) + + (WEIGHT_RX * rt2x00dev->link.rx_percentage)) / 100; + + return (signal > 100) ? 100 : signal; } static void rt2x00lib_link_tuner(struct work_struct *work) { struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, link.work.work); + container_of(work, struct rt2x00_dev, link.work.work); /* - * Update promisc mode (this function will first check - * if updating is really required). + * When the radio is shutting down we should + * immediately cease all link tuning. */ - rt2x00lib_config_promisc(rt2x00dev, rt2x00dev->interface.promisc); + if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) + return; /* - * Cancel all link tuning if the eeprom has indicated - * it is not required. + * Update statistics. */ - if (test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags)) - return; + rt2x00dev->ops->lib->link_stats(rt2x00dev); + + rt2x00dev->low_level_stats.dot11FCSErrorCount += + rt2x00dev->link.rx_failed; - rt2x00dev->ops->lib->link_tuner(rt2x00dev); + /* + * Only perform the link tuning when Link tuning + * has been enabled (This could have been disabled from the EEPROM). + */ + if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags)) + rt2x00dev->ops->lib->link_tuner(rt2x00dev); + + /* + * Precalculate a portion of the link signal which is + * in based on the tx/rx success/failure counters. + */ + rt2x00lib_precalculate_link_signal(&rt2x00dev->link); /* * Increase tuner counter, and reschedule the next link tuner run. */ rt2x00dev->link.count++; queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, - LINK_TUNE_INTERVAL); + LINK_TUNE_INTERVAL); } -/* - * Config handlers - */ -void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type) +static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) { - if (!(is_interface_present(&rt2x00dev->interface) ^ - test_bit(INTERFACE_ENABLED, &rt2x00dev->flags)) && - !(is_monitor_present(&rt2x00dev->interface) ^ - test_bit(INTERFACE_ENABLED_MONITOR, &rt2x00dev->flags))) - return; + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, filter_work); + unsigned int filter = rt2x00dev->interface.filter; - rt2x00dev->ops->lib->config_type(rt2x00dev, type); + /* + * Since we had stored the filter inside interface.filter, + * we should now clear that field. Otherwise the driver will + * assume nothing has changed (*total_flags will be compared + * to interface.filter to determine if any action is required). + */ + rt2x00dev->interface.filter = 0; - if (type != IEEE80211_IF_TYPE_MNTR) { - if (is_interface_present(&rt2x00dev->interface)) - __set_bit(INTERFACE_ENABLED, &rt2x00dev->flags); - else - __clear_bit(INTERFACE_ENABLED, &rt2x00dev->flags); - } else { - if (is_monitor_present(&rt2x00dev->interface)) - __set_bit(INTERFACE_ENABLED_MONITOR, - &rt2x00dev->flags); - else - __clear_bit(INTERFACE_ENABLED_MONITOR, - &rt2x00dev->flags); - } + rt2x00dev->ops->hw->configure_filter(rt2x00dev->hw, + filter, &filter, 0, NULL); } -void rt2x00lib_config_phymode(struct rt2x00_dev *rt2x00dev, const int phymode) +static void rt2x00lib_configuration_scheduled(struct work_struct *work) { - if (rt2x00dev->rx_status.phymode == phymode) - return; - - rt2x00dev->ops->lib->config_phymode(rt2x00dev, phymode); + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, config_work); + int preamble = !test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); - rt2x00dev->rx_status.phymode = phymode; + rt2x00mac_erp_ie_changed(rt2x00dev->hw, + IEEE80211_ERP_CHANGE_PREAMBLE, 0, preamble); } -void rt2x00lib_config_channel(struct rt2x00_dev *rt2x00dev, const int value, - const int channel, const int freq, const int txpower) +/* + * Interrupt context handlers. + */ +static void rt2x00lib_beacondone_scheduled(struct work_struct *work) { - if (channel == rt2x00dev->rx_status.channel) + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, beacon_work); + struct data_ring *ring = + rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + 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->lib->config_channel(rt2x00dev, value, channel, txpower); + rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, + &entry->tx_status.control); - INFO(rt2x00dev, "Switching channel. " - "RF1: 0x%08x, RF2: 0x%08x, RF3: 0x%08x, RF3: 0x%08x.\n", - rt2x00dev->rf1, rt2x00dev->rf2, - rt2x00dev->rf3, rt2x00dev->rf4); + dev_kfree_skb(skb); +} - rt2x00dev->rx_status.freq = freq; - rt2x00dev->rx_status.channel = channel; +void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) +{ + if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) + return; + + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->beacon_work); } +EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); -void rt2x00lib_config_promisc(struct rt2x00_dev *rt2x00dev, const int promisc) +void rt2x00lib_txdone(struct data_entry *entry, + const int status, const int retry) { + struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; + struct ieee80211_tx_status *tx_status = &entry->tx_status; + struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats; + int success = !!(status == TX_SUCCESS || status == TX_SUCCESS_RETRY); + int fail = !!(status == TX_FAIL_RETRY || status == TX_FAIL_INVALID || + status == TX_FAIL_OTHER); + /* - * Monitor mode implies promisc mode enabled. - * In all other instances, check if we need to toggle promisc mode. + * Update TX statistics. */ - if (is_monitor_present(&rt2x00dev->interface) && - !test_bit(INTERFACE_ENABLED_PROMISC, &rt2x00dev->flags)) { - rt2x00dev->ops->lib->config_promisc(rt2x00dev, 1); - __set_bit(INTERFACE_ENABLED_PROMISC, &rt2x00dev->flags); + tx_status->flags = 0; + tx_status->ack_signal = 0; + tx_status->excessive_retries = (status == TX_FAIL_RETRY); + tx_status->retry_count = retry; + rt2x00dev->link.tx_success += success; + rt2x00dev->link.tx_failed += retry + fail; + + if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) { + if (success) + tx_status->flags |= IEEE80211_TX_STATUS_ACK; + else + stats->dot11ACKFailureCount++; } - if (test_bit(INTERFACE_ENABLED_PROMISC, &rt2x00dev->flags) != promisc) { - rt2x00dev->ops->lib->config_promisc(rt2x00dev, promisc); - __change_bit(INTERFACE_ENABLED_PROMISC, &rt2x00dev->flags); + tx_status->queue_length = entry->ring->stats.limit; + tx_status->queue_number = tx_status->control.queue; + + if (tx_status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) { + if (success) + stats->dot11RTSSuccessCount++; + else + stats->dot11RTSFailureCount++; } + + /* + * Send the tx_status to mac80211, + * that method also cleans up the skb structure. + */ + ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status); + entry->skb = NULL; } +EXPORT_SYMBOL_GPL(rt2x00lib_txdone); -void rt2x00lib_config_txpower(struct rt2x00_dev *rt2x00dev, const int txpower) +void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, + struct rxdata_entry_desc *desc) { - if (txpower == rt2x00dev->tx_power) - return; + struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; + struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; + struct ieee80211_hw_mode *mode; + struct ieee80211_rate *rate; + unsigned int i; + int val = 0; + + /* + * Update RX statistics. + */ + mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode]; + for (i = 0; i < mode->num_rates; i++) { + rate = &mode->rates[i]; + + /* + * When frame was received with an OFDM bitrate, + * the signal is the PLCP value. If it was received with + * a CCK bitrate the signal is the rate in 0.5kbit/s. + */ + if (!desc->ofdm) + val = DEVICE_GET_RATE_FIELD(rate->val, RATE); + else + val = DEVICE_GET_RATE_FIELD(rate->val, PLCP); + + if (val == desc->signal) { + val = rate->val; + break; + } + } - rt2x00dev->ops->lib->config_txpower(rt2x00dev, txpower); + rt2x00_update_link_rssi(&rt2x00dev->link, desc->rssi); + rt2x00dev->link.rx_success++; + rx_status->rate = val; + rx_status->signal = + rt2x00lib_calculate_link_signal(rt2x00dev, desc->rssi); + rx_status->ssi = desc->rssi; + rx_status->flag = desc->flags; - rt2x00dev->tx_power = txpower; + /* + * Send frame to mac80211 + */ + ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status); } +EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); -void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, - const int antenna_tx, const int antenna_rx) +/* + * TX descriptor initializer + */ +void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, + struct data_desc *txd, + struct ieee80211_hdr *ieee80211hdr, + unsigned int length, + struct ieee80211_tx_control *control) { - if (rt2x00dev->rx_status.antenna == antenna_rx) - return; + struct txdata_entry_desc desc; + struct data_ring *ring; + int tx_rate; + int bitrate; + int duration; + int residual; + u16 frame_control; + u16 seq_ctrl; + + /* + * Make sure the descriptor is properly cleared. + */ + memset(&desc, 0x00, sizeof(desc)); + + /* + * Get ring pointer, if we fail to obtain the + * correct ring, then use the first TX ring. + */ + ring = rt2x00lib_get_ring(rt2x00dev, control->queue); + if (!ring) + ring = rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0); + + desc.cw_min = ring->tx_params.cw_min; + desc.cw_max = ring->tx_params.cw_max; + desc.aifs = ring->tx_params.aifs; + + /* + * Identify queue + */ + if (control->queue < rt2x00dev->hw->queues) + desc.queue = control->queue; + else if (control->queue == IEEE80211_TX_QUEUE_BEACON || + control->queue == IEEE80211_TX_QUEUE_AFTER_BEACON) + desc.queue = QUEUE_MGMT; + else + desc.queue = QUEUE_OTHER; + + /* + * Read required fields from ieee80211 header. + */ + frame_control = le16_to_cpu(ieee80211hdr->frame_control); + seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl); - rt2x00dev->ops->lib->config_antenna(rt2x00dev, antenna_tx, antenna_rx); + tx_rate = control->tx_rate; + + /* + * Check if this is a RTS/CTS frame + */ + if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) { + __set_bit(ENTRY_TXD_BURST, &desc.flags); + if (is_rts_frame(frame_control)) + __set_bit(ENTRY_TXD_RTS_FRAME, &desc.flags); + if (control->rts_cts_rate) + tx_rate = control->rts_cts_rate; + } + + /* + * Check for OFDM + */ + if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATEMASK) + __set_bit(ENTRY_TXD_OFDM_RATE, &desc.flags); + + /* + * Check if more fragments are pending + */ + if (ieee80211_get_morefrag(ieee80211hdr)) { + __set_bit(ENTRY_TXD_BURST, &desc.flags); + __set_bit(ENTRY_TXD_MORE_FRAG, &desc.flags); + } - rt2x00dev->rx_status.antenna = antenna_rx; + /* + * Beacons and probe responses require the tsf timestamp + * to be inserted into the frame. + */ + if (control->queue == IEEE80211_TX_QUEUE_BEACON || + is_probe_resp(frame_control)) + __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc.flags); + + /* + * Determine with what IFS priority this frame should be send. + * Set ifs to IFS_SIFS when the this is not the first fragment, + * or this fragment came after RTS/CTS. + */ + if ((seq_ctrl & IEEE80211_SCTL_FRAG) > 0 || + test_bit(ENTRY_TXD_RTS_FRAME, &desc.flags)) + desc.ifs = IFS_SIFS; + else + desc.ifs = IFS_BACKOFF; + + /* + * PLCP setup + * Length calculation depends on OFDM/CCK rate. + */ + desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP); + desc.service = 0x04; + + if (test_bit(ENTRY_TXD_OFDM_RATE, &desc.flags)) { + desc.length_high = ((length + FCS_LEN) >> 6) & 0x3f; + desc.length_low = ((length + FCS_LEN) & 0x3f); + } else { + bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE); + + /* + * Convert length to microseconds. + */ + residual = get_duration_res(length + FCS_LEN, bitrate); + duration = get_duration(length + FCS_LEN, bitrate); + + if (residual != 0) { + duration++; + + /* + * Check if we need to set the Length Extension + */ + if (bitrate == 110 && residual <= 30) + desc.service |= 0x80; + } + + desc.length_high = (duration >> 8) & 0xff; + desc.length_low = duration & 0xff; + + /* + * When preamble is enabled we should set the + * preamble bit for the signal. + */ + if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE)) + desc.signal |= 0x08; + } + + rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, txd, &desc, + ieee80211hdr, length, control); } +EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); /* * Driver initialization handlers. */ static void rt2x00lib_channel(struct ieee80211_channel *entry, - const int channel, const int tx_power, const int value) + const int channel, const int tx_power, + const int value) { entry->chan = channel; if (channel <= 14) @@ -241,21 +584,22 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry, entry->freq = 5000 + (5 * channel); entry->val = value; entry->flag = - IEEE80211_CHAN_W_IBSS | - IEEE80211_CHAN_W_ACTIVE_SCAN | - IEEE80211_CHAN_W_SCAN; + IEEE80211_CHAN_W_IBSS | + IEEE80211_CHAN_W_ACTIVE_SCAN | + IEEE80211_CHAN_W_SCAN; entry->power_level = tx_power; entry->antenna_max = 0xff; } static void rt2x00lib_rate(struct ieee80211_rate *entry, - const int rate,const int mask, const int plcp, const int flags) + const int rate, const int mask, + const int plcp, const int flags) { entry->rate = rate; entry->val = - DEVICE_SET_RATE_FIELD(rate, RATE) | - DEVICE_SET_RATE_FIELD(mask, RATEMASK) | - DEVICE_SET_RATE_FIELD(plcp, PLCP); + DEVICE_SET_RATE_FIELD(rate, RATE) | + DEVICE_SET_RATE_FIELD(mask, RATEMASK) | + DEVICE_SET_RATE_FIELD(plcp, PLCP); entry->flags = flags; entry->val2 = entry->val; if (entry->flags & IEEE80211_RATE_PREAMBLE2) @@ -264,8 +608,8 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry, entry->min_rssi_ack_delta = 0; } -static int rt2x00lib_init_hw_modes(struct rt2x00_dev *rt2x00dev, - struct hw_mode_spec *spec) +static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, + struct hw_mode_spec *spec) { struct ieee80211_hw *hw = rt2x00dev->hw; struct ieee80211_hw_mode *hwmodes; @@ -289,48 +633,47 @@ static int rt2x00lib_init_hw_modes(struct rt2x00_dev *rt2x00dev, /* * Initialize Rate list. */ - rt2x00lib_rate(&rates[0], 10, 0x001, 0x00, IEEE80211_RATE_CCK); - rt2x00lib_rate(&rates[1], 20, 0x003, 0x01, IEEE80211_RATE_CCK_2); - rt2x00lib_rate(&rates[2], 55, 0x007, 0x02, IEEE80211_RATE_CCK_2); - rt2x00lib_rate(&rates[3], 110, 0x00f, 0x03, IEEE80211_RATE_CCK_2); + rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB, + 0x00, IEEE80211_RATE_CCK); + rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB, + 0x01, IEEE80211_RATE_CCK_2); + rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB, + 0x02, IEEE80211_RATE_CCK_2); + rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB, + 0x03, IEEE80211_RATE_CCK_2); if (spec->num_rates > 4) { - rt2x00lib_rate(&rates[4], 60, 0x01f, 0x0b, IEEE80211_RATE_OFDM); - rt2x00lib_rate(&rates[5], 90, 0x03f, 0x0f, IEEE80211_RATE_OFDM); - rt2x00lib_rate(&rates[6], 120, 0x07f, 0x0a, IEEE80211_RATE_OFDM); - rt2x00lib_rate(&rates[7], 180, 0x0ff, 0x0e, IEEE80211_RATE_OFDM); - rt2x00lib_rate(&rates[8], 240, 0x1ff, 0x09, IEEE80211_RATE_OFDM); - rt2x00lib_rate(&rates[9], 360, 0x3ff, 0x0d, IEEE80211_RATE_OFDM); - rt2x00lib_rate(&rates[10], 480, 0x7ff, 0x08, IEEE80211_RATE_OFDM); - rt2x00lib_rate(&rates[11], 540, 0xfff, 0x0c, IEEE80211_RATE_OFDM); + rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB, + 0x0b, IEEE80211_RATE_OFDM); + rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB, + 0x0f, IEEE80211_RATE_OFDM); + rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB, + 0x0a, IEEE80211_RATE_OFDM); + rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB, + 0x0e, IEEE80211_RATE_OFDM); + rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB, + 0x09, IEEE80211_RATE_OFDM); + rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB, + 0x0d, IEEE80211_RATE_OFDM); + rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB, + 0x08, IEEE80211_RATE_OFDM); + rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB, + 0x0c, IEEE80211_RATE_OFDM); } /* * Initialize Channel list. */ - for (i = 0; i < 14; i++) - rt2x00lib_channel(&channels[i], i + 1, - spec->tx_power_bg[i], spec->chan_val_bg[i]); - - if (spec->num_channels > 14) { - for (i = 14; i < spec->num_channels; i++) { - if (i < 22) - channels[i].chan = 36; - else if (i < 33) - channels[i].chan = 100; - else - channels[i].chan = 149; - channels[i].chan += ((i - 14) * 4); - - if (spec->tx_power_a) - tx_power = spec->tx_power_a[i]; - else - tx_power = spec->tx_power_default; - - rt2x00lib_channel(&channels[i], - channels[i].chan, tx_power, - spec->chan_val_a[i]); - } + for (i = 0; i < spec->num_channels; i++) { + if (spec->channels[i].channel <= 14) + tx_power = spec->tx_power_bg[i]; + else if (spec->tx_power_a) + tx_power = spec->tx_power_a[i]; + else + tx_power = spec->tx_power_default; + + rt2x00lib_channel(&channels[i], + spec->channels[i].channel, tx_power, i); } /* @@ -402,9 +745,9 @@ exit: return -ENOMEM; } -static void rt2x00lib_deinit_hw(struct rt2x00_dev *rt2x00dev) +static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev) { - if (test_bit(DEVICE_INITIALIZED_HW, &rt2x00dev->flags)) + if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags)) ieee80211_unregister_hw(rt2x00dev->hw); if (likely(rt2x00dev->hwmodes)) { @@ -415,7 +758,7 @@ static void rt2x00lib_deinit_hw(struct rt2x00_dev *rt2x00dev) } } -static int rt2x00lib_init_hw(struct rt2x00_dev *rt2x00dev) +static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; int status; @@ -423,7 +766,7 @@ static int rt2x00lib_init_hw(struct rt2x00_dev *rt2x00dev) /* * Initialize HW modes. */ - status = rt2x00lib_init_hw_modes(rt2x00dev, spec); + status = rt2x00lib_probe_hw_modes(rt2x00dev, spec); if (status) return status; @@ -432,11 +775,11 @@ static int rt2x00lib_init_hw(struct rt2x00_dev *rt2x00dev) */ status = ieee80211_register_hw(rt2x00dev->hw); if (status) { - rt2x00lib_deinit_hw(rt2x00dev); + rt2x00lib_remove_hw(rt2x00dev); return status; } - __set_bit(DEVICE_INITIALIZED_HW, &rt2x00dev->flags); + __set_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags); return 0; } @@ -444,8 +787,9 @@ static int rt2x00lib_init_hw(struct rt2x00_dev *rt2x00dev) /* * Initialization/uninitialization handlers. */ -static int rt2x00lib_alloc_ring_entries(struct data_ring *ring, - const u16 max_entries, const u16 data_size, const u16 desc_size) +static int rt2x00lib_alloc_entries(struct data_ring *ring, + const u16 max_entries, const u16 data_size, + const u16 desc_size) { struct data_entry *entry; unsigned int i; @@ -472,41 +816,42 @@ static int rt2x00lib_alloc_ring_entries(struct data_ring *ring, return 0; } -static int rt2x00lib_allocate_ring_entries(struct rt2x00_dev *rt2x00dev) +static int rt2x00lib_alloc_ring_entries(struct rt2x00_dev *rt2x00dev) { struct data_ring *ring; /* * Allocate the RX ring. */ - if (rt2x00lib_alloc_ring_entries(rt2x00dev->rx, - RX_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->rxd_size)) + if (rt2x00lib_alloc_entries(rt2x00dev->rx, RX_ENTRIES, DATA_FRAME_SIZE, + rt2x00dev->ops->rxd_size)) return -ENOMEM; /* * First allocate the TX rings. */ txring_for_each(rt2x00dev, ring) { - if (rt2x00lib_alloc_ring_entries(ring, - TX_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->txd_size)) + if (rt2x00lib_alloc_entries(ring, TX_ENTRIES, DATA_FRAME_SIZE, + rt2x00dev->ops->txd_size)) return -ENOMEM; } + if (!test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags)) + return 0; + /* * Allocate the BEACON ring. */ - if (rt2x00lib_alloc_ring_entries(&rt2x00dev->bcn[0], - BEACON_ENTRIES, MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size)) + if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[0], BEACON_ENTRIES, + MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size)) return -ENOMEM; /* * Allocate the Atim ring. */ - if (test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags)) { - if (rt2x00lib_alloc_ring_entries(&rt2x00dev->bcn[1], - ATIM_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->txd_size)) - return -ENOMEM; - } + if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[1], ATIM_ENTRIES, + DATA_FRAME_SIZE, rt2x00dev->ops->txd_size)) + return -ENOMEM; return 0; } @@ -521,6 +866,27 @@ static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev) } } +void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) +{ + if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags)) + return; + + /* + * Unregister rfkill. + */ + rt2x00rfkill_unregister(rt2x00dev); + + /* + * Allow the HW to uninitialize. + */ + rt2x00dev->ops->lib->uninitialize(rt2x00dev); + + /* + * Free allocated ring entries. + */ + rt2x00lib_free_ring_entries(rt2x00dev); +} + int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) { int status; @@ -529,11 +895,11 @@ int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) return 0; /* - * Allocate all data rings. + * Allocate all ring entries. */ - status = rt2x00lib_allocate_ring_entries(rt2x00dev); + status = rt2x00lib_alloc_ring_entries(rt2x00dev); if (status) { - ERROR(rt2x00dev, "DMA allocation failed.\n"); + ERROR(rt2x00dev, "Ring entries allocation failed.\n"); return status; } @@ -549,7 +915,7 @@ int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) /* * Register the rfkill handler. */ - status = rt2x00lib_register_rfkill(rt2x00dev); + status = rt2x00rfkill_register(rt2x00dev); if (status) goto exit_unitialize; @@ -564,46 +930,24 @@ exit: return status; } -void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) -{ - if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags)) - return; - - /* - * Unregister rfkill. - */ - rt2x00lib_unregister_rfkill(rt2x00dev); - - /* - * Allow the HW to uninitialize. - */ - rt2x00dev->ops->lib->uninitialize(rt2x00dev); - - /* - * Free allocated datarings. - */ - rt2x00lib_free_ring_entries(rt2x00dev); -} - /* * driver allocation handlers. */ static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev) { struct data_ring *ring; - unsigned int ring_num; /* * We need the following rings: * RX: 1 * TX: hw->queues - * Beacon: 1 - * Atim: 1 (if supported) + * Beacon: 1 (if required) + * Atim: 1 (if required) */ - ring_num = 2 + rt2x00dev->hw->queues + - test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags); + rt2x00dev->data_rings = 1 + rt2x00dev->hw->queues + + (2 * test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags)); - ring = kzalloc(sizeof(*ring) * ring_num, GFP_KERNEL); + ring = kzalloc(rt2x00dev->data_rings * sizeof(*ring), GFP_KERNEL); if (!ring) { ERROR(rt2x00dev, "Ring allocation failed.\n"); return -ENOMEM; @@ -612,9 +956,10 @@ static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev) /* * Initialize pointers */ - rt2x00dev->rx = &ring[0]; - rt2x00dev->tx = &ring[1]; - rt2x00dev->bcn = &ring[1 + rt2x00dev->hw->queues]; + rt2x00dev->rx = ring; + rt2x00dev->tx = &rt2x00dev->rx[1]; + if (test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags)) + rt2x00dev->bcn = &rt2x00dev->tx[rt2x00dev->hw->queues]; /* * Initialize ring parameters. @@ -631,6 +976,14 @@ static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev) return 0; } +static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev) +{ + kfree(rt2x00dev->rx); + rt2x00dev->rx = NULL; + rt2x00dev->tx = NULL; + rt2x00dev->bcn = NULL; +} + int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) { int retval = -ENOMEM; @@ -638,7 +991,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Let the driver probe the device to detect the capabilities. */ - retval = rt2x00dev->ops->lib->init_hw(rt2x00dev); + retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev); if (retval) { ERROR(rt2x00dev, "Failed to allocate device.\n"); goto exit; @@ -647,12 +1000,15 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Initialize configuration work. */ + INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled); + INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); + INIT_WORK(&rt2x00dev->config_work, rt2x00lib_configuration_scheduled); INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); /* * Reset current working type. */ - rt2x00dev->interface.type = -EINVAL; + rt2x00dev->interface.type = INVALID_INTERFACE; /* * Allocate ring array. @@ -664,7 +1020,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Initialize ieee80211 structure. */ - retval = rt2x00lib_init_hw(rt2x00dev); + retval = rt2x00lib_probe_hw(rt2x00dev); if (retval) { ERROR(rt2x00dev, "Failed to initialize hw.\n"); goto exit; @@ -673,7 +1029,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Allocatie rfkill. */ - retval = rt2x00lib_allocate_rfkill(rt2x00dev); + retval = rt2x00rfkill_allocate(rt2x00dev); if (retval) goto exit; @@ -682,19 +1038,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) */ rt2x00debug_register(rt2x00dev); - /* - * Check if we need to load the firmware. - */ - if (test_bit(FIRMWARE_REQUIRED, &rt2x00dev->flags)) { - /* - * Request firmware and wait with further - * initializing of the card until the firmware - * has been loaded. - */ - retval = rt2x00lib_load_firmware(rt2x00dev); - if (retval) - goto exit; - } + __set_bit(DEVICE_PRESENT, &rt2x00dev->flags); return 0; @@ -707,6 +1051,8 @@ EXPORT_SYMBOL_GPL(rt2x00lib_probe_dev); void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) { + __clear_bit(DEVICE_PRESENT, &rt2x00dev->flags); + /* * Disable radio. */ @@ -725,41 +1071,52 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) /* * Free rfkill */ - rt2x00lib_free_rfkill(rt2x00dev); + rt2x00rfkill_free(rt2x00dev); /* * Free ieee80211_hw memory. */ - rt2x00lib_deinit_hw(rt2x00dev); + rt2x00lib_remove_hw(rt2x00dev); /* - * Free ring structures. + * Free firmware image. */ - kfree(rt2x00dev->rx); - rt2x00dev->rx = NULL; - rt2x00dev->tx = NULL; - rt2x00dev->bcn = NULL; + rt2x00lib_free_firmware(rt2x00dev); /* - * Free EEPROM memory. + * Free ring structures. */ - kfree(rt2x00dev->eeprom); - rt2x00dev->eeprom = NULL; + rt2x00lib_free_rings(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); /* * Device state handlers */ -int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, - pm_message_t state) +#ifdef CONFIG_PM +int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) { int retval; NOTICE(rt2x00dev, "Going to sleep.\n"); + __clear_bit(DEVICE_PRESENT, &rt2x00dev->flags); - rt2x00lib_disable_radio(rt2x00dev); + /* + * Only continue if mac80211 has open interfaces. + */ + if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags)) + goto exit; + __set_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags); + + /* + * Disable radio and unitialize all items + * that must be recreated on resume. + */ + rt2x00mac_stop(rt2x00dev->hw); + rt2x00lib_uninitialize(rt2x00dev); + rt2x00debug_deregister(rt2x00dev); +exit: /* * Set device mode to sleep for power management. */ @@ -767,259 +1124,74 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, if (retval) return retval; - rt2x00lib_remove_dev(rt2x00dev); - return 0; } EXPORT_SYMBOL_GPL(rt2x00lib_suspend); int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) { + struct interface *intf = &rt2x00dev->interface; int retval; NOTICE(rt2x00dev, "Waking up.\n"); - - retval = rt2x00lib_probe_dev(rt2x00dev); - if (retval) { - ERROR(rt2x00dev, "Failed to allocate device.\n"); - return retval; - } - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00lib_resume); - -/* - * Interrupt context handlers. - */ -void rt2x00lib_txdone(struct data_entry *entry, - const int status, const int retry) -{ - struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; - struct ieee80211_tx_status *tx_status = &entry->tx_status; - struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats; + __set_bit(DEVICE_PRESENT, &rt2x00dev->flags); /* - * Update TX statistics. - */ - tx_status->flags = 0; - tx_status->ack_signal = 0; - tx_status->excessive_retries = (status == TX_FAIL_RETRY); - tx_status->retry_count = retry; - - if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) { - if (status == TX_SUCCESS || status == TX_SUCCESS_RETRY) - tx_status->flags |= IEEE80211_TX_STATUS_ACK; - else - stats->dot11ACKFailureCount++; - } - - tx_status->queue_length = entry->ring->stats.limit; - tx_status->queue_number = tx_status->control.queue; - - if (tx_status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) { - if (status == TX_SUCCESS || status == TX_SUCCESS_RETRY) - stats->dot11RTSSuccessCount++; - else - stats->dot11RTSFailureCount++; - } - - /* - * Send the tx_status to mac80211, - * that method also cleans up the skb structure. - */ - ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status); - - entry->skb = NULL; -} -EXPORT_SYMBOL_GPL(rt2x00lib_txdone); - -void rt2x00lib_rxdone(struct data_entry *entry, char *data, - const int size, const int signal, const int rssi, const int ofdm) -{ - struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; - struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; - struct ieee80211_hw_mode *mode; - struct ieee80211_rate *rate; - struct sk_buff *skb; - unsigned int i; - int val = 0; - - /* - * Update RX statistics. - */ - mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode]; - for (i = 0; i < mode->num_rates; i++) { - rate = &mode->rates[i]; - - /* - * When frame was received with an OFDM bitrate, - * the signal is the PLCP value. If it was received with - * a CCK bitrate the signal is the rate in 0.5kbit/s. - */ - if (!ofdm) - val = DEVICE_GET_RATE_FIELD(rate->val, RATE); - else - val = DEVICE_GET_RATE_FIELD(rate->val, PLCP); - - if (val == signal) { - /* - * Check for preamble bit. - */ - if (signal & 0x08) - val = rate->val2; - else - val = rate->val; - break; - } - } - - rx_status->rate = val; - rx_status->ssi = rssi; - rt2x00_update_link_rssi(&rt2x00dev->link, rssi); - - /* - * Let's allocate a sk_buff where we can store the received data in, - * note that if data is NULL, we still have to allocate a sk_buff - * but that we should use that to replace the sk_buff which is already - * inside the entry. - */ - skb = dev_alloc_skb(size + NET_IP_ALIGN); - if (!skb) - return; - - skb_reserve(skb, NET_IP_ALIGN); - skb_put(skb, size); - - if (data) { - memcpy(skb->data, data, size); - entry->skb = skb; - skb = NULL; - } - - ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); - entry->skb = skb; -} -EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); - -/* - * TX descriptor initializer - */ -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) -{ - struct data_entry_desc desc; - int tx_rate; - int bitrate; - int duration; - int residual; - u16 frame_control; - u16 seq_ctrl; - - /* - * Identify queue - */ - if (control->queue < rt2x00dev->hw->queues) - desc.queue = control->queue; - else - desc.queue = 15; - - /* - * Read required fields from ieee80211 header. - */ - frame_control = le16_to_cpu(ieee80211hdr->frame_control); - seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl); - - tx_rate = control->tx_rate; - - /* - * Check if this is a rts frame + * Open the debugfs entry. */ - if (is_rts_frame(frame_control)) { - __set_bit(ENTRY_TXD_RTS_FRAME, &entry->flags); - if (control->rts_cts_rate) - tx_rate = control->rts_cts_rate; - } + rt2x00debug_register(rt2x00dev); /* - * Check for OFDM + * Only continue if mac80211 had open interfaces. */ - if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) - __set_bit(ENTRY_TXD_OFDM_RATE, &entry->flags); + if (!__test_and_clear_bit(DEVICE_STARTED_SUSPEND, &rt2x00dev->flags)) + return 0; /* - * Check if more fragments are pending + * Reinitialize device and all active interfaces. */ - if (ieee80211_get_morefrag(ieee80211hdr)) - __set_bit(ENTRY_TXD_MORE_FRAG, &entry->flags); + retval = rt2x00mac_start(rt2x00dev->hw); + if (retval) + goto exit; /* - * Beacons and probe responses require the tsf timestamp - * to be inserted into the frame. + * Reconfigure device. */ - if (control->queue == IEEE80211_TX_QUEUE_BEACON || - is_probe_resp(frame_control)) - __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &entry->flags); + rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf, 1); + if (!rt2x00dev->hw->conf.radio_enabled) + rt2x00lib_disable_radio(rt2x00dev); - /* - * Check if ACK is required - */ - if (!(control->flags & IEEE80211_TXCTL_NO_ACK)) - __set_bit(ENTRY_TXD_REQ_ACK, &entry->flags); + rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); + rt2x00lib_config_bssid(rt2x00dev, intf->bssid); + rt2x00lib_config_type(rt2x00dev, intf->type); /* - * Determine with what IFS priority this frame should be send. - * Set ifs to IFS_SIFS when the this is not the first fragment, - * or this fragment came after RTS/CTS. + * It is possible that during that mac80211 has attempted + * to send frames while we were suspending or resuming. + * In that case we have disabled the TX queue and should + * now enable it again */ - if ((seq_ctrl & IEEE80211_SCTL_FRAG) > 0 || - test_bit(ENTRY_TXD_RTS_FRAME, &entry->flags)) - desc.ifs = IFS_SIFS; - else - desc.ifs = IFS_BACKOFF; + ieee80211_start_queues(rt2x00dev->hw); /* - * How the length should be processed depends - * on if we are working with OFDM rates or not. + * When in Master or Ad-hoc mode, + * restart Beacon transmitting by faking a beacondone event. */ - if (test_bit(ENTRY_TXD_OFDM_RATE, &entry->flags)) { - residual = 0; - desc.length_high = ((length + FCS_LEN) >> 6) & 0x3f; - desc.length_low = ((length + FCS_LEN) & 0x3f); - - } else { - bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE); - - /* - * Convert length to microseconds. - */ - residual = get_duration_res(length + FCS_LEN, bitrate); - duration = get_duration(length + FCS_LEN, bitrate); - - if (residual != 0) - duration++; + if (intf->type == IEEE80211_IF_TYPE_AP || + intf->type == IEEE80211_IF_TYPE_IBSS) + rt2x00lib_beacondone(rt2x00dev); - desc.length_high = duration >> 8; - desc.length_low = duration & 0xff; - } - - /* - * Create the signal and service values. - */ - desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP); - if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE)) - desc.signal |= 0x08; + return 0; - desc.service = 0x04; - if (residual <= (8 % 11)) - desc.service |= 0x80; +exit: + rt2x00lib_disable_radio(rt2x00dev); + rt2x00lib_uninitialize(rt2x00dev); + rt2x00debug_deregister(rt2x00dev); - rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry, txd, &desc, - ieee80211hdr, length, control); + return retval; } -EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); +EXPORT_SYMBOL_GPL(rt2x00lib_resume); +#endif /* CONFIG_PM */ /* * rt2x00lib module information. diff --git a/package/rt2x00/src/rt2x00firmware.c b/package/rt2x00/src/rt2x00firmware.c index 4c1ce4cdb4..236025f8b9 100644 --- a/package/rt2x00/src/rt2x00firmware.c +++ b/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; } + diff --git a/package/rt2x00/src/rt2x00lib.h b/package/rt2x00/src/rt2x00lib.h index 461d13db0f..06d9bc0015 100644 --- a/package/rt2x00/src/rt2x00lib.h +++ b/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 */ diff --git a/package/rt2x00/src/rt2x00mac.c b/package/rt2x00/src/rt2x00mac.c index 8835df2e2e..85ea8a8e65 100644 --- a/package/rt2x00/src/rt2x00mac.c +++ b/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,131 +130,149 @@ 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); diff --git a/package/rt2x00/src/rt2x00pci.c b/package/rt2x00/src/rt2x00pci.c index 33c724d441..04663eb319 100644 --- a/package/rt2x00/src/rt2x00pci.c +++ b/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 */ diff --git a/package/rt2x00/src/rt2x00pci.h b/package/rt2x00/src/rt2x00pci.h index 8595cbff4e..82adeac061 100644 --- a/package/rt2x00/src/rt2x00pci.h +++ b/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 */ diff --git a/package/rt2x00/src/rt2x00reg.h b/package/rt2x00/src/rt2x00reg.h new file mode 100644 index 0000000000..838421216d --- /dev/null +++ b/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 */ diff --git a/package/rt2x00/src/rt2x00rfkill.c b/package/rt2x00/src/rt2x00rfkill.c index c08a2aa0ea..a0f8b8e0a2 100644 --- a/package/rt2x00/src/rt2x00rfkill.c +++ b/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); } diff --git a/package/rt2x00/src/rt2x00ring.h b/package/rt2x00/src/rt2x00ring.h new file mode 100644 index 0000000000..1a864d32cf --- /dev/null +++ b/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 */ diff --git a/package/rt2x00/src/rt2x00usb.c b/package/rt2x00/src/rt2x00usb.c index 4175aeffe9..568d73847d 100644 --- a/package/rt2x00/src/rt2x00usb.c +++ b/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 */ diff --git a/package/rt2x00/src/rt2x00usb.h b/package/rt2x00/src/rt2x00usb.h index 91627f2dd2..2681abe4d4 100644 --- a/package/rt2x00/src/rt2x00usb.h +++ b/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,20 +34,26 @@ /* * 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. */ #define USB_VENDOR_REQUEST ( USB_TYPE_VENDOR | USB_RECIP_DEVICE ) @@ -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 */ diff --git a/package/rt2x00/src/rt61pci.c b/package/rt2x00/src/rt61pci.c index 627754802d..ecae968ce0 100644 --- a/package/rt2x00/src/rt61pci.c +++ b/package/rt2x00/src/rt61pci.c @@ -29,20 +29,15 @@ */ #define DRV_NAME "rt61pci" +#include <linux/delay.h> +#include <linux/etherdevice.h> +#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> -#include <linux/init.h> #include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/delay.h> -#include <linux/etherdevice.h> #include <linux/eeprom_93cx6.h> -#include <asm/io.h> - #include "rt2x00.h" -#include "rt2x00lib.h" #include "rt2x00pci.h" #include "rt61pci.h" @@ -73,12 +68,12 @@ static u32 rt61pci_bbp_check(const struct rt2x00_dev *rt2x00dev) } static void rt61pci_bbp_write(const struct rt2x00_dev *rt2x00dev, - const u8 reg_id, const u8 value) + const unsigned int word, const u8 value) { u32 reg; /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt61pci_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { @@ -91,7 +86,7 @@ static void rt61pci_bbp_write(const struct rt2x00_dev *rt2x00dev, */ reg = 0; rt2x00_set_field32(®, PHY_CSR3_VALUE, value); - rt2x00_set_field32(®, PHY_CSR3_REGNUM, reg_id); + rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); @@ -99,12 +94,12 @@ static void rt61pci_bbp_write(const struct rt2x00_dev *rt2x00dev, } static void rt61pci_bbp_read(const struct rt2x00_dev *rt2x00dev, - const u8 reg_id, u8 *value) + const unsigned int word, u8 *value) { u32 reg; /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt61pci_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { @@ -115,15 +110,15 @@ static void rt61pci_bbp_read(const struct rt2x00_dev *rt2x00dev, /* * Write the request into the BBP. */ - reg =0; - rt2x00_set_field32(®, PHY_CSR3_REGNUM, reg_id); + reg = 0; + rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt61pci_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { @@ -136,11 +131,14 @@ static void rt61pci_bbp_read(const struct rt2x00_dev *rt2x00dev, } static void rt61pci_rf_write(const struct rt2x00_dev *rt2x00dev, - const u32 value) + const unsigned int word, const u32 value) { u32 reg; unsigned int i; + if (!word) + return; + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2x00pci_register_read(rt2x00dev, PHY_CSR4, ®); if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY)) @@ -159,10 +157,12 @@ rf_write: rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg); + rt2x00_rf_write(rt2x00dev, word, value); } static void rt61pci_mcu_request(const struct rt2x00_dev *rt2x00dev, - const u8 command, const u8 token, const u8 arg0, const u8 arg1) + const u8 command, const u8 token, + const u8 arg0, const u8 arg1) { u32 reg; @@ -170,8 +170,8 @@ static void rt61pci_mcu_request(const struct rt2x00_dev *rt2x00dev, if (rt2x00_get_field32(reg, H2M_MAILBOX_CSR_OWNER)) { ERROR(rt2x00dev, "mcu request error. " - "Request 0x%02x failed for token 0x%02x.\n", - command, token); + "Request 0x%02x failed for token 0x%02x.\n", + command, token); return; } @@ -194,14 +194,12 @@ static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom) rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); - eeprom->reg_data_in = !!rt2x00_get_field32(reg, - E2PROM_CSR_DATA_IN); - eeprom->reg_data_out = !!rt2x00_get_field32(reg, - E2PROM_CSR_DATA_OUT); - eeprom->reg_data_clock = !!rt2x00_get_field32(reg, - E2PROM_CSR_DATA_CLOCK); - eeprom->reg_chip_select = !!rt2x00_get_field32(reg, - E2PROM_CSR_CHIP_SELECT); + eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); + eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); + eeprom->reg_data_clock = + !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_CLOCK); + eeprom->reg_chip_select = + !!rt2x00_get_field32(reg, E2PROM_CSR_CHIP_SELECT); } static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom) @@ -209,14 +207,12 @@ static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom) struct rt2x00_dev *rt2x00dev = eeprom->data; u32 reg = 0; - rt2x00_set_field32(®, E2PROM_CSR_DATA_IN, - !!eeprom->reg_data_in); - rt2x00_set_field32(®, E2PROM_CSR_DATA_OUT, - !!eeprom->reg_data_out); + rt2x00_set_field32(®, E2PROM_CSR_DATA_IN, !!eeprom->reg_data_in); + rt2x00_set_field32(®, E2PROM_CSR_DATA_OUT, !!eeprom->reg_data_out); rt2x00_set_field32(®, E2PROM_CSR_DATA_CLOCK, - !!eeprom->reg_data_clock); + !!eeprom->reg_data_clock); rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, - !!eeprom->reg_chip_select); + !!eeprom->reg_chip_select); rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); } @@ -224,62 +220,44 @@ static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom) #ifdef CONFIG_RT2X00_LIB_DEBUGFS #define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) ) -static void rt61pci_read_csr(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) +static void rt61pci_read_csr(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 *data) { rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data); } -static void rt61pci_write_csr(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), *((u32*)data)); -} - -static void rt61pci_read_eeprom(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) +static void rt61pci_write_csr(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 data) { - rt2x00_eeprom_read(rt2x00dev, word, data); -} - -static void rt61pci_write_eeprom(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2x00_eeprom_write(rt2x00dev, word, *((u16*)data)); -} - -static void rt61pci_read_bbp(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt61pci_bbp_read(rt2x00dev, word, data); -} - -static void rt61pci_write_bbp(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt61pci_bbp_write(rt2x00dev, word, *((u8*)data)); + rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data); } static const struct rt2x00debug rt61pci_rt2x00debug = { - .owner = THIS_MODULE, - .reg_csr = { + .owner = THIS_MODULE, + .csr = { .read = rt61pci_read_csr, .write = rt61pci_write_csr, .word_size = sizeof(u32), .word_count = CSR_REG_SIZE / sizeof(u32), }, - .reg_eeprom = { - .read = rt61pci_read_eeprom, - .write = rt61pci_write_eeprom, + .eeprom = { + .read = rt2x00_eeprom_read, + .write = rt2x00_eeprom_write, .word_size = sizeof(u16), .word_count = EEPROM_SIZE / sizeof(u16), }, - .reg_bbp = { - .read = rt61pci_read_bbp, - .write = rt61pci_write_bbp, + .bbp = { + .read = rt61pci_bbp_read, + .write = rt61pci_bbp_write, .word_size = sizeof(u8), .word_count = BBP_SIZE / sizeof(u8), }, + .rf = { + .read = rt2x00_rf_read, + .write = rt61pci_rf_write, + .word_size = sizeof(u32), + .word_count = RF_SIZE / sizeof(u32), + }, }; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ @@ -291,478 +269,418 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); return rt2x00_get_field32(reg, MAC_CSR13_BIT5);; } -#endif /* CONFIG_RT2400PCI_RFKILL */ +#else +#define rt61pci_rfkill_poll NULL +#endif /* CONFIG_RT61PCI_RFKILL */ /* * Configuration handlers. */ -static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) +static void rt61pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac) { - u32 reg[2]; + u32 tmp; - memset(®, 0, sizeof(reg)); - memcpy(®, bssid, ETH_ALEN); + tmp = le32_to_cpu(mac[1]); + rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); + mac[1] = cpu_to_le32(tmp); - rt2x00_set_field32(®[1], MAC_CSR5_BSS_ID_MASK, 3); - - /* - * The BSSID is passed to us as an array of bytes, - * that array is little endian, so no need for byte ordering. - */ - rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, ®, sizeof(reg)); + rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, mac, + (2 * sizeof(__le32))); } -static void rt61pci_config_promisc(struct rt2x00_dev *rt2x00dev, - const int promisc) +static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid) { - u32 reg; + u32 tmp; - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, !promisc); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); + tmp = le32_to_cpu(bssid[1]); + rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3); + bssid[1] = cpu_to_le32(tmp); + + rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, bssid, + (2 * sizeof(__le32))); } -static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, - const int type) +static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, + const int tsf_sync) { u32 reg; - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); - /* - * Apply hardware packet filter. + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - - if (!is_monitor_present(&rt2x00dev->interface) && - (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA)) - rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, 1); - else - rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, 0); - - rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, 1); - if (is_monitor_present(&rt2x00dev->interface)) { - rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 0); - } else { - rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); - } - - rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_BORADCAST, 0); - - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); /* * Enable synchronisation. */ rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - if (is_interface_present(&rt2x00dev->interface)) { - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); - } - + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - if (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_AP) - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 2); - else if (type == IEEE80211_IF_TYPE_STA) - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 1); - else if (is_monitor_present(&rt2x00dev->interface) && - !is_interface_present(&rt2x00dev->interface)) - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 0); - + rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync); rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); } +static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) +{ + u32 reg; + + rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); + + rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); + rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, + !!short_preamble); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); +} + +static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev, + const int basic_rate_mask) +{ + rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, basic_rate_mask); +} + static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev, - const int value, const int channel, const int txpower) + struct rf_channel *rf, const int txpower) { - u8 reg = 0; - u32 rf1 = 0; - u32 rf2 = value; - u32 rf3 = 0; - u32 rf4 = 0; - - if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags) || channel <= 14) - rf1 = 0x00002ccc; - else if (channel == 36 || - (channel >= 100 && channel <= 116) || - channel >= 157) - rf1 = 0x00002cd4; - else - rf1 = 0x00002cd0; - - if (channel <= 14) { - rf3 = 0x00068455; - } else if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) { - if (channel >= 36 && channel <= 48) - rf3 = 0x0009be55; - else if (channel >= 52 && channel <= 64) - rf3 = 0x0009ae55; - else if (channel >= 100 && channel <= 112) - rf3 = 0x000bae55; - else - rf3 = 0x000bbe55; - } else { - switch (channel) { - case 36: - case 40: - case 44: - rf3 = 0x00098455; - break; - case 48: - rf3 = 0x00098655; - break; - case 52: - rf3 = 0x00098855; - break; - case 56: - rf3 = 0x00098c55; - - case 60: - rf3 = 0x00098e55; - break; - case 64: - rf3 = 0x00099255; - break; - case 100: - case 104: - case 108: - rf3 = 0x000b9855; - break; - case 112: - case 116: - case 120: - case 124: - rf3 = 0x000b9a55; - break; - case 128: - case 132: - rf3 = 0x000b9c55; - break; - case 136: - case 140: - rf3 = 0x000b9e55; - break; - case 149: - case 153: - case 157: - case 161: - case 165: - rf3 = 0x000ba255; - break; - } - } + u8 r3; + u8 r94; + u8 smart; - if (channel < 14) { - if (channel & 1) - rf4 = 0x000ffa0b; - else - rf4 = 0x000ffa1f; - } else if (channel == 14) { - rf4 = 0x000ffa13; - } else if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) { - switch (channel) { - case 36: - case 56: - case 116: - case 136: - rf4 = 0x000ffa23; - break; - case 40: - case 60: - case 100: - case 120: - case 140: - rf4 = 0x000ffa03; - break; - case 44: - case 64: - case 104: - case 124: - rf4 = 0x000ffa0b; - break; - case 48: - case 108: - case 128: - rf4 = 0x000ffa13; - break; - case 52: - case 112: - case 132: - rf4 = 0x000ffa1b; - break; - case 149: - rf4 = 0x000ffa1f; - break; - case 153: - rf4 = 0x000ffa27; - break; - case 157: - rf4 = 0x000ffa07; - break; - case 161: - rf4 = 0x000ffa0f; - break; - case 165: - rf4 = 0x000ffa17; - break; - } - } else { - switch (channel) { - case 36: - case 40: - case 60: - case 140: - case 100: - case 104: - case 108: - case 112: - case 116: - case 120: - rf4 = 0x000c0a03; - break; - case 44: - case 64: - case 124: - case 149: - rf4 = 0x000c0a1b; - break; - case 48: - case 128: - case 153: - rf4 = 0x000c0a0b; - break; - case 52: - case 132: - rf4 = 0x000c0a23; - break; - case 56: - case 136: - rf4 = 0x000c0a13; - break; - case 157: - case 161: - case 165: - rf4 = 0x000c0a17; - break; - } - } + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); + rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); - /* - * Set TXpower. - */ - rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); + smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || + rt2x00_rf(&rt2x00dev->chip, RF2527)); - /* - * Set Frequency offset. - */ - rt2x00_set_field32(&rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); + rt61pci_bbp_read(rt2x00dev, 3, &r3); + rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); + rt61pci_bbp_write(rt2x00dev, 3, r3); + + r94 = 6; + if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94)) + r94 += txpower - MAX_TXPOWER; + else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94)) + r94 += txpower; + rt61pci_bbp_write(rt2x00dev, 94, r94); - rt61pci_rf_write(rt2x00dev, rf1); - rt61pci_rf_write(rt2x00dev, rf2); - rt61pci_rf_write(rt2x00dev, rf3 & ~0x00000004); - rt61pci_rf_write(rt2x00dev, rf4); + rt61pci_rf_write(rt2x00dev, 1, rf->rf1); + rt61pci_rf_write(rt2x00dev, 2, rf->rf2); + rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt61pci_rf_write(rt2x00dev, 4, rf->rf4); udelay(200); - rt61pci_rf_write(rt2x00dev, rf1); - rt61pci_rf_write(rt2x00dev, rf2); - rt61pci_rf_write(rt2x00dev, rf3 | 0x00000004); - rt61pci_rf_write(rt2x00dev, rf4); + rt61pci_rf_write(rt2x00dev, 1, rf->rf1); + rt61pci_rf_write(rt2x00dev, 2, rf->rf2); + rt61pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); + rt61pci_rf_write(rt2x00dev, 4, rf->rf4); udelay(200); - rt61pci_rf_write(rt2x00dev, rf1); - rt61pci_rf_write(rt2x00dev, rf2); - rt61pci_rf_write(rt2x00dev, rf3 & ~0x00000004); - rt61pci_rf_write(rt2x00dev, rf4); - - rt61pci_bbp_read(rt2x00dev, 3, ®); - if (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527)) - reg &= ~0x01; - else - reg |= 0x01; - rt61pci_bbp_write(rt2x00dev, 3, reg); + rt61pci_rf_write(rt2x00dev, 1, rf->rf1); + rt61pci_rf_write(rt2x00dev, 2, rf->rf2); + rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt61pci_rf_write(rt2x00dev, 4, rf->rf4); msleep(1); - - /* - * Update rf fields - */ - rt2x00dev->rf1 = rf1; - rt2x00dev->rf2 = rf2; - rt2x00dev->rf3 = rf3; - rt2x00dev->rf4 = rf4; - rt2x00dev->tx_power = txpower; } static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev, - const int txpower) + const int txpower) { - rt2x00_set_field32(&rt2x00dev->rf3, RF3_TXPOWER, - TXPOWER_TO_DEV(txpower)); + struct rf_channel rf; - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf1); - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf2); - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf3 & ~0x00000004); - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf4); + rt2x00_rf_read(rt2x00dev, 1, &rf.rf1); + rt2x00_rf_read(rt2x00dev, 2, &rf.rf2); + rt2x00_rf_read(rt2x00dev, 3, &rf.rf3); + rt2x00_rf_read(rt2x00dev, 4, &rf.rf4); - udelay(200); + rt61pci_config_channel(rt2x00dev, &rf, txpower); +} + +static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, + const int antenna_tx, + const int antenna_rx) +{ + u8 r3; + u8 r4; + u8 r77; + + rt61pci_bbp_read(rt2x00dev, 3, &r3); + rt61pci_bbp_read(rt2x00dev, 4, &r4); + rt61pci_bbp_read(rt2x00dev, 77, &r77); - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf1); - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf2); - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf3 | 0x00000004); - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf4); + rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, + !rt2x00_rf(&rt2x00dev->chip, RF5225)); - udelay(200); + switch (antenna_rx) { + case ANTENNA_SW_DIVERSITY: + case ANTENNA_HW_DIVERSITY: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, + !!(rt2x00dev->curr_hwmode != HWMODE_A)); + break; + case ANTENNA_A: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf1); - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf2); - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf3 & ~0x00000004); - rt61pci_rf_write(rt2x00dev, rt2x00dev->rf4); + if (rt2x00dev->curr_hwmode == HWMODE_A) + rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); + else + rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); + break; + case ANTENNA_B: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); + + if (rt2x00dev->curr_hwmode == HWMODE_A) + rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); + else + rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); + break; + } + + rt61pci_bbp_write(rt2x00dev, 77, r77); + rt61pci_bbp_write(rt2x00dev, 3, r3); + rt61pci_bbp_write(rt2x00dev, 4, r4); } -static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev, - const int antenna_tx, const int antenna_rx) +static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, + const int antenna_tx, + const int antenna_rx) { - u32 reg; u8 r3; u8 r4; u8 r77; - rt2x00pci_register_read(rt2x00dev, PHY_CSR0, ®); + rt61pci_bbp_read(rt2x00dev, 3, &r3); + rt61pci_bbp_read(rt2x00dev, 4, &r4); + rt61pci_bbp_read(rt2x00dev, 77, &r77); - if (rt2x00dev->curr_hwmode == HWMODE_A) { - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { - rt61pci_bbp_write(rt2x00dev, 17, 0x38); - rt61pci_bbp_write(rt2x00dev, 96, 0x78); - rt61pci_bbp_write(rt2x00dev, 104, 0x48); - rt61pci_bbp_write(rt2x00dev, 75, 0x80); - rt61pci_bbp_write(rt2x00dev, 86, 0x80); - rt61pci_bbp_write(rt2x00dev, 88, 0x80); - } else { - rt61pci_bbp_write(rt2x00dev, 17, 0x28); - rt61pci_bbp_write(rt2x00dev, 96, 0x58); - rt61pci_bbp_write(rt2x00dev, 104, 0x38); - rt61pci_bbp_write(rt2x00dev, 75, 0xfe); - rt61pci_bbp_write(rt2x00dev, 86, 0xfe); - rt61pci_bbp_write(rt2x00dev, 88, 0xfe); - } - rt61pci_bbp_write(rt2x00dev, 35, 0x60); - rt61pci_bbp_write(rt2x00dev, 97, 0x58); - rt61pci_bbp_write(rt2x00dev, 98, 0x58); + rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, + !rt2x00_rf(&rt2x00dev->chip, RF2527)); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, + !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); - rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, 0); - rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, 1); - } else { - if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { - rt61pci_bbp_write(rt2x00dev, 17, 0x30); - rt61pci_bbp_write(rt2x00dev, 96, 0x68); - rt61pci_bbp_write(rt2x00dev, 104, 0x3c); - rt61pci_bbp_write(rt2x00dev, 75, 0x80); - rt61pci_bbp_write(rt2x00dev, 86, 0x80); - rt61pci_bbp_write(rt2x00dev, 88, 0x80); - } else { - rt61pci_bbp_write(rt2x00dev, 17, 0x20); - rt61pci_bbp_write(rt2x00dev, 96, 0x48); - rt61pci_bbp_write(rt2x00dev, 104, 0x2c); - rt61pci_bbp_write(rt2x00dev, 75, 0xfe); - rt61pci_bbp_write(rt2x00dev, 86, 0xfe); - rt61pci_bbp_write(rt2x00dev, 88, 0xfe); - } - rt61pci_bbp_write(rt2x00dev, 35, 0x50); - rt61pci_bbp_write(rt2x00dev, 97, 0x48); - rt61pci_bbp_write(rt2x00dev, 98, 0x48); + switch (antenna_rx) { + case ANTENNA_SW_DIVERSITY: + case ANTENNA_HW_DIVERSITY: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); + break; + case ANTENNA_A: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); + rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); + break; + case ANTENNA_B: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); + rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); + break; + } - rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, 1); - rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, 0); + rt61pci_bbp_write(rt2x00dev, 77, r77); + rt61pci_bbp_write(rt2x00dev, 3, r3); + rt61pci_bbp_write(rt2x00dev, 4, r4); +} + +static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev, + const int p1, const int p2) +{ + u32 reg; + + rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); + + if (p1 != 0xff) { + rt2x00_set_field32(®, MAC_CSR13_BIT4, !!p1); + rt2x00_set_field32(®, MAC_CSR13_BIT12, 0); + rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); } + if (p2 != 0xff) { + rt2x00_set_field32(®, MAC_CSR13_BIT3, !p2); + rt2x00_set_field32(®, MAC_CSR13_BIT11, 0); + rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); + } +} - rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); +static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev, + const int antenna_tx, + const int antenna_rx) +{ + u16 eeprom; + u8 r3; + u8 r4; + u8 r77; rt61pci_bbp_read(rt2x00dev, 3, &r3); rt61pci_bbp_read(rt2x00dev, 4, &r4); rt61pci_bbp_read(rt2x00dev, 77, &r77); + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - if (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527)) - rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); + rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); - if (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF5325)) { - if (antenna_rx == ANTENNA_DIVERSITY) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); - if (rt2x00dev->curr_hwmode != HWMODE_A) - rt2x00_set_field8(&r4, BBP_R4_RX_BG_MODE, 1); - } else if (antenna_rx == ANTENNA_A) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); - if (rt2x00dev->curr_hwmode == HWMODE_A) - rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); - else - rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); - rt61pci_bbp_write(rt2x00dev, 77, r77); - } else if (antenna_rx == ANTENNA_B) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); - if (rt2x00dev->curr_hwmode == HWMODE_A) - rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); - else - rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) && + rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) { + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 1); + rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1); + } else if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY)) { + if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED) >= 2) { + rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); rt61pci_bbp_write(rt2x00dev, 77, r77); } - } else if (rt2x00_rf(&rt2x00dev->chip, RF2527) || - (rt2x00_rf(&rt2x00dev->chip, RF2529) && - test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags))) { - if (antenna_rx == ANTENNA_DIVERSITY) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); - rt2x00_set_field8(&r4, BBP_R4_RX_BG_MODE, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); - } else if (antenna_rx == ANTENNA_A) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_BG_MODE, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); - rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); + rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1); + } else if (!rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) && + rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) { + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); + + switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) { + case 0: + rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1); + break; + case 1: + rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 0); + break; + case 2: + rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0); + break; + case 3: + rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1); + break; + } + } else if (!rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) && + !rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) { + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); + + switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) { + case 0: + rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); rt61pci_bbp_write(rt2x00dev, 77, r77); - } else if (antenna_rx == ANTENNA_B) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_BG_MODE, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); + rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1); + break; + case 1: rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); rt61pci_bbp_write(rt2x00dev, 77, r77); + rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 0); + break; + case 2: + rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); + rt61pci_bbp_write(rt2x00dev, 77, r77); + rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0); + break; + case 3: + rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); + rt61pci_bbp_write(rt2x00dev, 77, r77); + rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1); + break; } } + rt61pci_bbp_write(rt2x00dev, 3, r3); + rt61pci_bbp_write(rt2x00dev, 4, r4); +} + +struct antenna_sel { + u8 word; /* - * TODO: RF2529 with another antenna value then 2 are ignored. - * The legacy driver is unclear whether in those cases there is - * a possibility to switch antenna. + * value[0] -> non-LNA + * value[1] -> LNA */ + u8 value[2]; +}; - rt61pci_bbp_write(rt2x00dev, 3, r3); - rt61pci_bbp_write(rt2x00dev, 4, r4); +static const struct antenna_sel antenna_sel_a[] = { + { 96, { 0x58, 0x78 } }, + { 104, { 0x38, 0x48 } }, + { 75, { 0xfe, 0x80 } }, + { 86, { 0xfe, 0x80 } }, + { 88, { 0xfe, 0x80 } }, + { 35, { 0x60, 0x60 } }, + { 97, { 0x58, 0x58 } }, + { 98, { 0x58, 0x58 } }, +}; + +static const struct antenna_sel antenna_sel_bg[] = { + { 96, { 0x48, 0x68 } }, + { 104, { 0x2c, 0x3c } }, + { 75, { 0xfe, 0x80 } }, + { 86, { 0xfe, 0x80 } }, + { 88, { 0xfe, 0x80 } }, + { 35, { 0x50, 0x50 } }, + { 97, { 0x48, 0x48 } }, + { 98, { 0x48, 0x48 } }, +}; + +static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev, + const int antenna_tx, const int antenna_rx) +{ + const struct antenna_sel *sel; + unsigned int lna; + unsigned int i; + u32 reg; + + rt2x00pci_register_read(rt2x00dev, PHY_CSR0, ®); + + if (rt2x00dev->curr_hwmode == HWMODE_A) { + sel = antenna_sel_a; + lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); + + rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, 0); + rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, 1); + } else { + sel = antenna_sel_bg; + lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); + + rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, 1); + rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, 0); + } + + for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) + rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); + + rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); + + if (rt2x00_rf(&rt2x00dev->chip, RF5225) || + rt2x00_rf(&rt2x00dev->chip, RF5325)) + rt61pci_config_antenna_5x(rt2x00dev, antenna_tx, antenna_rx); + else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) + rt61pci_config_antenna_2x(rt2x00dev, antenna_tx, antenna_rx); + else if (rt2x00_rf(&rt2x00dev->chip, RF2529)) { + if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) + rt61pci_config_antenna_2x(rt2x00dev, antenna_tx, + antenna_rx); + else + rt61pci_config_antenna_2529(rt2x00dev, antenna_tx, + antenna_rx); + } } static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev, - const int short_slot_time, const int beacon_int) + struct rt2x00lib_conf *libconf) { u32 reg; rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); - rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, - short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME); + rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, libconf->slot_time); rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); rt2x00pci_register_read(rt2x00dev, MAC_CSR8, ®); - rt2x00_set_field32(®, MAC_CSR8_SIFS, SIFS); + rt2x00_set_field32(®, MAC_CSR8_SIFS, libconf->sifs); rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); - rt2x00_set_field32(®, MAC_CSR8_EIFS, EIFS); + rt2x00_set_field32(®, MAC_CSR8_EIFS, libconf->eifs); rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg); rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); @@ -774,77 +692,27 @@ static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, beacon_int * 16); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, + libconf->conf->beacon_int * 16); rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); } -static void rt61pci_config_rate(struct rt2x00_dev *rt2x00dev, const int rate) +static void rt61pci_config(struct rt2x00_dev *rt2x00dev, + const unsigned int flags, + struct rt2x00lib_conf *libconf) { - struct ieee80211_conf *conf = &rt2x00dev->hw->conf; - u32 reg; - u32 value; - u32 preamble; - - preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) - ? SHORT_PREAMBLE : PREAMBLE; - - /* - * Extract the allowed ratemask from the device specific rate value, - * We need to set TXRX_CSR5 to the basic rate mask so we need to mask - * off the non-basic rates. - */ - reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE; - - rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, reg); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ? - SHORT_DIFS : DIFS) + - PLCP + preamble + get_duration(ACK_SIZE, 10); - rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, value); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); - if (preamble == SHORT_PREAMBLE) - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, 1); - else - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, 0); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); -} - -static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev, - const int phymode) -{ - struct ieee80211_hw_mode *mode; - struct ieee80211_rate *rate; - - if (phymode == MODE_IEEE80211A) - rt2x00dev->curr_hwmode = HWMODE_A; - else if (phymode == MODE_IEEE80211B) - rt2x00dev->curr_hwmode = HWMODE_B; - else - rt2x00dev->curr_hwmode = HWMODE_G; - - mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode]; - rate = &mode->rates[mode->num_rates - 1]; - - rt61pci_config_rate(rt2x00dev, rate->val2); -} - -static void rt61pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *addr) -{ - u32 reg[2]; - - memset(®, 0, sizeof(reg)); - memcpy(®, addr, ETH_ALEN); - - rt2x00_set_field32(®[1], MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); - - /* - * The MAC address is passed to us as an array of bytes, - * that array is little endian, so no need for byte ordering. - */ - rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, ®, sizeof(reg)); + if (flags & CONFIG_UPDATE_PHYMODE) + rt61pci_config_phymode(rt2x00dev, libconf->basic_rates); + if (flags & CONFIG_UPDATE_CHANNEL) + rt61pci_config_channel(rt2x00dev, &libconf->rf, + libconf->conf->power_level); + if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL)) + rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level); + if (flags & CONFIG_UPDATE_ANTENNA) + rt61pci_config_antenna(rt2x00dev, libconf->conf->antenna_sel_tx, + libconf->conf->antenna_sel_rx); + if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) + rt61pci_config_duration(rt2x00dev, libconf); } /* @@ -924,10 +792,33 @@ static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, int rssi) /* * Link tuning */ +static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + /* + * Update FCS error count from register. + */ + rt2x00pci_register_read(rt2x00dev, STA_CSR0, ®); + rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); + + /* + * Update False CCA count from register. + */ + rt2x00pci_register_read(rt2x00dev, STA_CSR1, ®); + rt2x00dev->link.false_cca = + rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); +} + +static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev) +{ + rt61pci_bbp_write(rt2x00dev, 17, 0x20); + rt2x00dev->link.vgc_level = 0x20; +} + static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) { int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); - u32 reg; u8 r17; u8 up_bound; u8 low_bound; @@ -1013,27 +904,21 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. */ - rt2x00pci_register_read(rt2x00dev, STA_CSR1, ®); - rt2x00dev->link.false_cca = - rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); - if (rt2x00dev->link.false_cca > 512 && r17 < up_bound) { if (++r17 > up_bound) r17 = up_bound; rt61pci_bbp_write(rt2x00dev, 17, r17); - rt2x00dev->rx_status.noise = r17; } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) { if (--r17 < low_bound) r17 = low_bound; rt61pci_bbp_write(rt2x00dev, 17, r17); - rt2x00dev->rx_status.noise = r17; } } /* * Firmware name function. */ -static char *rt61pci_get_fw_name(struct rt2x00_dev *rt2x00dev) +static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) { char *fw_name; @@ -1059,7 +944,7 @@ static char *rt61pci_get_fw_name(struct rt2x00_dev *rt2x00dev) * Initialization functions. */ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, - const size_t len) + const size_t len) { int i; u32 reg; @@ -1097,8 +982,8 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, rt2x00_set_field32(®, MCU_CNTL_CSR_SELECT_BANK, 1); rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); - rt2x00pci_register_multiwrite( - rt2x00dev, FIRMWARE_IMAGE_BASE, data, len); + rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, + data, len); rt2x00_set_field32(®, MCU_CNTL_CSR_SELECT_BANK, 0); rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); @@ -1140,19 +1025,19 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, static void rt61pci_init_rxring(struct rt2x00_dev *rt2x00dev) { + struct data_ring *ring = rt2x00dev->rx; struct data_desc *rxd; unsigned int i; u32 word; - memset(rt2x00dev->rx->data_addr, 0x00, - rt2x00_get_ring_size(rt2x00dev->rx)); + memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring)); - for (i = 0; i < rt2x00dev->rx->stats.limit; i++) { - rxd = rt2x00dev->rx->entry[i].priv; + for (i = 0; i < ring->stats.limit; i++) { + rxd = ring->entry[i].priv; rt2x00_desc_read(rxd, 5, &word); rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, - rt2x00dev->rx->entry[i].data_dma); + ring->entry[i].data_dma); rt2x00_desc_write(rxd, 5, word); rt2x00_desc_read(rxd, 0, &word); @@ -1163,10 +1048,9 @@ static void rt61pci_init_rxring(struct rt2x00_dev *rt2x00dev) rt2x00_ring_index_clear(rt2x00dev->rx); } -static void rt61pci_init_txring(struct rt2x00_dev *rt2x00dev, - const int queue) +static void rt61pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue) { - struct data_ring *ring = rt2x00_get_ring(rt2x00dev, queue); + struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); struct data_desc *txd; unsigned int i; u32 word; @@ -1187,7 +1071,7 @@ static void rt61pci_init_txring(struct rt2x00_dev *rt2x00dev, rt2x00_desc_read(txd, 6, &word); rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, - ring->entry[i].data_dma); + ring->entry[i].data_dma); rt2x00_desc_write(txd, 6, word); rt2x00_desc_read(txd, 0, &word); @@ -1212,70 +1096,86 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev) rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA2); rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA3); rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA4); - rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); /* * Initialize registers. */ rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, ®); rt2x00_set_field32(®, TX_RING_CSR0_AC0_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); rt2x00_set_field32(®, TX_RING_CSR0_AC1_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); rt2x00_set_field32(®, TX_RING_CSR0_AC2_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].stats.limit); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].stats.limit); rt2x00_set_field32(®, TX_RING_CSR0_AC3_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].stats.limit); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].stats.limit); rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg); rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, ®); rt2x00_set_field32(®, TX_RING_CSR1_MGMT_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].stats.limit); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].stats.limit); rt2x00_set_field32(®, TX_RING_CSR1_TXD_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size / 4); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size / + 4); rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg); rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, ®); rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg); rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, ®); rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg); rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, ®); rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].data_dma); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].data_dma); rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg); rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, ®); rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].data_dma); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].data_dma); rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg); rt2x00pci_register_read(rt2x00dev, MGMT_BASE_CSR, ®); rt2x00_set_field32(®, MGMT_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].data_dma); + rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].data_dma); rt2x00pci_register_write(rt2x00dev, MGMT_BASE_CSR, reg); rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, ®); rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, - rt2x00dev->rx->stats.limit); + rt2x00dev->rx->stats.limit); rt2x00_set_field32(®, RX_RING_CSR_RXD_SIZE, - rt2x00dev->rx->desc_size / 4); + rt2x00dev->rx->desc_size / 4); rt2x00_set_field32(®, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4); rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg); rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, ®); rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER, - rt2x00dev->rx->data_dma); + rt2x00dev->rx->data_dma); rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg); - rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, 0x000000aa); - rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, 0x0000001f); - rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, 0x00000002); + rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, ®); + rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC0, 2); + rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC1, 2); + rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC2, 2); + rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC3, 2); + rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_MGMT, 0); + rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg); + + rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, ®); + rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC0, 1); + rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1); + rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1); + rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1); + rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 1); + rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg); + + rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); + rt2x00_set_field32(®, RX_CNTL_CSR_LOAD_RXD, 1); + rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg); return 0; } @@ -1284,49 +1184,86 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; - if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) - return -EBUSY; - - rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00000718); - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0); rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR1, 0x9eb39eb3); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR2, 0x8a8b8c8d); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR3, 0x00858687); - - rt2x00pci_register_write(rt2x00dev, TXRX_CSR7, 0x2e31353b); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR8, 0x2a2a2a2c); + rt2x00pci_register_read(rt2x00dev, TXRX_CSR1, ®); + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */ + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1, 30); /* Rssi */ + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2, 42); /* OFDM Rate */ + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3, 30); /* Rssi */ + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3_VALID, 1); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR1, reg); + + /* + * CCK TXD BBP registers + */ + rt2x00pci_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0, 13); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1, 12); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2, 11); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3, 10); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3_VALID, 1); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR2, reg); + + /* + * OFDM TXD BBP registers + */ + rt2x00pci_register_read(rt2x00dev, TXRX_CSR3, ®); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0, 7); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1, 6); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2, 5); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2_VALID, 1); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR3, reg); + + rt2x00pci_register_read(rt2x00dev, TXRX_CSR7, ®); + rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_6MBS, 59); + rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_9MBS, 53); + rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_12MBS, 49); + rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_18MBS, 46); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR7, reg); + + rt2x00pci_register_read(rt2x00dev, TXRX_CSR8, ®); + rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_24MBS, 44); + rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_36MBS, 42); + rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_48MBS, 42); + rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_54MBS, 42); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR8, reg); rt2x00pci_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); rt2x00pci_register_write(rt2x00dev, MAC_CSR6, 0x00000fff); + rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); + rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); + rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); + + rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x0000071c); + + if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) + return -EBUSY; + rt2x00pci_register_write(rt2x00dev, MAC_CSR13, 0x0000e000); + /* + * Invalidate all Shared Keys (SEC_CSR0), + * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) + */ rt2x00pci_register_write(rt2x00dev, SEC_CSR0, 0x00000000); rt2x00pci_register_write(rt2x00dev, SEC_CSR1, 0x00000000); rt2x00pci_register_write(rt2x00dev, SEC_CSR5, 0x00000000); - rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR0, ®); - rt2x00_set_field32(®, AC_TXOP_CSR0_AC0_TX_OP, 0); - rt2x00_set_field32(®, AC_TXOP_CSR0_AC1_TX_OP, 0); - rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR0, reg); - - rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR1, ®); - rt2x00_set_field32(®, AC_TXOP_CSR1_AC2_TX_OP, 192); - rt2x00_set_field32(®, AC_TXOP_CSR1_AC3_TX_OP, 48); - rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg); - - rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); - rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); - rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); - rt2x00pci_register_write(rt2x00dev, PHY_CSR1, 0x000023b0); rt2x00pci_register_write(rt2x00dev, PHY_CSR5, 0x060a100c); rt2x00pci_register_write(rt2x00dev, PHY_CSR6, 0x00080606); @@ -1338,6 +1275,16 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); + rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR0, ®); + rt2x00_set_field32(®, AC_TXOP_CSR0_AC0_TX_OP, 0); + rt2x00_set_field32(®, AC_TXOP_CSR0_AC1_TX_OP, 0); + rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR0, reg); + + rt2x00pci_register_read(rt2x00dev, AC_TXOP_CSR1, ®); + rt2x00_set_field32(®, AC_TXOP_CSR1_AC2_TX_OP, 192); + rt2x00_set_field32(®, AC_TXOP_CSR1_AC3_TX_OP, 48); + rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg); + /* * We must clear the error counters. * These registers are cleared on read, @@ -1350,7 +1297,7 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) /* * Reset MAC and BBP registers. */ - reg = 0; + rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); @@ -1388,7 +1335,6 @@ static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev) continue_csr_init: rt61pci_bbp_write(rt2x00dev, 3, 0x00); rt61pci_bbp_write(rt2x00dev, 15, 0x30); - rt61pci_bbp_write(rt2x00dev, 17, 0x20); rt61pci_bbp_write(rt2x00dev, 21, 0xc8); rt61pci_bbp_write(rt2x00dev, 22, 0x38); rt61pci_bbp_write(rt2x00dev, 23, 0x06); @@ -1420,7 +1366,7 @@ continue_csr_init: reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n", - reg_id, value); + reg_id, value); rt61pci_bbp_write(rt2x00dev, reg_id, value); } } @@ -1433,25 +1379,27 @@ continue_csr_init: * Device state switch handlers. */ static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { u32 reg; rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - state == STATE_RADIO_RX_OFF); + state == STATE_RADIO_RX_OFF); rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); } -static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled) +static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, + enum dev_state state) { + int mask = (state == STATE_RADIO_IRQ_OFF); u32 reg; /* * When interrupts are being enabled, the interrupt registers * should clear the register to assure a clean state. */ - if (enabled) { + if (state == STATE_RADIO_IRQ_ON) { rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); @@ -1464,27 +1412,28 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, int enabled) * Non-checked interrupt bits are disabled by default. */ rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); - rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, !enabled); - rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, !enabled); - rt2x00_set_field32(®, INT_MASK_CSR_BEACON_DONE, !enabled); - rt2x00_set_field32(®, INT_MASK_CSR_ENABLE_MITIGATION, !enabled); + rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, mask); + rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, mask); + rt2x00_set_field32(®, INT_MASK_CSR_ENABLE_MITIGATION, mask); rt2x00_set_field32(®, INT_MASK_CSR_MITIGATION_PERIOD, 0xff); rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_0, !enabled); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_1, !enabled); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_2, !enabled); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_3, !enabled); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_4, !enabled); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_5, !enabled); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_6, !enabled); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, !enabled); + rt2x00_set_field32(®, MCU_INT_MASK_CSR_0, mask); + rt2x00_set_field32(®, MCU_INT_MASK_CSR_1, mask); + rt2x00_set_field32(®, MCU_INT_MASK_CSR_2, mask); + rt2x00_set_field32(®, MCU_INT_MASK_CSR_3, mask); + rt2x00_set_field32(®, MCU_INT_MASK_CSR_4, mask); + rt2x00_set_field32(®, MCU_INT_MASK_CSR_5, mask); + rt2x00_set_field32(®, MCU_INT_MASK_CSR_6, mask); + rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, mask); rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); } static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) { + u32 reg; + /* * Initialize all registers. */ @@ -1498,12 +1447,14 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Enable interrupts. */ - rt61pci_toggle_irq(rt2x00dev, 1); + rt61pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON); /* * Enable RX. */ - rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, 0x00000001); + rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); + rt2x00_set_field32(®, RX_CNTL_CSR_ENABLE_RX_DMA, 1); + rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg); /* * Enable LED @@ -1543,11 +1494,10 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev) /* * Disable interrupts. */ - rt61pci_toggle_irq(rt2x00dev, 0); + rt61pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_OFF); } -static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) +static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) { u32 reg; unsigned int i; @@ -1561,18 +1511,6 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep); rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg); - if (put_to_sleep) { - rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000005); - rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c); - rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060); - rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0x00, 0x00); - } else { - rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007); - rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018); - rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020); - rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0x00, 0x00); - } - /* * Device is not guaranteed to be in the requested state yet. * We must wait until the register indicates that the @@ -1580,43 +1518,43 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®); - current_state = rt2x00_get_field32(reg, - MAC_CSR12_BBP_CURRENT_STATE); + current_state = + rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); if (current_state == !put_to_sleep) return 0; msleep(10); } NOTICE(rt2x00dev, "Device failed to enter state %d, " - "current device state %d.\n", !put_to_sleep, current_state); + "current device state %d.\n", !put_to_sleep, current_state); return -EBUSY; } static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { int retval = 0; switch (state) { - case STATE_RADIO_ON: - retval = rt61pci_enable_radio(rt2x00dev); + case STATE_RADIO_ON: + retval = rt61pci_enable_radio(rt2x00dev); break; - case STATE_RADIO_OFF: - rt61pci_disable_radio(rt2x00dev); + case STATE_RADIO_OFF: + rt61pci_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_OFF: - rt61pci_toggle_rx(rt2x00dev, state); + case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_OFF: + rt61pci_toggle_rx(rt2x00dev, state); break; - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: - case STATE_AWAKE: - retval = rt61pci_set_state(rt2x00dev, state); + case STATE_DEEP_SLEEP: + case STATE_SLEEP: + case STATE_STANDBY: + case STATE_AWAKE: + retval = rt61pci_set_state(rt2x00dev, state); break; - default: - retval = -ENOTSUPP; + default: + retval = -ENOTSUPP; break; } @@ -1627,9 +1565,11 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, * TX descriptor initialization */ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry, struct data_desc *txd, - struct data_entry_desc *desc, struct ieee80211_hdr *ieee80211hdr, - unsigned int length, struct ieee80211_tx_control *control) + struct data_desc *txd, + struct txdata_entry_desc *desc, + struct ieee80211_hdr *ieee80211hdr, + unsigned int length, + struct ieee80211_tx_control *control) { u32 word; @@ -1638,9 +1578,9 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue); - rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->ring->tx_params.aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->ring->tx_params.cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->ring->tx_params.cw_max); + rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1); rt2x00_desc_write(txd, 1, word); @@ -1654,7 +1594,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_read(txd, 5, &word); rt2x00_set_field32(&word, TXD_W5_TX_POWER, - TXPOWER_TO_DEV(control->power_level)); + TXPOWER_TO_DEV(control->power_level)); rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); @@ -1666,17 +1606,21 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &entry->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_REQ_ACK, &entry->flags)); + !(control->flags & IEEE80211_TXCTL_NO_ACK)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &entry->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &entry->flags)); + test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); - rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, 0); + rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, + !!(control->flags & + IEEE80211_TXCTL_LONG_RETRY_LIMIT)); rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0); rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length); + rt2x00_set_field32(&word, TXD_W0_BURST, + test_bit(ENTRY_TXD_BURST, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } @@ -1684,11 +1628,18 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * TX data initialization */ -static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue) +static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, + unsigned int queue) { u32 reg; if (queue == IEEE80211_TX_QUEUE_BEACON) { + /* + * For Wi-Fi faily generated beacons between participating + * stations. Set TBTT phase adaptive adjustment step to 8us. + */ + rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); @@ -1717,22 +1668,22 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue) static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) { u16 eeprom; - char offset; - char lna; + u8 offset; + u8 lna; lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA); switch (lna) { - case 3: - offset = 90; + case 3: + offset = 90; break; - case 2: - offset = 74; + case 2: + offset = 74; break; - case 1: - offset = 64; + case 1: + offset = 64; break; - default: - return 0; + default: + return 0; } if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) { @@ -1755,8 +1706,8 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset; } -static int rt61pci_fill_rxdone(struct data_entry *entry, - int *signal, int *rssi, int *ofdm) +static void rt61pci_fill_rxdone(struct data_entry *entry, + struct rxdata_entry_desc *desc) { struct data_desc *rxd = entry->priv; u32 word0; @@ -1765,22 +1716,19 @@ static int rt61pci_fill_rxdone(struct data_entry *entry, rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); - /* - * TODO: Don't we need to keep statistics - * updated about these errors? - */ - if (rt2x00_get_field32(word0, RXD_W0_CRC) || - rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR)) - return -EINVAL; + desc->flags = 0; + if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) + desc->flags |= RX_FLAG_FAILED_FCS_CRC; /* * Obtain the status about this packet. */ - *signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - *rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1); - *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + desc->rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1); + desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + return; } /* @@ -1790,24 +1738,41 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) { struct data_ring *ring; struct data_entry *entry; + struct data_entry *entry_done; struct data_desc *txd; u32 word; u32 reg; + u32 old_reg; + int type; int index; int tx_status; int retry; + /* + * During each loop we will compare the freshly read + * STA_CSR4 register value with the value read from + * the previous loop. If the 2 values are equal then + * we should stop processing because the chance it + * quite big that the device has been unplugged and + * we risk going into an endless loop. + */ + old_reg = 0; + while (1) { rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) break; + if (old_reg == reg) + break; + old_reg = reg; + /* * Skip this entry when it contains an invalid * ring identication number. */ - ring = rt2x00_get_ring(rt2x00dev, - rt2x00_get_field32(reg, STA_CSR4_PID_TYPE)); + type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE); + ring = rt2x00lib_get_ring(rt2x00dev, type); if (unlikely(!ring)) continue; @@ -1827,6 +1792,17 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) !rt2x00_get_field32(word, TXD_W0_VALID)) return; + entry_done = rt2x00_get_data_entry_done(ring); + while (entry != entry_done) { + /* Catch up. Just report any entries we missed as + * failed. */ + WARNING(rt2x00dev, + "TX status report missed for entry %p\n", + entry_done); + rt2x00lib_txdone(entry_done, TX_FAIL_OTHER, 0); + entry_done = rt2x00_get_data_entry_done(ring); + } + /* * Obtain the status about this packet. */ @@ -1850,26 +1826,27 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) */ if (!rt2x00_ring_full(ring)) ieee80211_wake_queue(rt2x00dev->hw, - entry->tx_status.control.queue); + entry->tx_status.control.queue); } } static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) { struct rt2x00_dev *rt2x00dev = dev_instance; + u32 reg_mcu; u32 reg; /* * Get the interrupt sources & saved to local variable. * Write register value back to clear pending interrupts. */ - rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®); - rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg); + rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®_mcu); + rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu); rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); - if (!reg) + if (!reg && !reg_mcu) return IRQ_NONE; if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) @@ -1882,44 +1859,37 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) */ /* - * 1 - Beacon timer expired interrupt. - */ - if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE)) - rt2x00pci_beacondone(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); - - /* - * 2 - Rx ring done interrupt. + * 1 - Rx ring done interrupt. */ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE)) rt2x00pci_rxdone(rt2x00dev); /* - * 3 - Tx ring done interrupt. + * 2 - Tx ring done interrupt. */ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE)) rt61pci_txdone(rt2x00dev); + /* + * 3 - Handle MCU command done. + */ + if (reg_mcu) + rt2x00pci_register_write(rt2x00dev, + M2H_CMD_DONE_CSR, 0xffffffff); + return IRQ_HANDLED; } /* - * Device initialization functions. + * Device probe functions. */ -static int rt61pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) { struct eeprom_93cx6 eeprom; u32 reg; u16 word; u8 *mac; - char value; - - /* - * Allocate the eeprom memory, check the eeprom width - * and copy the entire eeprom into this allocated memory. - */ - rt2x00dev->eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); - if (!rt2x00dev->eeprom) - return -ENOMEM; + s8 value; rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); @@ -1927,22 +1897,24 @@ static int rt61pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev) eeprom.register_read = rt61pci_eepromregister_read; eeprom.register_write = rt61pci_eepromregister_write; eeprom.width = rt2x00_get_field32(reg, E2PROM_CSR_TYPE_93C46) ? - PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; + PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; eeprom.reg_data_in = 0; eeprom.reg_data_out = 0; eeprom.reg_data_clock = 0; eeprom.reg_chip_select = 0; eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, - EEPROM_SIZE / sizeof(u16)); + EEPROM_SIZE / sizeof(u16)); /* * Start validation of the data that has been read. */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { + DECLARE_MAC_BUF(macbuf); + random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac)); + EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac)); } rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); @@ -1973,7 +1945,7 @@ static int rt61pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word); if (word == 0xffff) { rt2x00_set_field16(&word, EEPROM_LED_LED_MODE, - LED_MODE_DEFAULT); + LED_MODE_DEFAULT); rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word); EEPROM(rt2x00dev, "Led: 0x%04x\n", word); } @@ -2039,7 +2011,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * PCI header of the device. */ pci_read_config_word(rt2x00dev_pci(rt2x00dev), - PCI_CONFIG_HEADER_DEVICE, &device); + PCI_CONFIG_HEADER_DEVICE, &device); value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, device, value, reg); @@ -2055,10 +2027,10 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Identify default antenna configuration. */ - rt2x00dev->hw->conf.antenna_sel_tx = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_TX_DEFAULT); - rt2x00dev->hw->conf.antenna_sel_rx = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_RX_DEFAULT); + rt2x00dev->hw->conf.antenna_sel_tx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); + rt2x00dev->hw->conf.antenna_sel_rx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); /* * Read the Frame type. @@ -2075,8 +2047,10 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Detect if this device has an hardware controlled radio. */ +#ifdef CONFIG_RT61PCI_RFKILL if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(DEVICE_SUPPORT_HW_BUTTON, &rt2x00dev->flags); + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +#endif /* CONFIG_RT61PCI_RFKILL */ /* * Read frequency offset and RF programming sequence. @@ -2085,8 +2059,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ)) __set_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags); - rt2x00dev->freq_offset = - rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); + rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); /* * Read external LNA informations. @@ -2108,62 +2081,149 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00dev->led_mode = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE, - rt2x00dev->led_mode); + rt2x00dev->led_mode); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_0)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_GPIO_0)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_1)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_GPIO_1)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_2)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_GPIO_2)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_3)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_GPIO_3)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_4)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_GPIO_4)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT)); + rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_RDY_G)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_RDY_G)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_RDY_A)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_RDY_A)); return 0; } /* - * RF value list for RF5225, RF5325, RF2527 & RF2529 - * Supports: 2.4 GHz + * RF value list for RF5225 & RF5325 + * Supports: 2.4 GHz & 5.2 GHz, rf_sequence disabled */ -static const u32 rf_vals_bg[] = { - 0x00004786, 0x00004786, 0x0000478a, 0x0000478a, 0x0000478e, - 0x0000478e, 0x00004792, 0x00004792, 0x00004796, 0x00004796, - 0x0000479a, 0x0000479a, 0x0000479e, 0x000047a2 +static const struct rf_channel rf_vals_noseq[] = { + { 1, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b }, + { 2, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f }, + { 3, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b }, + { 4, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f }, + { 5, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b }, + { 6, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f }, + { 7, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b }, + { 8, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f }, + { 9, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b }, + { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f }, + { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b }, + { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f }, + { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b }, + { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 }, + + /* 802.11 UNI / HyperLan 2 */ + { 36, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa23 }, + { 40, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa03 }, + { 44, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa0b }, + { 48, 0x00002ccc, 0x000049aa, 0x0009be55, 0x000ffa13 }, + { 52, 0x00002ccc, 0x000049ae, 0x0009ae55, 0x000ffa1b }, + { 56, 0x00002ccc, 0x000049b2, 0x0009ae55, 0x000ffa23 }, + { 60, 0x00002ccc, 0x000049ba, 0x0009ae55, 0x000ffa03 }, + { 64, 0x00002ccc, 0x000049be, 0x0009ae55, 0x000ffa0b }, + + /* 802.11 HyperLan 2 */ + { 100, 0x00002ccc, 0x00004a2a, 0x000bae55, 0x000ffa03 }, + { 104, 0x00002ccc, 0x00004a2e, 0x000bae55, 0x000ffa0b }, + { 108, 0x00002ccc, 0x00004a32, 0x000bae55, 0x000ffa13 }, + { 112, 0x00002ccc, 0x00004a36, 0x000bae55, 0x000ffa1b }, + { 116, 0x00002ccc, 0x00004a3a, 0x000bbe55, 0x000ffa23 }, + { 120, 0x00002ccc, 0x00004a82, 0x000bbe55, 0x000ffa03 }, + { 124, 0x00002ccc, 0x00004a86, 0x000bbe55, 0x000ffa0b }, + { 128, 0x00002ccc, 0x00004a8a, 0x000bbe55, 0x000ffa13 }, + { 132, 0x00002ccc, 0x00004a8e, 0x000bbe55, 0x000ffa1b }, + { 136, 0x00002ccc, 0x00004a92, 0x000bbe55, 0x000ffa23 }, + + /* 802.11 UNII */ + { 140, 0x00002ccc, 0x00004a9a, 0x000bbe55, 0x000ffa03 }, + { 149, 0x00002ccc, 0x00004aa2, 0x000bbe55, 0x000ffa1f }, + { 153, 0x00002ccc, 0x00004aa6, 0x000bbe55, 0x000ffa27 }, + { 157, 0x00002ccc, 0x00004aae, 0x000bbe55, 0x000ffa07 }, + { 161, 0x00002ccc, 0x00004ab2, 0x000bbe55, 0x000ffa0f }, + { 165, 0x00002ccc, 0x00004ab6, 0x000bbe55, 0x000ffa17 }, + + /* MMAC(Japan)J52 ch 34,38,42,46 */ + { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa0b }, + { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000ffa13 }, + { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa1b }, + { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa23 }, }; /* - * RF value list for RF5225 & RF5325 (supplement to vals_bg) - * Supports: 5.2 GHz, rf_sequence disabled + * RF value list for RF5225 & RF5325 + * Supports: 2.4 GHz & 5.2 GHz, rf_sequence enabled */ -static const u32 rf_vals_a_5x_noseq[] = { - 0x0000499a, 0x000049a2, 0x000049a6, 0x000049aa, 0x000049ae, - 0x000049b2, 0x000049ba, 0x000049be, 0x00004a2a, 0x00004a2e, - 0x00004a32, 0x00004a36, 0x00004a3a, 0x00004a82, 0x00004a86, - 0x00004a8a, 0x00004a8e, 0x00004a92, 0x00004a9a, 0x00004aa2, - 0x00004aa6, 0x00004aae, 0x00004ab2, 0x00004ab6 +static const struct rf_channel rf_vals_seq[] = { + { 1, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b }, + { 2, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f }, + { 3, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b }, + { 4, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f }, + { 5, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b }, + { 6, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f }, + { 7, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b }, + { 8, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f }, + { 9, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b }, + { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f }, + { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b }, + { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f }, + { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b }, + { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 }, + + /* 802.11 UNI / HyperLan 2 */ + { 36, 0x00002cd4, 0x0004481a, 0x00098455, 0x000c0a03 }, + { 40, 0x00002cd0, 0x00044682, 0x00098455, 0x000c0a03 }, + { 44, 0x00002cd0, 0x00044686, 0x00098455, 0x000c0a1b }, + { 48, 0x00002cd0, 0x0004468e, 0x00098655, 0x000c0a0b }, + { 52, 0x00002cd0, 0x00044692, 0x00098855, 0x000c0a23 }, + { 56, 0x00002cd0, 0x0004469a, 0x00098c55, 0x000c0a13 }, + { 60, 0x00002cd0, 0x000446a2, 0x00098e55, 0x000c0a03 }, + { 64, 0x00002cd0, 0x000446a6, 0x00099255, 0x000c0a1b }, + + /* 802.11 HyperLan 2 */ + { 100, 0x00002cd4, 0x0004489a, 0x000b9855, 0x000c0a03 }, + { 104, 0x00002cd4, 0x000448a2, 0x000b9855, 0x000c0a03 }, + { 108, 0x00002cd4, 0x000448aa, 0x000b9855, 0x000c0a03 }, + { 112, 0x00002cd4, 0x000448b2, 0x000b9a55, 0x000c0a03 }, + { 116, 0x00002cd4, 0x000448ba, 0x000b9a55, 0x000c0a03 }, + { 120, 0x00002cd0, 0x00044702, 0x000b9a55, 0x000c0a03 }, + { 124, 0x00002cd0, 0x00044706, 0x000b9a55, 0x000c0a1b }, + { 128, 0x00002cd0, 0x0004470e, 0x000b9c55, 0x000c0a0b }, + { 132, 0x00002cd0, 0x00044712, 0x000b9c55, 0x000c0a23 }, + { 136, 0x00002cd0, 0x0004471a, 0x000b9e55, 0x000c0a13 }, + + /* 802.11 UNII */ + { 140, 0x00002cd0, 0x00044722, 0x000b9e55, 0x000c0a03 }, + { 149, 0x00002cd0, 0x0004472e, 0x000ba255, 0x000c0a1b }, + { 153, 0x00002cd0, 0x00044736, 0x000ba255, 0x000c0a0b }, + { 157, 0x00002cd4, 0x0004490a, 0x000ba255, 0x000c0a17 }, + { 161, 0x00002cd4, 0x00044912, 0x000ba255, 0x000c0a17 }, + { 165, 0x00002cd4, 0x0004491a, 0x000ba255, 0x000c0a17 }, + + /* MMAC(Japan)J52 ch 34,38,42,46 */ + { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000c0a0b }, + { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000c0a13 }, + { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000c0a1b }, + { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000c0a23 }, }; -/* - * RF value list for RF5225 & RF5325 (supplement to vals_bg) - * Supports: 5.2 GHz, rf_sequence enabled - */ -static const u32 rf_vals_a_5x_seq[] = { - 0x0004481a, 0x00044682, 0x00044686, 0x0004468e, 0x00044692, - 0x0004469a, 0x000446a2, 0x000446a6, 0x0004489a, 0x000448a2, - 0x000448aa, 0x000448b2, 0x000448ba, 0x00044702, 0x00044706, - 0x0004470e, 0x00044712, 0x0004471a, 0x00044722, 0x0004472e, - 0x00044736, 0x0004490a, 0x00044912, 0x0004491a -}; - -static void rt61pci_init_hw_mode(struct rt2x00_dev *rt2x00dev) +static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; u8 *txpower; @@ -2172,21 +2232,18 @@ static void rt61pci_init_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Initialize all hw fields. */ - rt2x00dev->hw->flags = IEEE80211_HW_HOST_GEN_BEACON | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_WEP_INCLUDE_IV | - IEEE80211_HW_DATA_NULLFUNC_ACK | - IEEE80211_HW_NO_TKIP_WMM_HWACCEL | - IEEE80211_HW_MONITOR_DURING_OPER | - IEEE80211_HW_NO_PROBE_FILTERING; + rt2x00dev->hw->flags = + IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; rt2x00dev->hw->extra_tx_headroom = 0; + rt2x00dev->hw->max_signal = MAX_SIGNAL; rt2x00dev->hw->max_rssi = MAX_RX_SSI; - rt2x00dev->hw->max_noise = MAX_RX_NOISE; rt2x00dev->hw->queues = 5; SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); + rt2x00_eeprom_addr(rt2x00dev, + EEPROM_MAC_ADDR_0)); /* * Convert tx_power array in eeprom. @@ -2200,38 +2257,39 @@ static void rt61pci_init_hw_mode(struct rt2x00_dev *rt2x00dev) */ spec->num_modes = 2; spec->num_rates = 12; - spec->num_channels = 14; spec->tx_power_a = NULL; spec->tx_power_bg = txpower; spec->tx_power_default = DEFAULT_TXPOWER; - spec->chan_val_a = NULL; - spec->chan_val_bg = rf_vals_bg; + + if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) { + spec->num_channels = 14; + spec->channels = rf_vals_noseq; + } else { + spec->num_channels = 14; + spec->channels = rf_vals_seq; + } if (rt2x00_rf(&rt2x00dev->chip, RF5225) || rt2x00_rf(&rt2x00dev->chip, RF5325)) { spec->num_modes = 3; - spec->num_channels += 24; + spec->num_channels = ARRAY_SIZE(rf_vals_seq); txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); for (i = 0; i < 14; i++) txpower[i] = TXPOWER_FROM_DEV(txpower[i]); spec->tx_power_a = txpower; - if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) - spec->chan_val_a = rf_vals_a_5x_noseq; - else - spec->chan_val_a = rf_vals_a_5x_seq; } } -static int rt61pci_init_hw(struct rt2x00_dev *rt2x00dev) +static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; /* * Allocate eeprom data. */ - retval = rt61pci_alloc_eeprom(rt2x00dev); + retval = rt61pci_validate_eeprom(rt2x00dev); if (retval) return retval; @@ -2242,12 +2300,12 @@ static int rt61pci_init_hw(struct rt2x00_dev *rt2x00dev) /* * Initialize hw specifications. */ - rt61pci_init_hw_mode(rt2x00dev); + rt61pci_probe_hw_mode(rt2x00dev); /* * This device requires firmware */ - __set_bit(FIRMWARE_REQUIRED, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); /* * Set the rssi offset. @@ -2260,28 +2318,76 @@ static int rt61pci_init_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static int rt61pci_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) +static void rt61pci_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_addr_list *mc_list) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct interface *intf = &rt2x00dev->interface; u32 reg; /* - * Update FCS error count from register. - * The dot11ACKFailureCount, dot11RTSFailureCount and - * dot11RTSSuccessCount are updated in interrupt time. + * Mask off any flags we are going to ignore from + * the total_flags field. */ - rt2x00pci_register_read(rt2x00dev, STA_CSR0, ®); - rt2x00dev->low_level_stats.dot11FCSErrorCount += - rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); + *total_flags &= + FIF_ALLMULTI | + FIF_FCSFAIL | + FIF_PLCPFAIL | + FIF_CONTROL | + FIF_OTHER_BSS | + FIF_PROMISC_IN_BSS; - memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats)); + /* + * Apply some rules to the filters: + * - Some filters imply different filters to be set. + * - Some things we can't filter out at all. + * - Some filters are set based on interface type. + */ + if (mc_count) + *total_flags |= FIF_ALLMULTI; + if (*total_flags & FIF_OTHER_BSS || + *total_flags & FIF_PROMISC_IN_BSS) + *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; + if (is_interface_type(intf, IEEE80211_IF_TYPE_AP)) + *total_flags |= FIF_PROMISC_IN_BSS; - return 0; + /* + * Check if there is any work left for us. + */ + if (intf->filter == *total_flags) + return; + intf->filter = *total_flags; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, + !(*total_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, + !(*total_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, + !(*total_flags & FIF_CONTROL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, + !(*total_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, + !(*total_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, + !(*total_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_BORADCAST, 0); + rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); } static int rt61pci_set_retry_limit(struct ieee80211_hw *hw, - u32 short_retry, u32 long_retry) + u32 short_retry, u32 long_retry) { struct rt2x00_dev *rt2x00dev = hw->priv; u32 reg; @@ -2301,7 +2407,7 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) u32 reg; rt2x00pci_register_read(rt2x00dev, TXRX_CSR13, ®); - tsf = (u64)rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; + tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; rt2x00pci_register_read(rt2x00dev, TXRX_CSR12, ®); tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER); @@ -2316,58 +2422,103 @@ static void rt61pci_reset_tsf(struct ieee80211_hw *hw) rt2x00pci_register_write(rt2x00dev, TXRX_CSR13, 0); } +static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ieee80211_tx_control *control) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + + /* + * 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; + + /* + * We need to append the descriptor in front of the + * beacon frame. + */ + if (skb_headroom(skb) < TXD_DESC_SIZE) { + if (pskb_expand_head(skb, TXD_DESC_SIZE, 0, GFP_ATOMIC)) { + dev_kfree_skb(skb); + return -ENOMEM; + } + } + + /* + * First we create the beacon. + */ + skb_push(skb, TXD_DESC_SIZE); + memset(skb->data, 0, TXD_DESC_SIZE); + + rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data, + (struct ieee80211_hdr *)(skb->data + + TXD_DESC_SIZE), + skb->len - TXD_DESC_SIZE, control); + + /* + * Write entire beacon with descriptor to register, + * and kick the beacon generator. + */ + rt2x00pci_register_multiwrite(rt2x00dev, HW_BEACON_BASE0, + skb->data, skb->len); + rt61pci_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + + return 0; +} + static const struct ieee80211_ops rt61pci_mac80211_ops = { - .tx = rt2x00lib_tx, - .reset = rt2x00lib_reset, - .add_interface = rt2x00lib_add_interface, - .remove_interface = rt2x00lib_remove_interface, - .config = rt2x00lib_config, - .config_interface = rt2x00lib_config_interface, - .set_multicast_list = rt2x00lib_set_multicast_list, - .get_stats = rt61pci_get_stats, + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, + .remove_interface = rt2x00mac_remove_interface, + .config = rt2x00mac_config, + .config_interface = rt2x00mac_config_interface, + .configure_filter = rt61pci_configure_filter, + .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt61pci_set_retry_limit, - .conf_tx = rt2x00lib_conf_tx, - .get_tx_stats = rt2x00lib_get_tx_stats, + .erp_ie_changed = rt2x00mac_erp_ie_changed, + .conf_tx = rt2x00mac_conf_tx, + .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt61pci_get_tsf, .reset_tsf = rt61pci_reset_tsf, - .beacon_update = rt2x00pci_beacon_update, + .beacon_update = rt61pci_beacon_update, }; static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .irq_handler = rt61pci_interrupt, - .init_hw = rt61pci_init_hw, - .get_fw_name = rt61pci_get_fw_name, + .probe_hw = rt61pci_probe_hw, + .get_firmware_name = rt61pci_get_firmware_name, .load_firmware = rt61pci_load_firmware, .initialize = rt2x00pci_initialize, .uninitialize = rt2x00pci_uninitialize, .set_device_state = rt61pci_set_device_state, -#ifdef CONFIG_RT61PCI_RFKILL .rfkill_poll = rt61pci_rfkill_poll, -#endif /* CONFIG_RT61PCI_RFKILL */ + .link_stats = rt61pci_link_stats, + .reset_tuner = rt61pci_reset_tuner, .link_tuner = rt61pci_link_tuner, .write_tx_desc = rt61pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, - .config_type = rt61pci_config_type, - .config_phymode = rt61pci_config_phymode, - .config_channel = rt61pci_config_channel, .config_mac_addr = rt61pci_config_mac_addr, .config_bssid = rt61pci_config_bssid, - .config_promisc = rt61pci_config_promisc, - .config_txpower = rt61pci_config_txpower, - .config_antenna = rt61pci_config_antenna, - .config_duration = rt61pci_config_duration, + .config_type = rt61pci_config_type, + .config_preamble = rt61pci_config_preamble, + .config = rt61pci_config, }; static const struct rt2x00_ops rt61pci_ops = { - .name = DRV_NAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, - .lib = &rt61pci_rt2x00_ops, - .hw = &rt61pci_mac80211_ops, + .name = DRV_NAME, + .rxd_size = RXD_DESC_SIZE, + .txd_size = TXD_DESC_SIZE, + .eeprom_size = EEPROM_SIZE, + .rf_size = RF_SIZE, + .lib = &rt61pci_rt2x00_ops, + .hw = &rt61pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt61pci_rt2x00debug, + .debugfs = &rt61pci_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; @@ -2388,7 +2539,7 @@ MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); MODULE_DESCRIPTION("Ralink RT61 PCI & PCMCIA Wireless LAN driver."); MODULE_SUPPORTED_DEVICE("Ralink RT2561, RT2561s & RT2661 " - "PCI & PCMCIA chipset based cards"); + "PCI & PCMCIA chipset based cards"); MODULE_DEVICE_TABLE(pci, rt61pci_device_table); MODULE_FIRMWARE(FIRMWARE_RT2561); MODULE_FIRMWARE(FIRMWARE_RT2561s); @@ -2400,10 +2551,8 @@ static struct pci_driver rt61pci_driver = { .id_table = rt61pci_device_table, .probe = rt2x00pci_probe, .remove = __devexit_p(rt2x00pci_remove), -#ifdef CONFIG_PM .suspend = rt2x00pci_suspend, .resume = rt2x00pci_resume, -#endif /* CONFIG_PM */ }; static int __init rt61pci_init(void) diff --git a/package/rt2x00/src/rt61pci.h b/package/rt2x00/src/rt61pci.h index 9dfd29356e..6721d7dd32 100644 --- a/package/rt2x00/src/rt61pci.h +++ b/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. @@ -982,9 +1059,44 @@ struct hw_pairwise_ta_entry { #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) /* @@ -1118,34 +1230,6 @@ struct hw_pairwise_ta_entry { #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. */ #define MCU_SLEEP 0x30 @@ -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) diff --git a/package/rt2x00/src/rt73usb.c b/package/rt2x00/src/rt73usb.c index c80bee1e5b..c0671c2e6e 100644 --- a/package/rt2x00/src/rt73usb.c +++ b/package/rt2x00/src/rt73usb.c @@ -29,16 +29,14 @@ */ #define DRV_NAME "rt73usb" +#include <linux/delay.h> +#include <linux/etherdevice.h> +#include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/version.h> -#include <linux/init.h> #include <linux/usb.h> -#include <linux/delay.h> -#include <linux/etherdevice.h> #include "rt2x00.h" -#include "rt2x00lib.h" #include "rt2x00usb.h" #include "rt73usb.h" @@ -55,45 +53,45 @@ * the access attempt is considered to have failed, * and we will print an error. */ -static inline void rt73usb_register_read( - const struct rt2x00_dev *rt2x00dev, - const u16 offset, u32 *value) +static inline void rt73usb_register_read(const struct rt2x00_dev *rt2x00dev, + const unsigned int offset, u32 *value) { __le32 reg; - rt2x00usb_vendor_request( - rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, - offset, 0x00, ®, sizeof(u32), REGISTER_TIMEOUT); + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, + USB_VENDOR_REQUEST_IN, offset, + ®, sizeof(u32), REGISTER_TIMEOUT); *value = le32_to_cpu(reg); } -static inline void rt73usb_register_multiread( - const struct rt2x00_dev *rt2x00dev, - const u16 offset, void *value, const u32 length) +static inline void rt73usb_register_multiread(const struct rt2x00_dev + *rt2x00dev, + const unsigned int offset, + void *value, const u32 length) { - rt2x00usb_vendor_request( - rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, - offset, 0x00, value, length, - REGISTER_TIMEOUT * (length / sizeof(u32))); + int timeout = REGISTER_TIMEOUT * (length / sizeof(u32)); + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, + USB_VENDOR_REQUEST_IN, offset, + value, length, timeout); } -static inline void rt73usb_register_write( - const struct rt2x00_dev *rt2x00dev, - const u16 offset, u32 value) +static inline void rt73usb_register_write(const struct rt2x00_dev *rt2x00dev, + const unsigned int offset, u32 value) { __le32 reg = cpu_to_le32(value); - rt2x00usb_vendor_request( - rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, - offset, 0x00, ®, sizeof(u32), REGISTER_TIMEOUT); + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, offset, + ®, sizeof(u32), REGISTER_TIMEOUT); } -static inline void rt73usb_register_multiwrite( - const struct rt2x00_dev *rt2x00dev, - const u16 offset, void *value, const u32 length) +static inline void rt73usb_register_multiwrite(const struct rt2x00_dev + *rt2x00dev, + const unsigned int offset, + void *value, const u32 length) { - rt2x00usb_vendor_request( - rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, - offset, 0x00, value, length, - REGISTER_TIMEOUT * (length / sizeof(u32))); + int timeout = REGISTER_TIMEOUT * (length / sizeof(u32)); + rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, offset, + value, length, timeout); } static u32 rt73usb_bbp_check(const struct rt2x00_dev *rt2x00dev) @@ -112,12 +110,12 @@ static u32 rt73usb_bbp_check(const struct rt2x00_dev *rt2x00dev) } static void rt73usb_bbp_write(const struct rt2x00_dev *rt2x00dev, - const u8 reg_id, const u8 value) + const unsigned int word, const u8 value) { u32 reg; /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt73usb_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { @@ -130,7 +128,7 @@ static void rt73usb_bbp_write(const struct rt2x00_dev *rt2x00dev, */ reg = 0; rt2x00_set_field32(®, PHY_CSR3_VALUE, value); - rt2x00_set_field32(®, PHY_CSR3_REGNUM, reg_id); + rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); @@ -138,12 +136,12 @@ static void rt73usb_bbp_write(const struct rt2x00_dev *rt2x00dev, } static void rt73usb_bbp_read(const struct rt2x00_dev *rt2x00dev, - const u8 reg_id, u8 *value) + const unsigned int word, u8 *value) { u32 reg; /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt73usb_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { @@ -154,15 +152,15 @@ static void rt73usb_bbp_read(const struct rt2x00_dev *rt2x00dev, /* * Write the request into the BBP. */ - reg =0; - rt2x00_set_field32(®, PHY_CSR3_REGNUM, reg_id); + reg = 0; + rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); rt73usb_register_write(rt2x00dev, PHY_CSR3, reg); /* - * Wait until the BBP becomes ready. + * Wait until the BBP becomes ready. */ reg = rt73usb_bbp_check(rt2x00dev); if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { @@ -175,11 +173,14 @@ static void rt73usb_bbp_read(const struct rt2x00_dev *rt2x00dev, } static void rt73usb_rf_write(const struct rt2x00_dev *rt2x00dev, - const u32 value) + const unsigned int word, const u32 value) { u32 reg; unsigned int i; + if (!word) + return; + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt73usb_register_read(rt2x00dev, PHY_CSR4, ®); if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY)) @@ -193,444 +194,370 @@ static void rt73usb_rf_write(const struct rt2x00_dev *rt2x00dev, rf_write: reg = 0; rt2x00_set_field32(®, PHY_CSR4_VALUE, value); - rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, 20); + + /* + * RF5225 and RF2527 contain 21 bits per RF register value, + * all others contain 20 bits. + */ + rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, + 20 + !!(rt2x00_rf(&rt2x00dev->chip, RF5225) || + rt2x00_rf(&rt2x00dev->chip, RF2527))); rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); rt73usb_register_write(rt2x00dev, PHY_CSR4, reg); + rt2x00_rf_write(rt2x00dev, word, value); } #ifdef CONFIG_RT2X00_LIB_DEBUGFS #define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) ) -static void rt73usb_read_csr(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) +static void rt73usb_read_csr(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 *data) { rt73usb_register_read(rt2x00dev, CSR_OFFSET(word), data); } -static void rt73usb_write_csr(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt73usb_register_write(rt2x00dev, CSR_OFFSET(word), *((u32*)data)); -} - -static void rt73usb_read_eeprom(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2x00_eeprom_read(rt2x00dev, word, data); -} - -static void rt73usb_write_eeprom(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt2x00_eeprom_write(rt2x00dev, word, *((u16*)data)); -} - -static void rt73usb_read_bbp(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) +static void rt73usb_write_csr(const struct rt2x00_dev *rt2x00dev, + const unsigned int word, u32 data) { - rt73usb_bbp_read(rt2x00dev, word, data); -} - -static void rt73usb_write_bbp(struct rt2x00_dev *rt2x00dev, - const unsigned long word, void *data) -{ - rt73usb_bbp_write(rt2x00dev, word, *((u8*)data)); + rt73usb_register_write(rt2x00dev, CSR_OFFSET(word), data); } static const struct rt2x00debug rt73usb_rt2x00debug = { - .owner = THIS_MODULE, - .reg_csr = { + .owner = THIS_MODULE, + .csr = { .read = rt73usb_read_csr, .write = rt73usb_write_csr, .word_size = sizeof(u32), .word_count = CSR_REG_SIZE / sizeof(u32), }, - .reg_eeprom = { - .read = rt73usb_read_eeprom, - .write = rt73usb_write_eeprom, + .eeprom = { + .read = rt2x00_eeprom_read, + .write = rt2x00_eeprom_write, .word_size = sizeof(u16), .word_count = EEPROM_SIZE / sizeof(u16), }, - .reg_bbp = { - .read = rt73usb_read_bbp, - .write = rt73usb_write_bbp, + .bbp = { + .read = rt73usb_bbp_read, + .write = rt73usb_bbp_write, .word_size = sizeof(u8), .word_count = BBP_SIZE / sizeof(u8), }, + .rf = { + .read = rt2x00_rf_read, + .write = rt73usb_rf_write, + .word_size = sizeof(u32), + .word_count = RF_SIZE / sizeof(u32), + }, }; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ /* * Configuration handlers. */ -static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) +static void rt73usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac) { - u32 reg[2]; - - memset(®, 0, sizeof(reg)); - memcpy(®, bssid, ETH_ALEN); + u32 tmp; - rt2x00_set_field32(®[1], MAC_CSR5_BSS_ID_MASK, 3); + tmp = le32_to_cpu(mac[1]); + rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); + mac[1] = cpu_to_le32(tmp); - /* - * The BSSID is passed to us as an array of bytes, - * that array is little endian, so no need for byte ordering. - */ - rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, ®, sizeof(reg)); + rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac, + (2 * sizeof(__le32))); } -static void rt73usb_config_promisc(struct rt2x00_dev *rt2x00dev, - const int promisc) +static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid) { - u32 reg; + u32 tmp; - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, !promisc); - rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); + tmp = le32_to_cpu(bssid[1]); + rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3); + bssid[1] = cpu_to_le32(tmp); + + rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, bssid, + (2 * sizeof(__le32))); } -static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, - const int type) +static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type, + const int tsf_sync) { u32 reg; + /* + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); /* - * Apply hardware packet filter. + * Enable synchronisation. */ - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); - - if (!is_monitor_present(&rt2x00dev->interface) && - (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_STA)) - rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, 1); - else - rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, 0); - - rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, 1); - if (is_monitor_present(&rt2x00dev->interface)) { - rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 0); - } else { - rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); - } - - rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_BORADCAST, 0); + rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync); + rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); +} - rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); +static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) +{ + u32 reg; /* - * Enable synchronisation. + * When in atomic context, reschedule and let rt2x00lib + * call this function again. */ - rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); - if (is_interface_present(&rt2x00dev->interface)) { - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); + if (in_atomic()) { + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work); + return; } - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - if (type == IEEE80211_IF_TYPE_IBSS || type == IEEE80211_IF_TYPE_AP) - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 2); - else if (type == IEEE80211_IF_TYPE_STA) - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 1); - else if (is_monitor_present(&rt2x00dev->interface) && - !is_interface_present(&rt2x00dev->interface)) - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 0); + rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout); + rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); - rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®); + rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, + !!short_preamble); + rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); +} + +static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev, + const int basic_rate_mask) +{ + rt73usb_register_write(rt2x00dev, TXRX_CSR5, basic_rate_mask); } static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev, - const int value, const int channel, const int txpower) + struct rf_channel *rf, const int txpower) { - u8 reg = 0; - u32 rf1 = rt2x00dev->rf1; - u32 rf2 = value; - u32 rf3 = rt2x00dev->rf3; - u32 rf4 = 0; + u8 r3; + u8 r94; + u8 smart; - if (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527)) - rf2 |= 0x00004000; - - if (rt2x00_rf(&rt2x00dev->chip, RF5225)) { - if (channel <= 14) - rf3 = 0x00068455; - else if (channel >= 36 && channel <= 48) - rf3 = 0x0009be55; - else if (channel >= 52 && channel <= 64) - rf3 = 0x0009ae55; - else if (channel >= 100 && channel <= 112) - rf3 = 0x000bae55; - else - rf3 = 0x000bbe55; - } + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); + rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); - if (channel < 14) { - if (channel & 0x01) - rf4 = 0x000fea0b; - else - rf4 = 0x000fea1f; - } else if (channel == 14) { - rf4 = 0x000fea13; - } else { - switch (channel) { - case 36: - case 56: - case 116: - case 136: - rf4 = 0x000fea23; - break; - case 40: - case 60: - case 100: - case 120: - case 140: - rf4 = 0x000fea03; - break; - case 44: - case 64: - case 104: - case 124: - rf4 = 0x000fea0b; - break; - case 48: - case 108: - case 128: - rf4 = 0x000fea13; - break; - case 52: - case 112: - case 132: - rf4 = 0x000fea1b; - break; - case 149: - rf4 = 0x000fea1f; - break; - case 153: - rf4 = 0x000fea27; - break; - case 157: - rf4 = 0x000fea07; - break; - case 161: - rf4 = 0x000fea0f; - break; - case 165: - rf4 = 0x000fea17; - break; - } - } + smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || + rt2x00_rf(&rt2x00dev->chip, RF2527)); - if (rt2x00_rf(&rt2x00dev->chip, RF2527) || - rt2x00_rf(&rt2x00dev->chip, RF5225)) - rf4 |= 0x00010000; + rt73usb_bbp_read(rt2x00dev, 3, &r3); + rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); + rt73usb_bbp_write(rt2x00dev, 3, r3); - /* - * Set TXpower. - */ - rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); + r94 = 6; + if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94)) + r94 += txpower - MAX_TXPOWER; + else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94)) + r94 += txpower; + rt73usb_bbp_write(rt2x00dev, 94, r94); + + rt73usb_rf_write(rt2x00dev, 1, rf->rf1); + rt73usb_rf_write(rt2x00dev, 2, rf->rf2); + rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt73usb_rf_write(rt2x00dev, 4, rf->rf4); + + rt73usb_rf_write(rt2x00dev, 1, rf->rf1); + rt73usb_rf_write(rt2x00dev, 2, rf->rf2); + rt73usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); + rt73usb_rf_write(rt2x00dev, 4, rf->rf4); + + rt73usb_rf_write(rt2x00dev, 1, rf->rf1); + rt73usb_rf_write(rt2x00dev, 2, rf->rf2); + rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); + rt73usb_rf_write(rt2x00dev, 4, rf->rf4); + + udelay(10); +} - /* - * Set Frequency offset. - */ - rt2x00_set_field32(&rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); +static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev, + const int txpower) +{ + struct rf_channel rf; - rt73usb_bbp_read(rt2x00dev, 3, ®); - if (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527)) - reg &= ~0x01; - else - reg |= 0x01; - rt73usb_bbp_write(rt2x00dev, 3, reg); + rt2x00_rf_read(rt2x00dev, 1, &rf.rf1); + rt2x00_rf_read(rt2x00dev, 2, &rf.rf2); + rt2x00_rf_read(rt2x00dev, 3, &rf.rf3); + rt2x00_rf_read(rt2x00dev, 4, &rf.rf4); - rt73usb_rf_write(rt2x00dev, rf1); - rt73usb_rf_write(rt2x00dev, rf2); - rt73usb_rf_write(rt2x00dev, rf3 & ~0x00000004); - rt73usb_rf_write(rt2x00dev, rf4); + rt73usb_config_channel(rt2x00dev, &rf, txpower); +} + +static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, + const int antenna_tx, + const int antenna_rx) +{ + u8 r3; + u8 r4; + u8 r77; - rt73usb_rf_write(rt2x00dev, rf1); - rt73usb_rf_write(rt2x00dev, rf2); - rt73usb_rf_write(rt2x00dev, rf3 | 0x00000004); - rt73usb_rf_write(rt2x00dev, rf4); + rt73usb_bbp_read(rt2x00dev, 3, &r3); + rt73usb_bbp_read(rt2x00dev, 4, &r4); + rt73usb_bbp_read(rt2x00dev, 77, &r77); - rt73usb_rf_write(rt2x00dev, rf1); - rt73usb_rf_write(rt2x00dev, rf2); - rt73usb_rf_write(rt2x00dev, rf3 & ~0x00000004); - rt73usb_rf_write(rt2x00dev, rf4); + rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); - msleep(1); + switch (antenna_rx) { + case ANTENNA_SW_DIVERSITY: + case ANTENNA_HW_DIVERSITY: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, + !!(rt2x00dev->curr_hwmode != HWMODE_A)); + break; + case ANTENNA_A: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - /* - * Update rf fields - */ - rt2x00dev->rf1 = rf1; - rt2x00dev->rf2 = rf2; - rt2x00dev->rf3 = rf3; - rt2x00dev->rf4 = rf4; - rt2x00dev->tx_power = txpower; + if (rt2x00dev->curr_hwmode == HWMODE_A) + rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); + else + rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); + break; + case ANTENNA_B: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); + + if (rt2x00dev->curr_hwmode == HWMODE_A) + rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); + else + rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); + break; + } + + rt73usb_bbp_write(rt2x00dev, 77, r77); + rt73usb_bbp_write(rt2x00dev, 3, r3); + rt73usb_bbp_write(rt2x00dev, 4, r4); } -static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev, - const int txpower) +static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev, + const int antenna_tx, + const int antenna_rx) { - rt2x00_set_field32(&rt2x00dev->rf3, RF3_TXPOWER, - TXPOWER_TO_DEV(txpower)); - - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf1); - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf2); - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf3 & ~0x00000004); - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf4); - - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf1); - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf2); - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf3 | 0x00000004); - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf4); - - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf1); - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf2); - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf3 & ~0x00000004); - rt73usb_rf_write(rt2x00dev, rt2x00dev->rf4); + u8 r3; + u8 r4; + u8 r77; + + rt73usb_bbp_read(rt2x00dev, 3, &r3); + rt73usb_bbp_read(rt2x00dev, 4, &r4); + rt73usb_bbp_read(rt2x00dev, 77, &r77); + + rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); + rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, + !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); + + switch (antenna_rx) { + case ANTENNA_SW_DIVERSITY: + case ANTENNA_HW_DIVERSITY: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); + break; + case ANTENNA_A: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); + rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); + break; + case ANTENNA_B: + rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); + rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); + break; + } + + rt73usb_bbp_write(rt2x00dev, 77, r77); + rt73usb_bbp_write(rt2x00dev, 3, r3); + rt73usb_bbp_write(rt2x00dev, 4, r4); } +struct antenna_sel { + u8 word; + /* + * value[0] -> non-LNA + * value[1] -> LNA + */ + u8 value[2]; +}; + +static const struct antenna_sel antenna_sel_a[] = { + { 96, { 0x58, 0x78 } }, + { 104, { 0x38, 0x48 } }, + { 75, { 0xfe, 0x80 } }, + { 86, { 0xfe, 0x80 } }, + { 88, { 0xfe, 0x80 } }, + { 35, { 0x60, 0x60 } }, + { 97, { 0x58, 0x58 } }, + { 98, { 0x58, 0x58 } }, +}; + +static const struct antenna_sel antenna_sel_bg[] = { + { 96, { 0x48, 0x68 } }, + { 104, { 0x2c, 0x3c } }, + { 75, { 0xfe, 0x80 } }, + { 86, { 0xfe, 0x80 } }, + { 88, { 0xfe, 0x80 } }, + { 35, { 0x50, 0x50 } }, + { 97, { 0x48, 0x48 } }, + { 98, { 0x48, 0x48 } }, +}; + static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev, - const int antenna_tx, const int antenna_rx) + const int antenna_tx, const int antenna_rx) { + const struct antenna_sel *sel; + unsigned int lna; + unsigned int i; u32 reg; - u8 r3; - u8 r4; - u8 r77; rt73usb_register_read(rt2x00dev, PHY_CSR0, ®); if (rt2x00dev->curr_hwmode == HWMODE_A) { - if (test_bit(CONFIG_EXTERNAL_LNA, &rt2x00dev->flags)) { - rt73usb_bbp_write(rt2x00dev, 17, 0x38); - rt73usb_bbp_write(rt2x00dev, 96, 0x78); - rt73usb_bbp_write(rt2x00dev, 104, 0x48); - rt73usb_bbp_write(rt2x00dev, 75, 0x80); - rt73usb_bbp_write(rt2x00dev, 86, 0x80); - rt73usb_bbp_write(rt2x00dev, 88, 0x80); - } else { - rt73usb_bbp_write(rt2x00dev, 17, 0x28); - rt73usb_bbp_write(rt2x00dev, 96, 0x58); - rt73usb_bbp_write(rt2x00dev, 104, 0x38); - rt73usb_bbp_write(rt2x00dev, 75, 0xfe); - rt73usb_bbp_write(rt2x00dev, 86, 0xfe); - rt73usb_bbp_write(rt2x00dev, 88, 0xfe); - } - rt73usb_bbp_write(rt2x00dev, 35, 0x60); - rt73usb_bbp_write(rt2x00dev, 97, 0x58); - rt73usb_bbp_write(rt2x00dev, 98, 0x58); + sel = antenna_sel_a; + lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, 0); rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, 1); } else { - if (test_bit(CONFIG_EXTERNAL_LNA, &rt2x00dev->flags)) { - rt73usb_bbp_write(rt2x00dev, 17, 0x30); - rt73usb_bbp_write(rt2x00dev, 96, 0x68); - rt73usb_bbp_write(rt2x00dev, 104, 0x3c); - rt73usb_bbp_write(rt2x00dev, 75, 0x80); - rt73usb_bbp_write(rt2x00dev, 86, 0x80); - rt73usb_bbp_write(rt2x00dev, 88, 0x80); - } else { - rt73usb_bbp_write(rt2x00dev, 17, 0x20); - rt73usb_bbp_write(rt2x00dev, 96, 0x48); - rt73usb_bbp_write(rt2x00dev, 104, 0x2c); - rt73usb_bbp_write(rt2x00dev, 75, 0xfe); - rt73usb_bbp_write(rt2x00dev, 86, 0xfe); - rt73usb_bbp_write(rt2x00dev, 88, 0xfe); - } - rt73usb_bbp_write(rt2x00dev, 35, 0x50); - rt73usb_bbp_write(rt2x00dev, 97, 0x48); - rt73usb_bbp_write(rt2x00dev, 98, 0x48); + sel = antenna_sel_bg; + lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, 1); rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, 0); } - rt73usb_register_write(rt2x00dev, PHY_CSR0, reg); - - rt73usb_bbp_read(rt2x00dev, 3, &r3); - rt73usb_bbp_read(rt2x00dev, 4, &r4); - rt73usb_bbp_read(rt2x00dev, 77, &r77); + for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) + rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); - rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); + rt73usb_register_write(rt2x00dev, PHY_CSR0, reg); if (rt2x00_rf(&rt2x00dev->chip, RF5226) || - rt2x00_rf(&rt2x00dev->chip, RF5225)) { - if (antenna_rx == ANTENNA_DIVERSITY) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); - if (rt2x00dev->curr_hwmode != HWMODE_A) - rt2x00_set_field8(&r4, BBP_R4_RX_BG_MODE, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); - } else if (antenna_rx == ANTENNA_A) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); - if (rt2x00dev->curr_hwmode == HWMODE_A) - rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); - else - rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); - rt73usb_bbp_write(rt2x00dev, 77, r77); - } else if (antenna_rx == ANTENNA_B) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); - if (rt2x00dev->curr_hwmode == HWMODE_A) - rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); - else - rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); - rt73usb_bbp_write(rt2x00dev, 77, r77); - } - } else if (rt2x00_rf(&rt2x00dev->chip, RF2528) || - rt2x00_rf(&rt2x00dev->chip, RF2527)) { - if (antenna_rx == ANTENNA_DIVERSITY) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); - rt2x00_set_field8(&r4, BBP_R4_RX_BG_MODE, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); - } else if (antenna_rx == ANTENNA_A) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_BG_MODE, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); - rt2x00_set_field8(&r77, BBP_R77_PAIR, 3); - rt73usb_bbp_write(rt2x00dev, 77, r77); - } else if (antenna_rx == ANTENNA_B) { - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_BG_MODE, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); - rt2x00_set_field8(&r77, BBP_R77_PAIR, 0); - } - } - - rt73usb_bbp_write(rt2x00dev, 3, r3); - rt73usb_bbp_write(rt2x00dev, 4, r4); + rt2x00_rf(&rt2x00dev->chip, RF5225)) + rt73usb_config_antenna_5x(rt2x00dev, antenna_tx, antenna_rx); + else if (rt2x00_rf(&rt2x00dev->chip, RF2528) || + rt2x00_rf(&rt2x00dev->chip, RF2527)) + rt73usb_config_antenna_2x(rt2x00dev, antenna_tx, antenna_rx); } static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, - const int short_slot_time, const int beacon_int) + struct rt2x00lib_conf *libconf) { u32 reg; rt73usb_register_read(rt2x00dev, MAC_CSR9, ®); - rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, - short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME); + rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, libconf->slot_time); rt73usb_register_write(rt2x00dev, MAC_CSR9, reg); rt73usb_register_read(rt2x00dev, MAC_CSR8, ®); - rt2x00_set_field32(®, MAC_CSR8_SIFS, SIFS); + rt2x00_set_field32(®, MAC_CSR8_SIFS, libconf->sifs); rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); - rt2x00_set_field32(®, MAC_CSR8_EIFS, EIFS); + rt2x00_set_field32(®, MAC_CSR8_EIFS, libconf->eifs); rt73usb_register_write(rt2x00dev, MAC_CSR8, reg); rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); @@ -642,72 +569,27 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, beacon_int * 16); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, + libconf->conf->beacon_int * 16); rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); } -static void rt73usb_config_rate(struct rt2x00_dev *rt2x00dev, const int rate) -{ - struct ieee80211_conf *conf = &rt2x00dev->hw->conf; - u32 reg; - u32 value; - u32 preamble; - - preamble = DEVICE_GET_RATE_FIELD(rate, PREAMBLE) - ? SHORT_PREAMBLE : PREAMBLE; - - reg = DEVICE_GET_RATE_FIELD(rate, RATEMASK) & DEV_BASIC_RATE; - - rt73usb_register_write(rt2x00dev, TXRX_CSR5, reg); - - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); - value = ((conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) ? - SHORT_DIFS : DIFS) + - PLCP + preamble + get_duration(ACK_SIZE, 10); - rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, value); - rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); - - rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®); - if (preamble == SHORT_PREAMBLE) - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, 1); - else - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, 0); - rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); -} - -static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev, - const int phymode) -{ - struct ieee80211_hw_mode *mode; - struct ieee80211_rate *rate; - - if (phymode == MODE_IEEE80211A) - rt2x00dev->curr_hwmode = HWMODE_A; - else if (phymode == MODE_IEEE80211B) - rt2x00dev->curr_hwmode = HWMODE_B; - else - rt2x00dev->curr_hwmode = HWMODE_G; - - mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode]; - rate = &mode->rates[mode->num_rates - 1]; - - rt73usb_config_rate(rt2x00dev, rate->val2); -} - -static void rt73usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *addr) +static void rt73usb_config(struct rt2x00_dev *rt2x00dev, + const unsigned int flags, + struct rt2x00lib_conf *libconf) { - u32 reg[2]; - - memset(®, 0, sizeof(reg)); - memcpy(®, addr, ETH_ALEN); - - rt2x00_set_field32(®[1], MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); - - /* - * The MAC address is passed to us as an array of bytes, - * that array is little endian, so no need for byte ordering. - */ - rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, ®, sizeof(reg)); + if (flags & CONFIG_UPDATE_PHYMODE) + rt73usb_config_phymode(rt2x00dev, libconf->basic_rates); + if (flags & CONFIG_UPDATE_CHANNEL) + rt73usb_config_channel(rt2x00dev, &libconf->rf, + libconf->conf->power_level); + if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL)) + rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level); + if (flags & CONFIG_UPDATE_ANTENNA) + rt73usb_config_antenna(rt2x00dev, libconf->conf->antenna_sel_tx, + libconf->conf->antenna_sel_rx); + if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) + rt73usb_config_duration(rt2x00dev, libconf); } /* @@ -724,15 +606,14 @@ static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1); if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) - rt2x00_set_field16( - &rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 1); + rt2x00_set_field16(&rt2x00dev->led_reg, + MCU_LEDCS_LINK_A_STATUS, 1); else - rt2x00_set_field16( - &rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 1); + rt2x00_set_field16(&rt2x00dev->led_reg, + MCU_LEDCS_LINK_BG_STATUS, 1); - rt2x00usb_vendor_request( - rt2x00dev, USB_LED_CONTROL, USB_VENDOR_REQUEST_OUT, - 0x00, rt2x00dev->led_reg, NULL, 0, REGISTER_TIMEOUT); + rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000, + rt2x00dev->led_reg, REGISTER_TIMEOUT); } static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev) @@ -741,9 +622,8 @@ static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 0); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 0); - rt2x00usb_vendor_request( - rt2x00dev, USB_LED_CONTROL, USB_VENDOR_REQUEST_OUT, - 0x00, rt2x00dev->led_reg, NULL, 0, REGISTER_TIMEOUT); + rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000, + rt2x00dev->led_reg, REGISTER_TIMEOUT); } static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi) @@ -772,18 +652,41 @@ static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi) else led = 5; - rt2x00usb_vendor_request( - rt2x00dev, USB_LED_CONTROL, USB_VENDOR_REQUEST_OUT, - led, rt2x00dev->led_reg, NULL, 0, REGISTER_TIMEOUT); + rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, led, + rt2x00dev->led_reg, REGISTER_TIMEOUT); } /* * Link tuning */ +static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev) +{ + u32 reg; + + /* + * Update FCS error count from register. + */ + rt73usb_register_read(rt2x00dev, STA_CSR0, ®); + rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); + + /* + * Update False CCA count from register. + */ + rt73usb_register_read(rt2x00dev, STA_CSR1, ®); + reg = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); + rt2x00dev->link.false_cca = + rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); +} + +static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev) +{ + rt73usb_bbp_write(rt2x00dev, 17, 0x20); + rt2x00dev->link.vgc_level = 0x20; +} + static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) { int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); - u32 reg; u8 r17; u8 up_bound; u8 low_bound; @@ -802,7 +705,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) low_bound = 0x28; up_bound = 0x48; - if (test_bit(CONFIG_EXTERNAL_LNA, &rt2x00dev->flags)) { + if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { low_bound += 0x10; up_bound += 0x10; } @@ -818,7 +721,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) up_bound = 0x1c; } - if (test_bit(CONFIG_EXTERNAL_LNA, &rt2x00dev->flags)) { + if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { low_bound += 0x14; up_bound += 0x10; } @@ -878,30 +781,23 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. */ - rt73usb_register_read(rt2x00dev, STA_CSR1, ®); - reg = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); - rt2x00dev->link.false_cca = - rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); - if (rt2x00dev->link.false_cca > 512 && r17 < up_bound) { r17 += 4; if (r17 > up_bound) r17 = up_bound; rt73usb_bbp_write(rt2x00dev, 17, r17); - rt2x00dev->rx_status.noise = r17; } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) { r17 -= 4; if (r17 < low_bound) r17 = low_bound; rt73usb_bbp_write(rt2x00dev, 17, r17); - rt2x00dev->rx_status.noise = r17; } } /* * Firmware name function. */ -static char *rt73usb_get_fw_name(struct rt2x00_dev *rt2x00dev) +static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) { return FIRMWARE_RT2571; } @@ -910,14 +806,15 @@ static char *rt73usb_get_fw_name(struct rt2x00_dev *rt2x00dev) * Initialization functions. */ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, - const size_t len) + const size_t len) { unsigned int i; int status; u32 reg; - char buf[64]; char *ptr = data; + char *cache; int buflen; + int timeout; /* * Wait for stable hardware. @@ -936,23 +833,40 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, /* * Write firmware to device. + * We setup a seperate cache for this action, + * since we are going to write larger chunks of data + * then normally used cache size. */ - for (i = 0; i < len; i += sizeof(buf)) { - buflen = min(len - i, sizeof(buf)); - memcpy(buf, ptr, buflen); - rt73usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE + i, - buf, buflen); + cache = kmalloc(CSR_CACHE_SIZE_FIRMWARE, GFP_KERNEL); + if (!cache) { + ERROR(rt2x00dev, "Failed to allocate firmware cache.\n"); + return -ENOMEM; + } + + for (i = 0; i < len; i += CSR_CACHE_SIZE_FIRMWARE) { + buflen = min_t(int, len - i, CSR_CACHE_SIZE_FIRMWARE); + timeout = REGISTER_TIMEOUT * (buflen / sizeof(u32)); + + memcpy(cache, ptr, buflen); + + rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, + FIRMWARE_IMAGE_BASE + i, 0x0000, + cache, buflen, timeout); + ptr += buflen; } + kfree(cache); + /* * Send firmware request to device to load firmware, * we need to specify a long timeout time. */ - status = rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE, - USB_VENDOR_REQUEST_OUT, 0x00, USB_MODE_FIRMWARE, - NULL, 0, REGISTER_TIMEOUT_FIRMWARE); - if (status < 0) { + status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, + 0x0000, USB_MODE_FIRMWARE, + REGISTER_TIMEOUT_FIRMWARE); + if (status < 0) { ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); return status; } @@ -966,31 +880,80 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; - if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) - return -EBUSY; - - rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718); - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); + rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0); rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); - rt73usb_register_write(rt2x00dev, TXRX_CSR1, 0x9eaa9eaf); - rt73usb_register_write(rt2x00dev, TXRX_CSR2, 0x8a8b8c8d); - rt73usb_register_write(rt2x00dev, TXRX_CSR3, 0x00858687); + rt73usb_register_read(rt2x00dev, TXRX_CSR1, ®); + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */ + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1, 30); /* Rssi */ + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2, 42); /* OFDM Rate */ + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3, 30); /* Rssi */ + rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3_VALID, 1); + rt73usb_register_write(rt2x00dev, TXRX_CSR1, reg); - rt73usb_register_write(rt2x00dev, TXRX_CSR7, 0x2e31353b); - rt73usb_register_write(rt2x00dev, TXRX_CSR8, 0x2a2a2a2c); + /* + * CCK TXD BBP registers + */ + rt73usb_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0, 13); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1, 12); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2, 11); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3, 10); + rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3_VALID, 1); + rt73usb_register_write(rt2x00dev, TXRX_CSR2, reg); + + /* + * OFDM TXD BBP registers + */ + rt73usb_register_read(rt2x00dev, TXRX_CSR3, ®); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0, 7); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1, 6); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1_VALID, 1); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2, 5); + rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2_VALID, 1); + rt73usb_register_write(rt2x00dev, TXRX_CSR3, reg); + + rt73usb_register_read(rt2x00dev, TXRX_CSR7, ®); + rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_6MBS, 59); + rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_9MBS, 53); + rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_12MBS, 49); + rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_18MBS, 46); + rt73usb_register_write(rt2x00dev, TXRX_CSR7, reg); + + rt73usb_register_read(rt2x00dev, TXRX_CSR8, ®); + rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_24MBS, 44); + rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_36MBS, 42); + rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_48MBS, 42); + rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_54MBS, 42); + rt73usb_register_write(rt2x00dev, TXRX_CSR8, reg); rt73usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); - rt73usb_register_write(rt2x00dev, MAC_CSR6, 0x00000fff); + rt73usb_register_read(rt2x00dev, MAC_CSR6, ®); + rt2x00_set_field32(®, MAC_CSR6_MAX_FRAME_UNIT, 0xfff); + rt73usb_register_write(rt2x00dev, MAC_CSR6, reg); + + rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718); + + if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) + return -EBUSY; rt73usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00); + /* + * Invalidate all Shared Keys (SEC_CSR0), + * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) + */ rt73usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000); rt73usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000); rt73usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); @@ -1031,7 +994,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) /* * Reset MAC and BBP registers. */ - reg = 0; + rt73usb_register_read(rt2x00dev, MAC_CSR1, ®); rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); rt73usb_register_write(rt2x00dev, MAC_CSR1, reg); @@ -1069,7 +1032,6 @@ static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev) continue_csr_init: rt73usb_bbp_write(rt2x00dev, 3, 0x80); rt73usb_bbp_write(rt2x00dev, 15, 0x30); - rt73usb_bbp_write(rt2x00dev, 17, 0x20); rt73usb_bbp_write(rt2x00dev, 21, 0xc8); rt73usb_bbp_write(rt2x00dev, 22, 0x38); rt73usb_bbp_write(rt2x00dev, 23, 0x06); @@ -1102,7 +1064,7 @@ continue_csr_init: reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n", - reg_id, value); + reg_id, value); rt73usb_bbp_write(rt2x00dev, reg_id, value); } } @@ -1115,13 +1077,13 @@ continue_csr_init: * Device state switch handlers. */ static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { u32 reg; rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - state == STATE_RADIO_RX_OFF); + state == STATE_RADIO_RX_OFF); rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); } @@ -1163,8 +1125,7 @@ static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev) rt2x00usb_disable_radio(rt2x00dev); } -static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) +static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) { u32 reg; unsigned int i; @@ -1173,21 +1134,11 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, put_to_sleep = (state != STATE_AWAKE); - if (!put_to_sleep) - rt2x00usb_vendor_request(rt2x00dev, - USB_DEVICE_MODE, USB_VENDOR_REQUEST_OUT, - 0x00, USB_MODE_WAKEUP, NULL, 0, REGISTER_TIMEOUT); - rt73usb_register_read(rt2x00dev, MAC_CSR12, ®); rt2x00_set_field32(®, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep); rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep); rt73usb_register_write(rt2x00dev, MAC_CSR12, reg); - if (put_to_sleep) - rt2x00usb_vendor_request(rt2x00dev, - USB_DEVICE_MODE, USB_VENDOR_REQUEST_OUT, - 0x00, USB_MODE_SLEEP, NULL, 0, REGISTER_TIMEOUT); - /* * Device is not guaranteed to be in the requested state yet. * We must wait until the register indicates that the @@ -1195,43 +1146,43 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, */ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { rt73usb_register_read(rt2x00dev, MAC_CSR12, ®); - current_state = rt2x00_get_field32(reg, - MAC_CSR12_BBP_CURRENT_STATE); + current_state = + rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); if (current_state == !put_to_sleep) return 0; msleep(10); } NOTICE(rt2x00dev, "Device failed to enter state %d, " - "current device state %d.\n", !put_to_sleep, current_state); + "current device state %d.\n", !put_to_sleep, current_state); return -EBUSY; } static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) + enum dev_state state) { int retval = 0; switch (state) { - case STATE_RADIO_ON: - retval = rt73usb_enable_radio(rt2x00dev); + case STATE_RADIO_ON: + retval = rt73usb_enable_radio(rt2x00dev); break; - case STATE_RADIO_OFF: - rt73usb_disable_radio(rt2x00dev); + case STATE_RADIO_OFF: + rt73usb_disable_radio(rt2x00dev); break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_OFF: - rt73usb_toggle_rx(rt2x00dev, state); + case STATE_RADIO_RX_ON: + case STATE_RADIO_RX_OFF: + rt73usb_toggle_rx(rt2x00dev, state); break; - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: - case STATE_AWAKE: - retval = rt73usb_set_state(rt2x00dev, state); + case STATE_DEEP_SLEEP: + case STATE_SLEEP: + case STATE_STANDBY: + case STATE_AWAKE: + retval = rt73usb_set_state(rt2x00dev, state); break; - default: - retval = -ENOTSUPP; + default: + retval = -ENOTSUPP; break; } @@ -1242,9 +1193,11 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, * TX descriptor initialization */ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry, struct data_desc *txd, - struct data_entry_desc *desc, struct ieee80211_hdr *ieee80211hdr, - unsigned int length, struct ieee80211_tx_control *control) + struct data_desc *txd, + struct txdata_entry_desc *desc, + struct ieee80211_hdr *ieee80211hdr, + unsigned int length, + struct ieee80211_tx_control *control) { u32 word; @@ -1253,9 +1206,9 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue); - rt2x00_set_field32(&word, TXD_W1_AIFSN, entry->ring->tx_params.aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->ring->tx_params.cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->ring->tx_params.cw_max); + rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1); rt2x00_desc_write(txd, 1, word); @@ -1269,38 +1222,66 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_read(txd, 5, &word); rt2x00_set_field32(&word, TXD_W5_TX_POWER, - TXPOWER_TO_DEV(control->power_level)); + TXPOWER_TO_DEV(control->power_level)); rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); rt2x00_desc_read(txd, 0, &word); + rt2x00_set_field32(&word, TXD_W0_BURST, + test_bit(ENTRY_TXD_BURST, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &entry->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_REQ_ACK, &entry->flags)); + !(control->flags & IEEE80211_TXCTL_NO_ACK)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &entry->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &entry->flags)); + test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); - rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, 0); + rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, + !!(control->flags & + IEEE80211_TXCTL_LONG_RETRY_LIMIT)); rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0); rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length); + rt2x00_set_field32(&word, TXD_W0_BURST2, + test_bit(ENTRY_TXD_BURST, &desc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } +static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, + struct sk_buff *skb) +{ + int length; + + /* + * The length _must_ be a multiple of 4, + * but it must _not_ be a multiple of the USB packet size. + */ + length = roundup(skb->len, 4); + length += (4 * !(length % rt2x00dev->usb_maxpacket)); + + return length; +} + /* * TX data initialization */ -static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue) +static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, + unsigned int queue) { u32 reg; if (queue != IEEE80211_TX_QUEUE_BEACON) return; + /* + * For Wi-Fi faily generated beacons between participating stations. + * Set TBTT phase adaptive adjustment step to 8us (default 16us) + */ + rt73usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); + rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); @@ -1314,26 +1295,26 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, int queue) static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) { u16 eeprom; - char offset; - char lna; + u8 offset; + u8 lna; lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA); switch (lna) { - case 3: - offset = 90; + case 3: + offset = 90; break; - case 2: - offset = 74; + case 2: + offset = 74; break; - case 1: - offset = 64; + case 1: + offset = 64; break; - default: - return 0; + default: + return 0; } if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) { - if (test_bit(CONFIG_EXTERNAL_LNA, &rt2x00dev->flags)) { + if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { if (lna == 3 || lna == 2) offset += 10; } else { @@ -1346,7 +1327,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); offset -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1); } else { - if (test_bit(CONFIG_EXTERNAL_LNA, &rt2x00dev->flags)) + if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) offset += 14; rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); @@ -1356,68 +1337,56 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset; } -static int rt73usb_fill_rxdone(struct data_entry *entry, - int *signal, int *rssi, int *ofdm) +static void rt73usb_fill_rxdone(struct data_entry *entry, + struct rxdata_entry_desc *desc) { - struct data_desc *rxd = (struct data_desc*)entry->skb->data; + struct data_desc *rxd = (struct data_desc *)entry->skb->data; u32 word0; u32 word1; rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); - /* - * TODO: Don't we need to keep statistics - * updated about these errors? - */ - if (rt2x00_get_field32(word0, RXD_W0_CRC) || - rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR)) - return -EINVAL; + desc->flags = 0; + if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) + desc->flags |= RX_FLAG_FAILED_FCS_CRC; /* * Obtain the status about this packet. */ - *signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - *rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1); - *ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1); + desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); /* * Pull the skb to clear the descriptor area. */ skb_pull(entry->skb, entry->ring->desc_size); - return rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + return; } /* - * Device initialization functions. + * Device probe functions. */ -static int rt73usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) { u16 word; u8 *mac; - char value; - - /* - * Allocate the eeprom memory, check the eeprom width - * and copy the entire eeprom into this allocated memory. - */ - rt2x00dev->eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); - if (!rt2x00dev->eeprom) - return -ENOMEM; + s8 value; - rt2x00usb_vendor_request( - rt2x00dev, USB_EEPROM_READ, USB_VENDOR_REQUEST_IN, - EEPROM_BASE, 0x00, rt2x00dev->eeprom, EEPROM_SIZE, - REGISTER_TIMEOUT * (EEPROM_SIZE / sizeof(u16))); + rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); /* * Start validation of the data that has been read. */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { + DECLARE_MAC_BUF(macbuf); + random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: " MAC_FMT "\n", MAC_ARG(mac)); + EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac)); } rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); @@ -1451,7 +1420,7 @@ static int rt73usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_3, 0); rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_4, 0); rt2x00_set_field16(&word, EEPROM_LED_LED_MODE, - LED_MODE_DEFAULT); + LED_MODE_DEFAULT); rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word); EEPROM(rt2x00dev, "Led: 0x%04x\n", word); } @@ -1517,6 +1486,11 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt73usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2571, value, reg); + if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) { + ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); + return -ENODEV; + } + if (!rt2x00_rf(&rt2x00dev->chip, RF5226) && !rt2x00_rf(&rt2x00dev->chip, RF2528) && !rt2x00_rf(&rt2x00dev->chip, RF5225) && @@ -1528,10 +1502,10 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Identify default antenna configuration. */ - rt2x00dev->hw->conf.antenna_sel_tx = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_TX_DEFAULT); - rt2x00dev->hw->conf.antenna_sel_rx = rt2x00_get_field16(eeprom, - EEPROM_ANTENNA_RX_DEFAULT); + rt2x00dev->hw->conf.antenna_sel_tx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); + rt2x00dev->hw->conf.antenna_sel_rx = + rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); /* * Read the Frame type. @@ -1543,16 +1517,17 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) * Read frequency offset. */ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); - rt2x00dev->freq_offset = - rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); + rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); /* * Read external LNA informations. */ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) - __set_bit(CONFIG_EXTERNAL_LNA, &rt2x00dev->flags); + if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) { + __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); + __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); + } /* * Store led settings, for correct led behaviour. @@ -1560,60 +1535,171 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE, - rt2x00dev->led_mode); + rt2x00dev->led_mode); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_0)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_GPIO_0)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_1)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_GPIO_1)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_2)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_GPIO_2)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_3)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_GPIO_3)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_4)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_GPIO_4)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT)); + rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_RDY_G)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_RDY_G)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_RDY_A)); + rt2x00_get_field16(eeprom, + EEPROM_LED_POLARITY_RDY_A)); return 0; } -static const struct { - unsigned int chip; - u32 val[3]; -} rf_vals[] = { - { RF5226, { 0x00002c0c, 0x00068255 } }, - { RF2528, { 0x00002c0c, 0x00068255 } }, - { RF5225, { 0x00002ccc, 0x00000000 } }, - { RF2527, { 0x00002ccc, 0x00068455 } }, +/* + * RF value list for RF2528 + * Supports: 2.4 GHz + */ +static const struct rf_channel rf_vals_bg_2528[] = { + { 1, 0x00002c0c, 0x00000786, 0x00068255, 0x000fea0b }, + { 2, 0x00002c0c, 0x00000786, 0x00068255, 0x000fea1f }, + { 3, 0x00002c0c, 0x0000078a, 0x00068255, 0x000fea0b }, + { 4, 0x00002c0c, 0x0000078a, 0x00068255, 0x000fea1f }, + { 5, 0x00002c0c, 0x0000078e, 0x00068255, 0x000fea0b }, + { 6, 0x00002c0c, 0x0000078e, 0x00068255, 0x000fea1f }, + { 7, 0x00002c0c, 0x00000792, 0x00068255, 0x000fea0b }, + { 8, 0x00002c0c, 0x00000792, 0x00068255, 0x000fea1f }, + { 9, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea0b }, + { 10, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea1f }, + { 11, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea0b }, + { 12, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea1f }, + { 13, 0x00002c0c, 0x0000079e, 0x00068255, 0x000fea0b }, + { 14, 0x00002c0c, 0x000007a2, 0x00068255, 0x000fea13 }, }; /* - * RF value list for RF5226, RF2528, RF5225 & RF2527 - * Supports: 2.4 GHz + * RF value list for RF5226 + * Supports: 2.4 GHz & 5.2 GHz */ -static const u32 rf_vals_bg[] = { - 0x00000786, 0x00000786, 0x0000078a, 0x0000078a, 0x0000078e, - 0x0000078e, 0x00000792, 0x00000792, 0x00000796, 0x00000796, - 0x0000079a, 0x0000079a, 0x0000079e, 0x000007a2 +static const struct rf_channel rf_vals_5226[] = { + { 1, 0x00002c0c, 0x00000786, 0x00068255, 0x000fea0b }, + { 2, 0x00002c0c, 0x00000786, 0x00068255, 0x000fea1f }, + { 3, 0x00002c0c, 0x0000078a, 0x00068255, 0x000fea0b }, + { 4, 0x00002c0c, 0x0000078a, 0x00068255, 0x000fea1f }, + { 5, 0x00002c0c, 0x0000078e, 0x00068255, 0x000fea0b }, + { 6, 0x00002c0c, 0x0000078e, 0x00068255, 0x000fea1f }, + { 7, 0x00002c0c, 0x00000792, 0x00068255, 0x000fea0b }, + { 8, 0x00002c0c, 0x00000792, 0x00068255, 0x000fea1f }, + { 9, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea0b }, + { 10, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea1f }, + { 11, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea0b }, + { 12, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea1f }, + { 13, 0x00002c0c, 0x0000079e, 0x00068255, 0x000fea0b }, + { 14, 0x00002c0c, 0x000007a2, 0x00068255, 0x000fea13 }, + + /* 802.11 UNI / HyperLan 2 */ + { 36, 0x00002c0c, 0x0000099a, 0x00098255, 0x000fea23 }, + { 40, 0x00002c0c, 0x000009a2, 0x00098255, 0x000fea03 }, + { 44, 0x00002c0c, 0x000009a6, 0x00098255, 0x000fea0b }, + { 48, 0x00002c0c, 0x000009aa, 0x00098255, 0x000fea13 }, + { 52, 0x00002c0c, 0x000009ae, 0x00098255, 0x000fea1b }, + { 56, 0x00002c0c, 0x000009b2, 0x00098255, 0x000fea23 }, + { 60, 0x00002c0c, 0x000009ba, 0x00098255, 0x000fea03 }, + { 64, 0x00002c0c, 0x000009be, 0x00098255, 0x000fea0b }, + + /* 802.11 HyperLan 2 */ + { 100, 0x00002c0c, 0x00000a2a, 0x000b8255, 0x000fea03 }, + { 104, 0x00002c0c, 0x00000a2e, 0x000b8255, 0x000fea0b }, + { 108, 0x00002c0c, 0x00000a32, 0x000b8255, 0x000fea13 }, + { 112, 0x00002c0c, 0x00000a36, 0x000b8255, 0x000fea1b }, + { 116, 0x00002c0c, 0x00000a3a, 0x000b8255, 0x000fea23 }, + { 120, 0x00002c0c, 0x00000a82, 0x000b8255, 0x000fea03 }, + { 124, 0x00002c0c, 0x00000a86, 0x000b8255, 0x000fea0b }, + { 128, 0x00002c0c, 0x00000a8a, 0x000b8255, 0x000fea13 }, + { 132, 0x00002c0c, 0x00000a8e, 0x000b8255, 0x000fea1b }, + { 136, 0x00002c0c, 0x00000a92, 0x000b8255, 0x000fea23 }, + + /* 802.11 UNII */ + { 140, 0x00002c0c, 0x00000a9a, 0x000b8255, 0x000fea03 }, + { 149, 0x00002c0c, 0x00000aa2, 0x000b8255, 0x000fea1f }, + { 153, 0x00002c0c, 0x00000aa6, 0x000b8255, 0x000fea27 }, + { 157, 0x00002c0c, 0x00000aae, 0x000b8255, 0x000fea07 }, + { 161, 0x00002c0c, 0x00000ab2, 0x000b8255, 0x000fea0f }, + { 165, 0x00002c0c, 0x00000ab6, 0x000b8255, 0x000fea17 }, + + /* MMAC(Japan)J52 ch 34,38,42,46 */ + { 34, 0x00002c0c, 0x0008099a, 0x000da255, 0x000d3a0b }, + { 38, 0x00002c0c, 0x0008099e, 0x000da255, 0x000d3a13 }, + { 42, 0x00002c0c, 0x000809a2, 0x000da255, 0x000d3a1b }, + { 46, 0x00002c0c, 0x000809a6, 0x000da255, 0x000d3a23 }, }; /* - * RF value list for RF5226 & RF5225 (supplement to vals_bg) - * Supports: 5.2 GHz + * RF value list for RF5225 & RF2527 + * Supports: 2.4 GHz & 5.2 GHz */ -static const u32 rf_vals_a_5x[] = { - 0x0000099a, 0x000009a2, 0x000009a6, 0x000009aa, 0x000009ae, - 0x000009b2, 0x000009ba, 0x000009be, 0x00000a2a, 0x00000a2e, - 0x00000a32, 0x00000a36, 0x00000a3a, 0x00000a82, 0x00000a86, - 0x00000a8a, 0x00000a8e, 0x00000a92, 0x00000a9a, 0x00000aa2, - 0x00000aa6, 0x00000aae, 0x00000ab2, 0x00000ab6 +static const struct rf_channel rf_vals_5225_2527[] = { + { 1, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b }, + { 2, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f }, + { 3, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b }, + { 4, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f }, + { 5, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b }, + { 6, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f }, + { 7, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b }, + { 8, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f }, + { 9, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b }, + { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f }, + { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b }, + { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f }, + { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b }, + { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 }, + + /* 802.11 UNI / HyperLan 2 */ + { 36, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa23 }, + { 40, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa03 }, + { 44, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa0b }, + { 48, 0x00002ccc, 0x000049aa, 0x0009be55, 0x000ffa13 }, + { 52, 0x00002ccc, 0x000049ae, 0x0009ae55, 0x000ffa1b }, + { 56, 0x00002ccc, 0x000049b2, 0x0009ae55, 0x000ffa23 }, + { 60, 0x00002ccc, 0x000049ba, 0x0009ae55, 0x000ffa03 }, + { 64, 0x00002ccc, 0x000049be, 0x0009ae55, 0x000ffa0b }, + + /* 802.11 HyperLan 2 */ + { 100, 0x00002ccc, 0x00004a2a, 0x000bae55, 0x000ffa03 }, + { 104, 0x00002ccc, 0x00004a2e, 0x000bae55, 0x000ffa0b }, + { 108, 0x00002ccc, 0x00004a32, 0x000bae55, 0x000ffa13 }, + { 112, 0x00002ccc, 0x00004a36, 0x000bae55, 0x000ffa1b }, + { 116, 0x00002ccc, 0x00004a3a, 0x000bbe55, 0x000ffa23 }, + { 120, 0x00002ccc, 0x00004a82, 0x000bbe55, 0x000ffa03 }, + { 124, 0x00002ccc, 0x00004a86, 0x000bbe55, 0x000ffa0b }, + { 128, 0x00002ccc, 0x00004a8a, 0x000bbe55, 0x000ffa13 }, + { 132, 0x00002ccc, 0x00004a8e, 0x000bbe55, 0x000ffa1b }, + { 136, 0x00002ccc, 0x00004a92, 0x000bbe55, 0x000ffa23 }, + + /* 802.11 UNII */ + { 140, 0x00002ccc, 0x00004a9a, 0x000bbe55, 0x000ffa03 }, + { 149, 0x00002ccc, 0x00004aa2, 0x000bbe55, 0x000ffa1f }, + { 153, 0x00002ccc, 0x00004aa6, 0x000bbe55, 0x000ffa27 }, + { 157, 0x00002ccc, 0x00004aae, 0x000bbe55, 0x000ffa07 }, + { 161, 0x00002ccc, 0x00004ab2, 0x000bbe55, 0x000ffa0f }, + { 165, 0x00002ccc, 0x00004ab6, 0x000bbe55, 0x000ffa17 }, + + /* MMAC(Japan)J52 ch 34,38,42,46 */ + { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa0b }, + { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000ffa13 }, + { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa1b }, + { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa23 }, }; -static void rt73usb_init_hw_mode(struct rt2x00_dev *rt2x00dev) + +static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; u8 *txpower; @@ -1622,31 +1708,18 @@ static void rt73usb_init_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Initialize all hw fields. */ - rt2x00dev->hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_WEP_INCLUDE_IV | - IEEE80211_HW_DATA_NULLFUNC_ACK | - IEEE80211_HW_NO_TKIP_WMM_HWACCEL | - IEEE80211_HW_MONITOR_DURING_OPER | - IEEE80211_HW_NO_PROBE_FILTERING; + rt2x00dev->hw->flags = + IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; + rt2x00dev->hw->max_signal = MAX_SIGNAL; rt2x00dev->hw->max_rssi = MAX_RX_SSI; - rt2x00dev->hw->max_noise = MAX_RX_NOISE; rt2x00dev->hw->queues = 5; SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); - - /* - * Set device specific, but channel independent RF values. - */ - for (i = 0; i < ARRAY_SIZE(rf_vals); i++) { - if (rt2x00_rf(&rt2x00dev->chip, rf_vals[i].chip)) { - rt2x00dev->rf1 = rf_vals[i].val[0]; - rt2x00dev->rf3 = rf_vals[i].val[1]; - } - } + rt2x00_eeprom_addr(rt2x00dev, + EEPROM_MAC_ADDR_0)); /* * Convert tx_power array in eeprom. @@ -1660,35 +1733,44 @@ static void rt73usb_init_hw_mode(struct rt2x00_dev *rt2x00dev) */ spec->num_modes = 2; spec->num_rates = 12; - spec->num_channels = 14; spec->tx_power_a = NULL; spec->tx_power_bg = txpower; spec->tx_power_default = DEFAULT_TXPOWER; - spec->chan_val_a = NULL; - spec->chan_val_bg = rf_vals_bg; + + if (rt2x00_rf(&rt2x00dev->chip, RF2528)) { + spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528); + spec->channels = rf_vals_bg_2528; + } else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) { + spec->num_channels = ARRAY_SIZE(rf_vals_5226); + spec->channels = rf_vals_5226; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) { + spec->num_channels = 14; + spec->channels = rf_vals_5225_2527; + } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) { + spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527); + spec->channels = rf_vals_5225_2527; + } if (rt2x00_rf(&rt2x00dev->chip, RF5225) || rt2x00_rf(&rt2x00dev->chip, RF5226)) { spec->num_modes = 3; - spec->num_channels += 24; txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); for (i = 0; i < 14; i++) txpower[i] = TXPOWER_FROM_DEV(txpower[i]); spec->tx_power_a = txpower; - spec->chan_val_a = rf_vals_a_5x; } } -static int rt73usb_init_hw(struct rt2x00_dev *rt2x00dev) +static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; /* * Allocate eeprom data. */ - retval = rt73usb_alloc_eeprom(rt2x00dev); + retval = rt73usb_validate_eeprom(rt2x00dev); if (retval) return retval; @@ -1699,12 +1781,12 @@ static int rt73usb_init_hw(struct rt2x00_dev *rt2x00dev) /* * Initialize hw specifications. */ - rt73usb_init_hw_mode(rt2x00dev); + rt73usb_probe_hw_mode(rt2x00dev); /* * This device requires firmware */ - __set_bit(FIRMWARE_REQUIRED, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1717,28 +1799,85 @@ static int rt73usb_init_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static int rt73usb_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) +static void rt73usb_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, + struct dev_addr_list *mc_list) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct interface *intf = &rt2x00dev->interface; u32 reg; /* - * Update FCS error count from register. - * The dot11ACKFailureCount, dot11RTSFailureCount and - * dot11RTSSuccessCount are updated in interrupt time. + * Mask off any flags we are going to ignore from + * the total_flags field. */ - rt73usb_register_read(rt2x00dev, STA_CSR0, ®); - rt2x00dev->low_level_stats.dot11FCSErrorCount += - rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); + *total_flags &= + FIF_ALLMULTI | + FIF_FCSFAIL | + FIF_PLCPFAIL | + FIF_CONTROL | + FIF_OTHER_BSS | + FIF_PROMISC_IN_BSS; - memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats)); + /* + * Apply some rules to the filters: + * - Some filters imply different filters to be set. + * - Some things we can't filter out at all. + * - Some filters are set based on interface type. + */ + if (mc_count) + *total_flags |= FIF_ALLMULTI; + if (*total_flags & FIF_OTHER_BSS || + *total_flags & FIF_PROMISC_IN_BSS) + *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; + if (is_interface_type(intf, IEEE80211_IF_TYPE_AP)) + *total_flags |= FIF_PROMISC_IN_BSS; - return 0; + /* + * Check if there is any work left for us. + */ + if (intf->filter == *total_flags) + return; + intf->filter = *total_flags; + + /* + * When in atomic context, reschedule and let rt2x00lib + * call this function again. + */ + if (in_atomic()) { + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); + return; + } + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, + !(*total_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, + !(*total_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, + !(*total_flags & FIF_CONTROL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, + !(*total_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, + !(*total_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, + !(*total_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); + rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); + rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); } static int rt73usb_set_retry_limit(struct ieee80211_hw *hw, - u32 short_retry, u32 long_retry) + u32 short_retry, u32 long_retry) { struct rt2x00_dev *rt2x00dev = hw->priv; u32 reg; @@ -1751,6 +1890,13 @@ static int rt73usb_set_retry_limit(struct ieee80211_hw *hw, return 0; } +#if 0 +/* + * Mac80211 demands get_tsf must be atomic. + * This is not possible for rt73usb since all register access + * functions require sleeping. Untill mac80211 no longer needs + * get_tsf to be atomic, this function should be disabled. + */ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -1758,12 +1904,15 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) u32 reg; rt73usb_register_read(rt2x00dev, TXRX_CSR13, ®); - tsf = (u64)rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; + tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; rt73usb_register_read(rt2x00dev, TXRX_CSR12, ®); tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER); return tsf; } +#else +#define rt73usb_get_tsf NULL +#endif static void rt73usb_reset_tsf(struct ieee80211_hw *hw) { @@ -1773,54 +1922,95 @@ static void rt73usb_reset_tsf(struct ieee80211_hw *hw) rt73usb_register_write(rt2x00dev, TXRX_CSR13, 0); } +static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ieee80211_tx_control *control) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + int timeout; + + /* + * 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; + + /* + * First we create the beacon. + */ + skb_push(skb, TXD_DESC_SIZE); + memset(skb->data, 0, TXD_DESC_SIZE); + + rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data, + (struct ieee80211_hdr *)(skb->data + + TXD_DESC_SIZE), + skb->len - TXD_DESC_SIZE, control); + + /* + * Write entire beacon with descriptor to register, + * and kick the beacon generator. + */ + timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32)); + rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, + USB_VENDOR_REQUEST_OUT, + HW_BEACON_BASE0, 0x0000, + skb->data, skb->len, timeout); + rt73usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + + return 0; +} + static const struct ieee80211_ops rt73usb_mac80211_ops = { - .tx = rt2x00lib_tx, - .reset = rt2x00lib_reset, - .add_interface = rt2x00lib_add_interface, - .remove_interface = rt2x00lib_remove_interface, - .config = rt2x00lib_config, - .config_interface = rt2x00lib_config_interface, - .set_multicast_list = rt2x00lib_set_multicast_list, - .get_stats = rt73usb_get_stats, + .tx = rt2x00mac_tx, + .start = rt2x00mac_start, + .stop = rt2x00mac_stop, + .add_interface = rt2x00mac_add_interface, + .remove_interface = rt2x00mac_remove_interface, + .config = rt2x00mac_config, + .config_interface = rt2x00mac_config_interface, + .configure_filter = rt73usb_configure_filter, + .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt73usb_set_retry_limit, - .conf_tx = rt2x00lib_conf_tx, - .get_tx_stats = rt2x00lib_get_tx_stats, + .erp_ie_changed = rt2x00mac_erp_ie_changed, + .conf_tx = rt2x00mac_conf_tx, + .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt73usb_get_tsf, .reset_tsf = rt73usb_reset_tsf, - .beacon_update = rt2x00usb_beacon_update, + .beacon_update = rt73usb_beacon_update, }; static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { - .init_hw = rt73usb_init_hw, - .get_fw_name = rt73usb_get_fw_name, + .probe_hw = rt73usb_probe_hw, + .get_firmware_name = rt73usb_get_firmware_name, .load_firmware = rt73usb_load_firmware, .initialize = rt2x00usb_initialize, .uninitialize = rt2x00usb_uninitialize, .set_device_state = rt73usb_set_device_state, + .link_stats = rt73usb_link_stats, + .reset_tuner = rt73usb_reset_tuner, .link_tuner = rt73usb_link_tuner, .write_tx_desc = rt73usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, + .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, - .config_type = rt73usb_config_type, - .config_phymode = rt73usb_config_phymode, - .config_channel = rt73usb_config_channel, .config_mac_addr = rt73usb_config_mac_addr, .config_bssid = rt73usb_config_bssid, - .config_promisc = rt73usb_config_promisc, - .config_txpower = rt73usb_config_txpower, - .config_antenna = rt73usb_config_antenna, - .config_duration = rt73usb_config_duration, + .config_type = rt73usb_config_type, + .config_preamble = rt73usb_config_preamble, + .config = rt73usb_config, }; static const struct rt2x00_ops rt73usb_ops = { - .name = DRV_NAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, - .lib = &rt73usb_rt2x00_ops, - .hw = &rt73usb_mac80211_ops, + .name = DRV_NAME, + .rxd_size = RXD_DESC_SIZE, + .txd_size = TXD_DESC_SIZE, + .eeprom_size = EEPROM_SIZE, + .rf_size = RF_SIZE, + .lib = &rt73usb_rt2x00_ops, + .hw = &rt73usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt73usb_rt2x00debug, + .debugfs = &rt73usb_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; @@ -1839,8 +2029,11 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) }, /* Billionton */ { USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) }, + /* Buffalo */ + { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, /* CNet */ { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) }, @@ -1864,6 +2057,7 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) }, /* MSI */ { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) }, /* Ralink */ @@ -1872,6 +2066,9 @@ static struct usb_device_id rt73usb_device_table[] = { /* Qcom */ { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x18e8, 0x6238), USB_DEVICE_DATA(&rt73usb_ops) }, + /* Senao */ + { USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) }, /* Sitecom */ { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) }, @@ -1896,10 +2093,8 @@ static struct usb_driver rt73usb_driver = { .id_table = rt73usb_device_table, .probe = rt2x00usb_probe, .disconnect = rt2x00usb_disconnect, -#ifdef CONFIG_PM .suspend = rt2x00usb_suspend, .resume = rt2x00usb_resume, -#endif /* CONFIG_PM */ }; static int __init rt73usb_init(void) diff --git a/package/rt2x00/src/rt73usb.h b/package/rt2x00/src/rt73usb.h index 159240f1cb..f0951519f7 100644 --- a/package/rt2x00/src/rt73usb.h +++ b/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. @@ -636,9 +695,44 @@ struct hw_pairwise_ta_entry { #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) /* @@ -764,34 +858,6 @@ struct hw_pairwise_ta_entry { #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. */ #define TXD_DESC_SIZE ( 6 * sizeof(struct data_desc) ) @@ -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) |