Messages in this thread Patch in this message | | | From | Benjamin Gaignard <> | Subject | [PATCH] tick: check if broadcast device could really be stopped | Date | Wed, 9 Oct 2019 18:02:46 +0200 |
| |
If the CPU isn't able to go in states where the clock event will be stopped we can ignore CLOCK_EVT_FEAT_C3STOP flag.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com> --- kernel/time/tick-broadcast.c | 6 +++--- kernel/time/tick-common.c | 4 ++-- kernel/time/tick-internal.h | 12 ++++++++++++ 3 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index e51778c312f1..5393778d7703 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -78,7 +78,7 @@ static bool tick_check_broadcast_device(struct clock_event_device *curdev, { if ((newdev->features & CLOCK_EVT_FEAT_DUMMY) || (newdev->features & CLOCK_EVT_FEAT_PERCPU) || - (newdev->features & CLOCK_EVT_FEAT_C3STOP)) + tick_broadcast_could_stop(newdev)) return false; if (tick_broadcast_device.mode == TICKDEV_MODE_ONESHOT && @@ -188,7 +188,7 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) * Clear the broadcast bit for this cpu if the * device is not power state affected. */ - if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) + if (!tick_broadcast_could_stop(dev)) cpumask_clear_cpu(cpu, tick_broadcast_mask); else tick_device_setup_broadcast_func(dev); @@ -368,7 +368,7 @@ void tick_broadcast_control(enum tick_broadcast_mode mode) /* * Is the device not affected by the powerstate ? */ - if (!dev || !(dev->features & CLOCK_EVT_FEAT_C3STOP)) + if (!dev || !tick_broadcast_could_stop(dev)) goto out; if (!tick_device_is_functional(dev)) diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 59225b484e4e..a300ee941c56 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -72,7 +72,7 @@ int tick_is_oneshot_available(void) if (!dev || !(dev->features & CLOCK_EVT_FEAT_ONESHOT)) return 0; - if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) + if (!tick_broadcast_could_stop(dev)) return 1; return tick_broadcast_oneshot_available(); } @@ -393,7 +393,7 @@ int tick_broadcast_oneshot_control(enum tick_broadcast_state state) { struct tick_device *td = this_cpu_ptr(&tick_cpu_device); - if (!(td->evtdev->features & CLOCK_EVT_FEAT_C3STOP)) + if (!tick_broadcast_could_stop(td->evtdev)) return 0; return __tick_broadcast_oneshot_control(state); diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index 7b2496136729..99aa7b5a8dae 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -2,6 +2,7 @@ /* * tick internal variable and functions used by low/high res code */ +#include <linux/cpuidle.h> #include <linux/hrtimer.h> #include <linux/tick.h> @@ -48,6 +49,17 @@ static inline void clockevent_set_state(struct clock_event_device *dev, dev->state_use_accessors = state; } +/** + * Return true if the cpu could go in states where the device will be stopped + */ +static inline int tick_broadcast_could_stop(struct clock_event_device *dev) +{ + struct cpuidle_driver *drv = cpuidle_get_driver(); + + return !!((dev->features & CLOCK_EVT_FEAT_C3STOP) + && drv && drv->bctimer); +} + extern void clockevents_shutdown(struct clock_event_device *dev); extern void clockevents_exchange_device(struct clock_event_device *old, struct clock_event_device *new); -- 2.15.0
| |