Merge branch 'rtc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'rtc-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
RTC: Re-enable UIE timer/polling emulation
RTC: Revert UIE emulation removal
RTC: Release mutex in error path of rtc_alarm_irq_enable

+150 -4
+12
drivers/rtc/Kconfig
··· 97 97 98 98 If unsure, say Y. 99 99 100 + config RTC_INTF_DEV_UIE_EMUL 101 + bool "RTC UIE emulation on dev interface" 102 + depends on RTC_INTF_DEV 103 + help 104 + Provides an emulation for RTC_UIE if the underlying rtc chip 105 + driver does not expose RTC_UIE ioctls. Those requests generate 106 + once-per-second update interrupts, used for synchronization. 107 + 108 + The emulation code will read the time from the hardware 109 + clock several times per second, please enable this option 110 + only if you know that you really need it. 111 + 100 112 config RTC_DRV_TEST 101 113 tristate "Test driver/device" 102 114 help
+19 -4
drivers/rtc/interface.c
··· 209 209 } 210 210 211 211 if (err) 212 - return err; 213 - 214 - if (!rtc->ops) 212 + /* nothing */; 213 + else if (!rtc->ops) 215 214 err = -ENODEV; 216 215 else if (!rtc->ops->alarm_irq_enable) 217 216 err = -EINVAL; ··· 228 229 if (err) 229 230 return err; 230 231 232 + #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL 233 + if (enabled == 0 && rtc->uie_irq_active) { 234 + mutex_unlock(&rtc->ops_lock); 235 + return rtc_dev_update_irq_enable_emul(rtc, 0); 236 + } 237 + #endif 231 238 /* make sure we're changing state */ 232 239 if (rtc->uie_rtctimer.enabled == enabled) 233 240 goto out; ··· 253 248 254 249 out: 255 250 mutex_unlock(&rtc->ops_lock); 251 + #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL 252 + /* 253 + * Enable emulation if the driver did not provide 254 + * the update_irq_enable function pointer or if returned 255 + * -EINVAL to signal that it has been configured without 256 + * interrupts or that are not available at the moment. 257 + */ 258 + if (err == -EINVAL) 259 + err = rtc_dev_update_irq_enable_emul(rtc, enabled); 260 + #endif 256 261 return err; 257 262 258 263 } ··· 278 263 * 279 264 * Triggers the registered irq_task function callback. 280 265 */ 281 - static void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) 266 + void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) 282 267 { 283 268 unsigned long flags; 284 269
+104
drivers/rtc/rtc-dev.c
··· 46 46 return err; 47 47 } 48 48 49 + #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL 50 + /* 51 + * Routine to poll RTC seconds field for change as often as possible, 52 + * after first RTC_UIE use timer to reduce polling 53 + */ 54 + static void rtc_uie_task(struct work_struct *work) 55 + { 56 + struct rtc_device *rtc = 57 + container_of(work, struct rtc_device, uie_task); 58 + struct rtc_time tm; 59 + int num = 0; 60 + int err; 61 + 62 + err = rtc_read_time(rtc, &tm); 63 + 64 + spin_lock_irq(&rtc->irq_lock); 65 + if (rtc->stop_uie_polling || err) { 66 + rtc->uie_task_active = 0; 67 + } else if (rtc->oldsecs != tm.tm_sec) { 68 + num = (tm.tm_sec + 60 - rtc->oldsecs) % 60; 69 + rtc->oldsecs = tm.tm_sec; 70 + rtc->uie_timer.expires = jiffies + HZ - (HZ/10); 71 + rtc->uie_timer_active = 1; 72 + rtc->uie_task_active = 0; 73 + add_timer(&rtc->uie_timer); 74 + } else if (schedule_work(&rtc->uie_task) == 0) { 75 + rtc->uie_task_active = 0; 76 + } 77 + spin_unlock_irq(&rtc->irq_lock); 78 + if (num) 79 + rtc_handle_legacy_irq(rtc, num, RTC_UF); 80 + } 81 + static void rtc_uie_timer(unsigned long data) 82 + { 83 + struct rtc_device *rtc = (struct rtc_device *)data; 84 + unsigned long flags; 85 + 86 + spin_lock_irqsave(&rtc->irq_lock, flags); 87 + rtc->uie_timer_active = 0; 88 + rtc->uie_task_active = 1; 89 + if ((schedule_work(&rtc->uie_task) == 0)) 90 + rtc->uie_task_active = 0; 91 + spin_unlock_irqrestore(&rtc->irq_lock, flags); 92 + } 93 + 94 + static int clear_uie(struct rtc_device *rtc) 95 + { 96 + spin_lock_irq(&rtc->irq_lock); 97 + if (rtc->uie_irq_active) { 98 + rtc->stop_uie_polling = 1; 99 + if (rtc->uie_timer_active) { 100 + spin_unlock_irq(&rtc->irq_lock); 101 + del_timer_sync(&rtc->uie_timer); 102 + spin_lock_irq(&rtc->irq_lock); 103 + rtc->uie_timer_active = 0; 104 + } 105 + if (rtc->uie_task_active) { 106 + spin_unlock_irq(&rtc->irq_lock); 107 + flush_scheduled_work(); 108 + spin_lock_irq(&rtc->irq_lock); 109 + } 110 + rtc->uie_irq_active = 0; 111 + } 112 + spin_unlock_irq(&rtc->irq_lock); 113 + return 0; 114 + } 115 + 116 + static int set_uie(struct rtc_device *rtc) 117 + { 118 + struct rtc_time tm; 119 + int err; 120 + 121 + err = rtc_read_time(rtc, &tm); 122 + if (err) 123 + return err; 124 + spin_lock_irq(&rtc->irq_lock); 125 + if (!rtc->uie_irq_active) { 126 + rtc->uie_irq_active = 1; 127 + rtc->stop_uie_polling = 0; 128 + rtc->oldsecs = tm.tm_sec; 129 + rtc->uie_task_active = 1; 130 + if (schedule_work(&rtc->uie_task) == 0) 131 + rtc->uie_task_active = 0; 132 + } 133 + rtc->irq_data = 0; 134 + spin_unlock_irq(&rtc->irq_lock); 135 + return 0; 136 + } 137 + 138 + int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled) 139 + { 140 + if (enabled) 141 + return set_uie(rtc); 142 + else 143 + return clear_uie(rtc); 144 + } 145 + EXPORT_SYMBOL(rtc_dev_update_irq_enable_emul); 146 + 147 + #endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */ 49 148 50 149 static ssize_t 51 150 rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) ··· 485 386 } 486 387 487 388 rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); 389 + 390 + #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL 391 + INIT_WORK(&rtc->uie_task, rtc_uie_task); 392 + setup_timer(&rtc->uie_timer, rtc_uie_timer, (unsigned long)rtc); 393 + #endif 488 394 489 395 cdev_init(&rtc->char_dev, &rtc_dev_fops); 490 396 rtc->char_dev.owner = rtc->owner;
+15
include/linux/rtc.h
··· 203 203 struct hrtimer pie_timer; /* sub second exp, so needs hrtimer */ 204 204 int pie_enabled; 205 205 struct work_struct irqwork; 206 + 207 + 208 + #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL 209 + struct work_struct uie_task; 210 + struct timer_list uie_timer; 211 + /* Those fields are protected by rtc->irq_lock */ 212 + unsigned int oldsecs; 213 + unsigned int uie_irq_active:1; 214 + unsigned int stop_uie_polling:1; 215 + unsigned int uie_task_active:1; 216 + unsigned int uie_timer_active:1; 217 + #endif 206 218 }; 207 219 #define to_rtc_device(d) container_of(d, struct rtc_device, dev) 208 220 ··· 247 235 struct rtc_task *task, int freq); 248 236 extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled); 249 237 extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled); 238 + extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, 239 + unsigned int enabled); 250 240 241 + void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode); 251 242 void rtc_aie_update_irq(void *private); 252 243 void rtc_uie_update_irq(void *private); 253 244 enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer);