aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hpet.c
diff options
context:
space:
mode:
authorYasunori Goto <y-goto@jp.fujitsu.com>2009-04-02 19:58:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-02 22:05:01 -0400
commit303d379c54fc9ed553562e36c1cbd1791a3f5d17 (patch)
treefa16886ba42f97af18eed3f2b791f54ce7ee2b09 /drivers/char/hpet.c
parent1f80769ffd36e74357fe896dc43dddf1af1510f3 (diff)
hpet: fix the possibility of insane return value of hpet_calibrate() against SMI
hpet_calibrate() has a possibility of miss-calibration due to SMI. If SMI interrupts in the while loop of calibration, then return value will be big. This change calibrates until stabilizing by the return value with a small value. [akpm@linux-foundation.org: trivial style tweaks] Signed-off-by: Yasunori Goto <y-goto@jp.fujitsu.com> Acked-by: Clemens Ladisch <clemens@ladisch.de> Acked-by: Vojtech Pavlik <vojtech@suse.cz> Cc: Robert Picco <Robert.Picco@hp.com> Cc: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Cc: Ingo Molnar <mingo@elte.hu> Acked-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/hpet.c')
-rw-r--r--drivers/char/hpet.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 32b8bbf5003e..50dfa3bc71ce 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -713,7 +713,7 @@ static struct ctl_table_header *sysctl_header;
713 */ 713 */
714#define TICK_CALIBRATE (1000UL) 714#define TICK_CALIBRATE (1000UL)
715 715
716static unsigned long hpet_calibrate(struct hpets *hpetp) 716static unsigned long __hpet_calibrate(struct hpets *hpetp)
717{ 717{
718 struct hpet_timer __iomem *timer = NULL; 718 struct hpet_timer __iomem *timer = NULL;
719 unsigned long t, m, count, i, flags, start; 719 unsigned long t, m, count, i, flags, start;
@@ -750,6 +750,26 @@ static unsigned long hpet_calibrate(struct hpets *hpetp)
750 return (m - start) / i; 750 return (m - start) / i;
751} 751}
752 752
753static unsigned long hpet_calibrate(struct hpets *hpetp)
754{
755 unsigned long ret = -1;
756 unsigned long tmp;
757
758 /*
759 * Try to calibrate until return value becomes stable small value.
760 * If SMI interruption occurs in calibration loop, the return value
761 * will be big. This avoids its impact.
762 */
763 for ( ; ; ) {
764 tmp = __hpet_calibrate(hpetp);
765 if (ret <= tmp)
766 break;
767 ret = tmp;
768 }
769
770 return ret;
771}
772
753int hpet_alloc(struct hpet_data *hdp) 773int hpet_alloc(struct hpet_data *hdp)
754{ 774{
755 u64 cap, mcfg; 775 u64 cap, mcfg;