aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>2011-01-31 13:47:08 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-04 16:29:48 -0500
commit78fc800f06a72c25842e585fd747fa6a98f3f0e5 (patch)
tree2c71d432229c54b0efb3103f04815c9f74e9ca1b
parent681d119047761cc59a15c0bb86891f3a878997cf (diff)
zd1211rw: use urb anchors for tx and fix tx-queue disabling
When stress testing AP-mode I hit OOPS when unpluging or rmmodding driver. It appears that when tx-queue is disabled, tx-urbs might be left pending. These can cause ehci to call non-existing tx_urb_complete() (after rmmod) or uninitialized/reseted private structure (after disconnect()). Add skb queue for submitted packets and unlink pending urbs on zd_usb_disable_tx(). Part of the problem seems to be usb->free_urb_list that isn't always working as it should, causing machine freeze when trying to free the list in zd_usb_disable_tx(). Caching free urbs isn't what other drivers seem to be doing (usbnet for example) so strip free_usb_list. Patch makes tx-urb handling saner with use of urb anchors. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c108
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.h8
2 files changed, 41 insertions, 75 deletions
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 06041cb1c42..c32a2472eb4 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -779,19 +779,20 @@ void zd_usb_disable_tx(struct zd_usb *usb)
779{ 779{
780 struct zd_usb_tx *tx = &usb->tx; 780 struct zd_usb_tx *tx = &usb->tx;
781 unsigned long flags; 781 unsigned long flags;
782 struct list_head *pos, *n; 782
783 atomic_set(&tx->enabled, 0);
784
785 /* kill all submitted tx-urbs */
786 usb_kill_anchored_urbs(&tx->submitted);
783 787
784 spin_lock_irqsave(&tx->lock, flags); 788 spin_lock_irqsave(&tx->lock, flags);
785 list_for_each_safe(pos, n, &tx->free_urb_list) { 789 WARN_ON(tx->submitted_urbs != 0);
786 list_del(pos);
787 usb_free_urb(list_entry(pos, struct urb, urb_list));
788 }
789 tx->enabled = 0;
790 tx->submitted_urbs = 0; 790 tx->submitted_urbs = 0;
791 spin_unlock_irqrestore(&tx->lock, flags);
792
791 /* The stopped state is ignored, relying on ieee80211_wake_queues() 793 /* The stopped state is ignored, relying on ieee80211_wake_queues()
792 * in a potentionally following zd_usb_enable_tx(). 794 * in a potentionally following zd_usb_enable_tx().
793 */ 795 */
794 spin_unlock_irqrestore(&tx->lock, flags);
795} 796}
796 797
797/** 798/**
@@ -807,63 +808,13 @@ void zd_usb_enable_tx(struct zd_usb *usb)
807 struct zd_usb_tx *tx = &usb->tx; 808 struct zd_usb_tx *tx = &usb->tx;
808 809
809 spin_lock_irqsave(&tx->lock, flags); 810 spin_lock_irqsave(&tx->lock, flags);
810 tx->enabled = 1; 811 atomic_set(&tx->enabled, 1);
811 tx->submitted_urbs = 0; 812 tx->submitted_urbs = 0;
812 ieee80211_wake_queues(zd_usb_to_hw(usb)); 813 ieee80211_wake_queues(zd_usb_to_hw(usb));
813 tx->stopped = 0; 814 tx->stopped = 0;
814 spin_unlock_irqrestore(&tx->lock, flags); 815 spin_unlock_irqrestore(&tx->lock, flags);
815} 816}
816 817
817/**
818 * alloc_tx_urb - provides an tx URB
819 * @usb: a &struct zd_usb pointer
820 *
821 * Allocates a new URB. If possible takes the urb from the free list in
822 * usb->tx.
823 */
824static struct urb *alloc_tx_urb(struct zd_usb *usb)
825{
826 struct zd_usb_tx *tx = &usb->tx;
827 unsigned long flags;
828 struct list_head *entry;
829 struct urb *urb;
830
831 spin_lock_irqsave(&tx->lock, flags);
832 if (list_empty(&tx->free_urb_list)) {
833 urb = usb_alloc_urb(0, GFP_ATOMIC);
834 goto out;
835 }
836 entry = tx->free_urb_list.next;
837 list_del(entry);
838 urb = list_entry(entry, struct urb, urb_list);
839out:
840 spin_unlock_irqrestore(&tx->lock, flags);
841 return urb;
842}
843
844/**
845 * free_tx_urb - frees a used tx URB
846 * @usb: a &struct zd_usb pointer
847 * @urb: URB to be freed
848 *
849 * Frees the transmission URB, which means to put it on the free URB
850 * list.
851 */
852static void free_tx_urb(struct zd_usb *usb, struct urb *urb)
853{
854 struct zd_usb_tx *tx = &usb->tx;
855 unsigned long flags;
856
857 spin_lock_irqsave(&tx->lock, flags);
858 if (!tx->enabled) {
859 usb_free_urb(urb);
860 goto out;
861 }
862 list_add(&urb->urb_list, &tx->free_urb_list);
863out:
864 spin_unlock_irqrestore(&tx->lock, flags);
865}
866
867static void tx_dec_submitted_urbs(struct zd_usb *usb) 818static void tx_dec_submitted_urbs(struct zd_usb *usb)
868{ 819{
869 struct zd_usb_tx *tx = &usb->tx; 820 struct zd_usb_tx *tx = &usb->tx;
@@ -905,6 +856,16 @@ static void tx_urb_complete(struct urb *urb)
905 struct sk_buff *skb; 856 struct sk_buff *skb;
906 struct ieee80211_tx_info *info; 857 struct ieee80211_tx_info *info;
907 struct zd_usb *usb; 858 struct zd_usb *usb;
859 struct zd_usb_tx *tx;
860
861 skb = (struct sk_buff *)urb->context;
862 info = IEEE80211_SKB_CB(skb);
863 /*
864 * grab 'usb' pointer before handing off the skb (since
865 * it might be freed by zd_mac_tx_to_dev or mac80211)
866 */
867 usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
868 tx = &usb->tx;
908 869
909 switch (urb->status) { 870 switch (urb->status) {
910 case 0: 871 case 0:
@@ -922,20 +883,15 @@ static void tx_urb_complete(struct urb *urb)
922 goto resubmit; 883 goto resubmit;
923 } 884 }
924free_urb: 885free_urb:
925 skb = (struct sk_buff *)urb->context;
926 /*
927 * grab 'usb' pointer before handing off the skb (since
928 * it might be freed by zd_mac_tx_to_dev or mac80211)
929 */
930 info = IEEE80211_SKB_CB(skb);
931 usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
932 zd_mac_tx_to_dev(skb, urb->status); 886 zd_mac_tx_to_dev(skb, urb->status);
933 free_tx_urb(usb, urb); 887 usb_free_urb(urb);
934 tx_dec_submitted_urbs(usb); 888 tx_dec_submitted_urbs(usb);
935 return; 889 return;
936resubmit: 890resubmit:
891 usb_anchor_urb(urb, &tx->submitted);
937 r = usb_submit_urb(urb, GFP_ATOMIC); 892 r = usb_submit_urb(urb, GFP_ATOMIC);
938 if (r) { 893 if (r) {
894 usb_unanchor_urb(urb);
939 dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r); 895 dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r);
940 goto free_urb; 896 goto free_urb;
941 } 897 }
@@ -958,8 +914,14 @@ int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb)
958 int r; 914 int r;
959 struct usb_device *udev = zd_usb_to_usbdev(usb); 915 struct usb_device *udev = zd_usb_to_usbdev(usb);
960 struct urb *urb; 916 struct urb *urb;
917 struct zd_usb_tx *tx = &usb->tx;
961 918
962 urb = alloc_tx_urb(usb); 919 if (!atomic_read(&tx->enabled)) {
920 r = -ENOENT;
921 goto out;
922 }
923
924 urb = usb_alloc_urb(0, GFP_ATOMIC);
963 if (!urb) { 925 if (!urb) {
964 r = -ENOMEM; 926 r = -ENOMEM;
965 goto out; 927 goto out;
@@ -968,13 +930,16 @@ int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb)
968 usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT), 930 usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
969 skb->data, skb->len, tx_urb_complete, skb); 931 skb->data, skb->len, tx_urb_complete, skb);
970 932
933 usb_anchor_urb(urb, &tx->submitted);
971 r = usb_submit_urb(urb, GFP_ATOMIC); 934 r = usb_submit_urb(urb, GFP_ATOMIC);
972 if (r) 935 if (r) {
936 usb_unanchor_urb(urb);
973 goto error; 937 goto error;
938 }
974 tx_inc_submitted_urbs(usb); 939 tx_inc_submitted_urbs(usb);
975 return 0; 940 return 0;
976error: 941error:
977 free_tx_urb(usb, urb); 942 usb_free_urb(urb);
978out: 943out:
979 return r; 944 return r;
980} 945}
@@ -1005,9 +970,9 @@ static inline void init_usb_tx(struct zd_usb *usb)
1005{ 970{
1006 struct zd_usb_tx *tx = &usb->tx; 971 struct zd_usb_tx *tx = &usb->tx;
1007 spin_lock_init(&tx->lock); 972 spin_lock_init(&tx->lock);
1008 tx->enabled = 0; 973 atomic_set(&tx->enabled, 0);
1009 tx->stopped = 0; 974 tx->stopped = 0;
1010 INIT_LIST_HEAD(&tx->free_urb_list); 975 init_usb_anchor(&tx->submitted);
1011 tx->submitted_urbs = 0; 976 tx->submitted_urbs = 0;
1012} 977}
1013 978
@@ -1240,6 +1205,7 @@ static void disconnect(struct usb_interface *intf)
1240 ieee80211_unregister_hw(hw); 1205 ieee80211_unregister_hw(hw);
1241 1206
1242 /* Just in case something has gone wrong! */ 1207 /* Just in case something has gone wrong! */
1208 zd_usb_disable_tx(usb);
1243 zd_usb_disable_rx(usb); 1209 zd_usb_disable_rx(usb);
1244 zd_usb_disable_int(usb); 1210 zd_usb_disable_int(usb);
1245 1211
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index 1b1655cb7cb..233ce825b71 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -184,18 +184,18 @@ struct zd_usb_rx {
184 184
185/** 185/**
186 * struct zd_usb_tx - structure used for transmitting frames 186 * struct zd_usb_tx - structure used for transmitting frames
187 * @enabled: atomic enabled flag, indicates whether tx is enabled
187 * @lock: lock for transmission 188 * @lock: lock for transmission
188 * @free_urb_list: list of free URBs, contains all the URBs, which can be used 189 * @submitted: anchor for URBs sent to device
189 * @submitted_urbs: atomic integer that counts the URBs having sent to the 190 * @submitted_urbs: atomic integer that counts the URBs having sent to the
190 * device, which haven't been completed 191 * device, which haven't been completed
191 * @enabled: enabled flag, indicates whether tx is enabled
192 * @stopped: indicates whether higher level tx queues are stopped 192 * @stopped: indicates whether higher level tx queues are stopped
193 */ 193 */
194struct zd_usb_tx { 194struct zd_usb_tx {
195 atomic_t enabled;
195 spinlock_t lock; 196 spinlock_t lock;
196 struct list_head free_urb_list; 197 struct usb_anchor submitted;
197 int submitted_urbs; 198 int submitted_urbs;
198 int enabled;
199 int stopped; 199 int stopped;
200}; 200};
201 201