Skip to content

Commit

Permalink
Merge branch 'ppi-irq-core-for-rmk' of git://github.com/mzyngier/arm-…
Browse files Browse the repository at this point in the history
…platforms into devel-stable
  • Loading branch information
Russell King committed Oct 23, 2011
2 parents cefd3e7 + 28af690 commit 34471a9
Show file tree
Hide file tree
Showing 46 changed files with 829 additions and 307 deletions.
25 changes: 25 additions & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1420,6 +1420,31 @@ config SMP_ON_UP

If you don't know what to do here, say Y.

config ARM_CPU_TOPOLOGY
bool "Support cpu topology definition"
depends on SMP && CPU_V7
default y
help
Support ARM cpu topology definition. The MPIDR register defines
affinity between processors which is then used to describe the cpu
topology of an ARM System.

config SCHED_MC
bool "Multi-core scheduler support"
depends on ARM_CPU_TOPOLOGY
help
Multi-core scheduler support improves the CPU scheduler's decision
making when dealing with multi-core CPU chips at a cost of slightly
increased overhead in some places. If unsure say N here.

config SCHED_SMT
bool "SMT scheduler support"
depends on ARM_CPU_TOPOLOGY
help
Improves the CPU scheduler's decision making when dealing with
MultiThreading at a cost of slightly increased overhead in some
places. If unsure say N here.

config HAVE_ARM_SCU
bool
help
Expand Down
60 changes: 46 additions & 14 deletions arch/arm/common/gic.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
#include <linux/cpu_pm.h>
#include <linux/cpumask.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <linux/slab.h>

#include <asm/irq.h>
#include <asm/mach/irq.h>
Expand Down Expand Up @@ -181,7 +184,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
return -EINVAL;

mask = 0xff << shift;
bit = 1 << (cpu + shift);
bit = 1 << (cpu_logical_map(cpu) + shift);

