linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
To: linux-wireless@vger.kernel.org
Cc: Daniel Drake <dsd@gentoo.org>,
	"John W. Linville" <linville@tuxdriver.com>,
	Ulrich Kunitz <kune@deine-taler.de>
Subject: [PATCH 20/22] zd1211rw: reset rx urbs after idle period of 30 seconds
Date: Mon, 31 Jan 2011 20:50:12 +0200	[thread overview]
Message-ID: <20110131185012.10044.21341.stgit@fate.lan> (raw)
In-Reply-To: <20110131184657.10044.98610.stgit@fate.lan>

RX appears to freeze while idle. Resetting rx-urbs appears to be enough to fix
this. Do reset 30 seconds after last rx.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
---
 drivers/net/wireless/zd1211rw/zd_usb.c |   79 +++++++++++++++++++++++++++++++-
 drivers/net/wireless/zd1211rw/zd_usb.h |    7 ++-
 2 files changed, 83 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 00c333f..5cedfea 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -638,6 +638,8 @@ static void rx_urb_complete(struct urb *urb)
 	usb = urb->context;
 	rx = &usb->rx;
 
+	zd_usb_reset_rx_idle_timer(usb);
+
 	if (length%rx->usb_packet_size > rx->usb_packet_size-4) {
 		/* If there is an old first fragment, we don't care. */
 		dev_dbg_f(urb_dev(urb), "*** first fragment ***\n");
@@ -702,7 +704,7 @@ static void free_rx_urb(struct urb *urb)
 	usb_free_urb(urb);
 }
 
-int zd_usb_enable_rx(struct zd_usb *usb)
+static int __zd_usb_enable_rx(struct zd_usb *usb)
 {
 	int i, r;
 	struct zd_usb_rx *rx = &usb->rx;
@@ -754,7 +756,21 @@ error:
 	return r;
 }
 
-void zd_usb_disable_rx(struct zd_usb *usb)
+int zd_usb_enable_rx(struct zd_usb *usb)
+{
+	int r;
+	struct zd_usb_rx *rx = &usb->rx;
+
+	mutex_lock(&rx->setup_mutex);
+	r = __zd_usb_enable_rx(usb);
+	mutex_unlock(&rx->setup_mutex);
+
+	zd_usb_reset_rx_idle_timer(usb);
+
+	return r;
+}
+
+static void __zd_usb_disable_rx(struct zd_usb *usb)
 {
 	int i;
 	unsigned long flags;
@@ -781,6 +797,40 @@ void zd_usb_disable_rx(struct zd_usb *usb)
 	spin_unlock_irqrestore(&rx->lock, flags);
 }
 
+void zd_usb_disable_rx(struct zd_usb *usb)
+{
+	struct zd_usb_rx *rx = &usb->rx;
+
+	mutex_lock(&rx->setup_mutex);
+	__zd_usb_disable_rx(usb);
+	mutex_unlock(&rx->setup_mutex);
+
+	cancel_delayed_work_sync(&rx->idle_work);
+}
+
+static void zd_usb_reset_rx(struct zd_usb *usb)
+{
+	bool do_reset;
+	struct zd_usb_rx *rx = &usb->rx;
+	unsigned long flags;
+
+	mutex_lock(&rx->setup_mutex);
+
+	spin_lock_irqsave(&rx->lock, flags);
+	do_reset = rx->urbs != NULL;
+	spin_unlock_irqrestore(&rx->lock, flags);
+
+	if (do_reset) {
+		__zd_usb_disable_rx(usb);
+		__zd_usb_enable_rx(usb);
+	}
+
+	mutex_unlock(&rx->setup_mutex);
+
+	if (do_reset)
+		zd_usb_reset_rx_idle_timer(usb);
+}
+
 /**
  * zd_usb_disable_tx - disable transmission
  * @usb: the zd1211rw-private USB structure
@@ -1033,6 +1083,29 @@ void zd_tx_watchdog_disable(struct zd_usb *usb)
 	}
 }
 
+static void zd_rx_idle_timer_handler(struct work_struct *work)
+{
+	struct zd_usb *usb =
+		container_of(work, struct zd_usb, rx.idle_work.work);
+	struct zd_mac *mac = zd_usb_to_mac(usb);
+
+	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+		return;
+
+	dev_dbg_f(zd_usb_dev(usb), "\n");
+
+	/* 30 seconds since last rx, reset rx */
+	zd_usb_reset_rx(usb);
+}
+
+void zd_usb_reset_rx_idle_timer(struct zd_usb *usb)
+{
+	struct zd_usb_rx *rx = &usb->rx;
+
+	cancel_delayed_work(&rx->idle_work);
+	queue_delayed_work(zd_workqueue, &rx->idle_work, ZD_RX_IDLE_INTERVAL);
+}
+
 static inline void init_usb_interrupt(struct zd_usb *usb)
 {
 	struct zd_usb_interrupt *intr = &usb->intr;
@@ -1047,12 +1120,14 @@ static inline void init_usb_rx(struct zd_usb *usb)
 {
 	struct zd_usb_rx *rx = &usb->rx;
 	spin_lock_init(&rx->lock);
+	mutex_init(&rx->setup_mutex);
 	if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) {
 		rx->usb_packet_size = 512;
 	} else {
 		rx->usb_packet_size = 64;
 	}
 	ZD_ASSERT(rx->fragment_length == 0);
+	INIT_DELAYED_WORK(&rx->idle_work, zd_rx_idle_timer_handler);
 }
 
 static inline void init_usb_tx(struct zd_usb *usb)
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index 98f09c2..2d688f4 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -34,6 +34,7 @@
 
 #define ZD_TX_TIMEOUT		(HZ * 5)
 #define ZD_TX_WATCHDOG_INTERVAL	round_jiffies_relative(HZ)
