diff options
Diffstat (limited to 'drivers/net/wireless/ath/ar9170/usb.c')
-rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.c | 175 |
1 files changed, 107 insertions, 68 deletions
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 0f361186b78f..99a6da464bd3 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> |
@@ -94,6 +95,8 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
94 | { USB_DEVICE(0x04bb, 0x093f) }, | 95 | { USB_DEVICE(0x04bb, 0x093f) }, |
95 | /* AVM FRITZ!WLAN USB Stick N */ | 96 | /* AVM FRITZ!WLAN USB Stick N */ |
96 | { USB_DEVICE(0x057C, 0x8401) }, | 97 | { USB_DEVICE(0x057C, 0x8401) }, |
98 | /* NEC WL300NU-G */ | ||
99 | { USB_DEVICE(0x0409, 0x0249) }, | ||
97 | /* AVM FRITZ!WLAN USB Stick N 2.4 */ | 100 | /* AVM FRITZ!WLAN USB Stick N 2.4 */ |
98 | { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, | 101 | { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, |
99 | 102 | ||
@@ -416,7 +419,7 @@ static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, | |||
416 | spin_unlock_irqrestore(&aru->common.cmdlock, flags); | 419 | spin_unlock_irqrestore(&aru->common.cmdlock, flags); |
417 | 420 | ||
418 | usb_fill_int_urb(urb, aru->udev, | 421 | usb_fill_int_urb(urb, aru->udev, |
419 | usb_sndbulkpipe(aru->udev, AR9170_EP_CMD), | 422 | usb_sndintpipe(aru->udev, AR9170_EP_CMD), |
420 | aru->common.cmdbuf, plen + 4, | 423 | aru->common.cmdbuf, plen + 4, |
421 | ar9170_usb_tx_urb_complete, NULL, 1); | 424 | ar9170_usb_tx_urb_complete, NULL, 1); |
422 | 425 | ||
@@ -582,43 +585,6 @@ static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, | |||
582 | return 0; | 585 | return 0; |
583 | } | 586 | } |
584 | 587 | ||
585 | static int ar9170_usb_request_firmware(struct ar9170_usb *aru) | ||
586 | { | ||
587 | int err = 0; | ||
588 | |||
589 | err = request_firmware(&aru->firmware, "ar9170.fw", | ||
590 | &aru->udev->dev); | ||
591 | if (!err) { | ||
592 | aru->init_values = NULL; | ||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | if (aru->req_one_stage_fw) { | ||
597 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
598 | "not found and is required for this device\n"); | ||
599 | return -EINVAL; | ||
600 | } | ||
601 | |||
602 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
603 | "not found, trying old firmware...\n"); | ||
604 | |||
605 | err = request_firmware(&aru->init_values, "ar9170-1.fw", | ||
606 | &aru->udev->dev); | ||
607 | if (err) { | ||
608 | dev_err(&aru->udev->dev, "file with init values not found.\n"); | ||
609 | return err; | ||
610 | } | ||
611 | |||
612 | err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev); | ||
613 | if (err) { | ||
614 | release_firmware(aru->init_values); | ||
615 | dev_err(&aru->udev->dev, "firmware file not found.\n"); | ||
616 | return err; | ||
617 | } | ||
618 | |||
619 | return err; | ||
620 | } | ||
621 | |||
622 | static int ar9170_usb_reset(struct ar9170_usb *aru) | 588 | static int ar9170_usb_reset(struct ar9170_usb *aru) |
623 | { | 589 | { |
624 | int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); | 590 | int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); |
@@ -757,6 +723,103 @@ err_out: | |||
757 | return err; | 723 | return err; |
758 | } | 724 | } |
759 | 725 | ||
726 | static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) | ||
727 | { | ||
728 | struct device *parent = aru->udev->dev.parent; | ||
729 | |||
730 | /* unbind anything failed */ | ||
731 | if (parent) | ||
732 | down(&parent->sem); | ||
733 | device_release_driver(&aru->udev->dev); | ||
734 | if (parent) | ||
735 | up(&parent->sem); | ||
736 | } | ||
737 | |||
738 | static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) | ||
739 | { | ||
740 | struct ar9170_usb *aru = context; | ||
741 | int err; | ||
742 | |||
743 | aru->firmware = fw; | ||
744 | |||
745 | if (!fw) { | ||
746 | dev_err(&aru->udev->dev, "firmware file not found.\n"); | ||
747 | goto err_freefw; | ||
748 | } | ||
749 | |||
750 | err = ar9170_usb_init_device(aru); | ||
751 | if (err) | ||
752 | goto err_freefw; | ||
753 | |||
754 | err = ar9170_usb_open(&aru->common); | ||
755 | if (err) | ||
756 | goto err_unrx; | ||
757 | |||
758 | err = ar9170_register(&aru->common, &aru->udev->dev); | ||
759 | |||
760 | ar9170_usb_stop(&aru->common); | ||
761 | if (err) | ||
762 | goto err_unrx; | ||
763 | |||
764 | return; | ||
765 | |||
766 | err_unrx: | ||
767 | ar9170_usb_cancel_urbs(aru); | ||
768 | |||
769 | err_freefw: | ||
770 | ar9170_usb_firmware_failed(aru); | ||
771 | } | ||
772 | |||
773 | static void ar9170_usb_firmware_inits(const struct firmware *fw, | ||
774 | void *context) | ||
775 | { | ||
776 | struct ar9170_usb *aru = context; | ||
777 | int err; | ||
778 | |||
779 | if (!fw) { | ||
780 | dev_err(&aru->udev->dev, "file with init values not found.\n"); | ||
781 | ar9170_usb_firmware_failed(aru); | ||
782 | return; | ||
783 | } | ||
784 | |||
785 | aru->init_values = fw; | ||
786 | |||
787 | /* ok so we have the init values -- get code for two-stage */ | ||
788 | |||
789 | err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-2.fw", | ||
790 | &aru->udev->dev, GFP_KERNEL, aru, | ||
791 | ar9170_usb_firmware_finish); | ||
792 | if (err) | ||
793 | ar9170_usb_firmware_failed(aru); | ||
794 | } | ||
795 | |||
796 | static void ar9170_usb_firmware_step2(const struct firmware *fw, void *context) | ||
797 | { | ||
798 | struct ar9170_usb *aru = context; | ||
799 | int err; | ||
800 | |||
801 | if (fw) { | ||
802 | ar9170_usb_firmware_finish(fw, context); | ||
803 | return; | ||
804 | } | ||
805 | |||
806 | if (aru->req_one_stage_fw) { | ||
807 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
808 | "not found and is required for this device\n"); | ||
809 | ar9170_usb_firmware_failed(aru); | ||
810 | return; | ||
811 | } | ||
812 | |||
813 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
814 | "not found, trying old firmware...\n"); | ||
815 | |||
816 | err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-1.fw", | ||
817 | &aru->udev->dev, GFP_KERNEL, aru, | ||
818 | ar9170_usb_firmware_inits); | ||
819 | if (err) | ||
820 | ar9170_usb_firmware_failed(aru); | ||
821 | } | ||
822 | |||
760 | static bool ar9170_requires_one_stage(const struct usb_device_id *id) | 823 | static bool ar9170_requires_one_stage(const struct usb_device_id *id) |
761 | { | 824 | { |
762 | if (!id->driver_info) | 825 | if (!id->driver_info) |
@@ -814,33 +877,9 @@ static int ar9170_usb_probe(struct usb_interface *intf, | |||
814 | if (err) | 877 | if (err) |
815 | goto err_freehw; | 878 | goto err_freehw; |
816 | 879 | ||
817 | err = ar9170_usb_request_firmware(aru); | 880 | return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", |
818 | if (err) | 881 | &aru->udev->dev, GFP_KERNEL, aru, |
819 | goto err_freehw; | 882 | ar9170_usb_firmware_step2); |
820 | |||
821 | err = ar9170_usb_init_device(aru); | ||
822 | if (err) | ||
823 | goto err_freefw; | ||
824 | |||
825 | err = ar9170_usb_open(ar); | ||
826 | if (err) | ||
827 | goto err_unrx; | ||
828 | |||
829 | err = ar9170_register(ar, &udev->dev); | ||
830 | |||
831 | ar9170_usb_stop(ar); | ||
832 | if (err) | ||
833 | goto err_unrx; | ||
834 | |||
835 | return 0; | ||
836 | |||
837 | err_unrx: | ||
838 | ar9170_usb_cancel_urbs(aru); | ||
839 | |||
840 | err_freefw: | ||
841 | release_firmware(aru->init_values); | ||
842 | release_firmware(aru->firmware); | ||
843 | |||
844 | err_freehw: | 883 | err_freehw: |
845 | usb_set_intfdata(intf, NULL); | 884 | usb_set_intfdata(intf, NULL); |
846 | usb_put_dev(udev); | 885 | usb_put_dev(udev); |
@@ -860,12 +899,12 @@ static void ar9170_usb_disconnect(struct usb_interface *intf) | |||
860 | ar9170_unregister(&aru->common); | 899 | ar9170_unregister(&aru->common); |
861 | ar9170_usb_cancel_urbs(aru); | 900 | ar9170_usb_cancel_urbs(aru); |
862 | 901 | ||
863 | release_firmware(aru->init_values); | ||
864 | release_firmware(aru->firmware); | ||
865 | |||
866 | usb_put_dev(aru->udev); | 902 | usb_put_dev(aru->udev); |
867 | usb_set_intfdata(intf, NULL); | 903 | usb_set_intfdata(intf, NULL); |
868 | ieee80211_free_hw(aru->common.hw); | 904 | ieee80211_free_hw(aru->common.hw); |
905 | |||
906 | release_firmware(aru->init_values); | ||
907 | release_firmware(aru->firmware); | ||
869 | } | 908 | } |
870 | 909 | ||
871 | #ifdef CONFIG_PM | 910 | #ifdef CONFIG_PM |