Patch from: Zwane Mwaikambo <zwane@linuxpower.ca>

Fix up a possible AB/BA deadlock identified by Dawson Engler's latest toy.



 drivers/char/rtc.c |   15 ++++++++++-----
 1 files changed, 10 insertions(+), 5 deletions(-)

diff -puN drivers/char/rtc.c~rtc-locking-fix drivers/char/rtc.c
--- 25/drivers/char/rtc.c~rtc-locking-fix	2003-03-02 21:25:37.000000000 -0800
+++ 25-akpm/drivers/char/rtc.c	2003-03-02 21:27:19.000000000 -0800
@@ -152,6 +152,9 @@ static unsigned long rtc_irq_data = 0;	/
 static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */
 
 #if RTC_IRQ
+/*
+ * rtc_task_lock nests inside rtc_lock.
+ */
 static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED;
 static rtc_task_t *rtc_callback = NULL;
 #endif
@@ -746,13 +749,15 @@ int rtc_unregister(rtc_task_t *task)
 #else
 	unsigned char tmp;
 
-	spin_lock_irq(&rtc_task_lock);
+	spin_lock_irq(&rtc_lock);
+	spin_lock(&rtc_task_lock);
 	if (rtc_callback != task) {
-		spin_unlock_irq(&rtc_task_lock);
+		spin_unlock(&rtc_task_lock);
+		spin_unlock_irq(&rtc_lock);
 		return -ENXIO;
 	}
 	rtc_callback = NULL;
-	spin_lock(&rtc_lock);
+	
 	/* disable controls */
 	tmp = CMOS_READ(RTC_CONTROL);
 	tmp &= ~RTC_PIE;
@@ -765,8 +770,8 @@ int rtc_unregister(rtc_task_t *task)
 		del_timer(&rtc_irq_timer);
 	}
 	rtc_status &= ~RTC_IS_OPEN;
-	spin_unlock(&rtc_lock);
-	spin_unlock_irq(&rtc_task_lock);
+	spin_unlock(&rtc_task_lock);
+	spin_unlock_irq(&rtc_lock);
 	return 0;
 #endif
 }

_