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 | |
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')
20 files changed, 194 insertions, 164 deletions
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 7a95a544a9b1..df5655cc55c0 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
@@ -410,6 +410,7 @@ void rtl_init_rfkill(struct ieee80211_hw *hw) | |||
410 | 410 | ||
411 | wiphy_rfkill_start_polling(hw->wiphy); | 411 | wiphy_rfkill_start_polling(hw->wiphy); |
412 | } | 412 | } |
413 | EXPORT_SYMBOL(rtl_init_rfkill); | ||
413 | 414 | ||
414 | void rtl_deinit_rfkill(struct ieee80211_hw *hw) | 415 | void rtl_deinit_rfkill(struct ieee80211_hw *hw) |
415 | { | 416 | { |
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; |
diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h index 57569e0e3d47..2fe46a1b4f1f 100644 --- a/drivers/net/wireless/rtlwifi/core.h +++ b/drivers/net/wireless/rtlwifi/core.h | |||
@@ -40,4 +40,6 @@ | |||
40 | #define RTL_SUPPORTED_CTRL_FILTER 0xFF | 40 | #define RTL_SUPPORTED_CTRL_FILTER 0xFF |
41 | 41 | ||
42 | extern const struct ieee80211_ops rtl_ops; | 42 | extern const struct ieee80211_ops rtl_ops; |
43 | void rtl_fw_cb(const struct firmware *firmware, void *context); | ||
44 | |||
43 | #endif | 45 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index e4d1dcfe8299..5cb2199435d2 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -1565,6 +1565,9 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) | |||
1565 | 1565 | ||
1566 | rtlpci->driver_is_goingto_unload = true; | 1566 | rtlpci->driver_is_goingto_unload = true; |
1567 | rtlpriv->cfg->ops->hw_disable(hw); | 1567 | rtlpriv->cfg->ops->hw_disable(hw); |
1568 | /* some things are not needed if firmware not available */ | ||
1569 | if (!rtlpriv->max_fw_size) | ||
1570 | return; | ||
1568 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); | 1571 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); |
1569 | 1572 | ||
1570 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); | 1573 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); |
@@ -1779,6 +1782,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
1779 | rtlpriv = hw->priv; | 1782 | rtlpriv = hw->priv; |
1780 | pcipriv = (void *)rtlpriv->priv; | 1783 | pcipriv = (void *)rtlpriv->priv; |
1781 | pcipriv->dev.pdev = pdev; | 1784 | pcipriv->dev.pdev = pdev; |
1785 | init_completion(&rtlpriv->firmware_loading_complete); | ||
1782 | 1786 | ||
1783 | /* init cfg & intf_ops */ | 1787 | /* init cfg & intf_ops */ |
1784 | rtlpriv->rtlhal.interface = INTF_PCI; | 1788 | rtlpriv->rtlhal.interface = INTF_PCI; |
@@ -1799,7 +1803,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
1799 | err = pci_request_regions(pdev, KBUILD_MODNAME); | 1803 | err = pci_request_regions(pdev, KBUILD_MODNAME); |
1800 | if (err) { | 1804 | if (err) { |
1801 | RT_ASSERT(false, "Can't obtain PCI resources\n"); | 1805 | RT_ASSERT(false, "Can't obtain PCI resources\n"); |
1802 | return err; | 1806 | goto fail2; |
1803 | } | 1807 | } |
1804 | 1808 | ||
1805 | pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); | 1809 | pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); |
@@ -1862,15 +1866,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
1862 | goto fail3; | 1866 | goto fail3; |
1863 | } | 1867 | } |
1864 | 1868 | ||
1865 | err = ieee80211_register_hw(hw); | ||
1866 | if (err) { | ||
1867 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1868 | "Can't register mac80211 hw\n"); | ||
1869 | goto fail3; | ||
1870 | } else { | ||
1871 | rtlpriv->mac80211.mac80211_registered = 1; | ||
1872 | } | ||
1873 | |||
1874 | err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); | 1869 | err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); |
1875 | if (err) { | 1870 | if (err) { |
1876 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 1871 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
@@ -1878,9 +1873,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
1878 | goto fail3; | 1873 | goto fail3; |
1879 | } | 1874 | } |
1880 | 1875 | ||
1881 | /*init rfkill */ | ||
1882 | rtl_init_rfkill(hw); | ||
1883 | |||
1884 | rtlpci = rtl_pcidev(pcipriv); | 1876 | rtlpci = rtl_pcidev(pcipriv); |
1885 | err = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, | 1877 | err = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, |
1886 | IRQF_SHARED, KBUILD_MODNAME, hw); | 1878 | IRQF_SHARED, KBUILD_MODNAME, hw); |
@@ -1889,24 +1881,22 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
1889 | "%s: failed to register IRQ handler\n", | 1881 | "%s: failed to register IRQ handler\n", |
1890 | wiphy_name(hw->wiphy)); | 1882 | wiphy_name(hw->wiphy)); |
1891 | goto fail3; | 1883 | goto fail3; |
1892 | } else { | ||
1893 | rtlpci->irq_alloc = 1; | ||
1894 | } | 1884 | } |
1885 | rtlpci->irq_alloc = 1; | ||
1895 | 1886 | ||
1896 | set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); | ||
1897 | return 0; | 1887 | return 0; |
1898 | 1888 | ||
1899 | fail3: | 1889 | fail3: |
1900 | pci_set_drvdata(pdev, NULL); | 1890 | pci_set_drvdata(pdev, NULL); |
1901 | rtl_deinit_core(hw); | 1891 | rtl_deinit_core(hw); |
1902 | _rtl_pci_io_handler_release(hw); | 1892 | _rtl_pci_io_handler_release(hw); |
1903 | ieee80211_free_hw(hw); | ||
1904 | 1893 | ||
1905 | if (rtlpriv->io.pci_mem_start != 0) | 1894 | if (rtlpriv->io.pci_mem_start != 0) |
1906 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); | 1895 | pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); |
1907 | 1896 | ||
1908 | fail2: | 1897 | fail2: |
1909 | pci_release_regions(pdev); | 1898 | pci_release_regions(pdev); |
1899 | complete(&rtlpriv->firmware_loading_complete); | ||
1910 | 1900 | ||
1911 | fail1: | 1901 | fail1: |
1912 | 1902 | ||
@@ -1925,6 +1915,8 @@ void rtl_pci_disconnect(struct pci_dev *pdev) | |||
1925 | struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); | 1915 | struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); |
1926 | struct rtl_mac *rtlmac = rtl_mac(rtlpriv); | 1916 | struct rtl_mac *rtlmac = rtl_mac(rtlpriv); |
1927 | 1917 | ||
1918 | /* just in case driver is removed before firmware callback */ | ||
1919 | wait_for_completion(&rtlpriv->firmware_loading_complete); | ||
1928 | clear_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); | 1920 | clear_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); |
1929 | 1921 | ||
1930 | sysfs_remove_group(&pdev->dev.kobj, &rtl_attribute_group); | 1922 | sysfs_remove_group(&pdev->dev.kobj, &rtl_attribute_group); |
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index 99d81ede17b8..241448fc9ed5 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h | |||
@@ -239,7 +239,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, | |||
239 | void rtl_pci_disconnect(struct pci_dev *pdev); | 239 | void rtl_pci_disconnect(struct pci_dev *pdev); |
240 | int rtl_pci_suspend(struct device *dev); | 240 | int rtl_pci_suspend(struct device *dev); |
241 | int rtl_pci_resume(struct device *dev); | 241 | int rtl_pci_resume(struct device *dev); |
242 | |||
243 | static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr) | 242 | static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr) |
244 | { | 243 | { |
245 | return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); | 244 | return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); |
diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index b151266ef9f6..15f86eaa1cd6 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c | |||
@@ -47,7 +47,8 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) | |||
47 | "Driver is already down!\n"); | 47 | "Driver is already down!\n"); |
48 | 48 | ||
49 | /*<2> Enable Adapter */ | 49 | /*<2> Enable Adapter */ |
50 | rtlpriv->cfg->ops->hw_init(hw); | 50 | if (rtlpriv->cfg->ops->hw_init(hw)) |
51 | return 1; | ||
51 | RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | 52 | RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); |
52 | 53 | ||
53 | /*<3> Enable Interrupt */ | 54 | /*<3> Enable Interrupt */ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index 82bbc8384aca..c20b3c30f62e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | |||
@@ -257,10 +257,9 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) | |||
257 | u32 fwsize; | 257 | u32 fwsize; |
258 | enum version_8192c version = rtlhal->version; | 258 | enum version_8192c version = rtlhal->version; |
259 | 259 | ||
260 | if (!rtlhal->pfirmware) | 260 | if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) |
261 | return 1; | 261 | return 1; |
262 | 262 | ||
263 | pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); | ||
264 | pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; | 263 | pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; |
265 | pfwdata = (u8 *) rtlhal->pfirmware; | 264 | pfwdata = (u8 *) rtlhal->pfirmware; |
266 | fwsize = rtlhal->fwsize; | 265 | fwsize = rtlhal->fwsize; |
@@ -512,15 +511,8 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, | |||
512 | void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, | 511 | void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, |
513 | u8 element_id, u32 cmd_len, u8 *p_cmdbuffer) | 512 | u8 element_id, u32 cmd_len, u8 *p_cmdbuffer) |
514 | { | 513 | { |
515 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
516 | u32 tmp_cmdbuf[2]; | 514 | u32 tmp_cmdbuf[2]; |
517 | 515 | ||
518 | if (rtlhal->fw_ready == false) { | ||
519 | RT_ASSERT(false, | ||
520 | "return H2C cmd because of Fw download fail!!!\n"); | ||
521 | return; | ||
522 | } | ||
523 | |||
524 | memset(tmp_cmdbuf, 0, 8); | 516 | memset(tmp_cmdbuf, 0, 8); |
525 | memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len); | 517 | memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len); |
526 | _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); | 518 | _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index c5aced459cd0..48c7b5d3fc5b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | |||
@@ -917,10 +917,7 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) | |||
917 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | 917 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, |
918 | "Failed to download FW. Init HW without FW now..\n"); | 918 | "Failed to download FW. Init HW without FW now..\n"); |
919 | err = 1; | 919 | err = 1; |
920 | rtlhal->fw_ready = false; | ||
921 | return err; | 920 | return err; |
922 | } else { | ||
923 | rtlhal->fw_ready = true; | ||
924 | } | 921 | } |
925 | 922 | ||
926 | rtlhal->last_hmeboxnum = 0; | 923 | rtlhal->last_hmeboxnum = 0; |
@@ -1193,7 +1190,6 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) | |||
1193 | { | 1190 | { |
1194 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1191 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1195 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); | 1192 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); |
1196 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1197 | u8 u1b_tmp; | 1193 | u8 u1b_tmp; |
1198 | u32 u4b_tmp; | 1194 | u32 u4b_tmp; |
1199 | 1195 | ||
@@ -1204,7 +1200,7 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) | |||
1204 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); | 1200 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); |
1205 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | 1201 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); |
1206 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0); | 1202 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0); |
1207 | if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready) | 1203 | if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) |
1208 | rtl92c_firmware_selfreset(hw); | 1204 | rtl92c_firmware_selfreset(hw); |
1209 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51); | 1205 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51); |
1210 | rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); | 1206 | rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 460dc925b4e4..2c3b73366cd2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | |||
@@ -91,9 +91,7 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) | |||
91 | int err; | 91 | int err; |
92 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 92 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
93 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 93 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
94 | const struct firmware *firmware; | ||
95 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | 94 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
96 | char *fw_name = NULL; | ||
97 | 95 | ||
98 | rtl8192ce_bt_reg_init(hw); | 96 | rtl8192ce_bt_reg_init(hw); |
99 | 97 | ||
@@ -165,26 +163,20 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) | |||
165 | /* request fw */ | 163 | /* request fw */ |
166 | if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && | 164 | if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && |
167 | !IS_92C_SERIAL(rtlhal->version)) | 165 | !IS_92C_SERIAL(rtlhal->version)) |
168 | fw_name = "rtlwifi/rtl8192cfwU.bin"; | 166 | rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; |
169 | else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) | 167 | else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) |
170 | fw_name = "rtlwifi/rtl8192cfwU_B.bin"; | 168 | rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; |
171 | else | 169 | |
172 | fw_name = rtlpriv->cfg->fw_name; | 170 | rtlpriv->max_fw_size = 0x4000; |
173 | err = request_firmware(&firmware, fw_name, rtlpriv->io.dev); | 171 | pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); |
172 | err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, | ||
173 | rtlpriv->io.dev, GFP_KERNEL, hw, | ||
174 | rtl_fw_cb); | ||
174 | if (err) { | 175 | if (err) { |
175 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 176 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
176 | "Failed to request firmware!\n"); | 177 | "Failed to request firmware!\n"); |
177 | return 1; | 178 | return 1; |
178 | } | 179 | } |
179 | if (firmware->size > 0x4000) { | ||
180 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
181 | "Firmware is too big!\n"); | ||
182 | release_firmware(firmware); | ||
183 | return 1; | ||
184 | } | ||
185 | memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); | ||
186 | rtlpriv->rtlhal.fwsize = firmware->size; | ||
187 | release_firmware(firmware); | ||
188 | 180 | ||
189 | return 0; | 181 | return 0; |
190 | } | 182 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 7f171682d3d6..0c74d4f2eeb4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
@@ -997,10 +997,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) | |||
997 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | 997 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, |
998 | "Failed to download FW. Init HW without FW now..\n"); | 998 | "Failed to download FW. Init HW without FW now..\n"); |
999 | err = 1; | 999 | err = 1; |
1000 | rtlhal->fw_ready = false; | ||
1001 | return err; | 1000 | return err; |
1002 | } else { | ||
1003 | rtlhal->fw_ready = true; | ||
1004 | } | 1001 | } |
1005 | rtlhal->last_hmeboxnum = 0; /* h2c */ | 1002 | rtlhal->last_hmeboxnum = 0; /* h2c */ |
1006 | _rtl92cu_phy_param_tab_init(hw); | 1003 | _rtl92cu_phy_param_tab_init(hw); |
@@ -1094,23 +1091,21 @@ static void _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM) | |||
1094 | if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(1)) { | 1091 | if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(1)) { |
1095 | /* reset MCU ready status */ | 1092 | /* reset MCU ready status */ |
1096 | rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); | 1093 | rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); |
1097 | if (rtlhal->fw_ready) { | 1094 | /* 8051 reset by self */ |
1098 | /* 8051 reset by self */ | 1095 | rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20); |
1099 | rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20); | 1096 | while ((retry_cnts++ < 100) && |
1100 | while ((retry_cnts++ < 100) && | 1097 | (FEN_CPUEN & rtl_read_word(rtlpriv, |
1101 | (FEN_CPUEN & rtl_read_word(rtlpriv, | 1098 | REG_SYS_FUNC_EN))) { |
1102 | REG_SYS_FUNC_EN))) { | 1099 | udelay(50); |
1103 | udelay(50); | 1100 | } |
1104 | } | 1101 | if (retry_cnts >= 100) { |
1105 | if (retry_cnts >= 100) { | 1102 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
1106 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 1103 | "#####=> 8051 reset failed!.........................\n"); |
1107 | "#####=> 8051 reset failed!.........................\n"); | 1104 | /* if 8051 reset fail, reset MAC. */ |
1108 | /* if 8051 reset fail, reset MAC. */ | 1105 | rtl_write_byte(rtlpriv, |
1109 | rtl_write_byte(rtlpriv, | 1106 | REG_SYS_FUNC_EN + 1, |
1110 | REG_SYS_FUNC_EN + 1, | 1107 | 0x50); |
1111 | 0x50); | 1108 | udelay(100); |
1112 | udelay(100); | ||
1113 | } | ||
1114 | } | 1109 | } |
1115 | } | 1110 | } |
1116 | /* Reset MAC and Enable 8051 */ | 1111 | /* Reset MAC and Enable 8051 */ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index c04c3be5bd4e..82c85286ab2e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | |||
@@ -53,7 +53,6 @@ MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); | |||
53 | static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) | 53 | static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) |
54 | { | 54 | { |
55 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 55 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
56 | const struct firmware *firmware; | ||
57 | int err; | 56 | int err; |
58 | 57 | ||
59 | rtlpriv->dm.dm_initialgain_enable = true; | 58 | rtlpriv->dm.dm_initialgain_enable = true; |
@@ -61,29 +60,21 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) | |||
61 | rtlpriv->dm.disable_framebursting = false; | 60 | rtlpriv->dm.disable_framebursting = false; |
62 | rtlpriv->dm.thermalvalue = 0; | 61 | rtlpriv->dm.thermalvalue = 0; |
63 | rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; | 62 | rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; |
64 | rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); | 63 | |
64 | /* for firmware buf */ | ||
65 | rtlpriv->rtlhal.pfirmware = vzalloc(0x4000); | ||
65 | if (!rtlpriv->rtlhal.pfirmware) { | 66 | if (!rtlpriv->rtlhal.pfirmware) { |
66 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 67 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
67 | "Can't alloc buffer for fw\n"); | 68 | "Can't alloc buffer for fw\n"); |
68 | return 1; | 69 | return 1; |
69 | } | 70 | } |
70 | /* request fw */ | 71 | |
71 | err = request_firmware(&firmware, rtlpriv->cfg->fw_name, | 72 | pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name); |
72 | rtlpriv->io.dev); | 73 | rtlpriv->max_fw_size = 0x4000; |
73 | if (err) { | 74 | err = request_firmware_nowait(THIS_MODULE, 1, |
74 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 75 | rtlpriv->cfg->fw_name, rtlpriv->io.dev, |
75 | "Failed to request firmware!\n"); | 76 | GFP_KERNEL, hw, rtl_fw_cb); |
76 | return 1; | 77 | |
77 | } | ||
78 | if (firmware->size > 0x4000) { | ||
79 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
80 | "Firmware is too big!\n"); | ||
81 | release_firmware(firmware); | ||
82 | return 1; | ||
83 | } | ||
84 | memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); | ||
85 | rtlpriv->rtlhal.fwsize = firmware->size; | ||
86 | release_firmware(firmware); | ||
87 | 78 | ||
88 | return 0; | 79 | return 0; |
89 | } | 80 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c index b59de75a3643..f548a8d0068d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c | |||
@@ -253,7 +253,7 @@ int rtl92d_download_fw(struct ieee80211_hw *hw) | |||
253 | bool fw_downloaded = false, fwdl_in_process = false; | 253 | bool fw_downloaded = false, fwdl_in_process = false; |
254 | unsigned long flags; | 254 | unsigned long flags; |
255 | 255 | ||
256 | if (!rtlhal->pfirmware) | 256 | if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) |
257 | return 1; | 257 | return 1; |
258 | fwsize = rtlhal->fwsize; | 258 | fwsize = rtlhal->fwsize; |
259 | pfwheader = (u8 *) rtlhal->pfirmware; | 259 | pfwheader = (u8 *) rtlhal->pfirmware; |
@@ -532,14 +532,8 @@ static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw, | |||
532 | void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, | 532 | void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, |
533 | u8 element_id, u32 cmd_len, u8 *cmdbuffer) | 533 | u8 element_id, u32 cmd_len, u8 *cmdbuffer) |
534 | { | 534 | { |
535 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
536 | u32 tmp_cmdbuf[2]; | 535 | u32 tmp_cmdbuf[2]; |
537 | 536 | ||
538 | if (rtlhal->fw_ready == false) { | ||
539 | RT_ASSERT(false, | ||
540 | "return H2C cmd because of Fw download fail!!!\n"); | ||
541 | return; | ||
542 | } | ||
543 | memset(tmp_cmdbuf, 0, 8); | 537 | memset(tmp_cmdbuf, 0, 8); |
544 | memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); | 538 | memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); |
545 | _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); | 539 | _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c index 695bccb43750..7d877125db29 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c | |||
@@ -931,10 +931,7 @@ int rtl92de_hw_init(struct ieee80211_hw *hw) | |||
931 | if (err) { | 931 | if (err) { |
932 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | 932 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, |
933 | "Failed to download FW. Init HW without FW..\n"); | 933 | "Failed to download FW. Init HW without FW..\n"); |
934 | rtlhal->fw_ready = false; | ||
935 | return 1; | 934 | return 1; |
936 | } else { | ||
937 | rtlhal->fw_ready = true; | ||
938 | } | 935 | } |
939 | rtlhal->last_hmeboxnum = 0; | 936 | rtlhal->last_hmeboxnum = 0; |
940 | rtlpriv->psc.fw_current_inpsmode = false; | 937 | rtlpriv->psc.fw_current_inpsmode = false; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index bf625f9e632e..4898c502974d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c | |||
@@ -91,7 +91,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) | |||
91 | u8 tid; | 91 | u8 tid; |
92 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 92 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
93 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 93 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
94 | const struct firmware *firmware; | ||
95 | static int header_print; | 94 | static int header_print; |
96 | 95 | ||
97 | rtlpriv->dm.dm_initialgain_enable = true; | 96 | rtlpriv->dm.dm_initialgain_enable = true; |
@@ -167,6 +166,15 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) | |||
167 | else if (rtlpriv->psc.reg_fwctrl_lps == 3) | 166 | else if (rtlpriv->psc.reg_fwctrl_lps == 3) |
168 | rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; | 167 | rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; |
169 | 168 | ||
169 | /* for early mode */ | ||
170 | rtlpriv->rtlhal.earlymode_enable = true; | ||
171 | for (tid = 0; tid < 8; tid++) | ||
172 | skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); | ||
173 | |||
174 | /* Only load firmware for first MAC */ | ||
175 | if (header_print) | ||
176 | return 0; | ||
177 | |||
170 | /* for firmware buf */ | 178 | /* for firmware buf */ |
171 | rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); | 179 | rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); |
172 | if (!rtlpriv->rtlhal.pfirmware) { | 180 | if (!rtlpriv->rtlhal.pfirmware) { |
@@ -175,33 +183,21 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) | |||
175 | return 1; | 183 | return 1; |
176 | } | 184 | } |
177 | 185 | ||
178 | if (!header_print) { | 186 | rtlpriv->max_fw_size = 0x8000; |
179 | pr_info("Driver for Realtek RTL8192DE WLAN interface\n"); | 187 | pr_info("Driver for Realtek RTL8192DE WLAN interface\n"); |
180 | pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); | 188 | pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); |
181 | header_print++; | 189 | header_print++; |
182 | } | 190 | |
183 | /* request fw */ | 191 | /* request fw */ |
184 | err = request_firmware(&firmware, rtlpriv->cfg->fw_name, | 192 | err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, |
185 | rtlpriv->io.dev); | 193 | rtlpriv->io.dev, GFP_KERNEL, hw, |
194 | rtl_fw_cb); | ||
186 | if (err) { | 195 | if (err) { |
187 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 196 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
188 | "Failed to request firmware!\n"); | 197 | "Failed to request firmware!\n"); |
189 | return 1; | 198 | return 1; |
190 | } | 199 | } |
191 | if (firmware->size > 0x8000) { | ||
192 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
193 | "Firmware is too big!\n"); | ||
194 | release_firmware(firmware); | ||
195 | return 1; | ||
196 | } | ||
197 | memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); | ||
198 | rtlpriv->rtlhal.fwsize = firmware->size; | ||
199 | release_firmware(firmware); | ||
200 | 200 | ||
201 | /* for early mode */ | ||
202 | rtlpriv->rtlhal.earlymode_enable = true; | ||
203 | for (tid = 0; tid < 8; tid++) | ||
204 | skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); | ||
205 | return 0; | 201 | return 0; |
206 | } | 202 | } |
207 | 203 | ||
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 | ||
1216 | void rtl92se_disable_interrupt(struct ieee80211_hw *hw) | 1215 | void 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 | ||
77 | void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) | 77 | void 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 | ||
91 | static 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 | |||
89 | static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) | 134 | static 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 | } |
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); |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 1e5fffb2db0b..b591614c3b9b 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/vmalloc.h> | 38 | #include <linux/vmalloc.h> |
39 | #include <linux/usb.h> | 39 | #include <linux/usb.h> |
40 | #include <net/mac80211.h> | 40 | #include <net/mac80211.h> |
41 | #include <linux/completion.h> | ||
41 | #include "debug.h" | 42 | #include "debug.h" |
42 | 43 | ||
43 | #define RF_CHANGE_BY_INIT 0 | 44 | #define RF_CHANGE_BY_INIT 0 |
@@ -1047,7 +1048,6 @@ struct rtl_hal { | |||
1047 | u16 fw_subversion; | 1048 | u16 fw_subversion; |
1048 | bool h2c_setinprogress; | 1049 | bool h2c_setinprogress; |
1049 | u8 last_hmeboxnum; | 1050 | u8 last_hmeboxnum; |
1050 | bool fw_ready; | ||
1051 | /*Reserve page start offset except beacon in TxQ. */ | 1051 | /*Reserve page start offset except beacon in TxQ. */ |
1052 | u8 fw_rsvdpage_startoffset; | 1052 | u8 fw_rsvdpage_startoffset; |
1053 | u8 h2c_txcmd_seq; | 1053 | u8 h2c_txcmd_seq; |
@@ -1593,6 +1593,7 @@ struct rtl_debug { | |||
1593 | }; | 1593 | }; |
1594 | 1594 | ||
1595 | struct rtl_priv { | 1595 | struct rtl_priv { |
1596 | struct completion firmware_loading_complete; | ||
1596 | struct rtl_locks locks; | 1597 | struct rtl_locks locks; |
1597 | struct rtl_works works; | 1598 | struct rtl_works works; |
1598 | struct rtl_mac mac80211; | 1599 | struct rtl_mac mac80211; |
@@ -1614,6 +1615,7 @@ struct rtl_priv { | |||
1614 | struct rtl_rate_priv *rate_priv; | 1615 | struct rtl_rate_priv *rate_priv; |
1615 | 1616 | ||
1616 | struct rtl_debug dbg; | 1617 | struct rtl_debug dbg; |
1618 | int max_fw_size; | ||
1617 | 1619 | ||
1618 | /* | 1620 | /* |
1619 | *hal_cfg : for diff cards | 1621 | *hal_cfg : for diff cards |