From 1178d575392f85a0c24e02d49a973b999fd8587f Mon Sep 17 00:00:00 2001
From: Luis Gerhorst <luis.gerhorst@fau.de>
Date: Tue, 10 Jul 2018 23:41:32 +0200
Subject: [PATCH] Seperate trigger from sysfs, cleanup

---
 arch/arm/measuremore/Kbuild              |   4 +-
 arch/arm/measuremore/measure.c           |   6 +-
 arch/arm/measuremore/pmccntr_timestamp.c |   2 -
 arch/arm/measuremore/sysfs.c             | 290 +++++++++++++++
 arch/arm/measuremore/sysfs.h             |   6 +
 arch/arm/measuremore/trigger.c           | 449 +++++------------------
 arch/arm/measuremore/trigger.h           |  26 +-
 7 files changed, 412 insertions(+), 371 deletions(-)
 create mode 100644 arch/arm/measuremore/sysfs.c
 create mode 100644 arch/arm/measuremore/sysfs.h

diff --git a/arch/arm/measuremore/Kbuild b/arch/arm/measuremore/Kbuild
index fbf934b..130b687 100644
--- a/arch/arm/measuremore/Kbuild
+++ b/arch/arm/measuremore/Kbuild
@@ -1,8 +1,8 @@
 ccflags-$(CONFIG_MEASUREMORE) := -std=gnu99 -Wno-declaration-after-statement
 obj-$(CONFIG_MEASUREMORE) += measuremore.o
-measuremore-objs += trigger.o measure.o pmccntr_timestamp.o
+measuremore-objs += sysfs.o trigger.o measure.o pmccntr_timestamp.o
 
-$(obj)/trigger.o: $(obj)/kernel_memo_git_commit.h $(obj)/kernel_memo_git_status.h
+$(obj)/sysfs.o: $(obj)/kernel_memo_git_commit.h $(obj)/kernel_memo_git_status.h
 
 targets += $(obj)/kernel_memo_git_commit.h $(obj)/kernel_memo_git_status.h
 
diff --git a/arch/arm/measuremore/measure.c b/arch/arm/measuremore/measure.c
index 84a8590..1168de7 100644
--- a/arch/arm/measuremore/measure.c
+++ b/arch/arm/measuremore/measure.c
@@ -8,12 +8,11 @@
 #include <linux/string.h>
 
 #include <linux/measuremore.h>
-#include "trigger.h"
 
+#include "sysfs.h"
 #ifdef CONFIG_MEASUREMORE_TIMESTAMP_TYPE_PMCCNTR
 #include "pmccntr_timestamp.h"
 #endif
-
 #include "measure.h"
 
 bool debugfs_vmalloc_cp_matrix;
@@ -191,11 +190,10 @@ static void create_csv_file(const char *name,
 			    struct dentry *folder)
 {
 	pr_info("Exporting %s field...", name);
-	pr_info("seq_write_field is %p\n", seq_write_field);
 	struct dentry *csv_file = debugfs_create_file(name, 0400, folder, seq_write_field,
 						      &csv_file_ops);
 	BUG_ON(!csv_file);
-	pr_info("done\n");
+	pr_info(" done\n");
 }
 
 #ifdef CONFIG_MEASUREMORE_TIMESTAMP_TYPE_PMCCNTR
