aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rtlwifi/rtl8192se
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2012-01-30 10:54:49 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-01-30 15:48:50 -0500
commitb0302aba812bcc39291cdab9ad7e37008f352a91 (patch)
tree82915b1e24f204babeb65e1d517115c0e31cfd9a /drivers/net/wireless/rtlwifi/rtl8192se
parentfeced2012e665468258a5c89b7f2a90b4e5695a4 (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/rtl8192se')
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/fw.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/hw.c16
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/led.c5
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/sw.c65
4 files changed, 65 insertions, 23 deletions
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
index 595ecd22ffa0..0d8bf5657008 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
@@ -364,7 +364,7 @@ int rtl92s_download_fw(struct ieee80211_hw *hw)
364 u8 fwstatus = FW_STATUS_INIT; 364 u8 fwstatus = FW_STATUS_INIT;
365 bool rtstatus = true; 365 bool rtstatus = true;
366 366
367 if (!rtlhal->pfirmware) 367 if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
368 return 1; 368 return 1;
369 369
370 firmware = (struct rt_firmware *)rtlhal->pfirmware; 370 firmware = (struct rt_firmware *)rtlhal->pfirmware;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index cbaf1f345c6e..22098c2f38f1 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -949,10 +949,9 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
949 rtstatus = rtl92s_download_fw(hw); 949 rtstatus = rtl92s_download_fw(hw);
950 if (!rtstatus) { 950 if (!rtstatus) {
951 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, 951 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
952 "Failed to download FW. Init HW without FW now... Please copy FW into /lib/firmware/rtlwifi\n"); 952 "Failed to download FW. Init HW without FW now... "
953 rtlhal->fw_ready = false; 953 "Please copy FW into /lib/firmware/rtlwifi\n");
954 } else { 954 return 1;
955 rtlhal->fw_ready = true;
956 } 955 }
957 956
958 /* After FW download, we have to reset MAC register */ 957 /* After FW download, we have to reset MAC register */
@@ -1215,9 +1214,14 @@ void rtl92se_enable_interrupt(struct ieee80211_hw *hw)
1215 1214
1216void rtl92se_disable_interrupt(struct ieee80211_hw *hw) 1215void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
1217{ 1216{
1218 struct rtl_priv *rtlpriv = rtl_priv(hw); 1217 struct rtl_priv *rtlpriv;
1219 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 1218 struct rtl_pci *rtlpci;
1220 1219
1220 rtlpriv = rtl_priv(hw);
1221 /* if firmware not available, no interrupts */
1222 if (!rtlpriv || !rtlpriv->max_fw_size)
1223 return;
1224 rtlpci = rtl_pcidev(rtl_pcipriv(hw));
1221 rtl_write_dword(rtlpriv, INTA_MASK, 0); 1225 rtl_write_dword(rtlpriv, INTA_MASK, 0);
1222 rtl_write_dword(rtlpriv, INTA_MASK + 4, 0); 1226 rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
1223 1227
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/rtlwifi/rtl8192se/led.c
index ef4211bca587..44949b5cbb87 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/led.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/led.c
@@ -76,10 +76,13 @@ void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
76 76
77void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) 77void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
78{ 78{
79 struct rtl_priv *rtlpriv = rtl_priv(hw); 79 struct rtl_priv *rtlpriv;
80 struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); 80 struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
81 u8 ledcfg; 81 u8 ledcfg;
82 82
83 rtlpriv = rtl_priv(hw);
84 if (!rtlpriv || rtlpriv->max_fw_size)
85 return;
83 RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n", 86 RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, "LedAddr:%X ledpin=%d\n",
84 LEDCFG, pled->ledpin); 87 LEDCFG, pled->ledpin);
85 88
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
index 0c47310b39b9..ca38dd9f3564 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
@@ -30,6 +30,8 @@
30#include "../wifi.h" 30#include "../wifi.h"
31#include "../core.h" 31#include "../core.h"
32#include "../pci.h" 32#include "../pci.h"
33#include "../base.h"
34#include "../pci.h"
33#include "reg.h" 35#include "reg.h"
34#include "def.h" 36#include "def.h"
35#include "phy.h" 37#include "phy.h"
@@ -86,12 +88,53 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw)
86 rtlpci->const_support_pciaspm = 2; 88 rtlpci->const_support_pciaspm = 2;
87} 89}
88 90
91static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
92{
93 struct ieee80211_hw *hw = context;
94 struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
95 struct rtl_priv *rtlpriv = rtl_priv(hw);
96 struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
97 struct rt_firmware *pfirmware = NULL;
98 int err;
99
100 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
101 "Firmware callback routine entered!\n");
102 complete(&rtlpriv->firmware_loading_complete);
103 if (!firmware) {
104 pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
105 rtlpriv->max_fw_size = 0;
106 return;
107 }
108 if (firmware->size > rtlpriv->max_fw_size) {
109 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
110 "Firmware is too big!\n");
111 release_firmware(firmware);
112 return;
113 }
114 pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware;
115 memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
116 pfirmware->sz_fw_tmpbufferlen = firmware->size;
117 release_firmware(firmware);
118
119 err = ieee80211_register_hw(hw);
120 if (err) {
121 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
122 "Can't register mac80211 hw\n");
123 return;
124 } else {
125 rtlpriv->mac80211.mac80211_registered = 1;
126 }
127 rtlpci->irq_alloc = 1;
128 set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
129
130 /*init rfkill */
131 rtl_init_rfkill(hw);
132}
133
89static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) 134static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
90{ 135{
91 struct rtl_priv *rtlpriv = rtl_priv(hw); 136 struct rtl_priv *rtlpriv = rtl_priv(hw);
92 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 137 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
93 const struct firmware *firmware;
94 struct rt_firmware *pfirmware = NULL;
95 int err = 0; 138 int err = 0;
96 u16 earlyrxthreshold = 7; 139 u16 earlyrxthreshold = 7;
97 140
@@ -189,27 +232,19 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
189 return 1; 232 return 1;
190 } 233 }
191 234
235 rtlpriv->max_fw_size = sizeof(struct rt_firmware);
236
192 pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n" 237 pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
193 "Loading firmware %s\n", rtlpriv->cfg->fw_name); 238 "Loading firmware %s\n", rtlpriv->cfg->fw_name);
194 /* request fw */ 239 /* request fw */
195 err = request_firmware(&firmware, rtlpriv->cfg->fw_name, 240 err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
196 rtlpriv->io.dev); 241 rtlpriv->io.dev, GFP_KERNEL, hw,
242 rtl92se_fw_cb);
197 if (err) { 243 if (err) {
198 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, 244 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
199 "Failed to request firmware!\n"); 245 "Failed to request firmware!\n");
200 return 1; 246 return 1;
201 } 247 }
202 if (firmware->size > sizeof(struct rt_firmware)) {
203 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
204 "Firmware is too big!\n");
205 release_firmware(firmware);
206 return 1;
207 }
208
209 pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware;
210 memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
211 pfirmware->sz_fw_tmpbufferlen = firmware->size;
212 release_firmware(firmware);
213 248
214 return err; 249 return err;
215} 250}