diff options
Diffstat (limited to 'package')
26 files changed, 9495 insertions, 7694 deletions
diff --git a/package/mac80211/Makefile b/package/mac80211/Makefile index 06e15532bf..47811ff615 100644 --- a/package/mac80211/Makefile +++ b/package/mac80211/Makefile @@ -13,8 +13,8 @@ PKG_NAME:=mac80211 PKG_RELEASE:=1 ifneq ($(CONFIG_LINUX_2_6_27),) - PKG_VERSION:=2008-10-08 - PKG_SOURCE_URL:=http://www.orbit-lab.org/kernel/compat-wireless-2.6/2008/10 + PKG_VERSION:=2008-11-03 + PKG_SOURCE_URL:=http://www.orbit-lab.org/kernel/compat-wireless-2.6/2008/11 else PKG_VERSION:=2008-08-06 PKG_SOURCE_URL:=http://www.orbit-lab.org/kernel/compat-wireless-2.6/2008/08 @@ -25,6 +25,7 @@ PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2 PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION) include $(INCLUDE_DIR)/package.mk +STAMP_CONFIGURED:=$(STAMP_CONFIGURED)_$(call confvar,CONFIG_PACKAGE_kmod-mac80211) define KernelPackage/mac80211 SUBMENU:=Wireless Drivers diff --git a/package/mac80211/patches/110-ath5k_stat.patch b/package/mac80211/patches/110-ath5k_stat.patch deleted file mode 100644 index 2c8d2f98b3..0000000000 --- a/package/mac80211/patches/110-ath5k_stat.patch +++ /dev/null @@ -1,53 +0,0 @@ -This patch removes the unnecessary ATH_STAT_MRRETRY flag and turns -other ATH_STAT_* defines into an enum - -Signed-off-by: Felix Fietkau <nbd@openwrt.org> - ---- a/drivers/net/wireless/ath5k/base.c -+++ b/drivers/net/wireless/ath5k/base.c -@@ -724,19 +724,6 @@ ath5k_attach(struct pci_dev *pdev, struc - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); - - /* -- * Check if the MAC has multi-rate retry support. -- * We do this by trying to setup a fake extended -- * descriptor. MAC's that don't have support will -- * return false w/o doing anything. MAC's that do -- * support it will return true w/o doing anything. -- */ -- ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); -- if (ret < 0) -- goto err; -- if (ret > 0) -- __set_bit(ATH_STAT_MRRETRY, sc->status); -- -- /* - * Reset the key cache since some parts do not - * reset the contents on initial power up. - */ ---- a/drivers/net/wireless/ath5k/base.h -+++ b/drivers/net/wireless/ath5k/base.h -@@ -99,6 +99,12 @@ struct ath5k_led - #define ATH_CHAN_MAX (14+14+14+252+20) - #endif - -+enum { -+ ATH_STAT_INVALID, /* disable hardware accesses */ -+ ATH_STAT_PROMISC, -+ ATH_STAT_LEDSOFT /* enable LED gpio status */ -+}; -+ - /* Software Carrier, keeps track of the driver state - * associated with an instance of a device */ - struct ath5k_softc { -@@ -129,10 +135,6 @@ struct ath5k_softc { - u16 cachelsz; /* cache line size */ - - DECLARE_BITMAP(status, 4); --#define ATH_STAT_INVALID 0 /* disable hardware accesses */ --#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ --#define ATH_STAT_PROMISC 2 --#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ - - unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ - unsigned int curmode; /* current phy mode */ diff --git a/package/mac80211/patches/210-remove_unused_stuff.patch b/package/mac80211/patches/210-remove_unused_stuff.patch index 044dc837e1..11a0dc5613 100644 --- a/package/mac80211/patches/210-remove_unused_stuff.patch +++ b/package/mac80211/patches/210-remove_unused_stuff.patch @@ -1,6 +1,6 @@ --- a/config.mk +++ b/config.mk -@@ -99,12 +99,12 @@ CONFIG_B43LEGACY_PIO=y +@@ -108,12 +108,12 @@ CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y # The Intel ipws @@ -19,7 +19,7 @@ # The above enables use a second interface prefixed 'rtap'. # Example usage: # -@@ -117,9 +117,9 @@ CONFIG_IPW2200_PROMISCUOUS=y +@@ -126,9 +126,9 @@ CONFIG_IPW2200_PROMISCUOUS=y # it on via sysfs: # # % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface @@ -31,7 +31,7 @@ CONFIG_P54_PCI=m -@@ -216,8 +216,8 @@ CONFIG_SSB_PCICORE_HOSTMODE=n +@@ -227,8 +227,8 @@ CONFIG_SSB_PCICORE_HOSTMODE=n # CONFIG_SSB_DRIVER_EXTIF=y ifneq ($(CONFIG_USB),) diff --git a/package/mac80211/patches/300-arm_alignment_fix.patch b/package/mac80211/patches/300-arm_alignment_fix.patch new file mode 100644 index 0000000000..1de5ed48e4 --- /dev/null +++ b/package/mac80211/patches/300-arm_alignment_fix.patch @@ -0,0 +1,21 @@ +On ARM alignment is done slightly different from other architectures. +struct ieee80211_tx_rate is aligned to word size, even though it only has 3 +single-byte members, which triggers the BUILD_BUG_ON in +ieee80211_tx_info_clear_status + +This patch marks the struct ieee80211_tx_rate as packed, so that ARM +behaves like the other architectures. + +Signed-off-by: Felix Fietkau <nbd@openwrt.org> + +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -299,7 +299,7 @@ struct ieee80211_tx_rate { + s8 idx; + u8 count; + u8 flags; +-}; ++} __attribute__((packed)); + + /** + * struct ieee80211_tx_info - skb transmit information diff --git a/package/mac80211/patches/310-rt2800_experimental.patch b/package/mac80211/patches/310-rt2800_experimental.patch new file mode 100644 index 0000000000..90d41bd8d7 --- /dev/null +++ b/package/mac80211/patches/310-rt2800_experimental.patch @@ -0,0 +1,9458 @@ +automatically generated from wireless-testing..rt2x00/experimental +do not edit + +--- a/drivers/net/wireless/rt2x00/Makefile ++++ b/drivers/net/wireless/rt2x00/Makefile +@@ -14,5 +14,7 @@ obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00u + obj-$(CONFIG_RT2400PCI) += rt2400pci.o + obj-$(CONFIG_RT2500PCI) += rt2500pci.o + obj-$(CONFIG_RT61PCI) += rt61pci.o ++obj-$(CONFIG_RT2800PCI) += rt2800pci.o + obj-$(CONFIG_RT2500USB) += rt2500usb.o + obj-$(CONFIG_RT73USB) += rt73usb.o ++obj-$(CONFIG_RT2800USB) += rt2800usb.o +--- a/drivers/net/wireless/rt2x00/rt2500usb.c ++++ b/drivers/net/wireless/rt2x00/rt2500usb.c +@@ -36,6 +36,13 @@ + #include "rt2500usb.h" + + /* ++ * Allow hardware encryption to be disabled. ++ */ ++static int modparam_nohwcrypt = 0; ++module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); ++MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); ++ ++/* + * Register access. + * All access to the CSR registers will go through the methods + * rt2500usb_register_read and rt2500usb_register_write. +@@ -343,6 +350,85 @@ static void rt2500usb_init_led(struct rt + /* + * Configuration handlers. + */ ++ ++/* ++ * rt2500usb does not differentiate between shared and pairwise ++ * keys, so we should use the same function for both key types. ++ */ ++static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_crypto *crypto, ++ struct ieee80211_key_conf *key) ++{ ++ int timeout; ++ u32 mask; ++ u16 reg; ++ ++ /* Support up to 4 keys */ ++ if (key->hw_key_idx >= 4) ++ return -ENOSPC; ++ ++ if (crypto->cmd == SET_KEY) { ++ /* ++ * Pairwise key will always be entry 0, but this ++ * could collide with a shared key on the same ++ * position... ++ */ ++ mask = TXRX_CSR0_KEY_ID.bit_mask; ++ ++ rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); ++ ++ if ((reg & mask) && (reg & mask) == mask) ++ return -ENOSPC; ++ ++ reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); ++ ++ key->hw_key_idx += reg ? ffz(reg) : 0; ++ ++ /* ++ * The encryption key doesn't fit within the CSR cache, ++ * this means we should allocate it seperately and use ++ * rt2x00usb_vendor_request() to send the key to the hardware. ++ */ ++ reg = KEY_ENTRY(key->hw_key_idx); ++ timeout = REGISTER_TIMEOUT32(sizeof(crypto->key)); ++ rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, ++ USB_VENDOR_REQUEST_OUT, reg, ++ crypto->key, ++ sizeof(crypto->key), ++ timeout); ++ ++ /* ++ * The driver does not support the IV/EIV generation ++ * in hardware. However it doesn't support the IV/EIV ++ * inside the ieee80211 frame either, but requires it ++ * to be provided seperately for the descriptor. ++ * rt2x00lib will cut the IV/EIV data out of all frames ++ * given to us by mac80211, but we must tell mac80211 ++ * to generate the IV/EIV data. ++ */ ++ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; ++ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; ++ } ++ ++ /* ++ * TXRX_CSR0_KEY_ID contains only single-bit fields to indicate ++ * a particular key is valid. ++ */ ++ rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); ++ rt2x00_set_field16(®, TXRX_CSR0_ALGORITHM, crypto->cipher); ++ rt2x00_set_field16(®, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER); ++ ++ mask = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); ++ if (crypto->cmd == SET_KEY) ++ mask |= 1 << key->hw_key_idx; ++ else if (crypto->cmd == DISABLE_KEY) ++ mask &= ~(1 << key->hw_key_idx); ++ rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, mask); ++ rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg); ++ ++ return 0; ++} ++ + static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) + { +@@ -864,7 +950,7 @@ static int rt2500usb_init_registers(stru + + rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field16(®, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER); +- rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, 0xff); ++ rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg); + + rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); +@@ -1086,7 +1172,7 @@ static void rt2500usb_write_tx_desc(stru + * Start writing the descriptor words. + */ + rt2x00_desc_read(txd, 1, &word); +- rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); ++ rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); + rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); +@@ -1099,6 +1185,11 @@ static void rt2500usb_write_tx_desc(stru + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); + rt2x00_desc_write(txd, 2, word); + ++ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { ++ _rt2x00_desc_write(txd, 3, skbdesc->iv); ++ _rt2x00_desc_write(txd, 4, skbdesc->eiv); ++ } ++ + rt2x00_desc_read(txd, 0, &word); + rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit); + rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, +@@ -1113,7 +1204,8 @@ static void rt2500usb_write_tx_desc(stru + test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); +- rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE); ++ rt2x00_set_field32(&word, TXD_W0_CIPHER, txdesc->cipher); ++ rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx); + rt2x00_desc_write(txd, 0, word); + } + +@@ -1225,6 +1317,7 @@ static void rt2500usb_kick_tx_queue(stru + static void rt2500usb_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) + { ++ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct queue_entry_priv_usb *entry_priv = entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + __le32 *rxd = +@@ -1252,6 +1345,31 @@ static void rt2500usb_fill_rxdone(struct + if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) + rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; + ++ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { ++ rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER); ++ if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR)) ++ rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY; ++ } ++ ++ if (rxdesc->cipher != CIPHER_NONE) { ++ _rt2x00_desc_read(rxd, 2, &rxdesc->iv); ++ _rt2x00_desc_read(rxd, 3, &rxdesc->eiv); ++ /* ICV is located at the end of frame */ ++ ++ /* ++ * Hardware has stripped IV/EIV data from 802.11 frame during ++ * decryption. It has provided the data seperately but rt2x00lib ++ * should decide if it should be reinserted. ++ */ ++ rxdesc->flags |= RX_FLAG_IV_STRIPPED; ++ if (rxdesc->cipher != CIPHER_TKIP) ++ 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; ++ } ++ + /* + * Obtain the status about this packet. + * When frame was received with an OFDM bitrate, +@@ -1259,8 +1377,8 @@ static void rt2500usb_fill_rxdone(struct + * a CCK bitrate the signal is the rate in 100kbit/s. + */ + rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); +- rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - +- entry->queue->rt2x00dev->rssi_offset; ++ rxdesc->rssi = ++ rt2x00_get_field32(word1, RXD_W1_RSSI) - rt2x00dev->rssi_offset; + rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + + if (rt2x00_get_field32(word0, RXD_W0_OFDM)) +@@ -1750,6 +1868,8 @@ static int rt2500usb_probe_hw(struct rt2 + __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); ++ if (!modparam_nohwcrypt) ++ __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); + __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); + + /* +@@ -1769,6 +1889,7 @@ static const struct ieee80211_ops rt2500 + .config = rt2x00mac_config, + .config_interface = rt2x00mac_config_interface, + .configure_filter = rt2x00mac_configure_filter, ++ .set_key = rt2x00mac_set_key, + .get_stats = rt2x00mac_get_stats, + .bss_info_changed = rt2x00mac_bss_info_changed, + .conf_tx = rt2x00mac_conf_tx, +@@ -1791,6 +1912,8 @@ static const struct rt2x00lib_ops rt2500 + .get_tx_data_len = rt2500usb_get_tx_data_len, + .kick_tx_queue = rt2500usb_kick_tx_queue, + .fill_rxdone = rt2500usb_fill_rxdone, ++ .config_shared_key = rt2500usb_config_key, ++ .config_pairwise_key = rt2500usb_config_key, + .config_filter = rt2500usb_config_filter, + .config_intf = rt2500usb_config_intf, + .config_erp = rt2500usb_config_erp, +--- a/drivers/net/wireless/rt2x00/rt2500usb.h ++++ b/drivers/net/wireless/rt2x00/rt2500usb.h +@@ -447,6 +447,9 @@ + #define SEC_CSR30 0x04bc + #define SEC_CSR31 0x04be + ++#define KEY_ENTRY(__idx) \ ++ ( SEC_CSR0 + ((__idx) * 16) ) ++ + /* + * PHY control registers. + */ +--- /dev/null ++++ b/drivers/net/wireless/rt2x00/rt2800pci.c +@@ -0,0 +1,2556 @@ ++/* ++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project ++ <http://rt2x00.serialmonkey.com> ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the ++ Free Software Foundation, Inc., ++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++/* ++ Module: rt2800pci ++ Abstract: rt2800pci device specific routines. ++ Supported chipsets: RT2800E & RT2800ED. ++ */ ++ ++#include <linux/crc-ccitt.h> ++#include <linux/delay.h> ++#include <linux/etherdevice.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/pci.h> ++#include <linux/eeprom_93cx6.h> ++ ++#include "rt2x00.h" ++#include "rt2x00pci.h" ++#include "rt2800pci.h" ++ ++/* ++ * Allow hardware encryption to be disabled. ++ */ ++static int modparam_nohwcrypt = 0; ++module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); ++MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); ++ ++/* ++ * Register access. ++ * BBP and RF register require indirect register access, ++ * and use the CSR registers PHY_CSR3 and PHY_CSR4 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, ++ * the access attempt is considered to have failed, ++ * and we will print an error. ++ */ ++static u32 rt2800pci_bbp_check(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ unsigned int i; ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2x00pci_register_read(rt2x00dev, BBP_CSR_CFG, ®); ++ if (!rt2x00_get_field32(reg, BBP_CSR_CFG_BUSY)) ++ break; ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ return reg; ++} ++ ++static void rt2800pci_bbp_write(struct rt2x00_dev *rt2x00dev, ++ const unsigned int word, const u8 value) ++{ ++ u32 reg; ++ ++ /* ++ * Wait until the BBP becomes ready. ++ */ ++ reg = rt2800pci_bbp_check(rt2x00dev); ++ if (rt2x00_get_field32(reg, BBP_CSR_CFG_BUSY)) { ++ ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); ++ return; ++ } ++ ++ /* ++ * Write the data into the BBP. ++ */ ++ reg = 0; ++ rt2x00_set_field32(®, BBP_CSR_CFG_VALUE, value); ++ rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); ++ rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); ++ rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); ++ rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); ++ ++ rt2x00pci_register_write(rt2x00dev, BBP_CSR_CFG, reg); ++} ++ ++static void rt2800pci_bbp_read(struct rt2x00_dev *rt2x00dev, ++ const unsigned int word, u8 *value) ++{ ++ u32 reg; ++ ++ /* ++ * Wait until the BBP becomes ready. ++ */ ++ reg = rt2800pci_bbp_check(rt2x00dev); ++ if (rt2x00_get_field32(reg, BBP_CSR_CFG_BUSY)) { ++ ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); ++ return; ++ } ++ ++ /* ++ * Write the request into the BBP. ++ */ ++ reg = 0; ++ rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); ++ rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); ++ rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); ++ rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1); ++ ++ rt2x00pci_register_write(rt2x00dev, BBP_CSR_CFG, reg); ++ ++ /* ++ * Wait until the BBP becomes ready. ++ */ ++ reg = rt2800pci_bbp_check(rt2x00dev); ++ if (rt2x00_get_field32(reg, BBP_CSR_CFG_BUSY)) { ++ ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); ++ *value = 0xff; ++ return; ++ } ++ ++ *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE); ++} ++ ++static void rt2800pci_rf_write(struct rt2x00_dev *rt2x00dev, ++ const unsigned int word, const u32 value) ++{ ++ u32 reg; ++ unsigned int i; ++ ++ if (!word) ++ return; ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2x00pci_register_read(rt2x00dev, RF_CSR_CFG0, ®); ++ if (!rt2x00_get_field32(reg, RF_CSR_CFG0_BUSY)) ++ goto rf_write; ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ ERROR(rt2x00dev, "RF_CSR_CFG0 register busy. Write failed.\n"); ++ return; ++ ++rf_write: ++ reg = 0; ++ rt2x00_set_field32(®, RF_CSR_CFG0_REG_VALUE_BW, value); ++ rt2x00_set_field32(®, RF_CSR_CFG0_STANDBYMODE, 0); ++ rt2x00_set_field32(®, RF_CSR_CFG0_SEL, 0); ++ rt2x00_set_field32(®, RF_CSR_CFG0_BUSY, 1); ++ ++ rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG0, reg); ++ rt2x00_rf_write(rt2x00dev, word, value); ++} ++ ++static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) ++{ ++ struct rt2x00_dev *rt2x00dev = eeprom->data; ++ u32 reg; ++ ++ rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); ++ ++ eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); ++ eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); ++ eeprom->reg_data_clock = ++ !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_CLOCK); ++ eeprom->reg_chip_select = ++ !!rt2x00_get_field32(reg, E2PROM_CSR_CHIP_SELECT); ++} ++ ++static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom) ++{ ++ struct rt2x00_dev *rt2x00dev = eeprom->data; ++ u32 reg = 0; ++ ++ rt2x00_set_field32(®, E2PROM_CSR_DATA_IN, !!eeprom->reg_data_in); ++ rt2x00_set_field32(®, E2PROM_CSR_DATA_OUT, !!eeprom->reg_data_out); ++ rt2x00_set_field32(®, E2PROM_CSR_DATA_CLOCK, ++ !!eeprom->reg_data_clock); ++ rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, ++ !!eeprom->reg_chip_select); ++ ++ rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); ++} ++ ++static void rt2800pci_mcu_request(struct rt2x00_dev *rt2x00dev, ++ const u8 command, const u8 token, ++ const u8 arg0, const u8 arg1) ++{ ++ unsigned int i; ++ u32 reg; ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CSR, ®); ++ if (!rt2x00_get_field32(reg, H2M_MAILBOX_CSR_OWNER)) ++ goto mcu_write; ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ ERROR(rt2x00dev, "mcu request error. " ++ "Request 0x%02x failed for token 0x%02x.\n", ++ command, token); ++ return; ++ ++mcu_write: ++ rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); ++ 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); ++ ++ reg = 0; ++ rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); ++ rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); ++} ++ ++#ifdef CONFIG_RT2X00_LIB_DEBUGFS ++static const struct rt2x00debug rt2800pci_rt2x00debug = { ++ .owner = THIS_MODULE, ++ .csr = { ++ .read = rt2x00pci_register_read, ++ .write = rt2x00pci_register_write, ++ .flags = RT2X00DEBUGFS_OFFSET, ++ .word_base = CSR_REG_BASE, ++ .word_size = sizeof(u32), ++ .word_count = CSR_REG_SIZE / sizeof(u32), ++ }, ++ .eeprom = { ++ .read = rt2x00_eeprom_read, ++ .write = rt2x00_eeprom_write, ++ .word_base = EEPROM_BASE, ++ .word_size = sizeof(u16), ++ .word_count = EEPROM_SIZE / sizeof(u16), ++ }, ++ .bbp = { ++ .read = rt2800pci_bbp_read, ++ .write = rt2800pci_bbp_write, ++ .word_base = BBP_BASE, ++ .word_size = sizeof(u8), ++ .word_count = BBP_SIZE / sizeof(u8), ++ }, ++ .rf = { ++ .read = rt2x00_rf_read, ++ .write = rt2800pci_rf_write, ++ .word_base = RF_BASE, ++ .word_size = sizeof(u32), ++ .word_count = RF_SIZE / sizeof(u32), ++ }, ++}; ++#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ ++ ++#ifdef CONFIG_RT2X00_LIB_RFKILL ++static int rt2800pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ ++ rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); ++ return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); ++} ++#else ++#define rt2800pci_rfkill_poll NULL ++#endif /* CONFIG_RT2X00_LIB_RFKILL */ ++ ++#ifdef CONFIG_RT2X00_LIB_LEDS ++static void rt2800pci_brightness_set(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct rt2x00_led *led = ++ container_of(led_cdev, struct rt2x00_led, led_dev); ++ unsigned int enabled = brightness != LED_OFF; ++ unsigned int bg_mode = ++ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); ++ unsigned int polarity = ++ rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, ++ EEPROM_FREQ_LED_POLARITY); ++ unsigned int ledmode = ++ rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, ++ EEPROM_FREQ_LED_MODE); ++ ++ if (led->type == LED_TYPE_RADIO) { ++ rt2800pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, ++ enabled ? 0x20 : 0); ++ } else if (led->type == LED_TYPE_ASSOC) { ++ rt2800pci_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 ++ */ ++ rt2800pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, ++ (1 << brightness / (LED_FULL / 6)) - 1, ++ polarity); ++ } ++} ++ ++static int rt2800pci_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; ++ ++ rt2x00pci_register_read(led->rt2x00dev, LED_CFG, ®); ++ rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); ++ rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); ++ rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); ++ rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); ++ rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); ++ rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); ++ rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); ++ rt2x00pci_register_write(led->rt2x00dev, LED_CFG, reg); ++ ++ return 0; ++} ++ ++static void rt2800pci_init_led(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00_led *led, ++ enum led_type type) ++{ ++ led->rt2x00dev = rt2x00dev; ++ led->type = type; ++ led->led_dev.brightness_set = rt2800pci_brightness_set; ++ led->led_dev.blink_set = rt2800pci_blink_set; ++ led->flags = LED_INITIALIZED; ++} ++#endif /* CONFIG_RT2X00_LIB_LEDS */ ++ ++/* ++ * Configuration handlers. ++ */ ++static void rt2800pci_config_wcid_attr(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_crypto *crypto, ++ struct ieee80211_key_conf *key) ++{ ++ u32 offset; ++ u32 reg; ++ ++ offset = MAC_WCID_ATTR_ENTRY(crypto->aid); ++ ++ reg = 0; ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, ++ !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_PAIRKEY_MODE, ++ crypto->cipher); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, ++ (crypto->cmd == SET_KEY) ? crypto->bssidx : 0); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0); ++ rt2x00pci_register_write(rt2x00dev, offset, reg); ++} ++ ++static int rt2800pci_config_shared_key(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_crypto *crypto, ++ struct ieee80211_key_conf *key) ++{ ++ struct hw_key_entry key_entry; ++ struct rt2x00_field32 field; ++ u32 offset; ++ u32 mask; ++ u32 reg; ++ ++ if (crypto->cmd == SET_KEY) { ++ memcpy(key_entry.key, crypto->key, ++ sizeof(key_entry.key)); ++ memcpy(key_entry.tx_mic, crypto->tx_mic, ++ sizeof(key_entry.tx_mic)); ++ memcpy(key_entry.rx_mic, crypto->rx_mic, ++ sizeof(key_entry.rx_mic)); ++ ++ offset = SHARED_KEY_ENTRY(key->hw_key_idx); ++ rt2x00pci_register_multiwrite(rt2x00dev, offset, ++ &key_entry, sizeof(key_entry)); ++ ++ /* ++ * The driver does not support the IV/EIV generation ++ * in hardware. However it doesn't support the IV/EIV ++ * inside the ieee80211 frame either, but requires it ++ * to be provided seperately for the descriptor. ++ * rt2x00lib will cut the IV/EIV data out of all frames ++ * given to us by mac80211, but we must tell mac80211 ++ * to generate the IV/EIV data. ++ */ ++ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; ++ } ++ ++ /* ++ * The cipher types are stored over multiple registers ++ * starting with SHARED_KEY_MODE_BASE each word will have ++ * 32 bits and contains the cipher types for 2 modes each. ++ * Using the correct defines correctly will cause overhead, ++ * so just calculate the correct offset. ++ */ ++ mask = key->hw_key_idx % 8; ++ field.bit_offset = (3 * mask); ++ field.bit_mask = 0x7 << field.bit_offset; ++ ++ offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); ++ rt2x00pci_register_read(rt2x00dev, offset, ®); ++ rt2x00_set_field32(®, field, ++ (crypto->cmd == SET_KEY) ? crypto->cipher : 0); ++ rt2x00pci_register_write(rt2x00dev, offset, reg); ++ ++ /* ++ * Update WCID information ++ */ ++ rt2800pci_config_wcid_attr(rt2x00dev, crypto, key); ++ ++ return 0; ++} ++ ++static int rt2800pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_crypto *crypto, ++ struct ieee80211_key_conf *key) ++{ ++ struct hw_key_entry key_entry; ++ u32 offset; ++ ++ /* ++ * 1 pairwise key is possible per AID, this means that the AID ++ * equals our hw_key_idx. ++ */ ++ key->hw_key_idx = crypto->aid; ++ ++ if (crypto->cmd == SET_KEY) { ++ memcpy(key_entry.key, crypto->key, ++ sizeof(key_entry.key)); ++ memcpy(key_entry.tx_mic, crypto->tx_mic, ++ sizeof(key_entry.tx_mic)); ++ memcpy(key_entry.rx_mic, crypto->rx_mic, ++ sizeof(key_entry.rx_mic)); ++ ++ offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); ++ rt2x00pci_register_multiwrite(rt2x00dev, offset, ++ &key_entry, sizeof(key_entry)); ++ ++ /* ++ * The driver does not support the IV/EIV generation ++ * in hardware. However it doesn't support the IV/EIV ++ * inside the ieee80211 frame either, but requires it ++ * to be provided seperately for the descriptor. ++ * rt2x00lib will cut the IV/EIV data out of all frames ++ * given to us by mac80211, but we must tell mac80211 ++ * to generate the IV/EIV data. ++ */ ++ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; ++ } ++ ++ /* ++ * Update WCID information ++ */ ++ rt2800pci_config_wcid_attr(rt2x00dev, crypto, key); ++ ++ return 0; ++} ++ ++static void rt2800pci_config_filter(struct rt2x00_dev *rt2x00dev, ++ const unsigned int filter_flags) ++{ ++ u32 reg; ++ ++ /* ++ * Start configuration steps. ++ * Note that the version error will always be dropped ++ * and broadcast frames will always be accepted since ++ * there is no filter for it at this time. ++ */ ++ rt2x00pci_register_read(rt2x00dev, RX_FILTER_CFG, ®); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, ++ !(filter_flags & FIF_FCSFAIL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, ++ !(filter_flags & FIF_PLCPFAIL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, ++ !(filter_flags & FIF_PROMISC_IN_BSS)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, ++ !(filter_flags & FIF_ALLMULTI)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 1); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00pci_register_write(rt2x00dev, RX_FILTER_CFG, reg); ++} ++ ++static void rt2800pci_config_intf(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00_intf *intf, ++ 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, 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, 1); ++ rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); ++ } ++ ++ if (flags & CONFIG_UPDATE_MAC) { ++ reg = le32_to_cpu(conf->mac[1]); ++ rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); ++ conf->mac[1] = cpu_to_le32(reg); ++ ++ rt2x00pci_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, ++ conf->mac, sizeof(conf->mac)); ++ } ++ ++ if (flags & CONFIG_UPDATE_BSSID) { ++ reg = le32_to_cpu(conf->bssid[1]); ++ rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); ++ rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); ++ conf->bssid[1] = cpu_to_le32(reg); ++ ++ rt2x00pci_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, ++ conf->bssid, sizeof(conf->bssid)); ++ } ++} ++ ++static void rt2800pci_config_erp(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_erp *erp) ++{ ++ u32 reg; ++ ++ rt2x00pci_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); ++ rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, ++ erp->ack_timeout); ++ rt2x00pci_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, AUTO_RSP_CFG, ®); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, ++ !!erp->short_preamble); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, ++ !!erp->short_preamble); ++ rt2x00pci_register_write(rt2x00dev, AUTO_RSP_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, OFDM_PROT_CFG, ®); ++ rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, ++ erp->cts_protection ? 2 : 0); ++ rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg); ++ ++ rt2x00pci_register_write(rt2x00dev, LEGACY_BASIC_RATE, ++ erp->basic_rates); ++ rt2x00pci_register_write(rt2x00dev, HT_BASIC_RATE, ++ erp->basic_rates >> 32); ++ ++ rt2x00pci_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); ++ rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); ++ rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); ++ rt2x00pci_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, XIFS_TIME_CFG, ®); ++ rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); ++ rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); ++ rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); ++ rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); ++ rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); ++ rt2x00pci_register_write(rt2x00dev, XIFS_TIME_CFG, reg); ++} ++ ++static void rt2800pci_config_ant(struct rt2x00_dev *rt2x00dev, ++ struct antenna_setup *ant) ++{ ++ u16 eeprom; ++ u8 r1; ++ u8 r3; ++ ++ /* ++ * FIXME: Use requested antenna configuration. ++ */ ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); ++ ++ rt2800pci_bbp_read(rt2x00dev, 1, &r1); ++ rt2800pci_bbp_read(rt2x00dev, 3, &r3); ++ ++ /* ++ * Configure the TX antenna. ++ */ ++ switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH)) { ++ case 1: ++ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); ++ break; ++ case 2: ++ case 3: ++ /* Do nothing */ ++ break; ++ } ++ ++ /* ++ * Configure the RX antenna. ++ */ ++ switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { ++ case 1: ++ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); ++ break; ++ case 2: ++ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); ++ break; ++ case 3: ++ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); ++ break; ++ } ++ ++ rt2800pci_bbp_write(rt2x00dev, 3, r3); ++ rt2800pci_bbp_write(rt2x00dev, 1, r1); ++} ++ ++static void rt2800pci_config_lna_gain(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_conf *libconf) ++{ ++ u16 eeprom; ++ short lna_gain; ++ ++ if (libconf->rf.channel <= 14) { ++ rt2x00_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); ++ 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); ++ } else { ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); ++ lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); ++ } ++ ++ rt2x00dev->lna_gain = lna_gain; ++} ++ ++static void rt2800pci_config_channel(struct rt2x00_dev *rt2x00dev, ++ struct rf_channel *rf, ++ struct channel_info *info) ++{ ++ u32 reg; ++ unsigned int tx_pin; ++ u16 eeprom; ++ ++ tx_pin = 0; ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); ++ 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_LNA_PE_A1_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_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(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); ++ ++ /* ++ * Determine antenna settings from EEPROM ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); ++ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) { ++ rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); ++ /* Turn off unused PA or LNA when only 1T or 1R */ ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 0); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 0); ++ } ++ ++ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) { ++ rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); ++ rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); ++ /* Turn off unused PA or LNA when only 1T or 1R */ ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 0); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 0); ++ } else if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 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). ++ * However this means that values between 0 and 7 have ++ * double meaning, and we should set a 7DBm boost flag. ++ */ ++ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, ++ (info->tx_power1 >= 0)); ++ ++ if (info->tx_power1 < 0) ++ info->tx_power1 += 7; ++ ++ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, ++ TXPOWER_A_TO_DEV(info->tx_power1)); ++ ++ rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, ++ (info->tx_power2 >= 0)); ++ ++ if (info->tx_power2 < 0) ++ info->tx_power2 += 7; ++ ++ rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, ++ TXPOWER_A_TO_DEV(info->tx_power2)); ++ ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 1); ++ } else { ++ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, ++ TXPOWER_G_TO_DEV(info->tx_power1)); ++ rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, ++ TXPOWER_G_TO_DEV(info->tx_power2)); ++ ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); ++ } ++ ++ /* FIXME: How to determine bandwidth ++ rt2x00_set_field32(&rf->rf4, RF4_BW40, !!(BBPCurrentBW == BW_40)); ++ */ ++ ++ rt2800pci_rf_write(rt2x00dev, 1, rf->rf1); ++ rt2800pci_rf_write(rt2x00dev, 2, rf->rf2); ++ rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); ++ rt2800pci_rf_write(rt2x00dev, 4, rf->rf4); ++ ++ udelay(200); ++ ++ rt2800pci_rf_write(rt2x00dev, 1, rf->rf1); ++ rt2800pci_rf_write(rt2x00dev, 2, rf->rf2); ++ rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); ++ rt2800pci_rf_write(rt2x00dev, 4, rf->rf4); ++ ++ udelay(200); ++ ++ rt2800pci_rf_write(rt2x00dev, 1, rf->rf1); ++ rt2800pci_rf_write(rt2x00dev, 2, rf->rf2); ++ rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); ++ rt2800pci_rf_write(rt2x00dev, 4, rf->rf4); ++ ++ /* ++ * Change BBP settings ++ */ ++ rt2800pci_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); ++ rt2800pci_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); ++ rt2800pci_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); ++ rt2800pci_bbp_write(rt2x00dev, 86, 0); ++ ++ if (rf->channel <= 14) { ++ if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { ++ rt2800pci_bbp_write(rt2x00dev, 82, 0x62); ++ rt2800pci_bbp_write(rt2x00dev, 75, 0x46); ++ } else { ++ rt2800pci_bbp_write(rt2x00dev, 82, 0x84); ++ rt2800pci_bbp_write(rt2x00dev, 75, 0x50); ++ } ++ ++ rt2x00pci_register_read(rt2x00dev, TX_BAND_CFG, ®); ++ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_A, 0); ++ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_BG, 1); ++ rt2x00pci_register_write(rt2x00dev, TX_BAND_CFG, reg); ++ } else { ++ rt2800pci_bbp_write(rt2x00dev, 82, 0xf2); ++ ++ if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) ++ rt2800pci_bbp_write(rt2x00dev, 75, 0x46); ++ else ++ rt2800pci_bbp_write(rt2x00dev, 75, 0x50); ++ ++ rt2x00pci_register_read(rt2x00dev, TX_BAND_CFG, ®); ++ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_A, 1); ++ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_BG, 0); ++ rt2x00pci_register_write(rt2x00dev, TX_BAND_CFG, reg); ++ } ++ ++ rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); ++ ++ msleep(1); ++} ++ ++static void rt2800pci_config_txpower(struct rt2x00_dev *rt2x00dev, ++ const int txpower) ++{ ++ u32 reg; ++ u32 value = TXPOWER_G_TO_DEV(txpower); ++ u8 r1; ++ ++ rt2800pci_bbp_read(rt2x00dev, 1, &r1); ++ rt2x00_set_field8(®, BBP1_TX_POWER, 0); ++ rt2800pci_bbp_write(rt2x00dev, 1, r1); ++ ++ rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_0, ®); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); ++ rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_0, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_1, ®); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); ++ rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_1, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_2, ®); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); ++ rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_2, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_3, ®); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); ++ rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_3, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_4, ®); ++ rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); ++ rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_4, reg); ++} ++ ++static void rt2800pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_conf *libconf) ++{ ++ u32 reg; ++ ++ rt2x00pci_register_read(rt2x00dev, TX_RTY_CFG, ®); ++ rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, ++ libconf->conf->short_frame_max_tx_count); ++ rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, ++ libconf->conf->long_frame_max_tx_count); ++ rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); ++ rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); ++ rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); ++ rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); ++ rt2x00pci_register_write(rt2x00dev, TX_RTY_CFG, reg); ++} ++ ++static void rt2800pci_config_duration(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_conf *libconf) ++{ ++ u32 reg; ++ ++ rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); ++ rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, ++ libconf->conf->beacon_int * 16); ++ rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); ++} ++ ++static void rt2800pci_config(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_conf *libconf, ++ const unsigned int flags) ++{ ++ /* Always recalculate LNA gain before changing configuration */ ++ rt2800pci_config_lna_gain(rt2x00dev, libconf); ++ ++ if (flags & IEEE80211_CONF_CHANGE_CHANNEL) ++ rt2800pci_config_channel(rt2x00dev, &libconf->rf, ++ &libconf->channel); ++ if (flags & IEEE80211_CONF_CHANGE_POWER) ++ rt2800pci_config_txpower(rt2x00dev, libconf->conf->power_level); ++ if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) ++ rt2800pci_config_retry_limit(rt2x00dev, libconf); ++ if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) ++ rt2800pci_config_duration(rt2x00dev, libconf); ++} ++ ++/* ++ * Link tuning ++ */ ++static void rt2800pci_link_stats(struct rt2x00_dev *rt2x00dev, ++ struct link_qual *qual) ++{ ++ u32 reg; ++ ++ /* ++ * Update FCS error count from register. ++ */ ++ rt2x00pci_register_read(rt2x00dev, RX_STA_CNT0, ®); ++ qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); ++ ++ /* ++ * Update False CCA count from register. ++ */ ++ rt2x00pci_register_read(rt2x00dev, RX_STA_CNT1, ®); ++ qual->false_cca = rt2x00_get_field32(reg, RX_STA_CNT1_FALSE_CCA); ++} ++ ++static void rt2800pci_reset_tuner(struct rt2x00_dev *rt2x00dev) ++{ ++ u8 r66; ++ ++ if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) ++ r66 = 0x2e + rt2x00dev->lna_gain; ++ else { ++ if (1 /* FIXME: pAd->CommonCfg.BBPCurrentBW == BW_20 */) ++ r66 = 0x32 + (rt2x00dev->lna_gain * 5) / 3; ++ else ++ r66 = 0x3a + (rt2x00dev->lna_gain * 5) / 3; ++ } ++ ++ rt2800pci_bbp_write(rt2x00dev, 66, r66); ++} ++ ++static void rt2800pci_link_tuner(struct rt2x00_dev *rt2x00dev) ++{ ++ int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); ++ u8 r66_orig; ++ u8 r66; ++ ++ if (rt2x00_rev(&rt2x00dev->chip) == RT2860_VERSION_C) ++ return; ++ ++ rt2800pci_bbp_read(rt2x00dev, 66, &r66_orig); ++ r66 = r66_orig; ++ ++ if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { ++ r66 = 0x2e + rt2x00dev->lna_gain; ++ } else { ++ if (1 /* FIXME: pAd->CommonCfg.BBPCurrentBW == BW_20 */) ++ r66 = 0x32 + (rt2x00dev->lna_gain * 5) / 3; ++ else ++ r66 = 0x3a + (rt2x00dev->lna_gain * 5) / 3; ++ } ++ ++ if (rssi > -80) ++ r66 += 0x10; ++ ++ if (rssi != r66_orig) ++ rt2800pci_bbp_write(rt2x00dev, 66, r66); ++} ++ ++/* ++ * Firmware functions ++ */ ++static char *rt2800pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) ++{ ++ return FIRMWARE_RT2860; ++} ++ ++static u16 rt2800pci_get_firmware_crc(const void *data, const size_t len) ++{ ++ u16 crc; ++ ++ /* ++ * Use the crc ccitt algorithm. ++ * This will return the same value as the legacy driver which ++ * used bit ordering reversion on the both the firmware bytes ++ * before input input as well as on the final output. ++ * Obviously using crc ccitt directly is much more efficient. ++ * The last 2 bytes in the firmware array are the crc checksum itself, ++ * this means that we should never pass those 2 bytes to the crc ++ * algorithm. ++ */ ++ crc = crc_ccitt(~0, data, len - 2); ++ ++ /* ++ * There is a small difference between the crc-itu-t + bitrev and ++ * the crc-ccitt crc calculation. In the latter method the 2 bytes ++ * will be swapped, use swab16 to convert the crc to the correct ++ * value. ++ */ ++ return swab16(crc); ++} ++ ++static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev, ++ const void *data, const size_t len) ++{ ++ unsigned int i; ++ u32 reg; ++ ++ /* ++ * Wait for stable hardware. ++ */ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); ++ if (reg && reg != ~0) ++ break; ++ msleep(1); ++ } ++ ++ if (i == REGISTER_BUSY_COUNT) { ++ ERROR(rt2x00dev, "Unstable hardware.\n"); ++ return -EBUSY; ++ } ++ ++ /* ++ * Disable DMA, will be reenabled later when enabling ++ * the radio. ++ */ ++ rt2x00pci_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); ++ rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); ++ ++ rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, ~0); ++ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x0e1f); ++ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x0e00); ++ ++ /* ++ * enable Host program ram write selection ++ */ ++ reg = 0; ++ rt2x00_set_field32(®, PBF_SYS_CTRL_HOST_RAM_WRITE, 1); ++ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg); ++ ++ /* ++ * Write firmware to device. ++ */ ++ rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, ++ data, len); ++ ++ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000); ++ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001); ++ ++ /* ++ * Wait for device to stabilize. ++ */ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2x00pci_register_read(rt2x00dev, PBF_SYS_CTRL, ®); ++ if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) ++ break; ++ msleep(1); ++ } ++ ++ if (i == REGISTER_BUSY_COUNT) { ++ ERROR(rt2x00dev, "PBF system register not ready.\n"); ++ return -EBUSY; ++ } ++ ++ /* ++ * Initialize BBP R/W access agent ++ */ ++ rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); ++ ++ return 0; ++} ++ ++/* ++ * Initialization functions. ++ */ ++static void rt2800pci_init_rxentry(struct rt2x00_dev *rt2x00dev, ++ 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); ++ u32 word; ++ ++ 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); ++} ++ ++static void rt2800pci_init_txentry(struct rt2x00_dev *rt2x00dev, ++ struct queue_entry *entry) ++{ ++ struct queue_entry_priv_pci *entry_priv = entry->priv_data; ++ u32 word; ++ ++ 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; ++ rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma); ++ rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit); ++ rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0); ++ ++ entry_priv = rt2x00dev->tx[1].entries[0].priv_data; ++ rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma); ++ rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit); ++ rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0); ++ ++ entry_priv = rt2x00dev->tx[2].entries[0].priv_data; ++ rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma); ++ rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit); ++ rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0); ++ ++ entry_priv = rt2x00dev->tx[3].entries[0].priv_data; ++ rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma); ++ rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit); ++ rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0); ++ ++ entry_priv = rt2x00dev->rx->entries[0].priv_data; ++ rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma); ++ rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit); ++ rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, 0); ++ ++ /* ++ * Enable global DMA configuration ++ */ ++ rt2x00pci_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); ++ rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); ++ ++ rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0); ++ ++ return 0; ++} ++ ++static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ unsigned int i; ++ ++ rt2x00pci_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); ++ rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); ++ ++ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f); ++ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000000); ++ ++ rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); ++ rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); ++ ++ rt2x00pci_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 */ ++ rt2x00pci_register_write(rt2x00dev, BCN_OFFSET0, reg); ++ ++ rt2x00pci_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 */ ++ rt2x00pci_register_write(rt2x00dev, BCN_OFFSET1, reg); ++ ++ rt2x00pci_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); ++ rt2x00pci_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); ++ ++ rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); ++ ++ rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); ++ rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 0); ++ rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); ++ rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0); ++ rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); ++ rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); ++ rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); ++ rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); ++ ++ rt2x00pci_register_write(rt2x00dev, TX_SW_CFG0, 0x00040a06); ++ rt2x00pci_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); ++ ++ rt2x00pci_register_read(rt2x00dev, TX_LINK_CFG, ®); ++ rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32); ++ rt2x00_set_field32(®, TX_LINK_CFG_MFB_ENABLE, 0); ++ rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0); ++ rt2x00_set_field32(®, TX_LINK_CFG_TX_MRQ_EN, 0); ++ rt2x00_set_field32(®, TX_LINK_CFG_TX_RDG_EN, 0); ++ rt2x00_set_field32(®, TX_LINK_CFG_TX_CF_ACK_EN, 1); ++ rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB, 0); ++ rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFS, 0); ++ rt2x00pci_register_write(rt2x00dev, TX_LINK_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); ++ rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); ++ rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); ++ rt2x00pci_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, MAX_LEN_CFG, ®); ++ rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); ++ rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); ++ rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 0); ++ rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); ++ rt2x00pci_register_write(rt2x00dev, MAX_LEN_CFG, reg); ++ ++ rt2x00pci_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); ++ ++ rt2x00pci_register_read(rt2x00dev, AUTO_RSP_CFG, ®); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); ++ rt2x00pci_register_write(rt2x00dev, AUTO_RSP_CFG, reg); ++ ++ rt2x00pci_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_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); ++ rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 0); ++ rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1); ++ rt2x00pci_register_write(rt2x00dev, CCK_PROT_CFG, reg); ++ ++ rt2x00pci_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_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); ++ rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 0); ++ rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1); ++ rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg); ++ ++ rt2x00pci_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_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); ++ rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); ++ rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); ++ rt2x00pci_register_write(rt2x00dev, MM20_PROT_CFG, reg); ++ ++ rt2x00pci_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_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); ++ rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); ++ rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); ++ rt2x00pci_register_write(rt2x00dev, MM40_PROT_CFG, reg); ++ ++ rt2x00pci_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_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); ++ rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); ++ rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); ++ rt2x00pci_register_write(rt2x00dev, GF20_PROT_CFG, reg); ++ ++ rt2x00pci_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_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); ++ rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); ++ rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); ++ rt2x00pci_register_write(rt2x00dev, GF40_PROT_CFG, reg); ++ ++ rt2x00pci_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); ++ rt2x00pci_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); ++ ++ rt2x00pci_register_read(rt2x00dev, TX_RTS_CFG, ®); ++ rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); ++ rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); ++ rt2x00pci_register_write(rt2x00dev, TX_RTS_CFG, reg); ++ ++ rt2x00pci_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); ++ rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); ++ ++ /* ++ * ASIC will keep garbage value after boot, clear encryption keys. ++ */ ++ for (i = 0; i < 254; i++) { ++ u32 wcid[2] = { 0xffffffff, 0x0000ffff }; ++ rt2x00pci_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), ++ wcid, sizeof(wcid)); ++ } ++ ++ for (i = 0; i < 4; i++) ++ rt2x00pci_register_write(rt2x00dev, ++ SHARED_KEY_MODE_ENTRY(i), 0); ++ ++ for (i = 0; i < 256; i++) ++ rt2x00pci_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); ++ ++ /* ++ * Clear all beacons ++ * For the Beacon base registers we only need to clear ++ * the first byte since that byte contains the VALID and OWNER ++ * bits which (when set to 0) will invalidate the entire beacon. ++ */ ++ rt2x00pci_register_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); ++ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE4, 0); ++ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE5, 0); ++ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE6, 0); ++ rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE7, 0); ++ ++ rt2x00pci_register_read(rt2x00dev, HT_FBK_CFG0, ®); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS0FBK, 0); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS1FBK, 0); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS2FBK, 1); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS3FBK, 2); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS4FBK, 3); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS5FBK, 4); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS6FBK, 5); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS7FBK, 6); ++ rt2x00pci_register_write(rt2x00dev, HT_FBK_CFG0, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, HT_FBK_CFG1, ®); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS8FBK, 8); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS9FBK, 8); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS10FBK, 9); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS11FBK, 10); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS12FBK, 11); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS13FBK, 12); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS14FBK, 13); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS15FBK, 14); ++ rt2x00pci_register_write(rt2x00dev, HT_FBK_CFG1, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, LG_FBK_CFG0, ®); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 10); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 11); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 12); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 13); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS6FBK, 14); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS7FBK, 15); ++ rt2x00pci_register_write(rt2x00dev, LG_FBK_CFG0, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, LG_FBK_CFG1, ®); ++ rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS0FBK, 0); ++ rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS1FBK, 0); ++ rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS2FBK, 1); ++ rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS3FBK, 2); ++ rt2x00pci_register_write(rt2x00dev, LG_FBK_CFG1, reg); ++ ++ /* ++ * 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, RX_STA_CNT0, ®); ++ rt2x00pci_register_read(rt2x00dev, RX_STA_CNT1, ®); ++ rt2x00pci_register_read(rt2x00dev, RX_STA_CNT2, ®); ++ rt2x00pci_register_read(rt2x00dev, TX_STA_CNT0, ®); ++ rt2x00pci_register_read(rt2x00dev, TX_STA_CNT1, ®); ++ rt2x00pci_register_read(rt2x00dev, TX_STA_CNT2, ®); ++ ++ return 0; ++} ++ ++static int rt2800pci_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev) ++{ ++ unsigned int i; ++ u32 reg; ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2x00pci_register_read(rt2x00dev, MAC_STATUS_CFG, ®); ++ if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY)) ++ return 0; ++ ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n"); ++ return -EACCES; ++} ++ ++static int rt2800pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) ++{ ++ unsigned int i; ++ u8 value; ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2800pci_bbp_read(rt2x00dev, 0, &value); ++ if ((value != 0xff) && (value != 0x00)) ++ return 0; ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); ++ return -EACCES; ++} ++ ++static int rt2800pci_init_bbp(struct rt2x00_dev *rt2x00dev) ++{ ++ unsigned int i; ++ u16 eeprom; ++ u8 reg_id; ++ u8 value; ++ ++ if (unlikely(rt2800pci_wait_bbp_rf_ready(rt2x00dev) || ++ rt2800pci_wait_bbp_ready(rt2x00dev))) ++ return -EACCES; ++ ++ rt2800pci_bbp_write(rt2x00dev, 65, 0x2c); ++ rt2800pci_bbp_write(rt2x00dev, 66, 0x38); ++ rt2800pci_bbp_write(rt2x00dev, 69, 0x12); ++ rt2800pci_bbp_write(rt2x00dev, 70, 0x0a); ++ rt2800pci_bbp_write(rt2x00dev, 73, 0x10); ++ rt2800pci_bbp_write(rt2x00dev, 81, 0x37); ++ rt2800pci_bbp_write(rt2x00dev, 82, 0x62); ++ rt2800pci_bbp_write(rt2x00dev, 83, 0x6a); ++ rt2800pci_bbp_write(rt2x00dev, 84, 0x99); ++ rt2800pci_bbp_write(rt2x00dev, 86, 0x00); ++ rt2800pci_bbp_write(rt2x00dev, 91, 0x04); ++ rt2800pci_bbp_write(rt2x00dev, 92, 0x00); ++ rt2800pci_bbp_write(rt2x00dev, 103, 0x00); ++ rt2800pci_bbp_write(rt2x00dev, 105, 0x05); ++ ++ if (rt2x00_rev(&rt2x00dev->chip) == RT2860_VERSION_C) { ++ rt2800pci_bbp_write(rt2x00dev, 69, 0x16); ++ rt2800pci_bbp_write(rt2x00dev, 73, 0x12); ++ } ++ ++ if (rt2x00_rev(&rt2x00dev->chip) == RT2860_VERSION_D) ++ rt2800pci_bbp_write(rt2x00dev, 84, 0x19); ++ ++ for (i = 0; i < EEPROM_BBP_SIZE; i++) { ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); ++ ++ if (eeprom != 0xffff && eeprom != 0x0000) { ++ reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); ++ value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); ++ rt2800pci_bbp_write(rt2x00dev, reg_id, value); ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * Device state switch handlers. ++ */ ++static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev, ++ enum dev_state state) ++{ ++ u32 reg; ++ ++ rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, ++ (state == STATE_RADIO_RX_ON) || ++ (state == STATE_RADIO_RX_ON_LINK)); ++ rt2x00pci_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_OFF); ++ 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) { ++ rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); ++ rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); ++ } ++ ++ rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); ++ rt2x00_set_field32(®, INT_MASK_CSR_RXDELAYINT, mask); ++ rt2x00_set_field32(®, INT_MASK_CSR_TXDELAYINT, mask); ++ rt2x00_set_field32(®, INT_MASK_CSR_RX_DONE, mask); ++ rt2x00_set_field32(®, INT_MASK_CSR_AC0_DMA_DONE, mask); ++ rt2x00_set_field32(®, INT_MASK_CSR_AC1_DMA_DONE, mask); ++ rt2x00_set_field32(®, INT_MASK_CSR_AC2_DMA_DONE, mask); ++ rt2x00_set_field32(®, INT_MASK_CSR_AC3_DMA_DONE, mask); ++ rt2x00_set_field32(®, INT_MASK_CSR_HCCA_DMA_DONE, mask); ++ rt2x00_set_field32(®, INT_MASK_CSR_MGMT_DMA_DONE, mask); ++ rt2x00_set_field32(®, INT_MASK_CSR_MCU_COMMAND, mask); ++ rt2x00_set_field32(®, INT_MASK_CSR_RX_COHERENT, mask); ++ rt2x00_set_field32(®, INT_MASK_CSR_TX_COHERENT, mask); ++ rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); ++} ++ ++static int rt2800pci_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) ++{ ++ unsigned int i; ++ u32 reg; ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); ++ if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && ++ !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) ++ return 0; ++ ++ msleep(1); ++ } ++ ++ ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); ++ return -EACCES; ++} ++ ++static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ u16 word; ++ ++ /* ++ * Initialize all registers. ++ */ ++ if (unlikely(rt2800pci_wait_wpdma_ready(rt2x00dev) || ++ rt2800pci_init_queues(rt2x00dev) || ++ rt2800pci_init_registers(rt2x00dev) || ++ rt2800pci_init_bbp(rt2x00dev))) ++ return -EIO; ++ ++ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001a80); ++ ++ /* Wait for DMA, ignore error */ ++ rt2800pci_wait_wpdma_ready(rt2x00dev); ++ ++ /* ++ * Enable RX. ++ */ ++ rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); ++ rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); ++ rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); ++ rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); ++ rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); ++ ++ /* ++ * Initialize LED control ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); ++ rt2800pci_mcu_request(rt2x00dev, MCU_LED_1, 0xff, ++ word & 0xff, (word >> 8) & 0xff); ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); ++ rt2800pci_mcu_request(rt2x00dev, MCU_LED_2, 0xff, ++ word & 0xff, (word >> 8) & 0xff); ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); ++ rt2800pci_mcu_request(rt2x00dev, MCU_LED_3, 0xff, ++ word & 0xff, (word >> 8) & 0xff); ++ ++ rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); ++ ++ /* ++ * Send signal to firmware during boot time. ++ */ ++ rt2800pci_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); ++ ++ return 0; ++} ++ ++static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ ++ rt2x00pci_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); ++ rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); ++ ++ rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0); ++ rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0); ++ rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0); ++ ++ rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280); ++ ++ /* Wait for DMA, ignore error */ ++ rt2800pci_wait_wpdma_ready(rt2x00dev); ++} ++ ++static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev, ++ enum dev_state state) ++{ ++ rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); ++ ++ if (state == STATE_AWAKE) ++ rt2800pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); ++ else ++ rt2800pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); ++ ++ return 0; ++} ++ ++static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, ++ enum dev_state state) ++{ ++ int retval = 0; ++ ++ 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 the radio can be enabled. ++ */ ++ rt2800pci_set_state(rt2x00dev, STATE_AWAKE); ++ msleep(1); ++ retval = rt2800pci_enable_radio(rt2x00dev); ++ break; ++ case STATE_RADIO_OFF: ++ /* ++ * After the radio has been disablee, 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_ON_LINK: ++ case STATE_RADIO_RX_OFF: ++ case STATE_RADIO_RX_OFF_LINK: ++ rt2800pci_toggle_rx(rt2x00dev, state); ++ break; ++ case STATE_RADIO_IRQ_ON: ++ case STATE_RADIO_IRQ_OFF: ++ rt2800pci_toggle_irq(rt2x00dev, state); ++ break; ++ case STATE_DEEP_SLEEP: ++ case STATE_SLEEP: ++ case STATE_STANDBY: ++ case STATE_AWAKE: ++ retval = rt2800pci_set_state(rt2x00dev, state); ++ break; ++ default: ++ retval = -ENOTSUPP; ++ break; ++ } ++ ++ if (unlikely(retval)) ++ ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", ++ state, retval); ++ ++ return retval; ++} ++ ++/* ++ * TX descriptor initialization ++ */ ++static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, ++ struct sk_buff *skb, ++ struct txentry_desc *txdesc) ++{ ++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); ++ __le32 *txd = skbdesc->desc; ++ __le32 *txwi = (__le32 *)(skb->data - rt2x00dev->hw->extra_tx_headroom); ++ u32 word; ++ ++ /* ++ * Initialize TX Info descriptor ++ */ ++ rt2x00_desc_read(txwi, 0, &word); ++ rt2x00_set_field32(&word, TXWI_W0_FRAG, ++ test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags) || ++ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); ++ rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); ++ rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); ++ rt2x00_set_field32(&word, TXWI_W0_TS, ++ 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->ifs); ++ rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->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_PHYMODE, txdesc->rate_mode); ++ rt2x00_desc_write(txwi, 0, word); ++ ++ rt2x00_desc_read(txwi, 1, &word); ++ rt2x00_set_field32(&word, TXWI_W1_ACK, ++ test_bit(ENTRY_TXD_ACK, &txdesc->flags)); ++ rt2x00_set_field32(&word, TXWI_W1_ACK, ++ test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); ++ rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); ++ rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, 0xff); ++ rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, skb->len); ++ rt2x00_set_field32(&word, TXWI_W1_PACKETID, ++ skbdesc->entry->entry_idx); ++ rt2x00_desc_write(txwi, 1, word); ++ ++ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { ++ _rt2x00_desc_write(txwi, 2, skbdesc->iv); ++ _rt2x00_desc_write(txwi, 3, skbdesc->eiv); ++ } ++ ++ /* ++ * 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, skb->len); ++ rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, 1); ++ rt2x00_set_field32(&word, TXD_W1_BURST, ++ test_bit(ENTRY_TXD_BURST, &txdesc->flags)); ++ rt2x00_set_field32(&word, TXD_W1_SD_LEN0, ++ rt2x00dev->hw->extra_tx_headroom); ++ rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, ++ !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); ++ 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 + rt2x00dev->hw->extra_tx_headroom); ++ rt2x00_desc_write(txd, 2, word); ++ ++ rt2x00_desc_read(txd, 3, &word); ++ rt2x00_set_field32(&word, TXD_W3_WIV, 1); ++ rt2x00_set_field32(&word, TXD_W3_QSEL, 2); ++ rt2x00_desc_write(txd, 3, word); ++} ++ ++/* ++ * TX data initialization ++ */ ++static void rt2800pci_write_beacon(struct queue_entry *entry) ++{ ++ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; ++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); ++ unsigned int beacon_base; ++ u32 reg; ++ ++ /* ++ * Disable beaconing while we are reloading the beacon data, ++ * otherwise we might be sending out invalid data. ++ */ ++ rt2x00pci_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); ++ rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); ++ ++ /* ++ * Write entire beacon with descriptor to register. ++ */ ++ beacon_base = HW_BEACON_OFFSET(entry->entry_idx); ++ rt2x00pci_register_multiwrite(rt2x00dev, ++ beacon_base, ++ skbdesc->desc, skbdesc->desc_len); ++ rt2x00pci_register_multiwrite(rt2x00dev, ++ beacon_base + skbdesc->desc_len, ++ entry->skb->data, entry->skb->len); ++ ++ /* ++ * Clean up beacon skb. ++ */ ++ dev_kfree_skb_any(entry->skb); ++ entry->skb = NULL; ++} ++ ++static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, ++ const enum data_queue_qid queue) ++{ ++ u32 reg; ++ ++ if (queue == QID_BEACON) { ++ rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, ®); ++ if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) { ++ 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); ++ rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); ++ } ++ return; ++ } ++ ++ /* FIXME: How can be kick normal TX queues? */ ++} ++ ++/* ++ * RX control handlers ++ */ ++static void rt2800pci_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; ++ __le32 *rxd = entry_priv->desc; ++ __le32 *rxwi = (__le32 *)entry->skb->data; ++ u32 rxd3; ++ u32 rxwi0; ++ u32 rxwi1; ++ u32 rxwi2; ++ u32 rxwi3; ++ u8 mcs; ++ u8 mode; ++ ++ rt2x00_desc_read(rxd, 3, &rxd3); ++ rt2x00_desc_read(rxwi, 0, &rxwi0); ++ rt2x00_desc_read(rxwi, 1, &rxwi1); ++ rt2x00_desc_read(rxwi, 2, &rxwi2); ++ rt2x00_desc_read(rxwi, 3, &rxwi3); ++ ++ if (rt2x00_get_field32(rxd3, RXD_W3_CRC_ERROR)) ++ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; ++ ++ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { ++ /* ++ * FIXME: Set cipher on WEP64 when it has been decrypted, ++ * at the moment we cannot determine the real cipher type yet. ++ */ ++ rxdesc->cipher = ++ rt2x00_get_field32(rxd3, RXD_W3_DECRYPTED); ++ rxdesc->cipher_status = ++ rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR); ++ } ++ ++ if (rxdesc->cipher != CIPHER_NONE) { ++ /* ++ * Hardware has stripped IV/EIV data from 802.11 frame during ++ * decryption. It has provided the data seperately but rt2x00lib ++ * should decide if it should be reinserted. ++ */ ++ 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(rxd3, RXD_W3_MY_BSS)) ++ rxdesc->dev_flags |= RXDONE_MY_BSS; ++ ++ /* ++ * Create the MCS value, when the mode is CCK, mask of 0x8 bit ++ * to remove the short preamble flag. ++ */ ++ mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE); ++ mcs = rt2x00_get_field32(rxwi1, RXWI_W1_MCS); ++ ++ if (mode == RATE_MODE_CCK) ++ mcs &= ~0x8; ++ ++ rxdesc->signal = (mode << 8) | mcs; ++ ++ rxdesc->rssi = ++ (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + ++ rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1) + ++ rt2x00_get_field32(rxwi2, RXWI_W2_RSSI2)) / 3; ++ ++ rxdesc->noise = ++ (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + ++ rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2; ++ ++ rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); ++ ++ /* ++ * Remove TXWI descriptor from start of buffer. ++ */ ++ skb_pull(entry->skb, TXWI_DESC_SIZE); ++ skb_trim(entry->skb, rxdesc->size); ++} ++ ++/* ++ * Interrupt functions. ++ */ ++static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance) ++{ ++ struct rt2x00_dev *rt2x00dev = dev_instance; ++ ++ /* FIXME */ ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * Device probe functions. ++ */ ++static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) ++{ ++ struct eeprom_93cx6 eeprom; ++ u32 reg; ++ u16 word; ++ u8 *mac; ++ u8 default_lna_gain; ++ ++ rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); ++ ++ eeprom.data = rt2x00dev; ++ eeprom.register_read = rt2800pci_eepromregister_read; ++ eeprom.register_write = rt2800pci_eepromregister_write; ++ eeprom.width = rt2x00_get_field32(reg, E2PROM_CSR_TYPE_93C46) ? ++ PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; ++ eeprom.reg_data_in = 0; ++ eeprom.reg_data_out = 0; ++ eeprom.reg_data_clock = 0; ++ eeprom.reg_chip_select = 0; ++ ++ eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, ++ EEPROM_SIZE / sizeof(u16)); ++ ++ /* ++ * Start validation of the data that has been read. ++ */ ++ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); ++ if (!is_valid_ether_addr(mac)) { ++ DECLARE_MAC_BUF(macbuf); ++ ++ random_ether_addr(mac); ++ EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac)); ++ } ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &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_eeprom_read(rt2x00dev, EEPROM_NIC, &word); ++ if (word != 0) { ++ /* NIC configuration must always be 0. */ ++ word = 0; ++ rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); ++ EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); ++ } ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); ++ if ((word & 0x00ff) == 0x00ff) { ++ rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); ++ 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, "Freq: 0x%04x\n", word); ++ } ++ ++ /* ++ * During the LNA validation we are going to use ++ * lna0 as correct value. Note that EEPROM_LNA ++ * is never validated. ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word); ++ default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0); ++ ++ rt2x00_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); ++ ++ rt2x00_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); ++ ++ rt2x00_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); ++ ++ rt2x00_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); ++ ++ return 0; ++} ++ ++static int rt2800pci_init_eeprom(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ u16 value; ++ u16 eeprom; ++ u16 device; ++ ++ /* ++ * Read EEPROM word for configuration. ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); ++ ++ /* ++ * Identify RF chipset. ++ * To determine the RT chip we have to read the ++ * PCI header of the device. ++ */ ++ pci_read_config_word(to_pci_dev(rt2x00dev->dev), ++ PCI_CONFIG_HEADER_DEVICE, &device); ++ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); ++ rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); ++ reg = rt2x00_get_field32(reg, MAC_CSR0_ASIC_REV); ++ rt2x00_set_chip(rt2x00dev, device, value, reg); ++ ++ if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && ++ !rt2x00_rf(&rt2x00dev->chip, RF2850) && ++ !rt2x00_rf(&rt2x00dev->chip, RF2720) && ++ !rt2x00_rf(&rt2x00dev->chip, RF2750)) { ++ ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); ++ return -ENODEV; ++ } ++ ++ /* ++ * Read frequency offset and RF programming sequence. ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); ++ rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); ++ ++ /* ++ * Read external LNA informations. ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); ++ ++ if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_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 an hardware controlled radio. ++ */ ++#ifdef CONFIG_RT2X00_LIB_RFKILL ++ if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO)) ++ __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); ++#endif /* CONFIG_RT2X00_LIB_RFKILL */ ++ ++ /* ++ * Store led settings, for correct led behaviour. ++ */ ++#ifdef CONFIG_RT2X00_LIB_LEDS ++ rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); ++ rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); ++ rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg); ++#endif /* CONFIG_RT2X00_LIB_LEDS */ ++ ++ return 0; ++} ++ ++/* ++ * RF value list for rt2860 ++ * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750) ++ */ ++static const struct rf_channel rf_vals[] = { ++ { 1, 0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b }, ++ { 2, 0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f }, ++ { 3, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b }, ++ { 4, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f }, ++ { 5, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b }, ++ { 6, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f }, ++ { 7, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b }, ++ { 8, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f }, ++ { 9, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b }, ++ { 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f }, ++ { 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b }, ++ { 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f }, ++ { 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b }, ++ { 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 }, ++ ++ /* 802.11 UNI / HyperLan 2 */ ++ { 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 }, ++ { 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 }, ++ { 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 }, ++ { 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 }, ++ { 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b }, ++ { 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b }, ++ { 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 }, ++ { 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 }, ++ { 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b }, ++ { 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 }, ++ { 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 }, ++ { 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 }, ++ ++ /* 802.11 HyperLan 2 */ ++ { 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 }, ++ { 102, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed793 }, ++ { 104, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed1a3 }, ++ { 108, 0x18402ecc, 0x184c0a32, 0x18178a55, 0x180ed193 }, ++ { 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 }, ++ { 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b }, ++ { 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 }, ++ { 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 }, ++ { 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 }, ++ { 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 }, ++ { 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b }, ++ { 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 }, ++ { 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b }, ++ { 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 }, ++ { 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b }, ++ { 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 }, ++ ++ /* 802.11 UNII */ ++ { 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 }, ++ { 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 }, ++ { 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f }, ++ { 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f }, ++ { 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 }, ++ { 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 }, ++ { 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 }, ++ ++ /* 802.11 Japan */ ++ { 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b }, ++ { 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 }, ++ { 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b }, ++ { 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 }, ++ { 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 }, ++ { 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b }, ++ { 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 }, ++}; ++ ++static int rt2800pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) ++{ ++ struct hw_mode_spec *spec = &rt2x00dev->spec; ++ struct channel_info *info; ++ char *tx_power1; ++ char *tx_power2; ++ unsigned int i; ++ ++ /* ++ * Initialize all hw fields. ++ */ ++ rt2x00dev->hw->flags = ++ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | ++ IEEE80211_HW_SIGNAL_DBM; ++ rt2x00dev->hw->extra_tx_headroom = TXWI_DESC_SIZE; ++ ++ SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); ++ SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, ++ rt2x00_eeprom_addr(rt2x00dev, ++ EEPROM_MAC_ADDR_0)); ++ ++ /* ++ * Initialize hw_mode information. ++ */ ++ spec->supported_bands = SUPPORT_BAND_2GHZ; ++ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; ++ ++ if (rt2x00_rf(&rt2x00dev->chip, RF2820) || ++ rt2x00_rf(&rt2x00dev->chip, RF2720)) { ++ spec->num_channels = 14; ++ spec->channels = rf_vals; ++ } else if (rt2x00_rf(&rt2x00dev->chip, RF2850) || ++ rt2x00_rf(&rt2x00dev->chip, RF2750)) { ++ spec->supported_bands |= SUPPORT_BAND_5GHZ; ++ spec->num_channels = ARRAY_SIZE(rf_vals); ++ spec->channels = rf_vals; ++ } ++ ++ /* ++ * Create channel information array ++ */ ++ info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ spec->channels_info = info; ++ ++ tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); ++ tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); ++ ++ for (i = 0; i < 14; i++) { ++ info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]); ++ info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]); ++ } ++ ++ if (spec->num_channels > 14) { ++ tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); ++ tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); ++ ++ for (i = 14; i < spec->num_channels; i++) { ++ info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]); ++ info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]); ++ } ++ } ++ ++ return 0; ++} ++ ++static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) ++{ ++ int retval; ++ ++ /* ++ * Allocate eeprom data. ++ */ ++ retval = rt2800pci_validate_eeprom(rt2x00dev); ++ if (retval) ++ return retval; ++ ++ retval = rt2800pci_init_eeprom(rt2x00dev); ++ if (retval) ++ return retval; ++ ++ /* ++ * Initialize hw specifications. ++ */ ++ retval = rt2800pci_probe_hw_mode(rt2x00dev); ++ if (retval) ++ return retval; ++ ++ /* ++ * This device requires firmware. ++ */ ++ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); ++ if (!modparam_nohwcrypt) ++ __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); ++ ++ /* ++ * Set the rssi offset. ++ */ ++ rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; ++ ++ return 0; ++} ++ ++/* ++ * IEEE80211 stack callback functions. ++ */ ++static int rt2800pci_set_rts_threshold(struct ieee80211_hw *hw, u32 value) ++{ ++ struct rt2x00_dev *rt2x00dev = hw->priv; ++ u32 reg; ++ ++ rt2x00pci_register_read(rt2x00dev, TX_RTS_CFG, ®); ++ rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, value); ++ rt2x00pci_register_write(rt2x00dev, TX_RTS_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, CCK_PROT_CFG, ®); ++ rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, 1); ++ rt2x00pci_register_write(rt2x00dev, CCK_PROT_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, OFDM_PROT_CFG, ®); ++ rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, 1); ++ rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, MM20_PROT_CFG, ®); ++ rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, 1); ++ rt2x00pci_register_write(rt2x00dev, MM20_PROT_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, MM40_PROT_CFG, ®); ++ rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, 1); ++ rt2x00pci_register_write(rt2x00dev, MM40_PROT_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, GF20_PROT_CFG, ®); ++ rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, 1); ++ rt2x00pci_register_write(rt2x00dev, GF20_PROT_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, GF40_PROT_CFG, ®); ++ rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, 1); ++ rt2x00pci_register_write(rt2x00dev, GF40_PROT_CFG, reg); ++ ++ return 0; ++} ++ ++static int rt2800pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, ++ const struct ieee80211_tx_queue_params *params) ++{ ++ struct rt2x00_dev *rt2x00dev = hw->priv; ++ struct data_queue *queue; ++ struct rt2x00_field32 field; ++ int retval; ++ u32 reg; ++ u32 offset; ++ ++ /* ++ * First pass the configuration through rt2x00lib, that will ++ * update the queue settings and validate the input. After that ++ * we are free to update the registers based on the value ++ * in the queue parameter. ++ */ ++ retval = rt2x00mac_conf_tx(hw, queue_idx, params); ++ if (retval) ++ return retval; ++ ++ queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); ++ ++ /* Update WMM TXOP register */ ++ if (queue_idx < 2) { ++ field.bit_offset = queue_idx * 16; ++ field.bit_mask = 0xffff << field.bit_offset; ++ ++ rt2x00pci_register_read(rt2x00dev, WMM_TXOP0_CFG, ®); ++ rt2x00_set_field32(®, field, queue->txop); ++ rt2x00pci_register_write(rt2x00dev, WMM_TXOP0_CFG, reg); ++ } else if (queue_idx < 4) { ++ field.bit_offset = (queue_idx - 2) * 16; ++ field.bit_mask = 0xffff << field.bit_offset; ++ ++ rt2x00pci_register_read(rt2x00dev, WMM_TXOP1_CFG, ®); ++ rt2x00_set_field32(®, field, queue->txop); ++ rt2x00pci_register_write(rt2x00dev, WMM_TXOP1_CFG, reg); ++ } ++ ++ /* Update WMM registers */ ++ field.bit_offset = queue_idx * 4; ++ field.bit_mask = 0xf << field.bit_offset; ++ ++ rt2x00pci_register_read(rt2x00dev, WMM_AIFSN_CFG, ®); ++ rt2x00_set_field32(®, field, queue->aifs); ++ rt2x00pci_register_write(rt2x00dev, WMM_AIFSN_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, WMM_CWMIN_CFG, ®); ++ rt2x00_set_field32(®, field, queue->cw_min); ++ rt2x00pci_register_write(rt2x00dev, WMM_CWMIN_CFG, reg); ++ ++ rt2x00pci_register_read(rt2x00dev, WMM_CWMAX_CFG, ®); ++ rt2x00_set_field32(®, field, queue->cw_max); ++ rt2x00pci_register_write(rt2x00dev, WMM_CWMAX_CFG, reg); ++ ++ /* Update EDCA registers */ ++ if (queue_idx < 4) { ++ offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); ++ ++ rt2x00pci_register_read(rt2x00dev, offset, ®); ++ rt2x00_set_field32(®, EDCA_AC0_CFG_AIFSN, queue->aifs); ++ rt2x00_set_field32(®, EDCA_AC0_CFG_CWMIN, queue->cw_min); ++ rt2x00_set_field32(®, EDCA_AC0_CFG_CWMAX, queue->cw_max); ++ rt2x00pci_register_write(rt2x00dev, offset, reg); ++ } ++ ++ return 0; ++} ++ ++static u64 rt2800pci_get_tsf(struct ieee80211_hw *hw) ++{ ++ struct rt2x00_dev *rt2x00dev = hw->priv; ++ u64 tsf; ++ u32 reg; ++ ++ rt2x00pci_register_read(rt2x00dev, TSF_TIMER_DW1, ®); ++ tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32; ++ rt2x00pci_register_read(rt2x00dev, TSF_TIMER_DW0, ®); ++ tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD); ++ ++ return tsf; ++} ++ ++static const struct ieee80211_ops rt2800pci_mac80211_ops = { ++ .tx = rt2x00mac_tx, ++ .start = rt2x00mac_start, ++ .stop = rt2x00mac_stop, ++ .add_interface = rt2x00mac_add_interface, ++ .remove_interface = rt2x00mac_remove_interface, ++ .config = rt2x00mac_config, ++ .config_interface = rt2x00mac_config_interface, ++ .configure_filter = rt2x00mac_configure_filter, ++ .set_key = rt2x00mac_set_key, ++ .get_stats = rt2x00mac_get_stats, ++ .set_rts_threshold = rt2800pci_set_rts_threshold, ++ .bss_info_changed = rt2x00mac_bss_info_changed, ++ .conf_tx = rt2800pci_conf_tx, ++ .get_tx_stats = rt2x00mac_get_tx_stats, ++ .get_tsf = rt2800pci_get_tsf, ++}; ++ ++static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { ++ .irq_handler = rt2800pci_interrupt, ++ .probe_hw = rt2800pci_probe_hw, ++ .get_firmware_name = rt2800pci_get_firmware_name, ++ .get_firmware_crc = rt2800pci_get_firmware_crc, ++ .load_firmware = rt2800pci_load_firmware, ++ .initialize = rt2x00pci_initialize, ++ .uninitialize = rt2x00pci_uninitialize, ++ .init_rxentry = rt2800pci_init_rxentry, ++ .init_txentry = rt2800pci_init_txentry, ++ .set_device_state = rt2800pci_set_device_state, ++ .rfkill_poll = rt2800pci_rfkill_poll, ++ .link_stats = rt2800pci_link_stats, ++ .reset_tuner = rt2800pci_reset_tuner, ++ .link_tuner = rt2800pci_link_tuner, ++ .write_tx_desc = rt2800pci_write_tx_desc, ++ .write_tx_data = rt2x00pci_write_tx_data, ++ .write_beacon = rt2800pci_write_beacon, ++ .kick_tx_queue = rt2800pci_kick_tx_queue, ++ .fill_rxdone = rt2800pci_fill_rxdone, ++ .config_shared_key = rt2800pci_config_shared_key, ++ .config_pairwise_key = rt2800pci_config_pairwise_key, ++ .config_filter = rt2800pci_config_filter, ++ .config_intf = rt2800pci_config_intf, ++ .config_erp = rt2800pci_config_erp, ++ .config_ant = rt2800pci_config_ant, ++ .config = rt2800pci_config, ++}; ++ ++static const struct data_queue_desc rt2800pci_queue_rx = { ++ .entry_num = RX_ENTRIES, ++ .data_size = DATA_FRAME_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 = TX_ENTRIES, ++ .data_size = DATA_FRAME_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 * BEACON_ENTRIES, ++ .data_size = 0, /* No DMA required for beacons */ ++ .desc_size = TXWI_DESC_SIZE, ++ .priv_size = sizeof(struct queue_entry_priv_pci), ++}; ++ ++static const struct rt2x00_ops rt2800pci_ops = { ++ .name = KBUILD_MODNAME, ++ .max_sta_intf = 1, ++ .max_ap_intf = 8, ++ .eeprom_size = EEPROM_SIZE, ++ .rf_size = RF_SIZE, ++ .tx_queues = NUM_TX_QUEUES, ++ .rx = &rt2800pci_queue_rx, ++ .tx = &rt2800pci_queue_tx, ++ .bcn = &rt2800pci_queue_bcn, ++ .lib = &rt2800pci_rt2x00_ops, ++ .hw = &rt2800pci_mac80211_ops, ++#ifdef CONFIG_RT2X00_LIB_DEBUGFS ++ .debugfs = &rt2800pci_rt2x00debug, ++#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ ++}; ++ ++/* ++ * RT2800pci module information. ++ */ ++static struct pci_device_id 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(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { 0, } ++}; ++ ++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"); ++MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); ++MODULE_FIRMWARE(FIRMWARE_RT2860); ++MODULE_LICENSE("GPL"); ++ ++static struct pci_driver rt2800pci_driver = { ++ .name = KBUILD_MODNAME, ++ .id_table = rt2800pci_device_table, ++ .probe = rt2x00pci_probe, ++ .remove = __devexit_p(rt2x00pci_remove), ++ .suspend = rt2x00pci_suspend, ++ .resume = rt2x00pci_resume, ++}; ++ ++static int __init rt2800pci_init(void) ++{ ++ return pci_register_driver(&rt2800pci_driver); ++} ++ ++static void __exit rt2800pci_exit(void) ++{ ++ pci_unregister_driver(&rt2800pci_driver); ++} ++ ++module_init(rt2800pci_init); ++module_exit(rt2800pci_exit); +--- /dev/null ++++ b/drivers/net/wireless/rt2x00/rt2800pci.h +@@ -0,0 +1,1862 @@ ++/* ++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project ++ <http://rt2x00.serialmonkey.com> ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the ++ Free Software Foundation, Inc., ++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++/* ++ Module: rt2800pci ++ Abstract: Data structures and registers for the rt2800pci module. ++ Supported chipsets: RT2800E & RT2800ED. ++ */ ++ ++#ifndef RT2800PCI_H ++#define RT2800PCI_H ++ ++/* ++ * RF chip defines. ++ * ++ * RF2820 2.4G 2T3R ++ * RF2850 2.4G/5G 2T3R ++ * RF2720 2.4G 1T2R ++ * RF2750 2.4G/5G 1T2R ++ */ ++#define RF2820 0x0001 ++#define RF2850 0x0002 ++#define RF2720 0x0003 ++#define RF2750 0x0004 ++ ++/* ++ * RT2860 version ++ */ ++#define RT2860_VERSION_C 0x0100 ++#define RT2860_VERSION_D 0x0101 ++#define RT2860_VERSION_E 0x0200 ++ ++/* ++ * Signal information. ++ * Defaul offset is required for RSSI <-> dBm conversion. ++ */ ++#define MAX_SIGNAL 0 /* FIXME */ ++#define MAX_RX_SSI 0 /* FIXME */ ++#define DEFAULT_RSSI_OFFSET 120 /* FIXME */ ++ ++/* ++ * Register layout information. ++ */ ++#define CSR_REG_BASE 0x1000 ++#define CSR_REG_SIZE 0x0800 ++#define EEPROM_BASE 0x0000 ++#define EEPROM_SIZE 0x0110 ++#define BBP_BASE 0x0000 ++#define BBP_SIZE 0x0080 ++#define RF_BASE 0x0000 ++#define RF_SIZE 0x0014 ++ ++/* ++ * Number of TX queues. ++ */ ++#define NUM_TX_QUEUES 4 ++ ++/* ++ * PCI registers. ++ */ ++ ++/* ++ * PCI Configuration Header ++ */ ++#define PCI_CONFIG_HEADER_VENDOR 0x0000 ++#define PCI_CONFIG_HEADER_DEVICE 0x0002 ++ ++/* ++ * E2PROM_CSR: EEPROM control register. ++ * RELOAD: Write 1 to reload eeprom content. ++ * TYPE_93C46: 1: 93c46, 0:93c66. ++ * LOAD_STATUS: 1:loading, 0:done. ++ */ ++#define E2PROM_CSR 0x0004 ++#define E2PROM_CSR_RELOAD FIELD32(0x00000001) ++#define E2PROM_CSR_DATA_CLOCK FIELD32(0x00000002) ++#define E2PROM_CSR_CHIP_SELECT FIELD32(0x00000004) ++#define E2PROM_CSR_DATA_IN FIELD32(0x00000008) ++#define E2PROM_CSR_DATA_OUT FIELD32(0x00000010) ++#define E2PROM_CSR_TYPE_93C46 FIELD32(0x00000020) ++#define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) ++ ++/* ++ * HOST-MCU shared memory ++ */ ++#define HOST_CMD_CSR 0x0404 ++#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff) ++ ++/* ++ * INT_SOURCE_CSR: Interrupt source register. ++ * Write one to clear corresponding bit. ++ * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c ++ */ ++#define INT_SOURCE_CSR 0x0200 ++#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001) ++#define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002) ++#define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004) ++#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008) ++#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010) ++#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020) ++#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040) ++#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080) ++#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100) ++#define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200) ++#define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400) ++#define INT_SOURCE_CSR_TBTT FIELD32(0x00000800) ++#define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000) ++#define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000) ++#define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000) ++#define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000) ++#define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000) ++#define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000) ++ ++/* ++ * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF. ++ */ ++#define INT_MASK_CSR 0x0204 ++#define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001) ++#define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002) ++#define INT_MASK_CSR_RX_DONE FIELD32(0x00000004) ++#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008) ++#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010) ++#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020) ++#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040) ++#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080) ++#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100) ++#define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200) ++#define INT_MASK_CSR_RX_COHERENT FIELD32(0x40000000) ++#define INT_MASK_CSR_TX_COHERENT FIELD32(0x80000000) ++ ++/* ++ * WPDMA_GLO_CFG ++ */ ++#define WPDMA_GLO_CFG 0x0208 ++#define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001) ++#define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002) ++#define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004) ++#define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008) ++#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030) ++#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040) ++#define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080) ++#define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00) ++#define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000) ++ ++/* ++ * WPDMA_RST_IDX ++ */ ++#define WPDMA_RST_IDX 0x020c ++#define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001) ++#define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002) ++#define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004) ++#define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008) ++#define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010) ++#define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020) ++#define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000) ++ ++/* ++ * DELAY_INT_CFG ++ */ ++#define DELAY_INT_CFG 0x0210 ++#define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff) ++#define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00) ++#define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000) ++#define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000) ++#define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000) ++#define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000) ++ ++/* ++ * WMM_AIFSN_CFG: Aifsn for each EDCA AC ++ * AIFSN0: AC_BE ++ * AIFSN1: AC_BK ++ * AIFSN1: AC_VI ++ * AIFSN1: AC_VO ++ */ ++#define WMM_AIFSN_CFG 0x0214 ++#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) ++#define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0) ++#define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00) ++#define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000) ++ ++/* ++ * WMM_CWMIN_CSR: CWmin for each EDCA AC ++ * CWMIN0: AC_BE ++ * CWMIN1: AC_BK ++ * CWMIN1: AC_VI ++ * CWMIN1: AC_VO ++ */ ++#define WMM_CWMIN_CFG 0x0218 ++#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) ++#define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0) ++#define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00) ++#define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000) ++ ++/* ++ * WMM_CWMAX_CSR: CWmax for each EDCA AC ++ * CWMAX0: AC_BE ++ * CWMAX1: AC_BK ++ * CWMAX1: AC_VI ++ * CWMAX1: AC_VO ++ */ ++#define WMM_CWMAX_CFG 0x021c ++#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) ++#define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0) ++#define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00) ++#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 ++ */ ++#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 ++ */ ++#define WMM_TXOP1_CFG 0x0224 ++#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff) ++#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) ++ ++/* ++ * RINGREG_DIFF ++ */ ++#define RINGREG_DIFF 0x0010 ++ ++/* ++ * 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) ++ ++/* ++ * MCU_CMD_CFG ++ */ ++#define MCU_CMD_CFG 0x022c ++ ++/* ++ * AC_BK register offsets ++ */ ++#define TX_BASE_PTR0 0x0230 ++#define TX_MAX_CNT0 0x0234 ++#define TX_CTX_IDX0 0x0238 ++#define TX_DTX_IDX0 0x023c ++ ++/* ++ * AC_BE register offsets ++ */ ++#define TX_BASE_PTR1 0x0240 ++#define TX_MAX_CNT1 0x0244 ++#define TX_CTX_IDX1 0x0248 ++#define TX_DTX_IDX1 0x024c ++ ++/* ++ * AC_VI register offsets ++ */ ++#define TX_BASE_PTR2 0x0250 ++#define TX_MAX_CNT2 0x0254 ++#define TX_CTX_IDX2 0x0258 ++#define TX_DTX_IDX2 0x025c ++ ++/* ++ * AC_VO register offsets ++ */ ++#define TX_BASE_PTR3 0x0260 ++#define TX_MAX_CNT3 0x0264 ++#define TX_CTX_IDX3 0x0268 ++#define TX_DTX_IDX3 0x026c ++ ++/* ++ * HCCA register offsets ++ */ ++#define TX_BASE_PTR4 0x0270 ++#define TX_MAX_CNT4 0x0274 ++#define TX_CTX_IDX4 0x0278 ++#define TX_DTX_IDX4 0x027c ++ ++/* ++ * MGMT register offsets ++ */ ++#define TX_BASE_PTR5 0x0280 ++#define TX_MAX_CNT5 0x0284 ++#define TX_CTX_IDX5 0x0288 ++#define TX_DTX_IDX5 0x028c ++ ++/* ++ * RX register offsets ++ */ ++#define RX_BASE_PTR 0x0290 ++#define RX_MAX_CNT 0x0294 ++#define RX_CRX_IDX 0x0298 ++#define RX_DRX_IDX 0x029c ++ ++/* ++ * PBF_SYS_CTRL ++ * HOST_RAM_WRITE: enable Host program ram write selection ++ */ ++#define PBF_SYS_CTRL 0x0400 ++#define PBF_SYS_CTRL_READY FIELD32(0x00000080) ++#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) ++ ++/* ++ * PBF registers ++ * Most are for debug. Driver doesn't touch PBF register. ++ */ ++#define PBF_CFG 0x0408 ++#define PBF_MAX_PCNT 0x040c ++#define PBF_CTRL 0x0410 ++#define PBF_INT_STA 0x0414 ++#define PBF_INT_ENA 0x0418 ++ ++/* ++ * BCN_OFFSET0: ++ */ ++#define BCN_OFFSET0 0x042c ++#define BCN_OFFSET0_BCN0 FIELD32(0x000000ff) ++#define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00) ++#define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000) ++#define BCN_OFFSET0_BCN3 FIELD32(0xff000000) ++ ++/* ++ * BCN_OFFSET1: ++ */ ++#define BCN_OFFSET1 0x0430 ++#define BCN_OFFSET1_BCN4 FIELD32(0x000000ff) ++#define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00) ++#define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000) ++#define BCN_OFFSET1_BCN7 FIELD32(0xff000000) ++ ++/* ++ * PBF registers ++ * Most are for debug. Driver doesn't touch PBF register. ++ */ ++#define TXRXQ_PCNT 0x0438 ++#define PBF_DBG 0x043c ++ ++/* ++ * MAC Control/Status Registers(CSR). ++ * Some values are set in TU, whereas 1 TU == 1024 us. ++ */ ++ ++/* ++ * MAC_CSR0: ASIC revision number. ++ * ASIC_REV: 0 ++ * ASIC_VER: 2860 ++ */ ++#define MAC_CSR0 0x1000 ++#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) ++#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) ++ ++/* ++ * MAC_SYS_CTRL: ++ */ ++#define MAC_SYS_CTRL 0x1004 ++#define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001) ++#define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002) ++#define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004) ++#define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008) ++#define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010) ++#define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020) ++#define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040) ++#define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080) ++ ++/* ++ * MAC_ADDR_DW0: STA MAC register 0 ++ */ ++#define MAC_ADDR_DW0 0x1008 ++#define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff) ++#define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00) ++#define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000) ++#define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000) ++ ++/* ++ * MAC_ADDR_DW1: STA MAC register 1 ++ * UNICAST_TO_ME_MASK: ++ * Used to mask off bits from byte 5 of the MAC address ++ * to determine the UNICAST_TO_ME bit for RX frames. ++ * The full mask is complemented by BSS_ID_MASK: ++ * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK ++ */ ++#define MAC_ADDR_DW1 0x100c ++#define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff) ++#define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00) ++#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000) ++ ++/* ++ * MAC_BSSID_DW0: BSSID register 0 ++ */ ++#define MAC_BSSID_DW0 0x1010 ++#define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff) ++#define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00) ++#define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000) ++#define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000) ++ ++/* ++ * MAC_BSSID_DW1: BSSID register 1 ++ * BSS_ID_MASK: ++ * 0: 1-BSSID mode (BSS index = 0) ++ * 1: 2-BSSID mode (BSS index: Byte5, bit 0) ++ * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1) ++ * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2) ++ * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the ++ * BSSID. This will make sure that those bits will be ignored ++ * when determining the MY_BSS of RX frames. ++ */ ++#define MAC_BSSID_DW1 0x1014 ++#define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff) ++#define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00) ++#define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000) ++#define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000) ++ ++/* ++ * MAX_LEN_CFG: Maximum frame length register. ++ * MAX_MPDU: rt2860b max 16k bytes ++ * MAX_PSDU: Maximum PSDU length ++ * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 ++ */ ++#define MAX_LEN_CFG 0x1018 ++#define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff) ++#define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000) ++#define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000) ++#define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000) ++ ++/* ++ * BBP_CSR_CFG: BBP serial control register ++ * VALUE: Register value to program into BBP ++ * REG_NUM: Selected BBP register ++ * 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 ++ */ ++#define BBP_CSR_CFG 0x101c ++#define BBP_CSR_CFG_VALUE FIELD32(0x000000ff) ++#define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00) ++#define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000) ++#define BBP_CSR_CFG_BUSY FIELD32(0x00020000) ++#define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000) ++#define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000) ++ ++/* ++ * RF_CSR_CFG0: RF control register ++ * REGID_AND_VALUE: Register value to program into RF ++ * BITWIDTH: Selected RF register ++ * STANDBYMODE: 0 high when standby, 1 low when standby ++ * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate ++ * BUSY: ASIC is busy executing RF commands ++ */ ++#define RF_CSR_CFG0 0x1020 ++#define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff) ++#define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000) ++#define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff) ++#define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000) ++#define RF_CSR_CFG0_SEL FIELD32(0x40000000) ++#define RF_CSR_CFG0_BUSY FIELD32(0x80000000) ++ ++/* ++ * RF_CSR_CFG1: RF control register ++ * REGID_AND_VALUE: Register value to program into RF ++ * RFGAP: Gap between BB_CONTROL_RF and RF_LE ++ * 0: 3 system clock cycle (37.5usec) ++ * 1: 5 system clock cycle (62.5usec) ++ */ ++#define RF_CSR_CFG1 0x1024 ++#define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff) ++#define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000) ++ ++/* ++ * RF_CSR_CFG2: RF control register ++ * VALUE: Register value to program into RF ++ * RFGAP: Gap between BB_CONTROL_RF and RF_LE ++ * 0: 3 system clock cycle (37.5usec) ++ * 1: 5 system clock cycle (62.5usec) ++ */ ++#define RF_CSR_CFG2 0x1028 ++#define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff) ++ ++/* ++ * LED_CFG: LED control ++ * color LED's: ++ * 0: off ++ * 1: blinking upon TX2 ++ * 2: periodic slow blinking ++ * 3: always on ++ * LED polarity: ++ * 0: active low ++ * 1: active high ++ */ ++#define LED_CFG 0x102c ++#define LED_CFG_ON_PERIOD FIELD32(0x000000ff) ++#define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00) ++#define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000) ++#define LED_CFG_R_LED_MODE FIELD32(0x03000000) ++#define LED_CFG_G_LED_MODE FIELD32(0x0c000000) ++#define LED_CFG_Y_LED_MODE FIELD32(0x30000000) ++#define LED_CFG_LED_POLAR FIELD32(0x40000000) ++ ++/* ++ * XIFS_TIME_CFG: MAC timing ++ * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX ++ * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX ++ * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX ++ * when MAC doesn't reference BBP signal BBRXEND ++ * EIFS: unit 1us ++ * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer ++ * ++ */ ++#define XIFS_TIME_CFG 0x1100 ++#define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff) ++#define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00) ++#define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000) ++#define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000) ++#define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000) ++ ++/* ++ * BKOFF_SLOT_CFG: ++ */ ++#define BKOFF_SLOT_CFG 0x1104 ++#define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff) ++#define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00) ++ ++/* ++ * NAV_TIME_CFG: ++ */ ++#define NAV_TIME_CFG 0x1108 ++#define NAV_TIME_CFG_SIFS FIELD32(0x000000ff) ++#define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00) ++#define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000) ++#define NAV_TIME_ZERO_SIFS FIELD32(0x02000000) ++ ++/* ++ * CH_TIME_CFG: count as channel busy ++ */ ++#define CH_TIME_CFG 0x110c ++ ++/* ++ * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us ++ */ ++#define PBF_LIFE_TIMER 0x1110 ++ ++/* ++ * BCN_TIME_CFG: ++ * BEACON_INTERVAL: in unit of 1/16 TU ++ * TSF_TICKING: Enable TSF auto counting ++ * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode ++ * BEACON_GEN: Enable beacon generator ++ */ ++#define BCN_TIME_CFG 0x1114 ++#define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff) ++#define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000) ++#define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000) ++#define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000) ++#define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000) ++#define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000) ++ ++/* ++ * TBTT_SYNC_CFG: ++ */ ++#define TBTT_SYNC_CFG 0x1118 ++ ++/* ++ * TSF_TIMER_DW0: Local lsb TSF timer, read-only ++ */ ++#define TSF_TIMER_DW0 0x111c ++#define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff) ++ ++/* ++ * TSF_TIMER_DW1: Local msb TSF timer, read-only ++ */ ++#define TSF_TIMER_DW1 0x1120 ++#define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff) ++ ++/* ++ * TBTT_TIMER: TImer remains till next TBTT, read-only ++ */ ++#define TBTT_TIMER 0x1124 ++ ++/* ++ * INT_TIMER_CFG: ++ */ ++#define INT_TIMER_CFG 0x1128 ++ ++/* ++ * INT_TIMER_EN: GP-timer and pre-tbtt Int enable ++ */ ++#define INT_TIMER_EN 0x112c ++ ++/* ++ * CH_IDLE_STA: channel idle time ++ */ ++#define CH_IDLE_STA 0x1130 ++ ++/* ++ * CH_BUSY_STA: channel busy time ++ */ ++#define CH_BUSY_STA 0x1134 ++ ++/* ++ * MAC_STATUS_CFG: ++ * BBP_RF_BUSY: When set to 0, BBP and RF are stable. ++ * if 1 or higher one of the 2 registers is busy. ++ */ ++#define MAC_STATUS_CFG 0x1200 ++#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003) ++ ++/* ++ * PWR_PIN_CFG: ++ */ ++#define PWR_PIN_CFG 0x1204 ++ ++/* ++ * AUTOWAKEUP_CFG: Manual power control / status register ++ * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set ++ * AUTOWAKE: 0:sleep, 1:awake ++ */ ++#define AUTOWAKEUP_CFG 0x1208 ++#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff) ++#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00) ++#define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000) ++ ++/* ++ * EDCA_AC0_CFG: ++ */ ++#define EDCA_AC0_CFG 0x1300 ++#define EDCA_AC0_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00) ++#define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000) ++#define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000) ++ ++/* ++ * EDCA_AC1_CFG: ++ */ ++#define EDCA_AC1_CFG 0x1304 ++#define EDCA_AC1_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00) ++#define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000) ++#define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000) ++ ++/* ++ * EDCA_AC2_CFG: ++ */ ++#define EDCA_AC2_CFG 0x1308 ++#define EDCA_AC2_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00) ++#define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000) ++#define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000) ++ ++/* ++ * EDCA_AC3_CFG: ++ */ ++#define EDCA_AC3_CFG 0x130c ++#define EDCA_AC3_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00) ++#define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000) ++#define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000) ++ ++/* ++ * EDCA_TID_AC_MAP: ++ */ ++#define EDCA_TID_AC_MAP 0x1310 ++ ++/* ++ * TX_PWR_CFG_0: ++ */ ++#define TX_PWR_CFG_0 0x1314 ++#define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f) ++#define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0) ++#define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00) ++#define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000) ++#define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000) ++#define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000) ++#define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000) ++#define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000) ++ ++/* ++ * TX_PWR_CFG_1: ++ */ ++#define TX_PWR_CFG_1 0x1318 ++#define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f) ++#define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0) ++#define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00) ++#define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000) ++#define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000) ++#define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000) ++#define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000) ++#define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000) ++ ++/* ++ * TX_PWR_CFG_2: ++ */ ++#define TX_PWR_CFG_2 0x131c ++#define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f) ++#define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0) ++#define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00) ++#define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000) ++#define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000) ++#define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000) ++#define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000) ++#define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000) ++ ++/* ++ * TX_PWR_CFG_3: ++ */ ++#define TX_PWR_CFG_3 0x1320 ++#define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f) ++#define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0) ++#define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00) ++#define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000) ++#define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000) ++#define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000) ++#define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000) ++#define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000) ++ ++/* ++ * TX_PWR_CFG_4: ++ */ ++#define TX_PWR_CFG_4 0x1324 ++#define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f) ++#define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0) ++#define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00) ++#define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000) ++ ++/* ++ * TX_PIN_CFG: ++ */ ++#define TX_PIN_CFG 0x1328 ++#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) ++#define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008) ++#define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010) ++#define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020) ++#define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040) ++#define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080) ++#define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100) ++#define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200) ++#define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400) ++#define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800) ++#define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000) ++#define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000) ++#define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000) ++#define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000) ++#define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000) ++#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000) ++#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000) ++#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000) ++ ++/* ++ * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz ++ */ ++#define TX_BAND_CFG 0x132c ++#define TX_BAND_CFG_A FIELD32(0x00000002) ++#define TX_BAND_CFG_BG FIELD32(0x00000004) ++ ++/* ++ * TX_SW_CFG0: ++ */ ++#define TX_SW_CFG0 0x1330 ++ ++/* ++ * TX_SW_CFG1: ++ */ ++#define TX_SW_CFG1 0x1334 ++ ++/* ++ * TX_SW_CFG2: ++ */ ++#define TX_SW_CFG2 0x1338 ++ ++/* ++ * TXOP_THRES_CFG: ++ */ ++#define TXOP_THRES_CFG 0x133c ++ ++/* ++ * TXOP_CTRL_CFG: ++ */ ++#define TXOP_CTRL_CFG 0x1340 ++ ++/* ++ * TX_RTS_CFG: ++ * RTS_THRES: unit:byte ++ * RTS_FBK_EN: enable rts rate fallback ++ */ ++#define TX_RTS_CFG 0x1344 ++#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff) ++#define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00) ++#define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000) ++ ++/* ++ * TX_TIMEOUT_CFG: ++ * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us ++ * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure ++ * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation. ++ * it is recommended that: ++ * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) ++ */ ++#define TX_TIMEOUT_CFG 0x1348 ++#define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0) ++#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00) ++#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000) ++ ++/* ++ * TX_RTY_CFG: ++ * SHORT_RTY_LIMIT: short retry limit ++ * LONG_RTY_LIMIT: long retry limit ++ * LONG_RTY_THRE: Long retry threshoold ++ * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode ++ * 0:expired by retry limit, 1: expired by mpdu life timer ++ * AGG_RTY_MODE: Aggregate MPDU retry mode ++ * 0:expired by retry limit, 1: expired by mpdu life timer ++ * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable ++ */ ++#define TX_RTY_CFG 0x134c ++#define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff) ++#define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00) ++#define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000) ++#define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000) ++#define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000) ++#define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000) ++ ++/* ++ * TX_LINK_CFG: ++ * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us ++ * MFB_ENABLE: TX apply remote MFB 1:enable ++ * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable ++ * 0: not apply remote remote unsolicit (MFS=7) ++ * TX_MRQ_EN: MCS request TX enable ++ * TX_RDG_EN: RDG TX enable ++ * TX_CF_ACK_EN: Piggyback CF-ACK enable ++ * REMOTE_MFB: remote MCS feedback ++ * REMOTE_MFS: remote MCS feedback sequence number ++ */ ++#define TX_LINK_CFG 0x1350 ++#define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff) ++#define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100) ++#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200) ++#define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400) ++#define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800) ++#define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000) ++#define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000) ++#define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000) ++ ++/* ++ * HT_FBK_CFG0: ++ */ ++#define HT_FBK_CFG0 0x1354 ++#define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f) ++#define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0) ++#define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00) ++#define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000) ++#define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000) ++#define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000) ++#define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000) ++#define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000) ++ ++/* ++ * HT_FBK_CFG1: ++ */ ++#define HT_FBK_CFG1 0x1358 ++#define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f) ++#define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0) ++#define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00) ++#define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000) ++#define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000) ++#define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000) ++#define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000) ++#define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000) ++ ++/* ++ * LG_FBK_CFG0: ++ */ ++#define LG_FBK_CFG0 0x135c ++#define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f) ++#define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0) ++#define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00) ++#define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000) ++#define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000) ++#define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000) ++#define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000) ++#define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000) ++ ++/* ++ * LG_FBK_CFG1: ++ */ ++#define LG_FBK_CFG1 0x1360 ++#define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f) ++#define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0) ++#define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00) ++#define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000) ++ ++/* ++ * CCK_PROT_CFG: CCK Protection ++ * 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 ++ * 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 ++ * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow ++ * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow ++ * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow ++ * RTS_TH_EN: RTS threshold enable on CCK TX ++ */ ++#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_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) ++#define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * OFDM_PROT_CFG: OFDM Protection ++ */ ++#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_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) ++#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * MM20_PROT_CFG: MM20 Protection ++ */ ++#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_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) ++#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * MM40_PROT_CFG: MM40 Protection ++ */ ++#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_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) ++#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * GF20_PROT_CFG: GF20 Protection ++ */ ++#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_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) ++#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * GF40_PROT_CFG: GF40 Protection ++ */ ++#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_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) ++#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * EXP_CTS_TIME: ++ */ ++#define EXP_CTS_TIME 0x137c ++ ++/* ++ * EXP_ACK_TIME: ++ */ ++#define EXP_ACK_TIME 0x1380 ++ ++/* ++ * RX_FILTER_CFG: RX configuration register. ++ */ ++#define RX_FILTER_CFG 0x1400 ++#define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001) ++#define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002) ++#define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004) ++#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008) ++#define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010) ++#define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020) ++#define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040) ++#define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080) ++#define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100) ++#define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200) ++#define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400) ++#define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800) ++#define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000) ++#define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000) ++#define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000) ++#define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000) ++#define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000) ++ ++/* ++ * AUTO_RSP_CFG: ++ * AUTORESPONDER: 0: disable, 1: enable ++ * BAC_ACK_POLICY: 0:long, 1:short preamble ++ * CTS_40_MMODE: Response CTS 40MHz duplicate mode ++ * CTS_40_MREF: Response CTS 40MHz duplicate mode ++ * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble ++ * DUAL_CTS_EN: Power bit value in control frame ++ * ACK_CTS_PSM_BIT:Power bit value in control frame ++ */ ++#define AUTO_RSP_CFG 0x1404 ++#define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001) ++#define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002) ++#define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004) ++#define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008) ++#define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010) ++#define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040) ++#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080) ++ ++/* ++ * LEGACY_BASIC_RATE: ++ */ ++#define LEGACY_BASIC_RATE 0x1408 ++ ++/* ++ * HT_BASIC_RATE: ++ */ ++#define HT_BASIC_RATE 0x140c ++ ++/* ++ * HT_CTRL_CFG: ++ */ ++#define HT_CTRL_CFG 0x1410 ++ ++/* ++ * SIFS_COST_CFG: ++ */ ++#define SIFS_COST_CFG 0x1414 ++ ++/* ++ * RX_PARSER_CFG: ++ * Set NAV for all received frames ++ */ ++#define RX_PARSER_CFG 0x1418 ++ ++/* ++ * TX_SEC_CNT0: ++ */ ++#define TX_SEC_CNT0 0x1500 ++ ++/* ++ * RX_SEC_CNT0: ++ */ ++#define RX_SEC_CNT0 0x1504 ++ ++/* ++ * CCMP_FC_MUTE: ++ */ ++#define CCMP_FC_MUTE 0x1508 ++ ++/* ++ * TXOP_HLDR_ADDR0: ++ */ ++#define TXOP_HLDR_ADDR0 0x1600 ++ ++/* ++ * TXOP_HLDR_ADDR1: ++ */ ++#define TXOP_HLDR_ADDR1 0x1604 ++ ++/* ++ * TXOP_HLDR_ET: ++ */ ++#define TXOP_HLDR_ET 0x1608 ++ ++/* ++ * QOS_CFPOLL_RA_DW0: ++ */ ++#define QOS_CFPOLL_RA_DW0 0x160c ++ ++/* ++ * QOS_CFPOLL_RA_DW1: ++ */ ++#define QOS_CFPOLL_RA_DW1 0x1610 ++ ++/* ++ * QOS_CFPOLL_QC: ++ */ ++#define QOS_CFPOLL_QC 0x1614 ++ ++/* ++ * RX_STA_CNT0: RX PLCP error count & RX CRC error count ++ */ ++#define RX_STA_CNT0 0x1700 ++#define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff) ++#define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000) ++ ++/* ++ * RX_STA_CNT1: RX False CCA count & RX LONG frame count ++ */ ++#define RX_STA_CNT1 0x1704 ++#define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff) ++#define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000) ++ ++/* ++ * RX_STA_CNT2: ++ */ ++#define RX_STA_CNT2 0x1708 ++#define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff) ++#define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000) ++ ++/* ++ * TX_STA_CNT0: TX Beacon count ++ */ ++#define TX_STA_CNT0 0x170c ++#define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff) ++#define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_STA_CNT1: TX tx count ++ */ ++#define TX_STA_CNT1 0x1710 ++#define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff) ++#define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000) ++ ++/* ++ * TX_STA_CNT2: TX tx count ++ */ ++#define TX_STA_CNT2 0x1714 ++#define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff) ++#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_STA_FIFO: TX Result for specific PID status fifo register ++ */ ++#define TX_STA_FIFO 0x1718 ++#define TX_STA_FIFO_B_VALID FIELD32(0x00000001) ++#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e) ++#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020) ++#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040) ++#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080) ++#define TX_STA_FIFO_WCID FIELD32(0x0000ff00) ++#define TX_STA_FIFO_SUCCESS_RATE FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT: Debug counter ++ */ ++#define TX_AGG_CNT 0x171c ++#define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT0: ++ */ ++#define TX_AGG_CNT0 0x1720 ++#define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT1: ++ */ ++#define TX_AGG_CNT1 0x1724 ++#define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT2: ++ */ ++#define TX_AGG_CNT2 0x1728 ++#define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT3: ++ */ ++#define TX_AGG_CNT3 0x172c ++#define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT4: ++ */ ++#define TX_AGG_CNT4 0x1730 ++#define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT5: ++ */ ++#define TX_AGG_CNT5 0x1734 ++#define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT6: ++ */ ++#define TX_AGG_CNT6 0x1738 ++#define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT7: ++ */ ++#define TX_AGG_CNT7 0x173c ++#define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000) ++ ++/* ++ * MPDU_DENSITY_CNT: ++ * TX_ZERO_DEL: TX zero length delimiter count ++ * RX_ZERO_DEL: RX zero length delimiter count ++ */ ++#define MPDU_DENSITY_CNT 0x1740 ++#define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff) ++#define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000) ++ ++/* ++ * Security key table memory, base address = 0x1800 ++ */ ++struct hw_pairwise_ta_entry { ++ u8 address[6]; ++ u8 reserved[2]; ++} __attribute__ ((packed)); ++ ++struct wcid_entry { ++ u8 rx_ba_bitmat7; ++ u8 rx_ba_bitmat0; ++ u8 mac[6]; ++} __attribute__ ((packed)); ++ ++struct hw_key_entry { ++ u8 key[16]; ++ u8 tx_mic[8]; ++ u8 rx_mic[8]; ++} __attribute__ ((packed)); ++ ++/* ++ * Security key table memory. ++ * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry ++ * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry ++ * PAIRWISE_IVEIV_TABLE_BASE: 8-byte * 256-entry ++ * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry ++ * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry ++ * SHARED_KEY_TABLE_BASE: 32-byte * 16-entry ++ * SHARED_KEY_MODE_BASE: 32-byte * 16-entry ++ */ ++#define MAC_WCID_BASE 0x1800 ++#define PAIRWISE_KEY_TABLE_BASE 0x4000 ++#define PAIRWISE_IVEIV_TABLE_BASE 0x6000 ++#define MAC_IVEIV_TABLE_BASE 0x6000 ++#define MAC_WCID_ATTRIBUTE_BASE 0x6800 ++#define SHARED_KEY_TABLE_BASE 0x6c00 ++#define SHARED_KEY_MODE_BASE 0x7000 ++ ++#define SHARED_KEY_ENTRY(__idx) \ ++ ( SHARED_KEY_TABLE_BASE + \ ++ ((__idx) * sizeof(struct hw_key_entry)) ) ++#define SHARED_KEY_MODE_ENTRY(__idx) \ ++ ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) ++#define PAIRWISE_KEY_ENTRY(__idx) \ ++ ( PAIRWISE_KEY_TABLE_BASE + \ ++ ((__idx) * sizeof(struct hw_key_entry)) ) ++ ++#define MAC_WCID_ENTRY(__idx) \ ++ ( MAC_WCID_BASE + (2 * sizeof(u32) * (__idx)) ) ++#define MAC_WCID_ATTR_ENTRY(__idx) \ ++ ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) ++ ++/* ++ * MAC_WCID_ATTRIBUTE: ++ * KEYTAB: 0: shared key table, 1: pairwise key table ++ * BSS_IDX: multipleBSS index for the WCID ++ */ ++#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001) ++#define MAC_WCID_ATTRIBUTE_PAIRKEY_MODE FIELD32(0x0000000e) ++#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) ++#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) ++ ++/* ++ * SHARED_KEY_MODE: ++ */ ++#define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007) ++#define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070) ++#define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700) ++#define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000) ++#define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000) ++#define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000) ++#define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000) ++#define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000) ++ ++/* ++ * HOST-MCU communication ++ */ ++ ++/* ++ * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. ++ */ ++#define H2M_MAILBOX_CSR 0x7010 ++#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) ++#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00) ++#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000) ++#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000) ++ ++/* ++ * H2M_MAILBOX_CID: ++ */ ++#define H2M_MAILBOX_CID 0x7014 ++ ++/* ++ * H2M_MAILBOX_STATUS: ++ */ ++#define H2M_MAILBOX_STATUS 0x701c ++ ++/* ++ * H2M_INT_SRC: ++ */ ++#define H2M_INT_SRC 0x7024 ++ ++/* ++ * H2M_BBP_AGENT: ++ */ ++#define H2M_BBP_AGENT 0x7028 ++ ++/* ++ * MCU_LEDCS: LED control for MCU Mailbox. ++ */ ++#define MCU_LEDCS_LED_MODE FIELD8(0x1f) ++#define MCU_LEDCS_POLARITY FIELD8(0x01) ++ ++/* ++ * HW_CS_CTS_BASE: ++ * Carrier-sense CTS frame base address. ++ * It's where mac stores carrier-sense frame for carrier-sense function. ++ */ ++#define HW_CS_CTS_BASE 0x7700 ++ ++/* ++ * HW_DFS_CTS_BASE: ++ * FS CTS frame base address. It's where mac stores CTS frame for DFS. ++ */ ++#define HW_DFS_CTS_BASE 0x7780 ++ ++/* ++ * TXRX control registers - base address 0x3000 ++ */ ++ ++/* ++ * TXRX_CSR1: ++ * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. ++ */ ++#define TXRX_CSR1 0x77d0 ++ ++/* ++ * HW_DEBUG_SETTING_BASE: ++ * since NULL frame won't be that long (256 byte) ++ * We steal 16 tail bytes to save debugging settings ++ */ ++#define HW_DEBUG_SETTING_BASE 0x77f0 ++#define HW_DEBUG_SETTING_BASE2 0x7770 ++ ++/* ++ * HW_BEACON_BASE ++ * In order to support maximum 8 MBSS and its maximum length ++ * is 512 bytes for each beacon ++ * Three section discontinue memory segments will be used. ++ * 1. The original region for BCN 0~3 ++ * 2. Extract memory from FCE table for BCN 4~5 ++ * 3. Extract memory from Pair-wise key table for BCN 6~7 ++ * It occupied those memory of wcid 238~253 for BCN 6 ++ * and wcid 222~237 for BCN 7 ++ * ++ * IMPORTANT NOTE: Not sure why legacy driver does this, ++ * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6. ++ */ ++#define HW_BEACON_BASE0 0x7800 ++#define HW_BEACON_BASE1 0x7a00 ++#define HW_BEACON_BASE2 0x7c00 ++#define HW_BEACON_BASE3 0x7e00 ++#define HW_BEACON_BASE4 0x7200 ++#define HW_BEACON_BASE5 0x7400 ++#define HW_BEACON_BASE6 0x5dc0 ++#define HW_BEACON_BASE7 0x5bc0 ++ ++#define HW_BEACON_OFFSET(__index) \ ++ ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ ++ (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ ++ (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) ++ ++/* ++ * 8051 firmware image. ++ */ ++#define FIRMWARE_RT2860 "rt2860.bin" ++#define FIRMWARE_IMAGE_BASE 0x2000 ++ ++/* ++ * BBP registers. ++ * The wordsize of the BBP is 8 bits. ++ */ ++ ++/* ++ * BBP 1: TX Antenna ++ */ ++#define BBP1_TX_POWER FIELD8(0x07) ++#define BBP1_TX_ANTENNA FIELD8(0x18) ++ ++/* ++ * BBP 3: RX Antenna ++ */ ++#define BBP3_RX_ANTENNA FIELD8(0x18) ++ ++/* ++ * RF registers ++ */ ++ ++/* ++ * RF 2 ++ */ ++#define RF2_ANTENNA_RX2 FIELD32(0x00000040) ++#define RF2_ANTENNA_TX1 FIELD32(0x00004000) ++#define RF2_ANTENNA_RX1 FIELD32(0x00020000) ++ ++/* ++ * RF 3 ++ */ ++#define RF3_TXPOWER_G FIELD32(0x00003e00) ++#define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200) ++#define RF3_TXPOWER_A FIELD32(0x00003c00) ++ ++/* ++ * RF 4 ++ */ ++#define RF4_TXPOWER_G FIELD32(0x000007c0) ++#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040) ++#define RF4_TXPOWER_A FIELD32(0x00000780) ++#define RF4_FREQ_OFFSET FIELD32(0x001f8000) ++#define RF4_BW40 FIELD32(0x00200000) ++ ++/* ++ * EEPROM content. ++ * The wordsize of the EEPROM is 16 bits. ++ */ ++ ++/* ++ * 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_ADDR1 0x0003 ++#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) ++#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) ++#define EEPROM_MAC_ADDR_2 0x0004 ++#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) ++#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) ++ ++/* ++ * EEPROM ANTENNA config ++ * 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) ++ ++/* ++ * 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) ++ ++/* ++ * EEPROM LED ++ * POLARITY_RDY_G: Polarity RDY_G setting. ++ * POLARITY_RDY_A: Polarity RDY_A setting. ++ * POLARITY_ACT: Polarity ACT setting. ++ * POLARITY_GPIO_0: Polarity GPIO0 setting. ++ * POLARITY_GPIO_1: Polarity GPIO1 setting. ++ * POLARITY_GPIO_2: Polarity GPIO2 setting. ++ * POLARITY_GPIO_3: Polarity GPIO3 setting. ++ * 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) ++#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008) ++#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010) ++#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020) ++#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040) ++#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080) ++#define EEPROM_LED_LED_MODE FIELD16(0x1f00) ++ ++/* ++ * 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 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 TXpower delta: 20MHZ AND 40 MHZ use different power. ++ * This is delta in 40MHZ. ++ * VALUE: Tx Power dalta value (MAX=4) ++ * TYPE: 1: Plus the delta value, 0: minus the delta value ++ * TXPOWER: Enable: ++ */ ++#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) ++ ++/* ++ * EEPROM TXPOWER 802.11G ++ */ ++#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 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 byrate: 20MHZ power ++ */ ++#define EEPROM_TXPOWER_BYRATE 0x006f ++ ++/* ++ * 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) ++ ++/* ++ * MCU mailbox commands. ++ */ ++#define MCU_SLEEP 0x30 ++#define MCU_WAKEUP 0x31 ++#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_RADAR 0x60 ++#define MCU_BOOT_SIGNAL 0x72 ++ ++/* ++ * DMA descriptor defines. ++ */ ++#define TXD_DESC_SIZE ( 4 * sizeof(__le32) ) ++#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) ++#define RXD_DESC_SIZE ( 4 * sizeof(__le32) ) ++#define RXWI_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) ++ ++/* ++ * TX WI structure ++ */ ++ ++/* ++ * Word0 ++ * FRAG: 1 To inform TKIP engine this is a fragment. ++ * MIMO_PS: The remote peer is in dynamic MIMO-PS mode ++ * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs ++ * BW: Channel bandwidth 20MHz or 40 MHz ++ * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED ++ */ ++#define TXWI_W0_FRAG FIELD32(0x00000001) ++#define TXWI_W0_MIMO_PS FIELD32(0x00000002) ++#define TXWI_W0_CF_ACK FIELD32(0x00000004) ++#define TXWI_W0_TS FIELD32(0x00000008) ++#define TXWI_W0_AMPDU FIELD32(0x00000010) ++#define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0) ++#define TXWI_W0_TX_OP FIELD32(0x00000300) ++#define TXWI_W0_MCS FIELD32(0x007f0000) ++#define TXWI_W0_BW FIELD32(0x00800000) ++#define TXWI_W0_SHORT_GI FIELD32(0x01000000) ++#define TXWI_W0_STBC FIELD32(0x06000000) ++#define TXWI_W0_IFS FIELD32(0x08000000) ++#define TXWI_W0_PHYMODE FIELD32(0xc0000000) ++ ++/* ++ * Word1 ++ */ ++#define TXWI_W1_ACK FIELD32(0x00000001) ++#define TXWI_W1_NSEQ FIELD32(0x00000002) ++#define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc) ++#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00) ++#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) ++#define TXWI_W1_PACKETID FIELD32(0xf0000000) ++ ++/* ++ * Word2 ++ */ ++#define TXWI_W2_IV FIELD32(0xffffffff) ++ ++/* ++ * Word3 ++ */ ++#define TXWI_W3_EIV FIELD32(0xffffffff) ++ ++/* ++ * 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) ++ ++/* ++ * RX WI structure ++ */ ++ ++/* ++ * Word0 ++ */ ++#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) ++#define RXWI_W0_KEY_INDEX FIELD32(0x00000300) ++#define RXWI_W0_BSSID FIELD32(0x00001c00) ++#define RXWI_W0_UDF FIELD32(0x0000e000) ++#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) ++#define RXWI_W0_TID FIELD32(0xf0000000) ++ ++/* ++ * Word1 ++ */ ++#define RXWI_W1_FRAG FIELD32(0x0000000f) ++#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) ++#define RXWI_W1_MCS FIELD32(0x007f0000) ++#define RXWI_W1_BW FIELD32(0x00800000) ++#define RXWI_W1_SHORT_GI FIELD32(0x01000000) ++#define RXWI_W1_STBC FIELD32(0x06000000) ++#define RXWI_W1_PHYMODE FIELD32(0xc0000000) ++ ++/* ++ * Word2 ++ */ ++#define RXWI_W2_RSSI0 FIELD32(0x000000ff) ++#define RXWI_W2_RSSI1 FIELD32(0x0000ff00) ++#define RXWI_W2_RSSI2 FIELD32(0x00ff0000) ++ ++/* ++ * Word3 ++ */ ++#define RXWI_W3_SNR0 FIELD32(0x000000ff) ++#define RXWI_W3_SNR1 FIELD32(0x0000ff00) ++ ++/* ++ * Macro's for converting txpower from EEPROM to mac80211 value ++ * and from mac80211 value to register value. ++ */ ++#define MIN_G_TXPOWER 0 ++#define MIN_A_TXPOWER -7 ++#define MAX_G_TXPOWER 31 ++#define MAX_A_TXPOWER 15 ++#define DEFAULT_TXPOWER 5 ++ ++#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) ++ ++#endif /* RT2800PCI_H */ +--- /dev/null ++++ b/drivers/net/wireless/rt2x00/rt2800usb.c +@@ -0,0 +1,2594 @@ ++/* ++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project ++ <http://rt2x00.serialmonkey.com> ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the ++ Free Software Foundation, Inc., ++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++/* ++ Module: rt2800usb ++ Abstract: rt2800usb device specific routines. ++ Supported chipsets: RT2800U. ++ */ ++ ++#include <linux/crc-ccitt.h> ++#include <linux/delay.h> ++#include <linux/etherdevice.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/usb.h> ++ ++#include "rt2x00.h" ++#include "rt2x00usb.h" ++#include "rt2800usb.h" ++ ++/* ++ * Allow hardware encryption to be disabled. ++ */ ++static int modparam_nohwcrypt = 0; ++module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); ++MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); ++ ++/* ++ * Register access. ++ * All access to the CSR registers will go through the methods ++ * rt2800usb_register_read and rt2800usb_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, ++ * the access attempt is considered to have failed, ++ * and we will print an error. ++ * The _lock versions must be used if you already hold the usb_cache_mutex ++ */ ++static inline void rt2800usb_register_read(struct rt2x00_dev *rt2x00dev, ++ const unsigned int offset, ++ u32 *value) ++{ ++ __le32 reg; ++ rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, ++ USB_VENDOR_REQUEST_IN, offset, ++ ®, sizeof(u32), REGISTER_TIMEOUT); ++ *value = le32_to_cpu(reg); ++} ++ ++static inline void rt2800usb_register_read_lock(struct rt2x00_dev *rt2x00dev, ++ const unsigned int offset, ++ u32 *value) ++{ ++ __le32 reg; ++ rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, ++ USB_VENDOR_REQUEST_IN, offset, ++ ®, sizeof(u32), REGISTER_TIMEOUT); ++ *value = le32_to_cpu(reg); ++} ++ ++static inline void rt2800usb_register_multiread(struct rt2x00_dev *rt2x00dev, ++ const unsigned int offset, ++ void *value, const u32 length) ++{ ++ int timeout = REGISTER_TIMEOUT * (length / sizeof(u32)); ++ rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, ++ USB_VENDOR_REQUEST_IN, offset, ++ value, length, timeout); ++} ++ ++static inline void rt2800usb_register_write(struct rt2x00_dev *rt2x00dev, ++ const unsigned int offset, ++ u32 value) ++{ ++ __le32 reg = cpu_to_le32(value); ++ rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, ++ USB_VENDOR_REQUEST_OUT, offset, ++ ®, sizeof(u32), REGISTER_TIMEOUT); ++} ++ ++static inline void rt2800usb_register_write_lock(struct rt2x00_dev *rt2x00dev, ++ const unsigned int offset, ++ u32 value) ++{ ++ __le32 reg = cpu_to_le32(value); ++ rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, ++ USB_VENDOR_REQUEST_OUT, offset, ++ ®, sizeof(u32), REGISTER_TIMEOUT); ++} ++ ++static inline void rt2800usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, ++ const unsigned int offset, ++ void *value, const u32 length) ++{ ++ int timeout = REGISTER_TIMEOUT * (length / sizeof(u32)); ++ rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, ++ USB_VENDOR_REQUEST_OUT, offset, ++ value, length, timeout); ++} ++ ++static u32 rt2800usb_bbp_check(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ unsigned int i; ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2800usb_register_read_lock(rt2x00dev, BBP_CSR_CFG, ®); ++ if (!rt2x00_get_field32(reg, BBP_CSR_CFG_BUSY)) ++ break; ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ return reg; ++} ++ ++static void rt2800usb_bbp_write(struct rt2x00_dev *rt2x00dev, ++ const unsigned int word, const u8 value) ++{ ++ u32 reg; ++ ++ mutex_lock(&rt2x00dev->usb_cache_mutex); ++ ++ /* ++ * Wait until the BBP becomes ready. ++ */ ++ reg = rt2800usb_bbp_check(rt2x00dev); ++ if (rt2x00_get_field32(reg, BBP_CSR_CFG_BUSY)) { ++ ERROR(rt2x00dev, "BBP_CSR_CFG register busy. Write failed.\n"); ++ mutex_unlock(&rt2x00dev->usb_cache_mutex); ++ return; ++ } ++ ++ /* ++ * Write the data into the BBP. ++ */ ++ reg = 0; ++ rt2x00_set_field32(®, BBP_CSR_CFG_VALUE, value); ++ rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); ++ rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); ++ rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); ++ ++ rt2800usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); ++ mutex_unlock(&rt2x00dev->usb_cache_mutex); ++} ++ ++static void rt2800usb_bbp_read(struct rt2x00_dev *rt2x00dev, ++ const unsigned int word, u8 *value) ++{ ++ u32 reg; ++ ++ mutex_lock(&rt2x00dev->usb_cache_mutex); ++ ++ /* ++ * Wait until the BBP becomes ready. ++ */ ++ reg = rt2800usb_bbp_check(rt2x00dev); ++ if (rt2x00_get_field32(reg, BBP_CSR_CFG_BUSY)) { ++ ERROR(rt2x00dev, "BBP_CSR_CFG register busy. Read failed.\n"); ++ mutex_unlock(&rt2x00dev->usb_cache_mutex); ++ return; ++ } ++ ++ /* ++ * Write the request into the BBP. ++ */ ++ reg = 0; ++ rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); ++ rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); ++ rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); ++ ++ rt2800usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); ++ ++ /* ++ * Wait until the BBP becomes ready. ++ */ ++ reg = rt2800usb_bbp_check(rt2x00dev); ++ if (rt2x00_get_field32(reg, BBP_CSR_CFG_BUSY)) { ++ ERROR(rt2x00dev, "BBP_CSR_CFG register busy. Read failed.\n"); ++ *value = 0xff; ++ return; ++ } ++ ++ *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE); ++ mutex_unlock(&rt2x00dev->usb_cache_mutex); ++} ++ ++static void rt2800usb_rf_write(struct rt2x00_dev *rt2x00dev, ++ const unsigned int word, const u32 value) ++{ ++ u32 reg; ++ unsigned int i; ++ ++ if (!word) ++ return; ++ ++ mutex_lock(&rt2x00dev->usb_cache_mutex); ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2800usb_register_read_lock(rt2x00dev, RF_CSR_CFG0, ®); ++ if (!rt2x00_get_field32(reg, RF_CSR_CFG0_BUSY)) ++ goto rf_write; ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ mutex_unlock(&rt2x00dev->usb_cache_mutex); ++ ERROR(rt2x00dev, "RF_CSR_CFG0 register busy. Write failed.\n"); ++ return; ++ ++rf_write: ++ reg = 0; ++ rt2x00_set_field32(®, RF_CSR_CFG0_REG_VALUE_BW, value); ++ rt2x00_set_field32(®, RF_CSR_CFG0_STANDBYMODE, 0); ++ rt2x00_set_field32(®, RF_CSR_CFG0_SEL, 0); ++ rt2x00_set_field32(®, RF_CSR_CFG0_BUSY, 1); ++ ++ rt2800usb_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg); ++ rt2x00_rf_write(rt2x00dev, word, value); ++ mutex_unlock(&rt2x00dev->usb_cache_mutex); ++} ++ ++static void rt2800usb_mcu_request(struct rt2x00_dev *rt2x00dev, ++ const u8 command, const u8 token, ++ const u8 arg0, const u8 arg1) ++{ ++ unsigned int i; ++ u32 reg; ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2800usb_register_read(rt2x00dev, H2M_MAILBOX_CSR, ®); ++ if (!rt2x00_get_field32(reg, H2M_MAILBOX_CSR_OWNER)) ++ goto mcu_write; ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ ERROR(rt2x00dev, "mcu request error. " ++ "Request 0x%02x failed for token 0x%02x.\n", ++ command, token); ++ return; ++ ++mcu_write: ++ rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); ++ 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); ++ rt2800usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); ++ ++ reg = 0; ++ rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); ++ rt2800usb_register_write(rt2x00dev, HOST_CMD_CSR, reg); ++} ++ ++#ifdef CONFIG_RT2X00_LIB_DEBUGFS ++static const struct rt2x00debug rt2800usb_rt2x00debug = { ++ .owner = THIS_MODULE, ++ .csr = { ++ .read = rt2800usb_register_read, ++ .write = rt2800usb_register_write, ++ .flags = RT2X00DEBUGFS_OFFSET, ++ .word_base = CSR_REG_BASE, ++ .word_size = sizeof(u32), ++ .word_count = CSR_REG_SIZE / sizeof(u32), ++ }, ++ .eeprom = { ++ .read = rt2x00_eeprom_read, ++ .write = rt2x00_eeprom_write, ++ .word_base = EEPROM_BASE, ++ .word_size = sizeof(u16), ++ .word_count = EEPROM_SIZE / sizeof(u16), ++ }, ++ .bbp = { ++ .read = rt2800usb_bbp_read, ++ .write = rt2800usb_bbp_write, ++ .word_base = BBP_BASE, ++ .word_size = sizeof(u8), ++ .word_count = BBP_SIZE / sizeof(u8), ++ }, ++ .rf = { ++ .read = rt2x00_rf_read, ++ .write = rt2800usb_rf_write, ++ .word_base = RF_BASE, ++ .word_size = sizeof(u32), ++ .word_count = RF_SIZE / sizeof(u32), ++ }, ++}; ++#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ ++ ++#ifdef CONFIG_RT2X00_LIB_LEDS ++static void rt2800usb_brightness_set(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct rt2x00_led *led = ++ container_of(led_cdev, struct rt2x00_led, led_dev); ++ unsigned int enabled = brightness != LED_OFF; ++ unsigned int bg_mode = ++ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); ++ unsigned int polarity = ++ rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, ++ EEPROM_FREQ_LED_POLARITY); ++ unsigned int ledmode = ++ rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, ++ EEPROM_FREQ_LED_MODE); ++ ++ if (led->type == LED_TYPE_RADIO) { ++ rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, ++ enabled ? 0x20 : 0); ++ } else if (led->type == LED_TYPE_ASSOC) { ++ rt2800usb_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 ++ */ ++ rt2800usb_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, ++ (1 << brightness / (LED_FULL / 6)) - 1, ++ polarity); ++ } ++} ++ ++static int rt2800usb_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; ++ ++ rt2800usb_register_read(led->rt2x00dev, LED_CFG, ®); ++ rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); ++ rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); ++ rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); ++ rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); ++ rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); ++ rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); ++ rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); ++ rt2800usb_register_write(led->rt2x00dev, LED_CFG, reg); ++ ++ return 0; ++} ++ ++static void rt2800usb_init_led(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00_led *led, ++ enum led_type type) ++{ ++ led->rt2x00dev = rt2x00dev; ++ led->type = type; ++ led->led_dev.brightness_set = rt2800usb_brightness_set; ++ led->led_dev.blink_set = rt2800usb_blink_set; ++ led->flags = LED_INITIALIZED; ++} ++#endif /* CONFIG_RT2X00_LIB_LEDS */ ++ ++/* ++ * Configuration handlers. ++ */ ++static void rt2800usb_config_wcid_attr(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_crypto *crypto, ++ struct ieee80211_key_conf *key) ++{ ++ u32 offset; ++ u32 reg; ++ ++ offset = MAC_WCID_ATTR_ENTRY(crypto->aid); ++ ++ reg = 0; ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, ++ !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_PAIRKEY_MODE, ++ crypto->cipher); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, ++ (crypto->cmd == SET_KEY) ? crypto->bssidx : 0); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, 0); ++ rt2800usb_register_write(rt2x00dev, offset, reg); ++} ++ ++static int rt2800usb_config_shared_key(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_crypto *crypto, ++ struct ieee80211_key_conf *key) ++{ ++ struct hw_key_entry key_entry; ++ struct rt2x00_field32 field; ++ int timeout; ++ u32 offset; ++ u32 mask; ++ u32 reg; ++ ++ if (crypto->cmd == SET_KEY) { ++ memcpy(key_entry.key, crypto->key, ++ sizeof(key_entry.key)); ++ memcpy(key_entry.tx_mic, crypto->tx_mic, ++ sizeof(key_entry.tx_mic)); ++ memcpy(key_entry.rx_mic, crypto->rx_mic, ++ sizeof(key_entry.rx_mic)); ++ ++ offset = SHARED_KEY_ENTRY(key->hw_key_idx); ++ timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); ++ rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, ++ USB_VENDOR_REQUEST_OUT, ++ offset, &key_entry, ++ sizeof(key_entry), ++ timeout); ++ ++ /* ++ * The driver does not support the IV/EIV generation ++ * in hardware. However it doesn't support the IV/EIV ++ * inside the ieee80211 frame either, but requires it ++ * to be provided seperately for the descriptor. ++ * rt2x00lib will cut the IV/EIV data out of all frames ++ * given to us by mac80211, but we must tell mac80211 ++ * to generate the IV/EIV data. ++ */ ++ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; ++ } ++ ++ /* ++ * The cipher types are stored over multiple registers ++ * starting with SHARED_KEY_MODE_BASE each word will have ++ * 32 bits and contains the cipher types for 2 modes each. ++ * Using the correct defines correctly will cause overhead, ++ * so just calculate the correct offset. ++ */ ++ mask = key->hw_key_idx % 8; ++ field.bit_offset = (3 * mask); ++ field.bit_mask = 0x7 << field.bit_offset; ++ ++ offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); ++ rt2800usb_register_read(rt2x00dev, offset, ®); ++ rt2x00_set_field32(®, field, ++ (crypto->cmd == SET_KEY) ? crypto->cipher : 0); ++ rt2800usb_register_write(rt2x00dev, offset, reg); ++ ++ /* ++ * Update WCID information ++ */ ++ rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); ++ ++ return 0; ++} ++ ++static int rt2800usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_crypto *crypto, ++ struct ieee80211_key_conf *key) ++{ ++ struct hw_key_entry key_entry; ++ int timeout; ++ u32 offset; ++ ++ /* ++ * 1 pairwise key is possible per AID, this means that the AID ++ * equals our hw_key_idx. ++ */ ++ key->hw_key_idx = crypto->aid; ++ ++ if (crypto->cmd == SET_KEY) { ++ memcpy(key_entry.key, crypto->key, ++ sizeof(key_entry.key)); ++ memcpy(key_entry.tx_mic, crypto->tx_mic, ++ sizeof(key_entry.tx_mic)); ++ memcpy(key_entry.rx_mic, crypto->rx_mic, ++ sizeof(key_entry.rx_mic)); ++ ++ offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); ++ timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); ++ rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, ++ USB_VENDOR_REQUEST_OUT, ++ offset, &key_entry, ++ sizeof(key_entry), ++ timeout); ++ ++ /* ++ * The driver does not support the IV/EIV generation ++ * in hardware. However it doesn't support the IV/EIV ++ * inside the ieee80211 frame either, but requires it ++ * to be provided seperately for the descriptor. ++ * rt2x00lib will cut the IV/EIV data out of all frames ++ * given to us by mac80211, but we must tell mac80211 ++ * to generate the IV/EIV data. ++ */ ++ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; ++ } ++ ++ /* ++ * Update WCID information ++ */ ++ rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); ++ ++ return 0; ++} ++ ++static void rt2800usb_config_filter(struct rt2x00_dev *rt2x00dev, ++ const unsigned int filter_flags) ++{ ++ u32 reg; ++ ++ /* ++ * Start configuration steps. ++ * Note that the version error will always be dropped ++ * and broadcast frames will always be accepted since ++ * there is no filter for it at this time. ++ */ ++ rt2800usb_register_read(rt2x00dev, RX_FILTER_CFG, ®); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, ++ !(filter_flags & FIF_FCSFAIL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, ++ !(filter_flags & FIF_PLCPFAIL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, ++ !(filter_flags & FIF_PROMISC_IN_BSS)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, ++ !(filter_flags & FIF_ALLMULTI)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, ++ !(filter_flags & FIF_CONTROL)); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 1); ++ rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, ++ !(filter_flags & FIF_CONTROL)); ++ rt2800usb_register_write(rt2x00dev, RX_FILTER_CFG, reg); ++} ++ ++static void rt2800usb_config_intf(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00_intf *intf, ++ 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); ++ rt2800usb_register_write(rt2x00dev, beacon_base, 0); ++ ++ /* ++ * Enable synchronisation. ++ */ ++ rt2800usb_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, 1); ++ rt2800usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); ++ } ++ ++ if (flags & CONFIG_UPDATE_MAC) { ++ reg = le32_to_cpu(conf->mac[1]); ++ rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); ++ conf->mac[1] = cpu_to_le32(reg); ++ ++ rt2800usb_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, ++ conf->mac, sizeof(conf->mac)); ++ } ++ ++ if (flags & CONFIG_UPDATE_BSSID) { ++ reg = le32_to_cpu(conf->bssid[1]); ++ rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); ++ rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); ++ conf->bssid[1] = cpu_to_le32(reg); ++ ++ rt2800usb_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, ++ conf->bssid, sizeof(conf->bssid)); ++ } ++} ++ ++static void rt2800usb_config_erp(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_erp *erp) ++{ ++ u32 reg; ++ ++ rt2800usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); ++ rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, ++ erp->ack_timeout); ++ rt2800usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, AUTO_RSP_CFG, ®); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, ++ !!erp->short_preamble); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, ++ !!erp->short_preamble); ++ rt2800usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); ++ rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, ++ erp->cts_protection ? 2 : 0); ++ rt2800usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); ++ ++ rt2800usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, ++ erp->basic_rates); ++ rt2800usb_register_write(rt2x00dev, HT_BASIC_RATE, ++ erp->basic_rates >> 32); ++ ++ rt2800usb_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); ++ rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); ++ rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); ++ rt2800usb_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, XIFS_TIME_CFG, ®); ++ rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); ++ rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); ++ rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); ++ rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); ++ rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); ++ rt2800usb_register_write(rt2x00dev, XIFS_TIME_CFG, reg); ++} ++ ++static void rt2800usb_config_ant(struct rt2x00_dev *rt2x00dev, ++ struct antenna_setup *ant) ++{ ++ u16 eeprom; ++ u8 r1; ++ u8 r3; ++ ++ /* ++ * FIXME: Use requested antenna configuration. ++ */ ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); ++ ++ rt2800usb_bbp_read(rt2x00dev, 1, &r1); ++ rt2800usb_bbp_read(rt2x00dev, 3, &r3); ++ ++ /* ++ * Configure the TX antenna. ++ */ ++ switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH)) { ++ case 1: ++ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); ++ break; ++ case 2: ++ case 3: ++ /* Do nothing */ ++ break; ++ } ++ ++ /* ++ * Configure the RX antenna. ++ */ ++ switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { ++ case 1: ++ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); ++ break; ++ case 2: ++ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); ++ break; ++ case 3: ++ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); ++ break; ++ } ++ ++ rt2800usb_bbp_write(rt2x00dev, 3, r3); ++ rt2800usb_bbp_write(rt2x00dev, 1, r1); ++} ++ ++static void rt2800usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_conf *libconf) ++{ ++ u16 eeprom; ++ short lna_gain; ++ ++ if (libconf->rf.channel <= 14) { ++ rt2x00_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); ++ 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); ++ } else { ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); ++ lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); ++ } ++ ++ rt2x00dev->lna_gain = lna_gain; ++} ++ ++static void rt2800usb_config_channel(struct rt2x00_dev *rt2x00dev, ++ struct rf_channel *rf, ++ struct channel_info *info) ++{ ++ u32 reg; ++ unsigned int tx_pin; ++ u16 eeprom; ++ ++ tx_pin = 0; ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); ++ 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_LNA_PE_A1_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_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(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); ++ ++ /* ++ * Determine antenna settings from EEPROM ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); ++ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1) { ++ rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); ++ /* Turn off unused PA or LNA when only 1T or 1R */ ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 0); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 0); ++ } ++ ++ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1) { ++ rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); ++ rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); ++ /* Turn off unused PA or LNA when only 1T or 1R */ ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 0); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 0); ++ } else if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 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). ++ * However this means that values between 0 and 7 have ++ * double meaning, and we should set a 7DBm boost flag. ++ */ ++ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, ++ (info->tx_power1 >= 0)); ++ ++ if (info->tx_power1 < 0) ++ info->tx_power1 += 7; ++ ++ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, ++ TXPOWER_A_TO_DEV(info->tx_power1)); ++ ++ rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, ++ (info->tx_power2 >= 0)); ++ ++ if (info->tx_power2 < 0) ++ info->tx_power2 += 7; ++ ++ rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, ++ TXPOWER_A_TO_DEV(info->tx_power2)); ++ ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 1); ++ } else { ++ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, ++ TXPOWER_G_TO_DEV(info->tx_power1)); ++ rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, ++ TXPOWER_G_TO_DEV(info->tx_power2)); ++ ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1); ++ } ++ ++ ++ /* FIXME: How to determine bandwidth ++ rt2x00_set_field32(&rf->rf4, RF4_BW40, !!(BBPCurrentBW == BW_40)); ++ */ ++ ++ rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); ++ rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); ++ rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); ++ rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); ++ ++ udelay(200); ++ ++ rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); ++ rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); ++ rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); ++ rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); ++ ++ udelay(200); ++ ++ rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); ++ rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); ++ rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); ++ rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); ++ ++ /* ++ * Change BBP settings ++ */ ++ rt2800usb_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); ++ rt2800usb_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); ++ rt2800usb_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); ++ rt2800usb_bbp_write(rt2x00dev, 86, 0); ++ ++ if (rf->channel <= 14) { ++ if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { ++ rt2800usb_bbp_write(rt2x00dev, 82, 0x62); ++ rt2800usb_bbp_write(rt2x00dev, 75, 0x46); ++ } else { ++ rt2800usb_bbp_write(rt2x00dev, 82, 0x84); ++ rt2800usb_bbp_write(rt2x00dev, 75, 0x50); ++ } ++ ++ rt2800usb_register_read(rt2x00dev, TX_BAND_CFG, ®); ++ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_A, 0); ++ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_BG, 1); ++ rt2800usb_register_write(rt2x00dev, TX_BAND_CFG, reg); ++ } else { ++ rt2800usb_bbp_write(rt2x00dev, 82, 0xf2); ++ ++ if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) ++ rt2800usb_bbp_write(rt2x00dev, 75, 0x46); ++ else ++ rt2800usb_bbp_write(rt2x00dev, 75, 0x50); ++ ++ rt2800usb_register_read(rt2x00dev, TX_BAND_CFG, ®); ++ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_A, 1); ++ rt2x00_set_field32(&rf->rf3, TX_BAND_CFG_BG, 0); ++ rt2800usb_register_write(rt2x00dev, TX_BAND_CFG, reg); ++ } ++ ++ rt2800usb_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); ++ ++ msleep(1); ++} ++ ++static void rt2800usb_config_txpower(struct rt2x00_dev *rt2x00dev, ++ const int txpower) ++{ ++ u32 reg; ++ u32 value = TXPOWER_G_TO_DEV(txpower); ++ u8 r1; ++ ++ rt2800usb_bbp_read(rt2x00dev, 1, &r1); ++ rt2x00_set_field8(®, BBP1_TX_POWER, 0); ++ rt2800usb_bbp_write(rt2x00dev, 1, r1); ++ ++ rt2800usb_register_read(rt2x00dev, TX_PWR_CFG_0, ®); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); ++ rt2800usb_register_write(rt2x00dev, TX_PWR_CFG_0, reg); ++ ++ rt2800usb_register_read(rt2x00dev, TX_PWR_CFG_1, ®); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); ++ rt2800usb_register_write(rt2x00dev, TX_PWR_CFG_1, reg); ++ ++ rt2800usb_register_read(rt2x00dev, TX_PWR_CFG_2, ®); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); ++ rt2800usb_register_write(rt2x00dev, TX_PWR_CFG_2, reg); ++ ++ rt2800usb_register_read(rt2x00dev, TX_PWR_CFG_3, ®); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); ++ rt2800usb_register_write(rt2x00dev, TX_PWR_CFG_3, reg); ++ ++ rt2800usb_register_read(rt2x00dev, TX_PWR_CFG_4, ®); ++ rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); ++ rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); ++ rt2800usb_register_write(rt2x00dev, TX_PWR_CFG_4, reg); ++} ++ ++static void rt2800usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_conf *libconf) ++{ ++ u32 reg; ++ ++ rt2800usb_register_read(rt2x00dev, TX_RTY_CFG, ®); ++ rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, ++ libconf->conf->short_frame_max_tx_count); ++ rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, ++ libconf->conf->long_frame_max_tx_count); ++ rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); ++ rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); ++ rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); ++ rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); ++ rt2800usb_register_write(rt2x00dev, TX_RTY_CFG, reg); ++} ++ ++static void rt2800usb_config_duration(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_conf *libconf) ++{ ++ u32 reg; ++ ++ rt2800usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); ++ rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, ++ libconf->conf->beacon_int * 16); ++ rt2800usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); ++} ++ ++static void rt2800usb_config(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_conf *libconf, ++ const unsigned int flags) ++{ ++ /* Always recalculate LNA gain before changing configuration */ ++ rt2800usb_config_lna_gain(rt2x00dev, libconf); ++ ++ if (flags & IEEE80211_CONF_CHANGE_CHANNEL) ++ rt2800usb_config_channel(rt2x00dev, &libconf->rf, ++ &libconf->channel); ++ if (flags & IEEE80211_CONF_CHANGE_POWER) ++ rt2800usb_config_txpower(rt2x00dev, libconf->conf->power_level); ++ if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) ++ rt2800usb_config_retry_limit(rt2x00dev, libconf); ++ if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) ++ rt2800usb_config_duration(rt2x00dev, libconf); ++} ++ ++/* ++ * Link tuning ++ */ ++static void rt2800usb_link_stats(struct rt2x00_dev *rt2x00dev, ++ struct link_qual *qual) ++{ ++ u32 reg; ++ ++ /* ++ * Update FCS error count from register. ++ */ ++ rt2800usb_register_read(rt2x00dev, RX_STA_CNT0, ®); ++ qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); ++ ++ /* ++ * Update False CCA count from register. ++ */ ++ rt2800usb_register_read(rt2x00dev, RX_STA_CNT1, ®); ++ qual->false_cca = rt2x00_get_field32(reg, RX_STA_CNT1_FALSE_CCA); ++} ++ ++static void rt2800usb_reset_tuner(struct rt2x00_dev *rt2x00dev) ++{ ++ u8 r66; ++ ++ if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) ++ r66 = 0x2e + rt2x00dev->lna_gain; ++ else { ++ if (1 /* FIXME: pAd->CommonCfg.BBPCurrentBW == BW_20 */) ++ r66 = 0x32 + (rt2x00dev->lna_gain * 5) / 3; ++ else ++ r66 = 0x3a + (rt2x00dev->lna_gain * 5) / 3; ++ } ++ ++ rt2800usb_bbp_write(rt2x00dev, 66, r66); ++} ++ ++static void rt2800usb_link_tuner(struct rt2x00_dev *rt2x00dev) ++{ ++ int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); ++ u8 r66_orig; ++ u8 r66; ++ ++ if (rt2x00_rev(&rt2x00dev->chip) == RT2870_VERSION_C) ++ return; ++ ++ rt2800usb_bbp_read(rt2x00dev, 66, &r66_orig); ++ r66 = r66_orig; ++ ++ if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { ++ r66 = 0x2e + rt2x00dev->lna_gain; ++ } else { ++ if (1 /* FIXME: pAd->CommonCfg.BBPCurrentBW == BW_20 */) ++ r66 = 0x32 + (rt2x00dev->lna_gain * 5) / 3; ++ else ++ r66 = 0x3a + (rt2x00dev->lna_gain * 5) / 3; ++ } ++ ++ if (rssi > -80) ++ r66 += 0x10; ++ ++ if (rssi != r66_orig) ++ rt2800usb_bbp_write(rt2x00dev, 66, r66); ++} ++ ++/* ++ * Firmware functions ++ */ ++static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) ++{ ++ return FIRMWARE_RT2870; ++} ++ ++static u16 rt2800usb_get_firmware_crc(const void *data, const size_t len) ++{ ++ u16 crc; ++ ++ /* ++ * Use the crc ccitt algorithm. ++ * This will return the same value as the legacy driver which ++ * used bit ordering reversion on the both the firmware bytes ++ * before input input as well as on the final output. ++ * Obviously using crc ccitt directly is much more efficient. ++ * The last 2 bytes in the firmware array are the crc checksum itself, ++ * this means that we should never pass those 2 bytes to the crc ++ * algorithm. ++ */ ++ crc = crc_ccitt(~0, data, len - 2); ++ ++ /* ++ * There is a small difference between the crc-itu-t + bitrev and ++ * the crc-ccitt crc calculation. In the latter method the 2 bytes ++ * will be swapped, use swab16 to convert the crc to the correct ++ * value. ++ */ ++ return swab16(crc); ++} ++ ++static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, ++ const void *data, const size_t len) ++{ ++ unsigned int i; ++ int status; ++ u32 reg; ++ ++ /* ++ * Wait for stable hardware. ++ */ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2800usb_register_read(rt2x00dev, MAC_CSR0, ®); ++ if (reg && reg != ~0) ++ break; ++ msleep(1); ++ } ++ ++ if (i == REGISTER_BUSY_COUNT) { ++ ERROR(rt2x00dev, "Unstable hardware.\n"); ++ return -EBUSY; ++ } ++ ++ /* ++ * Write firmware to device. ++ */ ++ rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, ++ USB_VENDOR_REQUEST_OUT, ++ FIRMWARE_IMAGE_BASE, ++ data, len, ++ REGISTER_TIMEOUT32(len)); ++ ++ rt2800usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); ++ rt2800usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); ++ ++ /* ++ * Send firmware request to device to load firmware, ++ * we need to specify a long timeout time. ++ */ ++ status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, ++ 0, USB_MODE_FIRMWARE, ++ REGISTER_TIMEOUT_FIRMWARE); ++ if (status < 0) { ++ ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); ++ return status; ++ } ++ ++ /* ++ * Wait for device to stabilize. ++ */ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2800usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); ++ if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) ++ break; ++ msleep(1); ++ } ++ ++ if (i == REGISTER_BUSY_COUNT) { ++ ERROR(rt2x00dev, "PBF system register not ready.\n"); ++ return -EBUSY; ++ } ++ ++ /* ++ * Initialize firmware. ++ */ ++ rt2800usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0); ++ rt2800usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); ++ msleep(1); ++ ++ return 0; ++} ++ ++/* ++ * Initialization functions. ++ */ ++static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ unsigned int i; ++ ++ /* ++ * Wait untill BBP and RF are ready. ++ */ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2800usb_register_read(rt2x00dev, MAC_CSR0, ®); ++ if (reg && reg != ~0) ++ break; ++ msleep(1); ++ } ++ ++ if (i == REGISTER_BUSY_COUNT) { ++ ERROR(rt2x00dev, "Unstable hardware.\n"); ++ return -EBUSY; ++ } ++ ++ rt2800usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); ++ rt2800usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); ++ ++ rt2800usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); ++ rt2800usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); ++ ++ rt2800usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); ++ ++ rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, ++ USB_MODE_RESET, REGISTER_TIMEOUT); ++ ++ rt2800usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); ++ ++ rt2800usb_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 */ ++ rt2800usb_register_write(rt2x00dev, BCN_OFFSET0, reg); ++ ++ rt2800usb_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 */ ++ rt2800usb_register_write(rt2x00dev, BCN_OFFSET1, reg); ++ ++ rt2800usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); ++ rt2800usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); ++ ++ rt2800usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); ++ ++ rt2800usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); ++ rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 0); ++ rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); ++ rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0); ++ rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); ++ rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); ++ rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); ++ rt2800usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); ++ ++ rt2800usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00040a06); ++ rt2800usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); ++ ++ rt2800usb_register_read(rt2x00dev, TX_LINK_CFG, ®); ++ rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32); ++ rt2x00_set_field32(®, TX_LINK_CFG_MFB_ENABLE, 0); ++ rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0); ++ rt2x00_set_field32(®, TX_LINK_CFG_TX_MRQ_EN, 0); ++ rt2x00_set_field32(®, TX_LINK_CFG_TX_RDG_EN, 0); ++ rt2x00_set_field32(®, TX_LINK_CFG_TX_CF_ACK_EN, 1); ++ rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB, 0); ++ rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFS, 0); ++ rt2800usb_register_write(rt2x00dev, TX_LINK_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); ++ rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); ++ rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); ++ rt2800usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, MAX_LEN_CFG, ®); ++ rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); ++ rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); ++ rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 0); ++ rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); ++ rt2800usb_register_write(rt2x00dev, MAX_LEN_CFG, reg); ++ ++ rt2800usb_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); ++ ++ rt2800usb_register_read(rt2x00dev, AUTO_RSP_CFG, ®); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); ++ rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); ++ rt2800usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg); ++ ++ rt2800usb_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_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); ++ rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 0); ++ rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1); ++ rt2800usb_register_write(rt2x00dev, CCK_PROT_CFG, reg); ++ ++ rt2800usb_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_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); ++ rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 0); ++ rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1); ++ rt2800usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); ++ ++ rt2800usb_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_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); ++ rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); ++ rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); ++ rt2800usb_register_write(rt2x00dev, MM20_PROT_CFG, reg); ++ ++ rt2800usb_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_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); ++ rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); ++ rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); ++ rt2800usb_register_write(rt2x00dev, MM40_PROT_CFG, reg); ++ ++ rt2800usb_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_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); ++ rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); ++ rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); ++ rt2800usb_register_write(rt2x00dev, GF20_PROT_CFG, reg); ++ ++ rt2800usb_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_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); ++ rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); ++ rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); ++ rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); ++ rt2800usb_register_write(rt2x00dev, GF40_PROT_CFG, reg); ++ ++ rt2800usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); ++ ++ rt2800usb_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_WP_DMA_BURST_SIZE, 3); ++ rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0); ++ rt2x00_set_field32(®, WPDMA_GLO_CFG_BIG_ENDIAN, 0); ++ rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0); ++ rt2x00_set_field32(®, WPDMA_GLO_CFG_HDR_SEG_LEN, 0); ++ rt2800usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); ++ ++ rt2800usb_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); ++ rt2800usb_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); ++ ++ rt2800usb_register_read(rt2x00dev, TX_RTS_CFG, ®); ++ rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); ++ rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); ++ rt2800usb_register_write(rt2x00dev, TX_RTS_CFG, reg); ++ ++ rt2800usb_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); ++ rt2800usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); ++ ++ /* ++ * ASIC will keep garbage value after boot, clear encryption keys. ++ */ ++ for (i = 0; i < 254; i++) { ++ u32 wcid[2] = { 0xffffffff, 0x0000ffff }; ++ rt2800usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), ++ wcid, sizeof(wcid)); ++ } ++ ++ for (i = 0; i < 4; i++) ++ rt2800usb_register_write(rt2x00dev, ++ SHARED_KEY_MODE_ENTRY(i), 0); ++ ++ for (i = 0; i < 256; i++) ++ rt2800usb_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); ++ ++ /* ++ * Clear all beacons ++ * 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. ++ */ ++ rt2800usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); ++ rt2800usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); ++ rt2800usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); ++ rt2800usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); ++ rt2800usb_register_write(rt2x00dev, HW_BEACON_BASE4, 0); ++ rt2800usb_register_write(rt2x00dev, HW_BEACON_BASE5, 0); ++ rt2800usb_register_write(rt2x00dev, HW_BEACON_BASE6, 0); ++ rt2800usb_register_write(rt2x00dev, HW_BEACON_BASE7, 0); ++ ++ rt2800usb_register_read(rt2x00dev, USB_CYC_CFG, ®); ++ rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); ++ rt2800usb_register_write(rt2x00dev, USB_CYC_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, HT_FBK_CFG0, ®); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS0FBK, 0); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS1FBK, 0); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS2FBK, 1); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS3FBK, 2); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS4FBK, 3); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS5FBK, 4); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS6FBK, 5); ++ rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS7FBK, 6); ++ rt2800usb_register_write(rt2x00dev, HT_FBK_CFG0, reg); ++ ++ rt2800usb_register_read(rt2x00dev, HT_FBK_CFG1, ®); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS8FBK, 8); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS9FBK, 8); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS10FBK, 9); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS11FBK, 10); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS12FBK, 11); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS13FBK, 12); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS14FBK, 13); ++ rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS15FBK, 14); ++ rt2800usb_register_write(rt2x00dev, HT_FBK_CFG1, reg); ++ ++ rt2800usb_register_read(rt2x00dev, LG_FBK_CFG0, ®); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 10); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 11); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 12); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 13); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS6FBK, 14); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS7FBK, 15); ++ rt2800usb_register_write(rt2x00dev, LG_FBK_CFG0, reg); ++ ++ rt2800usb_register_read(rt2x00dev, LG_FBK_CFG1, ®); ++ rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS0FBK, 0); ++ rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS1FBK, 0); ++ rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS2FBK, 1); ++ rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS3FBK, 2); ++ rt2800usb_register_write(rt2x00dev, LG_FBK_CFG1, reg); ++ ++ /* ++ * We must clear the error counters. ++ * These registers are cleared on read, ++ * so we may pass a useless variable to store the value. ++ */ ++ rt2800usb_register_read(rt2x00dev, RX_STA_CNT0, ®); ++ rt2800usb_register_read(rt2x00dev, RX_STA_CNT1, ®); ++ rt2800usb_register_read(rt2x00dev, RX_STA_CNT2, ®); ++ rt2800usb_register_read(rt2x00dev, TX_STA_CNT0, ®); ++ rt2800usb_register_read(rt2x00dev, TX_STA_CNT1, ®); ++ rt2800usb_register_read(rt2x00dev, TX_STA_CNT2, ®); ++ ++ return 0; ++} ++ ++static int rt2800usb_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev) ++{ ++ unsigned int i; ++ u32 reg; ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2800usb_register_read(rt2x00dev, MAC_STATUS_CFG, ®); ++ if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY)) ++ return 0; ++ ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n"); ++ return -EACCES; ++} ++ ++static int rt2800usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) ++{ ++ unsigned int i; ++ u8 value; ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2800usb_bbp_read(rt2x00dev, 0, &value); ++ if ((value != 0xff) && (value != 0x00)) ++ return 0; ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); ++ return -EACCES; ++} ++ ++static int rt2800usb_init_bbp(struct rt2x00_dev *rt2x00dev) ++{ ++ unsigned int i; ++ u16 eeprom; ++ u8 reg_id; ++ u8 value; ++ ++ if (unlikely(rt2800usb_wait_bbp_rf_ready(rt2x00dev) || ++ rt2800usb_wait_bbp_ready(rt2x00dev))) ++ return -EACCES; ++ ++ rt2800usb_bbp_write(rt2x00dev, 65, 0x2c); ++ rt2800usb_bbp_write(rt2x00dev, 66, 0x38); ++ rt2800usb_bbp_write(rt2x00dev, 69, 0x12); ++ rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); ++ rt2800usb_bbp_write(rt2x00dev, 73, 0x10); ++ rt2800usb_bbp_write(rt2x00dev, 81, 0x37); ++ rt2800usb_bbp_write(rt2x00dev, 82, 0x62); ++ rt2800usb_bbp_write(rt2x00dev, 83, 0x6a); ++ rt2800usb_bbp_write(rt2x00dev, 84, 0x99); ++ rt2800usb_bbp_write(rt2x00dev, 86, 0x00); ++ rt2800usb_bbp_write(rt2x00dev, 91, 0x04); ++ rt2800usb_bbp_write(rt2x00dev, 92, 0x00); ++ rt2800usb_bbp_write(rt2x00dev, 105, 0x05); ++ ++ if (rt2x00_rev(&rt2x00dev->chip) == RT2870_VERSION_C) { ++ rt2800usb_bbp_write(rt2x00dev, 69, 0x16); ++ rt2800usb_bbp_write(rt2x00dev, 73, 0x12); ++ } ++ ++ if (rt2x00_rev(&rt2x00dev->chip) != RT2870_VERSION_D) ++ rt2800usb_bbp_write(rt2x00dev, 84, 0x19); ++ ++ for (i = 0; i < EEPROM_BBP_SIZE; i++) { ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); ++ ++ if (eeprom != 0xffff && eeprom != 0x0000) { ++ reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); ++ value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); ++ rt2800usb_bbp_write(rt2x00dev, reg_id, value); ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * Device state switch handlers. ++ */ ++static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, ++ enum dev_state state) ++{ ++ u32 reg; ++ ++ rt2800usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, ++ (state == STATE_RADIO_RX_ON) || ++ (state == STATE_RADIO_RX_ON_LINK)); ++ rt2800usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); ++} ++ ++static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) ++{ ++ unsigned int i; ++ u32 reg; ++ ++ for (i = 0; i < REGISTER_BUSY_COUNT; i++) { ++ rt2800usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); ++ if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && ++ !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) ++ return 0; ++ ++ msleep(1); ++ } ++ ++ ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); ++ return -EACCES; ++} ++ ++static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ u16 word; ++ ++ /* ++ * Initialize all registers. ++ */ ++ if (unlikely(rt2800usb_wait_wpdma_ready(rt2x00dev) || ++ rt2800usb_init_registers(rt2x00dev) || ++ rt2800usb_init_bbp(rt2x00dev))) ++ return -EIO; ++ ++ rt2800usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); ++ rt2800usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); ++ ++ udelay(50); ++ ++ rt2800usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); ++ rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); ++ rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); ++ rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); ++ rt2800usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); ++ ++ ++ rt2800usb_register_read(rt2x00dev, USB_DMA_CFG, ®); ++ rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); ++ /* Don't use bulk in aggregation when working with USB 1.1 */ ++ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, ++ (rt2x00dev->usb_maxpacket == 512)); ++ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); ++ /* FIXME: Calculate this value based on Aggregation defines */ ++ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, 21); ++ rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); ++ rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); ++ rt2800usb_register_write(rt2x00dev, USB_DMA_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); ++ rt2800usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); ++ ++ /* ++ * Initialize LED control ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); ++ rt2800usb_mcu_request(rt2x00dev, MCU_LED_1, 0xff, ++ word & 0xff, (word >> 8) & 0xff); ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); ++ rt2800usb_mcu_request(rt2x00dev, MCU_LED_2, 0xff, ++ word & 0xff, (word >> 8) & 0xff); ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); ++ rt2800usb_mcu_request(rt2x00dev, MCU_LED_3, 0xff, ++ word & 0xff, (word >> 8) & 0xff); ++ ++ /* ++ * Send signal to firmware during boot time. ++ */ ++ rt2800usb_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); ++ ++ return 0; ++} ++ ++static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ ++ rt2800usb_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); ++ rt2800usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); ++ ++ rt2800usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0); ++ rt2800usb_register_write(rt2x00dev, PWR_PIN_CFG, 0); ++ rt2800usb_register_write(rt2x00dev, TX_PIN_CFG, 0); ++ ++ /* Wait for DMA, ignore error */ ++ rt2800usb_wait_wpdma_ready(rt2x00dev); ++ ++ rt2x00usb_disable_radio(rt2x00dev); ++} ++ ++static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev, ++ enum dev_state state) ++{ ++ rt2800usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); ++ ++ if (state == STATE_AWAKE) ++ rt2800usb_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); ++ else ++ rt2800usb_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); ++ ++ return 0; ++} ++ ++static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, ++ enum dev_state state) ++{ ++ int retval = 0; ++ ++ 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 the radio can be enabled. ++ */ ++ rt2800usb_set_state(rt2x00dev, STATE_AWAKE); ++ msleep(1); ++ retval = rt2800usb_enable_radio(rt2x00dev); ++ break; ++ case STATE_RADIO_OFF: ++ /* ++ * After the radio has been disablee, the device should ++ * be put to sleep for powersaving. ++ */ ++ rt2800usb_disable_radio(rt2x00dev); ++ rt2800usb_set_state(rt2x00dev, STATE_SLEEP); ++ break; ++ case STATE_RADIO_RX_ON: ++ case STATE_RADIO_RX_ON_LINK: ++ case STATE_RADIO_RX_OFF: ++ case STATE_RADIO_RX_OFF_LINK: ++ rt2800usb_toggle_rx(rt2x00dev, state); ++ break; ++ case STATE_RADIO_IRQ_ON: ++ case STATE_RADIO_IRQ_OFF: ++ /* No support, but no error either */ ++ break; ++ case STATE_DEEP_SLEEP: ++ case STATE_SLEEP: ++ case STATE_STANDBY: ++ case STATE_AWAKE: ++ retval = rt2800usb_set_state(rt2x00dev, state); ++ break; ++ default: ++ retval = -ENOTSUPP; ++ break; ++ } ++ ++ if (unlikely(retval)) ++ ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", ++ state, retval); ++ ++ return retval; ++} ++ ++/* ++ * TX descriptor initialization ++ */ ++static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, ++ struct sk_buff *skb, ++ struct txentry_desc *txdesc) ++{ ++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); ++ __le32 *txd = skbdesc->desc; ++ __le32 *txwi = txd + TXD_DESC_SIZE; ++ u32 word; ++ ++ /* ++ * Initialize TX Info descriptor ++ */ ++ rt2x00_desc_read(txwi, 0, &word); ++ rt2x00_set_field32(&word, TXWI_W0_FRAG, ++ test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags) || ++ test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); ++ rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); ++ rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); ++ rt2x00_set_field32(&word, TXWI_W0_TS, ++ 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->ifs); ++ rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->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_PHYMODE, txdesc->rate_mode); ++ rt2x00_desc_write(txwi, 0, word); ++ ++ rt2x00_desc_read(txwi, 1, &word); ++ rt2x00_set_field32(&word, TXWI_W1_ACK, ++ test_bit(ENTRY_TXD_ACK, &txdesc->flags)); ++ rt2x00_set_field32(&word, TXWI_W1_ACK, ++ test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); ++ rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); ++ rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, 0xff); ++ rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, skb->len); ++ rt2x00_set_field32(&word, TXWI_W1_PACKETID, ++ skbdesc->entry->entry_idx); ++ rt2x00_desc_write(txwi, 1, word); ++ ++ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { ++ _rt2x00_desc_write(txwi, 2, skbdesc->iv); ++ _rt2x00_desc_write(txwi, 3, skbdesc->eiv); ++ } ++ ++ /* ++ * 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, skb->len); ++ rt2x00_set_field32(&word, TXD_W1_LAST_SEC1, 1); ++ rt2x00_set_field32(&word, TXD_W1_BURST, ++ test_bit(ENTRY_TXD_BURST, &txdesc->flags)); ++ rt2x00_set_field32(&word, TXD_W1_SD_LEN0, ++ rt2x00dev->hw->extra_tx_headroom); ++ rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, ++ !test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); ++ 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 + rt2x00dev->hw->extra_tx_headroom); ++ rt2x00_desc_write(txd, 2, word); ++ ++ rt2x00_desc_read(txd, 3, &word); ++ rt2x00_set_field32(&word, TXD_W3_WIV, 1); ++ rt2x00_set_field32(&word, TXD_W3_QSEL, 2); ++ rt2x00_desc_write(txd, 3, word); ++} ++ ++/* ++ * TX data initialization ++ */ ++static void rt2800usb_write_beacon(struct queue_entry *entry) ++{ ++ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; ++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); ++ unsigned int beacon_base; ++ u32 reg; ++ ++ /* ++ * Add the descriptor in front of the skb. ++ */ ++ skb_push(entry->skb, entry->queue->desc_size); ++ memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); ++ skbdesc->desc = entry->skb->data; ++ ++ /* ++ * Disable beaconing while we are reloading the beacon data, ++ * otherwise we might be sending out invalid data. ++ */ ++ rt2800usb_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); ++ rt2800usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); ++ ++ /* ++ * Write entire beacon with descriptor to register. ++ */ ++ beacon_base = HW_BEACON_OFFSET(entry->entry_idx); ++ rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, ++ USB_VENDOR_REQUEST_OUT, beacon_base, ++ entry->skb->data, entry->skb->len, ++ REGISTER_TIMEOUT32(entry->skb->len)); ++ ++ /* ++ * Clean up the beacon skb. ++ */ ++ dev_kfree_skb(entry->skb); ++ entry->skb = NULL; ++} ++ ++static int rt2800usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, ++ struct sk_buff *skb) ++{ ++ int length; ++ ++ /* ++ * The length _must_ be a multiple of 4, ++ * but it must _not_ be a multiple of the USB packet size. ++ */ ++ length = roundup(skb->len, 4); ++ length += (4 * !(length % rt2x00dev->usb_maxpacket)); ++ ++ return length; ++} ++ ++static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, ++ const enum data_queue_qid queue) ++{ ++ u32 reg; ++ ++ if (queue != QID_BEACON) { ++ rt2x00usb_kick_tx_queue(rt2x00dev, queue); ++ return; ++ } ++ ++ rt2800usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); ++ if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) { ++ 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); ++ rt2800usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); ++ } ++} ++ ++/* ++ * RX control handlers ++ */ ++static void rt2800usb_fill_rxdone(struct queue_entry *entry, ++ struct rxdone_entry_desc *rxdesc) ++{ ++ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; ++ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); ++ __le32 *rxd = (__le32 *)entry->skb->data; ++ __le32 *rxwi = (__le32 *)(entry->skb->data + skbdesc->desc_len); ++ u32 rxd0; ++ u32 rxwi0; ++ u32 rxwi1; ++ u32 rxwi2; ++ u32 rxwi3; ++ u8 mcs; ++ u8 mode; ++ ++ /* ++ * Copy descriptor to the skbdesc->desc buffer, making it safe from ++ * moving of frame data in rt2x00usb. ++ */ ++ memcpy(skbdesc->desc, rxd, skbdesc->desc_len); ++ rxd = (__le32 *)skbdesc->desc; ++ ++ /* ++ * It is now safe to read the descriptor on all architectures. ++ */ ++ rt2x00_desc_read(rxd, 0, &rxd0); ++ rt2x00_desc_read(rxwi, 0, &rxwi0); ++ rt2x00_desc_read(rxwi, 1, &rxwi1); ++ rt2x00_desc_read(rxwi, 2, &rxwi2); ++ rt2x00_desc_read(rxwi, 3, &rxwi3); ++ ++ if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR)) ++ rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; ++ ++ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { ++ /* ++ * FIXME: Set cipher on WEP64 when it has been decrypted, ++ * at the moment we cannot determine the real cipher type yet. ++ */ ++ rxdesc->cipher = ++ rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED); ++ rxdesc->cipher_status = ++ rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR); ++ } ++ ++ if (rxdesc->cipher != CIPHER_NONE) { ++ /* ++ * Hardware has stripped IV/EIV data from 802.11 frame during ++ * decryption. It has provided the data seperately but rt2x00lib ++ * should decide if it should be reinserted. ++ */ ++ 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(rxd0, RXD_W0_MY_BSS)) ++ rxdesc->dev_flags |= RXDONE_MY_BSS; ++ ++ /* ++ * Create the MCS value, when the mode is CCK, mask of 0x8 bit ++ * to remove the short preamble flag. ++ */ ++ mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE); ++ mcs = rt2x00_get_field32(rxwi1, RXWI_W1_MCS); ++ ++ if (mode == RATE_MODE_CCK) ++ mcs &= ~0x8; ++ ++ rxdesc->signal = (mode << 8) | mcs; ++ ++ rxdesc->rssi = ++ (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + ++ rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1) + ++ rt2x00_get_field32(rxwi2, RXWI_W2_RSSI2)) / 3; ++ ++ rxdesc->noise = ++ (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + ++ rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2; ++ ++ rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); ++ ++ /* ++ * Remove TXWI descriptor from start of buffer. ++ */ ++ skb_pull(entry->skb, TXWI_DESC_SIZE + skbdesc->desc_len); ++ skb_trim(entry->skb, rxdesc->size); ++} ++ ++/* ++ * Device probe functions. ++ */ ++static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) ++{ ++ u16 word; ++ u8 *mac; ++ u8 default_lna_gain; ++ ++ rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); ++ ++ /* ++ * Start validation of the data that has been read. ++ */ ++ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); ++ if (!is_valid_ether_addr(mac)) { ++ DECLARE_MAC_BUF(macbuf); ++ ++ random_ether_addr(mac); ++ EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac)); ++ } ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &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_eeprom_read(rt2x00dev, EEPROM_NIC, &word); ++ if (word != 0) { ++ /* NIC configuration must always be 0. */ ++ word = 0; ++ rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); ++ EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); ++ } ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); ++ if ((word & 0x00ff) == 0x00ff) { ++ rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); ++ 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, "Freq: 0x%04x\n", word); ++ } ++ ++ /* ++ * During the LNA validation we are going to use ++ * lna0 as correct value. Note that EEPROM_LNA ++ * is never validated. ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word); ++ default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0); ++ ++ rt2x00_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); ++ ++ rt2x00_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); ++ ++ rt2x00_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); ++ ++ rt2x00_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); ++ ++ return 0; ++} ++ ++static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 reg; ++ u16 rev; ++ u16 value; ++ u16 eeprom; ++ ++ /* ++ * Read EEPROM word for configuration. ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); ++ ++ /* ++ * Identify RF chipset. ++ */ ++ value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); ++ rt2800usb_register_read(rt2x00dev, MAC_CSR0, ®); ++ rev = rt2x00_get_field32(reg, MAC_CSR0_ASIC_REV); ++ rt2x00_set_chip(rt2x00dev, RT2870, value, rev); ++ ++ /* ++ * The check for rt2860 is not a typo, some rt2870 hardware ++ * identifies itself as rt2860 in the CSR register. ++ */ ++ if ((rt2x00_get_field32(reg, MAC_CSR0_ASIC_VER) != 0x2860) && ++ (rt2x00_get_field32(reg, MAC_CSR0_ASIC_VER) != 0x2870)) { ++ ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); ++ return -ENODEV; ++ } ++ ++ if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && ++ !rt2x00_rf(&rt2x00dev->chip, RF2850) && ++ !rt2x00_rf(&rt2x00dev->chip, RF2720) && ++ !rt2x00_rf(&rt2x00dev->chip, RF2750)) { ++ ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); ++ return -ENODEV; ++ } ++ ++ /* ++ * Read frequency offset and RF programming sequence. ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); ++ rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); ++ ++ /* ++ * Read external LNA informations. ++ */ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); ++ ++ if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_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); ++ ++ /* ++ * Store led settings, for correct led behaviour. ++ */ ++#ifdef CONFIG_RT2X00_LIB_LEDS ++ rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); ++ rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); ++ rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); ++ ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, ++ &rt2x00dev->led_mcu_reg); ++#endif /* CONFIG_RT2X00_LIB_LEDS */ ++ ++ return 0; ++} ++ ++/* ++ * RF value list for rt2870 ++ * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750) ++ */ ++static const struct rf_channel rf_vals[] = { ++ { 1, 0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b }, ++ { 2, 0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f }, ++ { 3, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b }, ++ { 4, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f }, ++ { 5, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b }, ++ { 6, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f }, ++ { 7, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b }, ++ { 8, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f }, ++ { 9, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b }, ++ { 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f }, ++ { 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b }, ++ { 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f }, ++ { 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b }, ++ { 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 }, ++ ++ /* 802.11 UNI / HyperLan 2 */ ++ { 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 }, ++ { 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 }, ++ { 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 }, ++ { 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 }, ++ { 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b }, ++ { 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b }, ++ { 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 }, ++ { 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 }, ++ { 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b }, ++ { 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 }, ++ { 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 }, ++ { 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 }, ++ ++ /* 802.11 HyperLan 2 */ ++ { 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 }, ++ { 102, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed793 }, ++ { 104, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed1a3 }, ++ { 108, 0x18402ecc, 0x184c0a32, 0x18178a55, 0x180ed193 }, ++ { 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 }, ++ { 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b }, ++ { 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 }, ++ { 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 }, ++ { 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 }, ++ { 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 }, ++ { 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b }, ++ { 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 }, ++ { 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b }, ++ { 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 }, ++ { 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b }, ++ { 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 }, ++ ++ /* 802.11 UNII */ ++ { 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 }, ++ { 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 }, ++ { 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f }, ++ { 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f }, ++ { 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 }, ++ { 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 }, ++ { 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 }, ++ ++ /* 802.11 Japan */ ++ { 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b }, ++ { 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 }, ++ { 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b }, ++ { 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 }, ++ { 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 }, ++ { 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b }, ++ { 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 }, ++}; ++ ++static int rt2800usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) ++{ ++ struct hw_mode_spec *spec = &rt2x00dev->spec; ++ struct channel_info *info; ++ char *tx_power1; ++ char *tx_power2; ++ unsigned int i; ++ ++ /* ++ * Initialize all hw fields. ++ */ ++ rt2x00dev->hw->flags = ++ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | ++ IEEE80211_HW_SIGNAL_DBM; ++ rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE + TXINFO_DESC_SIZE; ++ ++ SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); ++ SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, ++ rt2x00_eeprom_addr(rt2x00dev, ++ EEPROM_MAC_ADDR_0)); ++ ++ /* ++ * Initialize hw_mode information. ++ */ ++ spec->supported_bands = SUPPORT_BAND_2GHZ; ++ spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; ++ ++ if (rt2x00_rf(&rt2x00dev->chip, RF2820) || ++ rt2x00_rf(&rt2x00dev->chip, RF2720)) { ++ spec->num_channels = 14; ++ spec->channels = rf_vals; ++ } else if (rt2x00_rf(&rt2x00dev->chip, RF2850) || ++ rt2x00_rf(&rt2x00dev->chip, RF2750)) { ++ spec->supported_bands |= SUPPORT_BAND_5GHZ; ++ spec->num_channels = ARRAY_SIZE(rf_vals); ++ spec->channels = rf_vals; ++ } ++ ++ /* ++ * Create channel information array ++ */ ++ info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ spec->channels_info = info; ++ ++ tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); ++ tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); ++ ++ for (i = 0; i < 14; i++) { ++ info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]); ++ info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]); ++ } ++ ++ if (spec->num_channels > 14) { ++ tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); ++ tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); ++ ++ for (i = 14; i < spec->num_channels; i++) { ++ info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]); ++ info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]); ++ } ++ } ++ ++ return 0; ++} ++ ++static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) ++{ ++ int retval; ++ ++ /* ++ * Allocate eeprom data. ++ */ ++ retval = rt2800usb_validate_eeprom(rt2x00dev); ++ if (retval) ++ return retval; ++ ++ retval = rt2800usb_init_eeprom(rt2x00dev); ++ if (retval) ++ return retval; ++ ++ /* ++ * Initialize hw specifications. ++ */ ++ retval = rt2800usb_probe_hw_mode(rt2x00dev); ++ if (retval) ++ return retval; ++ ++ /* ++ * This device requires firmware. ++ */ ++ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); ++ __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); ++ if (!modparam_nohwcrypt) ++ __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); ++ ++ /* ++ * Set the rssi offset. ++ */ ++ rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; ++ ++ return 0; ++} ++ ++/* ++ * IEEE80211 stack callback functions. ++ */ ++static int rt2800usb_set_rts_threshold(struct ieee80211_hw *hw, u32 value) ++{ ++ struct rt2x00_dev *rt2x00dev = hw->priv; ++ u32 reg; ++ ++ rt2800usb_register_read(rt2x00dev, TX_RTS_CFG, ®); ++ rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, value); ++ rt2800usb_register_write(rt2x00dev, TX_RTS_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, CCK_PROT_CFG, ®); ++ rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, 1); ++ rt2800usb_register_write(rt2x00dev, CCK_PROT_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); ++ rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, 1); ++ rt2800usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, MM20_PROT_CFG, ®); ++ rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, 1); ++ rt2800usb_register_write(rt2x00dev, MM20_PROT_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, MM40_PROT_CFG, ®); ++ rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, 1); ++ rt2800usb_register_write(rt2x00dev, MM40_PROT_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, GF20_PROT_CFG, ®); ++ rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, 1); ++ rt2800usb_register_write(rt2x00dev, GF20_PROT_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, GF40_PROT_CFG, ®); ++ rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, 1); ++ rt2800usb_register_write(rt2x00dev, GF40_PROT_CFG, reg); ++ ++ return 0; ++} ++ ++static int rt2800usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, ++ const struct ieee80211_tx_queue_params *params) ++{ ++ struct rt2x00_dev *rt2x00dev = hw->priv; ++ struct data_queue *queue; ++ struct rt2x00_field32 field; ++ int retval; ++ u32 reg; ++ u32 offset; ++ ++ /* ++ * First pass the configuration through rt2x00lib, that will ++ * update the queue settings and validate the input. After that ++ * we are free to update the registers based on the value ++ * in the queue parameter. ++ */ ++ retval = rt2x00mac_conf_tx(hw, queue_idx, params); ++ if (retval) ++ return retval; ++ ++ queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); ++ ++ /* Update WMM TXOP register */ ++ if (queue_idx < 2) { ++ field.bit_offset = queue_idx * 16; ++ field.bit_mask = 0xffff << field.bit_offset; ++ ++ rt2800usb_register_read(rt2x00dev, WMM_TXOP0_CFG, ®); ++ rt2x00_set_field32(®, field, queue->txop); ++ rt2800usb_register_write(rt2x00dev, WMM_TXOP0_CFG, reg); ++ } else if (queue_idx < 4) { ++ field.bit_offset = (queue_idx - 2) * 16; ++ field.bit_mask = 0xffff << field.bit_offset; ++ ++ rt2800usb_register_read(rt2x00dev, WMM_TXOP1_CFG, ®); ++ rt2x00_set_field32(®, field, queue->txop); ++ rt2800usb_register_write(rt2x00dev, WMM_TXOP1_CFG, reg); ++ } ++ ++ /* Update WMM registers */ ++ field.bit_offset = queue_idx * 4; ++ field.bit_mask = 0xf << field.bit_offset; ++ ++ rt2800usb_register_read(rt2x00dev, WMM_AIFSN_CFG, ®); ++ rt2x00_set_field32(®, field, queue->aifs); ++ rt2800usb_register_write(rt2x00dev, WMM_AIFSN_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, WMM_CWMIN_CFG, ®); ++ rt2x00_set_field32(®, field, queue->cw_min); ++ rt2800usb_register_write(rt2x00dev, WMM_CWMIN_CFG, reg); ++ ++ rt2800usb_register_read(rt2x00dev, WMM_CWMAX_CFG, ®); ++ rt2x00_set_field32(®, field, queue->cw_max); ++ rt2800usb_register_write(rt2x00dev, WMM_CWMAX_CFG, reg); ++ ++ /* Update EDCA registers */ ++ if (queue_idx < 4) { ++ offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); ++ ++ rt2800usb_register_read(rt2x00dev, offset, ®); ++ rt2x00_set_field32(®, EDCA_AC0_CFG_AIFSN, queue->aifs); ++ rt2x00_set_field32(®, EDCA_AC0_CFG_CWMIN, queue->cw_min); ++ rt2x00_set_field32(®, EDCA_AC0_CFG_CWMAX, queue->cw_max); ++ rt2800usb_register_write(rt2x00dev, offset, reg); ++ } ++ ++ return 0; ++} ++ ++#if 0 ++/* ++ * Mac80211 demands get_tsf must be atomic. ++ * This is not possible for rt2800usb since all register access ++ * functions require sleeping. Untill mac80211 no longer needs ++ * get_tsf to be atomic, this function should be disabled. ++ */ ++static u64 rt2800usb_get_tsf(struct ieee80211_hw *hw) ++{ ++ struct rt2x00_dev *rt2x00dev = hw->priv; ++ u64 tsf; ++ u32 reg; ++ ++ rt2800usb_register_read(rt2x00dev, TSF_TIMER_DW1, ®); ++ tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32; ++ rt2800usb_register_read(rt2x00dev, TSF_TIMER_DW0, ®); ++ tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD); ++ ++ return tsf; ++} ++#else ++#define rt2800usb_get_tsf NULL ++#endif ++ ++static const struct ieee80211_ops rt2800usb_mac80211_ops = { ++ .tx = rt2x00mac_tx, ++ .start = rt2x00mac_start, ++ .stop = rt2x00mac_stop, ++ .add_interface = rt2x00mac_add_interface, ++ .remove_interface = rt2x00mac_remove_interface, ++ .config = rt2x00mac_config, ++ .config_interface = rt2x00mac_config_interface, ++ .configure_filter = rt2x00mac_configure_filter, ++ .set_key = rt2x00mac_set_key, ++ .get_stats = rt2x00mac_get_stats, ++ .set_rts_threshold = rt2800usb_set_rts_threshold, ++ .bss_info_changed = rt2x00mac_bss_info_changed, ++ .conf_tx = rt2800usb_conf_tx, ++ .get_tx_stats = rt2x00mac_get_tx_stats, ++ .get_tsf = rt2800usb_get_tsf, ++}; ++ ++static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { ++ .probe_hw = rt2800usb_probe_hw, ++ .get_firmware_name = rt2800usb_get_firmware_name, ++ .get_firmware_crc = rt2800usb_get_firmware_crc, ++ .load_firmware = rt2800usb_load_firmware, ++ .initialize = rt2x00usb_initialize, ++ .uninitialize = rt2x00usb_uninitialize, ++ .init_rxentry = rt2x00usb_init_rxentry, ++ .init_txentry = rt2x00usb_init_txentry, ++ .set_device_state = rt2800usb_set_device_state, ++ .link_stats = rt2800usb_link_stats, ++ .reset_tuner = rt2800usb_reset_tuner, ++ .link_tuner = rt2800usb_link_tuner, ++ .write_tx_desc = rt2800usb_write_tx_desc, ++ .write_tx_data = rt2x00usb_write_tx_data, ++ .write_beacon = rt2800usb_write_beacon, ++ .get_tx_data_len = rt2800usb_get_tx_data_len, ++ .kick_tx_queue = rt2800usb_kick_tx_queue, ++ .fill_rxdone = rt2800usb_fill_rxdone, ++ .config_shared_key = rt2800usb_config_shared_key, ++ .config_pairwise_key = rt2800usb_config_pairwise_key, ++ .config_filter = rt2800usb_config_filter, ++ .config_intf = rt2800usb_config_intf, ++ .config_erp = rt2800usb_config_erp, ++ .config_ant = rt2800usb_config_ant, ++ .config = rt2800usb_config, ++}; ++ ++static const struct data_queue_desc rt2800usb_queue_rx = { ++ .entry_num = RX_ENTRIES, ++ .data_size = DATA_FRAME_SIZE, ++ .desc_size = RXD_DESC_SIZE, ++ .priv_size = sizeof(struct queue_entry_priv_usb), ++}; ++ ++static const struct data_queue_desc rt2800usb_queue_tx = { ++ .entry_num = TX_ENTRIES, ++ .data_size = DATA_FRAME_SIZE, ++ .desc_size = TXD_DESC_SIZE, ++ .priv_size = sizeof(struct queue_entry_priv_usb), ++}; ++ ++static const struct data_queue_desc rt2800usb_queue_bcn = { ++ .entry_num = 8 * BEACON_ENTRIES, ++ .data_size = MGMT_FRAME_SIZE, ++ .desc_size = TXWI_DESC_SIZE, ++ .priv_size = sizeof(struct queue_entry_priv_usb), ++}; ++ ++static const struct rt2x00_ops rt2800usb_ops = { ++ .name = KBUILD_MODNAME, ++ .max_sta_intf = 1, ++ .max_ap_intf = 8, ++ .eeprom_size = EEPROM_SIZE, ++ .rf_size = RF_SIZE, ++ .tx_queues = NUM_TX_QUEUES, ++ .rx = &rt2800usb_queue_rx, ++ .tx = &rt2800usb_queue_tx, ++ .bcn = &rt2800usb_queue_bcn, ++ .lib = &rt2800usb_rt2x00_ops, ++ .hw = &rt2800usb_mac80211_ops, ++#ifdef CONFIG_RT2X00_LIB_DEBUGFS ++ .debugfs = &rt2800usb_rt2x00debug, ++#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ ++}; ++ ++/* ++ * rt2800usb module information. ++ */ ++static struct usb_device_id rt2800usb_device_table[] = { ++ /* Amit */ ++ { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* 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) }, ++ /* AzureWave */ ++ { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* Belkin */ ++ { USB_DEVICE(0x050d, 0x8053), 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, 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) }, ++ /* 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) }, ++ /* D-Link */ ++ { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* EnGenius */ ++ { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* Gigabyte */ ++ { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* Hawking */ ++ { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* Linksys */ ++ { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* Philips */ ++ { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* Planex */ ++ { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* Ralink */ ++ { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* Siemens */ ++ { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* 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) }, ++ /* SMC */ ++ { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* Sparklan */ ++ { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* U-Media*/ ++ { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* ZCOM */ ++ { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ /* Zyxel */ ++ { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, ++ { 0, } ++}; ++ ++MODULE_AUTHOR(DRV_PROJECT); ++MODULE_VERSION(DRV_VERSION); ++MODULE_DESCRIPTION("Ralink RT2800 USB Wireless LAN driver."); ++MODULE_SUPPORTED_DEVICE("Ralink RT2870 USB chipset based cards"); ++MODULE_DEVICE_TABLE(usb, rt2800usb_device_table); ++MODULE_FIRMWARE(FIRMWARE_RT2870); ++MODULE_LICENSE("GPL"); ++ ++static struct usb_driver rt2800usb_driver = { ++ .name = KBUILD_MODNAME, ++ .id_table = rt2800usb_device_table, ++ .probe = rt2x00usb_probe, ++ .disconnect = rt2x00usb_disconnect, ++ .suspend = rt2x00usb_suspend, ++ .resume = rt2x00usb_resume, ++}; ++ ++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); +--- /dev/null ++++ b/drivers/net/wireless/rt2x00/rt2800usb.h +@@ -0,0 +1,1884 @@ ++/* ++ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project ++ <http://rt2x00.serialmonkey.com> ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the ++ Free Software Foundation, Inc., ++ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++/* ++ Module: rt2800usb ++ Abstract: Data structures and registers for the rt2800usb module. ++ Supported chipsets: RT2800U. ++ */ ++ ++#ifndef RT2800USB_H ++#define RT2800USB_H ++ ++/* ++ * RF chip defines. ++ * ++ * RF2820 2.4G 2T3R ++ * RF2850 2.4G/5G 2T3R ++ * RF2720 2.4G 1T2R ++ * RF2750 2.4G/5G 1T2R ++ */ ++#define RF2820 0x0001 ++#define RF2850 0x0002 ++#define RF2720 0x0003 ++#define RF2750 0x0004 ++ ++/* ++ * RT2870 version ++ */ ++#define RT2870_VERSION_C 0x0100 ++#define RT2870_VERSION_D 0x0101 ++#define RT2870_VERSION_E 0x0200 ++ ++/* ++ * Signal information. ++ * Defaul offset is required for RSSI <-> dBm conversion. ++ */ ++#define MAX_SIGNAL 0 /* FIXME */ ++#define MAX_RX_SSI 0 /* FIXME */ ++#define DEFAULT_RSSI_OFFSET 120 /* FIXME */ ++ ++/* ++ * Register layout information. ++ */ ++#define CSR_REG_BASE 0x1000 ++#define CSR_REG_SIZE 0x0800 ++#define EEPROM_BASE 0x0000 ++#define EEPROM_SIZE 0x0110 ++#define BBP_BASE 0x0000 ++#define BBP_SIZE 0x0080 ++#define RF_BASE 0x0000 ++#define RF_SIZE 0x0014 ++ ++/* ++ * Number of TX queues. ++ */ ++#define NUM_TX_QUEUES 4 ++ ++/* ++ * USB registers. ++ */ ++ ++/* ++ * HOST-MCU shared memory ++ */ ++#define HOST_CMD_CSR 0x0404 ++#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff) ++ ++/* ++ * INT_SOURCE_CSR: Interrupt source register. ++ * Write one to clear corresponding bit. ++ * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c ++ */ ++#define INT_SOURCE_CSR 0x0200 ++#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001) ++#define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002) ++#define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004) ++#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008) ++#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010) ++#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020) ++#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040) ++#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080) ++#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100) ++#define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200) ++#define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400) ++#define INT_SOURCE_CSR_TBTT FIELD32(0x00000800) ++#define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000) ++#define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000) ++#define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000) ++#define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000) ++#define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000) ++#define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000) ++ ++/* ++ * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF. ++ */ ++#define INT_MASK_CSR 0x0204 ++#define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001) ++#define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002) ++#define INT_MASK_CSR_RX_DONE FIELD32(0x00000004) ++#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008) ++#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010) ++#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020) ++#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040) ++#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080) ++#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100) ++#define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200) ++#define INT_MASK_CSR_RX_COHERENT FIELD32(0x40000000) ++#define INT_MASK_CSR_TX_COHERENT FIELD32(0x80000000) ++ ++/* ++ * WPDMA_GLO_CFG ++ */ ++#define WPDMA_GLO_CFG 0x0208 ++#define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001) ++#define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002) ++#define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004) ++#define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008) ++#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030) ++#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040) ++#define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080) ++#define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00) ++#define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000) ++ ++/* ++ * WPDMA_RST_IDX ++ */ ++#define WPDMA_RST_IDX 0x020c ++#define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001) ++#define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002) ++#define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004) ++#define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008) ++#define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010) ++#define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020) ++#define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000) ++ ++/* ++ * DELAY_INT_CFG ++ */ ++#define DELAY_INT_CFG 0x0210 ++#define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff) ++#define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00) ++#define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000) ++#define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000) ++#define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000) ++#define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000) ++ ++/* ++ * WMM_AIFSN_CFG: Aifsn for each EDCA AC ++ * AIFSN0: AC_BE ++ * AIFSN1: AC_BK ++ * AIFSN1: AC_VI ++ * AIFSN1: AC_VO ++ */ ++#define WMM_AIFSN_CFG 0x0214 ++#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) ++#define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0) ++#define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00) ++#define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000) ++ ++/* ++ * WMM_CWMIN_CSR: CWmin for each EDCA AC ++ * CWMIN0: AC_BE ++ * CWMIN1: AC_BK ++ * CWMIN1: AC_VI ++ * CWMIN1: AC_VO ++ */ ++#define WMM_CWMIN_CFG 0x0218 ++#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) ++#define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0) ++#define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00) ++#define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000) ++ ++/* ++ * WMM_CWMAX_CSR: CWmax for each EDCA AC ++ * CWMAX0: AC_BE ++ * CWMAX1: AC_BK ++ * CWMAX1: AC_VI ++ * CWMAX1: AC_VO ++ */ ++#define WMM_CWMAX_CFG 0x021c ++#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) ++#define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0) ++#define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00) ++#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 ++ */ ++#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 ++ */ ++#define WMM_TXOP1_CFG 0x0224 ++#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff) ++#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) ++ ++/* ++ * RINGREG_DIFF ++ */ ++#define RINGREG_DIFF 0x0010 ++ ++/* ++ * 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) ++ ++/* ++ * MCU_CMD_CFG ++ */ ++#define MCU_CMD_CFG 0x022c ++ ++/* ++ * AC_BK register offsets ++ */ ++#define TX_BASE_PTR0 0x0230 ++#define TX_MAX_CNT0 0x0234 ++#define TX_CTX_IDX0 0x0238 ++#define TX_DTX_IDX0 0x023c ++ ++/* ++ * AC_BE register offsets ++ */ ++#define TX_BASE_PTR1 0x0240 ++#define TX_MAX_CNT1 0x0244 ++#define TX_CTX_IDX1 0x0248 ++#define TX_DTX_IDX1 0x024c ++ ++/* ++ * AC_VI register offsets ++ */ ++#define TX_BASE_PTR2 0x0250 ++#define TX_MAX_CNT2 0x0254 ++#define TX_CTX_IDX2 0x0258 ++#define TX_DTX_IDX2 0x025c ++ ++/* ++ * AC_VO register offsets ++ */ ++#define TX_BASE_PTR3 0x0260 ++#define TX_MAX_CNT3 0x0264 ++#define TX_CTX_IDX3 0x0268 ++#define TX_DTX_IDX3 0x026c ++ ++/* ++ * HCCA register offsets ++ */ ++#define TX_BASE_PTR4 0x0270 ++#define TX_MAX_CNT4 0x0274 ++#define TX_CTX_IDX4 0x0278 ++#define TX_DTX_IDX4 0x027c ++ ++/* ++ * MGMT register offsets ++ */ ++#define TX_BASE_PTR5 0x0280 ++#define TX_MAX_CNT5 0x0284 ++#define TX_CTX_IDX5 0x0288 ++#define TX_DTX_IDX5 0x028c ++ ++/* ++ * RX register offsets ++ */ ++#define RX_BASE_PTR 0x0290 ++#define RX_MAX_CNT 0x0294 ++#define RX_CRX_IDX 0x0298 ++#define RX_DRX_IDX 0x029c ++ ++/* ++ * USB_DMA_CFG ++ * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns. ++ * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes. ++ * PHY_CLEAR: phy watch dog enable. ++ * TX_CLEAR: Clear USB DMA TX path. ++ * TXOP_HALT: Halt TXOP count down when TX buffer is full. ++ * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation. ++ * RX_BULK_EN: Enable USB DMA Rx. ++ * TX_BULK_EN: Enable USB DMA Tx. ++ * EP_OUT_VALID: OUT endpoint data valid. ++ * RX_BUSY: USB DMA RX FSM busy. ++ * TX_BUSY: USB DMA TX FSM busy. ++ */ ++#define USB_DMA_CFG 0x02a0 ++#define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT FIELD32(0x000000ff) ++#define USB_DMA_CFG_RX_BULK_AGG_LIMIT FIELD32(0x0000ff00) ++#define USB_DMA_CFG_PHY_CLEAR FIELD32(0x00010000) ++#define USB_DMA_CFG_TX_CLEAR FIELD32(0x00080000) ++#define USB_DMA_CFG_TXOP_HALT FIELD32(0x00100000) ++#define USB_DMA_CFG_RX_BULK_AGG_EN FIELD32(0x00200000) ++#define USB_DMA_CFG_RX_BULK_EN FIELD32(0x00400000) ++#define USB_DMA_CFG_TX_BULK_EN FIELD32(0x00800000) ++#define USB_DMA_CFG_EP_OUT_VALID FIELD32(0x3f000000) ++#define USB_DMA_CFG_RX_BUSY FIELD32(0x40000000) ++#define USB_DMA_CFG_TX_BUSY FIELD32(0x80000000) ++ ++/* ++ * USB_CYC_CFG ++ */ ++#define USB_CYC_CFG 0x02a4 ++#define USB_CYC_CFG_CLOCK_CYCLE FIELD32(0x000000ff) ++ ++/* ++ * PBF_SYS_CTRL ++ * HOST_RAM_WRITE: enable Host program ram write selection ++ */ ++#define PBF_SYS_CTRL 0x0400 ++#define PBF_SYS_CTRL_READY FIELD32(0x00000080) ++#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) ++ ++/* ++ * PBF registers ++ * Most are for debug. Driver doesn't touch PBF register. ++ */ ++#define PBF_CFG 0x0408 ++#define PBF_MAX_PCNT 0x040c ++#define PBF_CTRL 0x0410 ++#define PBF_INT_STA 0x0414 ++#define PBF_INT_ENA 0x0418 ++ ++/* ++ * BCN_OFFSET0: ++ */ ++#define BCN_OFFSET0 0x042c ++#define BCN_OFFSET0_BCN0 FIELD32(0x000000ff) ++#define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00) ++#define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000) ++#define BCN_OFFSET0_BCN3 FIELD32(0xff000000) ++ ++/* ++ * BCN_OFFSET1: ++ */ ++#define BCN_OFFSET1 0x0430 ++#define BCN_OFFSET1_BCN4 FIELD32(0x000000ff) ++#define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00) ++#define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000) ++#define BCN_OFFSET1_BCN7 FIELD32(0xff000000) ++ ++/* ++ * PBF registers ++ * Most are for debug. Driver doesn't touch PBF register. ++ */ ++#define TXRXQ_PCNT 0x0438 ++#define PBF_DBG 0x043c ++ ++/* ++ * MAC Control/Status Registers(CSR). ++ * Some values are set in TU, whereas 1 TU == 1024 us. ++ */ ++ ++/* ++ * MAC_CSR0: ASIC revision number. ++ * ASIC_REV: 0 ++ * ASIC_VER: 2870 ++ */ ++#define MAC_CSR0 0x1000 ++#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) ++#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) ++ ++/* ++ * MAC_SYS_CTRL: ++ */ ++#define MAC_SYS_CTRL 0x1004 ++#define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001) ++#define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002) ++#define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004) ++#define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008) ++#define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010) ++#define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020) ++#define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040) ++#define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080) ++ ++/* ++ * MAC_ADDR_DW0: STA MAC register 0 ++ */ ++#define MAC_ADDR_DW0 0x1008 ++#define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff) ++#define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00) ++#define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000) ++#define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000) ++ ++/* ++ * MAC_ADDR_DW1: STA MAC register 1 ++ * UNICAST_TO_ME_MASK: ++ * Used to mask off bits from byte 5 of the MAC address ++ * to determine the UNICAST_TO_ME bit for RX frames. ++ * The full mask is complemented by BSS_ID_MASK: ++ * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK ++ */ ++#define MAC_ADDR_DW1 0x100c ++#define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff) ++#define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00) ++#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000) ++ ++/* ++ * MAC_BSSID_DW0: BSSID register 0 ++ */ ++#define MAC_BSSID_DW0 0x1010 ++#define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff) ++#define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00) ++#define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000) ++#define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000) ++ ++/* ++ * MAC_BSSID_DW1: BSSID register 1 ++ * BSS_ID_MASK: ++ * 0: 1-BSSID mode (BSS index = 0) ++ * 1: 2-BSSID mode (BSS index: Byte5, bit 0) ++ * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1) ++ * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2) ++ * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the ++ * BSSID. This will make sure that those bits will be ignored ++ * when determining the MY_BSS of RX frames. ++ */ ++#define MAC_BSSID_DW1 0x1014 ++#define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff) ++#define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00) ++#define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000) ++#define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000) ++ ++/* ++ * MAX_LEN_CFG: Maximum frame length register. ++ * MAX_MPDU: rt2860b max 16k bytes ++ * MAX_PSDU: Maximum PSDU length ++ * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 ++ */ ++#define MAX_LEN_CFG 0x1018 ++#define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff) ++#define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000) ++#define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000) ++#define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000) ++ ++/* ++ * BBP_CSR_CFG: BBP serial control register ++ * VALUE: Register value to program into BBP ++ * REG_NUM: Selected BBP register ++ * 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 ++ */ ++#define BBP_CSR_CFG 0x101c ++#define BBP_CSR_CFG_VALUE FIELD32(0x000000ff) ++#define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00) ++#define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000) ++#define BBP_CSR_CFG_BUSY FIELD32(0x00020000) ++#define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000) ++#define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000) ++ ++/* ++ * RF_CSR_CFG0: RF control register ++ * REGID_AND_VALUE: Register value to program into RF ++ * BITWIDTH: Selected RF register ++ * STANDBYMODE: 0 high when standby, 1 low when standby ++ * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate ++ * BUSY: ASIC is busy executing RF commands ++ */ ++#define RF_CSR_CFG0 0x1020 ++#define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff) ++#define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000) ++#define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff) ++#define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000) ++#define RF_CSR_CFG0_SEL FIELD32(0x40000000) ++#define RF_CSR_CFG0_BUSY FIELD32(0x80000000) ++ ++/* ++ * RF_CSR_CFG1: RF control register ++ * REGID_AND_VALUE: Register value to program into RF ++ * RFGAP: Gap between BB_CONTROL_RF and RF_LE ++ * 0: 3 system clock cycle (37.5usec) ++ * 1: 5 system clock cycle (62.5usec) ++ */ ++#define RF_CSR_CFG1 0x1024 ++#define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff) ++#define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000) ++ ++/* ++ * RF_CSR_CFG2: RF control register ++ * VALUE: Register value to program into RF ++ * RFGAP: Gap between BB_CONTROL_RF and RF_LE ++ * 0: 3 system clock cycle (37.5usec) ++ * 1: 5 system clock cycle (62.5usec) ++ */ ++#define RF_CSR_CFG2 0x1028 ++#define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff) ++ ++/* ++ * LED_CFG: LED control ++ * color LED's: ++ * 0: off ++ * 1: blinking upon TX2 ++ * 2: periodic slow blinking ++ * 3: always on ++ * LED polarity: ++ * 0: active low ++ * 1: active high ++ */ ++#define LED_CFG 0x102c ++#define LED_CFG_ON_PERIOD FIELD32(0x000000ff) ++#define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00) ++#define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000) ++#define LED_CFG_R_LED_MODE FIELD32(0x03000000) ++#define LED_CFG_G_LED_MODE FIELD32(0x0c000000) ++#define LED_CFG_Y_LED_MODE FIELD32(0x30000000) ++#define LED_CFG_LED_POLAR FIELD32(0x40000000) ++ ++/* ++ * XIFS_TIME_CFG: MAC timing ++ * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX ++ * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX ++ * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX ++ * when MAC doesn't reference BBP signal BBRXEND ++ * EIFS: unit 1us ++ * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer ++ * ++ */ ++#define XIFS_TIME_CFG 0x1100 ++#define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff) ++#define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00) ++#define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000) ++#define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000) ++#define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000) ++ ++/* ++ * BKOFF_SLOT_CFG: ++ */ ++#define BKOFF_SLOT_CFG 0x1104 ++#define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff) ++#define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00) ++ ++/* ++ * NAV_TIME_CFG: ++ */ ++#define NAV_TIME_CFG 0x1108 ++#define NAV_TIME_CFG_SIFS FIELD32(0x000000ff) ++#define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00) ++#define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000) ++#define NAV_TIME_ZERO_SIFS FIELD32(0x02000000) ++ ++/* ++ * CH_TIME_CFG: count as channel busy ++ */ ++#define CH_TIME_CFG 0x110c ++ ++/* ++ * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us ++ */ ++#define PBF_LIFE_TIMER 0x1110 ++ ++/* ++ * BCN_TIME_CFG: ++ * BEACON_INTERVAL: in unit of 1/16 TU ++ * TSF_TICKING: Enable TSF auto counting ++ * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode ++ * BEACON_GEN: Enable beacon generator ++ */ ++#define BCN_TIME_CFG 0x1114 ++#define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff) ++#define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000) ++#define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000) ++#define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000) ++#define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000) ++#define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000) ++ ++/* ++ * TBTT_SYNC_CFG: ++ */ ++#define TBTT_SYNC_CFG 0x1118 ++ ++/* ++ * TSF_TIMER_DW0: Local lsb TSF timer, read-only ++ */ ++#define TSF_TIMER_DW0 0x111c ++#define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff) ++ ++/* ++ * TSF_TIMER_DW1: Local msb TSF timer, read-only ++ */ ++#define TSF_TIMER_DW1 0x1120 ++#define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff) ++ ++/* ++ * TBTT_TIMER: TImer remains till next TBTT, read-only ++ */ ++#define TBTT_TIMER 0x1124 ++ ++/* ++ * INT_TIMER_CFG: ++ */ ++#define INT_TIMER_CFG 0x1128 ++ ++/* ++ * INT_TIMER_EN: GP-timer and pre-tbtt Int enable ++ */ ++#define INT_TIMER_EN 0x112c ++ ++/* ++ * CH_IDLE_STA: channel idle time ++ */ ++#define CH_IDLE_STA 0x1130 ++ ++/* ++ * CH_BUSY_STA: channel busy time ++ */ ++#define CH_BUSY_STA 0x1134 ++ ++/* ++ * MAC_STATUS_CFG: ++ * BBP_RF_BUSY: When set to 0, BBP and RF are stable. ++ * if 1 or higher one of the 2 registers is busy. ++ */ ++#define MAC_STATUS_CFG 0x1200 ++#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003) ++ ++/* ++ * PWR_PIN_CFG: ++ */ ++#define PWR_PIN_CFG 0x1204 ++ ++/* ++ * AUTOWAKEUP_CFG: Manual power control / status register ++ * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set ++ * AUTOWAKE: 0:sleep, 1:awake ++ */ ++#define AUTOWAKEUP_CFG 0x1208 ++#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff) ++#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00) ++#define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000) ++ ++/* ++ * EDCA_AC0_CFG: ++ */ ++#define EDCA_AC0_CFG 0x1300 ++#define EDCA_AC0_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00) ++#define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000) ++#define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000) ++ ++/* ++ * EDCA_AC1_CFG: ++ */ ++#define EDCA_AC1_CFG 0x1304 ++#define EDCA_AC1_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00) ++#define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000) ++#define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000) ++ ++/* ++ * EDCA_AC2_CFG: ++ */ ++#define EDCA_AC2_CFG 0x1308 ++#define EDCA_AC2_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00) ++#define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000) ++#define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000) ++ ++/* ++ * EDCA_AC3_CFG: ++ */ ++#define EDCA_AC3_CFG 0x130c ++#define EDCA_AC3_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00) ++#define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000) ++#define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000) ++ ++/* ++ * EDCA_TID_AC_MAP: ++ */ ++#define EDCA_TID_AC_MAP 0x1310 ++ ++/* ++ * TX_PWR_CFG_0: ++ */ ++#define TX_PWR_CFG_0 0x1314 ++#define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f) ++#define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0) ++#define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00) ++#define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000) ++#define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000) ++#define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000) ++#define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000) ++#define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000) ++ ++/* ++ * TX_PWR_CFG_1: ++ */ ++#define TX_PWR_CFG_1 0x1318 ++#define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f) ++#define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0) ++#define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00) ++#define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000) ++#define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000) ++#define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000) ++#define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000) ++#define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000) ++ ++/* ++ * TX_PWR_CFG_2: ++ */ ++#define TX_PWR_CFG_2 0x131c ++#define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f) ++#define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0) ++#define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00) ++#define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000) ++#define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000) ++#define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000) ++#define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000) ++#define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000) ++ ++/* ++ * TX_PWR_CFG_3: ++ */ ++#define TX_PWR_CFG_3 0x1320 ++#define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f) ++#define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0) ++#define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00) ++#define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000) ++#define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000) ++#define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000) ++#define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000) ++#define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000) ++ ++/* ++ * TX_PWR_CFG_4: ++ */ ++#define TX_PWR_CFG_4 0x1324 ++#define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f) ++#define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0) ++#define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00) ++#define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000) ++ ++/* ++ * TX_PIN_CFG: ++ */ ++#define TX_PIN_CFG 0x1328 ++#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) ++#define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008) ++#define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010) ++#define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020) ++#define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040) ++#define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080) ++#define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100) ++#define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200) ++#define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400) ++#define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800) ++#define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000) ++#define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000) ++#define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000) ++#define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000) ++#define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000) ++#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000) ++#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000) ++#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000) ++ ++/* ++ * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz ++ */ ++#define TX_BAND_CFG 0x132c ++#define TX_BAND_CFG_A FIELD32(0x00000002) ++#define TX_BAND_CFG_BG FIELD32(0x00000004) ++ ++/* ++ * TX_SW_CFG0: ++ */ ++#define TX_SW_CFG0 0x1330 ++ ++/* ++ * TX_SW_CFG1: ++ */ ++#define TX_SW_CFG1 0x1334 ++ ++/* ++ * TX_SW_CFG2: ++ */ ++#define TX_SW_CFG2 0x1338 ++ ++/* ++ * TXOP_THRES_CFG: ++ */ ++#define TXOP_THRES_CFG 0x133c ++ ++/* ++ * TXOP_CTRL_CFG: ++ */ ++#define TXOP_CTRL_CFG 0x1340 ++ ++/* ++ * TX_RTS_CFG: ++ * RTS_THRES: unit:byte ++ * RTS_FBK_EN: enable rts rate fallback ++ */ ++#define TX_RTS_CFG 0x1344 ++#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff) ++#define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00) ++#define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000) ++ ++/* ++ * TX_TIMEOUT_CFG: ++ * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us ++ * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure ++ * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation. ++ * it is recommended that: ++ * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) ++ */ ++#define TX_TIMEOUT_CFG 0x1348 ++#define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0) ++#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00) ++#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000) ++ ++/* ++ * TX_RTY_CFG: ++ * SHORT_RTY_LIMIT: short retry limit ++ * LONG_RTY_LIMIT: long retry limit ++ * LONG_RTY_THRE: Long retry threshoold ++ * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode ++ * 0:expired by retry limit, 1: expired by mpdu life timer ++ * AGG_RTY_MODE: Aggregate MPDU retry mode ++ * 0:expired by retry limit, 1: expired by mpdu life timer ++ * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable ++ */ ++#define TX_RTY_CFG 0x134c ++#define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff) ++#define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00) ++#define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000) ++#define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000) ++#define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000) ++#define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000) ++ ++/* ++ * TX_LINK_CFG: ++ * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us ++ * MFB_ENABLE: TX apply remote MFB 1:enable ++ * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable ++ * 0: not apply remote remote unsolicit (MFS=7) ++ * TX_MRQ_EN: MCS request TX enable ++ * TX_RDG_EN: RDG TX enable ++ * TX_CF_ACK_EN: Piggyback CF-ACK enable ++ * REMOTE_MFB: remote MCS feedback ++ * REMOTE_MFS: remote MCS feedback sequence number ++ */ ++#define TX_LINK_CFG 0x1350 ++#define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff) ++#define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100) ++#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200) ++#define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400) ++#define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800) ++#define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000) ++#define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000) ++#define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000) ++ ++/* ++ * HT_FBK_CFG0: ++ */ ++#define HT_FBK_CFG0 0x1354 ++#define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f) ++#define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0) ++#define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00) ++#define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000) ++#define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000) ++#define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000) ++#define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000) ++#define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000) ++ ++/* ++ * HT_FBK_CFG1: ++ */ ++#define HT_FBK_CFG1 0x1358 ++#define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f) ++#define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0) ++#define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00) ++#define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000) ++#define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000) ++#define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000) ++#define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000) ++#define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000) ++ ++/* ++ * LG_FBK_CFG0: ++ */ ++#define LG_FBK_CFG0 0x135c ++#define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f) ++#define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0) ++#define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00) ++#define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000) ++#define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000) ++#define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000) ++#define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000) ++#define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000) ++ ++/* ++ * LG_FBK_CFG1: ++ */ ++#define LG_FBK_CFG1 0x1360 ++#define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f) ++#define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0) ++#define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00) ++#define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000) ++ ++/* ++ * CCK_PROT_CFG: CCK Protection ++ * 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 ++ * 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 ++ * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow ++ * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow ++ * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow ++ * RTS_TH_EN: RTS threshold enable on CCK TX ++ */ ++#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_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) ++#define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * OFDM_PROT_CFG: OFDM Protection ++ */ ++#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_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) ++#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * MM20_PROT_CFG: MM20 Protection ++ */ ++#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_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) ++#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * MM40_PROT_CFG: MM40 Protection ++ */ ++#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_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) ++#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * GF20_PROT_CFG: GF20 Protection ++ */ ++#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_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) ++#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * GF40_PROT_CFG: GF40 Protection ++ */ ++#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_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) ++#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) ++#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) ++#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) ++#define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) ++ ++/* ++ * EXP_CTS_TIME: ++ */ ++#define EXP_CTS_TIME 0x137c ++ ++/* ++ * EXP_ACK_TIME: ++ */ ++#define EXP_ACK_TIME 0x1380 ++ ++/* ++ * RX_FILTER_CFG: RX configuration register. ++ */ ++#define RX_FILTER_CFG 0x1400 ++#define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001) ++#define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002) ++#define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004) ++#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008) ++#define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010) ++#define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020) ++#define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040) ++#define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080) ++#define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100) ++#define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200) ++#define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400) ++#define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800) ++#define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000) ++#define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000) ++#define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000) ++#define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000) ++#define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000) ++ ++/* ++ * AUTO_RSP_CFG: ++ * AUTORESPONDER: 0: disable, 1: enable ++ * BAC_ACK_POLICY: 0:long, 1:short preamble ++ * CTS_40_MMODE: Response CTS 40MHz duplicate mode ++ * CTS_40_MREF: Response CTS 40MHz duplicate mode ++ * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble ++ * DUAL_CTS_EN: Power bit value in control frame ++ * ACK_CTS_PSM_BIT:Power bit value in control frame ++ */ ++#define AUTO_RSP_CFG 0x1404 ++#define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001) ++#define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002) ++#define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004) ++#define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008) ++#define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010) ++#define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040) ++#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080) ++ ++/* ++ * LEGACY_BASIC_RATE: ++ */ ++#define LEGACY_BASIC_RATE 0x1408 ++ ++/* ++ * HT_BASIC_RATE: ++ */ ++#define HT_BASIC_RATE 0x140c ++ ++/* ++ * HT_CTRL_CFG: ++ */ ++#define HT_CTRL_CFG 0x1410 ++ ++/* ++ * SIFS_COST_CFG: ++ */ ++#define SIFS_COST_CFG 0x1414 ++ ++/* ++ * RX_PARSER_CFG: ++ * Set NAV for all received frames ++ */ ++#define RX_PARSER_CFG 0x1418 ++ ++/* ++ * TX_SEC_CNT0: ++ */ ++#define TX_SEC_CNT0 0x1500 ++ ++/* ++ * RX_SEC_CNT0: ++ */ ++#define RX_SEC_CNT0 0x1504 ++ ++/* ++ * CCMP_FC_MUTE: ++ */ ++#define CCMP_FC_MUTE 0x1508 ++ ++/* ++ * TXOP_HLDR_ADDR0: ++ */ ++#define TXOP_HLDR_ADDR0 0x1600 ++ ++/* ++ * TXOP_HLDR_ADDR1: ++ */ ++#define TXOP_HLDR_ADDR1 0x1604 ++ ++/* ++ * TXOP_HLDR_ET: ++ */ ++#define TXOP_HLDR_ET 0x1608 ++ ++/* ++ * QOS_CFPOLL_RA_DW0: ++ */ ++#define QOS_CFPOLL_RA_DW0 0x160c ++ ++/* ++ * QOS_CFPOLL_RA_DW1: ++ */ ++#define QOS_CFPOLL_RA_DW1 0x1610 ++ ++/* ++ * QOS_CFPOLL_QC: ++ */ ++#define QOS_CFPOLL_QC 0x1614 ++ ++/* ++ * RX_STA_CNT0: RX PLCP error count & RX CRC error count ++ */ ++#define RX_STA_CNT0 0x1700 ++#define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff) ++#define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000) ++ ++/* ++ * RX_STA_CNT1: RX False CCA count & RX LONG frame count ++ */ ++#define RX_STA_CNT1 0x1704 ++#define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff) ++#define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000) ++ ++/* ++ * RX_STA_CNT2: ++ */ ++#define RX_STA_CNT2 0x1708 ++#define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff) ++#define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000) ++ ++/* ++ * TX_STA_CNT0: TX Beacon count ++ */ ++#define TX_STA_CNT0 0x170c ++#define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff) ++#define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_STA_CNT1: TX tx count ++ */ ++#define TX_STA_CNT1 0x1710 ++#define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff) ++#define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000) ++ ++/* ++ * TX_STA_CNT2: TX tx count ++ */ ++#define TX_STA_CNT2 0x1714 ++#define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff) ++#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_STA_FIFO: TX Result for specific PID status fifo register ++ */ ++#define TX_STA_FIFO 0x1718 ++#define TX_STA_FIFO_B_VALID FIELD32(0x00000001) ++#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e) ++#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020) ++#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040) ++#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080) ++#define TX_STA_FIFO_WCID FIELD32(0x0000ff00) ++#define TX_STA_FIFO_SUCCESS_RATE FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT: Debug counter ++ */ ++#define TX_AGG_CNT 0x171c ++#define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT0: ++ */ ++#define TX_AGG_CNT0 0x1720 ++#define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT1: ++ */ ++#define TX_AGG_CNT1 0x1724 ++#define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT2: ++ */ ++#define TX_AGG_CNT2 0x1728 ++#define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT3: ++ */ ++#define TX_AGG_CNT3 0x172c ++#define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT4: ++ */ ++#define TX_AGG_CNT4 0x1730 ++#define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT5: ++ */ ++#define TX_AGG_CNT5 0x1734 ++#define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT6: ++ */ ++#define TX_AGG_CNT6 0x1738 ++#define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000) ++ ++/* ++ * TX_AGG_CNT7: ++ */ ++#define TX_AGG_CNT7 0x173c ++#define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff) ++#define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000) ++ ++/* ++ * MPDU_DENSITY_CNT: ++ * TX_ZERO_DEL: TX zero length delimiter count ++ * RX_ZERO_DEL: RX zero length delimiter count ++ */ ++#define MPDU_DENSITY_CNT 0x1740 ++#define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff) ++#define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000) ++ ++/* ++ * Security key table memory, base address = 0x1800 ++ */ ++struct hw_pairwise_ta_entry { ++ u8 address[6]; ++ u8 reserved[2]; ++} __attribute__ ((packed)); ++ ++struct wcid_entry { ++ u8 rx_ba_bitmat7; ++ u8 rx_ba_bitmat0; ++ u8 mac[6]; ++} __attribute__ ((packed)); ++ ++struct hw_key_entry { ++ u8 key[16]; ++ u8 tx_mic[8]; ++ u8 rx_mic[8]; ++} __attribute__ ((packed)); ++ ++/* ++ * Security key table memory. ++ * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry ++ * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry ++ * PAIRWISE_IVEIV_TABLE_BASE: 8-byte * 256-entry ++ * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry ++ * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry ++ * SHARED_KEY_TABLE_BASE: 32-byte * 16-entry ++ * SHARED_KEY_MODE_BASE: 32-byte * 16-entry ++ */ ++#define MAC_WCID_BASE 0x1800 ++#define PAIRWISE_KEY_TABLE_BASE 0x4000 ++#define PAIRWISE_IVEIV_TABLE_BASE 0x6000 ++#define MAC_IVEIV_TABLE_BASE 0x6000 ++#define MAC_WCID_ATTRIBUTE_BASE 0x6800 ++#define SHARED_KEY_TABLE_BASE 0x6c00 ++#define SHARED_KEY_MODE_BASE 0x7000 ++ ++#define SHARED_KEY_ENTRY(__idx) \ ++ ( SHARED_KEY_TABLE_BASE + \ ++ ((__idx) * sizeof(struct hw_key_entry)) ) ++#define SHARED_KEY_MODE_ENTRY(__idx) \ ++ ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) ++#define PAIRWISE_KEY_ENTRY(__idx) \ ++ ( PAIRWISE_KEY_TABLE_BASE + \ ++ ((__idx) * sizeof(struct hw_key_entry)) ) ++ ++#define MAC_WCID_ENTRY(__idx) \ ++ ( MAC_WCID_BASE + (2 * sizeof(u32) * (__idx)) ) ++#define MAC_WCID_ATTR_ENTRY(__idx) \ ++ ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) ++ ++/* ++ * MAC_WCID_ATTRIBUTE: ++ * KEYTAB: 0: shared key table, 1: pairwise key table ++ * BSS_IDX: multipleBSS index for the WCID ++ */ ++#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001) ++#define MAC_WCID_ATTRIBUTE_PAIRKEY_MODE FIELD32(0x0000000e) ++#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) ++#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) ++ ++/* ++ * SHARED_KEY_MODE: ++ */ ++#define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007) ++#define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070) ++#define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700) ++#define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000) ++#define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000) ++#define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000) ++#define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000) ++#define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000) ++ ++/* ++ * HOST-MCU communication ++ */ ++ ++/* ++ * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. ++ */ ++#define H2M_MAILBOX_CSR 0x7010 ++#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) ++#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00) ++#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000) ++#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000) ++ ++/* ++ * H2M_MAILBOX_CID: ++ */ ++#define H2M_MAILBOX_CID 0x7014 ++ ++/* ++ * H2M_MAILBOX_STATUS: ++ */ ++#define H2M_MAILBOX_STATUS 0x701c ++ ++/* ++ * H2M_INT_SRC: ++ */ ++#define H2M_INT_SRC 0x7024 ++ ++/* ++ * H2M_BBP_AGENT: ++ */ ++#define H2M_BBP_AGENT 0x7028 ++ ++/* ++ * MCU_LEDCS: LED control for MCU Mailbox. ++ */ ++#define MCU_LEDCS_LED_MODE FIELD8(0x1f) ++#define MCU_LEDCS_POLARITY FIELD8(0x01) ++ ++/* ++ * HW_CS_CTS_BASE: ++ * Carrier-sense CTS frame base address. ++ * It's where mac stores carrier-sense frame for carrier-sense function. ++ */ ++#define HW_CS_CTS_BASE 0x7700 ++ ++/* ++ * HW_DFS_CTS_BASE: ++ * FS CTS frame base address. It's where mac stores CTS frame for DFS. ++ */ ++#define HW_DFS_CTS_BASE 0x7780 ++ ++/* ++ * TXRX control registers - base address 0x3000 ++ */ ++ ++/* ++ * TXRX_CSR1: ++ * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. ++ */ ++#define TXRX_CSR1 0x77d0 ++ ++/* ++ * HW_DEBUG_SETTING_BASE: ++ * since NULL frame won't be that long (256 byte) ++ * We steal 16 tail bytes to save debugging settings ++ */ ++#define HW_DEBUG_SETTING_BASE 0x77f0 ++#define HW_DEBUG_SETTING_BASE2 0x7770 ++ ++/* ++ * HW_BEACON_BASE ++ * In order to support maximum 8 MBSS and its maximum length ++ * is 512 bytes for each beacon ++ * Three section discontinue memory segments will be used. ++ * 1. The original region for BCN 0~3 ++ * 2. Extract memory from FCE table for BCN 4~5 ++ * 3. Extract memory from Pair-wise key table for BCN 6~7 ++ * It occupied those memory of wcid 238~253 for BCN 6 ++ * and wcid 222~237 for BCN 7 ++ * ++ * IMPORTANT NOTE: Not sure why legacy driver does this, ++ * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6. ++ */ ++#define HW_BEACON_BASE0 0x7800 ++#define HW_BEACON_BASE1 0x7a00 ++#define HW_BEACON_BASE2 0x7c00 ++#define HW_BEACON_BASE3 0x7e00 ++#define HW_BEACON_BASE4 0x7200 ++#define HW_BEACON_BASE5 0x7400 ++#define HW_BEACON_BASE6 0x5dc0 ++#define HW_BEACON_BASE7 0x5bc0 ++ ++#define HW_BEACON_OFFSET(__index) \ ++ ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ ++ (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ ++ (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) ++ ++/* ++ * 8051 firmware image. ++ */ ++#define FIRMWARE_RT2870 "rt2870.bin" ++#define FIRMWARE_IMAGE_BASE 0x3000 ++ ++/* ++ * BBP registers. ++ * The wordsize of the BBP is 8 bits. ++ */ ++ ++/* ++ * BBP 1: TX Antenna ++ */ ++#define BBP1_TX_POWER FIELD8(0x07) ++#define BBP1_TX_ANTENNA FIELD8(0x18) ++ ++/* ++ * BBP 3: RX Antenna ++ */ ++#define BBP3_RX_ANTENNA FIELD8(0x18) ++ ++/* ++ * RF registers ++ */ ++ ++/* ++ * RF 2 ++ */ ++#define RF2_ANTENNA_RX2 FIELD32(0x00000040) ++#define RF2_ANTENNA_TX1 FIELD32(0x00004000) ++#define RF2_ANTENNA_RX1 FIELD32(0x00020000) ++ ++/* ++ * RF 3 ++ */ ++#define RF3_TXPOWER_G FIELD32(0x00003e00) ++#define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200) ++#define RF3_TXPOWER_A FIELD32(0x00003c00) ++ ++/* ++ * RF 4 ++ */ ++#define RF4_TXPOWER_G FIELD32(0x000007c0) ++#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040) ++#define RF4_TXPOWER_A FIELD32(0x00000780) ++#define RF4_FREQ_OFFSET FIELD32(0x001f8000) ++#define RF4_BW40 FIELD32(0x00200000) ++ ++/* ++ * EEPROM content. ++ * The wordsize of the EEPROM is 16 bits. ++ */ ++ ++/* ++ * 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_ADDR1 0x0003 ++#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) ++#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) ++#define EEPROM_MAC_ADDR_2 0x0004 ++#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) ++#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) ++ ++/* ++ * EEPROM ANTENNA config ++ * 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) ++ ++/* ++ * 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) ++ ++/* ++ * EEPROM LED ++ * POLARITY_RDY_G: Polarity RDY_G setting. ++ * POLARITY_RDY_A: Polarity RDY_A setting. ++ * POLARITY_ACT: Polarity ACT setting. ++ * POLARITY_GPIO_0: Polarity GPIO0 setting. ++ * POLARITY_GPIO_1: Polarity GPIO1 setting. ++ * POLARITY_GPIO_2: Polarity GPIO2 setting. ++ * POLARITY_GPIO_3: Polarity GPIO3 setting. ++ * 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) ++#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008) ++#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010) ++#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020) ++#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040) ++#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080) ++#define EEPROM_LED_LED_MODE FIELD16(0x1f00) ++ ++/* ++ * 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 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 TXpower delta: 20MHZ AND 40 MHZ use different power. ++ * This is delta in 40MHZ. ++ * VALUE: Tx Power dalta value (MAX=4) ++ * TYPE: 1: Plus the delta value, 0: minus the delta value ++ * TXPOWER: Enable: ++ */ ++#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) ++ ++/* ++ * 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 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 byrate: 20MHZ power ++ */ ++#define EEPROM_TXPOWER_BYRATE 0x006f ++ ++/* ++ * 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) ++ ++/* ++ * MCU mailbox commands. ++ */ ++#define MCU_SLEEP 0x30 ++#define MCU_WAKEUP 0x31 ++#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_RADAR 0x60 ++#define MCU_BOOT_SIGNAL 0x72 ++ ++/* ++ * DMA descriptor defines. ++ */ ++#define TXD_DESC_SIZE ( 4 * sizeof(__le32) ) ++#define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) ++#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) ++#define RXD_DESC_SIZE ( 1 * sizeof(__le32) ) ++#define RXWI_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) ++ ++/* ++ * TX Info structure ++ */ ++ ++/* ++ * Word0 ++ * 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 ++ * USB_DMA_NEXT_VALID: Used ONLY in USB bulk Aggregation, NextValid ++ * DMA_TX_BURST: used ONLY in USB bulk Aggregation. ++ * Force USB DMA transmit frame from current selected endpoint ++ */ ++#define TXINFO_W0_USB_DMA_TX_PKT_LEN FIELD32(0x0000ffff) ++#define TXINFO_W0_WIV FIELD32(0x01000000) ++#define TXINFO_W0_QSEL FIELD32(0x06000000) ++#define TXINFO_W0_USB_DMA_NEXT_VALID FIELD32(0x40000000) ++#define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000) ++ ++/* ++ * TX WI structure ++ */ ++ ++/* ++ * Word0 ++ * FRAG: 1 To inform TKIP engine this is a fragment. ++ * MIMO_PS: The remote peer is in dynamic MIMO-PS mode ++ * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs ++ * BW: Channel bandwidth 20MHz or 40 MHz ++ * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED ++ */ ++#define TXWI_W0_FRAG FIELD32(0x00000001) ++#define TXWI_W0_MIMO_PS FIELD32(0x00000002) ++#define TXWI_W0_CF_ACK FIELD32(0x00000004) ++#define TXWI_W0_TS FIELD32(0x00000008) ++#define TXWI_W0_AMPDU FIELD32(0x00000010) ++#define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0) ++#define TXWI_W0_TX_OP FIELD32(0x00000300) ++#define TXWI_W0_MCS FIELD32(0x007f0000) ++#define TXWI_W0_BW FIELD32(0x00800000) ++#define TXWI_W0_SHORT_GI FIELD32(0x01000000) ++#define TXWI_W0_STBC FIELD32(0x06000000) ++#define TXWI_W0_IFS FIELD32(0x08000000) ++#define TXWI_W0_PHYMODE FIELD32(0xc0000000) ++ ++/* ++ * Word1 ++ */ ++#define TXWI_W1_ACK FIELD32(0x00000001) ++#define TXWI_W1_NSEQ FIELD32(0x00000002) ++#define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc) ++#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00) ++#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) ++#define TXWI_W1_PACKETID FIELD32(0xf0000000) ++ ++/* ++ * Word2 ++ */ ++#define TXWI_W2_IV FIELD32(0xffffffff) ++ ++/* ++ * Word3 ++ */ ++#define TXWI_W3_EIV FIELD32(0xffffffff) ++ ++/* ++ * RX descriptor format for RX Ring. ++ */ ++ ++/* ++ * Word0 ++ * UNICAST_TO_ME: This RX frame is unicast to me. ++ * MULTICAST: This is a multicast frame. ++ * BROADCAST: This is a broadcast frame. ++ * MY_BSS: this frame belongs to the same BSSID. ++ * CRC_ERROR: CRC error. ++ * CIPHER_ERROR: 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid. ++ * AMSDU: rx with 802.3 header, not 802.11 header. ++ */ ++ ++#define RXD_W0_BA FIELD32(0x00000001) ++#define RXD_W0_DATA FIELD32(0x00000002) ++#define RXD_W0_NULLDATA FIELD32(0x00000004) ++#define RXD_W0_FRAG FIELD32(0x00000008) ++#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000010) ++#define RXD_W0_MULTICAST FIELD32(0x00000020) ++#define RXD_W0_BROADCAST FIELD32(0x00000040) ++#define RXD_W0_MY_BSS FIELD32(0x00000080) ++#define RXD_W0_CRC_ERROR FIELD32(0x00000100) ++#define RXD_W0_CIPHER_ERROR FIELD32(0x00000600) ++#define RXD_W0_AMSDU FIELD32(0x00000800) ++#define RXD_W0_HTC FIELD32(0x00001000) ++#define RXD_W0_RSSI FIELD32(0x00002000) ++#define RXD_W0_L2PAD FIELD32(0x00004000) ++#define RXD_W0_AMPDU FIELD32(0x00008000) ++#define RXD_W0_DECRYPTED FIELD32(0x00010000) ++#define RXD_W0_PLCP_RSSI FIELD32(0x00020000) ++#define RXD_W0_CIPHER_ALG FIELD32(0x00040000) ++#define RXD_W0_LAST_AMSDU FIELD32(0x00080000) ++#define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000) ++ ++/* ++ * RX WI structure ++ */ ++ ++/* ++ * Word0 ++ */ ++#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) ++#define RXWI_W0_KEY_INDEX FIELD32(0x00000300) ++#define RXWI_W0_BSSID FIELD32(0x00001c00) ++#define RXWI_W0_UDF FIELD32(0x0000e000) ++#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) ++#define RXWI_W0_TID FIELD32(0xf0000000) ++ ++/* ++ * Word1 ++ */ ++#define RXWI_W1_FRAG FIELD32(0x0000000f) ++#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) ++#define RXWI_W1_MCS FIELD32(0x007f0000) ++#define RXWI_W1_BW FIELD32(0x00800000) ++#define RXWI_W1_SHORT_GI FIELD32(0x01000000) ++#define RXWI_W1_STBC FIELD32(0x06000000) ++#define RXWI_W1_PHYMODE FIELD32(0xc0000000) ++ ++/* ++ * Word2 ++ */ ++#define RXWI_W2_RSSI0 FIELD32(0x000000ff) ++#define RXWI_W2_RSSI1 FIELD32(0x0000ff00) ++#define RXWI_W2_RSSI2 FIELD32(0x00ff0000) ++ ++/* ++ * Word3 ++ */ ++#define RXWI_W3_SNR0 FIELD32(0x000000ff) ++#define RXWI_W3_SNR1 FIELD32(0x0000ff00) ++ ++/* ++ * Macro's for converting txpower from EEPROM to mac80211 value ++ * and from mac80211 value to register value. ++ */ ++#define MIN_G_TXPOWER 0 ++#define MIN_A_TXPOWER -7 ++#define MAX_G_TXPOWER 31 ++#define MAX_A_TXPOWER 15 ++#define DEFAULT_TXPOWER 5 ++ ++#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) ++ ++#endif /* RT2800USB_H */ +--- a/drivers/net/wireless/rt2x00/rt2x00.h ++++ b/drivers/net/wireless/rt2x00/rt2x00.h +@@ -97,6 +97,7 @@ + */ + #define ACK_SIZE 14 + #define IEEE80211_HEADER 24 ++#define AGGREGATION_SIZE 3840 + #define PLCP 48 + #define BEACON 100 + #define PREAMBLE 144 +@@ -127,6 +128,11 @@ struct rt2x00_chip { + #define RT2561 0x0302 + #define RT2661 0x0401 + #define RT2571 0x1300 ++#define RT2860 0x0601 /* 2.4GHz PCI/CB */ ++#define RT2860D 0x0681 /* 2.4GHz, 5GHz PCI/CB */ ++#define RT2890 0x0701 /* 2.4GHz PCIe */ ++#define RT2890D 0x0781 /* 2.4GHz, 5GHz PCIe */ ++#define RT2870 0x1600 + + u16 rf; + u32 rev; +--- a/drivers/net/wireless/rt2x00/rt2x00dev.c ++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c +@@ -658,7 +658,9 @@ void rt2x00lib_rxdone(struct rt2x00_dev + if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && + (rate->plcp == rxdesc.signal)) || + ((rxdesc.dev_flags & RXDONE_SIGNAL_BITRATE) && +- (rate->bitrate == rxdesc.signal))) { ++ (rate->bitrate == rxdesc.signal)) || ++ ((rxdesc.dev_flags & RXDONE_SIGNAL_MCS) && ++ (rate->mcs == rxdesc.signal))) { + idx = i; + break; + } +@@ -690,6 +692,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev + rx_status->qual = + rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi); + rx_status->signal = rxdesc.rssi; ++ rx_status->noise = rxdesc.noise; + rx_status->flag = rxdesc.flags; + rx_status->antenna = rt2x00dev->link.ant.active.rx; + +@@ -721,72 +724,84 @@ const struct rt2x00_rate rt2x00_supporte + .bitrate = 10, + .ratemask = BIT(0), + .plcp = 0x00, ++ .mcs = RATE_MCS(RATE_MODE_CCK, 0), + }, + { + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, + .bitrate = 20, + .ratemask = BIT(1), + .plcp = 0x01, ++ .mcs = RATE_MCS(RATE_MODE_CCK, 1), + }, + { + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, + .bitrate = 55, + .ratemask = BIT(2), + .plcp = 0x02, ++ .mcs = RATE_MCS(RATE_MODE_CCK, 2), + }, + { + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, + .bitrate = 110, + .ratemask = BIT(3), + .plcp = 0x03, ++ .mcs = RATE_MCS(RATE_MODE_CCK, 3), + }, + { + .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, + .bitrate = 60, + .ratemask = BIT(4), + .plcp = 0x0b, ++ .mcs = RATE_MCS(RATE_MODE_OFDM, 0), + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 90, + .ratemask = BIT(5), + .plcp = 0x0f, ++ .mcs = RATE_MCS(RATE_MODE_OFDM, 1), + }, + { + .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, + .bitrate = 120, + .ratemask = BIT(6), + .plcp = 0x0a, ++ .mcs = RATE_MCS(RATE_MODE_OFDM, 2), + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 180, + .ratemask = BIT(7), + .plcp = 0x0e, ++ .mcs = RATE_MCS(RATE_MODE_OFDM, 3), + }, + { + .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, + .bitrate = 240, + .ratemask = BIT(8), + .plcp = 0x09, ++ .mcs = RATE_MCS(RATE_MODE_OFDM, 4), + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 360, + .ratemask = BIT(9), + .plcp = 0x0d, ++ .mcs = RATE_MCS(RATE_MODE_OFDM, 5), + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 480, + .ratemask = BIT(10), + .plcp = 0x08, ++ .mcs = RATE_MCS(RATE_MODE_OFDM, 6), + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 540, + .ratemask = BIT(11), + .plcp = 0x0c, ++ .mcs = RATE_MCS(RATE_MODE_OFDM, 7), + }, + }; + +--- a/drivers/net/wireless/rt2x00/rt2x00lib.h ++++ b/drivers/net/wireless/rt2x00/rt2x00lib.h +@@ -49,6 +49,7 @@ struct rt2x00_rate { + unsigned short ratemask; + + unsigned short plcp; ++ unsigned short mcs; + }; + + extern const struct rt2x00_rate rt2x00_supported_rates[12]; +@@ -69,6 +70,9 @@ static inline int rt2x00_get_rate_preamb + return (hw_value & 0xff00); + } + ++#define RATE_MCS(__mode, __mcs) \ ++ ( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) ) ++ + /* + * Radio control handlers. + */ +--- a/drivers/net/wireless/rt2x00/rt2x00queue.c ++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c +@@ -303,6 +303,19 @@ static void rt2x00queue_create_tx_descri + } + + /* ++ * Check HT properties for this frame. ++ */ ++ if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) ++ __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); ++ if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) ++ __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); ++ ++ txdesc->ba_size = 0; /* FIXME: What value is needed? */ ++ txdesc->mpdu_density = 0; /* FIXME: What value is needed? */ ++ txdesc->stbc = 0; ++ txdesc->mcs = 33; /* Let hardware handle this */ ++ ++ /* + * PLCP setup + * Length calculation depends on OFDM/CCK rate. + */ +@@ -342,6 +355,20 @@ static void rt2x00queue_create_tx_descri + if (rt2x00_get_rate_preamble(rate->hw_value)) + txdesc->signal |= 0x08; + } ++ ++ /* ++ * Determine CCK/OFDM/HT rate mode ++ */ ++ txdesc->rate_mode = TXRATE_MODE_CCK; ++ if (hwrate->flags & DEV_RATE_OFDM) ++ txdesc->rate_mode = TXRATE_MODE_OFDM; ++ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_MCS) ++ txdesc->rate_mode = TXRATE_MODE_HTMIX; ++ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD) ++ txdesc->rate_mode = TXRATE_MODE_GREENFIELD; ++ ++ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ++ __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); + } + + static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, +--- a/drivers/net/wireless/rt2x00/rt2x00queue.h ++++ b/drivers/net/wireless/rt2x00/rt2x00queue.h +@@ -147,12 +147,14 @@ static inline struct skb_frame_desc* get + * + * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value. + * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value. ++ * @RXDONE_SIGNAL_MCS: Signal field contains the mcs value. + * @RXDONE_MY_BSS: Does this frame originate from device's BSS. + */ + enum rxdone_entry_desc_flags { + RXDONE_SIGNAL_PLCP = 1 << 0, + RXDONE_SIGNAL_BITRATE = 1 << 1, +- RXDONE_MY_BSS = 1 << 2, ++ RXDONE_SIGNAL_MCS = 1 << 2, ++ RXDONE_MY_BSS = 1 << 3, + }; + + /** +@@ -163,6 +165,7 @@ enum rxdone_entry_desc_flags { + * @timestamp: RX Timestamp + * @signal: Signal of the received frame. + * @rssi: RSSI of the received frame. ++ * @noise: Measured noise during frame reception. + * @size: Data size of the received frame. + * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags). + * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags). +@@ -176,6 +179,7 @@ struct rxdone_entry_desc { + u64 timestamp; + int signal; + int rssi; ++ int noise; + int size; + int flags; + int dev_flags; +@@ -234,6 +238,9 @@ struct txdone_entry_desc { + * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared). + * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware. + * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware. ++ * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. ++ * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. ++ * @ENTRY_TXD_HT_SHORT_GI: Use short GI. + */ + enum txentry_desc_flags { + ENTRY_TXD_RTS_FRAME, +@@ -250,6 +257,9 @@ enum txentry_desc_flags { + ENTRY_TXD_ENCRYPT_PAIRWISE, + ENTRY_TXD_ENCRYPT_IV, + ENTRY_TXD_ENCRYPT_MMIC, ++ ENTRY_TXD_HT_AMPDU, ++ ENTRY_TXD_HT_BW_40, ++ ENTRY_TXD_HT_SHORT_GI, + }; + + /** +@@ -263,6 +273,11 @@ enum txentry_desc_flags { + * @length_low: PLCP length low word. + * @signal: PLCP signal. + * @service: PLCP service. ++ * @msc: MCS. ++ * @stbc: STBC. ++ * @ba_size: BA size. ++ * @rate_mode: Rate mode (CCK, OFDM, HT). ++ * @mpdu_density: MDPU density. + * @retry_limit: Max number of retries. + * @aifs: AIFS value. + * @ifs: IFS value. +@@ -282,6 +297,12 @@ struct txentry_desc { + u16 signal; + u16 service; + ++ u16 mcs; ++ u16 stbc; ++ u16 ba_size; ++ u16 rate_mode; ++ u16 mpdu_density; ++ + short retry_limit; + short aifs; + short ifs; +--- a/drivers/net/wireless/rt2x00/rt2x00reg.h ++++ b/drivers/net/wireless/rt2x00/rt2x00reg.h +@@ -67,6 +67,16 @@ enum tsf_sync { + }; + + /* ++ * TX frame rate mode ++ */ ++enum txrate_mode { ++ TXRATE_MODE_CCK = 0, ++ TXRATE_MODE_OFDM = 1, ++ TXRATE_MODE_HTMIX = 2, ++ TXRATE_MODE_GREENFIELD = 3, ++}; ++ ++/* + * Device states + */ + enum dev_state { +@@ -125,6 +135,16 @@ enum cipher { + }; + + /* ++ * Rate modulations for 802.11n ++ */ ++enum rate_modulation { ++ RATE_MODE_CCK = 0, ++ RATE_MODE_OFDM = 1, ++ RATE_MODE_HT_MIX = 2, ++ RATE_MODE_HT_GREENFIELD = 3, ++}; ++ ++/* + * Register handlers. + * We store the position of a register field inside a field structure, + * This will simplify the process of setting and reading a certain field diff --git a/package/mac80211/patches/320-enable_rt2800.patch b/package/mac80211/patches/320-enable_rt2800.patch new file mode 100644 index 0000000000..996b47de6f --- /dev/null +++ b/package/mac80211/patches/320-enable_rt2800.patch @@ -0,0 +1,10 @@ +--- a/config.mk ++++ b/config.mk +@@ -146,6 +146,7 @@ CONFIG_ADM8211=m + CONFIG_RT2X00_LIB_PCI=m + CONFIG_RT2400PCI=m + CONFIG_RT2500PCI=m ++CONFIG_RT2800PCI=m + NEED_RT2X00=y + + # Two rt2x00 drivers require firmware: rt61pci and rt73usb. They depend on diff --git a/package/mac80211/patches/407-debugfs-sta-work-fix.patch b/package/mac80211/patches/407-debugfs-sta-work-fix.patch deleted file mode 100644 index 4dbdba998b..0000000000 --- a/package/mac80211/patches/407-debugfs-sta-work-fix.patch +++ /dev/null @@ -1,68 +0,0 @@ -Subject: mac80211: fix debugfs lockup - -When debugfs_create_dir fails, sta_info_debugfs_add_work will not -terminate because it will find the same station again and again. -This is possible whenever debugfs fails for whatever reason; one -reason is a race condition in mac80211, unfortunately we cannot -do much about it, so just document it, it just means some station -may be missing from debugfs. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> -Cc: Robin Holt <holt@sgi.com> ---- - net/mac80211/debugfs_sta.c | 11 +++++++++++ - net/mac80211/sta_info.c | 7 ++++++- - net/mac80211/sta_info.h | 1 + - 3 files changed, 18 insertions(+), 1 deletion(-) - ---- everything.orig/net/mac80211/debugfs_sta.c 2008-10-07 20:05:29.000000000 +0200 -+++ everything/net/mac80211/debugfs_sta.c 2008-10-07 20:06:39.000000000 +0200 -@@ -249,11 +249,22 @@ void ieee80211_sta_debugfs_add(struct st - DECLARE_MAC_BUF(mbuf); - u8 *mac; - -+ sta->debugfs.add_has_run = true; -+ - if (!stations_dir) - return; - - mac = print_mac(mbuf, sta->sta.addr); - -+ /* -+ * This might fail due to a race condition: -+ * When mac80211 unlinks a station, the debugfs entries -+ * remain, but it is already possible to link a new -+ * station with the same address which triggers adding -+ * it to debugfs; therefore, if the old station isn't -+ * destroyed quickly enough the old station's debugfs -+ * dir might still be around. -+ */ - sta->debugfs.dir = debugfs_create_dir(mac, stations_dir); - if (!sta->debugfs.dir) - return; ---- everything.orig/net/mac80211/sta_info.c 2008-10-07 20:05:29.000000000 +0200 -+++ everything/net/mac80211/sta_info.c 2008-10-07 20:06:39.000000000 +0200 -@@ -635,7 +635,12 @@ static void sta_info_debugfs_add_work(st - - spin_lock_irqsave(&local->sta_lock, flags); - list_for_each_entry(tmp, &local->sta_list, list) { -- if (!tmp->debugfs.dir) { -+ /* -+ * debugfs.add_has_run will be set by -+ * ieee80211_sta_debugfs_add regardless -+ * of what else it does. -+ */ -+ if (!tmp->debugfs.add_has_run) { - sta = tmp; - __sta_info_pin(sta); - break; ---- everything.orig/net/mac80211/sta_info.h 2008-10-07 20:05:29.000000000 +0200 -+++ everything/net/mac80211/sta_info.h 2008-10-07 20:06:39.000000000 +0200 -@@ -300,6 +300,7 @@ struct sta_info { - struct dentry *inactive_ms; - struct dentry *last_seq_ctrl; - struct dentry *agg_status; -+ bool add_has_run; - } debugfs; - #endif - diff --git a/package/mac80211/patches/408-mac80211-remove-agg-debugfs.patch b/package/mac80211/patches/408-mac80211-remove-agg-debugfs.patch deleted file mode 100644 index 5cbab6889a..0000000000 --- a/package/mac80211/patches/408-mac80211-remove-agg-debugfs.patch +++ /dev/null @@ -1,98 +0,0 @@ -Subject: mac80211: remove aggregation status write support from debugfs - -This code uses static variables and thus cannot be kept. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - net/mac80211/debugfs_sta.c | 73 --------------------------------------------- - 1 file changed, 1 insertion(+), 72 deletions(-) - ---- everything.orig/net/mac80211/debugfs_sta.c 2008-10-07 20:06:39.000000000 +0200 -+++ everything/net/mac80211/debugfs_sta.c 2008-10-07 20:06:40.000000000 +0200 -@@ -39,13 +39,6 @@ static const struct file_operations sta_ - .open = mac80211_open_file_generic, \ - } - --#define STA_OPS_WR(name) \ --static const struct file_operations sta_ ##name## _ops = { \ -- .read = sta_##name##_read, \ -- .write = sta_##name##_write, \ -- .open = mac80211_open_file_generic, \ --} -- - #define STA_FILE(name, field, format) \ - STA_READ_##format(name, field) \ - STA_OPS(name) -@@ -168,71 +161,7 @@ static ssize_t sta_agg_status_read(struc - - return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); - } -- --static ssize_t sta_agg_status_write(struct file *file, -- const char __user *user_buf, size_t count, loff_t *ppos) --{ -- struct sta_info *sta = file->private_data; -- struct ieee80211_local *local = sta->sdata->local; -- struct ieee80211_hw *hw = &local->hw; -- u8 *da = sta->sta.addr; -- static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, -- 0, 0, 0, 0, 0, 0, 0, 0}; -- static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1, -- 1, 1, 1, 1, 1, 1, 1, 1}; -- char *endp; -- char buf[32]; -- int buf_size, rs; -- unsigned int tid_num; -- char state[4]; -- -- memset(buf, 0x00, sizeof(buf)); -- buf_size = min(count, (sizeof(buf)-1)); -- if (copy_from_user(buf, user_buf, buf_size)) -- return -EFAULT; -- -- tid_num = simple_strtoul(buf, &endp, 0); -- if (endp == buf) -- return -EINVAL; -- -- if ((tid_num >= 100) && (tid_num <= 115)) { -- /* toggle Rx aggregation command */ -- tid_num = tid_num - 100; -- if (tid_static_rx[tid_num] == 1) { -- strcpy(state, "off "); -- ieee80211_sta_stop_rx_ba_session(sta->sdata, da, tid_num, 0, -- WLAN_REASON_QSTA_REQUIRE_SETUP); -- sta->ampdu_mlme.tid_state_rx[tid_num] |= -- HT_AGG_STATE_DEBUGFS_CTL; -- tid_static_rx[tid_num] = 0; -- } else { -- strcpy(state, "on "); -- sta->ampdu_mlme.tid_state_rx[tid_num] &= -- ~HT_AGG_STATE_DEBUGFS_CTL; -- tid_static_rx[tid_num] = 1; -- } -- printk(KERN_DEBUG "debugfs - try switching tid %u %s\n", -- tid_num, state); -- } else if ((tid_num >= 0) && (tid_num <= 15)) { -- /* toggle Tx aggregation command */ -- if (tid_static_tx[tid_num] == 0) { -- strcpy(state, "on "); -- rs = ieee80211_start_tx_ba_session(hw, da, tid_num); -- if (rs == 0) -- tid_static_tx[tid_num] = 1; -- } else { -- strcpy(state, "off"); -- rs = ieee80211_stop_tx_ba_session(hw, da, tid_num, 1); -- if (rs == 0) -- tid_static_tx[tid_num] = 0; -- } -- printk(KERN_DEBUG "debugfs - switching tid %u %s, return=%d\n", -- tid_num, state, rs); -- } -- -- return count; --} --STA_OPS_WR(agg_status); -+STA_OPS(agg_status); - - #define DEBUGFS_ADD(name) \ - sta->debugfs.name = debugfs_create_file(#name, 0400, \ diff --git a/package/mac80211/patches/409-mac80211-remove-mesh-debugfs.patch b/package/mac80211/patches/409-mac80211-remove-mesh-debugfs.patch deleted file mode 100644 index 77c4701495..0000000000 --- a/package/mac80211/patches/409-mac80211-remove-mesh-debugfs.patch +++ /dev/null @@ -1,155 +0,0 @@ -Subject: mac80211: remove writable debugs mesh parameters - -These parameters shouldn't be configurable via debugfs, if they -need to be configurable nl80211 support has to be added, if not -then they don't need to be writable here either. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> -Cc: Javier Cardona <javier@cozybit.com> -Cc: Luis Carlos Cobo <luisca@cozybit.com> ---- - net/mac80211/debugfs_netdev.c | 112 +++++++++--------------------------------- - 1 file changed, 24 insertions(+), 88 deletions(-) - ---- everything.orig/net/mac80211/debugfs_netdev.c 2008-10-07 20:05:28.000000000 +0200 -+++ everything/net/mac80211/debugfs_netdev.c 2008-10-07 20:06:40.000000000 +0200 -@@ -41,29 +41,6 @@ static ssize_t ieee80211_if_read( - return ret; - } - --#ifdef CONFIG_MAC80211_MESH --static ssize_t ieee80211_if_write( -- struct ieee80211_sub_if_data *sdata, -- char const __user *userbuf, -- size_t count, loff_t *ppos, -- int (*format)(struct ieee80211_sub_if_data *, char *)) --{ -- char buf[10]; -- int buf_size; -- -- memset(buf, 0x00, sizeof(buf)); -- buf_size = min(count, (sizeof(buf)-1)); -- if (copy_from_user(buf, userbuf, buf_size)) -- return count; -- read_lock(&dev_base_lock); -- if (sdata->dev->reg_state == NETREG_REGISTERED) -- (*format)(sdata, buf); -- read_unlock(&dev_base_lock); -- -- return count; --} --#endif -- - #define IEEE80211_IF_FMT(name, field, format_string) \ - static ssize_t ieee80211_if_fmt_##name( \ - const struct ieee80211_sub_if_data *sdata, char *buf, \ -@@ -71,19 +48,6 @@ static ssize_t ieee80211_if_fmt_##name( - { \ - return scnprintf(buf, buflen, format_string, sdata->field); \ - } --#define IEEE80211_IF_WFMT(name, field, type) \ --static int ieee80211_if_wfmt_##name( \ -- struct ieee80211_sub_if_data *sdata, char *buf) \ --{ \ -- unsigned long tmp; \ -- char *endp; \ -- \ -- tmp = simple_strtoul(buf, &endp, 0); \ -- if ((endp == buf) || ((type)tmp != tmp)) \ -- return -EINVAL; \ -- sdata->field = tmp; \ -- return 0; \ --} - #define IEEE80211_IF_FMT_DEC(name, field) \ - IEEE80211_IF_FMT(name, field, "%d\n") - #define IEEE80211_IF_FMT_HEX(name, field) \ -@@ -126,34 +90,6 @@ static const struct file_operations name - IEEE80211_IF_FMT_##format(name, field) \ - __IEEE80211_IF_FILE(name) - --#define __IEEE80211_IF_WFILE(name) \ --static ssize_t ieee80211_if_read_##name(struct file *file, \ -- char __user *userbuf, \ -- size_t count, loff_t *ppos) \ --{ \ -- return ieee80211_if_read(file->private_data, \ -- userbuf, count, ppos, \ -- ieee80211_if_fmt_##name); \ --} \ --static ssize_t ieee80211_if_write_##name(struct file *file, \ -- const char __user *userbuf, \ -- size_t count, loff_t *ppos) \ --{ \ -- return ieee80211_if_write(file->private_data, \ -- userbuf, count, ppos, \ -- ieee80211_if_wfmt_##name); \ --} \ --static const struct file_operations name##_ops = { \ -- .read = ieee80211_if_read_##name, \ -- .write = ieee80211_if_write_##name, \ -- .open = mac80211_open_file_generic, \ --} -- --#define IEEE80211_IF_WFILE(name, field, format, type) \ -- IEEE80211_IF_FMT_##format(name, field) \ -- IEEE80211_IF_WFMT(name, field, type) \ -- __IEEE80211_IF_WFILE(name) -- - /* common attributes */ - IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC); - IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC); -@@ -212,30 +148,30 @@ IEEE80211_IF_FILE(dropped_frames_no_rout - IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC); - - /* Mesh parameters */ --IEEE80211_IF_WFILE(dot11MeshMaxRetries, -- u.mesh.mshcfg.dot11MeshMaxRetries, DEC, u8); --IEEE80211_IF_WFILE(dot11MeshRetryTimeout, -- u.mesh.mshcfg.dot11MeshRetryTimeout, DEC, u16); --IEEE80211_IF_WFILE(dot11MeshConfirmTimeout, -- u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC, u16); --IEEE80211_IF_WFILE(dot11MeshHoldingTimeout, -- u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC, u16); --IEEE80211_IF_WFILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC, u8); --IEEE80211_IF_WFILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC, u8); --IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks, -- u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); --IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout, -- u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); --IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval, -- u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); --IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime, -- u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); --IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries, -- u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); --IEEE80211_IF_WFILE(path_refresh_time, -- u.mesh.mshcfg.path_refresh_time, DEC, u32); --IEEE80211_IF_WFILE(min_discovery_timeout, -- u.mesh.mshcfg.min_discovery_timeout, DEC, u16); -+IEEE80211_IF_FILE(dot11MeshMaxRetries, -+ u.mesh.mshcfg.dot11MeshMaxRetries, DEC); -+IEEE80211_IF_FILE(dot11MeshRetryTimeout, -+ u.mesh.mshcfg.dot11MeshRetryTimeout, DEC); -+IEEE80211_IF_FILE(dot11MeshConfirmTimeout, -+ u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC); -+IEEE80211_IF_FILE(dot11MeshHoldingTimeout, -+ u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC); -+IEEE80211_IF_FILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC); -+IEEE80211_IF_FILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC); -+IEEE80211_IF_FILE(dot11MeshMaxPeerLinks, -+ u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC); -+IEEE80211_IF_FILE(dot11MeshHWMPactivePathTimeout, -+ u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC); -+IEEE80211_IF_FILE(dot11MeshHWMPpreqMinInterval, -+ u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC); -+IEEE80211_IF_FILE(dot11MeshHWMPnetDiameterTraversalTime, -+ u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC); -+IEEE80211_IF_FILE(dot11MeshHWMPmaxPREQretries, -+ u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC); -+IEEE80211_IF_FILE(path_refresh_time, -+ u.mesh.mshcfg.path_refresh_time, DEC); -+IEEE80211_IF_FILE(min_discovery_timeout, -+ u.mesh.mshcfg.min_discovery_timeout, DEC); - #endif - - diff --git a/package/mac80211/patches/410-mac80211-cleanups.patch b/package/mac80211/patches/410-mac80211-cleanups.patch deleted file mode 100644 index bd66d04a9d..0000000000 --- a/package/mac80211/patches/410-mac80211-cleanups.patch +++ /dev/null @@ -1,364 +0,0 @@ -Subject: mac80211: minor code cleanups - -Nothing very interesting, some checkpatch inspired stuff, -some other things. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - net/mac80211/debugfs_sta.c | 6 +++--- - net/mac80211/main.c | 2 +- - net/mac80211/mesh.c | 2 +- - net/mac80211/rc80211_pid.h | 2 +- - net/mac80211/rx.c | 24 +++++++++++++----------- - net/mac80211/sta_info.c | 4 ++-- - net/mac80211/wep.c | 26 +++++++++++++------------- - net/mac80211/wep.h | 2 +- - net/mac80211/wpa.c | 29 ++++++++++------------------- - 9 files changed, 45 insertions(+), 52 deletions(-) - ---- everything.orig/net/mac80211/wep.c 2008-10-07 20:05:49.000000000 +0200 -+++ everything/net/mac80211/wep.c 2008-10-07 20:06:41.000000000 +0200 -@@ -49,17 +49,19 @@ void ieee80211_wep_free(struct ieee80211 - crypto_free_blkcipher(local->wep_rx_tfm); - } - --static inline int ieee80211_wep_weak_iv(u32 iv, int keylen) -+static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen) - { -- /* Fluhrer, Mantin, and Shamir have reported weaknesses in the -+ /* -+ * Fluhrer, Mantin, and Shamir have reported weaknesses in the - * key scheduling algorithm of RC4. At least IVs (KeyByte + 3, -- * 0xff, N) can be used to speedup attacks, so avoid using them. */ -+ * 0xff, N) can be used to speedup attacks, so avoid using them. -+ */ - if ((iv & 0xff00) == 0xff00) { - u8 B = (iv >> 16) & 0xff; - if (B >= 3 && B < 3 + keylen) -- return 1; -+ return true; - } -- return 0; -+ return false; - } - - -@@ -268,7 +270,7 @@ int ieee80211_wep_decrypt(struct ieee802 - } - - --u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) -+bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) - { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - unsigned int hdrlen; -@@ -276,16 +278,13 @@ u8 * ieee80211_wep_is_weak_iv(struct sk_ - u32 iv; - - if (!ieee80211_has_protected(hdr->frame_control)) -- return NULL; -+ return false; - - hdrlen = ieee80211_hdrlen(hdr->frame_control); - ivpos = skb->data + hdrlen; - iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; - -- if (ieee80211_wep_weak_iv(iv, key->conf.keylen)) -- return ivpos; -- -- return NULL; -+ return ieee80211_wep_weak_iv(iv, key->conf.keylen); - } - - ieee80211_rx_result -@@ -329,6 +328,8 @@ static int wep_encrypt_skb(struct ieee80 - ieee80211_tx_result - ieee80211_crypto_wep_encrypt(struct ieee80211_tx_data *tx) - { -+ int i; -+ - ieee80211_tx_set_protected(tx); - - if (wep_encrypt_skb(tx, tx->skb) < 0) { -@@ -337,9 +338,8 @@ ieee80211_crypto_wep_encrypt(struct ieee - } - - if (tx->extra_frag) { -- int i; - for (i = 0; i < tx->num_extra_frag; i++) { -- if (wep_encrypt_skb(tx, tx->extra_frag[i]) < 0) { -+ if (wep_encrypt_skb(tx, tx->extra_frag[i])) { - I802_DEBUG_INC(tx->local-> - tx_handlers_drop_wep); - return TX_DROP; ---- everything.orig/net/mac80211/wep.h 2008-10-07 20:05:28.000000000 +0200 -+++ everything/net/mac80211/wep.h 2008-10-07 20:06:41.000000000 +0200 -@@ -26,7 +26,7 @@ int ieee80211_wep_encrypt(struct ieee802 - struct ieee80211_key *key); - int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, - struct ieee80211_key *key); --u8 *ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); -+bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key); - - ieee80211_rx_result - ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx); ---- everything.orig/net/mac80211/wpa.c 2008-10-07 20:05:49.000000000 +0200 -+++ everything/net/mac80211/wpa.c 2008-10-07 20:06:41.000000000 +0200 -@@ -49,8 +49,7 @@ ieee80211_tx_h_michael_mic_add(struct ie - !(tx->flags & IEEE80211_TX_FRAGMENTED) && - !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) && - !wpa_test) { -- /* hwaccel - with no need for preallocated room for Michael MIC -- */ -+ /* hwaccel - with no need for preallocated room for MMIC */ - return TX_CONTINUE; - } - -@@ -67,8 +66,6 @@ ieee80211_tx_h_michael_mic_add(struct ie - #else - authenticator = 1; - #endif -- /* At this point we know we're using ALG_TKIP. To get the MIC key -- * we now will rely on the offset from the ieee80211_key_conf::key */ - key_offset = authenticator ? - NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY : - NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; -@@ -92,9 +89,7 @@ ieee80211_rx_h_michael_mic_verify(struct - int authenticator = 1, wpa_test = 0; - DECLARE_MAC_BUF(mac); - -- /* -- * No way to verify the MIC if the hardware stripped it -- */ -+ /* No way to verify the MIC if the hardware stripped it */ - if (rx->status->flag & RX_FLAG_MMIC_STRIPPED) - return RX_CONTINUE; - -@@ -116,8 +111,6 @@ ieee80211_rx_h_michael_mic_verify(struct - #else - authenticator = 1; - #endif -- /* At this point we know we're using ALG_TKIP. To get the MIC key -- * we now will rely on the offset from the ieee80211_key_conf::key */ - key_offset = authenticator ? - NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY : - NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; -@@ -202,6 +195,7 @@ ieee80211_tx_result - ieee80211_crypto_tkip_encrypt(struct ieee80211_tx_data *tx) - { - struct sk_buff *skb = tx->skb; -+ int i; - - ieee80211_tx_set_protected(tx); - -@@ -209,9 +203,8 @@ ieee80211_crypto_tkip_encrypt(struct iee - return TX_DROP; - - if (tx->extra_frag) { -- int i; - for (i = 0; i < tx->num_extra_frag; i++) { -- if (tkip_encrypt_skb(tx, tx->extra_frag[i]) < 0) -+ if (tkip_encrypt_skb(tx, tx->extra_frag[i])) - return TX_DROP; - } - } -@@ -350,7 +343,7 @@ static inline void ccmp_pn2hdr(u8 *hdr, - } - - --static inline int ccmp_hdr2pn(u8 *pn, u8 *hdr) -+static inline void ccmp_hdr2pn(u8 *pn, u8 *hdr) - { - pn[0] = hdr[7]; - pn[1] = hdr[6]; -@@ -358,7 +351,6 @@ static inline int ccmp_hdr2pn(u8 *pn, u8 - pn[3] = hdr[4]; - pn[4] = hdr[1]; - pn[5] = hdr[0]; -- return (hdr[3] >> 6) & 0x03; - } - - -@@ -373,7 +365,7 @@ static int ccmp_encrypt_skb(struct ieee8 - - if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && - !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { -- /* hwaccel - with no need for preallocated room for CCMP " -+ /* hwaccel - with no need for preallocated room for CCMP - * header or MIC fields */ - info->control.hw_key = &tx->key->conf; - return 0; -@@ -426,6 +418,7 @@ ieee80211_tx_result - ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) - { - struct sk_buff *skb = tx->skb; -+ int i; - - ieee80211_tx_set_protected(tx); - -@@ -433,9 +426,8 @@ ieee80211_crypto_ccmp_encrypt(struct iee - return TX_DROP; - - if (tx->extra_frag) { -- int i; - for (i = 0; i < tx->num_extra_frag; i++) { -- if (ccmp_encrypt_skb(tx, tx->extra_frag[i]) < 0) -+ if (ccmp_encrypt_skb(tx, tx->extra_frag[i])) - return TX_DROP; - } - } -@@ -468,7 +460,7 @@ ieee80211_crypto_ccmp_decrypt(struct iee - (rx->status->flag & RX_FLAG_IV_STRIPPED)) - return RX_CONTINUE; - -- (void) ccmp_hdr2pn(pn, skb->data + hdrlen); -+ ccmp_hdr2pn(pn, skb->data + hdrlen); - - if (memcmp(pn, key->u.ccmp.rx_pn[rx->queue], CCMP_PN_LEN) <= 0) { - key->u.ccmp.replays++; -@@ -483,9 +475,8 @@ ieee80211_crypto_ccmp_decrypt(struct iee - key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf, - skb->data + hdrlen + CCMP_HDR_LEN, data_len, - skb->data + skb->len - CCMP_MIC_LEN, -- skb->data + hdrlen + CCMP_HDR_LEN)) { -+ skb->data + hdrlen + CCMP_HDR_LEN)) - return RX_DROP_UNUSABLE; -- } - } - - memcpy(key->u.ccmp.rx_pn[rx->queue], pn, CCMP_PN_LEN); ---- everything.orig/net/mac80211/debugfs_sta.c 2008-10-07 20:06:40.000000000 +0200 -+++ everything/net/mac80211/debugfs_sta.c 2008-10-07 20:06:41.000000000 +0200 -@@ -137,7 +137,7 @@ static ssize_t sta_agg_status_read(struc - p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:"); - for (i = 0; i < STA_TID_NUM; i++) - p += scnprintf(p, sizeof(buf)+buf-p, "%5d", -- sta->ampdu_mlme.tid_state_rx[i]? -+ sta->ampdu_mlme.tid_state_rx[i] ? - sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); - - p += scnprintf(p, sizeof(buf)+buf-p, "\n TX :"); -@@ -148,13 +148,13 @@ static ssize_t sta_agg_status_read(struc - p += scnprintf(p, sizeof(buf)+buf-p, "\n DTKN:"); - for (i = 0; i < STA_TID_NUM; i++) - p += scnprintf(p, sizeof(buf)+buf-p, "%5d", -- sta->ampdu_mlme.tid_state_tx[i]? -+ sta->ampdu_mlme.tid_state_tx[i] ? - sta->ampdu_mlme.tid_tx[i]->dialog_token : 0); - - p += scnprintf(p, sizeof(buf)+buf-p, "\n SSN :"); - for (i = 0; i < STA_TID_NUM; i++) - p += scnprintf(p, sizeof(buf)+buf-p, "%5d", -- sta->ampdu_mlme.tid_state_tx[i]? -+ sta->ampdu_mlme.tid_state_tx[i] ? - sta->ampdu_mlme.tid_tx[i]->ssn : 0); - - p += scnprintf(p, sizeof(buf)+buf-p, "\n"); ---- everything.orig/net/mac80211/main.c 2008-10-07 20:05:49.000000000 +0200 -+++ everything/net/mac80211/main.c 2008-10-07 20:06:41.000000000 +0200 -@@ -1013,7 +1013,7 @@ static int __init ieee80211_init(void) - - BUILD_BUG_ON(sizeof(struct ieee80211_tx_info) > sizeof(skb->cb)); - BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + -- IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); -+ IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); - - ret = rc80211_minstrel_init(); - if (ret) ---- everything.orig/net/mac80211/mesh.c 2008-10-07 20:05:28.000000000 +0200 -+++ everything/net/mac80211/mesh.c 2008-10-07 20:06:41.000000000 +0200 -@@ -473,7 +473,7 @@ static void ieee80211_mesh_rx_bcn_presp( - size_t len, - struct ieee80211_rx_status *rx_status) - { -- struct ieee80211_local *local= sdata->local; -+ struct ieee80211_local *local = sdata->local; - struct ieee802_11_elems elems; - struct ieee80211_channel *channel; - u64 supp_rates = 0; ---- everything.orig/net/mac80211/rc80211_pid.h 2008-10-07 20:05:28.000000000 +0200 -+++ everything/net/mac80211/rc80211_pid.h 2008-10-07 20:06:41.000000000 +0200 -@@ -49,7 +49,7 @@ - - /* Arithmetic right shift for positive and negative values for ISO C. */ - #define RC_PID_DO_ARITH_RIGHT_SHIFT(x, y) \ -- (x) < 0 ? -((-(x)) >> (y)) : (x) >> (y) -+ ((x) < 0 ? -((-(x)) >> (y)) : (x) >> (y)) - - enum rc_pid_event_type { - RC_PID_EVENT_TYPE_TX_STATUS, ---- everything.orig/net/mac80211/rx.c 2008-10-07 20:06:38.000000000 +0200 -+++ everything/net/mac80211/rx.c 2008-10-07 20:06:41.000000000 +0200 -@@ -26,10 +26,11 @@ - #include "tkip.h" - #include "wme.h" - --u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, -- struct tid_ampdu_rx *tid_agg_rx, -- struct sk_buff *skb, u16 mpdu_seq_num, -- int bar_req); -+static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, -+ struct tid_ampdu_rx *tid_agg_rx, -+ struct sk_buff *skb, -+ u16 mpdu_seq_num, -+ int bar_req); - /* - * monitor mode reception - * -@@ -2000,17 +2001,17 @@ static void __ieee80211_rx_handle_packet - - static inline int seq_less(u16 sq1, u16 sq2) - { -- return (((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1)); -+ return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1); - } - - static inline u16 seq_inc(u16 sq) - { -- return ((sq + 1) & SEQ_MASK); -+ return (sq + 1) & SEQ_MASK; - } - - static inline u16 seq_sub(u16 sq1, u16 sq2) - { -- return ((sq1 - sq2) & SEQ_MASK); -+ return (sq1 - sq2) & SEQ_MASK; - } - - -@@ -2018,10 +2019,11 @@ static inline u16 seq_sub(u16 sq1, u16 s - * As it function blongs to Rx path it must be called with - * the proper rcu_read_lock protection for its flow. - */ --u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, -- struct tid_ampdu_rx *tid_agg_rx, -- struct sk_buff *skb, u16 mpdu_seq_num, -- int bar_req) -+static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, -+ struct tid_ampdu_rx *tid_agg_rx, -+ struct sk_buff *skb, -+ u16 mpdu_seq_num, -+ int bar_req) - { - struct ieee80211_local *local = hw_to_local(hw); - struct ieee80211_rx_status status; ---- everything.orig/net/mac80211/sta_info.c 2008-10-07 20:06:39.000000000 +0200 -+++ everything/net/mac80211/sta_info.c 2008-10-07 20:06:41.000000000 +0200 -@@ -294,7 +294,7 @@ int sta_info_insert(struct sta_info *sta - } - - if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 || -- is_multicast_ether_addr(sta->sta.addr))) { -+ is_multicast_ether_addr(sta->sta.addr))) { - err = -EINVAL; - goto out_free; - } -@@ -830,7 +830,7 @@ void ieee80211_sta_expire(struct ieee802 - } - - struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, -- const u8 *addr) -+ const u8 *addr) - { - struct sta_info *sta = sta_info_get(hw_to_local(hw), addr); - diff --git a/package/mac80211/patches/411-mac80211-remove-wiphy-to-hw.patch b/package/mac80211/patches/411-mac80211-remove-wiphy-to-hw.patch deleted file mode 100644 index c8a1a225b6..0000000000 --- a/package/mac80211/patches/411-mac80211-remove-wiphy-to-hw.patch +++ /dev/null @@ -1,38 +0,0 @@ -Subject: mac80211: remove wiphy_to_hw - -This isn't used by anyone, if we ever need it we can add -it back, until then it's useless. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - include/net/mac80211.h | 2 -- - net/mac80211/cfg.c | 7 ------- - 2 files changed, 9 deletions(-) - ---- everything.orig/include/net/mac80211.h 2008-10-07 20:05:49.000000000 +0200 -+++ everything/include/net/mac80211.h 2008-10-07 20:06:42.000000000 +0200 -@@ -867,8 +867,6 @@ struct ieee80211_hw { - u8 max_altrate_tries; - }; - --struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy); -- - /** - * SET_IEEE80211_DEV - set device for 802.11 hardware - * ---- everything.orig/net/mac80211/cfg.c 2008-10-07 20:06:37.000000000 +0200 -+++ everything/net/mac80211/cfg.c 2008-10-07 20:06:42.000000000 +0200 -@@ -17,13 +17,6 @@ - #include "rate.h" - #include "mesh.h" - --struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy) --{ -- struct ieee80211_local *local = wiphy_priv(wiphy); -- return &local->hw; --} --EXPORT_SYMBOL(wiphy_to_hw); -- - static bool nl80211_type_check(enum nl80211_iftype type) - { - switch (type) { diff --git a/package/mac80211/patches/412-mac80211-warn-ieee80211_hw_config-failure.patch b/package/mac80211/patches/412-mac80211-warn-ieee80211_hw_config-failure.patch deleted file mode 100644 index f18569b936..0000000000 --- a/package/mac80211/patches/412-mac80211-warn-ieee80211_hw_config-failure.patch +++ /dev/null @@ -1,113 +0,0 @@ -Subject: mac80211: clean up ieee80211_hw_config errors - -Warn when ieee80211_hw_config returns an error, it shouldn't -happen; remove a number of printks that would happen in such -a case and one printk that is user-triggerable. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - net/mac80211/cfg.c | 3 +-- - net/mac80211/main.c | 8 +++++++- - net/mac80211/scan.c | 16 +++------------- - net/mac80211/util.c | 5 +---- - net/mac80211/wext.c | 6 +----- - 5 files changed, 13 insertions(+), 25 deletions(-) - ---- everything.orig/net/mac80211/cfg.c 2008-10-07 20:06:42.000000000 +0200 -+++ everything/net/mac80211/cfg.c 2008-10-07 20:06:43.000000000 +0200 -@@ -396,8 +396,7 @@ static int ieee80211_config_beacon(struc - */ - if (params->interval) { - sdata->local->hw.conf.beacon_int = params->interval; -- if (ieee80211_hw_config(sdata->local)) -- return -EINVAL; -+ ieee80211_hw_config(sdata->local); - /* - * We updated some parameter so if below bails out - * it's not an error. ---- everything.orig/net/mac80211/main.c 2008-10-07 20:06:41.000000000 +0200 -+++ everything/net/mac80211/main.c 2008-10-07 20:06:43.000000000 +0200 -@@ -222,8 +222,14 @@ int ieee80211_hw_config(struct ieee80211 - wiphy_name(local->hw.wiphy), chan->center_freq); - #endif - -- if (local->open_count) -+ if (local->open_count) { - ret = local->ops->config(local_to_hw(local), &local->hw.conf); -+ /* -+ * HW reconfiguration should never fail, the driver has told -+ * us what it can support so it should live up to that promise. -+ */ -+ WARN_ON(ret); -+ } - - return ret; - } ---- everything.orig/net/mac80211/scan.c 2008-10-07 20:05:27.000000000 +0200 -+++ everything/net/mac80211/scan.c 2008-10-07 20:06:43.000000000 +0200 -@@ -447,18 +447,12 @@ void ieee80211_scan_completed(struct iee - - if (local->hw_scanning) { - local->hw_scanning = false; -- if (ieee80211_hw_config(local)) -- printk(KERN_DEBUG "%s: failed to restore operational " -- "channel after scan\n", wiphy_name(local->hw.wiphy)); -- -+ ieee80211_hw_config(local); - goto done; - } - - local->sw_scanning = false; -- if (ieee80211_hw_config(local)) -- printk(KERN_DEBUG "%s: failed to restore operational " -- "channel after scan\n", wiphy_name(local->hw.wiphy)); -- -+ ieee80211_hw_config(local); - - netif_tx_lock_bh(local->mdev); - netif_addr_lock(local->mdev); -@@ -545,12 +539,8 @@ void ieee80211_scan_work(struct work_str - - if (!skip) { - local->scan_channel = chan; -- if (ieee80211_hw_config(local)) { -- printk(KERN_DEBUG "%s: failed to set freq to " -- "%d MHz for scan\n", wiphy_name(local->hw.wiphy), -- chan->center_freq); -+ if (ieee80211_hw_config(local)) - skip = 1; -- } - } - - /* advance state machine to next channel/band */ ---- everything.orig/net/mac80211/util.c 2008-10-07 20:05:27.000000000 +0200 -+++ everything/net/mac80211/util.c 2008-10-07 20:06:43.000000000 +0200 -@@ -638,11 +638,8 @@ int ieee80211_set_freq(struct ieee80211_ - - if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { - if (sdata->vif.type == NL80211_IFTYPE_ADHOC && -- chan->flags & IEEE80211_CHAN_NO_IBSS) { -- printk(KERN_DEBUG "%s: IBSS not allowed on frequency " -- "%d MHz\n", sdata->dev->name, chan->center_freq); -+ chan->flags & IEEE80211_CHAN_NO_IBSS) - return ret; -- } - local->oper_channel = chan; - - if (local->sw_scanning || local->hw_scanning) ---- everything.orig/net/mac80211/wext.c 2008-10-07 20:05:27.000000000 +0200 -+++ everything/net/mac80211/wext.c 2008-10-07 20:06:43.000000000 +0200 -@@ -689,12 +689,8 @@ static int ieee80211_ioctl_siwtxpower(st - ieee80211_led_radio(local, local->hw.conf.radio_enabled); - } - -- if (need_reconfig) { -+ if (need_reconfig) - ieee80211_hw_config(local); -- /* The return value of hw_config is not of big interest here, -- * as it doesn't say that it failed because of _this_ config -- * change or something else. Ignore it. */ -- } - - return 0; - } diff --git a/package/mac80211/patches/413-mac80211-remove-antgain-cfg.patch b/package/mac80211/patches/413-mac80211-remove-antgain-cfg.patch deleted file mode 100644 index a7d8a9534a..0000000000 --- a/package/mac80211/patches/413-mac80211-remove-antgain-cfg.patch +++ /dev/null @@ -1,41 +0,0 @@ -Subject: mac80211: remove max_antenna_gain config - -The antenna gain isn't exactly configurable, despite the belief of -some unnamed individual who thinks that the EEPROM might influence -it. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - include/net/mac80211.h | 2 -- - net/mac80211/main.c | 2 -- - 2 files changed, 4 deletions(-) - ---- everything.orig/include/net/mac80211.h 2008-10-07 20:06:42.000000000 +0200 -+++ everything/include/net/mac80211.h 2008-10-07 20:06:43.000000000 +0200 -@@ -470,7 +470,6 @@ enum ieee80211_conf_flags { - * @listen_interval: listen interval in units of beacon interval - * @flags: configuration flags defined above - * @power_level: requested transmit power (in dBm) -- * @max_antenna_gain: maximum antenna gain (in dBi) - * @antenna_sel_tx: transmit antenna selection, 0: default/diversity, - * 1/2: antenna 0/1 - * @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx -@@ -485,7 +484,6 @@ struct ieee80211_conf { - u16 listen_interval; - u32 flags; - int power_level; -- int max_antenna_gain; - u8 antenna_sel_tx; - u8 antenna_sel_rx; - ---- everything.orig/net/mac80211/main.c 2008-10-07 20:06:43.000000000 +0200 -+++ everything/net/mac80211/main.c 2008-10-07 20:06:43.000000000 +0200 -@@ -215,8 +215,6 @@ int ieee80211_hw_config(struct ieee80211 - local->hw.conf.power_level = min(chan->max_power, - local->hw.conf.power_level); - -- local->hw.conf.max_antenna_gain = chan->max_antenna_gain; -- - #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n", - wiphy_name(local->hw.wiphy), chan->center_freq); diff --git a/package/mac80211/patches/414-mac80211-slot-time.patch b/package/mac80211/patches/414-mac80211-slot-time.patch deleted file mode 100644 index 145e273e5b..0000000000 --- a/package/mac80211/patches/414-mac80211-slot-time.patch +++ /dev/null @@ -1,201 +0,0 @@ -Subject: mac80211: fix short slot handling - -This patch makes mac80211 handle short slot requests from the AP -properly. Also warn about uses of IEEE80211_CONF_SHORT_SLOT_TIME -and optimise out the code since it cannot ever be hit anyway. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - include/net/mac80211.h | 28 ++++++++++-------- - net/mac80211/main.c | 9 +++-- - net/mac80211/mlme.c | 74 ++++++++++++++++++++++++++----------------------- - 3 files changed, 62 insertions(+), 49 deletions(-) - ---- everything.orig/net/mac80211/main.c 2008-10-07 20:06:43.000000000 +0200 -+++ everything/net/mac80211/main.c 2008-10-08 10:56:29.000000000 +0200 -@@ -346,9 +346,12 @@ void ieee80211_bss_info_change_notify(st - - u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) - { -- sdata->bss_conf.use_cts_prot = 0; -- sdata->bss_conf.use_short_preamble = 0; -- return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE; -+ sdata->bss_conf.use_cts_prot = false; -+ sdata->bss_conf.use_short_preamble = false; -+ sdata->bss_conf.use_short_slot = false; -+ return BSS_CHANGED_ERP_CTS_PROT | -+ BSS_CHANGED_ERP_PREAMBLE | -+ BSS_CHANGED_ERP_SLOT; - } - - void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, ---- everything.orig/net/mac80211/mlme.c 2008-10-07 20:05:49.000000000 +0200 -+++ everything/net/mac80211/mlme.c 2008-10-08 10:56:38.000000000 +0200 -@@ -568,9 +568,8 @@ static void ieee80211_sta_wmm_params(str - } - } - --static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, -- bool use_protection, -- bool use_short_preamble) -+static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, -+ u16 capab, bool erp_valid, u8 erp) - { - struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; - #ifdef CONFIG_MAC80211_VERBOSE_DEBUG -@@ -578,6 +577,19 @@ static u32 ieee80211_handle_protect_prea - DECLARE_MAC_BUF(mac); - #endif - u32 changed = 0; -+ bool use_protection; -+ bool use_short_preamble; -+ bool use_short_slot; -+ -+ if (erp_valid) { -+ use_protection = (erp & WLAN_ERP_USE_PROTECTION) != 0; -+ use_short_preamble = (erp & WLAN_ERP_BARKER_PREAMBLE) == 0; -+ } else { -+ use_protection = false; -+ use_short_preamble = !!(capab & WLAN_CAPABILITY_SHORT_PREAMBLE); -+ } -+ -+ use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); - - if (use_protection != bss_conf->use_cts_prot) { - #ifdef CONFIG_MAC80211_VERBOSE_DEBUG -@@ -607,30 +619,18 @@ static u32 ieee80211_handle_protect_prea - changed |= BSS_CHANGED_ERP_PREAMBLE; - } - -- return changed; --} -- --static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, -- u8 erp_value) --{ -- bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; -- bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; -- -- return ieee80211_handle_protect_preamb(sdata, -- use_protection, use_short_preamble); --} -- --static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, -- struct ieee80211_bss *bss) --{ -- u32 changed = 0; -- -- if (bss->has_erp_value) -- changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value); -- else { -- u16 capab = bss->capability; -- changed |= ieee80211_handle_protect_preamb(sdata, false, -- (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); -+ if (use_short_slot != bss_conf->use_short_slot) { -+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG -+ if (net_ratelimit()) { -+ printk(KERN_DEBUG "%s: switched to %s slot" -+ " (BSSID=%s)\n", -+ sdata->dev->name, -+ use_short_slot ? "short" : "long", -+ print_mac(mac, ifsta->bssid)); -+ } -+#endif -+ bss_conf->use_short_slot = use_short_slot; -+ changed |= BSS_CHANGED_ERP_SLOT; - } - - return changed; -@@ -723,7 +723,8 @@ static void ieee80211_set_associated(str - sdata->bss_conf.timestamp = bss->timestamp; - sdata->bss_conf.dtim_period = bss->dtim_period; - -- changed |= ieee80211_handle_bss_capability(sdata, bss); -+ changed |= ieee80211_handle_bss_capability(sdata, -+ bss->capability, bss->has_erp_value, bss->erp_value); - - ieee80211_rx_bss_put(local, bss); - } -@@ -1675,6 +1676,8 @@ static void ieee80211_rx_mgmt_beacon(str - struct ieee80211_local *local = sdata->local; - struct ieee80211_conf *conf = &local->hw.conf; - u32 changed = 0; -+ bool erp_valid; -+ u8 erp_value = 0; - - /* Process beacon from the current BSS */ - baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; -@@ -1696,13 +1699,16 @@ static void ieee80211_rx_mgmt_beacon(str - ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, - elems.wmm_param_len); - -- if (elems.erp_info && elems.erp_info_len >= 1) -- changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); -- else { -- u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info); -- changed |= ieee80211_handle_protect_preamb(sdata, false, -- (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); -+ -+ if (elems.erp_info && elems.erp_info_len >= 1) { -+ erp_valid = true; -+ erp_value = elems.erp_info[0]; -+ } else { -+ erp_valid = false; - } -+ changed |= ieee80211_handle_bss_capability(sdata, -+ le16_to_cpu(mgmt->u.beacon.capab_info), -+ erp_valid, erp_value); - - if (elems.ht_cap_elem && elems.ht_info_elem && - elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { ---- everything.orig/include/net/mac80211.h 2008-10-07 20:06:43.000000000 +0200 -+++ everything/include/net/mac80211.h 2008-10-08 10:57:06.000000000 +0200 -@@ -180,8 +180,12 @@ enum ieee80211_bss_change { - * @assoc: association status - * @aid: association ID number, valid only when @assoc is true - * @use_cts_prot: use CTS protection -- * @use_short_preamble: use 802.11b short preamble -- * @use_short_slot: use short slot time (only relevant for ERP) -+ * @use_short_preamble: use 802.11b short preamble; -+ * if the hardware cannot handle this it must set the -+ * IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE hardware flag -+ * @use_short_slot: use short slot time (only relevant for ERP); -+ * if the hardware cannot handle this it must set the -+ * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag - * @dtim_period: num of beacons before the next DTIM, for PSM - * @timestamp: beacon timestamp - * @beacon_int: beacon interval -@@ -442,23 +446,23 @@ struct ieee80211_rx_status { - * - * Flags to define PHY configuration options - * -- * @IEEE80211_CONF_SHORT_SLOT_TIME: use 802.11g short slot time - * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported) - * @IEEE80211_CONF_SUPPORT_HT_MODE: use 802.11n HT capabilities (if supported) - * @IEEE80211_CONF_PS: Enable 802.11 power save mode - */ - enum ieee80211_conf_flags { -- /* -- * TODO: IEEE80211_CONF_SHORT_SLOT_TIME will be removed once drivers -- * have been converted to use bss_info_changed() for slot time -- * configuration -- */ -- IEEE80211_CONF_SHORT_SLOT_TIME = (1<<0), -- IEEE80211_CONF_RADIOTAP = (1<<1), -- IEEE80211_CONF_SUPPORT_HT_MODE = (1<<2), -- IEEE80211_CONF_PS = (1<<3), -+ IEEE80211_CONF_RADIOTAP = (1<<0), -+ IEEE80211_CONF_SUPPORT_HT_MODE = (1<<1), -+ IEEE80211_CONF_PS = (1<<2), - }; - -+/* XXX: remove all this once drivers stop trying to use it */ -+static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) -+{ -+ return 0; -+} -+#define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME()) -+ - /** - * struct ieee80211_conf - configuration of the device - * diff --git a/package/mac80211/patches/415-mac80211-fix-exploit.patch b/package/mac80211/patches/415-mac80211-fix-exploit.patch deleted file mode 100644 index 114c94390b..0000000000 --- a/package/mac80211/patches/415-mac80211-fix-exploit.patch +++ /dev/null @@ -1,77 +0,0 @@ -Subject: mac80211: fix HT information element parsing - -There's no checking that the HT IEs are of the right length -which can be used by an attacker to cause an out-of-bounds -access by sending a too short HT information/capability IE. -Fix it by simply pretending those IEs didn't exist when too -short. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - net/mac80211/ieee80211_i.h | 6 ++---- - net/mac80211/mlme.c | 3 --- - net/mac80211/util.c | 8 ++++---- - 3 files changed, 6 insertions(+), 11 deletions(-) - ---- everything.orig/net/mac80211/ieee80211_i.h 2008-10-07 20:05:26.000000000 +0200 -+++ everything/net/mac80211/ieee80211_i.h 2008-10-07 20:06:45.000000000 +0200 -@@ -816,8 +816,8 @@ struct ieee802_11_elems { - u8 *ext_supp_rates; - u8 *wmm_info; - u8 *wmm_param; -- u8 *ht_cap_elem; -- u8 *ht_info_elem; -+ struct ieee80211_ht_cap *ht_cap_elem; -+ struct ieee80211_ht_addt_info *ht_info_elem; - u8 *mesh_config; - u8 *mesh_id; - u8 *peer_link; -@@ -844,8 +844,6 @@ struct ieee802_11_elems { - u8 ext_supp_rates_len; - u8 wmm_info_len; - u8 wmm_param_len; -- u8 ht_cap_elem_len; -- u8 ht_info_elem_len; - u8 mesh_config_len; - u8 mesh_id_len; - u8 peer_link_len; ---- everything.orig/net/mac80211/mlme.c 2008-10-07 20:06:44.000000000 +0200 -+++ everything/net/mac80211/mlme.c 2008-10-07 20:06:45.000000000 +0200 -@@ -1349,10 +1349,8 @@ static void ieee80211_rx_mgmt_assoc_resp - (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { - struct ieee80211_ht_bss_info bss_info; - ieee80211_ht_cap_ie_to_ht_info( -- (struct ieee80211_ht_cap *) - elems.ht_cap_elem, &sta->sta.ht_info); - ieee80211_ht_addt_info_ie_to_ht_bss_info( -- (struct ieee80211_ht_addt_info *) - elems.ht_info_elem, &bss_info); - ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); - } -@@ -1715,7 +1713,6 @@ static void ieee80211_rx_mgmt_beacon(str - struct ieee80211_ht_bss_info bss_info; - - ieee80211_ht_addt_info_ie_to_ht_bss_info( -- (struct ieee80211_ht_addt_info *) - elems.ht_info_elem, &bss_info); - changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf, - &bss_info); ---- everything.orig/net/mac80211/util.c 2008-10-07 20:06:43.000000000 +0200 -+++ everything/net/mac80211/util.c 2008-10-07 20:06:45.000000000 +0200 -@@ -529,12 +529,12 @@ void ieee802_11_parse_elems(u8 *start, s - elems->ext_supp_rates_len = elen; - break; - case WLAN_EID_HT_CAPABILITY: -- elems->ht_cap_elem = pos; -- elems->ht_cap_elem_len = elen; -+ if (elen >= sizeof(struct ieee80211_ht_cap)) -+ elems->ht_cap_elem = (void *)pos; - break; - case WLAN_EID_HT_EXTRA_INFO: -- elems->ht_info_elem = pos; -- elems->ht_info_elem_len = elen; -+ if (elen >= sizeof(struct ieee80211_ht_addt_info)) -+ elems->ht_info_elem = (void *)pos; - break; - case WLAN_EID_MESH_ID: - elems->mesh_id = pos; diff --git a/package/mac80211/patches/416-mac80211-fix-netdev-notifier.patch b/package/mac80211/patches/416-mac80211-fix-netdev-notifier.patch deleted file mode 100644 index aee45825ea..0000000000 --- a/package/mac80211/patches/416-mac80211-fix-netdev-notifier.patch +++ /dev/null @@ -1,27 +0,0 @@ -Subject: mac80211: fix debugfs netdev rename - -If, for some reason, a netdev has no debugfs dir, we shouldn't -try to rename that dir. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> -Cc: Robin Holt <holt@sgi.com> ---- - net/mac80211/debugfs_netdev.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - ---- everything.orig/net/mac80211/debugfs_netdev.c 2008-10-08 10:08:23.000000000 +0200 -+++ everything/net/mac80211/debugfs_netdev.c 2008-10-08 10:22:52.000000000 +0200 -@@ -481,8 +481,12 @@ static int netdev_notify(struct notifier - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - -- sprintf(buf, "netdev:%s", dev->name); - dir = sdata->debugfsdir; -+ -+ if (!dir) -+ return 0; -+ -+ sprintf(buf, "netdev:%s", dev->name); - if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf)) - printk(KERN_ERR "mac80211: debugfs: failed to rename debugfs " - "dir to %s\n", buf); diff --git a/package/mac80211/patches/417-cfg80211-fix-rename.patch b/package/mac80211/patches/417-cfg80211-fix-rename.patch deleted file mode 100644 index 3cfab61325..0000000000 --- a/package/mac80211/patches/417-cfg80211-fix-rename.patch +++ /dev/null @@ -1,32 +0,0 @@ -Subject: cfg80211: fix debugfs error handling - -If something goes wrong creating the debugfs dir or when -debugfs is not compiled in, the current code might lead to -trouble; make it more robust. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - net/wireless/core.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- everything.orig/net/wireless/core.c 2008-10-08 10:13:49.000000000 +0200 -+++ everything/net/wireless/core.c 2008-10-08 10:19:10.000000000 +0200 -@@ -185,7 +185,8 @@ int cfg80211_dev_rename(struct cfg80211_ - if (result) - goto out_unlock; - -- if (!debugfs_rename(rdev->wiphy.debugfsdir->d_parent, -+ if (rdev->wiphy.debugfsdir && -+ !debugfs_rename(rdev->wiphy.debugfsdir->d_parent, - rdev->wiphy.debugfsdir, - rdev->wiphy.debugfsdir->d_parent, - newname)) -@@ -318,6 +319,8 @@ int wiphy_register(struct wiphy *wiphy) - drv->wiphy.debugfsdir = - debugfs_create_dir(wiphy_name(&drv->wiphy), - ieee80211_debugfs_dir); -+ if (IS_ERR(drv->wiphy.debugfsdir)) -+ drv->wiphy.debugfsdir = NULL; - - res = 0; - out_unlock: diff --git a/package/mac80211/patches/418-ieee80211-cleanup-ht-terminology.patch b/package/mac80211/patches/418-ieee80211-cleanup-ht-terminology.patch deleted file mode 100644 index 61ae15a885..0000000000 --- a/package/mac80211/patches/418-ieee80211-cleanup-ht-terminology.patch +++ /dev/null @@ -1,1427 +0,0 @@ -Subject: 802.11: clean up/fix HT support - -This patch cleans up a number of things: - * the unusable definition of the HT capabilities/HT information - information elements - * variable names that are hard to understand - * mac80211: move ieee80211_handle_ht to ht.c and remove the unused - enable_ht parameter - * mac80211: fix bug with MCS rate 32 in ieee80211_handle_ht - * mac80211: fix bug with casting the result of ieee80211_bss_get_ie - to an information element _contents_ rather than the - whole element, add size checking (another out-of-bounds - access bug fixed!) - * mac80211: remove some unused return values in favour of BUG_ON - checking - * a few minor other things - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - drivers/net/wireless/ath9k/main.c | 57 +++++------ - drivers/net/wireless/ath9k/rc.c | 10 - - drivers/net/wireless/ath9k/rc.h | 1 - drivers/net/wireless/ath9k/recv.c | 2 - drivers/net/wireless/ath9k/xmit.c | 2 - drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 18 +-- - drivers/net/wireless/iwlwifi/iwl-agn.c | 20 +-- - drivers/net/wireless/iwlwifi/iwl-core.c | 71 +++++++------- - drivers/net/wireless/iwlwifi/iwl-core.h | 2 - drivers/net/wireless/iwlwifi/iwl-dev.h | 4 - drivers/net/wireless/iwlwifi/iwl-scan.c | 12 +- - drivers/net/wireless/iwlwifi/iwl-sta.c | 6 - - drivers/net/wireless/mac80211_hwsim.c | 19 +-- - include/linux/ieee80211.h | 133 ++++++++++++++++++-------- - include/net/mac80211.h | 12 +- - include/net/wireless.h | 15 +- - net/mac80211/cfg.c | 7 - - net/mac80211/ht.c | 151 +++++++++++++++++++++++++----- - net/mac80211/ieee80211_i.h | 16 +-- - net/mac80211/main.c | 94 ------------------ - net/mac80211/mlme.c | 45 ++++---- - net/mac80211/util.c | 4 - net/mac80211/wext.c | 4 - 23 files changed, 386 insertions(+), 319 deletions(-) - ---- everything.orig/include/linux/ieee80211.h 2008-10-08 20:44:47.000000000 +0200 -+++ everything/include/linux/ieee80211.h 2008-10-09 02:16:21.000000000 +0200 -@@ -685,28 +685,88 @@ struct ieee80211_bar { - #define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 - #define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 - -+ -+#define IEEE80211_HT_MCS_MASK_LEN 10 -+ -+/** -+ * struct ieee80211_mcs_info - MCS information -+ * @rx_mask: RX mask -+ * @rx_highest: highest supported RX rate -+ * @tx_params: TX parameters -+ */ -+struct ieee80211_mcs_info { -+ u8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; -+ __le16 rx_highest; -+ u8 tx_params; -+ u8 reserved[3]; -+} __attribute__((packed)); -+ -+/* 802.11n HT capability MSC set */ -+#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff -+#define IEEE80211_HT_MCS_TX_DEFINED 0x01 -+#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 -+/* value 0 == 1 stream etc */ -+#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C -+#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 -+#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 -+#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 -+ -+/* -+ * 802.11n D5.0 20.3.5 / 20.6 says: -+ * - indices 0 to 7 and 32 are single spatial stream -+ * - 8 to 31 are multiple spatial streams using equal modulation -+ * [8..15 for two streams, 16..23 for three and 24..31 for four] -+ * - remainder are multiple spatial streams using unequal modulation -+ */ -+#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 -+#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ -+ (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) -+ - /** - * struct ieee80211_ht_cap - HT capabilities - * -- * This structure refers to "HT capabilities element" as -- * described in 802.11n draft section 7.3.2.52 -+ * This structure is the "HT capabilities element" as -+ * described in 802.11n D5.0 7.3.2.57 - */ - struct ieee80211_ht_cap { - __le16 cap_info; - u8 ampdu_params_info; -- u8 supp_mcs_set[16]; -+ -+ /* 16 bytes MCS information */ -+ struct ieee80211_mcs_info mcs; -+ - __le16 extended_ht_cap_info; - __le32 tx_BF_cap_info; - u8 antenna_selection_info; - } __attribute__ ((packed)); - -+/* 802.11n HT capabilities masks (for cap_info) */ -+#define IEEE80211_HT_CAP_LDPC_CODING 0x0001 -+#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 -+#define IEEE80211_HT_CAP_SM_PS 0x000C -+#define IEEE80211_HT_CAP_GRN_FLD 0x0010 -+#define IEEE80211_HT_CAP_SGI_20 0x0020 -+#define IEEE80211_HT_CAP_SGI_40 0x0040 -+#define IEEE80211_HT_CAP_TX_STBC 0x0080 -+#define IEEE80211_HT_CAP_RX_STBC 0x0300 -+#define IEEE80211_HT_CAP_DELAY_BA 0x0400 -+#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 -+#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 -+#define IEEE80211_HT_CAP_PSMP_SUPPORT 0x2000 -+#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 -+#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 -+ -+/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ -+#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 -+#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C -+ - /** -- * struct ieee80211_ht_cap - HT additional information -+ * struct ieee80211_ht_info - HT information - * -- * This structure refers to "HT information element" as -- * described in 802.11n draft section 7.3.2.53 -+ * This structure is the "HT information element" as -+ * described in 802.11n D5.0 7.3.2.58 - */ --struct ieee80211_ht_addt_info { -+struct ieee80211_ht_info { - u8 control_chan; - u8 ht_param; - __le16 operation_mode; -@@ -714,36 +774,33 @@ struct ieee80211_ht_addt_info { - u8 basic_set[16]; - } __attribute__ ((packed)); - --/* 802.11n HT capabilities masks */ --#define IEEE80211_HT_CAP_SUP_WIDTH 0x0002 --#define IEEE80211_HT_CAP_SM_PS 0x000C --#define IEEE80211_HT_CAP_GRN_FLD 0x0010 --#define IEEE80211_HT_CAP_SGI_20 0x0020 --#define IEEE80211_HT_CAP_SGI_40 0x0040 --#define IEEE80211_HT_CAP_DELAY_BA 0x0400 --#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 --#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 --/* 802.11n HT capability AMPDU settings */ --#define IEEE80211_HT_CAP_AMPDU_FACTOR 0x03 --#define IEEE80211_HT_CAP_AMPDU_DENSITY 0x1C --/* 802.11n HT capability MSC set */ --#define IEEE80211_SUPP_MCS_SET_UEQM 4 --#define IEEE80211_HT_CAP_MAX_STREAMS 4 --#define IEEE80211_SUPP_MCS_SET_LEN 10 --/* maximum streams the spec allows */ --#define IEEE80211_HT_CAP_MCS_TX_DEFINED 0x01 --#define IEEE80211_HT_CAP_MCS_TX_RX_DIFF 0x02 --#define IEEE80211_HT_CAP_MCS_TX_STREAMS 0x0C --#define IEEE80211_HT_CAP_MCS_TX_UEQM 0x10 --/* 802.11n HT IE masks */ --#define IEEE80211_HT_IE_CHA_SEC_OFFSET 0x03 --#define IEEE80211_HT_IE_CHA_SEC_NONE 0x00 --#define IEEE80211_HT_IE_CHA_SEC_ABOVE 0x01 --#define IEEE80211_HT_IE_CHA_SEC_BELOW 0x03 --#define IEEE80211_HT_IE_CHA_WIDTH 0x04 --#define IEEE80211_HT_IE_HT_PROTECTION 0x0003 --#define IEEE80211_HT_IE_NON_GF_STA_PRSNT 0x0004 --#define IEEE80211_HT_IE_NON_HT_STA_PRSNT 0x0010 -+/* for ht_param */ -+#define IEEE80211_HT_PARAM_CHA_SEC_OFFSET 0x03 -+#define IEEE80211_HT_PARAM_CHA_SEC_NONE 0x00 -+#define IEEE80211_HT_PARAM_CHA_SEC_ABOVE 0x01 -+#define IEEE80211_HT_PARAM_CHA_SEC_BELOW 0x03 -+#define IEEE80211_HT_PARAM_CHAN_WIDTH_ANY 0x04 -+#define IEEE80211_HT_PARAM_RIFS_MODE 0x08 -+#define IEEE80211_HT_PARAM_SPSMP_SUPPORT 0x10 -+#define IEEE80211_HT_PARAM_SERV_INTERVAL_GRAN 0xE0 -+ -+/* for operation_mode */ -+#define IEEE80211_HT_OP_MODE_PROTECTION 0x0003 -+#define IEEE80211_HT_OP_MODE_PROTECTION_NONE 0 -+#define IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER 1 -+#define IEEE80211_HT_OP_MODE_PROTECTION_20MHZ 2 -+#define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 -+#define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 -+#define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 -+ -+/* for stbc_param */ -+#define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 -+#define IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT 0x0080 -+#define IEEE80211_HT_STBC_PARAM_STBC_BEACON 0x0100 -+#define IEEE80211_HT_STBC_PARAM_LSIG_TXOP_FULLPROT 0x0200 -+#define IEEE80211_HT_STBC_PARAM_PCO_ACTIVE 0x0400 -+#define IEEE80211_HT_STBC_PARAM_PCO_PHASE 0x0800 -+ - - /* block-ack parameters */ - #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 -@@ -949,7 +1006,7 @@ enum ieee80211_eid { - WLAN_EID_EXT_SUPP_RATES = 50, - /* 802.11n */ - WLAN_EID_HT_CAPABILITY = 45, -- WLAN_EID_HT_EXTRA_INFO = 61, -+ WLAN_EID_HT_INFORMATION = 61, - /* 802.11i */ - WLAN_EID_RSN = 48, - WLAN_EID_WPA = 221, ---- everything.orig/include/net/wireless.h 2008-10-08 20:44:46.000000000 +0200 -+++ everything/include/net/wireless.h 2008-10-09 02:16:20.000000000 +0200 -@@ -10,6 +10,7 @@ - #include <linux/netdevice.h> - #include <linux/debugfs.h> - #include <linux/list.h> -+#include <linux/ieee80211.h> - #include <net/cfg80211.h> - - /** -@@ -133,23 +134,23 @@ struct ieee80211_rate { - }; - - /** -- * struct ieee80211_ht_info - describing STA's HT capabilities -+ * struct ieee80211_sta_ht_cap - STA's HT capabilities - * - * This structure describes most essential parameters needed - * to describe 802.11n HT capabilities for an STA. - * -- * @ht_supported: is HT supported by STA, 0: no, 1: yes -+ * @ht_supported: is HT supported by the STA - * @cap: HT capabilities map as described in 802.11n spec - * @ampdu_factor: Maximum A-MPDU length factor - * @ampdu_density: Minimum A-MPDU spacing -- * @supp_mcs_set: Supported MCS set as described in 802.11n spec -+ * @mcs: Supported MCS rates - */ --struct ieee80211_ht_info { -+struct ieee80211_sta_ht_cap { - u16 cap; /* use IEEE80211_HT_CAP_ */ -- u8 ht_supported; -+ bool ht_supported; - u8 ampdu_factor; - u8 ampdu_density; -- u8 supp_mcs_set[16]; -+ struct ieee80211_mcs_info mcs; - }; - - /** -@@ -173,7 +174,7 @@ struct ieee80211_supported_band { - enum ieee80211_band band; - int n_channels; - int n_bitrates; -- struct ieee80211_ht_info ht_info; -+ struct ieee80211_sta_ht_cap ht_cap; - }; - - /** ---- everything.orig/net/mac80211/main.c 2008-10-08 20:45:06.000000000 +0200 -+++ everything/net/mac80211/main.c 2008-10-09 02:16:29.000000000 +0200 -@@ -232,100 +232,6 @@ int ieee80211_hw_config(struct ieee80211 - return ret; - } - --/** -- * ieee80211_handle_ht should be used only after legacy configuration -- * has been determined namely band, as ht configuration depends upon -- * the hardware's HT abilities for a _specific_ band. -- */ --u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, -- struct ieee80211_ht_info *req_ht_cap, -- struct ieee80211_ht_bss_info *req_bss_cap) --{ -- struct ieee80211_conf *conf = &local->hw.conf; -- struct ieee80211_supported_band *sband; -- struct ieee80211_ht_info ht_conf; -- struct ieee80211_ht_bss_info ht_bss_conf; -- u32 changed = 0; -- int i; -- u8 max_tx_streams = IEEE80211_HT_CAP_MAX_STREAMS; -- u8 tx_mcs_set_cap; -- -- sband = local->hw.wiphy->bands[conf->channel->band]; -- -- memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); -- memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); -- -- /* HT is not supported */ -- if (!sband->ht_info.ht_supported) { -- conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; -- goto out; -- } -- -- /* disable HT */ -- if (!enable_ht) { -- if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) -- changed |= BSS_CHANGED_HT; -- conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; -- conf->ht_conf.ht_supported = 0; -- goto out; -- } -- -- -- if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) -- changed |= BSS_CHANGED_HT; -- -- conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; -- ht_conf.ht_supported = 1; -- -- ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; -- ht_conf.cap &= ~(IEEE80211_HT_CAP_SM_PS); -- ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_SM_PS; -- ht_bss_conf.primary_channel = req_bss_cap->primary_channel; -- ht_bss_conf.bss_cap = req_bss_cap->bss_cap; -- ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; -- -- ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; -- ht_conf.ampdu_density = req_ht_cap->ampdu_density; -- -- /* Bits 96-100 */ -- tx_mcs_set_cap = sband->ht_info.supp_mcs_set[12]; -- -- /* configure suppoerted Tx MCS according to requested MCS -- * (based in most cases on Rx capabilities of peer) and self -- * Tx MCS capabilities (as defined by low level driver HW -- * Tx capabilities) */ -- if (!(tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_DEFINED)) -- goto check_changed; -- -- /* Counting from 0 therfore + 1 */ -- if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_RX_DIFF) -- max_tx_streams = ((tx_mcs_set_cap & -- IEEE80211_HT_CAP_MCS_TX_STREAMS) >> 2) + 1; -- -- for (i = 0; i < max_tx_streams; i++) -- ht_conf.supp_mcs_set[i] = -- sband->ht_info.supp_mcs_set[i] & -- req_ht_cap->supp_mcs_set[i]; -- -- if (tx_mcs_set_cap & IEEE80211_HT_CAP_MCS_TX_UEQM) -- for (i = IEEE80211_SUPP_MCS_SET_UEQM; -- i < IEEE80211_SUPP_MCS_SET_LEN; i++) -- ht_conf.supp_mcs_set[i] = -- sband->ht_info.supp_mcs_set[i] & -- req_ht_cap->supp_mcs_set[i]; -- --check_changed: -- /* if bss configuration changed store the new one */ -- if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || -- memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { -- changed |= BSS_CHANGED_HT; -- memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); -- memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); -- } --out: -- return changed; --} -- - void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, - u32 changed) - { ---- everything.orig/include/net/mac80211.h 2008-10-08 20:45:06.000000000 +0200 -+++ everything/include/net/mac80211.h 2008-10-09 02:16:30.000000000 +0200 -@@ -191,7 +191,7 @@ enum ieee80211_bss_change { - * @beacon_int: beacon interval - * @assoc_capability: capabilities taken from assoc resp - * @assoc_ht: association in HT mode -- * @ht_conf: ht capabilities -+ * @ht_cap: ht capabilities - * @ht_bss_conf: ht extended capabilities - * @basic_rates: bitmap of basic rates, each bit stands for an - * index into the rate table configured by the driver in -@@ -212,7 +212,7 @@ struct ieee80211_bss_conf { - u64 basic_rates; - /* ht related data */ - bool assoc_ht; -- struct ieee80211_ht_info *ht_conf; -+ struct ieee80211_sta_ht_cap *ht_cap; - struct ieee80211_ht_bss_info *ht_bss_conf; - }; - -@@ -477,7 +477,7 @@ static inline int __deprecated __IEEE802 - * @antenna_sel_tx: transmit antenna selection, 0: default/diversity, - * 1/2: antenna 0/1 - * @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx -- * @ht_conf: describes current self configuration of 802.11n HT capabilies -+ * @ht_cap: describes current self configuration of 802.11n HT capabilities - * @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters - * @channel: the channel to tune to - */ -@@ -493,7 +493,7 @@ struct ieee80211_conf { - - struct ieee80211_channel *channel; - -- struct ieee80211_ht_info ht_conf; -+ struct ieee80211_sta_ht_cap ht_cap; - struct ieee80211_ht_bss_info ht_bss_conf; - }; - -@@ -686,7 +686,7 @@ enum set_key_cmd { - * @addr: MAC address - * @aid: AID we assigned to the station if we're an AP - * @supp_rates: Bitmap of supported rates (per band) -- * @ht_info: HT capabilities of this STA -+ * @ht_cap: HT capabilities of this STA - * @drv_priv: data area for driver use, will always be aligned to - * sizeof(void *), size is determined in hw information. - */ -@@ -694,7 +694,7 @@ struct ieee80211_sta { - u64 supp_rates[IEEE80211_NUM_BANDS]; - u8 addr[ETH_ALEN]; - u16 aid; -- struct ieee80211_ht_info ht_info; -+ struct ieee80211_sta_ht_cap ht_cap; - - /* must be last */ - u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); ---- everything.orig/net/mac80211/ieee80211_i.h 2008-10-08 20:45:06.000000000 +0200 -+++ everything/net/mac80211/ieee80211_i.h 2008-10-09 02:16:30.000000000 +0200 -@@ -817,7 +817,7 @@ struct ieee802_11_elems { - u8 *wmm_info; - u8 *wmm_param; - struct ieee80211_ht_cap *ht_cap_elem; -- struct ieee80211_ht_addt_info *ht_info_elem; -+ struct ieee80211_ht_info *ht_info_elem; - u8 *mesh_config; - u8 *mesh_id; - u8 *peer_link; -@@ -885,9 +885,6 @@ static inline int ieee80211_bssid_match( - int ieee80211_hw_config(struct ieee80211_local *local); - int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); - void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); --u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, -- struct ieee80211_ht_info *req_ht_cap, -- struct ieee80211_ht_bss_info *req_bss_cap); - void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, - u32 changed); - void ieee80211_configure_filter(struct ieee80211_local *local); -@@ -968,11 +965,14 @@ int ieee80211_monitor_start_xmit(struct - int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); - - /* HT */ --int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, -- struct ieee80211_ht_info *ht_info); --int ieee80211_ht_addt_info_ie_to_ht_bss_info( -- struct ieee80211_ht_addt_info *ht_add_info_ie, -+void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_ht_cap *ht_cap_ie, -+ struct ieee80211_sta_ht_cap *ht_cap); -+void ieee80211_ht_info_ie_to_ht_bss_info( -+ struct ieee80211_ht_info *ht_add_info_ie, - struct ieee80211_ht_bss_info *bss_info); -+u32 ieee80211_handle_ht(struct ieee80211_local *local, -+ struct ieee80211_sta_ht_cap *req_ht_cap, -+ struct ieee80211_ht_bss_info *req_bss_cap); - void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); - - void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, ---- everything.orig/net/mac80211/wext.c 2008-10-08 20:45:06.000000000 +0200 -+++ everything/net/mac80211/wext.c 2008-10-09 02:16:28.000000000 +0200 -@@ -147,7 +147,7 @@ static int ieee80211_ioctl_giwname(struc - sband = local->hw.wiphy->bands[IEEE80211_BAND_5GHZ]; - if (sband) { - is_a = 1; -- is_ht |= sband->ht_info.ht_supported; -+ is_ht |= sband->ht_cap.ht_supported; - } - - sband = local->hw.wiphy->bands[IEEE80211_BAND_2GHZ]; -@@ -160,7 +160,7 @@ static int ieee80211_ioctl_giwname(struc - if (sband->bitrates[i].bitrate == 60) - is_g = 1; - } -- is_ht |= sband->ht_info.ht_supported; -+ is_ht |= sband->ht_cap.ht_supported; - } - - strcpy(name, "IEEE 802.11"); ---- everything.orig/net/mac80211/ht.c 2008-10-08 20:44:47.000000000 +0200 -+++ everything/net/mac80211/ht.c 2008-10-09 02:16:26.000000000 +0200 -@@ -20,37 +20,33 @@ - #include "sta_info.h" - #include "wme.h" - --int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, -- struct ieee80211_ht_info *ht_info) -+void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_ht_cap *ht_cap_ie, -+ struct ieee80211_sta_ht_cap *ht_cap) - { - -- if (ht_info == NULL) -- return -EINVAL; -+ BUG_ON(!ht_cap); - -- memset(ht_info, 0, sizeof(*ht_info)); -+ memset(ht_cap, 0, sizeof(*ht_cap)); - - if (ht_cap_ie) { - u8 ampdu_info = ht_cap_ie->ampdu_params_info; - -- ht_info->ht_supported = 1; -- ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info); -- ht_info->ampdu_factor = -- ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR; -- ht_info->ampdu_density = -- (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; -- memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16); -+ ht_cap->ht_supported = true; -+ ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info); -+ ht_cap->ampdu_factor = -+ ampdu_info & IEEE80211_HT_AMPDU_PARM_FACTOR; -+ ht_cap->ampdu_density = -+ (ampdu_info & IEEE80211_HT_AMPDU_PARM_DENSITY) >> 2; -+ memcpy(&ht_cap->mcs, &ht_cap_ie->mcs, sizeof(ht_cap->mcs)); - } else -- ht_info->ht_supported = 0; -- -- return 0; -+ ht_cap->ht_supported = false; - } - --int ieee80211_ht_addt_info_ie_to_ht_bss_info( -- struct ieee80211_ht_addt_info *ht_add_info_ie, -+void ieee80211_ht_info_ie_to_ht_bss_info( -+ struct ieee80211_ht_info *ht_add_info_ie, - struct ieee80211_ht_bss_info *bss_info) - { -- if (bss_info == NULL) -- return -EINVAL; -+ BUG_ON(!bss_info); - - memset(bss_info, 0, sizeof(*bss_info)); - -@@ -62,8 +58,119 @@ int ieee80211_ht_addt_info_ie_to_ht_bss_ - bss_info->bss_cap = ht_add_info_ie->ht_param; - bss_info->bss_op_mode = (u8)(op_mode & 0xff); - } -+} -+ -+/* -+ * ieee80211_handle_ht should be called only after the operating band -+ * has been determined as ht configuration depends on the hw's -+ * HT abilities for a specific band. -+ */ -+u32 ieee80211_handle_ht(struct ieee80211_local *local, -+ struct ieee80211_sta_ht_cap *req_ht_cap, -+ struct ieee80211_ht_bss_info *req_bss_cap) -+{ -+ struct ieee80211_conf *conf = &local->hw.conf; -+ struct ieee80211_supported_band *sband; -+ struct ieee80211_sta_ht_cap ht_cap; -+ struct ieee80211_ht_bss_info ht_bss_conf; -+ u32 changed = 0; -+ int i; -+ u8 max_tx_streams; -+ u8 tx_mcs_set_cap; -+ bool enable_ht = true; -+ -+ sband = local->hw.wiphy->bands[conf->channel->band]; -+ -+ memset(&ht_cap, 0, sizeof(ht_cap)); -+ memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); -+ -+ /* HT is not supported */ -+ if (!sband->ht_cap.ht_supported) -+ enable_ht = false; -+ -+ /* disable HT */ -+ if (!enable_ht) { -+ if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) -+ changed |= BSS_CHANGED_HT; -+ conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; -+ conf->ht_cap.ht_supported = false; -+ return changed; -+ } -+ -+ -+ if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) -+ changed |= BSS_CHANGED_HT; -+ -+ conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; -+ ht_cap.ht_supported = true; -+ -+ ht_cap.cap = req_ht_cap->cap & sband->ht_cap.cap; -+ ht_cap.cap &= ~IEEE80211_HT_CAP_SM_PS; -+ ht_cap.cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS; -+ -+ ht_bss_conf.primary_channel = req_bss_cap->primary_channel; -+ ht_bss_conf.bss_cap = req_bss_cap->bss_cap; -+ ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; -+ -+ ht_cap.ampdu_factor = req_ht_cap->ampdu_factor; -+ ht_cap.ampdu_density = req_ht_cap->ampdu_density; -+ -+ /* own MCS TX capabilities */ -+ tx_mcs_set_cap = sband->ht_cap.mcs.tx_params; -+ -+ /* -+ * configure supported Tx MCS according to requested MCS -+ * (based in most cases on Rx capabilities of peer) and self -+ * Tx MCS capabilities (as defined by low level driver HW -+ * Tx capabilities) -+ */ -+ -+ /* can we TX with MCS rates? */ -+ if (!(tx_mcs_set_cap & IEEE80211_HT_MCS_TX_DEFINED)) -+ goto check_changed; -+ -+ /* Counting from 0, therefore +1 */ -+ if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_RX_DIFF) -+ max_tx_streams = -+ ((tx_mcs_set_cap & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) -+ >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; -+ else -+ max_tx_streams = IEEE80211_HT_MCS_TX_MAX_STREAMS; -+ -+ /* -+ * 802.11n D5.0 20.3.5 / 20.6 says: -+ * - indices 0 to 7 and 32 are single spatial stream -+ * - 8 to 31 are multiple spatial streams using equal modulation -+ * [8..15 for two streams, 16..23 for three and 24..31 for four] -+ * - remainder are multiple spatial streams using unequal modulation -+ */ -+ for (i = 0; i < max_tx_streams; i++) -+ ht_cap.mcs.rx_mask[i] = -+ sband->ht_cap.mcs.rx_mask[i] & -+ req_ht_cap->mcs.rx_mask[i]; -+ -+ if (tx_mcs_set_cap & IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION) -+ for (i = IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE; -+ i < IEEE80211_HT_MCS_MASK_LEN; i++) -+ ht_cap.mcs.rx_mask[i] = -+ sband->ht_cap.mcs.rx_mask[i] & -+ req_ht_cap->mcs.rx_mask[i]; -+ -+ /* handle MCS rate 32 too */ -+ if (sband->ht_cap.mcs.rx_mask[32/8] & -+ req_ht_cap->mcs.rx_mask[32/8] & 1) -+ ht_cap.mcs.rx_mask[32/8] |= 1; -+ -+ check_changed: -+ /* if bss configuration changed store the new one */ -+ if (memcmp(&conf->ht_cap, &ht_cap, sizeof(ht_cap)) || -+ memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { -+ changed |= BSS_CHANGED_HT; -+ memcpy(&conf->ht_cap, &ht_cap, sizeof(ht_cap)); -+ memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); -+ } - -- return 0; -+ return changed; - } - - static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, -@@ -802,7 +909,7 @@ void ieee80211_process_addba_request(str - * check if configuration can support the BA policy - * and if buffer size does not exceeds max value */ - if (((ba_policy != 1) -- && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA))) -+ && (!(conf->ht_cap.cap & IEEE80211_HT_CAP_DELAY_BA))) - || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { - status = WLAN_STATUS_INVALID_QOS_PARAM; - #ifdef CONFIG_MAC80211_HT_DEBUG -@@ -820,7 +927,7 @@ void ieee80211_process_addba_request(str - - sband = local->hw.wiphy->bands[conf->channel->band]; - buf_size = IEEE80211_MIN_AMPDU_BUF; -- buf_size = buf_size << sband->ht_info.ampdu_factor; -+ buf_size = buf_size << sband->ht_cap.ampdu_factor; - } - - ---- everything.orig/net/mac80211/mlme.c 2008-10-08 20:45:06.000000000 +0200 -+++ everything/net/mac80211/mlme.c 2008-10-09 02:16:26.000000000 +0200 -@@ -236,7 +236,7 @@ static void ieee80211_send_assoc(struct - struct ieee80211_local *local = sdata->local; - struct sk_buff *skb; - struct ieee80211_mgmt *mgmt; -- u8 *pos, *ies, *ht_add_ie; -+ u8 *pos, *ies, *ht_ie; - int i, len, count, rates_len, supp_rates_len; - u16 capab; - struct ieee80211_bss *bss; -@@ -393,24 +393,25 @@ static void ieee80211_send_assoc(struct - - /* wmm support is a must to HT */ - if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && -- sband->ht_info.ht_supported && -- (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) { -- struct ieee80211_ht_addt_info *ht_add_info = -- (struct ieee80211_ht_addt_info *)ht_add_ie; -- u16 cap = sband->ht_info.cap; -+ sband->ht_cap.ht_supported && -+ (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) && -+ ht_ie[1] >= sizeof(struct ieee80211_ht_info)) { -+ struct ieee80211_ht_info *ht_info = -+ (struct ieee80211_ht_info *)(ht_ie + 2); -+ u16 cap = sband->ht_cap.cap; - __le16 tmp; - u32 flags = local->hw.conf.channel->flags; - -- switch (ht_add_info->ht_param & IEEE80211_HT_IE_CHA_SEC_OFFSET) { -- case IEEE80211_HT_IE_CHA_SEC_ABOVE: -+ switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { -+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) { -- cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; -+ cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - break; -- case IEEE80211_HT_IE_CHA_SEC_BELOW: -+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - if (flags & IEEE80211_CHAN_NO_FAT_BELOW) { -- cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; -+ cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - cap &= ~IEEE80211_HT_CAP_SGI_40; - } - break; -@@ -424,9 +425,9 @@ static void ieee80211_send_assoc(struct - memcpy(pos, &tmp, sizeof(u16)); - pos += sizeof(u16); - /* TODO: needs a define here for << 2 */ -- *pos++ = sband->ht_info.ampdu_factor | -- (sband->ht_info.ampdu_density << 2); -- memcpy(pos, sband->ht_info.supp_mcs_set, 16); -+ *pos++ = sband->ht_cap.ampdu_factor | -+ (sband->ht_cap.ampdu_density << 2); -+ memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); - } - - kfree(ifsta->assocreq_ies); -@@ -732,7 +733,7 @@ static void ieee80211_set_associated(str - if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { - changed |= BSS_CHANGED_HT; - sdata->bss_conf.assoc_ht = 1; -- sdata->bss_conf.ht_conf = &conf->ht_conf; -+ sdata->bss_conf.ht_cap = &conf->ht_cap; - sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; - } - -@@ -856,7 +857,7 @@ static void ieee80211_set_disassoc(struc - changed |= BSS_CHANGED_HT; - - sdata->bss_conf.assoc_ht = 0; -- sdata->bss_conf.ht_conf = NULL; -+ sdata->bss_conf.ht_cap = NULL; - sdata->bss_conf.ht_bss_conf = NULL; - - ieee80211_led_assoc(local, 0); -@@ -1348,11 +1349,11 @@ static void ieee80211_rx_mgmt_assoc_resp - if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && - (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { - struct ieee80211_ht_bss_info bss_info; -- ieee80211_ht_cap_ie_to_ht_info( -- elems.ht_cap_elem, &sta->sta.ht_info); -- ieee80211_ht_addt_info_ie_to_ht_bss_info( -+ ieee80211_ht_cap_ie_to_sta_ht_cap( -+ elems.ht_cap_elem, &sta->sta.ht_cap); -+ ieee80211_ht_info_ie_to_ht_bss_info( - elems.ht_info_elem, &bss_info); -- ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); -+ ieee80211_handle_ht(local, &sta->sta.ht_cap, &bss_info); - } - - rate_control_rate_init(sta); -@@ -1712,9 +1713,9 @@ static void ieee80211_rx_mgmt_beacon(str - elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { - struct ieee80211_ht_bss_info bss_info; - -- ieee80211_ht_addt_info_ie_to_ht_bss_info( -+ ieee80211_ht_info_ie_to_ht_bss_info( - elems.ht_info_elem, &bss_info); -- changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf, -+ changed |= ieee80211_handle_ht(local, &conf->ht_cap, - &bss_info); - } - ---- everything.orig/net/mac80211/util.c 2008-10-08 20:45:06.000000000 +0200 -+++ everything/net/mac80211/util.c 2008-10-09 02:16:28.000000000 +0200 -@@ -532,8 +532,8 @@ void ieee802_11_parse_elems(u8 *start, s - if (elen >= sizeof(struct ieee80211_ht_cap)) - elems->ht_cap_elem = (void *)pos; - break; -- case WLAN_EID_HT_EXTRA_INFO: -- if (elen >= sizeof(struct ieee80211_ht_addt_info)) -+ case WLAN_EID_HT_INFORMATION: -+ if (elen >= sizeof(struct ieee80211_ht_info)) - elems->ht_info_elem = (void *)pos; - break; - case WLAN_EID_MESH_ID: ---- everything.orig/net/mac80211/cfg.c 2008-10-08 20:45:06.000000000 +0200 -+++ everything/net/mac80211/cfg.c 2008-10-09 02:16:29.000000000 +0200 -@@ -635,10 +635,9 @@ static void sta_apply_parameters(struct - sta->sta.supp_rates[local->oper_channel->band] = rates; - } - -- if (params->ht_capa) { -- ieee80211_ht_cap_ie_to_ht_info(params->ht_capa, -- &sta->sta.ht_info); -- } -+ if (params->ht_capa) -+ ieee80211_ht_cap_ie_to_sta_ht_cap(params->ht_capa, -+ &sta->sta.ht_cap); - - if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { - switch (params->plink_action) { ---- everything.orig/drivers/net/wireless/iwlwifi/iwl-agn-rs.c 2008-10-08 20:44:47.000000000 +0200 -+++ everything/drivers/net/wireless/iwlwifi/iwl-agn-rs.c 2008-10-09 02:16:27.000000000 +0200 -@@ -1136,10 +1136,10 @@ static int rs_switch_to_mimo2(struct iwl - s8 is_green = lq_sta->is_green; - - if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || -- !sta->ht_info.ht_supported) -+ !sta->ht_cap.ht_supported) - return -1; - -- if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2) -+ if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) - == WLAN_HT_CAP_SM_PS_STATIC) - return -1; - -@@ -1204,7 +1204,7 @@ static int rs_switch_to_siso(struct iwl_ - s32 rate; - - if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || -- !sta->ht_info.ht_supported) -+ !sta->ht_cap.ht_supported) - return -1; - - IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); -@@ -2244,19 +2244,19 @@ static void rs_rate_init(void *priv_r, s - * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), - * supp_rates[] does not; shift to convert format, force 9 MBits off. - */ -- lq_sta->active_siso_rate = conf->ht_conf.supp_mcs_set[0] << 1; -- lq_sta->active_siso_rate |= conf->ht_conf.supp_mcs_set[0] & 0x1; -+ lq_sta->active_siso_rate = conf->ht_cap.mcs.rx_mask[0] << 1; -+ lq_sta->active_siso_rate |= conf->ht_cap.mcs.rx_mask[0] & 0x1; - lq_sta->active_siso_rate &= ~((u16)0x2); - lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; - - /* Same here */ -- lq_sta->active_mimo2_rate = conf->ht_conf.supp_mcs_set[1] << 1; -- lq_sta->active_mimo2_rate |= conf->ht_conf.supp_mcs_set[1] & 0x1; -+ lq_sta->active_mimo2_rate = conf->ht_cap.mcs.rx_mask[1] << 1; -+ lq_sta->active_mimo2_rate |= conf->ht_cap.mcs.rx_mask[1] & 0x1; - lq_sta->active_mimo2_rate &= ~((u16)0x2); - lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; - -- lq_sta->active_mimo3_rate = conf->ht_conf.supp_mcs_set[2] << 1; -- lq_sta->active_mimo3_rate |= conf->ht_conf.supp_mcs_set[2] & 0x1; -+ lq_sta->active_mimo3_rate = conf->ht_cap.mcs.rx_mask[2] << 1; -+ lq_sta->active_mimo3_rate |= conf->ht_cap.mcs.rx_mask[2] & 0x1; - lq_sta->active_mimo3_rate &= ~((u16)0x2); - lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; - ---- everything.orig/drivers/net/wireless/iwlwifi/iwl-agn.c 2008-10-08 20:44:48.000000000 +0200 -+++ everything/drivers/net/wireless/iwlwifi/iwl-agn.c 2008-10-09 02:16:29.000000000 +0200 -@@ -553,7 +553,7 @@ static int iwl4965_send_beacon_cmd(struc - static void iwl4965_ht_conf(struct iwl_priv *priv, - struct ieee80211_bss_conf *bss_conf) - { -- struct ieee80211_ht_info *ht_conf = bss_conf->ht_conf; -+ struct ieee80211_sta_ht_cap *ht_conf = bss_conf->ht_cap; - struct ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf; - struct iwl_ht_info *iwl_conf = &priv->current_ht_config; - -@@ -574,27 +574,27 @@ static void iwl4965_ht_conf(struct iwl_p - !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); - - iwl_conf->supported_chan_width = -- !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH); -+ !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); - iwl_conf->extension_chan_offset = -- ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET; -+ ht_bss_conf->bss_cap & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; - /* If no above or below channel supplied disable FAT channel */ -- if (iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_ABOVE && -- iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_BELOW) { -- iwl_conf->extension_chan_offset = IEEE80211_HT_IE_CHA_SEC_NONE; -+ if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && -+ iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) { -+ iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; - iwl_conf->supported_chan_width = 0; - } - - iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); - -- memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16); -+ memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); - - iwl_conf->control_channel = ht_bss_conf->primary_channel; - iwl_conf->tx_chan_width = -- !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH); -+ !!(ht_bss_conf->bss_cap & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY); - iwl_conf->ht_protection = -- ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION; -+ ht_bss_conf->bss_op_mode & IEEE80211_HT_OP_MODE_PROTECTION; - iwl_conf->non_GF_STA_present = -- !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT); -+ !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); - - IWL_DEBUG_MAC80211("control channel %d\n", iwl_conf->control_channel); - IWL_DEBUG_MAC80211("leave\n"); ---- everything.orig/drivers/net/wireless/iwlwifi/iwl-core.c 2008-10-08 20:44:47.000000000 +0200 -+++ everything/drivers/net/wireless/iwlwifi/iwl-core.c 2008-10-09 02:16:26.000000000 +0200 -@@ -382,10 +382,10 @@ void iwl_reset_qos(struct iwl_priv *priv - } - EXPORT_SYMBOL(iwl_reset_qos); - --#define MAX_BIT_RATE_40_MHZ 0x96 /* 150 Mbps */ --#define MAX_BIT_RATE_20_MHZ 0x48 /* 72 Mbps */ -+#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ -+#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ - static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, -- struct ieee80211_ht_info *ht_info, -+ struct ieee80211_sta_ht_cap *ht_info, - enum ieee80211_band band) - { - u16 max_bit_rate = 0; -@@ -393,45 +393,46 @@ static void iwlcore_init_ht_hw_capab(con - u8 tx_chains_num = priv->hw_params.tx_chains_num; - - ht_info->cap = 0; -- memset(ht_info->supp_mcs_set, 0, 16); -+ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - -- ht_info->ht_supported = 1; -+ ht_info->ht_supported = true; - -- ht_info->cap |= (u16)IEEE80211_HT_CAP_GRN_FLD; -- ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20; -- ht_info->cap |= (u16)(IEEE80211_HT_CAP_SM_PS & -+ ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; -+ ht_info->cap |= IEEE80211_HT_CAP_SGI_20; -+ ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & - (WLAN_HT_CAP_SM_PS_DISABLED << 2)); - - max_bit_rate = MAX_BIT_RATE_20_MHZ; - if (priv->hw_params.fat_channel & BIT(band)) { -- ht_info->cap |= (u16)IEEE80211_HT_CAP_SUP_WIDTH; -- ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_40; -- ht_info->supp_mcs_set[4] = 0x01; -+ ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; -+ ht_info->cap |= IEEE80211_HT_CAP_SGI_40; -+ ht_info->mcs.rx_mask[4] = 0x01; - max_bit_rate = MAX_BIT_RATE_40_MHZ; - } - - if (priv->cfg->mod_params->amsdu_size_8K) -- ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU; -+ ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; - - ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; - ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; - -- ht_info->supp_mcs_set[0] = 0xFF; -+ ht_info->mcs.rx_mask[0] = 0xFF; - if (rx_chains_num >= 2) -- ht_info->supp_mcs_set[1] = 0xFF; -+ ht_info->mcs.rx_mask[1] = 0xFF; - if (rx_chains_num >= 3) -- ht_info->supp_mcs_set[2] = 0xFF; -+ ht_info->mcs.rx_mask[2] = 0xFF; - - /* Highest supported Rx data rate */ - max_bit_rate *= rx_chains_num; -- ht_info->supp_mcs_set[10] = (u8)(max_bit_rate & 0x00FF); -- ht_info->supp_mcs_set[11] = (u8)((max_bit_rate & 0xFF00) >> 8); -+ WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); -+ ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); - - /* Tx MCS capabilities */ -- ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED; -+ ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - if (tx_chains_num != rx_chains_num) { -- ht_info->supp_mcs_set[12] |= IEEE80211_HT_CAP_MCS_TX_RX_DIFF; -- ht_info->supp_mcs_set[12] |= ((tx_chains_num - 1) << 2); -+ ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; -+ ht_info->mcs.tx_params |= ((tx_chains_num - 1) << -+ IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); - } - } - -@@ -495,7 +496,7 @@ static int iwlcore_init_geos(struct iwl_ - sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; - - if (priv->cfg->sku & IWL_SKU_N) -- iwlcore_init_ht_hw_capab(priv, &sband->ht_info, -+ iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, - IEEE80211_BAND_5GHZ); - - sband = &priv->bands[IEEE80211_BAND_2GHZ]; -@@ -505,7 +506,7 @@ static int iwlcore_init_geos(struct iwl_ - sband->n_bitrates = IWL_RATE_COUNT; - - if (priv->cfg->sku & IWL_SKU_N) -- iwlcore_init_ht_hw_capab(priv, &sband->ht_info, -+ iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, - IEEE80211_BAND_2GHZ); - - priv->ieee_channels = channels; -@@ -595,8 +596,8 @@ static void iwlcore_free_geos(struct iwl - static bool is_single_rx_stream(struct iwl_priv *priv) - { - return !priv->current_ht_config.is_ht || -- ((priv->current_ht_config.supp_mcs_set[1] == 0) && -- (priv->current_ht_config.supp_mcs_set[2] == 0)); -+ ((priv->current_ht_config.mcs.rx_mask[1] == 0) && -+ (priv->current_ht_config.mcs.rx_mask[2] == 0)); - } - - static u8 iwl_is_channel_extension(struct iwl_priv *priv, -@@ -609,10 +610,10 @@ static u8 iwl_is_channel_extension(struc - if (!is_channel_valid(ch_info)) - return 0; - -- if (extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) -+ if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) - return !(ch_info->fat_extension_channel & - IEEE80211_CHAN_NO_FAT_ABOVE); -- else if (extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) -+ else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) - return !(ch_info->fat_extension_channel & - IEEE80211_CHAN_NO_FAT_BELOW); - -@@ -620,18 +621,18 @@ static u8 iwl_is_channel_extension(struc - } - - u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, -- struct ieee80211_ht_info *sta_ht_inf) -+ struct ieee80211_sta_ht_cap *sta_ht_inf) - { - struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config; - - if ((!iwl_ht_conf->is_ht) || - (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) || -- (iwl_ht_conf->extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE)) -+ (iwl_ht_conf->extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE)) - return 0; - - if (sta_ht_inf) { - if ((!sta_ht_inf->ht_supported) || -- (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH))) -+ (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))) - return 0; - } - -@@ -671,13 +672,13 @@ void iwl_set_rxon_ht(struct iwl_priv *pr - - /* Note: control channel is opposite of extension channel */ - switch (ht_info->extension_chan_offset) { -- case IEEE80211_HT_IE_CHA_SEC_ABOVE: -+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); - break; -- case IEEE80211_HT_IE_CHA_SEC_BELOW: -+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; - break; -- case IEEE80211_HT_IE_CHA_SEC_NONE: -+ case IEEE80211_HT_PARAM_CHA_SEC_NONE: - default: - rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK; - break; -@@ -693,9 +694,9 @@ void iwl_set_rxon_ht(struct iwl_priv *pr - "rxon flags 0x%X operation mode :0x%X " - "extension channel offset 0x%x " - "control chan %d\n", -- ht_info->supp_mcs_set[0], -- ht_info->supp_mcs_set[1], -- ht_info->supp_mcs_set[2], -+ ht_info->mcs.rx_mask[0], -+ ht_info->mcs.rx_mask[1], -+ ht_info->mcs.rx_mask[2], - le32_to_cpu(rxon->flags), ht_info->ht_protection, - ht_info->extension_chan_offset, - ht_info->control_channel); ---- everything.orig/drivers/net/wireless/iwlwifi/iwl-core.h 2008-10-08 20:44:47.000000000 +0200 -+++ everything/drivers/net/wireless/iwlwifi/iwl-core.h 2008-10-08 20:45:06.000000000 +0200 -@@ -190,7 +190,7 @@ void iwl_set_rxon_chain(struct iwl_priv - int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); - void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info); - u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, -- struct ieee80211_ht_info *sta_ht_inf); -+ struct ieee80211_sta_ht_cap *sta_ht_inf); - int iwl_hw_nic_init(struct iwl_priv *priv); - int iwl_setup_mac(struct iwl_priv *priv); - int iwl_set_hw_params(struct iwl_priv *priv); ---- everything.orig/drivers/net/wireless/iwlwifi/iwl-dev.h 2008-10-08 20:44:47.000000000 +0200 -+++ everything/drivers/net/wireless/iwlwifi/iwl-dev.h 2008-10-09 02:16:27.000000000 +0200 -@@ -412,7 +412,7 @@ struct iwl_ht_info { - u8 max_amsdu_size; - u8 ampdu_factor; - u8 mpdu_density; -- u8 supp_mcs_set[16]; -+ struct ieee80211_mcs_info mcs; - /* BSS related data */ - u8 control_channel; - u8 extension_chan_offset; -@@ -584,7 +584,7 @@ struct iwl_addsta_cmd; - extern int iwl_send_add_sta(struct iwl_priv *priv, - struct iwl_addsta_cmd *sta, u8 flags); - extern u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, -- int is_ap, u8 flags, struct ieee80211_ht_info *ht_info); -+ int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info); - extern void iwl4965_update_chain_flags(struct iwl_priv *priv); - extern int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src); - extern const u8 iwl_bcast_addr[ETH_ALEN]; ---- everything.orig/drivers/net/wireless/iwlwifi/iwl-sta.c 2008-10-08 20:44:47.000000000 +0200 -+++ everything/drivers/net/wireless/iwlwifi/iwl-sta.c 2008-10-09 02:16:29.000000000 +0200 -@@ -183,7 +183,7 @@ int iwl_send_add_sta(struct iwl_priv *pr - EXPORT_SYMBOL(iwl_send_add_sta); - - static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, -- struct ieee80211_ht_info *sta_ht_inf) -+ struct ieee80211_sta_ht_cap *sta_ht_inf) - { - __le32 sta_flags; - u8 mimo_ps_mode; -@@ -231,7 +231,7 @@ static void iwl_set_ht_add_station(struc - * iwl_add_station_flags - Add station to tables in driver and device - */ - u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, -- u8 flags, struct ieee80211_ht_info *ht_info) -+ u8 flags, struct ieee80211_sta_ht_cap *ht_info) - { - int i; - int sta_id = IWL_INVALID_STATION; -@@ -900,7 +900,7 @@ int iwl_rxon_add_station(struct iwl_priv - - /* Add station to device's station table */ - struct ieee80211_conf *conf = &priv->hw->conf; -- struct ieee80211_ht_info *cur_ht_config = &conf->ht_conf; -+ struct ieee80211_sta_ht_cap *cur_ht_config = &conf->ht_cap; - - if ((is_ap) && - (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && ---- everything.orig/drivers/net/wireless/iwlwifi/iwl-scan.c 2008-10-08 20:44:47.000000000 +0200 -+++ everything/drivers/net/wireless/iwlwifi/iwl-scan.c 2008-10-08 20:45:06.000000000 +0200 -@@ -550,7 +550,7 @@ static void iwl_ht_cap_to_ie(const struc - { - struct ieee80211_ht_cap *ht_cap; - -- if (!sband || !sband->ht_info.ht_supported) -+ if (!sband || !sband->ht_cap.ht_supported) - return; - - if (*left < sizeof(struct ieee80211_ht_cap)) -@@ -559,12 +559,12 @@ static void iwl_ht_cap_to_ie(const struc - *pos++ = sizeof(struct ieee80211_ht_cap); - ht_cap = (struct ieee80211_ht_cap *) pos; - -- ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap); -- memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16); -+ ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap); -+ memcpy(&ht_cap->mcs, &sband->ht_cap.mcs, 16); - ht_cap->ampdu_params_info = -- (sband->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) | -- ((sband->ht_info.ampdu_density << 2) & -- IEEE80211_HT_CAP_AMPDU_DENSITY); -+ (sband->ht_cap.ampdu_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) | -+ ((sband->ht_cap.ampdu_density << 2) & -+ IEEE80211_HT_AMPDU_PARM_DENSITY); - *left -= sizeof(struct ieee80211_ht_cap); - } - ---- everything.orig/drivers/net/wireless/ath9k/main.c 2008-10-08 20:44:48.000000000 +0200 -+++ everything/drivers/net/wireless/ath9k/main.c 2008-10-09 02:16:30.000000000 +0200 -@@ -61,24 +61,24 @@ static u32 ath_get_extchanmode(struct at - - switch (chan->band) { - case IEEE80211_BAND_2GHZ: -- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) && -+ if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) && - (tx_chan_width == ATH9K_HT_MACMODE_20)) - chanmode = CHANNEL_G_HT20; -- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) && -+ if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) && - (tx_chan_width == ATH9K_HT_MACMODE_2040)) - chanmode = CHANNEL_G_HT40PLUS; -- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) && -+ if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) && - (tx_chan_width == ATH9K_HT_MACMODE_2040)) - chanmode = CHANNEL_G_HT40MINUS; - break; - case IEEE80211_BAND_5GHZ: -- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) && -+ if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) && - (tx_chan_width == ATH9K_HT_MACMODE_20)) - chanmode = CHANNEL_A_HT20; -- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) && -+ if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) && - (tx_chan_width == ATH9K_HT_MACMODE_2040)) - chanmode = CHANNEL_A_HT40PLUS; -- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) && -+ if ((ext_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) && - (tx_chan_width == ATH9K_HT_MACMODE_2040)) - chanmode = CHANNEL_A_HT40MINUS; - break; -@@ -215,24 +215,24 @@ static void ath_key_delete(struct ath_so - ath_key_reset(sc, key->keyidx, freeslot); - } - --static void setup_ht_cap(struct ieee80211_ht_info *ht_info) -+static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info) - { - #define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */ - #define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */ - -- ht_info->ht_supported = 1; -- ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH -- |(u16)IEEE80211_HT_CAP_SM_PS -- |(u16)IEEE80211_HT_CAP_SGI_40 -- |(u16)IEEE80211_HT_CAP_DSSSCCK40; -+ ht_info->ht_supported = true; -+ ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | -+ IEEE80211_HT_CAP_SM_PS | -+ IEEE80211_HT_CAP_SGI_40 | -+ IEEE80211_HT_CAP_DSSSCCK40; - - ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536; - ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8; -- /* setup supported mcs set */ -- memset(ht_info->supp_mcs_set, 0, 16); -- ht_info->supp_mcs_set[0] = 0xff; -- ht_info->supp_mcs_set[1] = 0xff; -- ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED; -+ /* set up supported mcs set */ -+ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); -+ ht_info->mcs.rx_mask[0] = 0xff; -+ ht_info->mcs.rx_mask[1] = 0xff; -+ ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - } - - static int ath_rate2idx(struct ath_softc *sc, int rate) -@@ -328,31 +328,28 @@ static u8 parse_mpdudensity(u8 mpdudensi - static void ath9k_ht_conf(struct ath_softc *sc, - struct ieee80211_bss_conf *bss_conf) - { --#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14) - struct ath_ht_info *ht_info = &sc->sc_ht_info; - - if (bss_conf->assoc_ht) { - ht_info->ext_chan_offset = - bss_conf->ht_bss_conf->bss_cap & -- IEEE80211_HT_IE_CHA_SEC_OFFSET; -+ IEEE80211_HT_PARAM_CHA_SEC_OFFSET; - -- if (!(bss_conf->ht_conf->cap & -+ if (!(bss_conf->ht_cap->cap & - IEEE80211_HT_CAP_40MHZ_INTOLERANT) && - (bss_conf->ht_bss_conf->bss_cap & -- IEEE80211_HT_IE_CHA_WIDTH)) -+ IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) - ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040; - else - ht_info->tx_chan_width = ATH9K_HT_MACMODE_20; - - ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width); - ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + -- bss_conf->ht_conf->ampdu_factor); -+ bss_conf->ht_cap->ampdu_factor); - ht_info->mpdudensity = -- parse_mpdudensity(bss_conf->ht_conf->ampdu_density); -+ parse_mpdudensity(bss_conf->ht_cap->ampdu_density); - - } -- --#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT - } - - static void ath9k_bss_assoc_info(struct ath_softc *sc, -@@ -412,7 +409,7 @@ static void ath9k_bss_assoc_info(struct - return; - } - -- if (hw->conf.ht_conf.ht_supported) -+ if (hw->conf.ht_cap.ht_supported) - sc->sc_ah->ah_channels[pos].chanmode = - ath_get_extchanmode(sc, curchan); - else -@@ -535,7 +532,7 @@ int _ath_rx_indicate(struct ath_softc *s - - if (an) { - ath_rx_input(sc, an, -- hw->conf.ht_conf.ht_supported, -+ hw->conf.ht_cap.ht_supported, - skb, status, &st); - } - if (!an || (st != ATH_RX_CONSUMED)) -@@ -944,7 +941,7 @@ static int ath_attach(u16 devid, - - if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) - /* Setup HT capabilities for 2.4Ghz*/ -- setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info); -+ setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); - - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &sc->sbands[IEEE80211_BAND_2GHZ]; -@@ -959,7 +956,7 @@ static int ath_attach(u16 devid, - - if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) - /* Setup HT capabilities for 5Ghz*/ -- setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info); -+ setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); - - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &sc->sbands[IEEE80211_BAND_5GHZ]; -@@ -1255,7 +1252,7 @@ static int ath9k_config(struct ieee80211 - (curchan->band == IEEE80211_BAND_2GHZ) ? - CHANNEL_G : CHANNEL_A; - -- if (sc->sc_curaid && hw->conf.ht_conf.ht_supported) -+ if (sc->sc_curaid && hw->conf.ht_cap.ht_supported) - sc->sc_ah->ah_channels[pos].chanmode = - ath_get_extchanmode(sc, curchan); - ---- everything.orig/drivers/net/wireless/ath9k/rc.c 2008-10-08 20:44:48.000000000 +0200 -+++ everything/drivers/net/wireless/ath9k/rc.c 2008-10-09 02:16:27.000000000 +0200 -@@ -1838,7 +1838,7 @@ void ath_rc_node_update(struct ieee80211 - struct ath_softc *sc = hw->priv; - u32 capflag = 0; - -- if (hw->conf.ht_conf.ht_supported) { -+ if (hw->conf.ht_cap.ht_supported) { - capflag |= ATH_RC_HT_FLAG | ATH_RC_DS_FLAG; - if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040) - capflag |= ATH_RC_CW40_FLAG; -@@ -1910,7 +1910,7 @@ static void ath_tx_aggr_resp(struct ath_ - */ - si = container_of(sta, struct sta_info, sta); - buffersize = IEEE80211_MIN_AMPDU_BUF << -- sband->ht_info.ampdu_factor; /* FIXME */ -+ sband->ht_cap.ampdu_factor; /* FIXME */ - state = si->ampdu_mlme.tid_state_tx[tidno]; - - if (state & HT_ADDBA_RECEIVED_MSK) { -@@ -1980,7 +1980,7 @@ static void ath_get_rate(void *priv, str - - /* Check if aggregation has to be enabled for this tid */ - -- if (hw->conf.ht_conf.ht_supported) { -+ if (hw->conf.ht_cap.ht_supported) { - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; -@@ -2028,8 +2028,8 @@ static void ath_rate_init(void *priv, st - - ath_setup_rates(sc, sband, sta, ath_rc_priv); - if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) { -- for (i = 0; i < MCS_SET_SIZE; i++) { -- if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8))) -+ for (i = 0; i < 77; i++) { -+ if (sc->hw->conf.ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) - ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; - if (j == ATH_RATE_MAX) - break; ---- everything.orig/drivers/net/wireless/ath9k/recv.c 2008-10-08 20:44:48.000000000 +0200 -+++ everything/drivers/net/wireless/ath9k/recv.c 2008-10-09 02:16:27.000000000 +0200 -@@ -1119,7 +1119,7 @@ int ath_rx_aggr_start(struct ath_softc * - - sband = hw->wiphy->bands[hw->conf.channel->band]; - buffersize = IEEE80211_MIN_AMPDU_BUF << -- sband->ht_info.ampdu_factor; /* FIXME */ -+ sband->ht_cap.ampdu_factor; /* FIXME */ - - rxtid = &an->an_aggr.rx.tid[tid]; - ---- everything.orig/drivers/net/wireless/ath9k/xmit.c 2008-10-08 20:44:48.000000000 +0200 -+++ everything/drivers/net/wireless/ath9k/xmit.c 2008-10-09 02:16:27.000000000 +0200 -@@ -300,7 +300,7 @@ static int ath_tx_prepare(struct ath_sof - if (ieee80211_is_data(fc) && !txctl->use_minrate) { - - /* Enable HT only for DATA frames and not for EAPOL */ -- txctl->ht = (hw->conf.ht_conf.ht_supported && -+ txctl->ht = (hw->conf.ht_cap.ht_supported && - (tx_info->flags & IEEE80211_TX_CTL_AMPDU)); - - if (is_multicast_ether_addr(hdr->addr1)) { ---- everything.orig/drivers/net/wireless/ath9k/rc.h 2008-10-08 20:44:48.000000000 +0200 -+++ everything/drivers/net/wireless/ath9k/rc.h 2008-10-08 20:45:06.000000000 +0200 -@@ -59,7 +59,6 @@ struct ath_softc; - #define FALSE 0 - - #define ATH_RATE_MAX 30 --#define MCS_SET_SIZE 128 - - enum ieee80211_fixed_rate_mode { - IEEE80211_FIXED_RATE_NONE = 0, ---- everything.orig/drivers/net/wireless/mac80211_hwsim.c 2008-10-08 20:44:48.000000000 +0200 -+++ everything/drivers/net/wireless/mac80211_hwsim.c 2008-10-09 02:16:30.000000000 +0200 -@@ -566,19 +566,18 @@ static int __init init_mac80211_hwsim(vo - data->band.n_channels = ARRAY_SIZE(hwsim_channels); - data->band.bitrates = data->rates; - data->band.n_bitrates = ARRAY_SIZE(hwsim_rates); -- data->band.ht_info.ht_supported = 1; -- data->band.ht_info.cap = IEEE80211_HT_CAP_SUP_WIDTH | -+ data->band.ht_cap.ht_supported = true; -+ data->band.ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_GRN_FLD | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_DSSSCCK40; -- data->band.ht_info.ampdu_factor = 0x3; -- data->band.ht_info.ampdu_density = 0x6; -- memset(data->band.ht_info.supp_mcs_set, 0, -- sizeof(data->band.ht_info.supp_mcs_set)); -- data->band.ht_info.supp_mcs_set[0] = 0xff; -- data->band.ht_info.supp_mcs_set[1] = 0xff; -- data->band.ht_info.supp_mcs_set[12] = -- IEEE80211_HT_CAP_MCS_TX_DEFINED; -+ data->band.ht_cap.ampdu_factor = 0x3; -+ data->band.ht_cap.ampdu_density = 0x6; -+ memset(&data->band.ht_cap.mcs, 0, -+ sizeof(data->band.ht_cap.mcs)); -+ data->band.ht_cap.mcs.rx_mask[0] = 0xff; -+ data->band.ht_cap.mcs.rx_mask[1] = 0xff; -+ data->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band; - - err = ieee80211_register_hw(hw); diff --git a/package/mac80211/patches/419-mac80211-remove-antenna-sel.patch b/package/mac80211/patches/419-mac80211-remove-antenna-sel.patch deleted file mode 100644 index dbdd64aa23..0000000000 --- a/package/mac80211/patches/419-mac80211-remove-antenna-sel.patch +++ /dev/null @@ -1,259 +0,0 @@ -Subject: mac80211: kill hw.conf.antenna_sel_{rx,tx} - -Never actually used. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - drivers/net/wireless/b43/main.c | 25 +++---------------------- - drivers/net/wireless/b43legacy/main.c | 18 ++---------------- - drivers/net/wireless/p54/p54common.c | 3 +-- - drivers/net/wireless/rt2x00/rt2x00config.c | 20 ++++---------------- - drivers/net/wireless/rt2x00/rt2x00dev.c | 6 ++---- - include/net/mac80211.h | 7 +------ - net/mac80211/debugfs.c | 8 -------- - net/mac80211/ieee80211_i.h | 2 -- - net/mac80211/tx.c | 1 - - 9 files changed, 13 insertions(+), 77 deletions(-) - ---- everything.orig/net/mac80211/debugfs.c 2008-10-08 22:35:20.000000000 +0200 -+++ everything/net/mac80211/debugfs.c 2008-10-08 22:35:26.000000000 +0200 -@@ -47,10 +47,6 @@ static const struct file_operations name - - DEBUGFS_READONLY_FILE(frequency, 20, "%d", - local->hw.conf.channel->center_freq); --DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d", -- local->hw.conf.antenna_sel_tx); --DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d", -- local->hw.conf.antenna_sel_rx); - DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", - local->rts_threshold); - DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", -@@ -202,8 +198,6 @@ void debugfs_hw_add(struct ieee80211_loc - local->debugfs.keys = debugfs_create_dir("keys", phyd); - - DEBUGFS_ADD(frequency); -- DEBUGFS_ADD(antenna_sel_tx); -- DEBUGFS_ADD(antenna_sel_rx); - DEBUGFS_ADD(rts_threshold); - DEBUGFS_ADD(fragmentation_threshold); - DEBUGFS_ADD(short_retry_limit); -@@ -258,8 +252,6 @@ void debugfs_hw_add(struct ieee80211_loc - void debugfs_hw_del(struct ieee80211_local *local) - { - DEBUGFS_DEL(frequency); -- DEBUGFS_DEL(antenna_sel_tx); -- DEBUGFS_DEL(antenna_sel_rx); - DEBUGFS_DEL(rts_threshold); - DEBUGFS_DEL(fragmentation_threshold); - DEBUGFS_DEL(short_retry_limit); ---- everything.orig/net/mac80211/ieee80211_i.h 2008-10-08 22:35:01.000000000 +0200 -+++ everything/net/mac80211/ieee80211_i.h 2008-10-08 22:35:10.000000000 +0200 -@@ -727,8 +727,6 @@ struct ieee80211_local { - struct dentry *rcdir; - struct dentry *rcname; - struct dentry *frequency; -- struct dentry *antenna_sel_tx; -- struct dentry *antenna_sel_rx; - struct dentry *rts_threshold; - struct dentry *fragmentation_threshold; - struct dentry *short_retry_limit; ---- everything.orig/include/net/mac80211.h 2008-10-08 22:35:30.000000000 +0200 -+++ everything/include/net/mac80211.h 2008-10-08 22:39:56.000000000 +0200 -@@ -324,7 +324,7 @@ struct ieee80211_tx_altrate { - * @flags: transmit info flags, defined above - * @band: TBD - * @tx_rate_idx: TBD -- * @antenna_sel_tx: TBD -+ * @antenna_sel_tx: antenna to use, 0 for automatic diversity - * @control: union for control data - * @status: union for status data - * @driver_data: array of driver_data pointers -@@ -474,9 +474,6 @@ static inline int __deprecated __IEEE802 - * @listen_interval: listen interval in units of beacon interval - * @flags: configuration flags defined above - * @power_level: requested transmit power (in dBm) -- * @antenna_sel_tx: transmit antenna selection, 0: default/diversity, -- * 1/2: antenna 0/1 -- * @antenna_sel_rx: receive antenna selection, like @antenna_sel_tx - * @ht_cap: describes current self configuration of 802.11n HT capabilities - * @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters - * @channel: the channel to tune to -@@ -488,8 +485,6 @@ struct ieee80211_conf { - u16 listen_interval; - u32 flags; - int power_level; -- u8 antenna_sel_tx; -- u8 antenna_sel_rx; - - struct ieee80211_channel *channel; - ---- everything.orig/net/mac80211/tx.c 2008-10-08 22:37:05.000000000 +0200 -+++ everything/net/mac80211/tx.c 2008-10-08 22:37:22.000000000 +0200 -@@ -1975,7 +1975,6 @@ struct sk_buff *ieee80211_beacon_get(str - sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) - info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; - -- info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; - info->control.retry_limit = 1; - - out: ---- everything.orig/drivers/net/wireless/b43/main.c 2008-10-08 22:40:06.000000000 +0200 -+++ everything/drivers/net/wireless/b43/main.c 2008-10-08 22:40:45.000000000 +0200 -@@ -1339,25 +1339,6 @@ u8 b43_ieee80211_antenna_sanitize(struct - return antenna_nr; - } - --static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna) --{ -- antenna = b43_ieee80211_antenna_sanitize(dev, antenna); -- switch (antenna) { -- case 0: /* default/diversity */ -- return B43_ANTENNA_DEFAULT; -- case 1: /* Antenna 0 */ -- return B43_ANTENNA0; -- case 2: /* Antenna 1 */ -- return B43_ANTENNA1; -- case 3: /* Antenna 2 */ -- return B43_ANTENNA2; -- case 4: /* Antenna 3 */ -- return B43_ANTENNA3; -- default: -- return B43_ANTENNA_DEFAULT; -- } --} -- - /* Convert a b43 antenna number value to the PHY TX control value. */ - static u16 b43_antenna_to_phyctl(int antenna) - { -@@ -1399,7 +1380,7 @@ static void b43_write_beacon_template(st - len, ram_offset, shm_size_offset, rate); - - /* Write the PHY TX control parameters. */ -- antenna = b43_antenna_from_ieee80211(dev, info->antenna_sel_tx); -+ antenna = B43_ANTENNA_DEFAULT; - antenna = b43_antenna_to_phyctl(antenna); - ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); - /* We can't send beacons with short preamble. Would get PHY errors. */ -@@ -3399,9 +3380,9 @@ static int b43_op_config(struct ieee8021 - } - - /* Antennas for RX and management frame TX. */ -- antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx); -+ antenna = B43_ANTENNA_DEFAULT; - b43_mgmtframe_txantenna(dev, antenna); -- antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx); -+ antenna = B43_ANTENNA_DEFAULT; - if (phy->ops->set_rx_antenna) - phy->ops->set_rx_antenna(dev, antenna); - ---- everything.orig/drivers/net/wireless/b43legacy/main.c 2008-10-08 22:41:36.000000000 +0200 -+++ everything/drivers/net/wireless/b43legacy/main.c 2008-10-08 22:41:59.000000000 +0200 -@@ -2556,20 +2556,6 @@ init_failure: - return err; - } - --static int b43legacy_antenna_from_ieee80211(u8 antenna) --{ -- switch (antenna) { -- case 0: /* default/diversity */ -- return B43legacy_ANTENNA_DEFAULT; -- case 1: /* Antenna 0 */ -- return B43legacy_ANTENNA0; -- case 2: /* Antenna 1 */ -- return B43legacy_ANTENNA1; -- default: -- return B43legacy_ANTENNA_DEFAULT; -- } --} -- - static int b43legacy_op_dev_config(struct ieee80211_hw *hw, - struct ieee80211_conf *conf) - { -@@ -2583,8 +2569,8 @@ static int b43legacy_op_dev_config(struc - int err = 0; - u32 savedirqs; - -- antenna_tx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_tx); -- antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx); -+ antenna_tx = B43legacy_ANTENNA_DEFAULT; -+ antenna_rx = B43legacy_ANTENNA_DEFAULT; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; ---- everything.orig/drivers/net/wireless/p54/p54common.c 2008-10-08 22:43:54.000000000 +0200 -+++ everything/drivers/net/wireless/p54/p54common.c 2008-10-08 22:44:12.000000000 +0200 -@@ -1211,8 +1211,7 @@ static int p54_config(struct ieee80211_h - struct p54_common *priv = dev->priv; - - mutex_lock(&priv->conf_mutex); -- priv->rx_antenna = (conf->antenna_sel_rx == 0) ? -- 2 : conf->antenna_sel_tx - 1; -+ priv->rx_antenna = 2; /* automatic */ - priv->output_power = conf->power_level << 2; - ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq)); - p54_set_vdcf(dev); ---- everything.orig/drivers/net/wireless/rt2x00/rt2x00config.c 2008-10-08 22:44:57.000000000 +0200 -+++ everything/drivers/net/wireless/rt2x00/rt2x00config.c 2008-10-08 22:45:36.000000000 +0200 -@@ -199,23 +199,15 @@ void rt2x00lib_config(struct rt2x00_dev - * to work with untill the link tuner decides that an antenna - * switch should be performed. - */ -- if (!conf->antenna_sel_rx && -- default_ant->rx != ANTENNA_SW_DIVERSITY && -+ if (default_ant->rx != ANTENNA_SW_DIVERSITY && - default_ant->rx != active_ant->rx) - flags |= CONFIG_UPDATE_ANTENNA; -- else if (conf->antenna_sel_rx && -- conf->antenna_sel_rx != active_ant->rx) -- flags |= CONFIG_UPDATE_ANTENNA; - else if (active_ant->rx == ANTENNA_SW_DIVERSITY) - flags |= CONFIG_UPDATE_ANTENNA; - -- if (!conf->antenna_sel_tx && -- default_ant->tx != ANTENNA_SW_DIVERSITY && -+ if (default_ant->tx != ANTENNA_SW_DIVERSITY && - default_ant->tx != active_ant->tx) - flags |= CONFIG_UPDATE_ANTENNA; -- else if (conf->antenna_sel_tx && -- conf->antenna_sel_tx != active_ant->tx) -- flags |= CONFIG_UPDATE_ANTENNA; - else if (active_ant->tx == ANTENNA_SW_DIVERSITY) - flags |= CONFIG_UPDATE_ANTENNA; - -@@ -252,18 +244,14 @@ config: - } - - if (flags & CONFIG_UPDATE_ANTENNA) { -- if (conf->antenna_sel_rx) -- libconf.ant.rx = conf->antenna_sel_rx; -- else if (default_ant->rx != ANTENNA_SW_DIVERSITY) -+ if (default_ant->rx != ANTENNA_SW_DIVERSITY) - libconf.ant.rx = default_ant->rx; - else if (active_ant->rx == ANTENNA_SW_DIVERSITY) - libconf.ant.rx = ANTENNA_B; - else - libconf.ant.rx = active_ant->rx; - -- if (conf->antenna_sel_tx) -- libconf.ant.tx = conf->antenna_sel_tx; -- else if (default_ant->tx != ANTENNA_SW_DIVERSITY) -+ if (default_ant->tx != ANTENNA_SW_DIVERSITY) - libconf.ant.tx = default_ant->tx; - else if (active_ant->tx == ANTENNA_SW_DIVERSITY) - libconf.ant.tx = ANTENNA_B; ---- everything.orig/drivers/net/wireless/rt2x00/rt2x00dev.c 2008-10-08 22:44:28.000000000 +0200 -+++ everything/drivers/net/wireless/rt2x00/rt2x00dev.c 2008-10-08 22:44:43.000000000 +0200 -@@ -249,11 +249,9 @@ static void rt2x00lib_evaluate_antenna(s - rt2x00dev->link.ant.flags &= ~ANTENNA_RX_DIVERSITY; - rt2x00dev->link.ant.flags &= ~ANTENNA_TX_DIVERSITY; - -- if (rt2x00dev->hw->conf.antenna_sel_rx == 0 && -- rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) -+ if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) - rt2x00dev->link.ant.flags |= ANTENNA_RX_DIVERSITY; -- if (rt2x00dev->hw->conf.antenna_sel_tx == 0 && -- rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) -+ if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) - rt2x00dev->link.ant.flags |= ANTENNA_TX_DIVERSITY; - - if (!(rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) && diff --git a/package/mac80211/patches/420-mac80211-hw-conf-change-flags.patch b/package/mac80211/patches/420-mac80211-hw-conf-change-flags.patch deleted file mode 100644 index 4bae8cbb59..0000000000 --- a/package/mac80211/patches/420-mac80211-hw-conf-change-flags.patch +++ /dev/null @@ -1,616 +0,0 @@ -Subject: mac80211: introduce hw config change flags - -This makes mac80211 notify the driver which configuration -actually changed, e.g. channel etc. - -No driver changes, this is just plumbing, driver authors are -expected to act on this if they want to. - -Also remove the HW CONFIG debug printk, it's incorrect, often -we configure something else. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - drivers/net/wireless/adm8211.c | 3 +- - drivers/net/wireless/at76_usb.c | 3 +- - drivers/net/wireless/ath5k/base.c | 7 ++---- - drivers/net/wireless/ath9k/main.c | 4 +-- - drivers/net/wireless/b43/main.c | 3 +- - drivers/net/wireless/b43legacy/main.c | 3 +- - drivers/net/wireless/iwlwifi/iwl-agn.c | 3 +- - drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 +++--- - drivers/net/wireless/libertas_tf/main.c | 4 ++- - drivers/net/wireless/mac80211_hwsim.c | 4 +-- - drivers/net/wireless/p54/p54common.c | 3 +- - drivers/net/wireless/rt2x00/rt2x00.h | 2 - - drivers/net/wireless/rt2x00/rt2x00dev.c | 2 - - drivers/net/wireless/rt2x00/rt2x00mac.c | 3 +- - drivers/net/wireless/rtl8180_dev.c | 3 +- - drivers/net/wireless/rtl8187_dev.c | 3 +- - drivers/net/wireless/zd1211rw/zd_mac.c | 4 ++- - include/net/mac80211.h | 30 +++++++++++++++++++++++----- - net/mac80211/cfg.c | 3 +- - net/mac80211/ieee80211_i.h | 2 - - net/mac80211/iface.c | 25 +++++++++++++++++------ - net/mac80211/main.c | 29 ++++++++++++++------------- - net/mac80211/scan.c | 12 ++++++++--- - net/mac80211/util.c | 3 +- - net/mac80211/wext.c | 14 ++++++------- - 25 files changed, 118 insertions(+), 61 deletions(-) - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -464,12 +464,32 @@ static inline int __deprecated __IEEE802 - #define IEEE80211_CONF_SHORT_SLOT_TIME (__IEEE80211_CONF_SHORT_SLOT_TIME()) - - /** -+ * enum ieee80211_conf_changed - denotes which configuration changed -+ * -+ * @IEEE80211_CONF_CHANGE_RADIO_ENABLED: the value of radio_enabled changed -+ * @IEEE80211_CONF_CHANGE_BEACON_INTERVAL: the beacon interval changed -+ * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed -+ * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed -+ * @IEEE80211_CONF_CHANGE_PS: the PS flag changed -+ * @IEEE80211_CONF_CHANGE_POWER: the TX power changed -+ * @IEEE80211_CONF_CHANGE_CHANNEL: the channel changed -+ */ -+enum ieee80211_conf_changed { -+ IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), -+ IEEE80211_CONF_CHANGE_BEACON_INTERVAL = BIT(1), -+ IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), -+ IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), -+ IEEE80211_CONF_CHANGE_PS = BIT(4), -+ IEEE80211_CONF_CHANGE_POWER = BIT(5), -+ IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), -+}; -+ -+/** - * struct ieee80211_conf - configuration of the device - * - * This struct indicates how the driver shall configure the hardware. - * - * @radio_enabled: when zero, driver is required to switch off the radio. -- * TODO make a flag - * @beacon_int: beacon interval (TODO make interface config) - * @listen_interval: listen interval in units of beacon interval - * @flags: configuration flags defined above -@@ -479,13 +499,13 @@ static inline int __deprecated __IEEE802 - * @channel: the channel to tune to - */ - struct ieee80211_conf { -- int radio_enabled; -- - int beacon_int; -- u16 listen_interval; - u32 flags; - int power_level; - -+ u16 listen_interval; -+ bool radio_enabled; -+ - struct ieee80211_channel *channel; - - struct ieee80211_sta_ht_cap ht_cap; -@@ -1213,7 +1233,7 @@ struct ieee80211_ops { - struct ieee80211_if_init_conf *conf); - void (*remove_interface)(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); -- int (*config)(struct ieee80211_hw *hw, struct ieee80211_conf *conf); -+ int (*config)(struct ieee80211_hw *hw, u32 changed); - int (*config_interface)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); ---- a/net/mac80211/cfg.c -+++ b/net/mac80211/cfg.c -@@ -394,7 +394,8 @@ static int ieee80211_config_beacon(struc - */ - if (params->interval) { - sdata->local->hw.conf.beacon_int = params->interval; -- ieee80211_hw_config(sdata->local); -+ ieee80211_hw_config(sdata->local, -+ IEEE80211_CONF_CHANGE_BEACON_INTERVAL); - /* - * We updated some parameter so if below bails out - * it's not an error. ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -880,7 +880,7 @@ static inline int ieee80211_bssid_match( - } - - --int ieee80211_hw_config(struct ieee80211_local *local); -+int ieee80211_hw_config(struct ieee80211_local *local, u32 changed); - int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); - void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); - void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, ---- a/net/mac80211/iface.c -+++ b/net/mac80211/iface.c -@@ -65,7 +65,7 @@ static int ieee80211_open(struct net_dev - struct ieee80211_if_init_conf conf; - u32 changed = 0; - int res; -- bool need_hw_reconfig = 0; -+ u32 hw_reconf_flags = 0; - u8 null_addr[ETH_ALEN] = {0}; - - /* fail early if user set an invalid address */ -@@ -152,7 +152,8 @@ static int ieee80211_open(struct net_dev - res = local->ops->start(local_to_hw(local)); - if (res) - goto err_del_bss; -- need_hw_reconfig = 1; -+ /* we're brought up, everything changes */ -+ hw_reconf_flags = ~0; - ieee80211_led_radio(local, local->hw.conf.radio_enabled); - } - -@@ -198,8 +199,10 @@ static int ieee80211_open(struct net_dev - - /* must be before the call to ieee80211_configure_filter */ - local->monitors++; -- if (local->monitors == 1) -+ if (local->monitors == 1) { - local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; -+ hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP; -+ } - - if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) - local->fif_fcsfail++; -@@ -279,8 +282,8 @@ static int ieee80211_open(struct net_dev - atomic_inc(&local->iff_promiscs); - - local->open_count++; -- if (need_hw_reconfig) { -- ieee80211_hw_config(local); -+ if (hw_reconf_flags) { -+ ieee80211_hw_config(local, hw_reconf_flags); - /* - * set default queue parameters so drivers don't - * need to initialise the hardware if the hardware -@@ -322,6 +325,7 @@ static int ieee80211_stop(struct net_dev - struct ieee80211_local *local = sdata->local; - struct ieee80211_if_init_conf conf; - struct sta_info *sta; -+ u32 hw_reconf_flags = 0; - - /* - * Stop TX on this interface first. -@@ -405,8 +409,10 @@ static int ieee80211_stop(struct net_dev - } - - local->monitors--; -- if (local->monitors == 0) -+ if (local->monitors == 0) { - local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; -+ hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP; -+ } - - if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) - local->fif_fcsfail--; -@@ -504,8 +510,15 @@ static int ieee80211_stop(struct net_dev - - tasklet_disable(&local->tx_pending_tasklet); - tasklet_disable(&local->tasklet); -+ -+ /* no reconfiguring after stop! */ -+ hw_reconf_flags = 0; - } - -+ /* do after stop to avoid reconfiguring when we stop anyway */ -+ if (hw_reconf_flags) -+ ieee80211_hw_config(local, hw_reconf_flags); -+ - return 0; - } - ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -197,31 +197,34 @@ int ieee80211_if_config(struct ieee80211 - &sdata->vif, &conf); - } - --int ieee80211_hw_config(struct ieee80211_local *local) -+int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) - { - struct ieee80211_channel *chan; - int ret = 0; -+ int power; - - if (local->sw_scanning) - chan = local->scan_channel; - else - chan = local->oper_channel; - -- local->hw.conf.channel = chan; -+ if (chan != local->hw.conf.channel) { -+ local->hw.conf.channel = chan; -+ changed |= IEEE80211_CONF_CHANGE_CHANNEL; -+ } -+ - - if (!local->hw.conf.power_level) -- local->hw.conf.power_level = chan->max_power; -+ power = chan->max_power; - else -- local->hw.conf.power_level = min(chan->max_power, -- local->hw.conf.power_level); -- --#ifdef CONFIG_MAC80211_VERBOSE_DEBUG -- printk(KERN_DEBUG "%s: HW CONFIG: freq=%d\n", -- wiphy_name(local->hw.wiphy), chan->center_freq); --#endif -+ power = min(chan->max_power, local->hw.conf.power_level); -+ if (local->hw.conf.power_level != power) { -+ changed |= IEEE80211_CONF_CHANGE_POWER; -+ local->hw.conf.power_level = power; -+ } - -- if (local->open_count) { -- ret = local->ops->config(local_to_hw(local), &local->hw.conf); -+ if (changed && local->open_count) { -+ ret = local->ops->config(local_to_hw(local), changed); - /* - * HW reconfiguration should never fail, the driver has told - * us what it can support so it should live up to that promise. -@@ -672,7 +675,7 @@ struct ieee80211_hw *ieee80211_alloc_hw( - local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - local->short_retry_limit = 7; - local->long_retry_limit = 4; -- local->hw.conf.radio_enabled = 1; -+ local->hw.conf.radio_enabled = true; - - INIT_LIST_HEAD(&local->interfaces); - ---- a/net/mac80211/scan.c -+++ b/net/mac80211/scan.c -@@ -447,12 +447,17 @@ void ieee80211_scan_completed(struct iee - - if (local->hw_scanning) { - local->hw_scanning = false; -- ieee80211_hw_config(local); -+ /* -+ * Somebody might have requested channel change during scan -+ * that we won't have acted upon, try now. ieee80211_hw_config -+ * will set the flag based on actual changes. -+ */ -+ ieee80211_hw_config(local, 0); - goto done; - } - - local->sw_scanning = false; -- ieee80211_hw_config(local); -+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - - netif_tx_lock_bh(local->mdev); - netif_addr_lock(local->mdev); -@@ -539,7 +544,8 @@ void ieee80211_scan_work(struct work_str - - if (!skip) { - local->scan_channel = chan; -- if (ieee80211_hw_config(local)) -+ if (ieee80211_hw_config(local, -+ IEEE80211_CONF_CHANGE_CHANNEL)) - skip = 1; - } - ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -645,7 +645,8 @@ int ieee80211_set_freq(struct ieee80211_ - if (local->sw_scanning || local->hw_scanning) - ret = 0; - else -- ret = ieee80211_hw_config(local); -+ ret = ieee80211_hw_config( -+ local, IEEE80211_CONF_CHANGE_CHANNEL); - - rate_control_clear(local); - } ---- a/net/mac80211/wext.c -+++ b/net/mac80211/wext.c -@@ -656,7 +656,7 @@ static int ieee80211_ioctl_siwtxpower(st - union iwreq_data *data, char *extra) - { - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); -- bool need_reconfig = 0; -+ u32 reconf_flags = 0; - int new_power_level; - - if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) -@@ -680,17 +680,17 @@ static int ieee80211_ioctl_siwtxpower(st - - if (local->hw.conf.power_level != new_power_level) { - local->hw.conf.power_level = new_power_level; -- need_reconfig = 1; -+ reconf_flags |= IEEE80211_CONF_CHANGE_POWER; - } - - if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) { - local->hw.conf.radio_enabled = !(data->txpower.disabled); -- need_reconfig = 1; -+ reconf_flags |= IEEE80211_CONF_CHANGE_RADIO_ENABLED; - ieee80211_led_radio(local, local->hw.conf.radio_enabled); - } - -- if (need_reconfig) -- ieee80211_hw_config(local); -+ if (reconf_flags) -+ ieee80211_hw_config(local, reconf_flags); - - return 0; - } -@@ -976,7 +976,7 @@ static int ieee80211_ioctl_siwpower(stru - - if (wrq->disabled) { - conf->flags &= ~IEEE80211_CONF_PS; -- return ieee80211_hw_config(local); -+ return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } - - switch (wrq->flags & IW_POWER_MODE) { -@@ -989,7 +989,7 @@ static int ieee80211_ioctl_siwpower(stru - return -EINVAL; - } - -- return ieee80211_hw_config(local); -+ return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - } - - static int ieee80211_ioctl_giwpower(struct net_device *dev, ---- a/drivers/net/wireless/adm8211.c -+++ b/drivers/net/wireless/adm8211.c -@@ -1314,9 +1314,10 @@ static int adm8211_set_ssid(struct ieee8 - return 0; - } - --static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) -+static int adm8211_config(struct ieee80211_hw *dev, u32 changed) - { - struct adm8211_priv *priv = dev->priv; -+ struct ieee80211_conf *conf = &dev->conf; - int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - - if (channel != priv->channel) { ---- a/drivers/net/wireless/at76_usb.c -+++ b/drivers/net/wireless/at76_usb.c -@@ -2057,9 +2057,10 @@ exit: - return 0; - } - --static int at76_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) -+static int at76_config(struct ieee80211_hw *hw, u32 changed) - { - struct at76_priv *priv = hw->priv; -+ struct ieee80211_conf *conf = &hw->conf; - - at76_dbg(DBG_MAC80211, "%s(): channel %d radio %d", - __func__, conf->channel->hw_value, conf->radio_enabled); ---- a/drivers/net/wireless/ath5k/base.c -+++ b/drivers/net/wireless/ath5k/base.c -@@ -219,8 +219,7 @@ static int ath5k_add_interface(struct ie - struct ieee80211_if_init_conf *conf); - static void ath5k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); --static int ath5k_config(struct ieee80211_hw *hw, -- struct ieee80211_conf *conf); -+static int ath5k_config(struct ieee80211_hw *hw, u32 changed); - static int ath5k_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); -@@ -2767,10 +2766,10 @@ end: - * TODO: Phy disable/diversity etc - */ - static int --ath5k_config(struct ieee80211_hw *hw, -- struct ieee80211_conf *conf) -+ath5k_config(struct ieee80211_hw *hw, u32 changed) - { - struct ath5k_softc *sc = hw->priv; -+ struct ieee80211_conf *conf = &hw->conf; - - sc->bintval = conf->beacon_int; - sc->power_level = conf->power_level; ---- a/drivers/net/wireless/ath9k/main.c -+++ b/drivers/net/wireless/ath9k/main.c -@@ -1231,11 +1231,11 @@ static void ath9k_remove_interface(struc - __func__, error); - } - --static int ath9k_config(struct ieee80211_hw *hw, -- struct ieee80211_conf *conf) -+static int ath9k_config(struct ieee80211_hw *hw, u32 changed) - { - struct ath_softc *sc = hw->priv; - struct ieee80211_channel *curchan = hw->conf.channel; -+ struct ieee80211_conf *conf = &hw->conf; - int pos; - - DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n", ---- a/drivers/net/wireless/b43/main.c -+++ b/drivers/net/wireless/b43/main.c -@@ -3320,11 +3320,12 @@ init_failure: - return err; - } - --static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) -+static int b43_op_config(struct ieee80211_hw *hw, u32 changed) - { - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - struct b43_phy *phy; -+ struct ieee80211_conf *conf = &hw->conf; - unsigned long flags; - int antenna; - int err = 0; ---- a/drivers/net/wireless/b43legacy/main.c -+++ b/drivers/net/wireless/b43legacy/main.c -@@ -2557,11 +2557,12 @@ init_failure: - } - - static int b43legacy_op_dev_config(struct ieee80211_hw *hw, -- struct ieee80211_conf *conf) -+ u32 changed) - { - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev; - struct b43legacy_phy *phy; -+ struct ieee80211_conf *conf = &hw->conf; - unsigned long flags; - unsigned int new_phymode = 0xFFFF; - int antenna_tx; ---- a/drivers/net/wireless/iwlwifi/iwl-agn.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c -@@ -2760,10 +2760,11 @@ static int iwl4965_mac_add_interface(str - * be set inappropriately and the driver currently sets the hardware up to - * use it whenever needed. - */ --static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) -+static int iwl4965_mac_config(struct ieee80211_hw *hw, u32 changed) - { - struct iwl_priv *priv = hw->priv; - const struct iwl_channel_info *ch_info; -+ struct ieee80211_conf *conf = &hw->conf; - unsigned long flags; - int ret = 0; - u16 channel; ---- a/drivers/net/wireless/iwlwifi/iwl3945-base.c -+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c -@@ -6427,7 +6427,7 @@ static void iwl3945_bg_abort_scan(struct - mutex_unlock(&priv->mutex); - } - --static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); -+static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed); - - static void iwl3945_bg_scan_completed(struct work_struct *work) - { -@@ -6440,7 +6440,7 @@ static void iwl3945_bg_scan_completed(st - return; - - if (test_bit(STATUS_CONF_PENDING, &priv->status)) -- iwl3945_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw)); -+ iwl3945_mac_config(priv->hw, 0); - - ieee80211_scan_completed(priv->hw); - -@@ -6629,10 +6629,11 @@ static int iwl3945_mac_add_interface(str - * be set inappropriately and the driver currently sets the hardware up to - * use it whenever needed. - */ --static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) -+static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed) - { - struct iwl3945_priv *priv = hw->priv; - const struct iwl3945_channel_info *ch_info; -+ struct ieee80211_conf *conf = &hw->conf; - unsigned long flags; - int ret = 0; - ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -361,10 +361,10 @@ static void mac80211_hwsim_beacon(unsign - } - - --static int mac80211_hwsim_config(struct ieee80211_hw *hw, -- struct ieee80211_conf *conf) -+static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) - { - struct mac80211_hwsim_data *data = hw->priv; -+ struct ieee80211_conf *conf = &hw->conf; - - printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d beacon_int=%d)\n", - wiphy_name(hw->wiphy), __func__, ---- a/drivers/net/wireless/p54/p54common.c -+++ b/drivers/net/wireless/p54/p54common.c -@@ -1205,10 +1205,11 @@ static void p54_remove_interface(struct - p54_set_filter(dev, 0, NULL); - } - --static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) -+static int p54_config(struct ieee80211_hw *dev, u32 changed) - { - int ret; - struct p54_common *priv = dev->priv; -+ struct ieee80211_conf *conf = &dev->conf; - - mutex_lock(&priv->conf_mutex); - priv->rx_antenna = 2; /* automatic */ ---- a/drivers/net/wireless/rt2x00/rt2x00.h -+++ b/drivers/net/wireless/rt2x00/rt2x00.h -@@ -997,7 +997,7 @@ int rt2x00mac_add_interface(struct ieee8 - struct ieee80211_if_init_conf *conf); - void rt2x00mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); --int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); -+int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); - int rt2x00mac_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf); ---- a/drivers/net/wireless/rt2x00/rt2x00mac.c -+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c -@@ -335,9 +335,10 @@ void rt2x00mac_remove_interface(struct i - } - EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); - --int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) -+int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) - { - struct rt2x00_dev *rt2x00dev = hw->priv; -+ struct ieee80211_conf *conf = &hw->conf; - int radio_on; - int status; - ---- a/drivers/net/wireless/rtl8180_dev.c -+++ b/drivers/net/wireless/rtl8180_dev.c -@@ -692,9 +692,10 @@ static void rtl8180_remove_interface(str - priv->vif = NULL; - } - --static int rtl8180_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) -+static int rtl8180_config(struct ieee80211_hw *dev, u32 changed) - { - struct rtl8180_priv *priv = dev->priv; -+ struct ieee80211_conf *conf = &dev->conf; - - priv->rf->set_chan(dev, conf); - ---- a/drivers/net/wireless/rtl8187_dev.c -+++ b/drivers/net/wireless/rtl8187_dev.c -@@ -870,9 +870,10 @@ static void rtl8187_remove_interface(str - mutex_unlock(&priv->conf_mutex); - } - --static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) -+static int rtl8187_config(struct ieee80211_hw *dev, u32 changed) - { - struct rtl8187_priv *priv = dev->priv; -+ struct ieee80211_conf *conf = &dev->conf; - u32 reg; - - mutex_lock(&priv->conf_mutex); ---- a/drivers/net/wireless/zd1211rw/zd_mac.c -+++ b/drivers/net/wireless/zd1211rw/zd_mac.c -@@ -743,9 +743,11 @@ static void zd_op_remove_interface(struc - zd_write_mac_addr(&mac->chip, NULL); - } - --static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) -+static int zd_op_config(struct ieee80211_hw *hw, u32 changed) - { - struct zd_mac *mac = zd_hw_mac(hw); -+ struct ieee80211_conf *conf = &hw->conf; -+ - return zd_chip_set_channel(&mac->chip, conf->channel->hw_value); - } - ---- a/drivers/net/wireless/rt2x00/rt2x00dev.c -+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c -@@ -1245,7 +1245,7 @@ int rt2x00lib_resume(struct rt2x00_dev * - /* - * Reconfigure device. - */ -- retval = rt2x00mac_config(rt2x00dev->hw, &rt2x00dev->hw->conf); -+ retval = rt2x00mac_config(rt2x00dev->hw, ~0); - if (retval) - goto exit; - diff --git a/package/mac80211/patches/421-nl80211-export-ht.patch b/package/mac80211/patches/421-nl80211-export-ht.patch deleted file mode 100644 index d6f6b5a589..0000000000 --- a/package/mac80211/patches/421-nl80211-export-ht.patch +++ /dev/null @@ -1,64 +0,0 @@ -Subject: nl80211: export HT capabilities - -This exports the local HT capabilities in nl80211. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - include/linux/nl80211.h | 12 ++++++++++++ - net/wireless/nl80211.c | 13 +++++++++++++ - 2 files changed, 25 insertions(+) - ---- everything.orig/include/linux/nl80211.h 2008-10-09 01:31:09.000000000 +0200 -+++ everything/include/linux/nl80211.h 2008-10-09 02:11:44.000000000 +0200 -@@ -452,17 +452,29 @@ enum nl80211_mpath_info { - * an array of nested frequency attributes - * @NL80211_BAND_ATTR_RATES: supported bitrates in this band, - * an array of nested bitrate attributes -+ * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as -+ * defined in 802.11n -+ * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE -+ * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n -+ * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n - */ - enum nl80211_band_attr { - __NL80211_BAND_ATTR_INVALID, - NL80211_BAND_ATTR_FREQS, - NL80211_BAND_ATTR_RATES, - -+ NL80211_BAND_ATTR_HT_MCS_SET, -+ NL80211_BAND_ATTR_HT_CAPA, -+ NL80211_BAND_ATTR_HT_AMPDU_FACTOR, -+ NL80211_BAND_ATTR_HT_AMPDU_DENSITY, -+ - /* keep last */ - __NL80211_BAND_ATTR_AFTER_LAST, - NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 - }; - -+#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA -+ - /** - * enum nl80211_frequency_attr - frequency attributes - * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz ---- everything.orig/net/wireless/nl80211.c 2008-10-09 01:32:05.000000000 +0200 -+++ everything/net/wireless/nl80211.c 2008-10-09 02:12:21.000000000 +0200 -@@ -157,6 +157,19 @@ static int nl80211_send_wiphy(struct sk_ - if (!nl_band) - goto nla_put_failure; - -+ /* add HT info */ -+ if (dev->wiphy.bands[band]->ht_cap.ht_supported) { -+ NLA_PUT(msg, NL80211_BAND_ATTR_HT_MCS_SET, -+ sizeof(dev->wiphy.bands[band]->ht_cap.mcs), -+ &dev->wiphy.bands[band]->ht_cap.mcs); -+ NLA_PUT_U16(msg, NL80211_BAND_ATTR_HT_CAPA, -+ dev->wiphy.bands[band]->ht_cap.cap); -+ NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_FACTOR, -+ dev->wiphy.bands[band]->ht_cap.ampdu_factor); -+ NLA_PUT_U8(msg, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, -+ dev->wiphy.bands[band]->ht_cap.ampdu_density); -+ } -+ - /* add frequencies */ - nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); - if (!nl_freqs) diff --git a/package/mac80211/patches/422-mac80211-seqno-station.patch b/package/mac80211/patches/422-mac80211-seqno-station.patch deleted file mode 100644 index 72fbd9cb70..0000000000 --- a/package/mac80211/patches/422-mac80211-seqno-station.patch +++ /dev/null @@ -1,142 +0,0 @@ -Subject: mac80211: provide sequence numbers - -I've come to think that not providing sequence numbers for -the normal STA mode case was a mistake, at least two drivers -now had to implement code they wouldn't otherwise need, and -I believe at76_usb and adm8211 might be broken. - -This patch makes mac80211 assign a sequence number to all -those frames that need one except beacons. That means that -if a driver only implements modes that do not do beaconing -it need not worry about the sequence number. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - drivers/net/wireless/p54/p54.h | 1 - - drivers/net/wireless/p54/p54common.c | 18 +++++------------- - drivers/net/wireless/rtl8187.h | 1 - - drivers/net/wireless/rtl8187_dev.c | 18 ++++-------------- - net/mac80211/ieee80211_i.h | 2 ++ - net/mac80211/tx.c | 10 ++++++++++ - 6 files changed, 21 insertions(+), 29 deletions(-) - ---- everything.orig/net/mac80211/ieee80211_i.h 2008-10-10 15:45:52.000000000 +0200 -+++ everything/net/mac80211/ieee80211_i.h 2008-10-10 15:45:56.000000000 +0200 -@@ -438,6 +438,8 @@ struct ieee80211_sub_if_data { - struct ieee80211_key *keys[NUM_DEFAULT_KEYS]; - struct ieee80211_key *default_key; - -+ u16 sequence_number; -+ - /* BSS configuration for this interface. */ - struct ieee80211_bss_conf bss_conf; - ---- everything.orig/net/mac80211/tx.c 2008-10-10 15:45:48.000000000 +0200 -+++ everything/net/mac80211/tx.c 2008-10-10 15:45:56.000000000 +0200 -@@ -602,8 +602,18 @@ ieee80211_tx_h_sequence(struct ieee80211 - if (ieee80211_hdrlen(hdr->frame_control) < 24) - return TX_CONTINUE; - -+ /* -+ * Anything but QoS data that has a sequence number field -+ * (is long enough) gets a sequence number from the global -+ * counter. -+ */ - if (!ieee80211_is_data_qos(hdr->frame_control)) { -+ /* driver should assign sequence number */ - info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; -+ /* for pure STA mode without beacons, we can do it */ -+ hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); -+ tx->sdata->sequence_number += 0x10; -+ tx->sdata->sequence_number &= IEEE80211_SCTL_SEQ; - return TX_CONTINUE; - } - ---- everything.orig/drivers/net/wireless/p54/p54.h 2008-10-10 15:45:49.000000000 +0200 -+++ everything/drivers/net/wireless/p54/p54.h 2008-10-10 15:45:56.000000000 +0200 -@@ -67,7 +67,6 @@ struct p54_common { - int (*open)(struct ieee80211_hw *dev); - void (*stop)(struct ieee80211_hw *dev); - int mode; -- u16 seqno; - u16 rx_mtu; - u8 headroom; - u8 tailroom; ---- everything.orig/drivers/net/wireless/p54/p54common.c 2008-10-10 15:45:49.000000000 +0200 -+++ everything/drivers/net/wireless/p54/p54common.c 2008-10-10 15:45:56.000000000 +0200 -@@ -865,19 +865,6 @@ static int p54_tx(struct ieee80211_hw *d - if (padding) - txhdr->align[0] = padding; - -- /* FIXME: The sequence that follows is needed for this driver to -- * work with mac80211 since "mac80211: fix TX sequence numbers". -- * As with the temporary code in rt2x00, changes will be needed -- * to get proper sequence numbers on beacons. In addition, this -- * patch places the sequence number in the hardware state, which -- * limits us to a single virtual state. -- */ -- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { -- if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) -- priv->seqno += 0x10; -- ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); -- ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno); -- } - /* modifies skb->cb and with it info, so must be last! */ - p54_assign_address(dev, skb, hdr, skb->len); - -@@ -1391,6 +1378,11 @@ struct ieee80211_hw *p54_init_common(siz - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; - -+ /* -+ * XXX: when this driver gets support for any mode that -+ * requires beacons (AP, MESH, IBSS) then it must -+ * implement IEEE80211_TX_CTL_ASSIGN_SEQ. -+ */ - dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - - dev->channel_change_time = 1000; /* TODO: find actual value */ ---- everything.orig/drivers/net/wireless/rtl8187_dev.c 2008-10-10 15:45:49.000000000 +0200 -+++ everything/drivers/net/wireless/rtl8187_dev.c 2008-10-10 15:45:56.000000000 +0200 -@@ -238,20 +238,6 @@ static int rtl8187_tx(struct ieee80211_h - ep = epmap[skb_get_queue_mapping(skb)]; - } - -- /* FIXME: The sequence that follows is needed for this driver to -- * work with mac80211 since "mac80211: fix TX sequence numbers". -- * As with the temporary code in rt2x00, changes will be needed -- * to get proper sequence numbers on beacons. In addition, this -- * patch places the sequence number in the hardware state, which -- * limits us to a single virtual state. -- */ -- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { -- if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) -- priv->seqno += 0x10; -- ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); -- ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno); -- } -- - info->driver_data[0] = dev; - info->driver_data[1] = urb; - -@@ -1185,6 +1171,10 @@ static int __devinit rtl8187_probe(struc - dev->max_signal = 65; - } - -+ /* -+ * XXX: Once this driver supports anything that requires -+ * beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ. -+ */ - dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - - if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) ---- everything.orig/drivers/net/wireless/rtl8187.h 2008-10-10 15:45:49.000000000 +0200 -+++ everything/drivers/net/wireless/rtl8187.h 2008-10-10 15:45:56.000000000 +0200 -@@ -100,7 +100,6 @@ struct rtl8187_priv { - struct usb_device *udev; - u32 rx_conf; - u16 txpwr_base; -- u16 seqno; - u8 asic_rev; - u8 is_rtl8187b; - enum { diff --git a/package/mac80211/patches/423-mac80211-make-bss-conf-part-of-vif.patch b/package/mac80211/patches/423-mac80211-make-bss-conf-part-of-vif.patch deleted file mode 100644 index 556d651a0a..0000000000 --- a/package/mac80211/patches/423-mac80211-make-bss-conf-part-of-vif.patch +++ /dev/null @@ -1,303 +0,0 @@ -Subject: mac80211: move bss_conf into vif - -Move bss_conf into the vif struct so that drivers can -access it during ->tx without having to store it in -the private data or similar. No driver updates because -this is only for when they want to start using it. - -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - include/net/mac80211.h | 3 +++ - net/mac80211/cfg.c | 6 +++--- - net/mac80211/debugfs_netdev.c | 2 +- - net/mac80211/ieee80211_i.h | 3 --- - net/mac80211/iface.c | 2 +- - net/mac80211/main.c | 8 ++++---- - net/mac80211/mlme.c | 30 +++++++++++++++--------------- - net/mac80211/tx.c | 16 ++++++++-------- - net/mac80211/util.c | 6 +++--- - 9 files changed, 38 insertions(+), 38 deletions(-) - ---- everything.orig/include/net/mac80211.h 2008-10-10 17:09:04.000000000 +0200 -+++ everything/include/net/mac80211.h 2008-10-10 17:09:41.000000000 +0200 -@@ -519,11 +519,14 @@ struct ieee80211_conf { - * use during the life of a virtual interface. - * - * @type: type of this virtual interface -+ * @bss_conf: BSS configuration for this interface, either our own -+ * or the BSS we're associated to - * @drv_priv: data area for driver use, will always be aligned to - * sizeof(void *). - */ - struct ieee80211_vif { - enum nl80211_iftype type; -+ struct ieee80211_bss_conf bss_conf; - /* must be last */ - u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); - }; ---- everything.orig/net/mac80211/ieee80211_i.h 2008-10-10 17:10:40.000000000 +0200 -+++ everything/net/mac80211/ieee80211_i.h 2008-10-10 17:10:45.000000000 +0200 -@@ -440,9 +440,6 @@ struct ieee80211_sub_if_data { - - u16 sequence_number; - -- /* BSS configuration for this interface. */ -- struct ieee80211_bss_conf bss_conf; -- - /* - * AP this belongs to: self in AP mode and - * corresponding AP in VLAN mode, NULL for ---- everything.orig/net/mac80211/main.c 2008-10-10 17:10:55.000000000 +0200 -+++ everything/net/mac80211/main.c 2008-10-10 17:11:10.000000000 +0200 -@@ -249,15 +249,15 @@ void ieee80211_bss_info_change_notify(st - if (local->ops->bss_info_changed) - local->ops->bss_info_changed(local_to_hw(local), - &sdata->vif, -- &sdata->bss_conf, -+ &sdata->vif.bss_conf, - changed); - } - - u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) - { -- sdata->bss_conf.use_cts_prot = false; -- sdata->bss_conf.use_short_preamble = false; -- sdata->bss_conf.use_short_slot = false; -+ sdata->vif.bss_conf.use_cts_prot = false; -+ sdata->vif.bss_conf.use_short_preamble = false; -+ sdata->vif.bss_conf.use_short_slot = false; - return BSS_CHANGED_ERP_CTS_PROT | - BSS_CHANGED_ERP_PREAMBLE | - BSS_CHANGED_ERP_SLOT; ---- everything.orig/net/mac80211/iface.c 2008-10-10 17:12:11.000000000 +0200 -+++ everything/net/mac80211/iface.c 2008-10-10 17:12:13.000000000 +0200 -@@ -695,7 +695,7 @@ int ieee80211_if_change_type(struct ieee - ieee80211_setup_sdata(sdata, type); - - /* reset some values that shouldn't be kept across type changes */ -- sdata->bss_conf.basic_rates = -+ sdata->vif.bss_conf.basic_rates = - ieee80211_mandatory_rates(sdata->local, - sdata->local->hw.conf.channel->band); - sdata->drop_unencrypted = 0; ---- everything.orig/net/mac80211/mlme.c 2008-10-10 17:11:49.000000000 +0200 -+++ everything/net/mac80211/mlme.c 2008-10-10 17:11:58.000000000 +0200 -@@ -572,7 +572,7 @@ static void ieee80211_sta_wmm_params(str - static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, - u16 capab, bool erp_valid, u8 erp) - { -- struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; -+ struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; - #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - struct ieee80211_if_sta *ifsta = &sdata->u.sta; - DECLARE_MAC_BUF(mac); -@@ -720,9 +720,9 @@ static void ieee80211_set_associated(str - ifsta->ssid, ifsta->ssid_len); - if (bss) { - /* set timing information */ -- sdata->bss_conf.beacon_int = bss->beacon_int; -- sdata->bss_conf.timestamp = bss->timestamp; -- sdata->bss_conf.dtim_period = bss->dtim_period; -+ sdata->vif.bss_conf.beacon_int = bss->beacon_int; -+ sdata->vif.bss_conf.timestamp = bss->timestamp; -+ sdata->vif.bss_conf.dtim_period = bss->dtim_period; - - changed |= ieee80211_handle_bss_capability(sdata, - bss->capability, bss->has_erp_value, bss->erp_value); -@@ -732,9 +732,9 @@ static void ieee80211_set_associated(str - - if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { - changed |= BSS_CHANGED_HT; -- sdata->bss_conf.assoc_ht = 1; -- sdata->bss_conf.ht_cap = &conf->ht_cap; -- sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; -+ sdata->vif.bss_conf.assoc_ht = 1; -+ sdata->vif.bss_conf.ht_cap = &conf->ht_cap; -+ sdata->vif.bss_conf.ht_bss_conf = &conf->ht_bss_conf; - } - - ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; -@@ -744,7 +744,7 @@ static void ieee80211_set_associated(str - ifsta->last_probe = jiffies; - ieee80211_led_assoc(local, 1); - -- sdata->bss_conf.assoc = 1; -+ sdata->vif.bss_conf.assoc = 1; - /* - * For now just always ask the driver to update the basic rateset - * when we have associated, we aren't checking whether it actually -@@ -853,15 +853,15 @@ static void ieee80211_set_disassoc(struc - ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; - changed |= ieee80211_reset_erp_info(sdata); - -- if (sdata->bss_conf.assoc_ht) -+ if (sdata->vif.bss_conf.assoc_ht) - changed |= BSS_CHANGED_HT; - -- sdata->bss_conf.assoc_ht = 0; -- sdata->bss_conf.ht_cap = NULL; -- sdata->bss_conf.ht_bss_conf = NULL; -+ sdata->vif.bss_conf.assoc_ht = 0; -+ sdata->vif.bss_conf.ht_cap = NULL; -+ sdata->vif.bss_conf.ht_bss_conf = NULL; - - ieee80211_led_assoc(local, 0); -- sdata->bss_conf.assoc = 0; -+ sdata->vif.bss_conf.assoc = 0; - - ieee80211_sta_send_apinfo(sdata, ifsta); - -@@ -1194,7 +1194,7 @@ static void ieee80211_rx_mgmt_assoc_resp - u64 rates, basic_rates; - u16 capab_info, status_code, aid; - struct ieee802_11_elems elems; -- struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; -+ struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; - u8 *pos; - int i, j; - DECLARE_MAC_BUF(mac); -@@ -1337,7 +1337,7 @@ static void ieee80211_rx_mgmt_assoc_resp - } - - sta->sta.supp_rates[local->hw.conf.channel->band] = rates; -- sdata->bss_conf.basic_rates = basic_rates; -+ sdata->vif.bss_conf.basic_rates = basic_rates; - - /* cf. IEEE 802.11 9.2.12 */ - if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && ---- everything.orig/net/mac80211/cfg.c 2008-10-10 17:12:29.000000000 +0200 -+++ everything/net/mac80211/cfg.c 2008-10-10 17:12:31.000000000 +0200 -@@ -966,16 +966,16 @@ static int ieee80211_change_bss(struct w - return -EINVAL; - - if (params->use_cts_prot >= 0) { -- sdata->bss_conf.use_cts_prot = params->use_cts_prot; -+ sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; - changed |= BSS_CHANGED_ERP_CTS_PROT; - } - if (params->use_short_preamble >= 0) { -- sdata->bss_conf.use_short_preamble = -+ sdata->vif.bss_conf.use_short_preamble = - params->use_short_preamble; - changed |= BSS_CHANGED_ERP_PREAMBLE; - } - if (params->use_short_slot_time >= 0) { -- sdata->bss_conf.use_short_slot = -+ sdata->vif.bss_conf.use_short_slot = - params->use_short_slot_time; - changed |= BSS_CHANGED_ERP_SLOT; - } ---- everything.orig/net/mac80211/debugfs_netdev.c 2008-10-10 17:13:26.000000000 +0200 -+++ everything/net/mac80211/debugfs_netdev.c 2008-10-10 17:13:28.000000000 +0200 -@@ -120,7 +120,7 @@ static ssize_t ieee80211_if_fmt_flags( - sdata->u.sta.flags & IEEE80211_STA_AUTHENTICATED ? "AUTH\n" : "", - sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED ? "ASSOC\n" : "", - sdata->u.sta.flags & IEEE80211_STA_PROBEREQ_POLL ? "PROBEREQ POLL\n" : "", -- sdata->bss_conf.use_cts_prot ? "CTS prot\n" : ""); -+ sdata->vif.bss_conf.use_cts_prot ? "CTS prot\n" : ""); - } - __IEEE80211_IF_FILE(flags); - ---- everything.orig/net/mac80211/tx.c 2008-10-10 17:12:46.000000000 +0200 -+++ everything/net/mac80211/tx.c 2008-10-10 17:12:49.000000000 +0200 -@@ -116,7 +116,7 @@ static __le16 ieee80211_duration(struct - if (r->bitrate > txrate->bitrate) - break; - -- if (tx->sdata->bss_conf.basic_rates & BIT(i)) -+ if (tx->sdata->vif.bss_conf.basic_rates & BIT(i)) - rate = r->bitrate; - - switch (sband->band) { -@@ -150,7 +150,7 @@ static __le16 ieee80211_duration(struct - * to closest integer */ - - dur = ieee80211_frame_duration(local, 10, rate, erp, -- tx->sdata->bss_conf.use_short_preamble); -+ tx->sdata->vif.bss_conf.use_short_preamble); - - if (next_frag_len) { - /* Frame is fragmented: duration increases with time needed to -@@ -159,7 +159,7 @@ static __le16 ieee80211_duration(struct - /* next fragment */ - dur += ieee80211_frame_duration(local, next_frag_len, - txrate->bitrate, erp, -- tx->sdata->bss_conf.use_short_preamble); -+ tx->sdata->vif.bss_conf.use_short_preamble); - } - - return cpu_to_le16(dur); -@@ -465,7 +465,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee8021 - } else - info->control.retries[0].rate_idx = -1; - -- if (tx->sdata->bss_conf.use_cts_prot && -+ if (tx->sdata->vif.bss_conf.use_cts_prot && - (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { - tx->last_frag_rate_idx = tx->rate_idx; - if (rsel.probe_idx >= 0) -@@ -531,7 +531,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_ - if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) && - (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_ERP_G) && - (tx->flags & IEEE80211_TX_UNICAST) && -- tx->sdata->bss_conf.use_cts_prot && -+ tx->sdata->vif.bss_conf.use_cts_prot && - !(info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)) - info->flags |= IEEE80211_TX_CTL_USE_CTS_PROTECT; - -@@ -540,7 +540,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_ - * available on the network at the current point in time. */ - if (ieee80211_is_data(hdr->frame_control) && - (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) && -- tx->sdata->bss_conf.use_short_preamble && -+ tx->sdata->vif.bss_conf.use_short_preamble && - (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) { - info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; - } -@@ -560,7 +560,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_ - for (idx = 0; idx < sband->n_bitrates; idx++) { - if (sband->bitrates[idx].bitrate > rate->bitrate) - continue; -- if (tx->sdata->bss_conf.basic_rates & BIT(idx) && -+ if (tx->sdata->vif.bss_conf.basic_rates & BIT(idx) && - (baserate < 0 || - (sband->bitrates[baserate].bitrate - < sband->bitrates[idx].bitrate))) -@@ -1981,7 +1981,7 @@ struct sk_buff *ieee80211_beacon_get(str - info->flags |= IEEE80211_TX_CTL_NO_ACK; - info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; - info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; -- if (sdata->bss_conf.use_short_preamble && -+ if (sdata->vif.bss_conf.use_short_preamble && - sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) - info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; - ---- everything.orig/net/mac80211/util.c 2008-10-10 17:13:03.000000000 +0200 -+++ everything/net/mac80211/util.c 2008-10-10 17:13:06.000000000 +0200 -@@ -239,7 +239,7 @@ __le16 ieee80211_generic_frame_duration( - erp = 0; - if (vif) { - sdata = vif_to_sdata(vif); -- short_preamble = sdata->bss_conf.use_short_preamble; -+ short_preamble = sdata->vif.bss_conf.use_short_preamble; - if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) - erp = rate->flags & IEEE80211_RATE_ERP_G; - } -@@ -272,7 +272,7 @@ __le16 ieee80211_rts_duration(struct iee - erp = 0; - if (vif) { - sdata = vif_to_sdata(vif); -- short_preamble = sdata->bss_conf.use_short_preamble; -+ short_preamble = sdata->vif.bss_conf.use_short_preamble; - if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) - erp = rate->flags & IEEE80211_RATE_ERP_G; - } -@@ -312,7 +312,7 @@ __le16 ieee80211_ctstoself_duration(stru - erp = 0; - if (vif) { - sdata = vif_to_sdata(vif); -- short_preamble = sdata->bss_conf.use_short_preamble; -+ short_preamble = sdata->vif.bss_conf.use_short_preamble; - if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) - erp = rate->flags & IEEE80211_RATE_ERP_G; - } diff --git a/package/mac80211/patches/424-mac80211-make-retry-limits-available.patch b/package/mac80211/patches/424-mac80211-make-retry-limits-available.patch deleted file mode 100644 index 084ed9a132..0000000000 --- a/package/mac80211/patches/424-mac80211-make-retry-limits-available.patch +++ /dev/null @@ -1,506 +0,0 @@ ---- - drivers/net/wireless/ath9k/main.c | 1 - drivers/net/wireless/b43/main.c | 67 +++++++++++++----------------- - drivers/net/wireless/b43legacy/main.c | 70 ++++++++++++++------------------ - drivers/net/wireless/rt2x00/rt2400pci.c | 2 - drivers/net/wireless/rt2x00/rt2500pci.c | 2 - drivers/net/wireless/rt2x00/rt2x00.h | 3 + - drivers/net/wireless/rt2x00/rt2x00mac.c | 9 ++++ - drivers/net/wireless/rt2x00/rt61pci.c | 2 - drivers/net/wireless/rt2x00/rt73usb.c | 2 - include/net/mac80211.h | 14 ++++-- - net/mac80211/debugfs.c | 4 - - net/mac80211/ieee80211_i.h | 2 - net/mac80211/main.c | 4 - - net/mac80211/tx.c | 4 - - net/mac80211/wext.c | 28 +++++------- - 15 files changed, 106 insertions(+), 108 deletions(-) - ---- everything.orig/include/net/mac80211.h 2008-10-10 23:27:46.000000000 +0200 -+++ everything/include/net/mac80211.h 2008-10-10 23:31:21.000000000 +0200 -@@ -473,6 +473,7 @@ static inline int __deprecated __IEEE802 - * @IEEE80211_CONF_CHANGE_PS: the PS flag changed - * @IEEE80211_CONF_CHANGE_POWER: the TX power changed - * @IEEE80211_CONF_CHANGE_CHANNEL: the channel changed -+ * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed - */ - enum ieee80211_conf_changed { - IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), -@@ -482,6 +483,7 @@ enum ieee80211_conf_changed { - IEEE80211_CONF_CHANGE_PS = BIT(4), - IEEE80211_CONF_CHANGE_POWER = BIT(5), - IEEE80211_CONF_CHANGE_CHANNEL = BIT(6), -+ IEEE80211_CONF_CHANGE_RETRY_LIMITS = BIT(7), - }; - - /** -@@ -497,6 +499,12 @@ enum ieee80211_conf_changed { - * @ht_cap: describes current self configuration of 802.11n HT capabilities - * @ht_bss_conf: describes current BSS configuration of 802.11n HT parameters - * @channel: the channel to tune to -+ * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame -+ * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, -+ * but actually means the number of transmissions not the number of retries -+ * @short_frame_max_tx_count: Maximum number of transmissions for a "short" frame, -+ * called "dot11ShortRetryLimit" in 802.11, but actually means the number -+ * of transmissions not the number of retries - */ - struct ieee80211_conf { - int beacon_int; -@@ -506,6 +514,8 @@ struct ieee80211_conf { - u16 listen_interval; - bool radio_enabled; - -+ u8 long_frame_max_tx_count, short_frame_max_tx_count; -+ - struct ieee80211_channel *channel; - - struct ieee80211_sta_ht_cap ht_cap; -@@ -1192,8 +1202,6 @@ enum ieee80211_ampdu_mlme_action { - * the device does fragmentation by itself; if this method is assigned then - * the stack will not do fragmentation. - * -- * @set_retry_limit: Configuration of retry limits (if device needs it) -- * - * @sta_notify: Notifies low level driver about addition or removal - * of assocaited station or AP. - * -@@ -1263,8 +1271,6 @@ struct ieee80211_ops { - u32 *iv32, u16 *iv16); - int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); - int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value); -- int (*set_retry_limit)(struct ieee80211_hw *hw, -- u32 short_retry, u32 long_retr); - void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - enum sta_notify_cmd, struct ieee80211_sta *sta); - int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, ---- everything.orig/net/mac80211/ieee80211_i.h 2008-10-10 23:27:46.000000000 +0200 -+++ everything/net/mac80211/ieee80211_i.h 2008-10-10 23:31:22.000000000 +0200 -@@ -632,8 +632,6 @@ struct ieee80211_local { - - int rts_threshold; - int fragmentation_threshold; -- int short_retry_limit; /* dot11ShortRetryLimit */ -- int long_retry_limit; /* dot11LongRetryLimit */ - - struct crypto_blkcipher *wep_tx_tfm; - struct crypto_blkcipher *wep_rx_tfm; ---- everything.orig/net/mac80211/main.c 2008-10-10 23:27:46.000000000 +0200 -+++ everything/net/mac80211/main.c 2008-10-10 23:31:22.000000000 +0200 -@@ -673,8 +673,8 @@ struct ieee80211_hw *ieee80211_alloc_hw( - - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; -- local->short_retry_limit = 7; -- local->long_retry_limit = 4; -+ local->hw.conf.long_frame_max_tx_count = 4; -+ local->hw.conf.short_frame_max_tx_count = 7; - local->hw.conf.radio_enabled = true; - - INIT_LIST_HEAD(&local->interfaces); ---- everything.orig/net/mac80211/wext.c 2008-10-10 23:27:46.000000000 +0200 -+++ everything/net/mac80211/wext.c 2008-10-10 23:31:22.000000000 +0200 -@@ -802,21 +802,16 @@ static int ieee80211_ioctl_siwretry(stru - (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) - return -EINVAL; - -- if (retry->flags & IW_RETRY_MAX) -- local->long_retry_limit = retry->value; -- else if (retry->flags & IW_RETRY_MIN) -- local->short_retry_limit = retry->value; -- else { -- local->long_retry_limit = retry->value; -- local->short_retry_limit = retry->value; -+ if (retry->flags & IW_RETRY_MAX) { -+ local->hw.conf.long_frame_max_tx_count = retry->value; -+ } else if (retry->flags & IW_RETRY_MIN) { -+ local->hw.conf.short_frame_max_tx_count = retry->value; -+ } else { -+ local->hw.conf.long_frame_max_tx_count = retry->value; -+ local->hw.conf.short_frame_max_tx_count = retry->value; - } - -- if (local->ops->set_retry_limit) { -- return local->ops->set_retry_limit( -- local_to_hw(local), -- local->short_retry_limit, -- local->long_retry_limit); -- } -+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); - - return 0; - } -@@ -833,14 +828,15 @@ static int ieee80211_ioctl_giwretry(stru - /* first return min value, iwconfig will ask max value - * later if needed */ - retry->flags |= IW_RETRY_LIMIT; -- retry->value = local->short_retry_limit; -- if (local->long_retry_limit != local->short_retry_limit) -+ retry->value = local->hw.conf.short_frame_max_tx_count; -+ if (local->hw.conf.long_frame_max_tx_count != -+ local->hw.conf.short_frame_max_tx_count) - retry->flags |= IW_RETRY_MIN; - return 0; - } - if (retry->flags & IW_RETRY_MAX) { - retry->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; -- retry->value = local->long_retry_limit; -+ retry->value = local->hw.conf.long_frame_max_tx_count; - } - - return 0; ---- everything.orig/drivers/net/wireless/ath9k/main.c 2008-10-10 23:27:47.000000000 +0200 -+++ everything/drivers/net/wireless/ath9k/main.c 2008-10-10 23:31:23.000000000 +0200 -@@ -1657,7 +1657,6 @@ static struct ieee80211_ops ath9k_ops = - .get_tkip_seq = NULL, - .set_rts_threshold = NULL, - .set_frag_threshold = NULL, -- .set_retry_limit = NULL, - .get_tsf = ath9k_get_tsf, - .reset_tsf = ath9k_reset_tsf, - .tx_last_beacon = NULL, ---- everything.orig/drivers/net/wireless/b43/main.c 2008-10-10 23:27:47.000000000 +0200 -+++ everything/drivers/net/wireless/b43/main.c 2008-10-10 23:31:23.000000000 +0200 -@@ -3320,6 +3320,22 @@ init_failure: - return err; - } - -+/* Write the short and long frame retry limit values. */ -+static void b43_set_retry_limits(struct b43_wldev *dev, -+ unsigned int short_retry, -+ unsigned int long_retry) -+{ -+ /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing -+ * the chip-internal counter. */ -+ short_retry = min(short_retry, (unsigned int)0xF); -+ long_retry = min(long_retry, (unsigned int)0xF); -+ -+ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT, -+ short_retry); -+ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT, -+ long_retry); -+} -+ - static int b43_op_config(struct ieee80211_hw *hw, u32 changed) - { - struct b43_wl *wl = hw_to_b43_wl(hw); -@@ -3333,6 +3349,20 @@ static int b43_op_config(struct ieee8021 - - mutex_lock(&wl->mutex); - -+ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { -+ dev = wl->current_dev; -+ if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED))) { -+ err = -ENODEV; -+ goto out_unlock_mutex; -+ } -+ b43_set_retry_limits(dev, conf->short_frame_max_tx_count, -+ conf->long_frame_max_tx_count); -+ changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; -+ } -+ -+ if (!changed) -+ goto out_unlock_mutex; -+ - /* Switch the band (if necessary). This might change the active core. */ - err = b43_switch_band(wl, conf->channel); - if (err) -@@ -3860,22 +3890,6 @@ static void b43_imcfglo_timeouts_workaro - #endif /* CONFIG_SSB_DRIVER_PCICORE */ - } - --/* Write the short and long frame retry limit values. */ --static void b43_set_retry_limits(struct b43_wldev *dev, -- unsigned int short_retry, -- unsigned int long_retry) --{ -- /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing -- * the chip-internal counter. */ -- short_retry = min(short_retry, (unsigned int)0xF); -- long_retry = min(long_retry, (unsigned int)0xF); -- -- b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT, -- short_retry); -- b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT, -- long_retry); --} -- - static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) - { - u16 pu_delay; -@@ -4196,26 +4210,6 @@ static void b43_op_stop(struct ieee80211 - cancel_work_sync(&(wl->txpower_adjust_work)); - } - --static int b43_op_set_retry_limit(struct ieee80211_hw *hw, -- u32 short_retry_limit, u32 long_retry_limit) --{ -- struct b43_wl *wl = hw_to_b43_wl(hw); -- struct b43_wldev *dev; -- int err = 0; -- -- mutex_lock(&wl->mutex); -- dev = wl->current_dev; -- if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED))) { -- err = -ENODEV; -- goto out_unlock; -- } -- b43_set_retry_limits(dev, short_retry_limit, long_retry_limit); --out_unlock: -- mutex_unlock(&wl->mutex); -- -- return err; --} -- - static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, bool set) - { -@@ -4252,7 +4246,6 @@ static const struct ieee80211_ops b43_hw - .get_tx_stats = b43_op_get_tx_stats, - .start = b43_op_start, - .stop = b43_op_stop, -- .set_retry_limit = b43_op_set_retry_limit, - .set_tim = b43_op_beacon_set_tim, - .sta_notify = b43_op_sta_notify, - }; ---- everything.orig/drivers/net/wireless/b43legacy/main.c 2008-10-10 23:27:47.000000000 +0200 -+++ everything/drivers/net/wireless/b43legacy/main.c 2008-10-10 23:31:23.000000000 +0200 -@@ -2556,6 +2556,20 @@ init_failure: - return err; - } - -+/* Write the short and long frame retry limit values. */ -+static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev, -+ unsigned int short_retry, -+ unsigned int long_retry) -+{ -+ /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing -+ * the chip-internal counter. */ -+ short_retry = min(short_retry, (unsigned int)0xF); -+ long_retry = min(long_retry, (unsigned int)0xF); -+ -+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry); -+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry); -+} -+ - static int b43legacy_op_dev_config(struct ieee80211_hw *hw, - u32 changed) - { -@@ -2570,10 +2584,27 @@ static int b43legacy_op_dev_config(struc - int err = 0; - u32 savedirqs; - -+ mutex_lock(&wl->mutex); -+ dev = wl->current_dev; -+ -+ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { -+ if (unlikely(!dev || -+ (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED))) { -+ err = -ENODEV; -+ goto out_unlock_mutex; -+ } -+ b43legacy_set_retry_limits(dev, -+ conf->short_frame_max_tx_count, -+ conf->long_frame_max_tx_count); -+ changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; -+ } -+ -+ if (!changed) -+ goto out_unlock_mutex; -+ - antenna_tx = B43legacy_ANTENNA_DEFAULT; - antenna_rx = B43legacy_ANTENNA_DEFAULT; - -- mutex_lock(&wl->mutex); - dev = wl->current_dev; - phy = &dev->phy; - -@@ -2989,20 +3020,6 @@ static void b43legacy_imcfglo_timeouts_w - #endif /* CONFIG_SSB_DRIVER_PCICORE */ - } - --/* Write the short and long frame retry limit values. */ --static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev, -- unsigned int short_retry, -- unsigned int long_retry) --{ -- /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing -- * the chip-internal counter. */ -- short_retry = min(short_retry, (unsigned int)0xF); -- long_retry = min(long_retry, (unsigned int)0xF); -- -- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry); -- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry); --} -- - static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev, - bool idle) { - u16 pu_delay = 1050; -@@ -3367,28 +3384,6 @@ static void b43legacy_op_stop(struct iee - mutex_unlock(&wl->mutex); - } - --static int b43legacy_op_set_retry_limit(struct ieee80211_hw *hw, -- u32 short_retry_limit, -- u32 long_retry_limit) --{ -- struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); -- struct b43legacy_wldev *dev; -- int err = 0; -- -- mutex_lock(&wl->mutex); -- dev = wl->current_dev; -- if (unlikely(!dev || -- (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED))) { -- err = -ENODEV; -- goto out_unlock; -- } -- b43legacy_set_retry_limits(dev, short_retry_limit, long_retry_limit); --out_unlock: -- mutex_unlock(&wl->mutex); -- -- return err; --} -- - static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, bool set) - { -@@ -3414,7 +3409,6 @@ static const struct ieee80211_ops b43leg - .get_tx_stats = b43legacy_op_get_tx_stats, - .start = b43legacy_op_start, - .stop = b43legacy_op_stop, -- .set_retry_limit = b43legacy_op_set_retry_limit, - .set_tim = b43legacy_op_beacon_set_tim, - }; - ---- everything.orig/drivers/net/wireless/rt2x00/rt2400pci.c 2008-10-10 23:27:46.000000000 +0200 -+++ everything/drivers/net/wireless/rt2x00/rt2400pci.c 2008-10-10 23:27:48.000000000 +0200 -@@ -1576,7 +1576,6 @@ static const struct ieee80211_ops rt2400 - .config_interface = rt2x00mac_config_interface, - .configure_filter = rt2x00mac_configure_filter, - .get_stats = rt2x00mac_get_stats, -- .set_retry_limit = rt2400pci_set_retry_limit, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt2400pci_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, -@@ -1605,6 +1604,7 @@ static const struct rt2x00lib_ops rt2400 - .config_intf = rt2400pci_config_intf, - .config_erp = rt2400pci_config_erp, - .config = rt2400pci_config, -+ .set_retry_limit = rt2400pci_set_retry_limit, - }; - - static const struct data_queue_desc rt2400pci_queue_rx = { ---- everything.orig/drivers/net/wireless/rt2x00/rt2x00.h 2008-10-10 23:27:47.000000000 +0200 -+++ everything/drivers/net/wireless/rt2x00/rt2x00.h 2008-10-10 23:27:48.000000000 +0200 -@@ -599,6 +599,9 @@ struct rt2x00lib_ops { - #define CONFIG_UPDATE_SLOT_TIME ( 1 << 5 ) - #define CONFIG_UPDATE_BEACON_INT ( 1 << 6 ) - #define CONFIG_UPDATE_ALL 0xffff -+ -+ int (*set_retry_limit) (struct ieee80211_hw *hw, -+ u32 short_limit, u32 long_limit); - }; - - /* ---- everything.orig/drivers/net/wireless/rt2x00/rt2500pci.c 2008-10-10 23:27:46.000000000 +0200 -+++ everything/drivers/net/wireless/rt2x00/rt2500pci.c 2008-10-10 23:27:48.000000000 +0200 -@@ -1877,7 +1877,6 @@ static const struct ieee80211_ops rt2500 - .config_interface = rt2x00mac_config_interface, - .configure_filter = rt2x00mac_configure_filter, - .get_stats = rt2x00mac_get_stats, -- .set_retry_limit = rt2500pci_set_retry_limit, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt2x00mac_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, -@@ -1906,6 +1905,7 @@ static const struct rt2x00lib_ops rt2500 - .config_intf = rt2500pci_config_intf, - .config_erp = rt2500pci_config_erp, - .config = rt2500pci_config, -+ .set_retry_limit = rt2500pci_set_retry_limit, - }; - - static const struct data_queue_desc rt2500pci_queue_rx = { ---- everything.orig/drivers/net/wireless/rt2x00/rt61pci.c 2008-10-10 23:27:47.000000000 +0200 -+++ everything/drivers/net/wireless/rt2x00/rt61pci.c 2008-10-10 23:27:48.000000000 +0200 -@@ -2726,7 +2726,6 @@ static const struct ieee80211_ops rt61pc - .configure_filter = rt2x00mac_configure_filter, - .set_key = rt2x00mac_set_key, - .get_stats = rt2x00mac_get_stats, -- .set_retry_limit = rt61pci_set_retry_limit, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt61pci_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, -@@ -2759,6 +2758,7 @@ static const struct rt2x00lib_ops rt61pc - .config_intf = rt61pci_config_intf, - .config_erp = rt61pci_config_erp, - .config = rt61pci_config, -+ .set_retry_limit = rt61pci_set_retry_limit, - }; - - static const struct data_queue_desc rt61pci_queue_rx = { ---- everything.orig/drivers/net/wireless/rt2x00/rt73usb.c 2008-10-10 23:27:47.000000000 +0200 -+++ everything/drivers/net/wireless/rt2x00/rt73usb.c 2008-10-10 23:27:48.000000000 +0200 -@@ -2317,7 +2317,6 @@ static const struct ieee80211_ops rt73us - .configure_filter = rt2x00mac_configure_filter, - .set_key = rt2x00mac_set_key, - .get_stats = rt2x00mac_get_stats, -- .set_retry_limit = rt73usb_set_retry_limit, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt73usb_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, -@@ -2349,6 +2348,7 @@ static const struct rt2x00lib_ops rt73us - .config_intf = rt73usb_config_intf, - .config_erp = rt73usb_config_erp, - .config = rt73usb_config, -+ .set_retry_limit = rt73usb_set_retry_limit, - }; - - static const struct data_queue_desc rt73usb_queue_rx = { ---- everything.orig/drivers/net/wireless/rt2x00/rt2x00mac.c 2008-10-10 23:27:46.000000000 +0200 -+++ everything/drivers/net/wireless/rt2x00/rt2x00mac.c 2008-10-10 23:31:23.000000000 +0200 -@@ -349,6 +349,15 @@ int rt2x00mac_config(struct ieee80211_hw - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return 0; - -+ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { -+ rt2x00dev->ops->lib->set_retry_limit(hw, -+ conf->short_frame_max_tx_count, -+ conf->long_frame_max_tx_count); -+ } -+ changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; -+ if (!changed) -+ return 0; -+ - /* - * Only change device state when the radio is enabled. It does not - * matter what parameters we have configured when the radio is disabled ---- everything.orig/net/mac80211/debugfs.c 2008-10-10 23:27:46.000000000 +0200 -+++ everything/net/mac80211/debugfs.c 2008-10-10 23:27:48.000000000 +0200 -@@ -52,9 +52,9 @@ DEBUGFS_READONLY_FILE(rts_threshold, 20, - DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", - local->fragmentation_threshold); - DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", -- local->short_retry_limit); -+ local->hw.conf.short_frame_max_tx_count); - DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", -- local->long_retry_limit); -+ local->hw.conf.long_frame_max_tx_count); - DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", - local->total_ps_buffered); - DEBUGFS_READONLY_FILE(wep_iv, 20, "%#06x", ---- everything.orig/net/mac80211/tx.c 2008-10-10 23:27:46.000000000 +0200 -+++ everything/net/mac80211/tx.c 2008-10-10 23:31:22.000000000 +0200 -@@ -507,10 +507,10 @@ ieee80211_tx_h_misc(struct ieee80211_tx_ - info->flags |= - IEEE80211_TX_CTL_LONG_RETRY_LIMIT; - info->control.retry_limit = -- tx->local->long_retry_limit; -+ tx->local->hw.conf.long_frame_max_tx_count - 1; - } else { - info->control.retry_limit = -- tx->local->short_retry_limit; -+ tx->local->hw.conf.short_frame_max_tx_count - 1; - } - } else { - info->control.retry_limit = 1; diff --git a/package/mac80211/patches/425-rewrite-rate-api.patch b/package/mac80211/patches/425-rewrite-rate-api.patch deleted file mode 100644 index c0652a0b0d..0000000000 --- a/package/mac80211/patches/425-rewrite-rate-api.patch +++ /dev/null @@ -1,3005 +0,0 @@ -Subject: mac80211/drivers: rewrite the rate control API - -So after the previous changes we were still unhappy with how -convoluted the API is and decided to make things simpler for -everybody. This completely changes the rate control API, now -taking into account 802.11n with MCS rates and more control, -most drivers don't support that though. - -Signed-off-by: Felix Fietkau <nbd@openwrt.org> -Signed-off-by: Johannes Berg <johannes@sipsolutions.net> ---- - drivers/net/wireless/adm8211.c | 21 - - drivers/net/wireless/ath5k/base.c | 34 +- - drivers/net/wireless/ath9k/main.c | 18 - - drivers/net/wireless/ath9k/rc.c | 40 +-- - drivers/net/wireless/ath9k/xmit.c | 28 +- - drivers/net/wireless/b43/dma.c | 4 - drivers/net/wireless/b43/main.c | 2 - drivers/net/wireless/b43/pio.c | 4 - drivers/net/wireless/b43/xmit.c | 60 +++- - drivers/net/wireless/b43/xmit.h | 5 - drivers/net/wireless/b43legacy/dma.c | 46 ++- - drivers/net/wireless/b43legacy/main.c | 2 - drivers/net/wireless/b43legacy/pio.c | 31 ++ - drivers/net/wireless/b43legacy/xmit.c | 26 +- - drivers/net/wireless/b43legacy/xmit.h | 2 - drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 57 +--- - drivers/net/wireless/iwlwifi/iwl-3945.c | 62 ++++- - drivers/net/wireless/iwlwifi/iwl-3945.h | 2 - drivers/net/wireless/iwlwifi/iwl-4965.c | 8 - drivers/net/wireless/iwlwifi/iwl-5000.c | 8 - drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 37 +- - drivers/net/wireless/iwlwifi/iwl-core.c | 19 - - drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 - drivers/net/wireless/libertas_tf/main.c | 4 - drivers/net/wireless/mac80211_hwsim.c | 12 - drivers/net/wireless/p54/p54common.c | 16 - - drivers/net/wireless/rt2x00/rt2x00dev.c | 11 - drivers/net/wireless/rt2x00/rt2x00mac.c | 14 - - drivers/net/wireless/rt2x00/rt2x00queue.c | 11 - drivers/net/wireless/rtl8180_dev.c | 28 +- - drivers/net/wireless/rtl8187_dev.c | 10 - drivers/net/wireless/zd1211rw/zd_mac.c | 28 +- - include/net/mac80211.h | 206 +++++++++------- - net/mac80211/ieee80211_i.h | 8 - net/mac80211/main.c | 54 +++- - net/mac80211/mesh_hwmp.c | 6 - net/mac80211/rate.c | 50 +--- - net/mac80211/rate.h | 5 - net/mac80211/rc80211_minstrel.c | 72 ++--- - net/mac80211/rc80211_pid.h | 1 - net/mac80211/rc80211_pid_algo.c | 26 +- - net/mac80211/rc80211_pid_debugfs.c | 5 - net/mac80211/sta_info.h | 4 - net/mac80211/tx.c | 347 +++++++++++----------------- - net/mac80211/wext.c | 4 - 45 files changed, 781 insertions(+), 662 deletions(-) - ---- a/include/net/mac80211.h -+++ b/include/net/mac80211.h -@@ -222,29 +222,24 @@ struct ieee80211_bss_conf { - * These flags are used with the @flags member of &ieee80211_tx_info. - * - * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame. -- * @IEEE80211_TX_CTL_USE_RTS_CTS: use RTS-CTS before sending frame -- * @IEEE80211_TX_CTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g., -- * for combined 802.11g / 802.11b networks) -+ * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence -+ * number to this frame, taking care of not overwriting the fragment -+ * number and increasing the sequence number only when the -+ * IEEE80211_TX_CTL_FIRST_FRAGMENT flags is set. mac80211 will properly -+ * assign sequence numbers to QoS-data frames but cannot do so correctly -+ * for non-QoS-data and management frames because beacons need them from -+ * that counter as well and mac80211 cannot guarantee proper sequencing. -+ * If this flag is set, the driver should instruct the hardware to -+ * assign a sequence number to the frame or assign one itself. Cf. IEEE -+ * 802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for -+ * beacons always be clear for frames without a sequence number field. - * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack -- * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: TBD - * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination - * station -- * @IEEE80211_TX_CTL_REQUEUE: TBD - * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame -- * @IEEE80211_TX_CTL_SHORT_PREAMBLE: TBD -- * @IEEE80211_TX_CTL_LONG_RETRY_LIMIT: this frame should be send using the -- * through set_retry_limit configured long retry value - * @IEEE80211_TX_CTL_SEND_AFTER_DTIM: send this frame after DTIM beacon - * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU -- * @IEEE80211_TX_CTL_OFDM_HT: this frame can be sent in HT OFDM rates. number -- * of streams when this flag is on can be extracted from antenna_sel_tx, -- * so if 1 antenna is marked use SISO, 2 antennas marked use MIMO, n -- * antennas marked use MIMO_n. -- * @IEEE80211_TX_CTL_GREEN_FIELD: use green field protection for this frame -- * @IEEE80211_TX_CTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width -- * @IEEE80211_TX_CTL_DUP_DATA: duplicate data frame on both 20 Mhz channels -- * @IEEE80211_TX_CTL_SHORT_GI: send this frame using short guard interval -- * @IEEE80211_TX_CTL_INJECTED: TBD -+ * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211. - * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted - * because the destination STA was in powersave mode. - * @IEEE80211_TX_STAT_ACK: Frame was acknowledged -@@ -252,42 +247,41 @@ struct ieee80211_bss_conf { - * is for the whole aggregation. - * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned, - * so consider using block ack request (BAR). -- * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence -- * number to this frame, taking care of not overwriting the fragment -- * number and increasing the sequence number only when the -- * IEEE80211_TX_CTL_FIRST_FRAGMENT flags is set. mac80211 will properly -- * assign sequence numbers to QoS-data frames but cannot do so correctly -- * for non-QoS-data and management frames because beacons need them from -- * that counter as well and mac80211 cannot guarantee proper sequencing. -- * If this flag is set, the driver should instruct the hardware to -- * assign a sequence number to the frame or assign one itself. Cf. IEEE -- * 802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for -- * beacons always be clear for frames without a sequence number field. -+ * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be -+ * set by rate control algorithms to indicate probe rate, will -+ * be cleared for fragmented frames (except on the last fragment) -+ * @IEEE80211_TX_CTL_REQUEUE: REMOVE THIS - */ - enum mac80211_tx_control_flags { - IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), -- IEEE80211_TX_CTL_USE_RTS_CTS = BIT(2), -- IEEE80211_TX_CTL_USE_CTS_PROTECT = BIT(3), -- IEEE80211_TX_CTL_NO_ACK = BIT(4), -- IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(5), -- IEEE80211_TX_CTL_CLEAR_PS_FILT = BIT(6), -- IEEE80211_TX_CTL_REQUEUE = BIT(7), -- IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(8), -- IEEE80211_TX_CTL_SHORT_PREAMBLE = BIT(9), -- IEEE80211_TX_CTL_LONG_RETRY_LIMIT = BIT(10), -- IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(12), -- IEEE80211_TX_CTL_AMPDU = BIT(13), -- IEEE80211_TX_CTL_OFDM_HT = BIT(14), -- IEEE80211_TX_CTL_GREEN_FIELD = BIT(15), -- IEEE80211_TX_CTL_40_MHZ_WIDTH = BIT(16), -- IEEE80211_TX_CTL_DUP_DATA = BIT(17), -- IEEE80211_TX_CTL_SHORT_GI = BIT(18), -- IEEE80211_TX_CTL_INJECTED = BIT(19), -- IEEE80211_TX_STAT_TX_FILTERED = BIT(20), -- IEEE80211_TX_STAT_ACK = BIT(21), -- IEEE80211_TX_STAT_AMPDU = BIT(22), -- IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(23), -- IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(24), -+ IEEE80211_TX_CTL_ASSIGN_SEQ = BIT(1), -+ IEEE80211_TX_CTL_NO_ACK = BIT(2), -+ IEEE80211_TX_CTL_CLEAR_PS_FILT = BIT(3), -+ IEEE80211_TX_CTL_FIRST_FRAGMENT = BIT(4), -+ IEEE80211_TX_CTL_SEND_AFTER_DTIM = BIT(5), -+ IEEE80211_TX_CTL_AMPDU = BIT(6), -+ IEEE80211_TX_CTL_INJECTED = BIT(7), -+ IEEE80211_TX_STAT_TX_FILTERED = BIT(8), -+ IEEE80211_TX_STAT_ACK = BIT(9), -+ IEEE80211_TX_STAT_AMPDU = BIT(10), -+ IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), -+ IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), -+ -+ /* XXX: remove this */ -+ IEEE80211_TX_CTL_REQUEUE = BIT(13), -+}; -+ -+enum mac80211_rate_control_flags { -+ IEEE80211_TX_RC_USE_RTS_CTS = BIT(0), -+ IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1), -+ IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2), -+ -+ /* rate index is an MCS rate number instead of an index */ -+ IEEE80211_TX_RC_MCS = BIT(3), -+ IEEE80211_TX_RC_GREEN_FIELD = BIT(4), -+ IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5), -+ IEEE80211_TX_RC_DUP_DATA = BIT(6), -+ IEEE80211_TX_RC_SHORT_GI = BIT(7), - }; - - -@@ -296,18 +290,26 @@ enum mac80211_tx_control_flags { - #define IEEE80211_TX_INFO_DRIVER_DATA_PTRS \ - (IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)) - --/* maximum number of alternate rate retry stages */ --#define IEEE80211_TX_MAX_ALTRATE 3 -+/* maximum number of rate stages */ -+#define IEEE80211_TX_MAX_RATES 4 - - /** -- * struct ieee80211_tx_altrate - alternate rate selection/status -+ * struct ieee80211_tx_rate - rate selection/status - * -- * @rate_idx: rate index to attempt to send with -+ * @idx: rate index to attempt to send with -+ * @flags: rate control flags (&enum mac80211_rate_control_flags) - * @limit: number of retries before fallback -+ * -+ * A value of -1 for @idx indicates an invalid rate and, if used -+ * in an array of retry rates, that no more rates should be tried. -+ * -+ * When used for transmit status reporting, the driver should -+ * always report the rate along with the flags it used. - */ --struct ieee80211_tx_altrate { -- s8 rate_idx; -- u8 limit; -+struct ieee80211_tx_rate { -+ s8 idx; -+ u8 count; -+ u8 flags; - }; - - /** -@@ -322,15 +324,12 @@ struct ieee80211_tx_altrate { - * it may be NULL. - * - * @flags: transmit info flags, defined above -- * @band: TBD -- * @tx_rate_idx: TBD -+ * @band: the band to transmit on (use for checking for races) - * @antenna_sel_tx: antenna to use, 0 for automatic diversity - * @control: union for control data - * @status: union for status data - * @driver_data: array of driver_data pointers - * @retry_count: number of retries -- * @excessive_retries: set to 1 if the frame was retried many times -- * but not acknowledged - * @ampdu_ack_len: number of aggregated frames. - * relevant only if IEEE80211_TX_STATUS_AMPDU was set. - * @ampdu_ack_map: block ack bit map for the aggregation. -@@ -341,28 +340,28 @@ struct ieee80211_tx_info { - /* common information */ - u32 flags; - u8 band; -- s8 tx_rate_idx; -+ - u8 antenna_sel_tx; - -- /* 1 byte hole */ -+ /* 2 byte hole */ - - union { - struct { -+ union { -+ struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; -+ /* we need the jiffies only before rate control */ -+ unsigned long jiffies; -+ }; -+ s8 rts_cts_rate_idx; - /* NB: vif can be NULL for injected frames */ - struct ieee80211_vif *vif; - struct ieee80211_key_conf *hw_key; - struct ieee80211_sta *sta; -- unsigned long jiffies; -- s8 rts_cts_rate_idx; -- u8 retry_limit; -- struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE]; - } control; - struct { -+ struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; - u64 ampdu_ack_map; - int ack_signal; -- struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE + 1]; -- u8 retry_count; -- bool excessive_retries; - u8 ampdu_ack_len; - } status; - void *driver_data[IEEE80211_TX_INFO_DRIVER_DATA_PTRS]; -@@ -374,6 +373,22 @@ static inline struct ieee80211_tx_info * - return (struct ieee80211_tx_info *)skb->cb; - } - -+static inline void -+ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) -+{ -+ int i; -+ -+ BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, status.rates) != -+ offsetof(struct ieee80211_tx_info, control.rates)); -+ /* clear the rate counts */ -+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) -+ info->status.rates[i].count = 0; -+ -+ memset(&info->status.ampdu_ack_map, 0, -+ sizeof(struct ieee80211_tx_info) - -+ offsetof(struct ieee80211_tx_info, status.ampdu_ack_map)); -+} -+ - - /** - * enum mac80211_rx_flags - receive flags -@@ -875,8 +890,8 @@ enum ieee80211_hw_flags { - * @sta_data_size: size (in bytes) of the drv_priv data area - * within &struct ieee80211_sta. - * -- * @max_altrates: maximum number of alternate rate retry stages -- * @max_altrate_tries: maximum number of tries for each stage -+ * @max_rates: maximum number of alternate rate retry stages -+ * @max_rate_tries: maximum number of tries for each stage - */ - struct ieee80211_hw { - struct ieee80211_conf conf; -@@ -893,8 +908,8 @@ struct ieee80211_hw { - u16 ampdu_queues; - u16 max_listen_interval; - s8 max_signal; -- u8 max_altrates; -- u8 max_altrate_tries; -+ u8 max_rates; -+ u8 max_rate_tries; - }; - - /** -@@ -933,9 +948,9 @@ static inline struct ieee80211_rate * - ieee80211_get_tx_rate(const struct ieee80211_hw *hw, - const struct ieee80211_tx_info *c) - { -- if (WARN_ON(c->tx_rate_idx < 0)) -+ if (WARN_ON(c->control.rates[0].idx < 0)) - return NULL; -- return &hw->wiphy->bands[c->band]->bitrates[c->tx_rate_idx]; -+ return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[0].idx]; - } - - static inline struct ieee80211_rate * -@@ -951,9 +966,9 @@ static inline struct ieee80211_rate * - ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, - const struct ieee80211_tx_info *c, int idx) - { -- if (c->control.retries[idx].rate_idx < 0) -+ if (c->control.rates[idx + 1].idx < 0) - return NULL; -- return &hw->wiphy->bands[c->band]->bitrates[c->control.retries[idx].rate_idx]; -+ return &hw->wiphy->bands[c->band]->bitrates[c->control.rates[idx + 1].idx]; - } - - /** -@@ -1847,17 +1862,28 @@ struct ieee80211_sta *ieee80211_find_sta - - - /* Rate control API */ -+ - /** -- * struct rate_selection - rate information for/from rate control algorithms -+ * struct ieee80211_tx_rate_control - rate control information for/from RC algo - * -- * @rate_idx: selected transmission rate index -- * @nonerp_idx: Non-ERP rate to use instead if ERP cannot be used -- * @probe_idx: rate for probing (or -1) -- * @max_rate_idx: maximum rate index that can be used, this is -- * input to the algorithm and will be enforced -- */ --struct rate_selection { -- s8 rate_idx, nonerp_idx, probe_idx, max_rate_idx; -+ * @sband: The band this frame is being transmitted on. -+ * @bss_conf: the current BSS configuration -+ * @reported_rate: The rate control algorithm can fill this in to indicate -+ * which rate should be reported to userspace as the current rate and -+ * used for rate calculations in the mesh network. -+ * @rts: whether RTS will be used for this frame because it is longer than the -+ * RTS threshold -+ * @short_preamble: whether mac80211 will request short-preamble transmission -+ * if the selected rate supports it -+ * @max_rate_idx: user-requested maximum rate (not MCS for now) -+ */ -+struct ieee80211_tx_rate_control { -+ struct ieee80211_supported_band *sband; -+ struct ieee80211_bss_conf *bss_conf; -+ struct sk_buff *skb; -+ struct ieee80211_tx_rate reported_rate; -+ bool rts, short_preamble; -+ u8 max_rate_idx; - }; - - struct rate_control_ops { -@@ -1876,10 +1902,8 @@ struct rate_control_ops { - void (*tx_status)(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb); -- void (*get_rate)(void *priv, struct ieee80211_supported_band *sband, -- struct ieee80211_sta *sta, void *priv_sta, -- struct sk_buff *skb, -- struct rate_selection *sel); -+ void (*get_rate)(void *priv, struct ieee80211_sta *sta, void *priv_sta, -+ struct ieee80211_tx_rate_control *txrc); - - void (*add_sta_debugfs)(void *priv, void *priv_sta, - struct dentry *dir); ---- a/net/mac80211/main.c -+++ b/net/mac80211/main.c -@@ -41,6 +41,8 @@ - */ - struct ieee80211_tx_status_rtap_hdr { - struct ieee80211_radiotap_header hdr; -+ u8 rate; -+ u8 padding_for_rate; - __le16 tx_flags; - u8 data_retries; - } __attribute__ ((packed)); -@@ -463,13 +465,28 @@ void ieee80211_tx_status(struct ieee8021 - struct ieee80211_sub_if_data *sdata; - struct net_device *prev_dev = NULL; - struct sta_info *sta; -+ int retry_count = -1, i; -+ -+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { -+ /* the HW cannot have attempted that rate */ -+ if (i >= hw->max_rates) { -+ info->status.rates[i].idx = -1; -+ info->status.rates[i].count = 0; -+ } -+ -+ retry_count += info->status.rates[i].count; -+ } -+ if (retry_count < 0) -+ retry_count = 0; - - rcu_read_lock(); - -+ sband = local->hw.wiphy->bands[info->band]; -+ - sta = sta_info_get(local, hdr->addr1); - - if (sta) { -- if (info->status.excessive_retries && -+ if (!(info->flags & IEEE80211_TX_STAT_ACK) && - test_sta_flags(sta, WLAN_STA_PS)) { - /* - * The STA is in power save mode, so assume -@@ -500,12 +517,11 @@ void ieee80211_tx_status(struct ieee8021 - rcu_read_unlock(); - return; - } else { -- if (info->status.excessive_retries) -+ if (!(info->flags & IEEE80211_TX_STAT_ACK)) - sta->tx_retry_failed++; -- sta->tx_retry_count += info->status.retry_count; -+ sta->tx_retry_count += retry_count; - } - -- sband = local->hw.wiphy->bands[info->band]; - rate_control_tx_status(local, sband, sta, skb); - } - -@@ -526,9 +542,9 @@ void ieee80211_tx_status(struct ieee8021 - local->dot11TransmittedFrameCount++; - if (is_multicast_ether_addr(hdr->addr1)) - local->dot11MulticastTransmittedFrameCount++; -- if (info->status.retry_count > 0) -+ if (retry_count > 0) - local->dot11RetryCount++; -- if (info->status.retry_count > 1) -+ if (retry_count > 1) - local->dot11MultipleRetryCount++; - } - -@@ -572,19 +588,30 @@ void ieee80211_tx_status(struct ieee8021 - rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); - rthdr->hdr.it_present = - cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | -- (1 << IEEE80211_RADIOTAP_DATA_RETRIES)); -+ (1 << IEEE80211_RADIOTAP_DATA_RETRIES) | -+ (1 << IEEE80211_RADIOTAP_RATE)); - - if (!(info->flags & IEEE80211_TX_STAT_ACK) && - !is_multicast_ether_addr(hdr->addr1)) - rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); - -- if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) && -- (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) -+ /* -+ * XXX: Once radiotap gets the bitmap reset thing the vendor -+ * extensions proposal contains, we can actually report -+ * the whole set of tries we did. -+ */ -+ if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || -+ (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) - rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); -- else if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) -+ else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); -+ if (info->status.rates[0].idx >= 0 && -+ !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) -+ rthdr->rate = sband->bitrates[ -+ info->status.rates[0].idx].bitrate / 5; - -- rthdr->data_retries = info->status.retry_count; -+ /* for now report the total retry_count */ -+ rthdr->data_retries = retry_count; - - /* XXX: is this sufficient for BPF? */ - skb_set_mac_header(skb, 0); -@@ -669,8 +696,9 @@ struct ieee80211_hw *ieee80211_alloc_hw( - BUG_ON(!ops->configure_filter); - local->ops = ops; - -- local->hw.queues = 1; /* default */ -- -+ /* set up some defaults */ -+ local->hw.queues = 1; -+ local->hw.max_rates = 1; - local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; - local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - local->hw.conf.long_frame_max_tx_count = 4; ---- a/net/mac80211/tx.c -+++ b/net/mac80211/tx.c -@@ -46,13 +46,20 @@ static __le16 ieee80211_duration(struct - struct ieee80211_local *local = tx->local; - struct ieee80211_supported_band *sband; - struct ieee80211_hdr *hdr; -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); -+ -+ /* assume HW handles this */ -+ if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) -+ return 0; -+ -+ /* uh huh? */ -+ if (WARN_ON(info->control.rates[0].idx < 0)) -+ return 0; - - sband = local->hw.wiphy->bands[tx->channel->band]; -- txrate = &sband->bitrates[tx->rate_idx]; -+ txrate = &sband->bitrates[info->control.rates[0].idx]; - -- erp = 0; -- if (tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) -- erp = txrate->flags & IEEE80211_RATE_ERP_G; -+ erp = txrate->flags & IEEE80211_RATE_ERP_G; - - /* - * data and mgmt (except PS Poll): -@@ -439,140 +446,123 @@ ieee80211_tx_h_select_key(struct ieee802 - static ieee80211_tx_result debug_noinline - ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) - { -- struct rate_selection rsel; -- struct ieee80211_supported_band *sband; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); -+ struct ieee80211_hdr *hdr = (void *)tx->skb->data; -+ struct ieee80211_supported_band *sband; -+ struct ieee80211_rate *rate; -+ int i, len; -+ bool inval = false, rts = false, short_preamble = false; -+ struct ieee80211_tx_rate_control txrc; - -- sband = tx->local->hw.wiphy->bands[tx->channel->band]; -+ memset(&txrc, 0, sizeof(txrc)); - -- if (likely(tx->rate_idx < 0)) { -- rate_control_get_rate(tx->sdata, sband, tx->sta, -- tx->skb, &rsel); -- if (tx->sta) -- tx->sta->last_txrate_idx = rsel.rate_idx; -- tx->rate_idx = rsel.rate_idx; -- if (unlikely(rsel.probe_idx >= 0)) { -- info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; -- tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; -- info->control.retries[0].rate_idx = tx->rate_idx; -- info->control.retries[0].limit = tx->local->hw.max_altrate_tries; -- tx->rate_idx = rsel.probe_idx; -- } else if (info->control.retries[0].limit == 0) -- info->control.retries[0].rate_idx = -1; -+ sband = tx->local->hw.wiphy->bands[tx->channel->band]; - -- if (unlikely(tx->rate_idx < 0)) -- return TX_DROP; -- } else -- info->control.retries[0].rate_idx = -1; -+ len = min_t(int, tx->skb->len + FCS_LEN, -+ tx->local->fragmentation_threshold); - -- if (tx->sdata->vif.bss_conf.use_cts_prot && -- (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { -- tx->last_frag_rate_idx = tx->rate_idx; -- if (rsel.probe_idx >= 0) -- tx->flags &= ~IEEE80211_TX_PROBE_LAST_FRAG; -- else -- tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; -- tx->rate_idx = rsel.nonerp_idx; -- info->tx_rate_idx = rsel.nonerp_idx; -- info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; -- } else { -- tx->last_frag_rate_idx = tx->rate_idx; -- info->tx_rate_idx = tx->rate_idx; -+ /* set up the tx rate control struct we give the RC algo */ -+ txrc.sband = sband; -+ txrc.bss_conf = &tx->sdata->vif.bss_conf; -+ txrc.skb = tx->skb; -+ txrc.reported_rate.idx = -1; -+ txrc.max_rate_idx = tx->sdata->max_ratectrl_rateidx; -+ -+ /* set up RTS protection if desired */ -+ if (tx->local->rts_threshold < IEEE80211_MAX_RTS_THRESHOLD && -+ len > tx->local->rts_threshold) { -+ txrc.rts = rts = true; - } -- info->tx_rate_idx = tx->rate_idx; - -- return TX_CONTINUE; --} -+ /* XXX: Is this really the right thing to check? */ -+ if (ieee80211_is_data(hdr->frame_control) && -+ tx->sdata->vif.bss_conf.use_short_preamble && -+ (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) -+ txrc.short_preamble = short_preamble = true; - --static ieee80211_tx_result debug_noinline --ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) --{ -- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; -- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); -- struct ieee80211_supported_band *sband; - -- sband = tx->local->hw.wiphy->bands[tx->channel->band]; -+ rate_control_get_rate(tx->sdata, tx->sta, &txrc); -+ -+ if (unlikely(info->control.rates[0].idx < 0)) -+ return TX_DROP; -+ -+ if (txrc.reported_rate.idx < 0) -+ txrc.reported_rate = info->control.rates[0]; - - if (tx->sta) -- info->control.sta = &tx->sta->sta; -+ tx->sta->last_tx_rate = txrc.reported_rate; - -- if (!info->control.retry_limit) { -- if (!is_multicast_ether_addr(hdr->addr1)) { -- int len = min_t(int, tx->skb->len + FCS_LEN, -- tx->local->fragmentation_threshold); -- if (len > tx->local->rts_threshold -- && tx->local->rts_threshold < -- IEEE80211_MAX_RTS_THRESHOLD) { -- info->flags |= IEEE80211_TX_CTL_USE_RTS_CTS; -- info->flags |= -- IEEE80211_TX_CTL_LONG_RETRY_LIMIT; -- info->control.retry_limit = -- tx->local->hw.conf.long_frame_max_tx_count - 1; -- } else { -- info->control.retry_limit = -- tx->local->hw.conf.short_frame_max_tx_count - 1; -- } -- } else { -- info->control.retry_limit = 1; -- } -- } -+ if (unlikely(!info->control.rates[0].count)) -+ info->control.rates[0].count = 1; - -- if (tx->flags & IEEE80211_TX_FRAGMENTED) { -- /* Do not use multiple retry rates when sending fragmented -- * frames. -- * TODO: The last fragment could still use multiple retry -- * rates. */ -- info->control.retries[0].rate_idx = -1; -- } -- -- /* Use CTS protection for unicast frames sent using extended rates if -- * there are associated non-ERP stations and RTS/CTS is not configured -- * for the frame. */ -- if ((tx->sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) && -- (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_ERP_G) && -- (tx->flags & IEEE80211_TX_UNICAST) && -- tx->sdata->vif.bss_conf.use_cts_prot && -- !(info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)) -- info->flags |= IEEE80211_TX_CTL_USE_CTS_PROTECT; -- -- /* Transmit data frames using short preambles if the driver supports -- * short preambles at the selected rate and short preambles are -- * available on the network at the current point in time. */ -- if (ieee80211_is_data(hdr->frame_control) && -- (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) && -- tx->sdata->vif.bss_conf.use_short_preamble && -- (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) { -- info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; -+ if (is_multicast_ether_addr(hdr->addr1)) { -+ /* -+ * XXX: verify the rate is in the basic rateset -+ */ -+ return TX_CONTINUE; - } - -- if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || -- (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { -- struct ieee80211_rate *rate; -- s8 baserate = -1; -- int idx; -+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { -+ /* -+ * make sure there's no valid rate following -+ * an invalid one, just in case drivers don't -+ * take the API seriously to stop at -1. -+ */ -+ if (inval) { -+ info->control.rates[i].idx = -1; -+ continue; -+ } -+ if (info->control.rates[i].idx < 0) { -+ inval = true; -+ continue; -+ } - -- /* Do not use multiple retry rates when using RTS/CTS */ -- info->control.retries[0].rate_idx = -1; -+ /* -+ * For now assume MCS is already set up correctly, this -+ * needs to be fixed. -+ */ -+ if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) { -+ WARN_ON(info->control.rates[i].idx > 76); -+ continue; -+ } - -- /* Use min(data rate, max base rate) as CTS/RTS rate */ -- rate = &sband->bitrates[tx->rate_idx]; -+ /* set up RTS protection if desired */ -+ if (rts) { -+ info->control.rates[i].flags |= -+ IEEE80211_TX_RC_USE_RTS_CTS; -+ rts = true; -+ } - -- for (idx = 0; idx < sband->n_bitrates; idx++) { -- if (sband->bitrates[idx].bitrate > rate->bitrate) -- continue; -- if (tx->sdata->vif.bss_conf.basic_rates & BIT(idx) && -- (baserate < 0 || -- (sband->bitrates[baserate].bitrate -- < sband->bitrates[idx].bitrate))) -- baserate = idx; -+ /* RC is busted */ -+ if (WARN_ON(info->control.rates[i].idx >= -+ sband->n_bitrates)) { -+ info->control.rates[i].idx = -1; -+ continue; - } - -- if (baserate >= 0) -- info->control.rts_cts_rate_idx = baserate; -- else -- info->control.rts_cts_rate_idx = 0; -+ rate = &sband->bitrates[info->control.rates[i].idx]; -+ -+ /* set up short preamble */ -+ if (short_preamble && -+ rate->flags & IEEE80211_RATE_SHORT_PREAMBLE) -+ info->control.rates[i].flags |= -+ IEEE80211_TX_RC_USE_SHORT_PREAMBLE; -+ -+ /* set up G protection */ -+ if (!rts && tx->sdata->vif.bss_conf.use_cts_prot && -+ rate->flags & IEEE80211_RATE_ERP_G) -+ info->control.rates[i].flags |= -+ IEEE80211_TX_RC_USE_CTS_PROTECT; - } - -+ return TX_CONTINUE; -+} -+ -+static ieee80211_tx_result debug_noinline -+ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) -+{ -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); -+ - if (tx->sta) - info->control.sta = &tx->sta->sta; - -@@ -680,6 +670,7 @@ ieee80211_tx_h_fragment(struct ieee80211 - left = payload_len - per_fragm; - for (i = 0; i < num_fragm - 1; i++) { - struct ieee80211_hdr *fhdr; -+ struct ieee80211_tx_info *info; - size_t copylen; - - if (left <= 0) -@@ -694,20 +685,44 @@ ieee80211_tx_h_fragment(struct ieee80211 - IEEE80211_ENCRYPT_TAILROOM); - if (!frag) - goto fail; -+ - /* Make sure that all fragments use the same priority so - * that they end up using the same TX queue */ - frag->priority = first->priority; -+ - skb_reserve(frag, tx->local->tx_headroom + - IEEE80211_ENCRYPT_HEADROOM); -+ -+ /* copy TX information */ -+ info = IEEE80211_SKB_CB(frag); -+ memcpy(info, first->cb, sizeof(frag->cb)); -+ -+ /* copy/fill in 802.11 header */ - fhdr = (struct ieee80211_hdr *) skb_put(frag, hdrlen); - memcpy(fhdr, first->data, hdrlen); -- if (i == num_fragm - 2) -- fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS); - fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG)); -+ -+ if (i == num_fragm - 2) { -+ /* clear MOREFRAGS bit for the last fragment */ -+ fhdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREFRAGS); -+ } else { -+ /* -+ * No multi-rate retries for fragmented frames, that -+ * would completely throw off the NAV at other STAs. -+ */ -+ info->control.rates[1].idx = -1; -+ info->control.rates[2].idx = -1; -+ info->control.rates[3].idx = -1; -+ BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 4); -+ info->flags &= ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; -+ } -+ -+ /* copy data */ - copylen = left > per_fragm ? per_fragm : left; - memcpy(skb_put(frag, copylen), pos, copylen); -- memcpy(frag->cb, first->cb, sizeof(frag->cb)); -+ - skb_copy_queue_mapping(frag, first); -+ - frag->do_not_encrypt = first->do_not_encrypt; - - pos += copylen; -@@ -767,12 +782,10 @@ ieee80211_tx_h_calculate_duration(struct - tx->extra_frag[0]->len); - - for (i = 0; i < tx->num_extra_frag; i++) { -- if (i + 1 < tx->num_extra_frag) { -+ if (i + 1 < tx->num_extra_frag) - next_len = tx->extra_frag[i + 1]->len; -- } else { -+ else - next_len = 0; -- tx->rate_idx = tx->last_frag_rate_idx; -- } - - hdr = (struct ieee80211_hdr *)tx->extra_frag[i]->data; - hdr->duration_id = ieee80211_duration(tx, 0, next_len); -@@ -825,7 +838,6 @@ __ieee80211_parse_tx_radiotap(struct iee - (struct ieee80211_radiotap_header *) skb->data; - struct ieee80211_supported_band *sband; - int ret = ieee80211_radiotap_iterator_init(&iterator, rthdr, skb->len); -- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - sband = tx->local->hw.wiphy->bands[tx->channel->band]; - -@@ -839,8 +851,6 @@ __ieee80211_parse_tx_radiotap(struct iee - */ - - while (!ret) { -- int i, target_rate; -- - ret = ieee80211_radiotap_iterator_next(&iterator); - - if (ret) -@@ -854,38 +864,6 @@ __ieee80211_parse_tx_radiotap(struct iee - * get_unaligned((type *)iterator.this_arg) to dereference - * iterator.this_arg for type "type" safely on all arches. - */ -- case IEEE80211_RADIOTAP_RATE: -- /* -- * radiotap rate u8 is in 500kbps units eg, 0x02=1Mbps -- * ieee80211 rate int is in 100kbps units eg, 0x0a=1Mbps -- */ -- target_rate = (*iterator.this_arg) * 5; -- for (i = 0; i < sband->n_bitrates; i++) { -- struct ieee80211_rate *r; -- -- r = &sband->bitrates[i]; -- -- if (r->bitrate == target_rate) { -- tx->rate_idx = i; -- break; -- } -- } -- break; -- -- case IEEE80211_RADIOTAP_ANTENNA: -- /* -- * radiotap uses 0 for 1st ant, mac80211 is 1 for -- * 1st ant -- */ -- info->antenna_sel_tx = (*iterator.this_arg) + 1; -- break; -- --#if 0 -- case IEEE80211_RADIOTAP_DBM_TX_POWER: -- control->power_level = *iterator.this_arg; -- break; --#endif -- - case IEEE80211_RADIOTAP_FLAGS: - if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS) { - /* -@@ -951,8 +929,6 @@ __ieee80211_tx_prepare(struct ieee80211_ - tx->local = local; - tx->sdata = IEEE80211_DEV_TO_SUB_IF(dev); - tx->channel = local->hw.conf.channel; -- tx->rate_idx = -1; -- tx->last_frag_rate_idx = -1; - /* - * Set this flag (used below to indicate "automatic fragmentation"), - * it will be cleared/left by radiotap as desired. -@@ -1053,23 +1029,11 @@ static int __ieee80211_tx(struct ieee802 - if (!tx->extra_frag[i]) - continue; - info = IEEE80211_SKB_CB(tx->extra_frag[i]); -- info->flags &= ~(IEEE80211_TX_CTL_USE_RTS_CTS | -- IEEE80211_TX_CTL_USE_CTS_PROTECT | -- IEEE80211_TX_CTL_CLEAR_PS_FILT | -+ info->flags &= ~(IEEE80211_TX_CTL_CLEAR_PS_FILT | - IEEE80211_TX_CTL_FIRST_FRAGMENT); - if (netif_subqueue_stopped(local->mdev, - tx->extra_frag[i])) - return IEEE80211_TX_FRAG_AGAIN; -- if (i == tx->num_extra_frag) { -- info->tx_rate_idx = tx->last_frag_rate_idx; -- -- if (tx->flags & IEEE80211_TX_PROBE_LAST_FRAG) -- info->flags |= -- IEEE80211_TX_CTL_RATE_CTRL_PROBE; -- else -- info->flags &= -- ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; -- } - - ret = local->ops->tx(local_to_hw(local), - tx->extra_frag[i]); -@@ -1206,9 +1170,6 @@ retry: - store->skb = skb; - store->extra_frag = tx.extra_frag; - store->num_extra_frag = tx.num_extra_frag; -- store->last_frag_rate_idx = tx.last_frag_rate_idx; -- store->last_frag_rate_ctrl_probe = -- !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG); - } - out: - rcu_read_unlock(); -@@ -1767,10 +1728,7 @@ void ieee80211_tx_pending(unsigned long - store = &local->pending_packet[i]; - tx.extra_frag = store->extra_frag; - tx.num_extra_frag = store->num_extra_frag; -- tx.last_frag_rate_idx = store->last_frag_rate_idx; - tx.flags = 0; -- if (store->last_frag_rate_ctrl_probe) -- tx.flags |= IEEE80211_TX_PROBE_LAST_FRAG; - ret = __ieee80211_tx(local, store->skb, &tx); - if (ret) { - if (ret == IEEE80211_TX_FRAG_AGAIN) -@@ -1858,7 +1816,6 @@ struct sk_buff *ieee80211_beacon_get(str - struct ieee80211_sub_if_data *sdata = NULL; - struct ieee80211_if_ap *ap = NULL; - struct ieee80211_if_sta *ifsta = NULL; -- struct rate_selection rsel; - struct beacon_data *beacon; - struct ieee80211_supported_band *sband; - enum ieee80211_band band = local->hw.conf.channel->band; -@@ -1962,32 +1919,22 @@ struct sk_buff *ieee80211_beacon_get(str - skb->do_not_encrypt = 1; - - info->band = band; -- rate_control_get_rate(sdata, sband, NULL, skb, &rsel); -- -- if (unlikely(rsel.rate_idx < 0)) { -- if (net_ratelimit()) { -- printk(KERN_DEBUG "%s: ieee80211_beacon_get: " -- "no rate found\n", -- wiphy_name(local->hw.wiphy)); -- } -- dev_kfree_skb_any(skb); -- skb = NULL; -- goto out; -- } -+ /* -+ * XXX: For now, always use the lowest rate -+ */ -+ info->control.rates[0].idx = 0; -+ info->control.rates[0].count = 1; -+ info->control.rates[1].idx = -1; -+ info->control.rates[2].idx = -1; -+ info->control.rates[3].idx = -1; -+ BUILD_BUG_ON(IEEE80211_TX_MAX_RATES != 4); - - info->control.vif = vif; -- info->tx_rate_idx = rsel.rate_idx; - - info->flags |= IEEE80211_TX_CTL_NO_ACK; - info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; - info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ; -- if (sdata->vif.bss_conf.use_short_preamble && -- sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) -- info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; -- -- info->control.retry_limit = 1; -- --out: -+ out: - rcu_read_unlock(); - return skb; - } ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -142,7 +142,6 @@ typedef unsigned __bitwise__ ieee80211_t - #define IEEE80211_TX_FRAGMENTED BIT(0) - #define IEEE80211_TX_UNICAST BIT(1) - #define IEEE80211_TX_PS_BUFFERED BIT(2) --#define IEEE80211_TX_PROBE_LAST_FRAG BIT(3) - - struct ieee80211_tx_data { - struct sk_buff *skb; -@@ -153,11 +152,6 @@ struct ieee80211_tx_data { - struct ieee80211_key *key; - - struct ieee80211_channel *channel; -- s8 rate_idx; -- /* use this rate (if set) for last fragment; rate can -- * be set to lower rate for the first fragments, e.g., -- * when using CTS protection with IEEE 802.11g. */ -- s8 last_frag_rate_idx; - - /* Extra fragments (in addition to the first fragment - * in skb) */ -@@ -203,9 +197,7 @@ struct ieee80211_rx_data { - struct ieee80211_tx_stored_packet { - struct sk_buff *skb; - struct sk_buff **extra_frag; -- s8 last_frag_rate_idx; - int num_extra_frag; -- bool last_frag_rate_ctrl_probe; - }; - - struct beacon_data { ---- a/net/mac80211/rate.c -+++ b/net/mac80211/rate.c -@@ -199,48 +199,44 @@ static void rate_control_release(struct - } - - void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, -- struct ieee80211_supported_band *sband, -- struct sta_info *sta, struct sk_buff *skb, -- struct rate_selection *sel) -+ struct sta_info *sta, -+ struct ieee80211_tx_rate_control *txrc) - { - struct rate_control_ref *ref = sdata->local->rate_ctrl; - void *priv_sta = NULL; - struct ieee80211_sta *ista = NULL; -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); - int i; - -- sel->rate_idx = -1; -- sel->nonerp_idx = -1; -- sel->probe_idx = -1; -- sel->max_rate_idx = sdata->max_ratectrl_rateidx; -- - if (sta) { - ista = &sta->sta; - priv_sta = sta->rate_ctrl_priv; - } - -+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { -+ info->control.rates[i].idx = -1; -+ info->control.rates[i].flags = 0; -+ info->control.rates[i].count = 1; -+ } -+ - if (sta && sdata->force_unicast_rateidx > -1) -- sel->rate_idx = sdata->force_unicast_rateidx; -+ info->control.rates[0].idx = sdata->force_unicast_rateidx; - else -- ref->ops->get_rate(ref->priv, sband, ista, priv_sta, skb, sel); -+ ref->ops->get_rate(ref->priv, ista, priv_sta, txrc); - -- if (sdata->max_ratectrl_rateidx > -1 && -- sel->rate_idx > sdata->max_ratectrl_rateidx) -- sel->rate_idx = sdata->max_ratectrl_rateidx; -- -- BUG_ON(sel->rate_idx < 0); -- -- /* Select a non-ERP backup rate. */ -- if (sel->nonerp_idx < 0) { -- for (i = 0; i < sband->n_bitrates; i++) { -- struct ieee80211_rate *rate = &sband->bitrates[i]; -- if (sband->bitrates[sel->rate_idx].bitrate < rate->bitrate) -- break; -- -- if (rate_supported(ista, sband->band, i) && -- !(rate->flags & IEEE80211_RATE_ERP_G)) -- sel->nonerp_idx = i; -- } -+ /* -+ * try to enforce the maximum rate the user wanted -+ */ -+ if (sdata->max_ratectrl_rateidx > -1) -+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { -+ if (info->control.rates[i].flags & IEEE80211_TX_RC_MCS) -+ continue; -+ info->control.rates[i].idx = -+ min_t(s8, info->control.rates[i].idx, -+ sdata->max_ratectrl_rateidx); - } -+ -+ BUG_ON(info->control.rates[0].idx < 0); - } - - struct rate_control_ref *rate_control_get(struct rate_control_ref *ref) ---- a/net/mac80211/rate.h -+++ b/net/mac80211/rate.h -@@ -31,9 +31,8 @@ struct rate_control_ref { - struct rate_control_ref *rate_control_alloc(const char *name, - struct ieee80211_local *local); - void rate_control_get_rate(struct ieee80211_sub_if_data *sdata, -- struct ieee80211_supported_band *sband, -- struct sta_info *sta, struct sk_buff *skb, -- struct rate_selection *sel); -+ struct sta_info *sta, -+ struct ieee80211_tx_rate_control *txrc); - struct rate_control_ref *rate_control_get(struct rate_control_ref *ref); - void rate_control_put(struct rate_control_ref *ref); - ---- a/net/mac80211/sta_info.h -+++ b/net/mac80211/sta_info.h -@@ -196,7 +196,7 @@ struct sta_ampdu_mlme { - * @tx_packets: number of RX/TX MSDUs - * @tx_bytes: TBD - * @tx_fragments: number of transmitted MPDUs -- * @last_txrate_idx: Index of the last used transmit rate -+ * @last_txrate: description of the last used transmit rate - * @tid_seq: TBD - * @ampdu_mlme: TBD - * @timer_to_tid: identity mapping to ID timers -@@ -267,7 +267,7 @@ struct sta_info { - unsigned long tx_packets; - unsigned long tx_bytes; - unsigned long tx_fragments; -- unsigned int last_txrate_idx; -+ struct ieee80211_tx_rate last_tx_rate; - u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; - - /* ---- a/net/mac80211/wext.c -+++ b/net/mac80211/wext.c -@@ -636,8 +636,8 @@ static int ieee80211_ioctl_giwrate(struc - - sta = sta_info_get(local, sdata->u.sta.bssid); - -- if (sta && sta->last_txrate_idx < sband->n_bitrates) -- rate->value = sband->bitrates[sta->last_txrate_idx].bitrate; -+ if (sta && !(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) -+ rate->value = sband->bitrates[sta->last_tx_rate.idx].bitrate; - else - rate->value = 0; - ---- a/net/mac80211/mesh_hwmp.c -+++ b/net/mac80211/mesh_hwmp.c -@@ -218,12 +218,16 @@ static u32 airtime_link_metric_get(struc - - if (sta->fail_avg >= 100) - return MAX_METRIC; -+ -+ if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS) -+ return MAX_METRIC; -+ - err = (sta->fail_avg << ARITH_SHIFT) / 100; - - /* bitrate is in units of 100 Kbps, while we need rate in units of - * 1Mbps. This will be corrected on tx_time computation. - */ -- rate = sband->bitrates[sta->last_txrate_idx].bitrate; -+ rate = sband->bitrates[sta->last_tx_rate.idx].bitrate; - tx_time = (device_constant + 10 * test_frame_len / rate); - estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); - result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ; ---- a/net/mac80211/rc80211_pid_algo.c -+++ b/net/mac80211/rc80211_pid_algo.c -@@ -241,7 +241,7 @@ static void rate_control_pid_tx_status(v - - /* Ignore all frames that were sent with a different rate than the rate - * we currently advise mac80211 to use. */ -- if (info->tx_rate_idx != spinfo->txrate_idx) -+ if (info->status.rates[0].idx != spinfo->txrate_idx) - return; - - spinfo->tx_num_xmit++; -@@ -253,10 +253,10 @@ static void rate_control_pid_tx_status(v - /* We count frames that totally failed to be transmitted as two bad - * frames, those that made it out but had some retries as one good and - * one bad frame. */ -- if (info->status.excessive_retries) { -+ if (!(info->flags & IEEE80211_TX_STAT_ACK)) { - spinfo->tx_num_failed += 2; - spinfo->tx_num_xmit++; -- } else if (info->status.retry_count) { -+ } else if (info->status.rates[0].count) { - spinfo->tx_num_failed++; - spinfo->tx_num_xmit++; - } -@@ -270,23 +270,31 @@ static void rate_control_pid_tx_status(v - } - - static void --rate_control_pid_get_rate(void *priv, struct ieee80211_supported_band *sband, -- struct ieee80211_sta *sta, void *priv_sta, -- struct sk_buff *skb, -- struct rate_selection *sel) -+rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, -+ void *priv_sta, -+ struct ieee80211_tx_rate_control *txrc) - { -+ struct sk_buff *skb = txrc->skb; -+ struct ieee80211_supported_band *sband = txrc->sband; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct rc_pid_sta_info *spinfo = priv_sta; - int rateidx; - u16 fc; - -+ /* XXX: Should use the user-configured values */ -+ if (txrc->rts) -+ info->control.rates[0].count = 4; /* long retry count */ -+ else -+ info->control.rates[0].count = 7; /* short retry count */ -+ - /* Send management frames and broadcast/multicast data using lowest - * rate. */ - fc = le16_to_cpu(hdr->frame_control); - if (!sta || !spinfo || - (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || - is_multicast_ether_addr(hdr->addr1)) { -- sel->rate_idx = rate_lowest_index(sband, sta); -+ info->control.rates[0].idx = rate_lowest_index(sband, sta); - return; - } - -@@ -295,7 +303,7 @@ rate_control_pid_get_rate(void *priv, st - if (rateidx >= sband->n_bitrates) - rateidx = sband->n_bitrates - 1; - -- sel->rate_idx = rateidx; -+ info->control.rates[0].idx = rateidx; - - #ifdef CONFIG_MAC80211_DEBUGFS - rate_control_pid_event_tx_rate(&spinfo->events, ---- a/net/mac80211/rc80211_minstrel.c -+++ b/net/mac80211/rc80211_minstrel.c -@@ -169,30 +169,20 @@ minstrel_tx_status(void *priv, struct ie - { - struct minstrel_sta_info *mi = priv_sta; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -- struct ieee80211_tx_altrate *ar = info->status.retries; -- struct minstrel_priv *mp = priv; -- int i, ndx, tries; -- int success = 0; -+ struct ieee80211_tx_rate *ar = info->status.rates; -+ int i, ndx; -+ int success; - -- if (!info->status.excessive_retries) -- success = 1; -+ success = !!(info->flags & IEEE80211_TX_STAT_ACK); - -- if (!mp->has_mrr || (ar[0].rate_idx < 0)) { -- ndx = rix_to_ndx(mi, info->tx_rate_idx); -- tries = info->status.retry_count + 1; -- mi->r[ndx].success += success; -- mi->r[ndx].attempts += tries; -- return; -- } -- -- for (i = 0; i < 4; i++) { -- if (ar[i].rate_idx < 0) -+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { -+ if (ar[i].idx < 0) - break; - -- ndx = rix_to_ndx(mi, ar[i].rate_idx); -- mi->r[ndx].attempts += ar[i].limit + 1; -+ ndx = rix_to_ndx(mi, ar[i].idx); -+ mi->r[ndx].attempts += ar[i].count; - -- if ((i != 3) && (ar[i + 1].rate_idx < 0)) -+ if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) - mi->r[ndx].success += success; - } - -@@ -210,9 +200,9 @@ minstrel_get_retry_count(struct minstrel - { - unsigned int retry = mr->adjusted_retry_count; - -- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) -+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - retry = max(2U, min(mr->retry_count_rtscts, retry)); -- else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) -+ else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - retry = max(2U, min(mr->retry_count_cts, retry)); - return retry; - } -@@ -234,14 +224,15 @@ minstrel_get_next_sample(struct minstrel - } - - void --minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband, -- struct ieee80211_sta *sta, void *priv_sta, -- struct sk_buff *skb, struct rate_selection *sel) -+minstrel_get_rate(void *priv, struct ieee80211_sta *sta, -+ void *priv_sta, struct ieee80211_tx_rate_control *txrc) - { -+ struct sk_buff *skb = txrc->skb; -+ struct ieee80211_supported_band *sband = txrc->sband; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct minstrel_sta_info *mi = priv_sta; - struct minstrel_priv *mp = priv; -- struct ieee80211_tx_altrate *ar = info->control.retries; -+ struct ieee80211_tx_rate *ar = info->control.rates; - unsigned int ndx, sample_ndx = 0; - bool mrr; - bool sample_slower = false; -@@ -251,16 +242,12 @@ minstrel_get_rate(void *priv, struct iee - int sample_rate; - - if (!sta || !mi || use_low_rate(skb)) { -- sel->rate_idx = rate_lowest_index(sband, sta); -+ ar[0].idx = rate_lowest_index(sband, sta); -+ ar[0].count = mp->max_retry; - return; - } - -- mrr = mp->has_mrr; -- -- /* mac80211 does not allow mrr for RTS/CTS */ -- if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || -- (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) -- mrr = false; -+ mrr = mp->has_mrr && !txrc->rts && !txrc->bss_conf->use_cts_prot; - - if (time_after(jiffies, mi->stats_update + (mp->update_interval * - HZ) / 1000)) -@@ -315,13 +302,12 @@ minstrel_get_rate(void *priv, struct iee - mi->sample_deferred++; - } - } -- sel->rate_idx = mi->r[ndx].rix; -- info->control.retry_limit = minstrel_get_retry_count(&mi->r[ndx], info); -+ ar[0].idx = mi->r[ndx].rix; -+ ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info); - - if (!mrr) { -- ar[0].rate_idx = mi->lowest_rix; -- ar[0].limit = mp->max_retry; -- ar[1].rate_idx = -1; -+ ar[1].idx = mi->lowest_rix; -+ ar[1].count = mp->max_retry; - return; - } - -@@ -336,9 +322,9 @@ minstrel_get_rate(void *priv, struct iee - } - mrr_ndx[1] = mi->max_prob_rate; - mrr_ndx[2] = 0; -- for (i = 0; i < 3; i++) { -- ar[i].rate_idx = mi->r[mrr_ndx[i]].rix; -- ar[i].limit = mi->r[mrr_ndx[i]].adjusted_retry_count; -+ for (i = 1; i < 4; i++) { -+ ar[i].idx = mi->r[mrr_ndx[i - 1]].rix; -+ ar[i].count = mi->r[mrr_ndx[i - 1]].adjusted_retry_count; - } - } - -@@ -532,13 +518,13 @@ minstrel_alloc(struct ieee80211_hw *hw, - /* maximum time that the hw is allowed to stay in one MRR segment */ - mp->segment_size = 6000; - -- if (hw->max_altrate_tries > 0) -- mp->max_retry = hw->max_altrate_tries; -+ if (hw->max_rate_tries > 0) -+ mp->max_retry = hw->max_rate_tries; - else - /* safe default, does not necessarily have to match hw properties */ - mp->max_retry = 7; - -- if (hw->max_altrates >= 3) -+ if (hw->max_rates >= 4) - mp->has_mrr = true; - - mp->hw = hw; ---- a/net/mac80211/rc80211_pid_debugfs.c -+++ b/net/mac80211/rc80211_pid_debugfs.c -@@ -43,6 +43,7 @@ void rate_control_pid_event_tx_status(st - { - union rc_pid_event_data evd; - -+ evd.flags = stat->flags; - memcpy(&evd.tx_status, stat, sizeof(struct ieee80211_tx_info)); - rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_STATUS, &evd); - } -@@ -167,8 +168,8 @@ static ssize_t rate_control_pid_events_r - switch (ev->type) { - case RC_PID_EVENT_TYPE_TX_STATUS: - p += snprintf(pb + p, length - p, "tx_status %u %u", -- ev->data.tx_status.status.excessive_retries, -- ev->data.tx_status.status.retry_count); -+ !(ev->data.flags & IEEE80211_TX_STAT_ACK), -+ ev->data.tx_status.status.rates[0].idx); - break; - case RC_PID_EVENT_TYPE_RATE_CHANGE: - p += snprintf(pb + p, length - p, "rate_change %d %d", ---- a/net/mac80211/rc80211_pid.h -+++ b/net/mac80211/rc80211_pid.h -@@ -61,6 +61,7 @@ enum rc_pid_event_type { - union rc_pid_event_data { - /* RC_PID_EVENT_TX_STATUS */ - struct { -+ u32 flags; - struct ieee80211_tx_info tx_status; - }; - /* RC_PID_EVENT_TYPE_RATE_CHANGE */ ---- a/drivers/net/wireless/zd1211rw/zd_mac.c -+++ b/drivers/net/wireless/zd1211rw/zd_mac.c -@@ -296,15 +296,14 @@ static void zd_op_stop(struct ieee80211_ - * If no status information has been requested, the skb is freed. - */ - static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, -- u32 flags, int ackssi, bool success) -+ int ackssi, bool success) - { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - -- memset(&info->status, 0, sizeof(info->status)); -+ ieee80211_tx_info_clear_status(info); - -- if (!success) -- info->status.excessive_retries = 1; -- info->flags |= flags; -+ if (success) -+ info->flags |= IEEE80211_TX_STAT_ACK; - info->status.ack_signal = ackssi; - ieee80211_tx_status_irqsafe(hw, skb); - } -@@ -326,7 +325,7 @@ void zd_mac_tx_failed(struct ieee80211_h - if (skb == NULL) - return; - -- tx_status(hw, skb, 0, 0, 0); -+ tx_status(hw, skb, 0, 0); - } - - /** -@@ -347,7 +346,7 @@ void zd_mac_tx_to_dev(struct sk_buff *sk - skb_pull(skb, sizeof(struct zd_ctrlset)); - if (unlikely(error || - (info->flags & IEEE80211_TX_CTL_NO_ACK))) { -- tx_status(hw, skb, 0, 0, !error); -+ tx_status(hw, skb, 0, !error); - } else { - struct sk_buff_head *q = - &zd_hw_mac(hw)->ack_wait_queue; -@@ -406,7 +405,8 @@ static int zd_calc_tx_length_us(u8 *serv - } - - static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, -- struct ieee80211_hdr *header, u32 flags) -+ struct ieee80211_hdr *header, -+ struct ieee80211_tx_info *info) - { - /* - * CONTROL TODO: -@@ -417,7 +417,7 @@ static void cs_set_control(struct zd_mac - cs->control = 0; - - /* First fragment */ -- if (flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) -+ if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - cs->control |= ZD_CS_NEED_RANDOM_BACKOFF; - - /* Multicast */ -@@ -428,10 +428,10 @@ static void cs_set_control(struct zd_mac - if (ieee80211_is_pspoll(header->frame_control)) - cs->control |= ZD_CS_PS_POLL_FRAME; - -- if (flags & IEEE80211_TX_CTL_USE_RTS_CTS) -+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - cs->control |= ZD_CS_RTS; - -- if (flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) -+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - cs->control |= ZD_CS_SELF_CTS; - - /* FIXME: Management frame? */ -@@ -517,12 +517,12 @@ static int fill_ctrlset(struct zd_mac *m - txrate = ieee80211_get_tx_rate(mac->hw, info); - - cs->modulation = txrate->hw_value; -- if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) -+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - cs->modulation = txrate->hw_value_short; - - cs->tx_length = cpu_to_le16(frag_len); - -- cs_set_control(mac, cs, hdr, info->flags); -+ cs_set_control(mac, cs, hdr, info); - - packet_length = frag_len + sizeof(struct zd_ctrlset) + 10; - ZD_ASSERT(packet_length <= 0xffff); -@@ -618,7 +618,7 @@ static int filter_ack(struct ieee80211_h - if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1))) - { - __skb_unlink(skb, q); -- tx_status(hw, skb, IEEE80211_TX_STAT_ACK, stats->signal, 1); -+ tx_status(hw, skb, stats->signal, 1); - goto out; - } - } ---- a/drivers/net/wireless/rt2x00/rt2x00dev.c -+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c -@@ -499,6 +499,7 @@ void rt2x00lib_txdone(struct queue_entry - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); - enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); -+ bool rts; - - /* - * Unmap the skb. -@@ -528,14 +529,14 @@ void rt2x00lib_txdone(struct queue_entry - rt2x00dev->link.qual.tx_failed += - test_bit(TXDONE_FAILURE, &txdesc->flags); - -+ rts = !!(tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS); -+ - /* - * Initialize TX status - */ -- memset(&tx_info->status, 0, sizeof(tx_info->status)); -+ ieee80211_tx_info_clear_status(tx_info); - tx_info->status.ack_signal = 0; -- tx_info->status.excessive_retries = -- test_bit(TXDONE_EXCESSIVE_RETRY, &txdesc->flags); -- tx_info->status.retry_count = txdesc->retry; -+ tx_info->status.rates[0].count = txdesc->retry + 1; - - if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (test_bit(TXDONE_SUCCESS, &txdesc->flags)) -@@ -544,7 +545,7 @@ void rt2x00lib_txdone(struct queue_entry - rt2x00dev->low_level_stats.dot11ACKFailureCount++; - } - -- if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { -+ if (rts) { - if (test_bit(TXDONE_SUCCESS, &txdesc->flags)) - rt2x00dev->low_level_stats.dot11RTSSuccessCount++; - else if (test_bit(TXDONE_FAILURE, &txdesc->flags)) ---- a/drivers/net/wireless/rt2x00/rt2x00mac.c -+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c -@@ -39,7 +39,7 @@ static int rt2x00mac_tx_rts_cts(struct r - unsigned int data_length; - int retval = 0; - -- if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) -+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - data_length = sizeof(struct ieee80211_cts); - else - data_length = sizeof(struct ieee80211_rts); -@@ -64,11 +64,11 @@ static int rt2x00mac_tx_rts_cts(struct r - */ - memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb)); - rts_info = IEEE80211_SKB_CB(skb); -- rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS; -- rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT; -+ rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; -+ rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT; - rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS; - -- if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) -+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - rts_info->flags |= IEEE80211_TX_CTL_NO_ACK; - else - rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK; -@@ -84,7 +84,7 @@ static int rt2x00mac_tx_rts_cts(struct r - data_length += rt2x00crypto_tx_overhead(tx_info); - #endif /* CONFIG_RT2X00_LIB_CRYPTO */ - -- if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) -+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif, - frag_skb->data, data_length, tx_info, - (struct ieee80211_cts *)(skb->data)); -@@ -146,8 +146,8 @@ int rt2x00mac_tx(struct ieee80211_hw *hw - * inside the hardware. - */ - frame_control = le16_to_cpu(ieee80211hdr->frame_control); -- if ((tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS | -- IEEE80211_TX_CTL_USE_CTS_PROTECT)) && -+ 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 (rt2x00queue_available(queue) <= 1) - goto exit_fail; ---- a/drivers/net/wireless/rt2x00/rt2x00queue.c -+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c -@@ -230,8 +230,15 @@ static void rt2x00queue_create_tx_descri - /* - * Determine retry information. - */ -- txdesc->retry_limit = tx_info->control.retry_limit; -- if (tx_info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) -+ txdesc->retry_limit = tx_info->control.rates[0].count - 1; -+ /* -+ * XXX: If at this point we knew whether the HW is going to use -+ * the RETRY_MODE bit or the retry_limit (currently all -+ * use the RETRY_MODE bit) we could do something like b43 -+ * does, set the RETRY_MODE bit when the RC algorithm is -+ * requesting more than the long retry limit. -+ */ -+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - __set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags); - - /* ---- a/drivers/net/wireless/adm8211.c -+++ b/drivers/net/wireless/adm8211.c -@@ -341,15 +341,14 @@ static void adm8211_interrupt_tci(struct - pci_unmap_single(priv->pdev, info->mapping, - info->skb->len, PCI_DMA_TODEVICE); - -- memset(&txi->status, 0, sizeof(txi->status)); -+ ieee80211_tx_info_clear_status(txi); -+ - skb_pull(skb, sizeof(struct adm8211_tx_hdr)); - memcpy(skb_push(skb, info->hdrlen), skb->cb, info->hdrlen); -- if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) { -- if (status & TDES0_STATUS_ES) -- txi->status.excessive_retries = 1; -- else -- txi->flags |= IEEE80211_TX_STAT_ACK; -- } -+ if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && -+ !(status & TDES0_STATUS_ES)) -+ txi->flags |= IEEE80211_TX_STAT_ACK; -+ - ieee80211_tx_status_irqsafe(dev, skb); - - info->skb = NULL; -@@ -1691,8 +1690,10 @@ static int adm8211_tx(struct ieee80211_h - struct ieee80211_hdr *hdr; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_rate *txrate = ieee80211_get_tx_rate(dev, info); -+ u8 rc_flags; - -- short_preamble = !!(txrate->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE); -+ rc_flags = info->control.rates[0].flags; -+ short_preamble = !!(rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE); - plcp_signal = txrate->bitrate; - - hdr = (struct ieee80211_hdr *)skb->data; -@@ -1724,10 +1725,10 @@ static int adm8211_tx(struct ieee80211_h - if (short_preamble) - txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_SHORT_PREAMBLE); - -- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) -+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) - txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_RTS); - -- txhdr->retry_limit = info->control.retry_limit; -+ txhdr->retry_limit = info->control.rates[0].count; - - adm8211_tx_raw(dev, skb, plcp_signal, hdrlen); - ---- a/drivers/net/wireless/ath5k/base.c -+++ b/drivers/net/wireless/ath5k/base.c -@@ -542,8 +542,8 @@ ath5k_pci_probe(struct pci_dev *pdev, - - /* set up multi-rate retry capabilities */ - if (sc->ah->ah_version == AR5K_AR5212) { -- hw->max_altrates = 3; -- hw->max_altrate_tries = 11; -+ hw->max_rates = 4; -+ hw->max_rate_tries = 11; - } - - /* Finish private driver data initialization */ -@@ -1188,7 +1188,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc - ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, - (sc->power_level * 2), - ieee80211_get_tx_rate(sc->hw, info)->hw_value, -- info->control.retry_limit, keyidx, 0, flags, 0, 0); -+ info->control.rates[0].count, keyidx, 0, flags, 0, 0); - if (ret) - goto err_unmap; - -@@ -1200,7 +1200,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc - break; - - mrr_rate[i] = rate->hw_value; -- mrr_tries[i] = info->control.retries[i].limit; -+ mrr_tries[i] = info->control.rates[i + 1].count; - } - - ah->ah_setup_mrr_tx_desc(ah, ds, -@@ -1846,30 +1846,26 @@ ath5k_tx_processq(struct ath5k_softc *sc - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, - PCI_DMA_TODEVICE); - -- memset(&info->status, 0, sizeof(info->status)); -- info->tx_rate_idx = ath5k_hw_to_driver_rix(sc, -- ts.ts_rate[ts.ts_final_idx]); -- info->status.retry_count = ts.ts_longretry; -- -+ ieee80211_tx_info_clear_status(info); - for (i = 0; i < 4; i++) { -- struct ieee80211_tx_altrate *r = -- &info->status.retries[i]; -+ struct ieee80211_tx_rate *r = -+ &info->status.rates[i]; - - if (ts.ts_rate[i]) { -- r->rate_idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]); -- r->limit = ts.ts_retry[i]; -+ r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]); -+ r->count = ts.ts_retry[i]; - } else { -- r->rate_idx = -1; -- r->limit = 0; -+ r->idx = -1; -+ r->count = 0; - } - } - -- info->status.excessive_retries = 0; -+ /* count the successful attempt as well */ -+ info->status.rates[ts.ts_final_idx].count++; -+ - if (unlikely(ts.ts_status)) { - sc->ll_stats.dot11ACKFailureCount++; -- if (ts.ts_status & AR5K_TXERR_XRETRY) -- info->status.excessive_retries = 1; -- else if (ts.ts_status & AR5K_TXERR_FILT) -+ if (ts.ts_status & AR5K_TXERR_FILT) - info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - } else { - info->flags |= IEEE80211_TX_STAT_ACK; ---- a/drivers/net/wireless/ath9k/main.c -+++ b/drivers/net/wireless/ath9k/main.c -@@ -461,12 +461,13 @@ void ath_tx_complete(struct ath_softc *s - DPRINTF(sc, ATH_DBG_XMIT, - "%s: TX complete: skb: %p\n", __func__, skb); - -+ ieee80211_tx_info_clear_status(tx_info); - if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || - tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { -- /* free driver's private data area of tx_info */ -- if (tx_info->driver_data[0] != NULL) -- kfree(tx_info->driver_data[0]); -- tx_info->driver_data[0] = NULL; -+ /* free driver's private data area of tx_info, XXX: HACK! */ -+ if (tx_info->control.vif != NULL) -+ kfree(tx_info->control.vif); -+ tx_info->control.vif = NULL; - } - - if (tx_status->flags & ATH_TX_BAR) { -@@ -474,17 +475,12 @@ void ath_tx_complete(struct ath_softc *s - tx_status->flags &= ~ATH_TX_BAR; - } - -- if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) { -- if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { -- /* Frame was not ACKed, but an ACK was expected */ -- tx_info->status.excessive_retries = 1; -- } -- } else { -+ if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { - /* Frame was ACKed */ - tx_info->flags |= IEEE80211_TX_STAT_ACK; - } - -- tx_info->status.retry_count = tx_status->retries; -+ tx_info->status.rates[0].count = tx_status->retries + 1; - - ieee80211_tx_status(hw, skb); - if (an) ---- a/drivers/net/wireless/ath9k/rc.c -+++ b/drivers/net/wireless/ath9k/rc.c -@@ -1864,24 +1864,21 @@ static void ath_tx_status(void *priv, st - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; -- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; -+ /* XXX: UGLY HACK!! */ -+ tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; - - spin_lock_bh(&sc->node_lock); - an = ath_node_find(sc, hdr->addr1); - spin_unlock_bh(&sc->node_lock); - -- if (!an || !priv_sta || !ieee80211_is_data(fc)) { -- if (tx_info->driver_data[0] != NULL) { -- kfree(tx_info->driver_data[0]); -- tx_info->driver_data[0] = NULL; -- } -+ if (tx_info_priv == NULL) - return; -- } -- if (tx_info->driver_data[0] != NULL) { -+ -+ if (an && priv_sta && ieee80211_is_data(fc)) - ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv); -- kfree(tx_info->driver_data[0]); -- tx_info->driver_data[0] = NULL; -- } -+ -+ kfree(tx_info_priv); -+ tx_info->control.vif = NULL; - } - - static void ath_tx_aggr_resp(struct ath_softc *sc, -@@ -1927,10 +1924,11 @@ static void ath_tx_aggr_resp(struct ath_ - } - } - --static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband, -- struct ieee80211_sta *sta, void *priv_sta, -- struct sk_buff *skb, struct rate_selection *sel) -+static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, -+ struct ieee80211_tx_rate_control *txrc) - { -+ struct ieee80211_supported_band *sband = txrc->sband; -+ struct sk_buff *skb = txrc->skb; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ath_softc *sc = priv; - struct ieee80211_hw *hw = sc->hw; -@@ -1946,17 +1944,17 @@ static void ath_get_rate(void *priv, str - - DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); - -- /* allocate driver private area of tx_info */ -- tx_info->driver_data[0] = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); -- ASSERT(tx_info->driver_data[0] != NULL); -- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; -+ /* allocate driver private area of tx_info, XXX: UGLY HACK! */ -+ tx_info->control.vif = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); -+ tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; -+ ASSERT(tx_info_priv != NULL); - - lowest_idx = rate_lowest_index(sband, sta); - tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10; - /* lowest rate for management and multicast/broadcast frames */ - if (!ieee80211_is_data(fc) || - is_multicast_ether_addr(hdr->addr1) || !sta) { -- sel->rate_idx = lowest_idx; -+ tx_info->control.rates[0].idx = lowest_idx; - return; - } - -@@ -1967,8 +1965,10 @@ static void ath_get_rate(void *priv, str - tx_info_priv->rcs, - &is_probe, - false); -+#if 0 - if (is_probe) - sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate; -+#endif - - /* Ratecontrol sometimes returns invalid rate index */ - if (tx_info_priv->rcs[0].rix != 0xff) -@@ -1976,7 +1976,7 @@ static void ath_get_rate(void *priv, str - else - tx_info_priv->rcs[0].rix = ath_rc_priv->prev_data_rix; - -- sel->rate_idx = tx_info_priv->rcs[0].rix; -+ tx_info->control.rates[0].idx = tx_info_priv->rcs[0].rix; - - /* Check if aggregation has to be enabled for this tid */ - ---- a/drivers/net/wireless/ath9k/xmit.c -+++ b/drivers/net/wireless/ath9k/xmit.c -@@ -168,7 +168,9 @@ static void fill_min_rates(struct sk_buf - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; -- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; -+ -+ /* XXX: HACK! */ -+ tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; - - if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) { - txctl->use_minrate = 1; -@@ -288,13 +290,16 @@ static int ath_tx_prepare(struct ath_sof - - if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) - txctl->flags |= ATH9K_TXDESC_NOACK; -- if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) -+ -+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - txctl->flags |= ATH9K_TXDESC_RTSENA; - - /* - * Setup for rate calculations. - */ -- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; -+ -+ /* XXX: HACK! */ -+ tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; - rcs = tx_info_priv->rcs; - - if (ieee80211_is_data(fc) && !txctl->use_minrate) { -@@ -854,7 +859,9 @@ static int ath_tx_send_normal(struct ath - - skb = (struct sk_buff *)bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); -- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; -+ -+ /* XXX: HACK! */ -+ tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; - memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); - - /* update starting sequence number for subsequent ADDBA request */ -@@ -1248,8 +1255,9 @@ static int ath_tx_processq(struct ath_so - } - skb = bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); -- tx_info_priv = (struct ath_tx_info_priv *) -- tx_info->driver_data[0]; -+ -+ /* XXX: HACK! */ -+ tx_info_priv = (struct ath_tx_info_priv *) tx_info->control.vif; - if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) - tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && -@@ -1430,7 +1438,8 @@ static int ath_tx_send_ampdu(struct ath_ - - skb = (struct sk_buff *)bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); -- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; -+ /* XXX: HACK! */ -+ tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; - memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); - - /* Add sub-frame to BAW */ -@@ -1464,7 +1473,7 @@ static u32 ath_lookup_rate(struct ath_so - skb = (struct sk_buff *)bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); - tx_info_priv = (struct ath_tx_info_priv *) -- tx_info->driver_data[0]; -+ tx_info->control.vif; /* XXX: HACK! */ - memcpy(bf->bf_rcs, - tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0])); - -@@ -1924,7 +1933,8 @@ static int ath_tx_start_dma(struct ath_s - - bf->bf_flags = txctl->flags; - bf->bf_keytype = txctl->keytype; -- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0]; -+ /* XXX: HACK! */ -+ tx_info_priv = (struct ath_tx_info_priv *)tx_info->control.vif; - rcs = tx_info_priv->rcs; - bf->bf_rcs[0] = rcs[0]; - bf->bf_rcs[1] = rcs[1]; ---- a/drivers/net/wireless/b43/dma.c -+++ b/drivers/net/wireless/b43/dma.c -@@ -1387,13 +1387,13 @@ void b43_dma_handle_txstatus(struct b43_ - - info = IEEE80211_SKB_CB(meta->skb); - -- memset(&info->status, 0, sizeof(info->status)); -+ ieee80211_tx_info_clear_status(info); - - /* - * Call back to inform the ieee80211 subsystem about - * the status of the transmission. - */ -- frame_succeed = b43_fill_txstatus_report(info, status); -+ frame_succeed = b43_fill_txstatus_report(dev, info, status); - #ifdef CONFIG_B43_DEBUG - if (frame_succeed) - ring->nr_succeed_tx_packets++; ---- a/drivers/net/wireless/b43/main.c -+++ b/drivers/net/wireless/b43/main.c -@@ -4563,7 +4563,7 @@ static int b43_wireless_init(struct ssb_ - BIT(NL80211_IFTYPE_ADHOC); - - hw->queues = b43_modparam_qos ? 4 : 1; -- hw->max_altrates = 1; -+ hw->max_rates = 2; - SET_IEEE80211_DEV(hw, dev->dev); - if (is_valid_ether_addr(sprom->et1mac)) - SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); ---- a/drivers/net/wireless/b43/pio.c -+++ b/drivers/net/wireless/b43/pio.c -@@ -587,9 +587,9 @@ void b43_pio_handle_txstatus(struct b43_ - spin_lock(&q->lock); /* IRQs are already disabled. */ - - info = IEEE80211_SKB_CB(pack->skb); -- memset(&info->status, 0, sizeof(info->status)); -+ ieee80211_tx_info_clear_status(info); - -- b43_fill_txstatus_report(info, status); -+ b43_fill_txstatus_report(dev, info, status); - - total_len = pack->skb->len + b43_txhdr_size(dev); - total_len = roundup(total_len, 4); ---- a/drivers/net/wireless/b43/xmit.c -+++ b/drivers/net/wireless/b43/xmit.c -@@ -185,7 +185,7 @@ int b43_generate_txhdr(struct b43_wldev - u8 *_txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, -- const struct ieee80211_tx_info *info, -+ struct ieee80211_tx_info *info, - u16 cookie) - { - struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; -@@ -202,6 +202,7 @@ int b43_generate_txhdr(struct b43_wldev - u16 phy_ctl = 0; - u8 extra_ft = 0; - struct ieee80211_rate *txrate; -+ struct ieee80211_tx_rate *rates; - - memset(txhdr, 0, sizeof(*txhdr)); - -@@ -291,7 +292,7 @@ int b43_generate_txhdr(struct b43_wldev - phy_ctl |= B43_TXH_PHY_ENC_OFDM; - else - phy_ctl |= B43_TXH_PHY_ENC_CCK; -- if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) -+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - phy_ctl |= B43_TXH_PHY_SHORTPRMBL; - - switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { -@@ -314,6 +315,7 @@ int b43_generate_txhdr(struct b43_wldev - B43_WARN_ON(1); - } - -+ rates = info->control.rates; - /* MAC control */ - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) - mac_ctl |= B43_TXH_MAC_ACK; -@@ -324,12 +326,22 @@ int b43_generate_txhdr(struct b43_wldev - mac_ctl |= B43_TXH_MAC_STMSDU; - if (phy->type == B43_PHYTYPE_A) - mac_ctl |= B43_TXH_MAC_5GHZ; -- if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) -+ -+ /* Overwrite rates[0].count to make the retry calculation -+ * in the tx status easier. need the actual retry limit to -+ * detect whether the fallback rate was used. -+ */ -+ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || -+ (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { -+ rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; - mac_ctl |= B43_TXH_MAC_LONGFRAME; -+ } else { -+ rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; -+ } - - /* Generate the RTS or CTS-to-self frame */ -- if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || -- (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { -+ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || -+ (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { - unsigned int len; - struct ieee80211_hdr *hdr; - int rts_rate, rts_rate_fb; -@@ -344,7 +356,7 @@ int b43_generate_txhdr(struct b43_wldev - rts_rate_fb = b43_calc_fallback_rate(rts_rate); - rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); - -- if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { -+ if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - struct ieee80211_cts *cts; - - if (b43_is_old_txhdr_format(dev)) { -@@ -687,10 +699,18 @@ void b43_handle_txstatus(struct b43_wlde - /* Fill out the mac80211 TXstatus report based on the b43-specific - * txstatus report data. This returns a boolean whether the frame was - * successfully transmitted. */ --bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, -+bool b43_fill_txstatus_report(struct b43_wldev *dev, -+ struct ieee80211_tx_info *report, - const struct b43_txstatus *status) - { - bool frame_success = 1; -+ int retry_limit; -+ -+ /* preserve the confiured retry limit before clearing the status -+ * The xmit function has overwritten the rc's value with the actual -+ * retry limit done by the hardware */ -+ retry_limit = report->status.rates[0].count; -+ ieee80211_tx_info_clear_status(report); - - if (status->acked) { - /* The frame was ACKed. */ -@@ -700,14 +720,32 @@ bool b43_fill_txstatus_report(struct iee - if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { - /* ...but we expected an ACK. */ - frame_success = 0; -- report->status.excessive_retries = 1; - } - } - if (status->frame_count == 0) { - /* The frame was not transmitted at all. */ -- report->status.retry_count = 0; -- } else -- report->status.retry_count = status->frame_count - 1; -+ report->status.rates[0].count = 0; -+ } else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { -+ /* -+ * If the short retries (RTS, not data frame) have exceeded -+ * the limit, the hw will not have tried the selected rate, -+ * but will have used the fallback rate instead. -+ * Don't let the rate control count attempts for the selected -+ * rate in this case, otherwise the statistics will be off. -+ */ -+ report->status.rates[0].count = 0; -+ report->status.rates[1].count = status->frame_count; -+ } else { -+ if (status->frame_count > retry_limit) { -+ report->status.rates[0].count = retry_limit; -+ report->status.rates[1].count = status->frame_count - -+ retry_limit; -+ -+ } else { -+ report->status.rates[0].count = status->frame_count; -+ report->status.rates[1].idx = -1; -+ } -+ } - - return frame_success; - } ---- a/drivers/net/wireless/b43/xmit.h -+++ b/drivers/net/wireless/b43/xmit.h -@@ -178,7 +178,7 @@ int b43_generate_txhdr(struct b43_wldev - u8 * txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, -- const struct ieee80211_tx_info *txctl, u16 cookie); -+ struct ieee80211_tx_info *txctl, u16 cookie); - - /* Transmit Status */ - struct b43_txstatus { -@@ -294,7 +294,8 @@ void b43_rx(struct b43_wldev *dev, struc - - void b43_handle_txstatus(struct b43_wldev *dev, - const struct b43_txstatus *status); --bool b43_fill_txstatus_report(struct ieee80211_tx_info *report, -+bool b43_fill_txstatus_report(struct b43_wldev *dev, -+ struct ieee80211_tx_info *report, - const struct b43_txstatus *status); - - void b43_tx_suspend(struct b43_wldev *dev); ---- a/drivers/net/wireless/b43legacy/dma.c -+++ b/drivers/net/wireless/b43legacy/dma.c -@@ -1411,6 +1411,7 @@ void b43legacy_dma_handle_txstatus(struc - struct b43legacy_dmaring *ring; - struct b43legacy_dmadesc_generic *desc; - struct b43legacy_dmadesc_meta *meta; -+ int retry_limit; - int slot; - - ring = parse_cookie(dev, status->cookie, &slot); -@@ -1437,25 +1438,42 @@ void b43legacy_dma_handle_txstatus(struc - struct ieee80211_tx_info *info; - BUG_ON(!meta->skb); - info = IEEE80211_SKB_CB(meta->skb); -- /* Call back to inform the ieee80211 subsystem about the -- * status of the transmission. -- * Some fields of txstat are already filled in dma_tx(). -- */ - -- memset(&info->status, 0, sizeof(info->status)); -+ /* preserve the confiured retry limit before clearing the status -+ * The xmit function has overwritten the rc's value with the actual -+ * retry limit done by the hardware */ -+ retry_limit = info->status.rates[0].count; -+ ieee80211_tx_info_clear_status(info); - -- if (status->acked) { -+ if (status->acked) - info->flags |= IEEE80211_TX_STAT_ACK; -+ -+ if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { -+ /* -+ * If the short retries (RTS, not data frame) have exceeded -+ * the limit, the hw will not have tried the selected rate, -+ * but will have used the fallback rate instead. -+ * Don't let the rate control count attempts for the selected -+ * rate in this case, otherwise the statistics will be off. -+ */ -+ info->status.rates[0].count = 0; -+ info->status.rates[1].count = status->frame_count; - } else { -- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) -- info->status.excessive_retries = 1; -+ if (status->frame_count > retry_limit) { -+ info->status.rates[0].count = retry_limit; -+ info->status.rates[1].count = status->frame_count - -+ retry_limit; -+ -+ } else { -+ info->status.rates[0].count = status->frame_count; -+ info->status.rates[1].idx = -1; -+ } - } -- if (status->frame_count == 0) { -- /* The frame was not transmitted at all. */ -- info->status.retry_count = 0; -- } else -- info->status.retry_count = status->frame_count -- - 1; -+ -+ /* Call back to inform the ieee80211 subsystem about the -+ * status of the transmission. -+ * Some fields of txstat are already filled in dma_tx(). -+ */ - ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb); - /* skb is freed by ieee80211_tx_status_irqsafe() */ - meta->skb = NULL; ---- a/drivers/net/wireless/b43legacy/main.c -+++ b/drivers/net/wireless/b43legacy/main.c -@@ -3691,7 +3691,7 @@ static int b43legacy_wireless_init(struc - BIT(NL80211_IFTYPE_WDS) | - BIT(NL80211_IFTYPE_ADHOC); - hw->queues = 1; /* FIXME: hardware has more queues */ -- hw->max_altrates = 1; -+ hw->max_rates = 2; - SET_IEEE80211_DEV(hw, dev->dev); - if (is_valid_ether_addr(sprom->et1mac)) - SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); ---- a/drivers/net/wireless/b43legacy/pio.c -+++ b/drivers/net/wireless/b43legacy/pio.c -@@ -491,6 +491,7 @@ void b43legacy_pio_handle_txstatus(struc - struct b43legacy_pioqueue *queue; - struct b43legacy_pio_txpacket *packet; - struct ieee80211_tx_info *info; -+ int retry_limit; - - queue = parse_cookie(dev, status->cookie, &packet); - B43legacy_WARN_ON(!queue); -@@ -503,11 +504,37 @@ void b43legacy_pio_handle_txstatus(struc - sizeof(struct b43legacy_txhdr_fw3)); - - info = IEEE80211_SKB_CB(packet->skb); -- memset(&info->status, 0, sizeof(info->status)); -+ -+ /* preserve the confiured retry limit before clearing the status -+ * The xmit function has overwritten the rc's value with the actual -+ * retry limit done by the hardware */ -+ retry_limit = info->status.rates[0].count; -+ ieee80211_tx_info_clear_status(info); - - if (status->acked) - info->flags |= IEEE80211_TX_STAT_ACK; -- info->status.retry_count = status->frame_count - 1; -+ -+ if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { -+ /* -+ * If the short retries (RTS, not data frame) have exceeded -+ * the limit, the hw will not have tried the selected rate, -+ * but will have used the fallback rate instead. -+ * Don't let the rate control count attempts for the selected -+ * rate in this case, otherwise the statistics will be off. -+ */ -+ info->status.rates[0].count = 0; -+ info->status.rates[1].count = status->frame_count; -+ } else { -+ if (status->frame_count > retry_limit) { -+ info->status.rates[0].count = retry_limit; -+ info->status.rates[1].count = status->frame_count - -+ retry_limit; -+ -+ } else { -+ info->status.rates[0].count = status->frame_count; -+ info->status.rates[1].idx = -1; -+ } -+ } - ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb); - packet->skb = NULL; - ---- a/drivers/net/wireless/b43legacy/xmit.c -+++ b/drivers/net/wireless/b43legacy/xmit.c -@@ -188,7 +188,7 @@ static int generate_txhdr_fw3(struct b43 - struct b43legacy_txhdr_fw3 *txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, -- const struct ieee80211_tx_info *info, -+ struct ieee80211_tx_info *info, - u16 cookie) - { - const struct ieee80211_hdr *wlhdr; -@@ -201,6 +201,7 @@ static int generate_txhdr_fw3(struct b43 - u32 mac_ctl = 0; - u16 phy_ctl = 0; - struct ieee80211_rate *tx_rate; -+ struct ieee80211_tx_rate *rates; - - wlhdr = (const struct ieee80211_hdr *)fragment_data; - -@@ -274,7 +275,7 @@ static int generate_txhdr_fw3(struct b43 - /* PHY TX Control word */ - if (rate_ofdm) - phy_ctl |= B43legacy_TX4_PHY_OFDM; -- if (dev->short_preamble) -+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL; - switch (info->antenna_sel_tx) { - case 0: -@@ -291,6 +292,7 @@ static int generate_txhdr_fw3(struct b43 - } - - /* MAC control */ -+ rates = info->control.rates; - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) - mac_ctl |= B43legacy_TX4_MAC_ACK; - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) -@@ -299,12 +301,22 @@ static int generate_txhdr_fw3(struct b43 - mac_ctl |= B43legacy_TX4_MAC_STMSDU; - if (rate_fb_ofdm) - mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM; -- if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT) -+ -+ /* Overwrite rates[0].count to make the retry calculation -+ * in the tx status easier. need the actual retry limit to -+ * detect whether the fallback rate was used. -+ */ -+ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || -+ (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { -+ rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; - mac_ctl |= B43legacy_TX4_MAC_LONGFRAME; -+ } else { -+ rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; -+ } - - /* Generate the RTS or CTS-to-self frame */ -- if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || -- (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { -+ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || -+ (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { - unsigned int len; - struct ieee80211_hdr *hdr; - int rts_rate; -@@ -319,7 +331,7 @@ static int generate_txhdr_fw3(struct b43 - if (rts_rate_fb_ofdm) - mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM; - -- if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { -+ if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - ieee80211_ctstoself_get(dev->wl->hw, - info->control.vif, - fragment_data, -@@ -362,7 +374,7 @@ int b43legacy_generate_txhdr(struct b43l - u8 *txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, -- const struct ieee80211_tx_info *info, -+ struct ieee80211_tx_info *info, - u16 cookie) - { - return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr, ---- a/drivers/net/wireless/b43legacy/xmit.h -+++ b/drivers/net/wireless/b43legacy/xmit.h -@@ -80,7 +80,7 @@ int b43legacy_generate_txhdr(struct b43l - u8 *txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, -- const struct ieee80211_tx_info *info, -+ struct ieee80211_tx_info *info, - u16 cookie); - - ---- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c -+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c -@@ -422,34 +422,6 @@ static void rs_free_sta(void *priv, stru - } - - --/* -- * get ieee prev rate from rate scale table. -- * for A and B mode we need to overright prev -- * value -- */ --static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate) --{ -- int next_rate = iwl3945_get_prev_ieee_rate(rate); -- -- switch (priv->band) { -- case IEEE80211_BAND_5GHZ: -- if (rate == IWL_RATE_12M_INDEX) -- next_rate = IWL_RATE_9M_INDEX; -- else if (rate == IWL_RATE_6M_INDEX) -- next_rate = IWL_RATE_6M_INDEX; -- break; --/* XXX cannot be invoked in current mac80211 so not a regression -- case MODE_IEEE80211B: -- if (rate == IWL_RATE_11M_INDEX_TABLE) -- next_rate = IWL_RATE_5M_INDEX_TABLE; -- break; -- */ -- default: -- break; -- } -- -- return next_rate; --} - /** - * rs_tx_status - Update rate control values based on Tx results - * -@@ -460,17 +432,21 @@ static void rs_tx_status(void *priv_rate - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb) - { -- u8 retries, current_count; -+ u8 retries = 0, current_count; - int scale_rate_index, first_index, last_index; - unsigned long flags; - struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; - struct iwl3945_rs_sta *rs_sta = priv_sta; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); -+ int i; - - IWL_DEBUG_RATE("enter\n"); - -- retries = info->status.retry_count; -- first_index = sband->bitrates[info->tx_rate_idx].hw_value; -+ for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) -+ retries += info->status.rates[i].count; -+ retries--; -+ -+ first_index = sband->bitrates[info->status.rates[0].idx].hw_value; - if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { - IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); - return; -@@ -502,7 +478,7 @@ static void rs_tx_status(void *priv_rate - last_index = scale_rate_index; - } else { - current_count = priv->retry_rate; -- last_index = rs_adjust_next_rate(priv, -+ last_index = iwl3945_rs_next_rate(priv, - scale_rate_index); - } - -@@ -518,7 +494,7 @@ static void rs_tx_status(void *priv_rate - - if (retries) - scale_rate_index = -- rs_adjust_next_rate(priv, scale_rate_index); -+ iwl3945_rs_next_rate(priv, scale_rate_index); - } - - -@@ -630,10 +606,11 @@ static u16 iwl3945_get_adjacent_rate(str - * rate table and must reference the driver allocated rate table - * - */ --static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, -- struct ieee80211_sta *sta, void *priv_sta, -- struct sk_buff *skb, struct rate_selection *sel) -+static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, -+ void *priv_sta, struct ieee80211_tx_rate_control *txrc) - { -+ struct ieee80211_supported_band *sband = txrc->sband; -+ struct sk_buff *skb = txrc->skb; - u8 low = IWL_RATE_INVALID; - u8 high = IWL_RATE_INVALID; - u16 high_low; -@@ -649,6 +626,7 @@ static void rs_get_rate(void *priv_r, st - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - u16 fc, rate_mask; - struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - DECLARE_MAC_BUF(mac); - - IWL_DEBUG_RATE("enter\n"); -@@ -660,7 +638,7 @@ static void rs_get_rate(void *priv_r, st - is_multicast_ether_addr(hdr->addr1) || - !sta || !priv_sta) { - IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); -- sel->rate_idx = rate_lowest_index(sband, sta); -+ info->control.rates[0].idx = rate_lowest_index(sband, sta); - return; - } - -@@ -793,9 +771,10 @@ static void rs_get_rate(void *priv_r, st - - rs_sta->last_txrate_idx = index; - if (sband->band == IEEE80211_BAND_5GHZ) -- sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; -+ info->control.rates[0].idx = rs_sta->last_txrate_idx - -+ IWL_FIRST_OFDM_RATE; - else -- sel->rate_idx = rs_sta->last_txrate_idx; -+ info->control.rates[0].idx = rs_sta->last_txrate_idx; - - IWL_DEBUG_RATE("leave: %d\n", index); - } ---- a/drivers/net/wireless/iwlwifi/iwl-3945.c -+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c -@@ -261,6 +261,35 @@ static inline const char *iwl3945_get_tx - } - #endif - -+/* -+ * get ieee prev rate from rate scale table. -+ * for A and B mode we need to overright prev -+ * value -+ */ -+int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate) -+{ -+ int next_rate = iwl3945_get_prev_ieee_rate(rate); -+ -+ switch (priv->band) { -+ case IEEE80211_BAND_5GHZ: -+ if (rate == IWL_RATE_12M_INDEX) -+ next_rate = IWL_RATE_9M_INDEX; -+ else if (rate == IWL_RATE_6M_INDEX) -+ next_rate = IWL_RATE_6M_INDEX; -+ break; -+/* XXX cannot be invoked in current mac80211 so not a regression -+ case MODE_IEEE80211B: -+ if (rate == IWL_RATE_11M_INDEX_TABLE) -+ next_rate = IWL_RATE_5M_INDEX_TABLE; -+ break; -+ */ -+ default: -+ break; -+ } -+ -+ return next_rate; -+} -+ - - /** - * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd -@@ -308,6 +337,7 @@ static void iwl3945_rx_reply_tx(struct i - struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - u32 status = le32_to_cpu(tx_resp->status); - int rate_idx; -+ int fail, i; - - if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { - IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " -@@ -318,9 +348,33 @@ static void iwl3945_rx_reply_tx(struct i - } - - info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); -- memset(&info->status, 0, sizeof(info->status)); -+ ieee80211_tx_info_clear_status(info); -+ -+ /* Fill the MRR chain with some info about on-chip retransmissions */ -+ rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); -+ if (info->band == IEEE80211_BAND_5GHZ) -+ rate_idx -= IWL_FIRST_OFDM_RATE; -+ -+ info->status.rates[0].count = tx_resp->failure_frame + 1; -+ fail = tx_resp->failure_frame; -+ for(i = 0; i < 4; i++) { -+ int next = iwl3945_rs_next_rate(priv, rate_idx); -+ -+ info->status.rates[i].idx = rate_idx; -+ -+ if ((rate_idx == next) || (i == 3)) { -+ info->status.rates[i].count = fail; -+ break; -+ } -+ -+ info->status.rates[i].count = priv->retry_rate; -+ fail -= priv->retry_rate; -+ rate_idx = next; -+ if (fail <= 0) -+ break; -+ } -+ info->status.rates[i].count++; /* add final attempt */ - -- info->status.retry_count = tx_resp->failure_frame; - /* tx_status->rts_retry_count = tx_resp->failure_rts; */ - info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ? - IEEE80211_TX_STAT_ACK : 0; -@@ -329,10 +383,6 @@ static void iwl3945_rx_reply_tx(struct i - txq_id, iwl3945_get_tx_fail_reason(status), status, - tx_resp->rate, tx_resp->failure_frame); - -- rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); -- if (info->band == IEEE80211_BAND_5GHZ) -- rate_idx -= IWL_FIRST_OFDM_RATE; -- info->tx_rate_idx = rate_idx; - IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); - iwl3945_tx_queue_reclaim(priv, txq_id, index); - ---- a/drivers/net/wireless/iwlwifi/iwl-3945.h -+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h -@@ -954,6 +954,8 @@ static inline int is_channel_ibss(const - extern const struct iwl3945_channel_info *iwl3945_get_channel_info( - const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel); - -+extern int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate); -+ - /* Requires full declaration of iwl3945_priv before including */ - #include "iwl-3945-io.h" - ---- a/drivers/net/wireless/iwlwifi/iwl-core.c -+++ b/drivers/net/wireless/iwlwifi/iwl-core.c -@@ -88,26 +88,27 @@ EXPORT_SYMBOL(iwl_rates); - * translate ucode response to mac80211 tx status control values - */ - void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, -- struct ieee80211_tx_info *control) -+ struct ieee80211_tx_info *info) - { - int rate_index; -+ struct ieee80211_tx_rate *r = &info->control.rates[0]; - -- control->antenna_sel_tx = -+ info->antenna_sel_tx = - ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); - if (rate_n_flags & RATE_MCS_HT_MSK) -- control->flags |= IEEE80211_TX_CTL_OFDM_HT; -+ r->flags |= IEEE80211_TX_RC_MCS; - if (rate_n_flags & RATE_MCS_GF_MSK) -- control->flags |= IEEE80211_TX_CTL_GREEN_FIELD; -+ r->flags |= IEEE80211_TX_RC_GREEN_FIELD; - if (rate_n_flags & RATE_MCS_FAT_MSK) -- control->flags |= IEEE80211_TX_CTL_40_MHZ_WIDTH; -+ r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (rate_n_flags & RATE_MCS_DUP_MSK) -- control->flags |= IEEE80211_TX_CTL_DUP_DATA; -+ r->flags |= IEEE80211_TX_RC_DUP_DATA; - if (rate_n_flags & RATE_MCS_SGI_MSK) -- control->flags |= IEEE80211_TX_CTL_SHORT_GI; -+ r->flags |= IEEE80211_TX_RC_SHORT_GI; - rate_index = iwl_hwrate_to_plcp_idx(rate_n_flags); -- if (control->band == IEEE80211_BAND_5GHZ) -+ if (info->band == IEEE80211_BAND_5GHZ) - rate_index -= IWL_FIRST_OFDM_RATE; -- control->tx_rate_idx = rate_index; -+ r->idx = rate_index; - } - EXPORT_SYMBOL(iwl_hwrate_to_tx_control); - ---- a/drivers/net/wireless/iwlwifi/iwl3945-base.c -+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c -@@ -2397,6 +2397,7 @@ static void iwl3945_build_tx_cmd_basic(s - { - __le16 fc = hdr->frame_control; - __le32 tx_flags = cmd->cmd.tx.tx_flags; -+ u8 rc_flags = info->control.rates[0].flags; - - cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { -@@ -2423,10 +2424,10 @@ static void iwl3945_build_tx_cmd_basic(s - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - } - -- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { -+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { - tx_flags |= TX_CMD_FLG_RTS_MSK; - tx_flags &= ~TX_CMD_FLG_CTS_MSK; -- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { -+ } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - tx_flags &= ~TX_CMD_FLG_RTS_MSK; - tx_flags |= TX_CMD_FLG_CTS_MSK; - } ---- a/drivers/net/wireless/mac80211_hwsim.c -+++ b/drivers/net/wireless/mac80211_hwsim.c -@@ -209,7 +209,7 @@ static bool mac80211_hwsim_tx_frame(stru - /* TODO: set mactime */ - rx_status.freq = data->channel->center_freq; - rx_status.band = data->channel->band; -- rx_status.rate_idx = info->tx_rate_idx; -+ rx_status.rate_idx = info->control.rates[0].idx; - /* TODO: simulate signal strength (and optional packet drop) */ - - /* Copy skb to all enabled radios that are on the current frequency */ -@@ -269,13 +269,9 @@ static int mac80211_hwsim_tx(struct ieee - if (txi->control.sta) - hwsim_check_sta_magic(txi->control.sta); - -- memset(&txi->status, 0, sizeof(txi->status)); -- if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) { -- if (ack) -- txi->flags |= IEEE80211_TX_STAT_ACK; -- else -- txi->status.excessive_retries = 1; -- } -+ ieee80211_tx_info_clear_status(txi); -+ if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) -+ txi->flags |= IEEE80211_TX_STAT_ACK; - ieee80211_tx_status_irqsafe(hw, skb); - return NETDEV_TX_OK; - } ---- a/drivers/net/wireless/rtl8180_dev.c -+++ b/drivers/net/wireless/rtl8180_dev.c -@@ -182,15 +182,13 @@ static void rtl8180_handle_tx(struct iee - skb->len, PCI_DMA_TODEVICE); - - info = IEEE80211_SKB_CB(skb); -- memset(&info->status, 0, sizeof(info->status)); -+ ieee80211_tx_info_clear_status(info); - -- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { -- if (flags & RTL818X_TX_DESC_FLAG_TX_OK) -- info->flags |= IEEE80211_TX_STAT_ACK; -- else -- info->status.excessive_retries = 1; -- } -- info->status.retry_count = flags & 0xFF; -+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && -+ (flags & RTL818X_TX_DESC_FLAG_TX_OK)) -+ info->flags |= IEEE80211_TX_STAT_ACK; -+ -+ info->status.rates[0].count = (flags & 0xFF) + 1; - - ieee80211_tx_status_irqsafe(dev, skb); - if (ring->entries - skb_queue_len(&ring->queue) == 2) -@@ -243,6 +241,7 @@ static int rtl8180_tx(struct ieee80211_h - unsigned int idx, prio; - dma_addr_t mapping; - u32 tx_flags; -+ u8 rc_flags; - u16 plcp_len = 0; - __le16 rts_duration = 0; - -@@ -261,15 +260,16 @@ static int rtl8180_tx(struct ieee80211_h - tx_flags |= RTL818X_TX_DESC_FLAG_DMA | - RTL818X_TX_DESC_FLAG_NO_ENC; - -- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { -+ rc_flags = info->control.rates[0].flags; -+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { - tx_flags |= RTL818X_TX_DESC_FLAG_RTS; - tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; -- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { -+ } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - tx_flags |= RTL818X_TX_DESC_FLAG_CTS; - tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - } - -- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) -+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) - rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len, - info); - -@@ -292,9 +292,9 @@ static int rtl8180_tx(struct ieee80211_h - entry->plcp_len = cpu_to_le16(plcp_len); - entry->tx_buf = cpu_to_le32(mapping); - entry->frame_len = cpu_to_le32(skb->len); -- entry->flags2 = info->control.retries[0].rate_idx >= 0 ? -+ entry->flags2 = info->control.rates[1].idx >= 0 ? - ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0; -- entry->retry_limit = info->control.retry_limit; -+ entry->retry_limit = info->control.rates[0].count; - entry->flags = cpu_to_le32(tx_flags); - __skb_queue_tail(&ring->queue, skb); - if (ring->entries - skb_queue_len(&ring->queue) < 2) -@@ -856,7 +856,7 @@ static int __devinit rtl8180_probe(struc - priv = dev->priv; - priv->pdev = pdev; - -- dev->max_altrates = 1; -+ dev->max_rates = 2; - SET_IEEE80211_DEV(dev, &pdev->dev); - pci_set_drvdata(pdev, dev); - ---- a/drivers/net/wireless/rtl8187_dev.c -+++ b/drivers/net/wireless/rtl8187_dev.c -@@ -163,7 +163,7 @@ static void rtl8187_tx_cb(struct urb *ur - usb_free_urb(info->driver_data[1]); - skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : - sizeof(struct rtl8187_tx_hdr)); -- memset(&info->status, 0, sizeof(info->status)); -+ ieee80211_tx_info_clear_status(info); - info->flags |= IEEE80211_TX_STAT_ACK; - ieee80211_tx_status_irqsafe(hw, skb); - } -@@ -192,12 +192,12 @@ static int rtl8187_tx(struct ieee80211_h - flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24; - if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control)) - flags |= RTL818X_TX_DESC_FLAG_MOREFRAG; -- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { -+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { - flags |= RTL818X_TX_DESC_FLAG_RTS; - flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - rts_dur = ieee80211_rts_duration(dev, priv->vif, - skb->len, info); -- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { -+ } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - flags |= RTL818X_TX_DESC_FLAG_CTS; - flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - } -@@ -208,7 +208,7 @@ static int rtl8187_tx(struct ieee80211_h - hdr->flags = cpu_to_le32(flags); - hdr->len = 0; - hdr->rts_duration = rts_dur; -- hdr->retry = cpu_to_le32(info->control.retry_limit << 8); -+ hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); - buf = hdr; - - ep = 2; -@@ -226,7 +226,7 @@ static int rtl8187_tx(struct ieee80211_h - memset(hdr, 0, sizeof(*hdr)); - hdr->flags = cpu_to_le32(flags); - hdr->rts_duration = rts_dur; -- hdr->retry = cpu_to_le32(info->control.retry_limit << 8); -+ hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); - hdr->tx_duration = - ieee80211_generic_frame_duration(dev, priv->vif, - skb->len, txrate); ---- a/drivers/net/wireless/p54/p54common.c -+++ b/drivers/net/wireless/p54/p54common.c -@@ -577,7 +577,7 @@ static void p54_rx_frame_sent(struct iee - __skb_unlink(entry, &priv->tx_queue); - spin_unlock_irqrestore(&priv->tx_queue.lock, flags); - -- memset(&info->status, 0, sizeof(info->status)); -+ ieee80211_tx_info_clear_status(info); - entry_hdr = (struct p54_control_hdr *) entry->data; - entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; - if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) -@@ -587,10 +587,8 @@ static void p54_rx_frame_sent(struct iee - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (!(payload->status & 0x01)) - info->flags |= IEEE80211_TX_STAT_ACK; -- else -- info->status.excessive_retries = 1; - } -- info->status.retry_count = payload->retries - 1; -+ info->status.rates[0].count = payload->retries; - info->status.ack_signal = p54_rssi_to_dbm(dev, - le16_to_cpu(payload->ack_rssi)); - skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); -@@ -816,6 +814,7 @@ static int p54_tx(struct ieee80211_hw *d - size_t padding, len; - u8 rate; - u8 cts_rate = 0x20; -+ u8 rc_flags; - - current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4]; - if (unlikely(current_queue->len > current_queue->limit)) -@@ -838,18 +837,19 @@ static int p54_tx(struct ieee80211_hw *d - hdr->magic1 = cpu_to_le16(0x0010); - hdr->len = cpu_to_le16(len); - hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1); -- hdr->retry1 = hdr->retry2 = info->control.retry_limit; -+ hdr->retry1 = hdr->retry2 = info->control.rates[0].count; - - /* TODO: add support for alternate retry TX rates */ - rate = ieee80211_get_tx_rate(dev, info)->hw_value; -- if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) { -+ rc_flags = info->control.rates[0].flags; -+ if (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) { - rate |= 0x10; - cts_rate |= 0x10; - } -- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { -+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { - rate |= 0x40; - cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; -- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { -+ } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - rate |= 0x20; - cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; - } ---- a/drivers/net/wireless/iwlwifi/iwl-4965.c -+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c -@@ -619,10 +619,10 @@ static void iwl4965_gain_computation(str - static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info, - __le32 *tx_flags) - { -- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { -+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { - *tx_flags |= TX_CMD_FLG_RTS_MSK; - *tx_flags &= ~TX_CMD_FLG_CTS_MSK; -- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { -+ } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - *tx_flags &= ~TX_CMD_FLG_RTS_MSK; - *tx_flags |= TX_CMD_FLG_CTS_MSK; - } -@@ -2070,7 +2070,7 @@ static int iwl4965_tx_status_reply_tx(st - agg->frame_count, agg->start_idx, idx); - - info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); -- info->status.retry_count = tx_resp->failure_frame; -+ info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - info->flags |= iwl_is_tx_success(status)? - IEEE80211_TX_STAT_ACK : 0; -@@ -2227,7 +2227,7 @@ static void iwl4965_rx_reply_tx(struct i - iwl_txq_check_empty(priv, sta_id, tid, txq_id); - } - } else { -- info->status.retry_count = tx_resp->failure_frame; -+ info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags |= - iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; - iwl_hwrate_to_tx_control(priv, ---- a/drivers/net/wireless/iwlwifi/iwl-5000.c -+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c -@@ -390,8 +390,8 @@ static void iwl5000_chain_noise_reset(st - static void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, - __le32 *tx_flags) - { -- if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || -- (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) -+ if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || -+ (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) - *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; - else - *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; -@@ -1136,7 +1136,7 @@ static int iwl5000_tx_status_reply_tx(st - agg->frame_count, agg->start_idx, idx); - - info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); -- info->status.retry_count = tx_resp->failure_frame; -+ info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - info->flags |= iwl_is_tx_success(status)? - IEEE80211_TX_STAT_ACK : 0; -@@ -1289,7 +1289,7 @@ static void iwl5000_rx_reply_tx(struct i - iwl_txq_check_empty(priv, sta_id, tid, txq_id); - } - } else { -- info->status.retry_count = tx_resp->failure_frame; -+ info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags = - iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; - iwl_hwrate_to_tx_control(priv, ---- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c -+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c -@@ -800,7 +800,7 @@ static void rs_tx_status(void *priv_r, s - !(info->flags & IEEE80211_TX_STAT_AMPDU)) - return; - -- retries = info->status.retry_count; -+ retries = info->status.rates[0].count + 1; - - if (retries > 15) - retries = 15; -@@ -832,20 +832,15 @@ static void rs_tx_status(void *priv_r, s - if (priv->band == IEEE80211_BAND_5GHZ) - rs_index -= IWL_FIRST_OFDM_RATE; - -- if ((info->tx_rate_idx < 0) || -- (tbl_type.is_SGI ^ -- !!(info->flags & IEEE80211_TX_CTL_SHORT_GI)) || -- (tbl_type.is_fat ^ -- !!(info->flags & IEEE80211_TX_CTL_40_MHZ_WIDTH)) || -- (tbl_type.is_dup ^ -- !!(info->flags & IEEE80211_TX_CTL_DUP_DATA)) || -- (tbl_type.ant_type ^ info->antenna_sel_tx) || -- (!!(tx_rate & RATE_MCS_HT_MSK) ^ -- !!(info->flags & IEEE80211_TX_CTL_OFDM_HT)) || -- (!!(tx_rate & RATE_MCS_GF_MSK) ^ -- !!(info->flags & IEEE80211_TX_CTL_GREEN_FIELD)) || -+ if ((info->status.rates[0].idx < 0) || -+ (tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) || -+ (tbl_type.is_fat != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || -+ (tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) || -+ (tbl_type.ant_type != info->antenna_sel_tx) || -+ (!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) || -+ (!!(tx_rate & RATE_MCS_GF_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) || - (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != -- hw->wiphy->bands[info->band]->bitrates[info->tx_rate_idx].bitrate)) { -+ hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) { - IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate); - goto out; - } -@@ -2103,15 +2098,17 @@ static void rs_initialize_lq(struct iwl_ - return; - } - --static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband, -- struct ieee80211_sta *sta, void *priv_sta, -- struct sk_buff *skb, struct rate_selection *sel) -+static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, -+ struct ieee80211_tx_rate_control *txrc) - { - - int i; -+ struct sk_buff *skb = txrc->skb; -+ struct ieee80211_supported_band *sband = txrc->sband; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; - struct ieee80211_conf *conf = &priv->hw->conf; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - __le16 fc; - struct iwl_lq_sta *lq_sta; - -@@ -2122,7 +2119,7 @@ static void rs_get_rate(void *priv_r, st - fc = hdr->frame_control; - if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || - !sta || !priv_sta) { -- sel->rate_idx = rate_lowest_index(sband, sta); -+ info->control.rates[0].idx = rate_lowest_index(sband, sta); - return; - } - -@@ -2149,13 +2146,13 @@ static void rs_get_rate(void *priv_r, st - } - - if ((i < 0) || (i > IWL_RATE_COUNT)) { -- sel->rate_idx = rate_lowest_index(sband, sta); -+ info->control.rates[0].idx = rate_lowest_index(sband, sta); - return; - } - - if (sband->band == IEEE80211_BAND_5GHZ) - i -= IWL_FIRST_OFDM_RATE; -- sel->rate_idx = i; -+ info->control.rates[0].idx = i; - } - - static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, diff --git a/package/mac80211/patches/426-minstrel_performance.patch b/package/mac80211/patches/426-minstrel_performance.patch deleted file mode 100644 index 7b95163c6c..0000000000 --- a/package/mac80211/patches/426-minstrel_performance.patch +++ /dev/null @@ -1,100 +0,0 @@ -This patch enhances minstrel's performance for non-MRR setups, -by preventing it from sampling slower rates with >95% success -probability and by putting at least 1 non-sample frame between -several sample frames. - -Signed-off-by: Felix Fietkau <nbd@openwrt.org> - ---- a/net/mac80211/rc80211_minstrel.c -+++ b/net/mac80211/rc80211_minstrel.c -@@ -126,7 +126,9 @@ minstrel_update_stats(struct minstrel_pr - mr->adjusted_retry_count = mr->retry_count >> 1; - if (mr->adjusted_retry_count > 2) - mr->adjusted_retry_count = 2; -+ mr->sample_limit = 4; - } else { -+ mr->sample_limit = -1; - mr->adjusted_retry_count = mr->retry_count; - } - if (!mr->adjusted_retry_count) -@@ -265,7 +267,8 @@ minstrel_get_rate(void *priv, struct iee - (mi->sample_count + mi->sample_deferred / 2); - - /* delta > 0: sampling required */ -- if (delta > 0) { -+ if ((delta > 0) && (mrr || !mi->prev_sample)) { -+ struct minstrel_rate *msr; - if (mi->packet_count >= 10000) { - mi->sample_deferred = 0; - mi->sample_count = 0; -@@ -284,13 +287,20 @@ minstrel_get_rate(void *priv, struct iee - } - - sample_ndx = minstrel_get_next_sample(mi); -+ msr = &mi->r[sample_ndx]; - sample = true; -- sample_slower = mrr && (mi->r[sample_ndx].perfect_tx_time > -+ sample_slower = mrr && (msr->perfect_tx_time > - mi->r[ndx].perfect_tx_time); - - if (!sample_slower) { -- ndx = sample_ndx; -- mi->sample_count++; -+ if (msr->sample_limit != 0) { -+ ndx = sample_ndx; -+ mi->sample_count++; -+ if (msr->sample_limit > 0) -+ msr->sample_limit--; -+ } else { -+ sample = false; -+ } - } else { - /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark - * packets that have the sampling rate deferred to the -@@ -302,10 +312,20 @@ minstrel_get_rate(void *priv, struct iee - mi->sample_deferred++; - } - } -+ mi->prev_sample = sample; -+ -+ /* If we're not using MRR and the sampling rate already -+ * has a probability of >95%, we shouldn't be attempting -+ * to use it, as this only wastes precious airtime */ -+ if (!mrr && sample && (mi->r[ndx].probability > 17100)) -+ ndx = mi->max_tp_rate; -+ - ar[0].idx = mi->r[ndx].rix; - ar[0].count = minstrel_get_retry_count(&mi->r[ndx], info); - - if (!mrr) { -+ if (!sample) -+ ar[0].count = mp->max_retry; - ar[1].idx = mi->lowest_rix; - ar[1].count = mp->max_retry; - return; -@@ -401,6 +421,7 @@ minstrel_rate_init(void *priv, struct ie - - /* calculate maximum number of retransmissions before - * fallback (based on maximum segment size) */ -+ mr->sample_limit = -1; - mr->retry_count = 1; - mr->retry_count_cts = 1; - mr->retry_count_rtscts = 1; ---- a/net/mac80211/rc80211_minstrel.h -+++ b/net/mac80211/rc80211_minstrel.h -@@ -16,6 +16,7 @@ struct minstrel_rate { - unsigned int perfect_tx_time; - unsigned int ack_time; - -+ int sample_limit; - unsigned int retry_count; - unsigned int retry_count_cts; - unsigned int retry_count_rtscts; -@@ -57,6 +58,7 @@ struct minstrel_sta_info { - - int n_rates; - struct minstrel_rate *r; -+ bool prev_sample; - - /* sampling table */ - u8 *sample_table; |