diff --git a/arch/arm/measuremore/pmccntr_timestamp.c b/arch/arm/measuremore/pmccntr_timestamp.c
index 7d6c29a..7be8dbb 100644
--- a/arch/arm/measuremore/pmccntr_timestamp.c
+++ b/arch/arm/measuremore/pmccntr_timestamp.c
@@ -122,12 +122,10 @@ union PMCR {
 static union PMCR pmcr_read(void) {
 	union PMCR pmcr;
 	asm volatile ("mrc p15, 0, %0, c9, c12, 0\n\t" : "=r" (pmcr.value));
-	pr_info("Read pmcr %x\n", pmcr.value);
 	return pmcr;
 }
 
 static void pmcr_write(union PMCR pmcr) {
-	pr_info("Writing pmcr %x\n", pmcr.value);
 	asm volatile ("mcr p15, 0, %0, c9, c12, 0\n\t" : : "r" (pmcr.value));
 }
 
diff --git a/arch/arm/measuremore/sysfs.c b/arch/arm/measuremore/sysfs.c
new file mode 100644
index 0000000..ca84e95
--- /dev/null
+++ b/arch/arm/measuremore/sysfs.c
@@ -0,0 +1,290 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/kernel.h>
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/ktime.h>
+#include <asm/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/workqueue.h>
+
+#include "kernel_memo_git_commit.h"
+#include "kernel_memo_git_status.h"
+#include "trigger.h"
+#include "measure.h"
+#include "sysfs.h"
+
+struct dentry *memo_root;
+
+/******************
+ * Bottom Handler *
+ ******************/
+
+static char *bottom_handler_map_strings[] = {"workqueue\n", "tasklet\n",
+						     "softirq\n", NULL};
+static enum memo_bottom_handler bottom_handler_map[] = {MMBH_WORKQUEUE,
+							MMBH_TASKLET,
+							MMBH_SOFTIRQ};
+
+static ssize_t debugfs_bottom_handler_read(struct file *fp, char __user *user_buffer,
+				   size_t count, loff_t *position)
+{
+	for (int i = 0; bottom_handler_map_strings[i]; i++) {
+		if (bottom_handler_map[i] == debugfs_bottom_handler) {
+			const char *str = bottom_handler_map_strings[i];
+			return simple_read_from_buffer(user_buffer, count,
+						       position, str,
+						       strlen(str));
+		}
+	}
+	BUG();
+	return 0;
+}
+
+static ssize_t debugfs_bottom_handler_write(struct file *fp,
+				    const char __user *user_buffer,
+				    size_t count, loff_t *position)
+{
+	char buf[count+1];
+	buf[count] = '\0';
+        if (simple_write_to_buffer(buf, count, position, user_buffer, count) < 0) {
+		BUG();
+	}
+
+	for (int i = 0; bottom_handler_map_strings[i]; i++) {
+		if (strcmp(bottom_handler_map_strings[i], buf) == 0) {
+			debugfs_bottom_handler = bottom_handler_map[i];
+			return count;
+		}
+	}
+	pr_err("Unrecognized bottom handler '%s'\n", buf);
+	return count;
+}
+
+static const struct file_operations debugfs_bottom_handler_fops = {
+	/* TODO: Not sure if this is legit, can't read/write only ask for a
+	 * portion of the string? */
+	.read = debugfs_bottom_handler_read,
+	.write = debugfs_bottom_handler_write,
+};
+
+/***********
+ * Waiting *
+ ***********/
+
+static char *delay_type_map_strings[] = {"udelay\n", "usleep_range\n", NULL};
+static enum memo_delay_type delay_type_map[] = {MMDT_UDELAY, MMDT_USLEEP_RANGE};
+
+static ssize_t delay_type_read(struct file *fp, char __user *user_buffer,
+			      size_t count, loff_t *position)
+{
+	for (int i = 0; delay_type_map_strings[i]; i++) {
+		if (delay_type_map[i] == debugfs_delay_type) {
+			const char *str = delay_type_map_strings[i];
+			return simple_read_from_buffer(user_buffer, count,
+						       position, str,
+						       strlen(str));
+		}
+	}
+	BUG();
+	return 0;
+}
+
+static ssize_t delay_type_write(struct file *fp, const char __user *user_buffer,
+			       size_t count, loff_t *position)
+{
+	char buf[count+1];
+	buf[count] = '\0';
+        if (simple_write_to_buffer(buf, count, position, user_buffer, count) < 0) {
+		BUG();
+	}
+
+	for (int i = 0; delay_type_map_strings[i]; i++) {
+		if (strcmp(delay_type_map_strings[i], buf) == 0) {
+			debugfs_delay_type = delay_type_map[i];
+			return count;
+		}
+	}
+	pr_err("Unrecognized delay type '%s'\n", buf);
+	return count;
+}
+
+static const struct file_operations debugfs_delay_type_fops = {
+	/* TODO: Not sure if this is legit, can't read/write only ask for a
+	 * portion of the string? */
+	.read = delay_type_read,
+	.write = delay_type_write,
+};
+
+static ssize_t prepare_trigger_write(struct file *file, const char __user *addr,
+			     size_t len, loff_t *pos)
+{
+	int err = memo_prepare_trigger();
+	if (err) {
+		pr_err("prepare_trigger failed with error %d\n", err);
+	}
+	return len;
+}
+
+static ssize_t memo_empty_read(struct file *fp, char __user *user_buffer,
+			       size_t count, loff_t *position)
+{
+	return simple_read_from_buffer(user_buffer, count, position, "", 0);
+}
+
+static const struct file_operations prepare_trigger_fops = {
+	.write = prepare_trigger_write,
+	.read = memo_empty_read,
+	.llseek = noop_llseek, /* TODO: via fs.c gcov_reset_fops, not sure why */
+};
+
+/* Do Trigger */
+
+static ssize_t do_trigger_write(struct file *file, const char __user *addr,
+			     size_t len, loff_t *pos)
+{
+	int err = memo_do_trigger();
+	if (err) {
+		pr_err("do_trigger failed with error %d\n", err);
+	}
+	return len;
+}
+
+/* TODO: Does block when logging in, triggering, logging out, triggering again. */
+static const struct file_operations do_trigger_fops = {
+	.write = do_trigger_write,
+	.read = memo_empty_read,
+	.llseek = noop_llseek, /* TODO: via fs.c gcov_reset_fops, not sure why */
+};
+
+/* Postprocess Trigger */
+
+static ssize_t postprocess_trigger_write(struct file *file,
+					 const char __user *addr, size_t len,
+					 loff_t *pos)
+{
+
+	int err = memo_postprocess_trigger();
+	if (err) {
+		pr_err("postprocess_trigger failed with error %d\n", err);
+	}
+	return len;
+}
+
+static const struct file_operations postprocess_trigger_fops = {
+	.write = postprocess_trigger_write,
+	.read = memo_empty_read,
+	.llseek = noop_llseek, /* TODO: via fs.c gcov_reset_fops, not sure why */
+};
+
+/*****************
+ * File Creation *
+ *****************/
+
+static struct dentry *memo_debugfs_create_str(const char *name, const char *str,
+					      struct debugfs_blob_wrapper *blob)
+{
+	blob->data = (char *) str;
+	blob->size = strlen(blob->data);
+	return debugfs_create_blob(name, 0400, memo_root, blob);
+}
+
+static struct debugfs_blob_wrapper debugfs_kernel_memo_git_commit_blob;
+static struct debugfs_blob_wrapper debugfs_kernel_memo_git_status_blob;
+
+static int create_files(void)
+{
+	/* TODO: error handling */
+
+	memo_debugfs_create_str("kernel_measuremore_git_commit",
+				kernel_memo_git_commit,
+				&debugfs_kernel_memo_git_commit_blob);
+	memo_debugfs_create_str("kernel_measuremore_git_status",
+				kernel_memo_git_status,
+				&debugfs_kernel_memo_git_status_blob);
+
+	debugfs_create_bool("vmalloc_checkpoint_matrix", 0400, memo_root,
+			    &debugfs_vmalloc_cp_matrix);
+	debugfs_create_u64("do_trigger_since_boot", 0600, memo_root,
+			   &debugfs_do_trigger_since_boot);
+
+	debugfs_create_u64("delay_ms", 0600, memo_root, &debugfs_delay_ms);
+	debugfs_create_u64("reps", 0600, memo_root, &debugfs_reps);
+	debugfs_create_u64("checkpoint_capacity", 0600, memo_root,
+			   &debugfs_cp_capacity);
+	debugfs_create_u32("progress_interval", 0600, memo_root,
+			   &debugfs_progress_interval);
+	debugfs_create_file("bottom_handler", 0600, memo_root, NULL,
+			    &debugfs_bottom_handler_fops);
+	debugfs_create_file("delay_type", 0600, memo_root, NULL,
+			    &debugfs_delay_type_fops);
+
+	/* We have to use debugfs_create_file_unsafe() here since we want to
+	 * remove other debugfs files in the fops' write function. Otherwise
+	 * those calls to remove would deadlock. TODO: Not sure whether this is
+	 * the right solution, maybe, to be completely correct, we must use
+	 * debugfs_use_file_start/finish() inside the write function. */
+	debugfs_create_file("prepare_trigger", 0600, memo_root, NULL,
+			    &prepare_trigger_fops);
+	debugfs_create_file("do_trigger", 0600, memo_root, NULL,
+			    &do_trigger_fops);
+	debugfs_create_file_unsafe("postprocess_trigger", 0600, memo_root, NULL,
+				   &postprocess_trigger_fops);
+
+	return 0;
+}
+
+static int memo_late_init(void)
+{
+	int err = memo_trigger_init_after_boot();
+	BUG_ON(err);
+	err = create_files();
+	BUG_ON(err);
+	return 0;
+}
+
+static ssize_t debugfs_late_init_write(struct file *file, const char __user *addr,
+				    size_t len, loff_t *pos)
+{
+	int err = memo_late_init();
+	if (err) {
+		pr_err("Late init failed with error %d\n", err);
+	}
+	return len;
+}
+
+static const struct file_operations debugfs_late_init_fops = {
+	.write = debugfs_late_init_write,
+	.read = memo_empty_read, /* So cp -r doen't fail. */
+	.llseek = noop_llseek, /* TODO: via fs.c gcov_reset_fops, not sure why */
+};
+
+static int __init memo_init(void)
+{
+	int err = memo_trigger_init();
+	BUG_ON(err);
+
+	memo_root = debugfs_create_dir("measuremore", NULL);
+	BUG_ON(!memo_root);
+	debugfs_create_file("init", 0600, memo_root, NULL, &debugfs_late_init_fops);
+
+	return 0;
+}
+
+static void __exit memo_exit(void)
+{
+	debugfs_remove_recursive(memo_root);
+	memo_trigger_deinit();
+}
+
+module_init(memo_init);
+module_exit(memo_exit);
+
+MODULE_DESCRIPTION("Trigger interrupt top / bottom handlers");
+MODULE_AUTHOR("Luis Gerhorst");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/measuremore/sysfs.h b/arch/arm/measuremore/sysfs.h
new file mode 100644
index 0000000..fde2fa5
--- /dev/null
+++ b/arch/arm/measuremore/sysfs.h
@@ -0,0 +1,6 @@
+#ifndef MEASUREMORE_SYSFS_H
+#define MEASUREMORE_SYSFS_H
+
+extern struct dentry *memo_root;
+
+#endif /* MEASUREMORE_SYSFS_H */
diff --git a/arch/arm/measuremore/trigger.c b/arch/arm/measuremore/trigger.c
index bb28a08..dbe9e34 100644
--- a/arch/arm/measuremore/trigger.c
+++ b/arch/arm/measuremore/trigger.c
@@ -1,38 +1,28 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 #include <linux/kernel.h>
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/device.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
-#include <linux/ktime.h>
-#include <asm/uaccess.h>
-#include <linux/debugfs.h>
-
 #include <linux/workqueue.h>
 
-#include "trigger.h"
-#include "measure.h"
-#include "pmccntr_timestamp.h"
 #include <linux/measuremore.h>
 
-#include "kernel_memo_git_commit.h"
-#include "kernel_memo_git_status.h"
-
-#define pr_here() pr_err("%s:%d %s called\n", __FILE__, __LINE__, __func__)
+#include "pmccntr_timestamp.h"
+#include "measure.h"
+#include "trigger.h"
 
-#define ECHO_1_OUTPUT "1\n"
-#define DEVICE_NAME KBUILD_MODNAME
-#define CLASS_NAME "interrupt_generator"
 #define GPIO_A6 0x60+26
 #define GPIO_A7 0x60+27
 #define GPIO_IRQ GPIO_A6
 #define GPIO_OUT GPIO_A7
 
-struct dentry *memo_root;
+enum memo_bottom_handler debugfs_bottom_handler = MMBH_TASKLET;
+enum memo_delay_type debugfs_delay_type = MMDT_UDELAY;
+u64 debugfs_do_trigger_since_boot = 0;
+u64 debugfs_delay_ms = 20;
+u64 debugfs_reps = 1000;
+u64 debugfs_cp_capacity = 25;
 
 static int irq_number;
 
@@ -75,120 +65,6 @@ static void memo_install_softirq(void)
 	open_softirq(MEASUREMORE_SOFTIRQ, memo_softirq_handler);
 }
 
