diff options
author | Larry Finger <Larry.Finger@lwfinger.net> | 2012-01-30 10:54:49 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-01-30 15:48:50 -0500 |
commit | b0302aba812bcc39291cdab9ad7e37008f352a91 (patch) | |
tree | 82915b1e24f204babeb65e1d517115c0e31cfd9a /drivers/net/wireless/rtlwifi/usb.c | |
parent | feced2012e665468258a5c89b7f2a90b4e5695a4 (diff) |
rtlwifi: Convert to asynchronous firmware load
This patch addresses a kernel bugzilla report and two recent mail threads.
The kernel bugzilla report is https://bugzilla.kernel.org/show_bug.cgi?id=42632,
which reports a udev timeout on boot.
The first mail thread, which was on LKML (http://lkml.indiana.edu/hypermail/
linux/kernel/1112.3/00965.html) was for a WARNING that occurs after a
suspend/resume cycle for rtl8192cu.
The scond mail thread (http://marc.info/?l=linux-wireless&m=132655490826766&w=2)
concerned changes in udev that break drivers that delay while firmware is loaded
on modprobe.
This patch converts all rtlwifi-based drivers to use the asynchronous firmware
loading mechanism. Drivers rtl8192ce, rtl8192cu and rtl8192de share a common
callback routine. Driver rtl8192se needs different handling of the firmware,
thus it has its own code.
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Stable <stable@vger.kernel.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rtlwifi/usb.c')
-rw-r--r-- | drivers/net/wireless/rtlwifi/usb.c | 34 |
1 files changed, 14 insertions, 20 deletions
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index e7a7ea96f42b..ffcf89fe45e4 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -664,15 +664,17 @@ static int rtl_usb_start(struct ieee80211_hw *hw) | |||
664 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); | 664 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
665 | 665 | ||
666 | err = rtlpriv->cfg->ops->hw_init(hw); | 666 | err = rtlpriv->cfg->ops->hw_init(hw); |
667 | rtl_init_rx_config(hw); | 667 | if (!err) { |
668 | rtl_init_rx_config(hw); | ||
668 | 669 | ||
669 | /* Enable software */ | 670 | /* Enable software */ |
670 | SET_USB_START(rtlusb); | 671 | SET_USB_START(rtlusb); |
671 | /* should after adapter start and interrupt enable. */ | 672 | /* should after adapter start and interrupt enable. */ |
672 | set_hal_start(rtlhal); | 673 | set_hal_start(rtlhal); |
673 | 674 | ||
674 | /* Start bulk IN */ | 675 | /* Start bulk IN */ |
675 | _rtl_usb_receive(hw); | 676 | _rtl_usb_receive(hw); |
677 | } | ||
676 | 678 | ||
677 | return err; | 679 | return err; |
678 | } | 680 | } |
@@ -949,6 +951,7 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, | |||
949 | return -ENOMEM; | 951 | return -ENOMEM; |
950 | } | 952 | } |
951 | rtlpriv = hw->priv; | 953 | rtlpriv = hw->priv; |
954 | init_completion(&rtlpriv->firmware_loading_complete); | ||
952 | SET_IEEE80211_DEV(hw, &intf->dev); | 955 | SET_IEEE80211_DEV(hw, &intf->dev); |
953 | udev = interface_to_usbdev(intf); | 956 | udev = interface_to_usbdev(intf); |
954 | usb_get_dev(udev); | 957 | usb_get_dev(udev); |
@@ -982,24 +985,12 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, | |||
982 | goto error_out; | 985 | goto error_out; |
983 | } | 986 | } |
984 | 987 | ||
985 | /*init rfkill */ | ||
986 | /* rtl_init_rfkill(hw); */ | ||
987 | |||
988 | err = ieee80211_register_hw(hw); | ||
989 | if (err) { | ||
990 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, | ||
991 | "Can't register mac80211 hw\n"); | ||
992 | goto error_out; | ||
993 | } else { | ||
994 | rtlpriv->mac80211.mac80211_registered = 1; | ||
995 | } | ||
996 | set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); | ||
997 | return 0; | 988 | return 0; |
998 | error_out: | 989 | error_out: |
999 | rtl_deinit_core(hw); | 990 | rtl_deinit_core(hw); |
1000 | _rtl_usb_io_handler_release(hw); | 991 | _rtl_usb_io_handler_release(hw); |
1001 | ieee80211_free_hw(hw); | ||
1002 | usb_put_dev(udev); | 992 | usb_put_dev(udev); |
993 | complete(&rtlpriv->firmware_loading_complete); | ||
1003 | return -ENODEV; | 994 | return -ENODEV; |
1004 | } | 995 | } |
1005 | EXPORT_SYMBOL(rtl_usb_probe); | 996 | EXPORT_SYMBOL(rtl_usb_probe); |
@@ -1013,6 +1004,9 @@ void rtl_usb_disconnect(struct usb_interface *intf) | |||
1013 | 1004 | ||
1014 | if (unlikely(!rtlpriv)) | 1005 | if (unlikely(!rtlpriv)) |
1015 | return; | 1006 | return; |
1007 | |||
1008 | /* just in case driver is removed before firmware callback */ | ||
1009 | wait_for_completion(&rtlpriv->firmware_loading_complete); | ||
1016 | /*ieee80211_unregister_hw will call ops_stop */ | 1010 | /*ieee80211_unregister_hw will call ops_stop */ |
1017 | if (rtlmac->mac80211_registered == 1) { | 1011 | if (rtlmac->mac80211_registered == 1) { |
1018 | ieee80211_unregister_hw(hw); | 1012 | ieee80211_unregister_hw(hw); |