|
@@ -49,6 +49,7 @@ static void bc_set_mode(enum clock_event_mode mode,
|
|
|
*/
|
|
|
static int bc_set_next(ktime_t expires, struct clock_event_device *bc)
|
|
|
{
|
|
|
+ int bc_moved;
|
|
|
/*
|
|
|
* We try to cancel the timer first. If the callback is on
|
|
|
* flight on some other cpu then we let it handle it. If we
|
|
@@ -60,9 +61,15 @@ static int bc_set_next(ktime_t expires, struct clock_event_device *bc)
|
|
|
* restart the timer because we are in the callback, but we
|
|
|
* can set the expiry time and let the callback return
|
|
|
* HRTIMER_RESTART.
|
|
|
+ *
|
|
|
+ * Since we are in the idle loop at this point and because
|
|
|
+ * hrtimer_{start/cancel} functions call into tracing,
|
|
|
+ * calls to these functions must be bound within RCU_NONIDLE.
|
|
|
*/
|
|
|
- if (hrtimer_try_to_cancel(&bctimer) >= 0) {
|
|
|
- hrtimer_start(&bctimer, expires, HRTIMER_MODE_ABS_PINNED);
|
|
|
+ RCU_NONIDLE(bc_moved = (hrtimer_try_to_cancel(&bctimer) >= 0) ?
|
|
|
+ !hrtimer_start(&bctimer, expires, HRTIMER_MODE_ABS_PINNED) :
|
|
|
+ 0);
|
|
|
+ if (bc_moved) {
|
|
|
/* Bind the "device" to the cpu */
|
|
|
bc->bound_on = smp_processor_id();
|
|
|
} else if (bc->bound_on == smp_processor_id()) {
|