summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rt2x00/rt2x00dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00dev.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c104
1 files changed, 43 insertions, 61 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 5ba79b935f09..9597a03242cc 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -66,20 +66,16 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);
/*
- * Enable RX.
+ * Enable queues.
*/
- rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
+ rt2x00queue_start_queues(rt2x00dev);
+ rt2x00link_start_tuner(rt2x00dev);
/*
* Start watchdog monitoring.
*/
rt2x00link_start_watchdog(rt2x00dev);
- /*
- * Start the TX queues.
- */
- ieee80211_wake_queues(rt2x00dev->hw);
-
return 0;
}
@@ -89,20 +85,16 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
return;
/*
- * Stop the TX queues in mac80211.
- */
- ieee80211_stop_queues(rt2x00dev->hw);
- rt2x00queue_stop_queues(rt2x00dev);
-
- /*
* Stop watchdog monitoring.
*/
rt2x00link_stop_watchdog(rt2x00dev);
/*
- * Disable RX.
+ * Stop all queues
*/
- rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
+ rt2x00link_stop_tuner(rt2x00dev);
+ rt2x00queue_stop_queues(rt2x00dev);
+ rt2x00queue_flush_queues(rt2x00dev, true);
/*
* Disable radio.
@@ -113,41 +105,11 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
rt2x00leds_led_radio(rt2x00dev, false);
}
-void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
-{
- /*
- * When we are disabling the RX, we should also stop the link tuner.
- */
- if (state == STATE_RADIO_RX_OFF)
- rt2x00link_stop_tuner(rt2x00dev);
-
- rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
-
- /*
- * When we are enabling the RX, we should also start the link tuner.
- */
- if (state == STATE_RADIO_RX_ON)
- rt2x00link_start_tuner(rt2x00dev);
-}
-
static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct rt2x00_dev *rt2x00dev = data;
struct rt2x00_intf *intf = vif_to_intf(vif);
- int delayed_flags;
-
- /*
- * Copy all data we need during this action under the protection
- * of a spinlock. Otherwise race conditions might occur which results
- * into an invalid configuration.
- */
- spin_lock(&intf->lock);
-
- delayed_flags = intf->delayed_flags;
- intf->delayed_flags = 0;
-
- spin_unlock(&intf->lock);
/*
* It is possible the radio was disabled while the work had been
@@ -158,7 +120,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
- if (delayed_flags & DELAYED_UPDATE_BEACON)
+ if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags))
rt2x00queue_update_beacon(rt2x00dev, vif, true);
}
@@ -251,8 +213,16 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
}
EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
+void rt2x00lib_dmastart(struct queue_entry *entry)
+{
+ set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+ rt2x00queue_index_inc(entry->queue, Q_INDEX);
+}
+EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);
+
void rt2x00lib_dmadone(struct queue_entry *entry)
{
+ set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
}
@@ -264,11 +234,9 @@ void rt2x00lib_txdone(struct queue_entry *entry,
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
- unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+ unsigned int header_length, i;
u8 rate_idx, rate_flags, retry_rates;
u8 skbdesc_flags = skbdesc->flags;
- unsigned int i;
bool success;
/*
@@ -287,6 +255,11 @@ void rt2x00lib_txdone(struct queue_entry *entry,
skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
/*
+ * Determine the length of 802.11 header.
+ */
+ header_length = ieee80211_get_hdrlen_from_skb(entry->skb);
+
+ /*
* Remove L2 padding which was added during
*/
if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags))
@@ -390,9 +363,12 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* through a mac80211 library call (RTS/CTS) then we should not
* send the status report back.
*/
- if (!(skbdesc_flags & SKBDESC_NOT_MAC80211))
- ieee80211_tx_status(rt2x00dev->hw, entry->skb);
- else
+ if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) {
+ if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags))
+ ieee80211_tx_status(rt2x00dev->hw, entry->skb);
+ else
+ ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
+ } else
dev_kfree_skb_any(entry->skb);
/*
@@ -411,7 +387,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* is reenabled when the txdone handler has finished.
*/
if (!rt2x00queue_threshold(entry->queue))
- ieee80211_wake_queue(rt2x00dev->hw, qid);
+ rt2x00queue_unpause_queue(entry->queue);
}
EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
@@ -483,6 +459,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
unsigned int header_length;
int rate_idx;
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
+ !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ goto submit_entry;
+
if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
goto submit_entry;
@@ -567,9 +547,11 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
entry->skb = skb;
submit_entry:
- rt2x00dev->ops->lib->clear_entry(entry);
- rt2x00queue_index_inc(entry->queue, Q_INDEX);
+ entry->flags = 0;
rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+ if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+ test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2x00dev->ops->lib->clear_entry(entry);
}
EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
@@ -678,7 +660,7 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry,
{
entry->flags = 0;
entry->bitrate = rate->bitrate;
- entry->hw_value =index;
+ entry->hw_value = index;
entry->hw_value_short = index;
if (rate->flags & DEV_RATE_SHORT_PREAMBLE)
@@ -818,8 +800,7 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* Allocate tx status FIFO for driver use.
*/
- if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags) &&
- rt2x00dev->ops->lib->txstatus_tasklet) {
+ if (test_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags)) {
/*
* Allocate txstatus fifo and tasklet, we use a size of 512
* for the kfifo which is big enough to store 512/4=128 tx
@@ -833,9 +814,10 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
return status;
/* tasklet for processing the tx status reports. */
- tasklet_init(&rt2x00dev->txstatus_tasklet,
- rt2x00dev->ops->lib->txstatus_tasklet,
- (unsigned long)rt2x00dev);
+ if (rt2x00dev->ops->lib->txstatus_tasklet)
+ tasklet_init(&rt2x00dev->txstatus_tasklet,
+ rt2x00dev->ops->lib->txstatus_tasklet,
+ (unsigned long)rt2x00dev);
}