Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'timers-fixes-for-linus' of git://tesla.tglx.de/git/linux-2.6-tip

* 'timers-fixes-for-linus' of git://tesla.tglx.de/git/linux-2.6-tip:
rtc: twl: Fix registration vs. init order
rtc: Initialized rtc_time->tm_isdst
rtc: Fix RTC PIE frequency limit
rtc: rtc-twl: Remove lockdep related local_irq_enable()
rtc: rtc-twl: Switch to using threaded irq
rtc: ep93xx: Fix 'rtc' may be used uninitialized warning
alarmtimers: Avoid possible denial of service with high freq periodic timers
alarmtimers: Memset itimerspec passed into alarm_timer_get
alarmtimers: Avoid possible null pointer traversal

+48 -50
+8 -8
drivers/rtc/rtc-ep93xx.c
··· 36 36 */ 37 37 struct ep93xx_rtc { 38 38 void __iomem *mmio_base; 39 + struct rtc_device *rtc; 39 40 }; 40 41 41 42 static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload, ··· 131 130 { 132 131 struct ep93xx_rtc *ep93xx_rtc; 133 132 struct resource *res; 134 - struct rtc_device *rtc; 135 133 int err; 136 134 137 135 ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL); ··· 151 151 return -ENXIO; 152 152 153 153 pdev->dev.platform_data = ep93xx_rtc; 154 - platform_set_drvdata(pdev, rtc); 154 + platform_set_drvdata(pdev, ep93xx_rtc); 155 155 156 - rtc = rtc_device_register(pdev->name, 156 + ep93xx_rtc->rtc = rtc_device_register(pdev->name, 157 157 &pdev->dev, &ep93xx_rtc_ops, THIS_MODULE); 158 - if (IS_ERR(rtc)) { 159 - err = PTR_ERR(rtc); 158 + if (IS_ERR(ep93xx_rtc->rtc)) { 159 + err = PTR_ERR(ep93xx_rtc->rtc); 160 160 goto exit; 161 161 } 162 162 ··· 167 167 return 0; 168 168 169 169 fail: 170 - rtc_device_unregister(rtc); 170 + rtc_device_unregister(ep93xx_rtc->rtc); 171 171 exit: 172 172 platform_set_drvdata(pdev, NULL); 173 173 pdev->dev.platform_data = NULL; ··· 176 176 177 177 static int __exit ep93xx_rtc_remove(struct platform_device *pdev) 178 178 { 179 - struct rtc_device *rtc = platform_get_drvdata(pdev); 179 + struct ep93xx_rtc *ep93xx_rtc = platform_get_drvdata(pdev); 180 180 181 181 sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files); 182 182 platform_set_drvdata(pdev, NULL); 183 - rtc_device_unregister(rtc); 183 + rtc_device_unregister(ep93xx_rtc->rtc); 184 184 pdev->dev.platform_data = NULL; 185 185 186 186 return 0;
+2
drivers/rtc/rtc-lib.c
··· 85 85 time -= tm->tm_hour * 3600; 86 86 tm->tm_min = time / 60; 87 87 tm->tm_sec = time - tm->tm_min * 60; 88 + 89 + tm->tm_isdst = 0; 88 90 } 89 91 EXPORT_SYMBOL(rtc_time_to_tm); 90 92
+25 -37
drivers/rtc/rtc-twl.c
··· 362 362 int res; 363 363 u8 rd_reg; 364 364 365 - #ifdef CONFIG_LOCKDEP 366 - /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which 367 - * we don't want and can't tolerate. Although it might be 368 - * friendlier not to borrow this thread context... 369 - */ 370 - local_irq_enable(); 371 - #endif 372 - 373 365 res = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); 374 366 if (res) 375 367 goto out; ··· 420 428 static int __devinit twl_rtc_probe(struct platform_device *pdev) 421 429 { 422 430 struct rtc_device *rtc; 423 - int ret = 0; 431 + int ret = -EINVAL; 424 432 int irq = platform_get_irq(pdev, 0); 425 433 u8 rd_reg; 426 434 427 435 if (irq <= 0) 428 - return -EINVAL; 429 - 430 - rtc = rtc_device_register(pdev->name, 431 - &pdev->dev, &twl_rtc_ops, THIS_MODULE); 432 - if (IS_ERR(rtc)) { 433 - ret = PTR_ERR(rtc); 434 - dev_err(&pdev->dev, "can't register RTC device, err %ld\n", 435 - PTR_ERR(rtc)); 436 - goto out0; 437 - 438 - } 439 - 440 - platform_set_drvdata(pdev, rtc); 436 + goto out1; 441 437 442 438 ret = twl_rtc_read_u8(&rd_reg, REG_RTC_STATUS_REG); 443 439 if (ret < 0) ··· 442 462 if (ret < 0) 443 463 goto out1; 444 464 445 - ret = request_irq(irq, twl_rtc_interrupt, 446 - IRQF_TRIGGER_RISING, 447 - dev_name(&rtc->dev), rtc); 448 - if (ret < 0) { 449 - dev_err(&pdev->dev, "IRQ is not free.\n"); 450 - goto out1; 451 - } 452 - 453 465 if (twl_class_is_6030()) { 454 466 twl6030_interrupt_unmask(TWL6030_RTC_INT_MASK, 455 467 REG_INT_MSK_LINE_A); ··· 452 480 /* Check RTC module status, Enable if it is off */ 453 481 ret = twl_rtc_read_u8(&rd_reg, REG_RTC_CTRL_REG); 454 482 if (ret < 0) 455 - goto out2; 483 + goto out1; 456 484 457 485 if (!(rd_reg & BIT_RTC_CTRL_REG_STOP_RTC_M)) { 458 486 dev_info(&pdev->dev, "Enabling TWL-RTC.\n"); 459 487 rd_reg = BIT_RTC_CTRL_REG_STOP_RTC_M; 460 488 ret = twl_rtc_write_u8(rd_reg, REG_RTC_CTRL_REG); 461 489 if (ret < 0) 462 - goto out2; 490 + goto out1; 463 491 } 464 492 465 493 /* init cached IRQ enable bits */ 466 494 ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); 467 495 if (ret < 0) 468 - goto out2; 496 + goto out1; 469 497 470 - return ret; 498 + rtc = rtc_device_register(pdev->name, 499 + &pdev->dev, &twl_rtc_ops, THIS_MODULE); 500 + if (IS_ERR(rtc)) { 501 + ret = PTR_ERR(rtc); 502 + dev_err(&pdev->dev, "can't register RTC device, err %ld\n", 503 + PTR_ERR(rtc)); 504 + goto out1; 505 + } 506 + 507 + ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt, 508 + IRQF_TRIGGER_RISING, 509 + dev_name(&rtc->dev), rtc); 510 + if (ret < 0) { 511 + dev_err(&pdev->dev, "IRQ is not free.\n"); 512 + goto out2; 513 + } 514 + 515 + platform_set_drvdata(pdev, rtc); 516 + return 0; 471 517 472 518 out2: 473 - free_irq(irq, rtc); 474 - out1: 475 519 rtc_device_unregister(rtc); 476 - out0: 520 + out1: 477 521 return ret; 478 522 } 479 523
+13 -5
kernel/time/alarmtimer.c
··· 441 441 static void alarm_timer_get(struct k_itimer *timr, 442 442 struct itimerspec *cur_setting) 443 443 { 444 + memset(cur_setting, 0, sizeof(struct itimerspec)); 445 + 444 446 cur_setting->it_interval = 445 447 ktime_to_timespec(timr->it.alarmtimer.period); 446 448 cur_setting->it_value = ··· 481 479 if (!rtcdev) 482 480 return -ENOTSUPP; 483 481 484 - /* Save old values */ 485 - old_setting->it_interval = 486 - ktime_to_timespec(timr->it.alarmtimer.period); 487 - old_setting->it_value = 488 - ktime_to_timespec(timr->it.alarmtimer.node.expires); 482 + /* 483 + * XXX HACK! Currently we can DOS a system if the interval 484 + * period on alarmtimers is too small. Cap the interval here 485 + * to 100us and solve this properly in a future patch! -jstultz 486 + */ 487 + if ((new_setting->it_interval.tv_sec == 0) && 488 + (new_setting->it_interval.tv_nsec < 100000)) 489 + new_setting->it_interval.tv_nsec = 100000; 490 + 491 + if (old_setting) 492 + alarm_timer_get(timr, old_setting); 489 493 490 494 /* If the timer was already set, cancel it */ 491 495 alarm_cancel(&timr->it.alarmtimer);