diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cpuset.c | 37 | ||||
-rw-r--r-- | kernel/time/clockevents.c | 15 | ||||
-rw-r--r-- | kernel/time/ntp.c | 2 | ||||
-rw-r--r-- | kernel/time/tick-broadcast.c | 85 | ||||
-rw-r--r-- | kernel/time/tick-common.c | 5 | ||||
-rw-r--r-- | kernel/time/tick-internal.h | 4 | ||||
-rw-r--r-- | kernel/time/tick-oneshot.c | 44 |
7 files changed, 134 insertions, 58 deletions
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index f227bc172690..827cd9adccb2 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -843,37 +843,25 @@ static void cpuset_change_cpumask(struct task_struct *tsk, | |||
843 | /** | 843 | /** |
844 | * update_tasks_cpumask - Update the cpumasks of tasks in the cpuset. | 844 | * update_tasks_cpumask - Update the cpumasks of tasks in the cpuset. |
845 | * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed | 845 | * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed |
846 | * @heap: if NULL, defer allocating heap memory to cgroup_scan_tasks() | ||
846 | * | 847 | * |
847 | * Called with cgroup_mutex held | 848 | * Called with cgroup_mutex held |
848 | * | 849 | * |
849 | * The cgroup_scan_tasks() function will scan all the tasks in a cgroup, | 850 | * The cgroup_scan_tasks() function will scan all the tasks in a cgroup, |
850 | * calling callback functions for each. | 851 | * calling callback functions for each. |
851 | * | 852 | * |
852 | * Return 0 if successful, -errno if not. | 853 | * No return value. It's guaranteed that cgroup_scan_tasks() always returns 0 |
854 | * if @heap != NULL. | ||
853 | */ | 855 | */ |
854 | static int update_tasks_cpumask(struct cpuset *cs) | 856 | static void update_tasks_cpumask(struct cpuset *cs, struct ptr_heap *heap) |
855 | { | 857 | { |
856 | struct cgroup_scanner scan; | 858 | struct cgroup_scanner scan; |
857 | struct ptr_heap heap; | ||
858 | int retval; | ||
859 | |||
860 | /* | ||
861 | * cgroup_scan_tasks() will initialize heap->gt for us. | ||
862 | * heap_init() is still needed here for we should not change | ||
863 | * cs->cpus_allowed when heap_init() fails. | ||
864 | */ | ||
865 | retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL); | ||
866 | if (retval) | ||
867 | return retval; | ||
868 | 859 | ||
869 | scan.cg = cs->css.cgroup; | 860 | scan.cg = cs->css.cgroup; |
870 | scan.test_task = cpuset_test_cpumask; | 861 | scan.test_task = cpuset_test_cpumask; |
871 | scan.process_task = cpuset_change_cpumask; | 862 | scan.process_task = cpuset_change_cpumask; |
872 | scan.heap = &heap; | 863 | scan.heap = heap; |
873 | retval = cgroup_scan_tasks(&scan); | 864 | cgroup_scan_tasks(&scan); |
874 | |||
875 | heap_free(&heap); | ||
876 | return retval; | ||
877 | } | 865 | } |
878 | 866 | ||
879 | /** | 867 | /** |
@@ -883,6 +871,7 @@ static int update_tasks_cpumask(struct cpuset *cs) | |||
883 | */ | 871 | */ |
884 | static int update_cpumask(struct cpuset *cs, const char *buf) | 872 | static int update_cpumask(struct cpuset *cs, const char *buf) |
885 | { | 873 | { |
874 | struct ptr_heap heap; | ||
886 | struct cpuset trialcs; | 875 | struct cpuset trialcs; |
887 | int retval; | 876 | int retval; |
888 | int is_load_balanced; | 877 | int is_load_balanced; |
@@ -917,6 +906,10 @@ static int update_cpumask(struct cpuset *cs, const char *buf) | |||
917 | if (cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed)) | 906 | if (cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed)) |
918 | return 0; | 907 | return 0; |
919 | 908 | ||
909 | retval = heap_init(&heap, PAGE_SIZE, GFP_KERNEL, NULL); | ||
910 | if (retval) | ||
911 | return retval; | ||
912 | |||
920 | is_load_balanced = is_sched_load_balance(&trialcs); | 913 | is_load_balanced = is_sched_load_balance(&trialcs); |
921 | 914 | ||
922 | mutex_lock(&callback_mutex); | 915 | mutex_lock(&callback_mutex); |
@@ -927,9 +920,9 @@ static int update_cpumask(struct cpuset *cs, const char *buf) | |||
927 | * Scan tasks in the cpuset, and update the cpumasks of any | 920 | * Scan tasks in the cpuset, and update the cpumasks of any |
928 | * that need an update. | 921 | * that need an update. |
929 | */ | 922 | */ |
930 | retval = update_tasks_cpumask(cs); | 923 | update_tasks_cpumask(cs, &heap); |
931 | if (retval < 0) | 924 | |
932 | return retval; | 925 | heap_free(&heap); |
933 | 926 | ||
934 | if (is_load_balanced) | 927 | if (is_load_balanced) |
935 | async_rebuild_sched_domains(); | 928 | async_rebuild_sched_domains(); |
@@ -1965,7 +1958,7 @@ static void scan_for_empty_cpusets(const struct cpuset *root) | |||
1965 | nodes_empty(cp->mems_allowed)) | 1958 | nodes_empty(cp->mems_allowed)) |
1966 | remove_tasks_in_empty_cpuset(cp); | 1959 | remove_tasks_in_empty_cpuset(cp); |
1967 | else { | 1960 | else { |
1968 | update_tasks_cpumask(cp); | 1961 | update_tasks_cpumask(cp, NULL); |
1969 | update_tasks_nodemask(cp, &oldmems); | 1962 | update_tasks_nodemask(cp, &oldmems); |
1970 | } | 1963 | } |
1971 | } | 1964 | } |
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 3d1e3e1a1971..f8d968063cea 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c | |||
@@ -72,6 +72,16 @@ void clockevents_set_mode(struct clock_event_device *dev, | |||
72 | } | 72 | } |
73 | 73 | ||
74 | /** | 74 | /** |
75 | * clockevents_shutdown - shutdown the device and clear next_event | ||
76 | * @dev: device to shutdown | ||
77 | */ | ||
78 | void clockevents_shutdown(struct clock_event_device *dev) | ||
79 | { | ||
80 | clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN); | ||
81 | dev->next_event.tv64 = KTIME_MAX; | ||
82 | } | ||
83 | |||
84 | /** | ||
75 | * clockevents_program_event - Reprogram the clock event device. | 85 | * clockevents_program_event - Reprogram the clock event device. |
76 | * @expires: absolute expiry time (monotonic clock) | 86 | * @expires: absolute expiry time (monotonic clock) |
77 | * | 87 | * |
@@ -177,7 +187,7 @@ void clockevents_register_device(struct clock_event_device *dev) | |||
177 | /* | 187 | /* |
178 | * Noop handler when we shut down an event device | 188 | * Noop handler when we shut down an event device |
179 | */ | 189 | */ |
180 | static void clockevents_handle_noop(struct clock_event_device *dev) | 190 | void clockevents_handle_noop(struct clock_event_device *dev) |
181 | { | 191 | { |
182 | } | 192 | } |
183 | 193 | ||
@@ -199,7 +209,6 @@ void clockevents_exchange_device(struct clock_event_device *old, | |||
199 | * released list and do a notify add later. | 209 | * released list and do a notify add later. |
200 | */ | 210 | */ |
201 | if (old) { | 211 | if (old) { |
202 | old->event_handler = clockevents_handle_noop; | ||
203 | clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); | 212 | clockevents_set_mode(old, CLOCK_EVT_MODE_UNUSED); |
204 | list_del(&old->list); | 213 | list_del(&old->list); |
205 | list_add(&old->list, &clockevents_released); | 214 | list_add(&old->list, &clockevents_released); |
@@ -207,7 +216,7 @@ void clockevents_exchange_device(struct clock_event_device *old, | |||
207 | 216 | ||
208 | if (new) { | 217 | if (new) { |
209 | BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED); | 218 | BUG_ON(new->mode != CLOCK_EVT_MODE_UNUSED); |
210 | clockevents_set_mode(new, CLOCK_EVT_MODE_SHUTDOWN); | 219 | clockevents_shutdown(new); |
211 | } | 220 | } |
212 | local_irq_restore(flags); | 221 | local_irq_restore(flags); |
213 | } | 222 | } |
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 5125ddd8196b..1ad46f3df6e7 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -245,7 +245,7 @@ static void sync_cmos_clock(unsigned long dummy) | |||
245 | if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) | 245 | if (abs(now.tv_nsec - (NSEC_PER_SEC / 2)) <= tick_nsec / 2) |
246 | fail = update_persistent_clock(now); | 246 | fail = update_persistent_clock(now); |
247 | 247 | ||
248 | next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec; | 248 | next.tv_nsec = (NSEC_PER_SEC / 2) - now.tv_nsec - (TICK_NSEC / 2); |
249 | if (next.tv_nsec <= 0) | 249 | if (next.tv_nsec <= 0) |
250 | next.tv_nsec += NSEC_PER_SEC; | 250 | next.tv_nsec += NSEC_PER_SEC; |
251 | 251 | ||
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index 31463d370b94..f1f3eee28113 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c | |||
@@ -175,6 +175,8 @@ static void tick_do_periodic_broadcast(void) | |||
175 | */ | 175 | */ |
176 | static void tick_handle_periodic_broadcast(struct clock_event_device *dev) | 176 | static void tick_handle_periodic_broadcast(struct clock_event_device *dev) |
177 | { | 177 | { |
178 | ktime_t next; | ||
179 | |||
178 | tick_do_periodic_broadcast(); | 180 | tick_do_periodic_broadcast(); |
179 | 181 | ||
180 | /* | 182 | /* |
@@ -185,10 +187,13 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) | |||
185 | 187 | ||
186 | /* | 188 | /* |
187 | * Setup the next period for devices, which do not have | 189 | * Setup the next period for devices, which do not have |
188 | * periodic mode: | 190 | * periodic mode. We read dev->next_event first and add to it |
191 | * when the event alrady expired. clockevents_program_event() | ||
192 | * sets dev->next_event only when the event is really | ||
193 | * programmed to the device. | ||
189 | */ | 194 | */ |
190 | for (;;) { | 195 | for (next = dev->next_event; ;) { |
191 | ktime_t next = ktime_add(dev->next_event, tick_period); | 196 | next = ktime_add(next, tick_period); |
192 | 197 | ||
193 | if (!clockevents_program_event(dev, next, ktime_get())) | 198 | if (!clockevents_program_event(dev, next, ktime_get())) |
194 | return; | 199 | return; |
@@ -205,7 +210,7 @@ static void tick_do_broadcast_on_off(void *why) | |||
205 | struct clock_event_device *bc, *dev; | 210 | struct clock_event_device *bc, *dev; |
206 | struct tick_device *td; | 211 | struct tick_device *td; |
207 | unsigned long flags, *reason = why; | 212 | unsigned long flags, *reason = why; |
208 | int cpu; | 213 | int cpu, bc_stopped; |
209 | 214 | ||
210 | spin_lock_irqsave(&tick_broadcast_lock, flags); | 215 | spin_lock_irqsave(&tick_broadcast_lock, flags); |
211 | 216 | ||
@@ -223,14 +228,15 @@ static void tick_do_broadcast_on_off(void *why) | |||
223 | if (!tick_device_is_functional(dev)) | 228 | if (!tick_device_is_functional(dev)) |
224 | goto out; | 229 | goto out; |
225 | 230 | ||
231 | bc_stopped = cpus_empty(tick_broadcast_mask); | ||
232 | |||
226 | switch (*reason) { | 233 | switch (*reason) { |
227 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: | 234 | case CLOCK_EVT_NOTIFY_BROADCAST_ON: |
228 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: | 235 | case CLOCK_EVT_NOTIFY_BROADCAST_FORCE: |
229 | if (!cpu_isset(cpu, tick_broadcast_mask)) { | 236 | if (!cpu_isset(cpu, tick_broadcast_mask)) { |
230 | cpu_set(cpu, tick_broadcast_mask); | 237 | cpu_set(cpu, tick_broadcast_mask); |
231 | if (td->mode == TICKDEV_MODE_PERIODIC) | 238 | if (td->mode == TICKDEV_MODE_PERIODIC) |
232 | clockevents_set_mode(dev, | 239 | clockevents_shutdown(dev); |
233 | CLOCK_EVT_MODE_SHUTDOWN); | ||
234 | } | 240 | } |
235 | if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE) | 241 | if (*reason == CLOCK_EVT_NOTIFY_BROADCAST_FORCE) |
236 | tick_broadcast_force = 1; | 242 | tick_broadcast_force = 1; |
@@ -245,9 +251,10 @@ static void tick_do_broadcast_on_off(void *why) | |||
245 | break; | 251 | break; |
246 | } | 252 | } |
247 | 253 | ||
248 | if (cpus_empty(tick_broadcast_mask)) | 254 | if (cpus_empty(tick_broadcast_mask)) { |
249 | clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); | 255 | if (!bc_stopped) |
250 | else { | 256 | clockevents_shutdown(bc); |
257 | } else if (bc_stopped) { | ||
251 | if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) | 258 | if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) |
252 | tick_broadcast_start_periodic(bc); | 259 | tick_broadcast_start_periodic(bc); |
253 | else | 260 | else |
@@ -298,7 +305,7 @@ void tick_shutdown_broadcast(unsigned int *cpup) | |||
298 | 305 | ||
299 | if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { | 306 | if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { |
300 | if (bc && cpus_empty(tick_broadcast_mask)) | 307 | if (bc && cpus_empty(tick_broadcast_mask)) |
301 | clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); | 308 | clockevents_shutdown(bc); |
302 | } | 309 | } |
303 | 310 | ||
304 | spin_unlock_irqrestore(&tick_broadcast_lock, flags); | 311 | spin_unlock_irqrestore(&tick_broadcast_lock, flags); |
@@ -313,7 +320,7 @@ void tick_suspend_broadcast(void) | |||
313 | 320 | ||
314 | bc = tick_broadcast_device.evtdev; | 321 | bc = tick_broadcast_device.evtdev; |
315 | if (bc) | 322 | if (bc) |
316 | clockevents_set_mode(bc, CLOCK_EVT_MODE_SHUTDOWN); | 323 | clockevents_shutdown(bc); |
317 | 324 | ||
318 | spin_unlock_irqrestore(&tick_broadcast_lock, flags); | 325 | spin_unlock_irqrestore(&tick_broadcast_lock, flags); |
319 | } | 326 | } |
@@ -364,16 +371,8 @@ cpumask_t *tick_get_broadcast_oneshot_mask(void) | |||
364 | static int tick_broadcast_set_event(ktime_t expires, int force) | 371 | static int tick_broadcast_set_event(ktime_t expires, int force) |
365 | { | 372 | { |
366 | struct clock_event_device *bc = tick_broadcast_device.evtdev; | 373 | struct clock_event_device *bc = tick_broadcast_device.evtdev; |
367 | ktime_t now = ktime_get(); | 374 | |
368 | int res; | 375 | return tick_dev_program_event(bc, expires, force); |
369 | |||
370 | for(;;) { | ||
371 | res = clockevents_program_event(bc, expires, now); | ||
372 | if (!res || !force) | ||
373 | return res; | ||
374 | now = ktime_get(); | ||
375 | expires = ktime_add(now, ktime_set(0, bc->min_delta_ns)); | ||
376 | } | ||
377 | } | 376 | } |
378 | 377 | ||
379 | int tick_resume_broadcast_oneshot(struct clock_event_device *bc) | 378 | int tick_resume_broadcast_oneshot(struct clock_event_device *bc) |
@@ -491,14 +490,52 @@ static void tick_broadcast_clear_oneshot(int cpu) | |||
491 | cpu_clear(cpu, tick_broadcast_oneshot_mask); | 490 | cpu_clear(cpu, tick_broadcast_oneshot_mask); |
492 | } | 491 | } |
493 | 492 | ||
493 | static void tick_broadcast_init_next_event(cpumask_t *mask, ktime_t expires) | ||
494 | { | ||
495 | struct tick_device *td; | ||
496 | int cpu; | ||
497 | |||
498 | for_each_cpu_mask_nr(cpu, *mask) { | ||
499 | td = &per_cpu(tick_cpu_device, cpu); | ||
500 | if (td->evtdev) | ||
501 | td->evtdev->next_event = expires; | ||
502 | } | ||
503 | } | ||
504 | |||
494 | /** | 505 | /** |
495 | * tick_broadcast_setup_oneshot - setup the broadcast device | 506 | * tick_broadcast_setup_oneshot - setup the broadcast device |
496 | */ | 507 | */ |
497 | void tick_broadcast_setup_oneshot(struct clock_event_device *bc) | 508 | void tick_broadcast_setup_oneshot(struct clock_event_device *bc) |
498 | { | 509 | { |
499 | bc->event_handler = tick_handle_oneshot_broadcast; | 510 | /* Set it up only once ! */ |
500 | clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); | 511 | if (bc->event_handler != tick_handle_oneshot_broadcast) { |
501 | bc->next_event.tv64 = KTIME_MAX; | 512 | int was_periodic = bc->mode == CLOCK_EVT_MODE_PERIODIC; |
513 | int cpu = smp_processor_id(); | ||
514 | cpumask_t mask; | ||
515 | |||
516 | bc->event_handler = tick_handle_oneshot_broadcast; | ||
517 | clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); | ||
518 | |||
519 | /* Take the do_timer update */ | ||
520 | tick_do_timer_cpu = cpu; | ||
521 | |||
522 | /* | ||
523 | * We must be careful here. There might be other CPUs | ||
524 | * waiting for periodic broadcast. We need to set the | ||
525 | * oneshot_mask bits for those and program the | ||
526 | * broadcast device to fire. | ||
527 | */ | ||
528 | mask = tick_broadcast_mask; | ||
529 | cpu_clear(cpu, mask); | ||
530 | cpus_or(tick_broadcast_oneshot_mask, | ||
531 | tick_broadcast_oneshot_mask, mask); | ||
532 | |||
533 | if (was_periodic && !cpus_empty(mask)) { | ||
534 | tick_broadcast_init_next_event(&mask, tick_next_period); | ||
535 | tick_broadcast_set_event(tick_next_period, 1); | ||
536 | } else | ||
537 | bc->next_event.tv64 = KTIME_MAX; | ||
538 | } | ||
502 | } | 539 | } |
503 | 540 | ||
504 | /* | 541 | /* |
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 80c4336f4188..019315ebf9de 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
@@ -161,6 +161,7 @@ static void tick_setup_device(struct tick_device *td, | |||
161 | } else { | 161 | } else { |
162 | handler = td->evtdev->event_handler; | 162 | handler = td->evtdev->event_handler; |
163 | next_event = td->evtdev->next_event; | 163 | next_event = td->evtdev->next_event; |
164 | td->evtdev->event_handler = clockevents_handle_noop; | ||
164 | } | 165 | } |
165 | 166 | ||
166 | td->evtdev = newdev; | 167 | td->evtdev = newdev; |
@@ -248,7 +249,7 @@ static int tick_check_new_device(struct clock_event_device *newdev) | |||
248 | * not give it back to the clockevents layer ! | 249 | * not give it back to the clockevents layer ! |
249 | */ | 250 | */ |
250 | if (tick_is_broadcast_device(curdev)) { | 251 | if (tick_is_broadcast_device(curdev)) { |
251 | clockevents_set_mode(curdev, CLOCK_EVT_MODE_SHUTDOWN); | 252 | clockevents_shutdown(curdev); |
252 | curdev = NULL; | 253 | curdev = NULL; |
253 | } | 254 | } |
254 | clockevents_exchange_device(curdev, newdev); | 255 | clockevents_exchange_device(curdev, newdev); |
@@ -310,7 +311,7 @@ static void tick_suspend(void) | |||
310 | unsigned long flags; | 311 | unsigned long flags; |
311 | 312 | ||
312 | spin_lock_irqsave(&tick_device_lock, flags); | 313 | spin_lock_irqsave(&tick_device_lock, flags); |
313 | clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_SHUTDOWN); | 314 | clockevents_shutdown(td->evtdev); |
314 | spin_unlock_irqrestore(&tick_device_lock, flags); | 315 | spin_unlock_irqrestore(&tick_device_lock, flags); |
315 | } | 316 | } |
316 | 317 | ||
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index f13f2b7f4fd4..6e9db9734aa6 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h | |||
@@ -10,6 +10,8 @@ extern int tick_do_timer_cpu __read_mostly; | |||
10 | extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast); | 10 | extern void tick_setup_periodic(struct clock_event_device *dev, int broadcast); |
11 | extern void tick_handle_periodic(struct clock_event_device *dev); | 11 | extern void tick_handle_periodic(struct clock_event_device *dev); |
12 | 12 | ||
13 | extern void clockevents_shutdown(struct clock_event_device *dev); | ||
14 | |||
13 | /* | 15 | /* |
14 | * NO_HZ / high resolution timer shared code | 16 | * NO_HZ / high resolution timer shared code |
15 | */ | 17 | */ |
@@ -17,6 +19,8 @@ extern void tick_handle_periodic(struct clock_event_device *dev); | |||
17 | extern void tick_setup_oneshot(struct clock_event_device *newdev, | 19 | extern void tick_setup_oneshot(struct clock_event_device *newdev, |
18 | void (*handler)(struct clock_event_device *), | 20 | void (*handler)(struct clock_event_device *), |
19 | ktime_t nextevt); | 21 | ktime_t nextevt); |
22 | extern int tick_dev_program_event(struct clock_event_device *dev, | ||
23 | ktime_t expires, int force); | ||
20 | extern int tick_program_event(ktime_t expires, int force); | 24 | extern int tick_program_event(ktime_t expires, int force); |
21 | extern void tick_oneshot_notify(void); | 25 | extern void tick_oneshot_notify(void); |
22 | extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *)); | 26 | extern int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *)); |
diff --git a/kernel/time/tick-oneshot.c b/kernel/time/tick-oneshot.c index 450c04935b66..2e8de678e767 100644 --- a/kernel/time/tick-oneshot.c +++ b/kernel/time/tick-oneshot.c | |||
@@ -23,24 +23,56 @@ | |||
23 | #include "tick-internal.h" | 23 | #include "tick-internal.h" |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * tick_program_event | 26 | * tick_program_event internal worker function |
27 | */ | 27 | */ |
28 | int tick_program_event(ktime_t expires, int force) | 28 | int tick_dev_program_event(struct clock_event_device *dev, ktime_t expires, |
29 | int force) | ||
29 | { | 30 | { |
30 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; | ||
31 | ktime_t now = ktime_get(); | 31 | ktime_t now = ktime_get(); |
32 | int i; | ||
32 | 33 | ||
33 | while (1) { | 34 | for (i = 0;;) { |
34 | int ret = clockevents_program_event(dev, expires, now); | 35 | int ret = clockevents_program_event(dev, expires, now); |
35 | 36 | ||
36 | if (!ret || !force) | 37 | if (!ret || !force) |
37 | return ret; | 38 | return ret; |
39 | |||
40 | /* | ||
41 | * We tried 2 times to program the device with the given | ||
42 | * min_delta_ns. If that's not working then we double it | ||
43 | * and emit a warning. | ||
44 | */ | ||
45 | if (++i > 2) { | ||
46 | /* Increase the min. delta and try again */ | ||
47 | if (!dev->min_delta_ns) | ||
48 | dev->min_delta_ns = 5000; | ||
49 | else | ||
50 | dev->min_delta_ns += dev->min_delta_ns >> 1; | ||
51 | |||
52 | printk(KERN_WARNING | ||
53 | "CE: %s increasing min_delta_ns to %lu nsec\n", | ||
54 | dev->name ? dev->name : "?", | ||
55 | dev->min_delta_ns << 1); | ||
56 | |||
57 | i = 0; | ||
58 | } | ||
59 | |||
38 | now = ktime_get(); | 60 | now = ktime_get(); |
39 | expires = ktime_add(now, ktime_set(0, dev->min_delta_ns)); | 61 | expires = ktime_add_ns(now, dev->min_delta_ns); |
40 | } | 62 | } |
41 | } | 63 | } |
42 | 64 | ||
43 | /** | 65 | /** |
66 | * tick_program_event | ||
67 | */ | ||
68 | int tick_program_event(ktime_t expires, int force) | ||
69 | { | ||
70 | struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev; | ||
71 | |||
72 | return tick_dev_program_event(dev, expires, force); | ||
73 | } | ||
74 | |||
75 | /** | ||
44 | * tick_resume_onshot - resume oneshot mode | 76 | * tick_resume_onshot - resume oneshot mode |
45 | */ | 77 | */ |
46 | void tick_resume_oneshot(void) | 78 | void tick_resume_oneshot(void) |
@@ -61,7 +93,7 @@ void tick_setup_oneshot(struct clock_event_device *newdev, | |||
61 | { | 93 | { |
62 | newdev->event_handler = handler; | 94 | newdev->event_handler = handler; |
63 | clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT); | 95 | clockevents_set_mode(newdev, CLOCK_EVT_MODE_ONESHOT); |
64 | clockevents_program_event(newdev, next_event, ktime_get()); | 96 | tick_dev_program_event(newdev, next_event, 1); |
65 | } | 97 | } |
66 | 98 | ||
67 | /** | 99 | /** |