-/******************
- * Bottom Handler *
- ******************/
-
-enum memo_bottom_handler {
-	MMBH_WORKQUEUE,
-	MMBH_TASKLET,
-	MMBH_SOFTIRQ
-};
-
-static char *debugfs_bottom_handler_map_strings[] = {"workqueue\n", "tasklet\n",
-						     "softirq\n", NULL};
-static enum memo_bottom_handler debugfs_bottom_handler_map[] = {MMBH_WORKQUEUE,
-								MMBH_TASKLET,
-								MMBH_SOFTIRQ};
-
-static const char *debugfs_bottom_handler_str = "tasklet\n";
-static enum memo_bottom_handler debugfs_bottom_handler = MMBH_TASKLET;
-
-static ssize_t debugfs_bottom_handler_read(struct file *fp, char __user *user_buffer,
-				   size_t count, loff_t *position)
-{
-	return simple_read_from_buffer(user_buffer, count, position,
-				       debugfs_bottom_handler_str,
-				       strlen(debugfs_bottom_handler_str));
-}
-
-static ssize_t debugfs_bottom_handler_write(struct file *fp,
-				    const char __user *user_buffer,
-				    size_t count, loff_t *position)
-{
-	char buf[count+1];
-	buf[count] = '\0';
-        if (simple_write_to_buffer(buf, count, position, user_buffer, count) < 0) {
-		BUG();
-	}
-
-	for (int i = 0; debugfs_bottom_handler_map_strings[i]; i++) {
-		if (strcmp(debugfs_bottom_handler_map_strings[i], buf) == 0) {
-			debugfs_bottom_handler = debugfs_bottom_handler_map[i];
-			debugfs_bottom_handler_str = debugfs_bottom_handler_map_strings[i];
-			return count;
-		}
-	}
-	pr_err("Unrecognized bottom handler '%s'\n", buf);
-	return count;
-}
-
-static const struct file_operations debugfs_bottom_handler_fops = {
-	/* TODO: Not sure if this is legit, can't read/write only ask for a
-	 * portion of the string? */
-	.read = debugfs_bottom_handler_read,
-	.write = debugfs_bottom_handler_write,
-};
-
-/***********
- * Waiting *
- ***********/
-
-enum memo_delay_type {
-	MMDT_UDELAY,
-	MMDT_USLEEP_RANGE
-};
-
-static char *delay_type_map_strings[] = {"udelay\n", "usleep_range\n", NULL};
-static enum memo_delay_type delay_type_map[] = {MMDT_UDELAY, MMDT_USLEEP_RANGE};
-
-static const char *debugfs_delay_type_str = "udelay\n";
-static enum memo_delay_type debugfs_delay_type = MMDT_UDELAY;
-
-static ssize_t delay_type_read(struct file *fp, char __user *user_buffer,
-			      size_t count, loff_t *position)
-{
-	return simple_read_from_buffer(user_buffer, count, position,
-				       debugfs_delay_type_str,
-				       strlen(debugfs_delay_type_str));
-}
-
-static ssize_t delay_type_write(struct file *fp, const char __user *user_buffer,
-			       size_t count, loff_t *position)
-{
-	char buf[count+1];
-	buf[count] = '\0';
-        if (simple_write_to_buffer(buf, count, position, user_buffer, count) < 0) {
-		BUG();
-	}
-
-	for (int i = 0; delay_type_map_strings[i]; i++) {
-		if (strcmp(delay_type_map_strings[i], buf) == 0) {
-			debugfs_delay_type = delay_type_map[i];
-			debugfs_delay_type_str = delay_type_map_strings[i];
-			return count;
-		}
-	}
-	pr_err("Unrecognized delay type '%s'\n", buf);
-	return count;
-}
-
-static const struct file_operations debugfs_delay_type_fops = {
-	/* TODO: Not sure if this is legit, can't read/write only ask for a
-	 * portion of the string? */
-	.read = delay_type_read,
-	.write = delay_type_write,
-};
-
-/******************************
- * Vars Exposed Through Sysfs *
- ******************************/
-
-static u64 debugfs_do_trigger_since_boot = 0;
-static u64 debugfs_delay_ms = 20;
-static u64 debugfs_reps = 1000;
-static u64 debugfs_cp_capacity = 25;
-
 /**************
  * Interrupts *
  **************/
