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/core.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/core.c')
-rw-r--r-- | drivers/net/wireless/rtlwifi/core.c | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 0ee01ab2e4f6..f231b9180436 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -31,8 +31,50 @@ | |||
31 | #include "core.h" | 31 | #include "core.h" |
32 | #include "cam.h" | 32 | #include "cam.h" |
33 | #include "base.h" | 33 | #include "base.h" |
34 | #include "pci.h" | ||
34 | #include "ps.h" | 35 | #include "ps.h" |
35 | 36 | ||
37 | #include <linux/export.h> | ||
38 | |||
39 | void rtl_fw_cb(const struct firmware *firmware, void *context) | ||
40 | { | ||
41 | struct ieee80211_hw *hw = context; | ||
42 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
43 | int err; | ||
44 | |||
45 | RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, | ||
46 | "Firmware callback routine entered!\n"); | ||
47 | complete(&rtlpriv->firmware_loading_complete); | ||
48 | if (!firmware) { | ||
49 | pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); | ||
50 | rtlpriv->max_fw_size = 0; | ||
51 | return; | ||
52 | } | ||
53 | if (firmware->size > rtlpriv->max_fw_size) { | ||
54 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
55 | "Firmware is too big!\n"); | ||
56 | release_firmware(firmware); | ||
57 | return; | ||
58 | } | ||
59 | memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); | ||
60 | rtlpriv->rtlhal.fwsize = firmware->size; | ||
61 | release_firmware(firmware); | ||
62 | |||
63 | err = ieee80211_register_hw(hw); | ||
64 | if (err) { | ||
65 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
66 | "Can't register mac80211 hw\n"); | ||
67 | return; | ||
68 | } else { | ||
69 | rtlpriv->mac80211.mac80211_registered = 1; | ||
70 | } | ||
71 | set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); | ||
72 | |||
73 | /*init rfkill */ | ||
74 | rtl_init_rfkill(hw); | ||
75 | } | ||
76 | EXPORT_SYMBOL(rtl_fw_cb); | ||
77 | |||
36 | /*mutex for start & stop is must here. */ | 78 | /*mutex for start & stop is must here. */ |
37 | static int rtl_op_start(struct ieee80211_hw *hw) | 79 | static int rtl_op_start(struct ieee80211_hw *hw) |
38 | { | 80 | { |
@@ -254,10 +296,12 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed) | |||
254 | * because that will cause nullfunc send by mac80211 | 296 | * because that will cause nullfunc send by mac80211 |
255 | * fail, and cause pkt loss, we have tested that 5mA | 297 | * fail, and cause pkt loss, we have tested that 5mA |
256 | * is worked very well */ | 298 | * is worked very well */ |
257 | if (!rtlpriv->psc.multi_buffered) | 299 | if (!rtlpriv->psc.multi_buffered) { |
258 | queue_delayed_work(rtlpriv->works.rtl_wq, | 300 | queue_delayed_work(rtlpriv->works.rtl_wq, |
259 | &rtlpriv->works.ps_work, | 301 | &rtlpriv->works.ps_work, |
260 | MSECS(5)); | 302 | MSECS(5)); |
303 | pr_info("In section\n"); | ||
304 | } | ||
261 | } else { | 305 | } else { |
262 | rtl_swlps_rf_awake(hw); | 306 | rtl_swlps_rf_awake(hw); |
263 | rtlpriv->psc.sw_ps_enabled = false; | 307 | rtlpriv->psc.sw_ps_enabled = false; |