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 | } |
