diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index d03eef28f0367aec063977f3d51ab84cff8eab6d..458bb489bc7ccd383c3aed2056e51c3fc908a55c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -650,10 +650,12 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, return ret; } -void rt2x00queue_for_each_entry(struct data_queue *queue, +bool rt2x00queue_for_each_entry(struct data_queue *queue, enum queue_index start, enum queue_index end, - void (*fn)(struct queue_entry *entry)) + void *data, + bool (*fn)(struct queue_entry *entry, + void *data)) { unsigned long irqflags; unsigned int index_start; @@ -664,7 +666,7 @@ void rt2x00queue_for_each_entry(struct data_queue *queue, ERROR(queue->rt2x00dev, "Entry requested from invalid index range (%d - %d)\n", start, end); - return; + return true; } /* @@ -683,15 +685,23 @@ void rt2x00queue_for_each_entry(struct data_queue *queue, * send out all frames in the correct order. */ if (index_start < index_end) { - for (i = index_start; i < index_end; i++) - fn(&queue->entries[i]); + for (i = index_start; i < index_end; i++) { + if (fn(&queue->entries[i], data)) + return true; + } } else { - for (i = index_start; i < queue->limit; i++) - fn(&queue->entries[i]); + for (i = index_start; i < queue->limit; i++) { + if (fn(&queue->entries[i], data)) + return true; + } - for (i = 0; i < index_end; i++) - fn(&queue->entries[i]); + for (i = 0; i < index_end; i++) { + if (fn(&queue->entries[i], data)) + return true; + } } + + return false; } EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 6ae820093997c99f68829b77369cb2681923dd7e..6b664525135db0d1cd5e86c7219bd8a8b98adf18 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -580,16 +580,22 @@ struct data_queue_desc { * @queue: Pointer to @data_queue * @start: &enum queue_index Pointer to start index * @end: &enum queue_index Pointer to end index + * @data: Data to pass to the callback function * @fn: The function to call for each &struct queue_entry * * This will walk through all entries in the queue, in chronological * order. This means it will start at the current @start pointer * and will walk through the queue until it reaches the @end pointer. + * + * If fn returns true for an entry rt2x00queue_for_each_entry will stop + * processing and return true as well. */ -void rt2x00queue_for_each_entry(struct data_queue *queue, +bool rt2x00queue_for_each_entry(struct data_queue *queue, enum queue_index start, enum queue_index end, - void (*fn)(struct queue_entry *entry)); + void *data, + bool (*fn)(struct queue_entry *entry, + void *data)); /** * rt2x00queue_empty - Check if the queue is empty. diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 94047e9b2ec61b8de248a3e1062faec8d1d9a9e0..0bc8dccd0f0ac968d8df6e2fca50be6bcd213361 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -230,7 +230,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); } -static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) +static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); @@ -240,7 +240,7 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) || test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) - return; + return true; /* * USB devices cannot blindly pass the skb->len as the @@ -261,6 +261,8 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); rt2x00lib_dmadone(entry); } + + return false; } /* @@ -323,7 +325,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work); } -static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) +static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); @@ -332,7 +334,7 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) - return; + return true; rt2x00lib_dmastart(entry); @@ -348,6 +350,8 @@ static void rt2x00usb_kick_rx_entry(struct queue_entry *entry) set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); rt2x00lib_dmadone(entry); } + + return false; } void rt2x00usb_kick_queue(struct data_queue *queue) @@ -358,12 +362,18 @@ void rt2x00usb_kick_queue(struct data_queue *queue) case QID_AC_BE: case QID_AC_BK: if (!rt2x00queue_empty(queue)) - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00queue_for_each_entry(queue, + Q_INDEX_DONE, + Q_INDEX, + NULL, rt2x00usb_kick_tx_entry); break; case QID_RX: if (!rt2x00queue_full(queue)) - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00queue_for_each_entry(queue, + Q_INDEX_DONE, + Q_INDEX, + NULL, rt2x00usb_kick_rx_entry); break; default: @@ -372,14 +382,14 @@ void rt2x00usb_kick_queue(struct data_queue *queue) } EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue); -static void rt2x00usb_flush_entry(struct queue_entry *entry) +static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_usb *entry_priv = entry->priv_data; struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) - return; + return true; usb_kill_urb(entry_priv->urb); @@ -389,6 +399,8 @@ static void rt2x00usb_flush_entry(struct queue_entry *entry) if ((entry->queue->qid == QID_BEACON) && (test_bit(REQUIRE_BEACON_GUARD, &rt2x00dev->cap_flags))) usb_kill_urb(bcn_priv->guardian_urb); + + return false; } void rt2x00usb_flush_queue(struct data_queue *queue) @@ -396,7 +408,7 @@ void rt2x00usb_flush_queue(struct data_queue *queue) struct work_struct *completion; unsigned int i; - rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, + rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX, NULL, rt2x00usb_flush_entry); /* @@ -489,7 +501,7 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) entry->flags = 0; if (entry->queue->qid == QID_RX) - rt2x00usb_kick_rx_entry(entry); + rt2x00usb_kick_rx_entry(entry, NULL); } EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);