]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.2.6/rtlwifi-rtl8821ae-fix-system-lockups-on-boot.patch
Linux 4.14.114
[thirdparty/kernel/stable-queue.git] / releases / 4.2.6 / rtlwifi-rtl8821ae-fix-system-lockups-on-boot.patch
CommitLineData
f514fb28
GKH
1From 54328e64047a54b8fc2362c2e1f0fa16c90f739f Mon Sep 17 00:00:00 2001
2From: Larry Finger <Larry.Finger@lwfinger.net>
3Date: Fri, 2 Oct 2015 11:44:30 -0500
4Subject: rtlwifi: rtl8821ae: Fix system lockups on boot
5
6From: Larry Finger <Larry.Finger@lwfinger.net>
7
8commit 54328e64047a54b8fc2362c2e1f0fa16c90f739f upstream.
9
10In commit 1277fa2ab2f9 ("rtlwifi: Remove the clear interrupt routine from all
11drivers"), the code that cleared all interrupt enable bits before setting them
12was removed for all PCI drivers. This fixed an issue that caused TX to be
13blocked for 3-5 seconds. On some RTL8821AE units, this change causes soft
14lockups to occur on boot. For that reason, the portion of the earlier commit
15that applied to rtl8821ae is reverted. Kernels 4.1 and newer are affected.
16
17See http://marc.info/?l=linux-wireless&m=144373370103285&w=2 and
18https://bugzilla.opensuse.org/show_bug.cgi?id=944978 for two cases where
19this regression affected user systems. Note that this bug does not appear on
20any of the developer's setups. For those users whose systems are affected
21by the TX blockage, but do not lock up on boot, a module parameter is added
22to disable the interrupt clear
23
24Fixes: 1277fa2ab2f9 ("rtlwifi: Remove the clear interrupt routine from all drivers")
25Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
26Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
27Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
28
29---
30 drivers/net/wireless/rtlwifi/pci.h | 2 ++
31 drivers/net/wireless/rtlwifi/rtl8821ae/hw.c | 17 +++++++++++++++++
32 drivers/net/wireless/rtlwifi/rtl8821ae/sw.c | 5 +++++
33 drivers/net/wireless/rtlwifi/wifi.h | 3 +++
34 4 files changed, 27 insertions(+)
35
36--- a/drivers/net/wireless/rtlwifi/pci.h
37+++ b/drivers/net/wireless/rtlwifi/pci.h
38@@ -247,6 +247,8 @@ struct rtl_pci {
39 /* MSI support */
40 bool msi_support;
41 bool using_msi;
42+ /* interrupt clear before set */
43+ bool int_clear;
44 };
45
46 struct mp_adapter {
47--- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
48+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
49@@ -2253,11 +2253,28 @@ void rtl8821ae_set_qos(struct ieee80211_
50 }
51 }
52
53+static void rtl8821ae_clear_interrupt(struct ieee80211_hw *hw)
54+{
55+ struct rtl_priv *rtlpriv = rtl_priv(hw);
56+ u32 tmp = rtl_read_dword(rtlpriv, REG_HISR);
57+
58+ rtl_write_dword(rtlpriv, REG_HISR, tmp);
59+
60+ tmp = rtl_read_dword(rtlpriv, REG_HISRE);
61+ rtl_write_dword(rtlpriv, REG_HISRE, tmp);
62+
63+ tmp = rtl_read_dword(rtlpriv, REG_HSISR);
64+ rtl_write_dword(rtlpriv, REG_HSISR, tmp);
65+}
66+
67 void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw)
68 {
69 struct rtl_priv *rtlpriv = rtl_priv(hw);
70 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
71
72+ if (!rtlpci->int_clear)
73+ rtl8821ae_clear_interrupt(hw);/*clear it here first*/
74+
75 rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
76 rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
77 rtlpci->irq_enabled = true;
78--- a/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c
79+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/sw.c
80@@ -96,6 +96,7 @@ int rtl8821ae_init_sw_vars(struct ieee80
81
82 rtl8821ae_bt_reg_init(hw);
83 rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
84+ rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
85 rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
86
87 rtlpriv->dm.dm_initialgain_enable = 1;
88@@ -167,6 +168,7 @@ int rtl8821ae_init_sw_vars(struct ieee80
89 rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
90 rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
91 rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
92+ rtlpci->msi_support = rtlpriv->cfg->mod_params->int_clear;
93 if (rtlpriv->cfg->mod_params->disable_watchdog)
94 pr_info("watchdog disabled\n");
95 rtlpriv->psc.reg_fwctrl_lps = 3;
96@@ -308,6 +310,7 @@ static struct rtl_mod_params rtl8821ae_m
97 .swctrl_lps = false,
98 .fwctrl_lps = true,
99 .msi_support = true,
100+ .int_clear = true,
101 .debug = DBG_EMERG,
102 .disable_watchdog = 0,
103 };
104@@ -437,6 +440,7 @@ module_param_named(fwlps, rtl8821ae_mod_
105 module_param_named(msi, rtl8821ae_mod_params.msi_support, bool, 0444);
106 module_param_named(disable_watchdog, rtl8821ae_mod_params.disable_watchdog,
107 bool, 0444);
108+module_param_named(int_clear, rtl8821ae_mod_params.int_clear, bool, 0444);
109 MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
110 MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
111 MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
112@@ -444,6 +448,7 @@ MODULE_PARM_DESC(fwlps, "Set to 1 to use
113 MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 1)\n");
114 MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
115 MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n");
116+MODULE_PARM_DESC(int_clear, "Set to 1 to disable interrupt clear before set (default 0)\n");
117
118 static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
119
120--- a/drivers/net/wireless/rtlwifi/wifi.h
121+++ b/drivers/net/wireless/rtlwifi/wifi.h
122@@ -2234,6 +2234,9 @@ struct rtl_mod_params {
123
124 /* default 0: 1 means disable */
125 bool disable_watchdog;
126+
127+ /* default 0: 1 means do not disable interrupts */
128+ bool int_clear;
129 };
130
131 struct rtl_hal_usbint_cfg {