diff --git a/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch new file mode 100644 index 000000000..7a3792c25 --- /dev/null +++ b/compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch @@ -0,0 +1,131 @@ +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +@@ -265,7 +265,6 @@ int rtl92c_download_fw(struct ieee80211_ + if (!rtlhal->pfirmware) + return 1; + +- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); + pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; + pfwdata = (u8 *) rtlhal->pfirmware; + fwsize = rtlhal->fwsize; +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211 + memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); + rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); ++ pr_info("rtl8192ce: Loaded firmware file %s\n", rtlpriv->cfg->fw_name); + + return 0; + } +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -43,6 +43,8 @@ + #include "hw.h" + #include + #include ++#include ++#include + + MODULE_AUTHOR("Georgia "); + MODULE_AUTHOR("Ziv Huang "); +@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); + MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); + ++static char *rtl8192cu_firmware; /* pointer to firmware */ ++static int firmware_size; ++static atomic_t usage_count; ++ + static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) + { + struct rtl_priv *rtlpriv = rtl_priv(hw); +@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i + rtlpriv->dm.disable_framebursting = false; + rtlpriv->dm.thermalvalue = 0; + rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; +- rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); +- if (!rtlpriv->rtlhal.pfirmware) { ++ ++ if (rtl8192cu_firmware) { ++ /* firmware already loaded - true for suspend/resume ++ * and multiple instances of the device */ ++ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; ++ rtlpriv->rtlhal.fwsize = firmware_size; ++ return 0; ++ } ++ rtl8192cu_firmware = vzalloc(0x4000); ++ if (!rtl8192cu_firmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't alloc buffer for fw.\n")); + return 1; + } ++ + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); +@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i + release_firmware(firmware); + return 1; + } +- memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); ++ pr_info("rtl8192cu: Loaded firmware from file %s\n", ++ rtlpriv->cfg->fw_name); ++ memcpy(rtl8192cu_firmware, firmware->data, firmware->size); ++ firmware_size = firmware->size; + rtlpriv->rtlhal.fwsize = firmware->size; ++ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; + release_firmware(firmware); ++ atomic_inc(&usage_count); + + return 0; + } +@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc + { + struct rtl_priv *rtlpriv = rtl_priv(hw); + +- if (rtlpriv->rtlhal.pfirmware) { +- vfree(rtlpriv->rtlhal.pfirmware); ++ atomic_dec(&usage_count); ++ if (!atomic_read(&usage_count) && rtlpriv->rtlhal.pfirmware) { ++ vfree(rtl8192cu_firmware); ++ rtl8192cu_firmware = NULL; + rtlpriv->rtlhal.pfirmware = NULL; + } + } + ++#ifdef CONFIG_PM_SLEEP ++static int rtl8192cu_usb_suspend(struct usb_interface *pusb_intf, ++ pm_message_t message) ++{ ++ /* Increase usage_count to Save loaded fw across suspend/resume */ ++ atomic_inc(&usage_count); ++ return 0; ++} ++ ++static int rtl8192cu_usb_resume(struct usb_interface *pusb_intf) ++{ ++ atomic_dec(&usage_count); /* after resume, decrease usage count */ ++ return 0; ++} ++#endif ++ + static struct rtl_hal_ops rtl8192cu_hal_ops = { + .init_sw_vars = rtl92cu_init_sw_vars, + .deinit_sw_vars = rtl92cu_deinit_sw_vars, +@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive + .disconnect = rtl_usb_disconnect, + .id_table = rtl8192c_usb_ids, + +-#ifdef CONFIG_PM +- /* .suspend = rtl_usb_suspend, */ +- /* .resume = rtl_usb_resume, */ +- /* .reset_resume = rtl8192c_resume, */ +-#endif /* CONFIG_PM */ ++#ifdef CONFIG_PM_SLEEP ++ .suspend = rtl8192cu_usb_suspend, ++ .resume = rtl8192cu_usb_resume, ++#endif /* CONFIG_PM_SLEEP */ + #ifdef CONFIG_AUTOSUSPEND + .supports_autosuspend = 1, + #endif diff --git a/kernel.spec b/kernel.spec index 4dc251b6e..84b8e98e7 100644 --- a/kernel.spec +++ b/kernel.spec @@ -54,7 +54,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 2 +%global baserelease 3 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -761,10 +761,14 @@ Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch Patch21073: KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch Patch21074: KVM-x86-fix-missing-checks-in-syscall-emulation.patch +#rhbz 728740 +Patch21076: rtl8192cu-Fix-WARNING-on-suspend-resume.patch + # compat-wireless patches Patch50000: compat-wireless-config-fixups.patch Patch50001: compat-wireless-pr_fmt-warning-avoidance.patch Patch50002: compat-wireless-integrated-build.patch +Patch50003: compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch %endif @@ -1475,6 +1479,9 @@ ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch ApplyPatch KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch +#rhbz 728740 +ApplyPatch rtl8192cu-Fix-WARNING-on-suspend-resume.patch + # END OF PATCH APPLICATIONS %endif @@ -1540,6 +1547,7 @@ cd compat-wireless-%{cwversion} ApplyPatch compat-wireless-config-fixups.patch ApplyPatch compat-wireless-pr_fmt-warning-avoidance.patch ApplyPatch compat-wireless-integrated-build.patch +ApplyPatch compat-wireless-rtl8192cu-Fix-WARNING-on-suspend-resume.patch cd .. @@ -2309,6 +2317,9 @@ fi # ||----w | # || || %changelog +* Fri Jan 13 2012 Josh Boyer +- Fix verbose logging messages in the rtl8192cu driver (rhbz 728740) + * Fri Jan 13 2012 Josh Boyer 3.2.1-2 - CVE-2012-0045 kvm: syscall instruction induced guest panic (rhbz 773392) diff --git a/rtl8192cu-Fix-WARNING-on-suspend-resume.patch b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch new file mode 100644 index 000000000..bdc8a5492 --- /dev/null +++ b/rtl8192cu-Fix-WARNING-on-suspend-resume.patch @@ -0,0 +1,163 @@ +A recent LKML thread (http://lkml.indiana.edu/hypermail/linux/kernel/1112.3/00965.html) +discusses warnings that occur during a suspend/resume cycle. The driver +attempts to read the firmware file before userspace is ready, leading to the +following warning: + +WARNING: at drivers/base/firmware_class.c:537 _request_firmware+0x3f6/0x420() + +For rtl8192cu, the problem is fixed by storing the firmware in a global buffer +rather than one allocated per device. The usage count is increased when +suspending and decreased when resuming. This way, the firmware is retained +through a suspend/resume cycle, and does not have to be reread. + +This patch should fix the bug reported in +https://bugzilla.redhat.com/show_bug.cgi?id=771002. + +Note: This patch also touches rtl8192ce as the "firmware" loaded message +is now printed in the wrong place. +Note: This patch also touches rtl8192ce as the "firmware" loaded message +is now printed in the wrong place. + +Reported-by: Mohammed Arafa +Reported-by: Dave Jones +Signed-off-by: Larry Finger +Cc: Linus Torvalds +Cc: Stable + +--- + drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | 1 - + drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 1 + + drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 58 +++++++++++++++++---- + 3 files changed, 49 insertions(+), 11 deletions(-) + +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:07:58.830625006 -0500 ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c 2012-01-13 13:08:06.825439927 -0500 +@@ -227,7 +227,6 @@ int rtl92c_download_fw(struct ieee80211_ + u32 fwsize; + enum version_8192c version = rtlhal->version; + +- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); + if (!rtlhal->pfirmware) + return 1; + +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +@@ -186,6 +186,7 @@ int rtl92c_init_sw_vars(struct ieee80211 + memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); + rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); ++ pr_info("rtl8192ce: Loaded firmware file %s\n", rtlpriv->cfg->fw_name); + + return 0; + } +--- linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ linux-2.6/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -43,6 +43,8 @@ + #include "hw.h" + #include + #include ++#include ++#include + + MODULE_AUTHOR("Georgia "); + MODULE_AUTHOR("Ziv Huang "); +@@ -51,6 +53,10 @@ MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless"); + MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); + ++static char *rtl8192cu_firmware; /* pointer to firmware */ ++static int firmware_size; ++static atomic_t usage_count; ++ + static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) + { + struct rtl_priv *rtlpriv = rtl_priv(hw); +@@ -62,12 +68,21 @@ static int rtl92cu_init_sw_vars(struct i + rtlpriv->dm.disable_framebursting = false; + rtlpriv->dm.thermalvalue = 0; + rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; +- rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); +- if (!rtlpriv->rtlhal.pfirmware) { ++ ++ if (rtl8192cu_firmware) { ++ /* firmware already loaded - true for suspend/resume ++ * and multiple instances of the device */ ++ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; ++ rtlpriv->rtlhal.fwsize = firmware_size; ++ return 0; ++ } ++ rtl8192cu_firmware = vzalloc(0x4000); ++ if (!rtl8192cu_firmware) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't alloc buffer for fw.\n")); + return 1; + } ++ + /* request fw */ + err = request_firmware(&firmware, rtlpriv->cfg->fw_name, + rtlpriv->io.dev); +@@ -82,9 +97,14 @@ static int rtl92cu_init_sw_vars(struct i + release_firmware(firmware); + return 1; + } +- memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); ++ pr_info("rtl8192cu: Loaded firmware from file %s\n", ++ rtlpriv->cfg->fw_name); ++ memcpy(rtl8192cu_firmware, firmware->data, firmware->size); ++ firmware_size = firmware->size; + rtlpriv->rtlhal.fwsize = firmware->size; ++ rtlpriv->rtlhal.pfirmware = rtl8192cu_firmware; + release_firmware(firmware); ++ atomic_inc(&usage_count); + + return 0; + } +@@ -93,12 +113,30 @@ static void rtl92cu_deinit_sw_vars(struc + { + struct rtl_priv *rtlpriv = rtl_priv(hw); + +- if (rtlpriv->rtlhal.pfirmware) { +- vfree(rtlpriv->rtlhal.pfirmware); ++ atomic_dec(&usage_count); ++ if (!atomic_read(&usage_count) && rtlpriv->rtlhal.pfirmware) { ++ vfree(rtl8192cu_firmware); ++ rtl8192cu_firmware = NULL; + rtlpriv->rtlhal.pfirmware = NULL; + } + } + ++#ifdef CONFIG_PM_SLEEP ++static int rtl8192cu_usb_suspend(struct usb_interface *pusb_intf, ++ pm_message_t message) ++{ ++ /* Increase usage_count to Save loaded fw across suspend/resume */ ++ atomic_inc(&usage_count); ++ return 0; ++} ++ ++static int rtl8192cu_usb_resume(struct usb_interface *pusb_intf) ++{ ++ atomic_dec(&usage_count); /* after resume, decrease usage count */ ++ return 0; ++} ++#endif ++ + static struct rtl_hal_ops rtl8192cu_hal_ops = { + .init_sw_vars = rtl92cu_init_sw_vars, + .deinit_sw_vars = rtl92cu_deinit_sw_vars, +@@ -374,11 +412,10 @@ static struct usb_driver rtl8192cu_drive + .disconnect = rtl_usb_disconnect, + .id_table = rtl8192c_usb_ids, + +-#ifdef CONFIG_PM +- /* .suspend = rtl_usb_suspend, */ +- /* .resume = rtl_usb_resume, */ +- /* .reset_resume = rtl8192c_resume, */ +-#endif /* CONFIG_PM */ ++#ifdef CONFIG_PM_SLEEP ++ .suspend = rtl8192cu_usb_suspend, ++ .resume = rtl8192cu_usb_resume, ++#endif /* CONFIG_PM_SLEEP */ + #ifdef CONFIG_AUTOSUSPEND + .supports_autosuspend = 1, + #endif