aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/time.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-12 21:48:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-12 21:48:26 -0400
commitbe835674b55324c1abe973b15343c3663910c620 (patch)
tree481604c6b68bc5c37e9674e72ea3f967ee609b1b /arch/powerpc/kernel/time.c
parent5ec390e046039942d59ef2634b967b8b23fc57c2 (diff)
parent131c6c9eddfa252e376edb4aeff9c7fe1b96a798 (diff)
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
Diffstat (limited to 'arch/powerpc/kernel/time.c')
-rw-r--r--arch/powerpc/kernel/time.c60
1 files changed, 48 insertions, 12 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 1b16b9a3e49a..0441bbdadbd1 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -532,25 +532,60 @@ void __init iSeries_time_init_early(void)
532} 532}
533#endif /* CONFIG_PPC_ISERIES */ 533#endif /* CONFIG_PPC_ISERIES */
534 534
535#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_PPC32) 535#ifdef CONFIG_PERF_EVENTS
536DEFINE_PER_CPU(u8, perf_event_pending);
537 536
538void set_perf_event_pending(void) 537/*
538 * 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable...
539 */
540#ifdef CONFIG_PPC64
541static inline unsigned long test_perf_event_pending(void)
539{ 542{
540 get_cpu_var(perf_event_pending) = 1; 543 unsigned long x;
541 set_dec(1); 544
542 put_cpu_var(perf_event_pending); 545 asm volatile("lbz %0,%1(13)"
546 : "=r" (x)
547 : "i" (offsetof(struct paca_struct, perf_event_pending)));
548 return x;
543} 549}
544 550
551static inline void set_perf_event_pending_flag(void)
552{
553 asm volatile("stb %0,%1(13)" : :
554 "r" (1),
555 "i" (offsetof(struct paca_struct, perf_event_pending)));
556}
557
558static inline void clear_perf_event_pending(void)
559{
560 asm volatile("stb %0,%1(13)" : :
561 "r" (0),
562 "i" (offsetof(struct paca_struct, perf_event_pending)));
563}
564
565#else /* 32-bit */
566
567DEFINE_PER_CPU(u8, perf_event_pending);
568
569#define set_perf_event_pending_flag() __get_cpu_var(perf_event_pending) = 1
545#define test_perf_event_pending() __get_cpu_var(perf_event_pending) 570#define test_perf_event_pending() __get_cpu_var(perf_event_pending)
546#define clear_perf_event_pending() __get_cpu_var(perf_event_pending) = 0 571#define clear_perf_event_pending() __get_cpu_var(perf_event_pending) = 0
547 572
548#else /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */ 573#endif /* 32 vs 64 bit */
574
575void set_perf_event_pending(void)
576{
577 preempt_disable();
578 set_perf_event_pending_flag();
579 set_dec(1);
580 preempt_enable();
581}
582
583#else /* CONFIG_PERF_EVENTS */
549 584
550#define test_perf_event_pending() 0 585#define test_perf_event_pending() 0
551#define clear_perf_event_pending() 586#define clear_perf_event_pending()
552 587
553#endif /* CONFIG_PERF_EVENTS && CONFIG_PPC32 */ 588#endif /* CONFIG_PERF_EVENTS */
554 589
555/* 590/*
556 * For iSeries shared processors, we have to let the hypervisor 591 * For iSeries shared processors, we have to let the hypervisor
@@ -582,10 +617,6 @@ void timer_interrupt(struct pt_regs * regs)
582 set_dec(DECREMENTER_MAX); 617 set_dec(DECREMENTER_MAX);
583 618
584#ifdef CONFIG_PPC32 619#ifdef CONFIG_PPC32
585 if (test_perf_event_pending()) {
586 clear_perf_event_pending();
587 perf_event_do_pending();
588 }
589 if (atomic_read(&ppc_n_lost_interrupts) != 0) 620 if (atomic_read(&ppc_n_lost_interrupts) != 0)
590 do_IRQ(regs); 621 do_IRQ(regs);
591#endif 622#endif
@@ -604,6 +635,11 @@ void timer_interrupt(struct pt_regs * regs)
604 635
605 calculate_steal_time(); 636 calculate_steal_time();
606 637
638 if (test_perf_event_pending()) {
639 clear_perf_event_pending();
640 perf_event_do_pending();
641 }
642
607#ifdef CONFIG_PPC_ISERIES 643#ifdef CONFIG_PPC_ISERIES
608 if (firmware_has_feature(FW_FEATURE_ISERIES)) 644 if (firmware_has_feature(FW_FEATURE_ISERIES))
609 get_lppaca()->int_dword.fields.decr_int = 0; 645 get_lppaca()->int_dword.fields.decr_int = 0;