summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rt2x00/rt2400pci.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2009-03-28 20:29:51 +0000
committerRussell King <rmk+kernel@arm.linux.org.uk>2009-03-28 20:29:51 +0000
commited40d0c472b136682b2fcba05f89762859c7374f (patch)
tree076b83a26bcd63d6158463735dd34c10bbc591dc /drivers/net/wireless/rt2x00/rt2400pci.c
parent9e495834e59ca9b29f1a1f63b9f5533bb022ac49 (diff)
parent5d80f8e5a9dc9c9a94d4aeaa567e219a808b8a4a (diff)
Merge branch 'origin' into devel
Conflicts: sound/soc/pxa/pxa2xx-i2s.c
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2400pci.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c103
1 files changed, 69 insertions, 34 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 6a977679124d..0f08773328c6 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.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
@@ -114,9 +114,6 @@ static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- if (!word)
- return;
-
mutex_lock(&rt2x00dev->csr_mutex);
/*
@@ -524,6 +521,32 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, CSR12, reg);
}
+static void rt2400pci_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_read(rt2x00dev, CSR20, &reg);
+ rt2x00_set_field32(&reg, CSR20_DELAY_AFTER_TBCN,
+ (libconf->conf->beacon_int - 20) * 16);
+ rt2x00_set_field32(&reg, CSR20_TBCN_BEFORE_WAKEUP,
+ libconf->conf->listen_interval - 1);
+
+ /* We must first disable autowake before it can be enabled */
+ rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 0);
+ rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+
+ rt2x00_set_field32(&reg, CSR20_AUTOWAKE, 1);
+ rt2x00pci_register_write(rt2x00dev, CSR20, reg);
+ }
+
+ rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+}
+
static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int flags)
@@ -537,6 +560,8 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
rt2400pci_config_retry_limit(rt2x00dev, libconf);
if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
rt2400pci_config_duration(rt2x00dev, libconf);
+ if (flags & IEEE80211_CONF_CHANGE_PS)
+ rt2400pci_config_ps(rt2x00dev, libconf);
}
static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev,
@@ -572,35 +597,37 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
qual->false_cca = bbp;
}
-static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
+static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, u8 vgc_level)
{
- rt2400pci_bbp_write(rt2x00dev, 13, 0x08);
- rt2x00dev->link.vgc_level = 0x08;
+ rt2400pci_bbp_write(rt2x00dev, 13, vgc_level);
+ qual->vgc_level = vgc_level;
+ qual->vgc_level_reg = vgc_level;
}
-static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
+static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
- u8 reg;
+ rt2400pci_set_vgc(rt2x00dev, qual, 0x08);
+}
+static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, const u32 count)
+{
/*
* The link tuner should not run longer then 60 seconds,
* and should run once every 2 seconds.
*/
- if (rt2x00dev->link.count > 60 || !(rt2x00dev->link.count & 1))
+ if (count > 60 || !(count & 1))
return;
/*
* Base r13 link tuning on the false cca count.
*/
- rt2400pci_bbp_read(rt2x00dev, 13, &reg);
-
- if (rt2x00dev->link.qual.false_cca > 512 && reg < 0x20) {
- rt2400pci_bbp_write(rt2x00dev, 13, ++reg);
- rt2x00dev->link.vgc_level = reg;
- } else if (rt2x00dev->link.qual.false_cca < 100 && reg > 0x08) {
- rt2400pci_bbp_write(rt2x00dev, 13, --reg);
- rt2x00dev->link.vgc_level = reg;
- }
+ if ((qual->false_cca > 512) && (qual->vgc_level < 0x20))
+ rt2400pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level);
+ else if ((qual->false_cca < 100) && (qual->vgc_level > 0x08))
+ rt2400pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
}
/*
@@ -904,21 +931,10 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev)
{
- u32 reg;
-
- rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
-
- /*
- * Disable synchronisation.
- */
- rt2x00pci_register_write(rt2x00dev, CSR14, 0);
-
/*
- * Cancel RX and TX.
+ * Disable power
*/
- rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
- rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
- rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0);
}
static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev,
@@ -1115,6 +1131,20 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
}
+static void rt2400pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
+ const enum data_queue_qid qid)
+{
+ u32 reg;
+
+ if (qid == QID_BEACON) {
+ rt2x00pci_register_write(rt2x00dev, CSR14, 0);
+ } else {
+ rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
+ rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
+ rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
+ }
+}
+
/*
* RX control handlers
*/
@@ -1365,7 +1395,9 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE);
rt2400pci_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)
rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_qual,
LED_TYPE_ACTIVITY);
#endif /* CONFIG_RT2X00_LIB_LEDS */
@@ -1419,7 +1451,9 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
* 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 = 0;
SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
@@ -1572,6 +1606,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.write_tx_data = rt2x00pci_write_tx_data,
.write_beacon = rt2400pci_write_beacon,
.kick_tx_queue = rt2400pci_kick_tx_queue,
+ .kill_tx_queue = rt2400pci_kill_tx_queue,
.fill_rxdone = rt2400pci_fill_rxdone,
.config_filter = rt2400pci_config_filter,
.config_intf = rt2400pci_config_intf,