aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-cmos.c
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-07-24 00:30:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-24 13:47:34 -0400
commit7e2a31da854dcf8324012a83a31b40bc11e52589 (patch)
treefb982e22f3d9ac6ec2fc67a96a297dc743ef67e6 /drivers/rtc/rtc-cmos.c
parent449321b39f6c6ebfa15d6da24f134240bd51db29 (diff)
rtc-cmos: avoid spurious irqs
This fixes kernel http://bugzilla.kernel.org/show_bug.cgi?id=11112 (bogus RTC update IRQs reported) for rtc-cmos, in two ways: - When HPET is stealing the IRQs, use the first IRQ to grab the seconds counter which will be monitored (instead of using whatever was previously in that memory); - In sane IRQ handling modes, scrub out old IRQ status before enabling IRQs. That latter is done by tightening up IRQ handling for rtc-cmos everywhere, also ensuring that when HPET is used it's the only thing triggering IRQ reports to userspace; net object shrink. Also fix a bogus HPET message related to its RTC emulation. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Report-by: W Unruh <unruh@physics.ubc.ca> Cc: Andrew Victor <avictor.za@gmail.com> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc/rtc-cmos.c')
-rw-r--r--drivers/rtc/rtc-cmos.c140
1 files changed, 63 insertions, 77 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index e9984650ea95..6ea349aba3ba 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -235,11 +235,56 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
235 return 0; 235 return 0;
236} 236}
237 237
238static void cmos_checkintr(struct cmos_rtc *cmos, unsigned char rtc_control)
239{
240 unsigned char rtc_intr;
241
242 /* NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
243 * allegedly some older rtcs need that to handle irqs properly
244 */
245 rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
246
247 if (is_hpet_enabled())
248 return;
249
250 rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
251 if (is_intr(rtc_intr))
252 rtc_update_irq(cmos->rtc, 1, rtc_intr);
253}
254
255static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask)
256{
257 unsigned char rtc_control;
258
259 /* flush any pending IRQ status, notably for update irqs,
260 * before we enable new IRQs
261 */
262 rtc_control = CMOS_READ(RTC_CONTROL);
263 cmos_checkintr(cmos, rtc_control);
264
265 rtc_control |= mask;
266 CMOS_WRITE(rtc_control, RTC_CONTROL);
267 hpet_set_rtc_irq_bit(mask);
268
269 cmos_checkintr(cmos, rtc_control);
270}
271
272static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask)
273{
274 unsigned char rtc_control;
275
276 rtc_control = CMOS_READ(RTC_CONTROL);
277 rtc_control &= ~mask;
278 CMOS_WRITE(rtc_control, RTC_CONTROL);
279 hpet_mask_rtc_irq_bit(mask);
280
281 cmos_checkintr(cmos, rtc_control);
282}
283
238static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t) 284static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
239{ 285{
240 struct cmos_rtc *cmos = dev_get_drvdata(dev); 286 struct cmos_rtc *cmos = dev_get_drvdata(dev);
241 unsigned char mon, mday, hrs, min, sec; 287 unsigned char mon, mday, hrs, min, sec;
242 unsigned char rtc_control, rtc_intr;
243 288
244 if (!is_valid_irq(cmos->irq)) 289 if (!is_valid_irq(cmos->irq))
245 return -EIO; 290 return -EIO;
@@ -266,15 +311,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
266 spin_lock_irq(&rtc_lock); 311 spin_lock_irq(&rtc_lock);
267 312
268 /* next rtc irq must not be from previous alarm setting */ 313 /* next rtc irq must not be from previous alarm setting */
269 rtc_control = CMOS_READ(RTC_CONTROL); 314 cmos_irq_disable(cmos, RTC_AIE);
270 rtc_control &= ~RTC_AIE;
271 CMOS_WRITE(rtc_control, RTC_CONTROL);
272 hpet_mask_rtc_irq_bit(RTC_AIE);
273
274 rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
275 rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
276 if (is_intr(rtc_intr))
277 rtc_update_irq(cmos->rtc, 1, rtc_intr);
278 315
279 /* update alarm */ 316 /* update alarm */
280 CMOS_WRITE(hrs, RTC_HOURS_ALARM); 317 CMOS_WRITE(hrs, RTC_HOURS_ALARM);
@@ -293,16 +330,8 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
293 */ 330 */
294 hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec); 331 hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
295 332
296 if (t->enabled) { 333 if (t->enabled)
297 rtc_control |= RTC_AIE; 334 cmos_irq_enable(cmos, RTC_AIE);
298 CMOS_WRITE(rtc_control, RTC_CONTROL);
299 hpet_set_rtc_irq_bit(RTC_AIE);
300
301 rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
302 rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
303 if (is_intr(rtc_intr))
304 rtc_update_irq(cmos->rtc, 1, rtc_intr);
305 }
306 335
307 spin_unlock_irq(&rtc_lock); 336 spin_unlock_irq(&rtc_lock);
308 337
@@ -335,28 +364,17 @@ static int cmos_irq_set_freq(struct device *dev, int freq)
335static int cmos_irq_set_state(struct device *dev, int enabled) 364static int cmos_irq_set_state(struct device *dev, int enabled)
336{ 365{
337 struct cmos_rtc *cmos = dev_get_drvdata(dev); 366 struct cmos_rtc *cmos = dev_get_drvdata(dev);
338 unsigned char rtc_control, rtc_intr;
339 unsigned long flags; 367 unsigned long flags;
340 368
341 if (!is_valid_irq(cmos->irq)) 369 if (!is_valid_irq(cmos->irq))
342 return -ENXIO; 370 return -ENXIO;
343 371
344 spin_lock_irqsave(&rtc_lock, flags); 372 spin_lock_irqsave(&rtc_lock, flags);
345 rtc_control = CMOS_READ(RTC_CONTROL);
346
347 if (enabled) {
348 rtc_control |= RTC_PIE;
349 hpet_set_rtc_irq_bit(RTC_PIE);
350 } else {
351 rtc_control &= ~RTC_PIE;
352 hpet_mask_rtc_irq_bit(RTC_PIE);
353 }
354 CMOS_WRITE(rtc_control, RTC_CONTROL);
355 373
356 rtc_intr = CMOS_READ(RTC_INTR_FLAGS); 374 if (enabled)
357 rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; 375 cmos_irq_enable(cmos, RTC_PIE);
358 if (is_intr(rtc_intr)) 376 else
359 rtc_update_irq(cmos->rtc, 1, rtc_intr); 377 cmos_irq_disable(cmos, RTC_PIE);
360 378
361 spin_unlock_irqrestore(&rtc_lock, flags); 379 spin_unlock_irqrestore(&rtc_lock, flags);
362 return 0; 380 return 0;
@@ -368,7 +386,6 @@ static int
368cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) 386cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
369{ 387{
370 struct cmos_rtc *cmos = dev_get_drvdata(dev); 388 struct cmos_rtc *cmos = dev_get_drvdata(dev);
371 unsigned char rtc_control, rtc_intr;
372 unsigned long flags; 389 unsigned long flags;
373 390
374 switch (cmd) { 391 switch (cmd) {
@@ -385,32 +402,20 @@ cmos_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
385 } 402 }
386 403
387 spin_lock_irqsave(&rtc_lock, flags); 404 spin_lock_irqsave(&rtc_lock, flags);
388 rtc_control = CMOS_READ(RTC_CONTROL);
389 switch (cmd) { 405 switch (cmd) {
390 case RTC_AIE_OFF: /* alarm off */ 406 case RTC_AIE_OFF: /* alarm off */
391 rtc_control &= ~RTC_AIE; 407 cmos_irq_disable(cmos, RTC_AIE);
392 hpet_mask_rtc_irq_bit(RTC_AIE);
393 break; 408 break;
394 case RTC_AIE_ON: /* alarm on */ 409 case RTC_AIE_ON: /* alarm on */
395 rtc_control |= RTC_AIE; 410 cmos_irq_enable(cmos, RTC_AIE);
396 hpet_set_rtc_irq_bit(RTC_AIE);
397 break; 411 break;
398 case RTC_UIE_OFF: /* update off */ 412 case RTC_UIE_OFF: /* update off */
399 rtc_control &= ~RTC_UIE; 413 cmos_irq_disable(cmos, RTC_UIE);
400 hpet_mask_rtc_irq_bit(RTC_UIE);
401 break; 414 break;
402 case RTC_UIE_ON: /* update on */ 415 case RTC_UIE_ON: /* update on */
403 rtc_control |= RTC_UIE; 416 cmos_irq_enable(cmos, RTC_UIE);
404 hpet_set_rtc_irq_bit(RTC_UIE);
405 break; 417 break;
406 } 418 }
407 CMOS_WRITE(rtc_control, RTC_CONTROL);
408
409 rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
410 rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
411 if (is_intr(rtc_intr))
412 rtc_update_irq(cmos->rtc, 1, rtc_intr);
413
414 spin_unlock_irqrestore(&rtc_lock, flags); 419 spin_unlock_irqrestore(&rtc_lock, flags);
415 return 0; 420 return 0;
416} 421}
@@ -571,7 +576,6 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
571 * alarm woke the system. 576 * alarm woke the system.
572 */ 577 */
573 if (irqstat & RTC_AIE) { 578 if (irqstat & RTC_AIE) {
574 rtc_control = CMOS_READ(RTC_CONTROL);
575 rtc_control &= ~RTC_AIE; 579 rtc_control &= ~RTC_AIE;
576 CMOS_WRITE(rtc_control, RTC_CONTROL); 580 CMOS_WRITE(rtc_control, RTC_CONTROL);
577 hpet_mask_rtc_irq_bit(RTC_AIE); 581 hpet_mask_rtc_irq_bit(RTC_AIE);
@@ -685,17 +689,10 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
685 hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq); 689 hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
686 CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT); 690 CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
687 691
688 /* disable irqs. 692 /* disable irqs */
689 * 693 cmos_irq_disable(&cmos_rtc, RTC_PIE | RTC_AIE | RTC_UIE);
690 * NOTE after changing RTC_xIE bits we always read INTR_FLAGS;
691 * allegedly some older rtcs need that to handle irqs properly
692 */
693 rtc_control = CMOS_READ(RTC_CONTROL);
694 rtc_control &= ~(RTC_PIE | RTC_AIE | RTC_UIE);
695 CMOS_WRITE(rtc_control, RTC_CONTROL);
696 hpet_mask_rtc_irq_bit(RTC_PIE | RTC_AIE | RTC_UIE);
697 694
698 CMOS_READ(RTC_INTR_FLAGS); 695 rtc_control = CMOS_READ(RTC_CONTROL);
699 696
700 spin_unlock_irq(&rtc_lock); 697 spin_unlock_irq(&rtc_lock);
701 698
@@ -768,15 +765,8 @@ cleanup0:
768 765
769static void cmos_do_shutdown(void) 766static void cmos_do_shutdown(void)
770{ 767{
771 unsigned char rtc_control;
772
773 spin_lock_irq(&rtc_lock); 768 spin_lock_irq(&rtc_lock);
774 rtc_control = CMOS_READ(RTC_CONTROL); 769 cmos_irq_disable(&cmos_rtc, RTC_IRQMASK);
775 rtc_control &= ~RTC_IRQMASK;
776 CMOS_WRITE(rtc_control, RTC_CONTROL);
777 hpet_mask_rtc_irq_bit(RTC_IRQMASK);
778
779 CMOS_READ(RTC_INTR_FLAGS);
780 spin_unlock_irq(&rtc_lock); 770 spin_unlock_irq(&rtc_lock);
781} 771}
782 772
@@ -817,7 +807,6 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
817 spin_lock_irq(&rtc_lock); 807 spin_lock_irq(&rtc_lock);
818 cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL); 808 cmos->suspend_ctrl = tmp = CMOS_READ(RTC_CONTROL);
819 if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) { 809 if (tmp & (RTC_PIE|RTC_AIE|RTC_UIE)) {
820 unsigned char irqstat;
821 unsigned char mask; 810 unsigned char mask;
822 811
823 if (do_wake) 812 if (do_wake)
@@ -828,10 +817,7 @@ static int cmos_suspend(struct device *dev, pm_message_t mesg)
828 CMOS_WRITE(tmp, RTC_CONTROL); 817 CMOS_WRITE(tmp, RTC_CONTROL);
829 hpet_mask_rtc_irq_bit(mask); 818 hpet_mask_rtc_irq_bit(mask);
830 819
831 irqstat = CMOS_READ(RTC_INTR_FLAGS); 820 cmos_checkintr(cmos, tmp);
832 irqstat &= (tmp & RTC_IRQMASK) | RTC_IRQF;
833 if (is_intr(irqstat))
834 rtc_update_irq(cmos->rtc, 1, irqstat);
835 } 821 }
836 spin_unlock_irq(&rtc_lock); 822 spin_unlock_irq(&rtc_lock);
837 823
@@ -875,7 +861,7 @@ static int cmos_resume(struct device *dev)
875 861
876 mask = CMOS_READ(RTC_INTR_FLAGS); 862 mask = CMOS_READ(RTC_INTR_FLAGS);
877 mask &= (tmp & RTC_IRQMASK) | RTC_IRQF; 863 mask &= (tmp & RTC_IRQMASK) | RTC_IRQF;
878 if (!is_intr(mask)) 864 if (!is_hpet_enabled() || !is_intr(mask))
879 break; 865 break;
880 866
881 /* force one-shot behavior if HPET blocked 867 /* force one-shot behavior if HPET blocked