diff options
-rw-r--r-- | drivers/net/wireless/zd1211rw/zd_usb.c | 79 | ||||
-rw-r--r-- | 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 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 | ||
705 | int zd_usb_enable_rx(struct zd_usb *usb) | 707 | static 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 | ||
757 | void zd_usb_disable_rx(struct zd_usb *usb) | 759 | int 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 | |||
773 | static 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 | ||
800 | void 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 | |||
811 | static 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 | ||
1086 | static 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 | |||
1101 | void 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 | |||
1036 | static inline void init_usb_interrupt(struct zd_usb *usb) | 1109 | static 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 | ||
1058 | static inline void init_usb_tx(struct zd_usb *usb) | 1133 | 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 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 | ||
38 | enum devicetype { | 39 | enum 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 | ||
181 | struct zd_usb_rx { | 182 | struct 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); | |||
251 | int zd_usb_enable_rx(struct zd_usb *usb); | 254 | int zd_usb_enable_rx(struct zd_usb *usb); |
252 | void zd_usb_disable_rx(struct zd_usb *usb); | 255 | void zd_usb_disable_rx(struct zd_usb *usb); |
253 | 256 | ||
257 | void zd_usb_reset_rx_idle_timer(struct zd_usb *usb); | ||
258 | |||
254 | void zd_usb_enable_tx(struct zd_usb *usb); | 259 | void zd_usb_enable_tx(struct zd_usb *usb); |
255 | void zd_usb_disable_tx(struct zd_usb *usb); | 260 | void zd_usb_disable_tx(struct zd_usb *usb); |
256 | 261 | ||