Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 125751
b: refs/heads/master
c: fe0bdec
h: refs/heads/master
i:
  125749: f46f7ed
  125747: e82ca89
  125743: 4b0d7d9
v: v3
  • Loading branch information
Linus Torvalds committed Jan 5, 2009
1 parent 00e5cee commit 465b5da
Show file tree
Hide file tree
Showing 35 changed files with 313 additions and 179 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5af75d8d58d0f9f7b7c0515b35786b22892d5f12
refs/heads/master: fe0bdec68b77020281dc814805edfe594ae89e0f
6 changes: 5 additions & 1 deletion trunk/drivers/rtc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,13 @@ config RTC_INTF_DEV_UIE_EMUL
depends on RTC_INTF_DEV
help
Provides an emulation for RTC_UIE if the underlying rtc chip
driver does not expose RTC_UIE ioctls. Those requests generate
driver does not expose RTC_UIE ioctls. Those requests generate
once-per-second update interrupts, used for synchronization.

The emulation code will read the time from the hardware
clock several times per second, please enable this option
only if you know that you really need it.

config RTC_DRV_TEST
tristate "Test driver/device"
help
Expand Down
54 changes: 54 additions & 0 deletions trunk/drivers/rtc/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,60 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
}
EXPORT_SYMBOL_GPL(rtc_set_alarm);

int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
{
int err = mutex_lock_interruptible(&rtc->ops_lock);
if (err)
return err;

if (!rtc->ops)
err = -ENODEV;
else if (!rtc->ops->alarm_irq_enable)
err = -EINVAL;
else
err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled);

mutex_unlock(&rtc->ops_lock);
return err;
}
EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable);

int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled)
{
int err = mutex_lock_interruptible(&rtc->ops_lock);
if (err)
return err;

#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
if (enabled == 0 && rtc->uie_irq_active) {
mutex_unlock(&rtc->ops_lock);
return rtc_dev_update_irq_enable_emul(rtc, enabled);
}
#endif

if (!rtc->ops)
err = -ENODEV;
else if (!rtc->ops->update_irq_enable)
err = -EINVAL;
else
err = rtc->ops->update_irq_enable(rtc->dev.parent, enabled);

mutex_unlock(&rtc->ops_lock);

#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
/*
* Enable emulation if the driver did not provide
* the update_irq_enable function pointer or if returned
* -EINVAL to signal that it has been configured without
* interrupts or that are not available at the moment.
*/
if (err == -EINVAL)
err = rtc_dev_update_irq_enable_emul(rtc, enabled);
#endif
return err;
}
EXPORT_SYMBOL_GPL(rtc_update_irq_enable);

/**
* rtc_update_irq - report RTC periodic, alarm, and/or update irqs
* @rtc: the rtc device
Expand Down
51 changes: 35 additions & 16 deletions trunk/drivers/rtc/rtc-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ static void rtc_uie_timer(unsigned long data)
spin_unlock_irqrestore(&rtc->irq_lock, flags);
}

static void clear_uie(struct rtc_device *rtc)
static int clear_uie(struct rtc_device *rtc)
{
spin_lock_irq(&rtc->irq_lock);
if (rtc->irq_active) {
if (rtc->uie_irq_active) {
rtc->stop_uie_polling = 1;
if (rtc->uie_timer_active) {
spin_unlock_irq(&rtc->irq_lock);
Expand All @@ -108,9 +108,10 @@ static void clear_uie(struct rtc_device *rtc)
flush_scheduled_work();
spin_lock_irq(&rtc->irq_lock);
}
rtc->irq_active = 0;
rtc->uie_irq_active = 0;
}
spin_unlock_irq(&rtc->irq_lock);
return 0;
}

static int set_uie(struct rtc_device *rtc)
Expand All @@ -122,8 +123,8 @@ static int set_uie(struct rtc_device *rtc)
if (err)
return err;
spin_lock_irq(&rtc->irq_lock);
if (!rtc->irq_active) {
rtc->irq_active = 1;
if (!rtc->uie_irq_active) {
rtc->uie_irq_active = 1;
rtc->stop_uie_polling = 0;
rtc->oldsecs = tm.tm_sec;
rtc->uie_task_active = 1;
Expand All @@ -134,6 +135,16 @@ static int set_uie(struct rtc_device *rtc)
spin_unlock_irq(&rtc->irq_lock);
return 0;
}

int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled)
{
if (enabled)
return set_uie(rtc);
else
return clear_uie(rtc);
}
EXPORT_SYMBOL(rtc_dev_update_irq_enable_emul);

#endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */

static ssize_t
Expand Down Expand Up @@ -357,6 +368,22 @@ static long rtc_dev_ioctl(struct file *file,
err = rtc_irq_set_state(rtc, NULL, 0);
break;

case RTC_AIE_ON:
mutex_unlock(&rtc->ops_lock);
return rtc_alarm_irq_enable(rtc, 1);

case RTC_AIE_OFF:
mutex_unlock(&rtc->ops_lock);
return rtc_alarm_irq_enable(rtc, 0);

case RTC_UIE_ON:
mutex_unlock(&rtc->ops_lock);
return rtc_update_irq_enable(rtc, 1);

case RTC_UIE_OFF:
mutex_unlock(&rtc->ops_lock);
return rtc_update_irq_enable(rtc, 0);

case RTC_IRQP_SET:
err = rtc_irq_set_freq(rtc, NULL, arg);
break;
Expand Down Expand Up @@ -401,17 +428,6 @@ static long rtc_dev_ioctl(struct file *file,
err = -EFAULT;
return err;

#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
case RTC_UIE_OFF:
mutex_unlock(&rtc->ops_lock);
clear_uie(rtc);
return 0;

case RTC_UIE_ON:
mutex_unlock(&rtc->ops_lock);
err = set_uie(rtc);
return err;
#endif
default:
err = -ENOTTY;
break;
Expand Down Expand Up @@ -440,7 +456,10 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
* Leave the alarm alone; it may be set to trigger a system wakeup
* later, or be used by kernel code, and is a one-shot event anyway.
*/

/* Keep ioctl until all drivers are converted */
rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
rtc_update_irq_enable(rtc, 0);
rtc_irq_set_state(rtc, NULL, 0);

if (rtc->ops->release)
Expand Down
Loading

0 comments on commit 465b5da

Please sign in to comment.