mirror of https://gitee.com/openkylin/linux.git
Merge branch 'for-rmk/broadcast' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into next/virt
* 'for-rmk/broadcast' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux: arm: Add generic timer broadcast support arm: Use generic timer broadcast receiver clockevents: Add generic timer broadcast function clockevents: Add generic timer broadcast receiver
This commit is contained in:
commit
3ddc0e1a7f
|
@ -4,6 +4,7 @@ config ARM
|
||||||
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
|
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
|
||||||
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
|
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
|
||||||
select ARCH_HAVE_CUSTOM_GPIO_H
|
select ARCH_HAVE_CUSTOM_GPIO_H
|
||||||
|
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
select ARCH_WANT_IPC_PARSE_VERSION
|
select ARCH_WANT_IPC_PARSE_VERSION
|
||||||
select BUILDTIME_EXTABLE_SORT if MMU
|
select BUILDTIME_EXTABLE_SORT if MMU
|
||||||
select CPU_PM if (SUSPEND || CPU_IDLE)
|
select CPU_PM if (SUSPEND || CPU_IDLE)
|
||||||
|
|
|
@ -475,14 +475,8 @@ u64 smp_irq_stat_cpu(unsigned int cpu)
|
||||||
*/
|
*/
|
||||||
static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
|
static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent);
|
||||||
|
|
||||||
static void ipi_timer(void)
|
|
||||||
{
|
|
||||||
struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);
|
|
||||||
evt->event_handler(evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
|
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
static void smp_timer_broadcast(const struct cpumask *mask)
|
void tick_broadcast(const struct cpumask *mask)
|
||||||
{
|
{
|
||||||
smp_cross_call(mask, IPI_TIMER);
|
smp_cross_call(mask, IPI_TIMER);
|
||||||
}
|
}
|
||||||
|
@ -530,7 +524,6 @@ static void __cpuinit percpu_timer_setup(void)
|
||||||
struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
|
struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
|
||||||
|
|
||||||
evt->cpumask = cpumask_of(cpu);
|
evt->cpumask = cpumask_of(cpu);
|
||||||
evt->broadcast = smp_timer_broadcast;
|
|
||||||
|
|
||||||
if (!lt_ops || lt_ops->setup(evt))
|
if (!lt_ops || lt_ops->setup(evt))
|
||||||
broadcast_timer_setup(evt);
|
broadcast_timer_setup(evt);
|
||||||
|
@ -596,11 +589,13 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
|
||||||
case IPI_WAKEUP:
|
case IPI_WAKEUP:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
case IPI_TIMER:
|
case IPI_TIMER:
|
||||||
irq_enter();
|
irq_enter();
|
||||||
ipi_timer();
|
tick_receive_broadcast();
|
||||||
irq_exit();
|
irq_exit();
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case IPI_RESCHEDULE:
|
case IPI_RESCHEDULE:
|
||||||
scheduler_ipi();
|
scheduler_ipi();
|
||||||
|
|
|
@ -161,6 +161,15 @@ clockevents_calc_mult_shift(struct clock_event_device *ce, u32 freq, u32 minsec)
|
||||||
extern void clockevents_suspend(void);
|
extern void clockevents_suspend(void);
|
||||||
extern void clockevents_resume(void);
|
extern void clockevents_resume(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
|
#ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
|
||||||
|
extern void tick_broadcast(const struct cpumask *mask);
|
||||||
|
#else
|
||||||
|
#define tick_broadcast NULL
|
||||||
|
#endif
|
||||||
|
extern int tick_receive_broadcast(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_GENERIC_CLOCKEVENTS
|
#ifdef CONFIG_GENERIC_CLOCKEVENTS
|
||||||
extern void clockevents_notify(unsigned long reason, void *arg);
|
extern void clockevents_notify(unsigned long reason, void *arg);
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -38,6 +38,10 @@ config GENERIC_CLOCKEVENTS_BUILD
|
||||||
default y
|
default y
|
||||||
depends on GENERIC_CLOCKEVENTS
|
depends on GENERIC_CLOCKEVENTS
|
||||||
|
|
||||||
|
# Architecture can handle broadcast in a driver-agnostic way
|
||||||
|
config ARCH_HAS_TICK_BROADCAST
|
||||||
|
bool
|
||||||
|
|
||||||
# Clockevents broadcasting infrastructure
|
# Clockevents broadcasting infrastructure
|
||||||
config GENERIC_CLOCKEVENTS_BROADCAST
|
config GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
#include <linux/profile.h>
|
#include <linux/profile.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/smp.h>
|
||||||
|
|
||||||
#include "tick-internal.h"
|
#include "tick-internal.h"
|
||||||
|
|
||||||
|
@ -86,6 +87,11 @@ int tick_is_broadcast_device(struct clock_event_device *dev)
|
||||||
return (dev && tick_broadcast_device.evtdev == dev);
|
return (dev && tick_broadcast_device.evtdev == dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void err_broadcast(const struct cpumask *mask)
|
||||||
|
{
|
||||||
|
pr_crit_once("Failed to broadcast timer tick. Some CPUs may be unresponsive.\n");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check, if the device is disfunctional and a place holder, which
|
* Check, if the device is disfunctional and a place holder, which
|
||||||
* needs to be handled by the broadcast device.
|
* needs to be handled by the broadcast device.
|
||||||
|
@ -105,6 +111,13 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
|
||||||
*/
|
*/
|
||||||
if (!tick_device_is_functional(dev)) {
|
if (!tick_device_is_functional(dev)) {
|
||||||
dev->event_handler = tick_handle_periodic;
|
dev->event_handler = tick_handle_periodic;
|
||||||
|
if (!dev->broadcast)
|
||||||
|
dev->broadcast = tick_broadcast;
|
||||||
|
if (!dev->broadcast) {
|
||||||
|
pr_warn_once("%s depends on broadcast, but no broadcast function available\n",
|
||||||
|
dev->name);
|
||||||
|
dev->broadcast = err_broadcast;
|
||||||
|
}
|
||||||
cpumask_set_cpu(cpu, tick_get_broadcast_mask());
|
cpumask_set_cpu(cpu, tick_get_broadcast_mask());
|
||||||
tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
|
tick_broadcast_start_periodic(tick_broadcast_device.evtdev);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
@ -125,6 +138,23 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
|
int tick_receive_broadcast(void)
|
||||||
|
{
|
||||||
|
struct tick_device *td = this_cpu_ptr(&tick_cpu_device);
|
||||||
|
struct clock_event_device *evt = td->evtdev;
|
||||||
|
|
||||||
|
if (!evt)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (!evt->event_handler)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
evt->event_handler(evt);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Broadcast the event to the cpus, which are set in the mask (mangled).
|
* Broadcast the event to the cpus, which are set in the mask (mangled).
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue