diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2500usb.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 72 |
1 files changed, 62 insertions, 10 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 3e2ac2bbb12..9e630e70fc9 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 rt2x00 SourceForge Project <http://rt2x00.serialmonkey.com> This program is free software; you can redistribute it and/or modify @@ -204,9 +204,6 @@ static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, { u16 reg; - if (!word) - return; - mutex_lock(&rt2x00dev->csr_mutex); /* @@ -280,6 +277,18 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = { }; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ +#ifdef CONFIG_RT2X00_LIB_RFKILL +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); +} +#else +#define rt2500usb_rfkill_poll NULL +#endif /* CONFIG_RT2X00_LIB_RFKILL */ + #ifdef CONFIG_RT2X00_LIB_LEDS static void rt2500usb_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) @@ -634,6 +643,32 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev, rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); } +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; + + if (state == STATE_SLEEP) { + rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); + rt2x00_set_field16(®, MAC_CSR18_DELAY_AFTER_BEACON, + libconf->conf->beacon_int - 20); + rt2x00_set_field16(®, MAC_CSR18_BEACONS_BEFORE_WAKEUP, + libconf->conf->listen_interval - 1); + + /* 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); + } + + rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); +} + static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int flags) @@ -647,6 +682,8 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, libconf->conf->power_level); if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) rt2500usb_config_duration(rt2x00dev, libconf); + if (flags & IEEE80211_CONF_CHANGE_PS) + rt2500usb_config_ps(rt2x00dev, libconf); } /* @@ -670,7 +707,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; @@ -691,7 +729,7 @@ 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; } /* @@ -1176,7 +1214,7 @@ 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); @@ -1562,12 +1600,22 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) 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_RT2X00_LIB_LEDS */ /* + * Detect if this device has an hardware controlled radio. + */ +#ifdef CONFIG_RT2X00_LIB_RFKILL + if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) + __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); +#endif /* CONFIG_RT2X00_LIB_RFKILL */ + + /* * Check if the BBP tuning should be disabled. */ rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); @@ -1752,7 +1800,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; + IEEE80211_HW_SIGNAL_DBM | + IEEE80211_HW_SUPPORTS_PS | + IEEE80211_HW_PS_NULLFUNC_STACK; rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; @@ -1839,7 +1889,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); if (!modparam_nohwcrypt) { __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - __set_bit(CONFIG_CRYPTO_COPY_IV, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); } __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); @@ -1873,6 +1923,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .uninitialize = rt2x00usb_uninitialize, .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, @@ -1881,6 +1932,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .write_beacon = rt2500usb_write_beacon, .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_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, |