diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/ath/ar9170/usb.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/ath/ar9170/usb.c')
-rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.c | 204 |
1 files changed, 129 insertions, 75 deletions
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index e974e5829e1a..e1c2fcaa8bed 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
@@ -38,6 +38,7 @@ | |||
38 | */ | 38 | */ |
39 | 39 | ||
40 | #include <linux/module.h> | 40 | #include <linux/module.h> |
41 | #include <linux/slab.h> | ||
41 | #include <linux/usb.h> | 42 | #include <linux/usb.h> |
42 | #include <linux/firmware.h> | 43 | #include <linux/firmware.h> |
43 | #include <linux/etherdevice.h> | 44 | #include <linux/etherdevice.h> |
@@ -68,8 +69,10 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
68 | { USB_DEVICE(0x0cf3, 0x1002) }, | 69 | { USB_DEVICE(0x0cf3, 0x1002) }, |
69 | /* Cace Airpcap NX */ | 70 | /* Cace Airpcap NX */ |
70 | { USB_DEVICE(0xcace, 0x0300) }, | 71 | { USB_DEVICE(0xcace, 0x0300) }, |
71 | /* D-Link DWA 160A */ | 72 | /* D-Link DWA 160 A1 */ |
72 | { USB_DEVICE(0x07d1, 0x3c10) }, | 73 | { USB_DEVICE(0x07d1, 0x3c10) }, |
74 | /* D-Link DWA 160 A2 */ | ||
75 | { USB_DEVICE(0x07d1, 0x3a09) }, | ||
73 | /* Netgear WNDA3100 */ | 76 | /* Netgear WNDA3100 */ |
74 | { USB_DEVICE(0x0846, 0x9010) }, | 77 | { USB_DEVICE(0x0846, 0x9010) }, |
75 | /* Netgear WN111 v2 */ | 78 | /* Netgear WN111 v2 */ |
@@ -82,6 +85,8 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
82 | { USB_DEVICE(0x0cde, 0x0023) }, | 85 | { USB_DEVICE(0x0cde, 0x0023) }, |
83 | /* Z-Com UB82 ABG */ | 86 | /* Z-Com UB82 ABG */ |
84 | { USB_DEVICE(0x0cde, 0x0026) }, | 87 | { USB_DEVICE(0x0cde, 0x0026) }, |
88 | /* Sphairon Homelink 1202 */ | ||
89 | { USB_DEVICE(0x0cde, 0x0027) }, | ||
85 | /* Arcadyan WN7512 */ | 90 | /* Arcadyan WN7512 */ |
86 | { USB_DEVICE(0x083a, 0xf522) }, | 91 | { USB_DEVICE(0x083a, 0xf522) }, |
87 | /* Planex GWUS300 */ | 92 | /* Planex GWUS300 */ |
@@ -90,6 +95,8 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
90 | { USB_DEVICE(0x04bb, 0x093f) }, | 95 | { USB_DEVICE(0x04bb, 0x093f) }, |
91 | /* AVM FRITZ!WLAN USB Stick N */ | 96 | /* AVM FRITZ!WLAN USB Stick N */ |
92 | { USB_DEVICE(0x057C, 0x8401) }, | 97 | { USB_DEVICE(0x057C, 0x8401) }, |
98 | /* NEC WL300NU-G */ | ||
99 | { USB_DEVICE(0x0409, 0x0249) }, | ||
93 | /* AVM FRITZ!WLAN USB Stick N 2.4 */ | 100 | /* AVM FRITZ!WLAN USB Stick N 2.4 */ |
94 | { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, | 101 | { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, |
95 | 102 | ||
@@ -108,15 +115,15 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru) | |||
108 | return ; | 115 | return ; |
109 | 116 | ||
110 | spin_lock_irqsave(&aru->tx_urb_lock, flags); | 117 | spin_lock_irqsave(&aru->tx_urb_lock, flags); |
111 | if (aru->tx_submitted_urbs >= AR9170_NUM_TX_URBS) { | 118 | if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) { |
112 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | 119 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); |
113 | return ; | 120 | return ; |
114 | } | 121 | } |
115 | aru->tx_submitted_urbs++; | 122 | atomic_inc(&aru->tx_submitted_urbs); |
116 | 123 | ||
117 | urb = usb_get_from_anchor(&aru->tx_pending); | 124 | urb = usb_get_from_anchor(&aru->tx_pending); |
118 | if (!urb) { | 125 | if (!urb) { |
119 | aru->tx_submitted_urbs--; | 126 | atomic_dec(&aru->tx_submitted_urbs); |
120 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); | 127 | spin_unlock_irqrestore(&aru->tx_urb_lock, flags); |
121 | 128 | ||
122 | return ; | 129 | return ; |
@@ -133,7 +140,7 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru) | |||
133 | err); | 140 | err); |
134 | 141 | ||
135 | usb_unanchor_urb(urb); | 142 | usb_unanchor_urb(urb); |
136 | aru->tx_submitted_urbs--; | 143 | atomic_dec(&aru->tx_submitted_urbs); |
137 | ar9170_tx_callback(&aru->common, urb->context); | 144 | ar9170_tx_callback(&aru->common, urb->context); |
138 | } | 145 | } |
139 | 146 | ||
@@ -151,7 +158,7 @@ static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) | |||
151 | return ; | 158 | return ; |
152 | } | 159 | } |
153 | 160 | ||
154 | aru->tx_submitted_urbs--; | 161 | atomic_dec(&aru->tx_submitted_urbs); |
155 | 162 | ||
156 | ar9170_tx_callback(&aru->common, skb); | 163 | ar9170_tx_callback(&aru->common, skb); |
157 | 164 | ||
@@ -412,7 +419,7 @@ static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, | |||
412 | spin_unlock_irqrestore(&aru->common.cmdlock, flags); | 419 | spin_unlock_irqrestore(&aru->common.cmdlock, flags); |
413 | 420 | ||
414 | usb_fill_int_urb(urb, aru->udev, | 421 | usb_fill_int_urb(urb, aru->udev, |
415 | usb_sndbulkpipe(aru->udev, AR9170_EP_CMD), | 422 | usb_sndintpipe(aru->udev, AR9170_EP_CMD), |
416 | aru->common.cmdbuf, plen + 4, | 423 | aru->common.cmdbuf, plen + 4, |
417 | ar9170_usb_tx_urb_complete, NULL, 1); | 424 | ar9170_usb_tx_urb_complete, NULL, 1); |
418 | 425 | ||
@@ -578,43 +585,6 @@ static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, | |||
578 | return 0; | 585 | return 0; |
579 | } | 586 | } |
580 | 587 | ||
581 | static int ar9170_usb_request_firmware(struct ar9170_usb *aru) | ||
582 | { | ||
583 | int err = 0; | ||
584 | |||
585 | err = request_firmware(&aru->firmware, "ar9170.fw", | ||
586 | &aru->udev->dev); | ||
587 | if (!err) { | ||
588 | aru->init_values = NULL; | ||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | if (aru->req_one_stage_fw) { | ||
593 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
594 | "not found and is required for this device\n"); | ||
595 | return -EINVAL; | ||
596 | } | ||
597 | |||
598 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
599 | "not found, trying old firmware...\n"); | ||
600 | |||
601 | err = request_firmware(&aru->init_values, "ar9170-1.fw", | ||
602 | &aru->udev->dev); | ||
603 | if (err) { | ||
604 | dev_err(&aru->udev->dev, "file with init values not found.\n"); | ||
605 | return err; | ||
606 | } | ||
607 | |||
608 | err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev); | ||
609 | if (err) { | ||
610 | release_firmware(aru->init_values); | ||
611 | dev_err(&aru->udev->dev, "firmware file not found.\n"); | ||
612 | return err; | ||
613 | } | ||
614 | |||
615 | return err; | ||
616 | } | ||
617 | |||
618 | static int ar9170_usb_reset(struct ar9170_usb *aru) | 588 | static int ar9170_usb_reset(struct ar9170_usb *aru) |
619 | { | 589 | { |
620 | int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); | 590 | int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); |
@@ -753,6 +723,109 @@ err_out: | |||
753 | return err; | 723 | return err; |
754 | } | 724 | } |
755 | 725 | ||
726 | static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) | ||
727 | { | ||
728 | struct device *parent = aru->udev->dev.parent; | ||
729 | |||
730 | complete(&aru->firmware_loading_complete); | ||
731 | |||
732 | /* unbind anything failed */ | ||
733 | if (parent) | ||
734 | down(&parent->sem); | ||
735 | device_release_driver(&aru->udev->dev); | ||
736 | if (parent) | ||
737 | up(&parent->sem); | ||
738 | |||
739 | usb_put_dev(aru->udev); | ||
740 | } | ||
741 | |||
742 | static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) | ||
743 | { | ||
744 | struct ar9170_usb *aru = context; | ||
745 | int err; | ||
746 | |||
747 | aru->firmware = fw; | ||
748 | |||
749 | if (!fw) { | ||
750 | dev_err(&aru->udev->dev, "firmware file not found.\n"); | ||
751 | goto err_freefw; | ||
752 | } | ||
753 | |||
754 | err = ar9170_usb_init_device(aru); | ||
755 | if (err) | ||
756 | goto err_freefw; | ||
757 | |||
758 | err = ar9170_usb_open(&aru->common); | ||
759 | if (err) | ||
760 | goto err_unrx; | ||
761 | |||
762 | err = ar9170_register(&aru->common, &aru->udev->dev); | ||
763 | |||
764 | ar9170_usb_stop(&aru->common); | ||
765 | if (err) | ||
766 | goto err_unrx; | ||
767 | |||
768 | complete(&aru->firmware_loading_complete); | ||
769 | usb_put_dev(aru->udev); | ||
770 | return; | ||
771 | |||
772 | err_unrx: | ||
773 | ar9170_usb_cancel_urbs(aru); | ||
774 | |||
775 | err_freefw: | ||
776 | ar9170_usb_firmware_failed(aru); | ||
777 | } | ||
778 | |||
779 | static void ar9170_usb_firmware_inits(const struct firmware *fw, | ||
780 | void *context) | ||
781 | { | ||
782 | struct ar9170_usb *aru = context; | ||
783 | int err; | ||
784 | |||
785 | if (!fw) { | ||
786 | dev_err(&aru->udev->dev, "file with init values not found.\n"); | ||
787 | ar9170_usb_firmware_failed(aru); | ||
788 | return; | ||
789 | } | ||
790 | |||
791 | aru->init_values = fw; | ||
792 | |||
793 | /* ok so we have the init values -- get code for two-stage */ | ||
794 | |||
795 | err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-2.fw", | ||
796 | &aru->udev->dev, GFP_KERNEL, aru, | ||
797 | ar9170_usb_firmware_finish); | ||
798 | if (err) | ||
799 | ar9170_usb_firmware_failed(aru); | ||
800 | } | ||
801 | |||
802 | static void ar9170_usb_firmware_step2(const struct firmware *fw, void *context) | ||
803 | { | ||
804 | struct ar9170_usb *aru = context; | ||
805 | int err; | ||
806 | |||
807 | if (fw) { | ||
808 | ar9170_usb_firmware_finish(fw, context); | ||
809 | return; | ||
810 | } | ||
811 | |||
812 | if (aru->req_one_stage_fw) { | ||
813 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
814 | "not found and is required for this device\n"); | ||
815 | ar9170_usb_firmware_failed(aru); | ||
816 | return; | ||
817 | } | ||
818 | |||
819 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
820 | "not found, trying old firmware...\n"); | ||
821 | |||
822 | err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-1.fw", | ||
823 | &aru->udev->dev, GFP_KERNEL, aru, | ||
824 | ar9170_usb_firmware_inits); | ||
825 | if (err) | ||
826 | ar9170_usb_firmware_failed(aru); | ||
827 | } | ||
828 | |||
756 | static bool ar9170_requires_one_stage(const struct usb_device_id *id) | 829 | static bool ar9170_requires_one_stage(const struct usb_device_id *id) |
757 | { | 830 | { |
758 | if (!id->driver_info) | 831 | if (!id->driver_info) |
@@ -791,10 +864,11 @@ static int ar9170_usb_probe(struct usb_interface *intf, | |||
791 | init_usb_anchor(&aru->tx_pending); | 864 | init_usb_anchor(&aru->tx_pending); |
792 | init_usb_anchor(&aru->tx_submitted); | 865 | init_usb_anchor(&aru->tx_submitted); |
793 | init_completion(&aru->cmd_wait); | 866 | init_completion(&aru->cmd_wait); |
867 | init_completion(&aru->firmware_loading_complete); | ||
794 | spin_lock_init(&aru->tx_urb_lock); | 868 | spin_lock_init(&aru->tx_urb_lock); |
795 | 869 | ||
796 | aru->tx_pending_urbs = 0; | 870 | aru->tx_pending_urbs = 0; |
797 | aru->tx_submitted_urbs = 0; | 871 | atomic_set(&aru->tx_submitted_urbs, 0); |
798 | 872 | ||
799 | aru->common.stop = ar9170_usb_stop; | 873 | aru->common.stop = ar9170_usb_stop; |
800 | aru->common.flush = ar9170_usb_flush; | 874 | aru->common.flush = ar9170_usb_flush; |
@@ -810,33 +884,10 @@ static int ar9170_usb_probe(struct usb_interface *intf, | |||
810 | if (err) | 884 | if (err) |
811 | goto err_freehw; | 885 | goto err_freehw; |
812 | 886 | ||
813 | err = ar9170_usb_request_firmware(aru); | 887 | usb_get_dev(aru->udev); |
814 | if (err) | 888 | return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", |
815 | goto err_freehw; | 889 | &aru->udev->dev, GFP_KERNEL, aru, |
816 | 890 | ar9170_usb_firmware_step2); | |
817 | err = ar9170_usb_init_device(aru); | ||
818 | if (err) | ||
819 | goto err_freefw; | ||
820 | |||
821 | err = ar9170_usb_open(ar); | ||
822 | if (err) | ||
823 | goto err_unrx; | ||
824 | |||
825 | err = ar9170_register(ar, &udev->dev); | ||
826 | |||
827 | ar9170_usb_stop(ar); | ||
828 | if (err) | ||
829 | goto err_unrx; | ||
830 | |||
831 | return 0; | ||
832 | |||
833 | err_unrx: | ||
834 | ar9170_usb_cancel_urbs(aru); | ||
835 | |||
836 | err_freefw: | ||
837 | release_firmware(aru->init_values); | ||
838 | release_firmware(aru->firmware); | ||
839 | |||
840 | err_freehw: | 891 | err_freehw: |
841 | usb_set_intfdata(intf, NULL); | 892 | usb_set_intfdata(intf, NULL); |
842 | usb_put_dev(udev); | 893 | usb_put_dev(udev); |
@@ -853,15 +904,18 @@ static void ar9170_usb_disconnect(struct usb_interface *intf) | |||
853 | return; | 904 | return; |
854 | 905 | ||
855 | aru->common.state = AR9170_IDLE; | 906 | aru->common.state = AR9170_IDLE; |
907 | |||
908 | wait_for_completion(&aru->firmware_loading_complete); | ||
909 | |||
856 | ar9170_unregister(&aru->common); | 910 | ar9170_unregister(&aru->common); |
857 | ar9170_usb_cancel_urbs(aru); | 911 | ar9170_usb_cancel_urbs(aru); |
858 | 912 | ||
859 | release_firmware(aru->init_values); | ||
860 | release_firmware(aru->firmware); | ||
861 | |||
862 | usb_put_dev(aru->udev); | 913 | usb_put_dev(aru->udev); |
863 | usb_set_intfdata(intf, NULL); | 914 | usb_set_intfdata(intf, NULL); |
864 | ieee80211_free_hw(aru->common.hw); | 915 | ieee80211_free_hw(aru->common.hw); |
916 | |||
917 | release_firmware(aru->init_values); | ||
918 | release_firmware(aru->firmware); | ||
865 | } | 919 | } |
866 | 920 | ||
867 | #ifdef CONFIG_PM | 921 | #ifdef CONFIG_PM |