Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb1c838f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 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.
parents db677ffa e04ed38d
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -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)) {
+11 −0
Original line number Original line Diff line number Diff line
@@ -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;
+38 −26
Original line number Original line Diff line number Diff line
@@ -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);
	}
}
}