@@ -216,12 +92,12 @@ static irqreturn_t memo_irq_handler(int irq, void *dev_id)
 static int memo_request_irq(int irqnum)
 {
 	return request_any_context_irq(irqnum, memo_irq_handler,
-				       IRQF_TRIGGER_FALLING, DEVICE_NAME, NULL);
+				       IRQF_TRIGGER_FALLING, KBUILD_MODNAME, NULL);
 }
 
-/*******************
- * Sysfs Interface *
- *******************/
+/********
+ * GPIO *
+ ********/
 
 static void memo_trigger_interrupt(void)
 {
@@ -229,198 +105,13 @@ static void memo_trigger_interrupt(void)
 	gpio_set_value(GPIO_OUT, 0);
 }
 
-enum memo_trigger_state {
-	MMTS_PREPARED,
-	MMTS_DONE,
-	MMTS_POSTPROCESSED
-};
-
-static enum memo_trigger_state current_trigger_state = MMTS_POSTPROCESSED;
-
-/* Prepare Trigger */
-
-static int memo_prepare_trigger(void) {
-	if (current_trigger_state != MMTS_POSTPROCESSED) {
-		return -1;
-	}
-	current_trigger_state = MMTS_PREPARED;
-
-	const unsigned long reps = debugfs_reps;
-	const unsigned long cp_capacity = debugfs_cp_capacity;
-	return memo_start_benchmark(reps, cp_capacity);
-}
-
-static ssize_t prepare_trigger_write(struct file *file, const char __user *addr,
-			     size_t len, loff_t *pos)
-{
-	int err = memo_prepare_trigger();
-	if (err) {
-		pr_err("prepare_trigger failed with error %d\n", err);
-	}
-	return len;
-}
-
-static ssize_t memo_empty_read(struct file *fp, char __user *user_buffer,
-			       size_t count, loff_t *position)
-{
-	return simple_read_from_buffer(user_buffer, count, position, "", 0);
-}
-
-static const struct file_operations prepare_trigger_fops = {
-	.write = prepare_trigger_write,
-	.read = memo_empty_read,
-	.llseek = noop_llseek, /* TODO: via fs.c gcov_reset_fops, not sure why */
-};
-
-/* Do Trigger */
-
-static int memo_do_trigger(void) {
-	if (current_trigger_state != MMTS_PREPARED) {
-		return -1;
-	}
-	current_trigger_state = MMTS_DONE;
-
-	debugfs_do_trigger_since_boot++;
-
-	const uint64_t delay_ms = debugfs_delay_ms;
-	const uint64_t delay_us = delay_ms*1000;
-	const uint64_t delay_ns = delay_ms*1000*1000;
-	const unsigned long reps = debugfs_reps;
-
-	for (uint64_t i = 0; i < reps; i++) {
-		memo_start_run();
-		memo_checkpoint("checkpoint_1");
-		memo_checkpoint("checkpoint_2");
-		memo_checkpoint("checkpoint_3");
-		memo_trigger_interrupt();
-		switch (debugfs_delay_type) {
-		case MMDT_USLEEP_RANGE:
-			usleep_range(delay_us, delay_us);
-			break;
-		case MMDT_UDELAY:
-			udelay(delay_us);
-			break;
-		default:
-			BUG();
-			break;
-		}
-		memo_stop_run();
-	}
-
-	return 0; /* TODO: Signal error. */
-}
-
-static ssize_t do_trigger_write(struct file *file, const char __user *addr,
-			     size_t len, loff_t *pos)
-{
-	int err = memo_do_trigger();
-	if (err) {
-		pr_err("do_trigger failed with error %d\n", err);
-	}
-	return len;
-}
-
-/* TODO: Does block when logging in, triggering, logging out, triggering again. */
-static const struct file_operations do_trigger_fops = {
-	.write = do_trigger_write,
-	.read = memo_empty_read,
-	.llseek = noop_llseek, /* TODO: via fs.c gcov_reset_fops, not sure why */
-};
-
-/* Postprocess Trigger */
-
-static int memo_postprocess_trigger(void) {
-	if (current_trigger_state != MMTS_DONE) {
-		return -1;
-	}
-	current_trigger_state = MMTS_POSTPROCESSED;
-
-	memo_stop_benchmark();
-	return 0;
-}
-
-static ssize_t postprocess_trigger_write(struct file *file,
-					 const char __user *addr, size_t len,
-					 loff_t *pos)
-{
-
-	int err = memo_postprocess_trigger();
-	if (err) {
-		pr_err("postprocess_trigger failed with error %d\n", err);
-	}
-	return len;
-}
-
-static const struct file_operations postprocess_trigger_fops = {
-	.write = postprocess_trigger_write,
-	.read = memo_empty_read,
-	.llseek = noop_llseek, /* TODO: via fs.c gcov_reset_fops, not sure why */
-};
-
-/*****************
- * File Creation *
- *****************/
-
-static struct dentry *memo_debugfs_create_str(const char *name, const char *str,
-					      struct debugfs_blob_wrapper *blob)
-{
-	blob->data = (char *) str;
-	blob->size = strlen(blob->data);
-	return debugfs_create_blob(name, 0400, memo_root, blob);
-}
-
-static struct debugfs_blob_wrapper debugfs_kernel_memo_git_commit_blob;
-static struct debugfs_blob_wrapper debugfs_kernel_memo_git_status_blob;
-
-static int create_files(void)
-{
-	/* TODO: error handling */
-
-	memo_debugfs_create_str("kernel_measuremore_git_commit",
-				kernel_memo_git_commit,
-				&debugfs_kernel_memo_git_commit_blob);
-	memo_debugfs_create_str("kernel_measuremore_git_status",
-				kernel_memo_git_status,
-				&debugfs_kernel_memo_git_status_blob);
-
-	debugfs_create_bool("vmalloc_checkpoint_matrix", 0400, memo_root,
-			    &debugfs_vmalloc_cp_matrix);
-	debugfs_create_u64("do_trigger_since_boot", 0600, memo_root,
-			   &debugfs_do_trigger_since_boot);
-
-	debugfs_create_u64("delay_ms", 0600, memo_root, &debugfs_delay_ms);
-	debugfs_create_u64("reps", 0600, memo_root, &debugfs_reps);
-	debugfs_create_u64("checkpoint_capacity", 0600, memo_root,
-			   &debugfs_cp_capacity);
-	debugfs_create_u32("progress_interval", 0600, memo_root,
-			   &debugfs_progress_interval);
-	debugfs_create_file("bottom_handler", 0600, memo_root, NULL,
-			    &debugfs_bottom_handler_fops);
-	debugfs_create_file("delay_type", 0600, memo_root, NULL,
-			    &debugfs_delay_type_fops);
-
-	/* We have to use debugfs_create_file_unsafe() here since we want to
-	 * remove other debugfs files in the fops' write function. Otherwise
-	 * those calls to remove would deadlock. TODO: Not sure whether this is
-	 * the right solution, maybe, to be completely correct, we must use
-	 * debugfs_use_file_start/finish() inside the write function. */
-	debugfs_create_file("prepare_trigger", 0600, memo_root, NULL,
-			    &prepare_trigger_fops);
-	debugfs_create_file("do_trigger", 0600, memo_root, NULL,
-			    &do_trigger_fops);
-	debugfs_create_file_unsafe("postprocess_trigger", 0600, memo_root, NULL,
-				   &postprocess_trigger_fops);
-
-	return 0;
-}
-
 static int gpio_init(void) {
-	int err = gpio_request_one(GPIO_OUT, GPIOF_OUT_INIT_HIGH, DEVICE_NAME " gpio");
+	int err = gpio_request_one(GPIO_OUT, GPIOF_OUT_INIT_HIGH, KBUILD_MODNAME " gpio");
 	if (err) {
 		goto ret;
 	}
 
-	err = gpio_request_one(GPIO_IRQ, GPIOF_IN, DEVICE_NAME " irq");
+	err = gpio_request_one(GPIO_IRQ, GPIOF_IN, KBUILD_MODNAME " irq");
 	if (err) {
 		goto free_a7;
 	}
@@ -438,7 +129,17 @@ static void release_gpio(void)
 	gpio_free(GPIO_OUT);
 }
 
