forked from luck/tmp_suning_uos_patched
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.
This commit is contained in:
commit
eb1c838fca
@ -96,7 +96,6 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
|
|||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
|
|
||||||
clear_softint(1 << irq);
|
clear_softint(1 << irq);
|
||||||
pcr_ops->write(PCR_PIC_PRIV);
|
|
||||||
|
|
||||||
local_cpu_data().__nmi_count++;
|
local_cpu_data().__nmi_count++;
|
||||||
|
|
||||||
@ -105,6 +104,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
|
|||||||
if (notify_die(DIE_NMI, "nmi", regs, 0,
|
if (notify_die(DIE_NMI, "nmi", regs, 0,
|
||||||
pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
|
pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
|
||||||
touched = 1;
|
touched = 1;
|
||||||
|
else
|
||||||
|
pcr_ops->write(PCR_PIC_PRIV);
|
||||||
|
|
||||||
sum = kstat_irqs_cpu(0, cpu);
|
sum = kstat_irqs_cpu(0, cpu);
|
||||||
if (__get_cpu_var(nmi_touch)) {
|
if (__get_cpu_var(nmi_touch)) {
|
||||||
|
@ -986,6 +986,17 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self,
|
|||||||
data.addr = 0;
|
data.addr = 0;
|
||||||
|
|
||||||
cpuc = &__get_cpu_var(cpu_hw_events);
|
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++) {
|
for (idx = 0; idx < MAX_HWEVENTS; idx++) {
|
||||||
struct perf_event *event = cpuc->events[idx];
|
struct perf_event *event = cpuc->events[idx];
|
||||||
struct hw_perf_event *hwc;
|
struct hw_perf_event *hwc;
|
||||||
|
@ -522,6 +522,40 @@ static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op,
|
|||||||
set_fan_speeds(fp);
|
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)
|
int bbc_envctrl_init(struct bbc_i2c_bus *bp)
|
||||||
{
|
{
|
||||||
struct of_device *op;
|
struct of_device *op;
|
||||||
@ -541,6 +575,8 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
|
|||||||
int err = PTR_ERR(kenvctrld_task);
|
int err = PTR_ERR(kenvctrld_task);
|
||||||
|
|
||||||
kenvctrld_task = NULL;
|
kenvctrld_task = NULL;
|
||||||
|
destroy_all_temps(bp);
|
||||||
|
destroy_all_fans(bp);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -548,35 +584,11 @@ int bbc_envctrl_init(struct bbc_i2c_bus *bp)
|
|||||||
return 0;
|
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)
|
void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp)
|
||||||
{
|
{
|
||||||
struct bbc_cpu_temperature *tp, *tpos;
|
|
||||||
struct bbc_fan_control *fp, *fpos;
|
|
||||||
|
|
||||||
if (kenvctrld_task)
|
if (kenvctrld_task)
|
||||||
kthread_stop(kenvctrld_task);
|
kthread_stop(kenvctrld_task);
|
||||||
|
|
||||||
list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) {
|
destroy_all_temps(bp);
|
||||||
list_del(&tp->bp_list);
|
destroy_all_fans(bp);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user