Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 270223
b: refs/heads/master
c: 28af690
h: refs/heads/master
i:
  270221: d4d735a
  270219: 0b67ad3
  270215: 064660a
  270207: c45f7fe
v: v3
  • Loading branch information
Marc Zyngier committed Oct 23, 2011
1 parent a2e96c1 commit 715d449
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 112 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 292b293ceef2eda1f96f0c90b96e954d7bdabd1c
refs/heads/master: 28af690a284dfcb627bd69d0963db1c0f412cb8c
52 changes: 0 additions & 52 deletions trunk/arch/arm/common/gic.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/hardware/gic.h>
#include <asm/localtimer.h>

static DEFINE_SPINLOCK(irq_controller_lock);

Expand Down Expand Up @@ -259,32 +258,6 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
irq_set_chained_handler(irq, gic_handle_cascade_irq);
}

#ifdef CONFIG_LOCAL_TIMERS
#define gic_ppi_handler percpu_timer_handler
#else
static irqreturn_t gic_ppi_handler(int irq, void *dev_id)
{
return IRQ_NONE;
}
#endif

#define PPI_IRQACT(nr) \
{ \
.handler = gic_ppi_handler, \
.flags = IRQF_PERCPU | IRQF_TIMER, \
.irq = nr, \
.name = "PPI-" # nr, \
}

static struct irqaction ppi_irqaction_template[16] __initdata = {
PPI_IRQACT(0), PPI_IRQACT(1), PPI_IRQACT(2), PPI_IRQACT(3),
PPI_IRQACT(4), PPI_IRQACT(5), PPI_IRQACT(6), PPI_IRQACT(7),
PPI_IRQACT(8), PPI_IRQACT(9), PPI_IRQACT(10), PPI_IRQACT(11),
PPI_IRQACT(12), PPI_IRQACT(13), PPI_IRQACT(14), PPI_IRQACT(15),
};

static struct irqaction *ppi_irqaction;

static void __init gic_dist_init(struct gic_chip_data *gic,
unsigned int irq_start)
{
Expand Down Expand Up @@ -325,16 +298,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
BUG();

ppi_base = gic->irq_offset + 32 - nrppis;

ppi_irqaction = kmemdup(&ppi_irqaction_template[16 - nrppis],
sizeof(*ppi_irqaction) * nrppis,
GFP_KERNEL);

if (nrppis && !ppi_irqaction) {
pr_err("GIC: Can't allocate PPI memory");
nrppis = 0;
ppi_base = 0;
}
}

pr_info("Configuring GIC with %d sources (%d PPIs)\n",
Expand Down Expand Up @@ -377,17 +340,12 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
*/
for (i = 0; i < nrppis; i++) {
int ppi = i + ppi_base;
int err;

irq_set_percpu_devid(ppi);
irq_set_chip_and_handler(ppi, &gic_chip,
handle_percpu_devid_irq);
irq_set_chip_data(ppi, gic);
set_irq_flags(ppi, IRQF_VALID | IRQF_NOAUTOEN);

err = setup_percpu_irq(ppi, &ppi_irqaction[i]);
if (err)
pr_err("GIC: can't setup PPI%d (%d)\n", ppi, err);
}

for (i = irq_start + nrppis; i < irq_limit; i++) {
Expand Down Expand Up @@ -448,16 +406,6 @@ void __cpuinit gic_secondary_init(unsigned int gic_nr)
gic_cpu_init(&gic_data[gic_nr]);
}

void __cpuinit gic_enable_ppi(unsigned int irq)
{
unsigned long flags;

local_irq_save(flags);
irq_set_status_flags(irq, IRQ_NOPROBE);
gic_unmask_irq(irq_get_irq_data(irq));
local_irq_restore(flags);
}

#ifdef CONFIG_SMP
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
{
Expand Down
1 change: 0 additions & 1 deletion trunk/arch/arm/include/asm/hardware/gic.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
void gic_secondary_init(unsigned int);
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
void gic_enable_ppi(unsigned int);

struct gic_chip_data {
unsigned int irq_offset;
Expand Down
16 changes: 7 additions & 9 deletions trunk/arch/arm/include/asm/localtimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,20 @@ struct clock_event_device;
*/
void percpu_timer_setup(void);

/*
* Per-cpu timer IRQ handler
*/
irqreturn_t percpu_timer_handler(int irq, void *dev_id);

#ifdef CONFIG_LOCAL_TIMERS

#ifdef CONFIG_HAVE_ARM_TWD

#include "smp_twd.h"

#define local_timer_ack() twd_timer_ack()
#define local_timer_stop(c) twd_timer_stop((c))

#else

/*
* Platform provides this to acknowledge a local timer IRQ.
* Returns true if the local timer IRQ is to be processed.
* Stop the local timer
*/
int local_timer_ack(void);
void local_timer_stop(struct clock_event_device *);

#endif

Expand All @@ -53,6 +47,10 @@ static inline int local_timer_setup(struct clock_event_device *evt)
{
return -ENXIO;
}

static inline void local_timer_stop(struct clock_event_device *evt)
{
}
#endif

#endif
2 changes: 1 addition & 1 deletion trunk/arch/arm/include/asm/smp_twd.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ struct clock_event_device;

extern void __iomem *twd_base;

int twd_timer_ack(void);
void twd_timer_setup(struct clock_event_device *);
void twd_timer_stop(struct clock_event_device *);

#endif
16 changes: 1 addition & 15 deletions trunk/arch/arm/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,20 +473,6 @@ static void ipi_timer(void)
irq_exit();
}

#ifdef CONFIG_LOCAL_TIMERS
irqreturn_t percpu_timer_handler(int irq, void *dev_id)
{
struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent);

if (local_timer_ack()) {
evt->event_handler(evt);
return IRQ_HANDLED;
}

return IRQ_NONE;
}
#endif

#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
static void smp_timer_broadcast(const struct cpumask *mask)
{
Expand Down Expand Up @@ -537,7 +523,7 @@ static void percpu_timer_stop(void)
unsigned int cpu = smp_processor_id();
struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);

evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
local_timer_stop(evt);
}
#endif