-static int late_init(void)
+/********
+ * Init *
+ ********/
+
+int memo_trigger_init(void)
+{
+	memo_install_softirq();
+	return 0;
+}
+
+int memo_trigger_init_after_boot(void)
 {
 	int err = gpio_init();
 	if (err) {
@@ -459,64 +160,88 @@ static int late_init(void)
 		goto release_gpio;
 	}
 
-	err = create_files();
-	if (err) {
-		goto free_irq;
-	}
-
 #ifdef CONFIG_MEASUREMORE_TIMESTAMP_TYPE_PMCCNTR
 	pmccntr_enable();
 #endif
 
 	goto ret;
-free_irq:
-	free_irq(irq_number, NULL);
 release_gpio:
 	release_gpio();
 ret:
 	return err;
 }
 
-static ssize_t late_init_write(struct file *file, const char __user *addr,
-			       size_t len, loff_t *pos)
+void memo_trigger_deinit(void)
 {
-	int err = late_init();
-	if (err) {
-		pr_err("Late init failed with error %d\n", err);
-	}
-	return len;
+	free_irq(irq_number, NULL);
+	release_gpio();
 }
 
-static const struct file_operations late_init_fops = {
-	.write = late_init_write,
-	.read = memo_empty_read, /* So cp -r doen't fail. */
-	.llseek = noop_llseek, /* TODO: via fs.c gcov_reset_fops, not sure why */
-};
+/**********
+ * Public *
+ **********/
 
