aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/zd1211rw
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2011-01-31 13:50:12 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-04 16:29:51 -0500
commit1f6cccccea3fe96464f7dbc39723d70165f1eef1 (patch)
tree58bbed82d37a4912b4a0c5c014c048d28be7ccfb /drivers/net/wireless/zd1211rw
parent3985a46543d47a50b94e839e0a16e67d959ab092 (diff)
zd1211rw: reset rx urbs after idle period of 30 seconds
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> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/zd1211rw')
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c79
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.h7
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 178d794be3fd..0631be6a53ac 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)
638 usb = urb->context; 638 usb = urb->context;
639 rx = &usb->rx; 639 rx = &usb->rx;
640 640
641 zd_usb_reset_rx_idle_timer(usb);
642
641 if (length%rx->usb_packet_size > rx->usb_packet_size-4) { 643 if (length%rx->usb_packet_size > rx->usb_packet_size-4) {
642 /* If there is an old first fragment, we don't care. */ 644 /* If there is an old first fragment, we don't care. */
643 dev_dbg_f(urb_dev(urb), "*** first fragment ***\n"); 645 dev_dbg_f(urb_dev(urb), "*** first fragment ***\n");
@@ -702,7 +704,7 @@ static void free_rx_urb(struct urb *urb)
702 usb_free_urb(urb); 704 usb_free_urb(urb);
703} 705}
704 706
705int zd_usb_enable_rx(struct zd_usb *usb) 707static int __zd_usb_enable_rx(struct zd_usb *usb)
706{ 708{
707 int i, r; 709 int i, r;
708 struct zd_usb_rx *rx = &usb->rx; 710 struct zd_usb_rx *rx = &usb->rx;
@@ -754,7 +756,21 @@ error:
754 return r; 756 return r;
755} 757}
756 758
757void zd_usb_disable_rx(struct zd_usb *usb) 759int zd_usb_enable_rx(struct zd_usb *usb)
760{
761 int r;
762 struct zd_usb_rx *rx = &usb->rx;
763
764 mutex_lock(&rx->setup_mutex);
765 r = __zd_usb_enable_rx(usb);
766 mutex_unlock(&rx->setup_mutex);
767
768 zd_usb_reset_rx_idle_timer(usb);
769
770 return r;
771}
772
773static void __zd_usb_disable_rx(struct zd_usb *usb)
758{ 774{
759 int i; 775 int i;
760 unsigned long flags; 776 unsigned long flags;
@@ -781,6 +797,40 @@ void zd_usb_disable_rx(struct zd_usb *usb)
781 spin_unlock_irqrestore(&rx->lock, flags); 797 spin_unlock_irqrestore(&rx->lock, flags);
782} 798}
783 799
800void zd_usb_disable_rx(struct zd_usb *usb)
801{
802 struct zd_usb_rx *rx = &usb->rx;
803
804 mutex_lock(&rx->setup_mutex);
805 __zd_usb_disable_rx(usb);
806 mutex_unlock(&rx->setup_mutex);
807
808 cancel_delayed_work_sync(&rx->idle_work);
809}
810
811static void zd_usb_reset_rx(struct zd_usb *usb)
812{
813 bool do_reset;
814 struct zd_usb_rx *rx = &usb->rx;
815 unsigned long flags;
816
817 mutex_lock(&rx->setup_mutex);
818
819 spin_lock_irqsave(&rx->lock, flags);
820 do_reset = rx->urbs != NULL;
821 spin_unlock_irqrestore(&rx->lock, flags);
822
823 if (do_reset) {
824 __zd_usb_disable_rx(usb);
825 __zd_usb_enable_rx(usb);
826 }
827
828 mutex_unlock(&rx->setup_mutex);
829
830 if (do_reset)
831 zd_usb_reset_rx_idle_timer(usb);
832}
833
784/** 834/**
785 * zd_usb_disable_tx - disable transmission 835 * zd_usb_disable_tx - disable transmission
786 * @usb: the zd1211rw-private USB structure 836 * @usb: the zd1211rw-private USB structure
@@ -1033,6 +1083,29 @@ void zd_tx_watchdog_disable(struct zd_usb *usb)
1033 } 1083 }
1034} 1084}
1035 1085
1086static void zd_rx_idle_timer_handler(struct work_struct *work)
1087{
1088 struct zd_usb *usb =
1089 container_of(work, struct zd_usb, rx.idle_work.work);
1090 struct zd_mac *mac = zd_usb_to_mac(usb);
1091
1092 if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
1093 return;
1094
1095 dev_dbg_f(zd_usb_dev(usb), "\n");
1096
1097 /* 30 seconds since last rx, reset rx */
1098 zd_usb_reset_rx(usb);
1099}
1100
1101void zd_usb_reset_rx_idle_timer(struct zd_usb *usb)
1102{
1103 struct zd_usb_rx *rx = &usb->rx;
1104
1105 cancel_delayed_work(&rx->idle_work);
1106 queue_delayed_work(zd_workqueue, &rx->idle_work, ZD_RX_IDLE_INTERVAL);
1107}
1108
1036static inline void init_usb_interrupt(struct zd_usb *usb) 1109static inline void init_usb_interrupt(struct zd_usb *usb)
1037{ 1110{
1038 struct zd_usb_interrupt *intr = &usb->intr; 1111 struct zd_usb_interrupt *intr = &usb->intr;
@@ -1047,12 +1120,14 @@ static inline void init_usb_rx(struct zd_usb *usb)
1047{ 1120{
1048 struct zd_usb_rx *rx = &usb->rx; 1121 struct zd_usb_rx *rx = &usb->rx;
1049 spin_lock_init(&rx->lock); 1122 spin_lock_init(&rx->lock);
1123 mutex_init(&rx->setup_mutex);
1050 if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) { 1124 if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) {
1051 rx->usb_packet_size = 512; 1125 rx->usb_packet_size = 512;
1052 } else { 1126 } else {
1053 rx->usb_packet_size = 64; 1127 rx->usb_packet_size = 64;
1054 } 1128 }
1055 ZD_ASSERT(rx->fragment_length == 0); 1129 ZD_ASSERT(rx->fragment_length == 0);
1130 INIT_DELAYED_WORK(&rx->idle_work, zd_rx_idle_timer_handler);
1056} 1131}
1057 1132
1058static inline void init_usb_tx(struct zd_usb *usb) 1133static 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 98f09c2dde7e..2d688f48a34c 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -34,6 +34,7 @@
34 34
35#define ZD_TX_TIMEOUT (HZ * 5) 35#define ZD_TX_TIMEOUT (HZ * 5)
36#define ZD_TX_WATCHDOG_INTERVAL round_jiffies_relative(HZ) 36#define ZD_TX_WATCHDOG_INTERVAL round_jiffies_relative(HZ)
37#define ZD_RX_IDLE_INTERVAL round_jiffies_relative(30 * HZ)
37 38
38enum devicetype { 39enum devicetype {
39 DEVICE_ZD1211 = 0, 40 DEVICE_ZD1211 = 0,
@@ -180,7 +181,9 @@ static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
180 181
181struct zd_usb_rx { 182struct zd_usb_rx {
182 spinlock_t lock; 183 spinlock_t lock;
183 u8 fragment[2*USB_MAX_RX_SIZE]; 184 struct mutex setup_mutex;
185 struct delayed_work idle_work;
186 u8 fragment[2 * USB_MAX_RX_SIZE];
184 unsigned int fragment_length; 187 unsigned int fragment_length;
185 unsigned int usb_packet_size; 188 unsigned int usb_packet_size;
186 struct urb **urbs; 189 struct urb **urbs;
@@ -251,6 +254,8 @@ void zd_usb_disable_int(struct zd_usb *usb);
251int zd_usb_enable_rx(struct zd_usb *usb); 254int zd_usb_enable_rx(struct zd_usb *usb);
252void zd_usb_disable_rx(struct zd_usb *usb); 255void zd_usb_disable_rx(struct zd_usb *usb);
253 256
257void zd_usb_reset_rx_idle_timer(struct zd_usb *usb);
258
254void zd_usb_enable_tx(struct zd_usb *usb); 259void zd_usb_enable_tx(struct zd_usb *usb);
255void zd_usb_disable_tx(struct zd_usb *usb); 260void zd_usb_disable_tx(struct zd_usb *usb);
256 261