aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r--drivers/net/wireless/rt2x00/Kconfig19
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c15
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c15
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c45
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c59
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00leds.c15
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c8
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c42
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c48
14 files changed, 194 insertions, 96 deletions
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index ab1029e..2d61187 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -32,12 +32,13 @@ config RT2X00_LIB_FIRMWARE
config RT2X00_LIB_RFKILL
boolean
depends on RT2X00_LIB
+ depends on INPUT
select RFKILL
select INPUT_POLLDEV
config RT2X00_LIB_LEDS
boolean
- depends on RT2X00_LIB
+ depends on RT2X00_LIB && NEW_LEDS
config RT2400PCI
tristate "Ralink rt2400 pci/pcmcia support"
@@ -51,7 +52,7 @@ config RT2400PCI
config RT2400PCI_RFKILL
bool "RT2400 rfkill support"
- depends on RT2400PCI
+ depends on RT2400PCI && INPUT
select RT2X00_LIB_RFKILL
---help---
This adds support for integrated rt2400 devices that feature a
@@ -60,7 +61,7 @@ config RT2400PCI_RFKILL
config RT2400PCI_LEDS
bool "RT2400 leds support"
- depends on RT2400PCI
+ depends on RT2400PCI && NEW_LEDS
select LEDS_CLASS
select RT2X00_LIB_LEDS
---help---
@@ -78,7 +79,7 @@ config RT2500PCI
config RT2500PCI_RFKILL
bool "RT2500 rfkill support"
- depends on RT2500PCI
+ depends on RT2500PCI && INPUT
select RT2X00_LIB_RFKILL
---help---
This adds support for integrated rt2500 devices that feature a
@@ -87,7 +88,7 @@ config RT2500PCI_RFKILL
config RT2500PCI_LEDS
bool "RT2500 leds support"
- depends on RT2500PCI
+ depends on RT2500PCI && NEW_LEDS
select LEDS_CLASS
select RT2X00_LIB_LEDS
---help---
@@ -107,7 +108,7 @@ config RT61PCI
config RT61PCI_RFKILL
bool "RT61 rfkill support"
- depends on RT61PCI
+ depends on RT61PCI && INPUT
select RT2X00_LIB_RFKILL
---help---
This adds support for integrated rt61 devices that feature a
@@ -116,7 +117,7 @@ config RT61PCI_RFKILL
config RT61PCI_LEDS
bool "RT61 leds support"
- depends on RT61PCI
+ depends on RT61PCI && NEW_LEDS
select LEDS_CLASS
select RT2X00_LIB_LEDS
---help---
@@ -133,7 +134,7 @@ config RT2500USB
config RT2500USB_LEDS
bool "RT2500 leds support"
- depends on RT2500USB
+ depends on RT2500USB && NEW_LEDS
select LEDS_CLASS
select RT2X00_LIB_LEDS
---help---
@@ -152,7 +153,7 @@ config RT73USB
config RT73USB_LEDS
bool "RT73 leds support"
- depends on RT73USB
+ depends on RT73USB && NEW_LEDS
select LEDS_CLASS
select RT2X00_LIB_LEDS
---help---
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index b41187a..b36ed1c 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -363,7 +363,7 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
- rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00 | preamble_mask);
+ rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10));
rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
@@ -731,6 +731,17 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev)
(rt2x00dev->rx->data_size / 128));
rt2x00pci_register_write(rt2x00dev, CSR9, reg);
+ rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+ rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
+ rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+ rt2x00_set_field32(&reg, CSR14_TCFP, 0);
+ rt2x00_set_field32(&reg, CSR14_TATIMW, 0);
+ rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+ rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
+ rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
+ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+
rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000);
rt2x00pci_register_read(rt2x00dev, ARCSR0, &reg);
@@ -1308,7 +1319,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
if (value == LED_MODE_TXRX_ACTIVITY) {
rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
- rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
+ rt2x00dev->led_qual.type = LED_TYPE_ACTIVITY;
rt2x00dev->led_qual.led_dev.brightness_set =
rt2400pci_brightness_set;
rt2x00dev->led_qual.led_dev.blink_set =
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 5ade097..f7731fb 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -370,7 +370,7 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
- rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00 | preamble_mask);
+ rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10));
rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
@@ -824,6 +824,17 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, CSR11_CW_SELECT, 0);
rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+ rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+ rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+ rt2x00_set_field32(&reg, CSR14_TSF_SYNC, 0);
+ rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+ rt2x00_set_field32(&reg, CSR14_TCFP, 0);
+ rt2x00_set_field32(&reg, CSR14_TATIMW, 0);
+ rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+ rt2x00_set_field32(&reg, CSR14_CFP_COUNT_PRELOAD, 0);
+ rt2x00_set_field32(&reg, CSR14_TBCM_PRELOAD, 0);
+ rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+
rt2x00pci_register_write(rt2x00dev, CNT3, 0);
rt2x00pci_register_read(rt2x00dev, TXCSR8, &reg);
@@ -1485,7 +1496,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
if (value == LED_MODE_TXRX_ACTIVITY) {
rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
- rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
+ rt2x00dev->led_qual.type = LED_TYPE_ACTIVITY;
rt2x00dev->led_qual.led_dev.brightness_set =
rt2500pci_brightness_set;
rt2x00dev->led_qual.led_dev.blink_set =
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 6bb07b3..d90512f 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -138,11 +138,8 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt2500usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
- ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
- return;
- }
+ if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
+ goto exit_fail;
/*
* Write the data into the BBP.
@@ -155,6 +152,13 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+ return;
+
+exit_fail:
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+ ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
}
static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -168,10 +172,8 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt2500usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
- ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
- return;
- }
+ if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
+ goto exit_fail;
/*
* Write the request into the BBP.
@@ -186,17 +188,21 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt2500usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
- ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
- *value = 0xff;
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
- return;
- }
+ if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
+ goto exit_fail;
rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
*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;
}
static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -795,6 +801,13 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&reg, TXRX_CSR8_BBP_ID1_VALID, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR8, reg);
+ rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+ rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
+ rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, 0);
+ rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
+ rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+
rt2500usb_register_write(rt2x00dev, TXRX_CSR21, 0xe78f);
rt2500usb_register_write(rt2x00dev, MAC_CSR9, 0xff1d);
@@ -1394,7 +1407,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
if (value == LED_MODE_TXRX_ACTIVITY) {
rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
- rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY;
+ rt2x00dev->led_qual.type = LED_TYPE_ACTIVITY;
rt2x00dev->led_qual.led_dev.brightness_set =
rt2500usb_brightness_set;
rt2x00dev->led_qual.led_dev.blink_set =
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 57bdc15..b4bf1e0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -328,6 +328,11 @@ static inline int rt2x00_get_link_ant_rssi(struct link *link)
return DEFAULT_RSSI;
}
+static inline void rt2x00_reset_link_ant_rssi(struct link *link)
+{
+ link->ant.rssi_ant = 0;
+}
+
static inline int rt2x00_get_link_ant_rssi_history(struct link *link,
enum antenna ant)
{
@@ -816,6 +821,7 @@ struct rt2x00_dev {
/*
* Scheduled work.
*/
+ struct workqueue_struct *workqueue;
struct work_struct intf_work;
struct work_struct filter_work;
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index a9930a0..48608e8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -129,6 +129,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
*/
rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA);
rt2x00lib_reset_link_tuner(rt2x00dev);
+ rt2x00_reset_link_ant_rssi(&rt2x00dev->link);
rt2x00dev->link.ant.active.rx = libconf.ant.rx;
rt2x00dev->link.ant.active.tx = libconf.ant.tx;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index f8fe7a1..c997d4f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -75,7 +75,7 @@ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev)
rt2x00lib_reset_link_tuner(rt2x00dev);
- queue_delayed_work(rt2x00dev->hw->workqueue,
+ queue_delayed_work(rt2x00dev->workqueue,
&rt2x00dev->link.work, LINK_TUNE_INTERVAL);
}
@@ -114,6 +114,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
return status;
rt2x00leds_led_radio(rt2x00dev, true);
+ rt2x00led_led_activity(rt2x00dev, true);
__set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags);
@@ -136,14 +137,6 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
return;
/*
- * Stop all scheduled work.
- */
- if (work_pending(&rt2x00dev->intf_work))
- cancel_work_sync(&rt2x00dev->intf_work);
- if (work_pending(&rt2x00dev->filter_work))
- cancel_work_sync(&rt2x00dev->filter_work);
-
- /*
* Stop the TX queues.
*/
ieee80211_stop_queues(rt2x00dev->hw);
@@ -157,6 +150,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
* Disable radio.
*/
rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF);
+ rt2x00led_led_activity(rt2x00dev, false);
rt2x00leds_led_radio(rt2x00dev, false);
}
@@ -396,8 +390,8 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
* Increase tuner counter, and reschedule the next link tuner run.
*/
rt2x00dev->link.count++;
- queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work,
- LINK_TUNE_INTERVAL);
+ queue_delayed_work(rt2x00dev->workqueue,
+ &rt2x00dev->link.work, LINK_TUNE_INTERVAL);
}
static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
@@ -431,6 +425,15 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
spin_unlock(&intf->lock);
+ /*
+ * It is possible the radio was disabled while the work had been
+ * scheduled. If that happens we should return here immediately,
+ * note that in the spinlock protected area above the delayed_flags
+ * have been cleared correctly.
+ */
+ if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ return;
+
if (delayed_flags & DELAYED_UPDATE_BEACON) {
skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control);
if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
@@ -439,7 +442,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
}
if (delayed_flags & DELAYED_CONFIG_ERP)
- rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf);
+ rt2x00lib_config_erp(rt2x00dev, intf, &conf);
if (delayed_flags & DELAYED_LED_ASSOC)
rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
@@ -481,11 +484,11 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
return;
- ieee80211_iterate_active_interfaces(rt2x00dev->hw,
- rt2x00lib_beacondone_iter,
- rt2x00dev);
+ ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
+ rt2x00lib_beacondone_iter,
+ rt2x00dev);
- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
+ queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work);
}
EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
@@ -505,7 +508,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* Update TX statistics.
*/
rt2x00dev->link.qual.tx_success += success;
- rt2x00dev->link.qual.tx_failed += txdesc->retry + fail;
+ rt2x00dev->link.qual.tx_failed += fail;
/*
* Initialize TX status
@@ -1030,8 +1033,10 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
* Initialize the device.
*/
status = rt2x00dev->ops->lib->initialize(rt2x00dev);
- if (status)
- goto exit;
+ if (status) {
+ rt2x00queue_uninitialize(rt2x00dev);
+ return status;
+ }
__set_bit(DEVICE_INITIALIZED, &rt2x00dev->flags);
@@ -1041,11 +1046,6 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
rt2x00rfkill_register(rt2x00dev);
return 0;
-
-exit:
- rt2x00lib_uninitialize(rt2x00dev);
-
- return status;
}
int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
@@ -1131,6 +1131,10 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
/*
* Initialize configuration work.
*/
+ rt2x00dev->workqueue = create_singlethread_workqueue("rt2x00lib");
+ if (!rt2x00dev->workqueue)
+ goto exit;
+
INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner);
@@ -1191,6 +1195,13 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
rt2x00leds_unregister(rt2x00dev);
/*
+ * Stop all queued work. Note that most tasks will already be halted
+ * during rt2x00lib_disable_radio() and rt2x00lib_uninitialize().
+ */
+ flush_workqueue(rt2x00dev->workqueue);
+ destroy_workqueue(rt2x00dev->workqueue);
+
+ /*
* Free ieee80211_hw memory.
*/
rt2x00lib_remove_hw(rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c
index 40c1f5c..b362a1c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00leds.c
+++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
@@ -72,6 +72,21 @@ void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi)
}
}
+void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled)
+{
+ struct rt2x00_led *led = &rt2x00dev->led_qual;
+ unsigned int brightness;
+
+ if ((led->type != LED_TYPE_ACTIVITY) || !(led->flags & LED_REGISTERED))
+ return;
+
+ brightness = enabled ? LED_FULL : LED_OFF;
+ if (brightness != led->led_dev.brightness) {
+ led->led_dev.brightness_set(&led->led_dev, brightness);
+ led->led_dev.brightness = brightness;
+ }
+}
+
void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled)
{
struct rt2x00_led *led = &rt2x00dev->led_assoc;
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 5be32ff..41ee02c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -185,6 +185,7 @@ static inline void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev)
*/
#ifdef CONFIG_RT2X00_LIB_LEDS
void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi);
+void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled);
void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled);
void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled);
void rt2x00leds_register(struct rt2x00_dev *rt2x00dev);
@@ -197,6 +198,11 @@ static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev,
{
}
+static inline void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev,
+ bool enabled)
+{
+}
+
static inline void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev,
bool enabled)
{
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index c206b50..9cb023e 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -93,6 +93,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) {
ieee80211_stop_queues(hw);
+ dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
@@ -427,7 +428,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
else
- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
+ queue_work(rt2x00dev->workqueue, &rt2x00dev->filter_work);
}
EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
@@ -508,7 +509,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
if (delayed) {
intf->delayed_flags |= delayed;
- queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work);
+ queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work);
}
spin_unlock(&intf->lock);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 7867ec6..60893de 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -314,13 +314,14 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
if (status) {
ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n",
pci_dev->irq, status);
- return status;
+ goto exit;
}
return 0;
exit:
- rt2x00pci_uninitialize(rt2x00dev);
+ queue_for_each(rt2x00dev, queue)
+ rt2x00pci_free_queue_dma(rt2x00dev, queue);
return status;
}
@@ -411,8 +412,7 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
if (pci_set_mwi(pci_dev))
ERROR_PROBE("MWI not available.\n");
- if (pci_set_dma_mask(pci_dev, DMA_64BIT_MASK) &&
- pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) {
+ if (pci_set_dma_mask(pci_dev, DMA_32BIT_MASK)) {
ERROR_PROBE("PCI DMA not supported.\n");
retval = -EIO;
goto exit_disable_device;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 5a33167..e5ceae8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -362,6 +362,12 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
}
}
+ /*
+ * Kill guardian urb (if required by driver).
+ */
+ if (!test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))
+ return;
+
for (i = 0; i < rt2x00dev->bcn->limit; i++) {
priv_bcn = rt2x00dev->bcn->entries[i].priv_data;
usb_kill_urb(priv_bcn->urb);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 468a31c..c3afb5c 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1201,6 +1201,15 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR8, reg);
+ rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
rt2x00pci_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
rt2x00pci_register_write(rt2x00dev, MAC_CSR6, 0x00000fff);
@@ -2087,7 +2096,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
if (value == LED_MODE_SIGNAL_STRENGTH) {
rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
- rt2x00dev->led_radio.type = LED_TYPE_QUALITY;
+ rt2x00dev->led_qual.type = LED_TYPE_QUALITY;
rt2x00dev->led_qual.led_dev.brightness_set =
rt61pci_brightness_set;
rt2x00dev->led_qual.led_dev.blink_set =
@@ -2366,6 +2375,7 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct rt2x00_intf *intf = vif_to_intf(control->vif);
+ struct queue_entry_priv_pci_tx *priv_tx;
struct skb_frame_desc *skbdesc;
unsigned int beacon_base;
u32 reg;
@@ -2373,21 +2383,8 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
if (unlikely(!intf->beacon))
return -ENOBUFS;
- /*
- * We need to append the descriptor in front of the
- * beacon frame.
- */
- if (skb_headroom(skb) < intf->beacon->queue->desc_size) {
- if (pskb_expand_head(skb, intf->beacon->queue->desc_size,
- 0, GFP_ATOMIC))
- return -ENOMEM;
- }
-
- /*
- * Add the descriptor in front of the skb.
- */
- skb_push(skb, intf->beacon->queue->desc_size);
- memset(skb->data, 0, intf->beacon->queue->desc_size);
+ priv_tx = intf->beacon->priv_data;
+ memset(priv_tx->desc, 0, intf->beacon->queue->desc_size);
/*
* Fill in skb descriptor
@@ -2395,9 +2392,9 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
skbdesc = get_skb_frame_desc(skb);
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED;
- skbdesc->data = skb->data + intf->beacon->queue->desc_size;
- skbdesc->data_len = skb->len - intf->beacon->queue->desc_size;
- skbdesc->desc = skb->data;
+ skbdesc->data = skb->data;
+ skbdesc->data_len = skb->len;
+ skbdesc->desc = priv_tx->desc;
skbdesc->desc_len = intf->beacon->queue->desc_size;
skbdesc->entry = intf->beacon;
@@ -2425,7 +2422,10 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
*/
beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
- skb->data, skb->len);
+ skbdesc->desc, skbdesc->desc_len);
+ rt2x00pci_register_multiwrite(rt2x00dev,
+ beacon_base + skbdesc->desc_len,
+ skbdesc->data, skbdesc->data_len);
rt61pci_kick_tx_queue(rt2x00dev, control->queue);
return 0;
@@ -2490,7 +2490,7 @@ static const struct data_queue_desc rt61pci_queue_tx = {
static const struct data_queue_desc rt61pci_queue_bcn = {
.entry_num = 4 * BEACON_ENTRIES,
- .data_size = MGMT_FRAME_SIZE,
+ .data_size = 0, /* No DMA required for beacons */
.desc_size = TXINFO_SIZE,
.priv_size = sizeof(struct queue_entry_priv_pci_tx),
};
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index a9efe25..46e9e08 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -134,11 +134,8 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt73usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
- return;
- }
+ if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
+ goto exit_fail;
/*
* Write the data into the BBP.
@@ -151,6 +148,13 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+ return;
+
+exit_fail:
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+ ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
}
static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -164,11 +168,8 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt73usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
- return;
- }
+ if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
+ goto exit_fail;
/*
* Write the request into the BBP.
@@ -184,14 +185,19 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
* Wait until the BBP becomes ready.
*/
reg = rt73usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
- *value = 0xff;
- return;
- }
+ if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
+ goto exit_fail;
*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+ return;
+
+exit_fail:
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+ ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
+ *value = 0xff;
}
static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
@@ -1000,6 +1006,15 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
rt73usb_register_write(rt2x00dev, TXRX_CSR8, reg);
+ rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+ rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
+ rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
rt73usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
rt73usb_register_read(rt2x00dev, MAC_CSR6, &reg);
@@ -1647,7 +1662,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
if (value == LED_MODE_SIGNAL_STRENGTH) {
rt2x00dev->led_qual.rt2x00dev = rt2x00dev;
- rt2x00dev->led_radio.type = LED_TYPE_QUALITY;
+ rt2x00dev->led_qual.type = LED_TYPE_QUALITY;
rt2x00dev->led_qual.led_dev.brightness_set =
rt73usb_brightness_set;
rt2x00dev->led_qual.led_dev.blink_set =
@@ -2131,6 +2146,7 @@ static struct usb_device_id rt73usb_device_table[] = {
/* D-Link */
{ USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) },
+ { USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) },
/* Gemtek */
{ USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) },