blob: 434f8e3232ebf3f564fee9513944f45bc3b61337 [file] [log] [blame]
Allen Martinfc468d82016-11-15 17:57:52 -08001From 6c228c7da079d24d92689fff1dca36b82f5094a3 Mon Sep 17 00:00:00 2001
Allen Martin685e0f82016-07-26 19:34:29 -07002From: Carsten Emde <C.Emde@osadl.org>
3Date: Tue, 19 Jul 2011 13:53:12 +0100
Allen Martinfc468d82016-11-15 17:57:52 -08004Subject: [PATCH 024/351] hwlatdetect.patch
Allen Martin685e0f82016-07-26 19:34:29 -07005X-NVConfidentiality: public
6
7Jon Masters developed this wonderful SMI detector. For details please
8consult Documentation/hwlat_detector.txt. It could be ported to Linux
93.0 RT without any major change.
10
11Signed-off-by: Carsten Emde <C.Emde@osadl.org>
Allen Martin685e0f82016-07-26 19:34:29 -070012---
13 Documentation/hwlat_detector.txt | 64 ++
14 drivers/misc/Kconfig | 29 +
15 drivers/misc/Makefile | 1 +
16 drivers/misc/hwlat_detector.c | 1212 ++++++++++++++++++++++++++++++++++++++
17 4 files changed, 1306 insertions(+)
18 create mode 100644 Documentation/hwlat_detector.txt
19 create mode 100644 drivers/misc/hwlat_detector.c
20
21diff --git a/Documentation/hwlat_detector.txt b/Documentation/hwlat_detector.txt
22new file mode 100644
23index 000000000000..cb61516483d3
24--- /dev/null
25+++ b/Documentation/hwlat_detector.txt
26@@ -0,0 +1,64 @@
27+Introduction:
28+-------------
29+
30+The module hwlat_detector is a special purpose kernel module that is used to
31+detect large system latencies induced by the behavior of certain underlying
32+hardware or firmware, independent of Linux itself. The code was developed
33+originally to detect SMIs (System Management Interrupts) on x86 systems,
34+however there is nothing x86 specific about this patchset. It was
35+originally written for use by the "RT" patch since the Real Time
36+kernel is highly latency sensitive.
37+
38+SMIs are usually not serviced by the Linux kernel, which typically does not
39+even know that they are occuring. SMIs are instead are set up by BIOS code
40+and are serviced by BIOS code, usually for "critical" events such as
41+management of thermal sensors and fans. Sometimes though, SMIs are used for
42+other tasks and those tasks can spend an inordinate amount of time in the
43+handler (sometimes measured in milliseconds). Obviously this is a problem if
44+you are trying to keep event service latencies down in the microsecond range.
45+
46+The hardware latency detector works by hogging all of the cpus for configurable
47+amounts of time (by calling stop_machine()), polling the CPU Time Stamp Counter
48+for some period, then looking for gaps in the TSC data. Any gap indicates a
49+time when the polling was interrupted and since the machine is stopped and
50+interrupts turned off the only thing that could do that would be an SMI.
51+
52+Note that the SMI detector should *NEVER* be used in a production environment.
53+It is intended to be run manually to determine if the hardware platform has a
54+problem with long system firmware service routines.
55+
56+Usage:
57+------
58+
59+Loading the module hwlat_detector passing the parameter "enabled=1" (or by
60+setting the "enable" entry in "hwlat_detector" debugfs toggled on) is the only
61+step required to start the hwlat_detector. It is possible to redefine the
62+threshold in microseconds (us) above which latency spikes will be taken
63+into account (parameter "threshold=").
64+
65+Example:
66+
67+ # modprobe hwlat_detector enabled=1 threshold=100
68+
69+After the module is loaded, it creates a directory named "hwlat_detector" under
70+the debugfs mountpoint, "/debug/hwlat_detector" for this text. It is necessary
71+to have debugfs mounted, which might be on /sys/debug on your system.
72+
73+The /debug/hwlat_detector interface contains the following files:
74+
75+count - number of latency spikes observed since last reset
76+enable - a global enable/disable toggle (0/1), resets count
77+max - maximum hardware latency actually observed (usecs)
78+sample - a pipe from which to read current raw sample data
79+ in the format <timestamp> <latency observed usecs>
80+ (can be opened O_NONBLOCK for a single sample)
81+threshold - minimum latency value to be considered (usecs)
82+width - time period to sample with CPUs held (usecs)
83+ must be less than the total window size (enforced)
84+window - total period of sampling, width being inside (usecs)
85+
86+By default we will set width to 500,000 and window to 1,000,000, meaning that
87+we will sample every 1,000,000 usecs (1s) for 500,000 usecs (0.5s). If we
88+observe any latencies that exceed the threshold (initially 100 usecs),
89+then we write to a global sample ring buffer of 8K samples, which is
90+consumed by reading from the "sample" (pipe) debugfs file interface.
91diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
Allen Martinfc468d82016-11-15 17:57:52 -080092index 696ae1112a2e..537bd1e7e0fb 100644
Allen Martin685e0f82016-07-26 19:34:29 -070093--- a/drivers/misc/Kconfig
94+++ b/drivers/misc/Kconfig
95@@ -121,6 +121,35 @@ config IBM_ASM
96 for information on the specific driver level and support statement
97 for your IBM server.
98
99+config HWLAT_DETECTOR
100+ tristate "Testing module to detect hardware-induced latencies"
101+ depends on DEBUG_FS
102+ depends on RING_BUFFER
103+ default m
104+ ---help---
105+ A simple hardware latency detector. Use this module to detect
106+ large latencies introduced by the behavior of the underlying
107+ system firmware external to Linux. We do this using periodic
108+ use of stop_machine to grab all available CPUs and measure
109+ for unexplainable gaps in the CPU timestamp counter(s). By
110+ default, the module is not enabled until the "enable" file
111+ within the "hwlat_detector" debugfs directory is toggled.
112+
113+ This module is often used to detect SMI (System Management
114+ Interrupts) on x86 systems, though is not x86 specific. To
115+ this end, we default to using a sample window of 1 second,
116+ during which we will sample for 0.5 seconds. If an SMI or
117+ similar event occurs during that time, it is recorded
118+ into an 8K samples global ring buffer until retreived.
119+
120+ WARNING: This software should never be enabled (it can be built
121+ but should not be turned on after it is loaded) in a production
122+ environment where high latencies are a concern since the
123+ sampling mechanism actually introduces latencies for
124+ regular tasks while the CPU(s) are being held.
125+
126+ If unsure, say N
127+
128 config PHANTOM
129 tristate "Sensable PHANToM (PCI)"
130 depends on PCI
131diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
Allen Martinfc468d82016-11-15 17:57:52 -0800132index 53960f774dfb..76dc2bd1dfa1 100644
Allen Martin685e0f82016-07-26 19:34:29 -0700133--- a/drivers/misc/Makefile
134+++ b/drivers/misc/Makefile
135@@ -39,6 +39,7 @@ obj-$(CONFIG_C2PORT) += c2port/
136 obj-$(CONFIG_HMC6352) += hmc6352.o
137 obj-y += eeprom/
138 obj-y += cb710/
139+obj-$(CONFIG_HWLAT_DETECTOR) += hwlat_detector.o
140 obj-$(CONFIG_SPEAR13XX_PCIE_GADGET) += spear13xx_pcie_gadget.o
141 obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
142 obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o
143diff --git a/drivers/misc/hwlat_detector.c b/drivers/misc/hwlat_detector.c
144new file mode 100644
Allen Martinfc468d82016-11-15 17:57:52 -0800145index 000000000000..6864f3c24c8b
Allen Martin685e0f82016-07-26 19:34:29 -0700146--- /dev/null
147+++ b/drivers/misc/hwlat_detector.c
148@@ -0,0 +1,1212 @@
149+/*
150+ * hwlat_detector.c - A simple Hardware Latency detector.
151+ *
152+ * Use this module to detect large system latencies induced by the behavior of
153+ * certain underlying system hardware or firmware, independent of Linux itself.
154+ * The code was developed originally to detect the presence of SMIs on Intel
155+ * and AMD systems, although there is no dependency upon x86 herein.
156+ *
157+ * The classical example usage of this module is in detecting the presence of
158+ * SMIs or System Management Interrupts on Intel and AMD systems. An SMI is a
159+ * somewhat special form of hardware interrupt spawned from earlier CPU debug
160+ * modes in which the (BIOS/EFI/etc.) firmware arranges for the South Bridge
161+ * LPC (or other device) to generate a special interrupt under certain
162+ * circumstances, for example, upon expiration of a special SMI timer device,
163+ * due to certain external thermal readings, on certain I/O address accesses,
164+ * and other situations. An SMI hits a special CPU pin, triggers a special
165+ * SMI mode (complete with special memory map), and the OS is unaware.
166+ *
167+ * Although certain hardware-inducing latencies are necessary (for example,
168+ * a modern system often requires an SMI handler for correct thermal control
169+ * and remote management) they can wreak havoc upon any OS-level performance
170+ * guarantees toward low-latency, especially when the OS is not even made
171+ * aware of the presence of these interrupts. For this reason, we need a
172+ * somewhat brute force mechanism to detect these interrupts. In this case,
173+ * we do it by hogging all of the CPU(s) for configurable timer intervals,
174+ * sampling the built-in CPU timer, looking for discontiguous readings.
175+ *
176+ * WARNING: This implementation necessarily introduces latencies. Therefore,
177+ * you should NEVER use this module in a production environment
178+ * requiring any kind of low-latency performance guarantee(s).
179+ *
180+ * Copyright (C) 2008-2009 Jon Masters, Red Hat, Inc. <jcm@redhat.com>
181+ *
182+ * Includes useful feedback from Clark Williams <clark@redhat.com>
183+ *
184+ * This file is licensed under the terms of the GNU General Public
185+ * License version 2. This program is licensed "as is" without any
186+ * warranty of any kind, whether express or implied.
187+ */
188+
189+#include <linux/module.h>
190+#include <linux/init.h>
191+#include <linux/ring_buffer.h>
192+#include <linux/stop_machine.h>
193+#include <linux/time.h>
194+#include <linux/hrtimer.h>
195+#include <linux/kthread.h>
196+#include <linux/debugfs.h>
197+#include <linux/seq_file.h>
198+#include <linux/uaccess.h>
199+#include <linux/version.h>
200+#include <linux/delay.h>
201+#include <linux/slab.h>
202+
203+#define BUF_SIZE_DEFAULT 262144UL /* 8K*(sizeof(entry)) */
204+#define BUF_FLAGS (RB_FL_OVERWRITE) /* no block on full */
205+#define U64STR_SIZE 22 /* 20 digits max */
206+
207+#define VERSION "1.0.0"
208+#define BANNER "hwlat_detector: "
209+#define DRVNAME "hwlat_detector"
210+#define DEFAULT_SAMPLE_WINDOW 1000000 /* 1s */
211+#define DEFAULT_SAMPLE_WIDTH 500000 /* 0.5s */
212+#define DEFAULT_LAT_THRESHOLD 10 /* 10us */
213+
214+/* Module metadata */
215+
216+MODULE_LICENSE("GPL");
217+MODULE_AUTHOR("Jon Masters <jcm@redhat.com>");
218+MODULE_DESCRIPTION("A simple hardware latency detector");
219+MODULE_VERSION(VERSION);
220+
221+/* Module parameters */
222+
223+static int debug;
224+static int enabled;
225+static int threshold;
226+
227+module_param(debug, int, 0); /* enable debug */
228+module_param(enabled, int, 0); /* enable detector */
229+module_param(threshold, int, 0); /* latency threshold */
230+
231+/* Buffering and sampling */
232+
233+static struct ring_buffer *ring_buffer; /* sample buffer */
234+static DEFINE_MUTEX(ring_buffer_mutex); /* lock changes */
235+static unsigned long buf_size = BUF_SIZE_DEFAULT;
236+static struct task_struct *kthread; /* sampling thread */
237+
238+/* DebugFS filesystem entries */
239+
240+static struct dentry *debug_dir; /* debugfs directory */
241+static struct dentry *debug_max; /* maximum TSC delta */
242+static struct dentry *debug_count; /* total detect count */
243+static struct dentry *debug_sample_width; /* sample width us */
244+static struct dentry *debug_sample_window; /* sample window us */
245+static struct dentry *debug_sample; /* raw samples us */
246+static struct dentry *debug_threshold; /* threshold us */
247+static struct dentry *debug_enable; /* enable/disable */
248+
249+/* Individual samples and global state */
250+
251+struct sample; /* latency sample */
252+struct data; /* Global state */
253+
254+/* Sampling functions */
255+static int __buffer_add_sample(struct sample *sample);
256+static struct sample *buffer_get_sample(struct sample *sample);
257+static int get_sample(void *unused);
258+
259+/* Threading and state */
260+static int kthread_fn(void *unused);
261+static int start_kthread(void);
262+static int stop_kthread(void);
263+static void __reset_stats(void);
264+static int init_stats(void);
265+
266+/* Debugfs interface */
267+static ssize_t simple_data_read(struct file *filp, char __user *ubuf,
268+ size_t cnt, loff_t *ppos, const u64 *entry);
269+static ssize_t simple_data_write(struct file *filp, const char __user *ubuf,
270+ size_t cnt, loff_t *ppos, u64 *entry);
271+static int debug_sample_fopen(struct inode *inode, struct file *filp);
272+static ssize_t debug_sample_fread(struct file *filp, char __user *ubuf,
273+ size_t cnt, loff_t *ppos);
274+static int debug_sample_release(struct inode *inode, struct file *filp);
275+static int debug_enable_fopen(struct inode *inode, struct file *filp);
276+static ssize_t debug_enable_fread(struct file *filp, char __user *ubuf,
277+ size_t cnt, loff_t *ppos);
278+static ssize_t debug_enable_fwrite(struct file *file,
279+ const char __user *user_buffer,
280+ size_t user_size, loff_t *offset);
281+
282+/* Initialization functions */
283+static int init_debugfs(void);
284+static void free_debugfs(void);
285+static int detector_init(void);
286+static void detector_exit(void);
287+
288+/* Individual latency samples are stored here when detected and packed into
289+ * the ring_buffer circular buffer, where they are overwritten when
290+ * more than buf_size/sizeof(sample) samples are received. */
291+struct sample {
292+ u64 seqnum; /* unique sequence */
293+ u64 duration; /* ktime delta */
294+ struct timespec timestamp; /* wall time */
295+ unsigned long lost;
296+};
297+
298+/* keep the global state somewhere. Mostly used under stop_machine. */
299+static struct data {
300+
301+ struct mutex lock; /* protect changes */
302+
303+ u64 count; /* total since reset */
304+ u64 max_sample; /* max hardware latency */
305+ u64 threshold; /* sample threshold level */
306+
307+ u64 sample_window; /* total sampling window (on+off) */
308+ u64 sample_width; /* active sampling portion of window */
309+
310+ atomic_t sample_open; /* whether the sample file is open */
311+
312+ wait_queue_head_t wq; /* waitqeue for new sample values */
313+
314+} data;
315+
316+/**
317+ * __buffer_add_sample - add a new latency sample recording to the ring buffer
318+ * @sample: The new latency sample value
319+ *
320+ * This receives a new latency sample and records it in a global ring buffer.
321+ * No additional locking is used in this case - suited for stop_machine use.
322+ */
323+static int __buffer_add_sample(struct sample *sample)
324+{
325+ return ring_buffer_write(ring_buffer,
326+ sizeof(struct sample), sample);
327+}
328+
329+/**
330+ * buffer_get_sample - remove a hardware latency sample from the ring buffer
331+ * @sample: Pre-allocated storage for the sample
332+ *
333+ * This retrieves a hardware latency sample from the global circular buffer
334+ */
335+static struct sample *buffer_get_sample(struct sample *sample)
336+{
337+ struct ring_buffer_event *e = NULL;
338+ struct sample *s = NULL;
339+ unsigned int cpu = 0;
340+
341+ if (!sample)
342+ return NULL;
343+
344+ mutex_lock(&ring_buffer_mutex);
345+ for_each_online_cpu(cpu) {
346+ e = ring_buffer_consume(ring_buffer, cpu, NULL, &sample->lost);
347+ if (e)
348+ break;
349+ }
350+
351+ if (e) {
352+ s = ring_buffer_event_data(e);
353+ memcpy(sample, s, sizeof(struct sample));
354+ } else
355+ sample = NULL;
356+ mutex_unlock(&ring_buffer_mutex);
357+
358+ return sample;
359+}
360+
361+/**
362+ * get_sample - sample the CPU TSC and look for likely hardware latencies
363+ * @unused: This is not used but is a part of the stop_machine API
364+ *
365+ * Used to repeatedly capture the CPU TSC (or similar), looking for potential
366+ * hardware-induced latency. Called under stop_machine, with data.lock held.
367+ */
368+static int get_sample(void *unused)
369+{
370+ ktime_t start, t1, t2;
371+ s64 diff, total = 0;
372+ u64 sample = 0;
373+ int ret = 1;
374+
375+ start = ktime_get(); /* start timestamp */
376+
377+ do {
378+
379+ t1 = ktime_get(); /* we'll look for a discontinuity */
380+ t2 = ktime_get();
381+
382+ total = ktime_to_us(ktime_sub(t2, start)); /* sample width */
383+ diff = ktime_to_us(ktime_sub(t2, t1)); /* current diff */
384+
385+ /* This shouldn't happen */
386+ if (diff < 0) {
387+ pr_err(BANNER "time running backwards\n");
388+ goto out;
389+ }
390+
391+ if (diff > sample)
392+ sample = diff; /* only want highest value */
393+
394+ } while (total <= data.sample_width);
395+
396+ /* If we exceed the threshold value, we have found a hardware latency */
397+ if (sample > data.threshold) {
398+ struct sample s;
399+
400+ data.count++;
401+ s.seqnum = data.count;
402+ s.duration = sample;
403+ s.timestamp = CURRENT_TIME;
404+ __buffer_add_sample(&s);
405+
406+ /* Keep a running maximum ever recorded hardware latency */
407+ if (sample > data.max_sample)
408+ data.max_sample = sample;
409+ }
410+
411+ ret = 0;
412+out:
413+ return ret;
414+}
415+
416+/*
417+ * kthread_fn - The CPU time sampling/hardware latency detection kernel thread
418+ * @unused: A required part of the kthread API.
419+ *
420+ * Used to periodically sample the CPU TSC via a call to get_sample. We
421+ * use stop_machine, whith does (intentionally) introduce latency since we
422+ * need to ensure nothing else might be running (and thus pre-empting).
423+ * Obviously this should never be used in production environments.
424+ *
425+ * stop_machine will schedule us typically only on CPU0 which is fine for
426+ * almost every real-world hardware latency situation - but we might later
427+ * generalize this if we find there are any actualy systems with alternate
428+ * SMI delivery or other non CPU0 hardware latencies.
429+ */
430+static int kthread_fn(void *unused)
431+{
432+ int err = 0;
433+ u64 interval = 0;
434+
435+ while (!kthread_should_stop()) {
436+
437+ mutex_lock(&data.lock);
438+
439+ err = stop_machine(get_sample, unused, 0);
440+ if (err) {
441+ /* Houston, we have a problem */
442+ mutex_unlock(&data.lock);
443+ goto err_out;
444+ }
445+
446+ wake_up(&data.wq); /* wake up reader(s) */
447+
448+ interval = data.sample_window - data.sample_width;
449+ do_div(interval, USEC_PER_MSEC); /* modifies interval value */
450+
451+ mutex_unlock(&data.lock);
452+
453+ if (msleep_interruptible(interval))
454+ goto out;
455+ }
456+ goto out;
457+err_out:
458+ pr_err(BANNER "could not call stop_machine, disabling\n");
459+ enabled = 0;
460+out:
461+ return err;
462+
463+}
464+
465+/**
466+ * start_kthread - Kick off the hardware latency sampling/detector kthread
467+ *
468+ * This starts a kernel thread that will sit and sample the CPU timestamp
469+ * counter (TSC or similar) and look for potential hardware latencies.
470+ */
471+static int start_kthread(void)
472+{
473+ kthread = kthread_run(kthread_fn, NULL,
474+ DRVNAME);
475+ if (IS_ERR(kthread)) {
476+ pr_err(BANNER "could not start sampling thread\n");
477+ enabled = 0;
478+ return -ENOMEM;
479+ }
480+
481+ return 0;
482+}
483+
484+/**
485+ * stop_kthread - Inform the hardware latency samping/detector kthread to stop
486+ *
487+ * This kicks the running hardware latency sampling/detector kernel thread and
488+ * tells it to stop sampling now. Use this on unload and at system shutdown.
489+ */
490+static int stop_kthread(void)
491+{
492+ int ret;
493+
494+ ret = kthread_stop(kthread);
495+
496+ return ret;
497+}
498+
499+/**
500+ * __reset_stats - Reset statistics for the hardware latency detector
501+ *
502+ * We use data to store various statistics and global state. We call this
503+ * function in order to reset those when "enable" is toggled on or off, and
504+ * also at initialization. Should be called with data.lock held.
505+ */
506+static void __reset_stats(void)
507+{
508+ data.count = 0;
509+ data.max_sample = 0;
510+ ring_buffer_reset(ring_buffer); /* flush out old sample entries */
511+}
512+
513+/**
514+ * init_stats - Setup global state statistics for the hardware latency detector
515+ *
516+ * We use data to store various statistics and global state. We also use
517+ * a global ring buffer (ring_buffer) to keep raw samples of detected hardware
518+ * induced system latencies. This function initializes these structures and
519+ * allocates the global ring buffer also.
520+ */
521+static int init_stats(void)
522+{
523+ int ret = -ENOMEM;
524+
525+ mutex_init(&data.lock);
526+ init_waitqueue_head(&data.wq);
527+ atomic_set(&data.sample_open, 0);
528+
529+ ring_buffer = ring_buffer_alloc(buf_size, BUF_FLAGS);
530+
531+ if (WARN(!ring_buffer, KERN_ERR BANNER
532+ "failed to allocate ring buffer!\n"))
533+ goto out;
534+
535+ __reset_stats();
536+ data.threshold = DEFAULT_LAT_THRESHOLD; /* threshold us */
537+ data.sample_window = DEFAULT_SAMPLE_WINDOW; /* window us */
538+ data.sample_width = DEFAULT_SAMPLE_WIDTH; /* width us */
539+
540+ ret = 0;
541+
542+out:
543+ return ret;
544+
545+}
546+
547+/*
548+ * simple_data_read - Wrapper read function for global state debugfs entries
549+ * @filp: The active open file structure for the debugfs "file"
550+ * @ubuf: The userspace provided buffer to read value into
551+ * @cnt: The maximum number of bytes to read
552+ * @ppos: The current "file" position
553+ * @entry: The entry to read from
554+ *
555+ * This function provides a generic read implementation for the global state
556+ * "data" structure debugfs filesystem entries. It would be nice to use
557+ * simple_attr_read directly, but we need to make sure that the data.lock
558+ * spinlock is held during the actual read (even though we likely won't ever
559+ * actually race here as the updater runs under a stop_machine context).
560+ */
561+static ssize_t simple_data_read(struct file *filp, char __user *ubuf,
562+ size_t cnt, loff_t *ppos, const u64 *entry)
563+{
564+ char buf[U64STR_SIZE];
565+ u64 val = 0;
566+ int len = 0;
567+
568+ memset(buf, 0, sizeof(buf));
569+
570+ if (!entry)
571+ return -EFAULT;
572+
573+ mutex_lock(&data.lock);
574+ val = *entry;
575+ mutex_unlock(&data.lock);
576+
577+ len = snprintf(buf, sizeof(buf), "%llu\n", (unsigned long long)val);
578+
579+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
580+
581+}
582+
583+/*
584+ * simple_data_write - Wrapper write function for global state debugfs entries
585+ * @filp: The active open file structure for the debugfs "file"
586+ * @ubuf: The userspace provided buffer to write value from
587+ * @cnt: The maximum number of bytes to write
588+ * @ppos: The current "file" position
589+ * @entry: The entry to write to
590+ *
591+ * This function provides a generic write implementation for the global state
592+ * "data" structure debugfs filesystem entries. It would be nice to use
593+ * simple_attr_write directly, but we need to make sure that the data.lock
594+ * spinlock is held during the actual write (even though we likely won't ever
595+ * actually race here as the updater runs under a stop_machine context).
596+ */
597+static ssize_t simple_data_write(struct file *filp, const char __user *ubuf,
598+ size_t cnt, loff_t *ppos, u64 *entry)
599+{
600+ char buf[U64STR_SIZE];
601+ int csize = min(cnt, sizeof(buf));
602+ u64 val = 0;
603+ int err = 0;
604+
605+ memset(buf, '\0', sizeof(buf));
606+ if (copy_from_user(buf, ubuf, csize))
607+ return -EFAULT;
608+
609+ buf[U64STR_SIZE-1] = '\0'; /* just in case */
610+ err = kstrtoull(buf, 10, &val);
611+ if (err)
612+ return -EINVAL;
613+
614+ mutex_lock(&data.lock);
615+ *entry = val;
616+ mutex_unlock(&data.lock);
617+
618+ return csize;
619+}
620+
621+/**
622+ * debug_count_fopen - Open function for "count" debugfs entry
623+ * @inode: The in-kernel inode representation of the debugfs "file"
624+ * @filp: The active open file structure for the debugfs "file"
625+ *
626+ * This function provides an open implementation for the "count" debugfs
627+ * interface to the hardware latency detector.
628+ */
629+static int debug_count_fopen(struct inode *inode, struct file *filp)
630+{
631+ return 0;
632+}
633+
634+/**
635+ * debug_count_fread - Read function for "count" debugfs entry
636+ * @filp: The active open file structure for the debugfs "file"
637+ * @ubuf: The userspace provided buffer to read value into
638+ * @cnt: The maximum number of bytes to read
639+ * @ppos: The current "file" position
640+ *
641+ * This function provides a read implementation for the "count" debugfs
642+ * interface to the hardware latency detector. Can be used to read the
643+ * number of latency readings exceeding the configured threshold since
644+ * the detector was last reset (e.g. by writing a zero into "count").
645+ */
646+static ssize_t debug_count_fread(struct file *filp, char __user *ubuf,
647+ size_t cnt, loff_t *ppos)
648+{
649+ return simple_data_read(filp, ubuf, cnt, ppos, &data.count);
650+}
651+
652+/**
653+ * debug_count_fwrite - Write function for "count" debugfs entry
654+ * @filp: The active open file structure for the debugfs "file"
655+ * @ubuf: The user buffer that contains the value to write
656+ * @cnt: The maximum number of bytes to write to "file"
657+ * @ppos: The current position in the debugfs "file"
658+ *
659+ * This function provides a write implementation for the "count" debugfs
660+ * interface to the hardware latency detector. Can be used to write a
661+ * desired value, especially to zero the total count.
662+ */
663+static ssize_t debug_count_fwrite(struct file *filp,
664+ const char __user *ubuf,
665+ size_t cnt,
666+ loff_t *ppos)
667+{
668+ return simple_data_write(filp, ubuf, cnt, ppos, &data.count);
669+}
670+
671+/**
672+ * debug_enable_fopen - Dummy open function for "enable" debugfs interface
673+ * @inode: The in-kernel inode representation of the debugfs "file"
674+ * @filp: The active open file structure for the debugfs "file"
675+ *
676+ * This function provides an open implementation for the "enable" debugfs
677+ * interface to the hardware latency detector.
678+ */
679+static int debug_enable_fopen(struct inode *inode, struct file *filp)
680+{
681+ return 0;
682+}
683+
684+/**
685+ * debug_enable_fread - Read function for "enable" debugfs interface
686+ * @filp: The active open file structure for the debugfs "file"
687+ * @ubuf: The userspace provided buffer to read value into
688+ * @cnt: The maximum number of bytes to read
689+ * @ppos: The current "file" position
690+ *
691+ * This function provides a read implementation for the "enable" debugfs
692+ * interface to the hardware latency detector. Can be used to determine
693+ * whether the detector is currently enabled ("0\n" or "1\n" returned).
694+ */
695+static ssize_t debug_enable_fread(struct file *filp, char __user *ubuf,
696+ size_t cnt, loff_t *ppos)
697+{
698+ char buf[4];
699+
700+ if ((cnt < sizeof(buf)) || (*ppos))
701+ return 0;
702+
703+ buf[0] = enabled ? '1' : '0';
704+ buf[1] = '\n';
705+ buf[2] = '\0';
706+ if (copy_to_user(ubuf, buf, strlen(buf)))
707+ return -EFAULT;
708+ return *ppos = strlen(buf);
709+}
710+
711+/**
712+ * debug_enable_fwrite - Write function for "enable" debugfs interface
713+ * @filp: The active open file structure for the debugfs "file"
714+ * @ubuf: The user buffer that contains the value to write
715+ * @cnt: The maximum number of bytes to write to "file"
716+ * @ppos: The current position in the debugfs "file"
717+ *
718+ * This function provides a write implementation for the "enable" debugfs
719+ * interface to the hardware latency detector. Can be used to enable or
720+ * disable the detector, which will have the side-effect of possibly
721+ * also resetting the global stats and kicking off the measuring
722+ * kthread (on an enable) or the converse (upon a disable).
723+ */
724+static ssize_t debug_enable_fwrite(struct file *filp,
725+ const char __user *ubuf,
726+ size_t cnt,
727+ loff_t *ppos)
728+{
729+ char buf[4];
730+ int csize = min(cnt, sizeof(buf));
731+ long val = 0;
732+ int err = 0;
733+
734+ memset(buf, '\0', sizeof(buf));
735+ if (copy_from_user(buf, ubuf, csize))
736+ return -EFAULT;
737+
738+ buf[sizeof(buf)-1] = '\0'; /* just in case */
739+ err = kstrtoul(buf, 10, &val);
Allen Martinfc468d82016-11-15 17:57:52 -0800740+ if (0 != err)
Allen Martin685e0f82016-07-26 19:34:29 -0700741+ return -EINVAL;
742+
743+ if (val) {
744+ if (enabled)
745+ goto unlock;
746+ enabled = 1;
747+ __reset_stats();
748+ if (start_kthread())
749+ return -EFAULT;
750+ } else {
751+ if (!enabled)
752+ goto unlock;
753+ enabled = 0;
754+ err = stop_kthread();
755+ if (err) {
756+ pr_err(BANNER "cannot stop kthread\n");
757+ return -EFAULT;
758+ }
759+ wake_up(&data.wq); /* reader(s) should return */
760+ }
761+unlock:
762+ return csize;
763+}
764+
765+/**
766+ * debug_max_fopen - Open function for "max" debugfs entry
767+ * @inode: The in-kernel inode representation of the debugfs "file"
768+ * @filp: The active open file structure for the debugfs "file"
769+ *
770+ * This function provides an open implementation for the "max" debugfs
771+ * interface to the hardware latency detector.
772+ */
773+static int debug_max_fopen(struct inode *inode, struct file *filp)
774+{
775+ return 0;
776+}
777+
778+/**
779+ * debug_max_fread - Read function for "max" debugfs entry
780+ * @filp: The active open file structure for the debugfs "file"
781+ * @ubuf: The userspace provided buffer to read value into
782+ * @cnt: The maximum number of bytes to read
783+ * @ppos: The current "file" position
784+ *
785+ * This function provides a read implementation for the "max" debugfs
786+ * interface to the hardware latency detector. Can be used to determine
787+ * the maximum latency value observed since it was last reset.
788+ */
789+static ssize_t debug_max_fread(struct file *filp, char __user *ubuf,
790+ size_t cnt, loff_t *ppos)
791+{
792+ return simple_data_read(filp, ubuf, cnt, ppos, &data.max_sample);
793+}
794+
795+/**
796+ * debug_max_fwrite - Write function for "max" debugfs entry
797+ * @filp: The active open file structure for the debugfs "file"
798+ * @ubuf: The user buffer that contains the value to write
799+ * @cnt: The maximum number of bytes to write to "file"
800+ * @ppos: The current position in the debugfs "file"
801+ *
802+ * This function provides a write implementation for the "max" debugfs
803+ * interface to the hardware latency detector. Can be used to reset the
804+ * maximum or set it to some other desired value - if, then, subsequent
805+ * measurements exceed this value, the maximum will be updated.
806+ */
807+static ssize_t debug_max_fwrite(struct file *filp,
808+ const char __user *ubuf,
809+ size_t cnt,
810+ loff_t *ppos)
811+{
812+ return simple_data_write(filp, ubuf, cnt, ppos, &data.max_sample);
813+}
814+
815+
816+/**
817+ * debug_sample_fopen - An open function for "sample" debugfs interface
818+ * @inode: The in-kernel inode representation of this debugfs "file"
819+ * @filp: The active open file structure for the debugfs "file"
820+ *
821+ * This function handles opening the "sample" file within the hardware
822+ * latency detector debugfs directory interface. This file is used to read
823+ * raw samples from the global ring_buffer and allows the user to see a
824+ * running latency history. Can be opened blocking or non-blocking,
825+ * affecting whether it behaves as a buffer read pipe, or does not.
826+ * Implements simple locking to prevent multiple simultaneous use.
827+ */
828+static int debug_sample_fopen(struct inode *inode, struct file *filp)
829+{
830+ if (!atomic_add_unless(&data.sample_open, 1, 1))
831+ return -EBUSY;
832+ else
833+ return 0;
834+}
835+
836+/**
837+ * debug_sample_fread - A read function for "sample" debugfs interface
838+ * @filp: The active open file structure for the debugfs "file"
839+ * @ubuf: The user buffer that will contain the samples read
840+ * @cnt: The maximum bytes to read from the debugfs "file"
841+ * @ppos: The current position in the debugfs "file"
842+ *
843+ * This function handles reading from the "sample" file within the hardware
844+ * latency detector debugfs directory interface. This file is used to read
845+ * raw samples from the global ring_buffer and allows the user to see a
846+ * running latency history. By default this will block pending a new
847+ * value written into the sample buffer, unless there are already a
848+ * number of value(s) waiting in the buffer, or the sample file was
849+ * previously opened in a non-blocking mode of operation.
850+ */
851+static ssize_t debug_sample_fread(struct file *filp, char __user *ubuf,
852+ size_t cnt, loff_t *ppos)
853+{
854+ int len = 0;
855+ char buf[64];
856+ struct sample *sample = NULL;
857+
858+ if (!enabled)
859+ return 0;
860+
861+ sample = kzalloc(sizeof(struct sample), GFP_KERNEL);
862+ if (!sample)
863+ return -ENOMEM;
864+
865+ while (!buffer_get_sample(sample)) {
866+
867+ DEFINE_WAIT(wait);
868+
869+ if (filp->f_flags & O_NONBLOCK) {
870+ len = -EAGAIN;
871+ goto out;
872+ }
873+
874+ prepare_to_wait(&data.wq, &wait, TASK_INTERRUPTIBLE);
875+ schedule();
876+ finish_wait(&data.wq, &wait);
877+
878+ if (signal_pending(current)) {
879+ len = -EINTR;
880+ goto out;
881+ }
882+
883+ if (!enabled) { /* enable was toggled */
884+ len = 0;
885+ goto out;
886+ }
887+ }
888+
889+ len = snprintf(buf, sizeof(buf), "%010lu.%010lu\t%llu\n",
890+ sample->timestamp.tv_sec,
891+ sample->timestamp.tv_nsec,
892+ sample->duration);
893+
894+
895+ /* handling partial reads is more trouble than it's worth */
896+ if (len > cnt)
897+ goto out;
898+
899+ if (copy_to_user(ubuf, buf, len))
900+ len = -EFAULT;
901+
902+out:
903+ kfree(sample);
904+ return len;
905+}
906+
907+/**
908+ * debug_sample_release - Release function for "sample" debugfs interface
909+ * @inode: The in-kernel inode represenation of the debugfs "file"
910+ * @filp: The active open file structure for the debugfs "file"
911+ *
912+ * This function completes the close of the debugfs interface "sample" file.
913+ * Frees the sample_open "lock" so that other users may open the interface.
914+ */
915+static int debug_sample_release(struct inode *inode, struct file *filp)
916+{
917+ atomic_dec(&data.sample_open);
918+
919+ return 0;
920+}
921+
922+/**
923+ * debug_threshold_fopen - Open function for "threshold" debugfs entry
924+ * @inode: The in-kernel inode representation of the debugfs "file"
925+ * @filp: The active open file structure for the debugfs "file"
926+ *
927+ * This function provides an open implementation for the "threshold" debugfs
928+ * interface to the hardware latency detector.
929+ */
930+static int debug_threshold_fopen(struct inode *inode, struct file *filp)
931+{
932+ return 0;
933+}
934+
935+/**
936+ * debug_threshold_fread - Read function for "threshold" debugfs entry
937+ * @filp: The active open file structure for the debugfs "file"
938+ * @ubuf: The userspace provided buffer to read value into
939+ * @cnt: The maximum number of bytes to read
940+ * @ppos: The current "file" position
941+ *
942+ * This function provides a read implementation for the "threshold" debugfs
943+ * interface to the hardware latency detector. It can be used to determine
944+ * the current threshold level at which a latency will be recorded in the
945+ * global ring buffer, typically on the order of 10us.
946+ */
947+static ssize_t debug_threshold_fread(struct file *filp, char __user *ubuf,
948+ size_t cnt, loff_t *ppos)
949+{
950+ return simple_data_read(filp, ubuf, cnt, ppos, &data.threshold);
951+}
952+
953+/**
954+ * debug_threshold_fwrite - Write function for "threshold" debugfs entry
955+ * @filp: The active open file structure for the debugfs "file"
956+ * @ubuf: The user buffer that contains the value to write
957+ * @cnt: The maximum number of bytes to write to "file"
958+ * @ppos: The current position in the debugfs "file"
959+ *
960+ * This function provides a write implementation for the "threshold" debugfs
961+ * interface to the hardware latency detector. It can be used to configure
962+ * the threshold level at which any subsequently detected latencies will
963+ * be recorded into the global ring buffer.
964+ */
965+static ssize_t debug_threshold_fwrite(struct file *filp,
966+ const char __user *ubuf,
967+ size_t cnt,
968+ loff_t *ppos)
969+{
970+ int ret;
971+
972+ ret = simple_data_write(filp, ubuf, cnt, ppos, &data.threshold);
973+
974+ if (enabled)
975+ wake_up_process(kthread);
976+
977+ return ret;
978+}
979+
980+/**
981+ * debug_width_fopen - Open function for "width" debugfs entry
982+ * @inode: The in-kernel inode representation of the debugfs "file"
983+ * @filp: The active open file structure for the debugfs "file"
984+ *
985+ * This function provides an open implementation for the "width" debugfs
986+ * interface to the hardware latency detector.
987+ */
988+static int debug_width_fopen(struct inode *inode, struct file *filp)
989+{
990+ return 0;
991+}
992+
993+/**
994+ * debug_width_fread - Read function for "width" debugfs entry
995+ * @filp: The active open file structure for the debugfs "file"
996+ * @ubuf: The userspace provided buffer to read value into
997+ * @cnt: The maximum number of bytes to read
998+ * @ppos: The current "file" position
999+ *
1000+ * This function provides a read implementation for the "width" debugfs
1001+ * interface to the hardware latency detector. It can be used to determine
1002+ * for how many us of the total window us we will actively sample for any
1003+ * hardware-induced latecy periods. Obviously, it is not possible to
1004+ * sample constantly and have the system respond to a sample reader, or,
1005+ * worse, without having the system appear to have gone out to lunch.
1006+ */
1007+static ssize_t debug_width_fread(struct file *filp, char __user *ubuf,
1008+ size_t cnt, loff_t *ppos)
1009+{
1010+ return simple_data_read(filp, ubuf, cnt, ppos, &data.sample_width);
1011+}
1012+
1013+/**
1014+ * debug_width_fwrite - Write function for "width" debugfs entry
1015+ * @filp: The active open file structure for the debugfs "file"
1016+ * @ubuf: The user buffer that contains the value to write
1017+ * @cnt: The maximum number of bytes to write to "file"
1018+ * @ppos: The current position in the debugfs "file"
1019+ *
1020+ * This function provides a write implementation for the "width" debugfs
1021+ * interface to the hardware latency detector. It can be used to configure
1022+ * for how many us of the total window us we will actively sample for any
1023+ * hardware-induced latency periods. Obviously, it is not possible to
1024+ * sample constantly and have the system respond to a sample reader, or,
1025+ * worse, without having the system appear to have gone out to lunch. It
1026+ * is enforced that width is less that the total window size.
1027+ */
1028+static ssize_t debug_width_fwrite(struct file *filp,
1029+ const char __user *ubuf,
1030+ size_t cnt,
1031+ loff_t *ppos)
1032+{
1033+ char buf[U64STR_SIZE];
1034+ int csize = min(cnt, sizeof(buf));
1035+ u64 val = 0;
1036+ int err = 0;
1037+
1038+ memset(buf, '\0', sizeof(buf));
1039+ if (copy_from_user(buf, ubuf, csize))
1040+ return -EFAULT;
1041+
1042+ buf[U64STR_SIZE-1] = '\0'; /* just in case */
1043+ err = kstrtoull(buf, 10, &val);
Allen Martinfc468d82016-11-15 17:57:52 -08001044+ if (0 != err)
Allen Martin685e0f82016-07-26 19:34:29 -07001045+ return -EINVAL;
1046+
1047+ mutex_lock(&data.lock);
1048+ if (val < data.sample_window)
1049+ data.sample_width = val;
1050+ else {
1051+ mutex_unlock(&data.lock);
1052+ return -EINVAL;
1053+ }
1054+ mutex_unlock(&data.lock);
1055+
1056+ if (enabled)
1057+ wake_up_process(kthread);
1058+
1059+ return csize;
1060+}
1061+
1062+/**
1063+ * debug_window_fopen - Open function for "window" debugfs entry
1064+ * @inode: The in-kernel inode representation of the debugfs "file"
1065+ * @filp: The active open file structure for the debugfs "file"
1066+ *
1067+ * This function provides an open implementation for the "window" debugfs
1068+ * interface to the hardware latency detector. The window is the total time
1069+ * in us that will be considered one sample period. Conceptually, windows
1070+ * occur back-to-back and contain a sample width period during which
1071+ * actual sampling occurs.
1072+ */
1073+static int debug_window_fopen(struct inode *inode, struct file *filp)
1074+{
1075+ return 0;
1076+}
1077+
1078+/**
1079+ * debug_window_fread - Read function for "window" debugfs entry
1080+ * @filp: The active open file structure for the debugfs "file"
1081+ * @ubuf: The userspace provided buffer to read value into
1082+ * @cnt: The maximum number of bytes to read
1083+ * @ppos: The current "file" position
1084+ *
1085+ * This function provides a read implementation for the "window" debugfs
1086+ * interface to the hardware latency detector. The window is the total time
1087+ * in us that will be considered one sample period. Conceptually, windows
1088+ * occur back-to-back and contain a sample width period during which
1089+ * actual sampling occurs. Can be used to read the total window size.
1090+ */
1091+static ssize_t debug_window_fread(struct file *filp, char __user *ubuf,
1092+ size_t cnt, loff_t *ppos)
1093+{
1094+ return simple_data_read(filp, ubuf, cnt, ppos, &data.sample_window);
1095+}
1096+
1097+/**
1098+ * debug_window_fwrite - Write function for "window" debugfs entry
1099+ * @filp: The active open file structure for the debugfs "file"
1100+ * @ubuf: The user buffer that contains the value to write
1101+ * @cnt: The maximum number of bytes to write to "file"
1102+ * @ppos: The current position in the debugfs "file"
1103+ *
1104+ * This function provides a write implementation for the "window" debufds
1105+ * interface to the hardware latency detetector. The window is the total time
1106+ * in us that will be considered one sample period. Conceptually, windows
1107+ * occur back-to-back and contain a sample width period during which
1108+ * actual sampling occurs. Can be used to write a new total window size. It
1109+ * is enfoced that any value written must be greater than the sample width
1110+ * size, or an error results.
1111+ */
1112+static ssize_t debug_window_fwrite(struct file *filp,
1113+ const char __user *ubuf,
1114+ size_t cnt,
1115+ loff_t *ppos)
1116+{
1117+ char buf[U64STR_SIZE];
1118+ int csize = min(cnt, sizeof(buf));
1119+ u64 val = 0;
1120+ int err = 0;
1121+
1122+ memset(buf, '\0', sizeof(buf));
1123+ if (copy_from_user(buf, ubuf, csize))
1124+ return -EFAULT;
1125+
1126+ buf[U64STR_SIZE-1] = '\0'; /* just in case */
1127+ err = kstrtoull(buf, 10, &val);
Allen Martinfc468d82016-11-15 17:57:52 -08001128+ if (0 != err)
Allen Martin685e0f82016-07-26 19:34:29 -07001129+ return -EINVAL;
1130+
1131+ mutex_lock(&data.lock);
1132+ if (data.sample_width < val)
1133+ data.sample_window = val;
1134+ else {
1135+ mutex_unlock(&data.lock);
1136+ return -EINVAL;
1137+ }
1138+ mutex_unlock(&data.lock);
1139+
1140+ return csize;
1141+}
1142+
1143+/*
1144+ * Function pointers for the "count" debugfs file operations
1145+ */
1146+static const struct file_operations count_fops = {
1147+ .open = debug_count_fopen,
1148+ .read = debug_count_fread,
1149+ .write = debug_count_fwrite,
1150+ .owner = THIS_MODULE,
1151+};
1152+
1153+/*
1154+ * Function pointers for the "enable" debugfs file operations
1155+ */
1156+static const struct file_operations enable_fops = {
1157+ .open = debug_enable_fopen,
1158+ .read = debug_enable_fread,
1159+ .write = debug_enable_fwrite,
1160+ .owner = THIS_MODULE,
1161+};
1162+
1163+/*
1164+ * Function pointers for the "max" debugfs file operations
1165+ */
1166+static const struct file_operations max_fops = {
1167+ .open = debug_max_fopen,
1168+ .read = debug_max_fread,
1169+ .write = debug_max_fwrite,
1170+ .owner = THIS_MODULE,
1171+};
1172+
1173+/*
1174+ * Function pointers for the "sample" debugfs file operations
1175+ */
1176+static const struct file_operations sample_fops = {
1177+ .open = debug_sample_fopen,
1178+ .read = debug_sample_fread,
1179+ .release = debug_sample_release,
1180+ .owner = THIS_MODULE,
1181+};
1182+
1183+/*
1184+ * Function pointers for the "threshold" debugfs file operations
1185+ */
1186+static const struct file_operations threshold_fops = {
1187+ .open = debug_threshold_fopen,
1188+ .read = debug_threshold_fread,
1189+ .write = debug_threshold_fwrite,
1190+ .owner = THIS_MODULE,
1191+};
1192+
1193+/*
1194+ * Function pointers for the "width" debugfs file operations
1195+ */
1196+static const struct file_operations width_fops = {
1197+ .open = debug_width_fopen,
1198+ .read = debug_width_fread,
1199+ .write = debug_width_fwrite,
1200+ .owner = THIS_MODULE,
1201+};
1202+
1203+/*
1204+ * Function pointers for the "window" debugfs file operations
1205+ */
1206+static const struct file_operations window_fops = {
1207+ .open = debug_window_fopen,
1208+ .read = debug_window_fread,
1209+ .write = debug_window_fwrite,
1210+ .owner = THIS_MODULE,
1211+};
1212+
1213+/**
1214+ * init_debugfs - A function to initialize the debugfs interface files
1215+ *
1216+ * This function creates entries in debugfs for "hwlat_detector", including
1217+ * files to read values from the detector, current samples, and the
1218+ * maximum sample that has been captured since the hardware latency
1219+ * dectector was started.
1220+ */
1221+static int init_debugfs(void)
1222+{
1223+ int ret = -ENOMEM;
1224+
1225+ debug_dir = debugfs_create_dir(DRVNAME, NULL);
1226+ if (!debug_dir)
1227+ goto err_debug_dir;
1228+
1229+ debug_sample = debugfs_create_file("sample", 0444,
1230+ debug_dir, NULL,
1231+ &sample_fops);
1232+ if (!debug_sample)
1233+ goto err_sample;
1234+
1235+ debug_count = debugfs_create_file("count", 0444,
1236+ debug_dir, NULL,
1237+ &count_fops);
1238+ if (!debug_count)
1239+ goto err_count;
1240+
1241+ debug_max = debugfs_create_file("max", 0444,
1242+ debug_dir, NULL,
1243+ &max_fops);
1244+ if (!debug_max)
1245+ goto err_max;
1246+
1247+ debug_sample_window = debugfs_create_file("window", 0644,
1248+ debug_dir, NULL,
1249+ &window_fops);
1250+ if (!debug_sample_window)
1251+ goto err_window;
1252+
1253+ debug_sample_width = debugfs_create_file("width", 0644,
1254+ debug_dir, NULL,
1255+ &width_fops);
1256+ if (!debug_sample_width)
1257+ goto err_width;
1258+
1259+ debug_threshold = debugfs_create_file("threshold", 0644,
1260+ debug_dir, NULL,
1261+ &threshold_fops);
1262+ if (!debug_threshold)
1263+ goto err_threshold;
1264+
1265+ debug_enable = debugfs_create_file("enable", 0644,
1266+ debug_dir, &enabled,
1267+ &enable_fops);
1268+ if (!debug_enable)
1269+ goto err_enable;
1270+
1271+ else {
1272+ ret = 0;
1273+ goto out;
1274+ }
1275+
1276+err_enable:
1277+ debugfs_remove(debug_threshold);
1278+err_threshold:
1279+ debugfs_remove(debug_sample_width);
1280+err_width:
1281+ debugfs_remove(debug_sample_window);
1282+err_window:
1283+ debugfs_remove(debug_max);
1284+err_max:
1285+ debugfs_remove(debug_count);
1286+err_count:
1287+ debugfs_remove(debug_sample);
1288+err_sample:
1289+ debugfs_remove(debug_dir);
1290+err_debug_dir:
1291+out:
1292+ return ret;
1293+}
1294+
1295+/**
1296+ * free_debugfs - A function to cleanup the debugfs file interface
1297+ */
1298+static void free_debugfs(void)
1299+{
1300+ /* could also use a debugfs_remove_recursive */
1301+ debugfs_remove(debug_enable);
1302+ debugfs_remove(debug_threshold);
1303+ debugfs_remove(debug_sample_width);
1304+ debugfs_remove(debug_sample_window);
1305+ debugfs_remove(debug_max);
1306+ debugfs_remove(debug_count);
1307+ debugfs_remove(debug_sample);
1308+ debugfs_remove(debug_dir);
1309+}
1310+
1311+/**
1312+ * detector_init - Standard module initialization code
1313+ */
1314+static int detector_init(void)
1315+{
1316+ int ret = -ENOMEM;
1317+
1318+ pr_info(BANNER "version %s\n", VERSION);
1319+
1320+ ret = init_stats();
Allen Martinfc468d82016-11-15 17:57:52 -08001321+ if (0 != ret)
Allen Martin685e0f82016-07-26 19:34:29 -07001322+ goto out;
1323+
1324+ ret = init_debugfs();
Allen Martinfc468d82016-11-15 17:57:52 -08001325+ if (0 != ret)
Allen Martin685e0f82016-07-26 19:34:29 -07001326+ goto err_stats;
1327+
1328+ if (enabled)
1329+ ret = start_kthread();
1330+
1331+ goto out;
1332+
1333+err_stats:
1334+ ring_buffer_free(ring_buffer);
1335+out:
1336+ return ret;
1337+
1338+}
1339+
1340+/**
1341+ * detector_exit - Standard module cleanup code
1342+ */
1343+static void detector_exit(void)
1344+{
1345+ int err;
1346+
1347+ if (enabled) {
1348+ enabled = 0;
1349+ err = stop_kthread();
1350+ if (err)
1351+ pr_err(BANNER "cannot stop kthread\n");
1352+ }
1353+
1354+ free_debugfs();
1355+ ring_buffer_free(ring_buffer); /* free up the ring buffer */
1356+
1357+}
1358+
1359+module_init(detector_init);
1360+module_exit(detector_exit);
1361--
Allen Martinfc468d82016-11-15 17:57:52 -080013622.10.1
Allen Martin685e0f82016-07-26 19:34:29 -07001363