mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: David Brownell <david-b@pacbell.net>
To: Alessandro Zummo <alessandro.zummo@towertech.it>,
	Linux Kernel list <linux-kernel@vger.kernel.org>
Subject: [patch 2.6.19-rc6] rtc class locking bugfixes
Date: Thu, 16 Nov 2006 23:27:37 -0800	[thread overview]
Message-ID: <200611162327.37306.david-b@pacbell.net> (raw)

I got a lockdep warning when running "rtctest" so I though it'd be good
to see what was up.

 - The warning was for rtc->irq_task_lock, gotten from rtc_update_irq()
   by irq handlerss ... but in a handful of other cases, grabbed without
   blocking IRQs.

 - Some callers to rtc_update_irq() were not ensuring IRQs were blocked,
   yet the routine expects that; make sure all callers block IRQs.

It would appear that RTC API tests haven't been part of anyone's kernel
regression test suite recently, at least not with lockdep running.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>

Index: g26/drivers/rtc/interface.c
===================================================================
--- g26.orig/drivers/rtc/interface.c	2006-06-28 22:02:19.000000000 -0700
+++ g26/drivers/rtc/interface.c	2006-11-16 21:54:35.000000000 -0800
@@ -145,6 +145,13 @@ int rtc_set_alarm(struct class_device *c
 }
 EXPORT_SYMBOL_GPL(rtc_set_alarm);
 
+/**
+ * rtc_update_irq - report RTC periodic, alarm, and/or update irqs
+ * @class_dev: the rtc's class device
+ * @num: how many irqs are being reported (usually one)
+ * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF
+ * Context: in_interrupt(), irqs blocked
+ */
 void rtc_update_irq(struct class_device *class_dev,
 		unsigned long num, unsigned long events)
 {
@@ -201,12 +208,12 @@ int rtc_irq_register(struct class_device
 	if (task == NULL || task->func == NULL)
 		return -EINVAL;
 
-	spin_lock(&rtc->irq_task_lock);
+	spin_lock_irq(&rtc->irq_task_lock);
 	if (rtc->irq_task == NULL) {
 		rtc->irq_task = task;
 		retval = 0;
 	}
-	spin_unlock(&rtc->irq_task_lock);
+	spin_unlock_irq(&rtc->irq_task_lock);
 
 	return retval;
 }
@@ -216,10 +223,10 @@ void rtc_irq_unregister(struct class_dev
 {
 	struct rtc_device *rtc = to_rtc_device(class_dev);
 
-	spin_lock(&rtc->irq_task_lock);
+	spin_lock_irq(&rtc->irq_task_lock);
 	if (rtc->irq_task == task)
 		rtc->irq_task = NULL;
-	spin_unlock(&rtc->irq_task_lock);
+	spin_unlock_irq(&rtc->irq_task_lock);
 }
 EXPORT_SYMBOL_GPL(rtc_irq_unregister);
 
Index: g26/drivers/rtc/rtc-dev.c
===================================================================
--- g26.orig/drivers/rtc/rtc-dev.c	2006-11-16 19:44:52.000000000 -0800
+++ g26/drivers/rtc/rtc-dev.c	2006-11-16 21:37:45.000000000 -0800
@@ -61,7 +61,9 @@ static void rtc_uie_task(void *data)
 	int err;
 
 	err = rtc_read_time(&rtc->class_dev, &tm);
-	spin_lock_irq(&rtc->irq_lock);
+
+	local_irq_disable();
+	spin_lock(&rtc->irq_lock);
 	if (rtc->stop_uie_polling || err) {
 		rtc->uie_task_active = 0;
 	} else if (rtc->oldsecs != tm.tm_sec) {
@@ -74,11 +76,11 @@ static void rtc_uie_task(void *data)
 	} else if (schedule_work(&rtc->uie_task) == 0) {
 		rtc->uie_task_active = 0;
 	}
-	spin_unlock_irq(&rtc->irq_lock);
+	spin_unlock(&rtc->irq_lock);
 	if (num)
 		rtc_update_irq(&rtc->class_dev, num, RTC_UF | RTC_IRQF);
+	local_irq_enable();
 }
-
 static void rtc_uie_timer(unsigned long data)
 {
 	struct rtc_device *rtc = (struct rtc_device *)data;
@@ -238,10 +240,10 @@ static int rtc_dev_ioctl(struct inode *i
 
 	/* avoid conflicting IRQ users */
 	if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) {
-		spin_lock(&rtc->irq_task_lock);
+		spin_lock_irq(&rtc->irq_task_lock);
 		if (rtc->irq_task)
 			err = -EBUSY;
-		spin_unlock(&rtc->irq_task_lock);
+		spin_unlock_irq(&rtc->irq_task_lock);
 
 		if (err < 0)
 			return err;
Index: g26/drivers/rtc/rtc-at91.c
===================================================================
--- g26.orig/drivers/rtc/rtc-at91.c	2006-11-16 18:47:20.000000000 -0800
+++ g26/drivers/rtc/rtc-at91.c	2006-11-16 19:46:11.000000000 -0800
@@ -292,7 +292,8 @@ static int __init at91_rtc_probe(struct 
 					AT91_RTC_CALEV);
 
 	ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
-				IRQF_SHARED, "at91_rtc", pdev);
+				IRQF_DISABLED | IRQF_SHARED,
+				"at91_rtc", pdev);
 	if (ret) {
 		printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n",
 				AT91_ID_SYS);
Index: g26/drivers/rtc/rtc-ds1553.c
===================================================================
--- g26.orig/drivers/rtc/rtc-ds1553.c	2006-10-13 15:41:11.000000000 -0700
+++ g26/drivers/rtc/rtc-ds1553.c	2006-11-16 19:47:08.000000000 -0800
@@ -340,7 +340,8 @@ static int __init ds1553_rtc_probe(struc
 
 	if (pdata->irq >= 0) {
 		writeb(0, ioaddr + RTC_INTERRUPTS);
-		if (request_irq(pdata->irq, ds1553_rtc_interrupt, IRQF_SHARED,
+		if (request_irq(pdata->irq, ds1553_rtc_interrupt,
+				IRQF_DISABLED | IRQF_SHARED,
 				pdev->name, pdev) < 0) {
 			dev_warn(&pdev->dev, "interrupt not available.\n");
 			pdata->irq = -1;
Index: g26/drivers/rtc/rtc-test.c
===================================================================
--- g26.orig/drivers/rtc/rtc-test.c	2006-10-05 19:43:53.000000000 -0700
+++ g26/drivers/rtc/rtc-test.c	2006-11-16 19:50:33.000000000 -0800
@@ -99,6 +99,7 @@ static ssize_t test_irq_store(struct dev
 	struct rtc_device *rtc = platform_get_drvdata(plat_dev);
 
 	retval = count;
+	local_irq_disable();
 	if (strncmp(buf, "tick", 4) == 0)
 		rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF);
 	else if (strncmp(buf, "alarm", 5) == 0)
@@ -107,6 +108,7 @@ static ssize_t test_irq_store(struct dev
 		rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF);
 	else
 		retval = -EINVAL;
+	local_irq_enable();
 
 	return retval;
 }

             reply	other threads:[~2006-11-17  9:36 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-11-17  7:27 David Brownell [this message]
2006-11-19 23:49 ` Alessandro Zummo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200611162327.37306.david-b@pacbell.net \
    --to=david-b@pacbell.net \
    --cc=alessandro.zummo@towertech.it \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®