Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e6229bec authored by Atsushi Nemoto's avatar Atsushi Nemoto Committed by Linus Torvalds
Browse files

rtc: make rtc_update_irq callable with irqs enabled



The rtc_update_irq() might be called with irqs enabled, if a interrupt
handler was registered without IRQF_DISABLED.  Use
spin_lock_irqsave/spin_unlock_irqrestore instead of spin_lock/spin_unlock.

Also update kerneldoc and drivers which do extra work to follow the
current interface spec, as suggestted by David Brownell.

Signed-off-by: default avatarAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: David Brownell <david-b@pacbell.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 575c5807
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -371,19 +371,21 @@ EXPORT_SYMBOL_GPL(rtc_update_irq_enable);
 * @rtc: the rtc 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
 * Context: any
 */
void rtc_update_irq(struct rtc_device *rtc,
		unsigned long num, unsigned long events)
{
	spin_lock(&rtc->irq_lock);
	unsigned long flags;

	spin_lock_irqsave(&rtc->irq_lock, flags);
	rtc->irq_data = (rtc->irq_data + (num << 8)) | events;
	spin_unlock(&rtc->irq_lock);
	spin_unlock_irqrestore(&rtc->irq_lock, flags);

	spin_lock(&rtc->irq_task_lock);
	spin_lock_irqsave(&rtc->irq_task_lock, flags);
	if (rtc->irq_task)
		rtc->irq_task->func(rtc->irq_task->private_data);
	spin_unlock(&rtc->irq_task_lock);
	spin_unlock_irqrestore(&rtc->irq_task_lock, flags);

	wake_up_interruptible(&rtc->irq_queue);
	kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
+2 −4
Original line number Diff line number Diff line
@@ -60,8 +60,7 @@ static void rtc_uie_task(struct work_struct *work)

	err = rtc_read_time(rtc, &tm);

	local_irq_disable();
	spin_lock(&rtc->irq_lock);
	spin_lock_irq(&rtc->irq_lock);
	if (rtc->stop_uie_polling || err) {
		rtc->uie_task_active = 0;
	} else if (rtc->oldsecs != tm.tm_sec) {
@@ -74,10 +73,9 @@ static void rtc_uie_task(struct work_struct *work)
	} else if (schedule_work(&rtc->uie_task) == 0) {
		rtc->uie_task_active = 0;
	}
	spin_unlock(&rtc->irq_lock);
	spin_unlock_irq(&rtc->irq_lock);
	if (num)
		rtc_update_irq(rtc, num, RTC_UF | RTC_IRQF);
	local_irq_enable();
}
static void rtc_uie_timer(unsigned long data)
{
+0 −3
Original line number Diff line number Diff line
@@ -499,10 +499,7 @@ static void ds1305_work(struct work_struct *work)
	if (!test_bit(FLAG_EXITING, &ds1305->flags))
		enable_irq(spi->irq);

	/* rtc_update_irq() requires an IRQ-disabled context */
	local_irq_disable();
	rtc_update_irq(ds1305->rtc, 1, RTC_AF | RTC_IRQF);
	local_irq_enable();
}

/*
+0 −5
Original line number Diff line number Diff line
@@ -267,12 +267,7 @@ static void ds1307_work(struct work_struct *work)
		control &= ~DS1337_BIT_A1IE;
		i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control);

		/* rtc_update_irq() assumes that it is called
		 * from IRQ-disabled context.
		 */
		local_irq_disable();
		rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
		local_irq_enable();
	}

out:
+0 −5
Original line number Diff line number Diff line
@@ -296,12 +296,7 @@ static void ds1374_work(struct work_struct *work)
		control &= ~(DS1374_REG_CR_WACE | DS1374_REG_CR_AIE);
		i2c_smbus_write_byte_data(client, DS1374_REG_CR, control);

		/* rtc_update_irq() assumes that it is called
		 * from IRQ-disabled context.
		 */
		local_irq_disable();
		rtc_update_irq(ds1374->rtc, 1, RTC_AF | RTC_IRQF);
		local_irq_enable();
	}

out:
Loading