Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
torvalds committed Jan 6, 2010
2 parents db677ff + e04ed38 commit eb1c838
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 27 deletions.
3 changes: 2 additions & 1 deletion arch/sparc/kernel/nmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
int cpu = smp_processor_id();

clear_softint(1 << irq);
pcr_ops->write(PCR_PIC_PRIV);

local_cpu_data().__nmi_count++;

Expand All @@ -105,6 +104,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
if (notify_die(DIE_NMI, "nmi", regs, 0,
pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
touched = 1;
else
pcr_ops->write(PCR_PIC_PRIV);

sum = kstat_irqs_cpu(0, cpu);
if (__get_cpu_var(nmi_touch)) {
Expand Down
11 changes: 11 additions & 0 deletions arch/sparc/kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,17 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
data.addr = 0;

cpuc = &__get_cpu_var(cpu_hw_events);

/* If the PMU has the TOE IRQ enable bits, we need to do a
* dummy write to the %pcr to clear the overflow bits and thus
* the interrupt.
*
* Do this before we peek at the counters to determine
* overflow so we don't lose any events.
*/
if (sparc_pmu->irq_bit)
pcr_ops->write(cpuc->pcr);

for (idx = 0; idx < MAX_HWEVENTS; idx++) {
struct perf_event *event = cpuc->events[idx];
struct hw_perf_event *hwc;
Expand Down
64 changes: 38 additions & 26 deletions drivers/sbus/char/bbc_envctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,40 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op,
set_fan_speeds(fp);
}

static void destroy_one_temp(struct bbc_cpu_temperature *tp)
{
bbc_i2c_detach(tp->client);
kfree(tp);
}

static void destroy_all_temps(struct bbc_i2c_bus *bp)
{
struct bbc_cpu_temperature *tp, *tpos;

list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
list_del(&tp->bp_list);
list_del(&tp->glob_list);
destroy_one_temp(tp);
}
}

static void destroy_one_fan(struct bbc_fan_control *fp)
{
bbc_i2c_detach(fp->client);
kfree(fp);
}

static void destroy_all_fans(struct bbc_i2c_bus *bp)
{
struct bbc_fan_control *fp, *fpos;

list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
list_del(&fp->bp_list);
list_del(&fp->glob_list);
destroy_one_fan(fp);
}
}

int bbc_envctrl_init(struct bbc_i2c_bus *bp)
{
struct of_device *op;
Expand All @@ -541,42 +575,20 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
int err = PTR_ERR(kenvctrld_task);

kenvctrld_task = NULL;
destroy_all_temps(bp);
destroy_all_fans(bp);
return err;
}
}

return 0;
}

static void destroy_one_temp(struct bbc_cpu_temperature *tp)
{
bbc_i2c_detach(tp->client);
kfree(tp);
}

static void destroy_one_fan(struct bbc_fan_control *fp)
{
bbc_i2c_detach(fp->client);
kfree(fp);
}

void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp)
{
struct bbc_cpu_temperature *tp, *tpos;
struct bbc_fan_control *fp, *fpos;

if (kenvctrld_task)
kthread_stop(kenvctrld_task);

list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
list_del(&tp->bp_list);
list_del(&tp->glob_list);
destroy_one_temp(tp);
}

list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) {
list_del(&fp->bp_list);
list_del(&fp->glob_list);
destroy_one_fan(fp);
}
destroy_all_temps(bp);
destroy_all_fans(bp);
}

0 comments on commit eb1c838

Please sign in to comment.