-static int __init memo_init(void)
-{
-	pr_err("init\n");
+enum memo_trigger_state {
+	MMTS_PREPARED,
+	MMTS_DONE,
+	MMTS_POSTPROCESSED
+};
 
-	memo_install_softirq();
+static enum memo_trigger_state current_trigger_state = MMTS_POSTPROCESSED;
 
-	memo_root = debugfs_create_dir("measuremore", NULL);
-	BUG_ON(!memo_root);
-	debugfs_create_file("init", 0600, memo_root, NULL, &late_init_fops);
+int memo_prepare_trigger(void) {
+	if (current_trigger_state != MMTS_POSTPROCESSED) {
+		return -1;
+	}
+	current_trigger_state = MMTS_PREPARED;
 
-	return 0;
+	const unsigned long reps = debugfs_reps;
+	const unsigned long cp_capacity = debugfs_cp_capacity;
+	return memo_start_benchmark(reps, cp_capacity);
 }
 
-static void __exit memo_exit(void)
-{
-	debugfs_remove_recursive(memo_root);
+int memo_do_trigger(void) {
+	if (current_trigger_state != MMTS_PREPARED) {
+		return -1;
+	}
+	current_trigger_state = MMTS_DONE;
 
-	free_irq(irq_number, NULL);
-	release_gpio();
+	debugfs_do_trigger_since_boot++;
+
+	const uint64_t delay_ms = debugfs_delay_ms;
+	const uint64_t delay_us = delay_ms*1000;
+	const uint64_t delay_ns = delay_ms*1000*1000;
+	const unsigned long reps = debugfs_reps;
+
+	for (uint64_t i = 0; i < reps; i++) {
+		memo_start_run();
+		memo_checkpoint("checkpoint_1");
+		memo_checkpoint("checkpoint_2");
+		memo_checkpoint("checkpoint_3");
+		memo_trigger_interrupt();
+		switch (debugfs_delay_type) {
+		case MMDT_USLEEP_RANGE:
+			usleep_range(delay_us, delay_us);
+			break;
+		case MMDT_UDELAY:
+			udelay(delay_us);
+			break;
+		default:
+			BUG();
+			break;
+		}
+		memo_stop_run();
+	}
+
+	return 0;
 }
 
-module_init(memo_init);
-module_exit(memo_exit);
+int memo_postprocess_trigger(void) {
+	if (current_trigger_state != MMTS_DONE) {
+		return -1;
+	}
+	current_trigger_state = MMTS_POSTPROCESSED;
 
-MODULE_DESCRIPTION("Trigger interrupt top / bottom handlers");
-MODULE_AUTHOR("Luis Gerhorst");
-MODULE_LICENSE("GPL");
+	memo_stop_benchmark();
+	return 0;
+}
diff --git a/arch/arm/measuremore/trigger.h b/arch/arm/measuremore/trigger.h
index 2050809..badb527 100644
--- a/arch/arm/measuremore/trigger.h
+++ b/arch/arm/measuremore/trigger.h
@@ -1,6 +1,30 @@
 #ifndef MEASUREMORE_TRIGGER_H
 #define MEASUREMORE_TRIGGER_H
 
-extern struct dentry *memo_root;
+enum memo_bottom_handler {
+	MMBH_WORKQUEUE,
+	MMBH_TASKLET,
+	MMBH_SOFTIRQ
+};
+
+enum memo_delay_type {
+	MMDT_UDELAY,
+	MMDT_USLEEP_RANGE
+};
+
+extern enum memo_bottom_handler debugfs_bottom_handler;
+extern enum memo_delay_type debugfs_delay_type;
+extern u64 debugfs_do_trigger_since_boot;
+extern u64 debugfs_delay_ms;
+extern u64 debugfs_reps;
+extern u64 debugfs_cp_capacity;
+
+int memo_trigger_init(void);
+int memo_trigger_init_after_boot(void);
+void memo_trigger_deinit(void);
+
+int memo_prepare_trigger(void);
+int memo_do_trigger(void);
+int memo_postprocess_trigger(void);
 
 #endif /* MEASUREMORE_TRIGGER_H */
-- 
GitLab