Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: powerpc/perf_event: Fix oops due to perf_event_do_pending call powerpc/swiotlb: Fix off by one in determining boundary of which ops to use
This commit is contained in:
commit
be835674b5
6 changed files with 51 additions and 68 deletions
|
@ -130,43 +130,5 @@ static inline int irqs_disabled_flags(unsigned long flags)
|
||||||
*/
|
*/
|
||||||
struct irq_chip;
|
struct irq_chip;
|
||||||
|
|
||||||
#ifdef CONFIG_PERF_EVENTS
|
|
||||||
|
|
||||||
#ifdef CONFIG_PPC64
|
|
||||||
static inline unsigned long test_perf_event_pending(void)
|
|
||||||
{
|
|
||||||
unsigned long x;
|
|
||||||
|
|
||||||
asm volatile("lbz %0,%1(13)"
|
|
||||||
: "=r" (x)
|
|
||||||
: "i" (offsetof(struct paca_struct, perf_event_pending)));
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void set_perf_event_pending(void)
|
|
||||||
{
|
|
||||||
asm volatile("stb %0,%1(13)" : :
|
|
||||||
"r" (1),
|
|
||||||
"i" (offsetof(struct paca_struct, perf_event_pending)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void clear_perf_event_pending(void)
|
|
||||||
{
|
|
||||||
asm volatile("stb %0,%1(13)" : :
|
|
||||||
"r" (0),
|
|
||||||
"i" (offsetof(struct paca_struct, perf_event_pending)));
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_PPC64 */
|
|
||||||
|
|
||||||
#else /* CONFIG_PERF_EVENTS */
|
|
||||||
|
|
||||||
static inline unsigned long test_perf_event_pending(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void clear_perf_event_pending(void) {}
|
|
||||||
#endif /* CONFIG_PERF_EVENTS */
|
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
#endif /* _ASM_POWERPC_HW_IRQ_H */
|
#endif /* _ASM_POWERPC_HW_IRQ_H */
|
||||||
|
|
|
@ -133,7 +133,6 @@ int main(void)
|
||||||
DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
|
DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
|
||||||
DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
|
DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
|
||||||
DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
|
DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
|
||||||
DEFINE(PACAPERFPEND, offsetof(struct paca_struct, perf_event_pending));
|
|
||||||
DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
|
DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id));
|
||||||
#ifdef CONFIG_PPC_MM_SLICES
|
#ifdef CONFIG_PPC_MM_SLICES
|
||||||
DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
|
DEFINE(PACALOWSLICESPSIZE, offsetof(struct paca_struct,
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Contains routines needed to support swiotlb for ppc.
|
* Contains routines needed to support swiotlb for ppc.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Becky Bruce, Freescale Semiconductor
|
* Copyright (C) 2009-2010 Freescale Semiconductor, Inc.
|
||||||
|
* Author: Becky Bruce
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
@ -70,7 +71,7 @@ static int ppc_swiotlb_bus_notify(struct notifier_block *nb,
|
||||||
sd->max_direct_dma_addr = 0;
|
sd->max_direct_dma_addr = 0;
|
||||||
|
|
||||||
/* May need to bounce if the device can't address all of DRAM */
|
/* May need to bounce if the device can't address all of DRAM */
|
||||||
if (dma_get_mask(dev) < lmb_end_of_DRAM())
|
if ((dma_get_mask(dev) + 1) < lmb_end_of_DRAM())
|
||||||
set_dma_ops(dev, &swiotlb_dma_ops);
|
set_dma_ops(dev, &swiotlb_dma_ops);
|
||||||
|
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
|
|
|
@ -556,15 +556,6 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
|
||||||
2:
|
2:
|
||||||
TRACE_AND_RESTORE_IRQ(r5);
|
TRACE_AND_RESTORE_IRQ(r5);
|
||||||
|
|
||||||
#ifdef CONFIG_PERF_EVENTS
|
|
||||||
/* check paca->perf_event_pending if we're enabling ints */
|
|
||||||
lbz r3,PACAPERFPEND(r13)
|
|
||||||
and. r3,r3,r5
|
|
||||||
beq 27f
|
|
||||||
bl .perf_event_do_pending
|
|
||||||
27:
|
|
||||||
#endif /* CONFIG_PERF_EVENTS */
|
|
||||||
|
|
||||||
/* extract EE bit and use it to restore paca->hard_enabled */
|
/* extract EE bit and use it to restore paca->hard_enabled */
|
||||||
ld r3,_MSR(r1)
|
ld r3,_MSR(r1)
|
||||||
rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */
|
rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */
|
||||||
|
|
|
@ -53,7 +53,6 @@
|
||||||
#include <linux/bootmem.h>
|
#include <linux/bootmem.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/perf_event.h>
|
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
@ -145,11 +144,6 @@ notrace void raw_local_irq_restore(unsigned long en)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PPC_STD_MMU_64 */
|
#endif /* CONFIG_PPC_STD_MMU_64 */
|
||||||
|
|
||||||
if (test_perf_event_pending()) {
|
|
||||||
clear_perf_event_pending();
|
|
||||||
perf_event_do_pending();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if (get_paca()->hard_enabled) return;
|
* if (get_paca()->hard_enabled) return;
|
||||||
* But again we need to take care that gcc gets hard_enabled directly
|
* But again we need to take care that gcc gets hard_enabled directly
|
||||||
|
|
|
@ -532,25 +532,60 @@ void __init iSeries_time_init_early(void)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PPC_ISERIES */
|
#endif /* CONFIG_PPC_ISERIES */
|
||||||
|
|
||||||
#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_PPC32)
|
#ifdef CONFIG_PERF_EVENTS
|
||||||
DEFINE_PER_CPU(u8, perf_event_pending);
|
|
||||||
|
|
||||||
void set_perf_event_pending(void)
|
/*
|
||||||
|
* 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable...
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_PPC64
|
||||||
|
static inline unsigned long test_perf_event_pending(void)
|
||||||
{
|
{
|
||||||
get_cpu_var(perf_event_pending) = 1;
|
unsigned long x;
|
||||||
set_dec(1);
|
|
||||||
put_cpu_var(perf_event_pending);
|
asm volatile("lbz %0,%1(13)"
|
||||||
|
: "=r" (x)
|
||||||
|
: "i" (offsetof(struct paca_struct, perf_event_pending)));
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void set_perf_event_pending_flag(void)
|
||||||
|
{
|
||||||
|
asm volatile("stb %0,%1(13)" : :
|
||||||
|
"r" (1),
|
||||||
|
"i" (offsetof(struct paca_struct, perf_event_pending)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void clear_perf_event_pending(void)
|
||||||
|
{
|
||||||
|
asm volatile("stb %0,%1(13)" : :
|
||||||
|
"r" (0),
|
||||||
|
"i" (offsetof(struct paca_struct, perf_event_pending)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* 32-bit */
|
||||||
|
|
||||||
|
DEFINE_PER_CPU(u8, perf_event_pending);
|
||||||
|
|
||||||
|
#define set_perf_event_pending_flag() __get_cpu_var(perf_event_pending) = 1
|
||||||
#define test_perf_event_pending() __get_cpu_var(perf_event_pending)
|
#define test_perf_event_pending() __get_cpu_var(perf_event_pending)
|
||||||
#define clear_perf_event_pending() __get_cpu_var(perf_event_pending) = 0
|
#define clear_perf_event_pending() __get_cpu_var(perf_event_pending) = 0
|
||||||
|
|
||||||
#else /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */
|
#endif /* 32 vs 64 bit */
|
||||||
|
|
||||||
|
void set_perf_event_pending(void)
|
||||||
|
{
|
||||||
|
preempt_disable();
|
||||||
|
set_perf_event_pending_flag();
|
||||||
|
set_dec(1);
|
||||||
|
preempt_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* CONFIG_PERF_EVENTS */
|
||||||
|
|
||||||
#define test_perf_event_pending() 0
|
#define test_perf_event_pending() 0
|
||||||
#define clear_perf_event_pending()
|
#define clear_perf_event_pending()
|
||||||
|
|
||||||
#endif /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */
|
#endif /* CONFIG_PERF_EVENTS */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For iSeries shared processors, we have to let the hypervisor
|
* For iSeries shared processors, we have to let the hypervisor
|
||||||
|
@ -582,10 +617,6 @@ void timer_interrupt(struct pt_regs * regs)
|
||||||
set_dec(DECREMENTER_MAX);
|
set_dec(DECREMENTER_MAX);
|
||||||
|
|
||||||
#ifdef CONFIG_PPC32
|
#ifdef CONFIG_PPC32
|
||||||
if (test_perf_event_pending()) {
|
|
||||||
clear_perf_event_pending();
|
|
||||||
perf_event_do_pending();
|
|
||||||
}
|
|
||||||
if (atomic_read(&ppc_n_lost_interrupts) != 0)
|
if (atomic_read(&ppc_n_lost_interrupts) != 0)
|
||||||
do_IRQ(regs);
|
do_IRQ(regs);
|
||||||
#endif
|
#endif
|
||||||
|
@ -604,6 +635,11 @@ void timer_interrupt(struct pt_regs * regs)
|
||||||
|
|
||||||
calculate_steal_time();
|
calculate_steal_time();
|
||||||
|
|
||||||
|
if (test_perf_event_pending()) {
|
||||||
|
clear_perf_event_pending();
|
||||||
|
perf_event_do_pending();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_ISERIES
|
#ifdef CONFIG_PPC_ISERIES
|
||||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||||
get_lppaca()->int_dword.fields.decr_int = 0;
|
get_lppaca()->int_dword.fields.decr_int = 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue