[rt2x00-users] [PATCH 4/5] rt2x00: Introduce ENTRY_DATA_STATUS_PENDING
Ivo van Doorn
ivdoorn at gmail.com
Sat Aug 14 19:03:03 UTC 2010
Introduce a new flag for the entry_data structure, which
indicates that a frame has been successfully transfered
to the device, but the TX status hasn't been available
during the first attempt, but is expected to be recieved
later.
If during the second attempt the status still isn't
available, the frame is reported with status UNKNOWN.
This situation happens frequently in rt2800usb, which
is caused by the device which skips the TX status information
for particular frames. But due insufficient information
in each TX status report, it is hard to predict to which
frame a TX status report belongs.
Signed-off-by: Ivo van Doorn <IvDoorn at gmail.com>
---
drivers/net/wireless/rt2x00/rt2800usb.c | 44 +++++++++++++++++++++++++---
drivers/net/wireless/rt2x00/rt2x00queue.h | 7 ++++-
drivers/net/wireless/rt2x00/rt61pci.c | 6 ++--
3 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 02f9589..2aa8ddb 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -380,6 +380,44 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry)
/*
* TX control handlers
*/
+static bool rt2800usb_work_txdone_entry(struct queue_entry *entry)
+{
+ if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
+ /*
+ * Entry is still owned by the device
+ */
+ return false;
+ } else if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) {
+ /*
+ * Entry has returned from the device, but the
+ * frame was not transfered to the device.
+ */
+ rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
+ return true;
+ } else if (test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) {
+ /*
+ * Entry has returned from the device, and the
+ * frame was transfered to the device. However
+ * we have now tried twice to obtain the status
+ * but we still have not received anything...
+ */
+ WARNING(entry->queue->rt2x00dev,
+ "TX status report missed for queue %d entry %d\n",
+ entry->queue->qid, entry->entry_idx);
+ rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
+ return true;
+ } else {
+ /*
+ * Entry has returned from the device, and the
+ * frame was transfered to the device. However
+ * we have not yet recieved the status from the
+ * device, so we are going to retry it later...
+ */
+ __set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
+ return false;
+ }
+}
+
static void rt2800usb_work_txdone(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
@@ -399,12 +437,8 @@ static void rt2800usb_work_txdone(struct work_struct *work)
tx_queue_for_each(rt2x00dev, queue) {
while (!rt2x00queue_empty(queue)) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
-
- if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
- !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
+ if (!rt2800usb_work_txdone_entry(entry))
break;
-
- rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE);
}
}
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index cecc908..738ac27 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -365,12 +365,17 @@ struct txentry_desc {
* @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured
* while transfering the data to the hardware. No TX status report will
* be expected from the hardware.
+ * @ENTRY_DATA_STATUS_PENDING: Hardware has indicated that the frame
+ * has been transfered to the hardware. During the first attempt
+ * to obtain the TX status for this frame, no data was yet available
+ * and a new attempt is needed.
*/
enum queue_entry_flags {
ENTRY_BCN_ASSIGNED,
ENTRY_OWNER_DEVICE_DATA,
ENTRY_DATA_PENDING,
- ENTRY_DATA_IO_FAILED
+ ENTRY_DATA_IO_FAILED,
+ ENTRY_DATA_STATUS_PENDING,
};
/**
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index ae4698e..f858783 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2102,9 +2102,9 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
/* Catch up.
* Just report any entries we missed as failed.
*/
- WARNING(rt2x00dev,
- "TX status report missed for entry %d\n",
- entry_done->entry_idx);
+ WARNING(entry->queue->rt2x00dev,
+ "TX status report missed for queue %d entry %d\n",
+ entry->queue->qid, entry->entry_idx);
rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN);
entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
--
1.7.2.1
More information about the users
mailing list