@@ -1193,6 +1193,9 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
struct queue_entry *entry;
struct txdone_entry_desc txdesc;
u32 word;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&queue->lock, irqflags);
while (!rt2x00queue_empty(queue)) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
@@ -1222,6 +1225,8 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
rt2x00lib_txdone(entry, &txdesc);
}
+
+ spin_unlock_irqrestore(&queue->lock, irqflags);
}
static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
@@ -1330,6 +1330,9 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
struct queue_entry *entry;
struct txdone_entry_desc txdesc;
u32 word;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&queue->lock, irqflags);
while (!rt2x00queue_empty(queue)) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
@@ -1359,6 +1362,8 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
rt2x00lib_txdone(entry, &txdesc);
}
+
+ spin_unlock_irqrestore(&queue->lock, irqflags);
}
static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
@@ -101,6 +101,9 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
struct queue_entry *entry;
struct queue_entry_priv_pci *entry_priv;
struct skb_frame_desc *skbdesc;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&queue->lock, irqflags);
while (1) {
entry = rt2x00queue_get_entry(queue, Q_INDEX);
@@ -121,6 +124,8 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
*/
rt2x00lib_rxdone(rt2x00dev, entry);
}
+
+ spin_unlock_irqrestore(&queue->lock, irqflags);
}
EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
@@ -453,20 +453,29 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
bool local)
{
struct ieee80211_tx_info *tx_info;
- struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
+ struct queue_entry *entry;
struct txentry_desc txdesc;
struct skb_frame_desc *skbdesc;
u8 rate_idx, rate_flags;
+ unsigned long irqflags;
+ int ret = 0;
- if (unlikely(rt2x00queue_full(queue)))
- return -ENOBUFS;
+ spin_lock_irqsave(&queue->lock, irqflags);
+
+ entry = rt2x00queue_get_entry(queue, Q_INDEX);
+
+ if (unlikely(rt2x00queue_full(queue))) {
+ ret = -ENOBUFS;
+ goto out;
+ }
if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
ERROR(queue->rt2x00dev,
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
queue->qid, DRV_PROJECT);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
/*
@@ -528,7 +537,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) {
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
entry->skb = NULL;
- return -EIO;
+ ret = -EIO;
+ goto out;
}
if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
@@ -539,6 +549,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
rt2x00queue_index_inc(queue, Q_INDEX);
rt2x00queue_write_tx_descriptor(entry, &txdesc);
+out:
+ spin_unlock_irqrestore(&queue->lock, irqflags);
+
return 0;
}
@@ -642,7 +655,6 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
enum queue_index index)
{
struct queue_entry *entry;
- unsigned long irqflags;
if (unlikely(index >= Q_INDEX_MAX)) {
ERROR(queue->rt2x00dev,
@@ -650,28 +662,20 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
return NULL;
}
- spin_lock_irqsave(&queue->lock, irqflags);
-
entry = &queue->entries[queue->index[index]];
- spin_unlock_irqrestore(&queue->lock, irqflags);
-
return entry;
}
EXPORT_SYMBOL_GPL(rt2x00queue_get_entry);
void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
{
- unsigned long irqflags;
-
if (unlikely(index >= Q_INDEX_MAX)) {
ERROR(queue->rt2x00dev,
"Index change on invalid index type (%d)\n", index);
return;
}
- spin_lock_irqsave(&queue->lock, irqflags);
-
queue->index[index]++;
if (queue->index[index] >= queue->limit)
queue->index[index] = 0;
@@ -682,8 +686,6 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
queue->length--;
queue->count++;
}
-
- spin_unlock_irqrestore(&queue->lock, irqflags);
}
static void rt2x00queue_reset(struct data_queue *queue)
@@ -270,7 +270,6 @@ void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
const enum data_queue_qid qid)
{
struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid);
- unsigned long irqflags;
unsigned int index;
unsigned int index_done;
unsigned int i;
@@ -281,10 +280,8 @@ void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
* it should not be kicked during this run, since it
* is part of another TX operation.
*/
- spin_lock_irqsave(&queue->lock, irqflags);
index = queue->index[Q_INDEX];
index_done = queue->index[Q_INDEX_DONE];
- spin_unlock_irqrestore(&queue->lock, irqflags);
/*
* Start from the TX done pointer, this guarentees that we will
@@ -2037,6 +2037,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
u32 old_reg;
int type;
int index;
+ unsigned long irqflags;
/*
* During each loop we will compare the freshly read
@@ -2074,13 +2075,17 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
if (unlikely(index >= queue->limit))
continue;
+ spin_lock_irqsave(&queue->lock, irqflags);
+
entry = &queue->entries[index];
entry_priv = entry->priv_data;
rt2x00_desc_read(entry_priv->desc, 0, &word);
if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
- !rt2x00_get_field32(word, TXD_W0_VALID))
+ !rt2x00_get_field32(word, TXD_W0_VALID)) {
+ spin_unlock_irqrestore(&queue->lock, irqflags);
return;
+ }
entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
while (entry != entry_done) {
@@ -2116,6 +2121,8 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
rt2x00lib_txdone(entry, &txdesc);
+
+ spin_unlock_irqrestore(&queue->lock, irqflags);
}
}