diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-05 19:01:58 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-05 19:01:58 -0500 |
commit | eb1c838fca2248ae62e5472b496ab52d3d774cc5 (patch) | |
tree | dc1e70881e0048fc67131f009e25a1aaece60901 | |
parent | db677ffa5f5a4f15b9dad4d132b3477b80766d82 (diff) | |
parent | e04ed38d4e0cd32141f723560efcc8252b0241e2 (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.c | 3 | ||||
-rw-r--r-- | arch/sparc/kernel/perf_event.c | 11 | ||||
-rw-r--r-- | drivers/sbus/char/bbc_envctrl.c | 64 |
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 | ||
525 | static void destroy_one_temp(struct bbc_cpu_temperature *tp) | ||
526 | { | ||
527 | bbc_i2c_detach(tp->client); | ||
528 | kfree(tp); | ||
529 | } | ||
530 | |||
531 | static 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 | |||
542 | static void destroy_one_fan(struct bbc_fan_control *fp) | ||
543 | { | ||
544 | bbc_i2c_detach(fp->client); | ||
545 | kfree(fp); | ||
546 | } | ||
547 | |||
548 | static 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 | |||
525 | int bbc_envctrl_init(struct bbc_i2c_bus *bp) | 559 | int 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 | ||
551 | static void destroy_one_temp(struct bbc_cpu_temperature *tp) | ||
552 | { | ||
553 | bbc_i2c_detach(tp->client); | ||
554 | kfree(tp); | ||
555 | } | ||
556 | |||
557 | static void destroy_one_fan(struct bbc_fan_control *fp) | ||
558 | { | ||
559 | bbc_i2c_detach(fp->client); | ||
560 | kfree(fp); | ||
561 | } | ||
562 | |||
563 | void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp) | 587 | void 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 | } |