summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLarry Finger <Larry.Finger@lwfinger.net>2013-02-02 15:55:00 -0600
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-02-14 10:48:50 -0800
commit5327297d3596654ca58e8a79ec38fa48c8f83fc0 (patch)
tree38069151fd580b9c1b0136fbdfd8e046d5d80ac9
parent5f2ffd29fe0438dfb683a8f0ca0e451408e36970 (diff)
rtlwifi: Fix scheduling while atomic bug
commit a5ffbe0a1993a27072742ef7db6cf9839956fce9 upstream. Kernel commits 41affd5 and 6539306 changed the locking in rtl_lps_leave() from a spinlock to a mutex by doing the calls indirectly from a work queue to reduce the time that interrupts were disabled. This change was fine for most systems; however a scheduling while atomic bug was reported in https://bugzilla.redhat.com/show_bug.cgi?id=903881. The backtrace indicates that routine rtl_is_special(), which calls rtl_lps_leave() in three places was entered in atomic context. These direct calls are replaced by putting a request on the appropriate work queue. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Reported-and-tested-by: Nathaniel Doherty <ntdoherty@gmail.com> Cc: Nathaniel Doherty <ntdoherty@gmail.com> Cc: Stanislaw Gruszka <sgruszka@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/wireless/rtlwifi/base.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index e54488db0e10..18d9eb3ad7af 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -980,7 +980,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
is_tx ? "Tx" : "Rx");
if (is_tx) {
- rtl_lps_leave(hw);
+ schedule_work(&rtlpriv->
+ works.lps_leave_work);
ppsc->last_delaylps_stamp_jiffies =
jiffies;
}
@@ -990,7 +991,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
}
} else if (ETH_P_ARP == ether_type) {
if (is_tx) {
- rtl_lps_leave(hw);
+ schedule_work(&rtlpriv->works.lps_leave_work);
ppsc->last_delaylps_stamp_jiffies = jiffies;
}
@@ -1000,7 +1001,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
"802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx");
if (is_tx) {
- rtl_lps_leave(hw);
+ schedule_work(&rtlpriv->works.lps_leave_work);
ppsc->last_delaylps_stamp_jiffies = jiffies;
}