X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fnet%2Fwireless%2Frt2x00%2Frt2500usb.c;h=9ae96a626e6d0fafc6b8a633af03c75a135c5b3d;hb=6fe70aae0d128339febfabc073ba4c4a03de4f45;hp=c5f49e36559a205e71381a48c295bed9fc627931;hpb=6c6aa3c004e702532cb0f549a96eb2f75636bd3b;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index c5f49e3..9ae96a6 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + Copyright (C) 2004 - 2009 Ivo van Doorn This program is free software; you can redistribute it and/or modify @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "rt2x00.h" @@ -36,6 +37,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. @@ -47,7 +55,7 @@ * 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. - * If the usb_cache_mutex is already held then the _lock variants must + * If the csr_mutex is already held then the _lock variants must * be used instead. */ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, @@ -57,7 +65,7 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, __le16 reg; rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(u16), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); *value = le16_to_cpu(reg); } @@ -68,7 +76,7 @@ static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev, __le16 reg; rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(u16), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); *value = le16_to_cpu(reg); } @@ -89,7 +97,7 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, __le16 reg = cpu_to_le16(value); rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(u16), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); } static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, @@ -99,7 +107,7 @@ static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, __le16 reg = cpu_to_le16(value); rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(u16), REGISTER_TIMEOUT); + ®, sizeof(reg), REGISTER_TIMEOUT); } static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, @@ -112,53 +120,53 @@ static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, REGISTER_TIMEOUT16(length)); } -static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev) +static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + struct rt2x00_field16 field, + u16 *reg) { - u16 reg; unsigned int i; for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, ®); - if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY)) - break; + rt2500usb_register_read_lock(rt2x00dev, offset, reg); + if (!rt2x00_get_field16(*reg, field)) + return 1; udelay(REGISTER_BUSY_DELAY); } - return reg; + ERROR(rt2x00dev, "Indirect register access failed: " + "offset=0x%.08x, value=0x%.08x\n", offset, *reg); + *reg = ~0; + + return 0; } +#define WAIT_FOR_BBP(__dev, __reg) \ + rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg)) +#define WAIT_FOR_RF(__dev, __reg) \ + rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg)) + static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u8 value) { u16 reg; - mutex_lock(&rt2x00dev->usb_cache_mutex); - - /* - * Wait until the BBP becomes ready. - */ - reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) - goto exit_fail; + mutex_lock(&rt2x00dev->csr_mutex); /* - * Write the data into the BBP. + * Wait until the BBP becomes available, afterwards we + * can safely write the new data into the register. */ - reg = 0; - rt2x00_set_field16(®, PHY_CSR7_DATA, value); - rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); - rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); - - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); - - mutex_unlock(&rt2x00dev->usb_cache_mutex); - - return; + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field16(®, PHY_CSR7_DATA, value); + rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); + rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); -exit_fail: - mutex_unlock(&rt2x00dev->usb_cache_mutex); + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); + } - ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); + mutex_unlock(&rt2x00dev->csr_mutex); } static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, @@ -166,129 +174,119 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, { u16 reg; - mutex_lock(&rt2x00dev->usb_cache_mutex); - - /* - * Wait until the BBP becomes ready. - */ - reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) - goto exit_fail; + mutex_lock(&rt2x00dev->csr_mutex); /* - * Write the request into the BBP. + * Wait until the BBP becomes available, afterwards we + * can safely write the read request into the register. + * After the data has been written, we wait until hardware + * returns the correct value, if at any time the register + * doesn't become available in time, reg will be 0xffffffff + * which means we return 0xff to the caller. */ - reg = 0; - rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); - rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); + if (WAIT_FOR_BBP(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); + rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); - /* - * Wait until the BBP becomes ready. - */ - reg = rt2500usb_bbp_check(rt2x00dev); - if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) - goto exit_fail; + if (WAIT_FOR_BBP(rt2x00dev, ®)) + rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); + } - rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); - mutex_unlock(&rt2x00dev->usb_cache_mutex); - - return; - -exit_fail: - mutex_unlock(&rt2x00dev->usb_cache_mutex); - - ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); - *value = 0xff; + mutex_unlock(&rt2x00dev->csr_mutex); } static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, const unsigned int word, const u32 value) { u16 reg; - unsigned int i; - if (!word) - return; + mutex_lock(&rt2x00dev->csr_mutex); - mutex_lock(&rt2x00dev->usb_cache_mutex); - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, ®); - if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY)) - goto rf_write; - udelay(REGISTER_BUSY_DELAY); - } - - mutex_unlock(&rt2x00dev->usb_cache_mutex); - ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n"); - return; - -rf_write: - reg = 0; - rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value); - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg); + /* + * Wait until the RF becomes available, afterwards we + * can safely write the new data into the register. + */ + if (WAIT_FOR_RF(rt2x00dev, ®)) { + reg = 0; + rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value); + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg); - reg = 0; - rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16); - rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20); - rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0); - rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); + reg = 0; + rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16); + rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20); + rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0); + rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); - rt2x00_rf_write(rt2x00dev, word, value); + rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); + rt2x00_rf_write(rt2x00dev, word, value); + } - mutex_unlock(&rt2x00dev->usb_cache_mutex); + mutex_unlock(&rt2x00dev->csr_mutex); } #ifdef CONFIG_RT2X00_LIB_DEBUGFS -#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u16)) ) - -static void rt2500usb_read_csr(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u32 *data) +static void _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u32 *value) { - rt2500usb_register_read(rt2x00dev, CSR_OFFSET(word), (u16 *) data); + rt2500usb_register_read(rt2x00dev, offset, (u16 *)value); } -static void rt2500usb_write_csr(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u32 data) +static void _rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, + const unsigned int offset, + u32 value) { - rt2500usb_register_write(rt2x00dev, CSR_OFFSET(word), data); + rt2500usb_register_write(rt2x00dev, offset, value); } static const struct rt2x00debug rt2500usb_rt2x00debug = { .owner = THIS_MODULE, .csr = { - .read = rt2500usb_read_csr, - .write = rt2500usb_write_csr, + .read = _rt2500usb_register_read, + .write = _rt2500usb_register_write, + .flags = RT2X00DEBUGFS_OFFSET, + .word_base = CSR_REG_BASE, .word_size = sizeof(u16), .word_count = CSR_REG_SIZE / sizeof(u16), }, .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 = rt2500usb_bbp_read, .write = rt2500usb_bbp_write, + .word_base = BBP_BASE, .word_size = sizeof(u8), .word_count = BBP_SIZE / sizeof(u8), }, .rf = { .read = rt2x00_rf_read, .write = rt2500usb_rf_write, + .word_base = RF_BASE, .word_size = sizeof(u32), .word_count = RF_SIZE / sizeof(u32), }, }; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ -#ifdef CONFIG_RT2500USB_LEDS +static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) +{ + u16 reg; + + rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); + return rt2x00_get_field32(reg, MAC_CSR19_BIT7); +} + +#ifdef CONFIG_RT2X00_LIB_LEDS static void rt2500usb_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { @@ -333,11 +331,87 @@ static void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev, led->led_dev.blink_set = rt2500usb_blink_set; led->flags = LED_INITIALIZED; } -#endif /* CONFIG_RT2500USB_LEDS */ +#endif /* CONFIG_RT2X00_LIB_LEDS */ /* * 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; + + 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, ®); + reg &= mask; + + if (reg && reg == 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 separately 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 demands the data to be provided + * both separately as well as inside the frame. + * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib + * to ensure rt2x00lib will not strip the data from the + * frame after the copy, now 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) { @@ -380,11 +454,11 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, /* * Enable beacon config */ - bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); + bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6); rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, - 2 * (conf->type != IEEE80211_IF_TYPE_STA)); + 2 * (conf->type != NL80211_IFTYPE_STATION)); rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg); /* @@ -415,65 +489,24 @@ static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, { u16 reg; - rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); - rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, erp->ack_timeout); - rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg); - rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®); rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, !!erp->short_preamble); rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); -} - -static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev, - const int basic_rate_mask) -{ - rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask); -} -static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, - struct rf_channel *rf, const int txpower) -{ - /* - * Set TXpower. - */ - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); - - /* - * For RT2525E we should first set the channel to half band higher. - */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { - static const u32 vals[] = { - 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2, - 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba, - 0x000008ba, 0x000008be, 0x000008b7, 0x00000902, - 0x00000902, 0x00000906 - }; - - rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]); - if (rf->rf4) - rt2500usb_rf_write(rt2x00dev, 4, rf->rf4); - } - - rt2500usb_rf_write(rt2x00dev, 1, rf->rf1); - rt2500usb_rf_write(rt2x00dev, 2, rf->rf2); - rt2500usb_rf_write(rt2x00dev, 3, rf->rf3); - if (rf->rf4) - rt2500usb_rf_write(rt2x00dev, 4, rf->rf4); -} + rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates); -static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev, - const int txpower) -{ - u32 rf3; + rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); + rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, erp->beacon_int * 4); + rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); - rt2x00_rf_read(rt2x00dev, 3, &rf3); - rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); - rt2500usb_rf_write(rt2x00dev, 3, rf3); + rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time); + rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs); + rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs); } -static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) +static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, + struct antenna_setup *ant) { u8 r2; u8 r14; @@ -533,8 +566,7 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, /* * RT2525E and RT5222 need to flip TX I/Q */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || - rt2x00_rf(&rt2x00dev->chip, RF5222)) { + if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) { rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1); rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1); @@ -542,7 +574,7 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, /* * RT2525E does not need RX I/Q Flip. */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) + if (rt2x00_rf(rt2x00dev, RF2525E)) rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); } else { rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0); @@ -555,37 +587,90 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, rt2500usb_register_write(rt2x00dev, PHY_CSR6, csr6); } -static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) +static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, + struct rf_channel *rf, const int txpower) +{ + /* + * Set TXpower. + */ + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); + + /* + * For RT2525E we should first set the channel to half band higher. + */ + if (rt2x00_rf(rt2x00dev, RF2525E)) { + static const u32 vals[] = { + 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2, + 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba, + 0x000008ba, 0x000008be, 0x000008b7, 0x00000902, + 0x00000902, 0x00000906 + }; + + rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]); + if (rf->rf4) + rt2500usb_rf_write(rt2x00dev, 4, rf->rf4); + } + + rt2500usb_rf_write(rt2x00dev, 1, rf->rf1); + rt2500usb_rf_write(rt2x00dev, 2, rf->rf2); + rt2500usb_rf_write(rt2x00dev, 3, rf->rf3); + if (rf->rf4) + rt2500usb_rf_write(rt2x00dev, 4, rf->rf4); +} + +static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev, + const int txpower) { + u32 rf3; + + rt2x00_rf_read(rt2x00dev, 3, &rf3); + rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); + rt2500usb_rf_write(rt2x00dev, 3, rf3); +} + +static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf) +{ + enum dev_state state = + (libconf->conf->flags & IEEE80211_CONF_PS) ? + STATE_SLEEP : STATE_AWAKE; u16 reg; - rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time); - rt2500usb_register_write(rt2x00dev, MAC_CSR11, libconf->sifs); - rt2500usb_register_write(rt2x00dev, MAC_CSR12, libconf->eifs); + if (state == STATE_SLEEP) { + rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); + rt2x00_set_field16(®, MAC_CSR18_DELAY_AFTER_BEACON, + rt2x00dev->beacon_int - 20); + rt2x00_set_field16(®, MAC_CSR18_BEACONS_BEFORE_WAKEUP, + libconf->conf->listen_interval - 1); - rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); - rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, - libconf->conf->beacon_int * 4); - rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); + /* We must first disable autowake before it can be enabled */ + rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); + + rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 1); + rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); + } else { + rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); + rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); + } + + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); } static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int flags) { - if (flags & CONFIG_UPDATE_PHYMODE) - rt2500usb_config_phymode(rt2x00dev, libconf->basic_rates); - if (flags & CONFIG_UPDATE_CHANNEL) + if (flags & IEEE80211_CONF_CHANGE_CHANNEL) rt2500usb_config_channel(rt2x00dev, &libconf->rf, libconf->conf->power_level); - if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL)) + if ((flags & IEEE80211_CONF_CHANGE_POWER) && + !(flags & IEEE80211_CONF_CHANGE_CHANNEL)) rt2500usb_config_txpower(rt2x00dev, libconf->conf->power_level); - if (flags & CONFIG_UPDATE_ANTENNA) - rt2500usb_config_antenna(rt2x00dev, &libconf->ant); - if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT)) - rt2500usb_config_duration(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_PS) + rt2500usb_config_ps(rt2x00dev, libconf); } /* @@ -609,7 +694,8 @@ static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev, qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR); } -static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev) +static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev, + struct link_qual *qual) { u16 eeprom; u16 value; @@ -630,143 +716,10 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev) value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER); rt2500usb_bbp_write(rt2x00dev, 17, value); - rt2x00dev->link.vgc_level = value; + qual->vgc_level = value; } /* - * NOTE: This function is directly ported from legacy driver, but - * despite it being declared it was never called. Although link tuning - * sounds like a good idea, and usually works well for the other drivers, - * it does _not_ work with rt2500usb. Enabling this function will result - * in TX capabilities only until association kicks in. Immediately - * after the successful association all TX frames will be kept in the - * hardware queue and never transmitted. - */ -#if 0 -static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) -{ - int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); - u16 bbp_thresh; - u16 vgc_bound; - u16 sens; - u16 r24; - u16 r25; - u16 r61; - u16 r17_sens; - u8 r17; - u8 up_bound; - u8 low_bound; - - /* - * Read current r17 value, as well as the sensitivity values - * for the r17 register. - */ - rt2500usb_bbp_read(rt2x00dev, 17, &r17); - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound); - up_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER); - low_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCLOWER); - - /* - * If we are not associated, we should go straight to the - * dynamic CCA tuning. - */ - if (!rt2x00dev->intf_associated) - goto dynamic_cca_tune; - - /* - * Determine the BBP tuning threshold and correctly - * set BBP 24, 25 and 61. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &bbp_thresh); - bbp_thresh = rt2x00_get_field16(bbp_thresh, EEPROM_BBPTUNE_THRESHOLD); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &r24); - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &r25); - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &r61); - - if ((rssi + bbp_thresh) > 0) { - r24 = rt2x00_get_field16(r24, EEPROM_BBPTUNE_R24_HIGH); - r25 = rt2x00_get_field16(r25, EEPROM_BBPTUNE_R25_HIGH); - r61 = rt2x00_get_field16(r61, EEPROM_BBPTUNE_R61_HIGH); - } else { - r24 = rt2x00_get_field16(r24, EEPROM_BBPTUNE_R24_LOW); - r25 = rt2x00_get_field16(r25, EEPROM_BBPTUNE_R25_LOW); - r61 = rt2x00_get_field16(r61, EEPROM_BBPTUNE_R61_LOW); - } - - rt2500usb_bbp_write(rt2x00dev, 24, r24); - rt2500usb_bbp_write(rt2x00dev, 25, r25); - rt2500usb_bbp_write(rt2x00dev, 61, r61); - - /* - * A too low RSSI will cause too much false CCA which will - * then corrupt the R17 tuning. To remidy this the tuning should - * be stopped (While making sure the R17 value will not exceed limits) - */ - if (rssi >= -40) { - if (r17 != 0x60) - rt2500usb_bbp_write(rt2x00dev, 17, 0x60); - return; - } - - /* - * Special big-R17 for short distance - */ - if (rssi >= -58) { - sens = rt2x00_get_field16(r17_sens, EEPROM_BBPTUNE_R17_LOW); - if (r17 != sens) - rt2500usb_bbp_write(rt2x00dev, 17, sens); - return; - } - - /* - * Special mid-R17 for middle distance - */ - if (rssi >= -74) { - sens = rt2x00_get_field16(r17_sens, EEPROM_BBPTUNE_R17_HIGH); - if (r17 != sens) - rt2500usb_bbp_write(rt2x00dev, 17, sens); - return; - } - - /* - * Leave short or middle distance condition, restore r17 - * to the dynamic tuning range. - */ - low_bound = 0x32; - if (rssi < -77) - up_bound -= (-77 - rssi); - - if (up_bound < low_bound) - up_bound = low_bound; - - if (r17 > up_bound) { - rt2500usb_bbp_write(rt2x00dev, 17, up_bound); - rt2x00dev->link.vgc_level = up_bound; - return; - } - -dynamic_cca_tune: - - /* - * R17 is inside the dynamic tuning range, - * start tuning the link based on the false cca counter. - */ - if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) { - rt2500usb_bbp_write(rt2x00dev, 17, ++r17); - rt2x00dev->link.vgc_level = r17; - } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) { - rt2500usb_bbp_write(rt2x00dev, 17, --r17); - rt2x00dev->link.vgc_level = r17; - } -} -#else -#define rt2500usb_link_tuner NULL -#endif - -/* * Initialization functions. */ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) @@ -844,7 +797,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); - if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { + if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) { rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); rt2x00_set_field16(®, PHY_CSR2_LNA, 0); } else { @@ -866,7 +819,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) 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, ®); @@ -1081,26 +1034,12 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct txentry_desc *txdesc) { struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = skbdesc->desc; + __le32 *txd = (__le32 *)(skb->data - TXD_DESC_SIZE); u32 word; /* * 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_AIFS, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); - rt2x00_desc_write(txd, 1, word); - - rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); - rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); - rt2x00_desc_write(txd, 2, word); - 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, @@ -1110,14 +1049,39 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); + (txdesc->rate_mode == RATE_MODE_OFDM)); rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, - skb->len - skbdesc->desc_len); - rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length); + rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher); + rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx); rt2x00_desc_write(txd, 0, word); + + rt2x00_desc_read(txd, 1, &word); + 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); + rt2x00_desc_write(txd, 1, word); + + rt2x00_desc_read(txd, 2, &word); + rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); + rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); + rt2x00_desc_write(txd, 2, word); + + if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { + _rt2x00_desc_write(txd, 3, skbdesc->iv[0]); + _rt2x00_desc_write(txd, 4, skbdesc->iv[1]); + } + + /* + * Register descriptor details in skb frame descriptor. + */ + skbdesc->desc = txd; + skbdesc->desc_len = TXD_DESC_SIZE; } /* @@ -1125,51 +1089,35 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ static void rt2500usb_beacondone(struct urb *urb); -static void rt2500usb_write_beacon(struct queue_entry *entry) +static void rt2500usb_write_beacon(struct queue_entry *entry, + struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - int pipe = usb_sndbulkpipe(usb_dev, 1); + int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint); int length; - u16 reg; - u32 word, len; - - /* - * 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; - - /* - * Adjust the beacon databyte count. The current number is - * calculated before this function gets called, but falsely - * assumes that the descriptor was already present in the SKB. - */ - rt2x00_desc_read(skbdesc->desc, 0, &word); - len = rt2x00_get_field32(word, TXD_W0_DATABYTE_COUNT); - len += skbdesc->desc_len; - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, len); - rt2x00_desc_write(skbdesc->desc, 0, word); + u16 reg, reg0; /* * Disable beaconing while we are reloading the beacon data, * otherwise we might be sending out invalid data. */ rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); /* + * Take the descriptor in front of the skb into account. + */ + skb_push(entry->skb, TXD_DESC_SIZE); + + /* * USB devices cannot blindly pass the skb->len as the * length of the data to usb_fill_bulk_urb. Pass the skb * to the driver to determine what the length should be. */ - length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb); + length = rt2x00dev->ops->lib->get_tx_data_len(entry); usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, entry->skb->data, length, rt2500usb_beacondone, @@ -1189,10 +1137,29 @@ static void rt2500usb_write_beacon(struct queue_entry *entry) * Send out the guardian byte. */ usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); + + /* + * Enable beaconing again. + */ + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); + reg0 = reg; + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1); + /* + * Beacon generation will fail initially. + * To prevent this we need to change the TXRX_CSR19 + * register several times (reg0 is the same as reg + * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0 + * and 1 in reg). + */ + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); } -static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb) +static int rt2500usb_get_tx_data_len(struct queue_entry *entry) { int length; @@ -1200,46 +1167,19 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, * The length _must_ be a multiple of 2, * but it must _not_ be a multiple of the USB packet size. */ - length = roundup(skb->len, 2); - length += (2 * !(length % rt2x00dev->usb_maxpacket)); + length = roundup(entry->skb->len, 2); + length += (2 * !(length % entry->queue->usb_maxpacket)); return length; } -static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) -{ - u16 reg; - - if (queue != QID_BEACON) { - rt2x00usb_kick_tx_queue(rt2x00dev, queue); - return; - } - - rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) { - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); - rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1); - /* - * Beacon generation will fail initially. - * To prevent this we need to register the TXRX_CSR19 - * register several times. - */ - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - } -} - /* * RX control handlers */ 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 = @@ -1267,6 +1207,24 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; + 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[0]); + _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]); + rxdesc->dev_flags |= RXDONE_CRYPTO_IV; + + /* ICV is located at the end of frame */ + + 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, @@ -1274,8 +1232,8 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, * 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)) @@ -1332,10 +1290,8 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) */ mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { - DECLARE_MAC_BUF(macbuf); - random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac)); + EEPROM(rt2x00dev, "MAC: %pM\n", mac); } rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); @@ -1449,17 +1405,17 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); rt2x00_set_chip(rt2x00dev, RT2570, value, reg); - if (!rt2x00_check_rev(&rt2x00dev->chip, 0)) { + if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) { ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } - if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && - !rt2x00_rf(&rt2x00dev->chip, RF2523) && - !rt2x00_rf(&rt2x00dev->chip, RF2524) && - !rt2x00_rf(&rt2x00dev->chip, RF2525) && - !rt2x00_rf(&rt2x00dev->chip, RF2525E) && - !rt2x00_rf(&rt2x00dev->chip, RF5222)) { + if (!rt2x00_rf(rt2x00dev, RF2522) && + !rt2x00_rf(rt2x00dev, RF2523) && + !rt2x00_rf(rt2x00dev, RF2524) && + !rt2x00_rf(rt2x00dev, RF2525) && + !rt2x00_rf(rt2x00dev, RF2525E) && + !rt2x00_rf(rt2x00dev, RF5222)) { ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); return -ENODEV; } @@ -1486,14 +1442,22 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Store led mode, for correct led behaviour. */ -#ifdef CONFIG_RT2500USB_LEDS +#ifdef CONFIG_RT2X00_LIB_LEDS value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - if (value == LED_MODE_TXRX_ACTIVITY) + if (value == LED_MODE_TXRX_ACTIVITY || + value == LED_MODE_DEFAULT || + value == LED_MODE_ASUS) rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_ACTIVITY); -#endif /* CONFIG_RT2500USB_LEDS */ +#endif /* CONFIG_RT2X00_LIB_LEDS */ + + /* + * Detect if this device has an hardware controlled radio. + */ + if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); /* * Check if the BBP tuning should be disabled. @@ -1680,9 +1644,9 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM; - - rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK; SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, @@ -1695,22 +1659,22 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->supported_bands = SUPPORT_BAND_2GHZ; spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { + if (rt2x00_rf(rt2x00dev, RF2522)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); spec->channels = rf_vals_bg_2522; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { + } else if (rt2x00_rf(rt2x00dev, RF2523)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); spec->channels = rf_vals_bg_2523; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { + } else if (rt2x00_rf(rt2x00dev, RF2524)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); spec->channels = rf_vals_bg_2524; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { + } else if (rt2x00_rf(rt2x00dev, RF2525)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); spec->channels = rf_vals_bg_2525; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { + } else if (rt2x00_rf(rt2x00dev, RF2525E)) { spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); spec->channels = rf_vals_bg_2525e; - } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { + } else if (rt2x00_rf(rt2x00dev, RF5222)) { spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_5222); spec->channels = rf_vals_5222; @@ -1764,7 +1728,10 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) */ __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(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); + } __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); /* @@ -1782,33 +1749,37 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .add_interface = rt2x00mac_add_interface, .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, - .config_interface = rt2x00mac_config_interface, .configure_filter = rt2x00mac_configure_filter, + .set_tim = rt2x00mac_set_tim, + .set_key = rt2x00mac_set_key, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, + .rfkill_poll = rt2x00mac_rfkill_poll, }; static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .probe_hw = rt2500usb_probe_hw, .initialize = rt2x00usb_initialize, .uninitialize = rt2x00usb_uninitialize, - .init_rxentry = rt2x00usb_init_rxentry, - .init_txentry = rt2x00usb_init_txentry, + .clear_entry = rt2x00usb_clear_entry, .set_device_state = rt2500usb_set_device_state, + .rfkill_poll = rt2500usb_rfkill_poll, .link_stats = rt2500usb_link_stats, .reset_tuner = rt2500usb_reset_tuner, - .link_tuner = rt2500usb_link_tuner, .write_tx_desc = rt2500usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, .write_beacon = rt2500usb_write_beacon, .get_tx_data_len = rt2500usb_get_tx_data_len, - .kick_tx_queue = rt2500usb_kick_tx_queue, + .kick_tx_queue = rt2x00usb_kick_tx_queue, + .kill_tx_queue = rt2x00usb_kill_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, + .config_ant = rt2500usb_config_ant, .config = rt2500usb_config, }; @@ -1841,20 +1812,21 @@ static const struct data_queue_desc rt2500usb_queue_atim = { }; static const struct rt2x00_ops rt2500usb_ops = { - .name = KBUILD_MODNAME, - .max_sta_intf = 1, - .max_ap_intf = 1, - .eeprom_size = EEPROM_SIZE, - .rf_size = RF_SIZE, - .tx_queues = NUM_TX_QUEUES, - .rx = &rt2500usb_queue_rx, - .tx = &rt2500usb_queue_tx, - .bcn = &rt2500usb_queue_bcn, - .atim = &rt2500usb_queue_atim, - .lib = &rt2500usb_rt2x00_ops, - .hw = &rt2500usb_mac80211_ops, + .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 1, + .eeprom_size = EEPROM_SIZE, + .rf_size = RF_SIZE, + .tx_queues = NUM_TX_QUEUES, + .extra_tx_headroom = TXD_DESC_SIZE, + .rx = &rt2500usb_queue_rx, + .tx = &rt2500usb_queue_tx, + .bcn = &rt2500usb_queue_bcn, + .atim = &rt2500usb_queue_atim, + .lib = &rt2500usb_rt2x00_ops, + .hw = &rt2500usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2500usb_rt2x00debug, + .debugfs = &rt2500usb_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; @@ -1873,6 +1845,8 @@ static struct usb_device_id rt2500usb_device_table[] = { { USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) }, + /* CNet */ + { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Conceptronic */ { USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) }, /* D-LINK */ @@ -1897,14 +1871,20 @@ static struct usb_device_id rt2500usb_device_table[] = { { USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt2500usb_ops) }, { USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, + /* Sagem */ + { USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Siemens */ { USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) }, /* SMC */ { USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Spairon */ { USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) }, + /* SURECOM */ + { USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Trust */ { USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, + /* VTech */ + { USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) }, /* Zinwell */ { USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) }, { 0, }