linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ivo van Doorn <ivdoorn@gmail.com>
To: "John W. Linville" <linville@tuxdriver.com>
Cc: linux-wireless@vger.kernel.org, users@rt2x00.serialmonkey.com
Subject: [PATCH 11/23] rt2800usb: add timer to handle TX_STA_FIFO
Date: Mon, 18 Apr 2011 15:30:36 +0200	[thread overview]
Message-ID: <201104181530.37227.IvDoorn@gmail.com> (raw)
In-Reply-To: <201104181530.02029.IvDoorn@gmail.com>

From: Johannes Stezenbach <js@sig21.net>

TX status is reported by the hardware when a packet has been
sent (or after TX failed after possible retries), which is some
time after the DMA completion.  Since the rt2800usb hardware can
not signal interrupts we have to use a timer, otherwise the
TX status would only be read by the next packet's TX DMA
completion, or by the watchdog thread.

Signed-off-by: Johannes Stezenbach <js@sig21.net>
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
---
 drivers/net/wireless/rt2x00/rt2800usb.c |   41 ++++++++++++++++++++++++++++++-
 drivers/net/wireless/rt2x00/rt2x00.h    |    6 ++++
 drivers/net/wireless/rt2x00/rt2x00dev.c |    1 +
 drivers/net/wireless/rt2x00/rt2x00usb.c |    5 +++-
 4 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 69004b9..2005972 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -98,6 +98,22 @@ static void rt2800usb_stop_queue(struct data_queue *queue)
 	}
 }
 
+/*
+ * test if there is an entry in any TX queue for which DMA is done
+ * but the TX status has not been returned yet
+ */
+static bool rt2800usb_txstatus_pending(struct rt2x00_dev *rt2x00dev)
+{
+	struct data_queue *queue;
+
+	tx_queue_for_each(rt2x00dev, queue) {
+		if (rt2x00queue_get_entry(queue, Q_INDEX_DMA_DONE) !=
+		    rt2x00queue_get_entry(queue, Q_INDEX_DONE))
+			return true;
+	}
+	return false;
+}
+
 static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
 						 int urb_status, u32 tx_status)
 {
@@ -115,8 +131,11 @@ static void rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev,
 		} else
 			rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
 						      rt2800usb_tx_sta_fifo_read_completed);
-	} else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+	} else if (!kfifo_is_empty(&rt2x00dev->txstatus_fifo)) {
 		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+	} else if (rt2800usb_txstatus_pending(rt2x00dev)) {
+		mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
+	}
 }
 
 static void rt2800usb_tx_dma_done(struct queue_entry *entry)
@@ -127,6 +146,14 @@ static void rt2800usb_tx_dma_done(struct queue_entry *entry)
 				      rt2800usb_tx_sta_fifo_read_completed);
 }
 
+static void rt2800usb_tx_sta_fifo_timeout(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+
+	rt2x00usb_register_read_async(rt2x00dev, TX_STA_FIFO,
+				      rt2800usb_tx_sta_fifo_read_completed);
+}
+
 /*
  * Firmware functions
  */
@@ -459,6 +486,14 @@ static void rt2800usb_work_txdone(struct work_struct *work)
 				break;
 		}
 	}
+
+	/*
+	 * The hw may delay sending the packet after DMA complete
+	 * if the medium is busy, thus the TX_STA_FIFO entry is
+	 * also delayed -> use a timer to retrieve it.
+	 */
+	if (rt2800usb_txstatus_pending(rt2x00dev))
+		mod_timer(&rt2x00dev->txstatus_timer, jiffies + msecs_to_jiffies(20));
 }
 
 /*
@@ -599,6 +634,10 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	__set_bit(REQUIRE_HT_TX_DESC, &rt2x00dev->cap_flags);
 	__set_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags);
 
+	setup_timer(&rt2x00dev->txstatus_timer,
+		    rt2800usb_tx_sta_fifo_timeout,
+		    (unsigned long) rt2x00dev);
+
 	/*
 	 * Set the rssi offset.
 	 */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index e3b9b51..8f37121 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -37,6 +37,7 @@
 #include <linux/etherdevice.h>
 #include <linux/input-polldev.h>
 #include <linux/kfifo.h>
+#include <linux/timer.h>
 
 #include <net/mac80211.h>
 
@@ -924,6 +925,11 @@ struct rt2x00_dev {
 	DECLARE_KFIFO_PTR(txstatus_fifo, u32);
 
 	/*
+	 * Timer to ensure tx status reports are read (rt2800usb).
+	 */
+	struct timer_list txstatus_timer;
+
+	/*
 	 * Tasklet for processing tx status reports (rt2800pci).
 	 */
 	struct tasklet_struct txstatus_tasklet;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 2e490e0..7776d9f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1071,6 +1071,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
 	/*
 	 * Stop all work.
 	 */
+	del_timer_sync(&rt2x00dev->txstatus_timer);
 	cancel_work_sync(&rt2x00dev->intf_work);
 	if (rt2x00_is_usb(rt2x00dev)) {
 		cancel_work_sync(&rt2x00dev->rxdone_work);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 14736e2..34b8a88 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -280,7 +280,9 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
 	 * Schedule the delayed work for reading the TX status
 	 * from the device.
 	 */
-	queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
+	if (!test_bit(REQUIRE_TXSTATUS_FIFO, &rt2x00dev->cap_flags) ||
+	    !kfifo_is_empty(&rt2x00dev->txstatus_fifo))
+		queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
 }
 
 static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data)
