aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-01-05 19:01:58 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-01-05 19:01:58 -0500
commiteb1c838fca2248ae62e5472b496ab52d3d774cc5 (patch)
treedc1e70881e0048fc67131f009e25a1aaece60901
parentdb677ffa5f5a4f15b9dad4d132b3477b80766d82 (diff)
parente04ed38d4e0cd32141f723560efcc8252b0241e2 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6: sparc64: Fix Niagara2 perf event handling. sparc64: Fix NMI programming when perf events are active. bbc_envctrl: Clean up properly if kthread_run() fails.
-rw-r--r--arch/sparc/kernel/nmi.c3
-rw-r--r--arch/sparc/kernel/perf_event.c11
-rw-r--r--drivers/sbus/char/bbc_envctrl.c64
3 files changed, 51 insertions, 27 deletions
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
index f30f4a1ead23..d242a7340541 100644
--- a/arch/sparc/kernel/nmi.c
+++ b/arch/sparc/kernel/nmi.c
@@ -96,7 +96,6 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
96 int cpu = smp_processor_id(); 96 int cpu = smp_processor_id();
97 97
98 clear_softint(1 << irq); 98 clear_softint(1 << irq);
99 pcr_ops->write(PCR_PIC_PRIV);
100 99
101 local_cpu_data().__nmi_count++; 100 local_cpu_data().__nmi_count++;
102 101
@@ -105,6 +104,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
105 if (notify_die(DIE_NMI, "nmi", regs, 0, 104 if (notify_die(DIE_NMI, "nmi", regs, 0,
106 pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) 105 pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
107 touched = 1; 106 touched = 1;
107 else
108 pcr_ops->write(PCR_PIC_PRIV);
108 109
109 sum = kstat_irqs_cpu(0, cpu); 110 sum = kstat_irqs_cpu(0, cpu);
110 if (__get_cpu_var(nmi_touch)) { 111 if (__get_cpu_var(nmi_touch)) {
diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c
index fa5936e1c3b9..198fb4e79ba2 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -986,6 +986,17 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
986 data.addr = 0; 986 data.addr = 0;
987 987
988 cpuc = &__get_cpu_var(cpu_hw_events); 988 cpuc = &__get_cpu_var(cpu_hw_events);
989
990 /* If the PMU has the TOE IRQ enable bits, we need to do a
991 * dummy write to the %pcr to clear the overflow bits and thus
992 * the interrupt.
993 *
994 * Do this before we peek at the counters to determine
995 * overflow so we don't lose any events.
996 */
997 if (sparc_pmu->irq_bit)
998 pcr_ops->write(cpuc->pcr);
999
989 for (idx = 0; idx < MAX_HWEVENTS; idx++) { 1000 for (idx = 0; idx < MAX_HWEVENTS; idx++) {
990 struct perf_event *event = cpuc->events[idx]; 1001 struct perf_event *event = cpuc->events[idx];
991 struct hw_perf_event *hwc; 1002 struct hw_perf_event *hwc;
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c
index 7c815d3327f7..28d86f9df83c 100644
--- a/drivers/sbus/char/bbc_envctrl.c
+++ b/drivers/sbus/char/bbc_envctrl.c
@@ -522,6 +522,40 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op,
522 set_fan_speeds(fp); 522 set_fan_speeds(fp);
523} 523}
524 524
525static void destroy_one_temp(struct bbc_cpu_temperature *tp)
526{
527 bbc_i2c_detach(tp->client);
528 kfree(tp);
529}
530
531static void destroy_all_temps(struct bbc_i2c_bus *bp)
532{
533 struct bbc_cpu_temperature *tp, *tpos;
534
535 list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
536 list_del(&tp->bp_list);
537 list_del(&tp->glob_list);
538 destroy_one_temp(tp);
539 }
540}
541
542static void destroy_one_fan(struct bbc_fan_control *fp)
543{
544 bbc_i2c_detach(fp->client);
545 kfree(fp);
546}
547
548static void destroy_all_fans(struct bbc_i2c_bus *bp)
549{
550 struct bbc_fan_control *fp, *fpos;
551
552 list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
553 list_del(&fp->bp_list);
554 list_del(&fp->glob_list);
555 destroy_one_fan(fp);
556 }
557}
558
525int bbc_envctrl_init(struct bbc_i2c_bus *bp) 559int bbc_envctrl_init(struct bbc_i2c_bus *bp)
526{ 560{
527 struct of_device *op; 561 struct of_device *op;
@@ -541,6 +575,8 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
541 int err = PTR_ERR(kenvctrld_task); 575 int err = PTR_ERR(kenvctrld_task);
542 576
543 kenvctrld_task = NULL; 577 kenvctrld_task = NULL;
578 destroy_all_temps(bp);
579 destroy_all_fans(bp);
544 return err; 580 return err;
545 } 581 }
546 } 582 }
@@ -548,35 +584,11 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
548 return 0; 584 return 0;
549} 585}
550 586
551static void destroy_one_temp(struct bbc_cpu_temperature *tp)
552{
553 bbc_i2c_detach(tp->client);
554 kfree(tp);
555}
556
557static void destroy_one_fan(struct bbc_fan_control *fp)
558{
559 bbc_i2c_detach(fp->client);
560 kfree(fp);
561}
562
563void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp) 587void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp)
564{ 588{
565 struct bbc_cpu_temperature *tp, *tpos;
566 struct bbc_fan_control *fp, *fpos;
567
568 if (kenvctrld_task) 589 if (kenvctrld_task)
569 kthread_stop(kenvctrld_task); 590 kthread_stop(kenvctrld_task);
570 591
571 list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) { 592 destroy_all_temps(bp);
572 list_del(&tp->bp_list); 593 destroy_all_fans(bp);
573 list_del(&tp->glob_list);
574 destroy_one_temp(tp);
575 }
576
577 list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
578 list_del(&fp->bp_list);
579 list_del(&fp->glob_list);
580 destroy_one_fan(fp);
581 }
582} 594}