Skip to content

Commit

Permalink
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/benh/powerpc

* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  powerpc/4xx: Adding PCIe MSI support
  powerpc: Fix irq_free_virt by adjusting bounds before loop
  powerpc/irq: Protect irq_radix_revmap_lookup against irq_free_virt
  powerpc/irq: Check desc in handle_one_irq and expand generic_handle_irq
  powerpc/irq: Always free duplicate IRQ_LEGACY hosts
  powerpc/irq: Remove stale and misleading comment
  powerpc/cell: Rename ipi functions to match current abstractions
  powerpc/cell: Use common smp ipi actions
  Remove unused MSG_ flags in linux/smp.h
  powerpc/pseries: Update MAX_HCALL_OPCODE to reflect page coalescing
  powerpc/oprofile: Handle events that raise an exception without overflowing
  powerpc/ftrace: Implement raw syscall tracepoints on PowerPC
  • Loading branch information
Linus Torvalds committed May 26, 2011
2 parents be93d8c + 3fb7933 commit 6ddb451
Show file tree
Hide file tree
Showing 25 changed files with 491 additions and 76 deletions.
1 change: 1 addition & 0 deletions arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ config PPC
select GENERIC_IRQ_SHOW
select GENERIC_IRQ_SHOW_LEVEL
select HAVE_RCU_TABLE_FREE if SMP
select HAVE_SYSCALL_TRACEPOINTS

config EARLY_PRINTK
bool
Expand Down
18 changes: 18 additions & 0 deletions arch/powerpc/boot/dts/canyonlands.dts
Original file line number Diff line number Diff line change
Expand Up @@ -530,5 +530,23 @@
0x0 0x0 0x0 0x3 &UIC3 0x12 0x4 /* swizzled int C */
0x0 0x0 0x0 0x4 &UIC3 0x13 0x4 /* swizzled int D */>;
};

MSI: ppc4xx-msi@C10000000 {
compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
reg = < 0xC 0x10000000 0x100>;
sdr-base = <0x36C>;
msi-data = <0x00000000>;
msi-mask = <0x44440000>;
interrupt-count = <3>;
interrupts = <0 1 2 3>;
interrupt-parent = <&UIC3>;
#interrupt-cells = <1>;
#address-cells = <0>;
#size-cells = <0>;
interrupt-map = <0 &UIC3 0x18 1
1 &UIC3 0x19 1
2 &UIC3 0x1A 1
3 &UIC3 0x1B 1>;
};
};
};
18 changes: 18 additions & 0 deletions arch/powerpc/boot/dts/katmai.dts
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,24 @@
0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>;
};

MSI: ppc4xx-msi@400300000 {
compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
reg = < 0x4 0x00300000 0x100>;
sdr-base = <0x3B0>;
msi-data = <0x00000000>;
msi-mask = <0x44440000>;
interrupt-count = <3>;
interrupts =<0 1 2 3>;
interrupt-parent = <&UIC0>;
#interrupt-cells = <1>;
#address-cells = <0>;
#size-cells = <0>;
interrupt-map = <0 &UIC0 0xC 1
1 &UIC0 0x0D 1
2 &UIC0 0x0E 1
3 &UIC0 0x0F 1>;
};

I2O: i2o@400100000 {
compatible = "ibm,i2o-440spe";
reg = <0x00000004 0x00100000 0x100>;
Expand Down
28 changes: 28 additions & 0 deletions arch/powerpc/boot/dts/kilauea.dts
Original file line number Diff line number Diff line change
Expand Up @@ -403,5 +403,33 @@
0x0 0x0 0x0 0x3 &UIC2 0xd 0x4 /* swizzled int C */
0x0 0x0 0x0 0x4 &UIC2 0xe 0x4 /* swizzled int D */>;
};

