From 74014c9a85207bb3b0093b531fb79c48801aa73c Mon Sep 17 00:00:00 2001
From: Oussama Ghorbel <ghorbel@gmail.com>
Date: Mon, 28 Nov 2016 16:00:51 +0100
Subject: [PATCH 1/2] arm: add stat support to fiq

This patch allows drivers that uses fiq to have a stat on the
execution number of the fiq handler.
For that three APIs has been defined:
- fiq_kstat_enable: this function enables fiq stat and allocates required
memory for it
- fiq_kstat_disable: this function disable fiq stat and free its allocated
memory
- fiq_kstat_this_cpu_inc: This function increments the fiq stat counter of
the current CPU running the fiq handler

A driver may call fiq_kstat_enable at its initialization to enable fiq
stat and then call fiq_kstat_this_cpu_inc from the fiq handler

When the fiq stat is enabled by a driver, then /proc/interrupts shows the
fiq entry as the following example:
FIQ:          0   21642080          0          0  usb_fiq
If the fiq stat is not enabled, the content will be similar to the old one
as the following example:
FIQ:                                              usb_fiq
The fiq name will be always written on the first column after the last CPU
column

Signed-off-by: Oussama Ghorbel <ghorbel@gmail.com>
---
 arch/arm/include/asm/fiq.h | 10 ++++++++++
 arch/arm/kernel/fiq.c      | 31 +++++++++++++++++++++++++++----
 2 files changed, 37 insertions(+), 4 deletions(-)

Index: linux-rpi-4.18.4-test/arch/arm/include/asm/fiq.h
===================================================================
@ linux-rpi-4.18.4-test/arch/arm/include/asm/fiq.h:35 @ struct fiq_handler {
 	/* data for the relinquish/reacquire functions
 	 */
 	void *dev_id;
+	/* fiq stats percpu */
+	unsigned int __percpu *fiq_kstat;
 };
 
 extern int claim_fiq(struct fiq_handler *f);
@ linux-rpi-4.18.4-test/arch/arm/include/asm/fiq.h:59 @ static inline void get_fiq_regs(struct p
 	__get_fiq_regs(&regs->ARM_r8);
 }
 
+extern int fiq_kstat_enable(struct fiq_handler *fh);
+extern void fiq_kstat_disable(struct fiq_handler *fh);
+
+static inline void fiq_kstat_this_cpu_inc(struct fiq_handler *fh)
+{
+	__this_cpu_inc(*fh->fiq_kstat);
+}
+
 #endif
Index: linux-rpi-4.18.4-test/arch/arm/kernel/fiq.c
===================================================================
--- linux-rpi-4.18.4-test.orig/arch/arm/kernel/fiq.c
+++ linux-rpi-4.18.4-test/arch/arm/kernel/fiq.c
@ linux-rpi-4.18.4-test/arch/arm/include/asm/fiq.h:89 @ static struct fiq_handler *current_fiq =
 
 int show_fiq_list(struct seq_file *p, int prec)
 {
-	if (current_fiq != &default_owner)
-		seq_printf(p, "%*s:              %s\n", prec, "FIQ",
-			current_fiq->name);
+	int j;
 
+	if (current_fiq == &default_owner)
+		return 0;
+	seq_printf(p, "%*s: ", prec, "FIQ");
+	for_each_online_cpu(j) {
+		if (current_fiq->fiq_kstat)
+			seq_printf(p, "%10u ",
+				*per_cpu_ptr(current_fiq->fiq_kstat, j));
+		else
+			seq_printf(p, "%10s ", "");
+	}
+	seq_printf(p, " %s\n", current_fiq->name);
 	return 0;
 }
 
@ linux-rpi-4.18.4-test/arch/arm/include/asm/fiq.h:179 @ void __init init_FIQ(int start)
 	get_fiq_regs(&dfl_fiq_regs);
 	fiq_start = start;
 }
+
+int fiq_kstat_enable(struct fiq_handler *fh)
+{
+	fh->fiq_kstat = alloc_percpu(unsigned int);
+	return fh->fiq_kstat != 0 ? 0 : 1;
+}
+EXPORT_SYMBOL(fiq_kstat_enable);
+
+void fiq_kstat_disable(struct fiq_handler *fh)
+{
+	free_percpu(fh->fiq_kstat);
+	fh->fiq_kstat = NULL;
+}
+EXPORT_SYMBOL(fiq_kstat_disable);