diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00')
47 files changed, 13684 insertions, 5330 deletions
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 6f383cd684b..006b8bcb2e3 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -1,6 +1,6 @@  menuconfig RT2X00  	tristate "Ralink driver support" -	depends on MAC80211 +	depends on MAC80211 && HAS_DMA  	---help---  	  This will enable the support for the Ralink drivers,  	  developed in the rt2x00 project <http://rt2x00.serialmonkey.com>. @@ -20,6 +20,7 @@ if RT2X00  config RT2400PCI  	tristate "Ralink rt2400 (PCI/PCMCIA) support"  	depends on PCI +	select RT2X00_LIB_MMIO  	select RT2X00_LIB_PCI  	select EEPROM_93CX6  	---help--- @@ -31,6 +32,7 @@ config RT2400PCI  config RT2500PCI  	tristate "Ralink rt2500 (PCI/PCMCIA) support"  	depends on PCI +	select RT2X00_LIB_MMIO  	select RT2X00_LIB_PCI  	select EEPROM_93CX6  	---help--- @@ -43,6 +45,7 @@ config RT61PCI  	tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support"  	depends on PCI  	select RT2X00_LIB_PCI +	select RT2X00_LIB_MMIO  	select RT2X00_LIB_FIRMWARE  	select RT2X00_LIB_CRYPTO  	select CRC_ITU_T @@ -55,11 +58,11 @@ config RT61PCI  config RT2800PCI  	tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" -	depends on PCI || RALINK_RT288X || RALINK_RT305X +	depends on PCI  	select RT2800_LIB -	select RT2X00_LIB_PCI if PCI -	select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X -	select RT2X00_LIB_HT +	select RT2800_LIB_MMIO +	select RT2X00_LIB_MMIO +	select RT2X00_LIB_PCI  	select RT2X00_LIB_FIRMWARE  	select RT2X00_LIB_CRYPTO  	select CRC_CCITT @@ -74,29 +77,37 @@ config RT2800PCI  if RT2800PCI  config RT2800PCI_RT33XX -	bool "rt2800pci - Include support for rt33xx devices (EXPERIMENTAL)" -	depends on EXPERIMENTAL -	default n +	bool "rt2800pci - Include support for rt33xx devices" +	default y  	---help---  	  This adds support for rt33xx wireless chipset family to the  	  rt2800pci driver.  	  Supported chips: RT3390 -	  Support for these devices is non-functional at the moment and is -	  intended for testers and developers. -  config RT2800PCI_RT35XX  	bool "rt2800pci - Include support for rt35xx devices (EXPERIMENTAL)" -	depends on EXPERIMENTAL -	default n +	default y  	---help---  	  This adds support for rt35xx wireless chipset family to the  	  rt2800pci driver.  	  Supported chips: RT3060, RT3062, RT3562, RT3592 -	  Support for these devices is non-functional at the moment and is -	  intended for testers and developers. +config RT2800PCI_RT53XX +       bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)" +       default y +       ---help--- +         This adds support for rt53xx wireless chipset family to the +         rt2800pci driver. +         Supported chips: RT5390 + +config RT2800PCI_RT3290 +       bool "rt2800pci - Include support for rt3290 devices (EXPERIMENTAL)" +       default y +       ---help--- +         This adds support for rt3290 wireless chipset family to the +         rt2800pci driver. +         Supported chips: RT3290  endif  config RT2500USB @@ -128,7 +139,6 @@ config RT2800USB  	depends on USB  	select RT2800_LIB  	select RT2X00_LIB_USB -	select RT2X00_LIB_HT  	select RT2X00_LIB_FIRMWARE  	select RT2X00_LIB_CRYPTO  	select CRC_CCITT @@ -141,28 +151,40 @@ config RT2800USB  if RT2800USB  config RT2800USB_RT33XX -	bool "rt2800usb - Include support for rt33xx devices (EXPERIMENTAL)" -	depends on EXPERIMENTAL -	default n +	bool "rt2800usb - Include support for rt33xx devices" +	default y  	---help---  	  This adds support for rt33xx wireless chipset family to the  	  rt2800usb driver.  	  Supported chips: RT3370 -	  Support for these devices is non-functional at the moment and is -	  intended for testers and developers. -  config RT2800USB_RT35XX  	bool "rt2800usb - Include support for rt35xx devices (EXPERIMENTAL)" -	depends on EXPERIMENTAL -	default n +	default y  	---help---  	  This adds support for rt35xx wireless chipset family to the  	  rt2800usb driver.  	  Supported chips: RT3572 -	  Support for these devices is non-functional at the moment and is -	  intended for testers and developers. +config RT2800USB_RT3573 +	bool "rt2800usb - Include support for rt3573 devices (EXPERIMENTAL)" +	---help--- +	  This enables support for RT3573 chipset based wireless USB devices +	  in the rt2800usb driver. + +config RT2800USB_RT53XX +       bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)" +       ---help--- +         This adds support for rt53xx wireless chipset family to the +         rt2800usb driver. +         Supported chips: RT5370 + +config RT2800USB_RT55XX +       bool "rt2800usb - Include support for rt55xx devices (EXPERIMENTAL)" +       ---help--- +         This adds support for rt55xx wireless chipset family to the +         rt2800usb driver. +         Supported chips: RT5572  config RT2800USB_UNKNOWN  	bool "rt2800usb - Include support for unknown (USB) devices" @@ -177,9 +199,33 @@ config RT2800USB_UNKNOWN  endif +config RT2800SOC +	tristate "Ralink WiSoC support" +	depends on SOC_RT288X || SOC_RT305X +	select RT2X00_LIB_SOC +	select RT2X00_LIB_MMIO +	select RT2X00_LIB_CRYPTO +	select RT2X00_LIB_FIRMWARE +	select RT2800_LIB +	select RT2800_LIB_MMIO +	---help--- +	  This adds support for Ralink WiSoC devices. +	  Supported chips: RT2880, RT3050, RT3052, RT3350, RT3352. + +	  When compiled as a module, this driver will be called rt2800soc. + +  config RT2800_LIB  	tristate +config RT2800_LIB_MMIO +	tristate +	select RT2X00_LIB_MMIO +	select RT2800_LIB + +config RT2X00_LIB_MMIO +	tristate +  config RT2X00_LIB_PCI  	tristate  	select RT2X00_LIB @@ -194,9 +240,7 @@ config RT2X00_LIB_USB  config RT2X00_LIB  	tristate - -config RT2X00_LIB_HT -	boolean +	select AVERAGE  config RT2X00_LIB_FIRMWARE  	boolean diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index 97133985829..24a66015a49 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile @@ -7,13 +7,14 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS)	+= rt2x00debug.o  rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO)	+= rt2x00crypto.o  rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE)	+= rt2x00firmware.o  rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS)	+= rt2x00leds.o -rt2x00lib-$(CONFIG_RT2X00_LIB_HT)	+= rt2x00ht.o  obj-$(CONFIG_RT2X00_LIB)		+= rt2x00lib.o +obj-$(CONFIG_RT2X00_LIB_MMIO)		+= rt2x00mmio.o  obj-$(CONFIG_RT2X00_LIB_PCI)		+= rt2x00pci.o  obj-$(CONFIG_RT2X00_LIB_SOC)		+= rt2x00soc.o  obj-$(CONFIG_RT2X00_LIB_USB)		+= rt2x00usb.o  obj-$(CONFIG_RT2800_LIB)		+= rt2800lib.o +obj-$(CONFIG_RT2800_LIB_MMIO)		+= rt2800mmio.o  obj-$(CONFIG_RT2400PCI)			+= rt2400pci.o  obj-$(CONFIG_RT2500PCI)			+= rt2500pci.o  obj-$(CONFIG_RT61PCI)			+= rt61pci.o @@ -21,3 +22,4 @@ obj-$(CONFIG_RT2800PCI)			+= rt2800pci.o  obj-$(CONFIG_RT2500USB)			+= rt2500usb.o  obj-$(CONFIG_RT73USB)			+= rt73usb.o  obj-$(CONFIG_RT2800USB)			+= rt2800usb.o +obj-$(CONFIG_RT2800SOC)			+= rt2800soc.o diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 9ec6691adf0..4ccfef5094e 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -26,7 +24,6 @@  #include <linux/delay.h>  #include <linux/etherdevice.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> @@ -34,26 +31,27 @@  #include <linux/slab.h>  #include "rt2x00.h" +#include "rt2x00mmio.h"  #include "rt2x00pci.h"  #include "rt2400pci.h"  /*   * Register access.   * All access to the CSR registers will go through the methods - * rt2x00pci_register_read and rt2x00pci_register_write. + * rt2x00mmio_register_read and rt2x00mmio_register_write.   * BBP and RF register require indirect register access,   * and use the CSR registers BBPCSR and RFCSR to achieve this.   * These indirect registers work with busy bits,   * and we will try maximal REGISTER_BUSY_COUNT times to access   * the register while taking a REGISTER_BUSY_DELAY us delay - * between each attampt. When the busy bit is still set at that time, + * between each attempt. When the busy bit is still set at that time,   * the access attempt is considered to have failed,   * and we will print an error.   */  #define WAIT_FOR_BBP(__dev, __reg) \ -	rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) +	rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))  #define WAIT_FOR_RF(__dev, __reg) \ -	rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) +	rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))  static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,  				const unsigned int word, const u8 value) @@ -73,7 +71,7 @@ static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, BBPCSR_BUSY, 1);  		rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); -		rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); +		rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);  	}  	mutex_unlock(&rt2x00dev->csr_mutex); @@ -100,7 +98,7 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, BBPCSR_BUSY, 1);  		rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); -		rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); +		rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);  		WAIT_FOR_BBP(rt2x00dev, ®);  	} @@ -128,7 +126,7 @@ static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, RFCSR_IF_SELECT, 0);  		rt2x00_set_field32(®, RFCSR_BUSY, 1); -		rt2x00pci_register_write(rt2x00dev, RFCSR, reg); +		rt2x00mmio_register_write(rt2x00dev, RFCSR, reg);  		rt2x00_rf_write(rt2x00dev, word, value);  	} @@ -140,7 +138,7 @@ static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom)  	struct rt2x00_dev *rt2x00dev = eeprom->data;  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, CSR21, ®); +	rt2x00mmio_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); @@ -162,15 +160,15 @@ static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom)  	rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT,  			   !!eeprom->reg_chip_select); -	rt2x00pci_register_write(rt2x00dev, CSR21, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR21, reg);  }  #ifdef CONFIG_RT2X00_LIB_DEBUGFS  static const struct rt2x00debug rt2400pci_rt2x00debug = {  	.owner	= THIS_MODULE,  	.csr	= { -		.read		= rt2x00pci_register_read, -		.write		= rt2x00pci_register_write, +		.read		= rt2x00mmio_register_read, +		.write		= rt2x00mmio_register_write,  		.flags		= RT2X00DEBUGFS_OFFSET,  		.word_base	= CSR_REG_BASE,  		.word_size	= sizeof(u32), @@ -204,8 +202,8 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); -	return rt2x00_get_field32(reg, GPIOCSR_BIT0); +	rt2x00mmio_register_read(rt2x00dev, GPIOCSR, ®); +	return rt2x00_get_field32(reg, GPIOCSR_VAL0);  }  #ifdef CONFIG_RT2X00_LIB_LEDS @@ -217,14 +215,14 @@ static void rt2400pci_brightness_set(struct led_classdev *led_cdev,  	unsigned int enabled = brightness != LED_OFF;  	u32 reg; -	rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); +	rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, ®);  	if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)  		rt2x00_set_field32(®, LEDCSR_LINK, enabled);  	else if (led->type == LED_TYPE_ACTIVITY)  		rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled); -	rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); +	rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);  }  static int rt2400pci_blink_set(struct led_classdev *led_cdev, @@ -235,10 +233,10 @@ static int rt2400pci_blink_set(struct led_classdev *led_cdev,  	    container_of(led_cdev, struct rt2x00_led, led_dev);  	u32 reg; -	rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); +	rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, ®);  	rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on);  	rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off); -	rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); +	rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);  	return 0;  } @@ -268,7 +266,7 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,  	 * Note that the version error will always be dropped  	 * since there is no filter for it at this time.  	 */ -	rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®);  	rt2x00_set_field32(®, RXCSR0_DROP_CRC,  			   !(filter_flags & FIF_FCSFAIL));  	rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, @@ -281,7 +279,7 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev,  			   !(filter_flags & FIF_PROMISC_IN_BSS) &&  			   !rt2x00dev->intf_ap_count);  	rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); -	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); +	rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);  }  static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, @@ -297,27 +295,26 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,  		 * Enable beacon config  		 */  		bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); -		rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); +		rt2x00mmio_register_read(rt2x00dev, BCNCSR1, ®);  		rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); -		rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); +		rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);  		/*  		 * Enable synchronisation.  		 */ -		rt2x00pci_register_read(rt2x00dev, CSR14, ®); -		rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); +		rt2x00mmio_register_read(rt2x00dev, CSR14, ®);  		rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); -		rt2x00_set_field32(®, CSR14_TBCN, 1); -		rt2x00pci_register_write(rt2x00dev, CSR14, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR14, reg);  	}  	if (flags & CONFIG_UPDATE_MAC) -		rt2x00pci_register_multiwrite(rt2x00dev, CSR3, -					      conf->mac, sizeof(conf->mac)); +		rt2x00mmio_register_multiwrite(rt2x00dev, CSR3, +					       conf->mac, sizeof(conf->mac));  	if (flags & CONFIG_UPDATE_BSSID) -		rt2x00pci_register_multiwrite(rt2x00dev, CSR5, -					      conf->bssid, sizeof(conf->bssid)); +		rt2x00mmio_register_multiwrite(rt2x00dev, CSR5, +					       conf->bssid, +					       sizeof(conf->bssid));  }  static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, @@ -333,68 +330,68 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,  	if (changed & BSS_CHANGED_ERP_PREAMBLE) {  		preamble_mask = erp->short_preamble << 3; -		rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); +		rt2x00mmio_register_read(rt2x00dev, TXCSR1, ®);  		rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x1ff);  		rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0x13a);  		rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);  		rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); -		rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); +		rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg); -		rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); +		rt2x00mmio_register_read(rt2x00dev, ARCSR2, ®);  		rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00);  		rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04);  		rt2x00_set_field32(®, ARCSR2_LENGTH,  				   GET_DURATION(ACK_SIZE, 10)); -		rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); +		rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg); -		rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); +		rt2x00mmio_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); +		rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg); -		rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); +		rt2x00mmio_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); +		rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg); -		rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); +		rt2x00mmio_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); +		rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg);  	}  	if (changed & BSS_CHANGED_BASIC_RATES) -		rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); +		rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);  	if (changed & BSS_CHANGED_ERP_SLOT) { -		rt2x00pci_register_read(rt2x00dev, CSR11, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR11, ®);  		rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); -		rt2x00pci_register_write(rt2x00dev, CSR11, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR11, reg); -		rt2x00pci_register_read(rt2x00dev, CSR18, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR18, ®);  		rt2x00_set_field32(®, CSR18_SIFS, erp->sifs);  		rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); -		rt2x00pci_register_write(rt2x00dev, CSR18, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR18, reg); -		rt2x00pci_register_read(rt2x00dev, CSR19, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR19, ®);  		rt2x00_set_field32(®, CSR19_DIFS, erp->difs);  		rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); -		rt2x00pci_register_write(rt2x00dev, CSR19, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR19, reg);  	}  	if (changed & BSS_CHANGED_BEACON_INT) { -		rt2x00pci_register_read(rt2x00dev, CSR12, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR12, ®);  		rt2x00_set_field32(®, CSR12_BEACON_INTERVAL,  				   erp->beacon_int * 16);  		rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION,  				   erp->beacon_int * 16); -		rt2x00pci_register_write(rt2x00dev, CSR12, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR12, reg);  	}  } @@ -498,7 +495,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,  	/*  	 * Clear false CRC during channel switch.  	 */ -	rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1); +	rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);  }  static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower) @@ -511,12 +508,12 @@ static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,  {  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, CSR11, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR11, ®);  	rt2x00_set_field32(®, CSR11_LONG_RETRY,  			   libconf->conf->long_frame_max_tx_count);  	rt2x00_set_field32(®, CSR11_SHORT_RETRY,  			   libconf->conf->short_frame_max_tx_count); -	rt2x00pci_register_write(rt2x00dev, CSR11, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR11, reg);  }  static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, @@ -528,7 +525,7 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,  	u32 reg;  	if (state == STATE_SLEEP) { -		rt2x00pci_register_read(rt2x00dev, CSR20, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR20, ®);  		rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN,  				   (rt2x00dev->beacon_int - 20) * 16);  		rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, @@ -536,14 +533,14 @@ static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,  		/* We must first disable autowake before it can be enabled */  		rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); -		rt2x00pci_register_write(rt2x00dev, CSR20, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR20, reg);  		rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); -		rt2x00pci_register_write(rt2x00dev, CSR20, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR20, reg);  	} else { -		rt2x00pci_register_read(rt2x00dev, CSR20, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR20, ®);  		rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); -		rt2x00pci_register_write(rt2x00dev, CSR20, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR20, reg);  	}  	rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); @@ -569,10 +566,10 @@ static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,  {  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, CSR11, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR11, ®);  	rt2x00_set_field32(®, CSR11_CWMIN, cw_min);  	rt2x00_set_field32(®, CSR11_CWMAX, cw_max); -	rt2x00pci_register_write(rt2x00dev, CSR11, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR11, reg);  }  /* @@ -587,7 +584,7 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,  	/*  	 * Update FCS error count from register.  	 */ -	rt2x00pci_register_read(rt2x00dev, CNT0, ®); +	rt2x00mmio_register_read(rt2x00dev, CNT0, ®);  	qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);  	/* @@ -633,11 +630,98 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev,  }  /* + * Queue handlers. + */ +static void rt2400pci_start_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_RX: +		rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®); +		rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); +		rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); +		break; +	case QID_BEACON: +		rt2x00mmio_register_read(rt2x00dev, CSR14, ®); +		rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); +		rt2x00_set_field32(®, CSR14_TBCN, 1); +		rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); +		rt2x00mmio_register_write(rt2x00dev, CSR14, reg); +		break; +	default: +		break; +	} +} + +static void rt2400pci_kick_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_AC_VO: +		rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); +		rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); +		rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); +		break; +	case QID_AC_VI: +		rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); +		rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); +		rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); +		break; +	case QID_ATIM: +		rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); +		rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); +		rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); +		break; +	default: +		break; +	} +} + +static void rt2400pci_stop_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_ATIM: +		rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); +		rt2x00_set_field32(®, TXCSR0_ABORT, 1); +		rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); +		break; +	case QID_RX: +		rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®); +		rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); +		rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); +		break; +	case QID_BEACON: +		rt2x00mmio_register_read(rt2x00dev, CSR14, ®); +		rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); +		rt2x00_set_field32(®, CSR14_TBCN, 0); +		rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); +		rt2x00mmio_register_write(rt2x00dev, CSR14, reg); + +		/* +		 * Wait for possibly running tbtt tasklets. +		 */ +		tasklet_kill(&rt2x00dev->tbtt_tasklet); +		break; +	default: +		break; +	} +} + +/*   * Initialization functions.   */  static bool rt2400pci_get_entry_state(struct queue_entry *entry)  { -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	u32 word;  	if (entry->queue->qid == QID_RX) { @@ -654,7 +738,7 @@ static bool rt2400pci_get_entry_state(struct queue_entry *entry)  static void rt2400pci_clear_entry(struct queue_entry *entry)  { -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);  	u32 word; @@ -680,53 +764,53 @@ static void rt2400pci_clear_entry(struct queue_entry *entry)  static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)  { -	struct queue_entry_priv_pci *entry_priv; +	struct queue_entry_priv_mmio *entry_priv;  	u32 reg;  	/*  	 * Initialize registers.  	 */ -	rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); +	rt2x00mmio_register_read(rt2x00dev, TXCSR2, ®);  	rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);  	rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); -	rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit); +	rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);  	rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); -	rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); +	rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);  	entry_priv = rt2x00dev->tx[1].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); +	rt2x00mmio_register_read(rt2x00dev, TXCSR3, ®);  	rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); +	rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);  	entry_priv = rt2x00dev->tx[0].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); +	rt2x00mmio_register_read(rt2x00dev, TXCSR5, ®);  	rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); +	rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg); -	entry_priv = rt2x00dev->bcn[1].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); +	entry_priv = rt2x00dev->atim->entries[0].priv_data; +	rt2x00mmio_register_read(rt2x00dev, TXCSR4, ®);  	rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); +	rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg); -	entry_priv = rt2x00dev->bcn[0].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); +	entry_priv = rt2x00dev->bcn->entries[0].priv_data; +	rt2x00mmio_register_read(rt2x00dev, TXCSR6, ®);  	rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); +	rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg); -	rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, RXCSR1, ®);  	rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);  	rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); -	rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);  	entry_priv = rt2x00dev->rx->entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); +	rt2x00mmio_register_read(rt2x00dev, RXCSR2, ®);  	rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); +	rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);  	return 0;  } @@ -735,23 +819,23 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; -	rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002); -	rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002); -	rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00023f20); -	rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002); +	rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002); +	rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002); +	rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00023f20); +	rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002); -	rt2x00pci_register_read(rt2x00dev, TIMECSR, ®); +	rt2x00mmio_register_read(rt2x00dev, TIMECSR, ®);  	rt2x00_set_field32(®, TIMECSR_US_COUNT, 33);  	rt2x00_set_field32(®, TIMECSR_US_64_COUNT, 63);  	rt2x00_set_field32(®, TIMECSR_BEACON_EXPECT, 0); -	rt2x00pci_register_write(rt2x00dev, TIMECSR, reg); +	rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg); -	rt2x00pci_register_read(rt2x00dev, CSR9, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR9, ®);  	rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT,  			   (rt2x00dev->rx->data_size / 128)); -	rt2x00pci_register_write(rt2x00dev, CSR9, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR9, reg); -	rt2x00pci_register_read(rt2x00dev, CSR14, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR14, ®);  	rt2x00_set_field32(®, CSR14_TSF_COUNT, 0);  	rt2x00_set_field32(®, CSR14_TSF_SYNC, 0);  	rt2x00_set_field32(®, CSR14_TBCN, 0); @@ -760,63 +844,63 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);  	rt2x00_set_field32(®, CSR14_CFP_COUNT_PRELOAD, 0);  	rt2x00_set_field32(®, CSR14_TBCM_PRELOAD, 0); -	rt2x00pci_register_write(rt2x00dev, CSR14, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR14, reg); -	rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000); +	rt2x00mmio_register_write(rt2x00dev, CNT3, 0x3f080000); -	rt2x00pci_register_read(rt2x00dev, ARCSR0, ®); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, ARCSR0, reg); -	rt2x00pci_register_read(rt2x00dev, RXCSR3, ®); +	rt2x00mmio_register_read(rt2x00dev, RXCSR3, ®);  	rt2x00_set_field32(®, RXCSR3_BBP_ID0, 3); /* Tx power.*/  	rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1);  	rt2x00_set_field32(®, RXCSR3_BBP_ID1, 32); /* Signal */  	rt2x00_set_field32(®, RXCSR3_BBP_ID1_VALID, 1);  	rt2x00_set_field32(®, RXCSR3_BBP_ID2, 36); /* Rssi */  	rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1); -	rt2x00pci_register_write(rt2x00dev, RXCSR3, reg); +	rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg); -	rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00217223); +	rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518); -	rt2x00pci_register_read(rt2x00dev, MACCSR2, ®); +	rt2x00mmio_register_read(rt2x00dev, MACCSR2, ®);  	rt2x00_set_field32(®, MACCSR2_DELAY, 64); -	rt2x00pci_register_write(rt2x00dev, MACCSR2, reg); +	rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg); -	rt2x00pci_register_read(rt2x00dev, RALINKCSR, ®); +	rt2x00mmio_register_read(rt2x00dev, RALINKCSR, ®);  	rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17);  	rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 154);  	rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA1, 0);  	rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID1, 154); -	rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg); +	rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg); -	rt2x00pci_register_read(rt2x00dev, CSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR1, ®);  	rt2x00_set_field32(®, CSR1_SOFT_RESET, 1);  	rt2x00_set_field32(®, CSR1_BBP_RESET, 0);  	rt2x00_set_field32(®, CSR1_HOST_READY, 0); -	rt2x00pci_register_write(rt2x00dev, CSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR1, reg); -	rt2x00pci_register_read(rt2x00dev, CSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR1, ®);  	rt2x00_set_field32(®, CSR1_SOFT_RESET, 0);  	rt2x00_set_field32(®, CSR1_HOST_READY, 1); -	rt2x00pci_register_write(rt2x00dev, CSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR1, reg);  	/*  	 * We must clear the FCS and FIFO error count.  	 * These registers are cleared on read,  	 * so we may pass a useless variable to store the value.  	 */ -	rt2x00pci_register_read(rt2x00dev, CNT0, ®); -	rt2x00pci_register_read(rt2x00dev, CNT4, ®); +	rt2x00mmio_register_read(rt2x00dev, CNT0, ®); +	rt2x00mmio_register_read(rt2x00dev, CNT4, ®);  	return 0;  } @@ -833,7 +917,7 @@ static int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)  		udelay(REGISTER_BUSY_DELAY);  	} -	ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); +	rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");  	return -EACCES;  } @@ -878,44 +962,47 @@ static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev)  /*   * Device state switch handlers.   */ -static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev, -				enum dev_state state) -{ -	u32 reg; - -	rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); -	rt2x00_set_field32(®, RXCSR0_DISABLE_RX, -			   (state == STATE_RADIO_RX_OFF)); -	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} -  static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,  				 enum dev_state state)  { -	int mask = (state == STATE_RADIO_IRQ_OFF) || -		   (state == STATE_RADIO_IRQ_OFF_ISR); +	int mask = (state == STATE_RADIO_IRQ_OFF);  	u32 reg; +	unsigned long flags;  	/*  	 * When interrupts are being enabled, the interrupt registers  	 * should clear the register to assure a clean state.  	 */  	if (state == STATE_RADIO_IRQ_ON) { -		rt2x00pci_register_read(rt2x00dev, CSR7, ®); -		rt2x00pci_register_write(rt2x00dev, CSR7, reg); +		rt2x00mmio_register_read(rt2x00dev, CSR7, ®); +		rt2x00mmio_register_write(rt2x00dev, CSR7, reg);  	}  	/*  	 * Only toggle the interrupts bits we are going to use.  	 * Non-checked interrupt bits are disabled by default.  	 */ -	rt2x00pci_register_read(rt2x00dev, CSR8, ®); +	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); + +	rt2x00mmio_register_read(rt2x00dev, CSR8, ®);  	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); +	rt2x00mmio_register_write(rt2x00dev, CSR8, reg); + +	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); + +	if (state == STATE_RADIO_IRQ_OFF) { +		/* +		 * Ensure that all tasklets are finished before +		 * disabling the interrupts. +		 */ +		tasklet_kill(&rt2x00dev->txstatus_tasklet); +		tasklet_kill(&rt2x00dev->rxdone_tasklet); +		tasklet_kill(&rt2x00dev->tbtt_tasklet); +	}  }  static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) @@ -936,7 +1023,7 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)  	/*  	 * Disable power  	 */ -	rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); +	rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0);  }  static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, @@ -950,12 +1037,12 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,  	put_to_sleep = (state != STATE_AWAKE); -	rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, PWRCSR1, ®);  	rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1);  	rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state);  	rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state);  	rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep); -	rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);  	/*  	 * Device is not guaranteed to be in the requested state yet. @@ -963,12 +1050,12 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,  	 * device has entered the correct state.  	 */  	for (i = 0; i < REGISTER_BUSY_COUNT; i++) { -		rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®2); +		rt2x00mmio_register_read(rt2x00dev, PWRCSR1, ®2);  		bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);  		rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);  		if (bbp_state == state && rf_state == state)  			return 0; -		rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); +		rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);  		msleep(10);  	} @@ -987,14 +1074,8 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *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); -		break;  	case STATE_RADIO_IRQ_ON: -	case STATE_RADIO_IRQ_ON_ISR:  	case STATE_RADIO_IRQ_OFF: -	case STATE_RADIO_IRQ_OFF_ISR:  		rt2400pci_toggle_irq(rt2x00dev, state);  		break;  	case STATE_DEEP_SLEEP: @@ -1009,8 +1090,8 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,  	}  	if (unlikely(retval)) -		ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", -		      state, retval); +		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", +			   state, retval);  	return retval;  } @@ -1022,7 +1103,7 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,  				    struct txentry_desc *txdesc)  {  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	__le32 *txd = entry_priv->desc;  	u32 word; @@ -1039,19 +1120,21 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,  	rt2x00_desc_write(txd, 2, word);  	rt2x00_desc_read(txd, 3, &word); -	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal); +	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);  	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);  	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1); -	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service); +	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);  	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);  	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);  	rt2x00_desc_write(txd, 3, word);  	rt2x00_desc_read(txd, 4, &word); -	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, txdesc->length_low); +	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, +			   txdesc->u.plcp.length_low);  	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);  	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1); -	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, txdesc->length_high); +	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, +			   txdesc->u.plcp.length_high);  	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);  	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);  	rt2x00_desc_write(txd, 4, word); @@ -1072,7 +1155,7 @@ static void rt2400pci_write_tx_desc(struct queue_entry *entry,  			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));  	rt2x00_set_field32(&word, TXD_W0_RTS,  			   test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)); -	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); +	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);  	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,  			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));  	rt2x00_desc_write(txd, 0, word); @@ -1097,12 +1180,18 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,  	 * Disable beaconing while we are reloading the beacon data,  	 * otherwise we might be sending out invalid data.  	 */ -	rt2x00pci_register_read(rt2x00dev, CSR14, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR14, ®);  	rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); -	rt2x00pci_register_write(rt2x00dev, CSR14, reg); - -	rt2x00queue_map_txskb(entry); +	rt2x00mmio_register_write(rt2x00dev, CSR14, reg); +	if (rt2x00queue_map_txskb(entry)) { +		rt2x00_err(rt2x00dev, "Fail to map beacon, aborting\n"); +		goto out; +	} +	/* +	 * Enable beaconing again. +	 */ +	rt2x00_set_field32(®, CSR14_BEACON_GEN, 1);  	/*  	 * Write the TX descriptor for the beacon.  	 */ @@ -1112,40 +1201,12 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,  	 * Dump beacon to userspace through debugfs.  	 */  	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); - +out:  	/*  	 * Enable beaconing again.  	 */ -	rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); -	rt2x00_set_field32(®, CSR14_TBCN, 1);  	rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); -	rt2x00pci_register_write(rt2x00dev, CSR14, reg); -} - -static void rt2400pci_kick_tx_queue(struct data_queue *queue) -{ -	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; -	u32 reg; - -	rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); -	rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE)); -	rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK)); -	rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM)); -	rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); -} - -static void rt2400pci_kill_tx_queue(struct data_queue *queue) -{ -	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; -	u32 reg; - -	if (queue->qid == QID_BEACON) { -		rt2x00pci_register_write(rt2x00dev, CSR14, 0); -	} else { -		rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); -		rt2x00_set_field32(®, TXCSR0_ABORT, 1); -		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); -	} +	rt2x00mmio_register_write(rt2x00dev, CSR14, reg);  }  /* @@ -1155,7 +1216,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,  				  struct rxdone_entry_desc *rxdesc)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	u32 word0;  	u32 word2;  	u32 word3; @@ -1183,7 +1244,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,  	 * call, we must decrease the higher 32bits with 1 to get  	 * to correct value.  	 */ -	tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw); +	tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw, NULL);  	rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME);  	rx_high = upper_32_bits(tsf); @@ -1197,7 +1258,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,  	 */  	rxdesc->timestamp = ((u64)rx_high << 32) | rx_low;  	rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; -	rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - +	rxdesc->rssi = rt2x00_get_field32(word3, RXD_W3_RSSI) -  	    entry->queue->rt2x00dev->rssi_offset;  	rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); @@ -1212,8 +1273,8 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,  static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,  			     const enum data_queue_qid queue_idx)  { -	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); -	struct queue_entry_priv_pci *entry_priv; +	struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx); +	struct queue_entry_priv_mmio *entry_priv;  	struct queue_entry *entry;  	struct txdone_entry_desc txdesc;  	u32 word; @@ -1248,64 +1309,80 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,  	}  } -static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance) +static inline void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, +					      struct rt2x00_field32 irq_field)  { -	struct rt2x00_dev *rt2x00dev = dev_instance; -	u32 reg = rt2x00dev->irqvalue[0]; +	u32 reg;  	/* -	 * Handle interrupts, walk through all bits -	 * and run the tasks, the bits are checked in order of -	 * priority. +	 * Enable a single interrupt. The interrupt mask register +	 * access needs locking.  	 */ +	spin_lock_irq(&rt2x00dev->irqmask_lock); -	/* -	 * 1 - Beacon timer expired interrupt. -	 */ -	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) -		rt2x00lib_beacondone(rt2x00dev); +	rt2x00mmio_register_read(rt2x00dev, CSR8, ®); +	rt2x00_set_field32(®, irq_field, 0); +	rt2x00mmio_register_write(rt2x00dev, CSR8, reg); -	/* -	 * 2 - Rx ring done interrupt. -	 */ -	if (rt2x00_get_field32(reg, CSR7_RXDONE)) -		rt2x00pci_rxdone(rt2x00dev); +	spin_unlock_irq(&rt2x00dev->irqmask_lock); +} -	/* -	 * 3 - Atim ring transmit done interrupt. -	 */ -	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING)) -		rt2400pci_txdone(rt2x00dev, QID_ATIM); +static void rt2400pci_txstatus_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	u32 reg;  	/* -	 * 4 - Priority ring transmit done interrupt. +	 * Handle all tx queues.  	 */ -	if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) -		rt2400pci_txdone(rt2x00dev, QID_AC_BE); +	rt2400pci_txdone(rt2x00dev, QID_ATIM); +	rt2400pci_txdone(rt2x00dev, QID_AC_VO); +	rt2400pci_txdone(rt2x00dev, QID_AC_VI);  	/* -	 * 5 - Tx ring transmit done interrupt. +	 * Enable all TXDONE interrupts again.  	 */ -	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) -		rt2400pci_txdone(rt2x00dev, QID_AC_BK); +	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) { +		spin_lock_irq(&rt2x00dev->irqmask_lock); -	/* Enable interrupts again. */ -	rt2x00dev->ops->lib->set_device_state(rt2x00dev, -					      STATE_RADIO_IRQ_ON_ISR); -	return IRQ_HANDLED; +		rt2x00mmio_register_read(rt2x00dev, CSR8, ®); +		rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0); +		rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0); +		rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0); +		rt2x00mmio_register_write(rt2x00dev, CSR8, reg); + +		spin_unlock_irq(&rt2x00dev->irqmask_lock); +	} +} + +static void rt2400pci_tbtt_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	rt2x00lib_beacondone(rt2x00dev); +	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE); +} + +static void rt2400pci_rxdone_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	if (rt2x00mmio_rxdone(rt2x00dev)) +		tasklet_schedule(&rt2x00dev->rxdone_tasklet); +	else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);  }  static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)  {  	struct rt2x00_dev *rt2x00dev = dev_instance; -	u32 reg; +	u32 reg, mask;  	/*  	 * Get the interrupt sources & saved to local variable.  	 * Write register value back to clear pending interrupts.  	 */ -	rt2x00pci_register_read(rt2x00dev, CSR7, ®); -	rt2x00pci_register_write(rt2x00dev, CSR7, reg); +	rt2x00mmio_register_read(rt2x00dev, CSR7, ®); +	rt2x00mmio_register_write(rt2x00dev, CSR7, reg);  	if (!reg)  		return IRQ_NONE; @@ -1313,14 +1390,44 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)  	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))  		return IRQ_HANDLED; -	/* Store irqvalues for use in the interrupt thread. */ -	rt2x00dev->irqvalue[0] = reg; +	mask = reg; -	/* Disable interrupts, will be enabled again in the interrupt thread. */ -	rt2x00dev->ops->lib->set_device_state(rt2x00dev, -					      STATE_RADIO_IRQ_OFF_ISR); +	/* +	 * Schedule tasklets for interrupt handling. +	 */ +	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) +		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); + +	if (rt2x00_get_field32(reg, CSR7_RXDONE)) +		tasklet_schedule(&rt2x00dev->rxdone_tasklet); + +	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) || +	    rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) || +	    rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) { +		tasklet_schedule(&rt2x00dev->txstatus_tasklet); +		/* +		 * Mask out all txdone interrupts. +		 */ +		rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1); +		rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1); +		rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1); +	} -	return IRQ_WAKE_THREAD; +	/* +	 * Disable all interrupts for which a tasklet was scheduled right now, +	 * the tasklet will reenable the appropriate interrupts. +	 */ +	spin_lock(&rt2x00dev->irqmask_lock); + +	rt2x00mmio_register_read(rt2x00dev, CSR8, ®); +	reg |= mask; +	rt2x00mmio_register_write(rt2x00dev, CSR8, reg); + +	spin_unlock(&rt2x00dev->irqmask_lock); + + + +	return IRQ_HANDLED;  }  /* @@ -1333,7 +1440,7 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  	u16 word;  	u8 *mac; -	rt2x00pci_register_read(rt2x00dev, CSR21, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR21, ®);  	eeprom.data = rt2x00dev;  	eeprom.register_read = rt2400pci_eepromregister_read; @@ -1353,13 +1460,13 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  	 */  	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);  	if (!is_valid_ether_addr(mac)) { -		random_ether_addr(mac); -		EEPROM(rt2x00dev, "MAC: %pM\n", mac); +		eth_random_addr(mac); +		rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);  	if (word == 0xffff) { -		ERROR(rt2x00dev, "Invalid EEPROM data detected.\n"); +		rt2x00_err(rt2x00dev, "Invalid EEPROM data detected\n");  		return -EINVAL;  	} @@ -1381,12 +1488,12 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Identify RF chipset.  	 */  	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); -	rt2x00pci_register_read(rt2x00dev, CSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR0, ®);  	rt2x00_set_chip(rt2x00dev, RT2460, value,  			rt2x00_get_field32(reg, CSR0_REVISION));  	if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) { -		ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); +		rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");  		return -ENODEV;  	} @@ -1427,13 +1534,13 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Detect if this device has an hardware controlled radio.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);  	/*  	 * Check if the BBP tuning should be enabled.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING)) -		__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); +		__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);  	return 0;  } @@ -1509,6 +1616,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -1522,6 +1630,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00mmio_register_read(rt2x00dev, GPIOCSR, ®); +	rt2x00_set_field32(®, GPIOCSR_DIR0, 1); +	rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2400pci_probe_hw_mode(rt2x00dev); @@ -1531,8 +1647,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)  	/*  	 * This device requires the atim queue and DMA-mapped skbs.  	 */ -	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); +	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);  	/*  	 * Set the rssi offset. @@ -1545,7 +1662,8 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)  /*   * IEEE80211 stack callback functions.   */ -static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue, +static int rt2400pci_conf_tx(struct ieee80211_hw *hw, +			     struct ieee80211_vif *vif, u16 queue,  			     const struct ieee80211_tx_queue_params *params)  {  	struct rt2x00_dev *rt2x00dev = hw->priv; @@ -1558,7 +1676,7 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,  	if (queue != 0)  		return -EINVAL; -	if (rt2x00mac_conf_tx(hw, queue, params)) +	if (rt2x00mac_conf_tx(hw, vif, queue, params))  		return -EINVAL;  	/* @@ -1570,15 +1688,16 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,  	return 0;  } -static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw) +static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw, +			     struct ieee80211_vif *vif)  {  	struct rt2x00_dev *rt2x00dev = hw->priv;  	u64 tsf;  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, CSR17, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR17, ®);  	tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; -	rt2x00pci_register_read(rt2x00dev, CSR16, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR16, ®);  	tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);  	return tsf; @@ -1589,7 +1708,7 @@ static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)  	struct rt2x00_dev *rt2x00dev = hw->priv;  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, CSR15, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR15, ®);  	return rt2x00_get_field32(reg, CSR15_BEACON_SENT);  } @@ -1610,14 +1729,20 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {  	.tx_last_beacon		= rt2400pci_tx_last_beacon,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.flush			= rt2x00mac_flush, +	.set_antenna		= rt2x00mac_set_antenna, +	.get_antenna		= rt2x00mac_get_antenna, +	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {  	.irq_handler		= rt2400pci_interrupt, -	.irq_handler_thread	= rt2400pci_interrupt_thread, +	.txstatus_tasklet	= rt2400pci_txstatus_tasklet, +	.tbtt_tasklet		= rt2400pci_tbtt_tasklet, +	.rxdone_tasklet		= rt2400pci_rxdone_tasklet,  	.probe_hw		= rt2400pci_probe_hw, -	.initialize		= rt2x00pci_initialize, -	.uninitialize		= rt2x00pci_uninitialize, +	.initialize		= rt2x00mmio_initialize, +	.uninitialize		= rt2x00mmio_uninitialize,  	.get_entry_state	= rt2400pci_get_entry_state,  	.clear_entry		= rt2400pci_clear_entry,  	.set_device_state	= rt2400pci_set_device_state, @@ -1625,10 +1750,12 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {  	.link_stats		= rt2400pci_link_stats,  	.reset_tuner		= rt2400pci_reset_tuner,  	.link_tuner		= rt2400pci_link_tuner, +	.start_queue		= rt2400pci_start_queue, +	.kick_queue		= rt2400pci_kick_queue, +	.stop_queue		= rt2400pci_stop_queue, +	.flush_queue		= rt2x00mmio_flush_queue,  	.write_tx_desc		= rt2400pci_write_tx_desc,  	.write_beacon		= rt2400pci_write_beacon, -	.kick_tx_queue		= rt2400pci_kick_tx_queue, -	.kill_tx_queue		= rt2400pci_kill_tx_queue,  	.fill_rxdone		= rt2400pci_fill_rxdone,  	.config_filter		= rt2400pci_config_filter,  	.config_intf		= rt2400pci_config_intf, @@ -1637,46 +1764,53 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {  	.config			= rt2400pci_config,  }; -static const struct data_queue_desc rt2400pci_queue_rx = { -	.entry_num		= 24, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= RXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; +static void rt2400pci_queue_init(struct data_queue *queue) +{ +	switch (queue->qid) { +	case QID_RX: +		queue->limit = 24; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = RXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; -static const struct data_queue_desc rt2400pci_queue_tx = { -	.entry_num		= 24, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		queue->limit = 24; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; -static const struct data_queue_desc rt2400pci_queue_bcn = { -	.entry_num		= 1, -	.data_size		= MGMT_FRAME_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; +	case QID_BEACON: +		queue->limit = 1; +		queue->data_size = MGMT_FRAME_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; -static const struct data_queue_desc rt2400pci_queue_atim = { -	.entry_num		= 8, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; +	case QID_ATIM: +		queue->limit = 8; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; + +	default: +		BUG(); +		break; +	} +}  static const struct rt2x00_ops rt2400pci_ops = {  	.name			= KBUILD_MODNAME, -	.max_sta_intf		= 1,  	.max_ap_intf		= 1,  	.eeprom_size		= EEPROM_SIZE,  	.rf_size		= RF_SIZE,  	.tx_queues		= NUM_TX_QUEUES, -	.extra_tx_headroom	= 0, -	.rx			= &rt2400pci_queue_rx, -	.tx			= &rt2400pci_queue_tx, -	.bcn			= &rt2400pci_queue_bcn, -	.atim			= &rt2400pci_queue_atim, +	.queue_init		= rt2400pci_queue_init,  	.lib			= &rt2400pci_rt2x00_ops,  	.hw			= &rt2400pci_mac80211_ops,  #ifdef CONFIG_RT2X00_LIB_DEBUGFS @@ -1688,10 +1822,11 @@ static const struct rt2x00_ops rt2400pci_ops = {   * RT2400pci module information.   */  static DEFINE_PCI_DEVICE_TABLE(rt2400pci_device_table) = { -	{ PCI_DEVICE(0x1814, 0x0101), PCI_DEVICE_DATA(&rt2400pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0101) },  	{ 0, }  }; +  MODULE_AUTHOR(DRV_PROJECT);  MODULE_VERSION(DRV_VERSION);  MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver."); @@ -1699,24 +1834,19 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards");  MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);  MODULE_LICENSE("GPL"); +static int rt2400pci_probe(struct pci_dev *pci_dev, +			   const struct pci_device_id *id) +{ +	return rt2x00pci_probe(pci_dev, &rt2400pci_ops); +} +  static struct pci_driver rt2400pci_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt2400pci_device_table, -	.probe		= rt2x00pci_probe, -	.remove		= __devexit_p(rt2x00pci_remove), +	.probe		= rt2400pci_probe, +	.remove		= rt2x00pci_remove,  	.suspend	= rt2x00pci_suspend,  	.resume		= rt2x00pci_resume,  }; -static int __init rt2400pci_init(void) -{ -	return pci_register_driver(&rt2400pci_driver); -} - -static void __exit rt2400pci_exit(void) -{ -	pci_unregister_driver(&rt2400pci_driver); -} - -module_init(rt2400pci_init); -module_exit(rt2400pci_exit); +module_pci_driver(rt2400pci_driver); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index d3a4a68cc43..0fd3a9d01a6 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -660,16 +658,26 @@  /*   * GPIOCSR: GPIO control register. + *	GPIOCSR_VALx: Actual GPIO pin x value + *	GPIOCSR_DIRx: GPIO direction: 0 = output; 1 = input   */  #define GPIOCSR				0x0120 -#define GPIOCSR_BIT0			FIELD32(0x00000001) -#define GPIOCSR_BIT1			FIELD32(0x00000002) -#define GPIOCSR_BIT2			FIELD32(0x00000004) -#define GPIOCSR_BIT3			FIELD32(0x00000008) -#define GPIOCSR_BIT4			FIELD32(0x00000010) -#define GPIOCSR_BIT5			FIELD32(0x00000020) -#define GPIOCSR_BIT6			FIELD32(0x00000040) -#define GPIOCSR_BIT7			FIELD32(0x00000080) +#define GPIOCSR_VAL0			FIELD32(0x00000001) +#define GPIOCSR_VAL1			FIELD32(0x00000002) +#define GPIOCSR_VAL2			FIELD32(0x00000004) +#define GPIOCSR_VAL3			FIELD32(0x00000008) +#define GPIOCSR_VAL4			FIELD32(0x00000010) +#define GPIOCSR_VAL5			FIELD32(0x00000020) +#define GPIOCSR_VAL6			FIELD32(0x00000040) +#define GPIOCSR_VAL7			FIELD32(0x00000080) +#define GPIOCSR_DIR0			FIELD32(0x00000100) +#define GPIOCSR_DIR1			FIELD32(0x00000200) +#define GPIOCSR_DIR2			FIELD32(0x00000400) +#define GPIOCSR_DIR3			FIELD32(0x00000800) +#define GPIOCSR_DIR4			FIELD32(0x00001000) +#define GPIOCSR_DIR5			FIELD32(0x00002000) +#define GPIOCSR_DIR6			FIELD32(0x00004000) +#define GPIOCSR_DIR7			FIELD32(0x00008000)  /*   * BBPPCSR: BBP Pin control register. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 3e7f2034624..a511cccc9f0 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -26,7 +24,6 @@  #include <linux/delay.h>  #include <linux/etherdevice.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> @@ -34,13 +31,14 @@  #include <linux/slab.h>  #include "rt2x00.h" +#include "rt2x00mmio.h"  #include "rt2x00pci.h"  #include "rt2500pci.h"  /*   * Register access.   * All access to the CSR registers will go through the methods - * rt2x00pci_register_read and rt2x00pci_register_write. + * rt2x00mmio_register_read and rt2x00mmio_register_write.   * BBP and RF register require indirect register access,   * and use the CSR registers BBPCSR and RFCSR to achieve this.   * These indirect registers work with busy bits, @@ -51,9 +49,9 @@   * and we will print an error.   */  #define WAIT_FOR_BBP(__dev, __reg) \ -	rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) +	rt2x00mmio_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))  #define WAIT_FOR_RF(__dev, __reg) \ -	rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) +	rt2x00mmio_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))  static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,  				const unsigned int word, const u8 value) @@ -73,7 +71,7 @@ static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, BBPCSR_BUSY, 1);  		rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); -		rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); +		rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);  	}  	mutex_unlock(&rt2x00dev->csr_mutex); @@ -100,7 +98,7 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, BBPCSR_BUSY, 1);  		rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); -		rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); +		rt2x00mmio_register_write(rt2x00dev, BBPCSR, reg);  		WAIT_FOR_BBP(rt2x00dev, ®);  	} @@ -128,7 +126,7 @@ static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, RFCSR_IF_SELECT, 0);  		rt2x00_set_field32(®, RFCSR_BUSY, 1); -		rt2x00pci_register_write(rt2x00dev, RFCSR, reg); +		rt2x00mmio_register_write(rt2x00dev, RFCSR, reg);  		rt2x00_rf_write(rt2x00dev, word, value);  	} @@ -140,7 +138,7 @@ static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom)  	struct rt2x00_dev *rt2x00dev = eeprom->data;  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, CSR21, ®); +	rt2x00mmio_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); @@ -162,15 +160,15 @@ static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom)  	rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT,  			   !!eeprom->reg_chip_select); -	rt2x00pci_register_write(rt2x00dev, CSR21, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR21, reg);  }  #ifdef CONFIG_RT2X00_LIB_DEBUGFS  static const struct rt2x00debug rt2500pci_rt2x00debug = {  	.owner	= THIS_MODULE,  	.csr	= { -		.read		= rt2x00pci_register_read, -		.write		= rt2x00pci_register_write, +		.read		= rt2x00mmio_register_read, +		.write		= rt2x00mmio_register_write,  		.flags		= RT2X00DEBUGFS_OFFSET,  		.word_base	= CSR_REG_BASE,  		.word_size	= sizeof(u32), @@ -204,8 +202,8 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); -	return rt2x00_get_field32(reg, GPIOCSR_BIT0); +	rt2x00mmio_register_read(rt2x00dev, GPIOCSR, ®); +	return rt2x00_get_field32(reg, GPIOCSR_VAL0);  }  #ifdef CONFIG_RT2X00_LIB_LEDS @@ -217,14 +215,14 @@ static void rt2500pci_brightness_set(struct led_classdev *led_cdev,  	unsigned int enabled = brightness != LED_OFF;  	u32 reg; -	rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); +	rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, ®);  	if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC)  		rt2x00_set_field32(®, LEDCSR_LINK, enabled);  	else if (led->type == LED_TYPE_ACTIVITY)  		rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled); -	rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); +	rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);  }  static int rt2500pci_blink_set(struct led_classdev *led_cdev, @@ -235,10 +233,10 @@ static int rt2500pci_blink_set(struct led_classdev *led_cdev,  	    container_of(led_cdev, struct rt2x00_led, led_dev);  	u32 reg; -	rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); +	rt2x00mmio_register_read(led->rt2x00dev, LEDCSR, ®);  	rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on);  	rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off); -	rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); +	rt2x00mmio_register_write(led->rt2x00dev, LEDCSR, reg);  	return 0;  } @@ -269,7 +267,7 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,  	 * and broadcast frames will always be accepted since  	 * there is no filter for it at this time.  	 */ -	rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®);  	rt2x00_set_field32(®, RXCSR0_DROP_CRC,  			   !(filter_flags & FIF_FCSFAIL));  	rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, @@ -285,7 +283,7 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(®, RXCSR0_DROP_MCAST,  			   !(filter_flags & FIF_ALLMULTI));  	rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); -	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); +	rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg);  }  static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, @@ -293,7 +291,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,  				  struct rt2x00intf_conf *conf,  				  const unsigned int flags)  { -	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); +	struct data_queue *queue = rt2x00dev->bcn;  	unsigned int bcn_preload;  	u32 reg; @@ -302,27 +300,25 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,  		 * Enable beacon config  		 */  		bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); -		rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); +		rt2x00mmio_register_read(rt2x00dev, BCNCSR1, ®);  		rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload);  		rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); -		rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); +		rt2x00mmio_register_write(rt2x00dev, BCNCSR1, reg);  		/*  		 * Enable synchronisation.  		 */ -		rt2x00pci_register_read(rt2x00dev, CSR14, ®); -		rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); +		rt2x00mmio_register_read(rt2x00dev, CSR14, ®);  		rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); -		rt2x00_set_field32(®, CSR14_TBCN, 1); -		rt2x00pci_register_write(rt2x00dev, CSR14, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR14, reg);  	}  	if (flags & CONFIG_UPDATE_MAC) -		rt2x00pci_register_multiwrite(rt2x00dev, CSR3, +		rt2x00mmio_register_multiwrite(rt2x00dev, CSR3,  					      conf->mac, sizeof(conf->mac));  	if (flags & CONFIG_UPDATE_BSSID) -		rt2x00pci_register_multiwrite(rt2x00dev, CSR5, +		rt2x00mmio_register_multiwrite(rt2x00dev, CSR5,  					      conf->bssid, sizeof(conf->bssid));  } @@ -339,68 +335,68 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,  	if (changed & BSS_CHANGED_ERP_PREAMBLE) {  		preamble_mask = erp->short_preamble << 3; -		rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); +		rt2x00mmio_register_read(rt2x00dev, TXCSR1, ®);  		rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x162);  		rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0xa2);  		rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);  		rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); -		rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); +		rt2x00mmio_register_write(rt2x00dev, TXCSR1, reg); -		rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); +		rt2x00mmio_register_read(rt2x00dev, ARCSR2, ®);  		rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00);  		rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04);  		rt2x00_set_field32(®, ARCSR2_LENGTH,  				   GET_DURATION(ACK_SIZE, 10)); -		rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); +		rt2x00mmio_register_write(rt2x00dev, ARCSR2, reg); -		rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); +		rt2x00mmio_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); +		rt2x00mmio_register_write(rt2x00dev, ARCSR3, reg); -		rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); +		rt2x00mmio_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); +		rt2x00mmio_register_write(rt2x00dev, ARCSR4, reg); -		rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); +		rt2x00mmio_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); +		rt2x00mmio_register_write(rt2x00dev, ARCSR5, reg);  	}  	if (changed & BSS_CHANGED_BASIC_RATES) -		rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); +		rt2x00mmio_register_write(rt2x00dev, ARCSR1, erp->basic_rates);  	if (changed & BSS_CHANGED_ERP_SLOT) { -		rt2x00pci_register_read(rt2x00dev, CSR11, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR11, ®);  		rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); -		rt2x00pci_register_write(rt2x00dev, CSR11, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR11, reg); -		rt2x00pci_register_read(rt2x00dev, CSR18, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR18, ®);  		rt2x00_set_field32(®, CSR18_SIFS, erp->sifs);  		rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); -		rt2x00pci_register_write(rt2x00dev, CSR18, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR18, reg); -		rt2x00pci_register_read(rt2x00dev, CSR19, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR19, ®);  		rt2x00_set_field32(®, CSR19_DIFS, erp->difs);  		rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); -		rt2x00pci_register_write(rt2x00dev, CSR19, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR19, reg);  	}  	if (changed & BSS_CHANGED_BEACON_INT) { -		rt2x00pci_register_read(rt2x00dev, CSR12, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR12, ®);  		rt2x00_set_field32(®, CSR12_BEACON_INTERVAL,  				   erp->beacon_int * 16);  		rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION,  				   erp->beacon_int * 16); -		rt2x00pci_register_write(rt2x00dev, CSR12, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR12, reg);  	}  } @@ -419,7 +415,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,  	BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||  	       ant->tx == ANTENNA_SW_DIVERSITY); -	rt2x00pci_register_read(rt2x00dev, BBPCSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, BBPCSR1, ®);  	rt2500pci_bbp_read(rt2x00dev, 14, &r14);  	rt2500pci_bbp_read(rt2x00dev, 2, &r2); @@ -471,7 +467,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 0);  	} -	rt2x00pci_register_write(rt2x00dev, BBPCSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, BBPCSR1, reg);  	rt2500pci_bbp_write(rt2x00dev, 14, r14);  	rt2500pci_bbp_write(rt2x00dev, 2, r2);  } @@ -542,7 +538,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,  	/*  	 * Clear false CRC during channel switch.  	 */ -	rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1); +	rt2x00mmio_register_read(rt2x00dev, CNT0, &rf->rf1);  }  static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev, @@ -560,12 +556,12 @@ static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,  {  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, CSR11, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR11, ®);  	rt2x00_set_field32(®, CSR11_LONG_RETRY,  			   libconf->conf->long_frame_max_tx_count);  	rt2x00_set_field32(®, CSR11_SHORT_RETRY,  			   libconf->conf->short_frame_max_tx_count); -	rt2x00pci_register_write(rt2x00dev, CSR11, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR11, reg);  }  static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, @@ -577,7 +573,7 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,  	u32 reg;  	if (state == STATE_SLEEP) { -		rt2x00pci_register_read(rt2x00dev, CSR20, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR20, ®);  		rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN,  				   (rt2x00dev->beacon_int - 20) * 16);  		rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, @@ -585,14 +581,14 @@ static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,  		/* We must first disable autowake before it can be enabled */  		rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); -		rt2x00pci_register_write(rt2x00dev, CSR20, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR20, reg);  		rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); -		rt2x00pci_register_write(rt2x00dev, CSR20, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR20, reg);  	} else { -		rt2x00pci_register_read(rt2x00dev, CSR20, ®); +		rt2x00mmio_register_read(rt2x00dev, CSR20, ®);  		rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); -		rt2x00pci_register_write(rt2x00dev, CSR20, reg); +		rt2x00mmio_register_write(rt2x00dev, CSR20, reg);  	}  	rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); @@ -626,13 +622,13 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,  	/*  	 * Update FCS error count from register.  	 */ -	rt2x00pci_register_read(rt2x00dev, CNT0, ®); +	rt2x00mmio_register_read(rt2x00dev, CNT0, ®);  	qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);  	/*  	 * Update False CCA count from register.  	 */ -	rt2x00pci_register_read(rt2x00dev, CNT3, ®); +	rt2x00mmio_register_read(rt2x00dev, CNT3, ®);  	qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);  } @@ -723,11 +719,98 @@ dynamic_cca_tune:  }  /* + * Queue handlers. + */ +static void rt2500pci_start_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_RX: +		rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®); +		rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 0); +		rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); +		break; +	case QID_BEACON: +		rt2x00mmio_register_read(rt2x00dev, CSR14, ®); +		rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); +		rt2x00_set_field32(®, CSR14_TBCN, 1); +		rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); +		rt2x00mmio_register_write(rt2x00dev, CSR14, reg); +		break; +	default: +		break; +	} +} + +static void rt2500pci_kick_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_AC_VO: +		rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); +		rt2x00_set_field32(®, TXCSR0_KICK_PRIO, 1); +		rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); +		break; +	case QID_AC_VI: +		rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); +		rt2x00_set_field32(®, TXCSR0_KICK_TX, 1); +		rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); +		break; +	case QID_ATIM: +		rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); +		rt2x00_set_field32(®, TXCSR0_KICK_ATIM, 1); +		rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); +		break; +	default: +		break; +	} +} + +static void rt2500pci_stop_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_ATIM: +		rt2x00mmio_register_read(rt2x00dev, TXCSR0, ®); +		rt2x00_set_field32(®, TXCSR0_ABORT, 1); +		rt2x00mmio_register_write(rt2x00dev, TXCSR0, reg); +		break; +	case QID_RX: +		rt2x00mmio_register_read(rt2x00dev, RXCSR0, ®); +		rt2x00_set_field32(®, RXCSR0_DISABLE_RX, 1); +		rt2x00mmio_register_write(rt2x00dev, RXCSR0, reg); +		break; +	case QID_BEACON: +		rt2x00mmio_register_read(rt2x00dev, CSR14, ®); +		rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); +		rt2x00_set_field32(®, CSR14_TBCN, 0); +		rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); +		rt2x00mmio_register_write(rt2x00dev, CSR14, reg); + +		/* +		 * Wait for possibly running tbtt tasklets. +		 */ +		tasklet_kill(&rt2x00dev->tbtt_tasklet); +		break; +	default: +		break; +	} +} + +/*   * Initialization functions.   */  static bool rt2500pci_get_entry_state(struct queue_entry *entry)  { -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	u32 word;  	if (entry->queue->qid == QID_RX) { @@ -744,7 +827,7 @@ static bool rt2500pci_get_entry_state(struct queue_entry *entry)  static void rt2500pci_clear_entry(struct queue_entry *entry)  { -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);  	u32 word; @@ -766,53 +849,53 @@ static void rt2500pci_clear_entry(struct queue_entry *entry)  static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)  { -	struct queue_entry_priv_pci *entry_priv; +	struct queue_entry_priv_mmio *entry_priv;  	u32 reg;  	/*  	 * Initialize registers.  	 */ -	rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); +	rt2x00mmio_register_read(rt2x00dev, TXCSR2, ®);  	rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);  	rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); -	rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit); +	rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);  	rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); -	rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); +	rt2x00mmio_register_write(rt2x00dev, TXCSR2, reg);  	entry_priv = rt2x00dev->tx[1].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); +	rt2x00mmio_register_read(rt2x00dev, TXCSR3, ®);  	rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); +	rt2x00mmio_register_write(rt2x00dev, TXCSR3, reg);  	entry_priv = rt2x00dev->tx[0].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); +	rt2x00mmio_register_read(rt2x00dev, TXCSR5, ®);  	rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); +	rt2x00mmio_register_write(rt2x00dev, TXCSR5, reg); -	entry_priv = rt2x00dev->bcn[1].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); +	entry_priv = rt2x00dev->atim->entries[0].priv_data; +	rt2x00mmio_register_read(rt2x00dev, TXCSR4, ®);  	rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); +	rt2x00mmio_register_write(rt2x00dev, TXCSR4, reg); -	entry_priv = rt2x00dev->bcn[0].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); +	entry_priv = rt2x00dev->bcn->entries[0].priv_data; +	rt2x00mmio_register_read(rt2x00dev, TXCSR6, ®);  	rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); +	rt2x00mmio_register_write(rt2x00dev, TXCSR6, reg); -	rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, RXCSR1, ®);  	rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size);  	rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); -	rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, RXCSR1, reg);  	entry_priv = rt2x00dev->rx->entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); +	rt2x00mmio_register_read(rt2x00dev, RXCSR2, ®);  	rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); +	rt2x00mmio_register_write(rt2x00dev, RXCSR2, reg);  	return 0;  } @@ -821,30 +904,30 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; -	rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002); -	rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002); -	rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00020002); -	rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002); +	rt2x00mmio_register_write(rt2x00dev, PSCSR0, 0x00020002); +	rt2x00mmio_register_write(rt2x00dev, PSCSR1, 0x00000002); +	rt2x00mmio_register_write(rt2x00dev, PSCSR2, 0x00020002); +	rt2x00mmio_register_write(rt2x00dev, PSCSR3, 0x00000002); -	rt2x00pci_register_read(rt2x00dev, TIMECSR, ®); +	rt2x00mmio_register_read(rt2x00dev, TIMECSR, ®);  	rt2x00_set_field32(®, TIMECSR_US_COUNT, 33);  	rt2x00_set_field32(®, TIMECSR_US_64_COUNT, 63);  	rt2x00_set_field32(®, TIMECSR_BEACON_EXPECT, 0); -	rt2x00pci_register_write(rt2x00dev, TIMECSR, reg); +	rt2x00mmio_register_write(rt2x00dev, TIMECSR, reg); -	rt2x00pci_register_read(rt2x00dev, CSR9, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR9, ®);  	rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT,  			   rt2x00dev->rx->data_size / 128); -	rt2x00pci_register_write(rt2x00dev, CSR9, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR9, reg);  	/*  	 * Always use CWmin and CWmax set in descriptor.  	 */ -	rt2x00pci_register_read(rt2x00dev, CSR11, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR11, ®);  	rt2x00_set_field32(®, CSR11_CW_SELECT, 0); -	rt2x00pci_register_write(rt2x00dev, CSR11, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR11, reg); -	rt2x00pci_register_read(rt2x00dev, CSR14, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR14, ®);  	rt2x00_set_field32(®, CSR14_TSF_COUNT, 0);  	rt2x00_set_field32(®, CSR14_TSF_SYNC, 0);  	rt2x00_set_field32(®, CSR14_TBCN, 0); @@ -853,11 +936,11 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);  	rt2x00_set_field32(®, CSR14_CFP_COUNT_PRELOAD, 0);  	rt2x00_set_field32(®, CSR14_TBCM_PRELOAD, 0); -	rt2x00pci_register_write(rt2x00dev, CSR14, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR14, reg); -	rt2x00pci_register_write(rt2x00dev, CNT3, 0); +	rt2x00mmio_register_write(rt2x00dev, CNT3, 0); -	rt2x00pci_register_read(rt2x00dev, TXCSR8, ®); +	rt2x00mmio_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); @@ -866,30 +949,30 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)  	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); +	rt2x00mmio_register_write(rt2x00dev, TXCSR8, reg); -	rt2x00pci_register_read(rt2x00dev, ARTCSR0, ®); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, ARTCSR0, reg); -	rt2x00pci_register_read(rt2x00dev, ARTCSR1, ®); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, ARTCSR1, reg); -	rt2x00pci_register_read(rt2x00dev, ARTCSR2, ®); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, ARTCSR2, reg); -	rt2x00pci_register_read(rt2x00dev, RXCSR3, ®); +	rt2x00mmio_register_read(rt2x00dev, RXCSR3, ®);  	rt2x00_set_field32(®, RXCSR3_BBP_ID0, 47); /* CCK Signal */  	rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1);  	rt2x00_set_field32(®, RXCSR3_BBP_ID1, 51); /* Rssi */ @@ -898,9 +981,9 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1);  	rt2x00_set_field32(®, RXCSR3_BBP_ID3, 51); /* RSSI */  	rt2x00_set_field32(®, RXCSR3_BBP_ID3_VALID, 1); -	rt2x00pci_register_write(rt2x00dev, RXCSR3, reg); +	rt2x00mmio_register_write(rt2x00dev, RXCSR3, reg); -	rt2x00pci_register_read(rt2x00dev, PCICSR, ®); +	rt2x00mmio_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); @@ -908,54 +991,54 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)  	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); +	rt2x00mmio_register_write(rt2x00dev, PCICSR, reg); -	rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); +	rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); -	rt2x00pci_register_write(rt2x00dev, GPIOCSR, 0x0000ff00); -	rt2x00pci_register_write(rt2x00dev, TESTCSR, 0x000000f0); +	rt2x00mmio_register_write(rt2x00dev, GPIOCSR, 0x0000ff00); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, MACCSR0, 0x00213223); +	rt2x00mmio_register_write(rt2x00dev, MACCSR1, 0x00235518); -	rt2x00pci_register_read(rt2x00dev, MACCSR2, ®); +	rt2x00mmio_register_read(rt2x00dev, MACCSR2, ®);  	rt2x00_set_field32(®, MACCSR2_DELAY, 64); -	rt2x00pci_register_write(rt2x00dev, MACCSR2, reg); +	rt2x00mmio_register_write(rt2x00dev, MACCSR2, reg); -	rt2x00pci_register_read(rt2x00dev, RALINKCSR, ®); +	rt2x00mmio_register_read(rt2x00dev, RALINKCSR, ®);  	rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17);  	rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 26);  	rt2x00_set_field32(®, RALINKCSR_AR_BBP_VALID0, 1);  	rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA1, 0);  	rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID1, 26);  	rt2x00_set_field32(®, RALINKCSR_AR_BBP_VALID1, 1); -	rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg); +	rt2x00mmio_register_write(rt2x00dev, RALINKCSR, reg); -	rt2x00pci_register_write(rt2x00dev, BBPCSR1, 0x82188200); +	rt2x00mmio_register_write(rt2x00dev, BBPCSR1, 0x82188200); -	rt2x00pci_register_write(rt2x00dev, TXACKCSR0, 0x00000020); +	rt2x00mmio_register_write(rt2x00dev, TXACKCSR0, 0x00000020); -	rt2x00pci_register_read(rt2x00dev, CSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR1, ®);  	rt2x00_set_field32(®, CSR1_SOFT_RESET, 1);  	rt2x00_set_field32(®, CSR1_BBP_RESET, 0);  	rt2x00_set_field32(®, CSR1_HOST_READY, 0); -	rt2x00pci_register_write(rt2x00dev, CSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR1, reg); -	rt2x00pci_register_read(rt2x00dev, CSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR1, ®);  	rt2x00_set_field32(®, CSR1_SOFT_RESET, 0);  	rt2x00_set_field32(®, CSR1_HOST_READY, 1); -	rt2x00pci_register_write(rt2x00dev, CSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR1, reg);  	/*  	 * We must clear the FCS and FIFO error count.  	 * These registers are cleared on read,  	 * so we may pass a useless variable to store the value.  	 */ -	rt2x00pci_register_read(rt2x00dev, CNT0, ®); -	rt2x00pci_register_read(rt2x00dev, CNT4, ®); +	rt2x00mmio_register_read(rt2x00dev, CNT0, ®); +	rt2x00mmio_register_read(rt2x00dev, CNT4, ®);  	return 0;  } @@ -972,7 +1055,7 @@ static int rt2500pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)  		udelay(REGISTER_BUSY_DELAY);  	} -	ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); +	rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");  	return -EACCES;  } @@ -1033,44 +1116,46 @@ static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev)  /*   * Device state switch handlers.   */ -static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev, -				enum dev_state state) -{ -	u32 reg; - -	rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); -	rt2x00_set_field32(®, RXCSR0_DISABLE_RX, -			   (state == STATE_RADIO_RX_OFF)); -	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} -  static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,  				 enum dev_state state)  { -	int mask = (state == STATE_RADIO_IRQ_OFF) || -		   (state == STATE_RADIO_IRQ_OFF_ISR); +	int mask = (state == STATE_RADIO_IRQ_OFF);  	u32 reg; +	unsigned long flags;  	/*  	 * When interrupts are being enabled, the interrupt registers  	 * should clear the register to assure a clean state.  	 */  	if (state == STATE_RADIO_IRQ_ON) { -		rt2x00pci_register_read(rt2x00dev, CSR7, ®); -		rt2x00pci_register_write(rt2x00dev, CSR7, reg); +		rt2x00mmio_register_read(rt2x00dev, CSR7, ®); +		rt2x00mmio_register_write(rt2x00dev, CSR7, reg);  	}  	/*  	 * Only toggle the interrupts bits we are going to use.  	 * Non-checked interrupt bits are disabled by default.  	 */ -	rt2x00pci_register_read(rt2x00dev, CSR8, ®); +	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); + +	rt2x00mmio_register_read(rt2x00dev, CSR8, ®);  	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); +	rt2x00mmio_register_write(rt2x00dev, CSR8, reg); + +	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); + +	if (state == STATE_RADIO_IRQ_OFF) { +		/* +		 * Ensure that all tasklets are finished. +		 */ +		tasklet_kill(&rt2x00dev->txstatus_tasklet); +		tasklet_kill(&rt2x00dev->rxdone_tasklet); +		tasklet_kill(&rt2x00dev->tbtt_tasklet); +	}  }  static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) @@ -1091,7 +1176,7 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev)  	/*  	 * Disable power  	 */ -	rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); +	rt2x00mmio_register_write(rt2x00dev, PWRCSR0, 0);  }  static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, @@ -1105,12 +1190,12 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,  	put_to_sleep = (state != STATE_AWAKE); -	rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, PWRCSR1, ®);  	rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1);  	rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state);  	rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state);  	rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep); -	rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);  	/*  	 * Device is not guaranteed to be in the requested state yet. @@ -1118,12 +1203,12 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev,  	 * device has entered the correct state.  	 */  	for (i = 0; i < REGISTER_BUSY_COUNT; i++) { -		rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®2); +		rt2x00mmio_register_read(rt2x00dev, PWRCSR1, ®2);  		bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE);  		rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE);  		if (bbp_state == state && rf_state == state)  			return 0; -		rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); +		rt2x00mmio_register_write(rt2x00dev, PWRCSR1, reg);  		msleep(10);  	} @@ -1142,14 +1227,8 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *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); -		break;  	case STATE_RADIO_IRQ_ON: -	case STATE_RADIO_IRQ_ON_ISR:  	case STATE_RADIO_IRQ_OFF: -	case STATE_RADIO_IRQ_OFF_ISR:  		rt2500pci_toggle_irq(rt2x00dev, state);  		break;  	case STATE_DEEP_SLEEP: @@ -1164,8 +1243,8 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,  	}  	if (unlikely(retval)) -		ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", -		      state, retval); +		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", +			   state, retval);  	return retval;  } @@ -1177,7 +1256,7 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,  				    struct txentry_desc *txdesc)  {  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	__le32 *txd = entry_priv->desc;  	u32 word; @@ -1196,10 +1275,12 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,  	rt2x00_desc_write(txd, 2, word);  	rt2x00_desc_read(txd, 3, &word); -	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal); -	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service); -	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, txdesc->length_low); -	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, txdesc->length_high); +	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal); +	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service); +	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, +			   txdesc->u.plcp.length_low); +	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, +			   txdesc->u.plcp.length_high);  	rt2x00_desc_write(txd, 3, word);  	rt2x00_desc_read(txd, 10, &word); @@ -1224,7 +1305,7 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,  	rt2x00_set_field32(&word, TXD_W0_OFDM,  			   (txdesc->rate_mode == RATE_MODE_OFDM));  	rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1); -	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); +	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);  	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,  			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));  	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); @@ -1251,11 +1332,14 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,  	 * Disable beaconing while we are reloading the beacon data,  	 * otherwise we might be sending out invalid data.  	 */ -	rt2x00pci_register_read(rt2x00dev, CSR14, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR14, ®);  	rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); -	rt2x00pci_register_write(rt2x00dev, CSR14, reg); +	rt2x00mmio_register_write(rt2x00dev, CSR14, reg); -	rt2x00queue_map_txskb(entry); +	if (rt2x00queue_map_txskb(entry)) { +		rt2x00_err(rt2x00dev, "Fail to map beacon, aborting\n"); +		goto out; +	}  	/*  	 * Write the TX descriptor for the beacon. @@ -1266,40 +1350,12 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,  	 * Dump beacon to userspace through debugfs.  	 */  	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb); - +out:  	/*  	 * Enable beaconing again.  	 */ -	rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); -	rt2x00_set_field32(®, CSR14_TBCN, 1);  	rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); -	rt2x00pci_register_write(rt2x00dev, CSR14, reg); -} - -static void rt2500pci_kick_tx_queue(struct data_queue *queue) -{ -	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; -	u32 reg; - -	rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); -	rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE)); -	rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK)); -	rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM)); -	rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); -} - -static void rt2500pci_kill_tx_queue(struct data_queue *queue) -{ -	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; -	u32 reg; - -	if (queue->qid == QID_BEACON) { -		rt2x00pci_register_write(rt2x00dev, CSR14, 0); -	} else { -		rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); -		rt2x00_set_field32(®, TXCSR0_ABORT, 1); -		rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); -	} +	rt2x00mmio_register_write(rt2x00dev, CSR14, reg);  }  /* @@ -1308,7 +1364,7 @@ static void rt2500pci_kill_tx_queue(struct data_queue *queue)  static void rt2500pci_fill_rxdone(struct queue_entry *entry,  				  struct rxdone_entry_desc *rxdesc)  { -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	u32 word0;  	u32 word2; @@ -1345,8 +1401,8 @@ static void rt2500pci_fill_rxdone(struct queue_entry *entry,  static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,  			     const enum data_queue_qid queue_idx)  { -	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); -	struct queue_entry_priv_pci *entry_priv; +	struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx); +	struct queue_entry_priv_mmio *entry_priv;  	struct queue_entry *entry;  	struct txdone_entry_desc txdesc;  	u32 word; @@ -1381,65 +1437,80 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,  	}  } -static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance) +static inline void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, +					      struct rt2x00_field32 irq_field)  { -	struct rt2x00_dev *rt2x00dev = dev_instance; -	u32 reg = rt2x00dev->irqvalue[0]; +	u32 reg;  	/* -	 * Handle interrupts, walk through all bits -	 * and run the tasks, the bits are checked in order of -	 * priority. +	 * Enable a single interrupt. The interrupt mask register +	 * access needs locking.  	 */ +	spin_lock_irq(&rt2x00dev->irqmask_lock); -	/* -	 * 1 - Beacon timer expired interrupt. -	 */ -	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) -		rt2x00lib_beacondone(rt2x00dev); +	rt2x00mmio_register_read(rt2x00dev, CSR8, ®); +	rt2x00_set_field32(®, irq_field, 0); +	rt2x00mmio_register_write(rt2x00dev, CSR8, reg); -	/* -	 * 2 - Rx ring done interrupt. -	 */ -	if (rt2x00_get_field32(reg, CSR7_RXDONE)) -		rt2x00pci_rxdone(rt2x00dev); +	spin_unlock_irq(&rt2x00dev->irqmask_lock); +} -	/* -	 * 3 - Atim ring transmit done interrupt. -	 */ -	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING)) -		rt2500pci_txdone(rt2x00dev, QID_ATIM); +static void rt2500pci_txstatus_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	u32 reg;  	/* -	 * 4 - Priority ring transmit done interrupt. +	 * Handle all tx queues.  	 */ -	if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) -		rt2500pci_txdone(rt2x00dev, QID_AC_BE); +	rt2500pci_txdone(rt2x00dev, QID_ATIM); +	rt2500pci_txdone(rt2x00dev, QID_AC_VO); +	rt2500pci_txdone(rt2x00dev, QID_AC_VI);  	/* -	 * 5 - Tx ring transmit done interrupt. +	 * Enable all TXDONE interrupts again.  	 */ -	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) -		rt2500pci_txdone(rt2x00dev, QID_AC_BK); +	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) { +		spin_lock_irq(&rt2x00dev->irqmask_lock); -	/* Enable interrupts again. */ -	rt2x00dev->ops->lib->set_device_state(rt2x00dev, -					      STATE_RADIO_IRQ_ON_ISR); +		rt2x00mmio_register_read(rt2x00dev, CSR8, ®); +		rt2x00_set_field32(®, CSR8_TXDONE_TXRING, 0); +		rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, 0); +		rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, 0); +		rt2x00mmio_register_write(rt2x00dev, CSR8, reg); -	return IRQ_HANDLED; +		spin_unlock_irq(&rt2x00dev->irqmask_lock); +	} +} + +static void rt2500pci_tbtt_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	rt2x00lib_beacondone(rt2x00dev); +	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE); +} + +static void rt2500pci_rxdone_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	if (rt2x00mmio_rxdone(rt2x00dev)) +		tasklet_schedule(&rt2x00dev->rxdone_tasklet); +	else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);  }  static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)  {  	struct rt2x00_dev *rt2x00dev = dev_instance; -	u32 reg; +	u32 reg, mask;  	/*  	 * Get the interrupt sources & saved to local variable.  	 * Write register value back to clear pending interrupts.  	 */ -	rt2x00pci_register_read(rt2x00dev, CSR7, ®); -	rt2x00pci_register_write(rt2x00dev, CSR7, reg); +	rt2x00mmio_register_read(rt2x00dev, CSR7, ®); +	rt2x00mmio_register_write(rt2x00dev, CSR7, reg);  	if (!reg)  		return IRQ_NONE; @@ -1447,14 +1518,42 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)  	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))  		return IRQ_HANDLED; -	/* Store irqvalues for use in the interrupt thread. */ -	rt2x00dev->irqvalue[0] = reg; +	mask = reg; + +	/* +	 * Schedule tasklets for interrupt handling. +	 */ +	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) +		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); + +	if (rt2x00_get_field32(reg, CSR7_RXDONE)) +		tasklet_schedule(&rt2x00dev->rxdone_tasklet); + +	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) || +	    rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) || +	    rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) { +		tasklet_schedule(&rt2x00dev->txstatus_tasklet); +		/* +		 * Mask out all txdone interrupts. +		 */ +		rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1); +		rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1); +		rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1); +	} + +	/* +	 * Disable all interrupts for which a tasklet was scheduled right now, +	 * the tasklet will reenable the appropriate interrupts. +	 */ +	spin_lock(&rt2x00dev->irqmask_lock); + +	rt2x00mmio_register_read(rt2x00dev, CSR8, ®); +	reg |= mask; +	rt2x00mmio_register_write(rt2x00dev, CSR8, reg); -	/* Disable interrupts, will be enabled again in the interrupt thread. */ -	rt2x00dev->ops->lib->set_device_state(rt2x00dev, -					      STATE_RADIO_IRQ_OFF_ISR); +	spin_unlock(&rt2x00dev->irqmask_lock); -	return IRQ_WAKE_THREAD; +	return IRQ_HANDLED;  }  /* @@ -1467,7 +1566,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  	u16 word;  	u8 *mac; -	rt2x00pci_register_read(rt2x00dev, CSR21, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR21, ®);  	eeprom.data = rt2x00dev;  	eeprom.register_read = rt2500pci_eepromregister_read; @@ -1487,8 +1586,8 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  	 */  	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);  	if (!is_valid_ether_addr(mac)) { -		random_ether_addr(mac); -		EEPROM(rt2x00dev, "MAC: %pM\n", mac); +		eth_random_addr(mac); +		rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); @@ -1504,7 +1603,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);  		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); -		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); @@ -1513,7 +1612,7 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);  		rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); -		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word); @@ -1521,7 +1620,8 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,  				   DEFAULT_RSSI_OFFSET);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word); -		EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n", +				  word);  	}  	return 0; @@ -1542,7 +1642,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Identify RF chipset.  	 */  	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); -	rt2x00pci_register_read(rt2x00dev, CSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR0, ®);  	rt2x00_set_chip(rt2x00dev, RT2560, value,  			rt2x00_get_field32(reg, CSR0_REVISION)); @@ -1552,7 +1652,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	    !rt2x00_rf(rt2x00dev, RF2525) &&  	    !rt2x00_rf(rt2x00dev, RF2525E) &&  	    !rt2x00_rf(rt2x00dev, RF5222)) { -		ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); +		rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");  		return -ENODEV;  	} @@ -1581,15 +1681,20 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	/*  	 * Detect if this device has an hardware controlled radio.  	 */ -	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) { +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); +		/* +		 * On this device RFKILL initialized during probe does not work. +		 */ +		__set_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags); +	}  	/*  	 * Check if the BBP tuning should be enabled.  	 */  	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);  	if (!rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE)) -		__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); +		__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);  	/*  	 * Read the RSSI <-> dBm offset information. @@ -1777,6 +1882,11 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  						   EEPROM_MAC_ADDR_0));  	/* +	 * Disable powersaving as default. +	 */ +	rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + +	/*  	 * Initialize hw_mode information.  	 */  	spec->supported_bands = SUPPORT_BAND_2GHZ; @@ -1831,6 +1941,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -1844,6 +1955,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00mmio_register_read(rt2x00dev, GPIOCSR, ®); +	rt2x00_set_field32(®, GPIOCSR_DIR0, 1); +	rt2x00mmio_register_write(rt2x00dev, GPIOCSR, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2500pci_probe_hw_mode(rt2x00dev); @@ -1853,8 +1972,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)  	/*  	 * This device requires the atim queue and DMA-mapped skbs.  	 */ -	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); +	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags);  	/*  	 * Set the rssi offset. @@ -1867,15 +1987,16 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)  /*   * IEEE80211 stack callback functions.   */ -static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw) +static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw, +			     struct ieee80211_vif *vif)  {  	struct rt2x00_dev *rt2x00dev = hw->priv;  	u64 tsf;  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, CSR17, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR17, ®);  	tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; -	rt2x00pci_register_read(rt2x00dev, CSR16, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR16, ®);  	tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER);  	return tsf; @@ -1886,7 +2007,7 @@ static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)  	struct rt2x00_dev *rt2x00dev = hw->priv;  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, CSR15, ®); +	rt2x00mmio_register_read(rt2x00dev, CSR15, ®);  	return rt2x00_get_field32(reg, CSR15_BEACON_SENT);  } @@ -1907,14 +2028,20 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {  	.tx_last_beacon		= rt2500pci_tx_last_beacon,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.flush			= rt2x00mac_flush, +	.set_antenna		= rt2x00mac_set_antenna, +	.get_antenna		= rt2x00mac_get_antenna, +	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {  	.irq_handler		= rt2500pci_interrupt, -	.irq_handler_thread	= rt2500pci_interrupt_thread, +	.txstatus_tasklet	= rt2500pci_txstatus_tasklet, +	.tbtt_tasklet		= rt2500pci_tbtt_tasklet, +	.rxdone_tasklet		= rt2500pci_rxdone_tasklet,  	.probe_hw		= rt2500pci_probe_hw, -	.initialize		= rt2x00pci_initialize, -	.uninitialize		= rt2x00pci_uninitialize, +	.initialize		= rt2x00mmio_initialize, +	.uninitialize		= rt2x00mmio_uninitialize,  	.get_entry_state	= rt2500pci_get_entry_state,  	.clear_entry		= rt2500pci_clear_entry,  	.set_device_state	= rt2500pci_set_device_state, @@ -1922,10 +2049,12 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {  	.link_stats		= rt2500pci_link_stats,  	.reset_tuner		= rt2500pci_reset_tuner,  	.link_tuner		= rt2500pci_link_tuner, +	.start_queue		= rt2500pci_start_queue, +	.kick_queue		= rt2500pci_kick_queue, +	.stop_queue		= rt2500pci_stop_queue, +	.flush_queue		= rt2x00mmio_flush_queue,  	.write_tx_desc		= rt2500pci_write_tx_desc,  	.write_beacon		= rt2500pci_write_beacon, -	.kick_tx_queue		= rt2500pci_kick_tx_queue, -	.kill_tx_queue		= rt2500pci_kill_tx_queue,  	.fill_rxdone		= rt2500pci_fill_rxdone,  	.config_filter		= rt2500pci_config_filter,  	.config_intf		= rt2500pci_config_intf, @@ -1934,46 +2063,53 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {  	.config			= rt2500pci_config,  }; -static const struct data_queue_desc rt2500pci_queue_rx = { -	.entry_num		= 32, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= RXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; +static void rt2500pci_queue_init(struct data_queue *queue) +{ +	switch (queue->qid) { +	case QID_RX: +		queue->limit = 32; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = RXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; -static const struct data_queue_desc rt2500pci_queue_tx = { -	.entry_num		= 32, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		queue->limit = 32; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; -static const struct data_queue_desc rt2500pci_queue_bcn = { -	.entry_num		= 1, -	.data_size		= MGMT_FRAME_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; +	case QID_BEACON: +		queue->limit = 1; +		queue->data_size = MGMT_FRAME_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; -static const struct data_queue_desc rt2500pci_queue_atim = { -	.entry_num		= 8, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; +	case QID_ATIM: +		queue->limit = 8; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; + +	default: +		BUG(); +		break; +	} +}  static const struct rt2x00_ops rt2500pci_ops = {  	.name			= KBUILD_MODNAME, -	.max_sta_intf		= 1,  	.max_ap_intf		= 1,  	.eeprom_size		= EEPROM_SIZE,  	.rf_size		= RF_SIZE,  	.tx_queues		= NUM_TX_QUEUES, -	.extra_tx_headroom	= 0, -	.rx			= &rt2500pci_queue_rx, -	.tx			= &rt2500pci_queue_tx, -	.bcn			= &rt2500pci_queue_bcn, -	.atim			= &rt2500pci_queue_atim, +	.queue_init		= rt2500pci_queue_init,  	.lib			= &rt2500pci_rt2x00_ops,  	.hw			= &rt2500pci_mac80211_ops,  #ifdef CONFIG_RT2X00_LIB_DEBUGFS @@ -1985,7 +2121,7 @@ static const struct rt2x00_ops rt2500pci_ops = {   * RT2500pci module information.   */  static DEFINE_PCI_DEVICE_TABLE(rt2500pci_device_table) = { -	{ PCI_DEVICE(0x1814, 0x0201), PCI_DEVICE_DATA(&rt2500pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0201) },  	{ 0, }  }; @@ -1996,24 +2132,19 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards");  MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);  MODULE_LICENSE("GPL"); +static int rt2500pci_probe(struct pci_dev *pci_dev, +			   const struct pci_device_id *id) +{ +	return rt2x00pci_probe(pci_dev, &rt2500pci_ops); +} +  static struct pci_driver rt2500pci_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt2500pci_device_table, -	.probe		= rt2x00pci_probe, -	.remove		= __devexit_p(rt2x00pci_remove), +	.probe		= rt2500pci_probe, +	.remove		= rt2x00pci_remove,  	.suspend	= rt2x00pci_suspend,  	.resume		= rt2x00pci_resume,  }; -static int __init rt2500pci_init(void) -{ -	return pci_register_driver(&rt2500pci_driver); -} - -static void __exit rt2500pci_exit(void) -{ -	pci_unregister_driver(&rt2500pci_driver); -} - -module_init(rt2500pci_init); -module_exit(rt2500pci_exit); +module_pci_driver(rt2500pci_driver); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index 2aad7ba8a10..573e87bcc55 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -789,16 +787,18 @@  /*   * GPIOCSR: GPIO control register. + *	GPIOCSR_VALx: GPIO value + *	GPIOCSR_DIRx: GPIO direction: 0 = output; 1 = input   */  #define GPIOCSR				0x0120 -#define GPIOCSR_BIT0			FIELD32(0x00000001) -#define GPIOCSR_BIT1			FIELD32(0x00000002) -#define GPIOCSR_BIT2			FIELD32(0x00000004) -#define GPIOCSR_BIT3			FIELD32(0x00000008) -#define GPIOCSR_BIT4			FIELD32(0x00000010) -#define GPIOCSR_BIT5			FIELD32(0x00000020) -#define GPIOCSR_BIT6			FIELD32(0x00000040) -#define GPIOCSR_BIT7			FIELD32(0x00000080) +#define GPIOCSR_VAL0			FIELD32(0x00000001) +#define GPIOCSR_VAL1			FIELD32(0x00000002) +#define GPIOCSR_VAL2			FIELD32(0x00000004) +#define GPIOCSR_VAL3			FIELD32(0x00000008) +#define GPIOCSR_VAL4			FIELD32(0x00000010) +#define GPIOCSR_VAL5			FIELD32(0x00000020) +#define GPIOCSR_VAL6			FIELD32(0x00000040) +#define GPIOCSR_VAL7			FIELD32(0x00000080)  #define GPIOCSR_DIR0			FIELD32(0x00000100)  #define GPIOCSR_DIR1			FIELD32(0x00000200)  #define GPIOCSR_DIR2			FIELD32(0x00000400) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 8152fec3175..d849d590de2 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -26,7 +24,6 @@  #include <linux/delay.h>  #include <linux/etherdevice.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/slab.h> @@ -39,7 +36,7 @@  /*   * Allow hardware encryption to be disabled.   */ -static int modparam_nohwcrypt; +static bool modparam_nohwcrypt;  module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);  MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -134,8 +131,8 @@ static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,  		udelay(REGISTER_BUSY_DELAY);  	} -	ERROR(rt2x00dev, "Indirect register access failed: " -	      "offset=0x%.08x, value=0x%.08x\n", offset, *reg); +	rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n", +		   offset, *reg);  	*reg = ~0;  	return 0; @@ -283,7 +280,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)  	u16 reg;  	rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); -	return rt2x00_get_field32(reg, MAC_CSR19_BIT7); +	return rt2x00_get_field16(reg, MAC_CSR19_VAL7);  }  #ifdef CONFIG_RT2X00_LIB_LEDS @@ -478,9 +475,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,  		rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);  		rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); -		rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1);  		rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); -		rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1);  		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);  	} @@ -739,6 +734,55 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev,  }  /* + * Queue handlers. + */ +static void rt2500usb_start_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u16 reg; + +	switch (queue->qid) { +	case QID_RX: +		rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); +		rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 0); +		rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); +		break; +	case QID_BEACON: +		rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); +		rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); +		rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); +		rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1); +		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); +		break; +	default: +		break; +	} +} + +static void rt2500usb_stop_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u16 reg; + +	switch (queue->qid) { +	case QID_RX: +		rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); +		rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 1); +		rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); +		break; +	case QID_BEACON: +		rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); +		rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); +		rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); +		rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); +		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); +		break; +	default: +		break; +	} +} + +/*   * Initialization functions.   */  static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) @@ -869,7 +913,7 @@ static int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)  		udelay(REGISTER_BUSY_DELAY);  	} -	ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); +	rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");  	return -EACCES;  } @@ -931,17 +975,6 @@ static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev)  /*   * Device state switch handlers.   */ -static void rt2500usb_toggle_rx(struct rt2x00_dev *rt2x00dev, -				enum dev_state state) -{ -	u16 reg; - -	rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); -	rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, -			   (state == STATE_RADIO_RX_OFF)); -	rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); -} -  static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)  {  	/* @@ -1017,14 +1050,8 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *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); -		break;  	case STATE_RADIO_IRQ_ON: -	case STATE_RADIO_IRQ_ON_ISR:  	case STATE_RADIO_IRQ_OFF: -	case STATE_RADIO_IRQ_OFF_ISR:  		/* No support, but no error either */  		break;  	case STATE_DEEP_SLEEP: @@ -1039,8 +1066,8 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,  	}  	if (unlikely(retval)) -		ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", -		      state, retval); +		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", +			   state, retval);  	return retval;  } @@ -1070,7 +1097,7 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,  			   (txdesc->rate_mode == RATE_MODE_OFDM));  	rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,  			   test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); -	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); +	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);  	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);  	rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);  	rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx); @@ -1084,10 +1111,12 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,  	rt2x00_desc_write(txd, 1, word);  	rt2x00_desc_read(txd, 2, &word); -	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); -	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); -	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); -	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); +	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal); +	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service); +	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, +			   txdesc->u.plcp.length_low); +	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, +			   txdesc->u.plcp.length_high);  	rt2x00_desc_write(txd, 2, word);  	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { @@ -1203,14 +1232,6 @@ static int rt2500usb_get_tx_data_len(struct queue_entry *entry)  	return length;  } -static void rt2500usb_kill_tx_queue(struct data_queue *queue) -{ -	if (queue->qid == QID_BEACON) -		rt2500usb_register_write(queue->rt2x00dev, TXRX_CSR19, 0); - -	rt2x00usb_kill_tx_queue(queue); -} -  /*   * RX control handlers   */ @@ -1328,8 +1349,8 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  	 */  	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);  	if (!is_valid_ether_addr(mac)) { -		random_ether_addr(mac); -		EEPROM(rt2x00dev, "MAC: %pM\n", mac); +		eth_random_addr(mac); +		rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); @@ -1345,7 +1366,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);  		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); -		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); @@ -1354,7 +1375,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0);  		rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); -		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word); @@ -1362,14 +1383,15 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI,  				   DEFAULT_RSSI_OFFSET);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word); -		EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "Calibrate offset: 0x%04x\n", +				  word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &word);  	if (word == 0xffff) {  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_THRESHOLD, 45);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE, word); -		EEPROM(rt2x00dev, "BBPtune: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune: 0x%04x\n", word);  	}  	/* @@ -1384,7 +1406,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40);  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); -		EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);  	} else {  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); @@ -1395,7 +1417,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_LOW, 0x48);  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word); -		EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r17: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word); @@ -1403,7 +1425,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_LOW, 0x40);  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_HIGH, 0x80);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R24, word); -		EEPROM(rt2x00dev, "BBPtune r24: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r24: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &word); @@ -1411,7 +1433,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_LOW, 0x40);  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_HIGH, 0x50);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R25, word); -		EEPROM(rt2x00dev, "BBPtune r25: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r25: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &word); @@ -1419,7 +1441,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_LOW, 0x60);  		rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_HIGH, 0x6d);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R61, word); -		EEPROM(rt2x00dev, "BBPtune r61: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "BBPtune r61: 0x%04x\n", word);  	}  	return 0; @@ -1444,7 +1466,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_chip(rt2x00dev, RT2570, value, reg);  	if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) { -		ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); +		rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");  		return -ENODEV;  	} @@ -1454,7 +1476,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)  	    !rt2x00_rf(rt2x00dev, RF2525) &&  	    !rt2x00_rf(rt2x00dev, RF2525E) &&  	    !rt2x00_rf(rt2x00dev, RF5222)) { -		ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); +		rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");  		return -ENODEV;  	} @@ -1495,7 +1517,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Detect if this device has an hardware controlled radio.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);  	/*  	 * Read the RSSI <-> dBm offset information. @@ -1684,6 +1706,11 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	    IEEE80211_HW_SUPPORTS_PS |  	    IEEE80211_HW_PS_NULLFUNC_STACK; +	/* +	 * Disable powersaving as default. +	 */ +	rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; +  	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);  	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,  				rt2x00_eeprom_addr(rt2x00dev, @@ -1744,6 +1771,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u16 reg;  	/*  	 * Allocate eeprom data. @@ -1757,6 +1785,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); +	rt2x00_set_field16(®, MAC_CSR19_DIR0, 0); +	rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2500usb_probe_hw_mode(rt2x00dev); @@ -1766,13 +1802,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)  	/*  	 * This device requires the atim queue  	 */ -	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); +	__set_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags);  	if (!modparam_nohwcrypt) { -		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); -		__set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); +		__set_bit(REQUIRE_COPY_IV, &rt2x00dev->cap_flags);  	} -	__set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); +	__set_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);  	/*  	 * Set the rssi offset. @@ -1799,6 +1836,10 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {  	.conf_tx		= rt2x00mac_conf_tx,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.flush			= rt2x00mac_flush, +	.set_antenna		= rt2x00mac_set_antenna, +	.get_antenna		= rt2x00mac_get_antenna, +	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { @@ -1811,11 +1852,13 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {  	.link_stats		= rt2500usb_link_stats,  	.reset_tuner		= rt2500usb_reset_tuner,  	.watchdog		= rt2x00usb_watchdog, +	.start_queue		= rt2500usb_start_queue, +	.kick_queue		= rt2x00usb_kick_queue, +	.stop_queue		= rt2500usb_stop_queue, +	.flush_queue		= rt2x00usb_flush_queue,  	.write_tx_desc		= rt2500usb_write_tx_desc,  	.write_beacon		= rt2500usb_write_beacon,  	.get_tx_data_len	= rt2500usb_get_tx_data_len, -	.kick_tx_queue		= rt2x00usb_kick_tx_queue, -	.kill_tx_queue		= rt2500usb_kill_tx_queue,  	.fill_rxdone		= rt2500usb_fill_rxdone,  	.config_shared_key	= rt2500usb_config_key,  	.config_pairwise_key	= rt2500usb_config_key, @@ -1826,46 +1869,53 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {  	.config			= rt2500usb_config,  }; -static const struct data_queue_desc rt2500usb_queue_rx = { -	.entry_num		= 32, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= RXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_usb), -}; +static void rt2500usb_queue_init(struct data_queue *queue) +{ +	switch (queue->qid) { +	case QID_RX: +		queue->limit = 32; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = RXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_usb); +		break; -static const struct data_queue_desc rt2500usb_queue_tx = { -	.entry_num		= 32, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_usb), -}; +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		queue->limit = 32; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_usb); +		break; -static const struct data_queue_desc rt2500usb_queue_bcn = { -	.entry_num		= 1, -	.data_size		= MGMT_FRAME_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_usb_bcn), -}; +	case QID_BEACON: +		queue->limit = 1; +		queue->data_size = MGMT_FRAME_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_usb_bcn); +		break; -static const struct data_queue_desc rt2500usb_queue_atim = { -	.entry_num		= 8, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_usb), -}; +	case QID_ATIM: +		queue->limit = 8; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_usb); +		break; + +	default: +		BUG(); +		break; +	} +}  static const struct rt2x00_ops rt2500usb_ops = {  	.name			= KBUILD_MODNAME, -	.max_sta_intf		= 1,  	.max_ap_intf		= 1,  	.eeprom_size		= EEPROM_SIZE,  	.rf_size		= RF_SIZE,  	.tx_queues		= NUM_TX_QUEUES, -	.extra_tx_headroom	= TXD_DESC_SIZE, -	.rx			= &rt2500usb_queue_rx, -	.tx			= &rt2500usb_queue_tx, -	.bcn			= &rt2500usb_queue_bcn, -	.atim			= &rt2500usb_queue_atim, +	.queue_init		= rt2500usb_queue_init,  	.lib			= &rt2500usb_rt2x00_ops,  	.hw			= &rt2500usb_mac80211_ops,  #ifdef CONFIG_RT2X00_LIB_DEBUGFS @@ -1878,58 +1928,54 @@ static const struct rt2x00_ops rt2500usb_ops = {   */  static struct usb_device_id rt2500usb_device_table[] = {  	/* ASUS */ -	{ USB_DEVICE(0x0b05, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1707), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0b05, 0x1706) }, +	{ USB_DEVICE(0x0b05, 0x1707) },  	/* Belkin */ -	{ USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x050d, 0x7051), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x050d, 0x7050) },	/* FCC ID: K7SF5D7050A ver. 2.x */ +	{ USB_DEVICE(0x050d, 0x7051) },  	/* Cisco Systems */ -	{ USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) }, -	/* CNet */ -	{ USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x13b1, 0x000d) }, +	{ USB_DEVICE(0x13b1, 0x0011) }, +	{ USB_DEVICE(0x13b1, 0x001a) },  	/* Conceptronic */ -	{ USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x14b2, 0x3c02) },  	/* D-LINK */ -	{ USB_DEVICE(0x2001, 0x3c00), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x2001, 0x3c00) },  	/* Gigabyte */ -	{ USB_DEVICE(0x1044, 0x8001), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x1044, 0x8007), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x1044, 0x8001) }, +	{ USB_DEVICE(0x1044, 0x8007) },  	/* Hercules */ -	{ USB_DEVICE(0x06f8, 0xe000), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x06f8, 0xe000) },  	/* Melco */ -	{ USB_DEVICE(0x0411, 0x005e), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ 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) }, +	{ USB_DEVICE(0x0411, 0x005e) }, +	{ USB_DEVICE(0x0411, 0x0066) }, +	{ USB_DEVICE(0x0411, 0x0067) }, +	{ USB_DEVICE(0x0411, 0x008b) }, +	{ USB_DEVICE(0x0411, 0x0097) },  	/* MSI */ -	{ USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x6869), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0db0, 0x6861) }, +	{ USB_DEVICE(0x0db0, 0x6865) }, +	{ USB_DEVICE(0x0db0, 0x6869) },  	/* Ralink */ -	{ USB_DEVICE(0x148f, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt2500usb_ops) }, -	{ USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x148f, 0x1706) }, +	{ USB_DEVICE(0x148f, 0x2570) }, +	{ USB_DEVICE(0x148f, 0x9020) },  	/* Sagem */ -	{ USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x079b, 0x004b) },  	/* Siemens */ -	{ USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0681, 0x3c06) },  	/* SMC */ -	{ USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0707, 0xee13) },  	/* Spairon */ -	{ USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x114b, 0x0110) },  	/* SURECOM */ -	{ USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0769, 0x11f3) },  	/* Trust */ -	{ USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0eb0, 0x9020) },  	/* VTech */ -	{ USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x0f88, 0x3012) },  	/* Zinwell */ -	{ USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) }, +	{ USB_DEVICE(0x5a57, 0x0260) },  	{ 0, }  }; @@ -1940,24 +1986,21 @@ MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards");  MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);  MODULE_LICENSE("GPL"); +static int rt2500usb_probe(struct usb_interface *usb_intf, +			   const struct usb_device_id *id) +{ +	return rt2x00usb_probe(usb_intf, &rt2500usb_ops); +} +  static struct usb_driver rt2500usb_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt2500usb_device_table, -	.probe		= rt2x00usb_probe, +	.probe		= rt2500usb_probe,  	.disconnect	= rt2x00usb_disconnect,  	.suspend	= rt2x00usb_suspend,  	.resume		= rt2x00usb_resume, +	.reset_resume	= rt2x00usb_resume, +	.disable_hub_initiated_lpm = 1,  }; -static int __init rt2500usb_init(void) -{ -	return usb_register(&rt2500usb_driver); -} - -static void __exit rt2500usb_exit(void) -{ -	usb_deregister(&rt2500usb_driver); -} - -module_init(rt2500usb_init); -module_exit(rt2500usb_exit); +module_usb_driver(rt2500usb_driver); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index b493306a7ee..afba0739c3b 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -187,16 +185,26 @@  /*   * MAC_CSR19: GPIO control register. + *	MAC_CSR19_VALx: GPIO value + *	MAC_CSR19_DIRx: GPIO direction: 0 = input; 1 = output   */  #define MAC_CSR19			0x0426 -#define MAC_CSR19_BIT0			FIELD32(0x0001) -#define MAC_CSR19_BIT1			FIELD32(0x0002) -#define MAC_CSR19_BIT2			FIELD32(0x0004) -#define MAC_CSR19_BIT3			FIELD32(0x0008) -#define MAC_CSR19_BIT4			FIELD32(0x0010) -#define MAC_CSR19_BIT5			FIELD32(0x0020) -#define MAC_CSR19_BIT6			FIELD32(0x0040) -#define MAC_CSR19_BIT7			FIELD32(0x0080) +#define MAC_CSR19_VAL0			FIELD16(0x0001) +#define MAC_CSR19_VAL1			FIELD16(0x0002) +#define MAC_CSR19_VAL2			FIELD16(0x0004) +#define MAC_CSR19_VAL3			FIELD16(0x0008) +#define MAC_CSR19_VAL4			FIELD16(0x0010) +#define MAC_CSR19_VAL5			FIELD16(0x0020) +#define MAC_CSR19_VAL6			FIELD16(0x0040) +#define MAC_CSR19_VAL7			FIELD16(0x0080) +#define MAC_CSR19_DIR0			FIELD16(0x0100) +#define MAC_CSR19_DIR1			FIELD16(0x0200) +#define MAC_CSR19_DIR2			FIELD16(0x0400) +#define MAC_CSR19_DIR3			FIELD16(0x0800) +#define MAC_CSR19_DIR4			FIELD16(0x1000) +#define MAC_CSR19_DIR5			FIELD16(0x2000) +#define MAC_CSR19_DIR6			FIELD16(0x4000) +#define MAC_CSR19_DIR7			FIELD16(0x8000)  /*   * MAC_CSR20: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index a81c4371835..a394a9a9591 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -21,9 +21,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -46,8 +44,16 @@   * RF2020 2.4G B/G   * RF3021 2.4G 1T2R   * RF3022 2.4G 2T2R - * RF3052 2.4G 2T2R - * RF3320 2.4G 1T1R + * RF3052 2.4G/5G 2T2R + * RF2853 2.4G/5G 3T3R + * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) + * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) + * RF3053 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) + * RF5592 2.4G/5G 2T2R + * RF3070 2.4G 1T1R + * RF5360 2.4G 1T1R + * RF5370 2.4G 1T1R + * RF5390 2.4G 1T1R   */  #define RF2820				0x0001  #define RF2850				0x0002 @@ -58,7 +64,18 @@  #define RF3021				0x0007  #define RF3022				0x0008  #define RF3052				0x0009 +#define RF2853				0x000a  #define RF3320				0x000b +#define RF3322				0x000c +#define RF3053				0x000d +#define RF5592				0x000f +#define RF3070				0x3070 +#define RF3290				0x3290 +#define RF5360				0x5360 +#define RF5370				0x5370 +#define RF5372				0x5372 +#define RF5390				0x5390 +#define RF5392				0x5392  /*   * Chipset revisions. @@ -71,11 +88,11 @@  #define REV_RT3071E			0x0211  #define REV_RT3090E			0x0211  #define REV_RT3390E			0x0211 +#define REV_RT3593E			0x0211 +#define REV_RT5390F			0x0502 +#define REV_RT5390R			0x1502 +#define REV_RT5592C			0x0221 -/* - * Signal information. - * Default offset is required for RSSI <-> dBm conversion. - */  #define DEFAULT_RSSI_OFFSET		120  /* @@ -84,11 +101,13 @@  #define CSR_REG_BASE			0x1000  #define CSR_REG_SIZE			0x0800  #define EEPROM_BASE			0x0000 -#define EEPROM_SIZE			0x0110 +#define EEPROM_SIZE			0x0200  #define BBP_BASE			0x0000 -#define BBP_SIZE			0x0080 +#define BBP_SIZE			0x00ff  #define RF_BASE				0x0004  #define RF_SIZE				0x0010 +#define RFCSR_BASE			0x0000 +#define RFCSR_SIZE			0x0040  /*   * Number of TX queues. @@ -99,6 +118,12 @@   * Registers.   */ + +/* + * MAC_CSR0_3290: MAC_CSR0 for RT3290 to identity MAC version number. + */ +#define MAC_CSR0_3290			0x0000 +  /*   * E2PROM_CSR: PCI EEPROM control register.   * RELOAD: Write 1 to reload eeprom content. @@ -115,6 +140,157 @@  #define E2PROM_CSR_RELOAD		FIELD32(0x00000080)  /* + * CMB_CTRL_CFG + */ +#define CMB_CTRL		0x0020 +#define AUX_OPT_BIT0		FIELD32(0x00000001) +#define AUX_OPT_BIT1		FIELD32(0x00000002) +#define AUX_OPT_BIT2		FIELD32(0x00000004) +#define AUX_OPT_BIT3		FIELD32(0x00000008) +#define AUX_OPT_BIT4		FIELD32(0x00000010) +#define AUX_OPT_BIT5		FIELD32(0x00000020) +#define AUX_OPT_BIT6		FIELD32(0x00000040) +#define AUX_OPT_BIT7		FIELD32(0x00000080) +#define AUX_OPT_BIT8		FIELD32(0x00000100) +#define AUX_OPT_BIT9		FIELD32(0x00000200) +#define AUX_OPT_BIT10		FIELD32(0x00000400) +#define AUX_OPT_BIT11		FIELD32(0x00000800) +#define AUX_OPT_BIT12		FIELD32(0x00001000) +#define AUX_OPT_BIT13		FIELD32(0x00002000) +#define AUX_OPT_BIT14		FIELD32(0x00004000) +#define AUX_OPT_BIT15		FIELD32(0x00008000) +#define LDO25_LEVEL		FIELD32(0x00030000) +#define LDO25_LARGEA		FIELD32(0x00040000) +#define LDO25_FRC_ON		FIELD32(0x00080000) +#define CMB_RSV			FIELD32(0x00300000) +#define XTAL_RDY		FIELD32(0x00400000) +#define PLL_LD			FIELD32(0x00800000) +#define LDO_CORE_LEVEL		FIELD32(0x0F000000) +#define LDO_BGSEL		FIELD32(0x30000000) +#define LDO3_EN			FIELD32(0x40000000) +#define LDO0_EN			FIELD32(0x80000000) + +/* + * EFUSE_CSR_3290: RT3290 EEPROM + */ +#define EFUSE_CTRL_3290			0x0024 + +/* + * EFUSE_DATA3 of 3290 + */ +#define EFUSE_DATA3_3290		0x0028 + +/* + * EFUSE_DATA2 of 3290 + */ +#define EFUSE_DATA2_3290		0x002c + +/* + * EFUSE_DATA1 of 3290 + */ +#define EFUSE_DATA1_3290		0x0030 + +/* + * EFUSE_DATA0 of 3290 + */ +#define EFUSE_DATA0_3290		0x0034 + +/* + * OSC_CTRL_CFG + * Ring oscillator configuration + */ +#define OSC_CTRL		0x0038 +#define OSC_REF_CYCLE		FIELD32(0x00001fff) +#define OSC_RSV			FIELD32(0x0000e000) +#define OSC_CAL_CNT		FIELD32(0x0fff0000) +#define OSC_CAL_ACK		FIELD32(0x10000000) +#define OSC_CLK_32K_VLD		FIELD32(0x20000000) +#define OSC_CAL_REQ		FIELD32(0x40000000) +#define OSC_ROSC_EN		FIELD32(0x80000000) + +/* + * COEX_CFG_0 + */ +#define COEX_CFG0		0x0040 +#define COEX_CFG_ANT		FIELD32(0xff000000) +/* + * COEX_CFG_1 + */ +#define COEX_CFG1		0x0044 + +/* + * COEX_CFG_2 + */ +#define COEX_CFG2		0x0048 +#define BT_COEX_CFG1		FIELD32(0xff000000) +#define BT_COEX_CFG0		FIELD32(0x00ff0000) +#define WL_COEX_CFG1		FIELD32(0x0000ff00) +#define WL_COEX_CFG0		FIELD32(0x000000ff) +/* + * PLL_CTRL_CFG + * PLL configuration register + */ +#define PLL_CTRL		0x0050 +#define PLL_RESERVED_INPUT1	FIELD32(0x000000ff) +#define PLL_RESERVED_INPUT2	FIELD32(0x0000ff00) +#define PLL_CONTROL		FIELD32(0x00070000) +#define PLL_LPF_R1		FIELD32(0x00080000) +#define PLL_LPF_C1_CTRL		FIELD32(0x00300000) +#define PLL_LPF_C2_CTRL		FIELD32(0x00c00000) +#define PLL_CP_CURRENT_CTRL	FIELD32(0x03000000) +#define PLL_PFD_DELAY_CTRL	FIELD32(0x0c000000) +#define PLL_LOCK_CTRL		FIELD32(0x70000000) +#define PLL_VBGBK_EN		FIELD32(0x80000000) + + +/* + * WLAN_CTRL_CFG + * RT3290 wlan configuration + */ +#define WLAN_FUN_CTRL			0x0080 +#define WLAN_EN				FIELD32(0x00000001) +#define WLAN_CLK_EN			FIELD32(0x00000002) +#define WLAN_RSV1			FIELD32(0x00000004) +#define WLAN_RESET			FIELD32(0x00000008) +#define PCIE_APP0_CLK_REQ		FIELD32(0x00000010) +#define FRC_WL_ANT_SET			FIELD32(0x00000020) +#define INV_TR_SW0			FIELD32(0x00000040) +#define WLAN_GPIO_IN_BIT0		FIELD32(0x00000100) +#define WLAN_GPIO_IN_BIT1		FIELD32(0x00000200) +#define WLAN_GPIO_IN_BIT2		FIELD32(0x00000400) +#define WLAN_GPIO_IN_BIT3		FIELD32(0x00000800) +#define WLAN_GPIO_IN_BIT4		FIELD32(0x00001000) +#define WLAN_GPIO_IN_BIT5		FIELD32(0x00002000) +#define WLAN_GPIO_IN_BIT6		FIELD32(0x00004000) +#define WLAN_GPIO_IN_BIT7		FIELD32(0x00008000) +#define WLAN_GPIO_IN_BIT_ALL		FIELD32(0x0000ff00) +#define WLAN_GPIO_OUT_BIT0		FIELD32(0x00010000) +#define WLAN_GPIO_OUT_BIT1		FIELD32(0x00020000) +#define WLAN_GPIO_OUT_BIT2		FIELD32(0x00040000) +#define WLAN_GPIO_OUT_BIT3		FIELD32(0x00050000) +#define WLAN_GPIO_OUT_BIT4		FIELD32(0x00100000) +#define WLAN_GPIO_OUT_BIT5		FIELD32(0x00200000) +#define WLAN_GPIO_OUT_BIT6		FIELD32(0x00400000) +#define WLAN_GPIO_OUT_BIT7		FIELD32(0x00800000) +#define WLAN_GPIO_OUT_BIT_ALL		FIELD32(0x00ff0000) +#define WLAN_GPIO_OUT_OE_BIT0		FIELD32(0x01000000) +#define WLAN_GPIO_OUT_OE_BIT1		FIELD32(0x02000000) +#define WLAN_GPIO_OUT_OE_BIT2		FIELD32(0x04000000) +#define WLAN_GPIO_OUT_OE_BIT3		FIELD32(0x08000000) +#define WLAN_GPIO_OUT_OE_BIT4		FIELD32(0x10000000) +#define WLAN_GPIO_OUT_OE_BIT5		FIELD32(0x20000000) +#define WLAN_GPIO_OUT_OE_BIT6		FIELD32(0x40000000) +#define WLAN_GPIO_OUT_OE_BIT7		FIELD32(0x80000000) +#define WLAN_GPIO_OUT_OE_BIT_ALL	FIELD32(0xff000000) + +/* + * AUX_CTRL: Aux/PCI-E related configuration + */ +#define AUX_CTRL			0x10c +#define AUX_CTRL_WAKE_PCIE_EN		FIELD32(0x00000002) +#define AUX_CTRL_FORCE_PCIE_CLK		FIELD32(0x00000400) + +/*   * OPT_14: Unknown register used by rt3xxx devices.   */  #define OPT_14_CSR			0x0114 @@ -207,10 +383,10 @@  /*   * WMM_AIFSN_CFG: Aifsn for each EDCA AC - * AIFSN0: AC_BE - * AIFSN1: AC_BK - * AIFSN2: AC_VI - * AIFSN3: AC_VO + * AIFSN0: AC_VO + * AIFSN1: AC_VI + * AIFSN2: AC_BE + * AIFSN3: AC_BK   */  #define WMM_AIFSN_CFG			0x0214  #define WMM_AIFSN_CFG_AIFSN0		FIELD32(0x0000000f) @@ -220,10 +396,10 @@  /*   * WMM_CWMIN_CSR: CWmin for each EDCA AC - * CWMIN0: AC_BE - * CWMIN1: AC_BK - * CWMIN2: AC_VI - * CWMIN3: AC_VO + * CWMIN0: AC_VO + * CWMIN1: AC_VI + * CWMIN2: AC_BE + * CWMIN3: AC_BK   */  #define WMM_CWMIN_CFG			0x0218  #define WMM_CWMIN_CFG_CWMIN0		FIELD32(0x0000000f) @@ -233,10 +409,10 @@  /*   * WMM_CWMAX_CSR: CWmax for each EDCA AC - * CWMAX0: AC_BE - * CWMAX1: AC_BK - * CWMAX2: AC_VI - * CWMAX3: AC_VO + * CWMAX0: AC_VO + * CWMAX1: AC_VI + * CWMAX2: AC_BE + * CWMAX3: AC_BK   */  #define WMM_CWMAX_CFG			0x021c  #define WMM_CWMAX_CFG_CWMAX0		FIELD32(0x0000000f) @@ -245,36 +421,51 @@  #define WMM_CWMAX_CFG_CWMAX3		FIELD32(0x0000f000)  /* - * AC_TXOP0: AC_BK/AC_BE TXOP register - * AC0TXOP: AC_BK in unit of 32us - * AC1TXOP: AC_BE in unit of 32us + * AC_TXOP0: AC_VO/AC_VI TXOP register + * AC0TXOP: AC_VO in unit of 32us + * AC1TXOP: AC_VI in unit of 32us   */  #define WMM_TXOP0_CFG			0x0220  #define WMM_TXOP0_CFG_AC0TXOP		FIELD32(0x0000ffff)  #define WMM_TXOP0_CFG_AC1TXOP		FIELD32(0xffff0000)  /* - * AC_TXOP1: AC_VO/AC_VI TXOP register - * AC2TXOP: AC_VI in unit of 32us - * AC3TXOP: AC_VO in unit of 32us + * AC_TXOP1: AC_BE/AC_BK TXOP register + * AC2TXOP: AC_BE in unit of 32us + * AC3TXOP: AC_BK in unit of 32us   */  #define WMM_TXOP1_CFG			0x0224  #define WMM_TXOP1_CFG_AC2TXOP		FIELD32(0x0000ffff)  #define WMM_TXOP1_CFG_AC3TXOP		FIELD32(0xffff0000)  /* - * GPIO_CTRL_CFG: - */ -#define GPIO_CTRL_CFG			0x0228 -#define GPIO_CTRL_CFG_BIT0		FIELD32(0x00000001) -#define GPIO_CTRL_CFG_BIT1		FIELD32(0x00000002) -#define GPIO_CTRL_CFG_BIT2		FIELD32(0x00000004) -#define GPIO_CTRL_CFG_BIT3		FIELD32(0x00000008) -#define GPIO_CTRL_CFG_BIT4		FIELD32(0x00000010) -#define GPIO_CTRL_CFG_BIT5		FIELD32(0x00000020) -#define GPIO_CTRL_CFG_BIT6		FIELD32(0x00000040) -#define GPIO_CTRL_CFG_BIT7		FIELD32(0x00000080) -#define GPIO_CTRL_CFG_BIT8		FIELD32(0x00000100) + * GPIO_CTRL: + *	GPIO_CTRL_VALx: GPIO value + *	GPIO_CTRL_DIRx: GPIO direction: 0 = output; 1 = input + */ +#define GPIO_CTRL			0x0228 +#define GPIO_CTRL_VAL0			FIELD32(0x00000001) +#define GPIO_CTRL_VAL1			FIELD32(0x00000002) +#define GPIO_CTRL_VAL2			FIELD32(0x00000004) +#define GPIO_CTRL_VAL3			FIELD32(0x00000008) +#define GPIO_CTRL_VAL4			FIELD32(0x00000010) +#define GPIO_CTRL_VAL5			FIELD32(0x00000020) +#define GPIO_CTRL_VAL6			FIELD32(0x00000040) +#define GPIO_CTRL_VAL7			FIELD32(0x00000080) +#define GPIO_CTRL_DIR0			FIELD32(0x00000100) +#define GPIO_CTRL_DIR1			FIELD32(0x00000200) +#define GPIO_CTRL_DIR2			FIELD32(0x00000400) +#define GPIO_CTRL_DIR3			FIELD32(0x00000800) +#define GPIO_CTRL_DIR4			FIELD32(0x00001000) +#define GPIO_CTRL_DIR5			FIELD32(0x00002000) +#define GPIO_CTRL_DIR6			FIELD32(0x00004000) +#define GPIO_CTRL_DIR7			FIELD32(0x00008000) +#define GPIO_CTRL_VAL8			FIELD32(0x00010000) +#define GPIO_CTRL_VAL9			FIELD32(0x00020000) +#define GPIO_CTRL_VAL10			FIELD32(0x00040000) +#define GPIO_CTRL_DIR8			FIELD32(0x01000000) +#define GPIO_CTRL_DIR9			FIELD32(0x02000000) +#define GPIO_CTRL_DIR10			FIELD32(0x04000000)  /*   * MCU_CMD_CFG @@ -282,7 +473,7 @@  #define MCU_CMD_CFG			0x022c  /* - * AC_BK register offsets + * AC_VO register offsets   */  #define TX_BASE_PTR0			0x0230  #define TX_MAX_CNT0			0x0234 @@ -290,7 +481,7 @@  #define TX_DTX_IDX0			0x023c  /* - * AC_BE register offsets + * AC_VI register offsets   */  #define TX_BASE_PTR1			0x0240  #define TX_MAX_CNT1			0x0244 @@ -298,7 +489,7 @@  #define TX_DTX_IDX1			0x024c  /* - * AC_VI register offsets + * AC_BE register offsets   */  #define TX_BASE_PTR2			0x0250  #define TX_MAX_CNT2			0x0254 @@ -306,7 +497,7 @@  #define TX_DTX_IDX2			0x025c  /* - * AC_VO register offsets + * AC_BK register offsets   */  #define TX_BASE_PTR3			0x0260  #define TX_MAX_CNT3			0x0264 @@ -366,8 +557,12 @@  /*   * US_CYC_CNT + * BT_MODE_EN: Bluetooth mode enable + * CLOCK CYCLE: Clock cycle count in 1us. + * PCI:0x21, PCIE:0x7d, USB:0x1e   */  #define US_CYC_CNT			0x02a4 +#define US_CYC_CNT_BT_MODE_EN		FIELD32(0x00000100)  #define US_CYC_CNT_CLOCK_CYCLE		FIELD32(0x000000ff)  /* @@ -436,7 +631,7 @@   */  #define	RF_CSR_CFG			0x0500  #define RF_CSR_CFG_DATA			FIELD32(0x000000ff) -#define RF_CSR_CFG_REGNUM		FIELD32(0x00001f00) +#define RF_CSR_CFG_REGNUM		FIELD32(0x00003f00)  #define RF_CSR_CFG_WRITE		FIELD32(0x00010000)  #define RF_CSR_CFG_BUSY			FIELD32(0x00020000) @@ -495,6 +690,12 @@  #define GPIO_SWITCH_7			FIELD32(0x00000080)  /* + * FIXME: where the DEBUG_INDEX name come from? + */ +#define MAC_DEBUG_INDEX			0x05e8 +#define MAC_DEBUG_INDEX_XTAL		FIELD32(0x80000000) + +/*   * MAC Control/Status Registers(CSR).   * Some values are set in TU, whereas 1 TU == 1024 us.   */ @@ -588,7 +789,7 @@   * READ_CONTROL: 0 write BBP, 1 read BBP   * BUSY: ASIC is busy executing BBP commands   * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks - * BBP_RW_MODE: 0 serial, 1 paralell + * BBP_RW_MODE: 0 serial, 1 parallel   */  #define BBP_CSR_CFG			0x101c  #define BBP_CSR_CFG_VALUE		FIELD32(0x000000ff) @@ -634,6 +835,9 @@  /*   * LED_CFG: LED control + * ON_PERIOD: LED active time (ms) during TX (only used for LED mode 1) + * OFF_PERIOD: LED inactive time (ms) during TX (only used for LED mode 1) + * SLOW_BLINK_PERIOD: LED blink interval in seconds (only used for LED mode 2)   * color LED's:   *   0: off   *   1: blinking upon TX2 @@ -699,8 +903,18 @@  /*   * CH_TIME_CFG: count as channel busy + * EIFS_BUSY: Count EIFS as channel busy + * NAV_BUSY: Count NAS as channel busy + * RX_BUSY: Count RX as channel busy + * TX_BUSY: Count TX as channel busy + * TMR_EN: Enable channel statistics timer   */  #define CH_TIME_CFG     	        0x110c +#define CH_TIME_CFG_EIFS_BUSY		FIELD32(0x00000010) +#define CH_TIME_CFG_NAV_BUSY		FIELD32(0x00000008) +#define CH_TIME_CFG_RX_BUSY		FIELD32(0x00000004) +#define CH_TIME_CFG_TX_BUSY		FIELD32(0x00000002) +#define CH_TIME_CFG_TMR_EN		FIELD32(0x00000001)  /*   * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us @@ -869,6 +1083,15 @@  #define TX_PWR_CFG_0_9MBS		FIELD32(0x00f00000)  #define TX_PWR_CFG_0_12MBS		FIELD32(0x0f000000)  #define TX_PWR_CFG_0_18MBS		FIELD32(0xf0000000) +/* bits for 3T devices */ +#define TX_PWR_CFG_0_CCK1_CH0		FIELD32(0x0000000f) +#define TX_PWR_CFG_0_CCK1_CH1		FIELD32(0x000000f0) +#define TX_PWR_CFG_0_CCK5_CH0		FIELD32(0x00000f00) +#define TX_PWR_CFG_0_CCK5_CH1		FIELD32(0x0000f000) +#define TX_PWR_CFG_0_OFDM6_CH0		FIELD32(0x000f0000) +#define TX_PWR_CFG_0_OFDM6_CH1		FIELD32(0x00f00000) +#define TX_PWR_CFG_0_OFDM12_CH0		FIELD32(0x0f000000) +#define TX_PWR_CFG_0_OFDM12_CH1		FIELD32(0xf0000000)  /*   * TX_PWR_CFG_1: @@ -882,6 +1105,15 @@  #define TX_PWR_CFG_1_MCS1		FIELD32(0x00f00000)  #define TX_PWR_CFG_1_MCS2		FIELD32(0x0f000000)  #define TX_PWR_CFG_1_MCS3		FIELD32(0xf0000000) +/* bits for 3T devices */ +#define TX_PWR_CFG_1_OFDM24_CH0		FIELD32(0x0000000f) +#define TX_PWR_CFG_1_OFDM24_CH1		FIELD32(0x000000f0) +#define TX_PWR_CFG_1_OFDM48_CH0		FIELD32(0x00000f00) +#define TX_PWR_CFG_1_OFDM48_CH1		FIELD32(0x0000f000) +#define TX_PWR_CFG_1_MCS0_CH0		FIELD32(0x000f0000) +#define TX_PWR_CFG_1_MCS0_CH1		FIELD32(0x00f00000) +#define TX_PWR_CFG_1_MCS2_CH0		FIELD32(0x0f000000) +#define TX_PWR_CFG_1_MCS2_CH1		FIELD32(0xf0000000)  /*   * TX_PWR_CFG_2: @@ -895,6 +1127,15 @@  #define TX_PWR_CFG_2_MCS9		FIELD32(0x00f00000)  #define TX_PWR_CFG_2_MCS10		FIELD32(0x0f000000)  #define TX_PWR_CFG_2_MCS11		FIELD32(0xf0000000) +/* bits for 3T devices */ +#define TX_PWR_CFG_2_MCS4_CH0		FIELD32(0x0000000f) +#define TX_PWR_CFG_2_MCS4_CH1		FIELD32(0x000000f0) +#define TX_PWR_CFG_2_MCS6_CH0		FIELD32(0x00000f00) +#define TX_PWR_CFG_2_MCS6_CH1		FIELD32(0x0000f000) +#define TX_PWR_CFG_2_MCS8_CH0		FIELD32(0x000f0000) +#define TX_PWR_CFG_2_MCS8_CH1		FIELD32(0x00f00000) +#define TX_PWR_CFG_2_MCS10_CH0		FIELD32(0x0f000000) +#define TX_PWR_CFG_2_MCS10_CH1		FIELD32(0xf0000000)  /*   * TX_PWR_CFG_3: @@ -908,6 +1149,15 @@  #define TX_PWR_CFG_3_UKNOWN2		FIELD32(0x00f00000)  #define TX_PWR_CFG_3_UKNOWN3		FIELD32(0x0f000000)  #define TX_PWR_CFG_3_UKNOWN4		FIELD32(0xf0000000) +/* bits for 3T devices */ +#define TX_PWR_CFG_3_MCS12_CH0		FIELD32(0x0000000f) +#define TX_PWR_CFG_3_MCS12_CH1		FIELD32(0x000000f0) +#define TX_PWR_CFG_3_MCS14_CH0		FIELD32(0x00000f00) +#define TX_PWR_CFG_3_MCS14_CH1		FIELD32(0x0000f000) +#define TX_PWR_CFG_3_STBC0_CH0		FIELD32(0x000f0000) +#define TX_PWR_CFG_3_STBC0_CH1		FIELD32(0x00f00000) +#define TX_PWR_CFG_3_STBC2_CH0		FIELD32(0x0f000000) +#define TX_PWR_CFG_3_STBC2_CH1		FIELD32(0xf0000000)  /*   * TX_PWR_CFG_4: @@ -917,11 +1167,17 @@  #define TX_PWR_CFG_4_UKNOWN6		FIELD32(0x000000f0)  #define TX_PWR_CFG_4_UKNOWN7		FIELD32(0x00000f00)  #define TX_PWR_CFG_4_UKNOWN8		FIELD32(0x0000f000) +/* bits for 3T devices */ +#define TX_PWR_CFG_3_STBC4_CH0		FIELD32(0x0000000f) +#define TX_PWR_CFG_3_STBC4_CH1		FIELD32(0x000000f0) +#define TX_PWR_CFG_3_STBC6_CH0		FIELD32(0x00000f00) +#define TX_PWR_CFG_3_STBC6_CH1		FIELD32(0x0000f000)  /*   * TX_PIN_CFG:   */  #define TX_PIN_CFG			0x1328 +#define TX_PIN_CFG_PA_PE_DISABLE	0xfcfffff0  #define TX_PIN_CFG_PA_PE_A0_EN		FIELD32(0x00000001)  #define TX_PIN_CFG_PA_PE_G0_EN		FIELD32(0x00000002)  #define TX_PIN_CFG_PA_PE_A1_EN		FIELD32(0x00000004) @@ -942,6 +1198,14 @@  #define TX_PIN_CFG_RFTR_POL		FIELD32(0x00020000)  #define TX_PIN_CFG_TRSW_EN		FIELD32(0x00040000)  #define TX_PIN_CFG_TRSW_POL		FIELD32(0x00080000) +#define TX_PIN_CFG_PA_PE_A2_EN		FIELD32(0x01000000) +#define TX_PIN_CFG_PA_PE_G2_EN		FIELD32(0x02000000) +#define TX_PIN_CFG_PA_PE_A2_POL		FIELD32(0x04000000) +#define TX_PIN_CFG_PA_PE_G2_POL		FIELD32(0x08000000) +#define TX_PIN_CFG_LNA_PE_A2_EN		FIELD32(0x10000000) +#define TX_PIN_CFG_LNA_PE_G2_EN		FIELD32(0x20000000) +#define TX_PIN_CFG_LNA_PE_A2_POL	FIELD32(0x40000000) +#define TX_PIN_CFG_LNA_PE_G2_POL	FIELD32(0x80000000)  /*   * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz @@ -1116,8 +1380,8 @@   * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd)   * PROTECT_CTRL: Protection control frame type for CCK TX   *               0:none, 1:RTS/CTS, 2:CTS-to-self - * PROTECT_NAV: TXOP protection type for CCK TX - *              0:none, 1:ShortNAVprotect, 2:LongNAVProtect + * PROTECT_NAV_SHORT: TXOP protection type for CCK TX with short NAV + * PROTECT_NAV_LONG: TXOP protection type for CCK TX with long NAV   * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow   * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow   * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow @@ -1129,7 +1393,8 @@  #define CCK_PROT_CFG			0x1364  #define CCK_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)  #define CCK_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000) -#define CCK_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000) +#define CCK_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000) +#define CCK_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)  #define CCK_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)  #define CCK_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)  #define CCK_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000) @@ -1144,7 +1409,8 @@  #define OFDM_PROT_CFG			0x1368  #define OFDM_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)  #define OFDM_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000) -#define OFDM_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000) +#define OFDM_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000) +#define OFDM_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)  #define OFDM_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)  #define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)  #define OFDM_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000) @@ -1159,7 +1425,8 @@  #define MM20_PROT_CFG			0x136c  #define MM20_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)  #define MM20_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000) -#define MM20_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000) +#define MM20_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000) +#define MM20_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)  #define MM20_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)  #define MM20_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)  #define MM20_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000) @@ -1174,7 +1441,8 @@  #define MM40_PROT_CFG			0x1370  #define MM40_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)  #define MM40_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000) -#define MM40_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000) +#define MM40_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000) +#define MM40_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)  #define MM40_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)  #define MM40_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)  #define MM40_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000) @@ -1189,7 +1457,8 @@  #define GF20_PROT_CFG			0x1374  #define GF20_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)  #define GF20_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000) -#define GF20_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000) +#define GF20_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000) +#define GF20_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)  #define GF20_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)  #define GF20_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)  #define GF20_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000) @@ -1204,7 +1473,8 @@  #define GF40_PROT_CFG			0x1378  #define GF40_PROT_CFG_PROTECT_RATE	FIELD32(0x0000ffff)  #define GF40_PROT_CFG_PROTECT_CTRL	FIELD32(0x00030000) -#define GF40_PROT_CFG_PROTECT_NAV	FIELD32(0x000c0000) +#define GF40_PROT_CFG_PROTECT_NAV_SHORT	FIELD32(0x00040000) +#define GF40_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)  #define GF40_PROT_CFG_TX_OP_ALLOW_CCK	FIELD32(0x00100000)  #define GF40_PROT_CFG_TX_OP_ALLOW_OFDM	FIELD32(0x00200000)  #define GF40_PROT_CFG_TX_OP_ALLOW_MM20	FIELD32(0x00400000) @@ -1223,6 +1493,81 @@   */  #define EXP_ACK_TIME			0x1380 +/* TX_PWR_CFG_5 */ +#define TX_PWR_CFG_5			0x1384 +#define TX_PWR_CFG_5_MCS16_CH0		FIELD32(0x0000000f) +#define TX_PWR_CFG_5_MCS16_CH1		FIELD32(0x000000f0) +#define TX_PWR_CFG_5_MCS16_CH2		FIELD32(0x00000f00) +#define TX_PWR_CFG_5_MCS18_CH0		FIELD32(0x000f0000) +#define TX_PWR_CFG_5_MCS18_CH1		FIELD32(0x00f00000) +#define TX_PWR_CFG_5_MCS18_CH2		FIELD32(0x0f000000) + +/* TX_PWR_CFG_6 */ +#define TX_PWR_CFG_6			0x1388 +#define TX_PWR_CFG_6_MCS20_CH0		FIELD32(0x0000000f) +#define TX_PWR_CFG_6_MCS20_CH1		FIELD32(0x000000f0) +#define TX_PWR_CFG_6_MCS20_CH2		FIELD32(0x00000f00) +#define TX_PWR_CFG_6_MCS22_CH0		FIELD32(0x000f0000) +#define TX_PWR_CFG_6_MCS22_CH1		FIELD32(0x00f00000) +#define TX_PWR_CFG_6_MCS22_CH2		FIELD32(0x0f000000) + +/* TX_PWR_CFG_0_EXT */ +#define TX_PWR_CFG_0_EXT		0x1390 +#define TX_PWR_CFG_0_EXT_CCK1_CH2	FIELD32(0x0000000f) +#define TX_PWR_CFG_0_EXT_CCK5_CH2	FIELD32(0x00000f00) +#define TX_PWR_CFG_0_EXT_OFDM6_CH2	FIELD32(0x000f0000) +#define TX_PWR_CFG_0_EXT_OFDM12_CH2	FIELD32(0x0f000000) + +/* TX_PWR_CFG_1_EXT */ +#define TX_PWR_CFG_1_EXT		0x1394 +#define TX_PWR_CFG_1_EXT_OFDM24_CH2	FIELD32(0x0000000f) +#define TX_PWR_CFG_1_EXT_OFDM48_CH2	FIELD32(0x00000f00) +#define TX_PWR_CFG_1_EXT_MCS0_CH2	FIELD32(0x000f0000) +#define TX_PWR_CFG_1_EXT_MCS2_CH2	FIELD32(0x0f000000) + +/* TX_PWR_CFG_2_EXT */ +#define TX_PWR_CFG_2_EXT		0x1398 +#define TX_PWR_CFG_2_EXT_MCS4_CH2	FIELD32(0x0000000f) +#define TX_PWR_CFG_2_EXT_MCS6_CH2	FIELD32(0x00000f00) +#define TX_PWR_CFG_2_EXT_MCS8_CH2	FIELD32(0x000f0000) +#define TX_PWR_CFG_2_EXT_MCS10_CH2	FIELD32(0x0f000000) + +/* TX_PWR_CFG_3_EXT */ +#define TX_PWR_CFG_3_EXT		0x139c +#define TX_PWR_CFG_3_EXT_MCS12_CH2	FIELD32(0x0000000f) +#define TX_PWR_CFG_3_EXT_MCS14_CH2	FIELD32(0x00000f00) +#define TX_PWR_CFG_3_EXT_STBC0_CH2	FIELD32(0x000f0000) +#define TX_PWR_CFG_3_EXT_STBC2_CH2	FIELD32(0x0f000000) + +/* TX_PWR_CFG_4_EXT */ +#define TX_PWR_CFG_4_EXT		0x13a0 +#define TX_PWR_CFG_4_EXT_STBC4_CH2	FIELD32(0x0000000f) +#define TX_PWR_CFG_4_EXT_STBC6_CH2	FIELD32(0x00000f00) + +/* TX_PWR_CFG_7 */ +#define TX_PWR_CFG_7			0x13d4 +#define TX_PWR_CFG_7_OFDM54_CH0		FIELD32(0x0000000f) +#define TX_PWR_CFG_7_OFDM54_CH1		FIELD32(0x000000f0) +#define TX_PWR_CFG_7_OFDM54_CH2		FIELD32(0x00000f00) +#define TX_PWR_CFG_7_MCS7_CH0		FIELD32(0x000f0000) +#define TX_PWR_CFG_7_MCS7_CH1		FIELD32(0x00f00000) +#define TX_PWR_CFG_7_MCS7_CH2		FIELD32(0x0f000000) + +/* TX_PWR_CFG_8 */ +#define TX_PWR_CFG_8			0x13d8 +#define TX_PWR_CFG_8_MCS15_CH0		FIELD32(0x0000000f) +#define TX_PWR_CFG_8_MCS15_CH1		FIELD32(0x000000f0) +#define TX_PWR_CFG_8_MCS15_CH2		FIELD32(0x00000f00) +#define TX_PWR_CFG_8_MCS23_CH0		FIELD32(0x000f0000) +#define TX_PWR_CFG_8_MCS23_CH1		FIELD32(0x00f00000) +#define TX_PWR_CFG_8_MCS23_CH2		FIELD32(0x0f000000) + +/* TX_PWR_CFG_9 */ +#define TX_PWR_CFG_9			0x13dc +#define TX_PWR_CFG_9_STBC7_CH0		FIELD32(0x0000000f) +#define TX_PWR_CFG_9_STBC7_CH1		FIELD32(0x000000f0) +#define TX_PWR_CFG_9_STBC7_CH2		FIELD32(0x00000f00) +  /*   * RX_FILTER_CFG: RX configuration register.   */ @@ -1578,6 +1923,7 @@ struct mac_iveiv_entry {  /*   * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. + * CMD_TOKEN: Command id, 0xff disable status reporting.   */  #define H2M_MAILBOX_CSR			0x7010  #define H2M_MAILBOX_CSR_ARG0		FIELD32(0x000000ff) @@ -1587,6 +1933,8 @@ struct mac_iveiv_entry {  /*   * H2M_MAILBOX_CID: + * Free slots contain 0xff. MCU will store command's token to lowest free slot. + * If all slots are occupied status will be dropped.   */  #define H2M_MAILBOX_CID			0x7014  #define H2M_MAILBOX_CID_CMD0		FIELD32(0x000000ff) @@ -1596,6 +1944,7 @@ struct mac_iveiv_entry {  /*   * H2M_MAILBOX_STATUS: + * Command status will be saved to same slot as command id.   */  #define H2M_MAILBOX_STATUS		0x701c @@ -1670,35 +2019,84 @@ struct mac_iveiv_entry {  #define HW_BEACON_BASE6			0x5dc0  #define HW_BEACON_BASE7			0x5bc0 -#define HW_BEACON_OFFSET(__index) \ +#define HW_BEACON_BASE(__index) \  	(((__index) < 4) ? (HW_BEACON_BASE0 + (__index * 0x0200)) : \  	  (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \  	  (HW_BEACON_BASE6 - ((__index - 6) * 0x0200)))) +#define BEACON_BASE_TO_OFFSET(_base)	(((_base) - 0x4000) / 64) +  /*   * BBP registers.   * The wordsize of the BBP is 8 bits.   */  /* - * BBP 1: TX Antenna & Power - * POWER: 0 - normal, 1 - drop tx power by 6dBm, 2 - drop tx power by 12dBm, - *	3 - increase tx power by 6dBm + * BBP 1: TX Antenna & Power Control + * POWER_CTRL: + * 0 - normal, + * 1 - drop tx power by 6dBm, + * 2 - drop tx power by 12dBm, + * 3 - increase tx power by 6dBm   */ -#define BBP1_TX_POWER			FIELD8(0x07) +#define BBP1_TX_POWER_CTRL		FIELD8(0x07)  #define BBP1_TX_ANTENNA			FIELD8(0x18)  /*   * BBP 3: RX Antenna   */ +#define BBP3_RX_ADC			FIELD8(0x03)  #define BBP3_RX_ANTENNA			FIELD8(0x18)  #define BBP3_HT40_MINUS			FIELD8(0x20) +#define BBP3_ADC_MODE_SWITCH		FIELD8(0x40) +#define BBP3_ADC_INIT_MODE		FIELD8(0x80)  /*   * BBP 4: Bandwidth   */  #define BBP4_TX_BF			FIELD8(0x01)  #define BBP4_BANDWIDTH			FIELD8(0x18) +#define BBP4_MAC_IF_CTRL		FIELD8(0x40) + +/* BBP27 */ +#define BBP27_RX_CHAIN_SEL		FIELD8(0x60) + +/* + * BBP 47: Bandwidth + */ +#define BBP47_TSSI_REPORT_SEL		FIELD8(0x03) +#define BBP47_TSSI_UPDATE_REQ		FIELD8(0x04) +#define BBP47_TSSI_TSSI_MODE		FIELD8(0x18) +#define BBP47_TSSI_ADC6			FIELD8(0x80) + +/* + * BBP 49 + */ +#define BBP49_UPDATE_FLAG		FIELD8(0x01) + +/* + * BBP 105: + * - bit0: detect SIG on primary channel only (on 40MHz bandwidth) + * - bit1: FEQ (Feed Forward Compensation) for independend streams + * - bit2: MLD (Maximum Likehood Detection) for 2 streams (reserved on single + *	   stream) + * - bit4: channel estimation updates based on remodulation of + *	   L-SIG and HT-SIG symbols + */ +#define BBP105_DETECT_SIG_ON_PRIMARY	FIELD8(0x01) +#define BBP105_FEQ			FIELD8(0x02) +#define BBP105_MLD			FIELD8(0x04) +#define BBP105_SIG_REMODULATION		FIELD8(0x08) + +/* + * BBP 109 + */ +#define BBP109_TX0_POWER		FIELD8(0x0f) +#define BBP109_TX1_POWER		FIELD8(0xf0) + +/* BBP 110 */ +#define BBP110_TX2_POWER		FIELD8(0x0f) +  /*   * BBP 138: Unknown @@ -1709,6 +2107,16 @@ struct mac_iveiv_entry {  #define BBP138_TX_DAC2			FIELD8(0x40)  /* + * BBP 152: Rx Ant + */ +#define BBP152_RX_DEFAULT_ANT		FIELD8(0x80) + +/* + * BBP 254: unknown + */ +#define BBP254_BIT7			FIELD8(0x80) + +/*   * RFCSR registers   * The wordsize of the RFCSR is 8 bits.   */ @@ -1717,31 +2125,90 @@ struct mac_iveiv_entry {   * RFCSR 1:   */  #define RFCSR1_RF_BLOCK_EN		FIELD8(0x01) +#define RFCSR1_PLL_PD			FIELD8(0x02)  #define RFCSR1_RX0_PD			FIELD8(0x04)  #define RFCSR1_TX0_PD			FIELD8(0x08)  #define RFCSR1_RX1_PD			FIELD8(0x10)  #define RFCSR1_TX1_PD			FIELD8(0x20) +#define RFCSR1_RX2_PD			FIELD8(0x40) +#define RFCSR1_TX2_PD			FIELD8(0x80) + +/* + * RFCSR 2: + */ +#define RFCSR2_RESCAL_EN		FIELD8(0x80) + +/* + * RFCSR 3: + */ +#define RFCSR3_K			FIELD8(0x0f) +/* Bits [7-4] for RF3320 (RT3370/RT3390), on other chipsets reserved */ +#define RFCSR3_PA1_BIAS_CCK		FIELD8(0x70) +#define RFCSR3_PA2_CASCODE_BIAS_CCKK	FIELD8(0x80) +/* Bits for RF3290/RF5360/RF5370/RF5372/RF5390/RF5392 */ +#define RFCSR3_VCOCAL_EN		FIELD8(0x80) +/* Bits for RF3050 */ +#define RFCSR3_BIT1			FIELD8(0x02) +#define RFCSR3_BIT2			FIELD8(0x04) +#define RFCSR3_BIT3			FIELD8(0x08) +#define RFCSR3_BIT4			FIELD8(0x10) +#define RFCSR3_BIT5			FIELD8(0x20) + +/* + * FRCSR 5: + */ +#define RFCSR5_R1			FIELD8(0x0c)  /*   * RFCSR 6:   */  #define RFCSR6_R1			FIELD8(0x03)  #define RFCSR6_R2			FIELD8(0x40) +#define RFCSR6_TXDIV			FIELD8(0x0c) +/* bits for RF3053 */ +#define RFCSR6_VCO_IC			FIELD8(0xc0)  /*   * RFCSR 7:   */  #define RFCSR7_RF_TUNING		FIELD8(0x01) +#define RFCSR7_BIT1			FIELD8(0x02) +#define RFCSR7_BIT2			FIELD8(0x04) +#define RFCSR7_BIT3			FIELD8(0x08) +#define RFCSR7_BIT4			FIELD8(0x10) +#define RFCSR7_BIT5			FIELD8(0x20) +#define RFCSR7_BITS67			FIELD8(0xc0) + +/* + * RFCSR 9: + */ +#define RFCSR9_K			FIELD8(0x0f) +#define RFCSR9_N			FIELD8(0x10) +#define RFCSR9_UNKNOWN			FIELD8(0x60) +#define RFCSR9_MOD			FIELD8(0x80) + +/* + * RFCSR 11: + */ +#define RFCSR11_R			FIELD8(0x03) +#define RFCSR11_PLL_MOD			FIELD8(0x0c) +#define RFCSR11_MOD			FIELD8(0xc0) +/* bits for RF3053 */ +/* TODO: verify RFCSR11_MOD usage on other chips */ +#define RFCSR11_PLL_IDOH		FIELD8(0x40) +  /*   * RFCSR 12:   */  #define RFCSR12_TX_POWER		FIELD8(0x1f) +#define RFCSR12_DR0			FIELD8(0xe0)  /*   * RFCSR 13:   */  #define RFCSR13_TX_POWER		FIELD8(0x1f) +#define RFCSR13_DR0			FIELD8(0xe0)  /*   * RFCSR 15: @@ -1749,11 +2216,21 @@ struct mac_iveiv_entry {  #define RFCSR15_TX_LO2_EN		FIELD8(0x08)  /* + * RFCSR 16: + */ +#define RFCSR16_TXMIXER_GAIN		FIELD8(0x07) + +/*   * RFCSR 17:   */  #define RFCSR17_TXMIXER_GAIN		FIELD8(0x07)  #define RFCSR17_TX_LO1_EN		FIELD8(0x08)  #define RFCSR17_R			FIELD8(0x20) +#define RFCSR17_CODE			FIELD8(0x7f) + +/* RFCSR 18 */ +#define RFCSR18_XO_TUNE_BYPASS		FIELD8(0x40) +  /*   * RFCSR 20: @@ -1776,6 +2253,13 @@ struct mac_iveiv_entry {  #define RFCSR23_FREQ_OFFSET		FIELD8(0x7f)  /* + * RFCSR 24: + */ +#define RFCSR24_TX_AGC_FC		FIELD8(0x1f) +#define RFCSR24_TX_H20M			FIELD8(0x20) +#define RFCSR24_TX_CALIB		FIELD8(0x7f) + +/*   * RFCSR 27:   */  #define RFCSR27_R1			FIELD8(0x03) @@ -1784,11 +2268,84 @@ struct mac_iveiv_entry {  #define RFCSR27_R4			FIELD8(0x40)  /* + * RFCSR 29: + */ +#define RFCSR29_ADC6_TEST		FIELD8(0x01) +#define RFCSR29_ADC6_INT_TEST		FIELD8(0x02) +#define RFCSR29_RSSI_RESET		FIELD8(0x04) +#define RFCSR29_RSSI_ON			FIELD8(0x08) +#define RFCSR29_RSSI_RIP_CTRL		FIELD8(0x30) +#define RFCSR29_RSSI_GAIN		FIELD8(0xc0) + +/*   * RFCSR 30:   */ +#define RFCSR30_TX_H20M			FIELD8(0x02) +#define RFCSR30_RX_H20M			FIELD8(0x04) +#define RFCSR30_RX_VCM			FIELD8(0x18)  #define RFCSR30_RF_CALIBRATION		FIELD8(0x80)  /* + * RFCSR 31: + */ +#define RFCSR31_RX_AGC_FC		FIELD8(0x1f) +#define RFCSR31_RX_H20M			FIELD8(0x20) +#define RFCSR31_RX_CALIB		FIELD8(0x7f) + +/* RFCSR 32 bits for RF3053 */ +#define RFCSR32_TX_AGC_FC		FIELD8(0xf8) + +/* RFCSR 36 bits for RF3053 */ +#define RFCSR36_RF_BS			FIELD8(0x80) + +/* + * RFCSR 38: + */ +#define RFCSR38_RX_LO1_EN		FIELD8(0x20) + +/* + * RFCSR 39: + */ +#define RFCSR39_RX_DIV			FIELD8(0x40) +#define RFCSR39_RX_LO2_EN		FIELD8(0x80) + +/* + * RFCSR 49: + */ +#define RFCSR49_TX			FIELD8(0x3f) +#define RFCSR49_EP			FIELD8(0xc0) +/* bits for RT3593 */ +#define RFCSR49_TX_LO1_IC		FIELD8(0x1c) +#define RFCSR49_TX_DIV			FIELD8(0x20) + +/* + * RFCSR 50: + */ +#define RFCSR50_TX			FIELD8(0x3f) +#define RFCSR50_EP			FIELD8(0xc0) +/* bits for RT3593 */ +#define RFCSR50_TX_LO1_EN		FIELD8(0x20) +#define RFCSR50_TX_LO2_EN		FIELD8(0x10) + +/* RFCSR 51 */ +/* bits for RT3593 */ +#define RFCSR51_BITS01			FIELD8(0x03) +#define RFCSR51_BITS24			FIELD8(0x1c) +#define RFCSR51_BITS57			FIELD8(0xe0) + +#define RFCSR53_TX_POWER		FIELD8(0x3f) +#define RFCSR53_UNKNOWN			FIELD8(0xc0) + +#define RFCSR54_TX_POWER		FIELD8(0x3f) +#define RFCSR54_UNKNOWN			FIELD8(0xc0) + +#define RFCSR55_TX_POWER		FIELD8(0x3f) +#define RFCSR55_UNKNOWN			FIELD8(0xc0) + +#define RFCSR57_DRV_CC			FIELD8(0xfc) + + +/*   * RF registers   */ @@ -1820,58 +2377,118 @@ struct mac_iveiv_entry {   * The wordsize of the EEPROM is 16 bits.   */ +enum rt2800_eeprom_word { +	EEPROM_CHIP_ID = 0, +	EEPROM_VERSION, +	EEPROM_MAC_ADDR_0, +	EEPROM_MAC_ADDR_1, +	EEPROM_MAC_ADDR_2, +	EEPROM_NIC_CONF0, +	EEPROM_NIC_CONF1, +	EEPROM_FREQ, +	EEPROM_LED_AG_CONF, +	EEPROM_LED_ACT_CONF, +	EEPROM_LED_POLARITY, +	EEPROM_NIC_CONF2, +	EEPROM_LNA, +	EEPROM_RSSI_BG, +	EEPROM_RSSI_BG2, +	EEPROM_TXMIXER_GAIN_BG, +	EEPROM_RSSI_A, +	EEPROM_RSSI_A2, +	EEPROM_TXMIXER_GAIN_A, +	EEPROM_EIRP_MAX_TX_POWER, +	EEPROM_TXPOWER_DELTA, +	EEPROM_TXPOWER_BG1, +	EEPROM_TXPOWER_BG2, +	EEPROM_TSSI_BOUND_BG1, +	EEPROM_TSSI_BOUND_BG2, +	EEPROM_TSSI_BOUND_BG3, +	EEPROM_TSSI_BOUND_BG4, +	EEPROM_TSSI_BOUND_BG5, +	EEPROM_TXPOWER_A1, +	EEPROM_TXPOWER_A2, +	EEPROM_TSSI_BOUND_A1, +	EEPROM_TSSI_BOUND_A2, +	EEPROM_TSSI_BOUND_A3, +	EEPROM_TSSI_BOUND_A4, +	EEPROM_TSSI_BOUND_A5, +	EEPROM_TXPOWER_BYRATE, +	EEPROM_BBP_START, + +	/* IDs for extended EEPROM format used by three-chain devices */ +	EEPROM_EXT_LNA2, +	EEPROM_EXT_TXPOWER_BG3, +	EEPROM_EXT_TXPOWER_A3, + +	/* New values must be added before this */ +	EEPROM_WORD_COUNT +}; +  /*   * EEPROM Version   */ -#define EEPROM_VERSION			0x0001  #define EEPROM_VERSION_FAE		FIELD16(0x00ff)  #define EEPROM_VERSION_VERSION		FIELD16(0xff00)  /*   * HW MAC address.   */ -#define EEPROM_MAC_ADDR_0		0x0002  #define EEPROM_MAC_ADDR_BYTE0		FIELD16(0x00ff)  #define EEPROM_MAC_ADDR_BYTE1		FIELD16(0xff00) -#define EEPROM_MAC_ADDR_1		0x0003  #define EEPROM_MAC_ADDR_BYTE2		FIELD16(0x00ff)  #define EEPROM_MAC_ADDR_BYTE3		FIELD16(0xff00) -#define EEPROM_MAC_ADDR_2		0x0004  #define EEPROM_MAC_ADDR_BYTE4		FIELD16(0x00ff)  #define EEPROM_MAC_ADDR_BYTE5		FIELD16(0xff00)  /* - * EEPROM ANTENNA config + * EEPROM NIC Configuration 0   * RXPATH: 1: 1R, 2: 2R, 3: 3R - * TXPATH: 1: 1T, 2: 2T - */ -#define	EEPROM_ANTENNA			0x001a -#define EEPROM_ANTENNA_RXPATH		FIELD16(0x000f) -#define EEPROM_ANTENNA_TXPATH		FIELD16(0x00f0) -#define EEPROM_ANTENNA_RF_TYPE		FIELD16(0x0f00) - -/* - * EEPROM NIC config - * CARDBUS_ACCEL: 0 - enable, 1 - disable - */ -#define	EEPROM_NIC			0x001b -#define EEPROM_NIC_HW_RADIO		FIELD16(0x0001) -#define EEPROM_NIC_DYNAMIC_TX_AGC	FIELD16(0x0002) -#define EEPROM_NIC_EXTERNAL_LNA_BG	FIELD16(0x0004) -#define EEPROM_NIC_EXTERNAL_LNA_A	FIELD16(0x0008) -#define EEPROM_NIC_CARDBUS_ACCEL	FIELD16(0x0010) -#define EEPROM_NIC_BW40M_SB_BG		FIELD16(0x0020) -#define EEPROM_NIC_BW40M_SB_A		FIELD16(0x0040) -#define EEPROM_NIC_WPS_PBC		FIELD16(0x0080) -#define EEPROM_NIC_BW40M_BG		FIELD16(0x0100) -#define EEPROM_NIC_BW40M_A		FIELD16(0x0200) -#define EEPROM_NIC_ANT_DIVERSITY	FIELD16(0x0800) -#define EEPROM_NIC_DAC_TEST		FIELD16(0x8000) + * TXPATH: 1: 1T, 2: 2T, 3: 3T + * RF_TYPE: RFIC type + */ +#define EEPROM_NIC_CONF0_RXPATH		FIELD16(0x000f) +#define EEPROM_NIC_CONF0_TXPATH		FIELD16(0x00f0) +#define EEPROM_NIC_CONF0_RF_TYPE	FIELD16(0x0f00) + +/* + * EEPROM NIC Configuration 1 + * HW_RADIO: 0: disable, 1: enable + * EXTERNAL_TX_ALC: 0: disable, 1: enable + * EXTERNAL_LNA_2G: 0: disable, 1: enable + * EXTERNAL_LNA_5G: 0: disable, 1: enable + * CARDBUS_ACCEL: 0: enable, 1: disable + * BW40M_SB_2G: 0: disable, 1: enable + * BW40M_SB_5G: 0: disable, 1: enable + * WPS_PBC: 0: disable, 1: enable + * BW40M_2G: 0: enable, 1: disable + * BW40M_5G: 0: enable, 1: disable + * BROADBAND_EXT_LNA: 0: disable, 1: enable + * ANT_DIVERSITY: 00: Disable, 01: Diversity, + * 				  10: Main antenna, 11: Aux antenna + * INTERNAL_TX_ALC: 0: disable, 1: enable + * BT_COEXIST: 0: disable, 1: enable + * DAC_TEST: 0: disable, 1: enable + */ +#define EEPROM_NIC_CONF1_HW_RADIO		FIELD16(0x0001) +#define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC	FIELD16(0x0002) +#define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G	FIELD16(0x0004) +#define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G	FIELD16(0x0008) +#define EEPROM_NIC_CONF1_CARDBUS_ACCEL		FIELD16(0x0010) +#define EEPROM_NIC_CONF1_BW40M_SB_2G		FIELD16(0x0020) +#define EEPROM_NIC_CONF1_BW40M_SB_5G		FIELD16(0x0040) +#define EEPROM_NIC_CONF1_WPS_PBC		FIELD16(0x0080) +#define EEPROM_NIC_CONF1_BW40M_2G		FIELD16(0x0100) +#define EEPROM_NIC_CONF1_BW40M_5G		FIELD16(0x0200) +#define EEPROM_NIC_CONF1_BROADBAND_EXT_LNA	FIELD16(0x400) +#define EEPROM_NIC_CONF1_ANT_DIVERSITY		FIELD16(0x1800) +#define EEPROM_NIC_CONF1_INTERNAL_TX_ALC	FIELD16(0x2000) +#define EEPROM_NIC_CONF1_BT_COEXIST		FIELD16(0x4000) +#define EEPROM_NIC_CONF1_DAC_TEST		FIELD16(0x8000)  /*   * EEPROM frequency   */ -#define	EEPROM_FREQ			0x001d  #define EEPROM_FREQ_OFFSET		FIELD16(0x00ff)  #define EEPROM_FREQ_LED_MODE		FIELD16(0x7f00)  #define EEPROM_FREQ_LED_POLARITY	FIELD16(0x1000) @@ -1888,9 +2505,6 @@ struct mac_iveiv_entry {   * POLARITY_GPIO_4: Polarity GPIO4 setting.   * LED_MODE: Led mode.   */ -#define EEPROM_LED1			0x001e -#define EEPROM_LED2			0x001f -#define EEPROM_LED3			0x0020  #define EEPROM_LED_POLARITY_RDY_BG	FIELD16(0x0001)  #define EEPROM_LED_POLARITY_RDY_A	FIELD16(0x0002)  #define EEPROM_LED_POLARITY_ACT		FIELD16(0x0004) @@ -1902,87 +2516,192 @@ struct mac_iveiv_entry {  #define EEPROM_LED_LED_MODE		FIELD16(0x1f00)  /* + * EEPROM NIC Configuration 2 + * RX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream + * TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream + * CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved + */ +#define EEPROM_NIC_CONF2_RX_STREAM	FIELD16(0x000f) +#define EEPROM_NIC_CONF2_TX_STREAM	FIELD16(0x00f0) +#define EEPROM_NIC_CONF2_CRYSTAL	FIELD16(0x0600) + +/*   * EEPROM LNA   */ -#define EEPROM_LNA			0x0022  #define EEPROM_LNA_BG			FIELD16(0x00ff)  #define EEPROM_LNA_A0			FIELD16(0xff00)  /*   * EEPROM RSSI BG offset   */ -#define EEPROM_RSSI_BG			0x0023  #define EEPROM_RSSI_BG_OFFSET0		FIELD16(0x00ff)  #define EEPROM_RSSI_BG_OFFSET1		FIELD16(0xff00)  /*   * EEPROM RSSI BG2 offset   */ -#define EEPROM_RSSI_BG2			0x0024  #define EEPROM_RSSI_BG2_OFFSET2		FIELD16(0x00ff)  #define EEPROM_RSSI_BG2_LNA_A1		FIELD16(0xff00)  /*   * EEPROM TXMIXER GAIN BG offset (note overlaps with EEPROM RSSI BG2).   */ -#define EEPROM_TXMIXER_GAIN_BG		0x0024  #define EEPROM_TXMIXER_GAIN_BG_VAL	FIELD16(0x0007)  /*   * EEPROM RSSI A offset   */ -#define EEPROM_RSSI_A			0x0025  #define EEPROM_RSSI_A_OFFSET0		FIELD16(0x00ff)  #define EEPROM_RSSI_A_OFFSET1		FIELD16(0xff00)  /*   * EEPROM RSSI A2 offset   */ -#define EEPROM_RSSI_A2			0x0026  #define EEPROM_RSSI_A2_OFFSET2		FIELD16(0x00ff)  #define EEPROM_RSSI_A2_LNA_A2		FIELD16(0xff00)  /* - * EEPROM Maximum TX power values + * EEPROM TXMIXER GAIN A offset (note overlaps with EEPROM RSSI A2). + */ +#define EEPROM_TXMIXER_GAIN_A_VAL	FIELD16(0x0007) + +/* + * EEPROM EIRP Maximum TX power values(unit: dbm)   */ -#define EEPROM_MAX_TX_POWER		0x0027 -#define EEPROM_MAX_TX_POWER_24GHZ	FIELD16(0x00ff) -#define EEPROM_MAX_TX_POWER_5GHZ	FIELD16(0xff00) +#define EEPROM_EIRP_MAX_TX_POWER_2GHZ	FIELD16(0x00ff) +#define EEPROM_EIRP_MAX_TX_POWER_5GHZ	FIELD16(0xff00)  /*   * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. - *	This is delta in 40MHZ. - * VALUE: Tx Power dalta value (MAX=4) + * This is delta in 40MHZ. + * VALUE: Tx Power dalta value, MAX=4(unit: dbm)   * TYPE: 1: Plus the delta value, 0: minus the delta value - * TXPOWER: Enable: + * ENABLE: enable tx power compensation for 40BW   */ -#define EEPROM_TXPOWER_DELTA		0x0028 -#define EEPROM_TXPOWER_DELTA_VALUE	FIELD16(0x003f) -#define EEPROM_TXPOWER_DELTA_TYPE	FIELD16(0x0040) -#define EEPROM_TXPOWER_DELTA_TXPOWER	FIELD16(0x0080) +#define EEPROM_TXPOWER_DELTA_VALUE_2G	FIELD16(0x003f) +#define EEPROM_TXPOWER_DELTA_TYPE_2G	FIELD16(0x0040) +#define EEPROM_TXPOWER_DELTA_ENABLE_2G	FIELD16(0x0080) +#define EEPROM_TXPOWER_DELTA_VALUE_5G	FIELD16(0x3f00) +#define EEPROM_TXPOWER_DELTA_TYPE_5G	FIELD16(0x4000) +#define EEPROM_TXPOWER_DELTA_ENABLE_5G	FIELD16(0x8000)  /*   * EEPROM TXPOWER 802.11BG   */ -#define	EEPROM_TXPOWER_BG1		0x0029 -#define	EEPROM_TXPOWER_BG2		0x0030  #define EEPROM_TXPOWER_BG_SIZE		7  #define EEPROM_TXPOWER_BG_1		FIELD16(0x00ff)  #define EEPROM_TXPOWER_BG_2		FIELD16(0xff00)  /* + * EEPROM temperature compensation boundaries 802.11BG + * MINUS4: If the actual TSSI is below this boundary, tx power needs to be + *         reduced by (agc_step * -4) + * MINUS3: If the actual TSSI is below this boundary, tx power needs to be + *         reduced by (agc_step * -3) + */ +#define EEPROM_TSSI_BOUND_BG1_MINUS4	FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_BG1_MINUS3	FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11BG + * MINUS2: If the actual TSSI is below this boundary, tx power needs to be + *         reduced by (agc_step * -2) + * MINUS1: If the actual TSSI is below this boundary, tx power needs to be + *         reduced by (agc_step * -1) + */ +#define EEPROM_TSSI_BOUND_BG2_MINUS2	FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_BG2_MINUS1	FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11BG + * REF: Reference TSSI value, no tx power changes needed + * PLUS1: If the actual TSSI is above this boundary, tx power needs to be + *        increased by (agc_step * 1) + */ +#define EEPROM_TSSI_BOUND_BG3_REF	FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_BG3_PLUS1	FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11BG + * PLUS2: If the actual TSSI is above this boundary, tx power needs to be + *        increased by (agc_step * 2) + * PLUS3: If the actual TSSI is above this boundary, tx power needs to be + *        increased by (agc_step * 3) + */ +#define EEPROM_TSSI_BOUND_BG4_PLUS2	FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_BG4_PLUS3	FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11BG + * PLUS4: If the actual TSSI is above this boundary, tx power needs to be + *        increased by (agc_step * 4) + * AGC_STEP: Temperature compensation step. + */ +#define EEPROM_TSSI_BOUND_BG5_PLUS4	FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_BG5_AGC_STEP	FIELD16(0xff00) + +/*   * EEPROM TXPOWER 802.11A   */ -#define EEPROM_TXPOWER_A1		0x003c -#define EEPROM_TXPOWER_A2		0x0053  #define EEPROM_TXPOWER_A_SIZE		6  #define EEPROM_TXPOWER_A_1		FIELD16(0x00ff)  #define EEPROM_TXPOWER_A_2		FIELD16(0xff00) +/* EEPROM_TXPOWER_{A,G} fields for RT3593 */ +#define EEPROM_TXPOWER_ALC		FIELD8(0x1f) +#define EEPROM_TXPOWER_FINE_CTRL	FIELD8(0xe0) + +/* + * EEPROM temperature compensation boundaries 802.11A + * MINUS4: If the actual TSSI is below this boundary, tx power needs to be + *         reduced by (agc_step * -4) + * MINUS3: If the actual TSSI is below this boundary, tx power needs to be + *         reduced by (agc_step * -3) + */ +#define EEPROM_TSSI_BOUND_A1_MINUS4	FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_A1_MINUS3	FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11A + * MINUS2: If the actual TSSI is below this boundary, tx power needs to be + *         reduced by (agc_step * -2) + * MINUS1: If the actual TSSI is below this boundary, tx power needs to be + *         reduced by (agc_step * -1) + */ +#define EEPROM_TSSI_BOUND_A2_MINUS2	FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_A2_MINUS1	FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11A + * REF: Reference TSSI value, no tx power changes needed + * PLUS1: If the actual TSSI is above this boundary, tx power needs to be + *        increased by (agc_step * 1) + */ +#define EEPROM_TSSI_BOUND_A3_REF	FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_A3_PLUS1	FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11A + * PLUS2: If the actual TSSI is above this boundary, tx power needs to be + *        increased by (agc_step * 2) + * PLUS3: If the actual TSSI is above this boundary, tx power needs to be + *        increased by (agc_step * 3) + */ +#define EEPROM_TSSI_BOUND_A4_PLUS2	FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_A4_PLUS3	FIELD16(0xff00) + +/* + * EEPROM temperature compensation boundaries 802.11A + * PLUS4: If the actual TSSI is above this boundary, tx power needs to be + *        increased by (agc_step * 4) + * AGC_STEP: Temperature compensation step. + */ +#define EEPROM_TSSI_BOUND_A5_PLUS4	FIELD16(0x00ff) +#define EEPROM_TSSI_BOUND_A5_AGC_STEP	FIELD16(0xff00) +  /*   * EEPROM TXPOWER by rate: tx power per tx rate for HT20 mode   */ -#define EEPROM_TXPOWER_BYRATE		0x006f  #define EEPROM_TXPOWER_BYRATE_SIZE	9  #define EEPROM_TXPOWER_BYRATE_RATE0	FIELD16(0x000f) @@ -1993,13 +2712,77 @@ struct mac_iveiv_entry {  /*   * EEPROM BBP.   */ -#define	EEPROM_BBP_START		0x0078  #define EEPROM_BBP_SIZE			16  #define EEPROM_BBP_VALUE		FIELD16(0x00ff)  #define EEPROM_BBP_REG_ID		FIELD16(0xff00) +/* EEPROM_EXT_LNA2 */ +#define EEPROM_EXT_LNA2_A1		FIELD16(0x00ff) +#define EEPROM_EXT_LNA2_A2		FIELD16(0xff00) + +/* + * EEPROM IQ Calibration, unlike other entries those are byte addresses. + */ + +#define EEPROM_IQ_GAIN_CAL_TX0_2G			0x130 +#define EEPROM_IQ_PHASE_CAL_TX0_2G			0x131 +#define EEPROM_IQ_GROUPDELAY_CAL_TX0_2G			0x132 +#define EEPROM_IQ_GAIN_CAL_TX1_2G			0x133 +#define EEPROM_IQ_PHASE_CAL_TX1_2G			0x134 +#define EEPROM_IQ_GROUPDELAY_CAL_TX1_2G			0x135 +#define EEPROM_IQ_GAIN_CAL_RX0_2G			0x136 +#define EEPROM_IQ_PHASE_CAL_RX0_2G			0x137 +#define EEPROM_IQ_GROUPDELAY_CAL_RX0_2G			0x138 +#define EEPROM_IQ_GAIN_CAL_RX1_2G			0x139 +#define EEPROM_IQ_PHASE_CAL_RX1_2G			0x13A +#define EEPROM_IQ_GROUPDELAY_CAL_RX1_2G			0x13B +#define EEPROM_RF_IQ_COMPENSATION_CONTROL		0x13C +#define EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL	0x13D +#define EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G		0x144 +#define EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G		0x145 +#define EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G	0X146 +#define EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G	0x147 +#define EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G	0x148 +#define EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G	0x149 +#define EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G		0x14A +#define EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G		0x14B +#define EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G	0X14C +#define EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G	0x14D +#define EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G	0x14E +#define EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G	0x14F +#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH36_TO_CH64_5G	0x150 +#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH36_TO_CH64_5G	0x151 +#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH100_TO_CH138_5G	0x152 +#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH100_TO_CH138_5G	0x153 +#define EEPROM_IQ_GROUPDELAY_CAL_TX0_CH140_TO_CH165_5G	0x154 +#define EEPROM_IQ_GROUPDELAY_CAL_TX1_CH140_TO_CH165_5G	0x155 +#define EEPROM_IQ_GAIN_CAL_RX0_CH36_TO_CH64_5G		0x156 +#define EEPROM_IQ_PHASE_CAL_RX0_CH36_TO_CH64_5G		0x157 +#define EEPROM_IQ_GAIN_CAL_RX0_CH100_TO_CH138_5G	0X158 +#define EEPROM_IQ_PHASE_CAL_RX0_CH100_TO_CH138_5G	0x159 +#define EEPROM_IQ_GAIN_CAL_RX0_CH140_TO_CH165_5G	0x15A +#define EEPROM_IQ_PHASE_CAL_RX0_CH140_TO_CH165_5G	0x15B +#define EEPROM_IQ_GAIN_CAL_RX1_CH36_TO_CH64_5G		0x15C +#define EEPROM_IQ_PHASE_CAL_RX1_CH36_TO_CH64_5G		0x15D +#define EEPROM_IQ_GAIN_CAL_RX1_CH100_TO_CH138_5G	0X15E +#define EEPROM_IQ_PHASE_CAL_RX1_CH100_TO_CH138_5G	0x15F +#define EEPROM_IQ_GAIN_CAL_RX1_CH140_TO_CH165_5G	0x160 +#define EEPROM_IQ_PHASE_CAL_RX1_CH140_TO_CH165_5G	0x161 +#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH36_TO_CH64_5G	0x162 +#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH36_TO_CH64_5G	0x163 +#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH100_TO_CH138_5G	0x164 +#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH100_TO_CH138_5G	0x165 +#define EEPROM_IQ_GROUPDELAY_CAL_RX0_CH140_TO_CH165_5G	0x166 +#define EEPROM_IQ_GROUPDELAY_CAL_RX1_CH140_TO_CH165_5G	0x167 +  /*   * MCU mailbox commands. + * MCU_SLEEP - go to power-save mode. + *             arg1: 1: save as much power as possible, 0: save less power. + *             status: 1: success, 2: already asleep, + *                     3: maybe MAC is busy so can't finish this task. + * MCU_RADIO_OFF + *             arg0: 0: do power-saving, NOT turn off radio.   */  #define MCU_SLEEP			0x30  #define MCU_WAKEUP			0x31 @@ -2007,24 +2790,35 @@ struct mac_iveiv_entry {  #define MCU_CURRENT			0x36  #define MCU_LED				0x50  #define MCU_LED_STRENGTH		0x51 -#define MCU_LED_1			0x52 -#define MCU_LED_2			0x53 -#define MCU_LED_3			0x54 +#define MCU_LED_AG_CONF			0x52 +#define MCU_LED_ACT_CONF		0x53 +#define MCU_LED_LED_POLARITY		0x54  #define MCU_RADAR			0x60  #define MCU_BOOT_SIGNAL			0x72 +#define MCU_ANT_SELECT			0X73 +#define MCU_FREQ_OFFSET			0x74  #define MCU_BBP_SIGNAL			0x80  #define MCU_POWER_SAVE			0x83 +#define MCU_BAND_SELECT			0x91  /*   * MCU mailbox tokens   */ -#define TOKEN_WAKUP			3 +#define TOKEN_SLEEP			1 +#define TOKEN_RADIO_OFF			2 +#define TOKEN_WAKEUP			3 +  /*   * DMA descriptor defines.   */ -#define TXWI_DESC_SIZE			(4 * sizeof(__le32)) -#define RXWI_DESC_SIZE			(4 * sizeof(__le32)) + +#define TXWI_DESC_SIZE_4WORDS		(4 * sizeof(__le32)) +#define TXWI_DESC_SIZE_5WORDS		(5 * sizeof(__le32)) + +#define RXWI_DESC_SIZE_4WORDS		(4 * sizeof(__le32)) +#define RXWI_DESC_SIZE_5WORDS		(5 * sizeof(__le32)) +#define RXWI_DESC_SIZE_6WORDS		(6 * sizeof(__le32))  /*   * TX WI structure @@ -2144,16 +2938,37 @@ struct mac_iveiv_entry {  #define MAX_A_TXPOWER	15  #define DEFAULT_TXPOWER	5 +#define MIN_A_TXPOWER_3593	0 +#define MAX_A_TXPOWER_3593	31 +  #define TXPOWER_G_FROM_DEV(__txpower) \  	((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) -#define TXPOWER_G_TO_DEV(__txpower) \ -	clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER) -  #define TXPOWER_A_FROM_DEV(__txpower) \  	((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) -#define TXPOWER_A_TO_DEV(__txpower) \ -	clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER) +/* + *  Board's maximun TX power limitation + */ +#define EIRP_MAX_TX_POWER_LIMIT	0x50 + +/* + * Number of TBTT intervals after which we have to adjust + * the hw beacon timer. + */ +#define BCN_TBTT_OFFSET 64 + +/* + * RT2800 driver data structure + */ +struct rt2800_drv_data { +	u8 calibration_bw20; +	u8 calibration_bw40; +	u8 bbp25; +	u8 bbp26; +	u8 txmixer_gain_24g; +	u8 txmixer_gain_5g; +	unsigned int tbtt_tick; +};  #endif /* RT2800_H */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 75631614aba..c17fcf27272 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -24,9 +24,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -80,7 +78,7 @@ static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev)  	    rt2x00_rf(rt2x00dev, RF3022))  		return true; -	NOTICE(rt2x00dev, "Unknown RF chipset on rt305x\n"); +	rt2x00_warn(rt2x00dev, "Unknown RF chipset on rt305x\n");  	return false;  } @@ -221,6 +219,215 @@ static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,  	mutex_unlock(&rt2x00dev->csr_mutex);  } +static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = { +	[EEPROM_CHIP_ID]		= 0x0000, +	[EEPROM_VERSION]		= 0x0001, +	[EEPROM_MAC_ADDR_0]		= 0x0002, +	[EEPROM_MAC_ADDR_1]		= 0x0003, +	[EEPROM_MAC_ADDR_2]		= 0x0004, +	[EEPROM_NIC_CONF0]		= 0x001a, +	[EEPROM_NIC_CONF1]		= 0x001b, +	[EEPROM_FREQ]			= 0x001d, +	[EEPROM_LED_AG_CONF]		= 0x001e, +	[EEPROM_LED_ACT_CONF]		= 0x001f, +	[EEPROM_LED_POLARITY]		= 0x0020, +	[EEPROM_NIC_CONF2]		= 0x0021, +	[EEPROM_LNA]			= 0x0022, +	[EEPROM_RSSI_BG]		= 0x0023, +	[EEPROM_RSSI_BG2]		= 0x0024, +	[EEPROM_TXMIXER_GAIN_BG]	= 0x0024, /* overlaps with RSSI_BG2 */ +	[EEPROM_RSSI_A]			= 0x0025, +	[EEPROM_RSSI_A2]		= 0x0026, +	[EEPROM_TXMIXER_GAIN_A]		= 0x0026, /* overlaps with RSSI_A2 */ +	[EEPROM_EIRP_MAX_TX_POWER]	= 0x0027, +	[EEPROM_TXPOWER_DELTA]		= 0x0028, +	[EEPROM_TXPOWER_BG1]		= 0x0029, +	[EEPROM_TXPOWER_BG2]		= 0x0030, +	[EEPROM_TSSI_BOUND_BG1]		= 0x0037, +	[EEPROM_TSSI_BOUND_BG2]		= 0x0038, +	[EEPROM_TSSI_BOUND_BG3]		= 0x0039, +	[EEPROM_TSSI_BOUND_BG4]		= 0x003a, +	[EEPROM_TSSI_BOUND_BG5]		= 0x003b, +	[EEPROM_TXPOWER_A1]		= 0x003c, +	[EEPROM_TXPOWER_A2]		= 0x0053, +	[EEPROM_TSSI_BOUND_A1]		= 0x006a, +	[EEPROM_TSSI_BOUND_A2]		= 0x006b, +	[EEPROM_TSSI_BOUND_A3]		= 0x006c, +	[EEPROM_TSSI_BOUND_A4]		= 0x006d, +	[EEPROM_TSSI_BOUND_A5]		= 0x006e, +	[EEPROM_TXPOWER_BYRATE]		= 0x006f, +	[EEPROM_BBP_START]		= 0x0078, +}; + +static const unsigned int rt2800_eeprom_map_ext[EEPROM_WORD_COUNT] = { +	[EEPROM_CHIP_ID]		= 0x0000, +	[EEPROM_VERSION]		= 0x0001, +	[EEPROM_MAC_ADDR_0]		= 0x0002, +	[EEPROM_MAC_ADDR_1]		= 0x0003, +	[EEPROM_MAC_ADDR_2]		= 0x0004, +	[EEPROM_NIC_CONF0]		= 0x001a, +	[EEPROM_NIC_CONF1]		= 0x001b, +	[EEPROM_NIC_CONF2]		= 0x001c, +	[EEPROM_EIRP_MAX_TX_POWER]	= 0x0020, +	[EEPROM_FREQ]			= 0x0022, +	[EEPROM_LED_AG_CONF]		= 0x0023, +	[EEPROM_LED_ACT_CONF]		= 0x0024, +	[EEPROM_LED_POLARITY]		= 0x0025, +	[EEPROM_LNA]			= 0x0026, +	[EEPROM_EXT_LNA2]		= 0x0027, +	[EEPROM_RSSI_BG]		= 0x0028, +	[EEPROM_RSSI_BG2]		= 0x0029, +	[EEPROM_RSSI_A]			= 0x002a, +	[EEPROM_RSSI_A2]		= 0x002b, +	[EEPROM_TXPOWER_BG1]		= 0x0030, +	[EEPROM_TXPOWER_BG2]		= 0x0037, +	[EEPROM_EXT_TXPOWER_BG3]	= 0x003e, +	[EEPROM_TSSI_BOUND_BG1]		= 0x0045, +	[EEPROM_TSSI_BOUND_BG2]		= 0x0046, +	[EEPROM_TSSI_BOUND_BG3]		= 0x0047, +	[EEPROM_TSSI_BOUND_BG4]		= 0x0048, +	[EEPROM_TSSI_BOUND_BG5]		= 0x0049, +	[EEPROM_TXPOWER_A1]		= 0x004b, +	[EEPROM_TXPOWER_A2]		= 0x0065, +	[EEPROM_EXT_TXPOWER_A3]		= 0x007f, +	[EEPROM_TSSI_BOUND_A1]		= 0x009a, +	[EEPROM_TSSI_BOUND_A2]		= 0x009b, +	[EEPROM_TSSI_BOUND_A3]		= 0x009c, +	[EEPROM_TSSI_BOUND_A4]		= 0x009d, +	[EEPROM_TSSI_BOUND_A5]		= 0x009e, +	[EEPROM_TXPOWER_BYRATE]		= 0x00a0, +}; + +static unsigned int rt2800_eeprom_word_index(struct rt2x00_dev *rt2x00dev, +					     const enum rt2800_eeprom_word word) +{ +	const unsigned int *map; +	unsigned int index; + +	if (WARN_ONCE(word >= EEPROM_WORD_COUNT, +		      "%s: invalid EEPROM word %d\n", +		      wiphy_name(rt2x00dev->hw->wiphy), word)) +		return 0; + +	if (rt2x00_rt(rt2x00dev, RT3593)) +		map = rt2800_eeprom_map_ext; +	else +		map = rt2800_eeprom_map; + +	index = map[word]; + +	/* Index 0 is valid only for EEPROM_CHIP_ID. +	 * Otherwise it means that the offset of the +	 * given word is not initialized in the map, +	 * or that the field is not usable on the +	 * actual chipset. +	 */ +	WARN_ONCE(word != EEPROM_CHIP_ID && index == 0, +		  "%s: invalid access of EEPROM word %d\n", +		  wiphy_name(rt2x00dev->hw->wiphy), word); + +	return index; +} + +static void *rt2800_eeprom_addr(struct rt2x00_dev *rt2x00dev, +				const enum rt2800_eeprom_word word) +{ +	unsigned int index; + +	index = rt2800_eeprom_word_index(rt2x00dev, word); +	return rt2x00_eeprom_addr(rt2x00dev, index); +} + +static void rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev, +			       const enum rt2800_eeprom_word word, u16 *data) +{ +	unsigned int index; + +	index = rt2800_eeprom_word_index(rt2x00dev, word); +	rt2x00_eeprom_read(rt2x00dev, index, data); +} + +static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev, +				const enum rt2800_eeprom_word word, u16 data) +{ +	unsigned int index; + +	index = rt2800_eeprom_word_index(rt2x00dev, word); +	rt2x00_eeprom_write(rt2x00dev, index, data); +} + +static void rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev, +					  const enum rt2800_eeprom_word array, +					  unsigned int offset, +					  u16 *data) +{ +	unsigned int index; + +	index = rt2800_eeprom_word_index(rt2x00dev, array); +	rt2x00_eeprom_read(rt2x00dev, index + offset, data); +} + +static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; +	int i, count; + +	rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); +	if (rt2x00_get_field32(reg, WLAN_EN)) +		return 0; + +	rt2x00_set_field32(®, WLAN_GPIO_OUT_OE_BIT_ALL, 0xff); +	rt2x00_set_field32(®, FRC_WL_ANT_SET, 1); +	rt2x00_set_field32(®, WLAN_CLK_EN, 0); +	rt2x00_set_field32(®, WLAN_EN, 1); +	rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); + +	udelay(REGISTER_BUSY_DELAY); + +	count = 0; +	do { +		/* +		 * Check PLL_LD & XTAL_RDY. +		 */ +		for (i = 0; i < REGISTER_BUSY_COUNT; i++) { +			rt2800_register_read(rt2x00dev, CMB_CTRL, ®); +			if (rt2x00_get_field32(reg, PLL_LD) && +			    rt2x00_get_field32(reg, XTAL_RDY)) +				break; +			udelay(REGISTER_BUSY_DELAY); +		} + +		if (i >= REGISTER_BUSY_COUNT) { + +			if (count >= 10) +				return -EIO; + +			rt2800_register_write(rt2x00dev, 0x58, 0x018); +			udelay(REGISTER_BUSY_DELAY); +			rt2800_register_write(rt2x00dev, 0x58, 0x418); +			udelay(REGISTER_BUSY_DELAY); +			rt2800_register_write(rt2x00dev, 0x58, 0x618); +			udelay(REGISTER_BUSY_DELAY); +			count++; +		} else { +			count = 0; +		} + +		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); +		rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 0); +		rt2x00_set_field32(®, WLAN_CLK_EN, 1); +		rt2x00_set_field32(®, WLAN_RESET, 1); +		rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); +		udelay(10); +		rt2x00_set_field32(®, WLAN_RESET, 0); +		rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); +		udelay(10); +		rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, 0x7fffffff); +	} while (count != 0); + +	return 0; +} +  void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,  			const u8 command, const u8 token,  			const u8 arg0, const u8 arg1) @@ -267,7 +474,7 @@ int rt2800_wait_csr_ready(struct rt2x00_dev *rt2x00dev)  		msleep(1);  	} -	ERROR(rt2x00dev, "Unstable hardware.\n"); +	rt2x00_err(rt2x00dev, "Unstable hardware\n");  	return -EBUSY;  }  EXPORT_SYMBOL_GPL(rt2800_wait_csr_ready); @@ -290,11 +497,48 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)  		msleep(10);  	} -	ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); +	rt2x00_err(rt2x00dev, "WPDMA TX/RX busy [0x%08x]\n", reg);  	return -EACCES;  }  EXPORT_SYMBOL_GPL(rt2800_wait_wpdma_ready); +void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; + +	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); +	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); +	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); +	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); +	rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); +	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); +	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); +} +EXPORT_SYMBOL_GPL(rt2800_disable_wpdma); + +void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev, +			       unsigned short *txwi_size, +			       unsigned short *rxwi_size) +{ +	switch (rt2x00dev->chip.rt) { +	case RT3593: +		*txwi_size = TXWI_DESC_SIZE_4WORDS; +		*rxwi_size = RXWI_DESC_SIZE_5WORDS; +		break; + +	case RT5592: +		*txwi_size = TXWI_DESC_SIZE_5WORDS; +		*rxwi_size = RXWI_DESC_SIZE_6WORDS; +		break; + +	default: +		*txwi_size = TXWI_DESC_SIZE_4WORDS; +		*rxwi_size = RXWI_DESC_SIZE_4WORDS; +		break; +	} +} +EXPORT_SYMBOL_GPL(rt2800_get_txwi_rxwi_size); +  static bool rt2800_check_firmware_crc(const u8 *data, const size_t len)  {  	u16 fw_crc; @@ -340,16 +584,15 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev,  	 * of 4kb. Certain USB chipsets however require different firmware,  	 * which Ralink only provides attached to the original firmware  	 * file. Thus for USB devices, firmware files have a length -	 * which is a multiple of 4kb. +	 * which is a multiple of 4kb. The firmware for rt3290 chip also +	 * have a length which is a multiple of 4kb.  	 */ -	if (rt2x00_is_usb(rt2x00dev)) { +	if (rt2x00_is_usb(rt2x00dev) || rt2x00_rt(rt2x00dev, RT3290))  		fw_len = 4096; -		multiple = true; -	} else { +	else  		fw_len = 8192; -		multiple = true; -	} +	multiple = true;  	/*  	 * Validate the firmware length  	 */ @@ -387,6 +630,13 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,  {  	unsigned int i;  	u32 reg; +	int retval; + +	if (rt2x00_rt(rt2x00dev, RT3290)) { +		retval = rt2800_enable_wlan_rt3290(rt2x00dev); +		if (retval) +			return -EBUSY; +	}  	/*  	 * If driver doesn't wake up firmware here, @@ -400,20 +650,20 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,  	if (rt2800_wait_csr_ready(rt2x00dev))  		return -EBUSY; -	if (rt2x00_is_pci(rt2x00dev)) +	if (rt2x00_is_pci(rt2x00dev)) { +		if (rt2x00_rt(rt2x00dev, RT3290) || +		    rt2x00_rt(rt2x00dev, RT3572) || +		    rt2x00_rt(rt2x00dev, RT5390) || +		    rt2x00_rt(rt2x00dev, RT5392)) { +			rt2800_register_read(rt2x00dev, AUX_CTRL, ®); +			rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); +			rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); +			rt2800_register_write(rt2x00dev, AUX_CTRL, reg); +		}  		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002); +	} -	/* -	 * Disable DMA, will be reenabled later when enabling -	 * the radio. -	 */ -	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); -	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); +	rt2800_disable_wpdma(rt2x00dev);  	/*  	 * Write firmware to the device. @@ -431,15 +681,25 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev,  	}  	if (i == REGISTER_BUSY_COUNT) { -		ERROR(rt2x00dev, "PBF system register not ready.\n"); +		rt2x00_err(rt2x00dev, "PBF system register not ready\n");  		return -EBUSY;  	}  	/* +	 * Disable DMA, will be reenabled later when enabling +	 * the radio. +	 */ +	rt2800_disable_wpdma(rt2x00dev); + +	/*  	 * Initialize firmware.  	 */  	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);  	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +	if (rt2x00_is_usb(rt2x00dev)) { +		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); +		rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); +	}  	msleep(1);  	return 0; @@ -451,6 +711,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,  {  	__le32 *txwi = rt2800_drv_get_txwi(entry);  	u32 word; +	int i;  	/*  	 * Initialize TX Info descriptor @@ -465,14 +726,15 @@ void rt2800_write_tx_data(struct queue_entry *entry,  			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));  	rt2x00_set_field32(&word, TXWI_W0_AMPDU,  			   test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags)); -	rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density); -	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->txop); -	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs); +	rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, +			   txdesc->u.ht.mpdu_density); +	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->u.ht.txop); +	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->u.ht.mcs);  	rt2x00_set_field32(&word, TXWI_W0_BW,  			   test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags));  	rt2x00_set_field32(&word, TXWI_W0_SHORT_GI,  			   test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags)); -	rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc); +	rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->u.ht.stbc);  	rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);  	rt2x00_desc_write(txwi, 0, word); @@ -481,10 +743,10 @@ void rt2800_write_tx_data(struct queue_entry *entry,  			   test_bit(ENTRY_TXD_ACK, &txdesc->flags));  	rt2x00_set_field32(&word, TXWI_W1_NSEQ,  			   test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); -	rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); +	rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->u.ht.ba_size);  	rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,  			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? -			   txdesc->key_idx : 0xff); +			   txdesc->key_idx : txdesc->u.ht.wcid);  	rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,  			   txdesc->length);  	rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid); @@ -492,38 +754,40 @@ void rt2800_write_tx_data(struct queue_entry *entry,  	rt2x00_desc_write(txwi, 1, word);  	/* -	 * Always write 0 to IV/EIV fields, hardware will insert the IV -	 * from the IVEIV register when TXD_W3_WIV is set to 0. +	 * Always write 0 to IV/EIV fields (word 2 and 3), hardware will insert +	 * the IV from the IVEIV register when TXD_W3_WIV is set to 0.  	 * When TXD_W3_WIV is set to 1 it will use the IV data  	 * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which  	 * crypto entry in the registers should be used to encrypt the frame. +	 * +	 * Nulify all remaining words as well, we don't know how to program them.  	 */ -	_rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); -	_rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); +	for (i = 2; i < entry->queue->winfo_size / sizeof(__le32); i++) +		_rt2x00_desc_write(txwi, i, 0);  }  EXPORT_SYMBOL_GPL(rt2800_write_tx_data);  static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)  { -	int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); -	int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); -	int rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2); +	s8 rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); +	s8 rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); +	s8 rssi2 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI2);  	u16 eeprom;  	u8 offset0;  	u8 offset1;  	u8 offset2;  	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom);  		offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0);  		offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);  		offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2);  	} else { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom);  		offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0);  		offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1); -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);  		offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2);  	} @@ -543,7 +807,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2)  	 * which gives less energy...  	 */  	rssi0 = max(rssi0, rssi1); -	return max(rssi0, rssi2); +	return (int)max(rssi0, rssi2);  }  void rt2800_process_rxwi(struct queue_entry *entry, @@ -584,58 +848,14 @@ void rt2800_process_rxwi(struct queue_entry *entry,  	 * Convert descriptor AGC value to RSSI value.  	 */  	rxdesc->rssi = rt2800_agc_to_rssi(entry->queue->rt2x00dev, word); -  	/* -	 * Remove RXWI descriptor from start of buffer. +	 * Remove RXWI descriptor from start of the buffer.  	 */ -	skb_pull(entry->skb, RXWI_DESC_SIZE); +	skb_pull(entry->skb, entry->queue->winfo_size);  }  EXPORT_SYMBOL_GPL(rt2800_process_rxwi); -static bool rt2800_txdone_entry_check(struct queue_entry *entry, u32 reg) -{ -	__le32 *txwi; -	u32 word; -	int wcid, ack, pid; -	int tx_wcid, tx_ack, tx_pid; - -	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID); -	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); -	pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); - -	/* -	 * This frames has returned with an IO error, -	 * so the status report is not intended for this -	 * frame. -	 */ -	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) { -		rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); -		return false; -	} - -	/* -	 * Validate if this TX status report is intended for -	 * this entry by comparing the WCID/ACK/PID fields. -	 */ -	txwi = rt2800_drv_get_txwi(entry); - -	rt2x00_desc_read(txwi, 1, &word); -	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); -	tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK); -	tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID); - -	if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) { -		WARNING(entry->queue->rt2x00dev, -			"TX status report missed for queue %d entry %d\n", -		entry->queue->qid, entry->entry_idx); -		rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); -		return false; -	} - -	return true; -} - -void rt2800_txdone_entry(struct queue_entry *entry, u32 status) +void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); @@ -643,13 +863,11 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)  	u32 word;  	u16 mcs, real_mcs;  	int aggr, ampdu; -	__le32 *txwi;  	/*  	 * Obtain the status about this packet.  	 */  	txdesc.flags = 0; -	txwi = rt2800_drv_get_txwi(entry);  	rt2x00_desc_read(txwi, 0, &word);  	mcs = rt2x00_get_field32(word, TXWI_W0_MCS); @@ -674,11 +892,14 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)  	 * confuse the rate control algortihm by providing clearly wrong  	 * data.  	 */ -	if (aggr == 1 && ampdu == 0 && real_mcs != mcs) { +	if (unlikely(aggr == 1 && ampdu == 0 && real_mcs != mcs)) {  		skbdesc->tx_rate_idx = real_mcs;  		mcs = real_mcs;  	} +	if (aggr == 1 || ampdu == 1) +		__set_bit(TXDONE_AMPDU, &txdesc.flags); +  	/*  	 * Ralink has a retry mechanism using a global fallback  	 * table. We setup this fallback table to try the immediate @@ -714,86 +935,47 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status)  }  EXPORT_SYMBOL_GPL(rt2800_txdone_entry); -void rt2800_txdone(struct rt2x00_dev *rt2x00dev) +static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, +					  unsigned int index)  { -	struct data_queue *queue; -	struct queue_entry *entry; -	u32 reg; -	u8 pid; -	int i; - -	/* -	 * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO -	 * at most X times and also stop processing once the TX_STA_FIFO_VALID -	 * flag is not set anymore. -	 * -	 * The legacy drivers use X=TX_RING_SIZE but state in a comment -	 * that the TX_STA_FIFO stack has a size of 16. We stick to our -	 * tx ring size for now. -	 */ -	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { -		rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); -		if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) -			break; - -		/* -		 * Skip this entry when it contains an invalid -		 * queue identication number. -		 */ -		pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); -		if (pid >= QID_RX) -			continue; - -		queue = rt2x00queue_get_queue(rt2x00dev, pid); -		if (unlikely(!queue)) -			continue; - -		/* -		 * Inside each queue, we process each entry in a chronological -		 * order. We first check that the queue is not empty. -		 */ -		entry = NULL; -		while (!rt2x00queue_empty(queue)) { -			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); -			if (rt2800_txdone_entry_check(entry, reg)) -				break; -		} - -		if (!entry || rt2x00queue_empty(queue)) -			break; +	return HW_BEACON_BASE(index); +} -		rt2800_txdone_entry(entry, reg); -	} +static inline u8 rt2800_get_beacon_offset(struct rt2x00_dev *rt2x00dev, +					  unsigned int index) +{ +	return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index));  } -EXPORT_SYMBOL_GPL(rt2800_txdone);  void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);  	unsigned int beacon_base; -	u32 reg; +	unsigned int padding_len; +	u32 orig_reg, reg; +	const int txwi_desc_size = entry->queue->winfo_size;  	/*  	 * Disable beaconing while we are reloading the beacon data,  	 * otherwise we might be sending out invalid data.  	 */  	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); +	orig_reg = reg;  	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0);  	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);  	/*  	 * Add space for the TXWI in front of the skb.  	 */ -	skb_push(entry->skb, TXWI_DESC_SIZE); -	memset(entry->skb, 0, TXWI_DESC_SIZE); +	memset(skb_push(entry->skb, txwi_desc_size), 0, txwi_desc_size);  	/*  	 * Register descriptor details in skb frame descriptor.  	 */  	skbdesc->flags |= SKBDESC_DESC_IN_SKB;  	skbdesc->desc = entry->skb->data; -	skbdesc->desc_len = TXWI_DESC_SIZE; +	skbdesc->desc_len = txwi_desc_size;  	/*  	 * Add the TXWI for the beacon to the skb. @@ -806,19 +988,26 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)  	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);  	/* -	 * Write entire beacon with TXWI to register. +	 * Write entire beacon with TXWI and padding to register.  	 */ -	beacon_base = HW_BEACON_OFFSET(entry->entry_idx); -	rt2800_register_multiwrite(rt2x00dev, beacon_base, -				   entry->skb->data, entry->skb->len); +	padding_len = roundup(entry->skb->len, 4) - entry->skb->len; +	if (padding_len && skb_pad(entry->skb, padding_len)) { +		rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n"); +		/* skb freed by skb_pad() on failure */ +		entry->skb = NULL; +		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg); +		return; +	} + +	beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx); + +	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, +				   entry->skb->len + padding_len);  	/* -	 * Enable beaconing again. +	 * Restore beaconing state.  	 */ -	rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); -	rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); -	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); -	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); +	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);  	/*  	 * Clean up beacon skb. @@ -828,20 +1017,50 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)  }  EXPORT_SYMBOL_GPL(rt2800_write_beacon); -static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev, -				       unsigned int beacon_base) +static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev, +						unsigned int index)  {  	int i; +	const int txwi_desc_size = rt2x00dev->bcn->winfo_size; +	unsigned int beacon_base; + +	beacon_base = rt2800_hw_beacon_base(rt2x00dev, index);  	/*  	 * For the Beacon base registers we only need to clear  	 * the whole TXWI which (when set to 0) will invalidate  	 * the entire beacon.  	 */ -	for (i = 0; i < TXWI_DESC_SIZE; i += sizeof(__le32)) +	for (i = 0; i < txwi_desc_size; i += sizeof(__le32))  		rt2800_register_write(rt2x00dev, beacon_base + i, 0);  } +void rt2800_clear_beacon(struct queue_entry *entry) +{ +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +	u32 orig_reg, reg; + +	/* +	 * Disable beaconing while we are reloading the beacon data, +	 * otherwise we might be sending out invalid data. +	 */ +	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &orig_reg); +	reg = orig_reg; +	rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); +	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + +	/* +	 * Clear beacon. +	 */ +	rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx); + +	/* +	 * Restore beaconing state. +	 */ +	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg); +} +EXPORT_SYMBOL_GPL(rt2800_clear_beacon); +  #ifdef CONFIG_RT2X00_LIB_DEBUGFS  const struct rt2x00debug rt2800_rt2x00debug = {  	.owner	= THIS_MODULE, @@ -854,6 +1073,9 @@ const struct rt2x00debug rt2800_rt2x00debug = {  		.word_count	= CSR_REG_SIZE / sizeof(u32),  	},  	.eeprom	= { +		/* NOTE: The local EEPROM access functions can't +		 * be used here, use the generic versions instead. +		 */  		.read		= rt2x00_eeprom_read,  		.write		= rt2x00_eeprom_write,  		.word_base	= EEPROM_BASE, @@ -874,6 +1096,13 @@ const struct rt2x00debug rt2800_rt2x00debug = {  		.word_size	= sizeof(u32),  		.word_count	= RF_SIZE / sizeof(u32),  	}, +	.rfcsr	= { +		.read		= rt2800_rfcsr_read, +		.write		= rt2800_rfcsr_write, +		.word_base	= RFCSR_BASE, +		.word_size	= sizeof(u8), +		.word_count	= RFCSR_SIZE / sizeof(u8), +	},  };  EXPORT_SYMBOL_GPL(rt2800_rt2x00debug);  #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ @@ -882,8 +1111,13 @@ int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; -	rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); -	return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); +	if (rt2x00_rt(rt2x00dev, RT3290)) { +		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); +		return rt2x00_get_field32(reg, WLAN_GPIO_IN_BIT0); +	} else { +		rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); +		return rt2x00_get_field32(reg, GPIO_CTRL_VAL2); +	}  }  EXPORT_SYMBOL_GPL(rt2800_rfkill_poll); @@ -902,41 +1136,50 @@ static void rt2800_brightness_set(struct led_classdev *led_cdev,  	unsigned int ledmode =  		rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,  				   EEPROM_FREQ_LED_MODE); - -	if (led->type == LED_TYPE_RADIO) { -		rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, -				      enabled ? 0x20 : 0); -	} else if (led->type == LED_TYPE_ASSOC) { -		rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, -				      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); -	} else if (led->type == LED_TYPE_QUALITY) { -		/* -		 * The brightness is divided into 6 levels (0 - 5), -		 * The specs tell us the following levels: -		 *	0, 1 ,3, 7, 15, 31 -		 * to determine the level in a simple way we can simply -		 * work with bitshifting: -		 *	(1 << level) - 1 -		 */ -		rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, -				      (1 << brightness / (LED_FULL / 6)) - 1, -				      polarity); -	} -} - -static int rt2800_blink_set(struct led_classdev *led_cdev, -			    unsigned long *delay_on, unsigned long *delay_off) -{ -	struct rt2x00_led *led = -	    container_of(led_cdev, struct rt2x00_led, led_dev);  	u32 reg; -	rt2800_register_read(led->rt2x00dev, LED_CFG, ®); -	rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); -	rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); -	rt2800_register_write(led->rt2x00dev, LED_CFG, reg); +	/* Check for SoC (SOC devices don't support MCU requests) */ +	if (rt2x00_is_soc(led->rt2x00dev)) { +		rt2800_register_read(led->rt2x00dev, LED_CFG, ®); + +		/* Set LED Polarity */ +		rt2x00_set_field32(®, LED_CFG_LED_POLAR, polarity); + +		/* Set LED Mode */ +		if (led->type == LED_TYPE_RADIO) { +			rt2x00_set_field32(®, LED_CFG_G_LED_MODE, +					   enabled ? 3 : 0); +		} else if (led->type == LED_TYPE_ASSOC) { +			rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, +					   enabled ? 3 : 0); +		} else if (led->type == LED_TYPE_QUALITY) { +			rt2x00_set_field32(®, LED_CFG_R_LED_MODE, +					   enabled ? 3 : 0); +		} -	return 0; +		rt2800_register_write(led->rt2x00dev, LED_CFG, reg); + +	} else { +		if (led->type == LED_TYPE_RADIO) { +			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, +					      enabled ? 0x20 : 0); +		} else if (led->type == LED_TYPE_ASSOC) { +			rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, +					      enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); +		} else if (led->type == LED_TYPE_QUALITY) { +			/* +			 * The brightness is divided into 6 levels (0 - 5), +			 * The specs tell us the following levels: +			 *	0, 1 ,3, 7, 15, 31 +			 * to determine the level in a simple way we can simply +			 * work with bitshifting: +			 *	(1 << level) - 1 +			 */ +			rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, +					      (1 << brightness / (LED_FULL / 6)) - 1, +					      polarity); +		} +	}  }  static void rt2800_init_led(struct rt2x00_dev *rt2x00dev, @@ -945,7 +1188,6 @@ static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,  	led->rt2x00dev = rt2x00dev;  	led->type = type;  	led->led_dev.brightness_set = rt2800_brightness_set; -	led->led_dev.blink_set = rt2800_blink_set;  	led->flags = LED_INITIALIZED;  }  #endif /* CONFIG_RT2X00_LIB_LEDS */ @@ -953,11 +1195,51 @@ static void rt2800_init_led(struct rt2x00_dev *rt2x00dev,  /*   * Configuration handlers.   */ -static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev, -				    struct rt2x00lib_crypto *crypto, -				    struct ieee80211_key_conf *key) +static void rt2800_config_wcid(struct rt2x00_dev *rt2x00dev, +			       const u8 *address, +			       int wcid)  {  	struct mac_wcid_entry wcid_entry; +	u32 offset; + +	offset = MAC_WCID_ENTRY(wcid); + +	memset(&wcid_entry, 0xff, sizeof(wcid_entry)); +	if (address) +		memcpy(wcid_entry.mac, address, ETH_ALEN); + +	rt2800_register_multiwrite(rt2x00dev, offset, +				      &wcid_entry, sizeof(wcid_entry)); +} + +static void rt2800_delete_wcid_attr(struct rt2x00_dev *rt2x00dev, int wcid) +{ +	u32 offset; +	offset = MAC_WCID_ATTR_ENTRY(wcid); +	rt2800_register_write(rt2x00dev, offset, 0); +} + +static void rt2800_config_wcid_attr_bssidx(struct rt2x00_dev *rt2x00dev, +					   int wcid, u32 bssidx) +{ +	u32 offset = MAC_WCID_ATTR_ENTRY(wcid); +	u32 reg; + +	/* +	 * The BSS Idx numbers is split in a main value of 3 bits, +	 * and a extended field for adding one additional bit to the value. +	 */ +	rt2800_register_read(rt2x00dev, offset, ®); +	rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, (bssidx & 0x7)); +	rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT, +			   (bssidx & 0x8) >> 3); +	rt2800_register_write(rt2x00dev, offset, reg); +} + +static void rt2800_config_wcid_attr_cipher(struct rt2x00_dev *rt2x00dev, +					   struct rt2x00lib_crypto *crypto, +					   struct ieee80211_key_conf *key) +{  	struct mac_iveiv_entry iveiv_entry;  	u32 offset;  	u32 reg; @@ -977,14 +1259,16 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,  				   (crypto->cipher & 0x7));  		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER_EXT,  				   (crypto->cipher & 0x8) >> 3); -		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, -				   (crypto->bssidx & 0x7)); -		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX_EXT, -				   (crypto->bssidx & 0x8) >> 3);  		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);  		rt2800_register_write(rt2x00dev, offset, reg);  	} else { -		rt2800_register_write(rt2x00dev, offset, 0); +		/* Delete the cipher without touching the bssidx */ +		rt2800_register_read(rt2x00dev, offset, ®); +		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, 0); +		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, 0); +		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER_EXT, 0); +		rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0); +		rt2800_register_write(rt2x00dev, offset, reg);  	}  	offset = MAC_IVEIV_ENTRY(key->hw_key_idx); @@ -997,14 +1281,6 @@ static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,  	iveiv_entry.iv[3] |= key->keyidx << 6;  	rt2800_register_multiwrite(rt2x00dev, offset,  				      &iveiv_entry, sizeof(iveiv_entry)); - -	offset = MAC_WCID_ENTRY(key->hw_key_idx); - -	memset(&wcid_entry, 0, sizeof(wcid_entry)); -	if (crypto->cmd == SET_KEY) -		memcpy(&wcid_entry, crypto->address, ETH_ALEN); -	rt2800_register_multiwrite(rt2x00dev, offset, -				      &wcid_entry, sizeof(wcid_entry));  }  int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev, @@ -1051,12 +1327,47 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,  	/*  	 * Update WCID information  	 */ -	rt2800_config_wcid_attr(rt2x00dev, crypto, key); +	rt2800_config_wcid(rt2x00dev, crypto->address, key->hw_key_idx); +	rt2800_config_wcid_attr_bssidx(rt2x00dev, key->hw_key_idx, +				       crypto->bssidx); +	rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);  	return 0;  }  EXPORT_SYMBOL_GPL(rt2800_config_shared_key); +static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev) +{ +	struct mac_wcid_entry wcid_entry; +	int idx; +	u32 offset; + +	/* +	 * Search for the first free WCID entry and return the corresponding +	 * index. +	 * +	 * Make sure the WCID starts _after_ the last possible shared key +	 * entry (>32). +	 * +	 * Since parts of the pairwise key table might be shared with +	 * the beacon frame buffers 6 & 7 we should only write into the +	 * first 222 entries. +	 */ +	for (idx = 33; idx <= 222; idx++) { +		offset = MAC_WCID_ENTRY(idx); +		rt2800_register_multiread(rt2x00dev, offset, &wcid_entry, +					  sizeof(wcid_entry)); +		if (is_broadcast_ether_addr(wcid_entry.mac)) +			return idx; +	} + +	/* +	 * Use -1 to indicate that we don't have any more space in the WCID +	 * table. +	 */ +	return -1; +} +  int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,  			       struct rt2x00lib_crypto *crypto,  			       struct ieee80211_key_conf *key) @@ -1066,18 +1377,12 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,  	if (crypto->cmd == SET_KEY) {  		/* -		 * 1 pairwise key is possible per AID, this means that the AID -		 * equals our hw_key_idx. Make sure the WCID starts _after_ the -		 * last possible shared key entry. -		 * -		 * Since parts of the pairwise key table might be shared with -		 * the beacon frame buffers 6 & 7 we should only write into the -		 * first 222 entries. +		 * Allow key configuration only for STAs that are +		 * known by the hw.  		 */ -		if (crypto->aid > (222 - 32)) +		if (crypto->wcid < 0)  			return -ENOSPC; - -		key->hw_key_idx = 32 + crypto->aid; +		key->hw_key_idx = crypto->wcid;  		memcpy(key_entry.key, crypto->key,  		       sizeof(key_entry.key)); @@ -1094,12 +1399,59 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,  	/*  	 * Update WCID information  	 */ -	rt2800_config_wcid_attr(rt2x00dev, crypto, key); +	rt2800_config_wcid_attr_cipher(rt2x00dev, crypto, key);  	return 0;  }  EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key); +int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif, +		   struct ieee80211_sta *sta) +{ +	int wcid; +	struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); + +	/* +	 * Find next free WCID. +	 */ +	wcid = rt2800_find_wcid(rt2x00dev); + +	/* +	 * Store selected wcid even if it is invalid so that we can +	 * later decide if the STA is uploaded into the hw. +	 */ +	sta_priv->wcid = wcid; + +	/* +	 * No space left in the device, however, we can still communicate +	 * with the STA -> No error. +	 */ +	if (wcid < 0) +		return 0; + +	/* +	 * Clean up WCID attributes and write STA address to the device. +	 */ +	rt2800_delete_wcid_attr(rt2x00dev, wcid); +	rt2800_config_wcid(rt2x00dev, sta->addr, wcid); +	rt2800_config_wcid_attr_bssidx(rt2x00dev, wcid, +				       rt2x00lib_get_bssidx(rt2x00dev, vif)); +	return 0; +} +EXPORT_SYMBOL_GPL(rt2800_sta_add); + +int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid) +{ +	/* +	 * Remove WCID entry, no need to clean the attributes as they will +	 * get renewed when the WCID is reused. +	 */ +	rt2800_config_wcid(rt2x00dev, NULL, wcid); + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2800_sta_remove); +  void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,  			  const unsigned int filter_flags)  { @@ -1136,8 +1488,9 @@ void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,  			   !(filter_flags & FIF_CONTROL));  	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL,  			   !(filter_flags & FIF_PSPOLL)); -	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); -	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); +	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 0); +	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, +			   !(filter_flags & FIF_CONTROL));  	rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL,  			   !(filter_flags & FIF_CONTROL));  	rt2800_register_write(rt2x00dev, RX_FILTER_CFG, reg); @@ -1152,29 +1505,30 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,  	if (flags & CONFIG_UPDATE_TYPE) {  		/* -		 * Clear current synchronisation setup. -		 */ -		rt2800_clear_beacon(rt2x00dev, -				    HW_BEACON_OFFSET(intf->beacon->entry_idx)); -		/*  		 * Enable synchronisation.  		 */  		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, ®); -		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1);  		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); -		rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, -				   (conf->sync == TSF_SYNC_ADHOC || -				    conf->sync == TSF_SYNC_AP_NONE));  		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); -		/* -		 * Enable pre tbtt interrupt for beaconing modes -		 */ -		rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); -		rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, -				   (conf->sync == TSF_SYNC_AP_NONE)); -		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); - +		if (conf->sync == TSF_SYNC_AP_NONE) { +			/* +			 * Tune beacon queue transmit parameters for AP mode +			 */ +			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 0); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 1); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 0); +			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); +		} else { +			rt2800_register_read(rt2x00dev, TBTT_SYNC_CFG, ®); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_CWMIN, 4); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_AIFSN, 2); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_BCN_EXP_WIN, 32); +			rt2x00_set_field32(®, TBTT_SYNC_CFG_TBTT_ADJUST, 16); +			rt2800_register_write(rt2x00dev, TBTT_SYNC_CFG, reg); +		}  	}  	if (flags & CONFIG_UPDATE_MAC) { @@ -1280,7 +1634,7 @@ static void rt2800_config_ht_opmode(struct rt2x00_dev *rt2x00dev,  			gf20_rate = gf40_rate = 0x0003;  		}  		break; -	}; +	}  	/* check for STAs not supporting greenfield mode */  	if (any_sta_nongf) @@ -1358,38 +1712,121 @@ void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp,  }  EXPORT_SYMBOL_GPL(rt2800_config_erp); +static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; +	u16 eeprom; +	u8 led_ctrl, led_g_mode, led_r_mode; + +	rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); +	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { +		rt2x00_set_field32(®, GPIO_SWITCH_0, 1); +		rt2x00_set_field32(®, GPIO_SWITCH_1, 1); +	} else { +		rt2x00_set_field32(®, GPIO_SWITCH_0, 0); +		rt2x00_set_field32(®, GPIO_SWITCH_1, 0); +	} +	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); + +	rt2800_register_read(rt2x00dev, LED_CFG, ®); +	led_g_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 3 : 0; +	led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3; +	if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) || +	    led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) { +		rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); +		led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE); +		if (led_ctrl == 0 || led_ctrl > 0x40) { +			rt2x00_set_field32(®, LED_CFG_G_LED_MODE, led_g_mode); +			rt2x00_set_field32(®, LED_CFG_R_LED_MODE, led_r_mode); +			rt2800_register_write(rt2x00dev, LED_CFG, reg); +		} else { +			rt2800_mcu_request(rt2x00dev, MCU_BAND_SELECT, 0xff, +					   (led_g_mode << 2) | led_r_mode, 1); +		} +	} +} + +static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev, +				     enum antenna ant) +{ +	u32 reg; +	u8 eesk_pin = (ant == ANTENNA_A) ? 1 : 0; +	u8 gpio_bit3 = (ant == ANTENNA_A) ? 0 : 1; + +	if (rt2x00_is_pci(rt2x00dev)) { +		rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); +		rt2x00_set_field32(®, E2PROM_CSR_DATA_CLOCK, eesk_pin); +		rt2800_register_write(rt2x00dev, E2PROM_CSR, reg); +	} else if (rt2x00_is_usb(rt2x00dev)) +		rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff, +				   eesk_pin, 0); + +	rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); +	rt2x00_set_field32(®, GPIO_CTRL_DIR3, 0); +	rt2x00_set_field32(®, GPIO_CTRL_VAL3, gpio_bit3); +	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); +} +  void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)  {  	u8 r1;  	u8 r3; +	u16 eeprom;  	rt2800_bbp_read(rt2x00dev, 1, &r1);  	rt2800_bbp_read(rt2x00dev, 3, &r3); +	if (rt2x00_rt(rt2x00dev, RT3572) && +	    rt2x00_has_cap_bt_coexist(rt2x00dev)) +		rt2800_config_3572bt_ant(rt2x00dev); +  	/*  	 * Configure the TX antenna.  	 */ -	switch ((int)ant->tx) { +	switch (ant->tx_chain_num) {  	case 1:  		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);  		break;  	case 2: -		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); +		if (rt2x00_rt(rt2x00dev, RT3572) && +		    rt2x00_has_cap_bt_coexist(rt2x00dev)) +			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 1); +		else +			rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);  		break;  	case 3: -		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); +		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);  		break;  	}  	/*  	 * Configure the RX antenna.  	 */ -	switch ((int)ant->rx) { +	switch (ant->rx_chain_num) {  	case 1: +		if (rt2x00_rt(rt2x00dev, RT3070) || +		    rt2x00_rt(rt2x00dev, RT3090) || +		    rt2x00_rt(rt2x00dev, RT3352) || +		    rt2x00_rt(rt2x00dev, RT3390)) { +			rt2800_eeprom_read(rt2x00dev, +					   EEPROM_NIC_CONF1, &eeprom); +			if (rt2x00_get_field16(eeprom, +						EEPROM_NIC_CONF1_ANT_DIVERSITY)) +				rt2800_set_ant_diversity(rt2x00dev, +						rt2x00dev->default_ant.rx); +		}  		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);  		break;  	case 2: -		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); +		if (rt2x00_rt(rt2x00dev, RT3572) && +		    rt2x00_has_cap_bt_coexist(rt2x00dev)) { +			rt2x00_set_field8(&r3, BBP3_RX_ADC, 1); +			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, +				rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); +			rt2800_set_ant_diversity(rt2x00dev, ANTENNA_B); +		} else { +			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); +		}  		break;  	case 3:  		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); @@ -1398,6 +1835,13 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)  	rt2800_bbp_write(rt2x00dev, 3, r3);  	rt2800_bbp_write(rt2x00dev, 1, r1); + +	if (rt2x00_rt(rt2x00dev, RT3593)) { +		if (ant->rx_chain_num == 1) +			rt2800_bbp_write(rt2x00dev, 86, 0x00); +		else +			rt2800_bbp_write(rt2x00dev, 86, 0x46); +	}  }  EXPORT_SYMBOL_GPL(rt2800_config_ant); @@ -1408,22 +1852,73 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,  	short lna_gain;  	if (libconf->rf.channel <= 14) { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);  		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);  	} else if (libconf->rf.channel <= 64) { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); +		rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);  		lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);  	} else if (libconf->rf.channel <= 128) { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); -		lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); +		if (rt2x00_rt(rt2x00dev, RT3593)) { +			rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); +			lna_gain = rt2x00_get_field16(eeprom, +						      EEPROM_EXT_LNA2_A1); +		} else { +			rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); +			lna_gain = rt2x00_get_field16(eeprom, +						      EEPROM_RSSI_BG2_LNA_A1); +		}  	} else { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); -		lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); +		if (rt2x00_rt(rt2x00dev, RT3593)) { +			rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); +			lna_gain = rt2x00_get_field16(eeprom, +						      EEPROM_EXT_LNA2_A2); +		} else { +			rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); +			lna_gain = rt2x00_get_field16(eeprom, +						      EEPROM_RSSI_A2_LNA_A2); +		}  	}  	rt2x00dev->lna_gain = lna_gain;  } +#define FREQ_OFFSET_BOUND	0x5f + +static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) +{ +	u8 freq_offset, prev_freq_offset; +	u8 rfcsr, prev_rfcsr; + +	freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE); +	freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND); + +	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); +	prev_rfcsr = rfcsr; + +	rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset); +	if (rfcsr == prev_rfcsr) +		return; + +	if (rt2x00_is_usb(rt2x00dev)) { +		rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff, +				   freq_offset, prev_rfcsr); +		return; +	} + +	prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE); +	while (prev_freq_offset != freq_offset) { +		if (prev_freq_offset < freq_offset) +			prev_freq_offset++; +		else +			prev_freq_offset--; + +		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset); +		rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); + +		usleep_range(1000, 1500); +	} +} +  static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,  					 struct ieee80211_conf *conf,  					 struct rf_channel *rf, @@ -1431,19 +1926,19 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,  {  	rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); -	if (rt2x00dev->default_ant.tx == 1) +	if (rt2x00dev->default_ant.tx_chain_num == 1)  		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); -	if (rt2x00dev->default_ant.rx == 1) { +	if (rt2x00dev->default_ant.rx_chain_num == 1) {  		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1);  		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); -	} else if (rt2x00dev->default_ant.rx == 2) +	} else if (rt2x00dev->default_ant.rx_chain_num == 2)  		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);  	if (rf->channel > 14) {  		/*  		 * When TX power is below 0, we should increase it by 7 to -		 * make it a positive value (Minumum value is -7). +		 * make it a positive value (Minimum value is -7).  		 * However this means that values between 0 and 7 have  		 * double meaning, and we should set a 7DBm boost flag.  		 */ @@ -1494,10 +1989,14 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,  					 struct rf_channel *rf,  					 struct channel_info *info)  { -	u8 rfcsr; +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 rfcsr, calib_tx, calib_rx;  	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); -	rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3); + +	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR3_K, rf->rf3); +	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);  	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);  	rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2); @@ -1511,65 +2010,1229 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2);  	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, +			  rt2x00dev->default_ant.rx_chain_num <= 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, +			  rt2x00dev->default_ant.rx_chain_num <= 2); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, +			  rt2x00dev->default_ant.tx_chain_num <= 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, +			  rt2x00dev->default_ant.tx_chain_num <= 2); +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); +  	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);  	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);  	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); -	rt2800_rfcsr_write(rt2x00dev, 24, -			      rt2x00dev->calibration[conf_is_ht40(conf)]); +	if (rt2x00_rt(rt2x00dev, RT3390)) { +		calib_tx = conf_is_ht40(conf) ? 0x68 : 0x4f; +		calib_rx = conf_is_ht40(conf) ? 0x6f : 0x4f; +	} else { +		if (conf_is_ht40(conf)) { +			calib_tx = drv_data->calibration_bw40; +			calib_rx = drv_data->calibration_bw40; +		} else { +			calib_tx = drv_data->calibration_bw20; +			calib_rx = drv_data->calibration_bw20; +		} +	} + +	rt2800_rfcsr_read(rt2x00dev, 24, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR24_TX_CALIB, calib_tx); +	rt2800_rfcsr_write(rt2x00dev, 24, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR31_RX_CALIB, calib_rx); +	rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);  	rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);  	rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);  	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); +	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); +	msleep(1); +	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); +	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);  } -static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, -				  struct ieee80211_conf *conf, -				  struct rf_channel *rf, -				  struct channel_info *info) +static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info)  { +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 rfcsr;  	u32 reg; -	unsigned int tx_pin; + +	if (rf->channel <= 14) { +		rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25); +		rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26); +	} else { +		rt2800_bbp_write(rt2x00dev, 25, 0x09); +		rt2800_bbp_write(rt2x00dev, 26, 0xff); +	} + +	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3); + +	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR6_R1, rf->rf2); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 2); +	else +		rt2x00_set_field8(&rfcsr, RFCSR6_TXDIV, 1); +	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 5, &rfcsr); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 1); +	else +		rt2x00_set_field8(&rfcsr, RFCSR5_R1, 2); +	rt2800_rfcsr_write(rt2x00dev, 5, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 3); +		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, +				  info->default_power1); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR12_DR0, 7); +		rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, +				(info->default_power1 & 0x3) | +				((info->default_power1 & 0xC) << 1)); +	} +	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 3); +		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, +				  info->default_power2); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR13_DR0, 7); +		rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, +				(info->default_power2 & 0x3) | +				((info->default_power2 & 0xC) << 1)); +	} +	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); +	if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { +		if (rf->channel <= 14) { +			rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); +			rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); +		} +		rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); +		rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); +	} else { +		switch (rt2x00dev->default_ant.tx_chain_num) { +		case 1: +			rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); +		case 2: +			rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); +			break; +		} + +		switch (rt2x00dev->default_ant.rx_chain_num) { +		case 1: +			rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); +		case 2: +			rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); +			break; +		} +	} +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); +	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); + +	if (conf_is_ht40(conf)) { +		rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw40); +		rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw40); +	} else { +		rt2800_rfcsr_write(rt2x00dev, 24, drv_data->calibration_bw20); +		rt2800_rfcsr_write(rt2x00dev, 31, drv_data->calibration_bw20); +	} + +	if (rf->channel <= 14) { +		rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); +		rt2800_rfcsr_write(rt2x00dev, 9, 0xc3); +		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); +		rt2800_rfcsr_write(rt2x00dev, 15, 0x53); +		rfcsr = 0x4c; +		rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN, +				  drv_data->txmixer_gain_24g); +		rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); +		rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +		rt2800_rfcsr_write(rt2x00dev, 19, 0x93); +		rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); +		rt2800_rfcsr_write(rt2x00dev, 25, 0x15); +		rt2800_rfcsr_write(rt2x00dev, 26, 0x85); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); +	} else { +		rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR7_BIT2, 1); +		rt2x00_set_field8(&rfcsr, RFCSR7_BIT3, 0); +		rt2x00_set_field8(&rfcsr, RFCSR7_BIT4, 1); +		rt2x00_set_field8(&rfcsr, RFCSR7_BITS67, 0); +		rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); +		rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); +		rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +		rt2800_rfcsr_write(rt2x00dev, 11, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 15, 0x43); +		rfcsr = 0x7a; +		rt2x00_set_field8(&rfcsr, RFCSR16_TXMIXER_GAIN, +				  drv_data->txmixer_gain_5g); +		rt2800_rfcsr_write(rt2x00dev, 16, rfcsr); +		rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +		if (rf->channel <= 64) { +			rt2800_rfcsr_write(rt2x00dev, 19, 0xb7); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf6); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); +		} else if (rf->channel <= 128) { +			rt2800_rfcsr_write(rt2x00dev, 19, 0x74); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf4); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x01); +		} else { +			rt2800_rfcsr_write(rt2x00dev, 19, 0x72); +			rt2800_rfcsr_write(rt2x00dev, 20, 0xf3); +			rt2800_rfcsr_write(rt2x00dev, 25, 0x01); +		} +		rt2800_rfcsr_write(rt2x00dev, 26, 0x87); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x01); +		rt2800_rfcsr_write(rt2x00dev, 29, 0x9f); +	} + +	rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); +	rt2x00_set_field32(®, GPIO_CTRL_DIR7, 0); +	if (rf->channel <= 14) +		rt2x00_set_field32(®, GPIO_CTRL_VAL7, 1); +	else +		rt2x00_set_field32(®, GPIO_CTRL_VAL7, 0); +	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + +	rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); +	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); +} + +static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 txrx_agc_fc; +	u8 txrx_h20m; +	u8 rfcsr;  	u8 bbp; +	const bool txbf_enabled = false; /* TODO */ + +	/* TODO: use TX{0,1,2}FinePowerControl values from EEPROM */ +	rt2800_bbp_read(rt2x00dev, 109, &bbp); +	rt2x00_set_field8(&bbp, BBP109_TX0_POWER, 0); +	rt2x00_set_field8(&bbp, BBP109_TX1_POWER, 0); +	rt2800_bbp_write(rt2x00dev, 109, bbp); + +	rt2800_bbp_read(rt2x00dev, 110, &bbp); +	rt2x00_set_field8(&bbp, BBP110_TX2_POWER, 0); +	rt2800_bbp_write(rt2x00dev, 110, bbp);  	if (rf->channel <= 14) { -		info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1); -		info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2); +		/* Restore BBP 25 & 26 for 2.4 GHz */ +		rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25); +		rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26);  	} else { -		info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1); -		info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2); +		/* Hard code BBP 25 & 26 for 5GHz */ + +		/* Enable IQ Phase correction */ +		rt2800_bbp_write(rt2x00dev, 25, 0x09); +		/* Setup IQ Phase correction value */ +		rt2800_bbp_write(rt2x00dev, 26, 0xff);  	} -	if (rt2x00_rf(rt2x00dev, RF2020) || -	    rt2x00_rf(rt2x00dev, RF3020) || -	    rt2x00_rf(rt2x00dev, RF3021) || -	    rt2x00_rf(rt2x00dev, RF3022) || -	    rt2x00_rf(rt2x00dev, RF3052) || -	    rt2x00_rf(rt2x00dev, RF3320)) -		rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); +	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3 & 0xf); + +	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR11_R, (rf->rf2 & 0x3)); +	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR11_PLL_IDOH, 1); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 1);  	else -		rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); +		rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 2); +	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); -	/* -	 * Change BBP settings +	rt2800_rfcsr_read(rt2x00dev, 53, &rfcsr); +	if (rf->channel <= 14) { +		rfcsr = 0; +		rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER, +				  info->default_power1 & 0x1f); +	} else { +		if (rt2x00_is_usb(rt2x00dev)) +			rfcsr = 0x40; + +		rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER, +				  ((info->default_power1 & 0x18) << 1) | +				  (info->default_power1 & 7)); +	} +	rt2800_rfcsr_write(rt2x00dev, 53, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 55, &rfcsr); +	if (rf->channel <= 14) { +		rfcsr = 0; +		rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER, +				  info->default_power2 & 0x1f); +	} else { +		if (rt2x00_is_usb(rt2x00dev)) +			rfcsr = 0x40; + +		rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER, +				  ((info->default_power2 & 0x18) << 1) | +				  (info->default_power2 & 7)); +	} +	rt2800_rfcsr_write(rt2x00dev, 55, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 54, &rfcsr); +	if (rf->channel <= 14) { +		rfcsr = 0; +		rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER, +				  info->default_power3 & 0x1f); +	} else { +		if (rt2x00_is_usb(rt2x00dev)) +			rfcsr = 0x40; + +		rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER, +				  ((info->default_power3 & 0x18) << 1) | +				  (info->default_power3 & 7)); +	} +	rt2800_rfcsr_write(rt2x00dev, 54, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); + +	switch (rt2x00dev->default_ant.tx_chain_num) { +	case 3: +		rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); +		/* fallthrough */ +	case 2: +		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); +		/* fallthrough */ +	case 1: +		rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); +		break; +	} + +	switch (rt2x00dev->default_ant.rx_chain_num) { +	case 3: +		rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); +		/* fallthrough */ +	case 2: +		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); +		/* fallthrough */ +	case 1: +		rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); +		break; +	} +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	if (conf_is_ht40(conf)) { +		txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40, +						RFCSR24_TX_AGC_FC); +		txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw40, +					      RFCSR24_TX_H20M); +	} else { +		txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw20, +						RFCSR24_TX_AGC_FC); +		txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw20, +					      RFCSR24_TX_H20M); +	} + +	/* NOTE: the reference driver does not writes the new value +	 * back to RFCSR 32  	 */ +	rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR32_TX_AGC_FC, txrx_agc_fc); + +	if (rf->channel <= 14) +		rfcsr = 0xa0; +	else +		rfcsr = 0x80; +	rt2800_rfcsr_write(rt2x00dev, 31, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, txrx_h20m); +	rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, txrx_h20m); +	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + +	/* Band selection */ +	rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1); +	else +		rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0); +	rt2800_rfcsr_write(rt2x00dev, 36, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 34, &rfcsr); +	if (rf->channel <= 14) +		rfcsr = 0x3c; +	else +		rfcsr = 0x20; +	rt2800_rfcsr_write(rt2x00dev, 34, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); +	if (rf->channel <= 14) +		rfcsr = 0x1a; +	else +		rfcsr = 0x12; +	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +	if (rf->channel >= 1 && rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1); +	else if (rf->channel >= 36 && rf->channel <= 64) +		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2); +	else if (rf->channel >= 100 && rf->channel <= 128) +		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2); +	else +		rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1); +	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2); +	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + +	rt2800_rfcsr_write(rt2x00dev, 46, 0x60); + +	if (rf->channel <= 14) { +		rt2800_rfcsr_write(rt2x00dev, 10, 0xd3); +		rt2800_rfcsr_write(rt2x00dev, 13, 0x12); +	} else { +		rt2800_rfcsr_write(rt2x00dev, 10, 0xd8); +		rt2800_rfcsr_write(rt2x00dev, 13, 0x23); +	} + +	rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR51_BITS01, 1); +	rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 5); +		rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 3); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 4); +		rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 2); +	} +	rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 3); +	else +		rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 2); + +	if (txbf_enabled) +		rt2x00_set_field8(&rfcsr, RFCSR49_TX_DIV, 1); + +	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO1_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr); +	if (rf->channel <= 14) +		rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x1b); +	else +		rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 57, rfcsr); + +	if (rf->channel <= 14) { +		rt2800_rfcsr_write(rt2x00dev, 44, 0x93); +		rt2800_rfcsr_write(rt2x00dev, 52, 0x45); +	} else { +		rt2800_rfcsr_write(rt2x00dev, 44, 0x9b); +		rt2800_rfcsr_write(rt2x00dev, 52, 0x05); +	} + +	/* Initiate VCO calibration */ +	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); +	if (rf->channel <= 14) { +		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); +	} else { +		rt2x00_set_field8(&rfcsr, RFCSR3_BIT1, 1); +		rt2x00_set_field8(&rfcsr, RFCSR3_BIT2, 1); +		rt2x00_set_field8(&rfcsr, RFCSR3_BIT3, 1); +		rt2x00_set_field8(&rfcsr, RFCSR3_BIT4, 1); +		rt2x00_set_field8(&rfcsr, RFCSR3_BIT5, 1); +		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); +	} +	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); + +	if (rf->channel >= 1 && rf->channel <= 14) { +		rfcsr = 0x23; +		if (txbf_enabled) +			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); +		rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + +		rt2800_rfcsr_write(rt2x00dev, 45, 0xbb); +	} else if (rf->channel >= 36 && rf->channel <= 64) { +		rfcsr = 0x36; +		if (txbf_enabled) +			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); +		rt2800_rfcsr_write(rt2x00dev, 39, 0x36); + +		rt2800_rfcsr_write(rt2x00dev, 45, 0xeb); +	} else if (rf->channel >= 100 && rf->channel <= 128) { +		rfcsr = 0x32; +		if (txbf_enabled) +			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); +		rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + +		rt2800_rfcsr_write(rt2x00dev, 45, 0xb3); +	} else { +		rfcsr = 0x30; +		if (txbf_enabled) +			rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); +		rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + +		rt2800_rfcsr_write(rt2x00dev, 45, 0x9b); +	} +} + +#define POWER_BOUND		0x27 +#define POWER_BOUND_5G		0x2b + +static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	u8 rfcsr; + +	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); +	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2); +	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); +	if (info->default_power1 > POWER_BOUND) +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND); +	else +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); +	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	if (rf->channel <= 14) { +		if (rf->channel == 6) +			rt2800_bbp_write(rt2x00dev, 68, 0x0c); +		else +			rt2800_bbp_write(rt2x00dev, 68, 0x0b); + +		if (rf->channel >= 1 && rf->channel <= 6) +			rt2800_bbp_write(rt2x00dev, 59, 0x0f); +		else if (rf->channel >= 7 && rf->channel <= 11) +			rt2800_bbp_write(rt2x00dev, 59, 0x0e); +		else if (rf->channel >= 12 && rf->channel <= 14) +			rt2800_bbp_write(rt2x00dev, 59, 0x0d); +	} +} + +static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	u8 rfcsr; + +	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); + +	rt2800_rfcsr_write(rt2x00dev, 11, 0x42); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x1c); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x00); + +	if (info->default_power1 > POWER_BOUND) +		rt2800_rfcsr_write(rt2x00dev, 47, POWER_BOUND); +	else +		rt2800_rfcsr_write(rt2x00dev, 47, info->default_power1); + +	if (info->default_power2 > POWER_BOUND) +		rt2800_rfcsr_write(rt2x00dev, 48, POWER_BOUND); +	else +		rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); + +	if ( rt2x00dev->default_ant.tx_chain_num == 2 ) +		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); +	else +		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); + +	if ( rt2x00dev->default_ant.rx_chain_num == 2 ) +		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); +	else +		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); + +	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); + +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_rfcsr_write(rt2x00dev, 31, 80); +} + +static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	u8 rfcsr; + +	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); +	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3); +	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2); +	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); +	if (info->default_power1 > POWER_BOUND) +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, POWER_BOUND); +	else +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); +	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); + +	if (rt2x00_rt(rt2x00dev, RT5392)) { +		rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); +		if (info->default_power2 > POWER_BOUND) +			rt2x00_set_field8(&rfcsr, RFCSR50_TX, POWER_BOUND); +		else +			rt2x00_set_field8(&rfcsr, RFCSR50_TX, +					  info->default_power2); +		rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); +	} + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	if (rt2x00_rt(rt2x00dev, RT5392)) { +		rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); +		rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); +	} +	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	if (rf->channel <= 14) { +		int idx = rf->channel-1; + +		if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { +			if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { +				/* r55/r59 value array of channel 1~14 */ +				static const char r55_bt_rev[] = {0x83, 0x83, +					0x83, 0x73, 0x73, 0x63, 0x53, 0x53, +					0x53, 0x43, 0x43, 0x43, 0x43, 0x43}; +				static const char r59_bt_rev[] = {0x0e, 0x0e, +					0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09, +					0x07, 0x07, 0x07, 0x07, 0x07, 0x07}; + +				rt2800_rfcsr_write(rt2x00dev, 55, +						   r55_bt_rev[idx]); +				rt2800_rfcsr_write(rt2x00dev, 59, +						   r59_bt_rev[idx]); +			} else { +				static const char r59_bt[] = {0x8b, 0x8b, 0x8b, +					0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89, +					0x88, 0x88, 0x86, 0x85, 0x84}; + +				rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]); +			} +		} else { +			if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { +				static const char r55_nonbt_rev[] = {0x23, 0x23, +					0x23, 0x23, 0x13, 0x13, 0x03, 0x03, +					0x03, 0x03, 0x03, 0x03, 0x03, 0x03}; +				static const char r59_nonbt_rev[] = {0x07, 0x07, +					0x07, 0x07, 0x07, 0x07, 0x07, 0x07, +					0x07, 0x07, 0x06, 0x05, 0x04, 0x04}; + +				rt2800_rfcsr_write(rt2x00dev, 55, +						   r55_nonbt_rev[idx]); +				rt2800_rfcsr_write(rt2x00dev, 59, +						   r59_nonbt_rev[idx]); +			} else if (rt2x00_rt(rt2x00dev, RT5390) || +				   rt2x00_rt(rt2x00dev, RT5392)) { +				static const char r59_non_bt[] = {0x8f, 0x8f, +					0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d, +					0x8a, 0x88, 0x88, 0x87, 0x87, 0x86}; + +				rt2800_rfcsr_write(rt2x00dev, 59, +						   r59_non_bt[idx]); +			} +		} +	} +} + +static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_conf *conf, +					 struct rf_channel *rf, +					 struct channel_info *info) +{ +	u8 rfcsr, ep_reg; +	u32 reg; +	int power_bound; + +	/* TODO */ +	const bool is_11b = false; +	const bool is_type_ep = false; + +	rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, +			   (rf->channel > 14 || conf_is_ht40(conf)) ? 5 : 0); +	rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + +	/* Order of values on rf_channel entry: N, K, mod, R */ +	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1 & 0xff); + +	rt2800_rfcsr_read(rt2x00dev,  9, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR9_K, rf->rf2 & 0xf); +	rt2x00_set_field8(&rfcsr, RFCSR9_N, (rf->rf1 & 0x100) >> 8); +	rt2x00_set_field8(&rfcsr, RFCSR9_MOD, ((rf->rf3 - 8) & 0x4) >> 2); +	rt2800_rfcsr_write(rt2x00dev, 9, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf4 - 1); +	rt2x00_set_field8(&rfcsr, RFCSR11_MOD, (rf->rf3 - 8) & 0x3); +	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); + +	if (rf->channel <= 14) { +		rt2800_rfcsr_write(rt2x00dev, 10, 0x90); +		/* FIXME: RF11 owerwrite ? */ +		rt2800_rfcsr_write(rt2x00dev, 11, 0x4A); +		rt2800_rfcsr_write(rt2x00dev, 12, 0x52); +		rt2800_rfcsr_write(rt2x00dev, 13, 0x42); +		rt2800_rfcsr_write(rt2x00dev, 22, 0x40); +		rt2800_rfcsr_write(rt2x00dev, 24, 0x4A); +		rt2800_rfcsr_write(rt2x00dev, 25, 0x80); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x42); +		rt2800_rfcsr_write(rt2x00dev, 36, 0x80); +		rt2800_rfcsr_write(rt2x00dev, 37, 0x08); +		rt2800_rfcsr_write(rt2x00dev, 38, 0x89); +		rt2800_rfcsr_write(rt2x00dev, 39, 0x1B); +		rt2800_rfcsr_write(rt2x00dev, 40, 0x0D); +		rt2800_rfcsr_write(rt2x00dev, 41, 0x9B); +		rt2800_rfcsr_write(rt2x00dev, 42, 0xD5); +		rt2800_rfcsr_write(rt2x00dev, 43, 0x72); +		rt2800_rfcsr_write(rt2x00dev, 44, 0x0E); +		rt2800_rfcsr_write(rt2x00dev, 45, 0xA2); +		rt2800_rfcsr_write(rt2x00dev, 46, 0x6B); +		rt2800_rfcsr_write(rt2x00dev, 48, 0x10); +		rt2800_rfcsr_write(rt2x00dev, 51, 0x3E); +		rt2800_rfcsr_write(rt2x00dev, 52, 0x48); +		rt2800_rfcsr_write(rt2x00dev, 54, 0x38); +		rt2800_rfcsr_write(rt2x00dev, 56, 0xA1); +		rt2800_rfcsr_write(rt2x00dev, 57, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 58, 0x39); +		rt2800_rfcsr_write(rt2x00dev, 60, 0x45); +		rt2800_rfcsr_write(rt2x00dev, 61, 0x91); +		rt2800_rfcsr_write(rt2x00dev, 62, 0x39); + +		/* TODO RF27 <- tssi */ + +		rfcsr = rf->channel <= 10 ? 0x07 : 0x06; +		rt2800_rfcsr_write(rt2x00dev, 23, rfcsr); +		rt2800_rfcsr_write(rt2x00dev, 59, rfcsr); + +		if (is_11b) { +			/* CCK */ +			rt2800_rfcsr_write(rt2x00dev, 31, 0xF8); +			rt2800_rfcsr_write(rt2x00dev, 32, 0xC0); +			if (is_type_ep) +				rt2800_rfcsr_write(rt2x00dev, 55, 0x06); +			else +				rt2800_rfcsr_write(rt2x00dev, 55, 0x47); +		} else { +			/* OFDM */ +			if (is_type_ep) +				rt2800_rfcsr_write(rt2x00dev, 55, 0x03); +			else +				rt2800_rfcsr_write(rt2x00dev, 55, 0x43); +		} + +		power_bound = POWER_BOUND; +		ep_reg = 0x2; +	} else { +		rt2800_rfcsr_write(rt2x00dev, 10, 0x97); +		/* FIMXE: RF11 overwrite */ +		rt2800_rfcsr_write(rt2x00dev, 11, 0x40); +		rt2800_rfcsr_write(rt2x00dev, 25, 0xBF); +		rt2800_rfcsr_write(rt2x00dev, 27, 0x42); +		rt2800_rfcsr_write(rt2x00dev, 36, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 37, 0x04); +		rt2800_rfcsr_write(rt2x00dev, 38, 0x85); +		rt2800_rfcsr_write(rt2x00dev, 40, 0x42); +		rt2800_rfcsr_write(rt2x00dev, 41, 0xBB); +		rt2800_rfcsr_write(rt2x00dev, 42, 0xD7); +		rt2800_rfcsr_write(rt2x00dev, 45, 0x41); +		rt2800_rfcsr_write(rt2x00dev, 48, 0x00); +		rt2800_rfcsr_write(rt2x00dev, 57, 0x77); +		rt2800_rfcsr_write(rt2x00dev, 60, 0x05); +		rt2800_rfcsr_write(rt2x00dev, 61, 0x01); + +		/* TODO RF27 <- tssi */ + +		if (rf->channel >= 36 && rf->channel <= 64) { + +			rt2800_rfcsr_write(rt2x00dev, 12, 0x2E); +			rt2800_rfcsr_write(rt2x00dev, 13, 0x22); +			rt2800_rfcsr_write(rt2x00dev, 22, 0x60); +			rt2800_rfcsr_write(rt2x00dev, 23, 0x7F); +			if (rf->channel <= 50) +				rt2800_rfcsr_write(rt2x00dev, 24, 0x09); +			else if (rf->channel >= 52) +				rt2800_rfcsr_write(rt2x00dev, 24, 0x07); +			rt2800_rfcsr_write(rt2x00dev, 39, 0x1C); +			rt2800_rfcsr_write(rt2x00dev, 43, 0x5B); +			rt2800_rfcsr_write(rt2x00dev, 44, 0X40); +			rt2800_rfcsr_write(rt2x00dev, 46, 0X00); +			rt2800_rfcsr_write(rt2x00dev, 51, 0xFE); +			rt2800_rfcsr_write(rt2x00dev, 52, 0x0C); +			rt2800_rfcsr_write(rt2x00dev, 54, 0xF8); +			if (rf->channel <= 50) { +				rt2800_rfcsr_write(rt2x00dev, 55, 0x06), +				rt2800_rfcsr_write(rt2x00dev, 56, 0xD3); +			} else if (rf->channel >= 52) { +				rt2800_rfcsr_write(rt2x00dev, 55, 0x04); +				rt2800_rfcsr_write(rt2x00dev, 56, 0xBB); +			} + +			rt2800_rfcsr_write(rt2x00dev, 58, 0x15); +			rt2800_rfcsr_write(rt2x00dev, 59, 0x7F); +			rt2800_rfcsr_write(rt2x00dev, 62, 0x15); + +		} else if (rf->channel >= 100 && rf->channel <= 165) { + +			rt2800_rfcsr_write(rt2x00dev, 12, 0x0E); +			rt2800_rfcsr_write(rt2x00dev, 13, 0x42); +			rt2800_rfcsr_write(rt2x00dev, 22, 0x40); +			if (rf->channel <= 153) { +				rt2800_rfcsr_write(rt2x00dev, 23, 0x3C); +				rt2800_rfcsr_write(rt2x00dev, 24, 0x06); +			} else if (rf->channel >= 155) { +				rt2800_rfcsr_write(rt2x00dev, 23, 0x38); +				rt2800_rfcsr_write(rt2x00dev, 24, 0x05); +			} +			if (rf->channel <= 138) { +				rt2800_rfcsr_write(rt2x00dev, 39, 0x1A); +				rt2800_rfcsr_write(rt2x00dev, 43, 0x3B); +				rt2800_rfcsr_write(rt2x00dev, 44, 0x20); +				rt2800_rfcsr_write(rt2x00dev, 46, 0x18); +			} else if (rf->channel >= 140) { +				rt2800_rfcsr_write(rt2x00dev, 39, 0x18); +				rt2800_rfcsr_write(rt2x00dev, 43, 0x1B); +				rt2800_rfcsr_write(rt2x00dev, 44, 0x10); +				rt2800_rfcsr_write(rt2x00dev, 46, 0X08); +			} +			if (rf->channel <= 124) +				rt2800_rfcsr_write(rt2x00dev, 51, 0xFC); +			else if (rf->channel >= 126) +				rt2800_rfcsr_write(rt2x00dev, 51, 0xEC); +			if (rf->channel <= 138) +				rt2800_rfcsr_write(rt2x00dev, 52, 0x06); +			else if (rf->channel >= 140) +				rt2800_rfcsr_write(rt2x00dev, 52, 0x06); +			rt2800_rfcsr_write(rt2x00dev, 54, 0xEB); +			if (rf->channel <= 138) +				rt2800_rfcsr_write(rt2x00dev, 55, 0x01); +			else if (rf->channel >= 140) +				rt2800_rfcsr_write(rt2x00dev, 55, 0x00); +			if (rf->channel <= 128) +				rt2800_rfcsr_write(rt2x00dev, 56, 0xBB); +			else if (rf->channel >= 130) +				rt2800_rfcsr_write(rt2x00dev, 56, 0xAB); +			if (rf->channel <= 116) +				rt2800_rfcsr_write(rt2x00dev, 58, 0x1D); +			else if (rf->channel >= 118) +				rt2800_rfcsr_write(rt2x00dev, 58, 0x15); +			if (rf->channel <= 138) +				rt2800_rfcsr_write(rt2x00dev, 59, 0x3F); +			else if (rf->channel >= 140) +				rt2800_rfcsr_write(rt2x00dev, 59, 0x7C); +			if (rf->channel <= 116) +				rt2800_rfcsr_write(rt2x00dev, 62, 0x1D); +			else if (rf->channel >= 118) +				rt2800_rfcsr_write(rt2x00dev, 62, 0x15); +		} + +		power_bound = POWER_BOUND_5G; +		ep_reg = 0x3; +	} + +	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); +	if (info->default_power1 > power_bound) +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, power_bound); +	else +		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); +	if (is_type_ep) +		rt2x00_set_field8(&rfcsr, RFCSR49_EP, ep_reg); +	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); +	if (info->default_power2 > power_bound) +		rt2x00_set_field8(&rfcsr, RFCSR50_TX, power_bound); +	else +		rt2x00_set_field8(&rfcsr, RFCSR50_TX, info->default_power2); +	if (is_type_ep) +		rt2x00_set_field8(&rfcsr, RFCSR50_EP, ep_reg); +	rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); + +	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, +			  rt2x00dev->default_ant.tx_chain_num >= 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, +			  rt2x00dev->default_ant.tx_chain_num == 2); +	rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); + +	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, +			  rt2x00dev->default_ant.rx_chain_num >= 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, +			  rt2x00dev->default_ant.rx_chain_num == 2); +	rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); + +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); +	rt2800_rfcsr_write(rt2x00dev, 6, 0xe4); + +	if (conf_is_ht40(conf)) +		rt2800_rfcsr_write(rt2x00dev, 30, 0x16); +	else +		rt2800_rfcsr_write(rt2x00dev, 30, 0x10); + +	if (!is_11b) { +		rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +		rt2800_rfcsr_write(rt2x00dev, 32, 0x80); +	} + +	/* TODO proper frequency adjustment */ +	rt2800_adjust_freq_offset(rt2x00dev); + +	/* TODO merge with others */ +	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); +	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); + +	/* BBP settings */  	rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);  	rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);  	rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); -	rt2800_bbp_write(rt2x00dev, 86, 0); -	if (rf->channel <= 14) { -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { -			rt2800_bbp_write(rt2x00dev, 82, 0x62); -			rt2800_bbp_write(rt2x00dev, 75, 0x46); +	rt2800_bbp_write(rt2x00dev, 79, (rf->channel <= 14) ? 0x1C : 0x18); +	rt2800_bbp_write(rt2x00dev, 80, (rf->channel <= 14) ? 0x0E : 0x08); +	rt2800_bbp_write(rt2x00dev, 81, (rf->channel <= 14) ? 0x3A : 0x38); +	rt2800_bbp_write(rt2x00dev, 82, (rf->channel <= 14) ? 0x62 : 0x92); + +	/* GLRT band configuration */ +	rt2800_bbp_write(rt2x00dev, 195, 128); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0xE0 : 0xF0); +	rt2800_bbp_write(rt2x00dev, 195, 129); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x1F : 0x1E); +	rt2800_bbp_write(rt2x00dev, 195, 130); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x38 : 0x28); +	rt2800_bbp_write(rt2x00dev, 195, 131); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x32 : 0x20); +	rt2800_bbp_write(rt2x00dev, 195, 133); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x28 : 0x7F); +	rt2800_bbp_write(rt2x00dev, 195, 124); +	rt2800_bbp_write(rt2x00dev, 196, (rf->channel <= 14) ? 0x19 : 0x7F); +} + +static void rt2800_bbp_write_with_rx_chain(struct rt2x00_dev *rt2x00dev, +					   const unsigned int word, +					   const u8 value) +{ +	u8 chain, reg; + +	for (chain = 0; chain < rt2x00dev->default_ant.rx_chain_num; chain++) { +		rt2800_bbp_read(rt2x00dev, 27, ®); +		rt2x00_set_field8(®,  BBP27_RX_CHAIN_SEL, chain); +		rt2800_bbp_write(rt2x00dev, 27, reg); + +		rt2800_bbp_write(rt2x00dev, word, value); +	} +} + +static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel) +{ +	u8 cal; + +	/* TX0 IQ Gain */ +	rt2800_bbp_write(rt2x00dev, 158, 0x2c); +	if (channel <= 14) +		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX0_2G); +	else if (channel >= 36 && channel <= 64) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX0_CH36_TO_CH64_5G); +	else if (channel >= 100 && channel <= 138) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX0_CH100_TO_CH138_5G); +	else if (channel >= 140 && channel <= 165) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX0_CH140_TO_CH165_5G); +	else +		cal = 0; +	rt2800_bbp_write(rt2x00dev, 159, cal); + +	/* TX0 IQ Phase */ +	rt2800_bbp_write(rt2x00dev, 158, 0x2d); +	if (channel <= 14) +		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX0_2G); +	else if (channel >= 36 && channel <= 64) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX0_CH36_TO_CH64_5G); +	else if (channel >= 100 && channel <= 138) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX0_CH100_TO_CH138_5G); +	else if (channel >= 140 && channel <= 165) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX0_CH140_TO_CH165_5G); +	else +		cal = 0; +	rt2800_bbp_write(rt2x00dev, 159, cal); + +	/* TX1 IQ Gain */ +	rt2800_bbp_write(rt2x00dev, 158, 0x4a); +	if (channel <= 14) +		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_GAIN_CAL_TX1_2G); +	else if (channel >= 36 && channel <= 64) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX1_CH36_TO_CH64_5G); +	else if (channel >= 100 && channel <= 138) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX1_CH100_TO_CH138_5G); +	else if (channel >= 140 && channel <= 165) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_GAIN_CAL_TX1_CH140_TO_CH165_5G); +	else +		cal = 0; +	rt2800_bbp_write(rt2x00dev, 159, cal); + +	/* TX1 IQ Phase */ +	rt2800_bbp_write(rt2x00dev, 158, 0x4b); +	if (channel <= 14) +		cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_IQ_PHASE_CAL_TX1_2G); +	else if (channel >= 36 && channel <= 64) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX1_CH36_TO_CH64_5G); +	else if (channel >= 100 && channel <= 138) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX1_CH100_TO_CH138_5G); +	else if (channel >= 140 && channel <= 165) +		cal = rt2x00_eeprom_byte(rt2x00dev, +					 EEPROM_IQ_PHASE_CAL_TX1_CH140_TO_CH165_5G); +	else +		cal = 0; +	rt2800_bbp_write(rt2x00dev, 159, cal); + +	/* FIXME: possible RX0, RX1 callibration ? */ + +	/* RF IQ compensation control */ +	rt2800_bbp_write(rt2x00dev, 158, 0x04); +	cal = rt2x00_eeprom_byte(rt2x00dev, EEPROM_RF_IQ_COMPENSATION_CONTROL); +	rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0); + +	/* RF IQ imbalance compensation control */ +	rt2800_bbp_write(rt2x00dev, 158, 0x03); +	cal = rt2x00_eeprom_byte(rt2x00dev, +				 EEPROM_RF_IQ_IMBALANCE_COMPENSATION_CONTROL); +	rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0); +} + +static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev, +				  unsigned int channel, +				  char txpower) +{ +	if (rt2x00_rt(rt2x00dev, RT3593)) +		txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC); + +	if (channel <= 14) +		return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER); + +	if (rt2x00_rt(rt2x00dev, RT3593)) +		return clamp_t(char, txpower, MIN_A_TXPOWER_3593, +			       MAX_A_TXPOWER_3593); +	else +		return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER); +} + +static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, +				  struct ieee80211_conf *conf, +				  struct rf_channel *rf, +				  struct channel_info *info) +{ +	u32 reg; +	unsigned int tx_pin; +	u8 bbp, rfcsr; + +	info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel, +						     info->default_power1); +	info->default_power2 = rt2800_txpower_to_dev(rt2x00dev, rf->channel, +						     info->default_power2); +	if (rt2x00dev->default_ant.tx_chain_num > 2) +		info->default_power3 = +			rt2800_txpower_to_dev(rt2x00dev, rf->channel, +					      info->default_power3); + +	switch (rt2x00dev->chip.rf) { +	case RF2020: +	case RF3020: +	case RF3021: +	case RF3022: +	case RF3320: +		rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); +		break; +	case RF3052: +		rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info); +		break; +	case RF3053: +		rt2800_config_channel_rf3053(rt2x00dev, conf, rf, info); +		break; +	case RF3290: +		rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info); +		break; +	case RF3322: +		rt2800_config_channel_rf3322(rt2x00dev, conf, rf, info); +		break; +	case RF3070: +	case RF5360: +	case RF5370: +	case RF5372: +	case RF5390: +	case RF5392: +		rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); +		break; +	case RF5592: +		rt2800_config_channel_rf55xx(rt2x00dev, conf, rf, info); +		break; +	default: +		rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); +	} + +	if (rt2x00_rf(rt2x00dev, RF3070) || +	    rt2x00_rf(rt2x00dev, RF3290) || +	    rt2x00_rf(rt2x00dev, RF3322) || +	    rt2x00_rf(rt2x00dev, RF5360) || +	    rt2x00_rf(rt2x00dev, RF5370) || +	    rt2x00_rf(rt2x00dev, RF5372) || +	    rt2x00_rf(rt2x00dev, RF5390) || +	    rt2x00_rf(rt2x00dev, RF5392)) { +		rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0); +		rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0); +		rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + +		rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); +		rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); +	} + +	/* +	 * Change BBP settings +	 */ +	if (rt2x00_rt(rt2x00dev, RT3352)) { +		rt2800_bbp_write(rt2x00dev, 27, 0x0); +		rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 27, 0x20); +		rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); +	} else if (rt2x00_rt(rt2x00dev, RT3593)) { +		if (rf->channel > 14) { +			/* Disable CCK Packet detection on 5GHz */ +			rt2800_bbp_write(rt2x00dev, 70, 0x00);  		} else { -			rt2800_bbp_write(rt2x00dev, 82, 0x84); -			rt2800_bbp_write(rt2x00dev, 75, 0x50); +			rt2800_bbp_write(rt2x00dev, 70, 0x0a); +		} + +		if (conf_is_ht40(conf)) +			rt2800_bbp_write(rt2x00dev, 105, 0x04); +		else +			rt2800_bbp_write(rt2x00dev, 105, 0x34); + +		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 77, 0x98); +	} else { +		rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); +		rt2800_bbp_write(rt2x00dev, 86, 0); +	} + +	if (rf->channel <= 14) { +		if (!rt2x00_rt(rt2x00dev, RT5390) && +		    !rt2x00_rt(rt2x00dev, RT5392)) { +			if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) { +				rt2800_bbp_write(rt2x00dev, 82, 0x62); +				rt2800_bbp_write(rt2x00dev, 75, 0x46); +			} else { +				if (rt2x00_rt(rt2x00dev, RT3593)) +					rt2800_bbp_write(rt2x00dev, 82, 0x62); +				else +					rt2800_bbp_write(rt2x00dev, 82, 0x84); +				rt2800_bbp_write(rt2x00dev, 75, 0x50); +			} +			if (rt2x00_rt(rt2x00dev, RT3593)) +				rt2800_bbp_write(rt2x00dev, 83, 0x8a);  		} +  	} else { -		rt2800_bbp_write(rt2x00dev, 82, 0xf2); +		if (rt2x00_rt(rt2x00dev, RT3572)) +			rt2800_bbp_write(rt2x00dev, 82, 0x94); +		else if (rt2x00_rt(rt2x00dev, RT3593)) +			rt2800_bbp_write(rt2x00dev, 82, 0x82); +		else +			rt2800_bbp_write(rt2x00dev, 82, 0xf2); + +		if (rt2x00_rt(rt2x00dev, RT3593)) +			rt2800_bbp_write(rt2x00dev, 83, 0x9a); -		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) +		if (rt2x00_has_cap_external_lna_a(rt2x00dev))  			rt2800_bbp_write(rt2x00dev, 75, 0x46);  		else  			rt2800_bbp_write(rt2x00dev, 75, 0x50); @@ -1581,29 +3244,127 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14);  	rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg); +	if (rt2x00_rt(rt2x00dev, RT3572)) +		rt2800_rfcsr_write(rt2x00dev, 8, 0); +  	tx_pin = 0; -	/* Turn on unused PA or LNA when not using 1T or 1R */ -	if (rt2x00dev->default_ant.tx != 1) { -		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); -		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); +	switch (rt2x00dev->default_ant.tx_chain_num) { +	case 3: +		/* Turn on tertiary PAs */ +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN, +				   rf->channel > 14); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN, +				   rf->channel <= 14); +		/* fall-through */ +	case 2: +		/* Turn on secondary PAs */ +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, +				   rf->channel > 14); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, +				   rf->channel <= 14); +		/* fall-through */ +	case 1: +		/* Turn on primary PAs */ +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, +				   rf->channel > 14); +		if (rt2x00_has_cap_bt_coexist(rt2x00dev)) +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); +		else +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, +					   rf->channel <= 14); +		break;  	} -	/* Turn on unused PA or LNA when not using 1T or 1R */ -	if (rt2x00dev->default_ant.rx != 1) { +	switch (rt2x00dev->default_ant.rx_chain_num) { +	case 3: +		/* Turn on tertiary LNAs */ +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A2_EN, 1); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G2_EN, 1); +		/* fall-through */ +	case 2: +		/* Turn on secondary LNAs */  		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);  		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); +		/* fall-through */ +	case 1: +		/* Turn on primary LNAs */ +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); +		rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); +		break;  	} -	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); -	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);  	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); -	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); -	rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);  	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); +	if (rt2x00_rt(rt2x00dev, RT3572)) { +		rt2800_rfcsr_write(rt2x00dev, 8, 0x80); + +		/* AGC init */ +		if (rf->channel <= 14) +			reg = 0x1c + (2 * rt2x00dev->lna_gain); +		else +			reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3); + +		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); +	} + +	if (rt2x00_rt(rt2x00dev, RT3593)) { +		rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); + +		/* Band selection */ +		if (rt2x00_is_usb(rt2x00dev) || +		    rt2x00_is_pcie(rt2x00dev)) { +			/* GPIO #8 controls all paths */ +			rt2x00_set_field32(®, GPIO_CTRL_DIR8, 0); +			if (rf->channel <= 14) +				rt2x00_set_field32(®, GPIO_CTRL_VAL8, 1); +			else +				rt2x00_set_field32(®, GPIO_CTRL_VAL8, 0); +		} + +		/* LNA PE control. */ +		if (rt2x00_is_usb(rt2x00dev)) { +			/* GPIO #4 controls PE0 and PE1, +			 * GPIO #7 controls PE2 +			 */ +			rt2x00_set_field32(®, GPIO_CTRL_DIR4, 0); +			rt2x00_set_field32(®, GPIO_CTRL_DIR7, 0); + +			rt2x00_set_field32(®, GPIO_CTRL_VAL4, 1); +			rt2x00_set_field32(®, GPIO_CTRL_VAL7, 1); +		} else if (rt2x00_is_pcie(rt2x00dev)) { +			/* GPIO #4 controls PE0, PE1 and PE2 */ +			rt2x00_set_field32(®, GPIO_CTRL_DIR4, 0); +			rt2x00_set_field32(®, GPIO_CTRL_VAL4, 1); +		} + +		rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + +		/* AGC init */ +		if (rf->channel <= 14) +			reg = 0x1c + 2 * rt2x00dev->lna_gain; +		else +			reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3); + +		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); + +		usleep_range(1000, 1500); +	} + +	if (rt2x00_rt(rt2x00dev, RT5592)) { +		rt2800_bbp_write(rt2x00dev, 195, 141); +		rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a); + +		/* AGC init */ +		reg = (rf->channel <= 14 ? 0x1c : 0x24) + 2 * rt2x00dev->lna_gain; +		rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); + +		rt2800_iq_calibrate(rt2x00dev, rf->channel); +	} +  	rt2800_bbp_read(rt2x00dev, 4, &bbp);  	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));  	rt2800_bbp_write(rt2x00dev, 4, bbp); @@ -1625,32 +3386,729 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,  	}  	msleep(1); + +	/* +	 * Clear channel statistic counters +	 */ +	rt2800_register_read(rt2x00dev, CH_IDLE_STA, ®); +	rt2800_register_read(rt2x00dev, CH_BUSY_STA, ®); +	rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, ®); + +	/* +	 * Clear update flag +	 */ +	if (rt2x00_rt(rt2x00dev, RT3352)) { +		rt2800_bbp_read(rt2x00dev, 49, &bbp); +		rt2x00_set_field8(&bbp, BBP49_UPDATE_FLAG, 0); +		rt2800_bbp_write(rt2x00dev, 49, bbp); +	}  } -static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, -				  const int max_txpower) +static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) +{ +	u8 tssi_bounds[9]; +	u8 current_tssi; +	u16 eeprom; +	u8 step; +	int i; + +	/* +	 * First check if temperature compensation is supported. +	 */ +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); +	if (!rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC)) +		return 0; + +	/* +	 * Read TSSI boundaries for temperature compensation from +	 * the EEPROM. +	 * +	 * Array idx               0    1    2    3    4    5    6    7    8 +	 * Matching Delta value   -4   -3   -2   -1    0   +1   +2   +3   +4 +	 * Example TSSI bounds  0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00 +	 */ +	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom); +		tssi_bounds[0] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG1_MINUS4); +		tssi_bounds[1] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG1_MINUS3); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom); +		tssi_bounds[2] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG2_MINUS2); +		tssi_bounds[3] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG2_MINUS1); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom); +		tssi_bounds[4] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG3_REF); +		tssi_bounds[5] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG3_PLUS1); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom); +		tssi_bounds[6] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG4_PLUS2); +		tssi_bounds[7] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG4_PLUS3); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom); +		tssi_bounds[8] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_BG5_PLUS4); + +		step = rt2x00_get_field16(eeprom, +					  EEPROM_TSSI_BOUND_BG5_AGC_STEP); +	} else { +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom); +		tssi_bounds[0] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A1_MINUS4); +		tssi_bounds[1] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A1_MINUS3); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom); +		tssi_bounds[2] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A2_MINUS2); +		tssi_bounds[3] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A2_MINUS1); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom); +		tssi_bounds[4] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A3_REF); +		tssi_bounds[5] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A3_PLUS1); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom); +		tssi_bounds[6] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A4_PLUS2); +		tssi_bounds[7] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A4_PLUS3); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom); +		tssi_bounds[8] = rt2x00_get_field16(eeprom, +					EEPROM_TSSI_BOUND_A5_PLUS4); + +		step = rt2x00_get_field16(eeprom, +					  EEPROM_TSSI_BOUND_A5_AGC_STEP); +	} + +	/* +	 * Check if temperature compensation is supported. +	 */ +	if (tssi_bounds[4] == 0xff || step == 0xff) +		return 0; + +	/* +	 * Read current TSSI (BBP 49). +	 */ +	rt2800_bbp_read(rt2x00dev, 49, ¤t_tssi); + +	/* +	 * Compare TSSI value (BBP49) with the compensation boundaries +	 * from the EEPROM and increase or decrease tx power. +	 */ +	for (i = 0; i <= 3; i++) { +		if (current_tssi > tssi_bounds[i]) +			break; +	} + +	if (i == 4) { +		for (i = 8; i >= 5; i--) { +			if (current_tssi < tssi_bounds[i]) +				break; +		} +	} + +	return (i - 4) * step; +} + +static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, +				      enum ieee80211_band band) +{ +	u16 eeprom; +	u8 comp_en; +	u8 comp_type; +	int comp_value = 0; + +	rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom); + +	/* +	 * HT40 compensation not required. +	 */ +	if (eeprom == 0xffff || +	    !test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) +		return 0; + +	if (band == IEEE80211_BAND_2GHZ) { +		comp_en = rt2x00_get_field16(eeprom, +				 EEPROM_TXPOWER_DELTA_ENABLE_2G); +		if (comp_en) { +			comp_type = rt2x00_get_field16(eeprom, +					   EEPROM_TXPOWER_DELTA_TYPE_2G); +			comp_value = rt2x00_get_field16(eeprom, +					    EEPROM_TXPOWER_DELTA_VALUE_2G); +			if (!comp_type) +				comp_value = -comp_value; +		} +	} else { +		comp_en = rt2x00_get_field16(eeprom, +				 EEPROM_TXPOWER_DELTA_ENABLE_5G); +		if (comp_en) { +			comp_type = rt2x00_get_field16(eeprom, +					   EEPROM_TXPOWER_DELTA_TYPE_5G); +			comp_value = rt2x00_get_field16(eeprom, +					    EEPROM_TXPOWER_DELTA_VALUE_5G); +			if (!comp_type) +				comp_value = -comp_value; +		} +	} + +	return comp_value; +} + +static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev, +					int power_level, int max_power) +{ +	int delta; + +	if (rt2x00_has_cap_power_limit(rt2x00dev)) +		return 0; + +	/* +	 * XXX: We don't know the maximum transmit power of our hardware since +	 * the EEPROM doesn't expose it. We only know that we are calibrated +	 * to 100% tx power. +	 * +	 * Hence, we assume the regulatory limit that cfg80211 calulated for +	 * the current channel is our maximum and if we are requested to lower +	 * the value we just reduce our tx power accordingly. +	 */ +	delta = power_level - max_power; +	return min(delta, 0); +} + +static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, +				   enum ieee80211_band band, int power_level, +				   u8 txpower, int delta) +{ +	u16 eeprom; +	u8 criterion; +	u8 eirp_txpower; +	u8 eirp_txpower_criterion; +	u8 reg_limit; + +	if (rt2x00_rt(rt2x00dev, RT3593)) +		return min_t(u8, txpower, 0xc); + +	if (rt2x00_has_cap_power_limit(rt2x00dev)) { +		/* +		 * Check if eirp txpower exceed txpower_limit. +		 * We use OFDM 6M as criterion and its eirp txpower +		 * is stored at EEPROM_EIRP_MAX_TX_POWER. +		 * .11b data rate need add additional 4dbm +		 * when calculating eirp txpower. +		 */ +		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +					      1, &eeprom); +		criterion = rt2x00_get_field16(eeprom, +					       EEPROM_TXPOWER_BYRATE_RATE0); + +		rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, +				   &eeprom); + +		if (band == IEEE80211_BAND_2GHZ) +			eirp_txpower_criterion = rt2x00_get_field16(eeprom, +						 EEPROM_EIRP_MAX_TX_POWER_2GHZ); +		else +			eirp_txpower_criterion = rt2x00_get_field16(eeprom, +						 EEPROM_EIRP_MAX_TX_POWER_5GHZ); + +		eirp_txpower = eirp_txpower_criterion + (txpower - criterion) + +			       (is_rate_b ? 4 : 0) + delta; + +		reg_limit = (eirp_txpower > power_level) ? +					(eirp_txpower - power_level) : 0; +	} else +		reg_limit = 0; + +	txpower = max(0, txpower + delta - reg_limit); +	return min_t(u8, txpower, 0xc); +} + + +enum { +	TX_PWR_CFG_0_IDX, +	TX_PWR_CFG_1_IDX, +	TX_PWR_CFG_2_IDX, +	TX_PWR_CFG_3_IDX, +	TX_PWR_CFG_4_IDX, +	TX_PWR_CFG_5_IDX, +	TX_PWR_CFG_6_IDX, +	TX_PWR_CFG_7_IDX, +	TX_PWR_CFG_8_IDX, +	TX_PWR_CFG_9_IDX, +	TX_PWR_CFG_0_EXT_IDX, +	TX_PWR_CFG_1_EXT_IDX, +	TX_PWR_CFG_2_EXT_IDX, +	TX_PWR_CFG_3_EXT_IDX, +	TX_PWR_CFG_4_EXT_IDX, +	TX_PWR_CFG_IDX_COUNT, +}; + +static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_channel *chan, +					 int power_level)  {  	u8 txpower; -	u8 max_value = (u8)max_txpower;  	u16 eeprom; +	u32 regs[TX_PWR_CFG_IDX_COUNT]; +	unsigned int offset; +	enum ieee80211_band band = chan->band; +	int delta;  	int i; -	u32 reg; -	u8 r1; -	u32 offset; + +	memset(regs, '\0', sizeof(regs)); + +	/* TODO: adapt TX power reduction from the rt28xx code */ + +	/* calculate temperature compensation delta */ +	delta = rt2800_get_gain_calibration_delta(rt2x00dev); + +	if (band == IEEE80211_BAND_5GHZ) +		offset = 16; +	else +		offset = 0; + +	if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) +		offset += 8; + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset, &eeprom); + +	/* CCK 1MBS,2MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_CCK1_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_CCK1_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], +			   TX_PWR_CFG_0_EXT_CCK1_CH2, txpower); + +	/* CCK 5.5MBS,11MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_CCK5_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_CCK5_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], +			   TX_PWR_CFG_0_EXT_CCK5_CH2, txpower); + +	/* OFDM 6MBS,9MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_OFDM6_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_OFDM6_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], +			   TX_PWR_CFG_0_EXT_OFDM6_CH2, txpower); + +	/* OFDM 12MBS,18MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_OFDM12_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], +			   TX_PWR_CFG_0_OFDM12_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], +			   TX_PWR_CFG_0_EXT_OFDM12_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 1, &eeprom); + +	/* OFDM 24MBS,36MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_OFDM24_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_OFDM24_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], +			   TX_PWR_CFG_1_EXT_OFDM24_CH2, txpower); + +	/* OFDM 48MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_OFDM48_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_OFDM48_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], +			   TX_PWR_CFG_1_EXT_OFDM48_CH2, txpower); + +	/* OFDM 54MBS */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_OFDM54_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_OFDM54_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_OFDM54_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 2, &eeprom); + +	/* MCS 0,1 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_MCS0_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_MCS0_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], +			   TX_PWR_CFG_1_EXT_MCS0_CH2, txpower); + +	/* MCS 2,3 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_MCS2_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], +			   TX_PWR_CFG_1_MCS2_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], +			   TX_PWR_CFG_1_EXT_MCS2_CH2, txpower); + +	/* MCS 4,5 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS4_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS4_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], +			   TX_PWR_CFG_2_EXT_MCS4_CH2, txpower); + +	/* MCS 6 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS6_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS6_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], +			   TX_PWR_CFG_2_EXT_MCS6_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 3, &eeprom); + +	/* MCS 7 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_MCS7_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_MCS7_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], +			   TX_PWR_CFG_7_MCS7_CH2, txpower); + +	/* MCS 8,9 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS8_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS8_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], +			   TX_PWR_CFG_2_EXT_MCS8_CH2, txpower); + +	/* MCS 10,11 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS10_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], +			   TX_PWR_CFG_2_MCS10_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], +			   TX_PWR_CFG_2_EXT_MCS10_CH2, txpower); + +	/* MCS 12,13 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_MCS12_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_MCS12_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], +			   TX_PWR_CFG_3_EXT_MCS12_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 4, &eeprom); + +	/* MCS 14 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_MCS14_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_MCS14_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], +			   TX_PWR_CFG_3_EXT_MCS14_CH2, txpower); + +	/* MCS 15 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS15_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS15_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS15_CH2, txpower); + +	/* MCS 16,17 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS16_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS16_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS16_CH2, txpower); + +	/* MCS 18,19 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS18_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS18_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], +			   TX_PWR_CFG_5_MCS18_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 5, &eeprom); + +	/* MCS 20,21 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS20_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS20_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS20_CH2, txpower); + +	/* MCS 22 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS22_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS22_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], +			   TX_PWR_CFG_6_MCS22_CH2, txpower); + +	/* MCS 23 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS23_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS23_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], +			   TX_PWR_CFG_8_MCS23_CH2, txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 6, &eeprom); + +	/* STBC, MCS 0,1 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_STBC0_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_STBC0_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], +			   TX_PWR_CFG_3_EXT_STBC0_CH2, txpower); + +	/* STBC, MCS 2,3 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_STBC2_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], +			   TX_PWR_CFG_3_STBC2_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], +			   TX_PWR_CFG_3_EXT_STBC2_CH2, txpower); + +	/* STBC, MCS 4,5 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE0, +			   txpower); + +	/* STBC, MCS 6 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE2, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE3, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE2, +			   txpower); + +	/* read the next four txpower values */ +	rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +				      offset + 7, &eeprom); + +	/* STBC, MCS 7 */ +	txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); +	txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, +					    txpower, delta); +	rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], +			   TX_PWR_CFG_9_STBC7_CH0, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], +			   TX_PWR_CFG_9_STBC7_CH1, txpower); +	rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], +			   TX_PWR_CFG_9_STBC7_CH2, txpower); + +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, regs[TX_PWR_CFG_0_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, regs[TX_PWR_CFG_1_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, regs[TX_PWR_CFG_2_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, regs[TX_PWR_CFG_3_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, regs[TX_PWR_CFG_4_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_5, regs[TX_PWR_CFG_5_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_6, regs[TX_PWR_CFG_6_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_7, regs[TX_PWR_CFG_7_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_8, regs[TX_PWR_CFG_8_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, regs[TX_PWR_CFG_9_IDX]); + +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_0_EXT, +			      regs[TX_PWR_CFG_0_EXT_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_1_EXT, +			      regs[TX_PWR_CFG_1_EXT_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_2_EXT, +			      regs[TX_PWR_CFG_2_EXT_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_3_EXT, +			      regs[TX_PWR_CFG_3_EXT_IDX]); +	rt2800_register_write(rt2x00dev, TX_PWR_CFG_4_EXT, +			      regs[TX_PWR_CFG_4_EXT_IDX]); + +	for (i = 0; i < TX_PWR_CFG_IDX_COUNT; i++) +		rt2x00_dbg(rt2x00dev, +			   "band:%cGHz, BW:%c0MHz, TX_PWR_CFG_%d%s = %08lx\n", +			   (band == IEEE80211_BAND_5GHZ) ? '5' : '2', +			   (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) ? +								'4' : '2', +			   (i > TX_PWR_CFG_9_IDX) ? +					(i - TX_PWR_CFG_9_IDX - 1) : i, +			   (i > TX_PWR_CFG_9_IDX) ? "_EXT" : "", +			   (unsigned long) regs[i]); +} + +/* + * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and + * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values, + * 4 bits for each rate (tune from 0 to 15 dBm). BBP_R1 controls transmit power + * for all rates, but allow to set only 4 discrete values: -12, -6, 0 and 6 dBm. + * Reference per rate transmit power values are located in the EEPROM at + * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to + * current conditions (i.e. band, bandwidth, temperature, user settings). + */ +static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev, +					 struct ieee80211_channel *chan, +					 int power_level) +{ +	u8 txpower, r1; +	u16 eeprom; +	u32 reg, offset; +	int i, is_rate_b, delta, power_ctrl; +	enum ieee80211_band band = chan->band;  	/* -	 * set to normal tx power mode: +/- 0dBm +	 * Calculate HT40 compensation. For 40MHz we need to add or subtract +	 * value read from EEPROM (different for 2GHz and for 5GHz).  	 */ -	rt2800_bbp_read(rt2x00dev, 1, &r1); -	rt2x00_set_field8(&r1, BBP1_TX_POWER, 0); -	rt2800_bbp_write(rt2x00dev, 1, r1); +	delta = rt2800_get_txpower_bw_comp(rt2x00dev, band); + +	/* +	 * Calculate temperature compensation. Depends on measurement of current +	 * TSSI (Transmitter Signal Strength Indication) we know TX power (due +	 * to temperature or maybe other factors) is smaller or bigger than +	 * expected. We adjust it, based on TSSI reference and boundaries values +	 * provided in EEPROM. +	 */ +	delta += rt2800_get_gain_calibration_delta(rt2x00dev);  	/* -	 * The eeprom contains the tx power values for each rate. These -	 * values map to 100% tx power. Each 16bit word contains four tx -	 * power values and the order is the same as used in the TX_PWR_CFG -	 * registers. +	 * Decrease power according to user settings, on devices with unknown +	 * maximum tx power. For other devices we take user power_level into +	 * consideration on rt2800_compensate_txpower().  	 */ +	delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level, +					      chan->max_power); + +	/* +	 * BBP_R1 controls TX power for all rates, it allow to set the following +	 * gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively. +	 * +	 * TODO: we do not use +6 dBm option to do not increase power beyond +	 * regulatory limit, however this could be utilized for devices with +	 * CAPABILITY_POWER_LIMIT. +	 * +	 * TODO: add different temperature compensation code for RT3290 & RT5390 +	 * to allow to use BBP_R1 for those chips. +	 */ +	if (!rt2x00_rt(rt2x00dev, RT3290) && +	    !rt2x00_rt(rt2x00dev, RT5390)) { +		rt2800_bbp_read(rt2x00dev, 1, &r1); +		if (delta <= -12) { +			power_ctrl = 2; +			delta += 12; +		} else if (delta <= -6) { +			power_ctrl = 1; +			delta += 6; +		} else { +			power_ctrl = 0; +		} +		rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl); +		rt2800_bbp_write(rt2x00dev, 1, r1); +	} +  	offset = TX_PWR_CFG_0;  	for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) { @@ -1661,76 +4119,102 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,  		rt2800_register_read(rt2x00dev, offset, ®);  		/* read the next four txpower values */ -		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i, -				   &eeprom); +		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +					      i, &eeprom); -		/* TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS, +		is_rate_b = i ? 0 : 1; +		/* +		 * TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS,  		 * TX_PWR_CFG_2: MCS4, TX_PWR_CFG_3: MCS12, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE0); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE0, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE0, txpower); -		/* TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS, +		/* +		 * TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS,  		 * TX_PWR_CFG_2: MCS5, TX_PWR_CFG_3: MCS13, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE1); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE1, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE1, txpower); -		/* TX_PWR_CFG_0: 55MBS, TX_PWR_CFG_1: 48MBS, +		/* +		 * TX_PWR_CFG_0: 5.5MBS, TX_PWR_CFG_1: 48MBS,  		 * TX_PWR_CFG_2: MCS6,  TX_PWR_CFG_3: MCS14, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE2); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE2, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE2, txpower); -		/* TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS, +		/* +		 * TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS,  		 * TX_PWR_CFG_2: MCS7,  TX_PWR_CFG_3: MCS15, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE3); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE3, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE3, txpower);  		/* read the next four txpower values */ -		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i + 1, -				   &eeprom); +		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, +					      i + 1, &eeprom); -		/* TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0, +		is_rate_b = 0; +		/* +		 * TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0,  		 * TX_PWR_CFG_2: MCS8, TX_PWR_CFG_3: unknown, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE0); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE4, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE4, txpower); -		/* TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1, +		/* +		 * TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1,  		 * TX_PWR_CFG_2: MCS9, TX_PWR_CFG_3: unknown, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE1); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE5, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE5, txpower); -		/* TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2, +		/* +		 * TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2,  		 * TX_PWR_CFG_2: MCS10, TX_PWR_CFG_3: unknown, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE2); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE6, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE6, txpower); -		/* TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3, +		/* +		 * TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3,  		 * TX_PWR_CFG_2: MCS11, TX_PWR_CFG_3: unknown, -		 * TX_PWR_CFG_4: unknown */ +		 * TX_PWR_CFG_4: unknown +		 */  		txpower = rt2x00_get_field16(eeprom,  					     EEPROM_TXPOWER_BYRATE_RATE3); -		rt2x00_set_field32(®, TX_PWR_CFG_RATE7, -				   min(txpower, max_value)); +		txpower = rt2800_compensate_txpower(rt2x00dev, is_rate_b, band, +					     power_level, txpower, delta); +		rt2x00_set_field32(®, TX_PWR_CFG_RATE7, txpower);  		rt2800_register_write(rt2x00dev, offset, reg); @@ -1739,6 +4223,102 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,  	}  } +static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, +				  struct ieee80211_channel *chan, +				  int power_level) +{ +	if (rt2x00_rt(rt2x00dev, RT3593)) +		rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level); +	else +		rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level); +} + +void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.chandef.chan, +			      rt2x00dev->tx_power); +} +EXPORT_SYMBOL_GPL(rt2800_gain_calibration); + +void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) +{ +	u32	tx_pin; +	u8	rfcsr; + +	/* +	 * A voltage-controlled oscillator(VCO) is an electronic oscillator +	 * designed to be controlled in oscillation frequency by a voltage +	 * input. Maybe the temperature will affect the frequency of +	 * oscillation to be shifted. The VCO calibration will be called +	 * periodically to adjust the frequency to be precision. +	*/ + +	rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin); +	tx_pin &= TX_PIN_CFG_PA_PE_DISABLE; +	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); + +	switch (rt2x00dev->chip.rf) { +	case RF2020: +	case RF3020: +	case RF3021: +	case RF3022: +	case RF3320: +	case RF3052: +		rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); +		rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); +		break; +	case RF3053: +	case RF3070: +	case RF3290: +	case RF5360: +	case RF5370: +	case RF5372: +	case RF5390: +	case RF5392: +		rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); +		rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); +		break; +	default: +		return; +	} + +	mdelay(1); + +	rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin); +	if (rt2x00dev->rf_channel <= 14) { +		switch (rt2x00dev->default_ant.tx_chain_num) { +		case 3: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN, 1); +			/* fall through */ +		case 2: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); +			/* fall through */ +		case 1: +		default: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); +			break; +		} +	} else { +		switch (rt2x00dev->default_ant.tx_chain_num) { +		case 3: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN, 1); +			/* fall through */ +		case 2: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); +			/* fall through */ +		case 1: +		default: +			rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 1); +			break; +		} +	} +	rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); + +} +EXPORT_SYMBOL_GPL(rt2800_vco_calibration); +  static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev,  				      struct rt2x00lib_conf *libconf)  { @@ -1789,11 +4369,15 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,  	/* Always recalculate LNA gain before changing configuration */  	rt2800_config_lna_gain(rt2x00dev, libconf); -	if (flags & IEEE80211_CONF_CHANGE_CHANNEL) +	if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {  		rt2800_config_channel(rt2x00dev, libconf->conf,  				      &libconf->rf, &libconf->channel); +		rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan, +				      libconf->conf->power_level); +	}  	if (flags & IEEE80211_CONF_CHANGE_POWER) -		rt2800_config_txpower(rt2x00dev, libconf->conf->power_level); +		rt2800_config_txpower(rt2x00dev, libconf->conf->chandef.chan, +				      libconf->conf->power_level);  	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)  		rt2800_config_retry_limit(rt2x00dev, libconf);  	if (flags & IEEE80211_CONF_CHANGE_PS) @@ -1818,27 +4402,53 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats);  static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)  { +	u8 vgc; +  	if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {  		if (rt2x00_rt(rt2x00dev, RT3070) ||  		    rt2x00_rt(rt2x00dev, RT3071) ||  		    rt2x00_rt(rt2x00dev, RT3090) || -		    rt2x00_rt(rt2x00dev, RT3390)) -			return 0x1c + (2 * rt2x00dev->lna_gain); +		    rt2x00_rt(rt2x00dev, RT3290) || +		    rt2x00_rt(rt2x00dev, RT3390) || +		    rt2x00_rt(rt2x00dev, RT3572) || +		    rt2x00_rt(rt2x00dev, RT3593) || +		    rt2x00_rt(rt2x00dev, RT5390) || +		    rt2x00_rt(rt2x00dev, RT5392) || +		    rt2x00_rt(rt2x00dev, RT5592)) +			vgc = 0x1c + (2 * rt2x00dev->lna_gain);  		else -			return 0x2e + rt2x00dev->lna_gain; +			vgc = 0x2e + rt2x00dev->lna_gain; +	} else { /* 5GHZ band */ +		if (rt2x00_rt(rt2x00dev, RT3593)) +			vgc = 0x20 + (rt2x00dev->lna_gain * 5) / 3; +		else if (rt2x00_rt(rt2x00dev, RT5592)) +			vgc = 0x24 + (2 * rt2x00dev->lna_gain); +		else { +			if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) +				vgc = 0x32 + (rt2x00dev->lna_gain * 5) / 3; +			else +				vgc = 0x3a + (rt2x00dev->lna_gain * 5) / 3; +		}  	} -	if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) -		return 0x32 + (rt2x00dev->lna_gain * 5) / 3; -	else -		return 0x3a + (rt2x00dev->lna_gain * 5) / 3; +	return vgc;  }  static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev,  				  struct link_qual *qual, u8 vgc_level)  {  	if (qual->vgc_level != vgc_level) { -		rt2800_bbp_write(rt2x00dev, 66, vgc_level); +		if (rt2x00_rt(rt2x00dev, RT3572) || +		    rt2x00_rt(rt2x00dev, RT3593)) { +			rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, +						       vgc_level); +		} else if (rt2x00_rt(rt2x00dev, RT5592)) { +			rt2800_bbp_write(rt2x00dev, 83, qual->rssi > -65 ? 0x4a : 0x7a); +			rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, vgc_level); +		} else { +			rt2800_bbp_write(rt2x00dev, 66, vgc_level); +		} +  		qual->vgc_level = vgc_level;  		qual->vgc_level_reg = vgc_level;  	} @@ -1853,15 +4463,41 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner);  void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,  		       const u32 count)  { +	u8 vgc; +  	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C))  		return; -	/* -	 * When RSSI is better then -80 increase VGC level with 0x10 +	/* When RSSI is better than a certain threshold, increase VGC +	 * with a chip specific value in order to improve the balance +	 * between sensibility and noise isolation.  	 */ -	rt2800_set_vgc(rt2x00dev, qual, -		       rt2800_get_default_vgc(rt2x00dev) + -		       ((qual->rssi > -80) * 0x10)); + +	vgc = rt2800_get_default_vgc(rt2x00dev); + +	switch (rt2x00dev->chip.rt) { +	case RT3572: +	case RT3593: +		if (qual->rssi > -65) { +			if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) +				vgc += 0x20; +			else +				vgc += 0x10; +		} +		break; + +	case RT5592: +		if (qual->rssi > -65) +			vgc += 0x20; +		break; + +	default: +		if (qual->rssi > -80) +			vgc += 0x10; +		break; +	} + +	rt2800_set_vgc(rt2x00dev, qual, vgc);  }  EXPORT_SYMBOL_GPL(rt2800_link_tuner); @@ -1875,30 +4511,32 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	unsigned int i;  	int ret; -	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); -	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); +	rt2800_disable_wpdma(rt2x00dev);  	ret = rt2800_drv_init_registers(rt2x00dev);  	if (ret)  		return ret;  	rt2800_register_read(rt2x00dev, BCN_OFFSET0, ®); -	rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ -	rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */ -	rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */ -	rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */ +	rt2x00_set_field32(®, BCN_OFFSET0_BCN0, +			   rt2800_get_beacon_offset(rt2x00dev, 0)); +	rt2x00_set_field32(®, BCN_OFFSET0_BCN1, +			   rt2800_get_beacon_offset(rt2x00dev, 1)); +	rt2x00_set_field32(®, BCN_OFFSET0_BCN2, +			   rt2800_get_beacon_offset(rt2x00dev, 2)); +	rt2x00_set_field32(®, BCN_OFFSET0_BCN3, +			   rt2800_get_beacon_offset(rt2x00dev, 3));  	rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);  	rt2800_register_read(rt2x00dev, BCN_OFFSET1, ®); -	rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */ -	rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */ -	rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */ -	rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */ +	rt2x00_set_field32(®, BCN_OFFSET1_BCN4, +			   rt2800_get_beacon_offset(rt2x00dev, 4)); +	rt2x00_set_field32(®, BCN_OFFSET1_BCN5, +			   rt2800_get_beacon_offset(rt2x00dev, 5)); +	rt2x00_set_field32(®, BCN_OFFSET1_BCN6, +			   rt2800_get_beacon_offset(rt2x00dev, 6)); +	rt2x00_set_field32(®, BCN_OFFSET1_BCN7, +			   rt2800_get_beacon_offset(rt2x00dev, 7));  	rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);  	rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); @@ -1922,16 +4560,61 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);  	rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); +	if (rt2x00_rt(rt2x00dev, RT3290)) { +		rt2800_register_read(rt2x00dev, WLAN_FUN_CTRL, ®); +		if (rt2x00_get_field32(reg, WLAN_EN) == 1) { +			rt2x00_set_field32(®, PCIE_APP0_CLK_REQ, 1); +			rt2800_register_write(rt2x00dev, WLAN_FUN_CTRL, reg); +		} + +		rt2800_register_read(rt2x00dev, CMB_CTRL, ®); +		if (!(rt2x00_get_field32(reg, LDO0_EN) == 1)) { +			rt2x00_set_field32(®, LDO0_EN, 1); +			rt2x00_set_field32(®, LDO_BGSEL, 3); +			rt2800_register_write(rt2x00dev, CMB_CTRL, reg); +		} + +		rt2800_register_read(rt2x00dev, OSC_CTRL, ®); +		rt2x00_set_field32(®, OSC_ROSC_EN, 1); +		rt2x00_set_field32(®, OSC_CAL_REQ, 1); +		rt2x00_set_field32(®, OSC_REF_CYCLE, 0x27); +		rt2800_register_write(rt2x00dev, OSC_CTRL, reg); + +		rt2800_register_read(rt2x00dev, COEX_CFG0, ®); +		rt2x00_set_field32(®, COEX_CFG_ANT, 0x5e); +		rt2800_register_write(rt2x00dev, COEX_CFG0, reg); + +		rt2800_register_read(rt2x00dev, COEX_CFG2, ®); +		rt2x00_set_field32(®, BT_COEX_CFG1, 0x00); +		rt2x00_set_field32(®, BT_COEX_CFG0, 0x17); +		rt2x00_set_field32(®, WL_COEX_CFG1, 0x93); +		rt2x00_set_field32(®, WL_COEX_CFG0, 0x7f); +		rt2800_register_write(rt2x00dev, COEX_CFG2, reg); + +		rt2800_register_read(rt2x00dev, PLL_CTRL, ®); +		rt2x00_set_field32(®, PLL_CONTROL, 1); +		rt2800_register_write(rt2x00dev, PLL_CTRL, reg); +	} +  	if (rt2x00_rt(rt2x00dev, RT3071) ||  	    rt2x00_rt(rt2x00dev, RT3090) || +	    rt2x00_rt(rt2x00dev, RT3290) ||  	    rt2x00_rt(rt2x00dev, RT3390)) { -		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); + +		if (rt2x00_rt(rt2x00dev, RT3290)) +			rt2800_register_write(rt2x00dev, TX_SW_CFG0, +					      0x00000404); +		else +			rt2800_register_write(rt2x00dev, TX_SW_CFG0, +					      0x00000400); +  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);  		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||  		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||  		    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { -			rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); -			if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) +			rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, +					   &eeprom); +			if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))  				rt2800_register_write(rt2x00dev, TX_SW_CFG2,  						      0x0000002c);  			else @@ -1953,7 +4636,37 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	} else if (rt2800_is_305x_soc(rt2x00dev)) {  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); -		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f); +		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000030); +	} else if (rt2x00_rt(rt2x00dev, RT3352)) { +		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402); +		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); +		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); +	} else if (rt2x00_rt(rt2x00dev, RT3572)) { +		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); +		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); +	} else if (rt2x00_rt(rt2x00dev, RT3593)) { +		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402); +		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); +		if (rt2x00_rt_rev_lt(rt2x00dev, RT3593, REV_RT3593E)) { +			rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, +					   &eeprom); +			if (rt2x00_get_field16(eeprom, +					       EEPROM_NIC_CONF1_DAC_TEST)) +				rt2800_register_write(rt2x00dev, TX_SW_CFG2, +						      0x0000001f); +			else +				rt2800_register_write(rt2x00dev, TX_SW_CFG2, +						      0x0000000f); +		} else { +			rt2800_register_write(rt2x00dev, TX_SW_CFG2, +					      0x00000000); +		} +	} else if (rt2x00_rt(rt2x00dev, RT5390) || +		   rt2x00_rt(rt2x00dev, RT5392) || +		   rt2x00_rt(rt2x00dev, RT5592)) { +		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404); +		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); +		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);  	} else {  		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);  		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); @@ -2022,7 +4735,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, CCK_PROT_CFG, ®);  	rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 3);  	rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2035,7 +4748,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, ®);  	rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 3);  	rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2048,7 +4761,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, MM20_PROT_CFG, ®);  	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, 0x4004);  	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2061,7 +4774,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, MM40_PROT_CFG, ®);  	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084);  	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2074,7 +4787,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, GF20_PROT_CFG, ®);  	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, 0x4004);  	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2087,7 +4800,7 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2800_register_read(rt2x00dev, GF40_PROT_CFG, ®);  	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, 0x4084);  	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, 0); -	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV, 1); +	rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV_SHORT, 1);  	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1);  	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);  	rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1); @@ -2130,7 +4843,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CWMIN, 0);  	rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg); -	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); +	reg = rt2x00_rt(rt2x00dev, RT5592) ? 0x00000082 : 0x00000002; +	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, reg);  	rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®);  	rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); @@ -2166,30 +4880,25 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  					 SHARED_KEY_MODE_ENTRY(i), 0);  	for (i = 0; i < 256; i++) { -		static const u32 wcid[2] = { 0xffffffff, 0x00ffffff }; -		rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), -					      wcid, sizeof(wcid)); - -		rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); +		rt2800_config_wcid(rt2x00dev, NULL, i); +		rt2800_delete_wcid_attr(rt2x00dev, i);  		rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);  	}  	/*  	 * Clear all beacons  	 */ -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE0); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE1); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE2); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE3); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE4); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE5); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE6); -	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE7); +	for (i = 0; i < 8; i++) +		rt2800_clear_beacon_register(rt2x00dev, i);  	if (rt2x00_is_usb(rt2x00dev)) {  		rt2800_register_read(rt2x00dev, US_CYC_CNT, ®);  		rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 30);  		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg); +	} else if (rt2x00_is_pcie(rt2x00dev)) { +		rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); +		rt2x00_set_field32(®, US_CYC_CNT_CLOCK_CYCLE, 125); +		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);  	}  	rt2800_register_read(rt2x00dev, HT_FBK_CFG0, ®); @@ -2259,6 +4968,17 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4);  	rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg); +	/* +	 * Set up channel statistics timer +	 */ +	rt2800_register_read(rt2x00dev, CH_TIME_CFG, ®); +	rt2x00_set_field32(®, CH_TIME_CFG_EIFS_BUSY, 1); +	rt2x00_set_field32(®, CH_TIME_CFG_NAV_BUSY, 1); +	rt2x00_set_field32(®, CH_TIME_CFG_RX_BUSY, 1); +	rt2x00_set_field32(®, CH_TIME_CFG_TX_BUSY, 1); +	rt2x00_set_field32(®, CH_TIME_CFG_TMR_EN, 1); +	rt2800_register_write(rt2x00dev, CH_TIME_CFG, reg); +  	return 0;  } @@ -2275,7 +4995,7 @@ static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)  		udelay(REGISTER_BUSY_DELAY);  	} -	ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n"); +	rt2x00_err(rt2x00dev, "BBP/RF register access failed, aborting\n");  	return -EACCES;  } @@ -2299,24 +5019,116 @@ static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)  		udelay(REGISTER_BUSY_DELAY);  	} -	ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); +	rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");  	return -EACCES;  } -static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) +static void rt2800_bbp4_mac_if_ctrl(struct rt2x00_dev *rt2x00dev) +{ +	u8 value; + +	rt2800_bbp_read(rt2x00dev, 4, &value); +	rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1); +	rt2800_bbp_write(rt2x00dev, 4, value); +} + +static void rt2800_init_freq_calibration(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 142, 1); +	rt2800_bbp_write(rt2x00dev, 143, 57); +} + +static void rt2800_init_bbp_5592_glrt(struct rt2x00_dev *rt2x00dev) +{ +	const u8 glrt_table[] = { +		0xE0, 0x1F, 0X38, 0x32, 0x08, 0x28, 0x19, 0x0A, 0xFF, 0x00, /* 128 ~ 137 */ +		0x16, 0x10, 0x10, 0x0B, 0x36, 0x2C, 0x26, 0x24, 0x42, 0x36, /* 138 ~ 147 */ +		0x30, 0x2D, 0x4C, 0x46, 0x3D, 0x40, 0x3E, 0x42, 0x3D, 0x40, /* 148 ~ 157 */ +		0X3C, 0x34, 0x2C, 0x2F, 0x3C, 0x35, 0x2E, 0x2A, 0x49, 0x41, /* 158 ~ 167 */ +		0x36, 0x31, 0x30, 0x30, 0x0E, 0x0D, 0x28, 0x21, 0x1C, 0x16, /* 168 ~ 177 */ +		0x50, 0x4A, 0x43, 0x40, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, /* 178 ~ 187 */ +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 188 ~ 197 */ +		0x00, 0x00, 0x7D, 0x14, 0x32, 0x2C, 0x36, 0x4C, 0x43, 0x2C, /* 198 ~ 207 */ +		0x2E, 0x36, 0x30, 0x6E,					    /* 208 ~ 211 */ +	}; +	int i; + +	for (i = 0; i < ARRAY_SIZE(glrt_table); i++) { +		rt2800_bbp_write(rt2x00dev, 195, 128 + i); +		rt2800_bbp_write(rt2x00dev, 196, glrt_table[i]); +	} +}; + +static void rt2800_init_bbp_early(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 65, 0x2C); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); +	rt2800_bbp_write(rt2x00dev, 68, 0x0B); +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); +	rt2800_bbp_write(rt2x00dev, 73, 0x10); +	rt2800_bbp_write(rt2x00dev, 81, 0x37); +	rt2800_bbp_write(rt2x00dev, 82, 0x62); +	rt2800_bbp_write(rt2x00dev, 83, 0x6A); +	rt2800_bbp_write(rt2x00dev, 84, 0x99); +	rt2800_bbp_write(rt2x00dev, 86, 0x00); +	rt2800_bbp_write(rt2x00dev, 91, 0x04); +	rt2800_bbp_write(rt2x00dev, 92, 0x00); +	rt2800_bbp_write(rt2x00dev, 103, 0x00); +	rt2800_bbp_write(rt2x00dev, 105, 0x05); +	rt2800_bbp_write(rt2x00dev, 106, 0x35); +} + +static void rt2800_disable_unused_dac_adc(struct rt2x00_dev *rt2x00dev)  { -	unsigned int i;  	u16 eeprom; -	u8 reg_id;  	u8 value; -	if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) || -		     rt2800_wait_bbp_ready(rt2x00dev))) -		return -EACCES; +	rt2800_bbp_read(rt2x00dev, 138, &value); +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) +		value |= 0x20; +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) +		value &= ~0x02; +	rt2800_bbp_write(rt2x00dev, 138, value); +} -	if (rt2800_is_305x_soc(rt2x00dev)) -		rt2800_bbp_write(rt2x00dev, 31, 0x08); +static void rt2800_init_bbp_305x_soc(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x10); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 78, 0x0e); +	rt2800_bbp_write(rt2x00dev, 80, 0x08); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x6a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x99); + +	rt2800_bbp_write(rt2x00dev, 86, 0x00); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x00); + +	rt2800_bbp_write(rt2x00dev, 103, 0xc0); +	rt2800_bbp_write(rt2x00dev, 105, 0x01); + +	rt2800_bbp_write(rt2x00dev, 106, 0x35); +} + +static void rt2800_init_bbp_28xx(struct rt2x00_dev *rt2x00dev) +{  	rt2800_bbp_write(rt2x00dev, 65, 0x2c);  	rt2800_bbp_write(rt2x00dev, 66, 0x38); @@ -2330,21 +5142,10 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  	rt2800_bbp_write(rt2x00dev, 70, 0x0a); -	if (rt2x00_rt(rt2x00dev, RT3070) || -	    rt2x00_rt(rt2x00dev, RT3071) || -	    rt2x00_rt(rt2x00dev, RT3090) || -	    rt2x00_rt(rt2x00dev, RT3390)) { -		rt2800_bbp_write(rt2x00dev, 79, 0x13); -		rt2800_bbp_write(rt2x00dev, 80, 0x05); -		rt2800_bbp_write(rt2x00dev, 81, 0x33); -	} else if (rt2800_is_305x_soc(rt2x00dev)) { -		rt2800_bbp_write(rt2x00dev, 78, 0x0e); -		rt2800_bbp_write(rt2x00dev, 80, 0x08); -	} else { -		rt2800_bbp_write(rt2x00dev, 81, 0x37); -	} +	rt2800_bbp_write(rt2x00dev, 81, 0x37);  	rt2800_bbp_write(rt2x00dev, 82, 0x62); +  	rt2800_bbp_write(rt2x00dev, 83, 0x6a);  	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D)) @@ -2353,41 +5154,526 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  		rt2800_bbp_write(rt2x00dev, 84, 0x99);  	rt2800_bbp_write(rt2x00dev, 86, 0x00); +  	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x00); + +	rt2800_bbp_write(rt2x00dev, 103, 0x00); + +	rt2800_bbp_write(rt2x00dev, 105, 0x05); + +	rt2800_bbp_write(rt2x00dev, 106, 0x35); +} + +static void rt2800_init_bbp_30xx(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x10); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 79, 0x13); +	rt2800_bbp_write(rt2x00dev, 80, 0x05); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x6a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x99); + +	rt2800_bbp_write(rt2x00dev, 86, 0x00); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); +  	rt2800_bbp_write(rt2x00dev, 92, 0x00);  	if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||  	    rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) || -	    rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) || -	    rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) || -	    rt2800_is_305x_soc(rt2x00dev)) +	    rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E))  		rt2800_bbp_write(rt2x00dev, 103, 0xc0);  	else  		rt2800_bbp_write(rt2x00dev, 103, 0x00); -	if (rt2800_is_305x_soc(rt2x00dev)) -		rt2800_bbp_write(rt2x00dev, 105, 0x01); -	else -		rt2800_bbp_write(rt2x00dev, 105, 0x05); +	rt2800_bbp_write(rt2x00dev, 105, 0x05); +  	rt2800_bbp_write(rt2x00dev, 106, 0x35);  	if (rt2x00_rt(rt2x00dev, RT3071) || -	    rt2x00_rt(rt2x00dev, RT3090) || -	    rt2x00_rt(rt2x00dev, RT3390)) { -		rt2800_bbp_read(rt2x00dev, 138, &value); +	    rt2x00_rt(rt2x00dev, RT3090)) +		rt2800_disable_unused_dac_adc(rt2x00dev); +} + +static void rt2800_init_bbp_3290(struct rt2x00_dev *rt2x00dev) +{ +	u8 value; + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 68, 0x0b); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x13); +	rt2800_bbp_write(rt2x00dev, 75, 0x46); +	rt2800_bbp_write(rt2x00dev, 76, 0x28); + +	rt2800_bbp_write(rt2x00dev, 77, 0x58); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 74, 0x0b); +	rt2800_bbp_write(rt2x00dev, 79, 0x18); +	rt2800_bbp_write(rt2x00dev, 80, 0x09); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x7a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x9a); + +	rt2800_bbp_write(rt2x00dev, 86, 0x38); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x02); + +	rt2800_bbp_write(rt2x00dev, 103, 0xc0); + +	rt2800_bbp_write(rt2x00dev, 104, 0x92); + +	rt2800_bbp_write(rt2x00dev, 105, 0x1c); + +	rt2800_bbp_write(rt2x00dev, 106, 0x03); + +	rt2800_bbp_write(rt2x00dev, 128, 0x12); + +	rt2800_bbp_write(rt2x00dev, 67, 0x24); +	rt2800_bbp_write(rt2x00dev, 143, 0x04); +	rt2800_bbp_write(rt2x00dev, 142, 0x99); +	rt2800_bbp_write(rt2x00dev, 150, 0x30); +	rt2800_bbp_write(rt2x00dev, 151, 0x2e); +	rt2800_bbp_write(rt2x00dev, 152, 0x20); +	rt2800_bbp_write(rt2x00dev, 153, 0x34); +	rt2800_bbp_write(rt2x00dev, 154, 0x40); +	rt2800_bbp_write(rt2x00dev, 155, 0x3b); +	rt2800_bbp_write(rt2x00dev, 253, 0x04); + +	rt2800_bbp_read(rt2x00dev, 47, &value); +	rt2x00_set_field8(&value, BBP47_TSSI_ADC6, 1); +	rt2800_bbp_write(rt2x00dev, 47, value); -		rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); -		if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) -			value |= 0x20; -		if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) -			value &= ~0x02; +	/* Use 5-bit ADC for Acquisition and 8-bit ADC for data */ +	rt2800_bbp_read(rt2x00dev, 3, &value); +	rt2x00_set_field8(&value, BBP3_ADC_MODE_SWITCH, 1); +	rt2x00_set_field8(&value, BBP3_ADC_INIT_MODE, 1); +	rt2800_bbp_write(rt2x00dev, 3, value); +} + +static void rt2800_init_bbp_3352(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 3, 0x00); +	rt2800_bbp_write(rt2x00dev, 4, 0x50); + +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	rt2800_bbp_write(rt2x00dev, 47, 0x48); + +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 68, 0x0b); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x13); +	rt2800_bbp_write(rt2x00dev, 75, 0x46); +	rt2800_bbp_write(rt2x00dev, 76, 0x28); + +	rt2800_bbp_write(rt2x00dev, 77, 0x59); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 78, 0x0e); +	rt2800_bbp_write(rt2x00dev, 80, 0x08); +	rt2800_bbp_write(rt2x00dev, 81, 0x37); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x6a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x99); + +	rt2800_bbp_write(rt2x00dev, 86, 0x38); + +	rt2800_bbp_write(rt2x00dev, 88, 0x90); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x02); + +	rt2800_bbp_write(rt2x00dev, 103, 0xc0); + +	rt2800_bbp_write(rt2x00dev, 104, 0x92); + +	rt2800_bbp_write(rt2x00dev, 105, 0x34); + +	rt2800_bbp_write(rt2x00dev, 106, 0x05); + +	rt2800_bbp_write(rt2x00dev, 120, 0x50); + +	rt2800_bbp_write(rt2x00dev, 137, 0x0f); + +	rt2800_bbp_write(rt2x00dev, 163, 0xbd); +	/* Set ITxBF timeout to 0x9c40=1000msec */ +	rt2800_bbp_write(rt2x00dev, 179, 0x02); +	rt2800_bbp_write(rt2x00dev, 180, 0x00); +	rt2800_bbp_write(rt2x00dev, 182, 0x40); +	rt2800_bbp_write(rt2x00dev, 180, 0x01); +	rt2800_bbp_write(rt2x00dev, 182, 0x9c); +	rt2800_bbp_write(rt2x00dev, 179, 0x00); +	/* Reprogram the inband interface to put right values in RXWI */ +	rt2800_bbp_write(rt2x00dev, 142, 0x04); +	rt2800_bbp_write(rt2x00dev, 143, 0x3b); +	rt2800_bbp_write(rt2x00dev, 142, 0x06); +	rt2800_bbp_write(rt2x00dev, 143, 0xa0); +	rt2800_bbp_write(rt2x00dev, 142, 0x07); +	rt2800_bbp_write(rt2x00dev, 143, 0xa1); +	rt2800_bbp_write(rt2x00dev, 142, 0x08); +	rt2800_bbp_write(rt2x00dev, 143, 0xa2); + +	rt2800_bbp_write(rt2x00dev, 148, 0xc8); +} + +static void rt2800_init_bbp_3390(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x10); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 79, 0x13); +	rt2800_bbp_write(rt2x00dev, 80, 0x05); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x6a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x99); + +	rt2800_bbp_write(rt2x00dev, 86, 0x00); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x00); + +	if (rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E)) +		rt2800_bbp_write(rt2x00dev, 103, 0xc0); +	else +		rt2800_bbp_write(rt2x00dev, 103, 0x00); + +	rt2800_bbp_write(rt2x00dev, 105, 0x05); + +	rt2800_bbp_write(rt2x00dev, 106, 0x35); + +	rt2800_disable_unused_dac_adc(rt2x00dev); +} + +static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x10); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 79, 0x13); +	rt2800_bbp_write(rt2x00dev, 80, 0x05); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x6a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x99); + +	rt2800_bbp_write(rt2x00dev, 86, 0x00); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x00); + +	rt2800_bbp_write(rt2x00dev, 103, 0xc0); + +	rt2800_bbp_write(rt2x00dev, 105, 0x05); + +	rt2800_bbp_write(rt2x00dev, 106, 0x35); + +	rt2800_disable_unused_dac_adc(rt2x00dev); +} + +static void rt2800_init_bbp_3593(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_init_bbp_early(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 79, 0x13); +	rt2800_bbp_write(rt2x00dev, 80, 0x05); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); +	rt2800_bbp_write(rt2x00dev, 137, 0x0f); + +	rt2800_bbp_write(rt2x00dev, 84, 0x19); + +	/* Enable DC filter */ +	if (rt2x00_rt_rev_gte(rt2x00dev, RT3593, REV_RT3593E)) +		rt2800_bbp_write(rt2x00dev, 103, 0xc0); +} + +static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) +{ +	int ant, div_mode; +	u16 eeprom; +	u8 value; + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	rt2800_bbp_write(rt2x00dev, 65, 0x2c); +	rt2800_bbp_write(rt2x00dev, 66, 0x38); + +	rt2800_bbp_write(rt2x00dev, 68, 0x0b); -		rt2800_bbp_write(rt2x00dev, 138, value); +	rt2800_bbp_write(rt2x00dev, 69, 0x12); +	rt2800_bbp_write(rt2x00dev, 73, 0x13); +	rt2800_bbp_write(rt2x00dev, 75, 0x46); +	rt2800_bbp_write(rt2x00dev, 76, 0x28); + +	rt2800_bbp_write(rt2x00dev, 77, 0x59); + +	rt2800_bbp_write(rt2x00dev, 70, 0x0a); + +	rt2800_bbp_write(rt2x00dev, 79, 0x13); +	rt2800_bbp_write(rt2x00dev, 80, 0x05); +	rt2800_bbp_write(rt2x00dev, 81, 0x33); + +	rt2800_bbp_write(rt2x00dev, 82, 0x62); + +	rt2800_bbp_write(rt2x00dev, 83, 0x7a); + +	rt2800_bbp_write(rt2x00dev, 84, 0x9a); + +	rt2800_bbp_write(rt2x00dev, 86, 0x38); + +	if (rt2x00_rt(rt2x00dev, RT5392)) +		rt2800_bbp_write(rt2x00dev, 88, 0x90); + +	rt2800_bbp_write(rt2x00dev, 91, 0x04); + +	rt2800_bbp_write(rt2x00dev, 92, 0x02); + +	if (rt2x00_rt(rt2x00dev, RT5392)) { +		rt2800_bbp_write(rt2x00dev, 95, 0x9a); +		rt2800_bbp_write(rt2x00dev, 98, 0x12); +	} + +	rt2800_bbp_write(rt2x00dev, 103, 0xc0); + +	rt2800_bbp_write(rt2x00dev, 104, 0x92); + +	rt2800_bbp_write(rt2x00dev, 105, 0x3c); + +	if (rt2x00_rt(rt2x00dev, RT5390)) +		rt2800_bbp_write(rt2x00dev, 106, 0x03); +	else if (rt2x00_rt(rt2x00dev, RT5392)) +		rt2800_bbp_write(rt2x00dev, 106, 0x12); +	else +		WARN_ON(1); + +	rt2800_bbp_write(rt2x00dev, 128, 0x12); + +	if (rt2x00_rt(rt2x00dev, RT5392)) { +		rt2800_bbp_write(rt2x00dev, 134, 0xd0); +		rt2800_bbp_write(rt2x00dev, 135, 0xf6); +	} + +	rt2800_disable_unused_dac_adc(rt2x00dev); + +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); +	div_mode = rt2x00_get_field16(eeprom, +				      EEPROM_NIC_CONF1_ANT_DIVERSITY); +	ant = (div_mode == 3) ? 1 : 0; + +	/* check if this is a Bluetooth combo card */ +	if (rt2x00_has_cap_bt_coexist(rt2x00dev)) { +		u32 reg; + +		rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); +		rt2x00_set_field32(®, GPIO_CTRL_DIR3, 0); +		rt2x00_set_field32(®, GPIO_CTRL_DIR6, 0); +		rt2x00_set_field32(®, GPIO_CTRL_VAL3, 0); +		rt2x00_set_field32(®, GPIO_CTRL_VAL6, 0); +		if (ant == 0) +			rt2x00_set_field32(®, GPIO_CTRL_VAL3, 1); +		else if (ant == 1) +			rt2x00_set_field32(®, GPIO_CTRL_VAL6, 1); +		rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); +	} + +	/* This chip has hardware antenna diversity*/ +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) { +		rt2800_bbp_write(rt2x00dev, 150, 0); /* Disable Antenna Software OFDM */ +		rt2800_bbp_write(rt2x00dev, 151, 0); /* Disable Antenna Software CCK */ +		rt2800_bbp_write(rt2x00dev, 154, 0); /* Clear previously selected antenna */  	} +	rt2800_bbp_read(rt2x00dev, 152, &value); +	if (ant == 0) +		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1); +	else +		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); +	rt2800_bbp_write(rt2x00dev, 152, value); + +	rt2800_init_freq_calibration(rt2x00dev); +} + +static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) +{ +	int ant, div_mode; +	u16 eeprom; +	u8 value; + +	rt2800_init_bbp_early(rt2x00dev); + +	rt2800_bbp_read(rt2x00dev, 105, &value); +	rt2x00_set_field8(&value, BBP105_MLD, +			  rt2x00dev->default_ant.rx_chain_num == 2); +	rt2800_bbp_write(rt2x00dev, 105, value); + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 20, 0x06); +	rt2800_bbp_write(rt2x00dev, 31, 0x08); +	rt2800_bbp_write(rt2x00dev, 65, 0x2C); +	rt2800_bbp_write(rt2x00dev, 68, 0xDD); +	rt2800_bbp_write(rt2x00dev, 69, 0x1A); +	rt2800_bbp_write(rt2x00dev, 70, 0x05); +	rt2800_bbp_write(rt2x00dev, 73, 0x13); +	rt2800_bbp_write(rt2x00dev, 74, 0x0F); +	rt2800_bbp_write(rt2x00dev, 75, 0x4F); +	rt2800_bbp_write(rt2x00dev, 76, 0x28); +	rt2800_bbp_write(rt2x00dev, 77, 0x59); +	rt2800_bbp_write(rt2x00dev, 84, 0x9A); +	rt2800_bbp_write(rt2x00dev, 86, 0x38); +	rt2800_bbp_write(rt2x00dev, 88, 0x90); +	rt2800_bbp_write(rt2x00dev, 91, 0x04); +	rt2800_bbp_write(rt2x00dev, 92, 0x02); +	rt2800_bbp_write(rt2x00dev, 95, 0x9a); +	rt2800_bbp_write(rt2x00dev, 98, 0x12); +	rt2800_bbp_write(rt2x00dev, 103, 0xC0); +	rt2800_bbp_write(rt2x00dev, 104, 0x92); +	/* FIXME BBP105 owerwrite */ +	rt2800_bbp_write(rt2x00dev, 105, 0x3C); +	rt2800_bbp_write(rt2x00dev, 106, 0x35); +	rt2800_bbp_write(rt2x00dev, 128, 0x12); +	rt2800_bbp_write(rt2x00dev, 134, 0xD0); +	rt2800_bbp_write(rt2x00dev, 135, 0xF6); +	rt2800_bbp_write(rt2x00dev, 137, 0x0F); + +	/* Initialize GLRT (Generalized Likehood Radio Test) */ +	rt2800_init_bbp_5592_glrt(rt2x00dev); + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); +	div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY); +	ant = (div_mode == 3) ? 1 : 0; +	rt2800_bbp_read(rt2x00dev, 152, &value); +	if (ant == 0) { +		/* Main antenna */ +		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1); +	} else { +		/* Auxiliary antenna */ +		rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0); +	} +	rt2800_bbp_write(rt2x00dev, 152, value); + +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) { +		rt2800_bbp_read(rt2x00dev, 254, &value); +		rt2x00_set_field8(&value, BBP254_BIT7, 1); +		rt2800_bbp_write(rt2x00dev, 254, value); +	} + +	rt2800_init_freq_calibration(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 84, 0x19); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) +		rt2800_bbp_write(rt2x00dev, 103, 0xc0); +} + +static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) +{ +	unsigned int i; +	u16 eeprom; +	u8 reg_id; +	u8 value; + +	if (rt2800_is_305x_soc(rt2x00dev)) +		rt2800_init_bbp_305x_soc(rt2x00dev); + +	switch (rt2x00dev->chip.rt) { +	case RT2860: +	case RT2872: +	case RT2883: +		rt2800_init_bbp_28xx(rt2x00dev); +		break; +	case RT3070: +	case RT3071: +	case RT3090: +		rt2800_init_bbp_30xx(rt2x00dev); +		break; +	case RT3290: +		rt2800_init_bbp_3290(rt2x00dev); +		break; +	case RT3352: +		rt2800_init_bbp_3352(rt2x00dev); +		break; +	case RT3390: +		rt2800_init_bbp_3390(rt2x00dev); +		break; +	case RT3572: +		rt2800_init_bbp_3572(rt2x00dev); +		break; +	case RT3593: +		rt2800_init_bbp_3593(rt2x00dev); +		return; +	case RT5390: +	case RT5392: +		rt2800_init_bbp_53xx(rt2x00dev); +		break; +	case RT5592: +		rt2800_init_bbp_5592(rt2x00dev); +		return; +	}  	for (i = 0; i < EEPROM_BBP_SIZE; i++) { -		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); +		rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_BBP_START, i, +					      &eeprom);  		if (eeprom != 0xffff && eeprom != 0x0000) {  			reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); @@ -2395,12 +5681,19 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)  			rt2800_bbp_write(rt2x00dev, reg_id, value);  		}  	} +} -	return 0; +static void rt2800_led_open_drain_enable(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; + +	rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); +	rt2x00_set_field32(®, OPT_14_CSR_BIT0, 1); +	rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);  } -static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, -				bool bw40, u8 rfcsr24, u8 filter_target) +static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev, bool bw40, +				u8 filter_target)  {  	unsigned int i;  	u8 bbp; @@ -2408,6 +5701,7 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,  	u8 passband;  	u8 stopband;  	u8 overtuned = 0; +	u8 rfcsr24 = (bw40) ? 0x27 : 0x07;  	rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24); @@ -2415,6 +5709,10 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);  	rt2800_bbp_write(rt2x00dev, 4, bbp); +	rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR31_RX_H20M, bw40); +	rt2800_rfcsr_write(rt2x00dev, 31, rfcsr); +  	rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);  	rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);  	rt2800_rfcsr_write(rt2x00dev, 22, rfcsr); @@ -2459,167 +5757,47 @@ static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,  	return rfcsr24;  } -static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) +static void rt2800_rf_init_calibration(struct rt2x00_dev *rt2x00dev, +				       const unsigned int rf_reg)  {  	u8 rfcsr; -	u8 bbp; -	u32 reg; -	u16 eeprom; -	if (!rt2x00_rt(rt2x00dev, RT3070) && -	    !rt2x00_rt(rt2x00dev, RT3071) && -	    !rt2x00_rt(rt2x00dev, RT3090) && -	    !rt2x00_rt(rt2x00dev, RT3390) && -	    !rt2800_is_305x_soc(rt2x00dev)) -		return 0; +	rt2800_rfcsr_read(rt2x00dev, rf_reg, &rfcsr); +	rt2x00_set_field8(&rfcsr, FIELD8(0x80), 1); +	rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr); +	msleep(1); +	rt2x00_set_field8(&rfcsr, FIELD8(0x80), 0); +	rt2800_rfcsr_write(rt2x00dev, rf_reg, rfcsr); +} + +static void rt2800_rx_filter_calibration(struct rt2x00_dev *rt2x00dev) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 filter_tgt_bw20; +	u8 filter_tgt_bw40; +	u8 rfcsr, bbp;  	/* -	 * Init RF calibration. +	 * TODO: sync filter_tgt values with vendor driver  	 */ -	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); -	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); -	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); -	msleep(1); -	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); -	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); - -	if (rt2x00_rt(rt2x00dev, RT3070) || -	    rt2x00_rt(rt2x00dev, RT3071) || -	    rt2x00_rt(rt2x00dev, RT3090)) { -		rt2800_rfcsr_write(rt2x00dev, 4, 0x40); -		rt2800_rfcsr_write(rt2x00dev, 5, 0x03); -		rt2800_rfcsr_write(rt2x00dev, 6, 0x02); -		rt2800_rfcsr_write(rt2x00dev, 7, 0x70); -		rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); -		rt2800_rfcsr_write(rt2x00dev, 10, 0x41); -		rt2800_rfcsr_write(rt2x00dev, 11, 0x21); -		rt2800_rfcsr_write(rt2x00dev, 12, 0x7b); -		rt2800_rfcsr_write(rt2x00dev, 14, 0x90); -		rt2800_rfcsr_write(rt2x00dev, 15, 0x58); -		rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); -		rt2800_rfcsr_write(rt2x00dev, 17, 0x92); -		rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); -		rt2800_rfcsr_write(rt2x00dev, 19, 0x02); -		rt2800_rfcsr_write(rt2x00dev, 20, 0xba); -		rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); -		rt2800_rfcsr_write(rt2x00dev, 24, 0x16); -		rt2800_rfcsr_write(rt2x00dev, 25, 0x01); -		rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); -	} else if (rt2x00_rt(rt2x00dev, RT3390)) { -		rt2800_rfcsr_write(rt2x00dev, 0, 0xa0); -		rt2800_rfcsr_write(rt2x00dev, 1, 0xe1); -		rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); -		rt2800_rfcsr_write(rt2x00dev, 3, 0x62); -		rt2800_rfcsr_write(rt2x00dev, 4, 0x40); -		rt2800_rfcsr_write(rt2x00dev, 5, 0x8b); -		rt2800_rfcsr_write(rt2x00dev, 6, 0x42); -		rt2800_rfcsr_write(rt2x00dev, 7, 0x34); -		rt2800_rfcsr_write(rt2x00dev, 8, 0x00); -		rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); -		rt2800_rfcsr_write(rt2x00dev, 10, 0x61); -		rt2800_rfcsr_write(rt2x00dev, 11, 0x21); -		rt2800_rfcsr_write(rt2x00dev, 12, 0x3b); -		rt2800_rfcsr_write(rt2x00dev, 13, 0xe0); -		rt2800_rfcsr_write(rt2x00dev, 14, 0x90); -		rt2800_rfcsr_write(rt2x00dev, 15, 0x53); -		rt2800_rfcsr_write(rt2x00dev, 16, 0xe0); -		rt2800_rfcsr_write(rt2x00dev, 17, 0x94); -		rt2800_rfcsr_write(rt2x00dev, 18, 0x5c); -		rt2800_rfcsr_write(rt2x00dev, 19, 0x4a); -		rt2800_rfcsr_write(rt2x00dev, 20, 0xb2); -		rt2800_rfcsr_write(rt2x00dev, 21, 0xf6); -		rt2800_rfcsr_write(rt2x00dev, 22, 0x00); -		rt2800_rfcsr_write(rt2x00dev, 23, 0x14); -		rt2800_rfcsr_write(rt2x00dev, 24, 0x08); -		rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); -		rt2800_rfcsr_write(rt2x00dev, 26, 0x85); -		rt2800_rfcsr_write(rt2x00dev, 27, 0x00); -		rt2800_rfcsr_write(rt2x00dev, 28, 0x41); -		rt2800_rfcsr_write(rt2x00dev, 29, 0x8f); -		rt2800_rfcsr_write(rt2x00dev, 30, 0x20); -		rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); -	} else if (rt2800_is_305x_soc(rt2x00dev)) { -		rt2800_rfcsr_write(rt2x00dev, 0, 0x50); -		rt2800_rfcsr_write(rt2x00dev, 1, 0x01); -		rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); -		rt2800_rfcsr_write(rt2x00dev, 3, 0x75); -		rt2800_rfcsr_write(rt2x00dev, 4, 0x40); -		rt2800_rfcsr_write(rt2x00dev, 5, 0x03); -		rt2800_rfcsr_write(rt2x00dev, 6, 0x02); -		rt2800_rfcsr_write(rt2x00dev, 7, 0x50); -		rt2800_rfcsr_write(rt2x00dev, 8, 0x39); -		rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); -		rt2800_rfcsr_write(rt2x00dev, 10, 0x60); -		rt2800_rfcsr_write(rt2x00dev, 11, 0x21); -		rt2800_rfcsr_write(rt2x00dev, 12, 0x75); -		rt2800_rfcsr_write(rt2x00dev, 13, 0x75); -		rt2800_rfcsr_write(rt2x00dev, 14, 0x90); -		rt2800_rfcsr_write(rt2x00dev, 15, 0x58); -		rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); -		rt2800_rfcsr_write(rt2x00dev, 17, 0x92); -		rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); -		rt2800_rfcsr_write(rt2x00dev, 19, 0x02); -		rt2800_rfcsr_write(rt2x00dev, 20, 0xba); -		rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); -		rt2800_rfcsr_write(rt2x00dev, 22, 0x00); -		rt2800_rfcsr_write(rt2x00dev, 23, 0x31); -		rt2800_rfcsr_write(rt2x00dev, 24, 0x08); -		rt2800_rfcsr_write(rt2x00dev, 25, 0x01); -		rt2800_rfcsr_write(rt2x00dev, 26, 0x25); -		rt2800_rfcsr_write(rt2x00dev, 27, 0x23); -		rt2800_rfcsr_write(rt2x00dev, 28, 0x13); -		rt2800_rfcsr_write(rt2x00dev, 29, 0x83); -		rt2800_rfcsr_write(rt2x00dev, 30, 0x00); -		rt2800_rfcsr_write(rt2x00dev, 31, 0x00); -		return 0; +	if (rt2x00_rt(rt2x00dev, RT3070)) { +		filter_tgt_bw20 = 0x16; +		filter_tgt_bw40 = 0x19; +	} else { +		filter_tgt_bw20 = 0x13; +		filter_tgt_bw40 = 0x15;  	} -	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { -		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); -		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); -		rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); -		rt2800_register_write(rt2x00dev, LDO_CFG0, reg); -	} else if (rt2x00_rt(rt2x00dev, RT3071) || -		   rt2x00_rt(rt2x00dev, RT3090)) { -		rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); -		rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); -		rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); - -		rt2800_rfcsr_write(rt2x00dev, 31, 0x14); - -		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); -		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); -		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || -		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { -			rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); -			if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST)) -				rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); -			else -				rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); -		} -		rt2800_register_write(rt2x00dev, LDO_CFG0, reg); -	} else if (rt2x00_rt(rt2x00dev, RT3390)) { -		rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); -		rt2x00_set_field32(®, GPIO_SWITCH_5, 0); -		rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); -	} +	drv_data->calibration_bw20 = +		rt2800_init_rx_filter(rt2x00dev, false, filter_tgt_bw20); +	drv_data->calibration_bw40 = +		rt2800_init_rx_filter(rt2x00dev, true, filter_tgt_bw40);  	/* -	 * Set RX Filter calibration for 20MHz and 40MHz +	 * Save BBP 25 & 26 values for later use in channel switching (for 3052)  	 */ -	if (rt2x00_rt(rt2x00dev, RT3070)) { -		rt2x00dev->calibration[0] = -			rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16); -		rt2x00dev->calibration[1] = -			rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19); -	} else if (rt2x00_rt(rt2x00dev, RT3071) || -		   rt2x00_rt(rt2x00dev, RT3090) || -		   rt2x00_rt(rt2x00dev, RT3390)) { -		rt2x00dev->calibration[0] = -			rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x13); -		rt2x00dev->calibration[1] = -			rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15); -	} +	rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25); +	rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26);  	/*  	 * Set back to initial state @@ -2631,52 +5809,62 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  	rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);  	/* -	 * set BBP back to BW20 +	 * Set BBP back to BW20  	 */  	rt2800_bbp_read(rt2x00dev, 4, &bbp);  	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);  	rt2800_bbp_write(rt2x00dev, 4, bbp); +} -	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || -	    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || -	    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || -	    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) -		rt2800_rfcsr_write(rt2x00dev, 27, 0x03); - -	rt2800_register_read(rt2x00dev, OPT_14_CSR, ®); -	rt2x00_set_field32(®, OPT_14_CSR_BIT0, 1); -	rt2800_register_write(rt2x00dev, OPT_14_CSR, reg); +static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 min_gain, rfcsr, bbp; +	u16 eeprom;  	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); +  	rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0); -	if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || +	if (rt2x00_rt(rt2x00dev, RT3070) || +	    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||  	    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||  	    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) +		if (!rt2x00_has_cap_external_lna_bg(rt2x00dev))  			rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);  	} -	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom); -	if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1) + +	min_gain = rt2x00_rt(rt2x00dev, RT3070) ? 1 : 2; +	if (drv_data->txmixer_gain_24g >= min_gain) {  		rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN, -				  rt2x00_get_field16(eeprom, -						   EEPROM_TXMIXER_GAIN_BG_VAL)); +				  drv_data->txmixer_gain_24g); +	} +  	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);  	if (rt2x00_rt(rt2x00dev, RT3090)) { +		/*  Turn off unused DAC1 and ADC1 to reduce power consumption */  		rt2800_bbp_read(rt2x00dev, 138, &bbp); - -		rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); -		if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) +		rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); +		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)  			rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0); -		if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) +		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)  			rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1); -  		rt2800_bbp_write(rt2x00dev, 138, bbp);  	} -	if (rt2x00_rt(rt2x00dev, RT3071) || -	    rt2x00_rt(rt2x00dev, RT3090) || -	    rt2x00_rt(rt2x00dev, RT3390)) { +	if (rt2x00_rt(rt2x00dev, RT3070)) { +		rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr); +		if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) +			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3); +		else +			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0); +		rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0); +		rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0); +		rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0); +		rt2800_rfcsr_write(rt2x00dev, 27, rfcsr); +	} else if (rt2x00_rt(rt2x00dev, RT3071) || +		   rt2x00_rt(rt2x00dev, RT3090) || +		   rt2x00_rt(rt2x00dev, RT3390)) {  		rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);  		rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);  		rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); @@ -2697,21 +5885,803 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field8(&rfcsr, RFCSR21_RX_LO2_EN, 0);  		rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);  	} +} -	if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071)) { -		rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr); -		if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || -		    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E)) -			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3); +static void rt2800_normal_mode_setup_3593(struct rt2x00_dev *rt2x00dev) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u8 rfcsr; +	u8 tx_gain; + +	rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO2_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); +	tx_gain = rt2x00_get_field8(drv_data->txmixer_gain_24g, +				    RFCSR17_TXMIXER_GAIN); +	rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, tx_gain); +	rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 38, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); +	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); +	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + +	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2); +	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + +	/* TODO: enable stream mode */ +} + +static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev) +{ +	u8 reg; +	u16 eeprom; + +	/*  Turn off unused DAC1 and ADC1 to reduce power consumption */ +	rt2800_bbp_read(rt2x00dev, 138, ®); +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) +		rt2x00_set_field8(®, BBP138_RX_ADC1, 0); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) +		rt2x00_set_field8(®, BBP138_TX_DAC1, 1); +	rt2800_bbp_write(rt2x00dev, 138, reg); + +	rt2800_rfcsr_read(rt2x00dev, 38, ®); +	rt2x00_set_field8(®, RFCSR38_RX_LO1_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 38, reg); + +	rt2800_rfcsr_read(rt2x00dev, 39, ®); +	rt2x00_set_field8(®, RFCSR39_RX_LO2_EN, 0); +	rt2800_rfcsr_write(rt2x00dev, 39, reg); + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_rfcsr_read(rt2x00dev, 30, ®); +	rt2x00_set_field8(®, RFCSR30_RX_VCM, 2); +	rt2800_rfcsr_write(rt2x00dev, 30, reg); +} + +static void rt2800_init_rfcsr_305x_soc(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 0, 0x50); +	rt2800_rfcsr_write(rt2x00dev, 1, 0x01); +	rt2800_rfcsr_write(rt2x00dev, 2, 0xf7); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x75); +	rt2800_rfcsr_write(rt2x00dev, 4, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x50); +	rt2800_rfcsr_write(rt2x00dev, 8, 0x39); +	rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x60); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x21); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x75); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x75); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x90); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x58); +	rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); +	rt2800_rfcsr_write(rt2x00dev, 17, 0x92); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 20, 0xba); +	rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x31); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x01); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x25); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x23); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x13); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x83); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x00); +} + +static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev) +{ +	u8 rfcsr; +	u16 eeprom; +	u32 reg; + +	/* XXX vendor driver do this only for 3070 */ +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 4, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x60); +	rt2800_rfcsr_write(rt2x00dev, 9, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x41); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x21); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x7b); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x90); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x58); +	rt2800_rfcsr_write(rt2x00dev, 16, 0xb3); +	rt2800_rfcsr_write(rt2x00dev, 17, 0x92); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x2c); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 20, 0xba); +	rt2800_rfcsr_write(rt2x00dev, 21, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x16); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x1f); + +	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) { +		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +		rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); +		rt2800_register_write(rt2x00dev, LDO_CFG0, reg); +	} else if (rt2x00_rt(rt2x00dev, RT3071) || +		   rt2x00_rt(rt2x00dev, RT3090)) { +		rt2800_rfcsr_write(rt2x00dev, 31, 0x14); + +		rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +		rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); +		rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || +		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { +			rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, +					   &eeprom); +			if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST)) +				rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); +			else +				rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); +		} +		rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + +		rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); +		rt2x00_set_field32(®, GPIO_SWITCH_5, 0); +		rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); +	} + +	rt2800_rx_filter_calibration(rt2x00dev); + +	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) || +	    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || +	    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) +		rt2800_rfcsr_write(rt2x00dev, 27, 0x03); + +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3xxx(rt2x00dev); +} + +static void rt2800_init_rfcsr_3290(struct rt2x00_dev *rt2x00dev) +{ +	u8 rfcsr; + +	rt2800_rf_init_calibration(rt2x00dev, 2); + +	rt2800_rfcsr_write(rt2x00dev, 1, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 2, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 4, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 6, 0xa0); +	rt2800_rfcsr_write(rt2x00dev, 8, 0xf3); +	rt2800_rfcsr_write(rt2x00dev, 9, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x53); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x46); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x83); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x82); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x09); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 32, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 33, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x05); +	rt2800_rfcsr_write(rt2x00dev, 35, 0x12); +	rt2800_rfcsr_write(rt2x00dev, 36, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 38, 0x85); +	rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); +	rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); +	rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); +	rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); +	rt2800_rfcsr_write(rt2x00dev, 43, 0x7b); +	rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); +	rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); +	rt2800_rfcsr_write(rt2x00dev, 46, 0x73); +	rt2800_rfcsr_write(rt2x00dev, 47, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 48, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 49, 0x98); +	rt2800_rfcsr_write(rt2x00dev, 52, 0x38); +	rt2800_rfcsr_write(rt2x00dev, 53, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 54, 0x78); +	rt2800_rfcsr_write(rt2x00dev, 55, 0x43); +	rt2800_rfcsr_write(rt2x00dev, 56, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 57, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); +	rt2800_rfcsr_write(rt2x00dev, 59, 0x09); +	rt2800_rfcsr_write(rt2x00dev, 60, 0x45); +	rt2800_rfcsr_write(rt2x00dev, 61, 0xc1); + +	rt2800_rfcsr_read(rt2x00dev, 29, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR29_RSSI_GAIN, 3); +	rt2800_rfcsr_write(rt2x00dev, 29, rfcsr); + +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3xxx(rt2x00dev); +} + +static void rt2800_init_rfcsr_3352(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 0, 0xf0); +	rt2800_rfcsr_write(rt2x00dev, 1, 0x23); +	rt2800_rfcsr_write(rt2x00dev, 2, 0x50); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x18); +	rt2800_rfcsr_write(rt2x00dev, 4, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x33); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 8, 0xf1); +	rt2800_rfcsr_write(rt2x00dev, 9, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 10, 0xd2); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x42); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x1c); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x5a); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 16, 0x01); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x45); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 20, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 21, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 32, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 33, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x01); +	rt2800_rfcsr_write(rt2x00dev, 35, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 36, 0xbd); +	rt2800_rfcsr_write(rt2x00dev, 37, 0x3c); +	rt2800_rfcsr_write(rt2x00dev, 38, 0x5f); +	rt2800_rfcsr_write(rt2x00dev, 39, 0xc5); +	rt2800_rfcsr_write(rt2x00dev, 40, 0x33); +	rt2800_rfcsr_write(rt2x00dev, 41, 0x5b); +	rt2800_rfcsr_write(rt2x00dev, 42, 0x5b); +	rt2800_rfcsr_write(rt2x00dev, 43, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 44, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 45, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 46, 0xdd); +	rt2800_rfcsr_write(rt2x00dev, 47, 0x0d); +	rt2800_rfcsr_write(rt2x00dev, 48, 0x14); +	rt2800_rfcsr_write(rt2x00dev, 49, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 50, 0x2d); +	rt2800_rfcsr_write(rt2x00dev, 51, 0x7f); +	rt2800_rfcsr_write(rt2x00dev, 52, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 53, 0x52); +	rt2800_rfcsr_write(rt2x00dev, 54, 0x1b); +	rt2800_rfcsr_write(rt2x00dev, 55, 0x7f); +	rt2800_rfcsr_write(rt2x00dev, 56, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 57, 0x52); +	rt2800_rfcsr_write(rt2x00dev, 58, 0x1b); +	rt2800_rfcsr_write(rt2x00dev, 59, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 60, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 61, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 62, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 63, 0x00); + +	rt2800_rx_filter_calibration(rt2x00dev); +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3xxx(rt2x00dev); +} + +static void rt2800_init_rfcsr_3390(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; + +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 0, 0xa0); +	rt2800_rfcsr_write(rt2x00dev, 1, 0xe1); +	rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x62); +	rt2800_rfcsr_write(rt2x00dev, 4, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x8b); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x42); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x34); +	rt2800_rfcsr_write(rt2x00dev, 8, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 9, 0xc0); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x61); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x21); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x3b); +	rt2800_rfcsr_write(rt2x00dev, 13, 0xe0); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x90); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x53); +	rt2800_rfcsr_write(rt2x00dev, 16, 0xe0); +	rt2800_rfcsr_write(rt2x00dev, 17, 0x94); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x5c); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x4a); +	rt2800_rfcsr_write(rt2x00dev, 20, 0xb2); +	rt2800_rfcsr_write(rt2x00dev, 21, 0xf6); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x14); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x3d); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x85); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x41); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x8f); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x0f); + +	rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); +	rt2x00_set_field32(®, GPIO_SWITCH_5, 0); +	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); + +	rt2800_rx_filter_calibration(rt2x00dev); + +	if (rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) +		rt2800_rfcsr_write(rt2x00dev, 27, 0x03); + +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3xxx(rt2x00dev); +} + +static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev) +{ +	u8 rfcsr; +	u32 reg; + +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 0, 0x70); +	rt2800_rfcsr_write(rt2x00dev, 1, 0x81); +	rt2800_rfcsr_write(rt2x00dev, 2, 0xf1); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 4, 0x4c); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x05); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x4a); +	rt2800_rfcsr_write(rt2x00dev, 7, 0xd8); +	rt2800_rfcsr_write(rt2x00dev, 9, 0xc3); +	rt2800_rfcsr_write(rt2x00dev, 10, 0xf1); +	rt2800_rfcsr_write(rt2x00dev, 11, 0xb9); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x70); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x65); +	rt2800_rfcsr_write(rt2x00dev, 14, 0xa0); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x53); +	rt2800_rfcsr_write(rt2x00dev, 16, 0x4c); +	rt2800_rfcsr_write(rt2x00dev, 17, 0x23); +	rt2800_rfcsr_write(rt2x00dev, 18, 0xac); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x93); +	rt2800_rfcsr_write(rt2x00dev, 20, 0xb3); +	rt2800_rfcsr_write(rt2x00dev, 21, 0xd0); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x3c); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x16); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x15); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x85); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x9b); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x09); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x10); + +	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1); +	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + +	rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); +	rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +	rt2800_register_write(rt2x00dev, LDO_CFG0, reg); +	msleep(1); +	rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); +	rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +	rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + +	rt2800_rx_filter_calibration(rt2x00dev); +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3xxx(rt2x00dev); +} + +static void rt3593_post_bbp_init(struct rt2x00_dev *rt2x00dev) +{ +	u8 bbp; +	bool txbf_enabled = false; /* FIXME */ + +	rt2800_bbp_read(rt2x00dev, 105, &bbp); +	if (rt2x00dev->default_ant.rx_chain_num == 1) +		rt2x00_set_field8(&bbp, BBP105_MLD, 0); +	else +		rt2x00_set_field8(&bbp, BBP105_MLD, 1); +	rt2800_bbp_write(rt2x00dev, 105, bbp); + +	rt2800_bbp4_mac_if_ctrl(rt2x00dev); + +	rt2800_bbp_write(rt2x00dev, 92, 0x02); +	rt2800_bbp_write(rt2x00dev, 82, 0x82); +	rt2800_bbp_write(rt2x00dev, 106, 0x05); +	rt2800_bbp_write(rt2x00dev, 104, 0x92); +	rt2800_bbp_write(rt2x00dev, 88, 0x90); +	rt2800_bbp_write(rt2x00dev, 148, 0xc8); +	rt2800_bbp_write(rt2x00dev, 47, 0x48); +	rt2800_bbp_write(rt2x00dev, 120, 0x50); + +	if (txbf_enabled) +		rt2800_bbp_write(rt2x00dev, 163, 0xbd); +	else +		rt2800_bbp_write(rt2x00dev, 163, 0x9d); + +	/* SNR mapping */ +	rt2800_bbp_write(rt2x00dev, 142, 6); +	rt2800_bbp_write(rt2x00dev, 143, 160); +	rt2800_bbp_write(rt2x00dev, 142, 7); +	rt2800_bbp_write(rt2x00dev, 143, 161); +	rt2800_bbp_write(rt2x00dev, 142, 8); +	rt2800_bbp_write(rt2x00dev, 143, 162); + +	/* ADC/DAC control */ +	rt2800_bbp_write(rt2x00dev, 31, 0x08); + +	/* RX AGC energy lower bound in log2 */ +	rt2800_bbp_write(rt2x00dev, 68, 0x0b); + +	/* FIXME: BBP 105 owerwrite? */ +	rt2800_bbp_write(rt2x00dev, 105, 0x04); + +} + +static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u32 reg; +	u8 rfcsr; + +	/* Disable GPIO #4 and #7 function for LAN PE control */ +	rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); +	rt2x00_set_field32(®, GPIO_SWITCH_4, 0); +	rt2x00_set_field32(®, GPIO_SWITCH_7, 0); +	rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); + +	/* Initialize default register values */ +	rt2800_rfcsr_write(rt2x00dev, 1, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 6, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 8, 0xf1); +	rt2800_rfcsr_write(rt2x00dev, 9, 0x02); +	rt2800_rfcsr_write(rt2x00dev, 10, 0xd3); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x4e); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x12); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x40); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 32, 0x78); +	rt2800_rfcsr_write(rt2x00dev, 33, 0x3b); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x3c); +	rt2800_rfcsr_write(rt2x00dev, 35, 0xe0); +	rt2800_rfcsr_write(rt2x00dev, 38, 0x86); +	rt2800_rfcsr_write(rt2x00dev, 39, 0x23); +	rt2800_rfcsr_write(rt2x00dev, 44, 0xd3); +	rt2800_rfcsr_write(rt2x00dev, 45, 0xbb); +	rt2800_rfcsr_write(rt2x00dev, 46, 0x60); +	rt2800_rfcsr_write(rt2x00dev, 49, 0x8e); +	rt2800_rfcsr_write(rt2x00dev, 50, 0x86); +	rt2800_rfcsr_write(rt2x00dev, 51, 0x75); +	rt2800_rfcsr_write(rt2x00dev, 52, 0x45); +	rt2800_rfcsr_write(rt2x00dev, 53, 0x18); +	rt2800_rfcsr_write(rt2x00dev, 54, 0x18); +	rt2800_rfcsr_write(rt2x00dev, 55, 0x18); +	rt2800_rfcsr_write(rt2x00dev, 56, 0xdb); +	rt2800_rfcsr_write(rt2x00dev, 57, 0x6e); + +	/* Initiate calibration */ +	/* TODO: use rt2800_rf_init_calibration ? */ +	rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1); +	rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr); +	rt2x00_set_field8(&rfcsr, RFCSR18_XO_TUNE_BYPASS, 1); +	rt2800_rfcsr_write(rt2x00dev, 18, rfcsr); + +	rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); +	rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); +	rt2800_register_write(rt2x00dev, LDO_CFG0, reg); +	usleep_range(1000, 1500); +	rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +	rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); +	rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + +	/* Set initial values for RX filter calibration */ +	drv_data->calibration_bw20 = 0x1f; +	drv_data->calibration_bw40 = 0x2f; + +	/* Save BBP 25 & 26 values for later use in channel switching */ +	rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25); +	rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26); + +	rt2800_led_open_drain_enable(rt2x00dev); +	rt2800_normal_mode_setup_3593(rt2x00dev); + +	rt3593_post_bbp_init(rt2x00dev); + +	/* TODO: enable stream mode support */ +} + +static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_rf_init_calibration(rt2x00dev, 2); + +	rt2800_rfcsr_write(rt2x00dev, 1, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 2, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x88); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x10); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) +		rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); +	else +		rt2800_rfcsr_write(rt2x00dev, 6, 0xa0); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x53); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x46); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 16, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x00); + +	rt2800_rfcsr_write(rt2x00dev, 20, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 21, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x00); +	if (rt2x00_is_usb(rt2x00dev) && +	    rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) +		rt2800_rfcsr_write(rt2x00dev, 25, 0x80); +	else +		rt2800_rfcsr_write(rt2x00dev, 25, 0xc0); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x09); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x10); + +	rt2800_rfcsr_write(rt2x00dev, 30, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 32, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 33, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x07); +	rt2800_rfcsr_write(rt2x00dev, 35, 0x12); +	rt2800_rfcsr_write(rt2x00dev, 36, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 37, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 38, 0x85); +	rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); + +	rt2800_rfcsr_write(rt2x00dev, 40, 0x0b); +	rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); +	rt2800_rfcsr_write(rt2x00dev, 42, 0xd2); +	rt2800_rfcsr_write(rt2x00dev, 43, 0x9a); +	rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); +	rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) +		rt2800_rfcsr_write(rt2x00dev, 46, 0x73); +	else +		rt2800_rfcsr_write(rt2x00dev, 46, 0x7b); +	rt2800_rfcsr_write(rt2x00dev, 47, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 48, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 49, 0x94); + +	rt2800_rfcsr_write(rt2x00dev, 52, 0x38); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) +		rt2800_rfcsr_write(rt2x00dev, 53, 0x00); +	else +		rt2800_rfcsr_write(rt2x00dev, 53, 0x84); +	rt2800_rfcsr_write(rt2x00dev, 54, 0x78); +	rt2800_rfcsr_write(rt2x00dev, 55, 0x44); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) +		rt2800_rfcsr_write(rt2x00dev, 56, 0x42); +	else +		rt2800_rfcsr_write(rt2x00dev, 56, 0x22); +	rt2800_rfcsr_write(rt2x00dev, 57, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 58, 0x7f); +	rt2800_rfcsr_write(rt2x00dev, 59, 0x8f); + +	rt2800_rfcsr_write(rt2x00dev, 60, 0x45); +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) { +		if (rt2x00_is_usb(rt2x00dev)) +			rt2800_rfcsr_write(rt2x00dev, 61, 0xd1);  		else -			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0); -		rt2x00_set_field8(&rfcsr, RFCSR27_R2, 0); -		rt2x00_set_field8(&rfcsr, RFCSR27_R3, 0); -		rt2x00_set_field8(&rfcsr, RFCSR27_R4, 0); -		rt2800_rfcsr_write(rt2x00dev, 27, rfcsr); +			rt2800_rfcsr_write(rt2x00dev, 61, 0xd5); +	} else { +		if (rt2x00_is_usb(rt2x00dev)) +			rt2800_rfcsr_write(rt2x00dev, 61, 0xdd); +		else +			rt2800_rfcsr_write(rt2x00dev, 61, 0xb5);  	} +	rt2800_rfcsr_write(rt2x00dev, 62, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 63, 0x00); -	return 0; +	rt2800_normal_mode_setup_5xxx(rt2x00dev); + +	rt2800_led_open_drain_enable(rt2x00dev); +} + +static void rt2800_init_rfcsr_5392(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_rf_init_calibration(rt2x00dev, 2); + +	rt2800_rfcsr_write(rt2x00dev, 1, 0x17); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x88); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 6, 0xe0); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 10, 0x53); +	rt2800_rfcsr_write(rt2x00dev, 11, 0x4a); +	rt2800_rfcsr_write(rt2x00dev, 12, 0x46); +	rt2800_rfcsr_write(rt2x00dev, 13, 0x9f); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 16, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x4d); +	rt2800_rfcsr_write(rt2x00dev, 20, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 21, 0x8d); +	rt2800_rfcsr_write(rt2x00dev, 22, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 23, 0x0b); +	rt2800_rfcsr_write(rt2x00dev, 24, 0x44); +	rt2800_rfcsr_write(rt2x00dev, 25, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x82); +	rt2800_rfcsr_write(rt2x00dev, 27, 0x09); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 30, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 31, 0x80); +	rt2800_rfcsr_write(rt2x00dev, 32, 0x20); +	rt2800_rfcsr_write(rt2x00dev, 33, 0xC0); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x07); +	rt2800_rfcsr_write(rt2x00dev, 35, 0x12); +	rt2800_rfcsr_write(rt2x00dev, 36, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 37, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 38, 0x89); +	rt2800_rfcsr_write(rt2x00dev, 39, 0x1b); +	rt2800_rfcsr_write(rt2x00dev, 40, 0x0f); +	rt2800_rfcsr_write(rt2x00dev, 41, 0xbb); +	rt2800_rfcsr_write(rt2x00dev, 42, 0xd5); +	rt2800_rfcsr_write(rt2x00dev, 43, 0x9b); +	rt2800_rfcsr_write(rt2x00dev, 44, 0x0e); +	rt2800_rfcsr_write(rt2x00dev, 45, 0xa2); +	rt2800_rfcsr_write(rt2x00dev, 46, 0x73); +	rt2800_rfcsr_write(rt2x00dev, 47, 0x0c); +	rt2800_rfcsr_write(rt2x00dev, 48, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 49, 0x94); +	rt2800_rfcsr_write(rt2x00dev, 50, 0x94); +	rt2800_rfcsr_write(rt2x00dev, 51, 0x3a); +	rt2800_rfcsr_write(rt2x00dev, 52, 0x48); +	rt2800_rfcsr_write(rt2x00dev, 53, 0x44); +	rt2800_rfcsr_write(rt2x00dev, 54, 0x38); +	rt2800_rfcsr_write(rt2x00dev, 55, 0x43); +	rt2800_rfcsr_write(rt2x00dev, 56, 0xa1); +	rt2800_rfcsr_write(rt2x00dev, 57, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 58, 0x39); +	rt2800_rfcsr_write(rt2x00dev, 59, 0x07); +	rt2800_rfcsr_write(rt2x00dev, 60, 0x45); +	rt2800_rfcsr_write(rt2x00dev, 61, 0x91); +	rt2800_rfcsr_write(rt2x00dev, 62, 0x39); +	rt2800_rfcsr_write(rt2x00dev, 63, 0x07); + +	rt2800_normal_mode_setup_5xxx(rt2x00dev); + +	rt2800_led_open_drain_enable(rt2x00dev); +} + +static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_rf_init_calibration(rt2x00dev, 30); + +	rt2800_rfcsr_write(rt2x00dev, 1, 0x3F); +	rt2800_rfcsr_write(rt2x00dev, 3, 0x08); +	rt2800_rfcsr_write(rt2x00dev, 5, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 6, 0xE4); +	rt2800_rfcsr_write(rt2x00dev, 7, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 14, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 15, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 16, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 18, 0x03); +	rt2800_rfcsr_write(rt2x00dev, 19, 0x4D); +	rt2800_rfcsr_write(rt2x00dev, 20, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 21, 0x8D); +	rt2800_rfcsr_write(rt2x00dev, 26, 0x82); +	rt2800_rfcsr_write(rt2x00dev, 28, 0x00); +	rt2800_rfcsr_write(rt2x00dev, 29, 0x10); +	rt2800_rfcsr_write(rt2x00dev, 33, 0xC0); +	rt2800_rfcsr_write(rt2x00dev, 34, 0x07); +	rt2800_rfcsr_write(rt2x00dev, 35, 0x12); +	rt2800_rfcsr_write(rt2x00dev, 47, 0x0C); +	rt2800_rfcsr_write(rt2x00dev, 53, 0x22); +	rt2800_rfcsr_write(rt2x00dev, 63, 0x07); + +	rt2800_rfcsr_write(rt2x00dev, 2, 0x80); +	msleep(1); + +	rt2800_adjust_freq_offset(rt2x00dev); + +	/* Enable DC filter */ +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) +		rt2800_bbp_write(rt2x00dev, 103, 0xc0); + +	rt2800_normal_mode_setup_5xxx(rt2x00dev); + +	if (rt2x00_rt_rev_lt(rt2x00dev, RT5592, REV_RT5592C)) +		rt2800_rfcsr_write(rt2x00dev, 27, 0x03); + +	rt2800_led_open_drain_enable(rt2x00dev); +} + +static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) +{ +	if (rt2800_is_305x_soc(rt2x00dev)) { +		rt2800_init_rfcsr_305x_soc(rt2x00dev); +		return; +	} + +	switch (rt2x00dev->chip.rt) { +	case RT3070: +	case RT3071: +	case RT3090: +		rt2800_init_rfcsr_30xx(rt2x00dev); +		break; +	case RT3290: +		rt2800_init_rfcsr_3290(rt2x00dev); +		break; +	case RT3352: +		rt2800_init_rfcsr_3352(rt2x00dev); +		break; +	case RT3390: +		rt2800_init_rfcsr_3390(rt2x00dev); +		break; +	case RT3572: +		rt2800_init_rfcsr_3572(rt2x00dev); +		break; +	case RT3593: +		rt2800_init_rfcsr_3593(rt2x00dev); +		break; +	case RT5390: +		rt2800_init_rfcsr_5390(rt2x00dev); +		break; +	case RT5392: +		rt2800_init_rfcsr_5392(rt2x00dev); +		break; +	case RT5592: +		rt2800_init_rfcsr_5592(rt2x00dev); +		break; +	}  }  int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) @@ -2720,18 +6690,39 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)  	u16 word;  	/* -	 * Initialize all registers. +	 * Initialize MAC registers.  	 */  	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || -		     rt2800_init_registers(rt2x00dev) || -		     rt2800_init_bbp(rt2x00dev) || -		     rt2800_init_rfcsr(rt2x00dev))) +		     rt2800_init_registers(rt2x00dev))) +		return -EIO; + +	/* +	 * Wait BBP/RF to wake up. +	 */ +	if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev)))  		return -EIO;  	/* -	 * Send signal to firmware during boot time. +	 * Send signal during boot time to initialize firmware.  	 */ +	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); +	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +	if (rt2x00_is_usb(rt2x00dev)) +		rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0);  	rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); +	msleep(1); + +	/* +	 * Make sure BBP is up and running. +	 */ +	if (unlikely(rt2800_wait_bbp_ready(rt2x00dev))) +		return -EIO; + +	/* +	 * Initialize BBP/RF registers. +	 */ +	rt2800_init_bbp(rt2x00dev); +	rt2800_init_rfcsr(rt2x00dev);  	if (rt2x00_is_usb(rt2x00dev) &&  	    (rt2x00_rt(rt2x00dev, RT3070) || @@ -2767,16 +6758,16 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)  	/*  	 * Initialize LED control  	 */ -	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); -	rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff, +	rt2800_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word); +	rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff,  			   word & 0xff, (word >> 8) & 0xff); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); -	rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff, +	rt2800_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word); +	rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff,  			   word & 0xff, (word >> 8) & 0xff); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); -	rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff, +	rt2800_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word); +	rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff,  			   word & 0xff, (word >> 8) & 0xff);  	return 0; @@ -2787,13 +6778,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; -	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); -	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); +	rt2800_disable_wpdma(rt2x00dev);  	/* Wait for DMA, ignore error */  	rt2800_wait_wpdma_ready(rt2x00dev); @@ -2802,18 +6787,20 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)  	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 0);  	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0);  	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - -	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0); -	rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);  }  EXPORT_SYMBOL_GPL(rt2800_disable_radio);  int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; +	u16 efuse_ctrl_reg; -	rt2800_register_read(rt2x00dev, EFUSE_CTRL, ®); +	if (rt2x00_rt(rt2x00dev, RT3290)) +		efuse_ctrl_reg = EFUSE_CTRL_3290; +	else +		efuse_ctrl_reg = EFUSE_CTRL; +	rt2800_register_read(rt2x00dev, efuse_ctrl_reg, ®);  	return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);  }  EXPORT_SYMBOL_GPL(rt2800_efuse_detect); @@ -2821,105 +6808,165 @@ EXPORT_SYMBOL_GPL(rt2800_efuse_detect);  static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)  {  	u32 reg; - +	u16 efuse_ctrl_reg; +	u16 efuse_data0_reg; +	u16 efuse_data1_reg; +	u16 efuse_data2_reg; +	u16 efuse_data3_reg; + +	if (rt2x00_rt(rt2x00dev, RT3290)) { +		efuse_ctrl_reg = EFUSE_CTRL_3290; +		efuse_data0_reg = EFUSE_DATA0_3290; +		efuse_data1_reg = EFUSE_DATA1_3290; +		efuse_data2_reg = EFUSE_DATA2_3290; +		efuse_data3_reg = EFUSE_DATA3_3290; +	} else { +		efuse_ctrl_reg = EFUSE_CTRL; +		efuse_data0_reg = EFUSE_DATA0; +		efuse_data1_reg = EFUSE_DATA1; +		efuse_data2_reg = EFUSE_DATA2; +		efuse_data3_reg = EFUSE_DATA3; +	}  	mutex_lock(&rt2x00dev->csr_mutex); -	rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, ®); +	rt2800_register_read_lock(rt2x00dev, efuse_ctrl_reg, ®);  	rt2x00_set_field32(®, EFUSE_CTRL_ADDRESS_IN, i);  	rt2x00_set_field32(®, EFUSE_CTRL_MODE, 0);  	rt2x00_set_field32(®, EFUSE_CTRL_KICK, 1); -	rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg); +	rt2800_register_write_lock(rt2x00dev, efuse_ctrl_reg, reg);  	/* Wait until the EEPROM has been loaded */ -	rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, ®); - +	rt2800_regbusy_read(rt2x00dev, efuse_ctrl_reg, EFUSE_CTRL_KICK, ®);  	/* Apparently the data is read from end to start */ -	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, -					(u32 *)&rt2x00dev->eeprom[i]); -	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, -					(u32 *)&rt2x00dev->eeprom[i + 2]); -	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, -					(u32 *)&rt2x00dev->eeprom[i + 4]); -	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0, -					(u32 *)&rt2x00dev->eeprom[i + 6]); +	rt2800_register_read_lock(rt2x00dev, efuse_data3_reg, ®); +	/* The returned value is in CPU order, but eeprom is le */ +	*(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg); +	rt2800_register_read_lock(rt2x00dev, efuse_data2_reg, ®); +	*(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg); +	rt2800_register_read_lock(rt2x00dev, efuse_data1_reg, ®); +	*(u32 *)&rt2x00dev->eeprom[i + 4] = cpu_to_le32(reg); +	rt2800_register_read_lock(rt2x00dev, efuse_data0_reg, ®); +	*(u32 *)&rt2x00dev->eeprom[i + 6] = cpu_to_le32(reg);  	mutex_unlock(&rt2x00dev->csr_mutex);  } -void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) +int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)  {  	unsigned int i;  	for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8)  		rt2800_efuse_read(rt2x00dev, i); + +	return 0;  }  EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse); -int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) +static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev)  {  	u16 word; + +	if (rt2x00_rt(rt2x00dev, RT3593)) +		return 0; + +	rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); +	if ((word & 0x00ff) != 0x00ff) +		return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL); + +	return 0; +} + +static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev) +{ +	u16 word; + +	if (rt2x00_rt(rt2x00dev, RT3593)) +		return 0; + +	rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); +	if ((word & 0x00ff) != 0x00ff) +		return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL); + +	return 0; +} + +static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) +{ +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u16 word;  	u8 *mac;  	u8 default_lna_gain; +	int retval; + +	/* +	 * Read the EEPROM. +	 */ +	retval = rt2800_read_eeprom(rt2x00dev); +	if (retval) +		return retval;  	/*  	 * Start validation of the data that has been read.  	 */ -	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); +	mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);  	if (!is_valid_ether_addr(mac)) { -		random_ether_addr(mac); -		EEPROM(rt2x00dev, "MAC: %pM\n", mac); +		eth_random_addr(mac); +		rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);  	} -	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);  	if (word == 0xffff) { -		rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); -		rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1); -		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); -		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820); +		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); +		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);  	} else if (rt2x00_rt(rt2x00dev, RT2860) ||  		   rt2x00_rt(rt2x00dev, RT2872)) {  		/*  		 * There is a max of 2 RX streams for RT28x0 series  		 */ -		if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2) -			rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); +		if (rt2x00_get_field16(word, EEPROM_NIC_CONF0_RXPATH) > 2) +			rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); +		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);  	} -	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word);  	if (word == 0xffff) { -		rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_ANT_DIVERSITY, 0); -		rt2x00_set_field16(&word, EEPROM_NIC_DAC_TEST, 0); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); -		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); -	} - -	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_CARDBUS_ACCEL, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_2G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_5G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_WPS_PBC, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_2G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_5G, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BROADBAND_EXT_LNA, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_ANT_DIVERSITY, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_INTERNAL_TX_ALC, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0); +		rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0); +		rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word); +		rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word); +	} + +	rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);  	if ((word & 0x00ff) == 0x00ff) {  		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); -		EEPROM(rt2x00dev, "Freq: 0x%04x\n", word); +		rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word); +		rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);  	}  	if ((word & 0xff00) == 0xff00) {  		rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,  				   LED_MODE_TXRX_ACTIVITY);  		rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221); -		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8); -		EEPROM(rt2x00dev, "Led Mode: 0x%04x\n", word); +		rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word); +		rt2800_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555); +		rt2800_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221); +		rt2800_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8); +		rt2x00_eeprom_dbg(rt2x00dev, "Led Mode: 0x%04x\n", word);  	}  	/* @@ -2927,127 +6974,181 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)  	 * lna0 as correct value. Note that EEPROM_LNA  	 * is never validated.  	 */ -	rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word); +	rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &word);  	default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word); +	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); -	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); +	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); +	drv_data->txmixer_gain_24g = rt2800_get_txmixer_gain_24g(rt2x00dev); + +	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); -	if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || -	    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) -		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, -				   default_lna_gain); -	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); +	if (!rt2x00_rt(rt2x00dev, RT3593)) { +		if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || +		    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) +			rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, +					   default_lna_gain); +	} +	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); +	drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev); + +	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0); -	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); +	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); +	rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);  	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)  		rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); -	if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || -	    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) -		rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, -				   default_lna_gain); -	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); - -	rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &word); -	if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_24GHZ) == 0xff) -		rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_24GHZ, MAX_G_TXPOWER); -	if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_5GHZ) == 0xff) -		rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_5GHZ, MAX_A_TXPOWER); -	rt2x00_eeprom_write(rt2x00dev, EEPROM_MAX_TX_POWER, word); +	if (!rt2x00_rt(rt2x00dev, RT3593)) { +		if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || +		    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) +			rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, +					   default_lna_gain); +	} +	rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); + +	if (rt2x00_rt(rt2x00dev, RT3593)) { +		rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &word); +		if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 || +		    rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff) +			rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1, +					   default_lna_gain); +		if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0x00 || +		    rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0xff) +			rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1, +					   default_lna_gain); +		rt2800_eeprom_write(rt2x00dev, EEPROM_EXT_LNA2, word); +	}  	return 0;  } -EXPORT_SYMBOL_GPL(rt2800_validate_eeprom); -int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)  { -	u32 reg;  	u16 value;  	u16 eeprom; +	u16 rf;  	/*  	 * Read EEPROM word for configuration.  	 */ -	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);  	/* -	 * Identify RF chipset. +	 * Identify RF chipset by EEPROM value +	 * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field +	 * RT53xx: defined in "EEPROM_CHIP_ID" field  	 */ -	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); -	rt2800_register_read(rt2x00dev, MAC_CSR0, ®); - -	rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET), -			value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); - -	if (!rt2x00_rt(rt2x00dev, RT2860) && -	    !rt2x00_rt(rt2x00dev, RT2872) && -	    !rt2x00_rt(rt2x00dev, RT2883) && -	    !rt2x00_rt(rt2x00dev, RT3070) && -	    !rt2x00_rt(rt2x00dev, RT3071) && -	    !rt2x00_rt(rt2x00dev, RT3090) && -	    !rt2x00_rt(rt2x00dev, RT3390) && -	    !rt2x00_rt(rt2x00dev, RT3572)) { -		ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); +	if (rt2x00_rt(rt2x00dev, RT3290) || +	    rt2x00_rt(rt2x00dev, RT5390) || +	    rt2x00_rt(rt2x00dev, RT5392)) +		rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); +	else +		rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); + +	switch (rf) { +	case RF2820: +	case RF2850: +	case RF2720: +	case RF2750: +	case RF3020: +	case RF2020: +	case RF3021: +	case RF3022: +	case RF3052: +	case RF3053: +	case RF3070: +	case RF3290: +	case RF3320: +	case RF3322: +	case RF5360: +	case RF5370: +	case RF5372: +	case RF5390: +	case RF5392: +	case RF5592: +		break; +	default: +		rt2x00_err(rt2x00dev, "Invalid RF chipset 0x%04x detected\n", +			   rf);  		return -ENODEV;  	} -	if (!rt2x00_rf(rt2x00dev, RF2820) && -	    !rt2x00_rf(rt2x00dev, RF2850) && -	    !rt2x00_rf(rt2x00dev, RF2720) && -	    !rt2x00_rf(rt2x00dev, RF2750) && -	    !rt2x00_rf(rt2x00dev, RF3020) && -	    !rt2x00_rf(rt2x00dev, RF2020) && -	    !rt2x00_rf(rt2x00dev, RF3021) && -	    !rt2x00_rf(rt2x00dev, RF3022) && -	    !rt2x00_rf(rt2x00dev, RF3052) && -	    !rt2x00_rf(rt2x00dev, RF3320)) { -		ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); -		return -ENODEV; -	} +	rt2x00_set_rf(rt2x00dev, rf);  	/*  	 * Identify default antenna configuration.  	 */ -	rt2x00dev->default_ant.tx = -	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH); -	rt2x00dev->default_ant.rx = -	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH); +	rt2x00dev->default_ant.tx_chain_num = +	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH); +	rt2x00dev->default_ant.rx_chain_num = +	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH); + +	rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + +	if (rt2x00_rt(rt2x00dev, RT3070) || +	    rt2x00_rt(rt2x00dev, RT3090) || +	    rt2x00_rt(rt2x00dev, RT3352) || +	    rt2x00_rt(rt2x00dev, RT3390)) { +		value = rt2x00_get_field16(eeprom, +				EEPROM_NIC_CONF1_ANT_DIVERSITY); +		switch (value) { +		case 0: +		case 1: +		case 2: +			rt2x00dev->default_ant.tx = ANTENNA_A; +			rt2x00dev->default_ant.rx = ANTENNA_A; +			break; +		case 3: +			rt2x00dev->default_ant.tx = ANTENNA_A; +			rt2x00dev->default_ant.rx = ANTENNA_B; +			break; +		} +	} else { +		rt2x00dev->default_ant.tx = ANTENNA_A; +		rt2x00dev->default_ant.rx = ANTENNA_A; +	} + +	if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390R)) { +		rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY; /* Unused */ +		rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY; /* Unused */ +	}  	/* -	 * Read frequency offset and RF programming sequence. +	 * Determine external LNA informations.  	 */ -	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); -	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G)) +		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G)) +		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);  	/* -	 * Read external LNA informations. +	 * Detect if this device has an hardware controlled radio.  	 */ -	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO)) +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags); -	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) -		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); -	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) -		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); +	/* +	 * Detect if this device has Bluetooth co-existence. +	 */ +	if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) +		__set_bit(CAPABILITY_BT_COEXIST, &rt2x00dev->cap_flags);  	/* -	 * Detect if this device has an hardware controlled radio. +	 * Read frequency offset and RF programming sequence.  	 */ -	if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +	rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); +	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);  	/*  	 * Store led settings, for correct led behaviour. @@ -3057,12 +7158,20 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)  	rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);  	rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); -	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg); +	rt2x00dev->led_mcu_reg = eeprom;  #endif /* CONFIG_RT2X00_LIB_LEDS */ +	/* +	 * Check if support EIRP tx power limit feature. +	 */ +	rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom); + +	if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) < +					EIRP_MAX_TX_POWER_LIMIT) +		__set_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags); +  	return 0;  } -EXPORT_SYMBOL_GPL(rt2800_init_eeprom);  /*   * RF value list for rt28xx @@ -3141,7 +7250,7 @@ static const struct rf_channel rf_vals[] = {  /*   * RF value list for rt3xxx - * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052) + * Supports: 2.4 GHz (all) & 5.2 GHz (RF3052 & RF3053)   */  static const struct rf_channel rf_vals_3x[] = {  	{1,  241, 2, 2 }, @@ -3205,21 +7314,152 @@ static const struct rf_channel rf_vals_3x[] = {  	{173, 0x61, 0, 9},  }; -int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) +static const struct rf_channel rf_vals_5592_xtal20[] = { +	/* Channel, N, K, mod, R */ +	{1, 482, 4, 10, 3}, +	{2, 483, 4, 10, 3}, +	{3, 484, 4, 10, 3}, +	{4, 485, 4, 10, 3}, +	{5, 486, 4, 10, 3}, +	{6, 487, 4, 10, 3}, +	{7, 488, 4, 10, 3}, +	{8, 489, 4, 10, 3}, +	{9, 490, 4, 10, 3}, +	{10, 491, 4, 10, 3}, +	{11, 492, 4, 10, 3}, +	{12, 493, 4, 10, 3}, +	{13, 494, 4, 10, 3}, +	{14, 496, 8, 10, 3}, +	{36, 172, 8, 12, 1}, +	{38, 173, 0, 12, 1}, +	{40, 173, 4, 12, 1}, +	{42, 173, 8, 12, 1}, +	{44, 174, 0, 12, 1}, +	{46, 174, 4, 12, 1}, +	{48, 174, 8, 12, 1}, +	{50, 175, 0, 12, 1}, +	{52, 175, 4, 12, 1}, +	{54, 175, 8, 12, 1}, +	{56, 176, 0, 12, 1}, +	{58, 176, 4, 12, 1}, +	{60, 176, 8, 12, 1}, +	{62, 177, 0, 12, 1}, +	{64, 177, 4, 12, 1}, +	{100, 183, 4, 12, 1}, +	{102, 183, 8, 12, 1}, +	{104, 184, 0, 12, 1}, +	{106, 184, 4, 12, 1}, +	{108, 184, 8, 12, 1}, +	{110, 185, 0, 12, 1}, +	{112, 185, 4, 12, 1}, +	{114, 185, 8, 12, 1}, +	{116, 186, 0, 12, 1}, +	{118, 186, 4, 12, 1}, +	{120, 186, 8, 12, 1}, +	{122, 187, 0, 12, 1}, +	{124, 187, 4, 12, 1}, +	{126, 187, 8, 12, 1}, +	{128, 188, 0, 12, 1}, +	{130, 188, 4, 12, 1}, +	{132, 188, 8, 12, 1}, +	{134, 189, 0, 12, 1}, +	{136, 189, 4, 12, 1}, +	{138, 189, 8, 12, 1}, +	{140, 190, 0, 12, 1}, +	{149, 191, 6, 12, 1}, +	{151, 191, 10, 12, 1}, +	{153, 192, 2, 12, 1}, +	{155, 192, 6, 12, 1}, +	{157, 192, 10, 12, 1}, +	{159, 193, 2, 12, 1}, +	{161, 193, 6, 12, 1}, +	{165, 194, 2, 12, 1}, +	{184, 164, 0, 12, 1}, +	{188, 164, 4, 12, 1}, +	{192, 165, 8, 12, 1}, +	{196, 166, 0, 12, 1}, +}; + +static const struct rf_channel rf_vals_5592_xtal40[] = { +	/* Channel, N, K, mod, R */ +	{1, 241, 2, 10, 3}, +	{2, 241, 7, 10, 3}, +	{3, 242, 2, 10, 3}, +	{4, 242, 7, 10, 3}, +	{5, 243, 2, 10, 3}, +	{6, 243, 7, 10, 3}, +	{7, 244, 2, 10, 3}, +	{8, 244, 7, 10, 3}, +	{9, 245, 2, 10, 3}, +	{10, 245, 7, 10, 3}, +	{11, 246, 2, 10, 3}, +	{12, 246, 7, 10, 3}, +	{13, 247, 2, 10, 3}, +	{14, 248, 4, 10, 3}, +	{36, 86, 4, 12, 1}, +	{38, 86, 6, 12, 1}, +	{40, 86, 8, 12, 1}, +	{42, 86, 10, 12, 1}, +	{44, 87, 0, 12, 1}, +	{46, 87, 2, 12, 1}, +	{48, 87, 4, 12, 1}, +	{50, 87, 6, 12, 1}, +	{52, 87, 8, 12, 1}, +	{54, 87, 10, 12, 1}, +	{56, 88, 0, 12, 1}, +	{58, 88, 2, 12, 1}, +	{60, 88, 4, 12, 1}, +	{62, 88, 6, 12, 1}, +	{64, 88, 8, 12, 1}, +	{100, 91, 8, 12, 1}, +	{102, 91, 10, 12, 1}, +	{104, 92, 0, 12, 1}, +	{106, 92, 2, 12, 1}, +	{108, 92, 4, 12, 1}, +	{110, 92, 6, 12, 1}, +	{112, 92, 8, 12, 1}, +	{114, 92, 10, 12, 1}, +	{116, 93, 0, 12, 1}, +	{118, 93, 2, 12, 1}, +	{120, 93, 4, 12, 1}, +	{122, 93, 6, 12, 1}, +	{124, 93, 8, 12, 1}, +	{126, 93, 10, 12, 1}, +	{128, 94, 0, 12, 1}, +	{130, 94, 2, 12, 1}, +	{132, 94, 4, 12, 1}, +	{134, 94, 6, 12, 1}, +	{136, 94, 8, 12, 1}, +	{138, 94, 10, 12, 1}, +	{140, 95, 0, 12, 1}, +	{149, 95, 9, 12, 1}, +	{151, 95, 11, 12, 1}, +	{153, 96, 1, 12, 1}, +	{155, 96, 3, 12, 1}, +	{157, 96, 5, 12, 1}, +	{159, 96, 7, 12, 1}, +	{161, 96, 9, 12, 1}, +	{165, 97, 1, 12, 1}, +	{184, 82, 0, 12, 1}, +	{188, 82, 4, 12, 1}, +	{192, 82, 8, 12, 1}, +	{196, 83, 0, 12, 1}, +}; + +static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  {  	struct hw_mode_spec *spec = &rt2x00dev->spec;  	struct channel_info *info;  	char *default_power1;  	char *default_power2; +	char *default_power3;  	unsigned int i; -	unsigned short max_power; -	u16 eeprom; +	u32 reg;  	/* -	 * Disable powersaving as default on PCI devices. +	 * Disable powersaving as default.  	 */ -	if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) -		rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; +	rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;  	/*  	 * Initialize all hw fields. @@ -3228,7 +7468,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	    IEEE80211_HW_SIGNAL_DBM |  	    IEEE80211_HW_SUPPORTS_PS |  	    IEEE80211_HW_PS_NULLFUNC_STACK | -	    IEEE80211_HW_AMPDU_AGGREGATION; +	    IEEE80211_HW_AMPDU_AGGREGATION | +	    IEEE80211_HW_REPORTS_TX_ACK_STATUS | +	    IEEE80211_HW_SUPPORTS_HT_CCK_RATES; +  	/*  	 * Don't set IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING for USB devices  	 * unless we are capable of sending the buffered frames out after the @@ -3242,7 +7485,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);  	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, -				rt2x00_eeprom_addr(rt2x00dev, +				rt2800_eeprom_addr(rt2x00dev,  						   EEPROM_MAC_ADDR_0));  	/* @@ -3258,36 +7501,66 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	rt2x00dev->hw->max_report_rates = 7;  	rt2x00dev->hw->max_rate_tries = 1; -	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); -  	/*  	 * Initialize hw_mode information.  	 */ -	spec->supported_bands = SUPPORT_BAND_2GHZ;  	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; -	if (rt2x00_rf(rt2x00dev, RF2820) || -	    rt2x00_rf(rt2x00dev, RF2720)) { +	switch (rt2x00dev->chip.rf) { +	case RF2720: +	case RF2820:  		spec->num_channels = 14;  		spec->channels = rf_vals; -	} else if (rt2x00_rf(rt2x00dev, RF2850) || -		   rt2x00_rf(rt2x00dev, RF2750)) { -		spec->supported_bands |= SUPPORT_BAND_5GHZ; +		break; + +	case RF2750: +	case RF2850:  		spec->num_channels = ARRAY_SIZE(rf_vals);  		spec->channels = rf_vals; -	} else if (rt2x00_rf(rt2x00dev, RF3020) || -		   rt2x00_rf(rt2x00dev, RF2020) || -		   rt2x00_rf(rt2x00dev, RF3021) || -		   rt2x00_rf(rt2x00dev, RF3022) || -		   rt2x00_rf(rt2x00dev, RF3320)) { +		break; + +	case RF2020: +	case RF3020: +	case RF3021: +	case RF3022: +	case RF3070: +	case RF3290: +	case RF3320: +	case RF3322: +	case RF5360: +	case RF5370: +	case RF5372: +	case RF5390: +	case RF5392:  		spec->num_channels = 14;  		spec->channels = rf_vals_3x; -	} else if (rt2x00_rf(rt2x00dev, RF3052)) { -		spec->supported_bands |= SUPPORT_BAND_5GHZ; +		break; + +	case RF3052: +	case RF3053:  		spec->num_channels = ARRAY_SIZE(rf_vals_3x);  		spec->channels = rf_vals_3x; +		break; + +	case RF5592: +		rt2800_register_read(rt2x00dev, MAC_DEBUG_INDEX, ®); +		if (rt2x00_get_field32(reg, MAC_DEBUG_INDEX_XTAL)) { +			spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal40); +			spec->channels = rf_vals_5592_xtal40; +		} else { +			spec->num_channels = ARRAY_SIZE(rf_vals_5592_xtal20); +			spec->channels = rf_vals_5592_xtal20; +		} +		break;  	} +	if (WARN_ON_ONCE(!spec->channels)) +		return -ENODEV; + +	spec->supported_bands = SUPPORT_BAND_2GHZ; +	if (spec->num_channels > 14) +		spec->supported_bands |= SUPPORT_BAND_5GHZ; +  	/*  	 * Initialize HT information.  	 */ @@ -3302,22 +7575,21 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	    IEEE80211_HT_CAP_SGI_20 |  	    IEEE80211_HT_CAP_SGI_40; -	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) >= 2) +	if (rt2x00dev->default_ant.tx_chain_num >= 2)  		spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC; -	spec->ht.cap |= -	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) << -		IEEE80211_HT_CAP_RX_STBC_SHIFT; +	spec->ht.cap |= rt2x00dev->default_ant.rx_chain_num << +			IEEE80211_HT_CAP_RX_STBC_SHIFT;  	spec->ht.ampdu_factor = 3;  	spec->ht.ampdu_density = 4;  	spec->ht.mcs.tx_params =  	    IEEE80211_HT_MCS_TX_DEFINED |  	    IEEE80211_HT_MCS_TX_RX_DIFF | -	    ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) << -		IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); +	    ((rt2x00dev->default_ant.tx_chain_num - 1) << +	     IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); -	switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { +	switch (rt2x00dev->default_ant.rx_chain_num) {  	case 3:  		spec->ht.mcs.rx_mask[2] = 0xff;  	case 2: @@ -3337,32 +7609,175 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	spec->channels_info = info; -	rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &eeprom); -	max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_24GHZ); -	default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); -	default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); +	default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); +	default_power2 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); + +	if (rt2x00dev->default_ant.tx_chain_num > 2) +		default_power3 = rt2800_eeprom_addr(rt2x00dev, +						    EEPROM_EXT_TXPOWER_BG3); +	else +		default_power3 = NULL;  	for (i = 0; i < 14; i++) { -		info[i].max_power = max_power; -		info[i].default_power1 = TXPOWER_G_FROM_DEV(default_power1[i]); -		info[i].default_power2 = TXPOWER_G_FROM_DEV(default_power2[i]); +		info[i].default_power1 = default_power1[i]; +		info[i].default_power2 = default_power2[i]; +		if (default_power3) +			info[i].default_power3 = default_power3[i];  	}  	if (spec->num_channels > 14) { -		max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_5GHZ); -		default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); -		default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); +		default_power1 = rt2800_eeprom_addr(rt2x00dev, +						    EEPROM_TXPOWER_A1); +		default_power2 = rt2800_eeprom_addr(rt2x00dev, +						    EEPROM_TXPOWER_A2); + +		if (rt2x00dev->default_ant.tx_chain_num > 2) +			default_power3 = +				rt2800_eeprom_addr(rt2x00dev, +						   EEPROM_EXT_TXPOWER_A3); +		else +			default_power3 = NULL;  		for (i = 14; i < spec->num_channels; i++) { -			info[i].max_power = max_power; -			info[i].default_power1 = TXPOWER_A_FROM_DEV(default_power1[i]); -			info[i].default_power2 = TXPOWER_A_FROM_DEV(default_power2[i]); +			info[i].default_power1 = default_power1[i - 14]; +			info[i].default_power2 = default_power2[i - 14]; +			if (default_power3) +				info[i].default_power3 = default_power3[i - 14];  		}  	} +	switch (rt2x00dev->chip.rf) { +	case RF2020: +	case RF3020: +	case RF3021: +	case RF3022: +	case RF3320: +	case RF3052: +	case RF3053: +	case RF3070: +	case RF3290: +	case RF5360: +	case RF5370: +	case RF5372: +	case RF5390: +	case RF5392: +		__set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags); +		break; +	} + +	return 0; +} + +static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; +	u32 rt; +	u32 rev; + +	if (rt2x00_rt(rt2x00dev, RT3290)) +		rt2800_register_read(rt2x00dev, MAC_CSR0_3290, ®); +	else +		rt2800_register_read(rt2x00dev, MAC_CSR0, ®); + +	rt = rt2x00_get_field32(reg, MAC_CSR0_CHIPSET); +	rev = rt2x00_get_field32(reg, MAC_CSR0_REVISION); + +	switch (rt) { +	case RT2860: +	case RT2872: +	case RT2883: +	case RT3070: +	case RT3071: +	case RT3090: +	case RT3290: +	case RT3352: +	case RT3390: +	case RT3572: +	case RT3593: +	case RT5390: +	case RT5392: +	case RT5592: +		break; +	default: +		rt2x00_err(rt2x00dev, "Invalid RT chipset 0x%04x, rev %04x detected\n", +			   rt, rev); +		return -ENODEV; +	} + +	rt2x00_set_rt(rt2x00dev, rt, rev); +  	return 0;  } -EXPORT_SYMBOL_GPL(rt2800_probe_hw_mode); + +int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev) +{ +	int retval; +	u32 reg; + +	retval = rt2800_probe_rt(rt2x00dev); +	if (retval) +		return retval; + +	/* +	 * Allocate eeprom data. +	 */ +	retval = rt2800_validate_eeprom(rt2x00dev); +	if (retval) +		return retval; + +	retval = rt2800_init_eeprom(rt2x00dev); +	if (retval) +		return retval; + +	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); +	rt2x00_set_field32(®, GPIO_CTRL_DIR2, 1); +	rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + +	/* +	 * Initialize hw specifications. +	 */ +	retval = rt2800_probe_hw_mode(rt2x00dev); +	if (retval) +		return retval; + +	/* +	 * Set device capabilities. +	 */ +	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_CONTROL_FILTER_PSPOLL, &rt2x00dev->cap_flags); +	if (!rt2x00_is_usb(rt2x00dev)) +		__set_bit(CAPABILITY_PRE_TBTT_INTERRUPT, &rt2x00dev->cap_flags); + +	/* +	 * Set device requirements. +	 */ +	if (!rt2x00_is_soc(rt2x00dev)) +		__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags); +	if (!rt2800_hwcrypt_disabled(rt2x00dev)) +		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags); +	if (rt2x00_is_usb(rt2x00dev)) +		__set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags); +	else { +		__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags); +		__set_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags); +	} + +	/* +	 * Set the rssi offset. +	 */ +	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2800_probe_hw);  /*   * IEEE80211 stack callback functions. @@ -3421,7 +7836,8 @@ int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)  }  EXPORT_SYMBOL_GPL(rt2800_set_rts_threshold); -int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, +int rt2800_conf_tx(struct ieee80211_hw *hw, +		   struct ieee80211_vif *vif, u16 queue_idx,  		   const struct ieee80211_tx_queue_params *params)  {  	struct rt2x00_dev *rt2x00dev = hw->priv; @@ -3437,7 +7853,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  	 * we are free to update the registers based on the value  	 * in the queue parameter.  	 */ -	retval = rt2x00mac_conf_tx(hw, queue_idx, params); +	retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);  	if (retval)  		return retval; @@ -3448,7 +7864,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  	if (queue_idx >= 4)  		return 0; -	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); +	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);  	/* Update WMM TXOP register */  	offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); @@ -3489,7 +7905,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  }  EXPORT_SYMBOL_GPL(rt2800_conf_tx); -u64 rt2800_get_tsf(struct ieee80211_hw *hw) +u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)  {  	struct rt2x00_dev *rt2x00dev = hw->priv;  	u64 tsf; @@ -3506,10 +7922,22 @@ EXPORT_SYMBOL_GPL(rt2800_get_tsf);  int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  			enum ieee80211_ampdu_mlme_action action, -			struct ieee80211_sta *sta, u16 tid, u16 *ssn) +			struct ieee80211_sta *sta, u16 tid, u16 *ssn, +			u8 buf_size)  { +	struct rt2x00_sta *sta_priv = (struct rt2x00_sta *)sta->drv_priv;  	int ret = 0; +	/* +	 * Don't allow aggregation for stations the hardware isn't aware +	 * of because tx status reports for frames to an unknown station +	 * always contain wcid=255 and thus we can't distinguish between +	 * multiple stations which leads to unwanted situations when the +	 * hw reorders frames due to aggregation. +	 */ +	if (sta_priv->wcid < 0) +		return 1; +  	switch (action) {  	case IEEE80211_AMPDU_RX_START:  	case IEEE80211_AMPDU_RX_STOP: @@ -3523,19 +7951,56 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	case IEEE80211_AMPDU_TX_START:  		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);  		break; -	case IEEE80211_AMPDU_TX_STOP: +	case IEEE80211_AMPDU_TX_STOP_CONT: +	case IEEE80211_AMPDU_TX_STOP_FLUSH: +	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:  		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);  		break;  	case IEEE80211_AMPDU_TX_OPERATIONAL:  		break;  	default: -		WARNING((struct rt2x00_dev *)hw->priv, "Unknown AMPDU action\n"); +		rt2x00_warn((struct rt2x00_dev *)hw->priv, +			    "Unknown AMPDU action\n");  	}  	return ret;  }  EXPORT_SYMBOL_GPL(rt2800_ampdu_action); +int rt2800_get_survey(struct ieee80211_hw *hw, int idx, +		      struct survey_info *survey) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct ieee80211_conf *conf = &hw->conf; +	u32 idle, busy, busy_ext; + +	if (idx != 0) +		return -ENOENT; + +	survey->channel = conf->chandef.chan; + +	rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle); +	rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy); +	rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext); + +	if (idle || busy) { +		survey->filled = SURVEY_INFO_CHANNEL_TIME | +				 SURVEY_INFO_CHANNEL_TIME_BUSY | +				 SURVEY_INFO_CHANNEL_TIME_EXT_BUSY; + +		survey->channel_time = (idle + busy) / 1000; +		survey->channel_time_busy = busy / 1000; +		survey->channel_time_ext_busy = busy_ext / 1000; +	} + +	if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) +		survey->filled |= SURVEY_INFO_IN_USE; + +	return 0; + +} +EXPORT_SYMBOL_GPL(rt2800_get_survey); +  MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");  MODULE_VERSION(DRV_VERSION);  MODULE_DESCRIPTION("Ralink RT2800 library"); diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 81cbc92e785..3019db637a4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -14,9 +14,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  #ifndef RT2800LIB_H @@ -43,6 +41,9 @@ struct rt2800_ops {  			    const unsigned int offset,  			    const struct rt2x00_field32 field, u32 *reg); +	int (*read_eeprom)(struct rt2x00_dev *rt2x00dev); +	bool (*hwcrypt_disabled)(struct rt2x00_dev *rt2x00dev); +  	int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev,  				  const u8 *data, const size_t len);  	int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); @@ -114,6 +115,20 @@ static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,  	return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg);  } +static inline int rt2800_read_eeprom(struct rt2x00_dev *rt2x00dev) +{ +	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; + +	return rt2800ops->read_eeprom(rt2x00dev); +} + +static inline bool rt2800_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) +{ +	const struct rt2800_ops *rt2800ops = rt2x00dev->ops->drv; + +	return rt2800ops->hwcrypt_disabled(rt2x00dev); +} +  static inline int rt2800_drv_write_firmware(struct rt2x00_dev *rt2x00dev,  					    const u8 *data, const size_t len)  { @@ -152,10 +167,10 @@ void rt2800_write_tx_data(struct queue_entry *entry,  			  struct txentry_desc *txdesc);  void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); -void rt2800_txdone(struct rt2x00_dev *rt2x00dev); -void rt2800_txdone_entry(struct queue_entry *entry, u32 status); +void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32* txwi);  void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); +void rt2800_clear_beacon(struct queue_entry *entry);  extern const struct rt2x00debug rt2800_rt2x00debug; @@ -166,6 +181,9 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,  int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,  			       struct rt2x00lib_crypto *crypto,  			       struct ieee80211_key_conf *key); +int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif, +		   struct ieee80211_sta *sta); +int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid);  void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,  			  const unsigned int filter_flags);  void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, @@ -180,24 +198,34 @@ void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);  void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);  void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,  		       const u32 count); +void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev); +void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev);  int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);  void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);  int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev); -void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev); -int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev); -int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev); -int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev); +int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev); + +int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev);  void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32,  			 u16 *iv16);  int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value); -int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, +int rt2800_conf_tx(struct ieee80211_hw *hw, +		   struct ieee80211_vif *vif, u16 queue_idx,  		   const struct ieee80211_tx_queue_params *params); -u64 rt2800_get_tsf(struct ieee80211_hw *hw); +u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);  int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  			enum ieee80211_ampdu_mlme_action action, -			struct ieee80211_sta *sta, u16 tid, u16 *ssn); +			struct ieee80211_sta *sta, u16 tid, u16 *ssn, +			u8 buf_size); +int rt2800_get_survey(struct ieee80211_hw *hw, int idx, +		      struct survey_info *survey); +void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); + +void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev, +			       unsigned short *txwi_size, +			       unsigned short *rxwi_size);  #endif /* RT2800LIB_H */ diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.c b/drivers/net/wireless/rt2x00/rt2800mmio.c new file mode 100644 index 00000000000..de4790b41be --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800mmio.c @@ -0,0 +1,871 @@ +/*	Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> + *	Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> + *	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> + *	Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> + *	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> + *	Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com> + *	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> + *	Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com> + *	<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, see <http://www.gnu.org/licenses/>. + */ + +/*	Module: rt2800mmio + *	Abstract: rt2800 MMIO device routines. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/export.h> + +#include "rt2x00.h" +#include "rt2x00mmio.h" +#include "rt2800.h" +#include "rt2800lib.h" +#include "rt2800mmio.h" + +/* + * TX descriptor initialization + */ +__le32 *rt2800mmio_get_txwi(struct queue_entry *entry) +{ +	return (__le32 *) entry->skb->data; +} +EXPORT_SYMBOL_GPL(rt2800mmio_get_txwi); + +void rt2800mmio_write_tx_desc(struct queue_entry *entry, +			      struct txentry_desc *txdesc) +{ +	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data; +	__le32 *txd = entry_priv->desc; +	u32 word; +	const unsigned int txwi_size = entry->queue->winfo_size; + +	/* +	 * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1 +	 * must contains a TXWI structure + 802.11 header + padding + 802.11 +	 * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and +	 * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11 +	 * data. It means that LAST_SEC0 is always 0. +	 */ + +	/* +	 * Initialize TX descriptor +	 */ +	word = 0; +	rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma); +	rt2x00_desc_write(txd, 0, word); + +	word = 0; +	rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len); +	rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, +			   !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); +	rt2x00_set_field32(&word, TXD_W1_BURST, +			   test_bit(ENTRY_TXD_BURST, &txdesc->flags)); +	rt2x00_set_field32(&word, TXD_W1_SD_LEN0, txwi_size); +	rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0); +	rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); +	rt2x00_desc_write(txd, 1, word); + +	word = 0; +	rt2x00_set_field32(&word, TXD_W2_SD_PTR1, +			   skbdesc->skb_dma + txwi_size); +	rt2x00_desc_write(txd, 2, word); + +	word = 0; +	rt2x00_set_field32(&word, TXD_W3_WIV, +			   !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); +	rt2x00_set_field32(&word, TXD_W3_QSEL, 2); +	rt2x00_desc_write(txd, 3, word); + +	/* +	 * Register descriptor details in skb frame descriptor. +	 */ +	skbdesc->desc = txd; +	skbdesc->desc_len = TXD_DESC_SIZE; +} +EXPORT_SYMBOL_GPL(rt2800mmio_write_tx_desc); + +/* + * RX control handlers + */ +void rt2800mmio_fill_rxdone(struct queue_entry *entry, +			    struct rxdone_entry_desc *rxdesc) +{ +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data; +	__le32 *rxd = entry_priv->desc; +	u32 word; + +	rt2x00_desc_read(rxd, 3, &word); + +	if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR)) +		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; + +	/* +	 * Unfortunately we don't know the cipher type used during +	 * decryption. This prevents us from correct providing +	 * correct statistics through debugfs. +	 */ +	rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR); + +	if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) { +		/* +		 * Hardware has stripped IV/EIV data from 802.11 frame during +		 * decryption. Unfortunately the descriptor doesn't contain +		 * any fields with the EIV/IV data either, so they can't +		 * be restored by rt2x00lib. +		 */ +		rxdesc->flags |= RX_FLAG_IV_STRIPPED; + +		/* +		 * The hardware has already checked the Michael Mic and has +		 * stripped it from the frame. Signal this to mac80211. +		 */ +		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; + +		if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) +			rxdesc->flags |= RX_FLAG_DECRYPTED; +		else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) +			rxdesc->flags |= RX_FLAG_MMIC_ERROR; +	} + +	if (rt2x00_get_field32(word, RXD_W3_MY_BSS)) +		rxdesc->dev_flags |= RXDONE_MY_BSS; + +	if (rt2x00_get_field32(word, RXD_W3_L2PAD)) +		rxdesc->dev_flags |= RXDONE_L2PAD; + +	/* +	 * Process the RXWI structure that is at the start of the buffer. +	 */ +	rt2800_process_rxwi(entry, rxdesc); +} +EXPORT_SYMBOL_GPL(rt2800mmio_fill_rxdone); + +/* + * Interrupt functions. + */ +static void rt2800mmio_wakeup(struct rt2x00_dev *rt2x00dev) +{ +	struct ieee80211_conf conf = { .flags = 0 }; +	struct rt2x00lib_conf libconf = { .conf = &conf }; + +	rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); +} + +static bool rt2800mmio_txdone_entry_check(struct queue_entry *entry, u32 status) +{ +	__le32 *txwi; +	u32 word; +	int wcid, tx_wcid; + +	wcid = rt2x00_get_field32(status, TX_STA_FIFO_WCID); + +	txwi = rt2800_drv_get_txwi(entry); +	rt2x00_desc_read(txwi, 1, &word); +	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); + +	return (tx_wcid == wcid); +} + +static bool rt2800mmio_txdone_find_entry(struct queue_entry *entry, void *data) +{ +	u32 status = *(u32 *)data; + +	/* +	 * rt2800pci hardware might reorder frames when exchanging traffic +	 * with multiple BA enabled STAs. +	 * +	 * For example, a tx queue +	 *    [ STA1 | STA2 | STA1 | STA2 ] +	 * can result in tx status reports +	 *    [ STA1 | STA1 | STA2 | STA2 ] +	 * when the hw decides to aggregate the frames for STA1 into one AMPDU. +	 * +	 * To mitigate this effect, associate the tx status to the first frame +	 * in the tx queue with a matching wcid. +	 */ +	if (rt2800mmio_txdone_entry_check(entry, status) && +	    !test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { +		/* +		 * Got a matching frame, associate the tx status with +		 * the frame +		 */ +		entry->status = status; +		set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); +		return true; +	} + +	/* Check the next frame */ +	return false; +} + +static bool rt2800mmio_txdone_match_first(struct queue_entry *entry, void *data) +{ +	u32 status = *(u32 *)data; + +	/* +	 * Find the first frame without tx status and assign this status to it +	 * regardless if it matches or not. +	 */ +	if (!test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { +		/* +		 * Got a matching frame, associate the tx status with +		 * the frame +		 */ +		entry->status = status; +		set_bit(ENTRY_DATA_STATUS_SET, &entry->flags); +		return true; +	} + +	/* Check the next frame */ +	return false; +} +static bool rt2800mmio_txdone_release_entries(struct queue_entry *entry, +					      void *data) +{ +	if (test_bit(ENTRY_DATA_STATUS_SET, &entry->flags)) { +		rt2800_txdone_entry(entry, entry->status, +				    rt2800mmio_get_txwi(entry)); +		return false; +	} + +	/* No more frames to release */ +	return true; +} + +static bool rt2800mmio_txdone(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue; +	u32 status; +	u8 qid; +	int max_tx_done = 16; + +	while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) { +		qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); +		if (unlikely(qid >= QID_RX)) { +			/* +			 * Unknown queue, this shouldn't happen. Just drop +			 * this tx status. +			 */ +			rt2x00_warn(rt2x00dev, "Got TX status report with unexpected pid %u, dropping\n", +				    qid); +			break; +		} + +		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); +		if (unlikely(queue == NULL)) { +			/* +			 * The queue is NULL, this shouldn't happen. Stop +			 * processing here and drop the tx status +			 */ +			rt2x00_warn(rt2x00dev, "Got TX status for an unavailable queue %u, dropping\n", +				    qid); +			break; +		} + +		if (unlikely(rt2x00queue_empty(queue))) { +			/* +			 * The queue is empty. Stop processing here +			 * and drop the tx status. +			 */ +			rt2x00_warn(rt2x00dev, "Got TX status for an empty queue %u, dropping\n", +				    qid); +			break; +		} + +		/* +		 * Let's associate this tx status with the first +		 * matching frame. +		 */ +		if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, +						Q_INDEX, &status, +						rt2800mmio_txdone_find_entry)) { +			/* +			 * We cannot match the tx status to any frame, so just +			 * use the first one. +			 */ +			if (!rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, +							Q_INDEX, &status, +							rt2800mmio_txdone_match_first)) { +				rt2x00_warn(rt2x00dev, "No frame found for TX status on queue %u, dropping\n", +					    qid); +				break; +			} +		} + +		/* +		 * Release all frames with a valid tx status. +		 */ +		rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, +					   Q_INDEX, NULL, +					   rt2800mmio_txdone_release_entries); + +		if (--max_tx_done == 0) +			break; +	} + +	return !max_tx_done; +} + +static inline void rt2800mmio_enable_interrupt(struct rt2x00_dev *rt2x00dev, +					       struct rt2x00_field32 irq_field) +{ +	u32 reg; + +	/* +	 * Enable a single interrupt. The interrupt mask register +	 * access needs locking. +	 */ +	spin_lock_irq(&rt2x00dev->irqmask_lock); +	rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); +	rt2x00_set_field32(®, irq_field, 1); +	rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); +	spin_unlock_irq(&rt2x00dev->irqmask_lock); +} + +void rt2800mmio_txstatus_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	if (rt2800mmio_txdone(rt2x00dev)) +		tasklet_schedule(&rt2x00dev->txstatus_tasklet); + +	/* +	 * No need to enable the tx status interrupt here as we always +	 * leave it enabled to minimize the possibility of a tx status +	 * register overflow. See comment in interrupt handler. +	 */ +} +EXPORT_SYMBOL_GPL(rt2800mmio_txstatus_tasklet); + +void rt2800mmio_pretbtt_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	rt2x00lib_pretbtt(rt2x00dev); +	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT); +} +EXPORT_SYMBOL_GPL(rt2800mmio_pretbtt_tasklet); + +void rt2800mmio_tbtt_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; +	u32 reg; + +	rt2x00lib_beacondone(rt2x00dev); + +	if (rt2x00dev->intf_ap_count) { +		/* +		 * The rt2800pci hardware tbtt timer is off by 1us per tbtt +		 * causing beacon skew and as a result causing problems with +		 * some powersaving clients over time. Shorten the beacon +		 * interval every 64 beacons by 64us to mitigate this effect. +		 */ +		if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) { +			rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); +			rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, +					   (rt2x00dev->beacon_int * 16) - 1); +			rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); +		} else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) { +			rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); +			rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, +					   (rt2x00dev->beacon_int * 16)); +			rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); +		} +		drv_data->tbtt_tick++; +		drv_data->tbtt_tick %= BCN_TBTT_OFFSET; +	} + +	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT); +} +EXPORT_SYMBOL_GPL(rt2800mmio_tbtt_tasklet); + +void rt2800mmio_rxdone_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	if (rt2x00mmio_rxdone(rt2x00dev)) +		tasklet_schedule(&rt2x00dev->rxdone_tasklet); +	else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt2800mmio_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); +} +EXPORT_SYMBOL_GPL(rt2800mmio_rxdone_tasklet); + +void rt2800mmio_autowake_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	rt2800mmio_wakeup(rt2x00dev); +	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt2800mmio_enable_interrupt(rt2x00dev, +					    INT_MASK_CSR_AUTO_WAKEUP); +} +EXPORT_SYMBOL_GPL(rt2800mmio_autowake_tasklet); + +static void rt2800mmio_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) +{ +	u32 status; +	int i; + +	/* +	 * The TX_FIFO_STATUS interrupt needs special care. We should +	 * read TX_STA_FIFO but we should do it immediately as otherwise +	 * the register can overflow and we would lose status reports. +	 * +	 * Hence, read the TX_STA_FIFO register and copy all tx status +	 * reports into a kernel FIFO which is handled in the txstatus +	 * tasklet. We use a tasklet to process the tx status reports +	 * because we can schedule the tasklet multiple times (when the +	 * interrupt fires again during tx status processing). +	 * +	 * Furthermore we don't disable the TX_FIFO_STATUS +	 * interrupt here but leave it enabled so that the TX_STA_FIFO +	 * can also be read while the tx status tasklet gets executed. +	 * +	 * Since we have only one producer and one consumer we don't +	 * need to lock the kfifo. +	 */ +	for (i = 0; i < rt2x00dev->tx->limit; i++) { +		rt2x00mmio_register_read(rt2x00dev, TX_STA_FIFO, &status); + +		if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) +			break; + +		if (!kfifo_put(&rt2x00dev->txstatus_fifo, status)) { +			rt2x00_warn(rt2x00dev, "TX status FIFO overrun, drop tx status report\n"); +			break; +		} +	} + +	/* Schedule the tasklet for processing the tx status. */ +	tasklet_schedule(&rt2x00dev->txstatus_tasklet); +} + +irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance) +{ +	struct rt2x00_dev *rt2x00dev = dev_instance; +	u32 reg, mask; + +	/* Read status and ACK all interrupts */ +	rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); +	rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); + +	if (!reg) +		return IRQ_NONE; + +	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		return IRQ_HANDLED; + +	/* +	 * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits +	 * for interrupts and interrupt masks we can just use the value of +	 * INT_SOURCE_CSR to create the interrupt mask. +	 */ +	mask = ~reg; + +	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) { +		rt2800mmio_txstatus_interrupt(rt2x00dev); +		/* +		 * Never disable the TX_FIFO_STATUS interrupt. +		 */ +		rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1); +	} + +	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) +		tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet); + +	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) +		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); + +	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) +		tasklet_schedule(&rt2x00dev->rxdone_tasklet); + +	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) +		tasklet_schedule(&rt2x00dev->autowake_tasklet); + +	/* +	 * Disable all interrupts for which a tasklet was scheduled right now, +	 * the tasklet will reenable the appropriate interrupts. +	 */ +	spin_lock(&rt2x00dev->irqmask_lock); +	rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); +	reg &= mask; +	rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); +	spin_unlock(&rt2x00dev->irqmask_lock); + +	return IRQ_HANDLED; +} +EXPORT_SYMBOL_GPL(rt2800mmio_interrupt); + +void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev, +			   enum dev_state state) +{ +	u32 reg; +	unsigned long flags; + +	/* +	 * When interrupts are being enabled, the interrupt registers +	 * should clear the register to assure a clean state. +	 */ +	if (state == STATE_RADIO_IRQ_ON) { +		rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); +		rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); +	} + +	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); +	reg = 0; +	if (state == STATE_RADIO_IRQ_ON) { +		rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, 1); +		rt2x00_set_field32(®, INT_MASK_CSR_TBTT, 1); +		rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, 1); +		rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); +		rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, 1); +	} +	rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); +	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); + +	if (state == STATE_RADIO_IRQ_OFF) { +		/* +		 * Wait for possibly running tasklets to finish. +		 */ +		tasklet_kill(&rt2x00dev->txstatus_tasklet); +		tasklet_kill(&rt2x00dev->rxdone_tasklet); +		tasklet_kill(&rt2x00dev->autowake_tasklet); +		tasklet_kill(&rt2x00dev->tbtt_tasklet); +		tasklet_kill(&rt2x00dev->pretbtt_tasklet); +	} +} +EXPORT_SYMBOL_GPL(rt2800mmio_toggle_irq); + +/* + * Queue handlers. + */ +void rt2800mmio_start_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_RX: +		rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); +		rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); +		rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +		break; +	case QID_BEACON: +		rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); +		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); +		rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); +		rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); +		rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); + +		rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); +		rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 1); +		rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); +		break; +	default: +		break; +	} +} +EXPORT_SYMBOL_GPL(rt2800mmio_start_queue); + +void rt2800mmio_kick_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	struct queue_entry *entry; + +	switch (queue->qid) { +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		entry = rt2x00queue_get_entry(queue, Q_INDEX); +		rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), +					  entry->entry_idx); +		break; +	case QID_MGMT: +		entry = rt2x00queue_get_entry(queue, Q_INDEX); +		rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX(5), +					  entry->entry_idx); +		break; +	default: +		break; +	} +} +EXPORT_SYMBOL_GPL(rt2800mmio_kick_queue); + +void rt2800mmio_stop_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_RX: +		rt2x00mmio_register_read(rt2x00dev, MAC_SYS_CTRL, ®); +		rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); +		rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +		break; +	case QID_BEACON: +		rt2x00mmio_register_read(rt2x00dev, BCN_TIME_CFG, ®); +		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); +		rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); +		rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); +		rt2x00mmio_register_write(rt2x00dev, BCN_TIME_CFG, reg); + +		rt2x00mmio_register_read(rt2x00dev, INT_TIMER_EN, ®); +		rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, 0); +		rt2x00mmio_register_write(rt2x00dev, INT_TIMER_EN, reg); + +		/* +		 * Wait for current invocation to finish. The tasklet +		 * won't be scheduled anymore afterwards since we disabled +		 * the TBTT and PRE TBTT timer. +		 */ +		tasklet_kill(&rt2x00dev->tbtt_tasklet); +		tasklet_kill(&rt2x00dev->pretbtt_tasklet); + +		break; +	default: +		break; +	} +} +EXPORT_SYMBOL_GPL(rt2800mmio_stop_queue); + +void rt2800mmio_queue_init(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	unsigned short txwi_size, rxwi_size; + +	rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size); + +	switch (queue->qid) { +	case QID_RX: +		queue->limit = 128; +		queue->data_size = AGGREGATION_SIZE; +		queue->desc_size = RXD_DESC_SIZE; +		queue->winfo_size = rxwi_size; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; + +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		queue->limit = 64; +		queue->data_size = AGGREGATION_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->winfo_size = txwi_size; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; + +	case QID_BEACON: +		queue->limit = 8; +		queue->data_size = 0; /* No DMA required for beacons */ +		queue->desc_size = TXD_DESC_SIZE; +		queue->winfo_size = txwi_size; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; + +	case QID_ATIM: +		/* fallthrough */ +	default: +		BUG(); +		break; +	} +} +EXPORT_SYMBOL_GPL(rt2800mmio_queue_init); + +/* + * Initialization functions. + */ +bool rt2800mmio_get_entry_state(struct queue_entry *entry) +{ +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data; +	u32 word; + +	if (entry->queue->qid == QID_RX) { +		rt2x00_desc_read(entry_priv->desc, 1, &word); + +		return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE)); +	} else { +		rt2x00_desc_read(entry_priv->desc, 1, &word); + +		return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE)); +	} +} +EXPORT_SYMBOL_GPL(rt2800mmio_get_entry_state); + +void rt2800mmio_clear_entry(struct queue_entry *entry) +{ +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data; +	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +	u32 word; + +	if (entry->queue->qid == QID_RX) { +		rt2x00_desc_read(entry_priv->desc, 0, &word); +		rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma); +		rt2x00_desc_write(entry_priv->desc, 0, word); + +		rt2x00_desc_read(entry_priv->desc, 1, &word); +		rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0); +		rt2x00_desc_write(entry_priv->desc, 1, word); + +		/* +		 * Set RX IDX in register to inform hardware that we have +		 * handled this entry and it is available for reuse again. +		 */ +		rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, +					  entry->entry_idx); +	} else { +		rt2x00_desc_read(entry_priv->desc, 1, &word); +		rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); +		rt2x00_desc_write(entry_priv->desc, 1, word); +	} +} +EXPORT_SYMBOL_GPL(rt2800mmio_clear_entry); + +int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev) +{ +	struct queue_entry_priv_mmio *entry_priv; + +	/* +	 * Initialize registers. +	 */ +	entry_priv = rt2x00dev->tx[0].entries[0].priv_data; +	rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR0, +				  entry_priv->desc_dma); +	rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT0, +				  rt2x00dev->tx[0].limit); +	rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX0, 0); +	rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX0, 0); + +	entry_priv = rt2x00dev->tx[1].entries[0].priv_data; +	rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR1, +				  entry_priv->desc_dma); +	rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT1, +				  rt2x00dev->tx[1].limit); +	rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX1, 0); +	rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX1, 0); + +	entry_priv = rt2x00dev->tx[2].entries[0].priv_data; +	rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR2, +				  entry_priv->desc_dma); +	rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT2, +				  rt2x00dev->tx[2].limit); +	rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX2, 0); +	rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX2, 0); + +	entry_priv = rt2x00dev->tx[3].entries[0].priv_data; +	rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR3, +				  entry_priv->desc_dma); +	rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT3, +				  rt2x00dev->tx[3].limit); +	rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX3, 0); +	rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX3, 0); + +	rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR4, 0); +	rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT4, 0); +	rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX4, 0); +	rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX4, 0); + +	rt2x00mmio_register_write(rt2x00dev, TX_BASE_PTR5, 0); +	rt2x00mmio_register_write(rt2x00dev, TX_MAX_CNT5, 0); +	rt2x00mmio_register_write(rt2x00dev, TX_CTX_IDX5, 0); +	rt2x00mmio_register_write(rt2x00dev, TX_DTX_IDX5, 0); + +	entry_priv = rt2x00dev->rx->entries[0].priv_data; +	rt2x00mmio_register_write(rt2x00dev, RX_BASE_PTR, +				  entry_priv->desc_dma); +	rt2x00mmio_register_write(rt2x00dev, RX_MAX_CNT, +				  rt2x00dev->rx[0].limit); +	rt2x00mmio_register_write(rt2x00dev, RX_CRX_IDX, +				  rt2x00dev->rx[0].limit - 1); +	rt2x00mmio_register_write(rt2x00dev, RX_DRX_IDX, 0); + +	rt2800_disable_wpdma(rt2x00dev); + +	rt2x00mmio_register_write(rt2x00dev, DELAY_INT_CFG, 0); + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2800mmio_init_queues); + +int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev) +{ +	u32 reg; + +	/* +	 * Reset DMA indexes +	 */ +	rt2x00mmio_register_read(rt2x00dev, WPDMA_RST_IDX, ®); +	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); +	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); +	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); +	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); +	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); +	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); +	rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); +	rt2x00mmio_register_write(rt2x00dev, WPDMA_RST_IDX, reg); + +	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); +	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); + +	if (rt2x00_is_pcie(rt2x00dev) && +	    (rt2x00_rt(rt2x00dev, RT3090) || +	     rt2x00_rt(rt2x00dev, RT3390) || +	     rt2x00_rt(rt2x00dev, RT3572) || +	     rt2x00_rt(rt2x00dev, RT3593) || +	     rt2x00_rt(rt2x00dev, RT5390) || +	     rt2x00_rt(rt2x00dev, RT5392) || +	     rt2x00_rt(rt2x00dev, RT5592))) { +		rt2x00mmio_register_read(rt2x00dev, AUX_CTRL, ®); +		rt2x00_set_field32(®, AUX_CTRL_FORCE_PCIE_CLK, 1); +		rt2x00_set_field32(®, AUX_CTRL_WAKE_PCIE_EN, 1); +		rt2x00mmio_register_write(rt2x00dev, AUX_CTRL, reg); +	} + +	rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); + +	reg = 0; +	rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); +	rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); +	rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, reg); + +	rt2x00mmio_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2800mmio_init_registers); + +/* + * Device state switch handlers. + */ +int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev) +{ +	/* Wait for DMA, ignore error until we initialize queues. */ +	rt2800_wait_wpdma_ready(rt2x00dev); + +	if (unlikely(rt2800mmio_init_queues(rt2x00dev))) +		return -EIO; + +	return rt2800_enable_radio(rt2x00dev); +} +EXPORT_SYMBOL_GPL(rt2800mmio_enable_radio); + +MODULE_AUTHOR(DRV_PROJECT); +MODULE_VERSION(DRV_VERSION); +MODULE_DESCRIPTION("rt2800 MMIO library"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/rt2x00/rt2800mmio.h b/drivers/net/wireless/rt2x00/rt2800mmio.h new file mode 100644 index 00000000000..b63312ce3f2 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800mmio.h @@ -0,0 +1,163 @@ +/*	Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> + *	Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> + *	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> + *	Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> + *	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> + *	Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com> + *	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> + *	Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com> + *	<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, see <http://www.gnu.org/licenses/>. + */ + +/*	Module: rt2800mmio + *	Abstract: forward declarations for the rt2800mmio module. + */ + +#ifndef RT2800MMIO_H +#define RT2800MMIO_H + +/* + * Queue register offset macros + */ +#define TX_QUEUE_REG_OFFSET	0x10 +#define TX_BASE_PTR(__x)	(TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_MAX_CNT(__x)		(TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_CTX_IDX(__x)		(TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) +#define TX_DTX_IDX(__x)		(TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) + +/* + * DMA descriptor defines. + */ +#define TXD_DESC_SIZE			(4 * sizeof(__le32)) +#define RXD_DESC_SIZE			(4 * sizeof(__le32)) + +/* + * TX descriptor format for TX, PRIO and Beacon Ring. + */ + +/* + * Word0 + */ +#define TXD_W0_SD_PTR0			FIELD32(0xffffffff) + +/* + * Word1 + */ +#define TXD_W1_SD_LEN1			FIELD32(0x00003fff) +#define TXD_W1_LAST_SEC1		FIELD32(0x00004000) +#define TXD_W1_BURST			FIELD32(0x00008000) +#define TXD_W1_SD_LEN0			FIELD32(0x3fff0000) +#define TXD_W1_LAST_SEC0		FIELD32(0x40000000) +#define TXD_W1_DMA_DONE			FIELD32(0x80000000) + +/* + * Word2 + */ +#define TXD_W2_SD_PTR1			FIELD32(0xffffffff) + +/* + * Word3 + * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI + * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. + *       0:MGMT, 1:HCCA 2:EDCA + */ +#define TXD_W3_WIV			FIELD32(0x01000000) +#define TXD_W3_QSEL			FIELD32(0x06000000) +#define TXD_W3_TCO			FIELD32(0x20000000) +#define TXD_W3_UCO			FIELD32(0x40000000) +#define TXD_W3_ICO			FIELD32(0x80000000) + +/* + * RX descriptor format for RX Ring. + */ + +/* + * Word0 + */ +#define RXD_W0_SDP0			FIELD32(0xffffffff) + +/* + * Word1 + */ +#define RXD_W1_SDL1			FIELD32(0x00003fff) +#define RXD_W1_SDL0			FIELD32(0x3fff0000) +#define RXD_W1_LS0			FIELD32(0x40000000) +#define RXD_W1_DMA_DONE			FIELD32(0x80000000) + +/* + * Word2 + */ +#define RXD_W2_SDP1			FIELD32(0xffffffff) + +/* + * Word3 + * AMSDU: RX with 802.3 header, not 802.11 header. + * DECRYPTED: This frame is being decrypted. + */ +#define RXD_W3_BA			FIELD32(0x00000001) +#define RXD_W3_DATA			FIELD32(0x00000002) +#define RXD_W3_NULLDATA			FIELD32(0x00000004) +#define RXD_W3_FRAG			FIELD32(0x00000008) +#define RXD_W3_UNICAST_TO_ME		FIELD32(0x00000010) +#define RXD_W3_MULTICAST		FIELD32(0x00000020) +#define RXD_W3_BROADCAST		FIELD32(0x00000040) +#define RXD_W3_MY_BSS			FIELD32(0x00000080) +#define RXD_W3_CRC_ERROR		FIELD32(0x00000100) +#define RXD_W3_CIPHER_ERROR		FIELD32(0x00000600) +#define RXD_W3_AMSDU			FIELD32(0x00000800) +#define RXD_W3_HTC			FIELD32(0x00001000) +#define RXD_W3_RSSI			FIELD32(0x00002000) +#define RXD_W3_L2PAD			FIELD32(0x00004000) +#define RXD_W3_AMPDU			FIELD32(0x00008000) +#define RXD_W3_DECRYPTED		FIELD32(0x00010000) +#define RXD_W3_PLCP_SIGNAL		FIELD32(0x00020000) +#define RXD_W3_PLCP_RSSI		FIELD32(0x00040000) + +/* TX descriptor initialization */ +__le32 *rt2800mmio_get_txwi(struct queue_entry *entry); +void rt2800mmio_write_tx_desc(struct queue_entry *entry, +			      struct txentry_desc *txdesc); + +/* RX control handlers */ +void rt2800mmio_fill_rxdone(struct queue_entry *entry, +			    struct rxdone_entry_desc *rxdesc); + +/* Interrupt functions */ +void rt2800mmio_txstatus_tasklet(unsigned long data); +void rt2800mmio_pretbtt_tasklet(unsigned long data); +void rt2800mmio_tbtt_tasklet(unsigned long data); +void rt2800mmio_rxdone_tasklet(unsigned long data); +void rt2800mmio_autowake_tasklet(unsigned long data); +irqreturn_t rt2800mmio_interrupt(int irq, void *dev_instance); +void rt2800mmio_toggle_irq(struct rt2x00_dev *rt2x00dev, +			   enum dev_state state); + +/* Queue handlers */ +void rt2800mmio_start_queue(struct data_queue *queue); +void rt2800mmio_kick_queue(struct data_queue *queue); +void rt2800mmio_stop_queue(struct data_queue *queue); +void rt2800mmio_queue_init(struct data_queue *queue); + +/* Initialization functions */ +bool rt2800mmio_get_entry_state(struct queue_entry *entry); +void rt2800mmio_clear_entry(struct queue_entry *entry); +int rt2800mmio_init_queues(struct rt2x00_dev *rt2x00dev); +int rt2800mmio_init_registers(struct rt2x00_dev *rt2x00dev); + +/* Device state switch handlers. */ +int rt2800mmio_enable_radio(struct rt2x00_dev *rt2x00dev); + +#endif /* RT2800MMIO_H */ diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 433c7f3ef83..a5b32ca2cf0 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -20,9 +20,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -37,23 +35,28 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/pci.h> -#include <linux/platform_device.h>  #include <linux/eeprom_93cx6.h>  #include "rt2x00.h" +#include "rt2x00mmio.h"  #include "rt2x00pci.h" -#include "rt2x00soc.h"  #include "rt2800lib.h" +#include "rt2800mmio.h"  #include "rt2800.h"  #include "rt2800pci.h"  /*   * Allow hardware encryption to be disabled.   */ -static int modparam_nohwcrypt = 0; +static bool modparam_nohwcrypt = false;  module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);  MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +static bool rt2800pci_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) +{ +	return modparam_nohwcrypt; +} +  static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)  {  	unsigned int i; @@ -66,7 +69,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)  		return;  	for (i = 0; i < 200; i++) { -		rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); +		rt2x00mmio_register_read(rt2x00dev, H2M_MAILBOX_CID, ®);  		if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||  		    (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || @@ -78,34 +81,18 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)  	}  	if (i == 200) -		ERROR(rt2x00dev, "MCU request failed, no response from hardware\n"); - -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); -} +		rt2x00_err(rt2x00dev, "MCU request failed, no response from hardware\n"); -#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) -static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) -{ -	void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); - -	memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); - -	iounmap(base_addr); -} -#else -static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) -{ +	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); +	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);  } -#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ -#ifdef CONFIG_PCI  static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)  {  	struct rt2x00_dev *rt2x00dev = eeprom->data;  	u32 reg; -	rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); +	rt2x00mmio_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); @@ -127,15 +114,15 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)  	rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT,  			   !!eeprom->reg_chip_select); -	rt2800_register_write(rt2x00dev, E2PROM_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg);  } -static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) +static int rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)  {  	struct eeprom_93cx6 eeprom;  	u32 reg; -	rt2800_register_read(rt2x00dev, E2PROM_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, ®);  	eeprom.data = rt2x00dev;  	eeprom.register_read = rt2800pci_eepromregister_read; @@ -159,6 +146,8 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)  	eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom,  			       EEPROM_SIZE / sizeof(u16)); + +	return 0;  }  static int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) @@ -166,31 +155,23 @@ static int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev)  	return rt2800_efuse_detect(rt2x00dev);  } -static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) -{ -	rt2800_read_eeprom_efuse(rt2x00dev); -} -#else -static inline void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) -{ -} - -static inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev) -{ -	return 0; -} - -static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) +static inline int rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)  { +	return rt2800_read_eeprom_efuse(rt2x00dev);  } -#endif /* CONFIG_PCI */  /*   * Firmware functions   */  static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)  { -	return FIRMWARE_RT2860; +	/* +	 * Chip rt3290 use specific 4KB firmware named rt3290.bin. +	 */ +	if (rt2x00_rt(rt2x00dev, RT3290)) +		return FIRMWARE_RT3290; +	else +		return FIRMWARE_RT2860;  }  static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev, @@ -203,119 +184,19 @@ static int rt2800pci_write_firmware(struct rt2x00_dev *rt2x00dev,  	 */  	reg = 0;  	rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg); +	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, reg);  	/*  	 * Write firmware to device.  	 */ -	rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, -				   data, len); - -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); - -	rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); - -	return 0; -} - -/* - * Initialization functions. - */ -static bool rt2800pci_get_entry_state(struct queue_entry *entry) -{ -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; -	u32 word; - -	if (entry->queue->qid == QID_RX) { -		rt2x00_desc_read(entry_priv->desc, 1, &word); - -		return (!rt2x00_get_field32(word, RXD_W1_DMA_DONE)); -	} else { -		rt2x00_desc_read(entry_priv->desc, 1, &word); - -		return (!rt2x00_get_field32(word, TXD_W1_DMA_DONE)); -	} -} - -static void rt2800pci_clear_entry(struct queue_entry *entry) -{ -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; -	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); -	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	u32 word; - -	if (entry->queue->qid == QID_RX) { -		rt2x00_desc_read(entry_priv->desc, 0, &word); -		rt2x00_set_field32(&word, RXD_W0_SDP0, skbdesc->skb_dma); -		rt2x00_desc_write(entry_priv->desc, 0, word); - -		rt2x00_desc_read(entry_priv->desc, 1, &word); -		rt2x00_set_field32(&word, RXD_W1_DMA_DONE, 0); -		rt2x00_desc_write(entry_priv->desc, 1, word); - -		/* -		 * Set RX IDX in register to inform hardware that we have -		 * handled this entry and it is available for reuse again. -		 */ -		rt2800_register_write(rt2x00dev, RX_CRX_IDX, -				      entry->entry_idx); -	} else { -		rt2x00_desc_read(entry_priv->desc, 1, &word); -		rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 1); -		rt2x00_desc_write(entry_priv->desc, 1, word); -	} -} - -static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev) -{ -	struct queue_entry_priv_pci *entry_priv; -	u32 reg; - -	/* -	 * Initialize registers. -	 */ -	entry_priv = rt2x00dev->tx[0].entries[0].priv_data; -	rt2800_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); -	rt2800_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit); -	rt2800_register_write(rt2x00dev, TX_CTX_IDX0, 0); -	rt2800_register_write(rt2x00dev, TX_DTX_IDX0, 0); - -	entry_priv = rt2x00dev->tx[1].entries[0].priv_data; -	rt2800_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); -	rt2800_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit); -	rt2800_register_write(rt2x00dev, TX_CTX_IDX1, 0); -	rt2800_register_write(rt2x00dev, TX_DTX_IDX1, 0); +	rt2x00mmio_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, +				       data, len); -	entry_priv = rt2x00dev->tx[2].entries[0].priv_data; -	rt2800_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); -	rt2800_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit); -	rt2800_register_write(rt2x00dev, TX_CTX_IDX2, 0); -	rt2800_register_write(rt2x00dev, TX_DTX_IDX2, 0); +	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); +	rt2x00mmio_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); -	entry_priv = rt2x00dev->tx[3].entries[0].priv_data; -	rt2800_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); -	rt2800_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit); -	rt2800_register_write(rt2x00dev, TX_CTX_IDX3, 0); -	rt2800_register_write(rt2x00dev, TX_DTX_IDX3, 0); - -	entry_priv = rt2x00dev->rx->entries[0].priv_data; -	rt2800_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); -	rt2800_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit); -	rt2800_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1); -	rt2800_register_write(rt2x00dev, RX_DRX_IDX, 0); - -	/* -	 * Enable global DMA configuration -	 */ -	rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); -	rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); -	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - -	rt2800_register_write(rt2x00dev, DELAY_INT_CFG, 0); +	rt2x00mmio_register_write(rt2x00dev, H2M_BBP_AGENT, 0); +	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);  	return 0;  } @@ -323,131 +204,41 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)  /*   * Device state switch handlers.   */ -static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev, -				enum dev_state state) -{ -	u32 reg; - -	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); -	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, -			   (state == STATE_RADIO_RX_ON)); -	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); -} - -static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev, -				 enum dev_state state) -{ -	int mask = (state == STATE_RADIO_IRQ_ON) || -		   (state == STATE_RADIO_IRQ_ON_ISR); -	u32 reg; - -	/* -	 * When interrupts are being enabled, the interrupt registers -	 * should clear the register to assure a clean state. -	 */ -	if (state == STATE_RADIO_IRQ_ON) { -		rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); -		rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); -	} - -	rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); -	rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, mask); -	rt2x00_set_field32(®, INT_MASK_CSR_AC0_DMA_DONE, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_AC1_DMA_DONE, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_AC2_DMA_DONE, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_AC3_DMA_DONE, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_HCCA_DMA_DONE, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_MGMT_DMA_DONE, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_MCU_COMMAND, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_RXTX_COHERENT, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_TBTT, mask); -	rt2x00_set_field32(®, INT_MASK_CSR_PRE_TBTT, mask); -	rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, mask); -	rt2x00_set_field32(®, INT_MASK_CSR_AUTO_WAKEUP, mask); -	rt2x00_set_field32(®, INT_MASK_CSR_GPTIMER, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, 0); -	rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, 0); -	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); -} - -static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) -{ -	u32 reg; - -	/* -	 * Reset DMA indexes -	 */ -	rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); -	rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); - -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); - -	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); - -	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); -	rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); -	rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); -	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - -	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); - -	return 0; -} -  static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)  { -	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev) || -		     rt2800pci_init_queues(rt2x00dev))) -		return -EIO; - -	return rt2800_enable_radio(rt2x00dev); -} +	int retval; -static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) -{ -	u32 reg; +	retval = rt2800mmio_enable_radio(rt2x00dev); +	if (retval) +		return retval; -	rt2800_disable_radio(rt2x00dev); +	/* After resume MCU_BOOT_SIGNAL will trash these. */ +	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); +	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280); +	rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_RADIO_OFF, 0xff, 0x02); +	rt2800pci_mcu_status(rt2x00dev, TOKEN_RADIO_OFF); -	rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1); -	rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); +	rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, 0, 0); +	rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00); +	return retval;  }  static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,  			       enum dev_state state)  { -	/* -	 * Always put the device to sleep (even when we intend to wakeup!) -	 * if the device is booting and wasn't asleep it will return -	 * failure when attempting to wakeup. -	 */ -	rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2); -  	if (state == STATE_AWAKE) { -		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0); -		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); +		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKEUP, +				   0, 0x02); +		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKEUP); +	} else if (state == STATE_SLEEP) { +		rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_STATUS, +					  0xffffffff); +		rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CID, +					  0xffffffff); +		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, TOKEN_SLEEP, +				   0xff, 0x01);  	}  	return 0; @@ -460,13 +251,6 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,  	switch (state) {  	case STATE_RADIO_ON: -		/* -		 * Before the radio can be enabled, the device first has -		 * to be woken up. After that it needs a bit of time -		 * to be fully awake and then the radio can be enabled. -		 */ -		rt2800pci_set_state(rt2x00dev, STATE_AWAKE); -		msleep(1);  		retval = rt2800pci_enable_radio(rt2x00dev);  		break;  	case STATE_RADIO_OFF: @@ -474,18 +258,11 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,  		 * After the radio has been disabled, the device should  		 * be put to sleep for powersaving.  		 */ -		rt2800pci_disable_radio(rt2x00dev);  		rt2800pci_set_state(rt2x00dev, STATE_SLEEP);  		break; -	case STATE_RADIO_RX_ON: -	case STATE_RADIO_RX_OFF: -		rt2800pci_toggle_rx(rt2x00dev, state); -		break;  	case STATE_RADIO_IRQ_ON: -	case STATE_RADIO_IRQ_ON_ISR:  	case STATE_RADIO_IRQ_OFF: -	case STATE_RADIO_IRQ_OFF_ISR: -		rt2800pci_toggle_irq(rt2x00dev, state); +		rt2800mmio_toggle_irq(rt2x00dev, state);  		break;  	case STATE_DEEP_SLEEP:  	case STATE_SLEEP: @@ -499,428 +276,25 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,  	}  	if (unlikely(retval)) -		ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", -		      state, retval); +		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", +			   state, retval);  	return retval;  }  /* - * TX descriptor initialization - */ -static __le32 *rt2800pci_get_txwi(struct queue_entry *entry) -{ -	return (__le32 *) entry->skb->data; -} - -static void rt2800pci_write_tx_desc(struct queue_entry *entry, -				    struct txentry_desc *txdesc) -{ -	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; -	__le32 *txd = entry_priv->desc; -	u32 word; - -	/* -	 * The buffers pointed by SD_PTR0/SD_LEN0 and SD_PTR1/SD_LEN1 -	 * must contains a TXWI structure + 802.11 header + padding + 802.11 -	 * data. We choose to have SD_PTR0/SD_LEN0 only contains TXWI and -	 * SD_PTR1/SD_LEN1 contains 802.11 header + padding + 802.11 -	 * data. It means that LAST_SEC0 is always 0. -	 */ - -	/* -	 * Initialize TX descriptor -	 */ -	rt2x00_desc_read(txd, 0, &word); -	rt2x00_set_field32(&word, TXD_W0_SD_PTR0, skbdesc->skb_dma); -	rt2x00_desc_write(txd, 0, word); - -	rt2x00_desc_read(txd, 1, &word); -	rt2x00_set_field32(&word, TXD_W1_SD_LEN1, entry->skb->len); -	rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, -			   !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); -	rt2x00_set_field32(&word, TXD_W1_BURST, -			   test_bit(ENTRY_TXD_BURST, &txdesc->flags)); -	rt2x00_set_field32(&word, TXD_W1_SD_LEN0, TXWI_DESC_SIZE); -	rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0); -	rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); -	rt2x00_desc_write(txd, 1, word); - -	rt2x00_desc_read(txd, 2, &word); -	rt2x00_set_field32(&word, TXD_W2_SD_PTR1, -			   skbdesc->skb_dma + TXWI_DESC_SIZE); -	rt2x00_desc_write(txd, 2, word); - -	rt2x00_desc_read(txd, 3, &word); -	rt2x00_set_field32(&word, TXD_W3_WIV, -			   !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); -	rt2x00_set_field32(&word, TXD_W3_QSEL, 2); -	rt2x00_desc_write(txd, 3, word); - -	/* -	 * Register descriptor details in skb frame descriptor. -	 */ -	skbdesc->desc = txd; -	skbdesc->desc_len = TXD_DESC_SIZE; -} - -/* - * TX data initialization - */ -static void rt2800pci_kick_tx_queue(struct data_queue *queue) -{ -	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; -	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); -	unsigned int qidx; - -	if (queue->qid == QID_MGMT) -		qidx = 5; -	else -		qidx = queue->qid; - -	rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), entry->entry_idx); -} - -static void rt2800pci_kill_tx_queue(struct data_queue *queue) -{ -	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; -	u32 reg; - -	if (queue->qid == QID_BEACON) { -		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, 0); -		return; -	} - -	rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, (queue->qid == QID_AC_BE)); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, (queue->qid == QID_AC_BK)); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, (queue->qid == QID_AC_VI)); -	rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, (queue->qid == QID_AC_VO)); -	rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg); -} - -/* - * RX control handlers - */ -static void rt2800pci_fill_rxdone(struct queue_entry *entry, -				  struct rxdone_entry_desc *rxdesc) -{ -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; -	__le32 *rxd = entry_priv->desc; -	u32 word; - -	rt2x00_desc_read(rxd, 3, &word); - -	if (rt2x00_get_field32(word, RXD_W3_CRC_ERROR)) -		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - -	/* -	 * Unfortunately we don't know the cipher type used during -	 * decryption. This prevents us from correct providing -	 * correct statistics through debugfs. -	 */ -	rxdesc->cipher_status = rt2x00_get_field32(word, RXD_W3_CIPHER_ERROR); - -	if (rt2x00_get_field32(word, RXD_W3_DECRYPTED)) { -		/* -		 * Hardware has stripped IV/EIV data from 802.11 frame during -		 * decryption. Unfortunately the descriptor doesn't contain -		 * any fields with the EIV/IV data either, so they can't -		 * be restored by rt2x00lib. -		 */ -		rxdesc->flags |= RX_FLAG_IV_STRIPPED; - -		if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) -			rxdesc->flags |= RX_FLAG_DECRYPTED; -		else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) -			rxdesc->flags |= RX_FLAG_MMIC_ERROR; -	} - -	if (rt2x00_get_field32(word, RXD_W3_MY_BSS)) -		rxdesc->dev_flags |= RXDONE_MY_BSS; - -	if (rt2x00_get_field32(word, RXD_W3_L2PAD)) -		rxdesc->dev_flags |= RXDONE_L2PAD; - -	/* -	 * Process the RXWI structure that is at the start of the buffer. -	 */ -	rt2800_process_rxwi(entry, rxdesc); -} - -/* - * Interrupt functions. - */ -static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) -{ -	struct ieee80211_conf conf = { .flags = 0 }; -	struct rt2x00lib_conf libconf = { .conf = &conf }; - -	rt2800_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); -} - -static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) -{ -	struct data_queue *queue; -	struct queue_entry *entry; -	u32 status; -	u8 qid; - -	while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) { -		/* Now remove the tx status from the FIFO */ -		if (kfifo_out(&rt2x00dev->txstatus_fifo, &status, -			      sizeof(status)) != sizeof(status)) { -			WARN_ON(1); -			break; -		} - -		qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); -		if (qid >= QID_RX) { -			/* -			 * Unknown queue, this shouldn't happen. Just drop -			 * this tx status. -			 */ -			WARNING(rt2x00dev, "Got TX status report with " -					   "unexpected pid %u, dropping", qid); -			break; -		} - -		queue = rt2x00queue_get_queue(rt2x00dev, qid); -		if (unlikely(queue == NULL)) { -			/* -			 * The queue is NULL, this shouldn't happen. Stop -			 * processing here and drop the tx status -			 */ -			WARNING(rt2x00dev, "Got TX status for an unavailable " -					   "queue %u, dropping", qid); -			break; -		} - -		if (rt2x00queue_empty(queue)) { -			/* -			 * The queue is empty. Stop processing here -			 * and drop the tx status. -			 */ -			WARNING(rt2x00dev, "Got TX status for an empty " -					   "queue %u, dropping", qid); -			break; -		} - -		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); -		rt2800_txdone_entry(entry, status); -	} -} - -static void rt2800pci_txstatus_tasklet(unsigned long data) -{ -	rt2800pci_txdone((struct rt2x00_dev *)data); -} - -static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) -{ -	struct rt2x00_dev *rt2x00dev = dev_instance; -	u32 reg = rt2x00dev->irqvalue[0]; - -	/* -	 * 1 - Pre TBTT interrupt. -	 */ -	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) -		rt2x00lib_pretbtt(rt2x00dev); - -	/* -	 * 2 - Beacondone interrupt. -	 */ -	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) -		rt2x00lib_beacondone(rt2x00dev); - -	/* -	 * 3 - Rx ring done interrupt. -	 */ -	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) -		rt2x00pci_rxdone(rt2x00dev); - -	/* -	 * 4 - Auto wakeup interrupt. -	 */ -	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) -		rt2800pci_wakeup(rt2x00dev); - -	/* Enable interrupts again. */ -	rt2x00dev->ops->lib->set_device_state(rt2x00dev, -					      STATE_RADIO_IRQ_ON_ISR); - -	return IRQ_HANDLED; -} - -static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) -{ -	u32 status; -	int i; - -	/* -	 * The TX_FIFO_STATUS interrupt needs special care. We should -	 * read TX_STA_FIFO but we should do it immediately as otherwise -	 * the register can overflow and we would lose status reports. -	 * -	 * Hence, read the TX_STA_FIFO register and copy all tx status -	 * reports into a kernel FIFO which is handled in the txstatus -	 * tasklet. We use a tasklet to process the tx status reports -	 * because we can schedule the tasklet multiple times (when the -	 * interrupt fires again during tx status processing). -	 * -	 * Furthermore we don't disable the TX_FIFO_STATUS -	 * interrupt here but leave it enabled so that the TX_STA_FIFO -	 * can also be read while the interrupt thread gets executed. -	 * -	 * Since we have only one producer and one consumer we don't -	 * need to lock the kfifo. -	 */ -	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { -		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status); - -		if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID)) -			break; - -		if (kfifo_is_full(&rt2x00dev->txstatus_fifo)) { -			WARNING(rt2x00dev, "TX status FIFO overrun," -				" drop tx status report.\n"); -			break; -		} - -		if (kfifo_in(&rt2x00dev->txstatus_fifo, &status, -			     sizeof(status)) != sizeof(status)) { -			WARNING(rt2x00dev, "TX status FIFO overrun," -				"drop tx status report.\n"); -			break; -		} -	} - -	/* Schedule the tasklet for processing the tx status. */ -	tasklet_schedule(&rt2x00dev->txstatus_tasklet); -} - -static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) -{ -	struct rt2x00_dev *rt2x00dev = dev_instance; -	u32 reg; -	irqreturn_t ret = IRQ_HANDLED; - -	/* Read status and ACK all interrupts */ -	rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, ®); -	rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg); - -	if (!reg) -		return IRQ_NONE; - -	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) -		return IRQ_HANDLED; - -	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) -		rt2800pci_txstatus_interrupt(rt2x00dev); - -	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT) || -	    rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT) || -	    rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE) || -	    rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) { -		/* -		 * All other interrupts are handled in the interrupt thread. -		 * Store irqvalue for use in the interrupt thread. -		 */ -		rt2x00dev->irqvalue[0] = reg; - -		/* -		 * Disable interrupts, will be enabled again in the -		 * interrupt thread. -		*/ -		rt2x00dev->ops->lib->set_device_state(rt2x00dev, -						      STATE_RADIO_IRQ_OFF_ISR); - -		/* -		 * Leave the TX_FIFO_STATUS interrupt enabled to not lose any -		 * tx status reports. -		 */ -		rt2800_register_read(rt2x00dev, INT_MASK_CSR, ®); -		rt2x00_set_field32(®, INT_MASK_CSR_TX_FIFO_STATUS, 1); -		rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg); - -		ret = IRQ_WAKE_THREAD; -	} - -	return ret; -} - -/*   * Device probe functions.   */ -static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) -{ -	/* -	 * Read EEPROM into buffer -	 */ -	if (rt2x00_is_soc(rt2x00dev)) -		rt2800pci_read_eeprom_soc(rt2x00dev); -	else if (rt2800pci_efuse_detect(rt2x00dev)) -		rt2800pci_read_eeprom_efuse(rt2x00dev); -	else -		rt2800pci_read_eeprom_pci(rt2x00dev); - -	return rt2800_validate_eeprom(rt2x00dev); -} - -static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) +static int rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev)  {  	int retval; -	/* -	 * Allocate eeprom data. -	 */ -	retval = rt2800pci_validate_eeprom(rt2x00dev); -	if (retval) -		return retval; - -	retval = rt2800_init_eeprom(rt2x00dev); -	if (retval) -		return retval; - -	/* -	 * Initialize hw specifications. -	 */ -	retval = rt2800_probe_hw_mode(rt2x00dev); -	if (retval) -		return retval; - -	/* -	 * This device has multiple filters for control frames -	 * and has a separate filter for PS Poll frames. -	 */ -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); - -	/* -	 * This device has a pre tbtt interrupt and thus fetches -	 * a new beacon directly prior to transmission. -	 */ -	__set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags); - -	/* -	 * This device requires firmware. -	 */ -	if (!rt2x00_is_soc(rt2x00dev)) -		__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags); -	if (!modparam_nohwcrypt) -		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); - -	/* -	 * Set the rssi offset. -	 */ -	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; +	if (rt2800pci_efuse_detect(rt2x00dev)) +		retval = rt2800pci_read_eeprom_efuse(rt2x00dev); +	else +		retval = rt2800pci_read_eeprom_pci(rt2x00dev); -	return 0; +	return retval;  }  static const struct ieee80211_ops rt2800pci_mac80211_ops = { @@ -937,50 +311,65 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {  	.get_stats		= rt2x00mac_get_stats,  	.get_tkip_seq		= rt2800_get_tkip_seq,  	.set_rts_threshold	= rt2800_set_rts_threshold, +	.sta_add		= rt2x00mac_sta_add, +	.sta_remove		= rt2x00mac_sta_remove,  	.bss_info_changed	= rt2x00mac_bss_info_changed,  	.conf_tx		= rt2800_conf_tx,  	.get_tsf		= rt2800_get_tsf,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.ampdu_action		= rt2800_ampdu_action,  	.flush			= rt2x00mac_flush, +	.get_survey		= rt2800_get_survey, +	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2800_ops rt2800pci_rt2800_ops = { -	.register_read		= rt2x00pci_register_read, -	.register_read_lock	= rt2x00pci_register_read, /* same for PCI */ -	.register_write		= rt2x00pci_register_write, -	.register_write_lock	= rt2x00pci_register_write, /* same for PCI */ -	.register_multiread	= rt2x00pci_register_multiread, -	.register_multiwrite	= rt2x00pci_register_multiwrite, -	.regbusy_read		= rt2x00pci_regbusy_read, +	.register_read		= rt2x00mmio_register_read, +	.register_read_lock	= rt2x00mmio_register_read, /* same for PCI */ +	.register_write		= rt2x00mmio_register_write, +	.register_write_lock	= rt2x00mmio_register_write, /* same for PCI */ +	.register_multiread	= rt2x00mmio_register_multiread, +	.register_multiwrite	= rt2x00mmio_register_multiwrite, +	.regbusy_read		= rt2x00mmio_regbusy_read, +	.read_eeprom		= rt2800pci_read_eeprom, +	.hwcrypt_disabled	= rt2800pci_hwcrypt_disabled,  	.drv_write_firmware	= rt2800pci_write_firmware, -	.drv_init_registers	= rt2800pci_init_registers, -	.drv_get_txwi		= rt2800pci_get_txwi, +	.drv_init_registers	= rt2800mmio_init_registers, +	.drv_get_txwi		= rt2800mmio_get_txwi,  };  static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { -	.irq_handler		= rt2800pci_interrupt, -	.irq_handler_thread	= rt2800pci_interrupt_thread, -	.txstatus_tasklet       = rt2800pci_txstatus_tasklet, -	.probe_hw		= rt2800pci_probe_hw, +	.irq_handler		= rt2800mmio_interrupt, +	.txstatus_tasklet	= rt2800mmio_txstatus_tasklet, +	.pretbtt_tasklet	= rt2800mmio_pretbtt_tasklet, +	.tbtt_tasklet		= rt2800mmio_tbtt_tasklet, +	.rxdone_tasklet		= rt2800mmio_rxdone_tasklet, +	.autowake_tasklet	= rt2800mmio_autowake_tasklet, +	.probe_hw		= rt2800_probe_hw,  	.get_firmware_name	= rt2800pci_get_firmware_name,  	.check_firmware		= rt2800_check_firmware,  	.load_firmware		= rt2800_load_firmware, -	.initialize		= rt2x00pci_initialize, -	.uninitialize		= rt2x00pci_uninitialize, -	.get_entry_state	= rt2800pci_get_entry_state, -	.clear_entry		= rt2800pci_clear_entry, +	.initialize		= rt2x00mmio_initialize, +	.uninitialize		= rt2x00mmio_uninitialize, +	.get_entry_state	= rt2800mmio_get_entry_state, +	.clear_entry		= rt2800mmio_clear_entry,  	.set_device_state	= rt2800pci_set_device_state,  	.rfkill_poll		= rt2800_rfkill_poll,  	.link_stats		= rt2800_link_stats,  	.reset_tuner		= rt2800_reset_tuner,  	.link_tuner		= rt2800_link_tuner, -	.write_tx_desc		= rt2800pci_write_tx_desc, +	.gain_calibration	= rt2800_gain_calibration, +	.vco_calibration	= rt2800_vco_calibration, +	.start_queue		= rt2800mmio_start_queue, +	.kick_queue		= rt2800mmio_kick_queue, +	.stop_queue		= rt2800mmio_stop_queue, +	.flush_queue		= rt2x00mmio_flush_queue, +	.write_tx_desc		= rt2800mmio_write_tx_desc,  	.write_tx_data		= rt2800_write_tx_data,  	.write_beacon		= rt2800_write_beacon, -	.kick_tx_queue		= rt2800pci_kick_tx_queue, -	.kill_tx_queue		= rt2800pci_kill_tx_queue, -	.fill_rxdone		= rt2800pci_fill_rxdone, +	.clear_beacon		= rt2800_clear_beacon, +	.fill_rxdone		= rt2800mmio_fill_rxdone,  	.config_shared_key	= rt2800_config_shared_key,  	.config_pairwise_key	= rt2800_config_pairwise_key,  	.config_filter		= rt2800_config_filter, @@ -988,40 +377,18 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {  	.config_erp		= rt2800_config_erp,  	.config_ant		= rt2800_config_ant,  	.config			= rt2800_config, -}; - -static const struct data_queue_desc rt2800pci_queue_rx = { -	.entry_num		= 128, -	.data_size		= AGGREGATION_SIZE, -	.desc_size		= RXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; - -static const struct data_queue_desc rt2800pci_queue_tx = { -	.entry_num		= 64, -	.data_size		= AGGREGATION_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; - -static const struct data_queue_desc rt2800pci_queue_bcn = { -	.entry_num		= 8, -	.data_size		= 0, /* No DMA required for beacons */ -	.desc_size		= TXWI_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), +	.sta_add		= rt2800_sta_add, +	.sta_remove		= rt2800_sta_remove,  };  static const struct rt2x00_ops rt2800pci_ops = {  	.name			= KBUILD_MODNAME, -	.max_sta_intf		= 1, +	.drv_data_size		= sizeof(struct rt2800_drv_data),  	.max_ap_intf		= 8,  	.eeprom_size		= EEPROM_SIZE,  	.rf_size		= RF_SIZE,  	.tx_queues		= NUM_TX_QUEUES, -	.extra_tx_headroom	= TXWI_DESC_SIZE, -	.rx			= &rt2800pci_queue_rx, -	.tx			= &rt2800pci_queue_tx, -	.bcn			= &rt2800pci_queue_bcn, +	.queue_init		= rt2800mmio_queue_init,  	.lib			= &rt2800pci_rt2x00_ops,  	.drv			= &rt2800pci_rt2800_ops,  	.hw			= &rt2800pci_mac80211_ops, @@ -1033,109 +400,72 @@ static const struct rt2x00_ops rt2800pci_ops = {  /*   * RT2800pci module information.   */ -#ifdef CONFIG_PCI  static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { -	{ PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7738), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0601) }, +	{ PCI_DEVICE(0x1814, 0x0681) }, +	{ PCI_DEVICE(0x1814, 0x0701) }, +	{ PCI_DEVICE(0x1814, 0x0781) }, +	{ PCI_DEVICE(0x1814, 0x3090) }, +	{ PCI_DEVICE(0x1814, 0x3091) }, +	{ PCI_DEVICE(0x1814, 0x3092) }, +	{ PCI_DEVICE(0x1432, 0x7708) }, +	{ PCI_DEVICE(0x1432, 0x7727) }, +	{ PCI_DEVICE(0x1432, 0x7728) }, +	{ PCI_DEVICE(0x1432, 0x7738) }, +	{ PCI_DEVICE(0x1432, 0x7748) }, +	{ PCI_DEVICE(0x1432, 0x7758) }, +	{ PCI_DEVICE(0x1432, 0x7768) }, +	{ PCI_DEVICE(0x1462, 0x891a) }, +	{ PCI_DEVICE(0x1a3b, 0x1059) }, +#ifdef CONFIG_RT2800PCI_RT3290 +	{ PCI_DEVICE(0x1814, 0x3290) }, +#endif  #ifdef CONFIG_RT2800PCI_RT33XX -	{ PCI_DEVICE(0x1814, 0x3390), PCI_DEVICE_DATA(&rt2800pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x3390) },  #endif  #ifdef CONFIG_RT2800PCI_RT35XX -	{ PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) }, -	{ PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) }, +	{ PCI_DEVICE(0x1432, 0x7711) }, +	{ PCI_DEVICE(0x1432, 0x7722) }, +	{ PCI_DEVICE(0x1814, 0x3060) }, +	{ PCI_DEVICE(0x1814, 0x3062) }, +	{ PCI_DEVICE(0x1814, 0x3562) }, +	{ PCI_DEVICE(0x1814, 0x3592) }, +	{ PCI_DEVICE(0x1814, 0x3593) }, +	{ PCI_DEVICE(0x1814, 0x359f) }, +#endif +#ifdef CONFIG_RT2800PCI_RT53XX +	{ PCI_DEVICE(0x1814, 0x5360) }, +	{ PCI_DEVICE(0x1814, 0x5362) }, +	{ PCI_DEVICE(0x1814, 0x5390) }, +	{ PCI_DEVICE(0x1814, 0x5392) }, +	{ PCI_DEVICE(0x1814, 0x539a) }, +	{ PCI_DEVICE(0x1814, 0x539b) }, +	{ PCI_DEVICE(0x1814, 0x539f) },  #endif  	{ 0, }  }; -#endif /* CONFIG_PCI */  MODULE_AUTHOR(DRV_PROJECT);  MODULE_VERSION(DRV_VERSION);  MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver.");  MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards"); -#ifdef CONFIG_PCI  MODULE_FIRMWARE(FIRMWARE_RT2860);  MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); -#endif /* CONFIG_PCI */  MODULE_LICENSE("GPL"); -#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) -static int rt2800soc_probe(struct platform_device *pdev) +static int rt2800pci_probe(struct pci_dev *pci_dev, +			   const struct pci_device_id *id)  { -	return rt2x00soc_probe(pdev, &rt2800pci_ops); +	return rt2x00pci_probe(pci_dev, &rt2800pci_ops);  } -static struct platform_driver rt2800soc_driver = { -	.driver		= { -		.name		= "rt2800_wmac", -		.owner		= THIS_MODULE, -		.mod_name	= KBUILD_MODNAME, -	}, -	.probe		= rt2800soc_probe, -	.remove		= __devexit_p(rt2x00soc_remove), -	.suspend	= rt2x00soc_suspend, -	.resume		= rt2x00soc_resume, -}; -#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ - -#ifdef CONFIG_PCI  static struct pci_driver rt2800pci_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt2800pci_device_table, -	.probe		= rt2x00pci_probe, -	.remove		= __devexit_p(rt2x00pci_remove), +	.probe		= rt2800pci_probe, +	.remove		= rt2x00pci_remove,  	.suspend	= rt2x00pci_suspend,  	.resume		= rt2x00pci_resume,  }; -#endif /* CONFIG_PCI */ - -static int __init rt2800pci_init(void) -{ -	int ret = 0; - -#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) -	ret = platform_driver_register(&rt2800soc_driver); -	if (ret) -		return ret; -#endif -#ifdef CONFIG_PCI -	ret = pci_register_driver(&rt2800pci_driver); -	if (ret) { -#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) -		platform_driver_unregister(&rt2800soc_driver); -#endif -		return ret; -	} -#endif - -	return ret; -} - -static void __exit rt2800pci_exit(void) -{ -#ifdef CONFIG_PCI -	pci_unregister_driver(&rt2800pci_driver); -#endif -#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) -	platform_driver_unregister(&rt2800soc_driver); -#endif -} -module_init(rt2800pci_init); -module_exit(rt2800pci_exit); +module_pci_driver(rt2800pci_driver); diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h index 70e050d904c..9dfef4607d6 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.h +++ b/drivers/net/wireless/rt2x00/rt2800pci.h @@ -20,9 +20,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -35,106 +33,10 @@  #define RT2800PCI_H  /* - * Queue register offset macros - */ -#define TX_QUEUE_REG_OFFSET		0x10 -#define TX_BASE_PTR(__x)		(TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET)) -#define TX_MAX_CNT(__x)			(TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET)) -#define TX_CTX_IDX(__x)			(TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) -#define TX_DTX_IDX(__x)			(TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)) - -/*   * 8051 firmware image.   */  #define FIRMWARE_RT2860			"rt2860.bin" +#define FIRMWARE_RT3290			"rt3290.bin"  #define FIRMWARE_IMAGE_BASE		0x2000 -/* - * DMA descriptor defines. - */ -#define TXD_DESC_SIZE			(4 * sizeof(__le32)) -#define RXD_DESC_SIZE			(4 * sizeof(__le32)) - -/* - * TX descriptor format for TX, PRIO and Beacon Ring. - */ - -/* - * Word0 - */ -#define TXD_W0_SD_PTR0			FIELD32(0xffffffff) - -/* - * Word1 - */ -#define TXD_W1_SD_LEN1			FIELD32(0x00003fff) -#define TXD_W1_LAST_SEC1		FIELD32(0x00004000) -#define TXD_W1_BURST			FIELD32(0x00008000) -#define TXD_W1_SD_LEN0			FIELD32(0x3fff0000) -#define TXD_W1_LAST_SEC0		FIELD32(0x40000000) -#define TXD_W1_DMA_DONE			FIELD32(0x80000000) - -/* - * Word2 - */ -#define TXD_W2_SD_PTR1			FIELD32(0xffffffff) - -/* - * Word3 - * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI - * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. - *       0:MGMT, 1:HCCA 2:EDCA - */ -#define TXD_W3_WIV			FIELD32(0x01000000) -#define TXD_W3_QSEL			FIELD32(0x06000000) -#define TXD_W3_TCO			FIELD32(0x20000000) -#define TXD_W3_UCO			FIELD32(0x40000000) -#define TXD_W3_ICO			FIELD32(0x80000000) - -/* - * RX descriptor format for RX Ring. - */ - -/* - * Word0 - */ -#define RXD_W0_SDP0			FIELD32(0xffffffff) - -/* - * Word1 - */ -#define RXD_W1_SDL1			FIELD32(0x00003fff) -#define RXD_W1_SDL0			FIELD32(0x3fff0000) -#define RXD_W1_LS0			FIELD32(0x40000000) -#define RXD_W1_DMA_DONE			FIELD32(0x80000000) - -/* - * Word2 - */ -#define RXD_W2_SDP1			FIELD32(0xffffffff) - -/* - * Word3 - * AMSDU: RX with 802.3 header, not 802.11 header. - * DECRYPTED: This frame is being decrypted. - */ -#define RXD_W3_BA			FIELD32(0x00000001) -#define RXD_W3_DATA			FIELD32(0x00000002) -#define RXD_W3_NULLDATA			FIELD32(0x00000004) -#define RXD_W3_FRAG			FIELD32(0x00000008) -#define RXD_W3_UNICAST_TO_ME		FIELD32(0x00000010) -#define RXD_W3_MULTICAST		FIELD32(0x00000020) -#define RXD_W3_BROADCAST		FIELD32(0x00000040) -#define RXD_W3_MY_BSS			FIELD32(0x00000080) -#define RXD_W3_CRC_ERROR		FIELD32(0x00000100) -#define RXD_W3_CIPHER_ERROR		FIELD32(0x00000600) -#define RXD_W3_AMSDU			FIELD32(0x00000800) -#define RXD_W3_HTC			FIELD32(0x00001000) -#define RXD_W3_RSSI			FIELD32(0x00002000) -#define RXD_W3_L2PAD			FIELD32(0x00004000) -#define RXD_W3_AMPDU			FIELD32(0x00008000) -#define RXD_W3_DECRYPTED		FIELD32(0x00010000) -#define RXD_W3_PLCP_SIGNAL		FIELD32(0x00020000) -#define RXD_W3_PLCP_RSSI		FIELD32(0x00040000) -  #endif /* RT2800PCI_H */ diff --git a/drivers/net/wireless/rt2x00/rt2800soc.c b/drivers/net/wireless/rt2x00/rt2800soc.c new file mode 100644 index 00000000000..f6d1bf5be00 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800soc.c @@ -0,0 +1,261 @@ +/*	Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> + *	Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> + *	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> + *	Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> + *	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> + *	Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com> + *	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> + *	Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com> + *	<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, see <http://www.gnu.org/licenses/>. + */ + +/*	Module: rt2800soc + *	Abstract: rt2800 WiSoC specific routines. + */ + +#include <linux/etherdevice.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include "rt2x00.h" +#include "rt2x00mmio.h" +#include "rt2x00soc.h" +#include "rt2800.h" +#include "rt2800lib.h" +#include "rt2800mmio.h" + +/* Allow hardware encryption to be disabled. */ +static bool modparam_nohwcrypt; +module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); +MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); + +static bool rt2800soc_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) +{ +	return modparam_nohwcrypt; +} + +static void rt2800soc_disable_radio(struct rt2x00_dev *rt2x00dev) +{ +	rt2800_disable_radio(rt2x00dev); +	rt2x00mmio_register_write(rt2x00dev, PWR_PIN_CFG, 0); +	rt2x00mmio_register_write(rt2x00dev, TX_PIN_CFG, 0); +} + +static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev, +				      enum dev_state state) +{ +	int retval = 0; + +	switch (state) { +	case STATE_RADIO_ON: +		retval = rt2800mmio_enable_radio(rt2x00dev); +		break; + +	case STATE_RADIO_OFF: +		rt2800soc_disable_radio(rt2x00dev); +		break; + +	case STATE_RADIO_IRQ_ON: +	case STATE_RADIO_IRQ_OFF: +		rt2800mmio_toggle_irq(rt2x00dev, state); +		break; + +	case STATE_DEEP_SLEEP: +	case STATE_SLEEP: +	case STATE_STANDBY: +	case STATE_AWAKE: +		/* These states are not supported, but don't report an error */ +		retval = 0; +		break; + +	default: +		retval = -ENOTSUPP; +		break; +	} + +	if (unlikely(retval)) +		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", +			   state, retval); + +	return retval; +} + +static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev) +{ +	void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); + +	if (!base_addr) +		return -ENOMEM; + +	memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); + +	iounmap(base_addr); +	return 0; +} + +/* Firmware functions */ +static char *rt2800soc_get_firmware_name(struct rt2x00_dev *rt2x00dev) +{ +	WARN_ON_ONCE(1); +	return NULL; +} + +static int rt2800soc_load_firmware(struct rt2x00_dev *rt2x00dev, +				   const u8 *data, const size_t len) +{ +	WARN_ON_ONCE(1); +	return 0; +} + +static int rt2800soc_check_firmware(struct rt2x00_dev *rt2x00dev, +				    const u8 *data, const size_t len) +{ +	WARN_ON_ONCE(1); +	return 0; +} + +static int rt2800soc_write_firmware(struct rt2x00_dev *rt2x00dev, +				    const u8 *data, const size_t len) +{ +	WARN_ON_ONCE(1); +	return 0; +} + +static const struct ieee80211_ops rt2800soc_mac80211_ops = { +	.tx			= rt2x00mac_tx, +	.start			= rt2x00mac_start, +	.stop			= rt2x00mac_stop, +	.add_interface		= rt2x00mac_add_interface, +	.remove_interface	= rt2x00mac_remove_interface, +	.config			= rt2x00mac_config, +	.configure_filter	= rt2x00mac_configure_filter, +	.set_key		= rt2x00mac_set_key, +	.sw_scan_start		= rt2x00mac_sw_scan_start, +	.sw_scan_complete	= rt2x00mac_sw_scan_complete, +	.get_stats		= rt2x00mac_get_stats, +	.get_tkip_seq		= rt2800_get_tkip_seq, +	.set_rts_threshold	= rt2800_set_rts_threshold, +	.sta_add		= rt2x00mac_sta_add, +	.sta_remove		= rt2x00mac_sta_remove, +	.bss_info_changed	= rt2x00mac_bss_info_changed, +	.conf_tx		= rt2800_conf_tx, +	.get_tsf		= rt2800_get_tsf, +	.rfkill_poll		= rt2x00mac_rfkill_poll, +	.ampdu_action		= rt2800_ampdu_action, +	.flush			= rt2x00mac_flush, +	.get_survey		= rt2800_get_survey, +	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending, +}; + +static const struct rt2800_ops rt2800soc_rt2800_ops = { +	.register_read		= rt2x00mmio_register_read, +	.register_read_lock	= rt2x00mmio_register_read, /* same for SoCs */ +	.register_write		= rt2x00mmio_register_write, +	.register_write_lock	= rt2x00mmio_register_write, /* same for SoCs */ +	.register_multiread	= rt2x00mmio_register_multiread, +	.register_multiwrite	= rt2x00mmio_register_multiwrite, +	.regbusy_read		= rt2x00mmio_regbusy_read, +	.read_eeprom		= rt2800soc_read_eeprom, +	.hwcrypt_disabled	= rt2800soc_hwcrypt_disabled, +	.drv_write_firmware	= rt2800soc_write_firmware, +	.drv_init_registers	= rt2800mmio_init_registers, +	.drv_get_txwi		= rt2800mmio_get_txwi, +}; + +static const struct rt2x00lib_ops rt2800soc_rt2x00_ops = { +	.irq_handler		= rt2800mmio_interrupt, +	.txstatus_tasklet	= rt2800mmio_txstatus_tasklet, +	.pretbtt_tasklet	= rt2800mmio_pretbtt_tasklet, +	.tbtt_tasklet		= rt2800mmio_tbtt_tasklet, +	.rxdone_tasklet		= rt2800mmio_rxdone_tasklet, +	.autowake_tasklet	= rt2800mmio_autowake_tasklet, +	.probe_hw		= rt2800_probe_hw, +	.get_firmware_name	= rt2800soc_get_firmware_name, +	.check_firmware		= rt2800soc_check_firmware, +	.load_firmware		= rt2800soc_load_firmware, +	.initialize		= rt2x00mmio_initialize, +	.uninitialize		= rt2x00mmio_uninitialize, +	.get_entry_state	= rt2800mmio_get_entry_state, +	.clear_entry		= rt2800mmio_clear_entry, +	.set_device_state	= rt2800soc_set_device_state, +	.rfkill_poll		= rt2800_rfkill_poll, +	.link_stats		= rt2800_link_stats, +	.reset_tuner		= rt2800_reset_tuner, +	.link_tuner		= rt2800_link_tuner, +	.gain_calibration	= rt2800_gain_calibration, +	.vco_calibration	= rt2800_vco_calibration, +	.start_queue		= rt2800mmio_start_queue, +	.kick_queue		= rt2800mmio_kick_queue, +	.stop_queue		= rt2800mmio_stop_queue, +	.flush_queue		= rt2x00mmio_flush_queue, +	.write_tx_desc		= rt2800mmio_write_tx_desc, +	.write_tx_data		= rt2800_write_tx_data, +	.write_beacon		= rt2800_write_beacon, +	.clear_beacon		= rt2800_clear_beacon, +	.fill_rxdone		= rt2800mmio_fill_rxdone, +	.config_shared_key	= rt2800_config_shared_key, +	.config_pairwise_key	= rt2800_config_pairwise_key, +	.config_filter		= rt2800_config_filter, +	.config_intf		= rt2800_config_intf, +	.config_erp		= rt2800_config_erp, +	.config_ant		= rt2800_config_ant, +	.config			= rt2800_config, +	.sta_add		= rt2800_sta_add, +	.sta_remove		= rt2800_sta_remove, +}; + +static const struct rt2x00_ops rt2800soc_ops = { +	.name			= KBUILD_MODNAME, +	.drv_data_size		= sizeof(struct rt2800_drv_data), +	.max_ap_intf		= 8, +	.eeprom_size		= EEPROM_SIZE, +	.rf_size		= RF_SIZE, +	.tx_queues		= NUM_TX_QUEUES, +	.queue_init		= rt2800mmio_queue_init, +	.lib			= &rt2800soc_rt2x00_ops, +	.drv			= &rt2800soc_rt2800_ops, +	.hw			= &rt2800soc_mac80211_ops, +#ifdef CONFIG_RT2X00_LIB_DEBUGFS +	.debugfs		= &rt2800_rt2x00debug, +#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ +}; + +static int rt2800soc_probe(struct platform_device *pdev) +{ +	return rt2x00soc_probe(pdev, &rt2800soc_ops); +} + +static struct platform_driver rt2800soc_driver = { +	.driver		= { +		.name		= "rt2800_wmac", +		.owner		= THIS_MODULE, +		.mod_name	= KBUILD_MODNAME, +	}, +	.probe		= rt2800soc_probe, +	.remove		= rt2x00soc_remove, +	.suspend	= rt2x00soc_suspend, +	.resume		= rt2x00soc_resume, +}; + +module_platform_driver(rt2800soc_driver); + +MODULE_AUTHOR(DRV_PROJECT); +MODULE_VERSION(DRV_VERSION); +MODULE_DESCRIPTION("Ralink WiSoC Wireless LAN driver."); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 935b76d3ce4..832006b5aab 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -18,9 +18,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -31,7 +29,6 @@  #include <linux/delay.h>  #include <linux/etherdevice.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/usb.h> @@ -45,13 +42,218 @@  /*   * Allow hardware encryption to be disabled.   */ -static int modparam_nohwcrypt; +static bool modparam_nohwcrypt;  module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);  MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +static bool rt2800usb_hwcrypt_disabled(struct rt2x00_dev *rt2x00dev) +{ +	return modparam_nohwcrypt; +} + +/* + * Queue handlers. + */ +static void rt2800usb_start_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_RX: +		rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); +		rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); +		rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +		break; +	case QID_BEACON: +		rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); +		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); +		rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); +		rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); +		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); +		break; +	default: +		break; +	} +} + +static void rt2800usb_stop_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_RX: +		rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); +		rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); +		rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +		break; +	case QID_BEACON: +		rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); +		rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); +		rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); +		rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); +		rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); +		break; +	default: +		break; +	} +} + +/* + * test if there is an entry in any TX queue for which DMA is done + * but the TX status has not been returned yet + */ +static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue; + +	tx_queue_for_each(rt2x00dev, queue) { +		if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) != +		    rt2x00queue_get_entry(queue, Q_INDEX_DONE)) +			return true; +	} +	return false; +} + +static inline bool rt2800usb_entry_txstatus_timeout(struct queue_entry *entry) +{ +	bool tout; + +	if (!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) +		return false; + +	tout = time_after(jiffies, entry->last_action + msecs_to_jiffies(100)); +	if (unlikely(tout)) +		rt2x00_dbg(entry->queue->rt2x00dev, +			   "TX status timeout for entry %d in queue %d\n", +			   entry->entry_idx, entry->queue->qid); +	return tout; + +} + +static bool rt2800usb_txstatus_timeout(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue; +	struct queue_entry *entry; + +	tx_queue_for_each(rt2x00dev, queue) { +		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); +		if (rt2800usb_entry_txstatus_timeout(entry)) +			return true; +	} +	return false; +} + +#define TXSTATUS_READ_INTERVAL 1000000 + +static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, +						 int urb_status, u32 tx_status) +{ +	bool valid; + +	if (urb_status) { +		rt2x00_warn(rt2x00dev, "TX status read failed %d\n", +			    urb_status); + +		goto stop_reading; +	} + +	valid = rt2x00_get_field32(tx_status, TX_STA_FIFO_VALID); +	if (valid) { +		if (!kfifo_put(&rt2x00dev->txstatus_fifo, tx_status)) +			rt2x00_warn(rt2x00dev, "TX status FIFO overrun\n"); + +		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); + +		/* Reschedule urb to read TX status again instantly */ +		return true; +	} + +	/* Check if there is any entry that timedout waiting on TX status */ +	if (rt2800usb_txstatus_timeout(rt2x00dev)) +		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); + +	if (rt2800usb_txstatus_pending(rt2x00dev)) { +		/* Read register after 1 ms */ +		hrtimer_start(&rt2x00dev->txstatus_timer, +			      ktime_set(0, TXSTATUS_READ_INTERVAL), +			      HRTIMER_MODE_REL); +		return false; +	} + +stop_reading: +	clear_bit(TX_STATUS_READING, &rt2x00dev->flags); +	/* +	 * There is small race window above, between txstatus pending check and +	 * clear_bit someone could do rt2x00usb_interrupt_txdone, so recheck +	 * here again if status reading is needed. +	 */ +	if (rt2800usb_txstatus_pending(rt2x00dev) && +	    !test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) +		return true; +	else +		return false; +} + +static void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev) +{ + +	if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) +		return; + +	/* Read TX_STA_FIFO register after 2 ms */ +	hrtimer_start(&rt2x00dev->txstatus_timer, +		      ktime_set(0, 2*TXSTATUS_READ_INTERVAL), +		      HRTIMER_MODE_REL); +} + +static void rt2800usb_tx_dma_done(struct queue_entry *entry) +{ +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + +	rt2800usb_async_read_tx_status(rt2x00dev); +} + +static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer) +{ +	struct rt2x00_dev *rt2x00dev = +	    container_of(timer, struct rt2x00_dev, txstatus_timer); + +	rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO, +				      rt2800usb_tx_sta_fifo_read_completed); + +	return HRTIMER_NORESTART; +} +  /*   * Firmware functions   */ +static int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev) +{ +	__le32 *reg; +	u32 fw_mode; + +	reg = kmalloc(sizeof(*reg), GFP_KERNEL); +	if (reg == NULL) +		return -ENOMEM; +	/* cannot use rt2x00usb_register_read here as it uses different +	 * mode (MULTI_READ vs. DEVICE_MODE) and does not pass the +	 * magic value USB_MODE_AUTORUN (0x11) to the device, thus the +	 * returned value would be invalid. +	 */ +	rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE, +				 USB_VENDOR_REQUEST_IN, 0, USB_MODE_AUTORUN, +				 reg, sizeof(*reg), REGISTER_TIMEOUT_FIRMWARE); +	fw_mode = le32_to_cpu(*reg); +	kfree(reg); + +	if ((fw_mode & 0x00000003) == 2) +		return 1; + +	return 0; +} +  static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)  {  	return FIRMWARE_RT2870; @@ -63,6 +265,7 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,  	int status;  	u32 offset;  	u32 length; +	int retval;  	/*  	 * Check which section of the firmware we need. @@ -80,11 +283,19 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,  	/*  	 * Write firmware to device.  	 */ -	rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, -				   data + offset, length); +	retval = rt2800usb_autorun_detect(rt2x00dev); +	if (retval < 0) +		return retval; +	if (retval) { +		rt2x00_info(rt2x00dev, +			    "Firmware loading not required - NIC in AutoRun mode\n"); +	} else { +		rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, +					      data + offset, length); +	} -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); +	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); +	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);  	/*  	 * Send firmware request to device to load firmware, @@ -94,12 +305,12 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,  					     0, USB_MODE_FIRMWARE,  					     REGISTER_TIMEOUT_FIRMWARE);  	if (status < 0) { -		ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); +		rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");  		return status;  	}  	msleep(10); -	rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +	rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);  	return 0;  } @@ -107,17 +318,6 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,  /*   * Device state switch handlers.   */ -static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, -				enum dev_state state) -{ -	u32 reg; - -	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); -	rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, -			   (state == STATE_RADIO_RX_ON)); -	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); -} -  static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; @@ -128,22 +328,20 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)  	if (rt2800_wait_csr_ready(rt2x00dev))  		return -EBUSY; -	rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®); -	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); - -	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); +	rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); +	rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); -	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®); +	reg = 0;  	rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1);  	rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); -	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg); +	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); -	rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); +	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);  	rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,  				    USB_MODE_RESET, REGISTER_TIMEOUT); -	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); +	rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);  	return 0;  } @@ -155,7 +353,7 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)  	if (unlikely(rt2800_wait_wpdma_ready(rt2x00dev)))  		return -EIO; -	rt2800_register_read(rt2x00dev, USB_DMA_CFG, ®); +	rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, ®);  	rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0);  	rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, 0);  	rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); @@ -164,11 +362,11 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)  	 * this limit so reduce the number to prevent errors.  	 */  	rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, -			   ((rt2x00dev->ops->rx->entry_num * DATA_FRAME_SIZE) +			   ((rt2x00dev->rx->limit * DATA_FRAME_SIZE)  			    / 1024) - 3);  	rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1);  	rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); -	rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg); +	rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);  	return rt2800_enable_radio(rt2x00dev);  } @@ -214,14 +412,8 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,  		rt2800usb_disable_radio(rt2x00dev);  		rt2800usb_set_state(rt2x00dev, STATE_SLEEP);  		break; -	case STATE_RADIO_RX_ON: -	case STATE_RADIO_RX_OFF: -		rt2800usb_toggle_rx(rt2x00dev, state); -		break;  	case STATE_RADIO_IRQ_ON: -	case STATE_RADIO_IRQ_ON_ISR:  	case STATE_RADIO_IRQ_OFF: -	case STATE_RADIO_IRQ_OFF_ISR:  		/* No support, but no error either */  		break;  	case STATE_DEEP_SLEEP: @@ -236,8 +428,8 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,  	}  	if (unlikely(retval)) -		ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", -		      state, retval); +		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", +			   state, retval);  	return retval;  } @@ -250,12 +442,11 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)  	unsigned int i;  	u32 reg; -	rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); +	rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®);  	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) { -		WARNING(rt2x00dev, "TX HW queue 0 timed out," -			" invoke forced kick"); +		rt2x00_warn(rt2x00dev, "TX HW queue 0 timed out, invoke forced kick\n"); -		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012); +		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40012);  		for (i = 0; i < 10; i++) {  			udelay(10); @@ -263,15 +454,14 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)  				break;  		} -		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); +		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);  	} -	rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®); +	rt2x00usb_register_read(rt2x00dev, TXRXQ_PCNT, ®);  	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) { -		WARNING(rt2x00dev, "TX HW queue 1 timed out," -			" invoke forced kick"); +		rt2x00_warn(rt2x00dev, "TX HW queue 1 timed out, invoke forced kick\n"); -		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a); +		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf4000a);  		for (i = 0; i < 10; i++) {  			udelay(10); @@ -279,7 +469,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)  				break;  		} -		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006); +		rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);  	}  	rt2x00usb_watchdog(rt2x00dev); @@ -311,10 +501,10 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry,  	/*  	 * The size of TXINFO_W0_USB_DMA_TX_PKT_LEN is  	 * TXWI + 802.11 header + L2 pad + payload + pad, -	 * so need to decrease size of TXINFO and USB end pad. +	 * so need to decrease size of TXINFO.  	 */  	rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, -			   entry->skb->len - TXINFO_DESC_SIZE - 4); +			   roundup(entry->skb->len, 4) - TXINFO_DESC_SIZE);  	rt2x00_set_field32(&word, TXINFO_W0_WIV,  			   !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));  	rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); @@ -329,45 +519,113 @@ static void rt2800usb_write_tx_desc(struct queue_entry *entry,  	 */  	skbdesc->flags |= SKBDESC_DESC_IN_SKB;  	skbdesc->desc = txi; -	skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; +	skbdesc->desc_len = TXINFO_DESC_SIZE + entry->queue->winfo_size;  } -static void rt2800usb_write_tx_data(struct queue_entry *entry, -					struct txentry_desc *txdesc) +/* + * TX data initialization + */ +static int rt2800usb_get_tx_data_len(struct queue_entry *entry)  { -	u8 padding_len; -  	/* -	 * pad(1~3 bytes) is added after each 802.11 payload. -	 * USB end pad(4 bytes) is added at each USB bulk out packet end. +	 * pad(1~3 bytes) is needed after each 802.11 payload. +	 * USB end pad(4 bytes) is needed at each USB bulk out packet end.  	 * TX frame format is :  	 * | TXINFO | TXWI | 802.11 header | L2 pad | payload | pad | USB end pad |  	 *                 |<------------- tx_pkt_len ------------->|  	 */ -        rt2800_write_tx_data(entry, txdesc); -        padding_len = roundup(entry->skb->len + 4, 4) - entry->skb->len; -        memset(skb_put(entry->skb, padding_len), 0, padding_len); + +	return roundup(entry->skb->len, 4) + 4;  }  /* - * TX data initialization + * TX control handlers   */ -static int rt2800usb_get_tx_data_len(struct queue_entry *entry) +static enum txdone_entry_desc_flags +rt2800usb_txdone_entry_check(struct queue_entry *entry, u32 reg)  { -	return entry->skb->len; +	__le32 *txwi; +	u32 word; +	int wcid, ack, pid; +	int tx_wcid, tx_ack, tx_pid, is_agg; + +	/* +	 * This frames has returned with an IO error, +	 * so the status report is not intended for this +	 * frame. +	 */ +	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) +		return TXDONE_FAILURE; + +	wcid	= rt2x00_get_field32(reg, TX_STA_FIFO_WCID); +	ack	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); +	pid	= rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); +	is_agg	= rt2x00_get_field32(reg, TX_STA_FIFO_TX_AGGRE); + +	/* +	 * Validate if this TX status report is intended for +	 * this entry by comparing the WCID/ACK/PID fields. +	 */ +	txwi = rt2800usb_get_txwi(entry); + +	rt2x00_desc_read(txwi, 1, &word); +	tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); +	tx_ack  = rt2x00_get_field32(word, TXWI_W1_ACK); +	tx_pid  = rt2x00_get_field32(word, TXWI_W1_PACKETID); + +	if (wcid != tx_wcid || ack != tx_ack || (!is_agg && pid != tx_pid)) { +		rt2x00_dbg(entry->queue->rt2x00dev, +			   "TX status report missed for queue %d entry %d\n", +			   entry->queue->qid, entry->entry_idx); +		return TXDONE_UNKNOWN; +	} + +	return TXDONE_SUCCESS;  } -/* - * TX control handlers - */ -static void rt2800usb_work_txdone(struct work_struct *work) +static void rt2800usb_txdone(struct rt2x00_dev *rt2x00dev)  { -	struct rt2x00_dev *rt2x00dev = -	    container_of(work, struct rt2x00_dev, txdone_work);  	struct data_queue *queue;  	struct queue_entry *entry; +	u32 reg; +	u8 qid; +	enum txdone_entry_desc_flags done_status; + +	while (kfifo_get(&rt2x00dev->txstatus_fifo, ®)) { +		/* +		 * TX_STA_FIFO_PID_QUEUE is a 2-bit field, thus qid is +		 * guaranteed to be one of the TX QIDs . +		 */ +		qid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_QUEUE); +		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid); + +		if (unlikely(rt2x00queue_empty(queue))) { +			rt2x00_dbg(rt2x00dev, "Got TX status for an empty queue %u, dropping\n", +				   qid); +			break; +		} + +		entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); + +		if (unlikely(test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || +			     !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))) { +			rt2x00_warn(rt2x00dev, "Data pending for entry %u in queue %u\n", +				    entry->entry_idx, qid); +			break; +		} + +		done_status = rt2800usb_txdone_entry_check(entry, reg); +		if (likely(done_status == TXDONE_SUCCESS)) +			rt2800_txdone_entry(entry, reg, rt2800usb_get_txwi(entry)); +		else +			rt2x00lib_txdone_noinfo(entry, done_status); +	} +} -	rt2800_txdone(rt2x00dev); +static void rt2800usb_txdone_nostatus(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue; +	struct queue_entry *entry;  	/*  	 * Process any trailing TX status reports for IO failures, @@ -381,20 +639,39 @@ static void rt2800usb_work_txdone(struct work_struct *work)  			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);  			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || -			    !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) +			    !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))  				break; -			rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); +			if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) +				rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); +			else if (rt2800usb_entry_txstatus_timeout(entry)) +				rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); +			else +				break;  		}  	}  } -static void rt2800usb_kill_tx_queue(struct data_queue *queue) +static void rt2800usb_work_txdone(struct work_struct *work)  { -	if (queue->qid == QID_BEACON) -		rt2x00usb_register_write(queue->rt2x00dev, BCN_TIME_CFG, 0); +	struct rt2x00_dev *rt2x00dev = +	    container_of(work, struct rt2x00_dev, txdone_work); + +	while (!kfifo_is_empty(&rt2x00dev->txstatus_fifo) || +	       rt2800usb_txstatus_timeout(rt2x00dev)) { + +		rt2800usb_txdone(rt2x00dev); + +		rt2800usb_txdone_nostatus(rt2x00dev); -	rt2x00usb_kill_tx_queue(queue); +		/* +		 * The hw may delay sending the packet after DMA complete +		 * if the medium is busy, thus the TX_STA_FIFO entry is +		 * also delayed -> use a timer to retrieve it. +		 */ +		if (rt2800usb_txstatus_pending(rt2x00dev)) +			rt2800usb_async_read_tx_status(rt2x00dev); +	}  }  /* @@ -429,8 +706,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,  	skb_pull(entry->skb, RXINFO_DESC_SIZE);  	/* -	 * FIXME: we need to check for rx_pkt_len validity +	 * Check for rx_pkt_len validity. Return if invalid, leaving +	 * rxdesc->size zeroed out by the upper level.  	 */ +	if (unlikely(rx_pkt_len == 0 || +			rx_pkt_len > entry->queue->data_size)) { +		rt2x00_err(entry->queue->rt2x00dev, +			   "Bad frame size %d, forcing to 0\n", rx_pkt_len); +		return; +	} +  	rxd = (__le32 *)(entry->skb->data + rx_pkt_len);  	/* @@ -452,6 +737,12 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,  		 */  		rxdesc->flags |= RX_FLAG_IV_STRIPPED; +		/* +		 * The hardware has already checked the Michael Mic and has +		 * stripped it from the frame. Signal this to mac80211. +		 */ +		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; +  		if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)  			rxdesc->flags |= RX_FLAG_DECRYPTED;  		else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) @@ -478,65 +769,51 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,  /*   * Device probe functions.   */ -static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt2800usb_efuse_detect(struct rt2x00_dev *rt2x00dev)  { -	if (rt2800_efuse_detect(rt2x00dev)) -		rt2800_read_eeprom_efuse(rt2x00dev); -	else -		rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, -				      EEPROM_SIZE); +	int retval; -	return rt2800_validate_eeprom(rt2x00dev); +	retval = rt2800usb_autorun_detect(rt2x00dev); +	if (retval < 0) +		return retval; +	if (retval) +		return 1; +	return rt2800_efuse_detect(rt2x00dev);  } -static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) +static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)  {  	int retval; -	/* -	 * Allocate eeprom data. -	 */ -	retval = rt2800usb_validate_eeprom(rt2x00dev); -	if (retval) +	retval = rt2800usb_efuse_detect(rt2x00dev); +	if (retval < 0)  		return retval; - -	retval = rt2800_init_eeprom(rt2x00dev);  	if (retval) -		return retval; +		retval = rt2800_read_eeprom_efuse(rt2x00dev); +	else +		retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, +					       EEPROM_SIZE); -	/* -	 * Initialize hw specifications. -	 */ -	retval = rt2800_probe_hw_mode(rt2x00dev); -	if (retval) -		return retval; +	return retval; +} -	/* -	 * This device has multiple filters for control frames -	 * and has a separate filter for PS Poll frames. -	 */ -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); +static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) +{ +	int retval; -	/* -	 * This device requires firmware. -	 */ -	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); -	if (!modparam_nohwcrypt) -		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); +	retval = rt2800_probe_hw(rt2x00dev); +	if (retval) +		return retval;  	/* -	 * Set the rssi offset. +	 * Set txstatus timer function.  	 */ -	rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; +	rt2x00dev->txstatus_timer.function = rt2800usb_tx_sta_fifo_timeout;  	/*  	 * Overwrite TX done handler  	 */ -	PREPARE_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone); +	INIT_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone);  	return 0;  } @@ -556,12 +833,17 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {  	.get_stats		= rt2x00mac_get_stats,  	.get_tkip_seq		= rt2800_get_tkip_seq,  	.set_rts_threshold	= rt2800_set_rts_threshold, +	.sta_add		= rt2x00mac_sta_add, +	.sta_remove		= rt2x00mac_sta_remove,  	.bss_info_changed	= rt2x00mac_bss_info_changed,  	.conf_tx		= rt2800_conf_tx,  	.get_tsf		= rt2800_get_tsf,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.ampdu_action		= rt2800_ampdu_action,  	.flush			= rt2x00mac_flush, +	.get_survey		= rt2800_get_survey, +	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2800_ops rt2800usb_rt2800_ops = { @@ -572,6 +854,8 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = {  	.register_multiread	= rt2x00usb_register_multiread,  	.register_multiwrite	= rt2x00usb_register_multiwrite,  	.regbusy_read		= rt2x00usb_regbusy_read, +	.read_eeprom		= rt2800usb_read_eeprom, +	.hwcrypt_disabled	= rt2800usb_hwcrypt_disabled,  	.drv_write_firmware	= rt2800usb_write_firmware,  	.drv_init_registers	= rt2800usb_init_registers,  	.drv_get_txwi		= rt2800usb_get_txwi, @@ -590,13 +874,19 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {  	.link_stats		= rt2800_link_stats,  	.reset_tuner		= rt2800_reset_tuner,  	.link_tuner		= rt2800_link_tuner, +	.gain_calibration	= rt2800_gain_calibration, +	.vco_calibration	= rt2800_vco_calibration,  	.watchdog		= rt2800usb_watchdog, +	.start_queue		= rt2800usb_start_queue, +	.kick_queue		= rt2x00usb_kick_queue, +	.stop_queue		= rt2800usb_stop_queue, +	.flush_queue		= rt2x00usb_flush_queue, +	.tx_dma_done		= rt2800usb_tx_dma_done,  	.write_tx_desc		= rt2800usb_write_tx_desc, -	.write_tx_data		= rt2800usb_write_tx_data, +	.write_tx_data		= rt2800_write_tx_data,  	.write_beacon		= rt2800_write_beacon, +	.clear_beacon		= rt2800_clear_beacon,  	.get_tx_data_len	= rt2800usb_get_tx_data_len, -	.kick_tx_queue		= rt2x00usb_kick_tx_queue, -	.kill_tx_queue		= rt2800usb_kill_tx_queue,  	.fill_rxdone		= rt2800usb_fill_rxdone,  	.config_shared_key	= rt2800_config_shared_key,  	.config_pairwise_key	= rt2800_config_pairwise_key, @@ -605,40 +895,61 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {  	.config_erp		= rt2800_config_erp,  	.config_ant		= rt2800_config_ant,  	.config			= rt2800_config, +	.sta_add		= rt2800_sta_add, +	.sta_remove		= rt2800_sta_remove,  }; -static const struct data_queue_desc rt2800usb_queue_rx = { -	.entry_num		= 128, -	.data_size		= AGGREGATION_SIZE, -	.desc_size		= RXINFO_DESC_SIZE + RXWI_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_usb), -}; +static void rt2800usb_queue_init(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	unsigned short txwi_size, rxwi_size; + +	rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size); + +	switch (queue->qid) { +	case QID_RX: +		queue->limit = 128; +		queue->data_size = AGGREGATION_SIZE; +		queue->desc_size = RXINFO_DESC_SIZE; +		queue->winfo_size = rxwi_size; +		queue->priv_size = sizeof(struct queue_entry_priv_usb); +		break; -static const struct data_queue_desc rt2800usb_queue_tx = { -	.entry_num		= 64, -	.data_size		= AGGREGATION_SIZE, -	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_usb), -}; +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		queue->limit = 16; +		queue->data_size = AGGREGATION_SIZE; +		queue->desc_size = TXINFO_DESC_SIZE; +		queue->winfo_size = txwi_size; +		queue->priv_size = sizeof(struct queue_entry_priv_usb); +		break; -static const struct data_queue_desc rt2800usb_queue_bcn = { -	.entry_num		= 8, -	.data_size		= MGMT_FRAME_SIZE, -	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_usb), -}; +	case QID_BEACON: +		queue->limit = 8; +		queue->data_size = MGMT_FRAME_SIZE; +		queue->desc_size = TXINFO_DESC_SIZE; +		queue->winfo_size = txwi_size; +		queue->priv_size = sizeof(struct queue_entry_priv_usb); +		break; + +	case QID_ATIM: +		/* fallthrough */ +	default: +		BUG(); +		break; +	} +}  static const struct rt2x00_ops rt2800usb_ops = {  	.name			= KBUILD_MODNAME, -	.max_sta_intf		= 1, +	.drv_data_size		= sizeof(struct rt2800_drv_data),  	.max_ap_intf		= 8,  	.eeprom_size		= EEPROM_SIZE,  	.rf_size		= RF_SIZE,  	.tx_queues		= NUM_TX_QUEUES, -	.extra_tx_headroom	= TXINFO_DESC_SIZE + TXWI_DESC_SIZE, -	.rx			= &rt2800usb_queue_rx, -	.tx			= &rt2800usb_queue_tx, -	.bcn			= &rt2800usb_queue_bcn, +	.queue_init		= rt2800usb_queue_init,  	.lib			= &rt2800usb_rt2x00_ops,  	.drv			= &rt2800usb_rt2800_ops,  	.hw			= &rt2800usb_mac80211_ops, @@ -652,285 +963,462 @@ static const struct rt2x00_ops rt2800usb_ops = {   */  static struct usb_device_id rt2800usb_device_table[] = {  	/* Abocom */ -	{ USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07b8, 0x2870) }, +	{ USB_DEVICE(0x07b8, 0x2770) }, +	{ USB_DEVICE(0x07b8, 0x3070) }, +	{ USB_DEVICE(0x07b8, 0x3071) }, +	{ USB_DEVICE(0x07b8, 0x3072) }, +	{ USB_DEVICE(0x1482, 0x3c09) },  	/* AirTies */ -	{ USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1eda, 0x2012) }, +	{ USB_DEVICE(0x1eda, 0x2210) }, +	{ USB_DEVICE(0x1eda, 0x2310) },  	/* Allwin */ -	{ USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x8516, 0x2070) }, +	{ USB_DEVICE(0x8516, 0x2770) }, +	{ USB_DEVICE(0x8516, 0x2870) }, +	{ USB_DEVICE(0x8516, 0x3070) }, +	{ USB_DEVICE(0x8516, 0x3071) }, +	{ USB_DEVICE(0x8516, 0x3072) }, +	/* Alpha Networks */ +	{ USB_DEVICE(0x14b2, 0x3c06) }, +	{ USB_DEVICE(0x14b2, 0x3c07) }, +	{ USB_DEVICE(0x14b2, 0x3c09) }, +	{ USB_DEVICE(0x14b2, 0x3c12) }, +	{ USB_DEVICE(0x14b2, 0x3c23) }, +	{ USB_DEVICE(0x14b2, 0x3c25) }, +	{ USB_DEVICE(0x14b2, 0x3c27) }, +	{ USB_DEVICE(0x14b2, 0x3c28) }, +	{ USB_DEVICE(0x14b2, 0x3c2c) },  	/* Amit */ -	{ USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x15c5, 0x0008) },  	/* Askey */ -	{ USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1690, 0x0740) },  	/* ASUS */ -	{ USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0b05, 0x1731) }, +	{ USB_DEVICE(0x0b05, 0x1732) }, +	{ USB_DEVICE(0x0b05, 0x1742) }, +	{ USB_DEVICE(0x0b05, 0x1784) }, +	{ USB_DEVICE(0x1761, 0x0b05) },  	/* AzureWave */ -	{ USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3307), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3321), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x13d3, 0x3247) }, +	{ USB_DEVICE(0x13d3, 0x3273) }, +	{ USB_DEVICE(0x13d3, 0x3305) }, +	{ USB_DEVICE(0x13d3, 0x3307) }, +	{ USB_DEVICE(0x13d3, 0x3321) },  	/* Belkin */ -	{ USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x050d, 0x8053) }, +	{ USB_DEVICE(0x050d, 0x805c) }, +	{ USB_DEVICE(0x050d, 0x815c) }, +	{ USB_DEVICE(0x050d, 0x825a) }, +	{ USB_DEVICE(0x050d, 0x825b) }, +	{ USB_DEVICE(0x050d, 0x935a) }, +	{ USB_DEVICE(0x050d, 0x935b) },  	/* Buffalo */ -	{ USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, -	/* Conceptronic */ -	{ USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0411, 0x00e8) }, +	{ USB_DEVICE(0x0411, 0x0158) }, +	{ USB_DEVICE(0x0411, 0x015d) }, +	{ USB_DEVICE(0x0411, 0x016f) }, +	{ USB_DEVICE(0x0411, 0x01a2) }, +	{ USB_DEVICE(0x0411, 0x01ee) }, +	{ USB_DEVICE(0x0411, 0x01a8) },  	/* Corega */ -	{ USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07aa, 0x002f) }, +	{ USB_DEVICE(0x07aa, 0x003c) }, +	{ USB_DEVICE(0x07aa, 0x003f) }, +	{ USB_DEVICE(0x18c5, 0x0012) },  	/* D-Link */ -	{ USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07d1, 0x3c09) }, +	{ USB_DEVICE(0x07d1, 0x3c0a) }, +	{ USB_DEVICE(0x07d1, 0x3c0d) }, +	{ USB_DEVICE(0x07d1, 0x3c0e) }, +	{ USB_DEVICE(0x07d1, 0x3c0f) }, +	{ USB_DEVICE(0x07d1, 0x3c11) }, +	{ USB_DEVICE(0x07d1, 0x3c13) }, +	{ USB_DEVICE(0x07d1, 0x3c15) }, +	{ USB_DEVICE(0x07d1, 0x3c16) }, +	{ USB_DEVICE(0x07d1, 0x3c17) }, +	{ USB_DEVICE(0x2001, 0x3317) }, +	{ USB_DEVICE(0x2001, 0x3c1b) },  	/* Draytek */ -	{ USB_DEVICE(0x07fa, 0x7712), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07fa, 0x7712) }, +	/* DVICO */ +	{ USB_DEVICE(0x0fe9, 0xb307) },  	/* Edimax */ -	{ USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x7392, 0x4085) }, +	{ USB_DEVICE(0x7392, 0x7711) }, +	{ USB_DEVICE(0x7392, 0x7717) }, +	{ USB_DEVICE(0x7392, 0x7718) }, +	{ USB_DEVICE(0x7392, 0x7722) },  	/* Encore */ -	{ USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x203d, 0x1480) }, +	{ USB_DEVICE(0x203d, 0x14a9) },  	/* EnGenius */ -	{ USB_DEVICE(0x1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1740, 0x9701) }, +	{ USB_DEVICE(0x1740, 0x9702) }, +	{ USB_DEVICE(0x1740, 0x9703) }, +	{ USB_DEVICE(0x1740, 0x9705) }, +	{ USB_DEVICE(0x1740, 0x9706) }, +	{ USB_DEVICE(0x1740, 0x9707) }, +	{ USB_DEVICE(0x1740, 0x9708) }, +	{ USB_DEVICE(0x1740, 0x9709) }, +	/* Gemtek */ +	{ USB_DEVICE(0x15a9, 0x0012) },  	/* Gigabyte */ -	{ USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1044, 0x800b) }, +	{ USB_DEVICE(0x1044, 0x800d) },  	/* Hawking */ -	{ USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x0013), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e66, 0x0018), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0e66, 0x0001) }, +	{ USB_DEVICE(0x0e66, 0x0003) }, +	{ USB_DEVICE(0x0e66, 0x0009) }, +	{ USB_DEVICE(0x0e66, 0x000b) }, +	{ USB_DEVICE(0x0e66, 0x0013) }, +	{ USB_DEVICE(0x0e66, 0x0017) }, +	{ USB_DEVICE(0x0e66, 0x0018) },  	/* I-O DATA */ -	{ USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x04bb, 0x0945) }, +	{ USB_DEVICE(0x04bb, 0x0947) }, +	{ USB_DEVICE(0x04bb, 0x0948) },  	/* Linksys */ -	{ USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x13b1, 0x0031) }, +	{ USB_DEVICE(0x1737, 0x0070) }, +	{ USB_DEVICE(0x1737, 0x0071) }, +	{ USB_DEVICE(0x1737, 0x0077) }, +	{ USB_DEVICE(0x1737, 0x0078) },  	/* Logitec */ -	{ USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0789, 0x0166), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0789, 0x0162) }, +	{ USB_DEVICE(0x0789, 0x0163) }, +	{ USB_DEVICE(0x0789, 0x0164) }, +	{ USB_DEVICE(0x0789, 0x0166) },  	/* Motorola */ -	{ USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x100d, 0x9031) },  	/* MSI */ -	{ USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x822b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x822c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x871b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x871c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0db0, 0x3820) }, +	{ USB_DEVICE(0x0db0, 0x3821) }, +	{ USB_DEVICE(0x0db0, 0x3822) }, +	{ USB_DEVICE(0x0db0, 0x3870) }, +	{ USB_DEVICE(0x0db0, 0x3871) }, +	{ USB_DEVICE(0x0db0, 0x6899) }, +	{ USB_DEVICE(0x0db0, 0x821a) }, +	{ USB_DEVICE(0x0db0, 0x822a) }, +	{ USB_DEVICE(0x0db0, 0x822b) }, +	{ USB_DEVICE(0x0db0, 0x822c) }, +	{ USB_DEVICE(0x0db0, 0x870a) }, +	{ USB_DEVICE(0x0db0, 0x871a) }, +	{ USB_DEVICE(0x0db0, 0x871b) }, +	{ USB_DEVICE(0x0db0, 0x871c) }, +	{ USB_DEVICE(0x0db0, 0x899a) }, +	/* Ovislink */ +	{ USB_DEVICE(0x1b75, 0x3071) }, +	{ USB_DEVICE(0x1b75, 0x3072) },  	/* Para */ -	{ USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x20b8, 0x8888) },  	/* Pegatron */ -	{ USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1d4d, 0x0002) }, +	{ USB_DEVICE(0x1d4d, 0x000c) }, +	{ USB_DEVICE(0x1d4d, 0x000e) }, +	{ USB_DEVICE(0x1d4d, 0x0011) },  	/* Philips */ -	{ USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0471, 0x200f) },  	/* Planex */ -	{ USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x2019, 0x5201) }, +	{ USB_DEVICE(0x2019, 0xab25) }, +	{ USB_DEVICE(0x2019, 0xed06) },  	/* Quanta */ -	{ USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1a32, 0x0304) },  	/* Ralink */ -	{ USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x148f, 0x2070) }, +	{ USB_DEVICE(0x148f, 0x2770) }, +	{ USB_DEVICE(0x148f, 0x2870) }, +	{ USB_DEVICE(0x148f, 0x3070) }, +	{ USB_DEVICE(0x148f, 0x3071) }, +	{ USB_DEVICE(0x148f, 0x3072) },  	/* Samsung */ -	{ USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x04e8, 0x2018) },  	/* Siemens */ -	{ USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x129b, 0x1828) },  	/* Sitecom */ -	{ USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0df6, 0x0017) }, +	{ USB_DEVICE(0x0df6, 0x002b) }, +	{ USB_DEVICE(0x0df6, 0x002c) }, +	{ USB_DEVICE(0x0df6, 0x002d) }, +	{ USB_DEVICE(0x0df6, 0x0039) }, +	{ USB_DEVICE(0x0df6, 0x003b) }, +	{ USB_DEVICE(0x0df6, 0x003d) }, +	{ USB_DEVICE(0x0df6, 0x003e) }, +	{ USB_DEVICE(0x0df6, 0x003f) }, +	{ USB_DEVICE(0x0df6, 0x0040) }, +	{ USB_DEVICE(0x0df6, 0x0042) }, +	{ USB_DEVICE(0x0df6, 0x0047) }, +	{ USB_DEVICE(0x0df6, 0x0048) }, +	{ USB_DEVICE(0x0df6, 0x0051) }, +	{ USB_DEVICE(0x0df6, 0x005f) }, +	{ USB_DEVICE(0x0df6, 0x0060) },  	/* SMC */ -	{ USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xa703), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x083a, 0x6618) }, +	{ USB_DEVICE(0x083a, 0x7511) }, +	{ USB_DEVICE(0x083a, 0x7512) }, +	{ USB_DEVICE(0x083a, 0x7522) }, +	{ USB_DEVICE(0x083a, 0x8522) }, +	{ USB_DEVICE(0x083a, 0xa618) }, +	{ USB_DEVICE(0x083a, 0xa701) }, +	{ USB_DEVICE(0x083a, 0xa702) }, +	{ USB_DEVICE(0x083a, 0xa703) }, +	{ USB_DEVICE(0x083a, 0xb522) },  	/* Sparklan */ -	{ USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x15a9, 0x0006) },  	/* Sweex */ -	{ USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, -	/* U-Media*/ -	{ USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x177f, 0x0153) }, +	{ USB_DEVICE(0x177f, 0x0164) }, +	{ USB_DEVICE(0x177f, 0x0302) }, +	{ USB_DEVICE(0x177f, 0x0313) }, +	{ USB_DEVICE(0x177f, 0x0323) }, +	{ USB_DEVICE(0x177f, 0x0324) }, +	/* U-Media */ +	{ USB_DEVICE(0x157e, 0x300e) }, +	{ USB_DEVICE(0x157e, 0x3013) },  	/* ZCOM */ -	{ USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0cde, 0x0022) }, +	{ USB_DEVICE(0x0cde, 0x0025) },  	/* Zinwell */ -	{ USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x5a57, 0x0280) }, +	{ USB_DEVICE(0x5a57, 0x0282) }, +	{ USB_DEVICE(0x5a57, 0x0283) }, +	{ USB_DEVICE(0x5a57, 0x5257) },  	/* Zyxel */ -	{ USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0586, 0x3416) }, +	{ USB_DEVICE(0x0586, 0x3418) }, +	{ USB_DEVICE(0x0586, 0x341a) }, +	{ USB_DEVICE(0x0586, 0x341e) }, +	{ USB_DEVICE(0x0586, 0x343e) },  #ifdef CONFIG_RT2800USB_RT33XX +	/* Belkin */ +	{ USB_DEVICE(0x050d, 0x945b) }, +	/* D-Link */ +	{ USB_DEVICE(0x2001, 0x3c17) }, +	/* Panasonic */ +	{ USB_DEVICE(0x083a, 0xb511) }, +	/* Philips */ +	{ USB_DEVICE(0x0471, 0x20dd) },  	/* Ralink */ -	{ USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x148f, 0x3370) }, +	{ USB_DEVICE(0x148f, 0x8070) },  	/* Sitecom */ -	{ USB_DEVICE(0x0df6, 0x0050), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0df6, 0x0050) }, +	/* Sweex */ +	{ USB_DEVICE(0x177f, 0x0163) }, +	{ USB_DEVICE(0x177f, 0x0165) },  #endif  #ifdef CONFIG_RT2800USB_RT35XX  	/* Allwin */ -	{ USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x8516, 0x3572) },  	/* Askey */ -	{ USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1690, 0x0744) }, +	{ USB_DEVICE(0x1690, 0x0761) }, +	{ USB_DEVICE(0x1690, 0x0764) }, +	/* ASUS */ +	{ USB_DEVICE(0x0b05, 0x179d) },  	/* Cisco */ -	{ USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x167b, 0x4001) },  	/* EnGenius */ -	{ USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1740, 0x9801) },  	/* I-O DATA */ -	{ USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x04bb, 0x0944) }, +	/* Linksys */ +	{ USB_DEVICE(0x13b1, 0x002f) }, +	{ USB_DEVICE(0x1737, 0x0079) }, +	/* Logitec */ +	{ USB_DEVICE(0x0789, 0x0170) },  	/* Ralink */ -	{ USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x148f, 0x3572) },  	/* Sitecom */ -	{ USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0df6, 0x0041) }, +	{ USB_DEVICE(0x0df6, 0x0062) }, +	{ USB_DEVICE(0x0df6, 0x0065) }, +	{ USB_DEVICE(0x0df6, 0x0066) }, +	{ USB_DEVICE(0x0df6, 0x0068) }, +	/* Toshiba */ +	{ USB_DEVICE(0x0930, 0x0a07) },  	/* Zinwell */ -	{ USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x5a57, 0x0284) }, +#endif +#ifdef CONFIG_RT2800USB_RT3573 +	/* AirLive */ +	{ USB_DEVICE(0x1b75, 0x7733) }, +	/* ASUS */ +	{ USB_DEVICE(0x0b05, 0x17bc) }, +	{ USB_DEVICE(0x0b05, 0x17ad) }, +	/* Belkin */ +	{ USB_DEVICE(0x050d, 0x1103) }, +	/* Cameo */ +	{ USB_DEVICE(0x148f, 0xf301) }, +	/* D-Link */ +	{ USB_DEVICE(0x2001, 0x3c1f) }, +	/* Edimax */ +	{ USB_DEVICE(0x7392, 0x7733) }, +	/* Hawking */ +	{ USB_DEVICE(0x0e66, 0x0020) }, +	{ USB_DEVICE(0x0e66, 0x0021) }, +	/* I-O DATA */ +	{ USB_DEVICE(0x04bb, 0x094e) }, +	/* Linksys */ +	{ USB_DEVICE(0x13b1, 0x003b) }, +	/* Logitec */ +	{ USB_DEVICE(0x0789, 0x016b) }, +	/* NETGEAR */ +	{ USB_DEVICE(0x0846, 0x9012) }, +	{ USB_DEVICE(0x0846, 0x9013) }, +	{ USB_DEVICE(0x0846, 0x9019) }, +	/* Planex */ +	{ USB_DEVICE(0x2019, 0xed19) }, +	/* Ralink */ +	{ USB_DEVICE(0x148f, 0x3573) }, +	/* Sitecom */ +	{ USB_DEVICE(0x0df6, 0x0067) }, +	{ USB_DEVICE(0x0df6, 0x006a) }, +	{ USB_DEVICE(0x0df6, 0x006e) }, +	/* ZyXEL */ +	{ USB_DEVICE(0x0586, 0x3421) }, +#endif +#ifdef CONFIG_RT2800USB_RT53XX +	/* Arcadyan */ +	{ USB_DEVICE(0x043e, 0x7a12) }, +	{ USB_DEVICE(0x043e, 0x7a32) }, +	/* Azurewave */ +	{ USB_DEVICE(0x13d3, 0x3329) }, +	{ USB_DEVICE(0x13d3, 0x3365) }, +	/* D-Link */ +	{ USB_DEVICE(0x2001, 0x3c15) }, +	{ USB_DEVICE(0x2001, 0x3c19) }, +	{ USB_DEVICE(0x2001, 0x3c1c) }, +	{ USB_DEVICE(0x2001, 0x3c1d) }, +	{ USB_DEVICE(0x2001, 0x3c1e) }, +	{ USB_DEVICE(0x2001, 0x3c20) }, +	{ USB_DEVICE(0x2001, 0x3c22) }, +	{ USB_DEVICE(0x2001, 0x3c23) }, +	/* LG innotek */ +	{ USB_DEVICE(0x043e, 0x7a22) }, +	{ USB_DEVICE(0x043e, 0x7a42) }, +	/* Panasonic */ +	{ USB_DEVICE(0x04da, 0x1801) }, +	{ USB_DEVICE(0x04da, 0x1800) }, +	{ USB_DEVICE(0x04da, 0x23f6) }, +	/* Philips */ +	{ USB_DEVICE(0x0471, 0x2104) }, +	{ USB_DEVICE(0x0471, 0x2126) }, +	{ USB_DEVICE(0x0471, 0x2180) }, +	{ USB_DEVICE(0x0471, 0x2181) }, +	{ USB_DEVICE(0x0471, 0x2182) }, +	/* Ralink */ +	{ USB_DEVICE(0x148f, 0x5370) }, +	{ USB_DEVICE(0x148f, 0x5372) }, +#endif +#ifdef CONFIG_RT2800USB_RT55XX +	/* Arcadyan */ +	{ USB_DEVICE(0x043e, 0x7a32) }, +	/* AVM GmbH */ +	{ USB_DEVICE(0x057c, 0x8501) }, +	/* Buffalo */ +	{ USB_DEVICE(0x0411, 0x0241) }, +	/* D-Link */ +	{ USB_DEVICE(0x2001, 0x3c1a) }, +	{ USB_DEVICE(0x2001, 0x3c21) }, +	/* Proware */ +	{ USB_DEVICE(0x043e, 0x7a13) }, +	/* Ralink */ +	{ USB_DEVICE(0x148f, 0x5572) }, +	/* TRENDnet */ +	{ USB_DEVICE(0x20f4, 0x724a) },  #endif  #ifdef CONFIG_RT2800USB_UNKNOWN  	/*  	 * Unclear what kind of devices these are (they aren't supported by the  	 * vendor linux driver).  	 */ +	/* Abocom */ +	{ USB_DEVICE(0x07b8, 0x3073) }, +	{ USB_DEVICE(0x07b8, 0x3074) }, +	/* Alpha Networks */ +	{ USB_DEVICE(0x14b2, 0x3c08) }, +	{ USB_DEVICE(0x14b2, 0x3c11) },  	/* Amigo */ -	{ USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0e0b, 0x9031) }, +	{ USB_DEVICE(0x0e0b, 0x9041) },  	/* ASUS */ -	{ USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0b05, 0x166a) }, +	{ USB_DEVICE(0x0b05, 0x1760) }, +	{ USB_DEVICE(0x0b05, 0x1761) }, +	{ USB_DEVICE(0x0b05, 0x1790) }, +	{ USB_DEVICE(0x0b05, 0x17a7) },  	/* AzureWave */ -	{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x13d3, 0x3262) }, +	{ USB_DEVICE(0x13d3, 0x3284) }, +	{ USB_DEVICE(0x13d3, 0x3322) }, +	{ USB_DEVICE(0x13d3, 0x3340) }, +	{ USB_DEVICE(0x13d3, 0x3399) }, +	{ USB_DEVICE(0x13d3, 0x3400) }, +	{ USB_DEVICE(0x13d3, 0x3401) },  	/* Belkin */ -	{ USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x050d, 0x1003) },  	/* Buffalo */ -	{ USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) }, -	/* Conceptronic */ -	{ USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x0411, 0x012e) }, +	{ USB_DEVICE(0x0411, 0x0148) }, +	{ USB_DEVICE(0x0411, 0x0150) },  	/* Corega */ -	{ USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07aa, 0x0041) }, +	{ USB_DEVICE(0x07aa, 0x0042) }, +	{ USB_DEVICE(0x18c5, 0x0008) },  	/* D-Link */ -	{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x07d1, 0x3c0b) },  	/* Encore */ -	{ USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x203d, 0x14a1) }, +	/* EnGenius */ +	{ USB_DEVICE(0x1740, 0x0600) }, +	{ USB_DEVICE(0x1740, 0x0602) },  	/* Gemtek */ -	{ USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x15a9, 0x0010) },  	/* Gigabyte */ -	{ USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1044, 0x800c) }, +	/* Hercules */ +	{ USB_DEVICE(0x06f8, 0xe036) }, +	/* Huawei */ +	{ USB_DEVICE(0x148f, 0xf101) }, +	/* I-O DATA */ +	{ USB_DEVICE(0x04bb, 0x094b) },  	/* LevelOne */ -	{ USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, -	/* Linksys */ -	{ USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x1740, 0x0605) }, +	{ USB_DEVICE(0x1740, 0x0615) }, +	/* Logitec */ +	{ USB_DEVICE(0x0789, 0x0168) }, +	{ USB_DEVICE(0x0789, 0x0169) },  	/* Motorola */ -	{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, -	/* Ovislink */ -	{ USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x100d, 0x9032) },  	/* Pegatron */ -	{ USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x05a6, 0x0101) }, +	{ USB_DEVICE(0x1d4d, 0x0010) },  	/* Planex */ -	{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x2019, 0xab24) }, +	{ USB_DEVICE(0x2019, 0xab29) },  	/* Qcom */ -	{ USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x18e8, 0x6259) }, +	/* RadioShack */ +	{ USB_DEVICE(0x08b9, 0x1197) }, +	/* Sitecom */ +	{ USB_DEVICE(0x0df6, 0x003c) }, +	{ USB_DEVICE(0x0df6, 0x004a) }, +	{ USB_DEVICE(0x0df6, 0x004d) }, +	{ USB_DEVICE(0x0df6, 0x0053) }, +	{ USB_DEVICE(0x0df6, 0x0069) }, +	{ USB_DEVICE(0x0df6, 0x006f) },  	/* SMC */ -	{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x083a, 0xa512) }, +	{ USB_DEVICE(0x083a, 0xc522) }, +	{ USB_DEVICE(0x083a, 0xd522) }, +	{ USB_DEVICE(0x083a, 0xf511) },  	/* Sweex */ -	{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, -	{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, -	/* Zyxel */ -	{ USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, +	{ USB_DEVICE(0x177f, 0x0254) }, +	/* TP-LINK */ +	{ USB_DEVICE(0xf201, 0x5370) },  #endif  	{ 0, }  }; @@ -943,24 +1431,21 @@ MODULE_DEVICE_TABLE(usb, rt2800usb_device_table);  MODULE_FIRMWARE(FIRMWARE_RT2870);  MODULE_LICENSE("GPL"); +static int rt2800usb_probe(struct usb_interface *usb_intf, +			   const struct usb_device_id *id) +{ +	return rt2x00usb_probe(usb_intf, &rt2800usb_ops); +} +  static struct usb_driver rt2800usb_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt2800usb_device_table, -	.probe		= rt2x00usb_probe, +	.probe		= rt2800usb_probe,  	.disconnect	= rt2x00usb_disconnect,  	.suspend	= rt2x00usb_suspend,  	.resume		= rt2x00usb_resume, +	.reset_resume	= rt2x00usb_resume, +	.disable_hub_initiated_lpm = 1,  }; -static int __init rt2800usb_init(void) -{ -	return usb_register(&rt2800usb_driver); -} - -static void __exit rt2800usb_exit(void) -{ -	usb_deregister(&rt2800usb_driver); -} - -module_init(rt2800usb_init); -module_exit(rt2800usb_exit); +module_usb_driver(rt2800usb_driver); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 671ea359261..ea7cac09599 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h @@ -17,9 +17,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 0a55eeff871..d13f25cd70d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -15,9 +15,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -29,6 +27,7 @@  #define RT2X00_H  #include <linux/bitops.h> +#include <linux/interrupt.h>  #include <linux/skbuff.h>  #include <linux/workqueue.h>  #include <linux/firmware.h> @@ -37,6 +36,8 @@  #include <linux/etherdevice.h>  #include <linux/input-polldev.h>  #include <linux/kfifo.h> +#include <linux/hrtimer.h> +#include <linux/average.h>  #include <net/mac80211.h> @@ -52,49 +53,36 @@  #define DRV_VERSION	"2.3.0"  #define DRV_PROJECT	"http://rt2x00.serialmonkey.com" -/* - * Debug definitions. +/* Debug definitions.   * Debug output has to be enabled during compile time.   */ -#define DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, __args...)	\ -	printk(__kernlvl "%s -> %s: %s - " __msg,			\ -	       wiphy_name((__dev)->hw->wiphy), __func__, __lvl, ##__args) - -#define DEBUG_PRINTK_PROBE(__kernlvl, __lvl, __msg, __args...)	\ -	printk(__kernlvl "%s -> %s: %s - " __msg,		\ -	       KBUILD_MODNAME, __func__, __lvl, ##__args) -  #ifdef CONFIG_RT2X00_DEBUG -#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...)	\ -	DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args); -#else -#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...)	\ -	do { } while (0) +#define DEBUG  #endif /* CONFIG_RT2X00_DEBUG */ -/* - * Various debug levels. - * The debug levels PANIC and ERROR both indicate serious problems, - * for this reason they should never be ignored. - * The special ERROR_PROBE message is for messages that are generated - * when the rt2x00_dev is not yet initialized. +/* Utility printing macros + * rt2x00_probe_err is for messages when rt2x00_dev is uninitialized   */ -#define PANIC(__dev, __msg, __args...) \ -	DEBUG_PRINTK_MSG(__dev, KERN_CRIT, "Panic", __msg, ##__args) -#define ERROR(__dev, __msg, __args...)	\ -	DEBUG_PRINTK_MSG(__dev, KERN_ERR, "Error", __msg, ##__args) -#define ERROR_PROBE(__msg, __args...) \ -	DEBUG_PRINTK_PROBE(KERN_ERR, "Error", __msg, ##__args) -#define WARNING(__dev, __msg, __args...) \ -	DEBUG_PRINTK(__dev, KERN_WARNING, "Warning", __msg, ##__args) -#define NOTICE(__dev, __msg, __args...) \ -	DEBUG_PRINTK(__dev, KERN_NOTICE, "Notice", __msg, ##__args) -#define INFO(__dev, __msg, __args...) \ -	DEBUG_PRINTK(__dev, KERN_INFO, "Info", __msg, ##__args) -#define DEBUG(__dev, __msg, __args...) \ -	DEBUG_PRINTK(__dev, KERN_DEBUG, "Debug", __msg, ##__args) -#define EEPROM(__dev, __msg, __args...) \ -	DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args) +#define rt2x00_probe_err(fmt, ...)					\ +	printk(KERN_ERR KBUILD_MODNAME ": %s: Error - " fmt,		\ +	       __func__, ##__VA_ARGS__) +#define rt2x00_err(dev, fmt, ...)					\ +	wiphy_err((dev)->hw->wiphy, "%s: Error - " fmt,			\ +		  __func__, ##__VA_ARGS__) +#define rt2x00_warn(dev, fmt, ...)					\ +	wiphy_warn((dev)->hw->wiphy, "%s: Warning - " fmt,		\ +		   __func__, ##__VA_ARGS__) +#define rt2x00_info(dev, fmt, ...)					\ +	wiphy_info((dev)->hw->wiphy, "%s: Info - " fmt,			\ +		   __func__, ##__VA_ARGS__) + +/* Various debug levels */ +#define rt2x00_dbg(dev, fmt, ...)					\ +	wiphy_dbg((dev)->hw->wiphy, "%s: Debug - " fmt,			\ +		  __func__, ##__VA_ARGS__) +#define rt2x00_eeprom_dbg(dev, fmt, ...)				\ +	wiphy_dbg((dev)->hw->wiphy, "%s: EEPROM recovery - " fmt,	\ +		  __func__, ##__VA_ARGS__)  /*   * Duration calculations @@ -149,17 +137,6 @@  #define SHORT_EIFS		( SIFS + SHORT_DIFS + \  				  GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) -/* - * Structure for average calculation - * The avg field contains the actual average value, - * but avg_weight is internally used during calculations - * to prevent rounding errors. - */ -struct avg_val { -	int avg; -	int avg_weight; -}; -  enum rt2x00_chip_intf {  	RT2X00_CHIP_INTF_PCI,  	RT2X00_CHIP_INTF_PCIE, @@ -185,10 +162,15 @@ struct rt2x00_chip {  #define RT3070		0x3070  #define RT3071		0x3071  #define RT3090		0x3090	/* 2.4GHz PCIe */ +#define RT3290		0x3290 +#define RT3352		0x3352  /* WSOC */  #define RT3390		0x3390  #define RT3572		0x3572 -#define RT3593		0x3593	/* PCIe */ +#define RT3593		0x3593  #define RT3883		0x3883	/* WSOC */ +#define RT5390		0x5390  /* 2.4GHz */ +#define RT5392		0x5392  /* 2.4GHz */ +#define RT5592		0x5592  	u16 rf;  	u16 rev; @@ -217,6 +199,7 @@ struct channel_info {  	short max_power;  	short default_power1;  	short default_power2; +	short default_power3;  };  /* @@ -225,6 +208,8 @@ struct channel_info {  struct antenna_setup {  	enum antenna rx;  	enum antenna tx; +	u8 rx_chain_num; +	u8 tx_chain_num;  };  /* @@ -300,7 +285,7 @@ struct link_ant {  	 * Similar to the avg_rssi in the link_qual structure  	 * this value is updated by using the walking average.  	 */ -	struct avg_val rssi_ant; +	struct ewma rssi_ant;  };  /* @@ -329,7 +314,7 @@ struct link {  	/*  	 * Currently active average RSSI value  	 */ -	struct avg_val avg_rssi; +	struct ewma avg_rssi;  	/*  	 * Work structure for scheduling periodic link tuning. @@ -345,30 +330,28 @@ struct link {  	 * to bring the device/driver back into the desired state.  	 */  	struct delayed_work watchdog_work; -}; -/* - * Interface structure - * Per interface configuration details, this structure - * is allocated as the private data for ieee80211_vif. - */ -struct rt2x00_intf {  	/* -	 * All fields within the rt2x00_intf structure -	 * must be protected with a spinlock. +	 * Work structure for scheduling periodic AGC adjustments.  	 */ -	spinlock_t lock; +	struct delayed_work agc_work;  	/* -	 * MAC of the device. +	 * Work structure for scheduling periodic VCO calibration.  	 */ -	u8 mac[ETH_ALEN]; +	struct delayed_work vco_work; +}; -	/* -	 * BBSID of the AP to associate with. -	 */ -	u8 bssid[ETH_ALEN]; +enum rt2x00_delayed_flags { +	DELAYED_UPDATE_BEACON, +}; +/* + * Interface structure + * Per interface configuration details, this structure + * is allocated as the private data for ieee80211_vif. + */ +struct rt2x00_intf {  	/*  	 * beacon->skb must be protected with the mutex.  	 */ @@ -380,20 +363,19 @@ struct rt2x00_intf {  	 * dedicated beacon entry.  	 */  	struct queue_entry *beacon; +	bool enable_beacon;  	/*  	 * Actions that needed rescheduling.  	 */ -	unsigned int delayed_flags; -#define DELAYED_UPDATE_BEACON		0x00000001 +	unsigned long delayed_flags;  	/*  	 * Software sequence counter, this is only required  	 * for hardware which doesn't support hardware  	 * sequence counting.  	 */ -	spinlock_t seqlock; -	u16 seqno; +	atomic_t seqno;  };  static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) @@ -476,11 +458,12 @@ struct rt2x00lib_crypto {  	const u8 *address;  	u32 bssidx; -	u32 aid;  	u8 key[16];  	u8 tx_mic[8];  	u8 rx_mic[8]; + +	int wcid;  };  /* @@ -494,13 +477,13 @@ struct rt2x00intf_conf {  	enum nl80211_iftype type;  	/* -	 * TSF sync value, this is dependant on the operation type. +	 * TSF sync value, this is dependent on the operation type.  	 */  	enum tsf_sync sync;  	/* -	 * The MAC and BSSID addressess are simple array of bytes, -	 * these arrays are little endian, so when sending the addressess +	 * The MAC and BSSID addresses are simple array of bytes, +	 * these arrays are little endian, so when sending the addresses  	 * to the drivers, copy the it into a endian-signed variable.  	 *  	 * Note that all devices (except rt2500usb) have 32 bits @@ -515,6 +498,19 @@ struct rt2x00intf_conf {  };  /* + * Private structure for storing STA details + * wcid: Wireless Client ID + */ +struct rt2x00_sta { +	int wcid; +}; + +static inline struct rt2x00_sta* sta_to_rt2x00_sta(struct ieee80211_sta *sta) +{ +	return (struct rt2x00_sta *)sta->drv_priv; +} + +/*   * rt2x00lib callback functions.   */  struct rt2x00lib_ops { @@ -524,14 +520,13 @@ struct rt2x00lib_ops {  	irq_handler_t irq_handler;  	/* -	 * Threaded Interrupt handlers. -	 */ -	irq_handler_t irq_handler_thread; - -	/*  	 * TX status tasklet handler.  	 */  	void (*txstatus_tasklet) (unsigned long data); +	void (*pretbtt_tasklet) (unsigned long data); +	void (*tbtt_tasklet) (unsigned long data); +	void (*rxdone_tasklet) (unsigned long data); +	void (*autowake_tasklet) (unsigned long data);  	/*  	 * Device init handlers. @@ -567,7 +562,18 @@ struct rt2x00lib_ops {  			     struct link_qual *qual);  	void (*link_tuner) (struct rt2x00_dev *rt2x00dev,  			    struct link_qual *qual, const u32 count); +	void (*gain_calibration) (struct rt2x00_dev *rt2x00dev); +	void (*vco_calibration) (struct rt2x00_dev *rt2x00dev); + +	/* +	 * Data queue handlers. +	 */  	void (*watchdog) (struct rt2x00_dev *rt2x00dev); +	void (*start_queue) (struct data_queue *queue); +	void (*kick_queue) (struct data_queue *queue); +	void (*stop_queue) (struct data_queue *queue); +	void (*flush_queue) (struct data_queue *queue, bool drop); +	void (*tx_dma_done) (struct queue_entry *entry);  	/*  	 * TX control handlers @@ -578,9 +584,8 @@ struct rt2x00lib_ops {  			       struct txentry_desc *txdesc);  	void (*write_beacon) (struct queue_entry *entry,  			      struct txentry_desc *txdesc); +	void (*clear_beacon) (struct queue_entry *entry);  	int (*get_tx_data_len) (struct queue_entry *entry); -	void (*kick_tx_queue) (struct data_queue *queue); -	void (*kill_tx_queue) (struct data_queue *queue);  	/*  	 * RX control handlers @@ -615,6 +620,11 @@ struct rt2x00lib_ops {  	void (*config) (struct rt2x00_dev *rt2x00dev,  			struct rt2x00lib_conf *libconf,  			const unsigned int changed_flags); +	int (*sta_add) (struct rt2x00_dev *rt2x00dev, +			struct ieee80211_vif *vif, +			struct ieee80211_sta *sta); +	int (*sta_remove) (struct rt2x00_dev *rt2x00dev, +			   int wcid);  };  /* @@ -622,16 +632,12 @@ struct rt2x00lib_ops {   */  struct rt2x00_ops {  	const char *name; -	const unsigned int max_sta_intf; +	const unsigned int drv_data_size;  	const unsigned int max_ap_intf;  	const unsigned int eeprom_size;  	const unsigned int rf_size;  	const unsigned int tx_queues; -	const unsigned int extra_tx_headroom; -	const struct data_queue_desc *rx; -	const struct data_queue_desc *tx; -	const struct data_queue_desc *bcn; -	const struct data_queue_desc *atim; +	void (*queue_init)(struct data_queue *queue);  	const struct rt2x00lib_ops *lib;  	const void *drv;  	const struct ieee80211_ops *hw; @@ -641,11 +647,11 @@ struct rt2x00_ops {  };  /* - * rt2x00 device flags + * rt2x00 state flags   */ -enum rt2x00_flags { +enum rt2x00_state_flags {  	/* -	 * Device state flags +	 * Device flags  	 */  	DEVICE_STATE_PRESENT,  	DEVICE_STATE_REGISTERED_HW, @@ -655,36 +661,65 @@ enum rt2x00_flags {  	DEVICE_STATE_SCANNING,  	/* -	 * Driver requirements +	 * Driver configuration  	 */ -	DRIVER_REQUIRE_FIRMWARE, -	DRIVER_REQUIRE_BEACON_GUARD, -	DRIVER_REQUIRE_ATIM_QUEUE, -	DRIVER_REQUIRE_DMA, -	DRIVER_REQUIRE_COPY_IV, -	DRIVER_REQUIRE_L2PAD, -	DRIVER_REQUIRE_TXSTATUS_FIFO, +	CONFIG_CHANNEL_HT40, +	CONFIG_POWERSAVING, +	CONFIG_HT_DISABLED, +	CONFIG_QOS_DISABLED,  	/* -	 * Driver features +	 * Mark we currently are sequentially reading TX_STA_FIFO register +	 * FIXME: this is for only rt2800usb, should go to private data  	 */ -	CONFIG_SUPPORT_HW_BUTTON, -	CONFIG_SUPPORT_HW_CRYPTO, -	DRIVER_SUPPORT_CONTROL_FILTERS, -	DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, -	DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, -	DRIVER_SUPPORT_LINK_TUNING, -	DRIVER_SUPPORT_WATCHDOG, +	TX_STATUS_READING, +}; -	/* -	 * Driver configuration -	 */ -	CONFIG_FRAME_TYPE, -	CONFIG_RF_SEQUENCE, -	CONFIG_EXTERNAL_LNA_A, -	CONFIG_EXTERNAL_LNA_BG, -	CONFIG_DOUBLE_ANTENNA, -	CONFIG_CHANNEL_HT40, +/* + * rt2x00 capability flags + */ +enum rt2x00_capability_flags { +	/* +	 * Requirements +	 */ +	REQUIRE_FIRMWARE, +	REQUIRE_BEACON_GUARD, +	REQUIRE_ATIM_QUEUE, +	REQUIRE_DMA, +	REQUIRE_COPY_IV, +	REQUIRE_L2PAD, +	REQUIRE_TXSTATUS_FIFO, +	REQUIRE_TASKLET_CONTEXT, +	REQUIRE_SW_SEQNO, +	REQUIRE_HT_TX_DESC, +	REQUIRE_PS_AUTOWAKE, +	REQUIRE_DELAYED_RFKILL, + +	/* +	 * Capabilities +	 */ +	CAPABILITY_HW_BUTTON, +	CAPABILITY_HW_CRYPTO, +	CAPABILITY_POWER_LIMIT, +	CAPABILITY_CONTROL_FILTERS, +	CAPABILITY_CONTROL_FILTER_PSPOLL, +	CAPABILITY_PRE_TBTT_INTERRUPT, +	CAPABILITY_LINK_TUNING, +	CAPABILITY_FRAME_TYPE, +	CAPABILITY_RF_SEQUENCE, +	CAPABILITY_EXTERNAL_LNA_A, +	CAPABILITY_EXTERNAL_LNA_BG, +	CAPABILITY_DOUBLE_ANTENNA, +	CAPABILITY_BT_COEXIST, +	CAPABILITY_VCO_RECALIBRATION, +}; + +/* + * Interface combinations + */ +enum { +	IF_COMB_AP = 0, +	NUM_IF_COMB,  };  /* @@ -706,6 +741,11 @@ struct rt2x00_dev {  	const struct rt2x00_ops *ops;  	/* +	 * Driver data. +	 */ +	void *drv_data; + +	/*  	 * IEEE80211 control structure.  	 */  	struct ieee80211_hw *hw; @@ -733,13 +773,20 @@ struct rt2x00_dev {  #endif /* CONFIG_RT2X00_LIB_LEDS */  	/* -	 * Device flags. -	 * In these flags the current status and some -	 * of the device capabilities are stored. +	 * Device state flags. +	 * In these flags the current status is stored. +	 * Access to these flags should occur atomically.  	 */  	unsigned long flags;  	/* +	 * Device capabiltiy flags. +	 * In these flags the device/driver capabilities are stored. +	 * Access to these flags should occur non-atomically. +	 */ +	unsigned long cap_flags; + +	/*  	 * Device information, Bus IRQ and name (PCI, SoC)  	 */  	int irq; @@ -794,10 +841,18 @@ struct rt2x00_dev {  	 *  - Open ap interface count.  	 *  - Open sta interface count.  	 *  - Association count. +	 *  - Beaconing enabled count.  	 */  	unsigned int intf_ap_count;  	unsigned int intf_sta_count;  	unsigned int intf_associated; +	unsigned int intf_beaconing; + +	/* +	 * Interface combinations +	 */ +	struct ieee80211_iface_limit if_limits_ap; +	struct ieee80211_iface_combination if_combinations[NUM_IF_COMB];  	/*  	 * Link quality @@ -841,28 +896,38 @@ struct rt2x00_dev {  	u8 rssi_offset;  	/* -	 * Frequency offset (for rt61pci & rt73usb). +	 * Frequency offset.  	 */  	u8 freq_offset;  	/* -	 * Calibration information (for rt2800usb & rt2800pci). -	 * [0] -> BW20 -	 * [1] -> BW40 +	 * Association id.  	 */ -	u8 calibration[2]; +	u16 aid;  	/*  	 * Beacon interval.  	 */  	u16 beacon_int; +	/** +	 * Timestamp of last received beacon +	 */ +	unsigned long last_beacon; +  	/*  	 * Low level statistics which will have  	 * to be kept up to date while device is running.  	 */  	struct ieee80211_low_level_stats low_level_stats; +	/** +	 * Work queue for all work which should not be placed +	 * on the mac80211 workqueue (because of dependencies +	 * between various work structures). +	 */ +	struct workqueue_struct *workqueue; +  	/*  	 * Scheduled work.  	 * NOTE: intf_work will use ieee80211_iterate_active_interfaces() @@ -878,14 +943,19 @@ struct rt2x00_dev {  	struct work_struct txdone_work;  	/* -	 * Data queue arrays for RX, TX and Beacon. -	 * The Beacon array also contains the Atim queue -	 * if that is supported by the device. +	 * Powersaving work +	 */ +	struct delayed_work autowakeup_work; +	struct work_struct sleep_work; + +	/* +	 * Data queue arrays for RX, TX, Beacon and ATIM.  	 */  	unsigned int data_queues;  	struct data_queue *rx;  	struct data_queue *tx;  	struct data_queue *bcn; +	struct data_queue *atim;  	/*  	 * Firmware image. @@ -893,20 +963,56 @@ struct rt2x00_dev {  	const struct firmware *fw;  	/* -	 * Interrupt values, stored between interrupt service routine -	 * and interrupt thread routine. +	 * FIFO for storing tx status reports between isr and tasklet.  	 */ -	u32 irqvalue[2]; +	DECLARE_KFIFO_PTR(txstatus_fifo, u32);  	/* -	 * FIFO for storing tx status reports between isr and tasklet. +	 * Timer to ensure tx status reports are read (rt2800usb).  	 */ -	struct kfifo txstatus_fifo; +	struct hrtimer txstatus_timer;  	/*  	 * Tasklet for processing tx status reports (rt2800pci).  	 */  	struct tasklet_struct txstatus_tasklet; +	struct tasklet_struct pretbtt_tasklet; +	struct tasklet_struct tbtt_tasklet; +	struct tasklet_struct rxdone_tasklet; +	struct tasklet_struct autowake_tasklet; + +	/* +	 * Used for VCO periodic calibration. +	 */ +	int rf_channel; + +	/* +	 * Protect the interrupt mask register. +	 */ +	spinlock_t irqmask_lock; + +	/* +	 * List of BlockAckReq TX entries that need driver BlockAck processing. +	 */ +	struct list_head bar_list; +	spinlock_t bar_list_lock; + +	/* Extra TX headroom required for alignment purposes. */ +	unsigned int extra_tx_headroom; +}; + +struct rt2x00_bar_list_entry { +	struct list_head list; +	struct rcu_head head; + +	struct queue_entry *entry; +	int block_acked; + +	/* Relevant parts of the IEEE80211 BAR header */ +	__u8 ra[6]; +	__u8 ta[6]; +	__le16 control; +	__le16 start_seq_num;  };  /* @@ -937,8 +1043,7 @@ static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev,  }  /* - *  Generic EEPROM access. - * The EEPROM is being accessed by word index. + * Generic EEPROM access. The EEPROM is being accessed by word or byte index.   */  static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev,  				       const unsigned int word) @@ -958,6 +1063,12 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev,  	rt2x00dev->eeprom[word] = cpu_to_le16(data);  } +static inline u8 rt2x00_eeprom_byte(struct rt2x00_dev *rt2x00dev, +				    const unsigned int byte) +{ +	return *(((u8 *)rt2x00dev->eeprom) + byte); +} +  /*   * Chipset handlers   */ @@ -968,9 +1079,27 @@ static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev,  	rt2x00dev->chip.rf = rf;  	rt2x00dev->chip.rev = rev; -	INFO(rt2x00dev, -	     "Chipset detected - rt: %04x, rf: %04x, rev: %04x.\n", -	     rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); +	rt2x00_info(rt2x00dev, "Chipset detected - rt: %04x, rf: %04x, rev: %04x\n", +		    rt2x00dev->chip.rt, rt2x00dev->chip.rf, +		    rt2x00dev->chip.rev); +} + +static inline void rt2x00_set_rt(struct rt2x00_dev *rt2x00dev, +				 const u16 rt, const u16 rev) +{ +	rt2x00dev->chip.rt = rt; +	rt2x00dev->chip.rev = rev; + +	rt2x00_info(rt2x00dev, "RT chipset %04x, rev %04x detected\n", +		    rt2x00dev->chip.rt, rt2x00dev->chip.rev); +} + +static inline void rt2x00_set_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) +{ +	rt2x00dev->chip.rf = rf; + +	rt2x00_info(rt2x00dev, "RF chipset %04x detected\n", +		    rt2x00dev->chip.rf);  }  static inline bool rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) @@ -1039,11 +1168,100 @@ static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev)  	return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);  } +/* Helpers for capability flags */ + +static inline bool +rt2x00_has_cap_flag(struct rt2x00_dev *rt2x00dev, +		    enum rt2x00_capability_flags cap_flag) +{ +	return test_bit(cap_flag, &rt2x00dev->cap_flags); +} + +static inline bool +rt2x00_has_cap_hw_crypto(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_HW_CRYPTO); +} + +static inline bool +rt2x00_has_cap_power_limit(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_POWER_LIMIT); +} + +static inline bool +rt2x00_has_cap_control_filters(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTERS); +} + +static inline bool +rt2x00_has_cap_control_filter_pspoll(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_CONTROL_FILTER_PSPOLL); +} + +static inline bool +rt2x00_has_cap_pre_tbtt_interrupt(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_PRE_TBTT_INTERRUPT); +} + +static inline bool +rt2x00_has_cap_link_tuning(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_LINK_TUNING); +} + +static inline bool +rt2x00_has_cap_frame_type(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_FRAME_TYPE); +} + +static inline bool +rt2x00_has_cap_rf_sequence(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_RF_SEQUENCE); +} + +static inline bool +rt2x00_has_cap_external_lna_a(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_A); +} + +static inline bool +rt2x00_has_cap_external_lna_bg(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_EXTERNAL_LNA_BG); +} + +static inline bool +rt2x00_has_cap_double_antenna(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_DOUBLE_ANTENNA); +} + +static inline bool +rt2x00_has_cap_bt_coexist(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_BT_COEXIST); +} + +static inline bool +rt2x00_has_cap_vco_recalibration(struct rt2x00_dev *rt2x00dev) +{ +	return rt2x00_has_cap_flag(rt2x00dev, CAPABILITY_VCO_RECALIBRATION); +} +  /**   * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.   * @entry: Pointer to &struct queue_entry + * + * Returns -ENOMEM if mapping fail, 0 otherwise.   */ -void rt2x00queue_map_txskb(struct queue_entry *entry); +int rt2x00queue_map_txskb(struct queue_entry *entry);  /**   * rt2x00queue_unmap_skb - Unmap a skb from DMA. @@ -1052,12 +1270,24 @@ void rt2x00queue_map_txskb(struct queue_entry *entry);  void rt2x00queue_unmap_skb(struct queue_entry *entry);  /** - * rt2x00queue_get_queue - Convert queue index to queue pointer + * rt2x00queue_get_tx_queue - Convert tx queue index to queue pointer   * @rt2x00dev: Pointer to &struct rt2x00_dev.   * @queue: rt2x00 queue index (see &enum data_queue_qid). + * + * Returns NULL for non tx queues.   */ -struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, -					 const enum data_queue_qid queue); +static inline struct data_queue * +rt2x00queue_get_tx_queue(struct rt2x00_dev *rt2x00dev, +			 const enum data_queue_qid queue) +{ +	if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx) +		return &rt2x00dev->tx[queue]; + +	if (queue == QID_ATIM) +		return rt2x00dev->atim; + +	return NULL; +}  /**   * rt2x00queue_get_entry - Get queue entry where the given index points to. @@ -1067,6 +1297,78 @@ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,  struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,  					  enum queue_index index); +/** + * rt2x00queue_pause_queue - Pause a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will pause the data queue locally, preventing + * new frames to be added to the queue (while the hardware is + * still allowed to run). + */ +void rt2x00queue_pause_queue(struct data_queue *queue); + +/** + * rt2x00queue_unpause_queue - unpause a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will unpause the data queue locally, allowing + * new frames to be added to the queue again. + */ +void rt2x00queue_unpause_queue(struct data_queue *queue); + +/** + * rt2x00queue_start_queue - Start a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will start handling all pending frames in the queue. + */ +void rt2x00queue_start_queue(struct data_queue *queue); + +/** + * rt2x00queue_stop_queue - Halt a data queue + * @queue: Pointer to &struct data_queue. + * + * This function will stop all pending frames in the queue. + */ +void rt2x00queue_stop_queue(struct data_queue *queue); + +/** + * rt2x00queue_flush_queue - Flush a data queue + * @queue: Pointer to &struct data_queue. + * @drop: True to drop all pending frames. + * + * This function will flush the queue. After this call + * the queue is guaranteed to be empty. + */ +void rt2x00queue_flush_queue(struct data_queue *queue, bool drop); + +/** + * rt2x00queue_start_queues - Start all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * This function will loop through all available queues to start them + */ +void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00queue_stop_queues - Halt all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * + * This function will loop through all available queues to stop + * any pending frames. + */ +void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00queue_flush_queues - Flush all data queues + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @drop: True to drop all pending frames. + * + * This function will loop through all available queues to flush + * any pending frames. + */ +void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop); +  /*   * Debugfs handlers.   */ @@ -1088,20 +1390,29 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,  #endif /* CONFIG_RT2X00_LIB_DEBUGFS */  /* + * Utility functions. + */ +u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev, +			 struct ieee80211_vif *vif); + +/*   * Interrupt context handlers.   */  void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);  void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); +void rt2x00lib_dmastart(struct queue_entry *entry);  void rt2x00lib_dmadone(struct queue_entry *entry);  void rt2x00lib_txdone(struct queue_entry *entry,  		      struct txdone_entry_desc *txdesc);  void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status); -void rt2x00lib_rxdone(struct queue_entry *entry); +void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp);  /*   * mac80211 handlers.   */ -int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); +void rt2x00mac_tx(struct ieee80211_hw *hw, +		  struct ieee80211_tx_control *control, +		  struct sk_buff *skb);  int rt2x00mac_start(struct ieee80211_hw *hw);  void rt2x00mac_stop(struct ieee80211_hw *hw);  int rt2x00mac_add_interface(struct ieee80211_hw *hw, @@ -1122,6 +1433,10 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,  #else  #define rt2x00mac_set_key	NULL  #endif /* CONFIG_RT2X00_LIB_CRYPTO */ +int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +		      struct ieee80211_sta *sta); +int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +			 struct ieee80211_sta *sta);  void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw);  void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw);  int rt2x00mac_get_stats(struct ieee80211_hw *hw, @@ -1130,10 +1445,17 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,  				struct ieee80211_vif *vif,  				struct ieee80211_bss_conf *bss_conf,  				u32 changes); -int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue, +int rt2x00mac_conf_tx(struct ieee80211_hw *hw, +		      struct ieee80211_vif *vif, u16 queue,  		      const struct ieee80211_tx_queue_params *params);  void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); -void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop); +void rt2x00mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +		     u32 queues, bool drop); +int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant); +int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant); +void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, +			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); +bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw);  /*   * Driver allocation handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index a238e908c85..1122dc44c9f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -60,15 +58,15 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev,  	 * Note that when NULL is passed as address 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. +	 * to ACK frames or considers itself associated.  	 */ -	memset(&conf.mac, 0, sizeof(conf.mac)); +	memset(conf.mac, 0, sizeof(conf.mac));  	if (mac) -		memcpy(&conf.mac, mac, ETH_ALEN); +		memcpy(conf.mac, mac, ETH_ALEN); -	memset(&conf.bssid, 0, sizeof(conf.bssid)); +	memset(conf.bssid, 0, sizeof(conf.bssid));  	if (bssid) -		memcpy(&conf.bssid, bssid, ETH_ALEN); +		memcpy(conf.bssid, bssid, ETH_ALEN);  	flags |= CONFIG_UPDATE_TYPE;  	if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) @@ -100,6 +98,10 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,  	erp.basic_rates = bss_conf->basic_rates;  	erp.beacon_int = bss_conf->beacon_int; +	/* Update the AID, this is needed for dynamic PS support */ +	rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0; +	rt2x00dev->last_beacon = bss_conf->sync_tsf; +  	/* Update global beacon interval time, this is needed for PS support */  	rt2x00dev->beacon_int = bss_conf->beacon_int; @@ -109,15 +111,6 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,  	rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp, changed);  } -static inline -enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant, -					    enum antenna default_ant) -{ -	if (current_ant != ANTENNA_SW_DIVERSITY) -		return current_ant; -	return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B; -} -  void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,  			      struct antenna_setup config)  { @@ -126,19 +119,35 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,  	struct antenna_setup *active = &rt2x00dev->link.ant.active;  	/* -	 * Failsafe: Make sure we are not sending the -	 * ANTENNA_SW_DIVERSITY state to the driver. -	 * If that happens, fallback to hardware defaults, -	 * or our own default. +	 * When the caller tries to send the SW diversity, +	 * we must update the ANTENNA_RX_DIVERSITY flag to +	 * enable the antenna diversity in the link tuner. +	 * +	 * Secondly, we must guarentee we never send the +	 * software antenna diversity command to the driver.  	 */ -	if (!(ant->flags & ANTENNA_RX_DIVERSITY)) -		config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); -	else if (config.rx == ANTENNA_SW_DIVERSITY) +	if (!(ant->flags & ANTENNA_RX_DIVERSITY)) { +		if (config.rx == ANTENNA_SW_DIVERSITY) { +			ant->flags |= ANTENNA_RX_DIVERSITY; + +			if (def->rx == ANTENNA_SW_DIVERSITY) +				config.rx = ANTENNA_B; +			else +				config.rx = def->rx; +		} +	} else if (config.rx == ANTENNA_SW_DIVERSITY)  		config.rx = active->rx; -	if (!(ant->flags & ANTENNA_TX_DIVERSITY)) -		config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx); -	else if (config.tx == ANTENNA_SW_DIVERSITY) +	if (!(ant->flags & ANTENNA_TX_DIVERSITY)) { +		if (config.tx == ANTENNA_SW_DIVERSITY) { +			ant->flags |= ANTENNA_TX_DIVERSITY; + +			if (def->tx == ANTENNA_SW_DIVERSITY) +				config.tx = ANTENNA_B; +			else +				config.tx = def->tx; +		} +	} else if (config.tx == ANTENNA_SW_DIVERSITY)  		config.tx = active->tx;  	/* @@ -146,8 +155,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,  	 * else the changes will be ignored by the device.  	 */  	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) -		rt2x00dev->ops->lib->set_device_state(rt2x00dev, -						      STATE_RADIO_RX_OFF); +		rt2x00queue_stop_queue(rt2x00dev->rx);  	/*  	 * Write new antenna setup to device and reset the link tuner. @@ -161,8 +169,35 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,  	memcpy(active, &config, sizeof(config));  	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) -		rt2x00dev->ops->lib->set_device_state(rt2x00dev, -						      STATE_RADIO_RX_ON); +		rt2x00queue_start_queue(rt2x00dev->rx); +} + +static u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, +				   struct ieee80211_conf *conf) +{ +	struct hw_mode_spec *spec = &rt2x00dev->spec; +	int center_channel; +	u16 i; + +	/* +	 * Initialize center channel to current channel. +	 */ +	center_channel = spec->channels[conf->chandef.chan->hw_value].channel; + +	/* +	 * Adjust center channel to HT40+ and HT40- operation. +	 */ +	if (conf_is_ht40_plus(conf)) +		center_channel += 2; +	else if (conf_is_ht40_minus(conf)) +		center_channel -= (center_channel == 14) ? 1 : 2; + +	for (i = 0; i < spec->num_channels; i++) +		if (spec->channels[i].channel == center_channel) +			return i; + +	WARN_ON(1); +	return conf->chandef.chan->hw_value;  }  void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, @@ -171,18 +206,26 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,  {  	struct rt2x00lib_conf libconf;  	u16 hw_value; +	u16 autowake_timeout; +	u16 beacon_int; +	u16 beacon_diff;  	memset(&libconf, 0, sizeof(libconf));  	libconf.conf = conf;  	if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { +		if (!conf_is_ht(conf)) +			set_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags); +		else +			clear_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags); +  		if (conf_is_ht40(conf)) { -			__set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); +			set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags);  			hw_value = rt2x00ht_center_channel(rt2x00dev, conf);  		} else { -			__clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); -			hw_value = conf->channel->hw_value; +			clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); +			hw_value = conf->chandef.chan->hw_value;  		}  		memcpy(&libconf.rf, @@ -192,8 +235,15 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,  		memcpy(&libconf.channel,  		       &rt2x00dev->spec.channels_info[hw_value],  		       sizeof(libconf.channel)); + +		/* Used for VCO periodic calibration */ +		rt2x00dev->rf_channel = libconf.rf.channel;  	} +	if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && +	    (ieee80211_flags & IEEE80211_CONF_CHANGE_PS)) +		cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); +  	/*  	 * Start configuration.  	 */ @@ -206,8 +256,29 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,  	if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)  		rt2x00link_reset_tuner(rt2x00dev, false); -	rt2x00dev->curr_band = conf->channel->band; -	rt2x00dev->curr_freq = conf->channel->center_freq; +	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && +	    test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && +	    (ieee80211_flags & IEEE80211_CONF_CHANGE_PS) && +	    (conf->flags & IEEE80211_CONF_PS)) { +		beacon_diff = (long)jiffies - (long)rt2x00dev->last_beacon; +		beacon_int = msecs_to_jiffies(rt2x00dev->beacon_int); + +		if (beacon_diff > beacon_int) +			beacon_diff = 0; + +		autowake_timeout = (conf->max_sleep_period * beacon_int) - beacon_diff; +		queue_delayed_work(rt2x00dev->workqueue, +				   &rt2x00dev->autowakeup_work, +				   autowake_timeout - 15); +	} + +	if (conf->flags & IEEE80211_CONF_PS) +		set_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); +	else +		clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); + +	rt2x00dev->curr_band = conf->chandef.chan->band; +	rt2x00dev->curr_freq = conf->chandef.chan->center_freq;  	rt2x00dev->tx_power = conf->power_level;  	rt2x00dev->short_retry = conf->short_frame_max_tx_count;  	rt2x00dev->long_retry = conf->long_frame_max_tx_count; diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 5e9074bf2b8..a2fd05ba25c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -45,14 +43,14 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)  	}  } -void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, +void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev, +				       struct sk_buff *skb,  				       struct txentry_desc *txdesc)  { -	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);  	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; -	if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !hw_key) +	if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !hw_key)  		return;  	__set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); @@ -80,7 +78,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,  	struct ieee80211_key_conf *key = tx_info->control.hw_key;  	unsigned int overhead = 0; -	if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !key) +	if (!rt2x00_has_cap_hw_crypto(rt2x00dev) || !key)  		return overhead;  	/* @@ -237,7 +235,7 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,  	}  	/* -	 * NOTE: Always count the payload as transfered, +	 * NOTE: Always count the payload as transferred,  	 * even when alignment was set to zero. This is required  	 * for determining the correct offset for the ICV data.  	 */ diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 64dfb1f6823..90fdb02b55e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -63,12 +61,14 @@ struct rt2x00debug_intf {  	 * - driver folder  	 *   - driver file  	 *   - chipset file -	 *   - device flags file +	 *   - device state flags file +	 *   - device capability flags file  	 *   - register folder  	 *     - csr offset/value files  	 *     - eeprom offset/value files  	 *     - bbp offset/value files  	 *     - rf offset/value files +	 *     - rfcsr offset/value files  	 *   - queue folder  	 *     - frame dump file  	 *     - queue stats file @@ -78,6 +78,7 @@ struct rt2x00debug_intf {  	struct dentry *driver_entry;  	struct dentry *chipset_entry;  	struct dentry *dev_flags; +	struct dentry *cap_flags;  	struct dentry *register_folder;  	struct dentry *csr_off_entry;  	struct dentry *csr_val_entry; @@ -87,6 +88,8 @@ struct rt2x00debug_intf {  	struct dentry *bbp_val_entry;  	struct dentry *rf_off_entry;  	struct dentry *rf_val_entry; +	struct dentry *rfcsr_off_entry; +	struct dentry *rfcsr_val_entry;  	struct dentry *queue_folder;  	struct dentry *queue_frame_dump_entry;  	struct dentry *queue_stats_entry; @@ -129,6 +132,7 @@ struct rt2x00debug_intf {  	unsigned int offset_eeprom;  	unsigned int offset_bbp;  	unsigned int offset_rf; +	unsigned int offset_rfcsr;  };  void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, @@ -168,7 +172,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,  	do_gettimeofday(×tamp);  	if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) { -		DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n"); +		rt2x00_dbg(rt2x00dev, "txrx dump queue length exceeded\n");  		return;  	} @@ -179,7 +183,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,  	skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + data_len,  			    GFP_ATOMIC);  	if (!skbcopy) { -		DEBUG(rt2x00dev, "Failed to copy skb for dump.\n"); +		rt2x00_dbg(rt2x00dev, "Failed to copy skb for dump\n");  		return;  	} @@ -282,7 +286,7 @@ static ssize_t rt2x00debug_read_queue_dump(struct file *file,  	if (retval)  		return retval; -	status = min((size_t)skb->len, length); +	status = min_t(size_t, skb->len, length);  	if (copy_to_user(buf, skb->data, status)) {  		status = -EFAULT;  		goto exit; @@ -339,12 +343,13 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file,  		return -ENOMEM;  	temp = data + -	    sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n"); +	    sprintf(data, "qid\tflags\t\tcount\tlimit\tlength\tindex\tdma done\tdone\n");  	queue_for_each(intf->rt2x00dev, queue) {  		spin_lock_irqsave(&queue->index_lock, irqflags); -		temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, +		temp += sprintf(temp, "%d\t0x%.8x\t%d\t%d\t%d\t%d\t%d\t\t%d\n", +				queue->qid, (unsigned int)queue->flags,  				queue->count, queue->limit, queue->length,  				queue->index[Q_INDEX],  				queue->index[Q_INDEX_DMA_DONE], @@ -522,6 +527,7 @@ 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); +RT2X00DEBUGFS_OPS(rfcsr, "0x%.2x\n", u8);  static ssize_t rt2x00debug_read_dev_flags(struct file *file,  					  char __user *buf, @@ -552,6 +558,35 @@ static const struct file_operations rt2x00debug_fop_dev_flags = {  	.llseek		= default_llseek,  }; +static ssize_t rt2x00debug_read_cap_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; + +	if (*offset) +		return 0; + +	size = sprintf(line, "0x%.8x\n", (unsigned int)intf->rt2x00dev->cap_flags); + +	if (copy_to_user(buf, line, size)) +		return -EFAULT; + +	*offset += size; +	return size; +} + +static const struct file_operations rt2x00debug_fop_cap_flags = { +	.owner		= THIS_MODULE, +	.read		= rt2x00debug_read_cap_flags, +	.open		= rt2x00debug_file_open, +	.release	= rt2x00debug_file_release, +	.llseek		= default_llseek, +}; +  static struct dentry *rt2x00debug_create_file_driver(const char *name,  						     struct rt2x00debug_intf  						     *intf, @@ -567,7 +602,6 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name,  	blob->data = data;  	data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name);  	data += sprintf(data, "version:\t%s\n", DRV_VERSION); -	data += sprintf(data, "compiled:\t%s %s\n", __DATE__, __TIME__);  	blob->size = strlen(blob->data);  	return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob); @@ -583,7 +617,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,  	const struct rt2x00debug *debug = intf->debug;  	char *data; -	data = kzalloc(8 * MAX_LINE_LENGTH, GFP_KERNEL); +	data = kzalloc(9 * MAX_LINE_LENGTH, GFP_KERNEL);  	if (!data)  		return NULL; @@ -593,22 +627,22 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,  	data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev);  	data += sprintf(data, "\n");  	data += sprintf(data, "register\tbase\twords\twordsize\n"); -	data += sprintf(data, "csr\t%d\t%d\t%d\n", -			debug->csr.word_base, -			debug->csr.word_count, -			debug->csr.word_size); -	data += sprintf(data, "eeprom\t%d\t%d\t%d\n", -			debug->eeprom.word_base, -			debug->eeprom.word_count, -			debug->eeprom.word_size); -	data += sprintf(data, "bbp\t%d\t%d\t%d\n", -			debug->bbp.word_base, -			debug->bbp.word_count, -			debug->bbp.word_size); -	data += sprintf(data, "rf\t%d\t%d\t%d\n", -			debug->rf.word_base, -			debug->rf.word_count, -			debug->rf.word_size); +#define RT2X00DEBUGFS_SPRINTF_REGISTER(__name)			\ +{								\ +	if(debug->__name.read)					\ +		data += sprintf(data, __stringify(__name)	\ +				"\t%d\t%d\t%d\n",		\ +				debug->__name.word_base,	\ +				debug->__name.word_count,	\ +				debug->__name.word_size);	\ +} +	RT2X00DEBUGFS_SPRINTF_REGISTER(csr); +	RT2X00DEBUGFS_SPRINTF_REGISTER(eeprom); +	RT2X00DEBUGFS_SPRINTF_REGISTER(bbp); +	RT2X00DEBUGFS_SPRINTF_REGISTER(rf); +	RT2X00DEBUGFS_SPRINTF_REGISTER(rfcsr); +#undef RT2X00DEBUGFS_SPRINTF_REGISTER +  	blob->size = strlen(blob->data);  	return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob); @@ -621,7 +655,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)  	intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL);  	if (!intf) { -		ERROR(rt2x00dev, "Failed to allocate debug handler.\n"); +		rt2x00_err(rt2x00dev, "Failed to allocate debug handler\n");  		return;  	} @@ -652,36 +686,45 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)  	if (IS_ERR(intf->dev_flags) || !intf->dev_flags)  		goto exit; +	intf->cap_flags = debugfs_create_file("cap_flags", S_IRUSR, +					      intf->driver_folder, intf, +					      &rt2x00debug_fop_cap_flags); +	if (IS_ERR(intf->cap_flags) || !intf->cap_flags) +		goto exit; +  	intf->register_folder =  	    debugfs_create_dir("register", intf->driver_folder);  	if (IS_ERR(intf->register_folder) || !intf->register_folder)  		goto exit; -#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name)	\ -({								\ -	(__intf)->__name##_off_entry =				\ -	    debugfs_create_u32(__stringify(__name) "_offset",	\ -			       S_IRUSR | S_IWUSR,		\ -			       (__intf)->register_folder,	\ -			       &(__intf)->offset_##__name);	\ -	if (IS_ERR((__intf)->__name##_off_entry)		\ -			|| !(__intf)->__name##_off_entry)	\ -		goto exit;					\ -								\ -	(__intf)->__name##_val_entry =				\ -	    debugfs_create_file(__stringify(__name) "_value",	\ -				S_IRUSR | S_IWUSR,		\ -				(__intf)->register_folder,	\ -				(__intf), &rt2x00debug_fop_##__name);\ -	if (IS_ERR((__intf)->__name##_val_entry)		\ -			|| !(__intf)->__name##_val_entry)	\ -		goto exit;					\ +#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name)			\ +({										\ +	if(debug->__name.read) {						\ +		(__intf)->__name##_off_entry =					\ +		debugfs_create_u32(__stringify(__name) "_offset",		\ +				       S_IRUSR | S_IWUSR,			\ +				       (__intf)->register_folder,		\ +				       &(__intf)->offset_##__name);		\ +		if (IS_ERR((__intf)->__name##_off_entry)			\ +				|| !(__intf)->__name##_off_entry)		\ +			goto exit;						\ +										\ +		(__intf)->__name##_val_entry =					\ +		debugfs_create_file(__stringify(__name) "_value",		\ +					S_IRUSR | S_IWUSR,			\ +					(__intf)->register_folder,		\ +					(__intf), &rt2x00debug_fop_##__name);	\ +		if (IS_ERR((__intf)->__name##_val_entry)			\ +				|| !(__intf)->__name##_val_entry)		\ +			goto exit;						\ +	}									\  })  	RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr);  	RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom);  	RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp);  	RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf); +	RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rfcsr);  #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY @@ -705,7 +748,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)  				intf, &rt2x00debug_fop_queue_stats);  #ifdef CONFIG_RT2X00_LIB_CRYPTO -	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) +	if (rt2x00_has_cap_hw_crypto(rt2x00dev))  		intf->crypto_stats_entry =  		    debugfs_create_file("crypto", S_IRUGO, intf->queue_folder,  					intf, &rt2x00debug_fop_crypto_stats); @@ -715,7 +758,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)  exit:  	rt2x00debug_deregister(rt2x00dev); -	ERROR(rt2x00dev, "Failed to register debug handler.\n"); +	rt2x00_err(rt2x00dev, "Failed to register debug handler\n");  }  void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) @@ -733,6 +776,8 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)  	debugfs_remove(intf->queue_stats_entry);  	debugfs_remove(intf->queue_frame_dump_entry);  	debugfs_remove(intf->queue_folder); +	debugfs_remove(intf->rfcsr_val_entry); +	debugfs_remove(intf->rfcsr_off_entry);  	debugfs_remove(intf->rf_val_entry);  	debugfs_remove(intf->rf_off_entry);  	debugfs_remove(intf->bbp_val_entry); @@ -743,6 +788,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)  	debugfs_remove(intf->csr_off_entry);  	debugfs_remove(intf->register_folder);  	debugfs_remove(intf->dev_flags); +	debugfs_remove(intf->cap_flags);  	debugfs_remove(intf->chipset_entry);  	debugfs_remove(intf->driver_entry);  	debugfs_remove(intf->driver_folder); diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h index fa11409cb5c..e65712c235b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.h +++ b/drivers/net/wireless/rt2x00/rt2x00debug.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -65,6 +63,7 @@ struct rt2x00debug {  	RT2X00DEBUGFS_REGISTER_ENTRY(eeprom, u16);  	RT2X00DEBUGFS_REGISTER_ENTRY(bbp, u8);  	RT2X00DEBUGFS_REGISTER_ENTRY(rf, u32); +	RT2X00DEBUGFS_REGISTER_ENTRY(rfcsr, u8);  };  #endif /* RT2X00DEBUG_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index c879f9a7037..4fa43a2eeb7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -14,9 +14,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -27,11 +25,28 @@  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/slab.h> +#include <linux/log2.h>  #include "rt2x00.h"  #include "rt2x00lib.h"  /* + * Utility functions. + */ +u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev, +			 struct ieee80211_vif *vif) +{ +	/* +	 * When in STA mode, bssidx is always 0 otherwise local_address[5] +	 * contains the bss number, see BSS_ID_MASK comments for details. +	 */ +	if (rt2x00dev->intf_sta_count) +		return 0; +	return vif->addr[5] & (rt2x00dev->ops->max_ap_intf - 1); +} +EXPORT_SYMBOL_GPL(rt2x00lib_get_bssidx); + +/*   * Radio control handlers.   */  int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) @@ -66,21 +81,19 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)  	set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);  	/* -	 * Enable RX. +	 * Enable queues.  	 */ -	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_ON); +	rt2x00queue_start_queues(rt2x00dev);  	rt2x00link_start_tuner(rt2x00dev); +	rt2x00link_start_agc(rt2x00dev); +	if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) +		rt2x00link_start_vcocal(rt2x00dev);  	/*  	 * Start watchdog monitoring.  	 */  	rt2x00link_start_watchdog(rt2x00dev); -	/* -	 * Start the TX queues. -	 */ -	ieee80211_wake_queues(rt2x00dev->hw); -  	return 0;  } @@ -90,21 +103,19 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)  		return;  	/* -	 * Stop the TX queues in mac80211. -	 */ -	ieee80211_stop_queues(rt2x00dev->hw); -	rt2x00queue_stop_queues(rt2x00dev); - -	/*  	 * Stop watchdog monitoring.  	 */  	rt2x00link_stop_watchdog(rt2x00dev);  	/* -	 * Disable RX. +	 * Stop all queues  	 */ +	rt2x00link_stop_agc(rt2x00dev); +	if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) +		rt2x00link_stop_vcocal(rt2x00dev);  	rt2x00link_stop_tuner(rt2x00dev); -	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_OFF); +	rt2x00queue_stop_queues(rt2x00dev); +	rt2x00queue_flush_queues(rt2x00dev, true);  	/*  	 * Disable radio. @@ -120,19 +131,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,  {  	struct rt2x00_dev *rt2x00dev = data;  	struct rt2x00_intf *intf = vif_to_intf(vif); -	int delayed_flags; - -	/* -	 * Copy all data we need during this action under the protection -	 * of a spinlock. Otherwise race conditions might occur which results -	 * into an invalid configuration. -	 */ -	spin_lock(&intf->lock); - -	delayed_flags = intf->delayed_flags; -	intf->delayed_flags = 0; - -	spin_unlock(&intf->lock);  	/*  	 * It is possible the radio was disabled while the work had been @@ -143,8 +141,8 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,  	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))  		return; -	if (delayed_flags & DELAYED_UPDATE_BEACON) -		rt2x00queue_update_beacon(rt2x00dev, vif, true); +	if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags)) +		rt2x00queue_update_beacon(rt2x00dev, vif);  }  static void rt2x00lib_intf_scheduled(struct work_struct *work) @@ -157,16 +155,31 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)  	 * requested configurations.  	 */  	ieee80211_iterate_active_interfaces(rt2x00dev->hw, +					    IEEE80211_IFACE_ITER_RESUME_ALL,  					    rt2x00lib_intf_scheduled_iter,  					    rt2x00dev);  } +static void rt2x00lib_autowakeup(struct work_struct *work) +{ +	struct rt2x00_dev *rt2x00dev = +	    container_of(work, struct rt2x00_dev, autowakeup_work.work); + +	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) +		return; + +	if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) +		rt2x00_err(rt2x00dev, "Device failed to wakeup\n"); +	clear_bit(CONFIG_POWERSAVING, &rt2x00dev->flags); +} +  /*   * Interrupt context handlers.   */  static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac,  				     struct ieee80211_vif *vif)  { +	struct ieee80211_tx_control control = {};  	struct rt2x00_dev *rt2x00dev = data;  	struct sk_buff *skb; @@ -181,7 +194,7 @@ static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac,  	 */  	skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);  	while (skb) { -		rt2x00mac_tx(rt2x00dev->hw, skb); +		rt2x00mac_tx(rt2x00dev->hw, &control, skb);  		skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);  	}  } @@ -197,7 +210,13 @@ static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac,  	    vif->type != NL80211_IFTYPE_WDS)  		return; -	rt2x00queue_update_beacon(rt2x00dev, vif, true); +	/* +	 * Update the beacon without locking. This is safe on PCI devices +	 * as they only update the beacon periodically here. This should +	 * never be called for USB devices. +	 */ +	WARN_ON(rt2x00_is_usb(rt2x00dev)); +	rt2x00queue_update_beacon_locked(rt2x00dev, vif);  }  void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) @@ -206,21 +225,21 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)  		return;  	/* send buffered bc/mc frames out for every bssid */ -	ieee80211_iterate_active_interfaces(rt2x00dev->hw, -					    rt2x00lib_bc_buffer_iter, -					    rt2x00dev); +	ieee80211_iterate_active_interfaces_atomic( +		rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL, +		rt2x00lib_bc_buffer_iter, rt2x00dev);  	/*  	 * Devices with pre tbtt interrupt don't need to update the beacon  	 * here as they will fetch the next beacon directly prior to  	 * transmission.  	 */ -	if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags)) +	if (rt2x00_has_cap_pre_tbtt_interrupt(rt2x00dev))  		return;  	/* fetch next beacon */ -	ieee80211_iterate_active_interfaces(rt2x00dev->hw, -					    rt2x00lib_beaconupdate_iter, -					    rt2x00dev); +	ieee80211_iterate_active_interfaces_atomic( +		rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL, +		rt2x00lib_beaconupdate_iter, rt2x00dev);  }  EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); @@ -230,26 +249,77 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)  		return;  	/* fetch next beacon */ -	ieee80211_iterate_active_interfaces(rt2x00dev->hw, -					    rt2x00lib_beaconupdate_iter, -					    rt2x00dev); +	ieee80211_iterate_active_interfaces_atomic( +		rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL, +		rt2x00lib_beaconupdate_iter, rt2x00dev);  }  EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); +void rt2x00lib_dmastart(struct queue_entry *entry) +{ +	set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); +	rt2x00queue_index_inc(entry, Q_INDEX); +} +EXPORT_SYMBOL_GPL(rt2x00lib_dmastart); +  void rt2x00lib_dmadone(struct queue_entry *entry)  { +	set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);  	clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); -	rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE); +	rt2x00queue_index_inc(entry, Q_INDEX_DMA_DONE);  }  EXPORT_SYMBOL_GPL(rt2x00lib_dmadone); +static inline int rt2x00lib_txdone_bar_status(struct queue_entry *entry) +{ +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +	struct ieee80211_bar *bar = (void *) entry->skb->data; +	struct rt2x00_bar_list_entry *bar_entry; +	int ret; + +	if (likely(!ieee80211_is_back_req(bar->frame_control))) +		return 0; + +	/* +	 * Unlike all other frames, the status report for BARs does +	 * not directly come from the hardware as it is incapable of +	 * matching a BA to a previously send BAR. The hardware will +	 * report all BARs as if they weren't acked at all. +	 * +	 * Instead the RX-path will scan for incoming BAs and set the +	 * block_acked flag if it sees one that was likely caused by +	 * a BAR from us. +	 * +	 * Remove remaining BARs here and return their status for +	 * TX done processing. +	 */ +	ret = 0; +	rcu_read_lock(); +	list_for_each_entry_rcu(bar_entry, &rt2x00dev->bar_list, list) { +		if (bar_entry->entry != entry) +			continue; + +		spin_lock_bh(&rt2x00dev->bar_list_lock); +		/* Return whether this BAR was blockacked or not */ +		ret = bar_entry->block_acked; +		/* Remove the BAR from our checklist */ +		list_del_rcu(&bar_entry->list); +		spin_unlock_bh(&rt2x00dev->bar_list_lock); +		kfree_rcu(bar_entry, head); + +		break; +	} +	rcu_read_unlock(); + +	return ret; +} +  void rt2x00lib_txdone(struct queue_entry *entry,  		      struct txdone_entry_desc *txdesc)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); -	enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);  	unsigned int header_length, i;  	u8 rate_idx, rate_flags, retry_rates;  	u8 skbdesc_flags = skbdesc->flags; @@ -263,7 +333,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	/*  	 * Remove the extra tx headroom from the skb.  	 */ -	skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom); +	skb_pull(entry->skb, rt2x00dev->extra_tx_headroom);  	/*  	 * Signal that the TX descriptor is no longer in the skb. @@ -278,7 +348,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	/*  	 * Remove L2 padding which was added during  	 */ -	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) +	if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))  		rt2x00queue_remove_l2pad(entry->skb, header_length);  	/* @@ -287,7 +357,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	 * mac80211 will expect the same data to be present it the  	 * frame as it was passed to us.  	 */ -	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) +	if (rt2x00_has_cap_hw_crypto(rt2x00dev))  		rt2x00crypto_tx_insert_iv(entry->skb, header_length);  	/* @@ -297,9 +367,12 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb);  	/* -	 * Determine if the frame has been successfully transmitted. +	 * Determine if the frame has been successfully transmitted and +	 * remove BARs from our check list while checking for their +	 * TX status.  	 */  	success = +	    rt2x00lib_txdone_bar_status(entry) ||  	    test_bit(TXDONE_SUCCESS, &txdesc->flags) ||  	    test_bit(TXDONE_UNKNOWN, &txdesc->flags); @@ -360,10 +433,14 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	 * which would allow the rc algorithm to better decide on  	 * which rates are suitable.  	 */ -	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { +	if (test_bit(TXDONE_AMPDU, &txdesc->flags) || +	    tx_info->flags & IEEE80211_TX_CTL_AMPDU) {  		tx_info->flags |= IEEE80211_TX_STAT_AMPDU;  		tx_info->status.ampdu_len = 1;  		tx_info->status.ampdu_ack_len = success ? 1 : 0; + +		if (!success) +			tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;  	}  	if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { @@ -379,9 +456,12 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	 * through a mac80211 library call (RTS/CTS) then we should not  	 * send the status report back.  	 */ -	if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) -		ieee80211_tx_status(rt2x00dev->hw, entry->skb); -	else +	if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) { +		if (test_bit(REQUIRE_TASKLET_CONTEXT, &rt2x00dev->cap_flags)) +			ieee80211_tx_status(rt2x00dev->hw, entry->skb); +		else +			ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb); +	} else  		dev_kfree_skb_any(entry->skb);  	/* @@ -392,15 +472,19 @@ void rt2x00lib_txdone(struct queue_entry *entry,  	rt2x00dev->ops->lib->clear_entry(entry); -	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); +	rt2x00queue_index_inc(entry, Q_INDEX_DONE);  	/*  	 * If the data queue was below the threshold before the txdone  	 * handler we must make sure the packet queue in the mac80211 stack -	 * is reenabled when the txdone handler has finished. +	 * is reenabled when the txdone handler has finished. This has to be +	 * serialized with rt2x00mac_tx(), otherwise we can wake up queue +	 * before it was stopped.  	 */ +	spin_lock_bh(&entry->queue->tx_lock);  	if (!rt2x00queue_threshold(entry->queue)) -		ieee80211_wake_queue(rt2x00dev->hw, qid); +		rt2x00queue_unpause_queue(entry->queue); +	spin_unlock_bh(&entry->queue->tx_lock);  }  EXPORT_SYMBOL_GPL(rt2x00lib_txdone); @@ -416,6 +500,137 @@ void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status)  }  EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo); +static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie) +{ +	struct ieee80211_mgmt *mgmt = (void *)data; +	u8 *pos, *end; + +	pos = (u8 *)mgmt->u.beacon.variable; +	end = data + len; +	while (pos < end) { +		if (pos + 2 + pos[1] > end) +			return NULL; + +		if (pos[0] == ie) +			return pos; + +		pos += 2 + pos[1]; +	} + +	return NULL; +} + +static void rt2x00lib_sleep(struct work_struct *work) +{ +	struct rt2x00_dev *rt2x00dev = +	    container_of(work, struct rt2x00_dev, sleep_work); + +	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) +		return; + +	/* +	 * Check again is powersaving is enabled, to prevent races from delayed +	 * work execution. +	 */ +	if (!test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags)) +		rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf, +				 IEEE80211_CONF_CHANGE_PS); +} + +static void rt2x00lib_rxdone_check_ba(struct rt2x00_dev *rt2x00dev, +				      struct sk_buff *skb, +				      struct rxdone_entry_desc *rxdesc) +{ +	struct rt2x00_bar_list_entry *entry; +	struct ieee80211_bar *ba = (void *)skb->data; + +	if (likely(!ieee80211_is_back(ba->frame_control))) +		return; + +	if (rxdesc->size < sizeof(*ba) + FCS_LEN) +		return; + +	rcu_read_lock(); +	list_for_each_entry_rcu(entry, &rt2x00dev->bar_list, list) { + +		if (ba->start_seq_num != entry->start_seq_num) +			continue; + +#define TID_CHECK(a, b) (						\ +	((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) ==	\ +	((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)))		\ + +		if (!TID_CHECK(ba->control, entry->control)) +			continue; + +#undef TID_CHECK + +		if (!ether_addr_equal_64bits(ba->ra, entry->ta)) +			continue; + +		if (!ether_addr_equal_64bits(ba->ta, entry->ra)) +			continue; + +		/* Mark BAR since we received the according BA */ +		spin_lock_bh(&rt2x00dev->bar_list_lock); +		entry->block_acked = 1; +		spin_unlock_bh(&rt2x00dev->bar_list_lock); +		break; +	} +	rcu_read_unlock(); + +} + +static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev, +				      struct sk_buff *skb, +				      struct rxdone_entry_desc *rxdesc) +{ +	struct ieee80211_hdr *hdr = (void *) skb->data; +	struct ieee80211_tim_ie *tim_ie; +	u8 *tim; +	u8 tim_len; +	bool cam; + +	/* If this is not a beacon, or if mac80211 has no powersaving +	 * configured, or if the device is already in powersaving mode +	 * we can exit now. */ +	if (likely(!ieee80211_is_beacon(hdr->frame_control) || +		   !(rt2x00dev->hw->conf.flags & IEEE80211_CONF_PS))) +		return; + +	/* min. beacon length + FCS_LEN */ +	if (skb->len <= 40 + FCS_LEN) +		return; + +	/* and only beacons from the associated BSSID, please */ +	if (!(rxdesc->dev_flags & RXDONE_MY_BSS) || +	    !rt2x00dev->aid) +		return; + +	rt2x00dev->last_beacon = jiffies; + +	tim = rt2x00lib_find_ie(skb->data, skb->len - FCS_LEN, WLAN_EID_TIM); +	if (!tim) +		return; + +	if (tim[1] < sizeof(*tim_ie)) +		return; + +	tim_len = tim[1]; +	tim_ie = (struct ieee80211_tim_ie *) &tim[2]; + +	/* Check whenever the PHY can be turned off again. */ + +	/* 1. What about buffered unicast traffic for our AID? */ +	cam = ieee80211_check_tim(tim_ie, tim_len, rt2x00dev->aid); + +	/* 2. Maybe the AP wants to send multicast/broadcast data? */ +	cam |= (tim_ie->bitmap_ctrl & 0x01); + +	if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags)) +		queue_work(rt2x00dev->workqueue, &rt2x00dev->sleep_work); +} +  static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,  					struct rxdone_entry_desc *rxdesc)  { @@ -457,13 +672,12 @@ static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,  		break;  	} -	WARNING(rt2x00dev, "Frame received with unrecognized signal, " -		"mode=0x%.4x, signal=0x%.4x, type=%d.\n", -		rxdesc->rate_mode, signal, type); +	rt2x00_warn(rt2x00dev, "Frame received with unrecognized signal, mode=0x%.4x, signal=0x%.4x, type=%d\n", +		    rxdesc->rate_mode, signal, type);  	return 0;  } -void rt2x00lib_rxdone(struct queue_entry *entry) +void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct rxdone_entry_desc rxdesc; @@ -483,7 +697,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)  	 * Allocate a new sk_buffer. If no new buffer available, drop the  	 * received frame and reuse the existing buffer.  	 */ -	skb = rt2x00queue_alloc_rxskb(entry); +	skb = rt2x00queue_alloc_rxskb(entry, gfp);  	if (!skb)  		goto submit_entry; @@ -499,6 +713,18 @@ void rt2x00lib_rxdone(struct queue_entry *entry)  	rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);  	/* +	 * Check for valid size in case we get corrupted descriptor from +	 * hardware. +	 */ +	if (unlikely(rxdesc.size == 0 || +		     rxdesc.size > entry->queue->data_size)) { +		rt2x00_err(rt2x00dev, "Wrong frame size %d max %d\n", +			   rxdesc.size, entry->queue->data_size); +		dev_kfree_skb(entry->skb); +		goto renew_skb; +	} + +	/*  	 * The data behind the ieee80211 header must be  	 * aligned on a 4 byte boundary.  	 */ @@ -518,8 +744,6 @@ void rt2x00lib_rxdone(struct queue_entry *entry)  		 (rxdesc.size > header_length) &&  		 (rxdesc.dev_flags & RXDONE_L2PAD))  		rt2x00queue_remove_l2pad(entry->skb, header_length); -	else -		rt2x00queue_align_payload(entry->skb, header_length);  	/* Trim buffer to correct size */  	skb_trim(entry->skb, rxdesc.size); @@ -533,6 +757,18 @@ void rt2x00lib_rxdone(struct queue_entry *entry)  		rxdesc.flags |= RX_FLAG_HT;  	/* +	 * Check if this is a beacon, and more frames have been +	 * buffered while we were in powersaving mode. +	 */ +	rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc); + +	/* +	 * Check for incoming BlockAcks to match to the BlockAckReqs +	 * we've send out. +	 */ +	rt2x00lib_rxdone_check_ba(rt2x00dev, entry->skb, &rxdesc); + +	/*  	 * Update extra components  	 */  	rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); @@ -544,6 +780,14 @@ void rt2x00lib_rxdone(struct queue_entry *entry)  	 * to mac80211.  	 */  	rx_status = IEEE80211_SKB_RXCB(entry->skb); + +	/* Ensure that all fields of rx_status are initialized +	 * properly. The skb->cb array was used for driver +	 * specific informations, so rx_status might contain +	 * garbage. +	 */ +	memset(rx_status, 0, sizeof(*rx_status)); +  	rx_status->mactime = rxdesc.timestamp;  	rx_status->band = rt2x00dev->curr_band;  	rx_status->freq = rt2x00dev->curr_freq; @@ -554,6 +798,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)  	ieee80211_rx_ni(rt2x00dev->hw, entry->skb); +renew_skb:  	/*  	 * Replace the skb with the freshly allocated one.  	 */ @@ -561,12 +806,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry)  submit_entry:  	entry->flags = 0; -	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); +	rt2x00queue_index_inc(entry, Q_INDEX_DONE);  	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && -	    test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) { +	    test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))  		rt2x00dev->ops->lib->clear_entry(entry); -		rt2x00queue_index_inc(entry->queue, Q_INDEX); -	}  }  EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); @@ -664,7 +907,10 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry,  			      const int channel, const int tx_power,  			      const int value)  { -	entry->center_freq = ieee80211_channel_to_frequency(channel); +	/* XXX: this assumption about the band is wrong for 802.11j */ +	entry->band = channel <= 14 ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; +	entry->center_freq = ieee80211_channel_to_frequency(channel, +							    entry->band);  	entry->hw_value = value;  	entry->max_power = tx_power;  	entry->max_antenna_gain = 0xff; @@ -697,11 +943,11 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,  	if (spec->supported_rates & SUPPORT_RATE_OFDM)  		num_rates += 8; -	channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL); +	channels = kcalloc(spec->num_channels, sizeof(*channels), GFP_KERNEL);  	if (!channels)  		return -ENOMEM; -	rates = kzalloc(sizeof(*rates) * num_rates, GFP_KERNEL); +	rates = kcalloc(num_rates, sizeof(*rates), GFP_KERNEL);  	if (!rates)  		goto exit_free_channels; @@ -758,7 +1004,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,   exit_free_channels:  	kfree(channels); -	ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n"); +	rt2x00_err(rt2x00dev, "Allocation ieee80211 modes failed\n");  	return -ENOMEM;  } @@ -802,40 +1048,63 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)  	 */  	rt2x00dev->hw->extra_tx_headroom =  		max_t(unsigned int, IEEE80211_TX_STATUS_HEADROOM, -		      rt2x00dev->ops->extra_tx_headroom); +		      rt2x00dev->extra_tx_headroom);  	/*  	 * Take TX headroom required for alignment into account.  	 */ -	if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) +	if (test_bit(REQUIRE_L2PAD, &rt2x00dev->cap_flags))  		rt2x00dev->hw->extra_tx_headroom += RT2X00_L2PAD_SIZE; -	else if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) +	else if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags))  		rt2x00dev->hw->extra_tx_headroom += RT2X00_ALIGN_SIZE;  	/* +	 * Tell mac80211 about the size of our private STA structure. +	 */ +	rt2x00dev->hw->sta_data_size = sizeof(struct rt2x00_sta); + +	/*  	 * Allocate tx status FIFO for driver use.  	 */ -	if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags) && -	    rt2x00dev->ops->lib->txstatus_tasklet) { +	if (test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags)) {  		/* -		 * Allocate txstatus fifo and tasklet, we use a size of 512 -		 * for the kfifo which is big enough to store 512/4=128 tx -		 * status reports. In the worst case (tx status for all tx -		 * queues gets reported before we've got a chance to handle -		 * them) 24*4=384 tx status reports need to be cached. +		 * Allocate the txstatus fifo. In the worst case the tx +		 * status fifo has to hold the tx status of all entries +		 * in all tx queues. Hence, calculate the kfifo size as +		 * tx_queues * entry_num and round up to the nearest +		 * power of 2.  		 */ -		status = kfifo_alloc(&rt2x00dev->txstatus_fifo, 512, +		int kfifo_size = +			roundup_pow_of_two(rt2x00dev->ops->tx_queues * +					   rt2x00dev->tx->limit * +					   sizeof(u32)); + +		status = kfifo_alloc(&rt2x00dev->txstatus_fifo, kfifo_size,  				     GFP_KERNEL);  		if (status)  			return status; +	} -		/* tasklet for processing the tx status reports. */ -		tasklet_init(&rt2x00dev->txstatus_tasklet, -			     rt2x00dev->ops->lib->txstatus_tasklet, -			     (unsigned long)rt2x00dev); - +	/* +	 * Initialize tasklets if used by the driver. Tasklets are +	 * disabled until the interrupts are turned on. The driver +	 * has to handle that. +	 */ +#define RT2X00_TASKLET_INIT(taskletname) \ +	if (rt2x00dev->ops->lib->taskletname) { \ +		tasklet_init(&rt2x00dev->taskletname, \ +			     rt2x00dev->ops->lib->taskletname, \ +			     (unsigned long)rt2x00dev); \  	} +	RT2X00_TASKLET_INIT(txstatus_tasklet); +	RT2X00_TASKLET_INIT(pretbtt_tasklet); +	RT2X00_TASKLET_INIT(tbtt_tasklet); +	RT2X00_TASKLET_INIT(rxdone_tasklet); +	RT2X00_TASKLET_INIT(autowake_tasklet); + +#undef RT2X00_TASKLET_INIT +  	/*  	 * Register HW.  	 */ @@ -857,9 +1126,10 @@ static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)  		return;  	/* -	 * Unregister extra components. +	 * Stop rfkill polling.  	 */ -	rt2x00rfkill_unregister(rt2x00dev); +	if (test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags)) +		rt2x00rfkill_unregister(rt2x00dev);  	/*  	 * Allow the HW to uninitialize. @@ -898,9 +1168,10 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)  	set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags);  	/* -	 * Register the extra components. +	 * Start rfkill polling.  	 */ -	rt2x00rfkill_register(rt2x00dev); +	if (test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags)) +		rt2x00rfkill_register(rt2x00dev);  	return 0;  } @@ -957,6 +1228,51 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)  	rt2x00dev->intf_associated = 0;  } +static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev) +{ +	struct ieee80211_iface_limit *if_limit; +	struct ieee80211_iface_combination *if_combination; + +	if (rt2x00dev->ops->max_ap_intf < 2) +		return; + +	/* +	 * Build up AP interface limits structure. +	 */ +	if_limit = &rt2x00dev->if_limits_ap; +	if_limit->max = rt2x00dev->ops->max_ap_intf; +	if_limit->types = BIT(NL80211_IFTYPE_AP); +#ifdef CONFIG_MAC80211_MESH +	if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT); +#endif + +	/* +	 * Build up AP interface combinations structure. +	 */ +	if_combination = &rt2x00dev->if_combinations[IF_COMB_AP]; +	if_combination->limits = if_limit; +	if_combination->n_limits = 1; +	if_combination->max_interfaces = if_limit->max; +	if_combination->num_different_channels = 1; + +	/* +	 * Finally, specify the possible combinations to mac80211. +	 */ +	rt2x00dev->hw->wiphy->iface_combinations = rt2x00dev->if_combinations; +	rt2x00dev->hw->wiphy->n_iface_combinations = 1; +} + +static unsigned int rt2x00dev_extra_tx_headroom(struct rt2x00_dev *rt2x00dev) +{ +	if (WARN_ON(!rt2x00dev->tx)) +		return 0; + +	if (rt2x00_is_usb(rt2x00dev)) +		return rt2x00dev->tx[0].winfo_size + rt2x00dev->tx[0].desc_size; + +	return rt2x00dev->tx[0].winfo_size; +} +  /*   * driver allocation handlers.   */ @@ -964,7 +1280,27 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)  {  	int retval = -ENOMEM; +	/* +	 * Set possible interface combinations. +	 */ +	rt2x00lib_set_if_combinations(rt2x00dev); + +	/* +	 * Allocate the driver data memory, if necessary. +	 */ +	if (rt2x00dev->ops->drv_data_size > 0) { +		rt2x00dev->drv_data = kzalloc(rt2x00dev->ops->drv_data_size, +			                      GFP_KERNEL); +		if (!rt2x00dev->drv_data) { +			retval = -ENOMEM; +			goto exit; +		} +	} + +	spin_lock_init(&rt2x00dev->irqmask_lock);  	mutex_init(&rt2x00dev->csr_mutex); +	INIT_LIST_HEAD(&rt2x00dev->bar_list); +	spin_lock_init(&rt2x00dev->bar_list_lock);  	set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); @@ -975,29 +1311,32 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)  	rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);  	/* -	 * Determine which operating modes are supported, all modes -	 * which require beaconing, depend on the availability of -	 * beacon entries. +	 * rt2x00 devices can only use the last n bits of the MAC address +	 * for virtual interfaces.  	 */ -	rt2x00dev->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); -	if (rt2x00dev->ops->bcn->entry_num > 0) -		rt2x00dev->hw->wiphy->interface_modes |= -		    BIT(NL80211_IFTYPE_ADHOC) | -		    BIT(NL80211_IFTYPE_AP) | -		    BIT(NL80211_IFTYPE_MESH_POINT) | -		    BIT(NL80211_IFTYPE_WDS); +	rt2x00dev->hw->wiphy->addr_mask[ETH_ALEN - 1] = +		(rt2x00dev->ops->max_ap_intf - 1);  	/* -	 * Initialize configuration work. +	 * Initialize work.  	 */ +	rt2x00dev->workqueue = +	    alloc_ordered_workqueue("%s", 0, wiphy_name(rt2x00dev->hw->wiphy)); +	if (!rt2x00dev->workqueue) { +		retval = -ENOMEM; +		goto exit; +	} +  	INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); +	INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup); +	INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);  	/*  	 * Let the driver probe the device to detect the capabilities.  	 */  	retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev);  	if (retval) { -		ERROR(rt2x00dev, "Failed to allocate device.\n"); +		rt2x00_err(rt2x00dev, "Failed to allocate device\n");  		goto exit;  	} @@ -1008,12 +1347,32 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)  	if (retval)  		goto exit; +	/* Cache TX headroom value */ +	rt2x00dev->extra_tx_headroom = rt2x00dev_extra_tx_headroom(rt2x00dev); + +	/* +	 * Determine which operating modes are supported, all modes +	 * which require beaconing, depend on the availability of +	 * beacon entries. +	 */ +	rt2x00dev->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); +	if (rt2x00dev->bcn->limit > 0) +		rt2x00dev->hw->wiphy->interface_modes |= +		    BIT(NL80211_IFTYPE_ADHOC) | +		    BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH +		    BIT(NL80211_IFTYPE_MESH_POINT) | +#endif +		    BIT(NL80211_IFTYPE_WDS); + +	rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; +  	/*  	 * Initialize ieee80211 structure.  	 */  	retval = rt2x00lib_probe_hw(rt2x00dev);  	if (retval) { -		ERROR(rt2x00dev, "Failed to initialize hw.\n"); +		rt2x00_err(rt2x00dev, "Failed to initialize hw\n");  		goto exit;  	} @@ -1024,6 +1383,12 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)  	rt2x00leds_register(rt2x00dev);  	rt2x00debug_register(rt2x00dev); +	/* +	 * Start rfkill polling. +	 */ +	if (!test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags)) +		rt2x00rfkill_register(rt2x00dev); +  	return 0;  exit: @@ -1038,6 +1403,12 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)  	clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);  	/* +	 * Stop rfkill polling. +	 */ +	if (!test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags)) +		rt2x00rfkill_unregister(rt2x00dev); + +	/*  	 * Disable radio.  	 */  	rt2x00lib_disable_radio(rt2x00dev); @@ -1046,8 +1417,15 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)  	 * Stop all work.  	 */  	cancel_work_sync(&rt2x00dev->intf_work); -	cancel_work_sync(&rt2x00dev->rxdone_work); -	cancel_work_sync(&rt2x00dev->txdone_work); +	cancel_delayed_work_sync(&rt2x00dev->autowakeup_work); +	cancel_work_sync(&rt2x00dev->sleep_work); +	if (rt2x00_is_usb(rt2x00dev)) { +		hrtimer_cancel(&rt2x00dev->txstatus_timer); +		cancel_work_sync(&rt2x00dev->rxdone_work); +		cancel_work_sync(&rt2x00dev->txdone_work); +	} +	if (rt2x00dev->workqueue) +		destroy_workqueue(rt2x00dev->workqueue);  	/*  	 * Free the tx status fifo. @@ -1058,6 +1436,10 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)  	 * Kill the tx status tasklet.  	 */  	tasklet_kill(&rt2x00dev->txstatus_tasklet); +	tasklet_kill(&rt2x00dev->pretbtt_tasklet); +	tasklet_kill(&rt2x00dev->tbtt_tasklet); +	tasklet_kill(&rt2x00dev->rxdone_tasklet); +	tasklet_kill(&rt2x00dev->autowake_tasklet);  	/*  	 * Uninitialize device. @@ -1084,6 +1466,12 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)  	 * Free queue structures.  	 */  	rt2x00queue_free(rt2x00dev); + +	/* +	 * Free the driver data. +	 */ +	if (rt2x00dev->drv_data) +		kfree(rt2x00dev->drv_data);  }  EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); @@ -1093,7 +1481,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev);  #ifdef CONFIG_PM  int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)  { -	NOTICE(rt2x00dev, "Going to sleep.\n"); +	rt2x00_dbg(rt2x00dev, "Going to sleep\n");  	/*  	 * Prevent mac80211 from accessing driver while suspended. @@ -1124,8 +1512,7 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)  	 * device is as good as disabled.  	 */  	if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP)) -		WARNING(rt2x00dev, "Device failed to enter sleep state, " -			"continue suspending.\n"); +		rt2x00_warn(rt2x00dev, "Device failed to enter sleep state, continue suspending\n");  	return 0;  } @@ -1133,7 +1520,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_suspend);  int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)  { -	NOTICE(rt2x00dev, "Waking up.\n"); +	rt2x00_dbg(rt2x00dev, "Waking up\n");  	/*  	 * Restore/enable extra components. diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index 5d6e0b83151..4c0e01b5d51 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -51,7 +49,7 @@   *   [rt2x00dump header][hardware descriptor][ieee802.11 frame]   *   * rt2x00dump header: The description of the dumped frame, as well as - *	additional information usefull for debugging. See &rt2x00dump_hdr. + *	additional information useful for debugging. See &rt2x00dump_hdr.   * hardware descriptor: Descriptor that was used to receive or transmit   *	the frame.   * ieee802.11 frame: The actual frame that was received or transmitted. diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index f0e1eb72bef..fbae2799e3e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -14,9 +14,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -42,27 +40,28 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)  	 */  	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); +		rt2x00_err(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); +	rt2x00_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"); +		rt2x00_err(rt2x00dev, "Failed to request Firmware\n");  		return retval;  	}  	if (!fw || !fw->size || !fw->data) { -		ERROR(rt2x00dev, "Failed to read Firmware.\n"); +		rt2x00_err(rt2x00dev, "Failed to read Firmware\n"); +		release_firmware(fw);  		return -ENOENT;  	} -	INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", -	     fw->data[fw->size - 4], fw->data[fw->size - 3]); +	rt2x00_info(rt2x00dev, "Firmware detected - version: %d.%d\n", +		    fw->data[fw->size - 4], fw->data[fw->size - 3]);  	snprintf(rt2x00dev->hw->wiphy->fw_version,  			sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d",  			fw->data[fw->size - 4], fw->data[fw->size - 3]); @@ -72,15 +71,14 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev)  	case FW_OK:  		break;  	case FW_BAD_CRC: -		ERROR(rt2x00dev, "Firmware checksum error.\n"); +		rt2x00_err(rt2x00dev, "Firmware checksum error\n");  		goto exit;  	case FW_BAD_LENGTH: -		ERROR(rt2x00dev, -		      "Invalid firmware file length (len=%zu)\n", fw->size); +		rt2x00_err(rt2x00dev, "Invalid firmware file length (len=%zu)\n", +			   fw->size);  		goto exit;  	case FW_BAD_VERSION: -		ERROR(rt2x00dev, -		      "Current firmware does not support detected chipset.\n"); +		rt2x00_err(rt2x00dev, "Current firmware does not support detected chipset\n");  		goto exit;  	} @@ -98,7 +96,7 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)  {  	int retval; -	if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) +	if (!test_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags))  		return 0;  	if (!rt2x00dev->fw) { diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c deleted file mode 100644 index c637bcaec5f..00000000000 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ /dev/null @@ -1,144 +0,0 @@ -/* -	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> -	<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 HT specific routines. - */ - -#include <linux/kernel.h> -#include <linux/module.h> - -#include "rt2x00.h" -#include "rt2x00lib.h" - -void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, -				   struct txentry_desc *txdesc, -				   const struct rt2x00_rate *hwrate) -{ -	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); -	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; -	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; - -	if (tx_info->control.sta) -		txdesc->mpdu_density = -		    tx_info->control.sta->ht_cap.ampdu_density; -	else -		txdesc->mpdu_density = 0; - -	txdesc->ba_size = 7;	/* FIXME: What value is needed? */ - -	txdesc->stbc = -	    (tx_info->flags & IEEE80211_TX_CTL_STBC) >> IEEE80211_TX_CTL_STBC_SHIFT; - -	/* -	 * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the -	 * mcs rate to be used -	 */ -	if (txrate->flags & IEEE80211_TX_RC_MCS) { -		txdesc->mcs = txrate->idx; - -		/* -		 * MIMO PS should be set to 1 for STA's using dynamic SM PS -		 * when using more then one tx stream (>MCS7). -		 */ -		if (tx_info->control.sta && txdesc->mcs > 7 && -		    ((tx_info->control.sta->ht_cap.cap & -		      IEEE80211_HT_CAP_SM_PS) >> -		     IEEE80211_HT_CAP_SM_PS_SHIFT) == -		    WLAN_HT_CAP_SM_PS_DYNAMIC) -			__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); -	} else { -		txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); -		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) -			txdesc->mcs |= 0x08; -	} - - -	/* -	 * This frame is eligible for an AMPDU, however, don't aggregate -	 * frames that are intended to probe a specific tx rate. -	 */ -	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU && -	    !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) -		__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); - -	/* -	 * Determine HT Mix/Greenfield rate mode -	 */ -	if (txrate->flags & IEEE80211_TX_RC_MCS) -		txdesc->rate_mode = RATE_MODE_HT_MIX; -	if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) -		txdesc->rate_mode = RATE_MODE_HT_GREENFIELD; - -	/* -	 * Set 40Mhz mode if necessary (for legacy rates this will -	 * duplicate the frame to both channels). -	 */ -	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH || -	    txrate->flags & IEEE80211_TX_RC_DUP_DATA) -		__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); -	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) -		__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); - -	/* -	 * Determine IFS values -	 * - Use TXOP_BACKOFF for management frames -	 * - Use TXOP_SIFS for fragment bursts -	 * - Use TXOP_HTTXOP for everything else -	 * -	 * Note: rt2800 devices won't use CTS protection (if used) -	 * for frames not transmitted with TXOP_HTTXOP -	 */ -	if (ieee80211_is_mgmt(hdr->frame_control)) -		txdesc->txop = TXOP_BACKOFF; -	else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) -		txdesc->txop = TXOP_SIFS; -	else -		txdesc->txop = TXOP_HTTXOP; -} - -u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, -			    struct ieee80211_conf *conf) -{ -	struct hw_mode_spec *spec = &rt2x00dev->spec; -	int center_channel; -	u16 i; - -	/* -	 * Initialize center channel to current channel. -	 */ -	center_channel = spec->channels[conf->channel->hw_value].channel; - -	/* -	 * Adjust center channel to HT40+ and HT40- operation. -	 */ -	if (conf_is_ht40_plus(conf)) -		center_channel += 2; -	else if (conf_is_ht40_minus(conf)) -		center_channel -= (center_channel == 14) ? 1 : 2; - -	for (i = 0; i < spec->num_channels; i++) -		if (spec->channels[i].channel == center_channel) -			return i; - -	WARN_ON(1); -	return conf->channel->hw_value; -} diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index ca585e34d00..c681d04b506 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -113,7 +111,7 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,  	retval = led_classdev_register(device, &led->led_dev);  	if (retval) { -		ERROR(rt2x00dev, "Failed to register led handler.\n"); +		rt2x00_err(rt2x00dev, "Failed to register led handler\n");  		return retval;  	} @@ -124,17 +122,15 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,  void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)  { -	char dev_name[16]; -	char name[32]; +	char name[36];  	int retval;  	unsigned long on_period;  	unsigned long off_period; - -	snprintf(dev_name, sizeof(dev_name), "%s-%s", -		 rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy)); +	const char *phy_name = wiphy_name(rt2x00dev->hw->wiphy);  	if (rt2x00dev->led_radio.flags & LED_INITIALIZED) { -		snprintf(name, sizeof(name), "%s::radio", dev_name); +		snprintf(name, sizeof(name), "%s-%s::radio", +			 rt2x00dev->ops->name, phy_name);  		retval = rt2x00leds_register_led(rt2x00dev,  						 &rt2x00dev->led_radio, @@ -144,7 +140,8 @@ void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)  	}  	if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) { -		snprintf(name, sizeof(name), "%s::assoc", dev_name); +		snprintf(name, sizeof(name), "%s-%s::assoc", +			 rt2x00dev->ops->name, phy_name);  		retval = rt2x00leds_register_led(rt2x00dev,  						 &rt2x00dev->led_assoc, @@ -154,7 +151,8 @@ void rt2x00leds_register(struct rt2x00_dev *rt2x00dev)  	}  	if (rt2x00dev->led_qual.flags & LED_INITIALIZED) { -		snprintf(name, sizeof(name), "%s::quality", dev_name); +		snprintf(name, sizeof(name), "%s-%s::quality", +			 rt2x00dev->ops->name, phy_name);  		retval = rt2x00leds_register_led(rt2x00dev,  						 &rt2x00dev->led_qual, diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h index 3b46f0c3332..b2c5269570d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.h +++ b/drivers/net/wireless/rt2x00/rt2x00leds.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 2cf68f82674..fb7c349ccc9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -14,9 +14,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -32,6 +30,8 @@   */  #define WATCHDOG_INTERVAL	round_jiffies_relative(HZ)  #define LINK_TUNE_INTERVAL	round_jiffies_relative(HZ) +#define AGC_INTERVAL		round_jiffies_relative(4 * HZ) +#define VCO_INTERVAL		round_jiffies_relative(10 * HZ) /* 10 sec */  /*   * rt2x00_rate: Per rate device information @@ -101,7 +101,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,   * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes.   * @entry: The entry for which the skb will be applicable.   */ -struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry); +struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp);  /**   * rt2x00queue_free_skb - free a skb @@ -119,16 +119,6 @@ void rt2x00queue_free_skb(struct queue_entry *entry);  void rt2x00queue_align_frame(struct sk_buff *skb);  /** - * rt2x00queue_align_payload - Align 802.11 payload to 4-byte boundary - * @skb: The skb to align - * @header_length: Length of 802.11 header - * - * Align the 802.11 payload to a 4-byte boundary, this could - * mean the header is not aligned properly though. - */ -void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length); - -/**   * rt2x00queue_insert_l2pad - Align 802.11 header & payload to 4-byte boundary   * @skb: The skb to align   * @header_length: Length of 802.11 header @@ -154,37 +144,44 @@ void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length);   * @local: frame is not from mac80211   */  int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, -			       bool local); +			       struct ieee80211_sta *sta, bool local);  /** - * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware + * rt2x00queue_update_beacon - Send new beacon from mac80211 + *	to hardware. Handles locking by itself (mutex).   * @rt2x00dev: Pointer to &struct rt2x00_dev.   * @vif: Interface for which the beacon should be updated. - * @enable_beacon: Enable beaconing   */  int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, -			      struct ieee80211_vif *vif, -			      const bool enable_beacon); +			      struct ieee80211_vif *vif);  /** - * rt2x00queue_index_inc - Index incrementation function - * @queue: Queue (&struct data_queue) to perform the action on. - * @index: Index type (&enum queue_index) to perform the action on. - * - * This function will increase the requested index on the queue, - * it will grab the appropriate locks and handle queue overflow events by - * resetting the index to the start of the queue. + * rt2x00queue_update_beacon_locked - Send new beacon from mac80211 + *	to hardware. Caller needs to ensure locking. + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @vif: Interface for which the beacon should be updated.   */ -void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); +int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev, +				     struct ieee80211_vif *vif);  /** - * rt2x00queue_stop_queues - Halt all data queues + * rt2x00queue_clear_beacon - Clear beacon in hardware   * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @vif: Interface for which the beacon should be updated. + */ +int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev, +			     struct ieee80211_vif *vif); + +/** + * rt2x00queue_index_inc - Index incrementation function + * @entry: Queue entry (&struct queue_entry) to perform the action on. + * @index: Index type (&enum queue_index) to perform the action on.   * - * This function will loop through all available queues to stop - * any pending outgoing frames. + * This function will increase the requested index on the entry's queue, + * it will grab the appropriate locks and handle queue overflow events by + * resetting the index to the start of the queue.   */ -void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev); +void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index);  /**   * rt2x00queue_init_queues - Initialize all data queues @@ -274,6 +271,30 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev);  void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev);  /** + * rt2x00link_start_agc - Start periodic gain calibration + * @rt2x00dev: Pointer to &struct rt2x00_dev. + */ +void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00link_start_vcocal - Start periodic VCO calibration + * @rt2x00dev: Pointer to &struct rt2x00_dev. + */ +void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00link_stop_agc - Stop periodic gain calibration + * @rt2x00dev: Pointer to &struct rt2x00_dev. + */ +void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00link_stop_vcocal - Stop periodic VCO calibration + * @rt2x00dev: Pointer to &struct rt2x00_dev. + */ +void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev); + +/**   * rt2x00link_register - Initialize link tuning & watchdog functionality   * @rt2x00dev: Pointer to &struct rt2x00_dev.   * @@ -326,7 +347,8 @@ static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,   */  #ifdef CONFIG_RT2X00_LIB_CRYPTO  enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key); -void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, +void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev, +				       struct sk_buff *skb,  				       struct txentry_desc *txdesc);  unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev,  				      struct sk_buff *skb); @@ -344,7 +366,8 @@ static inline enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *  	return CIPHER_NONE;  } -static inline void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, +static inline void rt2x00crypto_create_tx_descriptor(struct rt2x00_dev *rt2x00dev, +						     struct sk_buff *skb,  						     struct txentry_desc *txdesc)  {  } @@ -378,41 +401,17 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,  #endif /* CONFIG_RT2X00_LIB_CRYPTO */  /* - * HT handlers. - */ -#ifdef CONFIG_RT2X00_LIB_HT -void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, -				   struct txentry_desc *txdesc, -				   const struct rt2x00_rate *hwrate); - -u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, -			    struct ieee80211_conf *conf); -#else -static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, -						 struct txentry_desc *txdesc, -						 const struct rt2x00_rate *hwrate) -{ -} - -static inline u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev, -					  struct ieee80211_conf *conf) -{ -	return conf->channel->hw_value; -} -#endif /* CONFIG_RT2X00_LIB_HT */ - -/*   * RFkill handlers.   */  static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)  { -	if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) +	if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))  		wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy);  }  static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev)  { -	if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) +	if (test_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags))  		wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy);  } diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index bfda60eaf4e..9b941c0c126 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -35,50 +33,28 @@   */  #define DEFAULT_RSSI		-128 -/* - * Helper struct and macro to work with moving/walking averages. - * When adding a value to the average value the following calculation - * is needed: - * - *        avg_rssi = ((avg_rssi * 7) + rssi) / 8; - * - * The advantage of this approach is that we only need 1 variable - * to store the average in (No need for a count and a total). - * But more importantly, normal average values will over time - * move less and less towards newly added values this 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, - * the speed of the average moving towards other values depends - * on the value for the number of samples. The higher the number - * of samples, the slower the average will move. - * We use two variables to keep track of the average value to - * compensate for the rounding errors. This can be a significant - * error (>5dBm) if the factor is too low. - */ -#define AVG_SAMPLES	8 -#define AVG_FACTOR	1000 -#define MOVING_AVERAGE(__avg, __val) \ -({ \ -	struct avg_val __new; \ -	__new.avg_weight = \ -	    (__avg).avg_weight  ? \ -		((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \ -		  ((__val) * (AVG_FACTOR))) / \ -		 (AVG_SAMPLES)) : \ -		((__val) * (AVG_FACTOR)); \ -	__new.avg = __new.avg_weight / (AVG_FACTOR); \ -	__new; \ -}) +/* Constants for EWMA calculations. */ +#define RT2X00_EWMA_FACTOR	1024 +#define RT2X00_EWMA_WEIGHT	8 + +static inline int rt2x00link_get_avg_rssi(struct ewma *ewma) +{ +	unsigned long avg; + +	avg = ewma_read(ewma); +	if (avg) +		return -avg; + +	return DEFAULT_RSSI; +}  static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)  {  	struct link_ant *ant = &rt2x00dev->link.ant; -	if (ant->rssi_ant.avg && rt2x00dev->link.qual.rx_success) -		return ant->rssi_ant.avg; +	if (rt2x00dev->link.qual.rx_success) +		return rt2x00link_get_avg_rssi(&ant->rssi_ant); +  	return DEFAULT_RSSI;  } @@ -100,8 +76,8 @@ static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev,  static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev)  { -	rt2x00dev->link.ant.rssi_ant.avg = 0; -	rt2x00dev->link.ant.rssi_ant.avg_weight = 0; +	ewma_init(&rt2x00dev->link.ant.rssi_ant, RT2X00_EWMA_FACTOR, +		  RT2X00_EWMA_WEIGHT);  }  static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) @@ -192,17 +168,7 @@ static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)  	/*  	 * Determine if software diversity is enabled for  	 * either the TX or RX antenna (or both). -	 * Always perform this check since within the link -	 * tuner interval the configuration might have changed.  	 */ -	ant->flags &= ~ANTENNA_RX_DIVERSITY; -	ant->flags &= ~ANTENNA_TX_DIVERSITY; - -	if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) -		ant->flags |= ANTENNA_RX_DIVERSITY; -	if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) -		ant->flags |= ANTENNA_TX_DIVERSITY; -  	if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&  	    !(ant->flags & ANTENNA_TX_DIVERSITY)) {  		ant->flags = 0; @@ -259,12 +225,12 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,  	/*  	 * Update global RSSI  	 */ -	link->avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi); +	ewma_add(&link->avg_rssi, -rxdesc->rssi);  	/*  	 * Update antenna RSSI  	 */ -	ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi); +	ewma_add(&ant->rssi_ant, -rxdesc->rssi);  }  void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) @@ -283,7 +249,7 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)  	/**  	 * While scanning, link tuning is disabled. By default  	 * the most sensitive settings will be used to make sure -	 * that all beacons and probe responses will be recieved +	 * that all beacons and probe responses will be received  	 * during the scan.  	 */  	if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags)) @@ -319,6 +285,8 @@ void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna)  	 */  	rt2x00dev->link.count = 0;  	memset(qual, 0, sizeof(*qual)); +	ewma_init(&rt2x00dev->link.avg_rssi, RT2X00_EWMA_FACTOR, +		  RT2X00_EWMA_WEIGHT);  	/*  	 * Restore the VGC level as stored in the registers, @@ -373,17 +341,17 @@ static void rt2x00link_tuner(struct work_struct *work)  	 * collect the RSSI data we could use this. Otherwise we  	 * must fallback to the default RSSI value.  	 */ -	if (!link->avg_rssi.avg || !qual->rx_success) +	if (!qual->rx_success)  		qual->rssi = DEFAULT_RSSI;  	else -		qual->rssi = link->avg_rssi.avg; +		qual->rssi = rt2x00link_get_avg_rssi(&link->avg_rssi);  	/*  	 * Check if link tuning is supported by the hardware, some hardware  	 * do not support link tuning at all, while other devices can disable  	 * the feature from the EEPROM.  	 */ -	if (test_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags)) +	if (rt2x00_has_cap_link_tuning(rt2x00dev))  		rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);  	/* @@ -413,11 +381,11 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev)  {  	struct link *link = &rt2x00dev->link; -	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || -	    !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) -		return; - -	schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL); +	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && +	    rt2x00dev->ops->lib->watchdog) +		ieee80211_queue_delayed_work(rt2x00dev->hw, +					     &link->watchdog_work, +					     WATCHDOG_INTERVAL);  }  void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) @@ -441,11 +409,90 @@ static void rt2x00link_watchdog(struct work_struct *work)  	rt2x00dev->ops->lib->watchdog(rt2x00dev);  	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) -		schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL); +		ieee80211_queue_delayed_work(rt2x00dev->hw, +					     &link->watchdog_work, +					     WATCHDOG_INTERVAL); +} + +void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev) +{ +	struct link *link = &rt2x00dev->link; + +	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && +	    rt2x00dev->ops->lib->gain_calibration) +		ieee80211_queue_delayed_work(rt2x00dev->hw, +					     &link->agc_work, +					     AGC_INTERVAL); +} + +void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev) +{ +	struct link *link = &rt2x00dev->link; + +	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) && +	    rt2x00dev->ops->lib->vco_calibration) +		ieee80211_queue_delayed_work(rt2x00dev->hw, +					     &link->vco_work, +					     VCO_INTERVAL); +} + +void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev) +{ +	cancel_delayed_work_sync(&rt2x00dev->link.agc_work); +} + +void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev) +{ +	cancel_delayed_work_sync(&rt2x00dev->link.vco_work); +} + +static void rt2x00link_agc(struct work_struct *work) +{ +	struct rt2x00_dev *rt2x00dev = +	    container_of(work, struct rt2x00_dev, link.agc_work.work); +	struct link *link = &rt2x00dev->link; + +	/* +	 * When the radio is shutting down we should +	 * immediately cease the watchdog monitoring. +	 */ +	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		return; + +	rt2x00dev->ops->lib->gain_calibration(rt2x00dev); + +	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) +		ieee80211_queue_delayed_work(rt2x00dev->hw, +					     &link->agc_work, +					     AGC_INTERVAL); +} + +static void rt2x00link_vcocal(struct work_struct *work) +{ +	struct rt2x00_dev *rt2x00dev = +	    container_of(work, struct rt2x00_dev, link.vco_work.work); +	struct link *link = &rt2x00dev->link; + +	/* +	 * When the radio is shutting down we should +	 * immediately cease the VCO calibration. +	 */ +	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		return; + +	rt2x00dev->ops->lib->vco_calibration(rt2x00dev); + +	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) +		ieee80211_queue_delayed_work(rt2x00dev->hw, +					     &link->vco_work, +					     VCO_INTERVAL);  }  void rt2x00link_register(struct rt2x00_dev *rt2x00dev)  { +	INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); +	if (rt2x00_has_cap_vco_recalibration(rt2x00dev)) +		INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal);  	INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);  	INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);  } diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 829bf4be9bc..004dff9b962 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -46,7 +44,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,  	skb = dev_alloc_skb(data_length + rt2x00dev->hw->extra_tx_headroom);  	if (unlikely(!skb)) { -		WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n"); +		rt2x00_warn(rt2x00dev, "Failed to create RTS/CTS frame\n");  		return -ENOMEM;  	} @@ -90,21 +88,23 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,  				  frag_skb->data, data_length, tx_info,  				  (struct ieee80211_rts *)(skb->data)); -	retval = rt2x00queue_write_tx_frame(queue, skb, true); +	retval = rt2x00queue_write_tx_frame(queue, skb, NULL, true);  	if (retval) {  		dev_kfree_skb_any(skb); -		WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); +		rt2x00_warn(rt2x00dev, "Failed to send RTS/CTS frame\n");  	}  	return retval;  } -int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) +void rt2x00mac_tx(struct ieee80211_hw *hw, +		  struct ieee80211_tx_control *control, +		  struct sk_buff *skb)  {  	struct rt2x00_dev *rt2x00dev = hw->priv;  	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);  	enum data_queue_qid qid = skb_get_queue_mapping(skb); -	struct data_queue *queue; +	struct data_queue *queue = NULL;  	/*  	 * Mac80211 might be calling this function while we are trying @@ -113,21 +113,21 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  	 * due to possible race conditions in mac80211.  	 */  	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) -		goto exit_fail; +		goto exit_free_skb;  	/* -	 * Determine which queue to put packet on. +	 * Use the ATIM queue if appropriate and present.  	 */  	if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && -	    test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) -		queue = rt2x00queue_get_queue(rt2x00dev, QID_ATIM); -	else -		queue = rt2x00queue_get_queue(rt2x00dev, qid); +	    test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) +		qid = QID_ATIM; + +	queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);  	if (unlikely(!queue)) { -		ERROR(rt2x00dev, -		      "Attempt to send packet over invalid queue %d.\n" -		      "Please file bug report to %s.\n", qid, DRV_PROJECT); -		goto exit_fail; +		rt2x00_err(rt2x00dev, +			   "Attempt to send packet over invalid queue %d\n" +			   "Please file bug report to %s\n", qid, DRV_PROJECT); +		goto exit_free_skb;  	}  	/* @@ -139,9 +139,9 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  	 * either RTS or CTS-to-self frame and handles everything  	 * inside the hardware.  	 */ -	if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS | -						IEEE80211_TX_RC_USE_CTS_PROTECT)) && -	    !rt2x00dev->ops->hw->set_rts_threshold) { +	if (!rt2x00dev->ops->hw->set_rts_threshold && +	    (tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS | +						IEEE80211_TX_RC_USE_CTS_PROTECT))) {  		if (rt2x00queue_available(queue) <= 1)  			goto exit_fail; @@ -149,18 +149,27 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)  			goto exit_fail;  	} -	if (rt2x00queue_write_tx_frame(queue, skb, false)) +	if (unlikely(rt2x00queue_write_tx_frame(queue, skb, control->sta, false)))  		goto exit_fail; +	/* +	 * Pausing queue has to be serialized with rt2x00lib_txdone(). Note +	 * we should not use spin_lock_bh variant as bottom halve was already +	 * disabled before ieee80211_xmit() call. +	 */ +	spin_lock(&queue->tx_lock);  	if (rt2x00queue_threshold(queue)) -		ieee80211_stop_queue(rt2x00dev->hw, qid); +		rt2x00queue_pause_queue(queue); +	spin_unlock(&queue->tx_lock); -	return NETDEV_TX_OK; +	return;   exit_fail: -	ieee80211_stop_queue(rt2x00dev->hw, qid); -	dev_kfree_skb_any(skb); -	return NETDEV_TX_OK; +	spin_lock(&queue->tx_lock); +	rt2x00queue_pause_queue(queue); +	spin_unlock(&queue->tx_lock); + exit_free_skb: +	ieee80211_free_txskb(hw, skb);  }  EXPORT_SYMBOL_GPL(rt2x00mac_tx); @@ -191,7 +200,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,  {  	struct rt2x00_dev *rt2x00dev = hw->priv;  	struct rt2x00_intf *intf = vif_to_intf(vif); -	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); +	struct data_queue *queue = rt2x00dev->bcn;  	struct queue_entry *entry = NULL;  	unsigned int i; @@ -203,46 +212,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,  	    !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))  		return -ENODEV; -	switch (vif->type) { -	case NL80211_IFTYPE_AP: -		/* -		 * We don't support mixed combinations of -		 * sta and ap interfaces. -		 */ -		if (rt2x00dev->intf_sta_count) -			return -ENOBUFS; - -		/* -		 * Check if we exceeded the maximum amount -		 * of supported interfaces. -		 */ -		if (rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) -			return -ENOBUFS; - -		break; -	case NL80211_IFTYPE_STATION: -	case NL80211_IFTYPE_ADHOC: -	case NL80211_IFTYPE_MESH_POINT: -	case NL80211_IFTYPE_WDS: -		/* -		 * We don't support mixed combinations of -		 * sta and ap interfaces. -		 */ -		if (rt2x00dev->intf_ap_count) -			return -ENOBUFS; - -		/* -		 * Check if we exceeded the maximum amount -		 * of supported interfaces. -		 */ -		if (rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf) -			return -ENOBUFS; - -		break; -	default: -		return -EINVAL; -	} -  	/*  	 * Loop through all beacon queues to find a free  	 * entry. Since there are as much beacon entries @@ -268,13 +237,11 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,  	else  		rt2x00dev->intf_sta_count++; -	spin_lock_init(&intf->lock); -	spin_lock_init(&intf->seqlock);  	mutex_init(&intf->beacon_skb_mutex);  	intf->beacon = entry;  	/* -	 * The MAC adddress must be configured after the device +	 * The MAC address must be configured after the device  	 * has been initialized. Otherwise the device can reset  	 * the MAC registers.  	 * The BSSID address must only be configured in AP mode, @@ -282,9 +249,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,  	 * STA interfaces at this time, since this can cause  	 * invalid behavior in the device.  	 */ -	memcpy(&intf->mac, vif->addr, ETH_ALEN);  	rt2x00lib_config_intf(rt2x00dev, intf, vif->type, -			      intf->mac, NULL); +			      vif->addr, NULL);  	/*  	 * Some filters depend on the current working mode. We can force @@ -352,7 +318,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)  	 * if for any reason the link tuner must be reset, this will be  	 * handled by rt2x00lib_config().  	 */ -	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_OFF); +	rt2x00queue_stop_queue(rt2x00dev->rx);  	/*  	 * When we've just turned on the radio, we want to reprogram @@ -370,7 +336,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)  	rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant);  	/* Turn RX back on */ -	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_ON); +	rt2x00queue_start_queue(rt2x00dev->rx);  	return 0;  } @@ -414,11 +380,11 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,  	 * of different types, but has no a separate filter for PS Poll frames,  	 * FIF_CONTROL flag implies FIF_PSPOLL.  	 */ -	if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags)) { +	if (!rt2x00_has_cap_control_filters(rt2x00dev)) {  		if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL)  			*total_flags |= FIF_CONTROL | FIF_PSPOLL;  	} -	if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags)) { +	if (!rt2x00_has_cap_control_filter_pspoll(rt2x00dev)) {  		if (*total_flags & FIF_CONTROL)  			*total_flags |= FIF_PSPOLL;  	} @@ -445,9 +411,7 @@ static void rt2x00mac_set_tim_iter(void *data, u8 *mac,  	    vif->type != NL80211_IFTYPE_WDS)  		return; -	spin_lock(&intf->lock); -	intf->delayed_flags |= DELAYED_UPDATE_BEACON; -	spin_unlock(&intf->lock); +	set_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags);  }  int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, @@ -458,9 +422,9 @@ int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,  	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))  		return 0; -	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, -						   rt2x00mac_set_tim_iter, -						   rt2x00dev); +	ieee80211_iterate_active_interfaces_atomic( +		rt2x00dev->hw, IEEE80211_IFACE_ITER_RESUME_ALL, +		rt2x00mac_set_tim_iter, rt2x00dev);  	/* queue work to upodate the beacon template */  	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work); @@ -472,17 +436,17 @@ EXPORT_SYMBOL_GPL(rt2x00mac_set_tim);  static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len)  {  	if (key_len > NL80211_TKIP_DATA_OFFSET_ENCR_KEY) -		memcpy(&crypto->key, +		memcpy(crypto->key,  		       &key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY],  		       sizeof(crypto->key));  	if (key_len > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) -		memcpy(&crypto->tx_mic, +		memcpy(crypto->tx_mic,  		       &key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],  		       sizeof(crypto->tx_mic));  	if (key_len > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY) -		memcpy(&crypto->rx_mic, +		memcpy(crypto->rx_mic,  		       &key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],  		       sizeof(crypto->rx_mic));  } @@ -492,49 +456,53 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,  		      struct ieee80211_key_conf *key)  {  	struct rt2x00_dev *rt2x00dev = hw->priv; -	struct rt2x00_intf *intf = vif_to_intf(vif);  	int (*set_key) (struct rt2x00_dev *rt2x00dev,  			struct rt2x00lib_crypto *crypto,  			struct ieee80211_key_conf *key);  	struct rt2x00lib_crypto crypto;  	static const u8 bcast_addr[ETH_ALEN] =  		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; +	struct rt2x00_sta *sta_priv = NULL;  	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))  		return 0; -	else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) -		return -EOPNOTSUPP; -	else if (key->keylen > 32) -		return -ENOSPC; -	memset(&crypto, 0, sizeof(crypto)); +	if (!rt2x00_has_cap_hw_crypto(rt2x00dev)) +		return -EOPNOTSUPP;  	/* -	 * When in STA mode, bssidx is always 0 otherwise local_address[5] -	 * contains the bss number, see BSS_ID_MASK comments for details. +	 * To support IBSS RSN, don't program group keys in IBSS, the +	 * hardware will then not attempt to decrypt the frames.  	 */ -	if (rt2x00dev->intf_sta_count) -		crypto.bssidx = 0; -	else -		crypto.bssidx = intf->mac[5] & (rt2x00dev->ops->max_ap_intf - 1); +	if (vif->type == NL80211_IFTYPE_ADHOC && +	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) +		return -EOPNOTSUPP; + +	if (key->keylen > 32) +		return -ENOSPC; +	memset(&crypto, 0, sizeof(crypto)); + +	crypto.bssidx = rt2x00lib_get_bssidx(rt2x00dev, vif);  	crypto.cipher = rt2x00crypto_key_to_cipher(key);  	if (crypto.cipher == CIPHER_NONE)  		return -EOPNOTSUPP; +	if (crypto.cipher == CIPHER_TKIP && rt2x00_is_usb(rt2x00dev)) +		return -EOPNOTSUPP;  	crypto.cmd = cmd;  	if (sta) { -		/* some drivers need the AID */ -		crypto.aid = sta->aid;  		crypto.address = sta->addr; +		sta_priv = sta_to_rt2x00_sta(sta); +		crypto.wcid = sta_priv->wcid;  	} else  		crypto.address = bcast_addr;  	if (crypto.cipher == CIPHER_TKIP)  		memcpy_tkip(&crypto, &key->key[0], key->keylen);  	else -		memcpy(&crypto.key, &key->key[0], key->keylen); +		memcpy(crypto.key, &key->key[0], key->keylen);  	/*  	 * Each BSS has a maximum of 4 shared keys.  	 * Shared key index values: @@ -567,10 +535,43 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,  EXPORT_SYMBOL_GPL(rt2x00mac_set_key);  #endif /* CONFIG_RT2X00_LIB_CRYPTO */ +int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +		      struct ieee80211_sta *sta) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); + +	/* +	 * If there's no space left in the device table store +	 * -1 as wcid but tell mac80211 everything went ok. +	 */ +	if (rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta)) +		sta_priv->wcid = -1; + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2x00mac_sta_add); + +int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +			 struct ieee80211_sta *sta) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); + +	/* +	 * If we never sent the STA to the device no need to clean it up. +	 */ +	if (sta_priv->wcid < 0) +		return 0; + +	return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid); +} +EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove); +  void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)  {  	struct rt2x00_dev *rt2x00dev = hw->priv; -	__set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); +	set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);  	rt2x00link_stop_tuner(rt2x00dev);  }  EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); @@ -578,7 +579,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);  void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw)  {  	struct rt2x00_dev *rt2x00dev = hw->priv; -	__clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); +	clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);  	rt2x00link_start_tuner(rt2x00dev);  }  EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_complete); @@ -614,33 +615,57 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,  	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))  		return; -	spin_lock(&intf->lock); - -	/* -	 * conf->bssid can be NULL if coming from the internal -	 * beacon update routine. -	 */ -	if (changes & BSS_CHANGED_BSSID) -		memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN); - -	spin_unlock(&intf->lock); -  	/* -	 * Call rt2x00_config_intf() outside of the spinlock context since -	 * the call will sleep for USB drivers. By using the ieee80211_if_conf -	 * values as arguments we make keep access to rt2x00_intf thread safe -	 * even without the lock. +	 * Update the BSSID.  	 */  	if (changes & BSS_CHANGED_BSSID)  		rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,  				      bss_conf->bssid);  	/* -	 * Update the beacon. -	 */ -	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) -		rt2x00queue_update_beacon(rt2x00dev, vif, -					  bss_conf->enable_beacon); +	 * Start/stop beaconing. +	 */ +	if (changes & BSS_CHANGED_BEACON_ENABLED) { +		if (!bss_conf->enable_beacon && intf->enable_beacon) { +			rt2x00dev->intf_beaconing--; +			intf->enable_beacon = false; +			/* +			 * Clear beacon in the H/W for this vif. This is needed +			 * to disable beaconing on this particular interface +			 * and keep it running on other interfaces. +			 */ +			rt2x00queue_clear_beacon(rt2x00dev, vif); + +			if (rt2x00dev->intf_beaconing == 0) { +				/* +				 * Last beaconing interface disabled +				 * -> stop beacon queue. +				 */ +				mutex_lock(&intf->beacon_skb_mutex); +				rt2x00queue_stop_queue(rt2x00dev->bcn); +				mutex_unlock(&intf->beacon_skb_mutex); +			} +		} else if (bss_conf->enable_beacon && !intf->enable_beacon) { +			rt2x00dev->intf_beaconing++; +			intf->enable_beacon = true; +			/* +			 * Upload beacon to the H/W. This is only required on +			 * USB devices. PCI devices fetch beacons periodically. +			 */ +			if (rt2x00_is_usb(rt2x00dev)) +				rt2x00queue_update_beacon(rt2x00dev, vif); + +			if (rt2x00dev->intf_beaconing == 1) { +				/* +				 * First beaconing interface enabled +				 * -> start beacon queue. +				 */ +				mutex_lock(&intf->beacon_skb_mutex); +				rt2x00queue_start_queue(rt2x00dev->bcn); +				mutex_unlock(&intf->beacon_skb_mutex); +			} +		} +	}  	/*  	 * When the association status has changed we must reset the link @@ -657,9 +682,19 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,  			rt2x00dev->intf_associated--;  		rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); + +		clear_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags);  	}  	/* +	 * Check for access point which do not support 802.11e . We have to +	 * generate data frames sequence number in S/W for such AP, because +	 * of H/W bug. +	 */ +	if (changes & BSS_CHANGED_QOS && !bss_conf->qos) +		set_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags); + +	/*  	 * When the erp information has changed, we should perform  	 * additional configuration steps. For all other changes we are done.  	 */ @@ -670,13 +705,14 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,  }  EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); -int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, +int rt2x00mac_conf_tx(struct ieee80211_hw *hw, +		      struct ieee80211_vif *vif, u16 queue_idx,  		      const struct ieee80211_tx_queue_params *params)  {  	struct rt2x00_dev *rt2x00dev = hw->priv;  	struct data_queue *queue; -	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); +	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);  	if (unlikely(!queue))  		return -EINVAL; @@ -697,9 +733,10 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  	queue->aifs = params->aifs;  	queue->txop = params->txop; -	INFO(rt2x00dev, -	     "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d.\n", -	     queue_idx, queue->cw_min, queue->cw_max, queue->aifs, queue->txop); +	rt2x00_dbg(rt2x00dev, +		   "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d\n", +		   queue_idx, queue->cw_min, queue->cw_max, queue->aifs, +		   queue->txop);  	return 0;  } @@ -714,40 +751,111 @@ void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw)  }  EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll); -void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop) +void rt2x00mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, +		     u32 queues, bool drop)  {  	struct rt2x00_dev *rt2x00dev = hw->priv;  	struct data_queue *queue; -	unsigned int i = 0; -	ieee80211_stop_queues(hw); +	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) +		return; -	/* -	 * Run over all queues to kick them, this will force -	 * any pending frames to be transmitted. -	 */ -	tx_queue_for_each(rt2x00dev, queue) { -		rt2x00dev->ops->lib->kick_tx_queue(queue); +	tx_queue_for_each(rt2x00dev, queue) +		rt2x00queue_flush_queue(queue, drop); +} +EXPORT_SYMBOL_GPL(rt2x00mac_flush); + +int rt2x00mac_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct link_ant *ant = &rt2x00dev->link.ant; +	struct antenna_setup *def = &rt2x00dev->default_ant; +	struct antenna_setup setup; + +	// The antenna value is not supposed to be 0, +	// or exceed the maximum number of antenna's. +	if (!tx_ant || (tx_ant & ~3) || !rx_ant || (rx_ant & ~3)) +		return -EINVAL; + +	// When the client tried to configure the antenna to or from +	// diversity mode, we must reset the default antenna as well +	// as that controls the diversity switch. +	if (ant->flags & ANTENNA_TX_DIVERSITY && tx_ant != 3) +		ant->flags &= ~ANTENNA_TX_DIVERSITY; +	if (ant->flags & ANTENNA_RX_DIVERSITY && rx_ant != 3) +		ant->flags &= ~ANTENNA_RX_DIVERSITY; + +	// If diversity is being enabled, check if we need hardware +	// or software diversity. In the latter case, reset the value, +	// and make sure we update the antenna flags to have the +	// link tuner pick up the diversity tuning. +	if (tx_ant == 3 && def->tx == ANTENNA_SW_DIVERSITY) { +		tx_ant = ANTENNA_SW_DIVERSITY; +		ant->flags |= ANTENNA_TX_DIVERSITY;  	} -	/** -	 * All queues have been kicked, now wait for each queue -	 * to become empty. With a bit of luck, we only have to wait -	 * for the first queue to become empty, because while waiting -	 * for the that queue, the other queues will have transmitted -	 * all their frames as well (since they were already kicked). -	 */ +	if (rx_ant == 3 && def->rx == ANTENNA_SW_DIVERSITY) { +		rx_ant = ANTENNA_SW_DIVERSITY; +		ant->flags |= ANTENNA_RX_DIVERSITY; +	} + +	setup.tx = tx_ant; +	setup.rx = rx_ant; + +	rt2x00lib_config_antenna(rt2x00dev, setup); + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2x00mac_set_antenna); + +int rt2x00mac_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct link_ant *ant = &rt2x00dev->link.ant; +	struct antenna_setup *active = &rt2x00dev->link.ant.active; + +	// When software diversity is active, we must report this to the +	// client and not the current active antenna state. +	if (ant->flags & ANTENNA_TX_DIVERSITY) +		*tx_ant = ANTENNA_HW_DIVERSITY; +	else +		*tx_ant = active->tx; + +	if (ant->flags & ANTENNA_RX_DIVERSITY) +		*rx_ant = ANTENNA_HW_DIVERSITY; +	else +		*rx_ant = active->rx; + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2x00mac_get_antenna); + +void rt2x00mac_get_ringparam(struct ieee80211_hw *hw, +			     u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct data_queue *queue; +  	tx_queue_for_each(rt2x00dev, queue) { -		for (i = 0; i < 10; i++) { -			if (rt2x00queue_empty(queue)) -				break; -			msleep(100); -		} +		*tx += queue->length; +		*tx_max += queue->limit; +	} + +	*rx = rt2x00dev->rx->length; +	*rx_max = rt2x00dev->rx->limit; +} +EXPORT_SYMBOL_GPL(rt2x00mac_get_ringparam); +bool rt2x00mac_tx_frames_pending(struct ieee80211_hw *hw) +{ +	struct rt2x00_dev *rt2x00dev = hw->priv; +	struct data_queue *queue; + +	tx_queue_for_each(rt2x00dev, queue) {  		if (!rt2x00queue_empty(queue)) -			WARNING(rt2x00dev, "Failed to flush queue %d", queue->qid); +			return true;  	} -	ieee80211_wake_queues(hw); +	return false;  } -EXPORT_SYMBOL_GPL(rt2x00mac_flush); +EXPORT_SYMBOL_GPL(rt2x00mac_tx_frames_pending); diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.c b/drivers/net/wireless/rt2x00/rt2x00mmio.c new file mode 100644 index 00000000000..6f236ea180a --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00mmio.c @@ -0,0 +1,214 @@ +/* +	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> +	<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, see <http://www.gnu.org/licenses/>. + */ + +/* +	Module: rt2x00mmio +	Abstract: rt2x00 generic mmio device routines. + */ + +#include <linux/dma-mapping.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/slab.h> + +#include "rt2x00.h" +#include "rt2x00mmio.h" + +/* + * Register access. + */ +int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev, +			    const unsigned int offset, +			    const struct rt2x00_field32 field, +			    u32 *reg) +{ +	unsigned int i; + +	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) +		return 0; + +	for (i = 0; i < REGISTER_BUSY_COUNT; i++) { +		rt2x00mmio_register_read(rt2x00dev, offset, reg); +		if (!rt2x00_get_field32(*reg, field)) +			return 1; +		udelay(REGISTER_BUSY_DELAY); +	} + +	printk_once(KERN_ERR "%s() Indirect register access failed: " +	      "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg); +	*reg = ~0; + +	return 0; +} +EXPORT_SYMBOL_GPL(rt2x00mmio_regbusy_read); + +bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue = rt2x00dev->rx; +	struct queue_entry *entry; +	struct queue_entry_priv_mmio *entry_priv; +	struct skb_frame_desc *skbdesc; +	int max_rx = 16; + +	while (--max_rx) { +		entry = rt2x00queue_get_entry(queue, Q_INDEX); +		entry_priv = entry->priv_data; + +		if (rt2x00dev->ops->lib->get_entry_state(entry)) +			break; + +		/* +		 * Fill in desc fields of the skb descriptor +		 */ +		skbdesc = get_skb_frame_desc(entry->skb); +		skbdesc->desc = entry_priv->desc; +		skbdesc->desc_len = entry->queue->desc_size; + +		/* +		 * DMA is already done, notify rt2x00lib that +		 * it finished successfully. +		 */ +		rt2x00lib_dmastart(entry); +		rt2x00lib_dmadone(entry); + +		/* +		 * Send the frame to rt2x00lib for further processing. +		 */ +		rt2x00lib_rxdone(entry, GFP_ATOMIC); +	} + +	return !max_rx; +} +EXPORT_SYMBOL_GPL(rt2x00mmio_rxdone); + +void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop) +{ +	unsigned int i; + +	for (i = 0; !rt2x00queue_empty(queue) && i < 10; i++) +		msleep(10); +} +EXPORT_SYMBOL_GPL(rt2x00mmio_flush_queue); + +/* + * Device initialization handlers. + */ +static int rt2x00mmio_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, +				      struct data_queue *queue) +{ +	struct queue_entry_priv_mmio *entry_priv; +	void *addr; +	dma_addr_t dma; +	unsigned int i; + +	/* +	 * Allocate DMA memory for descriptor and buffer. +	 */ +	addr = dma_alloc_coherent(rt2x00dev->dev, +				  queue->limit * queue->desc_size, +				  &dma, GFP_KERNEL); +	if (!addr) +		return -ENOMEM; + +	memset(addr, 0, queue->limit * queue->desc_size); + +	/* +	 * Initialize all queue entries to contain valid addresses. +	 */ +	for (i = 0; i < queue->limit; i++) { +		entry_priv = queue->entries[i].priv_data; +		entry_priv->desc = addr + i * queue->desc_size; +		entry_priv->desc_dma = dma + i * queue->desc_size; +	} + +	return 0; +} + +static void rt2x00mmio_free_queue_dma(struct rt2x00_dev *rt2x00dev, +				      struct data_queue *queue) +{ +	struct queue_entry_priv_mmio *entry_priv = +	    queue->entries[0].priv_data; + +	if (entry_priv->desc) +		dma_free_coherent(rt2x00dev->dev, +				  queue->limit * queue->desc_size, +				  entry_priv->desc, entry_priv->desc_dma); +	entry_priv->desc = NULL; +} + +int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue; +	int status; + +	/* +	 * Allocate DMA +	 */ +	queue_for_each(rt2x00dev, queue) { +		status = rt2x00mmio_alloc_queue_dma(rt2x00dev, queue); +		if (status) +			goto exit; +	} + +	/* +	 * Register interrupt handler. +	 */ +	status = request_irq(rt2x00dev->irq, +			     rt2x00dev->ops->lib->irq_handler, +			     IRQF_SHARED, rt2x00dev->name, rt2x00dev); +	if (status) { +		rt2x00_err(rt2x00dev, "IRQ %d allocation failed (error %d)\n", +			   rt2x00dev->irq, status); +		goto exit; +	} + +	return 0; + +exit: +	queue_for_each(rt2x00dev, queue) +		rt2x00mmio_free_queue_dma(rt2x00dev, queue); + +	return status; +} +EXPORT_SYMBOL_GPL(rt2x00mmio_initialize); + +void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue; + +	/* +	 * Free irq line. +	 */ +	free_irq(rt2x00dev->irq, rt2x00dev); + +	/* +	 * Free DMA +	 */ +	queue_for_each(rt2x00dev, queue) +		rt2x00mmio_free_queue_dma(rt2x00dev, queue); +} +EXPORT_SYMBOL_GPL(rt2x00mmio_uninitialize); + +/* + * rt2x00mmio module information. + */ +MODULE_AUTHOR(DRV_PROJECT); +MODULE_VERSION(DRV_VERSION); +MODULE_DESCRIPTION("rt2x00 mmio library"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/rt2x00/rt2x00mmio.h b/drivers/net/wireless/rt2x00/rt2x00mmio.h new file mode 100644 index 00000000000..701c3127efb --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00mmio.h @@ -0,0 +1,117 @@ +/* +	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> +	<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, see <http://www.gnu.org/licenses/>. + */ + +/* +	Module: rt2x00mmio +	Abstract: Data structures for the rt2x00mmio module. + */ + +#ifndef RT2X00MMIO_H +#define RT2X00MMIO_H + +#include <linux/io.h> + +/* + * Register access. + */ +static inline void rt2x00mmio_register_read(struct rt2x00_dev *rt2x00dev, +					    const unsigned int offset, +					    u32 *value) +{ +	*value = readl(rt2x00dev->csr.base + offset); +} + +static inline void rt2x00mmio_register_multiread(struct rt2x00_dev *rt2x00dev, +						 const unsigned int offset, +						 void *value, const u32 length) +{ +	memcpy_fromio(value, rt2x00dev->csr.base + offset, length); +} + +static inline void rt2x00mmio_register_write(struct rt2x00_dev *rt2x00dev, +					     const unsigned int offset, +					     u32 value) +{ +	writel(value, rt2x00dev->csr.base + offset); +} + +static inline void rt2x00mmio_register_multiwrite(struct rt2x00_dev *rt2x00dev, +						  const unsigned int offset, +						  const void *value, +						  const u32 length) +{ +	__iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2); +} + +/** + * rt2x00mmio_regbusy_read - Read from register with busy check + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @field: Field to check if register is busy + * @reg: Pointer to where register contents should be stored + * + * This function will read the given register, and checks if the + * register is busy. If it is, it will sleep for a couple of + * microseconds before reading the register again. If the register + * is not read after a certain timeout, this function will return + * FALSE. + */ +int rt2x00mmio_regbusy_read(struct rt2x00_dev *rt2x00dev, +			    const unsigned int offset, +			    const struct rt2x00_field32 field, +			    u32 *reg); + +/** + * struct queue_entry_priv_mmio: Per entry PCI specific information + * + * @desc: Pointer to device descriptor + * @desc_dma: DMA pointer to &desc. + * @data: Pointer to device's entry memory. + * @data_dma: DMA pointer to &data. + */ +struct queue_entry_priv_mmio { +	__le32 *desc; +	dma_addr_t desc_dma; +}; + +/** + * rt2x00mmio_rxdone - Handle RX done events + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * + * Returns true if there are still rx frames pending and false if all + * pending rx frames were processed. + */ +bool rt2x00mmio_rxdone(struct rt2x00_dev *rt2x00dev); + +/** + * rt2x00mmio_flush_queue - Flush data queue + * @queue: Data queue to stop + * @drop: True to drop all pending frames. + * + * This will wait for a maximum of 100ms, waiting for the queues + * to become empty. + */ +void rt2x00mmio_flush_queue(struct data_queue *queue, bool drop); + +/* + * Device initialization handlers. + */ +int rt2x00mmio_initialize(struct rt2x00_dev *rt2x00dev); +void rt2x00mmio_uninitialize(struct rt2x00_dev *rt2x00dev); + +#endif /* RT2X00MMIO_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 868ca19b13e..d93db4b0371 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -33,164 +31,6 @@  #include "rt2x00pci.h"  /* - * Register access. - */ -int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, -			   const unsigned int offset, -			   const struct rt2x00_field32 field, -			   u32 *reg) -{ -	unsigned int i; - -	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) -		return 0; - -	for (i = 0; i < REGISTER_BUSY_COUNT; i++) { -		rt2x00pci_register_read(rt2x00dev, offset, reg); -		if (!rt2x00_get_field32(*reg, field)) -			return 1; -		udelay(REGISTER_BUSY_DELAY); -	} - -	ERROR(rt2x00dev, "Indirect register access failed: " -	      "offset=0x%.08x, value=0x%.08x\n", offset, *reg); -	*reg = ~0; - -	return 0; -} -EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); - -void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) -{ -	struct data_queue *queue = rt2x00dev->rx; -	struct queue_entry *entry; -	struct queue_entry_priv_pci *entry_priv; -	struct skb_frame_desc *skbdesc; - -	while (1) { -		entry = rt2x00queue_get_entry(queue, Q_INDEX); -		entry_priv = entry->priv_data; - -		if (rt2x00dev->ops->lib->get_entry_state(entry)) -			break; - -		/* -		 * Fill in desc fields of the skb descriptor -		 */ -		skbdesc = get_skb_frame_desc(entry->skb); -		skbdesc->desc = entry_priv->desc; -		skbdesc->desc_len = entry->queue->desc_size; - -		/* -		 * Send the frame to rt2x00lib for further processing. -		 */ -		rt2x00lib_rxdone(entry); -	} -} -EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); - -/* - * Device initialization handlers. - */ -static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, -				     struct data_queue *queue) -{ -	struct queue_entry_priv_pci *entry_priv; -	void *addr; -	dma_addr_t dma; -	unsigned int i; - -	/* -	 * Allocate DMA memory for descriptor and buffer. -	 */ -	addr = dma_alloc_coherent(rt2x00dev->dev, -				  queue->limit * queue->desc_size, -				  &dma, GFP_KERNEL); -	if (!addr) -		return -ENOMEM; - -	memset(addr, 0, queue->limit * queue->desc_size); - -	/* -	 * Initialize all queue entries to contain valid addresses. -	 */ -	for (i = 0; i < queue->limit; i++) { -		entry_priv = queue->entries[i].priv_data; -		entry_priv->desc = addr + i * queue->desc_size; -		entry_priv->desc_dma = dma + i * queue->desc_size; -	} - -	return 0; -} - -static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, -				     struct data_queue *queue) -{ -	struct queue_entry_priv_pci *entry_priv = -	    queue->entries[0].priv_data; - -	if (entry_priv->desc) -		dma_free_coherent(rt2x00dev->dev, -				  queue->limit * queue->desc_size, -				  entry_priv->desc, entry_priv->desc_dma); -	entry_priv->desc = NULL; -} - -int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) -{ -	struct data_queue *queue; -	int status; - -	/* -	 * Allocate DMA -	 */ -	queue_for_each(rt2x00dev, queue) { -		status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue); -		if (status) -			goto exit; -	} - -	/* -	 * Register interrupt handler. -	 */ -	status = request_threaded_irq(rt2x00dev->irq, -				      rt2x00dev->ops->lib->irq_handler, -				      rt2x00dev->ops->lib->irq_handler_thread, -				      IRQF_SHARED, rt2x00dev->name, rt2x00dev); -	if (status) { -		ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", -		      rt2x00dev->irq, status); -		goto exit; -	} - -	return 0; - -exit: -	queue_for_each(rt2x00dev, queue) -		rt2x00pci_free_queue_dma(rt2x00dev, queue); - -	return status; -} -EXPORT_SYMBOL_GPL(rt2x00pci_initialize); - -void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) -{ -	struct data_queue *queue; - -	/* -	 * Free irq line. -	 */ -	free_irq(rt2x00dev->irq, rt2x00dev); - -	/* -	 * Free DMA -	 */ -	queue_for_each(rt2x00dev, queue) -		rt2x00pci_free_queue_dma(rt2x00dev, queue); -} -EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); - -/*   * PCI driver handlers.   */  static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev) @@ -226,46 +66,46 @@ static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev)  	return 0;  exit: -	ERROR_PROBE("Failed to allocate registers.\n"); +	rt2x00_probe_err("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) +int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops)  { -	struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data;  	struct ieee80211_hw *hw;  	struct rt2x00_dev *rt2x00dev;  	int retval; +	u16 chip;  	retval = pci_enable_device(pci_dev);  	if (retval) { -		ERROR_PROBE("Enable device failed.\n"); +		rt2x00_probe_err("Enable device failed\n");  		return retval;  	}  	retval = pci_request_regions(pci_dev, pci_name(pci_dev));  	if (retval) { -		ERROR_PROBE("PCI request regions failed.\n"); +		rt2x00_probe_err("PCI request regions failed\n");  		goto exit_disable_device;  	}  	pci_set_master(pci_dev);  	if (pci_set_mwi(pci_dev)) -		ERROR_PROBE("MWI not available.\n"); +		rt2x00_probe_err("MWI not available\n");  	if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) { -		ERROR_PROBE("PCI DMA not supported.\n"); +		rt2x00_probe_err("PCI DMA not supported\n");  		retval = -EIO;  		goto exit_release_regions;  	}  	hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);  	if (!hw) { -		ERROR_PROBE("Failed to allocate hardware.\n"); +		rt2x00_probe_err("Failed to allocate hardware\n");  		retval = -ENOMEM;  		goto exit_release_regions;  	} @@ -277,9 +117,9 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)  	rt2x00dev->ops = ops;  	rt2x00dev->hw = hw;  	rt2x00dev->irq = pci_dev->irq; -	rt2x00dev->name = pci_name(pci_dev); +	rt2x00dev->name = ops->name; -	if (pci_dev->is_pcie) +	if (pci_is_pcie(pci_dev))  		rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCIE);  	else  		rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); @@ -288,6 +128,14 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)  	if (retval)  		goto exit_free_device; +	/* +	 * Because rt3290 chip use different efuse offset to read efuse data. +	 * So before read efuse it need to indicate it is the +	 * rt3290 or not. +	 */ +	pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip); +	rt2x00dev->chip.rt = chip; +  	retval = rt2x00lib_probe_dev(rt2x00dev);  	if (retval)  		goto exit_free_reg; @@ -306,8 +154,6 @@ exit_release_regions:  exit_disable_device:  	pci_disable_device(pci_dev); -	pci_set_drvdata(pci_dev, NULL); -  	return retval;  }  EXPORT_SYMBOL_GPL(rt2x00pci_probe); @@ -327,7 +173,6 @@ void rt2x00pci_remove(struct pci_dev *pci_dev)  	/*  	 * Free the PCI device data.  	 */ -	pci_set_drvdata(pci_dev, NULL);  	pci_disable_device(pci_dev);  	pci_release_regions(pci_dev);  } @@ -356,12 +201,12 @@ int rt2x00pci_resume(struct pci_dev *pci_dev)  	struct rt2x00_dev *rt2x00dev = hw->priv;  	if (pci_set_power_state(pci_dev, PCI_D0) || -	    pci_enable_device(pci_dev) || -	    pci_restore_state(pci_dev)) { -		ERROR(rt2x00dev, "Failed to resume device.\n"); +	    pci_enable_device(pci_dev)) { +		rt2x00_err(rt2x00dev, "Failed to resume device\n");  		return -EIO;  	} +	pci_restore_state(pci_dev);  	return rt2x00lib_resume(rt2x00dev);  }  EXPORT_SYMBOL_GPL(rt2x00pci_resume); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index b854d62ff99..bc0ca5f58f3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -36,84 +34,9 @@  #define PCI_DEVICE_DATA(__ops)	.driver_data = (kernel_ulong_t)(__ops)  /* - * Register access. - */ -static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev, -					   const unsigned int offset, -					   u32 *value) -{ -	*value = readl(rt2x00dev->csr.base + offset); -} - -static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev, -						const unsigned int offset, -						void *value, const u32 length) -{ -	memcpy_fromio(value, rt2x00dev->csr.base + offset, length); -} - -static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev, -					    const unsigned int offset, -					    u32 value) -{ -	writel(value, rt2x00dev->csr.base + offset); -} - -static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, -						 const unsigned int offset, -						 const void *value, -						 const u32 length) -{ -	memcpy_toio(rt2x00dev->csr.base + offset, value, length); -} - -/** - * rt2x00pci_regbusy_read - Read from register with busy check - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - * @offset: Register offset - * @field: Field to check if register is busy - * @reg: Pointer to where register contents should be stored - * - * This function will read the given register, and checks if the - * register is busy. If it is, it will sleep for a couple of - * microseconds before reading the register again. If the register - * is not read after a certain timeout, this function will return - * FALSE. - */ -int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, -			   const unsigned int offset, -			   const struct rt2x00_field32 field, -			   u32 *reg); - -/** - * struct queue_entry_priv_pci: Per entry PCI specific information - * - * @desc: Pointer to device descriptor - * @desc_dma: DMA pointer to &desc. - * @data: Pointer to device's entry memory. - * @data_dma: DMA pointer to &data. - */ -struct queue_entry_priv_pci { -	__le32 *desc; -	dma_addr_t desc_dma; -}; - -/** - * rt2x00pci_rxdone - Handle RX done events - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - */ -void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); - -/* - * Device initialization handlers. - */ -int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev); -void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev); - -/*   * PCI driver handlers.   */ -int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id); +int rt2x00pci_probe(struct pci_dev *pci_dev, const struct rt2x00_ops *ops);  void rt2x00pci_remove(struct pci_dev *pci_dev);  #ifdef CONFIG_PM  int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index a3d79c7a21c..5642ccceca7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -15,9 +15,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -33,9 +31,10 @@  #include "rt2x00.h"  #include "rt2x00lib.h" -struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry) +struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry, gfp_t gfp)  { -	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +	struct data_queue *queue = entry->queue; +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;  	struct sk_buff *skb;  	struct skb_frame_desc *skbdesc;  	unsigned int frame_size; @@ -46,7 +45,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)  	 * The frame size includes descriptor size, because the  	 * hardware directly receive the frame into the skbuffer.  	 */ -	frame_size = entry->queue->data_size + entry->queue->desc_size; +	frame_size = queue->data_size + queue->desc_size + queue->winfo_size;  	/*  	 * The payload should be aligned to a 4-byte boundary, @@ -60,7 +59,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)  	 * at least 8 bytes bytes available in headroom for IV/EIV  	 * and 8 bytes for ICV data as tailroon.  	 */ -	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { +	if (rt2x00_has_cap_hw_crypto(rt2x00dev)) {  		head_size += 8;  		tail_size += 8;  	} @@ -68,7 +67,7 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)  	/*  	 * Allocate skbuffer.  	 */ -	skb = dev_alloc_skb(frame_size + head_size + tail_size); +	skb = __dev_alloc_skb(frame_size + head_size + tail_size, gfp);  	if (!skb)  		return NULL; @@ -86,25 +85,36 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry)  	memset(skbdesc, 0, sizeof(*skbdesc));  	skbdesc->entry = entry; -	if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) { -		skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, -						  skb->data, -						  skb->len, -						  DMA_FROM_DEVICE); +	if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags)) { +		dma_addr_t skb_dma; + +		skb_dma = dma_map_single(rt2x00dev->dev, skb->data, skb->len, +					 DMA_FROM_DEVICE); +		if (unlikely(dma_mapping_error(rt2x00dev->dev, skb_dma))) { +			dev_kfree_skb_any(skb); +			return NULL; +		} + +		skbdesc->skb_dma = skb_dma;  		skbdesc->flags |= SKBDESC_DMA_MAPPED_RX;  	}  	return skb;  } -void rt2x00queue_map_txskb(struct queue_entry *entry) +int rt2x00queue_map_txskb(struct queue_entry *entry)  {  	struct device *dev = entry->queue->rt2x00dev->dev;  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);  	skbdesc->skb_dma =  	    dma_map_single(dev, entry->skb->data, entry->skb->len, DMA_TO_DEVICE); + +	if (unlikely(dma_mapping_error(dev, skbdesc->skb_dma))) +		return -ENOMEM; +  	skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; +	return 0;  }  EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); @@ -148,19 +158,6 @@ void rt2x00queue_align_frame(struct sk_buff *skb)  	skb_trim(skb, frame_length);  } -void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length) -{ -	unsigned int frame_length = skb->len; -	unsigned int align = ALIGN_SIZE(skb, header_length); - -	if (!align) -		return; - -	skb_push(skb, align); -	memmove(skb->data, skb->data + align, frame_length); -	skb_trim(skb, frame_length); -} -  void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)  {  	unsigned int payload_length = skb->len - header_length; @@ -199,33 +196,51 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)  void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)  { -	unsigned int l2pad = L2PAD_SIZE(header_length); +	/* +	 * L2 padding is only present if the skb contains more than just the +	 * IEEE 802.11 header. +	 */ +	unsigned int l2pad = (skb->len > header_length) ? +				L2PAD_SIZE(header_length) : 0;  	if (!l2pad)  		return; -	memmove(skb->data + header_length, skb->data + header_length + l2pad, -				skb->len - header_length - l2pad); - -	skb_trim(skb, skb->len - l2pad); +	memmove(skb->data + l2pad, skb->data, header_length); +	skb_pull(skb, l2pad);  } -static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, +static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, +						 struct sk_buff *skb,  						 struct txentry_desc *txdesc)  { -	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); -	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;  	struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); -	unsigned long irqflags; +	u16 seqno; -	if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) || -	    unlikely(!tx_info->control.vif)) +	if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))  		return; +	__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); + +	if (!test_bit(REQUIRE_SW_SEQNO, &rt2x00dev->cap_flags)) { +		/* +		 * rt2800 has a H/W (or F/W) bug, device incorrectly increase +		 * seqno on retransmited data (non-QOS) frames. To workaround +		 * the problem let's generate seqno in software if QOS is +		 * disabled. +		 */ +		if (test_bit(CONFIG_QOS_DISABLED, &rt2x00dev->flags)) +			__clear_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); +		else +			/* H/W will generate sequence number */ +			return; +	} +  	/* -	 * Hardware should insert sequence counter. -	 * FIXME: We insert a software sequence counter first for -	 * hardware that doesn't support hardware sequence counting. +	 * The hardware is not able to insert a sequence number. Assign a +	 * software generated one here.  	 *  	 * This is wrong because beacons are not getting sequence  	 * numbers assigned properly. @@ -234,43 +249,50 @@ static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,  	 * sequence counting per-frame, since those will override the  	 * sequence counter given by mac80211.  	 */ -	spin_lock_irqsave(&intf->seqlock, irqflags); -  	if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) -		intf->seqno += 0x10; -	hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); -	hdr->seq_ctrl |= cpu_to_le16(intf->seqno); +		seqno = atomic_add_return(0x10, &intf->seqno); +	else +		seqno = atomic_read(&intf->seqno); -	spin_unlock_irqrestore(&intf->seqlock, irqflags); - -	__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); +	hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); +	hdr->seq_ctrl |= cpu_to_le16(seqno);  } -static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry, +static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev, +						  struct sk_buff *skb,  						  struct txentry_desc *txdesc,  						  const struct rt2x00_rate *hwrate)  { -	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);  	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];  	unsigned int data_length;  	unsigned int duration;  	unsigned int residual; +	/* +	 * 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 (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) +		txdesc->u.plcp.ifs = IFS_BACKOFF; +	else +		txdesc->u.plcp.ifs = IFS_SIFS; +  	/* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */ -	data_length = entry->skb->len + 4; -	data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb); +	data_length = skb->len + 4; +	data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);  	/*  	 * PLCP setup  	 * Length calculation depends on OFDM/CCK rate.  	 */ -	txdesc->signal = hwrate->plcp; -	txdesc->service = 0x04; +	txdesc->u.plcp.signal = hwrate->plcp; +	txdesc->u.plcp.service = 0x04;  	if (hwrate->flags & DEV_RATE_OFDM) { -		txdesc->length_high = (data_length >> 6) & 0x3f; -		txdesc->length_low = data_length & 0x3f; +		txdesc->u.plcp.length_high = (data_length >> 6) & 0x3f; +		txdesc->u.plcp.length_low = data_length & 0x3f;  	} else {  		/*  		 * Convert length to microseconds. @@ -285,38 +307,132 @@ static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,  			 * Check if we need to set the Length Extension  			 */  			if (hwrate->bitrate == 110 && residual <= 30) -				txdesc->service |= 0x80; +				txdesc->u.plcp.service |= 0x80;  		} -		txdesc->length_high = (duration >> 8) & 0xff; -		txdesc->length_low = duration & 0xff; +		txdesc->u.plcp.length_high = (duration >> 8) & 0xff; +		txdesc->u.plcp.length_low = duration & 0xff;  		/*  		 * When preamble is enabled we should set the  		 * preamble bit for the signal.  		 */  		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) -			txdesc->signal |= 0x08; +			txdesc->u.plcp.signal |= 0x08;  	}  } -static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, -					     struct txentry_desc *txdesc) +static void rt2x00queue_create_tx_descriptor_ht(struct rt2x00_dev *rt2x00dev, +						struct sk_buff *skb, +						struct txentry_desc *txdesc, +						struct ieee80211_sta *sta, +						const struct rt2x00_rate *hwrate)  { -	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); -	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; -	struct ieee80211_rate *rate = -	    ieee80211_get_tx_rate(rt2x00dev->hw, tx_info); -	const struct rt2x00_rate *hwrate; +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); +	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +	struct rt2x00_sta *sta_priv = NULL; + +	if (sta) { +		txdesc->u.ht.mpdu_density = +		    sta->ht_cap.ampdu_density; + +		sta_priv = sta_to_rt2x00_sta(sta); +		txdesc->u.ht.wcid = sta_priv->wcid; +	} + +	/* +	 * If IEEE80211_TX_RC_MCS is set txrate->idx just contains the +	 * mcs rate to be used +	 */ +	if (txrate->flags & IEEE80211_TX_RC_MCS) { +		txdesc->u.ht.mcs = txrate->idx; + +		/* +		 * MIMO PS should be set to 1 for STA's using dynamic SM PS +		 * when using more then one tx stream (>MCS7). +		 */ +		if (sta && txdesc->u.ht.mcs > 7 && +		    sta->smps_mode == IEEE80211_SMPS_DYNAMIC) +			__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); +	} else { +		txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs); +		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) +			txdesc->u.ht.mcs |= 0x08; +	} + +	if (test_bit(CONFIG_HT_DISABLED, &rt2x00dev->flags)) { +		if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) +			txdesc->u.ht.txop = TXOP_SIFS; +		else +			txdesc->u.ht.txop = TXOP_BACKOFF; + +		/* Left zero on all other settings. */ +		return; +	} + +	txdesc->u.ht.ba_size = 7;	/* FIXME: What value is needed? */ + +	/* +	 * Only one STBC stream is supported for now. +	 */ +	if (tx_info->flags & IEEE80211_TX_CTL_STBC) +		txdesc->u.ht.stbc = 1; + +	/* +	 * This frame is eligible for an AMPDU, however, don't aggregate +	 * frames that are intended to probe a specific tx rate. +	 */ +	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU && +	    !(tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) +		__set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); + +	/* +	 * Set 40Mhz mode if necessary (for legacy rates this will +	 * duplicate the frame to both channels). +	 */ +	if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH || +	    txrate->flags & IEEE80211_TX_RC_DUP_DATA) +		__set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); +	if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) +		__set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); + +	/* +	 * Determine IFS values +	 * - Use TXOP_BACKOFF for management frames except beacons +	 * - Use TXOP_SIFS for fragment bursts +	 * - Use TXOP_HTTXOP for everything else +	 * +	 * Note: rt2800 devices won't use CTS protection (if used) +	 * for frames not transmitted with TXOP_HTTXOP +	 */ +	if (ieee80211_is_mgmt(hdr->frame_control) && +	    !ieee80211_is_beacon(hdr->frame_control)) +		txdesc->u.ht.txop = TXOP_BACKOFF; +	else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)) +		txdesc->u.ht.txop = TXOP_SIFS; +	else +		txdesc->u.ht.txop = TXOP_HTTXOP; +} + +static void rt2x00queue_create_tx_descriptor(struct rt2x00_dev *rt2x00dev, +					     struct sk_buff *skb, +					     struct txentry_desc *txdesc, +					     struct ieee80211_sta *sta) +{ +	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); +	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; +	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; +	struct ieee80211_rate *rate; +	const struct rt2x00_rate *hwrate = NULL;  	memset(txdesc, 0, sizeof(*txdesc));  	/*  	 * Header and frame information.  	 */ -	txdesc->length = entry->skb->len; -	txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); +	txdesc->length = skb->len; +	txdesc->header_length = ieee80211_get_hdrlen_from_skb(skb);  	/*  	 * Check whether this frame is to be acked. @@ -362,42 +478,44 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,  	/*  	 * Beacons and probe responses require the tsf timestamp -	 * to be inserted into the frame, except for a frame that has been injected -	 * through a monitor interface. This latter is needed for testing a -	 * monitor interface. +	 * to be inserted into the frame.  	 */ -	if ((ieee80211_is_beacon(hdr->frame_control) || -	    ieee80211_is_probe_resp(hdr->frame_control)) && -	    (!(tx_info->flags & IEEE80211_TX_CTL_INJECTED))) +	if (ieee80211_is_beacon(hdr->frame_control) || +	    ieee80211_is_probe_resp(hdr->frame_control))  		__set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->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 ((tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) && -	    !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) { +	    !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags))  		__set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags); -		txdesc->ifs = IFS_BACKOFF; -	} else -		txdesc->ifs = IFS_SIFS;  	/*  	 * Determine rate modulation.  	 */ -	hwrate = rt2x00_get_rate(rate->hw_value); -	txdesc->rate_mode = RATE_MODE_CCK; -	if (hwrate->flags & DEV_RATE_OFDM) -		txdesc->rate_mode = RATE_MODE_OFDM; +	if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) +		txdesc->rate_mode = RATE_MODE_HT_GREENFIELD; +	else if (txrate->flags & IEEE80211_TX_RC_MCS) +		txdesc->rate_mode = RATE_MODE_HT_MIX; +	else { +		rate = ieee80211_get_tx_rate(rt2x00dev->hw, tx_info); +		hwrate = rt2x00_get_rate(rate->hw_value); +		if (hwrate->flags & DEV_RATE_OFDM) +			txdesc->rate_mode = RATE_MODE_OFDM; +		else +			txdesc->rate_mode = RATE_MODE_CCK; +	}  	/*  	 * Apply TX descriptor handling by components  	 */ -	rt2x00crypto_create_tx_descriptor(entry, txdesc); -	rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate); -	rt2x00queue_create_tx_descriptor_seq(entry, txdesc); -	rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); +	rt2x00crypto_create_tx_descriptor(rt2x00dev, skb, txdesc); +	rt2x00queue_create_tx_descriptor_seq(rt2x00dev, skb, txdesc); + +	if (test_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags)) +		rt2x00queue_create_tx_descriptor_ht(rt2x00dev, skb, txdesc, +						   sta, hwrate); +	else +		rt2x00queue_create_tx_descriptor_plcp(rt2x00dev, skb, txdesc, +						      hwrate);  }  static int rt2x00queue_write_tx_data(struct queue_entry *entry, @@ -412,18 +530,18 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,  	 */  	if (unlikely(rt2x00dev->ops->lib->get_entry_state &&  		     rt2x00dev->ops->lib->get_entry_state(entry))) { -		ERROR(rt2x00dev, -		      "Corrupt queue %d, accessing entry which is not ours.\n" -		      "Please file bug report to %s.\n", -		      entry->queue->qid, DRV_PROJECT); +		rt2x00_err(rt2x00dev, +			   "Corrupt queue %d, accessing entry which is not ours\n" +			   "Please file bug report to %s\n", +			   entry->queue->qid, DRV_PROJECT);  		return -EINVAL;  	}  	/*  	 * Add the requested extra tx headroom in front of the skb.  	 */ -	skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom); -	memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom); +	skb_push(entry->skb, rt2x00dev->extra_tx_headroom); +	memset(entry->skb->data, 0, rt2x00dev->extra_tx_headroom);  	/*  	 * Call the driver's write_tx_data function, if it exists. @@ -434,8 +552,9 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry,  	/*  	 * Map the skb to DMA.  	 */ -	if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) -		rt2x00queue_map_txskb(entry); +	if (test_bit(REQUIRE_DMA, &rt2x00dev->cap_flags) && +	    rt2x00queue_map_txskb(entry)) +		return -ENOMEM;  	return 0;  } @@ -468,37 +587,67 @@ static void rt2x00queue_kick_tx_queue(struct data_queue *queue,  	 */  	if (rt2x00queue_threshold(queue) ||  	    !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) -		queue->rt2x00dev->ops->lib->kick_tx_queue(queue); +		queue->rt2x00dev->ops->lib->kick_queue(queue); +} + +static void rt2x00queue_bar_check(struct queue_entry *entry) +{ +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +	struct ieee80211_bar *bar = (void *) (entry->skb->data + +				    rt2x00dev->extra_tx_headroom); +	struct rt2x00_bar_list_entry *bar_entry; + +	if (likely(!ieee80211_is_back_req(bar->frame_control))) +		return; + +	bar_entry = kmalloc(sizeof(*bar_entry), GFP_ATOMIC); + +	/* +	 * If the alloc fails we still send the BAR out but just don't track +	 * it in our bar list. And as a result we will report it to mac80211 +	 * back as failed. +	 */ +	if (!bar_entry) +		return; + +	bar_entry->entry = entry; +	bar_entry->block_acked = 0; + +	/* +	 * Copy the relevant parts of the 802.11 BAR into out check list +	 * such that we can use RCU for less-overhead in the RX path since +	 * sending BARs and processing the according BlockAck should be +	 * the exception. +	 */ +	memcpy(bar_entry->ra, bar->ra, sizeof(bar->ra)); +	memcpy(bar_entry->ta, bar->ta, sizeof(bar->ta)); +	bar_entry->control = bar->control; +	bar_entry->start_seq_num = bar->start_seq_num; + +	/* +	 * Insert BAR into our BAR check list. +	 */ +	spin_lock_bh(&rt2x00dev->bar_list_lock); +	list_add_tail_rcu(&bar_entry->list, &rt2x00dev->bar_list); +	spin_unlock_bh(&rt2x00dev->bar_list_lock);  }  int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, -			       bool local) +			       struct ieee80211_sta *sta, bool local)  {  	struct ieee80211_tx_info *tx_info; -	struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); +	struct queue_entry *entry;  	struct txentry_desc txdesc;  	struct skb_frame_desc *skbdesc;  	u8 rate_idx, rate_flags; - -	if (unlikely(rt2x00queue_full(queue))) -		return -ENOBUFS; - -	if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, -				      &entry->flags))) { -		ERROR(queue->rt2x00dev, -		      "Arrived at non-free entry in the non-full queue %d.\n" -		      "Please file bug report to %s.\n", -		      queue->qid, DRV_PROJECT); -		return -EINVAL; -	} +	int ret = 0;  	/*  	 * Copy all TX descriptor information into txdesc,  	 * after that we are free to use the skb->cb array  	 * for our information.  	 */ -	entry->skb = skb; -	rt2x00queue_create_tx_descriptor(entry, &txdesc); +	rt2x00queue_create_tx_descriptor(queue->rt2x00dev, skb, &txdesc, sta);  	/*  	 * All information is retrieved from the skb->cb array, @@ -510,7 +659,6 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	rate_flags = tx_info->control.rates[0].flags;  	skbdesc = get_skb_frame_desc(skb);  	memset(skbdesc, 0, sizeof(*skbdesc)); -	skbdesc->entry = entry;  	skbdesc->tx_rate_idx = rate_idx;  	skbdesc->tx_rate_flags = rate_flags; @@ -524,24 +672,51 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	 */  	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&  	    !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { -		if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags)) +		if (test_bit(REQUIRE_COPY_IV, &queue->rt2x00dev->cap_flags))  			rt2x00crypto_tx_copy_iv(skb, &txdesc);  		else  			rt2x00crypto_tx_remove_iv(skb, &txdesc);  	}  	/* -	 * When DMA allocation is required we should guarentee to the +	 * When DMA allocation is required we should guarantee to the  	 * driver that the DMA is aligned to a 4-byte boundary.  	 * However some drivers require L2 padding to pad the payload  	 * rather then the header. This could be a requirement for  	 * PCI and USB devices, while header alignment only is valid  	 * for PCI devices.  	 */ -	if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) -		rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length); -	else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) -		rt2x00queue_align_frame(entry->skb); +	if (test_bit(REQUIRE_L2PAD, &queue->rt2x00dev->cap_flags)) +		rt2x00queue_insert_l2pad(skb, txdesc.header_length); +	else if (test_bit(REQUIRE_DMA, &queue->rt2x00dev->cap_flags)) +		rt2x00queue_align_frame(skb); + +	/* +	 * That function must be called with bh disabled. +	 */ +	spin_lock(&queue->tx_lock); + +	if (unlikely(rt2x00queue_full(queue))) { +		rt2x00_err(queue->rt2x00dev, "Dropping frame due to full tx queue %d\n", +			   queue->qid); +		ret = -ENOBUFS; +		goto out; +	} + +	entry = rt2x00queue_get_entry(queue, Q_INDEX); + +	if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, +				      &entry->flags))) { +		rt2x00_err(queue->rt2x00dev, +			   "Arrived at non-free entry in the non-full queue %d\n" +			   "Please file bug report to %s\n", +			   queue->qid, DRV_PROJECT); +		ret = -EINVAL; +		goto out; +	} + +	skbdesc->entry = entry; +	entry->skb = skb;  	/*  	 * It could be possible that the queue was corrupted and this @@ -551,25 +726,30 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,  	if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {  		clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);  		entry->skb = NULL; -		return -EIO; +		ret = -EIO; +		goto out;  	} +	/* +	 * Put BlockAckReqs into our check list for driver BA processing. +	 */ +	rt2x00queue_bar_check(entry); +  	set_bit(ENTRY_DATA_PENDING, &entry->flags); -	rt2x00queue_index_inc(queue, Q_INDEX); +	rt2x00queue_index_inc(entry, Q_INDEX);  	rt2x00queue_write_tx_descriptor(entry, &txdesc);  	rt2x00queue_kick_tx_queue(queue, &txdesc); -	return 0; +out: +	spin_unlock(&queue->tx_lock); +	return ret;  } -int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, -			      struct ieee80211_vif *vif, -			      const bool enable_beacon) +int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev, +			     struct ieee80211_vif *vif)  {  	struct rt2x00_intf *intf = vif_to_intf(vif); -	struct skb_frame_desc *skbdesc; -	struct txentry_desc txdesc;  	if (unlikely(!intf->beacon))  		return -ENOBUFS; @@ -581,24 +761,43 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,  	 */  	rt2x00queue_free_skb(intf->beacon); -	if (!enable_beacon) { -		rt2x00dev->ops->lib->kill_tx_queue(intf->beacon->queue); -		mutex_unlock(&intf->beacon_skb_mutex); -		return 0; -	} +	/* +	 * Clear beacon (single bssid devices don't need to clear the beacon +	 * since the beacon queue will get stopped anyway). +	 */ +	if (rt2x00dev->ops->lib->clear_beacon) +		rt2x00dev->ops->lib->clear_beacon(intf->beacon); + +	mutex_unlock(&intf->beacon_skb_mutex); + +	return 0; +} + +int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev, +				     struct ieee80211_vif *vif) +{ +	struct rt2x00_intf *intf = vif_to_intf(vif); +	struct skb_frame_desc *skbdesc; +	struct txentry_desc txdesc; + +	if (unlikely(!intf->beacon)) +		return -ENOBUFS; + +	/* +	 * Clean up the beacon skb. +	 */ +	rt2x00queue_free_skb(intf->beacon);  	intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); -	if (!intf->beacon->skb) { -		mutex_unlock(&intf->beacon_skb_mutex); +	if (!intf->beacon->skb)  		return -ENOMEM; -	}  	/*  	 * Copy all TX descriptor information into txdesc,  	 * after that we are free to use the skb->cb array  	 * for our information.  	 */ -	rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); +	rt2x00queue_create_tx_descriptor(rt2x00dev, intf->beacon->skb, &txdesc, NULL);  	/*  	 * Fill in skb descriptor @@ -608,19 +807,33 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,  	skbdesc->entry = intf->beacon;  	/* -	 * Send beacon to hardware and enable beacon genaration.. +	 * Send beacon to hardware.  	 */  	rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc); +	return 0; + +} + +int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, +			      struct ieee80211_vif *vif) +{ +	struct rt2x00_intf *intf = vif_to_intf(vif); +	int ret; + +	mutex_lock(&intf->beacon_skb_mutex); +	ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif);  	mutex_unlock(&intf->beacon_skb_mutex); -	return 0; +	return ret;  } -void rt2x00queue_for_each_entry(struct data_queue *queue, +bool rt2x00queue_for_each_entry(struct data_queue *queue,  				enum queue_index start,  				enum queue_index end, -				void (*fn)(struct queue_entry *entry)) +				void *data, +				bool (*fn)(struct queue_entry *entry, +					   void *data))  {  	unsigned long irqflags;  	unsigned int index_start; @@ -628,10 +841,10 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,  	unsigned int i;  	if (unlikely(start >= Q_INDEX_MAX || end >= Q_INDEX_MAX)) { -		ERROR(queue->rt2x00dev, -		      "Entry requested from invalid index range (%d - %d)\n", -		      start, end); -		return; +		rt2x00_err(queue->rt2x00dev, +			   "Entry requested from invalid index range (%d - %d)\n", +			   start, end); +		return true;  	}  	/* @@ -646,44 +859,29 @@ void rt2x00queue_for_each_entry(struct data_queue *queue,  	spin_unlock_irqrestore(&queue->index_lock, irqflags);  	/* -	 * Start from the TX done pointer, this guarentees that we will +	 * Start from the TX done pointer, this guarantees that we will  	 * send out all frames in the correct order.  	 */  	if (index_start < index_end) { -		for (i = index_start; i < index_end; i++) -			fn(&queue->entries[i]); +		for (i = index_start; i < index_end; i++) { +			if (fn(&queue->entries[i], data)) +				return true; +		}  	} else { -		for (i = index_start; i < queue->limit; i++) -			fn(&queue->entries[i]); +		for (i = index_start; i < queue->limit; i++) { +			if (fn(&queue->entries[i], data)) +				return true; +		} -		for (i = 0; i < index_end; i++) -			fn(&queue->entries[i]); +		for (i = 0; i < index_end; i++) { +			if (fn(&queue->entries[i], data)) +				return true; +		}  	} -} -EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry); - -struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, -					 const enum data_queue_qid queue) -{ -	int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); - -	if (queue == QID_RX) -		return rt2x00dev->rx; - -	if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx) -		return &rt2x00dev->tx[queue]; - -	if (!rt2x00dev->bcn) -		return NULL; -	if (queue == QID_BEACON) -		return &rt2x00dev->bcn[0]; -	else if (queue == QID_ATIM && atim) -		return &rt2x00dev->bcn[1]; - -	return NULL; +	return false;  } -EXPORT_SYMBOL_GPL(rt2x00queue_get_queue); +EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);  struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,  					  enum queue_index index) @@ -692,8 +890,8 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,  	unsigned long irqflags;  	if (unlikely(index >= Q_INDEX_MAX)) { -		ERROR(queue->rt2x00dev, -		      "Entry requested from invalid index type (%d)\n", index); +		rt2x00_err(queue->rt2x00dev, "Entry requested from invalid index type (%d)\n", +			   index);  		return NULL;  	} @@ -707,13 +905,14 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,  }  EXPORT_SYMBOL_GPL(rt2x00queue_get_entry); -void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) +void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)  { +	struct data_queue *queue = entry->queue;  	unsigned long irqflags;  	if (unlikely(index >= Q_INDEX_MAX)) { -		ERROR(queue->rt2x00dev, -		      "Index change on invalid index type (%d)\n", index); +		rt2x00_err(queue->rt2x00dev, +			   "Index change on invalid index type (%d)\n", index);  		return;  	} @@ -723,7 +922,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)  	if (queue->index[index] >= queue->limit)  		queue->index[index] = 0; -	queue->last_action[index] = jiffies; +	entry->last_action = jiffies;  	if (index == Q_INDEX) {  		queue->length++; @@ -735,6 +934,181 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)  	spin_unlock_irqrestore(&queue->index_lock, irqflags);  } +static void rt2x00queue_pause_queue_nocheck(struct data_queue *queue) +{ +	switch (queue->qid) { +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		/* +		 * For TX queues, we have to disable the queue +		 * inside mac80211. +		 */ +		ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid); +		break; +	default: +		break; +	} +} +void rt2x00queue_pause_queue(struct data_queue *queue) +{ +	if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || +	    !test_bit(QUEUE_STARTED, &queue->flags) || +	    test_and_set_bit(QUEUE_PAUSED, &queue->flags)) +		return; + +	rt2x00queue_pause_queue_nocheck(queue); +} +EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue); + +void rt2x00queue_unpause_queue(struct data_queue *queue) +{ +	if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || +	    !test_bit(QUEUE_STARTED, &queue->flags) || +	    !test_and_clear_bit(QUEUE_PAUSED, &queue->flags)) +		return; + +	switch (queue->qid) { +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		/* +		 * For TX queues, we have to enable the queue +		 * inside mac80211. +		 */ +		ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid); +		break; +	case QID_RX: +		/* +		 * For RX we need to kick the queue now in order to +		 * receive frames. +		 */ +		queue->rt2x00dev->ops->lib->kick_queue(queue); +	default: +		break; +	} +} +EXPORT_SYMBOL_GPL(rt2x00queue_unpause_queue); + +void rt2x00queue_start_queue(struct data_queue *queue) +{ +	mutex_lock(&queue->status_lock); + +	if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || +	    test_and_set_bit(QUEUE_STARTED, &queue->flags)) { +		mutex_unlock(&queue->status_lock); +		return; +	} + +	set_bit(QUEUE_PAUSED, &queue->flags); + +	queue->rt2x00dev->ops->lib->start_queue(queue); + +	rt2x00queue_unpause_queue(queue); + +	mutex_unlock(&queue->status_lock); +} +EXPORT_SYMBOL_GPL(rt2x00queue_start_queue); + +void rt2x00queue_stop_queue(struct data_queue *queue) +{ +	mutex_lock(&queue->status_lock); + +	if (!test_and_clear_bit(QUEUE_STARTED, &queue->flags)) { +		mutex_unlock(&queue->status_lock); +		return; +	} + +	rt2x00queue_pause_queue_nocheck(queue); + +	queue->rt2x00dev->ops->lib->stop_queue(queue); + +	mutex_unlock(&queue->status_lock); +} +EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue); + +void rt2x00queue_flush_queue(struct data_queue *queue, bool drop) +{ +	bool tx_queue = +		(queue->qid == QID_AC_VO) || +		(queue->qid == QID_AC_VI) || +		(queue->qid == QID_AC_BE) || +		(queue->qid == QID_AC_BK); + + +	/* +	 * If we are not supposed to drop any pending +	 * frames, this means we must force a start (=kick) +	 * to the queue to make sure the hardware will +	 * start transmitting. +	 */ +	if (!drop && tx_queue) +		queue->rt2x00dev->ops->lib->kick_queue(queue); + +	/* +	 * Check if driver supports flushing, if that is the case we can +	 * defer the flushing to the driver. Otherwise we must use the +	 * alternative which just waits for the queue to become empty. +	 */ +	if (likely(queue->rt2x00dev->ops->lib->flush_queue)) +		queue->rt2x00dev->ops->lib->flush_queue(queue, drop); + +	/* +	 * The queue flush has failed... +	 */ +	if (unlikely(!rt2x00queue_empty(queue))) +		rt2x00_warn(queue->rt2x00dev, "Queue %d failed to flush\n", +			    queue->qid); +} +EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue); + +void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue; + +	/* +	 * rt2x00queue_start_queue will call ieee80211_wake_queue +	 * for each queue after is has been properly initialized. +	 */ +	tx_queue_for_each(rt2x00dev, queue) +		rt2x00queue_start_queue(queue); + +	rt2x00queue_start_queue(rt2x00dev->rx); +} +EXPORT_SYMBOL_GPL(rt2x00queue_start_queues); + +void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue; + +	/* +	 * rt2x00queue_stop_queue will call ieee80211_stop_queue +	 * as well, but we are completely shutting doing everything +	 * now, so it is much safer to stop all TX queues at once, +	 * and use rt2x00queue_stop_queue for cleaning up. +	 */ +	ieee80211_stop_queues(rt2x00dev->hw); + +	tx_queue_for_each(rt2x00dev, queue) +		rt2x00queue_stop_queue(queue); + +	rt2x00queue_stop_queue(rt2x00dev->rx); +} +EXPORT_SYMBOL_GPL(rt2x00queue_stop_queues); + +void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop) +{ +	struct data_queue *queue; + +	tx_queue_for_each(rt2x00dev, queue) +		rt2x00queue_flush_queue(queue, drop); + +	rt2x00queue_flush_queue(rt2x00dev->rx, drop); +} +EXPORT_SYMBOL_GPL(rt2x00queue_flush_queues); +  static void rt2x00queue_reset(struct data_queue *queue)  {  	unsigned long irqflags; @@ -745,22 +1119,12 @@ static void rt2x00queue_reset(struct data_queue *queue)  	queue->count = 0;  	queue->length = 0; -	for (i = 0; i < Q_INDEX_MAX; i++) { +	for (i = 0; i < Q_INDEX_MAX; i++)  		queue->index[i] = 0; -		queue->last_action[i] = jiffies; -	}  	spin_unlock_irqrestore(&queue->index_lock, irqflags);  } -void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev) -{ -	struct data_queue *queue; - -	txall_queue_for_each(rt2x00dev, queue) -		rt2x00dev->ops->lib->kill_tx_queue(queue); -} -  void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev)  {  	struct data_queue *queue; @@ -769,16 +1133,12 @@ void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev)  	queue_for_each(rt2x00dev, queue) {  		rt2x00queue_reset(queue); -		for (i = 0; i < queue->limit; i++) { +		for (i = 0; i < queue->limit; i++)  			rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); -			if (queue->qid == QID_RX) -				rt2x00queue_index_inc(queue, Q_INDEX); -		}  	}  } -static int rt2x00queue_alloc_entries(struct data_queue *queue, -				     const struct data_queue_desc *qdesc) +static int rt2x00queue_alloc_entries(struct data_queue *queue)  {  	struct queue_entry *entries;  	unsigned int entry_size; @@ -786,15 +1146,10 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue,  	rt2x00queue_reset(queue); -	queue->limit = qdesc->entry_num; -	queue->threshold = DIV_ROUND_UP(qdesc->entry_num, 10); -	queue->data_size = qdesc->data_size; -	queue->desc_size = qdesc->desc_size; -  	/*  	 * Allocate all queue entries.  	 */ -	entry_size = sizeof(*entries) + qdesc->priv_size; +	entry_size = sizeof(*entries) + queue->priv_size;  	entries = kcalloc(queue->limit, entry_size, GFP_KERNEL);  	if (!entries)  		return -ENOMEM; @@ -810,7 +1165,7 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue,  		entries[i].entry_idx = i;  		entries[i].priv_data =  		    QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit, -					    sizeof(*entries), qdesc->priv_size); +					    sizeof(*entries), queue->priv_size);  	}  #undef QUEUE_ENTRY_PRIV_OFFSET @@ -838,7 +1193,7 @@ static int rt2x00queue_alloc_rxskbs(struct data_queue *queue)  	struct sk_buff *skb;  	for (i = 0; i < queue->limit; i++) { -		skb = rt2x00queue_alloc_rxskb(&queue->entries[i]); +		skb = rt2x00queue_alloc_rxskb(&queue->entries[i], GFP_KERNEL);  		if (!skb)  			return -ENOMEM;  		queue->entries[i].skb = skb; @@ -852,23 +1207,22 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)  	struct data_queue *queue;  	int status; -	status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx); +	status = rt2x00queue_alloc_entries(rt2x00dev->rx);  	if (status)  		goto exit;  	tx_queue_for_each(rt2x00dev, queue) { -		status = rt2x00queue_alloc_entries(queue, rt2x00dev->ops->tx); +		status = rt2x00queue_alloc_entries(queue);  		if (status)  			goto exit;  	} -	status = rt2x00queue_alloc_entries(rt2x00dev->bcn, rt2x00dev->ops->bcn); +	status = rt2x00queue_alloc_entries(rt2x00dev->bcn);  	if (status)  		goto exit; -	if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) { -		status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1], -						   rt2x00dev->ops->atim); +	if (test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags)) { +		status = rt2x00queue_alloc_entries(rt2x00dev->atim);  		if (status)  			goto exit;  	} @@ -880,7 +1234,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev)  	return 0;  exit: -	ERROR(rt2x00dev, "Queue entries allocation failed.\n"); +	rt2x00_err(rt2x00dev, "Queue entries allocation failed\n");  	rt2x00queue_uninitialize(rt2x00dev); @@ -902,6 +1256,8 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev)  static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,  			     struct data_queue *queue, enum data_queue_qid qid)  { +	mutex_init(&queue->status_lock); +	spin_lock_init(&queue->tx_lock);  	spin_lock_init(&queue->index_lock);  	queue->rt2x00dev = rt2x00dev; @@ -910,6 +1266,10 @@ static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,  	queue->aifs = 2;  	queue->cw_min = 5;  	queue->cw_max = 10; + +	rt2x00dev->ops->queue_init(queue); + +	queue->threshold = DIV_ROUND_UP(queue->limit, 10);  }  int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) @@ -917,7 +1277,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)  	struct data_queue *queue;  	enum data_queue_qid qid;  	unsigned int req_atim = -	    !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); +	    !!test_bit(REQUIRE_ATIM_QUEUE, &rt2x00dev->cap_flags);  	/*  	 * We need the following queues: @@ -930,7 +1290,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)  	queue = kcalloc(rt2x00dev->data_queues, sizeof(*queue), GFP_KERNEL);  	if (!queue) { -		ERROR(rt2x00dev, "Queue allocation failed.\n"); +		rt2x00_err(rt2x00dev, "Queue allocation failed\n");  		return -ENOMEM;  	} @@ -940,11 +1300,12 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)  	rt2x00dev->rx = queue;  	rt2x00dev->tx = &queue[1];  	rt2x00dev->bcn = &queue[1 + rt2x00dev->ops->tx_queues]; +	rt2x00dev->atim = req_atim ? &queue[2 + rt2x00dev->ops->tx_queues] : NULL;  	/*  	 * Initialize queue parameters.  	 * RX: qid = QID_RX -	 * TX: qid = QID_AC_BE + index +	 * TX: qid = QID_AC_VO + index  	 * TX: cw_min: 2^5 = 32.  	 * TX: cw_max: 2^10 = 1024.  	 * BCN: qid = QID_BEACON @@ -952,13 +1313,13 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)  	 */  	rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX); -	qid = QID_AC_BE; +	qid = QID_AC_VO;  	tx_queue_for_each(rt2x00dev, queue)  		rt2x00queue_init(rt2x00dev, queue, qid++); -	rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_BEACON); +	rt2x00queue_init(rt2x00dev, rt2x00dev->bcn, QID_BEACON);  	if (req_atim) -		rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_ATIM); +		rt2x00queue_init(rt2x00dev, rt2x00dev->atim, QID_ATIM);  	return 0;  } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 29b051ac640..c48125be0e3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -45,22 +43,22 @@  /**   * enum data_queue_qid: Queue identification   * + * @QID_AC_VO: AC VO queue + * @QID_AC_VI: AC VI queue   * @QID_AC_BE: AC BE queue   * @QID_AC_BK: AC BK queue - * @QID_AC_VI: AC VI queue - * @QID_AC_VO: AC VO queue   * @QID_HCCA: HCCA queue   * @QID_MGMT: MGMT queue (prio queue)   * @QID_RX: RX queue   * @QID_OTHER: None of the above (don't use, only present for completeness)   * @QID_BEACON: Beacon queue (value unspecified, don't send it to device) - * @QID_ATIM: Atim queue (value unspeficied, don't send it to device) + * @QID_ATIM: Atim queue (value unspecified, don't send it to device)   */  enum data_queue_qid { -	QID_AC_BE = 0, -	QID_AC_BK = 1, -	QID_AC_VI = 2, -	QID_AC_VO = 3, +	QID_AC_VO = 0, +	QID_AC_VI = 1, +	QID_AC_BE = 2, +	QID_AC_BK = 3,  	QID_HCCA = 4,  	QID_MGMT = 13,  	QID_RX = 14, @@ -217,6 +215,7 @@ enum txdone_entry_desc_flags {  	TXDONE_FALLBACK,  	TXDONE_FAILURE,  	TXDONE_EXCESSIVE_RETRY, +	TXDONE_AMPDU,  };  /** @@ -287,8 +286,8 @@ enum txentry_desc_flags {   * @signal: PLCP signal.   * @service: PLCP service.   * @msc: MCS. - * @stbc: STBC. - * @ba_size: BA size. + * @stbc: Use Space Time Block Coding (only available for MCS rates < 8). + * @ba_size: Size of the recepients RX reorder buffer - 1.   * @rate_mode: Rate mode (See @enum rate_modulation).   * @mpdu_density: MDPU density.   * @retry_limit: Max number of retries. @@ -305,20 +304,28 @@ struct txentry_desc {  	u16 length;  	u16 header_length; -	u16 length_high; -	u16 length_low; -	u16 signal; -	u16 service; - -	u16 mcs; -	u16 stbc; -	u16 ba_size; -	u16 rate_mode; -	u16 mpdu_density; +	union { +		struct { +			u16 length_high; +			u16 length_low; +			u16 signal; +			u16 service; +			enum ifs ifs; +		} plcp; + +		struct { +			u16 mcs; +			u8 stbc; +			u8 ba_size; +			u8 mpdu_density; +			enum txop txop; +			int wcid; +		} ht; +	} u; + +	enum rate_modulation rate_mode;  	short retry_limit; -	short ifs; -	short txop;  	enum cipher cipher;  	u16 key_idx; @@ -337,30 +344,38 @@ struct txentry_desc {   *	only be touched after the device has signaled it is done with it.   * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting   *	for the signal to start sending. - * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured - *	while transfering the data to the hardware. No TX status report will + * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occurred + *	while transferring the data to the hardware. No TX status report will   *	be expected from the hardware. + * @ENTRY_DATA_STATUS_PENDING: The entry has been send to the device and + *	returned. It is now waiting for the status reporting before the + *	entry can be reused again.   */  enum queue_entry_flags {  	ENTRY_BCN_ASSIGNED,  	ENTRY_OWNER_DEVICE_DATA,  	ENTRY_DATA_PENDING, -	ENTRY_DATA_IO_FAILED +	ENTRY_DATA_IO_FAILED, +	ENTRY_DATA_STATUS_PENDING, +	ENTRY_DATA_STATUS_SET,  };  /**   * struct queue_entry: Entry inside the &struct data_queue   *   * @flags: Entry flags, see &enum queue_entry_flags. + * @last_action: Timestamp of last change.   * @queue: The data queue (&struct data_queue) to which this entry belongs.   * @skb: The buffer which is currently being transmitted (for TX queue), - *	or used to directly recieve data in (for RX queue). + *	or used to directly receive data in (for RX queue).   * @entry_idx: The entry index number.   * @priv_data: Private data belonging to this queue entry. The pointer   *	points to data specific to a particular driver and queue type. + * @status: Device specific status   */  struct queue_entry {  	unsigned long flags; +	unsigned long last_action;  	struct data_queue *queue; @@ -368,6 +383,8 @@ struct queue_entry {  	unsigned int entry_idx; +	u32 status; +  	void *priv_data;  }; @@ -377,7 +394,7 @@ struct queue_entry {   * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is   *	owned by the hardware then the queue is considered to be full.   * @Q_INDEX_DMA_DONE: Index pointer for the next entry which will have been - *	transfered to the hardware. + *	transferred to the hardware.   * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by   *	the hardware and for which we need to run the txdone handler. If this   *	entry is not owned by the hardware the queue is considered to be empty. @@ -392,12 +409,33 @@ enum queue_index {  };  /** + * enum data_queue_flags: Status flags for data queues + * + * @QUEUE_STARTED: The queue has been started. Fox RX queues this means the + *	device might be DMA'ing skbuffers. TX queues will accept skbuffers to + *	be transmitted and beacon queues will start beaconing the configured + *	beacons. + * @QUEUE_PAUSED: The queue has been started but is currently paused. + *	When this bit is set, the queue has been stopped in mac80211, + *	preventing new frames to be enqueued. However, a few frames + *	might still appear shortly after the pausing... + */ +enum data_queue_flags { +	QUEUE_STARTED, +	QUEUE_PAUSED, +}; + +/**   * struct data_queue: Data queue   *   * @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to.   * @entries: Base address of the &struct queue_entry which are   *	part of this queue.   * @qid: The queue identification, see &enum data_queue_qid. + * @flags: Entry flags, see &enum queue_entry_flags. + * @status_lock: The mutex for protecting the start/stop/flush + *	handling on this queue. + * @tx_lock: Spinlock to serialize tx operations on this queue.   * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or   *	@index_crypt needs to be changed this lock should be grabbed to prevent   *	index corruption due to concurrency. @@ -413,6 +451,7 @@ enum queue_index {   * @cw_max: The cw max value for outgoing frames (field ignored in RX queue).   * @data_size: Maximum data size for the frames in this queue.   * @desc_size: Hardware descriptor size for the data in this queue. + * @priv_size: Size of per-queue_entry private data.   * @usb_endpoint: Device endpoint used for communication (USB only)   * @usb_maxpacket: Max packet size for given endpoint (USB only)   */ @@ -421,14 +460,17 @@ struct data_queue {  	struct queue_entry *entries;  	enum data_queue_qid qid; +	unsigned long flags; +	struct mutex status_lock; +	spinlock_t tx_lock;  	spinlock_t index_lock; +  	unsigned int count;  	unsigned short limit;  	unsigned short threshold;  	unsigned short length;  	unsigned short index[Q_INDEX_MAX]; -	unsigned long last_action[Q_INDEX_MAX];  	unsigned short txop;  	unsigned short aifs; @@ -436,31 +478,15 @@ struct data_queue {  	unsigned short cw_max;  	unsigned short data_size; -	unsigned short desc_size; +	unsigned char  desc_size; +	unsigned char  winfo_size; +	unsigned short priv_size;  	unsigned short usb_endpoint;  	unsigned short usb_maxpacket;  };  /** - * struct data_queue_desc: Data queue description - * - * The information in this structure is used by drivers - * to inform rt2x00lib about the creation of the data queue. - * - * @entry_num: Maximum number of entries for a queue. - * @data_size: Maximum data size for the frames in this queue. - * @desc_size: Hardware descriptor size for the data in this queue. - * @priv_size: Size of per-queue_entry private data. - */ -struct data_queue_desc { -	unsigned short entry_num; -	unsigned short data_size; -	unsigned short desc_size; -	unsigned short priv_size; -}; - -/**   * queue_end - Return pointer to the last queue (HELPER MACRO).   * @__dev: Pointer to &struct rt2x00_dev   * @@ -545,16 +571,22 @@ struct data_queue_desc {   * @queue: Pointer to @data_queue   * @start: &enum queue_index Pointer to start index   * @end: &enum queue_index Pointer to end index + * @data: Data to pass to the callback function   * @fn: The function to call for each &struct queue_entry   *   * This will walk through all entries in the queue, in chronological   * order. This means it will start at the current @start pointer   * and will walk through the queue until it reaches the @end pointer. + * + * If fn returns true for an entry rt2x00queue_for_each_entry will stop + * processing and return true as well.   */ -void rt2x00queue_for_each_entry(struct data_queue *queue, +bool rt2x00queue_for_each_entry(struct data_queue *queue,  				enum queue_index start,  				enum queue_index end, -				void (*fn)(struct queue_entry *entry)); +				void *data, +				bool (*fn)(struct queue_entry *entry, +					   void *data));  /**   * rt2x00queue_empty - Check if the queue is empty. @@ -591,25 +623,15 @@ static inline int rt2x00queue_threshold(struct data_queue *queue)  {  	return rt2x00queue_available(queue) < queue->threshold;  } -  /** - * rt2x00queue_status_timeout - Check if a timeout occured for STATUS reports - * @queue: Queue to check. - */ -static inline int rt2x00queue_status_timeout(struct data_queue *queue) -{ -	return time_after(queue->last_action[Q_INDEX_DMA_DONE], -			  queue->last_action[Q_INDEX_DONE] + (HZ / 10)); -} - -/** - * rt2x00queue_timeout - Check if a timeout occured for DMA transfers - * @queue: Queue to check. + * rt2x00queue_dma_timeout - Check if a timeout occurred for DMA transfers + * @entry: Queue entry to check.   */ -static inline int rt2x00queue_dma_timeout(struct data_queue *queue) +static inline int rt2x00queue_dma_timeout(struct queue_entry *entry)  { -	return time_after(queue->last_action[Q_INDEX], -			  queue->last_action[Q_INDEX_DMA_DONE] + (HZ / 10)); +	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) +		return false; +	return time_after(jiffies, entry->last_action + msecs_to_jiffies(100));  }  /** diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index ed71be95136..3cc541d13d6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -83,12 +81,8 @@ enum dev_state {   */  	STATE_RADIO_ON,  	STATE_RADIO_OFF, -	STATE_RADIO_RX_ON, -	STATE_RADIO_RX_OFF,  	STATE_RADIO_IRQ_ON,  	STATE_RADIO_IRQ_OFF, -	STATE_RADIO_IRQ_ON_ISR, -	STATE_RADIO_IRQ_OFF_ISR,  };  /* diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c index 2aa5c38022f..69a0cdadb07 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c @@ -14,9 +14,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -68,7 +66,7 @@ static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev)  	return 0;  exit: -	ERROR_PROBE("Failed to allocate registers.\n"); +	rt2x00_probe_err("Failed to allocate registers\n");  	rt2x00soc_free_reg(rt2x00dev);  	return -ENOMEM; @@ -82,7 +80,7 @@ int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)  	hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);  	if (!hw) { -		ERROR_PROBE("Failed to allocate hardware.\n"); +		rt2x00_probe_err("Failed to allocate hardware\n");  		return -ENOMEM;  	} diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.h b/drivers/net/wireless/rt2x00/rt2x00soc.h index 474cbfc1efc..9948d355e9a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.h +++ b/drivers/net/wireless/rt2x00/rt2x00soc.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 9ac14598e2a..86c43d112a4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -14,9 +14,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -70,9 +68,15 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,  		}  	} -	ERROR(rt2x00dev, -	      "Vendor Request 0x%02x failed for offset 0x%04x with error %d.\n", -	      request, offset, status); +	/* If the port is powered down, we get a -EPROTO error, and this +	 * leads to a endless loop. So just say that the device is gone. +	 */ +	if (status == -EPROTO) +		clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); + +	rt2x00_err(rt2x00dev, +		   "Vendor Request 0x%02x failed for offset 0x%04x with error %d\n", +		   request, offset, status);  	return status;  } @@ -91,7 +95,7 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,  	 * Check for Cache availability.  	 */  	if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) { -		ERROR(rt2x00dev, "CSR cache not available.\n"); +		rt2x00_err(rt2x00dev, "CSR cache not available\n");  		return -ENOMEM;  	} @@ -157,14 +161,67 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,  		udelay(REGISTER_BUSY_DELAY);  	} -	ERROR(rt2x00dev, "Indirect register access failed: " -	      "offset=0x%.08x, value=0x%.08x\n", offset, *reg); +	rt2x00_err(rt2x00dev, "Indirect register access failed: offset=0x%.08x, value=0x%.08x\n", +		   offset, *reg);  	*reg = ~0;  	return 0;  }  EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); + +struct rt2x00_async_read_data { +	__le32 reg; +	struct usb_ctrlrequest cr; +	struct rt2x00_dev *rt2x00dev; +	bool (*callback)(struct rt2x00_dev *, int, u32); +}; + +static void rt2x00usb_register_read_async_cb(struct urb *urb) +{ +	struct rt2x00_async_read_data *rd = urb->context; +	if (rd->callback(rd->rt2x00dev, urb->status, le32_to_cpu(rd->reg))) { +		if (usb_submit_urb(urb, GFP_ATOMIC) < 0) +			kfree(rd); +	} else +		kfree(rd); +} + +void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, +				   const unsigned int offset, +				   bool (*callback)(struct rt2x00_dev*, int, u32)) +{ +	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); +	struct urb *urb; +	struct rt2x00_async_read_data *rd; + +	rd = kmalloc(sizeof(*rd), GFP_ATOMIC); +	if (!rd) +		return; + +	urb = usb_alloc_urb(0, GFP_ATOMIC); +	if (!urb) { +		kfree(rd); +		return; +	} + +	rd->rt2x00dev = rt2x00dev; +	rd->callback = callback; +	rd->cr.bRequestType = USB_VENDOR_REQUEST_IN; +	rd->cr.bRequest = USB_MULTI_READ; +	rd->cr.wValue = 0; +	rd->cr.wIndex = cpu_to_le16(offset); +	rd->cr.wLength = cpu_to_le16(sizeof(u32)); + +	usb_fill_control_urb(urb, usb_dev, usb_rcvctrlpipe(usb_dev, 0), +			     (unsigned char *)(&rd->cr), &rd->reg, sizeof(rd->reg), +			     rt2x00usb_register_read_async_cb, rd); +	if (usb_submit_urb(urb, GFP_ATOMIC) < 0) +		kfree(rd); +	usb_free_urb(urb); +} +EXPORT_SYMBOL_GPL(rt2x00usb_register_read_async); +  /*   * TX data handlers.   */ @@ -173,7 +230,7 @@ static void rt2x00usb_work_txdone_entry(struct queue_entry *entry)  	/*  	 * If the transfer to hardware succeeded, it does not mean the  	 * frame was send out correctly. It only means the frame -	 * was succesfully pushed to the hardware, we have no +	 * was successfully pushed to the hardware, we have no  	 * way to determine the transmission status right now.  	 * (Only indirectly by looking at the failed TX counters  	 * in the register). @@ -195,7 +252,8 @@ static void rt2x00usb_work_txdone(struct work_struct *work)  		while (!rt2x00queue_empty(queue)) {  			entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); -			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) +			if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || +			    !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))  				break;  			rt2x00usb_work_txdone_entry(entry); @@ -208,148 +266,73 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)  	struct queue_entry *entry = (struct queue_entry *)urb->context;  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) +	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))  		return; - -	/* -	 * Report the frame as DMA done -	 */ -	rt2x00lib_dmadone(entry); -  	/*  	 * Check if the frame was correctly uploaded  	 */  	if (urb->status)  		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); +	/* +	 * Report the frame as DMA done +	 */ +	rt2x00lib_dmadone(entry); +	if (rt2x00dev->ops->lib->tx_dma_done) +		rt2x00dev->ops->lib->tx_dma_done(entry);  	/*  	 * Schedule the delayed work for reading the TX status  	 * from the device.  	 */ -	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); +	if (!test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags) || +	    !kfifo_is_empty(&rt2x00dev->txstatus_fifo)) +		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);  } -static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) +static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void *data)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);  	struct queue_entry_priv_usb *entry_priv = entry->priv_data;  	u32 length; +	int status; -	if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) -		return; +	if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) || +	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) +		return false;  	/* -	 * 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. +	 * USB devices require certain padding at the end of each frame +	 * and urb. Those paddings are not included in skbs. Pass entry +	 * to the driver to determine what the overall length should be.  	 */  	length = rt2x00dev->ops->lib->get_tx_data_len(entry); +	status = skb_padto(entry->skb, length); +	if (unlikely(status)) { +		/* TODO: report something more appropriate than IO_FAILED. */ +		rt2x00_warn(rt2x00dev, "TX SKB padding error, out of memory\n"); +		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); +		rt2x00lib_dmadone(entry); + +		return false; +	} +  	usb_fill_bulk_urb(entry_priv->urb, usb_dev,  			  usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),  			  entry->skb->data, length,  			  rt2x00usb_interrupt_txdone, entry); -	if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) { +	status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); +	if (status) { +		if (status == -ENODEV) +			clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);  		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);  		rt2x00lib_dmadone(entry);  	} -} -void rt2x00usb_kick_tx_queue(struct data_queue *queue) -{ -	rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, -				   rt2x00usb_kick_tx_entry); +	return false;  } -EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue); - -static void rt2x00usb_kill_tx_entry(struct queue_entry *entry) -{ -	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	struct queue_entry_priv_usb *entry_priv = entry->priv_data; -	struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; - -	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) -		return; - -	usb_kill_urb(entry_priv->urb); - -	/* -	 * Kill guardian urb (if required by driver). -	 */ -	if ((entry->queue->qid == QID_BEACON) && -	    (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) -		usb_kill_urb(bcn_priv->guardian_urb); -} - -void rt2x00usb_kill_tx_queue(struct data_queue *queue) -{ -	rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, -				   rt2x00usb_kill_tx_entry); -} -EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); - -static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) -{ -	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; -	unsigned short threshold = queue->threshold; - -	WARNING(queue->rt2x00dev, "TX queue %d DMA timed out," -		" invoke forced forced reset", queue->qid); - -	/* -	 * Temporarily disable the TX queue, this will force mac80211 -	 * to use the other queues until this queue has been restored. -	 * -	 * Set the queue threshold to the queue limit. This prevents the -	 * queue from being enabled during the txdone handler. -	 */ -	queue->threshold = queue->limit; -	ieee80211_stop_queue(rt2x00dev->hw, queue->qid); - -	/* -	 * Kill all entries in the queue, afterwards we need to -	 * wait a bit for all URBs to be cancelled. -	 */ -	rt2x00usb_kill_tx_queue(queue); - -	/* -	 * In case that a driver has overriden the txdone_work -	 * function, we invoke the TX done through there. -	 */ -	rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work); - -	/* -	 * The queue has been reset, and mac80211 is allowed to use the -	 * queue again. -	 */ -	queue->threshold = threshold; -	ieee80211_wake_queue(rt2x00dev->hw, queue->qid); -} - -static void rt2x00usb_watchdog_tx_status(struct data_queue *queue) -{ -	WARNING(queue->rt2x00dev, "TX queue %d status timed out," -		" invoke forced tx handler", queue->qid); - -	ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work); -} - -void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) -{ -	struct data_queue *queue; - -	tx_queue_for_each(rt2x00dev, queue) { -		if (!rt2x00queue_empty(queue)) { -			if (rt2x00queue_dma_timeout(queue)) -				rt2x00usb_watchdog_tx_dma(queue); -			if (rt2x00queue_status_timeout(queue)) -				rt2x00usb_watchdog_tx_status(queue); -		} -	} -} -EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);  /*   * RX data handlers. @@ -365,7 +348,8 @@ static void rt2x00usb_work_rxdone(struct work_struct *work)  	while (!rt2x00queue_empty(rt2x00dev->rx)) {  		entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); -		if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) +		if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || +		    !test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))  			break;  		/* @@ -378,7 +362,7 @@ static void rt2x00usb_work_rxdone(struct work_struct *work)  		/*  		 * Send the frame to rt2x00lib for further processing.  		 */ -		rt2x00lib_rxdone(entry); +		rt2x00lib_rxdone(entry, GFP_KERNEL);  	}  } @@ -407,9 +391,168 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)  	 * Schedule the delayed work for reading the RX status  	 * from the device.  	 */ -	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); +	queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);  } +static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void *data) +{ +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); +	struct queue_entry_priv_usb *entry_priv = entry->priv_data; +	int status; + +	if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || +	    test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) +		return false; + +	rt2x00lib_dmastart(entry); + +	usb_fill_bulk_urb(entry_priv->urb, usb_dev, +			  usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint), +			  entry->skb->data, entry->skb->len, +			  rt2x00usb_interrupt_rxdone, entry); + +	status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC); +	if (status) { +		if (status == -ENODEV) +			clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); +		set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); +		rt2x00lib_dmadone(entry); +	} + +	return false; +} + +void rt2x00usb_kick_queue(struct data_queue *queue) +{ +	switch (queue->qid) { +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		if (!rt2x00queue_empty(queue)) +			rt2x00queue_for_each_entry(queue, +						   Q_INDEX_DONE, +						   Q_INDEX, +						   NULL, +						   rt2x00usb_kick_tx_entry); +		break; +	case QID_RX: +		if (!rt2x00queue_full(queue)) +			rt2x00queue_for_each_entry(queue, +						   Q_INDEX, +						   Q_INDEX_DONE, +						   NULL, +						   rt2x00usb_kick_rx_entry); +		break; +	default: +		break; +	} +} +EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); + +static bool rt2x00usb_flush_entry(struct queue_entry *entry, void *data) +{ +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +	struct queue_entry_priv_usb *entry_priv = entry->priv_data; +	struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; + +	if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) +		return false; + +	usb_kill_urb(entry_priv->urb); + +	/* +	 * Kill guardian urb (if required by driver). +	 */ +	if ((entry->queue->qid == QID_BEACON) && +	    (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))) +		usb_kill_urb(bcn_priv->guardian_urb); + +	return false; +} + +void rt2x00usb_flush_queue(struct data_queue *queue, bool drop) +{ +	struct work_struct *completion; +	unsigned int i; + +	if (drop) +		rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, +					   rt2x00usb_flush_entry); + +	/* +	 * Obtain the queue completion handler +	 */ +	switch (queue->qid) { +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		completion = &queue->rt2x00dev->txdone_work; +		break; +	case QID_RX: +		completion = &queue->rt2x00dev->rxdone_work; +		break; +	default: +		return; +	} + +	for (i = 0; i < 10; i++) { +		/* +		 * Check if the driver is already done, otherwise we +		 * have to sleep a little while to give the driver/hw +		 * the oppurtunity to complete interrupt process itself. +		 */ +		if (rt2x00queue_empty(queue)) +			break; + +		/* +		 * Schedule the completion handler manually, when this +		 * worker function runs, it should cleanup the queue. +		 */ +		queue_work(queue->rt2x00dev->workqueue, completion); + +		/* +		 * Wait for a little while to give the driver +		 * the oppurtunity to recover itself. +		 */ +		msleep(10); +	} +} +EXPORT_SYMBOL_GPL(rt2x00usb_flush_queue); + +static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue) +{ +	rt2x00_warn(queue->rt2x00dev, "TX queue %d DMA timed out, invoke forced forced reset\n", +		    queue->qid); + +	rt2x00queue_stop_queue(queue); +	rt2x00queue_flush_queue(queue, true); +	rt2x00queue_start_queue(queue); +} + +static int rt2x00usb_dma_timeout(struct data_queue *queue) +{ +	struct queue_entry *entry; + +	entry = rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE); +	return rt2x00queue_dma_timeout(entry); +} + +void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) +{ +	struct data_queue *queue; + +	tx_queue_for_each(rt2x00dev, queue) { +		if (!rt2x00queue_empty(queue)) { +			if (rt2x00usb_dma_timeout(queue)) +				rt2x00usb_watchdog_tx_dma(queue); +		} +	} +} +EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); +  /*   * Radio handlers   */ @@ -417,12 +560,6 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)  {  	rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0,  				    REGISTER_TIMEOUT); - -	/* -	 * The USB version of kill_tx_queue also works -	 * on the RX queue. -	 */ -	rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev->rx);  }  EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); @@ -431,25 +568,10 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);   */  void rt2x00usb_clear_entry(struct queue_entry *entry)  { -	struct usb_device *usb_dev = -	    to_usb_device_intf(entry->queue->rt2x00dev->dev); -	struct queue_entry_priv_usb *entry_priv = entry->priv_data; -	int pipe; -  	entry->flags = 0; -	if (entry->queue->qid == QID_RX) { -		pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); -		usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, -				entry->skb->data, entry->skb->len, -				rt2x00usb_interrupt_rxdone, entry); - -		set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); -		if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) { -			set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); -			rt2x00lib_dmadone(entry); -		} -	} +	if (entry->queue->qid == QID_RX) +		rt2x00usb_kick_rx_entry(entry, NULL);  }  EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); @@ -506,7 +628,7 @@ static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)  	 * At least 1 endpoint for RX and 1 endpoint for TX must be available.  	 */  	if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) { -		ERROR(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n"); +		rt2x00_err(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");  		return -EPIPE;  	} @@ -543,7 +665,7 @@ static int rt2x00usb_alloc_entries(struct data_queue *queue)  	 * then we are done.  	 */  	if (queue->qid != QID_BEACON || -	    !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) +	    !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))  		return 0;  	for (i = 0; i < queue->limit; i++) { @@ -578,7 +700,7 @@ static void rt2x00usb_free_entries(struct data_queue *queue)  	 * then we are done.  	 */  	if (queue->qid != QID_BEACON || -	    !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) +	    !test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))  		return;  	for (i = 0; i < queue->limit; i++) { @@ -659,7 +781,7 @@ static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev)  	return 0;  exit: -	ERROR_PROBE("Failed to allocate registers.\n"); +	rt2x00_probe_err("Failed to allocate registers\n");  	rt2x00usb_free_reg(rt2x00dev); @@ -667,19 +789,19 @@ exit:  }  int rt2x00usb_probe(struct usb_interface *usb_intf, -		    const struct usb_device_id *id) +		    const struct rt2x00_ops *ops)  {  	struct usb_device *usb_dev = interface_to_usbdev(usb_intf); -	struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info;  	struct ieee80211_hw *hw;  	struct rt2x00_dev *rt2x00dev;  	int retval;  	usb_dev = usb_get_dev(usb_dev); +	usb_reset_device(usb_dev);  	hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);  	if (!hw) { -		ERROR_PROBE("Failed to allocate hardware.\n"); +		rt2x00_probe_err("Failed to allocate hardware\n");  		retval = -ENOMEM;  		goto exit_put_device;  	} @@ -695,6 +817,8 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,  	INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);  	INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone); +	hrtimer_init(&rt2x00dev->txstatus_timer, CLOCK_MONOTONIC, +		     HRTIMER_MODE_REL);  	retval = rt2x00usb_alloc_reg(rt2x00dev);  	if (retval) @@ -746,18 +870,8 @@ int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state)  {  	struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);  	struct rt2x00_dev *rt2x00dev = hw->priv; -	int retval; - -	retval = rt2x00lib_suspend(rt2x00dev, state); -	if (retval) -		return retval; -	/* -	 * Decrease usbdev refcount. -	 */ -	usb_put_dev(interface_to_usbdev(usb_intf)); - -	return 0; +	return rt2x00lib_suspend(rt2x00dev, state);  }  EXPORT_SYMBOL_GPL(rt2x00usb_suspend); @@ -766,8 +880,6 @@ int rt2x00usb_resume(struct usb_interface *usb_intf)  	struct ieee80211_hw *hw = usb_get_intfdata(usb_intf);  	struct rt2x00_dev *rt2x00dev = hw->priv; -	usb_get_dev(interface_to_usbdev(usb_intf)); -  	return rt2x00lib_resume(rt2x00dev);  }  EXPORT_SYMBOL_GPL(rt2x00usb_resume); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index c2d997f67b3..831b65f93fe 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -35,12 +33,6 @@  })  /* - * This variable should be used with the - * usb_driver structure initialization. - */ -#define USB_DEVICE_DATA(__ops)	.driver_info = (kernel_ulong_t)(__ops) - -/*   * 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 @@ -101,6 +93,7 @@ enum rt2x00usb_mode_offset {  	USB_MODE_SLEEP = 7,	/* RT73USB */  	USB_MODE_FIRMWARE = 8,	/* RT73USB */  	USB_MODE_WAKEUP = 9,	/* RT73USB */ +	USB_MODE_AUTORUN = 17, /* RT2800USB */  };  /** @@ -345,6 +338,23 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,  			   const struct rt2x00_field32 field,  			   u32 *reg); +/** + * rt2x00usb_register_read_async - Asynchronously read 32bit register word + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @offset: Register offset + * @callback: Functon to call when read completes. + * + * Submit a control URB to read a 32bit register. This safe to + * be called from atomic context.  The callback will be called + * when the URB completes. Otherwise the function is similar + * to rt2x00usb_register_read(). + * When the callback function returns false, the memory will be cleaned up, + * when it returns true, the urb will be fired again. + */ +void rt2x00usb_register_read_async(struct rt2x00_dev *rt2x00dev, +				   const unsigned int offset, +				   bool (*callback)(struct rt2x00_dev*, int, u32)); +  /*   * Radio handlers   */ @@ -378,29 +388,31 @@ struct queue_entry_priv_usb_bcn {  };  /** - * rt2x00usb_kick_tx_queue - Kick data queue + * rt2x00usb_kick_queue - Kick data queue   * @queue: Data queue to kick   *   * This will walk through all entries of the queue and push all pending   * frames to the hardware as a single burst.   */ -void rt2x00usb_kick_tx_queue(struct data_queue *queue); +void rt2x00usb_kick_queue(struct data_queue *queue);  /** - * rt2x00usb_kill_tx_queue - Kill data queue - * @queue: Data queue to kill + * rt2x00usb_flush_queue - Flush data queue + * @queue: Data queue to stop + * @drop: True to drop all pending frames.   * - * This will walk through all entries of the queue and kill all - * previously kicked frames before they can be send. + * This will walk through all entries of the queue and will optionally + * kill all URB's which were send to the device, or at least wait until + * they have been returned from the device..   */ -void rt2x00usb_kill_tx_queue(struct data_queue *queue); +void rt2x00usb_flush_queue(struct data_queue *queue, bool drop);  /**   * rt2x00usb_watchdog - Watchdog for USB communication   * @rt2x00dev: Pointer to &struct rt2x00_dev   *   * Check the health of the USB communication and determine - * if timeouts have occured. If this is the case, this function + * if timeouts have occurred. If this is the case, this function   * will reset all communication to restore functionality again.   */  void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev); @@ -416,7 +428,7 @@ 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 rt2x00_ops *ops);  void rt2x00usb_disconnect(struct usb_interface *usb_intf);  #ifdef CONFIG_PM  int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 6b09b01f634..9048a9cbe52 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -27,7 +25,6 @@  #include <linux/crc-itu-t.h>  #include <linux/delay.h>  #include <linux/etherdevice.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/slab.h> @@ -35,13 +32,14 @@  #include <linux/eeprom_93cx6.h>  #include "rt2x00.h" +#include "rt2x00mmio.h"  #include "rt2x00pci.h"  #include "rt61pci.h"  /*   * Allow hardware encryption to be disabled.   */ -static int modparam_nohwcrypt = 0; +static bool modparam_nohwcrypt = false;  module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);  MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -57,12 +55,12 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");   * and we will print an error.   */  #define WAIT_FOR_BBP(__dev, __reg) \ -	rt2x00pci_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) +	rt2x00mmio_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))  #define WAIT_FOR_RF(__dev, __reg) \ -	rt2x00pci_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) +	rt2x00mmio_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))  #define WAIT_FOR_MCU(__dev, __reg) \ -	rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \ -			       H2M_MAILBOX_CSR_OWNER, (__reg)) +	rt2x00mmio_regbusy_read((__dev), H2M_MAILBOX_CSR, \ +				H2M_MAILBOX_CSR_OWNER, (__reg))  static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,  			      const unsigned int word, const u8 value) @@ -82,7 +80,7 @@ static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);  		rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); -		rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); +		rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg);  	}  	mutex_unlock(&rt2x00dev->csr_mutex); @@ -109,7 +107,7 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, PHY_CSR3_BUSY, 1);  		rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); -		rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); +		rt2x00mmio_register_write(rt2x00dev, PHY_CSR3, reg);  		WAIT_FOR_BBP(rt2x00dev, ®);  	} @@ -137,7 +135,7 @@ static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0);  		rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); -		rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg); +		rt2x00mmio_register_write(rt2x00dev, PHY_CSR4, reg);  		rt2x00_rf_write(rt2x00dev, word, value);  	} @@ -161,12 +159,12 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token);  		rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0);  		rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); -		rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); +		rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); -		rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, ®); +		rt2x00mmio_register_read(rt2x00dev, HOST_CMD_CSR, ®);  		rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command);  		rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1); -		rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); +		rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, reg);  	}  	mutex_unlock(&rt2x00dev->csr_mutex); @@ -178,7 +176,7 @@ static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom)  	struct rt2x00_dev *rt2x00dev = eeprom->data;  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); +	rt2x00mmio_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); @@ -200,15 +198,15 @@ static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom)  	rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT,  			   !!eeprom->reg_chip_select); -	rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, E2PROM_CSR, reg);  }  #ifdef CONFIG_RT2X00_LIB_DEBUGFS  static const struct rt2x00debug rt61pci_rt2x00debug = {  	.owner	= THIS_MODULE,  	.csr	= { -		.read		= rt2x00pci_register_read, -		.write		= rt2x00pci_register_write, +		.read		= rt2x00mmio_register_read, +		.write		= rt2x00mmio_register_write,  		.flags		= RT2X00DEBUGFS_OFFSET,  		.word_base	= CSR_REG_BASE,  		.word_size	= sizeof(u32), @@ -242,8 +240,8 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); -	return rt2x00_get_field32(reg, MAC_CSR13_BIT5); +	rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, ®); +	return rt2x00_get_field32(reg, MAC_CSR13_VAL5);  }  #ifdef CONFIG_RT2X00_LIB_LEDS @@ -293,10 +291,10 @@ static int rt61pci_blink_set(struct led_classdev *led_cdev,  	    container_of(led_cdev, struct rt2x00_led, led_dev);  	u32 reg; -	rt2x00pci_register_read(led->rt2x00dev, MAC_CSR14, ®); +	rt2x00mmio_register_read(led->rt2x00dev, MAC_CSR14, ®);  	rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on);  	rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off); -	rt2x00pci_register_write(led->rt2x00dev, MAC_CSR14, reg); +	rt2x00mmio_register_write(led->rt2x00dev, MAC_CSR14, reg);  	return 0;  } @@ -338,7 +336,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,  		 */  		mask = (0xf << crypto->bssidx); -		rt2x00pci_register_read(rt2x00dev, SEC_CSR0, ®); +		rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, ®);  		reg &= mask;  		if (reg && reg == mask) @@ -357,8 +355,8 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,  		       sizeof(key_entry.rx_mic));  		reg = SHARED_KEY_ENTRY(key->hw_key_idx); -		rt2x00pci_register_multiwrite(rt2x00dev, reg, -					      &key_entry, sizeof(key_entry)); +		rt2x00mmio_register_multiwrite(rt2x00dev, reg, +					       &key_entry, sizeof(key_entry));  		/*  		 * The cipher types are stored over 2 registers. @@ -371,16 +369,16 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,  			field.bit_offset = (3 * key->hw_key_idx);  			field.bit_mask = 0x7 << field.bit_offset; -			rt2x00pci_register_read(rt2x00dev, SEC_CSR1, ®); +			rt2x00mmio_register_read(rt2x00dev, SEC_CSR1, ®);  			rt2x00_set_field32(®, field, crypto->cipher); -			rt2x00pci_register_write(rt2x00dev, SEC_CSR1, reg); +			rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, reg);  		} else {  			field.bit_offset = (3 * (key->hw_key_idx - 8));  			field.bit_mask = 0x7 << field.bit_offset; -			rt2x00pci_register_read(rt2x00dev, SEC_CSR5, ®); +			rt2x00mmio_register_read(rt2x00dev, SEC_CSR5, ®);  			rt2x00_set_field32(®, field, crypto->cipher); -			rt2x00pci_register_write(rt2x00dev, SEC_CSR5, reg); +			rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, reg);  		}  		/* @@ -403,12 +401,12 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,  	 */  	mask = 1 << key->hw_key_idx; -	rt2x00pci_register_read(rt2x00dev, SEC_CSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, SEC_CSR0, ®);  	if (crypto->cmd == SET_KEY)  		reg |= mask;  	else if (crypto->cmd == DISABLE_KEY)  		reg &= ~mask; -	rt2x00pci_register_write(rt2x00dev, SEC_CSR0, reg); +	rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, reg);  	return 0;  } @@ -432,10 +430,10 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,  		 * When both registers are full, we drop the key.  		 * Otherwise, we use the first invalid entry.  		 */ -		rt2x00pci_register_read(rt2x00dev, SEC_CSR2, ®); +		rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, ®);  		if (reg && reg == ~0) {  			key->hw_key_idx = 32; -			rt2x00pci_register_read(rt2x00dev, SEC_CSR3, ®); +			rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, ®);  			if (reg && reg == ~0)  				return -ENOSPC;  		} @@ -457,21 +455,21 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,  		addr_entry.cipher = crypto->cipher;  		reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx); -		rt2x00pci_register_multiwrite(rt2x00dev, reg, -					      &key_entry, sizeof(key_entry)); +		rt2x00mmio_register_multiwrite(rt2x00dev, reg, +					       &key_entry, sizeof(key_entry));  		reg = PAIRWISE_TA_ENTRY(key->hw_key_idx); -		rt2x00pci_register_multiwrite(rt2x00dev, reg, -					      &addr_entry, sizeof(addr_entry)); +		rt2x00mmio_register_multiwrite(rt2x00dev, reg, +					       &addr_entry, sizeof(addr_entry));  		/*  		 * Enable pairwise lookup table for given BSS idx.  		 * Without this, received frames will not be decrypted  		 * by the hardware.  		 */ -		rt2x00pci_register_read(rt2x00dev, SEC_CSR4, ®); +		rt2x00mmio_register_read(rt2x00dev, SEC_CSR4, ®);  		reg |= (1 << crypto->bssidx); -		rt2x00pci_register_write(rt2x00dev, SEC_CSR4, reg); +		rt2x00mmio_register_write(rt2x00dev, SEC_CSR4, reg);  		/*  		 * The driver does not support the IV/EIV generation @@ -494,21 +492,21 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,  	if (key->hw_key_idx < 32) {  		mask = 1 << key->hw_key_idx; -		rt2x00pci_register_read(rt2x00dev, SEC_CSR2, ®); +		rt2x00mmio_register_read(rt2x00dev, SEC_CSR2, ®);  		if (crypto->cmd == SET_KEY)  			reg |= mask;  		else if (crypto->cmd == DISABLE_KEY)  			reg &= ~mask; -		rt2x00pci_register_write(rt2x00dev, SEC_CSR2, reg); +		rt2x00mmio_register_write(rt2x00dev, SEC_CSR2, reg);  	} else {  		mask = 1 << (key->hw_key_idx - 32); -		rt2x00pci_register_read(rt2x00dev, SEC_CSR3, ®); +		rt2x00mmio_register_read(rt2x00dev, SEC_CSR3, ®);  		if (crypto->cmd == SET_KEY)  			reg |= mask;  		else if (crypto->cmd == DISABLE_KEY)  			reg &= ~mask; -		rt2x00pci_register_write(rt2x00dev, SEC_CSR3, reg); +		rt2x00mmio_register_write(rt2x00dev, SEC_CSR3, reg);  	}  	return 0; @@ -525,7 +523,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,  	 * and broadcast frames will always be accepted since  	 * there is no filter for it at this time.  	 */ -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, ®);  	rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC,  			   !(filter_flags & FIF_FCSFAIL));  	rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, @@ -543,7 +541,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0);  	rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS,  			   !(filter_flags & FIF_CONTROL)); -	rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);  }  static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, @@ -551,27 +549,15 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,  				struct rt2x00intf_conf *conf,  				const unsigned int flags)  { -	unsigned int beacon_base;  	u32 reg;  	if (flags & CONFIG_UPDATE_TYPE) {  		/* -		 * 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. -		 */ -		beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); -		rt2x00pci_register_write(rt2x00dev, beacon_base, 0); - -		/*  		 * Enable synchronisation.  		 */ -		rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); -		rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); +		rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®);  		rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); -		rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); -		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); +		rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);  	}  	if (flags & CONFIG_UPDATE_MAC) { @@ -579,8 +565,8 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);  		conf->mac[1] = cpu_to_le32(reg); -		rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, -					      conf->mac, sizeof(conf->mac)); +		rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR2, +					       conf->mac, sizeof(conf->mac));  	}  	if (flags & CONFIG_UPDATE_BSSID) { @@ -588,8 +574,9 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,  		rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3);  		conf->bssid[1] = cpu_to_le32(reg); -		rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, -					      conf->bssid, sizeof(conf->bssid)); +		rt2x00mmio_register_multiwrite(rt2x00dev, MAC_CSR4, +					       conf->bssid, +					       sizeof(conf->bssid));  	}  } @@ -599,40 +586,40 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,  {  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, ®);  	rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32);  	rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); -	rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg);  	if (changed & BSS_CHANGED_ERP_PREAMBLE) { -		rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); +		rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, ®);  		rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1);  		rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE,  				   !!erp->short_preamble); -		rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); +		rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg);  	}  	if (changed & BSS_CHANGED_BASIC_RATES) -		rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, -					 erp->basic_rates); +		rt2x00mmio_register_write(rt2x00dev, TXRX_CSR5, +					  erp->basic_rates);  	if (changed & BSS_CHANGED_BEACON_INT) { -		rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); +		rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®);  		rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL,  				   erp->beacon_int * 16); -		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); +		rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);  	}  	if (changed & BSS_CHANGED_ERP_SLOT) { -		rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); +		rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, ®);  		rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); -		rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); +		rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg); -		rt2x00pci_register_read(rt2x00dev, MAC_CSR8, ®); +		rt2x00mmio_register_read(rt2x00dev, MAC_CSR8, ®);  		rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs);  		rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);  		rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); -		rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg); +		rt2x00mmio_register_write(rt2x00dev, MAC_CSR8, reg);  	}  } @@ -695,7 +682,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529));  	rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, -			  !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); +			  !rt2x00_has_cap_frame_type(rt2x00dev));  	/*  	 * Configure the RX antenna. @@ -725,15 +712,15 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,  {  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); +	rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, ®); -	rt2x00_set_field32(®, MAC_CSR13_BIT4, p1); -	rt2x00_set_field32(®, MAC_CSR13_BIT12, 0); +	rt2x00_set_field32(®, MAC_CSR13_DIR4, 0); +	rt2x00_set_field32(®, MAC_CSR13_VAL4, p1); -	rt2x00_set_field32(®, MAC_CSR13_BIT3, !p2); -	rt2x00_set_field32(®, MAC_CSR13_BIT11, 0); +	rt2x00_set_field32(®, MAC_CSR13_DIR3, 0); +	rt2x00_set_field32(®, MAC_CSR13_VAL3, !p2); -	rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg);  }  static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev, @@ -823,30 +810,30 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,  	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {  		sel = antenna_sel_a; -		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); +		lna = rt2x00_has_cap_external_lna_a(rt2x00dev);  	} else {  		sel = antenna_sel_bg; -		lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); +		lna = rt2x00_has_cap_external_lna_bg(rt2x00dev);  	}  	for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)  		rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); -	rt2x00pci_register_read(rt2x00dev, PHY_CSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, PHY_CSR0, ®);  	rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG,  			   rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);  	rt2x00_set_field32(®, PHY_CSR0_PA_PE_A,  			   rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); -	rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); +	rt2x00mmio_register_write(rt2x00dev, PHY_CSR0, reg);  	if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325))  		rt61pci_config_antenna_5x(rt2x00dev, ant);  	else if (rt2x00_rf(rt2x00dev, RF2527))  		rt61pci_config_antenna_2x(rt2x00dev, ant);  	else if (rt2x00_rf(rt2x00dev, RF2529)) { -		if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) +		if (rt2x00_has_cap_double_antenna(rt2x00dev))  			rt61pci_config_antenna_2x(rt2x00dev, ant);  		else  			rt61pci_config_antenna_2529(rt2x00dev, ant); @@ -859,14 +846,14 @@ static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,  	u16 eeprom;  	short lna_gain = 0; -	if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) { -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) +	if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { +		if (rt2x00_has_cap_external_lna_bg(rt2x00dev))  			lna_gain += 14;  		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);  		lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);  	} else { -		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) +		if (rt2x00_has_cap_external_lna_a(rt2x00dev))  			lna_gain += 14;  		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); @@ -939,7 +926,7 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,  {  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); +	rt2x00mmio_register_read(rt2x00dev, TXRX_CSR4, ®);  	rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_DOWN, 1);  	rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_RATE_STEP, 0);  	rt2x00_set_field32(®, TXRX_CSR4_OFDM_TX_FALLBACK_CCK, 0); @@ -947,7 +934,7 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,  			   libconf->conf->long_frame_max_tx_count);  	rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT,  			   libconf->conf->short_frame_max_tx_count); -	rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR4, reg);  }  static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev, @@ -959,7 +946,7 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,  	u32 reg;  	if (state == STATE_SLEEP) { -		rt2x00pci_register_read(rt2x00dev, MAC_CSR11, ®); +		rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, ®);  		rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN,  				   rt2x00dev->beacon_int - 10);  		rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, @@ -968,27 +955,29 @@ static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,  		/* We must first disable autowake before it can be enabled */  		rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); -		rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); +		rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg);  		rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 1); -		rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); +		rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg); -		rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000005); -		rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c); -		rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060); +		rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR, +					  0x00000005); +		rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c); +		rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060);  		rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0);  	} else { -		rt2x00pci_register_read(rt2x00dev, MAC_CSR11, ®); +		rt2x00mmio_register_read(rt2x00dev, MAC_CSR11, ®);  		rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0);  		rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0);  		rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0);  		rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); -		rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); +		rt2x00mmio_register_write(rt2x00dev, MAC_CSR11, reg); -		rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007); -		rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018); -		rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020); +		rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR, +					  0x00000007); +		rt2x00mmio_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018); +		rt2x00mmio_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020);  		rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);  	} @@ -1024,13 +1013,13 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,  	/*  	 * Update FCS error count from register.  	 */ -	rt2x00pci_register_read(rt2x00dev, STA_CSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, STA_CSR0, ®);  	qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);  	/*  	 * Update False CCA count from register.  	 */ -	rt2x00pci_register_read(rt2x00dev, STA_CSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, STA_CSR1, ®);  	qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);  } @@ -1062,14 +1051,14 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev,  	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {  		low_bound = 0x28;  		up_bound = 0x48; -		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { +		if (rt2x00_has_cap_external_lna_a(rt2x00dev)) {  			low_bound += 0x10;  			up_bound += 0x10;  		}  	} else {  		low_bound = 0x20;  		up_bound = 0x40; -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { +		if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {  			low_bound += 0x10;  			up_bound += 0x10;  		} @@ -1140,6 +1129,111 @@ dynamic_cca_tune:  }  /* + * Queue handlers. + */ +static void rt61pci_start_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_RX: +		rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, ®); +		rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); +		rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg); +		break; +	case QID_BEACON: +		rt2x00mmio_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, 1); +		rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); +		break; +	default: +		break; +	} +} + +static void rt61pci_kick_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_AC_VO: +		rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); +		rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, 1); +		rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); +		break; +	case QID_AC_VI: +		rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); +		rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, 1); +		rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); +		break; +	case QID_AC_BE: +		rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); +		rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, 1); +		rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); +		break; +	case QID_AC_BK: +		rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); +		rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, 1); +		rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); +		break; +	default: +		break; +	} +} + +static void rt61pci_stop_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_AC_VO: +		rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); +		rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, 1); +		rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); +		break; +	case QID_AC_VI: +		rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); +		rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, 1); +		rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); +		break; +	case QID_AC_BE: +		rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); +		rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, 1); +		rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); +		break; +	case QID_AC_BK: +		rt2x00mmio_register_read(rt2x00dev, TX_CNTL_CSR, ®); +		rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, 1); +		rt2x00mmio_register_write(rt2x00dev, TX_CNTL_CSR, reg); +		break; +	case QID_RX: +		rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, ®); +		rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); +		rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg); +		break; +	case QID_BEACON: +		rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®); +		rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); +		rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); +		rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); +		rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); + +		/* +		 * Wait for possibly running tbtt tasklets. +		 */ +		tasklet_kill(&rt2x00dev->tbtt_tasklet); +		break; +	default: +		break; +	} +} + +/*   * Firmware functions   */  static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) @@ -1205,14 +1299,14 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,  	 * Wait for stable hardware.  	 */  	for (i = 0; i < 100; i++) { -		rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); +		rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, ®);  		if (reg)  			break;  		msleep(1);  	}  	if (!reg) { -		ERROR(rt2x00dev, "Unstable hardware.\n"); +		rt2x00_err(rt2x00dev, "Unstable hardware\n");  		return -EBUSY;  	} @@ -1221,10 +1315,10 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,  	 */  	reg = 0;  	rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 1); -	rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); -	rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); -	rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); -	rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, 0); +	rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); +	rt2x00mmio_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); +	rt2x00mmio_register_write(rt2x00dev, HOST_CMD_CSR, 0);  	/*  	 * Write firmware to device. @@ -1232,26 +1326,26 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,  	reg = 0;  	rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 1);  	rt2x00_set_field32(®, MCU_CNTL_CSR_SELECT_BANK, 1); -	rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg); -	rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, -				      data, len); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);  	rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 0); -	rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, MCU_CNTL_CSR, reg);  	for (i = 0; i < 100; i++) { -		rt2x00pci_register_read(rt2x00dev, MCU_CNTL_CSR, ®); +		rt2x00mmio_register_read(rt2x00dev, MCU_CNTL_CSR, ®);  		if (rt2x00_get_field32(reg, MCU_CNTL_CSR_READY))  			break;  		msleep(1);  	}  	if (i == 100) { -		ERROR(rt2x00dev, "MCU Control register not ready.\n"); +		rt2x00_err(rt2x00dev, "MCU Control register not ready\n");  		return -EBUSY;  	} @@ -1266,16 +1360,16 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,  	reg = 0;  	rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1);  	rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); -	rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg); -	rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, ®);  	rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0);  	rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); -	rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg); -	rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, ®);  	rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); -	rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);  	return 0;  } @@ -1285,7 +1379,7 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev,   */  static bool rt61pci_get_entry_state(struct queue_entry *entry)  { -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	u32 word;  	if (entry->queue->qid == QID_RX) { @@ -1302,7 +1396,7 @@ static bool rt61pci_get_entry_state(struct queue_entry *entry)  static void rt61pci_clear_entry(struct queue_entry *entry)  { -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);  	u32 word; @@ -1325,13 +1419,13 @@ static void rt61pci_clear_entry(struct queue_entry *entry)  static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)  { -	struct queue_entry_priv_pci *entry_priv; +	struct queue_entry_priv_mmio *entry_priv;  	u32 reg;  	/*  	 * Initialize registers.  	 */ -	rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR0, ®);  	rt2x00_set_field32(®, TX_RING_CSR0_AC0_RING_SIZE,  			   rt2x00dev->tx[0].limit);  	rt2x00_set_field32(®, TX_RING_CSR0_AC1_RING_SIZE, @@ -1340,67 +1434,67 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)  			   rt2x00dev->tx[2].limit);  	rt2x00_set_field32(®, TX_RING_CSR0_AC3_RING_SIZE,  			   rt2x00dev->tx[3].limit); -	rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg); +	rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR0, reg); -	rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, TX_RING_CSR1, ®);  	rt2x00_set_field32(®, TX_RING_CSR1_TXD_SIZE,  			   rt2x00dev->tx[0].desc_size / 4); -	rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, TX_RING_CSR1, reg);  	entry_priv = rt2x00dev->tx[0].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, AC0_BASE_CSR, ®);  	rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, AC0_BASE_CSR, reg);  	entry_priv = rt2x00dev->tx[1].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, AC1_BASE_CSR, ®);  	rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, AC1_BASE_CSR, reg);  	entry_priv = rt2x00dev->tx[2].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, AC2_BASE_CSR, ®);  	rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, AC2_BASE_CSR, reg);  	entry_priv = rt2x00dev->tx[3].entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, AC3_BASE_CSR, ®);  	rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, AC3_BASE_CSR, reg); -	rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, RX_RING_CSR, ®);  	rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit);  	rt2x00_set_field32(®, RX_RING_CSR_RXD_SIZE,  			   rt2x00dev->rx->desc_size / 4);  	rt2x00_set_field32(®, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4); -	rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, RX_RING_CSR, reg);  	entry_priv = rt2x00dev->rx->entries[0].priv_data; -	rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, RX_BASE_CSR, ®);  	rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER,  			   entry_priv->desc_dma); -	rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, RX_BASE_CSR, reg); -	rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, ®); +	rt2x00mmio_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); -	rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, TX_DMA_DST_CSR, reg); -	rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, ®); +	rt2x00mmio_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); -	rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg); -	rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, ®);  	rt2x00_set_field32(®, RX_CNTL_CSR_LOAD_RXD, 1); -	rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);  	return 0;  } @@ -1409,13 +1503,13 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)  {  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, TXRX_CSR0, ®);  	rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 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); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR0, reg); -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR1, ®); +	rt2x00mmio_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 */ @@ -1424,12 +1518,12 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)  	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); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR1, reg);  	/*  	 * CCK TXD BBP registers  	 */ -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR2, ®); +	rt2x00mmio_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); @@ -1438,76 +1532,76 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)  	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); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR2, reg);  	/*  	 * OFDM TXD BBP registers  	 */ -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR3, ®); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR3, reg); -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR7, ®); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR7, reg); -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR8, ®); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR8, reg); -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); +	rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®);  	rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, 0);  	rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0);  	rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 0);  	rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0);  	rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);  	rt2x00_set_field32(®, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0); -	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); -	rt2x00pci_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); -	rt2x00pci_register_write(rt2x00dev, MAC_CSR6, 0x00000fff); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR6, 0x00000fff); -	rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); +	rt2x00mmio_register_read(rt2x00dev, MAC_CSR9, ®);  	rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); -	rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR9, reg); -	rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x0000071c); +	rt2x00mmio_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); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, SEC_CSR0, 0x00000000); +	rt2x00mmio_register_write(rt2x00dev, SEC_CSR1, 0x00000000); +	rt2x00mmio_register_write(rt2x00dev, SEC_CSR5, 0x00000000); -	rt2x00pci_register_write(rt2x00dev, PHY_CSR1, 0x000023b0); -	rt2x00pci_register_write(rt2x00dev, PHY_CSR5, 0x060a100c); -	rt2x00pci_register_write(rt2x00dev, PHY_CSR6, 0x00080606); -	rt2x00pci_register_write(rt2x00dev, PHY_CSR7, 0x00000a08); +	rt2x00mmio_register_write(rt2x00dev, PHY_CSR1, 0x000023b0); +	rt2x00mmio_register_write(rt2x00dev, PHY_CSR5, 0x060a100c); +	rt2x00mmio_register_write(rt2x00dev, PHY_CSR6, 0x00080606); +	rt2x00mmio_register_write(rt2x00dev, PHY_CSR7, 0x00000a08); -	rt2x00pci_register_write(rt2x00dev, PCI_CFG_CSR, 0x28ca4404); +	rt2x00mmio_register_write(rt2x00dev, PCI_CFG_CSR, 0x28ca4404); -	rt2x00pci_register_write(rt2x00dev, TEST_MODE_CSR, 0x00000200); +	rt2x00mmio_register_write(rt2x00dev, TEST_MODE_CSR, 0x00000200); -	rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); +	rt2x00mmio_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff);  	/*  	 * Clear all beacons @@ -1515,36 +1609,36 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)  	 * the first byte since that byte contains the VALID and OWNER  	 * bits which (when set to 0) will invalidate the entire beacon.  	 */ -	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); +	rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE0, 0); +	rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE1, 0); +	rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE2, 0); +	rt2x00mmio_register_write(rt2x00dev, HW_BEACON_BASE3, 0);  	/*  	 * We must clear the error counters.  	 * These registers are cleared on read,  	 * so we may pass a useless variable to store the value.  	 */ -	rt2x00pci_register_read(rt2x00dev, STA_CSR0, ®); -	rt2x00pci_register_read(rt2x00dev, STA_CSR1, ®); -	rt2x00pci_register_read(rt2x00dev, STA_CSR2, ®); +	rt2x00mmio_register_read(rt2x00dev, STA_CSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, STA_CSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, STA_CSR2, ®);  	/*  	 * Reset MAC and BBP registers.  	 */ -	rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); +	rt2x00mmio_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); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg); -	rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, ®);  	rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0);  	rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); -	rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg); -	rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); +	rt2x00mmio_register_read(rt2x00dev, MAC_CSR1, ®);  	rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); -	rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR1, reg);  	return 0;  } @@ -1561,7 +1655,7 @@ static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)  		udelay(REGISTER_BUSY_DELAY);  	} -	ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); +	rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");  	return -EACCES;  } @@ -1616,49 +1710,40 @@ static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)  /*   * Device state switch handlers.   */ -static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev, -			      enum dev_state state) -{ -	u32 reg; - -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); -	rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, -			   (state == STATE_RADIO_RX_OFF)); -	rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); -} -  static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,  			       enum dev_state state)  { -	int mask = (state == STATE_RADIO_IRQ_OFF) || -		   (state == STATE_RADIO_IRQ_OFF_ISR); +	int mask = (state == STATE_RADIO_IRQ_OFF);  	u32 reg; +	unsigned long flags;  	/*  	 * When interrupts are being enabled, the interrupt registers  	 * should clear the register to assure a clean state.  	 */  	if (state == STATE_RADIO_IRQ_ON) { -		rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); -		rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); +		rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); +		rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg); -		rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®); -		rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg); +		rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®); +		rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);  	}  	/*  	 * Only toggle the interrupts bits we are going to use.  	 * Non-checked interrupt bits are disabled by default.  	 */ -	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); +	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); + +	rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®);  	rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, mask);  	rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, mask);  	rt2x00_set_field32(®, INT_MASK_CSR_BEACON_DONE, 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); +	rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); -	rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®);  	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); @@ -1668,7 +1753,19 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,  	rt2x00_set_field32(®, MCU_INT_MASK_CSR_6, mask);  	rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, mask);  	rt2x00_set_field32(®, MCU_INT_MASK_CSR_TWAKEUP, mask); -	rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); + +	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags); + +	if (state == STATE_RADIO_IRQ_OFF) { +		/* +		 * Ensure that all tasklets are finished. +		 */ +		tasklet_kill(&rt2x00dev->txstatus_tasklet); +		tasklet_kill(&rt2x00dev->rxdone_tasklet); +		tasklet_kill(&rt2x00dev->autowake_tasklet); +		tasklet_kill(&rt2x00dev->tbtt_tasklet); +	}  }  static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) @@ -1686,9 +1783,9 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)  	/*  	 * Enable RX.  	 */ -	rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, RX_CNTL_CSR, ®);  	rt2x00_set_field32(®, RX_CNTL_CSR_ENABLE_RX_DMA, 1); -	rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, RX_CNTL_CSR, reg);  	return 0;  } @@ -1698,7 +1795,7 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev)  	/*  	 * Disable power  	 */ -	rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR10, 0x00001818);  }  static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) @@ -1709,10 +1806,10 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)  	put_to_sleep = (state != STATE_AWAKE); -	rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®); +	rt2x00mmio_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); -	rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);  	/*  	 * Device is not guaranteed to be in the requested state yet. @@ -1720,11 +1817,11 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)  	 * device has entered the correct state.  	 */  	for (i = 0; i < REGISTER_BUSY_COUNT; i++) { -		rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®2); +		rt2x00mmio_register_read(rt2x00dev, MAC_CSR12, ®2);  		state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE);  		if (state == !put_to_sleep)  			return 0; -		rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg); +		rt2x00mmio_register_write(rt2x00dev, MAC_CSR12, reg);  		msleep(10);  	} @@ -1743,14 +1840,8 @@ static int rt61pci_set_device_state(struct rt2x00_dev *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); -		break;  	case STATE_RADIO_IRQ_ON: -	case STATE_RADIO_IRQ_ON_ISR:  	case STATE_RADIO_IRQ_OFF: -	case STATE_RADIO_IRQ_OFF_ISR:  		rt61pci_toggle_irq(rt2x00dev, state);  		break;  	case STATE_DEEP_SLEEP: @@ -1765,8 +1856,8 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,  	}  	if (unlikely(retval)) -		ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", -		      state, retval); +		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", +			   state, retval);  	return retval;  } @@ -1778,7 +1869,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,  				  struct txentry_desc *txdesc)  {  	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	__le32 *txd = entry_priv->desc;  	u32 word; @@ -1797,10 +1888,12 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,  	rt2x00_desc_write(txd, 1, word);  	rt2x00_desc_read(txd, 2, &word); -	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); -	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); -	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); -	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); +	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal); +	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service); +	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, +			   txdesc->u.plcp.length_low); +	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, +			   txdesc->u.plcp.length_high);  	rt2x00_desc_write(txd, 2, word);  	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { @@ -1845,7 +1938,7 @@ static void rt61pci_write_tx_desc(struct queue_entry *entry,  			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));  	rt2x00_set_field32(&word, TXD_W0_OFDM,  			   (txdesc->rate_mode == RATE_MODE_OFDM)); -	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); +	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);  	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,  			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));  	rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, @@ -1874,17 +1967,19 @@ static void rt61pci_write_beacon(struct queue_entry *entry,  				 struct txentry_desc *txdesc)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	unsigned int beacon_base; -	u32 reg; +	unsigned int padding_len; +	u32 orig_reg, reg;  	/*  	 * Disable beaconing while we are reloading the beacon data,  	 * otherwise we might be sending out invalid data.  	 */ -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); +	rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, ®); +	orig_reg = reg;  	rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); -	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);  	/*  	 * Write the TX descriptor for the beacon. @@ -1897,13 +1992,23 @@ static void rt61pci_write_beacon(struct queue_entry *entry,  	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);  	/* -	 * Write entire beacon with descriptor to register. +	 * Write entire beacon with descriptor and padding to register.  	 */ +	padding_len = roundup(entry->skb->len, 4) - entry->skb->len; +	if (padding_len && skb_pad(entry->skb, padding_len)) { +		rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n"); +		/* skb freed by skb_pad() on failure */ +		entry->skb = NULL; +		rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, orig_reg); +		return; +	} +  	beacon_base = HW_BEACON_OFFSET(entry->entry_idx); -	rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, -				      entry_priv->desc, TXINFO_SIZE); -	rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE, -				      entry->skb->data, entry->skb->len); +	rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base, +				       entry_priv->desc, TXINFO_SIZE); +	rt2x00mmio_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE, +				       entry->skb->data, +				       entry->skb->len + padding_len);  	/*  	 * Enable beaconing again. @@ -1911,12 +2016,10 @@ static void rt61pci_write_beacon(struct queue_entry *entry,  	 * For Wi-Fi faily generated beacons between participating  	 * stations. Set TBTT phase adaptive adjustment step to 8us.  	 */ -	rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); -	rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); -	rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);  	rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); -	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg);  	/*  	 * Clean up beacon skb. @@ -1925,35 +2028,30 @@ static void rt61pci_write_beacon(struct queue_entry *entry,  	entry->skb = NULL;  } -static void rt61pci_kick_tx_queue(struct data_queue *queue) +static void rt61pci_clear_beacon(struct queue_entry *entry)  { -	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; -	u32 reg; - -	rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); -	rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, (queue->qid == QID_AC_BE)); -	rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, (queue->qid == QID_AC_BK)); -	rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, (queue->qid == QID_AC_VI)); -	rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, (queue->qid == QID_AC_VO)); -	rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); -} +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +	u32 orig_reg, reg; -static void rt61pci_kill_tx_queue(struct data_queue *queue) -{ -	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; -	u32 reg; +	/* +	 * Disable beaconing while we are reloading the beacon data, +	 * otherwise we might be sending out invalid data. +	 */ +	rt2x00mmio_register_read(rt2x00dev, TXRX_CSR9, &orig_reg); +	reg = orig_reg; +	rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, reg); -	if (queue->qid == QID_BEACON) { -		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); -		return; -	} +	/* +	 * Clear beacon. +	 */ +	rt2x00mmio_register_write(rt2x00dev, +				  HW_BEACON_OFFSET(entry->entry_idx), 0); -	rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); -	rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, (queue->qid == QID_AC_BE)); -	rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, (queue->qid == QID_AC_BK)); -	rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, (queue->qid == QID_AC_VI)); -	rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, (queue->qid == QID_AC_VO)); -	rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); +	/* +	 * Restore global beaconing state. +	 */ +	rt2x00mmio_register_write(rt2x00dev, TXRX_CSR9, orig_reg);  }  /* @@ -1991,7 +2089,7 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,  				struct rxdone_entry_desc *rxdesc)  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; -	struct queue_entry_priv_pci *entry_priv = entry->priv_data; +	struct queue_entry_priv_mmio *entry_priv = entry->priv_data;  	u32 word0;  	u32 word1; @@ -2020,9 +2118,8 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,  		rxdesc->flags |= RX_FLAG_IV_STRIPPED;  		/* -		 * FIXME: Legacy driver indicates that the frame does -		 * contain the Michael Mic. Unfortunately, in rt2x00 -		 * the MIC seems to be missing completely... +		 * The hardware has already checked the Michael Mic and has +		 * stripped it from the frame. Signal this to mac80211.  		 */  		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; @@ -2058,7 +2155,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)  	struct data_queue *queue;  	struct queue_entry *entry;  	struct queue_entry *entry_done; -	struct queue_entry_priv_pci *entry_priv; +	struct queue_entry_priv_mmio *entry_priv;  	struct txdone_entry_desc txdesc;  	u32 word;  	u32 reg; @@ -2075,8 +2172,8 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)  	 * that the TX_STA_FIFO stack has a size of 16. We stick to our  	 * tx ring size for now.  	 */ -	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) { -		rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); +	for (i = 0; i < rt2x00dev->tx->limit; i++) { +		rt2x00mmio_register_read(rt2x00dev, STA_CSR4, ®);  		if (!rt2x00_get_field32(reg, STA_CSR4_VALID))  			break; @@ -2085,7 +2182,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)  		 * queue identication number.  		 */  		type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE); -		queue = rt2x00queue_get_queue(rt2x00dev, type); +		queue = rt2x00queue_get_tx_queue(rt2x00dev, type);  		if (unlikely(!queue))  			continue; @@ -2110,9 +2207,8 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)  			/* Catch up.  			 * Just report any entries we missed as failed.  			 */ -			WARNING(rt2x00dev, -				"TX status report missed for entry %d\n", -				entry_done->entry_idx); +			rt2x00_warn(rt2x00dev, "TX status report missed for entry %d\n", +				    entry_done->entry_idx);  			rt2x00lib_txdone_noinfo(entry_done, TXDONE_UNKNOWN);  			entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); @@ -2147,77 +2243,97 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)  static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev)  { -	struct ieee80211_conf conf = { .flags = 0 }; -	struct rt2x00lib_conf libconf = { .conf = &conf }; +	struct rt2x00lib_conf libconf = { .conf = &rt2x00dev->hw->conf };  	rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);  } -static irqreturn_t rt61pci_interrupt_thread(int irq, void *dev_instance) +static inline void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev, +					    struct rt2x00_field32 irq_field)  { -	struct rt2x00_dev *rt2x00dev = dev_instance; -	u32 reg = rt2x00dev->irqvalue[0]; -	u32 reg_mcu = rt2x00dev->irqvalue[1]; +	u32 reg;  	/* -	 * Handle interrupts, walk through all bits -	 * and run the tasks, the bits are checked in order of -	 * priority. +	 * Enable a single interrupt. The interrupt mask register +	 * access needs locking.  	 */ +	spin_lock_irq(&rt2x00dev->irqmask_lock); -	/* -	 * 1 - Rx ring done interrupt. -	 */ -	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE)) -		rt2x00pci_rxdone(rt2x00dev); +	rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); +	rt2x00_set_field32(®, irq_field, 0); +	rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); -	/* -	 * 2 - Tx ring done interrupt. -	 */ -	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE)) -		rt61pci_txdone(rt2x00dev); +	spin_unlock_irq(&rt2x00dev->irqmask_lock); +} -	/* -	 * 3 - Handle MCU command done. -	 */ -	if (reg_mcu) -		rt2x00pci_register_write(rt2x00dev, -					 M2H_CMD_DONE_CSR, 0xffffffff); +static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev, +					 struct rt2x00_field32 irq_field) +{ +	u32 reg;  	/* -	 * 4 - MCU Autowakeup interrupt. +	 * Enable a single MCU interrupt. The interrupt mask register +	 * access needs locking.  	 */ -	if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP)) -		rt61pci_wakeup(rt2x00dev); +	spin_lock_irq(&rt2x00dev->irqmask_lock); -	/* -	 * 5 - Beacon done interrupt. -	 */ -	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE)) -		rt2x00lib_beacondone(rt2x00dev); +	rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); +	rt2x00_set_field32(®, irq_field, 0); +	rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); -	/* Enable interrupts again. */ -	rt2x00dev->ops->lib->set_device_state(rt2x00dev, -					      STATE_RADIO_IRQ_ON_ISR); -	return IRQ_HANDLED; +	spin_unlock_irq(&rt2x00dev->irqmask_lock); +} + +static void rt61pci_txstatus_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	rt61pci_txdone(rt2x00dev); +	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE); +} + +static void rt61pci_tbtt_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	rt2x00lib_beacondone(rt2x00dev); +	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE);  } +static void rt61pci_rxdone_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	if (rt2x00mmio_rxdone(rt2x00dev)) +		tasklet_schedule(&rt2x00dev->rxdone_tasklet); +	else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); +} + +static void rt61pci_autowake_tasklet(unsigned long data) +{ +	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; +	rt61pci_wakeup(rt2x00dev); +	rt2x00mmio_register_write(rt2x00dev, +				  M2H_CMD_DONE_CSR, 0xffffffff); +	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) +		rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP); +}  static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)  {  	struct rt2x00_dev *rt2x00dev = dev_instance; -	u32 reg_mcu; -	u32 reg; +	u32 reg_mcu, mask_mcu; +	u32 reg, mask;  	/*  	 * Get the interrupt sources & saved to local variable.  	 * Write register value back to clear pending interrupts.  	 */ -	rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®_mcu); -	rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu); +	rt2x00mmio_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®_mcu); +	rt2x00mmio_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu); -	rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); -	rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); +	rt2x00mmio_register_read(rt2x00dev, INT_SOURCE_CSR, ®); +	rt2x00mmio_register_write(rt2x00dev, INT_SOURCE_CSR, reg);  	if (!reg && !reg_mcu)  		return IRQ_NONE; @@ -2225,14 +2341,46 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)  	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))  		return IRQ_HANDLED; -	/* Store irqvalues for use in the interrupt thread. */ -	rt2x00dev->irqvalue[0] = reg; -	rt2x00dev->irqvalue[1] = reg_mcu; +	/* +	 * Schedule tasklets for interrupt handling. +	 */ +	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE)) +		tasklet_schedule(&rt2x00dev->rxdone_tasklet); + +	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE)) +		tasklet_schedule(&rt2x00dev->txstatus_tasklet); + +	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE)) +		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet); + +	if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP)) +		tasklet_schedule(&rt2x00dev->autowake_tasklet); + +	/* +	 * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits +	 * for interrupts and interrupt masks we can just use the value of +	 * INT_SOURCE_CSR to create the interrupt mask. +	 */ +	mask = reg; +	mask_mcu = reg_mcu; + +	/* +	 * Disable all interrupts for which a tasklet was scheduled right now, +	 * the tasklet will reenable the appropriate interrupts. +	 */ +	spin_lock(&rt2x00dev->irqmask_lock); + +	rt2x00mmio_register_read(rt2x00dev, INT_MASK_CSR, ®); +	reg |= mask; +	rt2x00mmio_register_write(rt2x00dev, INT_MASK_CSR, reg); + +	rt2x00mmio_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); +	reg |= mask_mcu; +	rt2x00mmio_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); -	/* Disable interrupts, will be enabled again in the interrupt thread. */ -	rt2x00dev->ops->lib->set_device_state(rt2x00dev, -					      STATE_RADIO_IRQ_OFF_ISR); -	return IRQ_WAKE_THREAD; +	spin_unlock(&rt2x00dev->irqmask_lock); + +	return IRQ_HANDLED;  }  /* @@ -2246,7 +2394,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  	u8 *mac;  	s8 value; -	rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, E2PROM_CSR, ®);  	eeprom.data = rt2x00dev;  	eeprom.register_read = rt61pci_eepromregister_read; @@ -2266,8 +2414,8 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  	 */  	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);  	if (!is_valid_ether_addr(mac)) { -		random_ether_addr(mac); -		EEPROM(rt2x00dev, "MAC: %pM\n", mac); +		eth_random_addr(mac); +		rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); @@ -2282,7 +2430,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);  		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5225);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); -		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); @@ -2295,7 +2443,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);  		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); -		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word); @@ -2303,7 +2451,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,  				   LED_MODE_DEFAULT);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word); -		EEPROM(rt2x00dev, "Led: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); @@ -2311,7 +2459,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);  		rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); -		EEPROM(rt2x00dev, "Freq: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word); @@ -2319,7 +2467,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);  		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word); -		EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);  	} else {  		value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);  		if (value < -10 || value > 10) @@ -2335,7 +2483,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);  		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word); -		EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);  	} else {  		value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);  		if (value < -10 || value > 10) @@ -2364,7 +2512,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Identify RF chipset.  	 */  	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); -	rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); +	rt2x00mmio_register_read(rt2x00dev, MAC_CSR0, ®);  	rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),  			value, rt2x00_get_field32(reg, MAC_CSR0_REVISION)); @@ -2372,7 +2520,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	    !rt2x00_rf(rt2x00dev, RF5325) &&  	    !rt2x00_rf(rt2x00dev, RF2527) &&  	    !rt2x00_rf(rt2x00dev, RF2529)) { -		ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); +		rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");  		return -ENODEV;  	} @@ -2380,7 +2528,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Determine number of antennas.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2) -		__set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags); +		__set_bit(CAPABILITY_DOUBLE_ANTENNA, &rt2x00dev->cap_flags);  	/*  	 * Identify default antenna configuration. @@ -2394,20 +2542,20 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Read the Frame type.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE)) -		__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags); +		__set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);  	/*  	 * Detect if this device has a hardware controlled radio.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);  	/*  	 * Read frequency offset and RF programming sequence.  	 */  	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);  	if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ)) -		__set_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags); +		__set_bit(CAPABILITY_RF_SEQUENCE, &rt2x00dev->cap_flags);  	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); @@ -2417,9 +2565,9 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);  	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) -		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); +		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags);  	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) -		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); +		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);  	/*  	 * When working with a RF2529 chip without double antenna, @@ -2427,7 +2575,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * eeprom word.  	 */  	if (rt2x00_rf(rt2x00dev, RF2529) && -	    !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { +	    !rt2x00_has_cap_double_antenna(rt2x00dev)) {  		rt2x00dev->default_ant.rx =  		    ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED);  		rt2x00dev->default_ant.tx = @@ -2642,7 +2790,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  	spec->supported_bands = SUPPORT_BAND_2GHZ;  	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; -	if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) { +	if (!rt2x00_has_cap_rf_sequence(rt2x00dev)) {  		spec->num_channels = 14;  		spec->channels = rf_vals_noseq;  	} else { @@ -2674,7 +2822,8 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  		tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);  		for (i = 14; i < spec->num_channels; i++) {  			info[i].max_power = MAX_TXPOWER; -			info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); +			info[i].default_power1 = +					TXPOWER_FROM_DEV(tx_power[i - 14]);  		}  	} @@ -2684,11 +2833,12 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Disable power saving.  	 */ -	rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007); +	rt2x00mmio_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007);  	/*  	 * Allocate eeprom data. @@ -2702,6 +2852,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00mmio_register_read(rt2x00dev, MAC_CSR13, ®); +	rt2x00_set_field32(®, MAC_CSR13_DIR5, 1); +	rt2x00mmio_register_write(rt2x00dev, MAC_CSR13, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt61pci_probe_hw_mode(rt2x00dev); @@ -2712,16 +2870,16 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)  	 * This device has multiple filters for control frames,  	 * but has no a separate filter for PS Poll frames.  	 */ -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); +	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);  	/*  	 * This device requires firmware and DMA mapped skbs.  	 */ -	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); -	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); +	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_DMA, &rt2x00dev->cap_flags);  	if (!modparam_nohwcrypt) -		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags);  	/*  	 * Set the rssi offset. @@ -2734,7 +2892,8 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)  /*   * IEEE80211 stack callback functions.   */ -static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, +static int rt61pci_conf_tx(struct ieee80211_hw *hw, +			   struct ieee80211_vif *vif, u16 queue_idx,  			   const struct ieee80211_tx_queue_params *params)  {  	struct rt2x00_dev *rt2x00dev = hw->priv; @@ -2750,7 +2909,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  	 * we are free to update the registers based on the value  	 * in the queue parameter.  	 */ -	retval = rt2x00mac_conf_tx(hw, queue_idx, params); +	retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);  	if (retval)  		return retval; @@ -2761,45 +2920,45 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  	if (queue_idx >= 4)  		return 0; -	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); +	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);  	/* Update WMM TXOP register */  	offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));  	field.bit_offset = (queue_idx & 1) * 16;  	field.bit_mask = 0xffff << field.bit_offset; -	rt2x00pci_register_read(rt2x00dev, offset, ®); +	rt2x00mmio_register_read(rt2x00dev, offset, ®);  	rt2x00_set_field32(®, field, queue->txop); -	rt2x00pci_register_write(rt2x00dev, offset, reg); +	rt2x00mmio_register_write(rt2x00dev, offset, reg);  	/* Update WMM registers */  	field.bit_offset = queue_idx * 4;  	field.bit_mask = 0xf << field.bit_offset; -	rt2x00pci_register_read(rt2x00dev, AIFSN_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, AIFSN_CSR, ®);  	rt2x00_set_field32(®, field, queue->aifs); -	rt2x00pci_register_write(rt2x00dev, AIFSN_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, AIFSN_CSR, reg); -	rt2x00pci_register_read(rt2x00dev, CWMIN_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, CWMIN_CSR, ®);  	rt2x00_set_field32(®, field, queue->cw_min); -	rt2x00pci_register_write(rt2x00dev, CWMIN_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, CWMIN_CSR, reg); -	rt2x00pci_register_read(rt2x00dev, CWMAX_CSR, ®); +	rt2x00mmio_register_read(rt2x00dev, CWMAX_CSR, ®);  	rt2x00_set_field32(®, field, queue->cw_max); -	rt2x00pci_register_write(rt2x00dev, CWMAX_CSR, reg); +	rt2x00mmio_register_write(rt2x00dev, CWMAX_CSR, reg);  	return 0;  } -static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) +static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)  {  	struct rt2x00_dev *rt2x00dev = hw->priv;  	u64 tsf;  	u32 reg; -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR13, ®); +	rt2x00mmio_register_read(rt2x00dev, TXRX_CSR13, ®);  	tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; -	rt2x00pci_register_read(rt2x00dev, TXRX_CSR12, ®); +	rt2x00mmio_register_read(rt2x00dev, TXRX_CSR12, ®);  	tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);  	return tsf; @@ -2822,17 +2981,24 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {  	.get_tsf		= rt61pci_get_tsf,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.flush			= rt2x00mac_flush, +	.set_antenna		= rt2x00mac_set_antenna, +	.get_antenna		= rt2x00mac_get_antenna, +	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {  	.irq_handler		= rt61pci_interrupt, -	.irq_handler_thread	= rt61pci_interrupt_thread, +	.txstatus_tasklet	= rt61pci_txstatus_tasklet, +	.tbtt_tasklet		= rt61pci_tbtt_tasklet, +	.rxdone_tasklet		= rt61pci_rxdone_tasklet, +	.autowake_tasklet	= rt61pci_autowake_tasklet,  	.probe_hw		= rt61pci_probe_hw,  	.get_firmware_name	= rt61pci_get_firmware_name,  	.check_firmware		= rt61pci_check_firmware,  	.load_firmware		= rt61pci_load_firmware, -	.initialize		= rt2x00pci_initialize, -	.uninitialize		= rt2x00pci_uninitialize, +	.initialize		= rt2x00mmio_initialize, +	.uninitialize		= rt2x00mmio_uninitialize,  	.get_entry_state	= rt61pci_get_entry_state,  	.clear_entry		= rt61pci_clear_entry,  	.set_device_state	= rt61pci_set_device_state, @@ -2840,10 +3006,13 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {  	.link_stats		= rt61pci_link_stats,  	.reset_tuner		= rt61pci_reset_tuner,  	.link_tuner		= rt61pci_link_tuner, +	.start_queue		= rt61pci_start_queue, +	.kick_queue		= rt61pci_kick_queue, +	.stop_queue		= rt61pci_stop_queue, +	.flush_queue		= rt2x00mmio_flush_queue,  	.write_tx_desc		= rt61pci_write_tx_desc,  	.write_beacon		= rt61pci_write_beacon, -	.kick_tx_queue		= rt61pci_kick_tx_queue, -	.kill_tx_queue		= rt61pci_kill_tx_queue, +	.clear_beacon		= rt61pci_clear_beacon,  	.fill_rxdone		= rt61pci_fill_rxdone,  	.config_shared_key	= rt61pci_config_shared_key,  	.config_pairwise_key	= rt61pci_config_pairwise_key, @@ -2854,38 +3023,48 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {  	.config			= rt61pci_config,  }; -static const struct data_queue_desc rt61pci_queue_rx = { -	.entry_num		= 32, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= RXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; +static void rt61pci_queue_init(struct data_queue *queue) +{ +	switch (queue->qid) { +	case QID_RX: +		queue->limit = 32; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = RXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; -static const struct data_queue_desc rt61pci_queue_tx = { -	.entry_num		= 32, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		queue->limit = 32; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; -static const struct data_queue_desc rt61pci_queue_bcn = { -	.entry_num		= 4, -	.data_size		= 0, /* No DMA required for beacons */ -	.desc_size		= TXINFO_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_pci), -}; +	case QID_BEACON: +		queue->limit = 4; +		queue->data_size = 0; /* No DMA required for beacons */ +		queue->desc_size = TXINFO_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_mmio); +		break; + +	case QID_ATIM: +		/* fallthrough */ +	default: +		BUG(); +		break; +	} +}  static const struct rt2x00_ops rt61pci_ops = {  	.name			= KBUILD_MODNAME, -	.max_sta_intf		= 1,  	.max_ap_intf		= 4,  	.eeprom_size		= EEPROM_SIZE,  	.rf_size		= RF_SIZE,  	.tx_queues		= NUM_TX_QUEUES, -	.extra_tx_headroom	= 0, -	.rx			= &rt61pci_queue_rx, -	.tx			= &rt61pci_queue_tx, -	.bcn			= &rt61pci_queue_bcn, +	.queue_init		= rt61pci_queue_init,  	.lib			= &rt61pci_rt2x00_ops,  	.hw			= &rt61pci_mac80211_ops,  #ifdef CONFIG_RT2X00_LIB_DEBUGFS @@ -2898,11 +3077,11 @@ static const struct rt2x00_ops rt61pci_ops = {   */  static DEFINE_PCI_DEVICE_TABLE(rt61pci_device_table) = {  	/* RT2561s */ -	{ PCI_DEVICE(0x1814, 0x0301), PCI_DEVICE_DATA(&rt61pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0301) },  	/* RT2561 v2 */ -	{ PCI_DEVICE(0x1814, 0x0302), PCI_DEVICE_DATA(&rt61pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0302) },  	/* RT2661 */ -	{ PCI_DEVICE(0x1814, 0x0401), PCI_DEVICE_DATA(&rt61pci_ops) }, +	{ PCI_DEVICE(0x1814, 0x0401) },  	{ 0, }  }; @@ -2917,24 +3096,19 @@ MODULE_FIRMWARE(FIRMWARE_RT2561s);  MODULE_FIRMWARE(FIRMWARE_RT2661);  MODULE_LICENSE("GPL"); +static int rt61pci_probe(struct pci_dev *pci_dev, +			 const struct pci_device_id *id) +{ +	return rt2x00pci_probe(pci_dev, &rt61pci_ops); +} +  static struct pci_driver rt61pci_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt61pci_device_table, -	.probe		= rt2x00pci_probe, -	.remove		= __devexit_p(rt2x00pci_remove), +	.probe		= rt61pci_probe, +	.remove		= rt2x00pci_remove,  	.suspend	= rt2x00pci_suspend,  	.resume		= rt2x00pci_resume,  }; -static int __init rt61pci_init(void) -{ -	return pci_register_driver(&rt61pci_driver); -} - -static void __exit rt61pci_exit(void) -{ -	pci_unregister_driver(&rt61pci_driver); -} - -module_init(rt61pci_init); -module_exit(rt61pci_exit); +module_pci_driver(rt61pci_driver); diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index afc803b7959..1442075a838 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -357,21 +355,22 @@ struct hw_pairwise_ta_entry {  /*   * MAC_CSR13: GPIO. + *	MAC_CSR13_VALx: GPIO value + *	MAC_CSR13_DIRx: GPIO direction: 0 = output; 1 = input   */  #define MAC_CSR13			0x3034 -#define MAC_CSR13_BIT0			FIELD32(0x00000001) -#define MAC_CSR13_BIT1			FIELD32(0x00000002) -#define MAC_CSR13_BIT2			FIELD32(0x00000004) -#define MAC_CSR13_BIT3			FIELD32(0x00000008) -#define MAC_CSR13_BIT4			FIELD32(0x00000010) -#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) +#define MAC_CSR13_VAL0			FIELD32(0x00000001) +#define MAC_CSR13_VAL1			FIELD32(0x00000002) +#define MAC_CSR13_VAL2			FIELD32(0x00000004) +#define MAC_CSR13_VAL3			FIELD32(0x00000008) +#define MAC_CSR13_VAL4			FIELD32(0x00000010) +#define MAC_CSR13_VAL5			FIELD32(0x00000020) +#define MAC_CSR13_DIR0			FIELD32(0x00000100) +#define MAC_CSR13_DIR1			FIELD32(0x00000200) +#define MAC_CSR13_DIR2			FIELD32(0x00000400) +#define MAC_CSR13_DIR3			FIELD32(0x00000800) +#define MAC_CSR13_DIR4			FIELD32(0x00001000) +#define MAC_CSR13_DIR5			FIELD32(0x00002000)  /*   * MAC_CSR14: LED control register. @@ -784,25 +783,25 @@ struct hw_pairwise_ta_entry {   */  /* - * AC0_BASE_CSR: AC_BK base address. + * AC0_BASE_CSR: AC_VO base address.   */  #define AC0_BASE_CSR			0x3400  #define AC0_BASE_CSR_RING_REGISTER	FIELD32(0xffffffff)  /* - * AC1_BASE_CSR: AC_BE base address. + * AC1_BASE_CSR: AC_VI base address.   */  #define AC1_BASE_CSR			0x3404  #define AC1_BASE_CSR_RING_REGISTER	FIELD32(0xffffffff)  /* - * AC2_BASE_CSR: AC_VI base address. + * AC2_BASE_CSR: AC_BE base address.   */  #define AC2_BASE_CSR			0x3408  #define AC2_BASE_CSR_RING_REGISTER	FIELD32(0xffffffff)  /* - * AC3_BASE_CSR: AC_VO base address. + * AC3_BASE_CSR: AC_BK base address.   */  #define AC3_BASE_CSR			0x340c  #define AC3_BASE_CSR_RING_REGISTER	FIELD32(0xffffffff) @@ -814,7 +813,7 @@ struct hw_pairwise_ta_entry {  #define MGMT_BASE_CSR_RING_REGISTER	FIELD32(0xffffffff)  /* - * TX_RING_CSR0: TX Ring size for AC_BK, AC_BE, AC_VI, AC_VO. + * TX_RING_CSR0: TX Ring size for AC_VO, AC_VI, AC_BE, AC_BK.   */  #define TX_RING_CSR0			0x3418  #define TX_RING_CSR0_AC0_RING_SIZE	FIELD32(0x000000ff) @@ -833,10 +832,10 @@ struct hw_pairwise_ta_entry {  /*   * AIFSN_CSR: AIFSN for each EDCA AC. - * AIFSN0: For AC_BK. - * AIFSN1: For AC_BE. - * AIFSN2: For AC_VI. - * AIFSN3: For AC_VO. + * AIFSN0: For AC_VO. + * AIFSN1: For AC_VI. + * AIFSN2: For AC_BE. + * AIFSN3: For AC_BK.   */  #define AIFSN_CSR			0x3420  #define AIFSN_CSR_AIFSN0		FIELD32(0x0000000f) @@ -846,10 +845,10 @@ struct hw_pairwise_ta_entry {  /*   * CWMIN_CSR: CWmin for each EDCA AC. - * CWMIN0: For AC_BK. - * CWMIN1: For AC_BE. - * CWMIN2: For AC_VI. - * CWMIN3: For AC_VO. + * CWMIN0: For AC_VO. + * CWMIN1: For AC_VI. + * CWMIN2: For AC_BE. + * CWMIN3: For AC_BK.   */  #define CWMIN_CSR			0x3424  #define CWMIN_CSR_CWMIN0		FIELD32(0x0000000f) @@ -859,10 +858,10 @@ struct hw_pairwise_ta_entry {  /*   * CWMAX_CSR: CWmax for each EDCA AC. - * CWMAX0: For AC_BK. - * CWMAX1: For AC_BE. - * CWMAX2: For AC_VI. - * CWMAX3: For AC_VO. + * CWMAX0: For AC_VO. + * CWMAX1: For AC_VI. + * CWMAX2: For AC_BE. + * CWMAX3: For AC_BK.   */  #define CWMAX_CSR			0x3428  #define CWMAX_CSR_CWMAX0		FIELD32(0x0000000f) @@ -883,14 +882,14 @@ struct hw_pairwise_ta_entry {  /*   * TX_CNTL_CSR: KICK/Abort TX. - * KICK_TX_AC0: For AC_BK. - * KICK_TX_AC1: For AC_BE. - * KICK_TX_AC2: For AC_VI. - * KICK_TX_AC3: For AC_VO. - * ABORT_TX_AC0: For AC_BK. - * ABORT_TX_AC1: For AC_BE. - * ABORT_TX_AC2: For AC_VI. - * ABORT_TX_AC3: For AC_VO. + * KICK_TX_AC0: For AC_VO. + * KICK_TX_AC1: For AC_VI. + * KICK_TX_AC2: For AC_BE. + * KICK_TX_AC3: For AC_BK. + * ABORT_TX_AC0: For AC_VO. + * ABORT_TX_AC1: For AC_VI. + * ABORT_TX_AC2: For AC_BE. + * ABORT_TX_AC3: For AC_BK.   */  #define TX_CNTL_CSR			0x3430  #define TX_CNTL_CSR_KICK_TX_AC0		FIELD32(0x00000001) @@ -1010,18 +1009,18 @@ struct hw_pairwise_ta_entry {  #define E2PROM_CSR_LOAD_STATUS		FIELD32(0x00000040)  /* - * AC_TXOP_CSR0: AC_BK/AC_BE TXOP register. - * AC0_TX_OP: For AC_BK, in unit of 32us. - * AC1_TX_OP: For AC_BE, in unit of 32us. + * AC_TXOP_CSR0: AC_VO/AC_VI TXOP register. + * AC0_TX_OP: For AC_VO, in unit of 32us. + * AC1_TX_OP: For AC_VI, in unit of 32us.   */  #define AC_TXOP_CSR0			0x3474  #define AC_TXOP_CSR0_AC0_TX_OP		FIELD32(0x0000ffff)  #define AC_TXOP_CSR0_AC1_TX_OP		FIELD32(0xffff0000)  /* - * AC_TXOP_CSR1: AC_VO/AC_VI TXOP register. - * AC2_TX_OP: For AC_VI, in unit of 32us. - * AC3_TX_OP: For AC_VO, in unit of 32us. + * AC_TXOP_CSR1: AC_BE/AC_BK TXOP register. + * AC2_TX_OP: For AC_BE, in unit of 32us. + * AC3_TX_OP: For AC_BK, in unit of 32us.   */  #define AC_TXOP_CSR1			0x3478  #define AC_TXOP_CSR1_AC2_TX_OP		FIELD32(0x0000ffff) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6f04552f581..95724ff9c72 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -27,7 +25,6 @@  #include <linux/crc-itu-t.h>  #include <linux/delay.h>  #include <linux/etherdevice.h> -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/slab.h> @@ -40,7 +37,7 @@  /*   * Allow hardware encryption to be disabled.   */ -static int modparam_nohwcrypt; +static bool modparam_nohwcrypt;  module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);  MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); @@ -189,7 +186,7 @@ static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)  	u32 reg;  	rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); -	return rt2x00_get_field32(reg, MAC_CSR13_BIT7); +	return rt2x00_get_field32(reg, MAC_CSR13_VAL7);  }  #ifdef CONFIG_RT2X00_LIB_LEDS @@ -502,26 +499,14 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,  				struct rt2x00intf_conf *conf,  				const unsigned int flags)  { -	unsigned int beacon_base;  	u32 reg;  	if (flags & CONFIG_UPDATE_TYPE) {  		/* -		 * 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. -		 */ -		beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); -		rt2x00usb_register_write(rt2x00dev, beacon_base, 0); - -		/*  		 * Enable synchronisation.  		 */  		rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); -		rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1);  		rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); -		rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);  		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);  	} @@ -607,8 +592,8 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,  	switch (ant->rx) {  	case ANTENNA_HW_DIVERSITY:  		rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); -		temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags) -		       && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); +		temp = !rt2x00_has_cap_frame_type(rt2x00dev) && +		       (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ);  		rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);  		break;  	case ANTENNA_A: @@ -648,7 +633,7 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,  	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)); +			  !rt2x00_has_cap_frame_type(rt2x00dev));  	/*  	 * Configure the RX antenna. @@ -721,10 +706,10 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,  	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) {  		sel = antenna_sel_a; -		lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); +		lna = rt2x00_has_cap_external_lna_a(rt2x00dev);  	} else {  		sel = antenna_sel_bg; -		lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); +		lna = rt2x00_has_cap_external_lna_bg(rt2x00dev);  	}  	for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) @@ -751,8 +736,8 @@ static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,  	u16 eeprom;  	short lna_gain = 0; -	if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) { -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) +	if (libconf->conf->chandef.chan->band == IEEE80211_BAND_2GHZ) { +		if (rt2x00_has_cap_external_lna_bg(rt2x00dev))  			lna_gain += 14;  		rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); @@ -942,7 +927,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,  		low_bound = 0x28;  		up_bound = 0x48; -		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { +		if (rt2x00_has_cap_external_lna_a(rt2x00dev)) {  			low_bound += 0x10;  			up_bound += 0x10;  		} @@ -958,7 +943,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev,  			up_bound = 0x1c;  		} -		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { +		if (rt2x00_has_cap_external_lna_bg(rt2x00dev)) {  			low_bound += 0x14;  			up_bound += 0x10;  		} @@ -1031,6 +1016,55 @@ dynamic_cca_tune:  }  /* + * Queue handlers. + */ +static void rt73usb_start_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_RX: +		rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); +		rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); +		rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); +		break; +	case QID_BEACON: +		rt2x00usb_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, 1); +		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); +		break; +	default: +		break; +	} +} + +static void rt73usb_stop_queue(struct data_queue *queue) +{ +	struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; +	u32 reg; + +	switch (queue->qid) { +	case QID_RX: +		rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); +		rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 1); +		rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); +		break; +	case QID_BEACON: +		rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); +		rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); +		rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); +		rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); +		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); +		break; +	default: +		break; +	} +} + +/*   * Firmware functions   */  static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) @@ -1085,7 +1119,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,  	}  	if (!reg) { -		ERROR(rt2x00dev, "Unstable hardware.\n"); +		rt2x00_err(rt2x00dev, "Unstable hardware\n");  		return -EBUSY;  	} @@ -1102,7 +1136,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev,  					     0, USB_MODE_FIRMWARE,  					     REGISTER_TIMEOUT_FIRMWARE);  	if (status < 0) { -		ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); +		rt2x00_err(rt2x00dev, "Failed to write Firmware to device\n");  		return status;  	} @@ -1268,7 +1302,7 @@ static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)  		udelay(REGISTER_BUSY_DELAY);  	} -	ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); +	rt2x00_err(rt2x00dev, "BBP register access failed, aborting\n");  	return -EACCES;  } @@ -1324,17 +1358,6 @@ static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)  /*   * Device state switch handlers.   */ -static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev, -			      enum dev_state state) -{ -	u32 reg; - -	rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); -	rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, -			   (state == STATE_RADIO_RX_OFF)); -	rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); -} -  static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)  {  	/* @@ -1401,14 +1424,8 @@ static int rt73usb_set_device_state(struct rt2x00_dev *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); -		break;  	case STATE_RADIO_IRQ_ON: -	case STATE_RADIO_IRQ_ON_ISR:  	case STATE_RADIO_IRQ_OFF: -	case STATE_RADIO_IRQ_OFF_ISR:  		/* No support, but no error either */  		break;  	case STATE_DEEP_SLEEP: @@ -1423,8 +1440,8 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,  	}  	if (unlikely(retval)) -		ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", -		      state, retval); +		rt2x00_err(rt2x00dev, "Device failed to enter state %d (%d)\n", +			   state, retval);  	return retval;  } @@ -1454,7 +1471,7 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,  			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));  	rt2x00_set_field32(&word, TXD_W0_OFDM,  			   (txdesc->rate_mode == RATE_MODE_OFDM)); -	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); +	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);  	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,  			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));  	rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, @@ -1479,10 +1496,12 @@ static void rt73usb_write_tx_desc(struct queue_entry *entry,  	rt2x00_desc_write(txd, 1, word);  	rt2x00_desc_read(txd, 2, &word); -	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); -	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); -	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); -	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); +	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal); +	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service); +	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, +			   txdesc->u.plcp.length_low); +	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, +			   txdesc->u.plcp.length_high);  	rt2x00_desc_write(txd, 2, word);  	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { @@ -1512,13 +1531,15 @@ static void rt73usb_write_beacon(struct queue_entry *entry,  {  	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;  	unsigned int beacon_base; -	u32 reg; +	unsigned int padding_len; +	u32 orig_reg, reg;  	/*  	 * Disable beaconing while we are reloading the beacon data,  	 * otherwise we might be sending out invalid data.  	 */  	rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); +	orig_reg = reg;  	rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);  	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); @@ -1539,11 +1560,20 @@ static void rt73usb_write_beacon(struct queue_entry *entry,  	rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);  	/* -	 * Write entire beacon with descriptor to register. +	 * Write entire beacon with descriptor and padding to register.  	 */ +	padding_len = roundup(entry->skb->len, 4) - entry->skb->len; +	if (padding_len && skb_pad(entry->skb, padding_len)) { +		rt2x00_err(rt2x00dev, "Failure padding beacon, aborting\n"); +		/* skb freed by skb_pad() on failure */ +		entry->skb = NULL; +		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg); +		return; +	} +  	beacon_base = HW_BEACON_OFFSET(entry->entry_idx); -	rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, -				      entry->skb->data, entry->skb->len); +	rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, +				      entry->skb->len + padding_len);  	/*  	 * Enable beaconing again. @@ -1553,8 +1583,6 @@ static void rt73usb_write_beacon(struct queue_entry *entry,  	 */  	rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); -	rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); -	rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1);  	rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1);  	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); @@ -1565,6 +1593,33 @@ static void rt73usb_write_beacon(struct queue_entry *entry,  	entry->skb = NULL;  } +static void rt73usb_clear_beacon(struct queue_entry *entry) +{ +	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; +	unsigned int beacon_base; +	u32 orig_reg, reg; + +	/* +	 * Disable beaconing while we are reloading the beacon data, +	 * otherwise we might be sending out invalid data. +	 */ +	rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &orig_reg); +	reg = orig_reg; +	rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); +	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); + +	/* +	 * Clear beacon. +	 */ +	beacon_base = HW_BEACON_OFFSET(entry->entry_idx); +	rt2x00usb_register_write(rt2x00dev, beacon_base, 0); + +	/* +	 * Restore beaconing state. +	 */ +	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg); +} +  static int rt73usb_get_tx_data_len(struct queue_entry *entry)  {  	int length; @@ -1579,14 +1634,6 @@ static int rt73usb_get_tx_data_len(struct queue_entry *entry)  	return length;  } -static void rt73usb_kill_tx_queue(struct data_queue *queue) -{ -	if (queue->qid == QID_BEACON) -		rt2x00usb_register_write(queue->rt2x00dev, TXRX_CSR9, 0); - -	rt2x00usb_kill_tx_queue(queue); -} -  /*   * RX control handlers   */ @@ -1611,7 +1658,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)  	}  	if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { -		if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { +		if (rt2x00_has_cap_external_lna_a(rt2x00dev)) {  			if (lna == 3 || lna == 2)  				offset += 10;  		} else { @@ -1669,9 +1716,8 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,  		rxdesc->flags |= RX_FLAG_IV_STRIPPED;  		/* -		 * FIXME: Legacy driver indicates that the frame does -		 * contain the Michael Mic. Unfortunately, in rt2x00 -		 * the MIC seems to be missing completely... +		 * The hardware has already checked the Michael Mic and has +		 * stripped it from the frame. Signal this to mac80211.  		 */  		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; @@ -1721,8 +1767,8 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  	 */  	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);  	if (!is_valid_ether_addr(mac)) { -		random_ether_addr(mac); -		EEPROM(rt2x00dev, "MAC: %pM\n", mac); +		eth_random_addr(mac); +		rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); @@ -1737,14 +1783,14 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);  		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5226);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); -		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);  	if (word == 0xffff) {  		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA, 0);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); -		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word); @@ -1760,7 +1806,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_LED_LED_MODE,  				   LED_MODE_DEFAULT);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word); -		EEPROM(rt2x00dev, "Led: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "Led: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); @@ -1768,7 +1814,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);  		rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); -		EEPROM(rt2x00dev, "Freq: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word);  	}  	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word); @@ -1776,7 +1822,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0);  		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word); -		EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word);  	} else {  		value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1);  		if (value < -10 || value > 10) @@ -1792,7 +1838,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0);  		rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0);  		rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word); -		EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word); +		rt2x00_eeprom_dbg(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word);  	} else {  		value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1);  		if (value < -10 || value > 10) @@ -1826,7 +1872,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)  			value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));  	if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) { -		ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); +		rt2x00_err(rt2x00dev, "Invalid RT chipset detected\n");  		return -ENODEV;  	} @@ -1834,7 +1880,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)  	    !rt2x00_rf(rt2x00dev, RF2528) &&  	    !rt2x00_rf(rt2x00dev, RF5225) &&  	    !rt2x00_rf(rt2x00dev, RF2527)) { -		ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); +		rt2x00_err(rt2x00dev, "Invalid RF chipset detected\n");  		return -ENODEV;  	} @@ -1850,13 +1896,13 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)  	 * Read the Frame type.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE)) -		__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags); +		__set_bit(CAPABILITY_FRAME_TYPE, &rt2x00dev->cap_flags);  	/*  	 * Detect if this device has an hardware controlled radio.  	 */  	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) -		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);  	/*  	 * Read frequency offset. @@ -1870,8 +1916,8 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)  	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);  	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); +		__set_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags); +		__set_bit(CAPABILITY_EXTERNAL_LNA_BG, &rt2x00dev->cap_flags);  	}  	/* @@ -2118,7 +2164,8 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  		tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);  		for (i = 14; i < spec->num_channels; i++) {  			info[i].max_power = MAX_TXPOWER; -			info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); +			info[i].default_power1 = +					TXPOWER_FROM_DEV(tx_power[i - 14]);  		}  	} @@ -2128,6 +2175,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -2141,6 +2189,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); +	rt2x00_set_field32(®, MAC_CSR13_DIR7, 0); +	rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt73usb_probe_hw_mode(rt2x00dev); @@ -2151,16 +2207,16 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)  	 * This device has multiple filters for control frames,  	 * but has no a separate filter for PS Poll frames.  	 */ -	__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); +	__set_bit(CAPABILITY_CONTROL_FILTERS, &rt2x00dev->cap_flags);  	/*  	 * This device requires firmware.  	 */ -	__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); +	__set_bit(REQUIRE_FIRMWARE, &rt2x00dev->cap_flags);  	if (!modparam_nohwcrypt) -		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags); -	__set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags); +		__set_bit(CAPABILITY_HW_CRYPTO, &rt2x00dev->cap_flags); +	__set_bit(CAPABILITY_LINK_TUNING, &rt2x00dev->cap_flags); +	__set_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags);  	/*  	 * Set the rssi offset. @@ -2173,7 +2229,8 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)  /*   * IEEE80211 stack callback functions.   */ -static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, +static int rt73usb_conf_tx(struct ieee80211_hw *hw, +			   struct ieee80211_vif *vif, u16 queue_idx,  			   const struct ieee80211_tx_queue_params *params)  {  	struct rt2x00_dev *rt2x00dev = hw->priv; @@ -2189,7 +2246,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  	 * we are free to update the registers based on the value  	 * in the queue parameter.  	 */ -	retval = rt2x00mac_conf_tx(hw, queue_idx, params); +	retval = rt2x00mac_conf_tx(hw, vif, queue_idx, params);  	if (retval)  		return retval; @@ -2200,7 +2257,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  	if (queue_idx >= 4)  		return 0; -	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); +	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);  	/* Update WMM TXOP register */  	offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2))); @@ -2230,7 +2287,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,  	return 0;  } -static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) +static u64 rt73usb_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)  {  	struct rt2x00_dev *rt2x00dev = hw->priv;  	u64 tsf; @@ -2262,6 +2319,10 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {  	.get_tsf		= rt73usb_get_tsf,  	.rfkill_poll		= rt2x00mac_rfkill_poll,  	.flush			= rt2x00mac_flush, +	.set_antenna		= rt2x00mac_set_antenna, +	.get_antenna		= rt2x00mac_get_antenna, +	.get_ringparam		= rt2x00mac_get_ringparam, +	.tx_frames_pending	= rt2x00mac_tx_frames_pending,  };  static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { @@ -2278,11 +2339,14 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {  	.reset_tuner		= rt73usb_reset_tuner,  	.link_tuner		= rt73usb_link_tuner,  	.watchdog		= rt2x00usb_watchdog, +	.start_queue		= rt73usb_start_queue, +	.kick_queue		= rt2x00usb_kick_queue, +	.stop_queue		= rt73usb_stop_queue, +	.flush_queue		= rt2x00usb_flush_queue,  	.write_tx_desc		= rt73usb_write_tx_desc,  	.write_beacon		= rt73usb_write_beacon, +	.clear_beacon		= rt73usb_clear_beacon,  	.get_tx_data_len	= rt73usb_get_tx_data_len, -	.kick_tx_queue		= rt2x00usb_kick_tx_queue, -	.kill_tx_queue		= rt73usb_kill_tx_queue,  	.fill_rxdone		= rt73usb_fill_rxdone,  	.config_shared_key	= rt73usb_config_shared_key,  	.config_pairwise_key	= rt73usb_config_pairwise_key, @@ -2293,38 +2357,48 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {  	.config			= rt73usb_config,  }; -static const struct data_queue_desc rt73usb_queue_rx = { -	.entry_num		= 32, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= RXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_usb), -}; +static void rt73usb_queue_init(struct data_queue *queue) +{ +	switch (queue->qid) { +	case QID_RX: +		queue->limit = 32; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = RXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_usb); +		break; -static const struct data_queue_desc rt73usb_queue_tx = { -	.entry_num		= 32, -	.data_size		= DATA_FRAME_SIZE, -	.desc_size		= TXD_DESC_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_usb), -}; +	case QID_AC_VO: +	case QID_AC_VI: +	case QID_AC_BE: +	case QID_AC_BK: +		queue->limit = 32; +		queue->data_size = DATA_FRAME_SIZE; +		queue->desc_size = TXD_DESC_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_usb); +		break; -static const struct data_queue_desc rt73usb_queue_bcn = { -	.entry_num		= 4, -	.data_size		= MGMT_FRAME_SIZE, -	.desc_size		= TXINFO_SIZE, -	.priv_size		= sizeof(struct queue_entry_priv_usb), -}; +	case QID_BEACON: +		queue->limit = 4; +		queue->data_size = MGMT_FRAME_SIZE; +		queue->desc_size = TXINFO_SIZE; +		queue->priv_size = sizeof(struct queue_entry_priv_usb); +		break; + +	case QID_ATIM: +		/* fallthrough */ +	default: +		BUG(); +		break; +	} +}  static const struct rt2x00_ops rt73usb_ops = {  	.name			= KBUILD_MODNAME, -	.max_sta_intf		= 1,  	.max_ap_intf		= 4,  	.eeprom_size		= EEPROM_SIZE,  	.rf_size		= RF_SIZE,  	.tx_queues		= NUM_TX_QUEUES, -	.extra_tx_headroom	= TXD_DESC_SIZE, -	.rx			= &rt73usb_queue_rx, -	.tx			= &rt73usb_queue_tx, -	.bcn			= &rt73usb_queue_bcn, +	.queue_init		= rt73usb_queue_init,  	.lib			= &rt73usb_rt2x00_ops,  	.hw			= &rt73usb_mac80211_ops,  #ifdef CONFIG_RT2X00_LIB_DEBUGFS @@ -2337,113 +2411,115 @@ static const struct rt2x00_ops rt73usb_ops = {   */  static struct usb_device_id rt73usb_device_table[] = {  	/* AboCom */ -	{ USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x07b8, 0xb21b) }, +	{ USB_DEVICE(0x07b8, 0xb21c) }, +	{ USB_DEVICE(0x07b8, 0xb21d) }, +	{ USB_DEVICE(0x07b8, 0xb21e) }, +	{ USB_DEVICE(0x07b8, 0xb21f) },  	/* AL */ -	{ USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x14b2, 0x3c10) },  	/* Amigo */ -	{ USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x148f, 0x9021) }, +	{ USB_DEVICE(0x0eb0, 0x9021) },  	/* AMIT  */ -	{ USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x18c5, 0x0002) },  	/* Askey */ -	{ USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1690, 0x0722) },  	/* ASUS */ -	{ USB_DEVICE(0x0b05, 0x1723), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0b05, 0x1724), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0b05, 0x1723) }, +	{ USB_DEVICE(0x0b05, 0x1724) },  	/* Belkin */ -	{ 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) }, +	{ USB_DEVICE(0x050d, 0x7050) },	/* FCC ID: K7SF5D7050B ver. 3.x */ +	{ USB_DEVICE(0x050d, 0x705a) }, +	{ USB_DEVICE(0x050d, 0x905b) }, +	{ USB_DEVICE(0x050d, 0x905c) },  	/* Billionton */ -	{ USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1631, 0xc019) }, +	{ USB_DEVICE(0x08dd, 0x0120) },  	/* Buffalo */ -	{ USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0411, 0x00d9), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0411, 0x0137), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0411, 0x00d8) }, +	{ USB_DEVICE(0x0411, 0x00d9) }, +	{ USB_DEVICE(0x0411, 0x00e6) }, +	{ USB_DEVICE(0x0411, 0x00f4) }, +	{ USB_DEVICE(0x0411, 0x0116) }, +	{ USB_DEVICE(0x0411, 0x0119) }, +	{ USB_DEVICE(0x0411, 0x0137) },  	/* CEIVA */ -	{ USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x178d, 0x02be) },  	/* CNet */ -	{ USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1371, 0x9022) }, +	{ USB_DEVICE(0x1371, 0x9032) },  	/* Conceptronic */ -	{ USB_DEVICE(0x14b2, 0x3c22), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x14b2, 0x3c22) },  	/* Corega */ -	{ USB_DEVICE(0x07aa, 0x002e), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x07aa, 0x002e) },  	/* D-Link */ -	{ USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x07d1, 0x3c03) }, +	{ USB_DEVICE(0x07d1, 0x3c04) }, +	{ USB_DEVICE(0x07d1, 0x3c06) }, +	{ USB_DEVICE(0x07d1, 0x3c07) },  	/* Edimax */ -	{ USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x7392, 0x7318) }, +	{ USB_DEVICE(0x7392, 0x7618) },  	/* EnGenius */ -	{ USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1740, 0x3701) },  	/* Gemtek */ -	{ USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x15a9, 0x0004) },  	/* Gigabyte */ -	{ USB_DEVICE(0x1044, 0x8008), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x1044, 0x800a), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1044, 0x8008) }, +	{ USB_DEVICE(0x1044, 0x800a) },  	/* Huawei-3Com */ -	{ USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1472, 0x0009) },  	/* Hercules */ -	{ USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x06f8, 0xe002) }, +	{ USB_DEVICE(0x06f8, 0xe010) }, +	{ USB_DEVICE(0x06f8, 0xe020) },  	/* Linksys */ -	{ USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x13b1, 0x0020) }, +	{ USB_DEVICE(0x13b1, 0x0023) }, +	{ USB_DEVICE(0x13b1, 0x0028) },  	/* MSI */ -	{ USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ 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) }, +	{ USB_DEVICE(0x0db0, 0x4600) }, +	{ USB_DEVICE(0x0db0, 0x6877) }, +	{ USB_DEVICE(0x0db0, 0x6874) }, +	{ USB_DEVICE(0x0db0, 0xa861) }, +	{ USB_DEVICE(0x0db0, 0xa874) },  	/* Ovislink */ -	{ USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1b75, 0x7318) },  	/* Ralink */ -	{ USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x04bb, 0x093d) }, +	{ USB_DEVICE(0x148f, 0x2573) }, +	{ USB_DEVICE(0x148f, 0x2671) }, +	{ USB_DEVICE(0x0812, 0x3101) },  	/* 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) }, +	{ USB_DEVICE(0x18e8, 0x6196) }, +	{ USB_DEVICE(0x18e8, 0x6229) }, +	{ USB_DEVICE(0x18e8, 0x6238) },  	/* Samsung */ -	{ USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x04e8, 0x4471) },  	/* Senao */ -	{ USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x1740, 0x7100) },  	/* Sitecom */ -	{ USB_DEVICE(0x0df6, 0x0024), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x0027), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x002f), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0df6, 0x0024) }, +	{ USB_DEVICE(0x0df6, 0x0027) }, +	{ USB_DEVICE(0x0df6, 0x002f) }, +	{ USB_DEVICE(0x0df6, 0x90ac) }, +	{ USB_DEVICE(0x0df6, 0x9712) },  	/* Surecom */ -	{ USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0769, 0x31f3) },  	/* Tilgin */ -	{ USB_DEVICE(0x6933, 0x5001), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x6933, 0x5001) },  	/* Philips */ -	{ USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0471, 0x200a) },  	/* Planex */ -	{ USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) }, -	{ USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x2019, 0xab01) }, +	{ USB_DEVICE(0x2019, 0xab50) },  	/* WideTell */ -	{ USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x7167, 0x3840) },  	/* Zcom */ -	{ USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0cde, 0x001c) },  	/* ZyXEL */ -	{ USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) }, +	{ USB_DEVICE(0x0586, 0x3415) },  	{ 0, }  }; @@ -2455,24 +2531,21 @@ MODULE_DEVICE_TABLE(usb, rt73usb_device_table);  MODULE_FIRMWARE(FIRMWARE_RT2571);  MODULE_LICENSE("GPL"); +static int rt73usb_probe(struct usb_interface *usb_intf, +			 const struct usb_device_id *id) +{ +	return rt2x00usb_probe(usb_intf, &rt73usb_ops); +} +  static struct usb_driver rt73usb_driver = {  	.name		= KBUILD_MODNAME,  	.id_table	= rt73usb_device_table, -	.probe		= rt2x00usb_probe, +	.probe		= rt73usb_probe,  	.disconnect	= rt2x00usb_disconnect,  	.suspend	= rt2x00usb_suspend,  	.resume		= rt2x00usb_resume, +	.reset_resume	= rt2x00usb_resume, +	.disable_hub_initiated_lpm = 1,  }; -static int __init rt73usb_init(void) -{ -	return usb_register(&rt73usb_driver); -} - -static void __exit rt73usb_exit(void) -{ -	usb_deregister(&rt73usb_driver); -} - -module_init(rt73usb_init); -module_exit(rt73usb_exit); +module_usb_driver(rt73usb_driver); diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 1315ce5c992..4a4f235466d 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -13,9 +13,7 @@  	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. +	along with this program; if not, see <http://www.gnu.org/licenses/>.   */  /* @@ -267,21 +265,26 @@ struct hw_pairwise_ta_entry {  /*   * MAC_CSR13: GPIO. + *	MAC_CSR13_VALx: GPIO value + *	MAC_CSR13_DIRx: GPIO direction: 0 = input; 1 = output   */  #define MAC_CSR13			0x3034 -#define MAC_CSR13_BIT0			FIELD32(0x00000001) -#define MAC_CSR13_BIT1			FIELD32(0x00000002) -#define MAC_CSR13_BIT2			FIELD32(0x00000004) -#define MAC_CSR13_BIT3			FIELD32(0x00000008) -#define MAC_CSR13_BIT4			FIELD32(0x00000010) -#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) +#define MAC_CSR13_VAL0			FIELD32(0x00000001) +#define MAC_CSR13_VAL1			FIELD32(0x00000002) +#define MAC_CSR13_VAL2			FIELD32(0x00000004) +#define MAC_CSR13_VAL3			FIELD32(0x00000008) +#define MAC_CSR13_VAL4			FIELD32(0x00000010) +#define MAC_CSR13_VAL5			FIELD32(0x00000020) +#define MAC_CSR13_VAL6			FIELD32(0x00000040) +#define MAC_CSR13_VAL7			FIELD32(0x00000080) +#define MAC_CSR13_DIR0			FIELD32(0x00000100) +#define MAC_CSR13_DIR1			FIELD32(0x00000200) +#define MAC_CSR13_DIR2			FIELD32(0x00000400) +#define MAC_CSR13_DIR3			FIELD32(0x00000800) +#define MAC_CSR13_DIR4			FIELD32(0x00001000) +#define MAC_CSR13_DIR5			FIELD32(0x00002000) +#define MAC_CSR13_DIR6			FIELD32(0x00004000) +#define MAC_CSR13_DIR7			FIELD32(0x00008000)  /*   * MAC_CSR14: LED control register. @@ -689,10 +692,10 @@ struct hw_pairwise_ta_entry {  /*   * AIFSN_CSR: AIFSN for each EDCA AC. - * AIFSN0: For AC_BK. - * AIFSN1: For AC_BE. - * AIFSN2: For AC_VI. - * AIFSN3: For AC_VO. + * AIFSN0: For AC_VO. + * AIFSN1: For AC_VI. + * AIFSN2: For AC_BE. + * AIFSN3: For AC_BK.   */  #define AIFSN_CSR			0x0400  #define AIFSN_CSR_AIFSN0		FIELD32(0x0000000f) @@ -702,10 +705,10 @@ struct hw_pairwise_ta_entry {  /*   * CWMIN_CSR: CWmin for each EDCA AC. - * CWMIN0: For AC_BK. - * CWMIN1: For AC_BE. - * CWMIN2: For AC_VI. - * CWMIN3: For AC_VO. + * CWMIN0: For AC_VO. + * CWMIN1: For AC_VI. + * CWMIN2: For AC_BE. + * CWMIN3: For AC_BK.   */  #define CWMIN_CSR			0x0404  #define CWMIN_CSR_CWMIN0		FIELD32(0x0000000f) @@ -715,10 +718,10 @@ struct hw_pairwise_ta_entry {  /*   * CWMAX_CSR: CWmax for each EDCA AC. - * CWMAX0: For AC_BK. - * CWMAX1: For AC_BE. - * CWMAX2: For AC_VI. - * CWMAX3: For AC_VO. + * CWMAX0: For AC_VO. + * CWMAX1: For AC_VI. + * CWMAX2: For AC_BE. + * CWMAX3: For AC_BK.   */  #define CWMAX_CSR			0x0408  #define CWMAX_CSR_CWMAX0		FIELD32(0x0000000f) @@ -727,18 +730,18 @@ struct hw_pairwise_ta_entry {  #define CWMAX_CSR_CWMAX3		FIELD32(0x0000f000)  /* - * AC_TXOP_CSR0: AC_BK/AC_BE TXOP register. - * AC0_TX_OP: For AC_BK, in unit of 32us. - * AC1_TX_OP: For AC_BE, in unit of 32us. + * AC_TXOP_CSR0: AC_VO/AC_VI TXOP register. + * AC0_TX_OP: For AC_VO, in unit of 32us. + * AC1_TX_OP: For AC_VI, in unit of 32us.   */  #define AC_TXOP_CSR0			0x040c  #define AC_TXOP_CSR0_AC0_TX_OP		FIELD32(0x0000ffff)  #define AC_TXOP_CSR0_AC1_TX_OP		FIELD32(0xffff0000)  /* - * AC_TXOP_CSR1: AC_VO/AC_VI TXOP register. - * AC2_TX_OP: For AC_VI, in unit of 32us. - * AC3_TX_OP: For AC_VO, in unit of 32us. + * AC_TXOP_CSR1: AC_BE/AC_BK TXOP register. + * AC2_TX_OP: For AC_BE, in unit of 32us. + * AC3_TX_OP: For AC_BK, in unit of 32us.   */  #define AC_TXOP_CSR1			0x0410  #define AC_TXOP_CSR1_AC2_TX_OP		FIELD32(0x0000ffff)  | 