MSI: ppc4xx-msi@C10000000 {
compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
reg = < 0x0 0xEF620000 0x100>;
sdr-base = <0x4B0>;
msi-data = <0x00000000>;
msi-mask = <0x44440000>;
interrupt-count = <12>;
interrupts = <0 1 2 3 4 5 6 7 8 9 0xA 0xB 0xC 0xD>;
interrupt-parent = <&UIC2>;
#interrupt-cells = <1>;
#address-cells = <0>;
#size-cells = <0>;
interrupt-map = <0 &UIC2 0x10 1
1 &UIC2 0x11 1
2 &UIC2 0x12 1
2 &UIC2 0x13 1
2 &UIC2 0x14 1
2 &UIC2 0x15 1
2 &UIC2 0x16 1
2 &UIC2 0x17 1
2 &UIC2 0x18 1
2 &UIC2 0x19 1
2 &UIC2 0x1A 1
2 &UIC2 0x1B 1
2 &UIC2 0x1C 1
3 &UIC2 0x1D 1>;
};
};
};
20 changes: 20 additions & 0 deletions arch/powerpc/boot/dts/redwood.dts
Original file line number Diff line number Diff line change
Expand Up @@ -358,8 +358,28 @@
0x0 0x0 0x0 0x4 &UIC3 0xb 0x4 /* swizzled int D */>;
};

MSI: ppc4xx-msi@400300000 {
compatible = "amcc,ppc4xx-msi", "ppc4xx-msi";
reg = < 0x4 0x00300000 0x100
0x4 0x00300000 0x100>;
sdr-base = <0x3B0>;
msi-data = <0x00000000>;
msi-mask = <0x44440000>;
interrupt-count = <3>;
interrupts =<0 1 2 3>;
interrupt-parent = <&UIC0>;
#interrupt-cells = <1>;
#address-cells = <0>;
#size-cells = <0>;
interrupt-map = <0 &UIC0 0xC 1
1 &UIC0 0x0D 1
2 &UIC0 0x0E 1
3 &UIC0 0x0F 1>;
};

};


chosen {
linux,stdout-path = "/plb/opb/serial@ef600200";
};
Expand Down
14 changes: 14 additions & 0 deletions arch/powerpc/include/asm/ftrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,18 @@ struct dyn_arch_ftrace {

#endif

#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64) && !defined(__ASSEMBLY__)
#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
static inline bool arch_syscall_match_sym_name(const char *sym, const char *name)
{
/*
* Compare the symbol name with the system call name. Skip the .sys or .SyS
* prefix from the symbol name and the sys prefix from the system call name and
* just match the rest. This is only needed on ppc64 since symbol names on
* 32bit do not start with a period so the generic function will work.
*/
return !strcmp(sym + 4, name + 3);
}
#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 && !__ASSEMBLY__ */

#endif /* _ASM_POWERPC_FTRACE */
2 changes: 1 addition & 1 deletion arch/powerpc/include/asm/hvcall.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@
#define H_HOME_NODE_ASSOCIATIVITY 0x2EC
#define H_BEST_ENERGY 0x2F4
#define H_GET_MPP_X 0x314
#define MAX_HCALL_OPCODE H_BEST_ENERGY
#define MAX_HCALL_OPCODE H_GET_MPP_X

#ifndef __ASSEMBLY__

Expand Down
2 changes: 0 additions & 2 deletions arch/powerpc/include/asm/smp.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,6 @@ extern unsigned long __secondary_hold_spinloop;
extern unsigned long __secondary_hold_acknowledge;
extern char __secondary_hold;

extern irqreturn_t debug_ipi_action(int irq, void *data);

#endif /* __ASSEMBLY__ */

#endif /* __KERNEL__ */
Expand Down
5 changes: 5 additions & 0 deletions arch/powerpc/include/asm/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@

#include <linux/sched.h>

/* ftrace syscalls requires exporting the sys_call_table */
#ifdef CONFIG_FTRACE_SYSCALLS
extern const unsigned long *sys_call_table;
#endif /* CONFIG_FTRACE_SYSCALLS */

static inline long syscall_get_nr(struct task_struct *task,
struct pt_regs *regs)
{
Expand Down
7 changes: 5 additions & 2 deletions arch/powerpc/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NOERROR 12 /* Force successful syscall return */
#define TIF_NOTIFY_RESUME 13 /* callback before returning to user */
#define TIF_FREEZE 14 /* Freezing for suspend */
#define TIF_RUNLATCH 15 /* Is the runlatch enabled? */
#define TIF_SYSCALL_TRACEPOINT 15 /* syscall tracepoint instrumentation */
#define TIF_RUNLATCH 16 /* Is the runlatch enabled? */

/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
Expand All @@ -127,8 +128,10 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NOERROR (1<<TIF_NOERROR)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_FREEZE (1<<TIF_FREEZE)
#define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT)
#define _TIF_RUNLATCH (1<<TIF_RUNLATCH)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT)

#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
_TIF_NOTIFY_RESUME)
Expand Down
1 change: 1 addition & 0 deletions arch/powerpc/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ obj-$(CONFIG_PPC_IO_WORKAROUNDS) += io-workarounds.o

obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o

obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o
Expand Down
8 changes: 8 additions & 0 deletions arch/powerpc/kernel/ftrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <asm/cacheflush.h>
#include <asm/code-patching.h>
#include <asm/ftrace.h>
#include <asm/syscall.h>


#ifdef CONFIG_DYNAMIC_FTRACE
Expand Down Expand Up @@ -600,3 +601,10 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
}
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */

