From: Chris Redpath <chris.redpath@arm.com>
Date: Fri, 11 Oct 2013 10:45:01 +0000 (+0100)
Subject: smp: smp_cross_call function pointer tracing
X-Git-Tag: firefly_0821_release~3680^2~16^2^2~38
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=5ecaba3d9f4ab514fe8d383534e24b306f116896;p=firefly-linux-kernel-4.4.55.git

smp: smp_cross_call function pointer tracing

generic tracing for smp_cross_call function calls

Signed-off-by: Chris Redpath <chris.redpath@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
Signed-off-by: Jon Medhurst <tixy@linaro.org>
---

diff --git a/include/trace/events/smp.h b/include/trace/events/smp.h
new file mode 100644
index 000000000000..c8abfd744723
--- /dev/null
+++ b/include/trace/events/smp.h
@@ -0,0 +1,91 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM smp
+
+#if !defined(_TRACE_SMP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SMP_H
+
+#include <linux/tracepoint.h>
+typedef void (*__smp_call_func_t)(void *info);
+
+DECLARE_EVENT_CLASS(smp_call_class,
+
+	TP_PROTO(__smp_call_func_t fnc),
+
+	TP_ARGS(fnc),
+
+	TP_STRUCT__entry(
+		__field( void *, func )
+	),
+
+	TP_fast_assign(
+		__entry->func = fnc;
+	),
+
+	TP_printk("func=%pf", __entry->func)
+);
+
+/**
+ * smp_call_func_entry - called in the generic smp-cross-call-handler
+ * 						 immediately before calling the destination
+ * 						 function
+ * @func:  function pointer
+ *
+ * When used in combination with the smp_call_func_exit tracepoint
+ * we can determine the cross-call runtime.
+ */
+DEFINE_EVENT(smp_call_class, smp_call_func_entry,
+
+	TP_PROTO(__smp_call_func_t fnc),
+
+	TP_ARGS(fnc)
+);
+
+/**
+ * smp_call_func_exit - called in the generic smp-cross-call-handler
+ * 						immediately after the destination function
+ * 						returns
+ * @func:  function pointer
+ *
+ * When used in combination with the smp_call_entry tracepoint
+ * we can determine the cross-call runtime.
+ */
+DEFINE_EVENT(smp_call_class, smp_call_func_exit,
+
+	TP_PROTO(__smp_call_func_t fnc),
+
+	TP_ARGS(fnc)
+);
+
+/**
+ * smp_call_func_send - called as destination function is set
+ * 						in the per-cpu storage
+ * @func:  function pointer
+ * @dest:  cpu to send to
+ *
+ * When used in combination with the smp_cross_call_entry tracepoint
+ * we can determine the call-to-run latency.
+ */
+TRACE_EVENT(smp_call_func_send,
+
+	TP_PROTO(__smp_call_func_t func, int dest),
+
+	TP_ARGS(func, dest),
+
+	TP_STRUCT__entry(
+		__field(	void * 	,	func )
+		__field(	int		,	dest )
+	),
+
+	TP_fast_assign(
+		__entry->func = func;
+		__entry->dest = dest;
+	),
+
+	TP_printk("dest=%d func=%pf", __entry->dest,
+			__entry->func)
+);
+
+#endif /*  _TRACE_SMP_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/kernel/smp.c b/kernel/smp.c
index 4dba0f7b72ad..23ccc67dcbb2 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -12,6 +12,8 @@
 #include <linux/gfp.h>
 #include <linux/smp.h>
 #include <linux/cpu.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/smp.h>
 
 #include "smpboot.h"
 
@@ -159,8 +161,10 @@ void generic_exec_single(int cpu, struct call_single_data *csd, int wait)
 	 * locking and barrier primitives. Generic code isn't really
 	 * equipped to do the right thing...
 	 */
-	if (ipi)
+	if (ipi) {
+		trace_smp_call_func_send(csd->func, cpu);
 		arch_send_call_function_single_ipi(cpu);
+	}
 
 	if (wait)
 		csd_lock_wait(csd);
@@ -197,8 +201,9 @@ void generic_smp_call_function_single_interrupt(void)
 		 * so save them away before making the call:
 		 */
 		csd_flags = csd->flags;
-
+		trace_smp_call_func_entry(csd->func);
 		csd->func(csd->info);
+		trace_smp_call_func_exit(csd->func);
 
 		/*
 		 * Unlocked CSDs are valid through generic_exec_single():
@@ -228,6 +233,7 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
 	int this_cpu;
 	int err = 0;
 
+	trace_smp_call_func_send(func, cpu);
 	/*
 	 * prevent preemption and reschedule on another processor,
 	 * as well as CPU removal
@@ -245,7 +251,9 @@ int smp_call_function_single(int cpu, smp_call_func_t func, void *info,
 
 	if (cpu == this_cpu) {
 		local_irq_save(flags);
+		trace_smp_call_func_entry(func);
 		func(info);
+		trace_smp_call_func_exit(func);
 		local_irq_restore(flags);
 	} else {
 		if ((unsigned)cpu < nr_cpu_ids && cpu_online(cpu)) {