From: Greg Kroah-Hartman Date: Tue, 11 Feb 2014 18:07:05 +0000 (-0800) Subject: 3.10-stable patches X-Git-Tag: v3.4.80~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ef42141088ca724f5b298af210d5353d9ab77d3e;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: rtc-cmos-add-an-alarm-disable-quirk.patch timekeeping-avoid-possible-deadlock-from-clock_was_set_delayed.patch --- diff --git a/queue-3.10/rtc-cmos-add-an-alarm-disable-quirk.patch b/queue-3.10/rtc-cmos-add-an-alarm-disable-quirk.patch new file mode 100644 index 00000000000..421c863a51e --- /dev/null +++ b/queue-3.10/rtc-cmos-add-an-alarm-disable-quirk.patch @@ -0,0 +1,125 @@ +From d5a1c7e3fc38d9c7d629e1e47f32f863acbdec3d Mon Sep 17 00:00:00 2001 +From: Borislav Petkov +Date: Sat, 20 Jul 2013 19:00:23 +0200 +Subject: rtc-cmos: Add an alarm disable quirk + +From: Borislav Petkov + +commit d5a1c7e3fc38d9c7d629e1e47f32f863acbdec3d upstream. + +41c7f7424259f ("rtc: Disable the alarm in the hardware (v2)") added the +functionality to disable the RTC wake alarm when shutting down the box. + +However, there are at least two b0rked BIOSes we know about: + +https://bugzilla.novell.com/show_bug.cgi?id=812592 +https://bugzilla.novell.com/show_bug.cgi?id=805740 + +where, when wakeup alarm is enabled in the BIOS, the machine reboots +automatically right after shutdown, regardless of what wakeup time is +programmed. + +Bisecting the issue lead to this patch so disable its functionality with +a DMI quirk only for those boxes. + +Cc: Brecht Machiels +Cc: Thomas Gleixner +Cc: John Stultz +Cc: Rabin Vincent +Signed-off-by: Borislav Petkov +[jstultz: Changed variable name for clarity, added extra dmi entry] +Tested-by: Brecht Machiels +Tested-by: Borislav Petkov +Signed-off-by: John Stultz +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/rtc/rtc-cmos.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 51 insertions(+), 1 deletion(-) + +--- a/drivers/rtc/rtc-cmos.c ++++ b/drivers/rtc/rtc-cmos.c +@@ -34,11 +34,11 @@ + #include + #include + #include +-#include + #include + #include + #include + #include ++#include + + /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */ + #include +@@ -377,6 +377,51 @@ static int cmos_set_alarm(struct device + return 0; + } + ++/* ++ * Do not disable RTC alarm on shutdown - workaround for b0rked BIOSes. ++ */ ++static bool alarm_disable_quirk; ++ ++static int __init set_alarm_disable_quirk(const struct dmi_system_id *id) ++{ ++ alarm_disable_quirk = true; ++ pr_info("rtc-cmos: BIOS has alarm-disable quirk. "); ++ pr_info("RTC alarms disabled\n"); ++ return 0; ++} ++ ++static const struct dmi_system_id rtc_quirks[] __initconst = { ++ /* https://bugzilla.novell.com/show_bug.cgi?id=805740 */ ++ { ++ .callback = set_alarm_disable_quirk, ++ .ident = "IBM Truman", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "4852570"), ++ }, ++ }, ++ /* https://bugzilla.novell.com/show_bug.cgi?id=812592 */ ++ { ++ .callback = set_alarm_disable_quirk, ++ .ident = "Gigabyte GA-990XA-UD3", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, ++ "Gigabyte Technology Co., Ltd."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "GA-990XA-UD3"), ++ }, ++ }, ++ /* http://permalink.gmane.org/gmane.linux.kernel/1604474 */ ++ { ++ .callback = set_alarm_disable_quirk, ++ .ident = "Toshiba Satellite L300", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), ++ }, ++ }, ++ {} ++}; ++ + static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled) + { + struct cmos_rtc *cmos = dev_get_drvdata(dev); +@@ -385,6 +430,9 @@ static int cmos_alarm_irq_enable(struct + if (!is_valid_irq(cmos->irq)) + return -EINVAL; + ++ if (alarm_disable_quirk) ++ return 0; ++ + spin_lock_irqsave(&rtc_lock, flags); + + if (enabled) +@@ -1163,6 +1211,8 @@ static int __init cmos_init(void) + platform_driver_registered = true; + } + ++ dmi_check_system(rtc_quirks); ++ + if (retval == 0) + return 0; + diff --git a/queue-3.10/series b/queue-3.10/series index 34a6da9ce41..ad4649baa20 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -71,3 +71,5 @@ ftrace-have-function-graph-only-trace-based-on-global_ops-filters.patch timekeeping-fix-lost-updates-to-tai-adjustment.patch timekeeping-fix-clock_tai-timer-nanosleep-delays.patch timekeeping-fix-missing-timekeeping_update-in-suspend-path.patch +rtc-cmos-add-an-alarm-disable-quirk.patch +timekeeping-avoid-possible-deadlock-from-clock_was_set_delayed.patch diff --git a/queue-3.10/timekeeping-avoid-possible-deadlock-from-clock_was_set_delayed.patch b/queue-3.10/timekeeping-avoid-possible-deadlock-from-clock_was_set_delayed.patch new file mode 100644 index 00000000000..11d35e4052b --- /dev/null +++ b/queue-3.10/timekeeping-avoid-possible-deadlock-from-clock_was_set_delayed.patch @@ -0,0 +1,210 @@ +From 6fdda9a9c5db367130cf32df5d6618d08b89f46a Mon Sep 17 00:00:00 2001 +From: John Stultz +Date: Tue, 10 Dec 2013 17:18:18 -0800 +Subject: timekeeping: Avoid possible deadlock from clock_was_set_delayed + +From: John Stultz + +commit 6fdda9a9c5db367130cf32df5d6618d08b89f46a upstream. + +As part of normal operaions, the hrtimer subsystem frequently calls +into the timekeeping code, creating a locking order of + hrtimer locks -> timekeeping locks + +clock_was_set_delayed() was suppoed to allow us to avoid deadlocks +between the timekeeping the hrtimer subsystem, so that we could +notify the hrtimer subsytem the time had changed while holding +the timekeeping locks. This was done by scheduling delayed work +that would run later once we were out of the timekeeing code. + +But unfortunately the lock chains are complex enoguh that in +scheduling delayed work, we end up eventually trying to grab +an hrtimer lock. + +Sasha Levin noticed this in testing when the new seqlock lockdep +enablement triggered the following (somewhat abrieviated) message: + +[ 251.100221] ====================================================== +[ 251.100221] [ INFO: possible circular locking dependency detected ] +[ 251.100221] 3.13.0-rc2-next-20131206-sasha-00005-g8be2375-dirty #4053 Not tainted +[ 251.101967] ------------------------------------------------------- +[ 251.101967] kworker/10:1/4506 is trying to acquire lock: +[ 251.101967] (timekeeper_seq){----..}, at: [] retrigger_next_event+0x56/0x70 +[ 251.101967] +[ 251.101967] but task is already holding lock: +[ 251.101967] (hrtimer_bases.lock#11){-.-...}, at: [] retrigger_next_event+0x3c/0x70 +[ 251.101967] +[ 251.101967] which lock already depends on the new lock. +[ 251.101967] +[ 251.101967] +[ 251.101967] the existing dependency chain (in reverse order) is: +[ 251.101967] +-> #5 (hrtimer_bases.lock#11){-.-...}: +[snipped] +-> #4 (&rt_b->rt_runtime_lock){-.-...}: +[snipped] +-> #3 (&rq->lock){-.-.-.}: +[snipped] +-> #2 (&p->pi_lock){-.-.-.}: +[snipped] +-> #1 (&(&pool->lock)->rlock){-.-...}: +[ 251.101967] [] validate_chain+0x6c3/0x7b0 +[ 251.101967] [] __lock_acquire+0x4ad/0x580 +[ 251.101967] [] lock_acquire+0x182/0x1d0 +[ 251.101967] [] _raw_spin_lock+0x40/0x80 +[ 251.101967] [] __queue_work+0x1a9/0x3f0 +[ 251.101967] [] queue_work_on+0x98/0x120 +[ 251.101967] [] clock_was_set_delayed+0x21/0x30 +[ 251.101967] [] do_adjtimex+0x111/0x160 +[ 251.101967] [] compat_sys_adjtimex+0x41/0x70 +[ 251.101967] [] ia32_sysret+0x0/0x5 +[ 251.101967] +-> #0 (timekeeper_seq){----..}: +[snipped] +[ 251.101967] other info that might help us debug this: +[ 251.101967] +[ 251.101967] Chain exists of: + timekeeper_seq --> &rt_b->rt_runtime_lock --> hrtimer_bases.lock#11 + +[ 251.101967] Possible unsafe locking scenario: +[ 251.101967] +[ 251.101967] CPU0 CPU1 +[ 251.101967] ---- ---- +[ 251.101967] lock(hrtimer_bases.lock#11); +[ 251.101967] lock(&rt_b->rt_runtime_lock); +[ 251.101967] lock(hrtimer_bases.lock#11); +[ 251.101967] lock(timekeeper_seq); +[ 251.101967] +[ 251.101967] *** DEADLOCK *** +[ 251.101967] +[ 251.101967] 3 locks held by kworker/10:1/4506: +[ 251.101967] #0: (events){.+.+.+}, at: [] process_one_work+0x200/0x530 +[ 251.101967] #1: (hrtimer_work){+.+...}, at: [] process_one_work+0x200/0x530 +[ 251.101967] #2: (hrtimer_bases.lock#11){-.-...}, at: [] retrigger_next_event+0x3c/0x70 +[ 251.101967] +[ 251.101967] stack backtrace: +[ 251.101967] CPU: 10 PID: 4506 Comm: kworker/10:1 Not tainted 3.13.0-rc2-next-20131206-sasha-00005-g8be2375-dirty #4053 +[ 251.101967] Workqueue: events clock_was_set_work + +So the best solution is to avoid calling clock_was_set_delayed() while +holding the timekeeping lock, and instead using a flag variable to +decide if we should call clock_was_set() once we've released the locks. + +This works for the case here, where the do_adjtimex() was the deadlock +trigger point. Unfortuantely, in update_wall_time() we still hold +the jiffies lock, which would deadlock with the ipi triggered by +clock_was_set(), preventing us from calling it even after we drop the +timekeeping lock. So instead call clock_was_set_delayed() at that point. + +Cc: Thomas Gleixner +Cc: Prarit Bhargava +Cc: Richard Cochran +Cc: Ingo Molnar +Cc: Sasha Levin +Reported-by: Sasha Levin +Tested-by: Sasha Levin +Signed-off-by: John Stultz +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/time/timekeeping.c | 25 ++++++++++++++++++------- + 1 file changed, 18 insertions(+), 7 deletions(-) + +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -1239,9 +1239,10 @@ out_adjust: + * It also calls into the NTP code to handle leapsecond processing. + * + */ +-static inline void accumulate_nsecs_to_secs(struct timekeeper *tk) ++static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk) + { + u64 nsecps = (u64)NSEC_PER_SEC << tk->shift; ++ unsigned int clock_set = 0; + + while (tk->xtime_nsec >= nsecps) { + int leap; +@@ -1263,9 +1264,10 @@ static inline void accumulate_nsecs_to_s + + __timekeeping_set_tai_offset(tk, tk->tai_offset - leap); + +- clock_was_set_delayed(); ++ clock_set = 1; + } + } ++ return clock_set; + } + + /** +@@ -1278,7 +1280,8 @@ static inline void accumulate_nsecs_to_s + * Returns the unconsumed cycles. + */ + static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset, +- u32 shift) ++ u32 shift, ++ unsigned int *clock_set) + { + cycle_t interval = tk->cycle_interval << shift; + u64 raw_nsecs; +@@ -1292,7 +1295,7 @@ static cycle_t logarithmic_accumulation( + tk->cycle_last += interval; + + tk->xtime_nsec += tk->xtime_interval << shift; +- accumulate_nsecs_to_secs(tk); ++ *clock_set |= accumulate_nsecs_to_secs(tk); + + /* Accumulate raw time */ + raw_nsecs = (u64)tk->raw_interval << shift; +@@ -1350,6 +1353,7 @@ static void update_wall_time(void) + struct timekeeper *tk = &shadow_timekeeper; + cycle_t offset; + int shift = 0, maxshift; ++ unsigned int clock_set = 0; + unsigned long flags; + + raw_spin_lock_irqsave(&timekeeper_lock, flags); +@@ -1384,7 +1388,8 @@ static void update_wall_time(void) + maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1; + shift = min(shift, maxshift); + while (offset >= tk->cycle_interval) { +- offset = logarithmic_accumulation(tk, offset, shift); ++ offset = logarithmic_accumulation(tk, offset, shift, ++ &clock_set); + if (offset < tk->cycle_interval<cycle_last with the new value */ +@@ -1422,6 +1427,10 @@ static void update_wall_time(void) + write_seqcount_end(&timekeeper_seq); + out: + raw_spin_unlock_irqrestore(&timekeeper_lock, flags); ++ if (clock_set) ++ /* have to call outside the timekeeper_seq */ ++ clock_was_set_delayed(); ++ + } + + /** +@@ -1681,11 +1690,13 @@ int do_adjtimex(struct timex *txc) + if (tai != orig_tai) { + __timekeeping_set_tai_offset(tk, tai); + timekeeping_update(tk, false, true); +- clock_was_set_delayed(); + } + write_seqcount_end(&timekeeper_seq); + raw_spin_unlock_irqrestore(&timekeeper_lock, flags); + ++ if (tai != orig_tai) ++ clock_was_set(); ++ + ntp_notify_cmos_timer(); + + return ret;