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

Commit ba339c03 authored by Ralf Baechle's avatar Ralf Baechle Committed by
Browse files

MIPS: Oprofile: Fixup the loose ends in the plumbing.

parent 0401572a
Loading
Loading
Loading
Loading
+25 −1
Original line number Original line Diff line number Diff line
@@ -507,14 +507,38 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
	return IRQ_HANDLED;
	return IRQ_HANDLED;
}
}


int null_perf_irq(struct pt_regs *regs)
{
	return 0;
}

int (*perf_irq)(struct pt_regs *regs) = null_perf_irq;

EXPORT_SYMBOL(null_perf_irq);
EXPORT_SYMBOL(perf_irq);

asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs)
asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs)
{
{
	int r2 = cpu_has_mips_r2;

	irq_enter();
	irq_enter();
	kstat_this_cpu.irqs[irq]++;
	kstat_this_cpu.irqs[irq]++;


	/*
	 * Suckage alert:
	 * Before R2 of the architecture there was no way to see if a
	 * performance counter interrupt was pending, so we have to run the
	 * performance counter interrupt handler anyway.
	 */
	if (!r2 || (read_c0_cause() & (1 << 26)))
		if (perf_irq(regs))
			goto out;

	/* we keep interrupt disabled all the time */
	/* we keep interrupt disabled all the time */
	if (!r2 || (read_c0_cause() & (1 << 30)))
		timer_interrupt(irq, NULL, regs);
		timer_interrupt(irq, NULL, regs);


out:
	irq_exit();
	irq_exit();
}
}


+17 −3
Original line number Original line Diff line number Diff line
@@ -75,16 +75,29 @@ static void mips_timer_dispatch (struct pt_regs *regs)
	do_IRQ (mips_cpu_timer_irq, regs);
	do_IRQ (mips_cpu_timer_irq, regs);
}
}


extern int null_perf_irq(struct pt_regs *regs);

extern int (*perf_irq)(struct pt_regs *regs);

irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
{
	int r2 = cpu_has_mips_r2;
	int cpu = smp_processor_id();
	int cpu = smp_processor_id();


	if (cpu == 0) {
	if (cpu == 0) {
		/*
		/*
		 * CPU 0 handles the global timer interrupt job and process accounting
		 * CPU 0 handles the global timer interrupt job and process
		 * resets count/compare registers to trigger next timer int.
		 * accounting resets count/compare registers to trigger next
		 * timer int.
		 */
		 */
		timer_interrupt(irq, dev_id, regs);
		if (!r2 || (read_c0_cause() & (1 << 26)))
			if (perf_irq(regs))
				goto out;

		/* we keep interrupt disabled all the time */
		if (!r2 || (read_c0_cause() & (1 << 30)))
			timer_interrupt(irq, NULL, regs);

		scroll_display_message();
		scroll_display_message();
	} else {
	} else {
		/* Everyone else needs to reset the timer int here as
		/* Everyone else needs to reset the timer int here as
@@ -101,6 +114,7 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
		local_timer_interrupt (irq, dev_id, regs);
		local_timer_interrupt (irq, dev_id, regs);
	}
	}


out:
	return IRQ_HANDLED;
	return IRQ_HANDLED;
}
}


+2 −2
Original line number Original line Diff line number Diff line
@@ -12,8 +12,8 @@


struct pt_regs;
struct pt_regs;


extern void null_perf_irq(struct pt_regs *regs);
extern int null_perf_irq(struct pt_regs *regs);
extern void (*perf_irq)(struct pt_regs *regs);
extern int (*perf_irq)(struct pt_regs *regs);


/* Per-counter configuration as set via oprofilefs.  */
/* Per-counter configuration as set via oprofilefs.  */
struct op_counter_config {
struct op_counter_config {
+5 −1
Original line number Original line Diff line number Diff line
@@ -114,11 +114,12 @@ static void mipsxx_cpu_stop(void *args)
	}
	}
}
}


static void mipsxx_perfcount_handler(struct pt_regs *regs)
static int mipsxx_perfcount_handler(struct pt_regs *regs)
{
{
	unsigned int counters = op_model_mipsxx.num_counters;
	unsigned int counters = op_model_mipsxx.num_counters;
	unsigned int control;
	unsigned int control;
	unsigned int counter;
	unsigned int counter;
	int handled = 0;


	switch (counters) {
	switch (counters) {
#define HANDLE_COUNTER(n)						\
#define HANDLE_COUNTER(n)						\
@@ -129,12 +130,15 @@ static void mipsxx_perfcount_handler(struct pt_regs *regs)
		    (counter & M_COUNTER_OVERFLOW)) {			\
		    (counter & M_COUNTER_OVERFLOW)) {			\
			oprofile_add_sample(regs, n);			\
			oprofile_add_sample(regs, n);			\
			write_c0_perfcntr ## n(reg.counter[n]);		\
			write_c0_perfcntr ## n(reg.counter[n]);		\
			handled = 1;					\
		}
		}
	HANDLE_COUNTER(3)
	HANDLE_COUNTER(3)
	HANDLE_COUNTER(2)
	HANDLE_COUNTER(2)
	HANDLE_COUNTER(1)
	HANDLE_COUNTER(1)
	HANDLE_COUNTER(0)
	HANDLE_COUNTER(0)
	}
	}

	return handled;
}
}


#define M_CONFIG1_PC	(1 << 4)
#define M_CONFIG1_PC	(1 << 4)