diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-19 20:44:40 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-19 20:44:40 -0400 |
| commit | 7e6628e4bcb3b3546c625ec63ca724f28ab14f0c (patch) | |
| tree | 111a94cefa9d800ec5c5e59520f4b5d1880965d0 /kernel/time | |
| parent | 0f1bdc1815c4cb29b3cd71a7091b478e426faa0b (diff) | |
| parent | ab0e08f15d23628dd8d50bf6ce1a935a8840c7dc (diff) | |
Merge branch 'timers-clockevents-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-clockevents-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
x86: hpet: Cleanup the clockevents init and register code
x86: Convert PIT to clockevents_config_and_register()
clockevents: Provide interface to reconfigure an active clock event device
clockevents: Provide combined configure and register function
clockevents: Restructure clock_event_device members
clocksource: Get rid of the hardcoded 5 seconds sleep time limit
clocksource: Restructure clocksource struct members
Diffstat (limited to 'kernel/time')
| -rw-r--r-- | kernel/time/clockevents.c | 64 | ||||
| -rw-r--r-- | kernel/time/clocksource.c | 38 |
2 files changed, 83 insertions, 19 deletions
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 0d74b9ba90c8..22a9da9a9c96 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c | |||
| @@ -194,6 +194,70 @@ void clockevents_register_device(struct clock_event_device *dev) | |||
| 194 | } | 194 | } |
| 195 | EXPORT_SYMBOL_GPL(clockevents_register_device); | 195 | EXPORT_SYMBOL_GPL(clockevents_register_device); |
| 196 | 196 | ||
| 197 | static void clockevents_config(struct clock_event_device *dev, | ||
| 198 | u32 freq) | ||
| 199 | { | ||
| 200 | unsigned long sec; | ||
| 201 | |||
| 202 | if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT)) | ||
| 203 | return; | ||
| 204 | |||
| 205 | /* | ||
| 206 | * Calculate the maximum number of seconds we can sleep. Limit | ||
| 207 | * to 10 minutes for hardware which can program more than | ||
| 208 | * 32bit ticks so we still get reasonable conversion values. | ||
| 209 | */ | ||
| 210 | sec = dev->max_delta_ticks; | ||
| 211 | do_div(sec, freq); | ||
| 212 | if (!sec) | ||
| 213 | sec = 1; | ||
| 214 | else if (sec > 600 && dev->max_delta_ticks > UINT_MAX) | ||
| 215 | sec = 600; | ||
| 216 | |||
| 217 | clockevents_calc_mult_shift(dev, freq, sec); | ||
| 218 | dev->min_delta_ns = clockevent_delta2ns(dev->min_delta_ticks, dev); | ||
| 219 | dev->max_delta_ns = clockevent_delta2ns(dev->max_delta_ticks, dev); | ||
| 220 | } | ||
| 221 | |||
| 222 | /** | ||
| 223 | * clockevents_config_and_register - Configure and register a clock event device | ||
| 224 | * @dev: device to register | ||
| 225 | * @freq: The clock frequency | ||
| 226 | * @min_delta: The minimum clock ticks to program in oneshot mode | ||
| 227 | * @max_delta: The maximum clock ticks to program in oneshot mode | ||
| 228 | * | ||
| 229 | * min/max_delta can be 0 for devices which do not support oneshot mode. | ||
| 230 | */ | ||
| 231 | void clockevents_config_and_register(struct clock_event_device *dev, | ||
| 232 | u32 freq, unsigned long min_delta, | ||
| 233 | unsigned long max_delta) | ||
| 234 | { | ||
| 235 | dev->min_delta_ticks = min_delta; | ||
| 236 | dev->max_delta_ticks = max_delta; | ||
| 237 | clockevents_config(dev, freq); | ||
| 238 | clockevents_register_device(dev); | ||
| 239 | } | ||
| 240 | |||
| 241 | /** | ||
| 242 | * clockevents_update_freq - Update frequency and reprogram a clock event device. | ||
| 243 | * @dev: device to modify | ||
| 244 | * @freq: new device frequency | ||
| 245 | * | ||
| 246 | * Reconfigure and reprogram a clock event device in oneshot | ||
| 247 | * mode. Must be called on the cpu for which the device delivers per | ||
| 248 | * cpu timer events with interrupts disabled! Returns 0 on success, | ||
| 249 | * -ETIME when the event is in the past. | ||
| 250 | */ | ||
| 251 | int clockevents_update_freq(struct clock_event_device *dev, u32 freq) | ||
| 252 | { | ||
| 253 | clockevents_config(dev, freq); | ||
| 254 | |||
| 255 | if (dev->mode != CLOCK_EVT_MODE_ONESHOT) | ||
| 256 | return 0; | ||
| 257 | |||
| 258 | return clockevents_program_event(dev, dev->next_event, ktime_get()); | ||
| 259 | } | ||
| 260 | |||
| 197 | /* | 261 | /* |
| 198 | * Noop handler when we shut down an event device | 262 | * Noop handler when we shut down an event device |
| 199 | */ | 263 | */ |
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 0e17c10f8a9d..d9d5f8c885f6 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c | |||
| @@ -626,19 +626,6 @@ static void clocksource_enqueue(struct clocksource *cs) | |||
| 626 | list_add(&cs->list, entry); | 626 | list_add(&cs->list, entry); |
| 627 | } | 627 | } |
| 628 | 628 | ||
| 629 | |||
| 630 | /* | ||
| 631 | * Maximum time we expect to go between ticks. This includes idle | ||
| 632 | * tickless time. It provides the trade off between selecting a | ||
| 633 | * mult/shift pair that is very precise but can only handle a short | ||
| 634 | * period of time, vs. a mult/shift pair that can handle long periods | ||
| 635 | * of time but isn't as precise. | ||
| 636 | * | ||
| 637 | * This is a subsystem constant, and actual hardware limitations | ||
| 638 | * may override it (ie: clocksources that wrap every 3 seconds). | ||
| 639 | */ | ||
| 640 | #define MAX_UPDATE_LENGTH 5 /* Seconds */ | ||
| 641 | |||
| 642 | /** | 629 | /** |
| 643 | * __clocksource_updatefreq_scale - Used update clocksource with new freq | 630 | * __clocksource_updatefreq_scale - Used update clocksource with new freq |
| 644 | * @t: clocksource to be registered | 631 | * @t: clocksource to be registered |
| @@ -652,15 +639,28 @@ static void clocksource_enqueue(struct clocksource *cs) | |||
| 652 | */ | 639 | */ |
| 653 | void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) | 640 | void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq) |
| 654 | { | 641 | { |
| 642 | unsigned long sec; | ||
| 643 | |||
| 655 | /* | 644 | /* |
| 656 | * Ideally we want to use some of the limits used in | 645 | * Calc the maximum number of seconds which we can run before |
| 657 | * clocksource_max_deferment, to provide a more informed | 646 | * wrapping around. For clocksources which have a mask > 32bit |
| 658 | * MAX_UPDATE_LENGTH. But for now this just gets the | 647 | * we need to limit the max sleep time to have a good |
| 659 | * register interface working properly. | 648 | * conversion precision. 10 minutes is still a reasonable |
| 649 | * amount. That results in a shift value of 24 for a | ||
| 650 | * clocksource with mask >= 40bit and f >= 4GHz. That maps to | ||
| 651 | * ~ 0.06ppm granularity for NTP. We apply the same 12.5% | ||
| 652 | * margin as we do in clocksource_max_deferment() | ||
| 660 | */ | 653 | */ |
| 654 | sec = (cs->mask - (cs->mask >> 5)); | ||
| 655 | do_div(sec, freq); | ||
| 656 | do_div(sec, scale); | ||
| 657 | if (!sec) | ||
| 658 | sec = 1; | ||
| 659 | else if (sec > 600 && cs->mask > UINT_MAX) | ||
| 660 | sec = 600; | ||
| 661 | |||
| 661 | clocks_calc_mult_shift(&cs->mult, &cs->shift, freq, | 662 | clocks_calc_mult_shift(&cs->mult, &cs->shift, freq, |
| 662 | NSEC_PER_SEC/scale, | 663 | NSEC_PER_SEC / scale, sec * scale); |
| 663 | MAX_UPDATE_LENGTH*scale); | ||
| 664 | cs->max_idle_ns = clocksource_max_deferment(cs); | 664 | cs->max_idle_ns = clocksource_max_deferment(cs); |
| 665 | } | 665 | } |
| 666 | EXPORT_SYMBOL_GPL(__clocksource_updatefreq_scale); | 666 | EXPORT_SYMBOL_GPL(__clocksource_updatefreq_scale); |
