aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-12-23 07:15:30 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-03-02 14:31:50 -0500
commit535765179fd4e8af26b69d2240d7ec33702a370a (patch)
treea21ca3bdc1b4b5f40e233672f16ec618aab604fa /drivers
parent6e93d7195e75741e9ebe23ca5591977d0b39ecc0 (diff)
ar9170: load firmware asynchronously
This converts ar9170 to load firmware asynchronously out of ->probe() and only register with mac80211 when all firmware has been loaded successfully. If, on the other hand, any firmware fails to load, it will now unbind from the device. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ar9170/ar9170.h1
-rw-r--r--drivers/net/wireless/ath/ar9170/main.c10
-rw-r--r--drivers/net/wireless/ath/ar9170/usb.c170
3 files changed, 111 insertions, 70 deletions
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h
index 8c8ce67971e9..dc662b76a1c8 100644
--- a/drivers/net/wireless/ath/ar9170/ar9170.h
+++ b/drivers/net/wireless/ath/ar9170/ar9170.h
@@ -166,6 +166,7 @@ struct ar9170 {
166 struct ath_common common; 166 struct ath_common common;
167 struct mutex mutex; 167 struct mutex mutex;
168 enum ar9170_device_state state; 168 enum ar9170_device_state state;
169 bool registered;
169 unsigned long bad_hw_nagger; 170 unsigned long bad_hw_nagger;
170 171
171 int (*open)(struct ar9170 *); 172 int (*open)(struct ar9170 *);
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 8a964f130367..f4650fcdebc9 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -2701,7 +2701,8 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev)
2701 dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", 2701 dev_info(pdev, "Atheros AR9170 is registered as '%s'\n",
2702 wiphy_name(ar->hw->wiphy)); 2702 wiphy_name(ar->hw->wiphy));
2703 2703
2704 return err; 2704 ar->registered = true;
2705 return 0;
2705 2706
2706err_unreg: 2707err_unreg:
2707 ieee80211_unregister_hw(ar->hw); 2708 ieee80211_unregister_hw(ar->hw);
@@ -2712,11 +2713,14 @@ err_out:
2712 2713
2713void ar9170_unregister(struct ar9170 *ar) 2714void ar9170_unregister(struct ar9170 *ar)
2714{ 2715{
2716 if (ar->registered) {
2715#ifdef CONFIG_AR9170_LEDS 2717#ifdef CONFIG_AR9170_LEDS
2716 ar9170_unregister_leds(ar); 2718 ar9170_unregister_leds(ar);
2717#endif /* CONFIG_AR9170_LEDS */ 2719#endif /* CONFIG_AR9170_LEDS */
2718 2720
2719 kfree_skb(ar->rx_failover);
2720 ieee80211_unregister_hw(ar->hw); 2721 ieee80211_unregister_hw(ar->hw);
2722 }
2723
2724 kfree_skb(ar->rx_failover);
2721 mutex_destroy(&ar->mutex); 2725 mutex_destroy(&ar->mutex);
2722} 2726}
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
585static 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
622static int ar9170_usb_reset(struct ar9170_usb *aru) 585static 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
723static 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
735static 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
770static 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
793static 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
760static bool ar9170_requires_one_stage(const struct usb_device_id *id) 820static 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
837err_unrx:
838 ar9170_usb_cancel_urbs(aru);
839
840err_freefw:
841 release_firmware(aru->init_values);
842 release_firmware(aru->firmware);
843
844err_freehw: 880err_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