summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/rtasd.c
diff options
context:
space:
mode:
authorRavi K. Nittala <ravi.nittala@in.ibm.com>2011-10-03 21:49:53 +0000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-11-25 14:11:29 +1100
commitdf17f56d8a1a3a533b6b3e3a49a624626a49b197 (patch)
treef88a555f03a8d1933d829c8b14ac252cc3f33420 /arch/powerpc/kernel/rtasd.c
parentcc35b6766878e31accc95c3fdae945bdadc73a46 (diff)
powerpc/pseries: Cancel RTAS event scan before firmware flash
The RTAS firmware flash update is conducted using an RTAS call that is serialized by lock_rtas() which uses spin_lock. While the flash is in progress, rtasd performs scan for any RTAS events that are generated by the system. rtasd keeps scanning for the RTAS events generated on the machine. This is performed via workqueue mechanism. The rtas_event_scan() also uses an RTAS call to scan the events, eventually trying to acquire the spin_lock before issuing the request. The flash update takes a while to complete and during this time, any other RTAS call has to wait. In this case, rtas_event_scan() waits for a long time on the spin_lock resulting in a soft lockup. Fix: Just before the flash update is performed, the queued rtas_event_scan() work item is cancelled from the work queue so that there is no other RTAS call issued while the flash is in progress. After the flash completes, the system reboots and the rtas_event_scan() is rescheduled. Signed-off-by: Suzuki Poulose <suzuki@in.ibm.com> Signed-off-by: Ravi Nittala <ravi.nittala@in.ibm.com> Reported-by: Divya Vikas <divya.vikas@in.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/rtasd.c')
-rw-r--r--arch/powerpc/kernel/rtasd.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index 481ef064c8f1..1045ff49cc6d 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -472,6 +472,13 @@ static void start_event_scan(void)
&event_scan_work, event_scan_delay);
}
+/* Cancel the rtas event scan work */
+void rtas_cancel_event_scan(void)
+{
+ cancel_delayed_work_sync(&event_scan_work);
+}
+EXPORT_SYMBOL_GPL(rtas_cancel_event_scan);
+
static int __init rtas_init(void)
{
struct proc_dir_entry *entry;