Expand Down
47 changes: 45 additions & 2 deletions trunk/arch/arm/kernel/smp_twd.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
#include <linux/io.h>

#include <asm/smp_twd.h>
#include <asm/localtimer.h>
#include <asm/hardware/gic.h>

/* set up by the platform code */
void __iomem *twd_base;

static unsigned long twd_timer_rate;

static struct clock_event_device __percpu **twd_evt;

static void twd_set_mode(enum clock_event_mode mode,
struct clock_event_device *clk)
{
Expand Down Expand Up @@ -80,6 +83,12 @@ int twd_timer_ack(void)
return 0;
}

void twd_timer_stop(struct clock_event_device *clk)
{
twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk);
disable_percpu_irq(clk->irq);
}

static void __cpuinit twd_calibrate_rate(void)
{
unsigned long count;
Expand Down Expand Up @@ -119,11 +128,43 @@ static void __cpuinit twd_calibrate_rate(void)
}
}

static irqreturn_t twd_handler(int irq, void *dev_id)
{
struct clock_event_device *evt = *(struct clock_event_device **)dev_id;

if (twd_timer_ack()) {
evt->event_handler(evt);
return IRQ_HANDLED;
}

return IRQ_NONE;
}

/*
* Setup the local clock events for a CPU.
*/
void __cpuinit twd_timer_setup(struct clock_event_device *clk)
{
struct clock_event_device **this_cpu_clk;

if (!twd_evt) {
int err;

twd_evt = alloc_percpu(struct clock_event_device *);
if (!twd_evt) {
pr_err("twd: can't allocate memory\n");
return;
}

err = request_percpu_irq(clk->irq, twd_handler,
"twd", twd_evt);
if (err) {
pr_err("twd: can't register interrupt %d (%d)\n",
clk->irq, err);
return;
}
}

twd_calibrate_rate();

clk->name = "local_timer";
Expand All @@ -137,8 +178,10 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
clk->max_delta_ns = clockevent_delta2ns(0xffffffff, clk);
clk->min_delta_ns = clockevent_delta2ns(0xf, clk);

this_cpu_clk = __this_cpu_ptr(twd_evt);
*this_cpu_clk = clk;

clockevents_register_device(clk);

/* Make sure our local interrupt controller has this enabled */
gic_enable_ppi(clk->irq);
enable_percpu_irq(clk->irq, 0);
}
7 changes: 5 additions & 2 deletions trunk/arch/arm/mach-exynos4/mct.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,11 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt)

if (cpu == 0) {
mct_tick0_event_irq.dev_id = &mct_tick[cpu];
evt->irq = IRQ_MCT_L0;
setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
} else {
mct_tick1_event_irq.dev_id = &mct_tick[cpu];
evt->irq = IRQ_MCT_L1;
setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
irq_set_affinity(IRQ_MCT_L1, cpumask_of(1));
}
Expand All @@ -394,9 +396,10 @@ void __cpuinit local_timer_setup(struct clock_event_device *evt)
exynos4_mct_tick_init(evt);
}

int local_timer_ack(void)
void local_timer_stop(struct clock_event_device *evt)
{
return 0;
evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
disable_irq(evt->irq);
}

#endif /* CONFIG_LOCAL_TIMERS */
Expand Down
Loading

0 comments on commit 715d449

Please sign in to comment.