spin_lock(&irq_controller_lock);
val = readl_relaxed(reg) & ~mask;
Expand Down Expand Up @@ -260,9 +263,16 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
unsigned int irq_start)
{
unsigned int gic_irqs, irq_limit, i;
u32 cpumask;
void __iomem *base = gic->dist_base;
u32 cpumask = 1 << smp_processor_id();
u32 cpu = 0;
u32 nrppis = 0, ppi_base = 0;

#ifdef CONFIG_SMP
cpu = cpu_logical_map(smp_processor_id());
#endif

cpumask = 1 << cpu;
cpumask |= cpumask << 8;
cpumask |= cpumask << 16;

Expand All @@ -279,6 +289,23 @@ static void __init gic_dist_init(struct gic_chip_data *gic,

gic->gic_irqs = gic_irqs;

/*
* Nobody would be insane enough to use PPIs on a secondary
* GIC, right?
*/
if (gic == &gic_data[0]) {
nrppis = (32 - irq_start) & 31;

/* The GIC only supports up to 16 PPIs. */
if (nrppis > 16)
BUG();

ppi_base = gic->irq_offset + 32 - nrppis;
}

pr_info("Configuring GIC with %d sources (%d PPIs)\n",
gic_irqs, (gic == &gic_data[0]) ? nrppis : 0);

/*
* Set all global interrupts to be level triggered, active low.
*/
Expand Down Expand Up @@ -314,7 +341,17 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
/*
* Setup the Linux IRQ subsystem.
*/
for (i = irq_start; i < irq_limit; i++) {
for (i = 0; i < nrppis; i++) {
int ppi = i + ppi_base;

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);
}

for (i = irq_start + nrppis; i < irq_limit; i++) {
irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
irq_set_chip_data(i, gic);
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
Expand Down Expand Up @@ -557,20 +594,15 @@ 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)
{
unsigned long map = *cpus_addr(*mask);
int cpu;
unsigned long map = 0;

/* Convert our logical CPU mask into a physical one. */
for_each_cpu(cpu, mask)
map |= 1 << cpu_logical_map(cpu);

/*
* Ensure that stores to Normal memory are visible to the
Expand Down
6 changes: 6 additions & 0 deletions arch/arm/include/asm/cputype.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define CPUID_CACHETYPE 1
#define CPUID_TCM 2
#define CPUID_TLBTYPE 3
#define CPUID_MPIDR 5

#define CPUID_EXT_PFR0 "c1, 0"
#define CPUID_EXT_PFR1 "c1, 1"
Expand Down Expand Up @@ -70,6 +71,11 @@ static inline unsigned int __attribute_const__ read_cpuid_tcmstatus(void)
return read_cpuid(CPUID_TCM);
}

static inline unsigned int __attribute_const__ read_cpuid_mpidr(void)
{
return read_cpuid(CPUID_MPIDR);
}

/*
* Intel's XScale3 core supports some v6 features (supersections, L2)
* but advertises itself as v5 as it does not support the v6 ISA. For
Expand Down
7 changes: 0 additions & 7 deletions arch/arm/include/asm/entry-macro-multi.S
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,6 @@
movne r1, sp
adrne lr, BSYM(1b)
bne do_IPI

#ifdef CONFIG_LOCAL_TIMERS
test_for_ltirq r0, r2, r6, lr
movne r0, sp
adrne lr, BSYM(1b)
bne do_local_timer
#endif
#endif
9997:
.endm
Expand Down
19 changes: 19 additions & 0 deletions arch/arm/include/asm/exception.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Annotations for marking C functions as exception handlers.
*
* These should only be used for C functions that are called from the low
* level exception entry code and not any intervening C code.
*/
#ifndef __ASM_ARM_EXCEPTION_H
#define __ASM_ARM_EXCEPTION_H

#include <linux/ftrace.h>

#define __exception __attribute__((section(".exception.text")))
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
#define __exception_irq_entry __irq_entry
#else
#define __exception_irq_entry __exception
#endif

#endif /* __ASM_ARM_EXCEPTION_H */
3 changes: 0 additions & 3 deletions arch/arm/include/asm/hardirq.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@

typedef struct {
unsigned int __softirq_pending;
#ifdef CONFIG_LOCAL_TIMERS
unsigned int local_timer_irqs;
#endif
#ifdef CONFIG_SMP
unsigned int ipi_irqs[NR_IPI];
#endif
Expand Down
19 changes: 2 additions & 17 deletions arch/arm/include/asm/hardware/entry-macro-gic.S
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,11 @@
* interrupt controller spec. To wit:
*
* Interrupts 0-15 are IPI
* 16-28 are reserved
* 29-31 are local. We allow 30 to be used for the watchdog.
* 16-31 are local. We allow 30 to be used for the watchdog.
* 32-1020 are global
* 1021-1022 are reserved
* 1023 is "spurious" (no interrupt)
*
* For now, we ignore all local interrupts so only return an interrupt if it's
* between 30 and 1020. The test_for_ipi routine below will pick up on IPIs.
*
* A simple read from the controller will tell us the number of the highest
* priority enabled interrupt. We then just need to check whether it is in the
* valid range for an IRQ (30-1020 inclusive).
Expand All @@ -43,7 +39,7 @@

ldr \tmp, =1021
bic \irqnr, \irqstat, #0x1c00
cmp \irqnr, #29
cmp \irqnr, #15
cmpcc \irqnr, \irqnr
cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr
Expand All @@ -62,14 +58,3 @@
strcc \irqstat, [\base, #GIC_CPU_EOI]
cmpcs \irqnr, \irqnr
.endm

/* As above, this assumes that irqstat and base are preserved.. */

.macro test_for_ltirq, irqnr, irqstat, base, tmp
bic \irqnr, \irqstat, #0x1c00
mov \tmp, #0
cmp \irqnr, #29
moveq \tmp, #1
streq \irqstat, [\base, #GIC_CPU_EOI]
cmp \tmp, #0
.endm
1 change: 0 additions & 1 deletion 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
19 changes: 9 additions & 10 deletions arch/arm/include/asm/localtimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,29 @@
#ifndef __ASM_ARM_LOCALTIMER_H
#define __ASM_ARM_LOCALTIMER_H

#include <linux/interrupt.h>

struct clock_event_device;

/*
* Setup a per-cpu timer, whether it be a local timer or dummy broadcast
*/
void percpu_timer_setup(void);

/*
* Called from assembly, this is the local timer IRQ handler
*/
asmlinkage void do_local_timer(struct pt_regs *);


#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 @@ -52,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
16 changes: 11 additions & 5 deletions arch/arm/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ extern void show_ipi_list(struct seq_file *, int);
*/
asmlinkage void do_IPI(int ipinr, struct pt_regs *regs);

/*
* Called from C code, this handles an IPI.
*/
void handle_IPI(int ipinr, struct pt_regs *regs);

/*
* Setup the set of possible CPUs (via set_cpu_possible)
*/
Expand Down Expand Up @@ -65,6 +70,12 @@ extern void platform_secondary_init(unsigned int cpu);
*/
extern void platform_smp_prepare_cpus(unsigned int);

/*
* Logical CPU mapping.
*/
extern int __cpu_logical_map[NR_CPUS];
#define cpu_logical_map(cpu) __cpu_logical_map[cpu]

/*
* Initial data for bringing up a secondary CPU.
*/
Expand All @@ -88,9 +99,4 @@ extern void platform_cpu_enable(unsigned int cpu);
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);

/*
* show local interrupt info
*/
extern void show_local_irqs(struct seq_file *, int);

#endif /* ifndef __ASM_ARM_SMP_H */
2 changes: 1 addition & 1 deletion 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
7 changes: 0 additions & 7 deletions arch/arm/include/asm/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,6 @@

#include <asm/outercache.h>

#define __exception __attribute__((section(".exception.text")))
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
#define __exception_irq_entry __irq_entry
#else
#define __exception_irq_entry __exception
#endif

struct thread_info;
struct task_struct;

Expand Down
Loading

0 comments on commit 34471a9

Please sign in to comment.