diff options
Diffstat (limited to 'drivers/net/wireless/ath/ar9170/usb.c')
| -rw-r--r-- | drivers/net/wireless/ath/ar9170/usb.c | 170 |
1 files changed, 103 insertions, 67 deletions
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 0f361186b78f..4e30197afff6 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
| @@ -582,43 +582,6 @@ static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, | |||
| 582 | return 0; | 582 | return 0; |
| 583 | } | 583 | } |
| 584 | 584 | ||
| 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) | 585 | static int ar9170_usb_reset(struct ar9170_usb *aru) |
| 623 | { | 586 | { |
| 624 | int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); | 587 | int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); |
| @@ -757,6 +720,103 @@ err_out: | |||
| 757 | return err; | 720 | return err; |
| 758 | } | 721 | } |
| 759 | 722 | ||
| 723 | static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) | ||
| 724 | { | ||
| 725 | struct device *parent = aru->udev->dev.parent; | ||
| 726 | |||
| 727 | /* unbind anything failed */ | ||
| 728 | if (parent) | ||
| 729 | down(&parent->sem); | ||
| 730 | device_release_driver(&aru->udev->dev); | ||
| 731 | if (parent) | ||
| 732 | up(&parent->sem); | ||
| 733 | } | ||
| 734 | |||
| 735 | static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) | ||
| 736 | { | ||
| 737 | struct ar9170_usb *aru = context; | ||
| 738 | int err; | ||
| 739 | |||
| 740 | aru->firmware = fw; | ||
| 741 | |||
| 742 | if (!fw) { | ||
| 743 | dev_err(&aru->udev->dev, "firmware file not found.\n"); | ||
| 744 | goto err_freefw; | ||
| 745 | } | ||
| 746 | |||
| 747 | err = ar9170_usb_init_device(aru); | ||
| 748 | if (err) | ||
| 749 | goto err_freefw; | ||
| 750 | |||
| 751 | err = ar9170_usb_open(&aru->common); | ||
| 752 | if (err) | ||
| 753 | goto err_unrx; | ||
| 754 | |||
| 755 | err = ar9170_register(&aru->common, &aru->udev->dev); | ||
| 756 | |||
| 757 | ar9170_usb_stop(&aru->common); | ||
| 758 | if (err) | ||
| 759 | goto err_unrx; | ||
| 760 | |||
| 761 | return; | ||
| 762 | |||
| 763 | err_unrx: | ||
| 764 | ar9170_usb_cancel_urbs(aru); | ||
| 765 | |||
| 766 | err_freefw: | ||
| 767 | ar9170_usb_firmware_failed(aru); | ||
| 768 | } | ||
| 769 | |||
| 770 | static void ar9170_usb_firmware_inits(const struct firmware *fw, | ||
| 771 | void *context) | ||
| 772 | { | ||
| 773 | struct ar9170_usb *aru = context; | ||
| 774 | int err; | ||
| 775 | |||
| 776 | if (!fw) { | ||
| 777 | dev_err(&aru->udev->dev, "file with init values not found.\n"); | ||
| 778 | ar9170_usb_firmware_failed(aru); | ||
| 779 | return; | ||
| 780 | } | ||
| 781 | |||
| 782 | aru->init_values = fw; | ||
| 783 | |||
| 784 | /* ok so we have the init values -- get code for two-stage */ | ||
| 785 | |||
| 786 | err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-2.fw", | ||
| 787 | &aru->udev->dev, GFP_KERNEL, aru, | ||
| 788 | ar9170_usb_firmware_finish); | ||
| 789 | if (err) | ||
| 790 | ar9170_usb_firmware_failed(aru); | ||
| 791 | } | ||
| 792 | |||
| 793 | static void ar9170_usb_firmware_step2(const struct firmware *fw, void *context) | ||
| 794 | { | ||
| 795 | struct ar9170_usb *aru = context; | ||
| 796 | int err; | ||
| 797 | |||
| 798 | if (fw) { | ||
| 799 | ar9170_usb_firmware_finish(fw, context); | ||
| 800 | return; | ||
| 801 | } | ||
| 802 | |||
| 803 | if (aru->req_one_stage_fw) { | ||
| 804 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
| 805 | "not found and is required for this device\n"); | ||
| 806 | ar9170_usb_firmware_failed(aru); | ||
| 807 | return; | ||
| 808 | } | ||
| 809 | |||
| 810 | dev_err(&aru->udev->dev, "ar9170.fw firmware file " | ||
| 811 | "not found, trying old firmware...\n"); | ||
| 812 | |||
| 813 | err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-1.fw", | ||
| 814 | &aru->udev->dev, GFP_KERNEL, aru, | ||
| 815 | ar9170_usb_firmware_inits); | ||
| 816 | if (err) | ||
| 817 | ar9170_usb_firmware_failed(aru); | ||
| 818 | } | ||
| 819 | |||
| 760 | static bool ar9170_requires_one_stage(const struct usb_device_id *id) | 820 | static bool ar9170_requires_one_stage(const struct usb_device_id *id) |
| 761 | { | 821 | { |
| 762 | if (!id->driver_info) | 822 | if (!id->driver_info) |
| @@ -814,33 +874,9 @@ static int ar9170_usb_probe(struct usb_interface *intf, | |||
| 814 | if (err) | 874 | if (err) |
| 815 | goto err_freehw; | 875 | goto err_freehw; |
| 816 | 876 | ||
| 817 | err = ar9170_usb_request_firmware(aru); | 877 | return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", |
| 818 | if (err) | 878 | &aru->udev->dev, GFP_KERNEL, aru, |
| 819 | goto err_freehw; | 879 | 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: | 880 | err_freehw: |
| 845 | usb_set_intfdata(intf, NULL); | 881 | usb_set_intfdata(intf, NULL); |
| 846 | usb_put_dev(udev); | 882 | usb_put_dev(udev); |
| @@ -860,12 +896,12 @@ static void ar9170_usb_disconnect(struct usb_interface *intf) | |||
| 860 | ar9170_unregister(&aru->common); | 896 | ar9170_unregister(&aru->common); |
| 861 | ar9170_usb_cancel_urbs(aru); | 897 | ar9170_usb_cancel_urbs(aru); |
| 862 | 898 | ||
| 863 | release_firmware(aru->init_values); | ||
| 864 | release_firmware(aru->firmware); | ||
| 865 | |||
| 866 | usb_put_dev(aru->udev); | 899 | usb_put_dev(aru->udev); |
| 867 | usb_set_intfdata(intf, NULL); | 900 | usb_set_intfdata(intf, NULL); |
| 868 | ieee80211_free_hw(aru->common.hw); | 901 | ieee80211_free_hw(aru->common.hw); |
| 902 | |||
| 903 | release_firmware(aru->init_values); | ||
| 904 | release_firmware(aru->firmware); | ||
| 869 | } | 905 | } |
| 870 | 906 | ||
| 871 | #ifdef CONFIG_PM | 907 | #ifdef CONFIG_PM |
