forked from Minki/linux
8cf868affd
Some tracepoints have a registration function that gets enabled when the tracepoint is enabled. There may be cases that the registraction function must fail (for example, can't allocate enough memory). In this case, the tracepoint should also fail to register, otherwise the user would not know why the tracepoint is not working. Cc: David Howells <dhowells@redhat.com> Cc: Seiji Aguchi <seiji.aguchi@hds.com> Cc: Anton Blanchard <anton@samba.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
61 lines
1.3 KiB
C
61 lines
1.3 KiB
C
/*
|
|
* Code for supporting irq vector tracepoints.
|
|
*
|
|
* Copyright (C) 2013 Seiji Aguchi <seiji.aguchi@hds.com>
|
|
*
|
|
*/
|
|
#include <asm/hw_irq.h>
|
|
#include <asm/desc.h>
|
|
#include <linux/atomic.h>
|
|
|
|
atomic_t trace_idt_ctr = ATOMIC_INIT(0);
|
|
struct desc_ptr trace_idt_descr = { NR_VECTORS * 16 - 1,
|
|
(unsigned long) trace_idt_table };
|
|
|
|
/* No need to be aligned, but done to keep all IDTs defined the same way. */
|
|
gate_desc trace_idt_table[NR_VECTORS] __page_aligned_bss;
|
|
|
|
static int trace_irq_vector_refcount;
|
|
static DEFINE_MUTEX(irq_vector_mutex);
|
|
|
|
static void set_trace_idt_ctr(int val)
|
|
{
|
|
atomic_set(&trace_idt_ctr, val);
|
|
/* Ensure the trace_idt_ctr is set before sending IPI */
|
|
wmb();
|
|
}
|
|
|
|
static void switch_idt(void *arg)
|
|
{
|
|
unsigned long flags;
|
|
|
|
local_irq_save(flags);
|
|
load_current_idt();
|
|
local_irq_restore(flags);
|
|
}
|
|
|
|
int trace_irq_vector_regfunc(void)
|
|
{
|
|
mutex_lock(&irq_vector_mutex);
|
|
if (!trace_irq_vector_refcount) {
|
|
set_trace_idt_ctr(1);
|
|
smp_call_function(switch_idt, NULL, 0);
|
|
switch_idt(NULL);
|
|
}
|
|
trace_irq_vector_refcount++;
|
|
mutex_unlock(&irq_vector_mutex);
|
|
return 0;
|
|
}
|
|
|
|
void trace_irq_vector_unregfunc(void)
|
|
{
|
|
mutex_lock(&irq_vector_mutex);
|
|
trace_irq_vector_refcount--;
|
|
if (!trace_irq_vector_refcount) {
|
|
set_trace_idt_ctr(0);
|
|
smp_call_function(switch_idt, NULL, 0);
|
|
switch_idt(NULL);
|
|
}
|
|
mutex_unlock(&irq_vector_mutex);
|
|
}
|