@@ -816,6 +818,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
 
 	INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone);
 	INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone);
+	init_timer(&rt2x00dev->txstatus_timer);
 
 	retval = rt2x00usb_alloc_reg(rt2x00dev);
 	if (retval)
-- 
1.7.2.3


  reply	other threads:[~2011-04-18 13:36 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-18 13:26 [PATCH 01/23] Enable WLAN LED on Ralink SoC (rt305x) devices Ivo van Doorn
2011-04-18 13:26 ` [PATCH 02/23] rt2x00: Fix stuck queue in tx failure case Ivo van Doorn
2011-04-18 13:27   ` [PATCH 03/23] rt2x00: Split rt2x00dev->flags Ivo van Doorn
2011-04-18 13:27     ` [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible Ivo van Doorn
2011-04-18 13:28       ` [PATCH 05/23] rt2x00: Use correct TBTT_SYNC config in AP mode Ivo van Doorn
2011-04-18 13:28         ` [PATCH 06/23] rt2x00: Update TX_SW_CFG2 init value Ivo van Doorn
2011-04-18 13:28           ` [PATCH 07/23] rt2x00: Use TXOP_HTTXOP for beacons Ivo van Doorn
2011-04-18 13:29             ` [PATCH 08/23] rt2800usb: read TX_STA_FIFO asynchronously Ivo van Doorn
2011-04-18 13:29               ` [PATCH 09/23] rt2x00: fix queue timeout checks Ivo van Doorn
2011-04-18 13:30                 ` [PATCH 10/23] rt2800usb: handle TX status timeouts Ivo van Doorn
2011-04-18 13:30                   ` Ivo van Doorn [this message]
2011-04-18 13:31                     ` [PATCH 12/23] Decrease association time for USB devices Ivo van Doorn
2011-04-18 13:31                       ` [PATCH 13/23] rt2x00: Always inline rt2x00pci_enable_interrupt Ivo van Doorn
2011-04-18 13:31                         ` [PATCH 14/23] rt2x00: Linksys WUSB600N rev2 is a RT3572 device Ivo van Doorn
2011-04-18 13:32                           ` [PATCH 15/23] rt2x00: Allow dynamic addition of PCI/USB IDs Ivo van Doorn
2011-04-18 13:32                             ` [PATCH 16/23] rt2x00: Add USB IDs Ivo van Doorn
2011-04-18 13:33                               ` [PATCH 17/23] rt2x00: RT33xx device support is no longer experimental Ivo van Doorn
2011-04-18 13:33                                 ` [PATCH 18/23] rt2x00: Enable support for RT53xx PCI devices by default Ivo van Doorn
2011-04-18 13:33                                   ` [PATCH 19/23] rt2x00: Merge rt2x00ht.c contents in other files Ivo van Doorn
2011-04-18 13:34                                     ` [PATCH 20/23] rt2x00: Optimize register access in rt2800pci Ivo van Doorn
2011-04-18 13:34                                       ` [PATCH 21/23] rt2x00: Optimize register access in rt2800usb Ivo van Doorn
2011-04-18 13:34                                         ` [PATCH 22/23] rt2x00: Implement get_ringparam callback function Ivo van Doorn
2011-04-18 13:35                                           ` [PATCH 23/23] rt2x00: Implement get_antenna and set_antenna callback functions Ivo van Doorn
2011-04-18 13:56                                         ` [PATCH 21/23] rt2x00: Optimize register access in rt2800usb Rafał Miłecki
2011-04-18 14:06                                           ` Ivo Van Doorn
2011-04-18 14:14                                             ` Rafał Miłecki
2011-04-18 14:48                                             ` Helmut Schaa
2011-04-18 15:02                                               ` Rafał Miłecki
2011-04-28  2:55       ` [PATCH 04/23] rt2x00: Make rt2x00_queue_entry_for_each more flexible Yasushi SHOJI
2011-04-28  2:55       ` Yasushi SHOJI
2011-04-28 18:55         ` Ivo Van Doorn
2011-04-29  6:06           ` Gertjan van Wingerde
2011-04-30 14:01             ` Ivo van Doorn
2011-05-02 13:33               ` Yasushi SHOJI
2011-05-02 19:24                 ` Ivo van Doorn
2011-05-09  8:08                   ` Yasushi SHOJI
2011-05-09  8:50                     ` Ivo Van Doorn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201104181530.37227.IvDoorn@gmail.com \
    --to=ivdoorn@gmail.com \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.com \
    --cc=users@rt2x00.serialmonkey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).