#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64)
unsigned long __init arch_syscall_addr(int nr)
{
return sys_call_table[nr*2];
}
#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 */
46 changes: 26 additions & 20 deletions arch/powerpc/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,17 +295,20 @@ static inline void handle_one_irq(unsigned int irq)
unsigned long saved_sp_limit;
struct irq_desc *desc;

desc = irq_to_desc(irq);
if (!desc)
return;

/* Switch to the irq stack to handle this */
curtp = current_thread_info();
irqtp = hardirq_ctx[smp_processor_id()];

if (curtp == irqtp) {
/* We're already on the irq stack, just handle it */
generic_handle_irq(irq);
desc->handle_irq(irq, desc);
return;
}

desc = irq_to_desc(irq);
saved_sp_limit = current->thread.ksp_limit;

irqtp->task = curtp->task;
Expand Down Expand Up @@ -557,15 +560,8 @@ struct irq_host *irq_alloc_host(struct device_node *of_node,
if (revmap_type == IRQ_HOST_MAP_LEGACY) {
if (irq_map[0].host != NULL) {
raw_spin_unlock_irqrestore(&irq_big_lock, flags);
/* If we are early boot, we can't free the structure,
* too bad...
* this will be fixed once slab is made available early
* instead of the current cruft
*/
if (mem_init_done) {
of_node_put(host->of_node);
kfree(host);
}
of_node_put(host->of_node);
kfree(host);
return NULL;
}
irq_map[0].host = host;
Expand Down Expand Up @@ -727,9 +723,7 @@ unsigned int irq_create_mapping(struct irq_host *host,
}
pr_debug("irq: -> using host @%p\n", host);

/* Check if mapping already exist, if it does, call
* host->ops->map() to update the flags
*/
/* Check if mapping already exists */
virq = irq_find_mapping(host, hwirq);
if (virq != NO_IRQ) {
pr_debug("irq: -> existing mapping on virq %d\n", virq);
Expand Down Expand Up @@ -899,10 +893,13 @@ unsigned int irq_radix_revmap_lookup(struct irq_host *host,
return irq_find_mapping(host, hwirq);

/*
* No rcu_read_lock(ing) needed, the ptr returned can't go under us
* as it's referencing an entry in the static irq_map table.
* The ptr returned references the static global irq_map.
* but freeing an irq can delete nodes along the path to
* do the lookup via call_rcu.
*/
rcu_read_lock();
ptr = radix_tree_lookup(&host->revmap_data.tree, hwirq);
rcu_read_unlock();

/*
* If found in radix tree, then fine.
Expand Down Expand Up @@ -1010,14 +1007,23 @@ void irq_free_virt(unsigned int virq, unsigned int count)
WARN_ON (virq < NUM_ISA_INTERRUPTS);
WARN_ON (count == 0 || (virq + count) > irq_virq_count);

if (virq < NUM_ISA_INTERRUPTS) {
if (virq + count < NUM_ISA_INTERRUPTS)
return;
count =- NUM_ISA_INTERRUPTS - virq;
virq = NUM_ISA_INTERRUPTS;
}

if (count > irq_virq_count || virq > irq_virq_count - count) {
if (virq > irq_virq_count)
return;
count = irq_virq_count - virq;
}

raw_spin_lock_irqsave(&irq_big_lock, flags);
for (i = virq; i < (virq + count); i++) {
struct irq_host *host;

if (i < NUM_ISA_INTERRUPTS ||
(virq + count) > irq_virq_count)
continue;

host = irq_map[i].host;
irq_map[i].hwirq = host->inval_irq;
smp_wmb();
Expand Down
10 changes: 10 additions & 0 deletions arch/powerpc/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <linux/signal.h>
#include <linux/seccomp.h>
#include <linux/audit.h>
#include <trace/syscall.h>
#ifdef CONFIG_PPC32
#include <linux/module.h>
#endif
Expand All @@ -40,6 +41,9 @@
#include <asm/pgtable.h>
#include <asm/system.h>

#define CREATE_TRACE_POINTS
#include <trace/events/syscalls.h>

/*
* The parameter save area on the stack is used to store arguments being passed
* to callee function and is located at fixed offset from stack pointer.
Expand Down Expand Up @@ -1710,6 +1714,9 @@ long do_syscall_trace_enter(struct pt_regs *regs)
*/
ret = -1L;

if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_enter(regs, regs->gpr[0]);

if (unlikely(current->audit_context)) {
#ifdef CONFIG_PPC64
if (!is_32bit_task())
Expand Down Expand Up @@ -1738,6 +1745,9 @@ void do_syscall_trace_leave(struct pt_regs *regs)
audit_syscall_exit((regs->ccr&0x10000000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
regs->result);

if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_exit(regs, regs->result);

step = test_thread_flag(TIF_SINGLESTEP);
if (step || test_thread_flag(TIF_SYSCALL_TRACE))
tracehook_report_syscall_exit(regs, step);
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ static irqreturn_t call_function_single_action(int irq, void *data)
return IRQ_HANDLED;
}

irqreturn_t debug_ipi_action(int irq, void *data)
static irqreturn_t debug_ipi_action(int irq, void *data)
{
if (crash_ipi_function_ptr) {
crash_ipi_function_ptr(get_irq_regs());
Expand Down
24 changes: 23 additions & 1 deletion arch/powerpc/oprofile/op_model_power4.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,28 @@ static int get_kernel(unsigned long pc, unsigned long mmcra)
return is_kernel;
}

static bool pmc_overflow(unsigned long val)
{
if ((int)val < 0)
return true;

/*
* Events on POWER7 can roll back if a speculative event doesn't
* eventually complete. Unfortunately in some rare cases they will
* raise a performance monitor exception. We need to catch this to
* ensure we reset the PMC. In all cases the PMC will be 256 or less
* cycles from overflow.
*
* We only do this if the first pass fails to find any overflowing
* PMCs because a user might set a period of less than 256 and we
* don't want to mistakenly reset them.
*/
if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
return true;

return false;
}

static void power4_handle_interrupt(struct pt_regs *regs,
struct op_counter_config *ctr)
{
Expand All @@ -281,7 +303,7 @@ static void power4_handle_interrupt(struct pt_regs *regs,

for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
val = classic_ctr_read(i);
if (val < 0) {
if (pmc_overflow(val)) {
if (oprofile_running && ctr[i].enabled) {
oprofile_add_ext_sample(pc, regs, i, is_kernel);
classic_ctr_write(i, reset_value[i]);
Expand Down
Loading

0 comments on commit 6ddb451

Please sign in to comment.