X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/ef81e099e64abbc5d86875d7281809d7e35e50dc..ae965dac51b9cef95bea9da7bd7ae4c57d4bf191:/package/mac80211/patches/302-rt2x00-Implement-support-for-rt2800pci.patch diff --git a/package/mac80211/patches/302-rt2x00-Implement-support-for-rt2800pci.patch b/package/mac80211/patches/302-rt2x00-Implement-support-for-rt2800pci.patch index ed697bb7e..9cd2289e0 100644 --- a/package/mac80211/patches/302-rt2x00-Implement-support-for-rt2800pci.patch +++ b/package/mac80211/patches/302-rt2x00-Implement-support-for-rt2800pci.patch @@ -1,12 +1,13 @@ -From dda25991ee4dc0a2ebe2e3b50857971fe1d878c4 Mon Sep 17 00:00:00 2001 +From a34c288f7214637f214ec17fb2b35dd5d20b0634 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn -Date: Sat, 10 Jan 2009 11:03:23 +0100 +Date: Sat, 14 Mar 2009 20:41:58 +0100 Subject: [PATCH] rt2x00: Implement support for rt2800pci Add support for the rt2800pci chipset. -Includes various patches from Mattias, Mark and Felix. +Includes various patches from Mattias, Mark, Felix and Xose. +Signed-off-by: Xose Vazquez Perez Signed-off-by: Mattias Nissler Signed-off-by: Mark Asselstine Signed-off-by: Felix Fietkau @@ -14,10 +15,10 @@ Signed-off-by: Ivo van Doorn --- drivers/net/wireless/rt2x00/Kconfig | 15 + drivers/net/wireless/rt2x00/Makefile | 1 + - drivers/net/wireless/rt2x00/rt2800pci.c | 2707 +++++++++++++++++++++++++++++++ - drivers/net/wireless/rt2x00/rt2800pci.h | 1879 +++++++++++++++++++++ - drivers/net/wireless/rt2x00/rt2x00.h | 4 + - 5 files changed, 4606 insertions(+), 0 deletions(-) + drivers/net/wireless/rt2x00/rt2800pci.c | 3035 +++++++++++++++++++++++++++++++ + drivers/net/wireless/rt2x00/rt2800pci.h | 1880 +++++++++++++++++++ + drivers/net/wireless/rt2x00/rt2x00.h | 6 + + 5 files changed, 4937 insertions(+), 0 deletions(-) create mode 100644 drivers/net/wireless/rt2x00/rt2800pci.c create mode 100644 drivers/net/wireless/rt2x00/rt2800pci.h @@ -32,9 +33,9 @@ Signed-off-by: Ivo van Doorn obj-$(CONFIG_RT73USB) += rt73usb.o --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800pci.c -@@ -0,0 +1,2707 @@ +@@ -0,0 +1,3035 @@ +/* -+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project ++ Copyright (C) 2004 - 2009 rt2x00 SourceForge Project + + + This program is free software; you can redistribute it and/or modify @@ -66,12 +67,21 @@ Signed-off-by: Ivo van Doorn +#include +#include +#include ++#include +#include + +#include "rt2x00.h" +#include "rt2x00pci.h" +#include "rt2800pci.h" + ++/* FIXME: Make Kconfig dependent */ ++#ifdef CONFIG_PCI ++#define CONFIG_RT2800PCI_PCI ++#endif ++#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) ++#define CONFIG_RT2800PCI_WISOC ++#endif ++ +/* + * Allow hardware encryption to be disabled. + */ @@ -160,9 +170,6 @@ Signed-off-by: Ivo van Doorn +{ + u32 reg; + -+ if (!word) -+ return; -+ + mutex_lock(&rt2x00dev->csr_mutex); + + /* @@ -210,6 +217,44 @@ Signed-off-by: Ivo van Doorn + mutex_unlock(&rt2x00dev->csr_mutex); +} + ++static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) ++{ ++ unsigned int i; ++ u32 reg; ++ ++ for (i = 0; i < 200; i++) { ++ rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, ®); ++ ++ if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) || ++ (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) || ++ (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD2) == token) || ++ (rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD3) == token)) ++ break; ++ ++ udelay(REGISTER_BUSY_DELAY); ++ } ++ ++ if (i == 200) ++ ERROR(rt2x00dev, "MCU request failed, no response from hardware\n"); ++ ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); ++} ++ ++#ifdef CONFIG_RT2800PCI_WISOC ++static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) ++{ ++ u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ ++ ++ memcpy_fromio(rt2x00dev->eeprom, base_addr, EEPROM_SIZE); ++} ++#else ++static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) ++{ ++} ++#endif /* CONFIG_RT2800PCI_WISOC */ ++ ++#ifdef CONFIG_RT2800PCI_PCI +static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) +{ + struct rt2x00_dev *rt2x00dev = eeprom->data; @@ -240,6 +285,32 @@ Signed-off-by: Ivo van Doorn + rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); +} + ++static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) ++{ ++ struct eeprom_93cx6 eeprom; ++ u32 reg; ++ ++ 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) ? ++ 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)); ++} ++#else ++static inline void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev) ++{ ++} ++#endif /* CONFIG_RT2800PCI_PCI */ ++ +#ifdef CONFIG_RT2X00_LIB_DEBUGFS +static const struct rt2x00debug rt2800pci_rt2x00debug = { + .owner = THIS_MODULE, @@ -364,20 +435,41 @@ Signed-off-by: Ivo van Doorn + struct rt2x00lib_crypto *crypto, + struct ieee80211_key_conf *key) +{ ++ struct mac_wcid_entry wcid_entry; ++ struct mac_iveiv_entry iveiv_entry; + u32 offset; + u32 reg; + -+ offset = MAC_WCID_ATTR_ENTRY(crypto->aid); ++ offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); + -+ reg = 0; ++ rt2x00pci_register_read(rt2x00dev, offset, ®); + 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_CIPHER, ++ (crypto->cmd == SET_KEY) * 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); ++ (crypto->cmd == SET_KEY) * crypto->bssidx); ++ rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); + rt2x00pci_register_write(rt2x00dev, offset, reg); ++ ++ offset = MAC_IVEIV_ENTRY(key->hw_key_idx); ++ ++ memset(&iveiv_entry, 0, sizeof(iveiv_entry)); ++ if ((crypto->cipher == CIPHER_TKIP) || ++ (crypto->cipher == CIPHER_TKIP_NO_MIC) || ++ (crypto->cipher == CIPHER_AES)) ++ iveiv_entry.iv[3] |= 0x20; ++ iveiv_entry.iv[3] |= key->keyidx << 6; ++ rt2x00pci_register_multiwrite(rt2x00dev, offset, ++ &iveiv_entry, sizeof(iveiv_entry)); ++ ++ offset = MAC_WCID_ENTRY(key->hw_key_idx); ++ ++ memset(&wcid_entry, 0, sizeof(wcid_entry)); ++ if (crypto->cmd == SET_KEY) ++ memcpy(&wcid_entry, crypto->address, ETH_ALEN); ++ rt2x00pci_register_multiwrite(rt2x00dev, offset, ++ &wcid_entry, sizeof(wcid_entry)); +} + +static int rt2800pci_config_shared_key(struct rt2x00_dev *rt2x00dev, @@ -387,10 +479,11 @@ Signed-off-by: Ivo van Doorn + struct hw_key_entry key_entry; + struct rt2x00_field32 field; + u32 offset; -+ u32 mask; + u32 reg; + + if (crypto->cmd == SET_KEY) { ++ key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx; ++ + memcpy(key_entry.key, crypto->key, + sizeof(key_entry.key)); + memcpy(key_entry.tx_mic, crypto->tx_mic, @@ -401,34 +494,23 @@ Signed-off-by: Ivo van Doorn + 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. ++ * 32 bits and contains the cipher types for 2 bssidx 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_offset = 4 * (key->hw_key_idx % 8); + 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); ++ (crypto->cmd == SET_KEY) * crypto->cipher); + rt2x00pci_register_write(rt2x00dev, offset, reg); + + /* @@ -446,13 +528,18 @@ Signed-off-by: Ivo van Doorn + 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) { ++ /* ++ * 1 pairwise key is possible per AID, this means that the AID ++ * equals our hw_key_idx. Make sure the WCID starts _after_ the ++ * last possible shared key entry. ++ */ ++ if (crypto->aid > (256 - 32)) ++ return -ENOSPC; ++ ++ key->hw_key_idx = 32 + crypto->aid; ++ ++ + memcpy(key_entry.key, crypto->key, + sizeof(key_entry.key)); + memcpy(key_entry.tx_mic, crypto->tx_mic, @@ -463,17 +550,6 @@ Signed-off-by: Ivo van Doorn + 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; + } + + /* @@ -502,8 +578,7 @@ Signed-off-by: Ivo van Doorn + !(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, -+ !(filter_flags & FIF_OTHER_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)); @@ -522,7 +597,7 @@ Signed-off-by: Ivo van Doorn + 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_BAR, 0); + rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, + !(filter_flags & FIF_CONTROL)); + rt2x00pci_register_write(rt2x00dev, RX_FILTER_CFG, reg); @@ -583,7 +658,7 @@ Signed-off-by: Ivo van Doorn + + rt2x00pci_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); + rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, -+ erp->ack_timeout); ++ DIV_ROUND_UP(erp->ack_timeout, erp->slot_time)); + rt2x00pci_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); + + rt2x00pci_register_read(rt2x00dev, AUTO_RSP_CFG, ®); @@ -600,8 +675,7 @@ Signed-off-by: Ivo van Doorn + + rt2x00pci_register_write(rt2x00dev, LEGACY_BASIC_RATE, + erp->basic_rates); -+ rt2x00pci_register_write(rt2x00dev, HT_BASIC_RATE, -+ erp->basic_rates >> 32); ++ rt2x00pci_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); + + rt2x00pci_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); + rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); @@ -638,9 +712,12 @@ Signed-off-by: Ivo van Doorn + */ + switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH)) { + case 1: ++ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); + rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); + break; + case 2: ++ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); ++ break; + case 3: + /* Do nothing */ + break; @@ -689,6 +766,7 @@ Signed-off-by: Ivo van Doorn +} + +static void rt2800pci_config_channel(struct rt2x00_dev *rt2x00dev, ++ struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ @@ -696,34 +774,20 @@ Signed-off-by: Ivo van Doorn + 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); + @@ -751,19 +815,14 @@ Signed-off-by: Ivo van Doorn + + 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); + } + -+ rt2x00_set_field32(&rf->rf4, RF4_BW40, -+ test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)); ++ rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); + + rt2800pci_rf_write(rt2x00dev, 1, rf->rf1); + rt2800pci_rf_write(rt2x00dev, 2, rf->rf2); @@ -800,11 +859,6 @@ Signed-off-by: Ivo van Doorn + 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); + @@ -812,13 +866,35 @@ Signed-off-by: Ivo van Doorn + rt2800pci_bbp_write(rt2x00dev, 75, 0x46); + else + rt2800pci_bbp_write(rt2x00dev, 75, 0x50); ++ } ++ ++ rt2x00pci_register_read(rt2x00dev, TX_BAND_CFG, ®); ++ rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); ++ rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); ++ rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); ++ rt2x00pci_register_write(rt2x00dev, TX_BAND_CFG, reg); ++ ++ tx_pin = 0; ++ ++ /* Turn on unused PA or LNA when not using 1T or 1R */ ++ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) != 1) { ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); ++ } + -+ 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); ++ /* Turn on unused PA or LNA when not using 1T or 1R */ ++ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) != 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_LNA_PE_A0_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); ++ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); ++ + rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); + + msleep(1); @@ -915,6 +991,36 @@ Signed-off-by: Ivo van Doorn + rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg); +} + ++static void rt2800pci_config_ps(struct rt2x00_dev *rt2x00dev, ++ struct rt2x00lib_conf *libconf) ++{ ++ enum dev_state state = ++ (libconf->conf->flags & IEEE80211_CONF_PS) ? ++ STATE_SLEEP : STATE_AWAKE; ++ u32 reg; ++ ++ if (state == STATE_SLEEP) { ++ rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); ++ ++ rt2x00pci_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); ++ rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5); ++ rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, ++ libconf->conf->listen_interval - 1); ++ rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); ++ rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); ++ ++ rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); ++ } else { ++ rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); ++ ++ rt2x00pci_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); ++ rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); ++ rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); ++ rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); ++ rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); ++ } ++} ++ +static void rt2800pci_config(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf, + const unsigned int flags) @@ -923,14 +1029,16 @@ Signed-off-by: Ivo van Doorn + rt2800pci_config_lna_gain(rt2x00dev, libconf); + + if (flags & IEEE80211_CONF_CHANGE_CHANNEL) -+ rt2800pci_config_channel(rt2x00dev, &libconf->rf, -+ &libconf->channel); ++ rt2800pci_config_channel(rt2x00dev, libconf->conf, ++ &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); ++ if (flags & IEEE80211_CONF_CHANGE_PS) ++ rt2800pci_config_ps(rt2x00dev, libconf); +} + +/* @@ -946,12 +1054,6 @@ Signed-off-by: Ivo van Doorn + */ + 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 u8 rt2800pci_get_default_vgc(struct rt2x00_dev *rt2x00dev) @@ -985,7 +1087,7 @@ Signed-off-by: Ivo van Doorn +static void rt2800pci_link_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual, const u32 count) +{ -+ if (rt2x00_rev(&rt2x00dev->chip) == RT2860_VERSION_C) ++ if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) + return; + + /* @@ -1004,19 +1106,31 @@ Signed-off-by: Ivo van Doorn + return FIRMWARE_RT2860; +} + -+static u16 rt2800pci_get_firmware_crc(const void *data, const size_t len) ++static int rt2800pci_check_firmware(struct rt2x00_dev *rt2x00dev, ++ const u8 *data, const size_t len) +{ ++ u16 fw_crc; + u16 crc; + + /* ++ * Only support 8kb firmware files. ++ */ ++ if (len != 8192) ++ return FW_BAD_LENGTH; ++ ++ /* ++ * 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. ++ */ ++ fw_crc = (data[len - 2] << 8 | data[len - 1]); ++ ++ /* + * 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); + @@ -1026,11 +1140,13 @@ Signed-off-by: Ivo van Doorn + * will be swapped, use swab16 to convert the crc to the correct + * value. + */ -+ return swab16(crc); ++ crc = swab16(crc); ++ ++ return (fw_crc == crc) ? FW_OK : FW_BAD_CRC; +} + +static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev, -+ const void *data, const size_t len) ++ const u8 *data, const size_t len) +{ + unsigned int i; + u32 reg; @@ -1162,26 +1278,31 @@ Signed-off-by: Ivo van Doorn + 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); ++ rt2x00pci_register_write(rt2x00dev, TX_DTX_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); ++ rt2x00pci_register_write(rt2x00dev, TX_DTX_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); ++ rt2x00pci_register_write(rt2x00dev, TX_DTX_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); ++ rt2x00pci_register_write(rt2x00dev, TX_DTX_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); ++ rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0); + + /* + * Enable global DMA configuration @@ -1252,7 +1373,7 @@ Signed-off-by: Ivo van Doorn + 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_CFG0, 0x00000000); + rt2x00pci_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + + rt2x00pci_register_read(rt2x00dev, TX_LINK_CFG, ®); @@ -1273,7 +1394,11 @@ Signed-off-by: Ivo van Doorn + + 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); ++ if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && ++ rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) ++ rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); ++ else ++ 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); @@ -1289,25 +1414,25 @@ Signed-off-by: Ivo van Doorn + 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_RATE, 8); + 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_MM40, 1); + 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_RATE, 8); + 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_MM40, 1); + 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); @@ -1365,6 +1490,8 @@ Signed-off-by: Ivo van Doorn + + 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_THRES, ++ IEEE80211_MAX_RTS_THRESHOLD); + rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); + rt2x00pci_register_write(rt2x00dev, TX_RTS_CFG, reg); + @@ -1374,19 +1501,19 @@ Signed-off-by: Ivo van Doorn + /* + * ASIC will keep garbage value after boot, clear encryption keys. + */ -+ for (i = 0; i < 254; i++) { -+ u32 wcid[2] = { 0xffffffff, 0x0000ffff }; ++ for (i = 0; i < 256; i++) { ++ u32 wcid[2] = { 0xffffffff, 0x00ffffff }; + rt2x00pci_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), + wcid, sizeof(wcid)); ++ ++ rt2x00pci_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); ++ rt2x00pci_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); + } + -+ for (i = 0; i < 4; i++) ++ for (i = 0; i < 16; 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 @@ -1427,12 +1554,12 @@ Signed-off-by: Ivo van Doorn + 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); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 3); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS6FBK, 13); ++ rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS7FBK, 14); + rt2x00pci_register_write(rt2x00dev, LG_FBK_CFG0, reg); + + rt2x00pci_register_read(rt2x00dev, LG_FBK_CFG1, ®); @@ -1483,8 +1610,8 @@ Signed-off-by: Ivo van Doorn + * BBP was enabled after firmware was loaded, + * but we need to reactivate it now. + */ -+ rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0x00000000); -+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0x00000000); ++ rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0); ++ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); + msleep(1); + + for (i = 0; i < REGISTER_BUSY_COUNT; i++) { @@ -1524,12 +1651,12 @@ Signed-off-by: Ivo van Doorn + rt2800pci_bbp_write(rt2x00dev, 103, 0x00); + rt2800pci_bbp_write(rt2x00dev, 105, 0x05); + -+ if (rt2x00_rev(&rt2x00dev->chip) == RT2860_VERSION_C) { ++ if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { + rt2800pci_bbp_write(rt2x00dev, 69, 0x16); + rt2800pci_bbp_write(rt2x00dev, 73, 0x12); + } + -+ if (rt2x00_rev(&rt2x00dev->chip) == RT2860_VERSION_D) ++ if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) + rt2800pci_bbp_write(rt2x00dev, 84, 0x19); + + for (i = 0; i < EEPROM_BBP_SIZE; i++) { @@ -1626,6 +1753,7 @@ Signed-off-by: Ivo van Doorn + if (unlikely(rt2800pci_wait_wpdma_ready(rt2x00dev) || + rt2800pci_init_queues(rt2x00dev) || + rt2800pci_init_registers(rt2x00dev) || ++ rt2800pci_wait_wpdma_ready(rt2x00dev) || + rt2800pci_init_bbp(rt2x00dev))) + return -EIO; + @@ -1634,12 +1762,14 @@ Signed-off-by: Ivo van Doorn + */ + rt2800pci_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); + -+ /* Wait for DMA, ignore error */ -+ rt2800pci_wait_wpdma_ready(rt2x00dev); -+ + /* + * Enable RX. + */ ++ rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, ®); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); ++ rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0); ++ rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); ++ + 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); @@ -1697,9 +1827,10 @@ Signed-off-by: Ivo van Doorn +{ + rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); + -+ if (state == STATE_AWAKE) -+ rt2800pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); -+ else ++ if (state == STATE_AWAKE) { ++ rt2800pci_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0); ++ rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP); ++ } else + rt2800pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); + + return 0; @@ -1774,7 +1905,6 @@ Signed-off-by: Ivo van Doorn + */ + 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); @@ -1800,16 +1930,22 @@ Signed-off-by: Ivo van Doorn + test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); + rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); + rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, -+ skbdesc->entry->entry_idx); ++ test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? ++ txdesc->key_idx : 0xff); + rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, skb->len); + rt2x00_set_field32(&word, TXWI_W1_PACKETID, + skbdesc->entry->queue->qid); + rt2x00_desc_write(txwi, 1, word); + -+ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { -+ _rt2x00_desc_write(txwi, 2, skbdesc->iv[0]); -+ _rt2x00_desc_write(txwi, 3, skbdesc->iv[1]); -+ } ++ /* ++ * Always write 0 to IV/EIV fields, hardware will insert the IV ++ * from the IVEIV register when ENTRY_TXD_ENCRYPT_IV is set to 0. ++ * When ENTRY_TXD_ENCRYPT_IV is set to 1 it will use the IV data ++ * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which ++ * crypto entry in the registers should be used to encrypt the frame. ++ */ ++ _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); ++ _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); + + /* + * Initialize TX descriptor @@ -1836,7 +1972,8 @@ Signed-off-by: Ivo van Doorn + 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_WIV, ++ !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W3_QSEL, 2); + rt2x00_desc_write(txd, 3, word); +} @@ -1911,6 +2048,24 @@ Signed-off-by: Ivo van Doorn + rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx); +} + ++static void rt2800pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, ++ const enum data_queue_qid qid) ++{ ++ u32 reg; ++ ++ if (qid == QID_BEACON) { ++ rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, 0); ++ return; ++ } ++ ++ rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, ®); ++ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, (qid == QID_AC_BE)); ++ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, (qid == QID_AC_BK)); ++ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, (qid == QID_AC_VI)); ++ rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, (qid == QID_AC_VO)); ++ rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg); ++} ++ +/* + * RX control handlers + */ @@ -1942,7 +2097,7 @@ Signed-off-by: Ivo van Doorn + * decryption. This prevents us from correct providing + * correct statistics through debugfs. + */ -+ rxdesc->cipher = CIPHER_NONE; ++ rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); + rxdesc->cipher_status = + rt2x00_get_field32(rxd3, RXD_W3_CIPHER_ERROR); + } @@ -1981,13 +2136,12 @@ Signed-off-by: Ivo van Doorn + /* + * Mask of 0x8 bit to remove the short preamble flag. + */ -+ if (rxdesc->dev_flags == RATE_MODE_CCK) ++ if (rxdesc->rate_mode == RATE_MODE_CCK) + rxdesc->signal &= ~0x8; + + rxdesc->rssi = + (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + -+ rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1) + -+ rt2x00_get_field32(rxwi2, RXWI_W2_RSSI2)) / 3; ++ rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; + + rxdesc->noise = + (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + @@ -1998,7 +2152,7 @@ Signed-off-by: Ivo van Doorn + /* + * Remove TXWI descriptor from start of buffer. + */ -+ skb_pull(entry->skb, TXWI_DESC_SIZE); ++ skb_pull(entry->skb, RXWI_DESC_SIZE); + skb_trim(entry->skb, rxdesc->size); +} + @@ -2122,26 +2276,22 @@ Signed-off-by: Ivo van Doorn + */ +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)); ++ /* ++ * Read EEPROM into buffer ++ */ ++ switch(rt2x00dev->chip.rt) { ++ case RT2880: ++ case RT3052: ++ rt2800pci_read_eeprom_soc(rt2x00dev); ++ break; ++ default: ++ rt2800pci_read_eeprom_pci(rt2x00dev); ++ break; ++ } + + /* + * Start validation of the data that has been read. @@ -2161,12 +2311,27 @@ Signed-off-by: Ivo van Doorn + rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); + rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); ++ } else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) { ++ /* ++ * There is a max of 2 RX streams for RT2860 series ++ */ ++ if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2) ++ rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); ++ rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); + } + + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); -+ if (word != 0) { -+ /* NIC configuration must always be 0. */ -+ word = 0; ++ if (word == 0xffff) { ++ rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0); ++ rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0); ++ rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0); ++ rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0); ++ rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); ++ rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0); ++ rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0); ++ rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0); ++ rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0); ++ rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0); + rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); + EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); + } @@ -2232,7 +2397,6 @@ Signed-off-by: Ivo van Doorn + u32 reg; + u16 value; + u16 eeprom; -+ u16 device; + + /* + * Read EEPROM word for configuration. @@ -2241,20 +2405,18 @@ Signed-off-by: Ivo van Doorn + + /* + * 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); ++ rt2x00_set_chip_rf(rt2x00dev, value, reg); + + if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && + !rt2x00_rf(&rt2x00dev->chip, RF2850) && + !rt2x00_rf(&rt2x00dev->chip, RF2720) && -+ !rt2x00_rf(&rt2x00dev->chip, RF2750)) { ++ !rt2x00_rf(&rt2x00dev->chip, RF2750) && ++ !rt2x00_rf(&rt2x00dev->chip, RF3020) && ++ !rt2x00_rf(&rt2x00dev->chip, RF2020) && ++ !rt2x00_rf(&rt2x00dev->chip, RF3052)) { + ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); + return -ENODEV; + } @@ -2375,13 +2537,16 @@ Signed-off-by: Ivo van Doorn + char *tx_power1; + char *tx_power2; + unsigned int i; ++ u16 eeprom; + + /* + * Initialize all hw fields. + */ + rt2x00dev->hw->flags = + IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | -+ IEEE80211_HW_SIGNAL_DBM; ++ IEEE80211_HW_SIGNAL_DBM | ++ IEEE80211_HW_SUPPORTS_PS | ++ IEEE80211_HW_PS_NULLFUNC_STACK; + rt2x00dev->hw->extra_tx_headroom = TXWI_DESC_SIZE; + + SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); @@ -2389,6 +2554,8 @@ Signed-off-by: Ivo van Doorn + rt2x00_eeprom_addr(rt2x00dev, + EEPROM_MAC_ADDR_0)); + ++ rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); ++ + /* + * Initialize hw_mode information. + */ @@ -2396,7 +2563,8 @@ Signed-off-by: Ivo van Doorn + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; + + if (rt2x00_rf(&rt2x00dev->chip, RF2820) || -+ rt2x00_rf(&rt2x00dev->chip, RF2720)) { ++ rt2x00_rf(&rt2x00dev->chip, RF2720) || ++ rt2x00_rf(&rt2x00dev->chip, RF3052)) { + spec->num_channels = 14; + spec->channels = rf_vals; + } else if (rt2x00_rf(&rt2x00dev->chip, RF2850) || @@ -2420,10 +2588,22 @@ Signed-off-by: Ivo van Doorn + IEEE80211_HT_CAP_PSMP_SUPPORT; + spec->ht.ampdu_factor = 3; + spec->ht.ampdu_density = 4; -+ spec->ht.mcs.rx_mask[0] = 0xff; -+ spec->ht.mcs.rx_mask[1] = 0xff; + spec->ht.mcs.tx_params = -+ IEEE80211_HT_MCS_TX_DEFINED; ++ IEEE80211_HT_MCS_TX_DEFINED | ++ IEEE80211_HT_MCS_TX_RX_DIFF | ++ ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) << ++ IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); ++ ++ switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { ++ case 3: ++ spec->ht.mcs.rx_mask[2] = 0xff; ++ case 2: ++ spec->ht.mcs.rx_mask[1] = 0xff; ++ case 1: ++ spec->ht.mcs.rx_mask[0] = 0xff; ++ spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */ ++ break; ++ } + + /* + * Create channel information array @@ -2495,37 +2675,53 @@ Signed-off-by: Ivo van Doorn +/* + * IEEE80211 stack callback functions. + */ ++static void rt2800pci_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, ++ u32 *iv32, u16 *iv16) ++{ ++ struct rt2x00_dev *rt2x00dev = hw->priv; ++ struct mac_iveiv_entry iveiv_entry; ++ u32 offset; ++ ++ offset = MAC_IVEIV_ENTRY(hw_key_idx); ++ rt2x00pci_register_multiread(rt2x00dev, offset, ++ &iveiv_entry, sizeof(iveiv_entry)); ++ ++ memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16)); ++ memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32)); ++} ++ +static int rt2800pci_set_rts_threshold(struct ieee80211_hw *hw, u32 value) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + u32 reg; ++ bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD); + + 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); ++ rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, enabled); + 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); ++ rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, enabled); + 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); ++ rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, enabled); + 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); ++ rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, enabled); + 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); ++ rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, enabled); + 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); ++ rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, enabled); + rt2x00pci_register_write(rt2x00dev, GF40_PROT_CFG, reg); + + return 0; @@ -2551,24 +2747,23 @@ Signed-off-by: Ivo van Doorn + if (retval) + return retval; + ++ /* ++ * We only need to perform additional register initialization ++ * for WMM queues/ ++ */ ++ if (queue_idx >= 4) ++ return 0; ++ + 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); -+ } ++ offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); ++ field.bit_offset = (queue_idx & 1) * 16; ++ field.bit_mask = 0xffff << field.bit_offset; ++ ++ rt2x00pci_register_read(rt2x00dev, offset, ®); ++ rt2x00_set_field32(®, field, queue->txop); ++ rt2x00pci_register_write(rt2x00dev, offset, reg); + + /* Update WMM registers */ + field.bit_offset = queue_idx * 4; @@ -2587,15 +2782,14 @@ Signed-off-by: Ivo van Doorn + 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); -+ } ++ offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); ++ ++ rt2x00pci_register_read(rt2x00dev, offset, ®); ++ rt2x00_set_field32(®, EDCA_AC0_CFG_TX_OP, queue->txop); ++ 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; +} @@ -2625,6 +2819,7 @@ Signed-off-by: Ivo van Doorn + .configure_filter = rt2x00mac_configure_filter, + .set_key = rt2x00mac_set_key, + .get_stats = rt2x00mac_get_stats, ++ .get_tkip_seq = rt2800pci_get_tkip_seq, + .set_rts_threshold = rt2800pci_set_rts_threshold, + .bss_info_changed = rt2x00mac_bss_info_changed, + .conf_tx = rt2800pci_conf_tx, @@ -2636,7 +2831,7 @@ Signed-off-by: Ivo van Doorn + .irq_handler = rt2800pci_interrupt, + .probe_hw = rt2800pci_probe_hw, + .get_firmware_name = rt2800pci_get_firmware_name, -+ .get_firmware_crc = rt2800pci_get_firmware_crc, ++ .check_firmware = rt2800pci_check_firmware, + .load_firmware = rt2800pci_load_firmware, + .initialize = rt2x00pci_initialize, + .uninitialize = rt2x00pci_uninitialize, @@ -2651,6 +2846,7 @@ Signed-off-by: Ivo van Doorn + .write_tx_data = rt2x00pci_write_tx_data, + .write_beacon = rt2800pci_write_beacon, + .kick_tx_queue = rt2800pci_kick_tx_queue, ++ .kill_tx_queue = rt2800pci_kill_tx_queue, + .fill_rxdone = rt2800pci_fill_rxdone, + .config_shared_key = rt2800pci_config_shared_key, + .config_pairwise_key = rt2800pci_config_pairwise_key, @@ -2663,14 +2859,14 @@ Signed-off-by: Ivo van Doorn + +static const struct data_queue_desc rt2800pci_queue_rx = { + .entry_num = RX_ENTRIES, -+ .data_size = DATA_FRAME_SIZE, ++ .data_size = AGGREGATION_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci), +}; + +static const struct data_queue_desc rt2800pci_queue_tx = { + .entry_num = TX_ENTRIES, -+ .data_size = DATA_FRAME_SIZE, ++ .data_size = AGGREGATION_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci), +}; @@ -2702,23 +2898,142 @@ Signed-off-by: Ivo van Doorn +/* + * RT2800pci module information. + */ ++#ifdef CONFIG_RT2800PCI_PCI +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(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) }, ++ { PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) }, + { 0, } +}; ++MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); ++#endif /* CONFIG_RT2800PCI_PCI */ + +MODULE_AUTHOR(DRV_PROJECT); +MODULE_VERSION(DRV_VERSION); +MODULE_DESCRIPTION("Ralink RT2800 PCI & PCMCIA Wireless LAN driver."); +MODULE_SUPPORTED_DEVICE("Ralink RT2860 PCI & PCMCIA chipset based cards"); -+MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); +MODULE_FIRMWARE(FIRMWARE_RT2860); +MODULE_LICENSE("GPL"); + ++#ifdef CONFIG_RT2800PCI_WISOC ++ ++#ifdef CONFIG_RALINK_RT288X ++#define WSOC_RT_CHIPSET RT2880 ++#endif /* CONFIG_RALINK_RT288X */ ++ ++#ifdef CONFIG_RALINK_RT305X ++#define WSOC_RT_CHIPSET RT3052 ++#endif /* CONFIG_RALINK_RT305X */ ++ ++static void rt2800soc_free_reg(struct rt2x00_dev *rt2x00dev) ++{ ++ kfree(rt2x00dev->rf); ++ rt2x00dev->rf = NULL; ++ ++ kfree(rt2x00dev->eeprom); ++ rt2x00dev->eeprom = NULL; ++} ++ ++static int rt2800soc_alloc_reg(struct rt2x00_dev *rt2x00dev) ++{ ++ struct platform_device *pdev = to_platform_device(rt2x00dev->dev); ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ ERROR_PROBE("Failed to get MMIO resource\n"); ++ return -ENODEV; ++ } ++ ++ rt2x00dev->csr.base = (void __iomem *) KSEG1ADDR(res->start); ++ rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL); ++ if (!rt2x00dev->eeprom) ++ goto exit; ++ ++ rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL); ++ if (!rt2x00dev->rf) ++ goto exit; ++ ++ return 0; ++ ++exit: ++ ERROR_PROBE("Failed to allocate registers.\n"); ++ rt2800soc_free_reg(rt2x00dev); ++ ++ return -ENOMEM; ++} ++ ++static int rt2800soc_probe(struct platform_device *pdev) ++{ ++ const struct rt2x00_ops *ops = &rt2800pci_ops; ++ struct ieee80211_hw *hw; ++ struct rt2x00_dev *rt2x00dev; ++ int retval; ++ ++ hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); ++ if (!hw) { ++ ERROR_PROBE("Failed to allocate hardware.\n"); ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(pdev, hw); ++ ++ rt2x00dev = hw->priv; ++ rt2x00dev->dev = &pdev->dev; ++ rt2x00dev->ops = ops; ++ rt2x00dev->hw = hw; ++ rt2x00dev->irq = platform_get_irq(pdev, 0); ++ rt2x00dev->name = pdev->dev.driver->name; ++ ++ rt2x00_set_chip_rt(rt2x00dev, WSOC_RT_CHIPSET); ++ ++ retval = rt2800soc_alloc_reg(rt2x00dev); ++ if (retval) ++ goto exit_free_device; ++ ++ retval = rt2x00lib_probe_dev(rt2x00dev); ++ if (retval) ++ goto exit_free_reg; ++ ++ return 0; ++ ++exit_free_reg: ++ rt2800soc_free_reg(rt2x00dev); ++ ++exit_free_device: ++ ieee80211_free_hw(hw); ++ ++ return retval; ++} ++ ++static int rt2800soc_remove(struct platform_device *pdev) ++{ ++ struct ieee80211_hw *hw = platform_get_drvdata(pdev); ++ struct rt2x00_dev *rt2x00dev = hw->priv; ++ ++ /* ++ * Free all allocated data. ++ */ ++ rt2x00lib_remove_dev(rt2x00dev); ++ rt2800soc_free_reg(rt2x00dev); ++ ieee80211_free_hw(hw); ++ ++ return 0; ++} ++ ++static struct platform_driver rt2800soc_driver = { ++ .driver.name = "rt2800_wmac", ++ .probe = rt2800soc_probe, ++ .remove = rt2800soc_remove, ++}; ++#endif /* CONFIG_RT2800PCI_WISOC */ ++ ++#ifdef CONFIG_RT2800PCI_PCI +static struct pci_driver rt2800pci_driver = { + .name = KBUILD_MODNAME, + .id_table = rt2800pci_device_table, @@ -2727,24 +3042,38 @@ Signed-off-by: Ivo van Doorn + .suspend = rt2x00pci_suspend, + .resume = rt2x00pci_resume, +}; ++#endif /* CONFIG_RT2800PCI_PCI */ + +static int __init rt2800pci_init(void) +{ -+ return pci_register_driver(&rt2800pci_driver); ++ int ret = 0; ++ ++#ifdef CONFIG_RT2800PCI_WISOC ++ ret = platform_driver_register(&rt2800soc_driver); ++#endif ++#ifdef CONFIG_RT2800PCI_PCI ++ ret = pci_register_driver(&rt2800pci_driver); ++#endif ++ return ret; +} + +static void __exit rt2800pci_exit(void) +{ ++#ifdef CONFIG_RT2800PCI_PCI + pci_unregister_driver(&rt2800pci_driver); ++#endif ++#ifdef CONFIG_RT2800PCI_WISOC ++ platform_driver_unregister(&rt2800soc_driver); ++#endif +} + +module_init(rt2800pci_init); +module_exit(rt2800pci_exit); --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2800pci.h -@@ -0,0 +1,1879 @@ +@@ -0,0 +1,1880 @@ +/* -+ Copyright (C) 2004 - 2008 rt2x00 SourceForge Project ++ Copyright (C) 2004 - 2009 rt2x00 SourceForge Project + + + This program is free software; you can redistribute it and/or modify @@ -2781,6 +3110,7 @@ Signed-off-by: Ivo van Doorn + * RF2750 2.4G/5G 1T2R + * RF3020 2.4G 1T1R + * RF2020 2.4G B/G ++ * RF3052 2.4G 2T2R + */ +#define RF2820 0x0001 +#define RF2850 0x0002 @@ -2788,13 +3118,16 @@ Signed-off-by: Ivo van Doorn +#define RF2750 0x0004 +#define RF3020 0x0005 +#define RF2020 0x0006 ++#define RF3052 0x0008 + +/* + * RT2860 version + */ -+#define RT2860_VERSION_C 0x0100 -+#define RT2860_VERSION_D 0x0101 -+#define RT2860_VERSION_E 0x0200 ++#define RT2860C_VERSION 0x28600100 ++#define RT2860D_VERSION 0x28600101 ++#define RT2880E_VERSION 0x28720200 ++#define RT2883_VERSION 0x28830300 ++#define RT3070_VERSION 0x30700200 + +/* + * Signal information. @@ -2811,8 +3144,8 @@ Signed-off-by: Ivo van Doorn +#define EEPROM_SIZE 0x0110 +#define BBP_BASE 0x0000 +#define BBP_SIZE 0x0080 -+#define RF_BASE 0x0000 -+#define RF_SIZE 0x0014 ++#define RF_BASE 0x0004 ++#define RF_SIZE 0x0010 + +/* + * Number of TX queues. @@ -2832,7 +3165,7 @@ Signed-off-by: Ivo van Doorn +/* + * E2PROM_CSR: EEPROM control register. + * RELOAD: Write 1 to reload eeprom content. -+ * TYPE_93C46: 1: 93c46, 0:93c66. ++ * TYPE: 0: 93c46, 1:93c66. + * LOAD_STATUS: 1:loading, 0:done. + */ +#define E2PROM_CSR 0x0004 @@ -2840,7 +3173,7 @@ Signed-off-by: Ivo van Doorn +#define E2PROM_CSR_CHIP_SELECT FIELD32(0x00000002) +#define E2PROM_CSR_DATA_IN FIELD32(0x00000004) +#define E2PROM_CSR_DATA_OUT FIELD32(0x00000008) -+#define E2PROM_CSR_TYPE_93C46 FIELD32(0x00000020) ++#define E2PROM_CSR_TYPE FIELD32(0x00000030) +#define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) +#define E2PROM_CSR_RELOAD FIELD32(0x00000080) + @@ -2993,11 +3326,6 @@ Signed-off-by: Ivo van Doorn +#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) + +/* -+ * RINGREG_DIFF -+ */ -+#define RINGREG_DIFF 0x0010 -+ -+/* + * GPIO_CTRL_CFG: + */ +#define GPIO_CTRL_CFG 0x0228 @@ -3090,7 +3418,7 @@ Signed-off-by: Ivo van Doorn +#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) + +/* -+ * PBF registers ++ * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define PBF_CFG 0x0408 @@ -3118,7 +3446,7 @@ Signed-off-by: Ivo van Doorn +#define BCN_OFFSET1_BCN7 FIELD32(0xff000000) + +/* -+ * PBF registers ++ * PBF registers + * Most are for debug. Driver doesn't touch PBF register. + */ +#define TXRXQ_PCNT 0x0438 @@ -3412,7 +3740,7 @@ Signed-off-by: Ivo van Doorn + * EDCA_AC0_CFG: + */ +#define EDCA_AC0_CFG 0x1300 -+#define EDCA_AC0_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC0_CFG_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) @@ -3421,7 +3749,7 @@ Signed-off-by: Ivo van Doorn + * EDCA_AC1_CFG: + */ +#define EDCA_AC1_CFG 0x1304 -+#define EDCA_AC1_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC1_CFG_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) @@ -3430,7 +3758,7 @@ Signed-off-by: Ivo van Doorn + * EDCA_AC2_CFG: + */ +#define EDCA_AC2_CFG 0x1308 -+#define EDCA_AC2_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC2_CFG_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) @@ -3439,7 +3767,7 @@ Signed-off-by: Ivo van Doorn + * EDCA_AC3_CFG: + */ +#define EDCA_AC3_CFG 0x130c -+#define EDCA_AC3_CFG_AC_TX_OP FIELD32(0x000000ff) ++#define EDCA_AC3_CFG_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) @@ -3539,6 +3867,7 @@ Signed-off-by: Ivo van Doorn + * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz + */ +#define TX_BAND_CFG 0x132c ++#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001) +#define TX_BAND_CFG_A FIELD32(0x00000002) +#define TX_BAND_CFG_BG FIELD32(0x00000004) + @@ -4030,64 +4359,54 @@ Signed-off-by: Ivo van Doorn +#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 ++ * SHARED_KEY_MODE_BASE: 4-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 MAC_WCID_ENTRY(__idx) \ ++ ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) ) ++#define PAIRWISE_KEY_ENTRY(__idx) \ ++ ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) ++#define MAC_IVEIV_ENTRY(__idx) \ ++ ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) ) ++#define MAC_WCID_ATTR_ENTRY(__idx) \ ++ ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) +#define SHARED_KEY_ENTRY(__idx) \ -+ ( SHARED_KEY_TABLE_BASE + \ -+ ((__idx) * sizeof(struct hw_key_entry)) ) ++ ( 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)) ) ++struct mac_wcid_entry { ++ u8 mac[6]; ++ u8 reserved[2]; ++} __attribute__ ((packed)); ++ ++struct hw_key_entry { ++ u8 key[16]; ++ u8 tx_mic[8]; ++ u8 rx_mic[8]; ++} __attribute__ ((packed)); ++ ++struct mac_iveiv_entry { ++ u8 iv[8]; ++} __attribute__ ((packed)); + +/* + * 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_CIPHER FIELD32(0x0000000e) +#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) +#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) + @@ -4120,6 +4439,10 @@ Signed-off-by: Ivo van Doorn + * H2M_MAILBOX_CID: + */ +#define H2M_MAILBOX_CID 0x7014 ++#define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) ++#define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00) ++#define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000) ++#define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000) + +/* + * H2M_MAILBOX_STATUS: @@ -4248,7 +4571,7 @@ Signed-off-by: Ivo van Doorn +#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) ++#define RF4_HT40 FIELD32(0x00200000) + +/* + * EEPROM content. @@ -4382,7 +4705,7 @@ Signed-off-by: Ivo van Doorn +#define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080) + +/* -+ * EEPROM TXPOWER 802.11G ++ * EEPROM TXPOWER 802.11BG + */ +#define EEPROM_TXPOWER_BG1 0x0029 +#define EEPROM_TXPOWER_BG2 0x0030 @@ -4417,6 +4740,7 @@ Signed-off-by: Ivo van Doorn + */ +#define MCU_SLEEP 0x30 +#define MCU_WAKEUP 0x31 ++#define MCU_RADIO_OFF 0x35 +#define MCU_LED 0x50 +#define MCU_LED_STRENGTH 0x51 +#define MCU_LED_1 0x52 @@ -4424,6 +4748,12 @@ Signed-off-by: Ivo van Doorn +#define MCU_LED_3 0x54 +#define MCU_RADAR 0x60 +#define MCU_BOOT_SIGNAL 0x72 ++#define MCU_BBP_SIGNAL 0x80 ++ ++/* ++ * MCU mailbox tokens ++ */ ++#define TOKEN_WAKUP 3 + +/* + * DMA descriptor defines. @@ -4624,7 +4954,7 @@ Signed-off-by: Ivo van Doorn +#endif /* RT2800PCI_H */ --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h -@@ -139,6 +139,10 @@ struct rt2x00_chip { +@@ -138,6 +138,12 @@ struct rt2x00_chip { #define RT2561 0x0302 #define RT2661 0x0401 #define RT2571 0x1300 @@ -4632,6 +4962,8 @@ Signed-off-by: Ivo van Doorn +#define RT2860D 0x0681 /* 2.4GHz, 5GHz PCI/CB */ +#define RT2890 0x0701 /* 2.4GHz PCIe */ +#define RT2890D 0x0781 /* 2.4GHz, 5GHz PCIe */ ++#define RT2880 0x2880 /* WSOC */ ++#define RT3052 0x3052 /* WSOC */ u16 rf; u32 rev;