+#define ZD_RX_IDLE_INTERVAL	round_jiffies_relative(30 * HZ)
 
 enum devicetype {
 	DEVICE_ZD1211  = 0,
@@ -180,7 +181,9 @@ static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
 
 struct zd_usb_rx {
 	spinlock_t lock;
-	u8 fragment[2*USB_MAX_RX_SIZE];
+	struct mutex setup_mutex;
+	struct delayed_work idle_work;
+	u8 fragment[2 * USB_MAX_RX_SIZE];
 	unsigned int fragment_length;
 	unsigned int usb_packet_size;
 	struct urb **urbs;
@@ -251,6 +254,8 @@ void zd_usb_disable_int(struct zd_usb *usb);
 int zd_usb_enable_rx(struct zd_usb *usb);
 void zd_usb_disable_rx(struct zd_usb *usb);
 
+void zd_usb_reset_rx_idle_timer(struct zd_usb *usb);
+
 void zd_usb_enable_tx(struct zd_usb *usb);
 void zd_usb_disable_tx(struct zd_usb *usb);
 


  parent reply	other threads:[~2011-01-31 18:50 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-31 18:46 [PATCH 00/22] zd1211rw: add support for AP-mode Jussi Kivilinna
2011-01-31 18:47 ` [PATCH 01/22] zd1211rw: use urb anchors for tx and fix tx-queue disabling Jussi Kivilinna
2011-01-31 18:47 ` [PATCH 02/22] zd1211rw: cancel process_intr work on zd_chip_disable_int() Jussi Kivilinna
2011-01-31 18:47 ` [PATCH 03/22] zd1211rw: add locking for mac->process_intr Jussi Kivilinna
2011-01-31 18:47 ` [PATCH 04/22] zd1211rw: fix beacon interval setup Jussi Kivilinna
2011-01-31 18:47 ` [PATCH 05/22] zd1211rw: move set_multicast_hash and set_rx_filter from workers to configure_filter Jussi Kivilinna
2011-01-31 18:47 ` [PATCH 06/22] zd1211rw: move set_rts_cts_work to bss_info_changed Jussi Kivilinna
2011-01-31 18:48 ` [PATCH 07/22] zd1211rw: support setting BSSID for AP mode Jussi Kivilinna
2011-01-31 18:48 ` [PATCH 08/22] zd1211rw: fix ack_pending in filter_ack causing tx-packet ordering problem on monitor Jussi Kivilinna
2011-01-31 18:48 ` [PATCH 09/22] zd1211rw: let zd_set_beacon_interval() set dtim_period and add AP-beacon flag Jussi Kivilinna
2011-01-31 18:48 ` [PATCH 10/22] zd1211rw: implement beacon fetching and handling ieee80211_get_buffered_bc() Jussi Kivilinna
2011-01-31 18:48 ` [PATCH 11/22] mac80211: fix race between next beacon dtim and ieee80211_get_buffered_bc Jussi Kivilinna
2011-01-31 18:48 ` [PATCH 12/22] zd1211rw: add beacon watchdog and setting HW beacon more failsafe Jussi Kivilinna
2011-01-31 18:49 ` [PATCH 13/22] zd1211rw: batch beacon config commands together Jussi Kivilinna
2011-01-31 18:49 ` [PATCH 14/22] [v2] zd1211rw: use stack and preallocated memory for small cmd-buffers Jussi Kivilinna
2011-01-31 18:49 ` [PATCH 15/22] zd1211rw: change interrupt URB buffer to DMA buffer Jussi Kivilinna
2011-01-31 18:49 ` [PATCH 16/22] zd1211rw: lower hw command timeouts Jussi Kivilinna
2011-01-31 18:49 ` [PATCH 17/22] zd1211rw: collect driver settings and add function to restore theim Jussi Kivilinna
2011-01-31 18:49 ` [PATCH 18/22] zd1211rw: add TX watchdog and device resetting Jussi Kivilinna
2011-01-31 18:50 ` [PATCH 19/22] zd1211rw: reset device when CR_BCN_FIFO_SEMAPHORE freezes in beacon setup Jussi Kivilinna
2011-01-31 18:50 ` Jussi Kivilinna [this message]
2011-01-31 18:50 ` [PATCH 21/22] zd1211rw: enable NL80211_IFTYPE_AP Jussi Kivilinna
2011-01-31 18:50 ` [PATCH 22/22] zd1211rw: add useful debug output Jussi Kivilinna
2011-02-04 14:06 ` [PATCH 00/22] zd1211rw: add support for AP-mode Jussi Kivilinna
2011-02-04 21:25   ` John W. Linville

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=20110131185012.10044.21341.stgit@fate.lan \
    --to=jussi.kivilinna@mbnet.fi \
    --cc=dsd@gentoo.org \
    --cc=kune@deine-taler.de \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linville@tuxdriver.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).