aboutsummaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorDrew Richardson <drew.richardson@arm.com>2011-07-28 12:00:00 -0700
committerDrew Richardson <drew.richardson@arm.com>2014-12-19 15:11:29 -0800
commit73158f9d05b7087bb6ff895e820017af3c94a1a6 (patch)
tree721e2415eafaf46a659770672a46ad8731360315 /driver
parent538231c5bf600e61a4ac4f7a25e6ba2c61ad68ee (diff)
gator: Version 5.65.6
Signed-off-by: Drew Richardson <drew.richardson@arm.com>
Diffstat (limited to 'driver')
-rw-r--r--driver/Makefile25
-rw-r--r--driver/gator.h19
-rw-r--r--driver/gator_annotate.c109
-rw-r--r--driver/gator_cookies.c4
-rw-r--r--driver/gator_events.c40
-rw-r--r--driver/gator_events.sh19
-rw-r--r--driver/gator_events_armv6.c53
-rw-r--r--driver/gator_events_armv7.c217
-rw-r--r--driver/gator_events_block.c41
-rw-r--r--driver/gator_events_irq.c43
-rw-r--r--driver/gator_events_meminfo.c40
-rw-r--r--driver/gator_events_mmaped.c196
-rw-r--r--driver/gator_events_net.c45
-rw-r--r--driver/gator_events_pl310.c176
-rw-r--r--driver/gator_events_sched.c36
-rw-r--r--driver/gator_events_scorpion.c661
-rw-r--r--driver/gator_fs.c2
-rw-r--r--driver/gator_main.c291
18 files changed, 1476 insertions, 541 deletions
diff --git a/driver/Makefile b/driver/Makefile
index 0583ae3..b3680e1 100644
--- a/driver/Makefile
+++ b/driver/Makefile
@@ -2,15 +2,34 @@ ifneq ($(KERNELRELEASE),)
obj-m := gator.o
-gator-objs := gator_main.o \
- gator_events_armv6.o \
- gator_events_armv7.o \
+gator-y := gator_main.o \
gator_events_irq.o \
gator_events_sched.o \
gator_events_net.o \
gator_events_block.o \
gator_events_meminfo.o
+gator-y += gator_events_mmaped.o
+
+ifneq ($(GATOR_WITH_MALI_SUPPORT),)
+gator-y += gator_events_mali.o
+endif
+
+gator-$(CONFIG_ARM) += gator_events_armv6.o \
+ gator_events_armv7.o \
+ gator_events_pl310.o
+
+$(obj)/gator_main.o: gator_events.h
+
+clean-files := gator_events.h
+
+ chk_events.h = :
+ quiet_chk_events.h = echo ' CHK $@'
+silent_chk_events.h = :
+gator_events.h: FORCE
+ @$($(quiet)chk_events.h)
+ $(Q)cd $(obj) ; $(CONFIG_SHELL) $(obj)/gator_events.sh $@
+
else
all:
diff --git a/driver/gator.h b/driver/gator.h
index f0c95bf..9d802a3 100644
--- a/driver/gator.h
+++ b/driver/gator.h
@@ -1,5 +1,5 @@
/**
- * Copyright 2010 ARM, Ltd.
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -12,6 +12,7 @@
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/mm.h>
+#include <linux/list.h>
/******************************************************************************
* Filesystem
@@ -28,6 +29,8 @@ int gatorfs_create_ulong(struct super_block *sb, struct dentry *root,
int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root,
char const *name, unsigned long *val);
+void gator_op_create_files(struct super_block *sb, struct dentry *root);
+
/******************************************************************************
* Tracepoints
******************************************************************************/
@@ -52,21 +55,25 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root,
/******************************************************************************
* Events
******************************************************************************/
-struct __gator_interface {
+struct gator_interface {
int (*create_files)(struct super_block *sb, struct dentry *root);
- int (*init)(int *key);
int (*start)(void);
void (*stop)(void);
void (*online)(void);
void (*offline)(void);
int (*read)(int **buffer);
- struct __gator_interface *next;
+ struct list_head list;
};
-typedef struct __gator_interface gator_interface;
+#define gator_events_init(initfn) \
+ static inline int __gator_events_init_test(void) \
+ { return initfn(); }
-int gator_event_install(int (*event_install)(gator_interface *));
+int gator_events_install(struct gator_interface *interface);
+int gator_events_get_key(void);
+extern u32 gator_cpuid(void);
extern unsigned long gator_net_traffic;
+
#endif // GATOR_H_
diff --git a/driver/gator_annotate.c b/driver/gator_annotate.c
index f261f73..d8d86af 100644
--- a/driver/gator_annotate.c
+++ b/driver/gator_annotate.c
@@ -15,7 +15,7 @@
#include <asm/current.h>
#include <linux/spinlock.h>
-#define INSTSIZE 1024
+#define ANNOTATE_SIZE (16*1024)
static DEFINE_SPINLOCK(annotate_lock);
static char *annotateBuf;
static char *annotateBuf0;
@@ -25,35 +25,42 @@ static int annotateSel;
static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
{
- char tempBuffer[32];
- unsigned long flags;
+ char tempBuffer[512];
int retval, remaining, size;
if (*offset)
return -EINVAL;
// determine size to capture
- remaining = INSTSIZE - annotatePos - 24; // leave some extra space
+ remaining = ANNOTATE_SIZE - annotatePos - 256; // pad for headers and release
size = count < sizeof(tempBuffer) ? count : sizeof(tempBuffer);
size = size < remaining ? size : remaining;
- if (size <= 0)
+ if (size <= 0) {
+ wake_up(&gator_buffer_wait);
return 0;
+ }
// copy from user space
retval = copy_from_user(tempBuffer, buf, size);
if (retval == 0) {
// synchronize shared variables annotateBuf and annotatePos
- spin_lock_irqsave(&annotate_lock, flags);
- if (!annotateBuf) {
- size = -EINVAL;
- } else {
- *(int*)&annotateBuf[annotatePos + 0] = current->pid; // thread id
- *(int*)&annotateBuf[annotatePos + 4] = size; // length in bytes
- memcpy(&annotateBuf[annotatePos + 8], tempBuffer, size); // data
- annotatePos = annotatePos + 8 + size; // increment position
- annotatePos = (annotatePos + 3) & ~3; // align to 4-byte boundary
+ spin_lock(&annotate_lock);
+ if (annotateBuf) {
+ uint32_t tid = current->pid;
+ uint32_t tick = gator_master_tick;
+ uint64_t time = gator_get_time();
+ uint32_t cpuid = smp_processor_id();
+ int pos = annotatePos;
+ pos += gator_write_packed_int(&annotateBuf[pos], tid);
+ pos += gator_write_packed_int(&annotateBuf[pos], tick);
+ pos += gator_write_packed_int(&annotateBuf[pos], time);
+ pos += gator_write_packed_int(&annotateBuf[pos], time >> 32);
+ pos += gator_write_packed_int(&annotateBuf[pos], cpuid);
+ pos += gator_write_packed_int(&annotateBuf[pos], size);
+ memcpy(&annotateBuf[pos], tempBuffer, size);
+ annotatePos = pos + size;
}
- spin_unlock_irqrestore(&annotate_lock, flags);
+ spin_unlock(&annotate_lock);
// return the number of bytes written
retval = size;
@@ -64,64 +71,96 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t
return retval;
}
+static int annotate_release(struct inode *inode, struct file *file)
+{
+ int remaining = ANNOTATE_SIZE - annotatePos;
+ if (remaining < 16) {
+ return -EFAULT;
+ }
+
+ spin_lock(&annotate_lock);
+ if (annotateBuf) {
+ uint32_t tid = current->pid;
+ uint32_t tick = gator_master_tick;
+ int pos = annotatePos;
+ pos += gator_write_packed_int(&annotateBuf[pos], tid);
+ pos += gator_write_packed_int(&annotateBuf[pos], tick);
+ pos += gator_write_packed_int(&annotateBuf[pos], 0); // time
+ pos += gator_write_packed_int(&annotateBuf[pos], 0); // time
+ pos += gator_write_packed_int(&annotateBuf[pos], 0); // cpuid
+ pos += gator_write_packed_int(&annotateBuf[pos], 0); // size
+ annotatePos = pos;
+ }
+ spin_unlock(&annotate_lock);
+
+ return 0;
+}
+
static const struct file_operations annotate_fops = {
- .write = annotate_write
+ .write = annotate_write,
+ .release = annotate_release
};
-int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
+static int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
{
- annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
+ annotateBuf = NULL;
return gatorfs_create_file_perm(sb, root, "annotate", &annotate_fops, 0666);
}
-int gator_annotate_init(void)
+static int gator_annotate_init(void)
{
+ annotateBuf0 = kmalloc(ANNOTATE_SIZE, GFP_KERNEL);
+ annotateBuf1 = kmalloc(ANNOTATE_SIZE, GFP_KERNEL);
+ if (!annotateBuf0 || !annotateBuf1)
+ return -1;
return 0;
}
-int gator_annotate_start(void)
+static int gator_annotate_start(void)
{
annotatePos = annotateSel = 0;
- annotateBuf0 = kmalloc(INSTSIZE, GFP_KERNEL);
- annotateBuf1 = kmalloc(INSTSIZE, GFP_KERNEL);
annotateBuf = annotateBuf0;
- if (!annotateBuf0 || !annotateBuf1)
- return -1;
return 0;
}
-void gator_annotate_stop(void)
+static void gator_annotate_stop(void)
{
- unsigned long flags;
- spin_lock_irqsave(&annotate_lock, flags);
+ spin_lock(&annotate_lock);
+ annotateBuf = NULL;
+ spin_unlock(&annotate_lock);
+}
+static void gator_annotate_exit(void)
+{
+ spin_lock(&annotate_lock);
kfree(annotateBuf0);
kfree(annotateBuf1);
annotateBuf = annotateBuf0 = annotateBuf1 = NULL;
+ spin_unlock(&annotate_lock);
+}
- spin_unlock_irqrestore(&annotate_lock, flags);
+static int gator_annotate_ready(void)
+{
+ return annotatePos && annotateBuf;
}
-int gator_annotate_read(int **buffer)
+static int gator_annotate_read(char **buffer)
{
int len;
- if (smp_processor_id() || !annotatePos || !annotateBuf)
+ if (!gator_annotate_ready())
return 0;
annotateSel = !annotateSel;
if (buffer)
- *buffer = (int *)annotateBuf;
+ *buffer = annotateBuf;
spin_lock(&annotate_lock);
-
len = annotatePos;
annotatePos = 0;
annotateBuf = annotateSel ? annotateBuf1 : annotateBuf0;
-
spin_unlock(&annotate_lock);
- // Return number of 4-byte words
- return len / 4;
+ return len;
}
diff --git a/driver/gator_cookies.c b/driver/gator_cookies.c
index 70fece0..64be841 100644
--- a/driver/gator_cookies.c
+++ b/driver/gator_cookies.c
@@ -57,7 +57,7 @@ static uint32_t gator_chksum_crc32(char *data)
*/
static uint32_t cookiemap_exists(uint64_t key) {
unsigned long x, flags, retval = 0;
- int cpu = raw_smp_processor_id();
+ int cpu = smp_processor_id();
uint32_t cookiecode = cookiemap_code(key);
uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]);
uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]);
@@ -88,7 +88,7 @@ static uint32_t cookiemap_exists(uint64_t key) {
* Post: [v][0][1][2]..[n-2]
*/
static void cookiemap_add(uint64_t key, uint32_t value) {
- int cpu = raw_smp_processor_id();
+ int cpu = smp_processor_id();
int cookiecode = cookiemap_code(key);
uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]);
uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]);
diff --git a/driver/gator_events.c b/driver/gator_events.c
deleted file mode 100644
index d837257..0000000
--- a/driver/gator_events.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2010-2011. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-/**
- * This file is #included in gator_main.c
- * Update this file and Makefile to add custom counters.
- */
-
-extern int gator_events_armv6_install(gator_interface *gi);
-extern int gator_events_armv7_install(gator_interface *gi);
-extern int gator_events_irq_install(gator_interface *gi);
-extern int gator_events_sched_install(gator_interface *gi);
-extern int gator_events_block_install(gator_interface *gi);
-extern int gator_events_meminfo_install(gator_interface *gi);
-extern int gator_events_net_install(gator_interface *gi);
-
-static int gator_events_install(void)
-{
- if (gator_event_install(gator_events_armv6_install))
- return -1;
- if (gator_event_install(gator_events_armv7_install))
- return -1;
- if (gator_event_install(gator_events_irq_install))
- return -1;
- if (gator_event_install(gator_events_sched_install))
- return -1;
- if (gator_event_install(gator_events_block_install))
- return -1;
- if (gator_event_install(gator_events_meminfo_install))
- return -1;
- if (gator_event_install(gator_events_net_install))
- return -1;
- return 0;
-}
diff --git a/driver/gator_events.sh b/driver/gator_events.sh
new file mode 100644
index 0000000..5467dd6
--- /dev/null
+++ b/driver/gator_events.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+EVENTS=`grep gator_events_init *.c | sed 's/.\+gator_events_init(\(.\+\)).\+/\1/'`
+
+(
+ echo /\* This file is auto generated \*/
+ echo
+ for EVENT in $EVENTS; do
+ echo __weak int $EVENT\(void\)\;
+ done
+ echo
+ echo static int \(*gator_events_list[]\)\(void\) = {
+ for EVENT in $EVENTS; do
+ echo \ $EVENT,
+ done
+ echo }\;
+) > $1.tmp
+
+cmp -s $1 $1.tmp && rm $1.tmp || mv $1.tmp $1
diff --git a/driver/gator_events_armv6.c b/driver/gator_events_armv6.c
index c571e44..7b1d875 100644
--- a/driver/gator_events_armv6.c
+++ b/driver/gator_events_armv6.c
@@ -8,16 +8,12 @@
#include "gator.h"
-#if defined(__arm__)
-
#define ARM1136 0xb36
#define ARM1156 0xb56
#define ARM1176 0xb76
static const char *pmnc_name;
-extern u32 gator_cpuid(void);
-
/*
* Per-CPU PMCR
*/
@@ -99,20 +95,6 @@ int gator_events_armv6_create_files(struct super_block *sb, struct dentry *root)
return 0;
}
-static int gator_events_armv6_init(int *key)
-{
- unsigned int cnt;
-
- for (cnt = PMN0; cnt <= CCNT; cnt++) {
- pmnc_enabled[cnt] = 0;
- pmnc_event[cnt] = 0;
- pmnc_key[cnt] = *key;
- *key = *key + 1;
- }
-
- return 0;
-}
-
static void gator_events_armv6_online(void)
{
unsigned int cnt;
@@ -130,7 +112,7 @@ static void gator_events_armv6_online(void)
for (pmnc = 0, cnt = PMN0; cnt <= CCNT; cnt++) {
unsigned long event;
- per_cpu(perfPrev, raw_smp_processor_id())[cnt] = 0;
+ per_cpu(perfPrev, smp_processor_id())[cnt] = 0;
if (!pmnc_enabled[cnt])
continue;
@@ -177,7 +159,7 @@ static void gator_events_armv6_stop(void)
static int gator_events_armv6_read(int **buffer)
{
int cnt, len = 0;
- int cpu = raw_smp_processor_id();
+ int cpu = smp_processor_id();
for (cnt = PMN0; cnt <= CCNT; cnt++) {
if (pmnc_enabled[cnt]) {
@@ -208,10 +190,19 @@ static int gator_events_armv6_read(int **buffer)
return len;
}
-#endif
-int gator_events_armv6_install(gator_interface *gi) {
-#if defined(__arm__)
+static struct gator_interface gator_events_armv6_interface = {
+ .create_files = gator_events_armv6_create_files,
+ .stop = gator_events_armv6_stop,
+ .online = gator_events_armv6_online,
+ .offline = gator_events_armv6_offline,
+ .read = gator_events_armv6_read,
+};
+
+int gator_events_armv6_init(void)
+{
+ unsigned int cnt;
+
switch (gator_cpuid()) {
case ARM1136:
case ARM1156:
@@ -222,12 +213,12 @@ int gator_events_armv6_install(gator_interface *gi) {
return -1;
}
- gi->create_files = gator_events_armv6_create_files;
- gi->init = gator_events_armv6_init;
- gi->stop = gator_events_armv6_stop;
- gi->online = gator_events_armv6_online;
- gi->offline = gator_events_armv6_offline;
- gi->read = gator_events_armv6_read;
-#endif
- return 0;
+ for (cnt = PMN0; cnt <= CCNT; cnt++) {
+ pmnc_enabled[cnt] = 0;
+ pmnc_event[cnt] = 0;
+ pmnc_key[cnt] = gator_events_get_key();
+ }
+
+ return gator_events_install(&gator_events_armv6_interface);
}
+gator_events_init(gator_events_armv6_init);
diff --git a/driver/gator_events_armv7.c b/driver/gator_events_armv7.c
index 5a3268f..0f0d7ef 100644
--- a/driver/gator_events_armv7.c
+++ b/driver/gator_events_armv7.c
@@ -8,76 +8,22 @@
#include "gator.h"
-#if defined(__arm__)
-
+#define CORTEX_A5 0xc05
#define CORTEX_A8 0xc08
#define CORTEX_A9 0xc09
+#define CORTEX_A15 0xc0f
static const char *pmnc_name;
static int pmnc_count;
-extern u32 gator_cpuid(void);
-
-/*
- * Per-CPU PMNC: config reg
- */
+// Per-CPU PMNC: config reg
#define PMNC_E (1 << 0) /* Enable all counters */
#define PMNC_P (1 << 1) /* Reset all counters */
#define PMNC_C (1 << 2) /* Cycle counter reset */
-#define PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */
-#define PMNC_X (1 << 4) /* Export to ETM */
-#define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug*/
#define PMNC_MASK 0x3f /* Mask for writable bits */
-/*
- * CNTENS: counters enable reg
- */
-#define CNTENS_P0 (1 << 0)
-#define CNTENS_P1 (1 << 1)
-#define CNTENS_P2 (1 << 2)
-#define CNTENS_P3 (1 << 3)
-#define CNTENS_C (1 << 31)
-#define CNTENS_MASK 0x8000000f /* Mask for writable bits */
-
-/*
- * CNTENC: counters disable reg
- */
-#define CNTENC_P0 (1 << 0)
-#define CNTENC_P1 (1 << 1)
-#define CNTENC_P2 (1 << 2)
-#define CNTENC_P3 (1 << 3)
-#define CNTENC_C (1 << 31)
-#define CNTENC_MASK 0x8000000f /* Mask for writable bits */
-
-/*
- * INTENS: counters overflow interrupt enable reg
- */
-#define INTENS_P0 (1 << 0)
-#define INTENS_P1 (1 << 1)
-#define INTENS_P2 (1 << 2)
-#define INTENS_P3 (1 << 3)
-#define INTENS_C (1 << 31)
-#define INTENS_MASK 0x8000000f /* Mask for writable bits */
-
-/*
- * EVTSEL: Event selection reg
- */
-#define EVTSEL_MASK 0x7f /* Mask for writable bits */
-
-/*
- * SELECT: Counter selection reg
- */
-#define SELECT_MASK 0x1f /* Mask for writable bits */
-
-/*
- * FLAG: counters overflow flag status reg
- */
-#define FLAG_P0 (1 << 0)
-#define FLAG_P1 (1 << 1)
-#define FLAG_P2 (1 << 2)
-#define FLAG_P3 (1 << 3)
-#define FLAG_C (1 << 31)
-#define FLAG_MASK 0x8000000f /* Mask for writable bits */
+// ccnt reg
+#define CCNT_REG (1 << 31)
#define CCNT 0
#define CNT0 1
@@ -105,15 +51,31 @@ static inline u32 armv7_pmnc_read(void)
static inline u32 armv7_ccnt_read(void)
{
+ u32 zero = 0;
+ u32 den = CCNT_REG;
u32 val;
- asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
+
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable
+ asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); // read
+ asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (zero)); // zero
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable
+
return val;
}
-static inline u32 armv7_cntn_read(void)
+static inline u32 armv7_cntn_read(unsigned int cnt)
{
+ u32 zero = 0;
+ u32 sel = (cnt - CNT0);
+ u32 den = 1 << sel;
u32 val;
- asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
+
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (den)); // disable
+ asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (sel)); // select
+ asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); // read
+ asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (zero)); // zero
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable
+
return val;
}
@@ -127,11 +89,10 @@ static inline u32 armv7_pmnc_enable_counter(unsigned int cnt)
}
if (cnt == CCNT)
- val = CNTENS_C;
+ val = CCNT_REG;
else
val = (1 << (cnt - CNT0));
- val &= CNTENS_MASK;
asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
return cnt;
@@ -147,50 +108,15 @@ static inline u32 armv7_pmnc_disable_counter(unsigned int cnt)
}
if (cnt == CCNT)
- val = CNTENC_C;
+ val = CCNT_REG;
else
val = (1 << (cnt - CNT0));
- val &= CNTENC_MASK;
asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
return cnt;
}
-static inline u32 armv7_pmnc_enable_intens(unsigned int cnt)
-{
- u32 val;
-
- if (cnt >= CNTMAX) {
- pr_err("gator: CPU%u enabling wrong PMNC counter interrupt enable %d\n", smp_processor_id(), cnt);
- return -1;
- }
-
- if (cnt == CCNT)
- val = INTENS_C;
- else
- val = (1 << (cnt - CNT0));
-
- val &= INTENS_MASK;
- asm volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (val));
-
- return cnt;
-}
-
-static inline u32 armv7_pmnc_getreset_flags(void)
-{
- u32 val;
-
- /* Read */
- asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (val));
-
- /* Write to clear flags */
- val &= FLAG_MASK;
- asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (val));
-
- return val;
-}
-
static inline int armv7_pmnc_select_counter(unsigned int cnt)
{
u32 val;
@@ -200,7 +126,7 @@ static inline int armv7_pmnc_select_counter(unsigned int cnt)
return -1;
}
- val = (cnt - CNT0) & SELECT_MASK;
+ val = (cnt - CNT0);
asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
return cnt;
@@ -209,7 +135,6 @@ static inline int armv7_pmnc_select_counter(unsigned int cnt)
static inline void armv7_pmnc_write_evtsel(unsigned int cnt, u32 val)
{
if (armv7_pmnc_select_counter(cnt) == cnt) {
- val &= EVTSEL_MASK;
asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
}
}
@@ -265,66 +190,39 @@ static int gator_events_armv7_create_files(struct super_block *sb, struct dentry
return 0;
}
-static int gator_events_armv7_init(int *key)
-{
- unsigned int cnt;
-
- for (cnt = CCNT; cnt < CNTMAX; cnt++) {
- pmnc_enabled[cnt] = 0;
- pmnc_event[cnt] = 0;
- pmnc_key[cnt] = *key;
- *key = *key + 1;
- }
-
- return 0;
-}
-
static void gator_events_armv7_online(void)
{
unsigned int cnt;
+ int cpu = smp_processor_id();
if (armv7_pmnc_read() & PMNC_E) {
armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E);
}
- /* Initialize & Reset PMNC: C bit and P bit */
+ // Initialize & Reset PMNC: C bit and P bit
armv7_pmnc_write(PMNC_P | PMNC_C);
for (cnt = CCNT; cnt < CNTMAX; cnt++) {
unsigned long event;
- per_cpu(perfPrev, raw_smp_processor_id())[cnt] = 0;
+ per_cpu(perfPrev, cpu)[cnt] = 0;
if (!pmnc_enabled[cnt])
continue;
- /*
- * Disable counter
- */
+ // Disable counter
armv7_pmnc_disable_counter(cnt);
event = pmnc_event[cnt] & 255;
- /*
- * Set event (if destined for PMNx counters)
- * We don't need to set the event if it's a cycle count
- */
+ // Set event (if destined for PMNx counters), we don't need to set the event if it's a cycle count
if (cnt != CCNT)
armv7_pmnc_write_evtsel(cnt, event);
- /*
- * [Do not] Enable interrupt for this counter
- */
- /* armv7_pmnc_enable_intens(cnt); */
-
- /*
- * Reset counter
- */
+ // Reset counter
armv7_pmnc_reset_counter(cnt);
- /*
- * Enable counter
- */
+ // Enable counter, but do not enable interrupt for this counter
armv7_pmnc_enable_counter(cnt);
}
@@ -350,23 +248,19 @@ static void gator_events_armv7_stop(void)
static int gator_events_armv7_read(int **buffer)
{
int cnt, len = 0;
- int cpu = raw_smp_processor_id();
+ int cpu = smp_processor_id();
if (!pmnc_count)
return 0;
- armv7_pmnc_getreset_flags();
for (cnt = 0; cnt < pmnc_count; cnt++) {
if (pmnc_enabled[cnt]) {
int value;
if (cnt == CCNT) {
value = armv7_ccnt_read();
- } else if (armv7_pmnc_select_counter(cnt) == cnt) {
- value = armv7_cntn_read();
} else {
- value = 0;
+ value = armv7_cntn_read(cnt);
}
- armv7_pmnc_reset_counter(cnt);
if (value != per_cpu(perfPrev, cpu)[cnt]) {
per_cpu(perfPrev, cpu)[cnt] = value;
per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
@@ -381,11 +275,24 @@ static int gator_events_armv7_read(int **buffer)
return len;
}
-#endif
-int gator_events_armv7_install(gator_interface *gi) {
-#if defined(__arm__)
+static struct gator_interface gator_events_armv7_interface = {
+ .create_files = gator_events_armv7_create_files,
+ .stop = gator_events_armv7_stop,
+ .online = gator_events_armv7_online,
+ .offline = gator_events_armv7_offline,
+ .read = gator_events_armv7_read,
+};
+
+int gator_events_armv7_init(void)
+{
+ unsigned int cnt;
+
switch (gator_cpuid()) {
+ case CORTEX_A5:
+ pmnc_name = "Cortex-A5";
+ pmnc_count = 2;
+ break;
case CORTEX_A8:
pmnc_name = "Cortex-A8";
pmnc_count = 4;
@@ -394,18 +301,22 @@ int gator_events_armv7_install(gator_interface *gi) {
pmnc_name = "Cortex-A9";
pmnc_count = 6;
break;
+ case CORTEX_A15:
+ pmnc_name = "Cortex-A15";
+ pmnc_count = 6;
+ break;
default:
return -1;
}
pmnc_count++; // CNT[n] + CCNT
- gi->create_files = gator_events_armv7_create_files;
- gi->init = gator_events_armv7_init;
- gi->stop = gator_events_armv7_stop;
- gi->online = gator_events_armv7_online;
- gi->offline = gator_events_armv7_offline;
- gi->read = gator_events_armv7_read;
-#endif
- return 0;
+ for (cnt = CCNT; cnt < CNTMAX; cnt++) {
+ pmnc_enabled[cnt] = 0;
+ pmnc_event[cnt] = 0;
+ pmnc_key[cnt] = gator_events_get_key();
+ }
+
+ return gator_events_install(&gator_events_armv7_interface);
}
+gator_events_init(gator_events_armv7_init);
diff --git a/driver/gator_events_block.c b/driver/gator_events_block.c
index f32d8ef..cbfed86 100644
--- a/driver/gator_events_block.c
+++ b/driver/gator_events_block.c
@@ -33,7 +33,7 @@ GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct r
{
unsigned long flags;
int write, size;
- int cpu = raw_smp_processor_id();
+ int cpu = smp_processor_id();
if (!rq)
return;
@@ -79,19 +79,6 @@ static int gator_events_block_create_files(struct super_block *sb, struct dentry
return 0;
}
-static int gator_events_block_init(int *key)
-{
- block_rq_wr_enabled = 0;
- block_rq_rd_enabled = 0;
-
- block_rq_wr_key = *key;
- *key = *key + 1;
- block_rq_rd_key = *key;
- *key = *key + 1;
-
- return 0;
-}
-
static int gator_events_block_start(void)
{
int cpu;
@@ -128,7 +115,7 @@ static int gator_events_block_read(int **buffer)
{
unsigned long flags;
int len, value, cpu, data = 0;
- cpu = raw_smp_processor_id();
+ cpu = smp_processor_id();
if (per_cpu(new_data_avail, cpu) == false)
return 0;
@@ -164,11 +151,21 @@ static int gator_events_block_read(int **buffer)
return len;
}
-int gator_events_block_install(gator_interface *gi) {
- gi->create_files = gator_events_block_create_files;
- gi->init = gator_events_block_init;
- gi->start = gator_events_block_start;
- gi->stop = gator_events_block_stop;
- gi->read = gator_events_block_read;
- return 0;
+static struct gator_interface gator_events_block_interface = {
+ .create_files = gator_events_block_create_files,
+ .start = gator_events_block_start,
+ .stop = gator_events_block_stop,
+ .read = gator_events_block_read,
+};
+
+int gator_events_block_init(void)
+{
+ block_rq_wr_enabled = 0;
+ block_rq_rd_enabled = 0;
+
+ block_rq_wr_key = gator_events_get_key();
+ block_rq_rd_key = gator_events_get_key();
+
+ return gator_events_install(&gator_events_block_interface);
}
+gator_events_init(gator_events_block_init);
diff --git a/driver/gator_events_irq.c b/driver/gator_events_irq.c
index 7bbbd4b..36a6589 100644
--- a/driver/gator_events_irq.c
+++ b/driver/gator_events_irq.c
@@ -30,7 +30,7 @@ GATOR_DEFINE_PROBE(irq_handler_exit, TP_PROTO(int irq,
// disable interrupts to synchronize with gator_events_irq_read()
// spinlocks not needed since percpu buffers are used
local_irq_save(flags);
- per_cpu(irqCnt, raw_smp_processor_id())[HARDIRQ]++;
+ per_cpu(irqCnt, smp_processor_id())[HARDIRQ]++;
local_irq_restore(flags);
}
@@ -45,7 +45,7 @@ GATOR_DEFINE_PROBE(softirq_exit, TP_PROTO(unsigned int vec_nr))
// disable interrupts to synchronize with gator_events_irq_read()
// spinlocks not needed since percpu buffers are used
local_irq_save(flags);
- per_cpu(irqCnt, raw_smp_processor_id())[SOFTIRQ]++;
+ per_cpu(irqCnt, smp_processor_id())[SOFTIRQ]++;
local_irq_restore(flags);
}
@@ -72,19 +72,6 @@ static int gator_events_irq_create_files(struct super_block *sb, struct dentry *
return 0;
}
-static int gator_events_irq_init(int *key)
-{
- hardirq_key = *key;
- *key = *key + 1;
- softirq_key = *key;
- *key = *key + 1;
-
- hardirq_enabled = 0;
- softirq_enabled = 0;
-
- return 0;
-}
-
static int gator_events_irq_start(void)
{
int cpu, i;
@@ -131,7 +118,7 @@ static int gator_events_irq_read(int **buffer)
{
unsigned long flags;
int len, value;
- int cpu = raw_smp_processor_id();
+ int cpu = smp_processor_id();
len = 0;
if (hardirq_enabled) {
@@ -164,11 +151,21 @@ static int gator_events_irq_read(int **buffer)
return len;
}
-int gator_events_irq_install(gator_interface *gi) {
- gi->create_files = gator_events_irq_create_files;
- gi->init = gator_events_irq_init;
- gi->start = gator_events_irq_start;
- gi->stop = gator_events_irq_stop;
- gi->read = gator_events_irq_read;
- return 0;
+static struct gator_interface gator_events_irq_interface = {
+ .create_files = gator_events_irq_create_files,
+ .start = gator_events_irq_start,
+ .stop = gator_events_irq_stop,
+ .read = gator_events_irq_read,
+};
+
+int gator_events_irq_init(void)
+{
+ hardirq_key = gator_events_get_key();
+ softirq_key = gator_events_get_key();
+
+ hardirq_enabled = 0;
+ softirq_enabled = 0;
+
+ return gator_events_install(&gator_events_irq_interface);
}
+gator_events_init(gator_events_irq_init);
diff --git a/driver/gator_events_meminfo.c b/driver/gator_events_meminfo.c
index 1b576f8..f1595bd 100644
--- a/driver/gator_events_meminfo.c
+++ b/driver/gator_events_meminfo.c
@@ -69,20 +69,6 @@ static int gator_events_meminfo_create_files(struct super_block *sb, struct dent
return 0;
}
-static int gator_events_meminfo_init(int *key)
-{
- int i;
-
- meminfo_global_enabled = 0;
- for (i = 0; i < MEMINFO_TOTAL; i++) {
- meminfo_enabled[i] = 0;
- meminfo_key[i] = *key;
- *key = *key + 1;
- }
-
- return 0;
-}
-
static int gator_events_meminfo_start(void)
{
int i;
@@ -187,11 +173,23 @@ static int gator_events_meminfo_read(int **buffer)
return meminfo_length;
}
-int gator_events_meminfo_install(gator_interface *gi) {
- gi->create_files = gator_events_meminfo_create_files;
- gi->init = gator_events_meminfo_init;
- gi->start = gator_events_meminfo_start;
- gi->stop = gator_events_meminfo_stop;
- gi->read = gator_events_meminfo_read;
- return 0;
+static struct gator_interface gator_events_meminfo_interface = {
+ .create_files = gator_events_meminfo_create_files,
+ .start = gator_events_meminfo_start,
+ .stop = gator_events_meminfo_stop,
+ .read = gator_events_meminfo_read,
+};
+
+int gator_events_meminfo_init(void)
+{
+ int i;
+
+ meminfo_global_enabled = 0;
+ for (i = 0; i < MEMINFO_TOTAL; i++) {
+ meminfo_enabled[i] = 0;
+ meminfo_key[i] = gator_events_get_key();
+ }
+
+ return gator_events_install(&gator_events_meminfo_interface);
}
+gator_events_init(gator_events_meminfo_init);
diff --git a/driver/gator_events_mmaped.c b/driver/gator_events_mmaped.c
new file mode 100644
index 0000000..6884684
--- /dev/null
+++ b/driver/gator_events_mmaped.c
@@ -0,0 +1,196 @@
+/*
+ * Example events provider
+ *
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Similar entires must be present in events.xml file:
+ *
+ * <counter_set name="mmaped_cntX">
+ * <counter name="mmaped_cnt0"/>
+ * <counter name="mmaped_cnt1"/>
+ * </counter_set>
+ * <category name="mmaped" counter_set="mmaped_cntX" per_cpu="no">
+ * <event event="0x0" title="Simulated" name="Sine" description="Sort-of-sine"/>
+ * <event event="0x1" title="Simulated" name="Triangle" description="Triangular wave"/>
+ * <event event="0x2" title="Simulated" name="PWM" description="PWM Signal"/>
+ * </category>
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/ratelimit.h>
+
+#include "gator.h"
+
+#define MMAPED_COUNTERS_NUM 3
+
+static struct {
+ unsigned long enabled;
+ unsigned long event;
+ unsigned long key;
+} mmaped_counters[MMAPED_COUNTERS_NUM];
+
+static int mmaped_buffer[MMAPED_COUNTERS_NUM * 2];
+
+#ifdef TODO
+static void __iomem *mmaped_base;
+#endif
+
+/* Adds mmaped_cntX directories and enabled, event, and key files to /dev/gator/events */
+static int gator_events_mmaped_create_files(struct super_block *sb,
+ struct dentry *root)
+{
+ int i;
+
+ for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
+ char buf[16];
+ struct dentry *dir;
+
+ snprintf(buf, sizeof(buf), "mmaped_cnt%d", i);
+ dir = gatorfs_mkdir(sb, root, buf);
+ if (WARN_ON(!dir))
+ return -1;
+ gatorfs_create_ulong(sb, dir, "enabled",
+ &mmaped_counters[i].enabled);
+ gatorfs_create_ulong(sb, dir, "event",
+ &mmaped_counters[i].event);
+ gatorfs_create_ro_ulong(sb, dir, "key",
+ &mmaped_counters[i].key);
+ }
+
+ return 0;
+}
+
+static int gator_events_mmaped_start(void)
+{
+#ifdef TODO
+ for (i = 0; i < MMAPED_COUNTERS_NUM; i++)
+ writel(mmaped_counters[i].event,
+ mmaped_base + COUNTERS_CONFIG_OFFSET[i]);
+
+ writel(ENABLED, COUNTERS_CONTROL_OFFSET);
+#endif
+
+ return 0;
+}
+
+static void gator_events_mmaped_stop(void)
+{
+#ifdef TODO
+ writel(DISABLED, COUNTERS_CONTROL_OFFSET);
+#endif
+}
+
+#ifndef TODO
+/* This function "simulates" counters, generating values of fancy
+ * functions like sine or triangle... */
+static int mmaped_simulate(int counter)
+{
+ int result = 0;
+
+ switch (counter) {
+ case 0: /* sort-of-sine */
+ {
+ static int t;
+ int x;
+
+ if (t % 1024 < 512)
+ x = 512 - (t % 512);
+ else
+ x = t % 512;
+
+ result = 32 * x / 512;
+ result = result * result;
+
+ if (t < 1024)
+ result = 1922 - result;
+
+ t = (t + 1) % 2048;
+ }
+ break;
+ case 1: /* triangle */
+ {
+ static int v, d = 1;
+
+ v += d;
+ if (v % 2000 == 0)
+ d = -d;
+
+ result = v;
+ }
+ break;
+ case 2: /* PWM signal */
+ {
+ static int t, dc;
+
+ t = (t + 1) % 2000;
+ if (t % 100)
+ dc = (dc + 200) % 2000;
+
+ result = t < dc ? 0 : 2000;
+ }
+ break;
+ }
+
+ return result;
+}
+#endif
+
+static int gator_events_mmaped_read(int **buffer)
+{
+ int i;
+ int len = 0;
+
+ /* System wide counters - read from one core only */
+ if (smp_processor_id())
+ return 0;
+
+ for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
+ if (mmaped_counters[i].enabled) {
+ mmaped_buffer[len++] = mmaped_counters[i].key;
+#ifdef TODO
+ mmaped_buffer[len++] = readl(mmaped_base +
+ COUNTERS_VALUE_OFFSET[i]);
+#else
+ mmaped_buffer[len++] = mmaped_simulate(
+ mmaped_counters[i].event);
+#endif
+ }
+ }
+
+ if (buffer)
+ *buffer = mmaped_buffer;
+
+ return len;
+}
+
+static struct gator_interface gator_events_mmaped_interface = {
+ .create_files = gator_events_mmaped_create_files,
+ .start = gator_events_mmaped_start,
+ .stop = gator_events_mmaped_stop,
+ .read = gator_events_mmaped_read,
+};
+
+/* Must not be static! */
+int __init gator_events_mmaped_init(void)
+{
+ int i;
+
+#ifdef TODO
+ mmaped_base = ioremap(COUNTERS_PHYS_ADDR, SZ_4K);
+ if (!mmaped_base)
+ return -ENOMEM;
+#endif
+
+ for (i = 0; i < MMAPED_COUNTERS_NUM; i++) {
+ mmaped_counters[i].enabled = 0;
+ mmaped_counters[i].key = gator_events_get_key();
+ }
+
+ return gator_events_install(&gator_events_mmaped_interface);
+}
+gator_events_init(gator_events_mmaped_init);
diff --git a/driver/gator_events_net.c b/driver/gator_events_net.c
index 15a395e..a921586 100644
--- a/driver/gator_events_net.c
+++ b/driver/gator_events_net.c
@@ -101,22 +101,6 @@ static int gator_events_net_create_files(struct super_block *sb, struct dentry *
return 0;
}
-static int gator_events_net_init(int *key)
-{
- netdrv_key = *key;
- *key = *key + 1;
- netrx_key = *key;
- *key = *key + 1;
- nettx_key = *key;
- *key = *key + 1;
-
- netdrv_enabled = 0;
- netrx_enabled = 0;
- nettx_enabled = 0;
-
- return 0;
-}
-
static int gator_events_net_start(void)
{
get_network_stats(NULL);
@@ -138,7 +122,7 @@ static int gator_events_net_read(int **buffer)
int len, drv_delta, rx_delta, tx_delta;
static int last_drv_delta = 0, last_rx_delta = 0, last_tx_delta = 0;
- if (raw_smp_processor_id() != 0)
+ if (smp_processor_id() != 0)
return 0;
schedule_work(&wq_get_stats);
@@ -169,12 +153,25 @@ static int gator_events_net_read(int **buffer)
return len;
}
-int gator_events_net_install(gator_interface *gi) {
- gi->create_files = gator_events_net_create_files;
- gi->init = gator_events_net_init;
- gi->start = gator_events_net_start;
- gi->stop = gator_events_net_stop;
- gi->read = gator_events_net_read;
+static struct gator_interface gator_events_net_interface = {
+ .create_files = gator_events_net_create_files,
+ .start = gator_events_net_start,
+ .stop = gator_events_net_stop,
+ .read = gator_events_net_read,
+};
+
+int gator_events_net_init(void)
+{
gator_net_traffic++;
- return 0;
+
+ netdrv_key = gator_events_get_key();
+ netrx_key = gator_events_get_key();
+ nettx_key = gator_events_get_key();
+
+ netdrv_enabled = 0;
+ netrx_enabled = 0;
+ nettx_enabled = 0;
+
+ return gator_events_install(&gator_events_net_interface);
}
+gator_events_init(gator_events_net_init);
diff --git a/driver/gator_events_pl310.c b/driver/gator_events_pl310.c
new file mode 100644
index 0000000..0ef0cf3
--- /dev/null
+++ b/driver/gator_events_pl310.c
@@ -0,0 +1,176 @@
+/**
+ * PL310 (L2 Cache Controller) event counters for gator
+ *
+ * Copyright (C) ARM Limited 2010-2011. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include "gator.h"
+
+#define PL310_COUNTERS_NUM 2
+
+static struct {
+ unsigned long enabled;
+ unsigned long event;
+ unsigned long key;
+} pl310_counters[PL310_COUNTERS_NUM];
+
+static int pl310_buffer[PL310_COUNTERS_NUM * 2];
+
+static void __iomem *pl310_base;
+
+
+
+static void gator_events_pl310_reset_counters(void)
+{
+ u32 val = readl(pl310_base + L2X0_EVENT_CNT_CTRL);
+
+ val |= ((1 << PL310_COUNTERS_NUM) - 1) << 1;
+
+ writel(val, pl310_base + L2X0_EVENT_CNT_CTRL);
+}
+
+
+static int gator_events_pl310_create_files(struct super_block *sb,
+ struct dentry *root)
+{
+ int i;
+
+ for (i = 0; i < PL310_COUNTERS_NUM; i++) {
+ char buf[16];
+ struct dentry *dir;
+
+ snprintf(buf, sizeof(buf), "PL310_cnt%d", i);
+ dir = gatorfs_mkdir(sb, root, buf);
+ if (WARN_ON(!dir))
+ return -1;
+ gatorfs_create_ulong(sb, dir, "enabled",
+ &pl310_counters[i].enabled);
+ gatorfs_create_ulong(sb, dir, "event",
+ &pl310_counters[i].event);
+ gatorfs_create_ro_ulong(sb, dir, "key",
+ &pl310_counters[i].key);
+ }
+
+ return 0;
+}
+
+static int gator_events_pl310_start(void)
+{
+ static const unsigned long l2x0_event_cntx_cfg[PL310_COUNTERS_NUM] = {
+ L2X0_EVENT_CNT0_CFG,
+ L2X0_EVENT_CNT1_CFG,
+ };
+ int i;
+
+ /* Counter event sources */
+ for (i = 0; i < PL310_COUNTERS_NUM; i++)
+ writel((pl310_counters[i].event & 0xf) << 2,
+ pl310_base + l2x0_event_cntx_cfg[i]);
+
+ gator_events_pl310_reset_counters();
+
+ /* Event counter enable */
+ writel(1, pl310_base + L2X0_EVENT_CNT_CTRL);
+
+ return 0;
+}
+
+static void gator_events_pl310_stop(void)
+{
+ /* Event counter disable */
+ writel(0, pl310_base + L2X0_EVENT_CNT_CTRL);
+}
+
+static int gator_events_pl310_read(int **buffer)
+{
+ static const unsigned long l2x0_event_cntx_val[PL310_COUNTERS_NUM] = {
+ L2X0_EVENT_CNT0_VAL,
+ L2X0_EVENT_CNT1_VAL,
+ };
+ int i;
+ int len = 0;
+
+ if (smp_processor_id())
+ return 0;
+
+ for (i = 0; i < PL310_COUNTERS_NUM; i++) {
+ if (pl310_counters[i].enabled) {
+ pl310_buffer[len++] = pl310_counters[i].key;
+ pl310_buffer[len++] = readl(pl310_base +
+ l2x0_event_cntx_val[i]);
+ }
+ }
+
+ /* PL310 counters are saturating, not wrapping in case of overflow */
+ gator_events_pl310_reset_counters();
+
+ if (buffer)
+ *buffer = pl310_buffer;
+
+ return len;
+}
+
+static struct gator_interface gator_events_pl310_interface = {
+ .create_files = gator_events_pl310_create_files,
+ .start = gator_events_pl310_start,
+ .stop = gator_events_pl310_stop,
+ .read = gator_events_pl310_read,
+};
+
+static void __maybe_unused gator_events_pl310_probe(unsigned long phys)
+{
+ if (pl310_base)
+ return;
+
+ pl310_base = ioremap(phys, SZ_4K);
+ if (pl310_base) {
+ u32 cache_id = readl(pl310_base + L2X0_CACHE_ID);
+
+ if ((cache_id & 0xff0003c0) != 0x410000c0) {
+ iounmap(pl310_base);
+ pl310_base = NULL;
+ }
+ }
+}
+
+int gator_events_pl310_init(void)
+{
+ int i;
+
+#if defined(CONFIG_ARCH_EXYNOS4)
+ gator_events_pl310_probe(0xfe600000);
+#endif
+#if defined(CONFIG_ARCH_OMAP4)
+ gator_events_pl310_probe(0x48242000);
+#endif
+#if defined(CONFIG_ARCH_TEGRA)
+ gator_events_pl310_probe(0x50043000);
+#endif
+#if defined(CONFIG_ARCH_U8500)
+ gator_events_pl310_probe(0xa0412000);
+#endif
+#if defined(CONFIG_ARCH_VEXPRESS) && !defined(CONFIG_ARCH_VEXPRESS_CA15X4)
+ // A9x4 core tile (HBI-0191)
+ gator_events_pl310_probe(0x1e00a000);
+ // New memory map tiles
+ gator_events_pl310_probe(0x2c0f0000);
+#endif
+ if (!pl310_base)
+ return -1;
+
+ for (i = 0; i < PL310_COUNTERS_NUM; i++) {
+ pl310_counters[i].enabled = 0;
+ pl310_counters[i].key = gator_events_get_key();
+ }
+
+ return gator_events_install(&gator_events_pl310_interface);
+}
+gator_events_init(gator_events_pl310_init);
diff --git a/driver/gator_events_sched.c b/driver/gator_events_sched.c
index 138b7e4..7e9db60 100644
--- a/driver/gator_events_sched.c
+++ b/driver/gator_events_sched.c
@@ -29,7 +29,7 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_
// disable interrupts to synchronize with gator_events_sched_read()
// spinlocks not needed since percpu buffers are used
local_irq_save(flags);
- per_cpu(schedCnt, raw_smp_processor_id())[SCHED_SWITCH]++;
+ per_cpu(schedCnt, smp_processor_id())[SCHED_SWITCH]++;
local_irq_restore(flags);
}
@@ -48,16 +48,6 @@ static int gator_events_sched_create_files(struct super_block *sb, struct dentry
return 0;
}
-static int gator_events_sched_init(int *key)
-{
- sched_switch_enabled = 0;
-
- sched_switch_key = *key;
- *key = *key + 1;
-
- return 0;
-}
-
static int gator_events_sched_start(void)
{
// register tracepoints
@@ -88,7 +78,7 @@ static int gator_events_sched_read(int **buffer)
{
unsigned long flags;
int len, value;
- int cpu = raw_smp_processor_id();
+ int cpu = smp_processor_id();
len = 0;
if (sched_switch_enabled) {
@@ -106,11 +96,19 @@ static int gator_events_sched_read(int **buffer)
return len;
}
-int gator_events_sched_install(gator_interface *gi) {
- gi->create_files = gator_events_sched_create_files;
- gi->init = gator_events_sched_init;
- gi->start = gator_events_sched_start;
- gi->stop = gator_events_sched_stop;
- gi->read = gator_events_sched_read;
- return 0;
+static struct gator_interface gator_events_sched_interface = {
+ .create_files = gator_events_sched_create_files,
+ .start = gator_events_sched_start,
+ .stop = gator_events_sched_stop,
+ .read = gator_events_sched_read,
+};
+
+int gator_events_sched_init(void)
+{
+ sched_switch_enabled = 0;
+
+ sched_switch_key = gator_events_get_key();
+
+ return gator_events_install(&gator_events_sched_interface);
}
+gator_events_init(gator_events_sched_init);
diff --git a/driver/gator_events_scorpion.c b/driver/gator_events_scorpion.c
new file mode 100644
index 0000000..d831a50
--- /dev/null
+++ b/driver/gator_events_scorpion.c
@@ -0,0 +1,661 @@
+/**
+ * Copyright (C) ARM Limited 2011. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "gator.h"
+
+#define SCORPION 0xf
+#define SCORPIONMP 0x2d
+
+static const char *pmnc_name;
+static int pmnc_count;
+
+// Per-CPU PMNC: config reg
+#define PMNC_E (1 << 0) /* Enable all counters */
+#define PMNC_P (1 << 1) /* Reset all counters */
+#define PMNC_C (1 << 2) /* Cycle counter reset */
+#define PMNC_D (1 << 3) /* CCNT counts every 64th cpu cycle */
+#define PMNC_X (1 << 4) /* Export to ETM */
+#define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug*/
+#define PMNC_MASK 0x3f /* Mask for writable bits */
+
+// ccnt reg
+#define CCNT_REG (1 << 31)
+
+#define CCNT 0
+#define CNT0 1
+#define CNTMAX (4+1)
+
+static unsigned long pmnc_enabled[CNTMAX];
+static unsigned long pmnc_event[CNTMAX];
+static unsigned long pmnc_key[CNTMAX];
+
+static DEFINE_PER_CPU(int[CNTMAX], perfPrev);
+static DEFINE_PER_CPU(int[CNTMAX * 2], perfCnt);
+
+enum scorpion_perf_types {
+ SCORPION_ICACHE_EXPL_INV = 0x4c,
+ SCORPION_ICACHE_MISS = 0x4d,
+ SCORPION_ICACHE_ACCESS = 0x4e,
+ SCORPION_ICACHE_CACHEREQ_L2 = 0x4f,
+ SCORPION_ICACHE_NOCACHE_L2 = 0x50,
+ SCORPION_HIQUP_NOPED = 0x51,
+ SCORPION_DATA_ABORT = 0x52,
+ SCORPION_IRQ = 0x53,
+ SCORPION_FIQ = 0x54,
+ SCORPION_ALL_EXCPT = 0x55,
+ SCORPION_UNDEF = 0x56,
+ SCORPION_SVC = 0x57,
+ SCORPION_SMC = 0x58,
+ SCORPION_PREFETCH_ABORT = 0x59,
+ SCORPION_INDEX_CHECK = 0x5a,
+ SCORPION_NULL_CHECK = 0x5b,
+ SCORPION_EXPL_ICIALLU = 0x5c,
+ SCORPION_IMPL_ICIALLU = 0x5d,
+ SCORPION_NONICIALLU_BTAC_INV = 0x5e,
+ SCORPION_ICIMVAU_IMPL_ICIALLU = 0x5f,
+ SCORPION_SPIPE_ONLY_CYCLES = 0x60,
+ SCORPION_XPIPE_ONLY_CYCLES = 0x61,
+ SCORPION_DUAL_CYCLES = 0x62,
+ SCORPION_DISPATCH_ANY_CYCLES = 0x63,
+ SCORPION_FIFO_FULLBLK_CMT = 0x64,
+ SCORPION_FAIL_COND_INST = 0x65,
+ SCORPION_PASS_COND_INST = 0x66,
+ SCORPION_ALLOW_VU_CLK = 0x67,
+ SCORPION_VU_IDLE = 0x68,
+ SCORPION_ALLOW_L2_CLK = 0x69,
+ SCORPION_L2_IDLE = 0x6a,
+ SCORPION_DTLB_IMPL_INV_SCTLR_DACR = 0x6b,
+ SCORPION_DTLB_EXPL_INV = 0x6c,
+ SCORPION_DTLB_MISS = 0x6d,
+ SCORPION_DTLB_ACCESS = 0x6e,
+ SCORPION_ITLB_MISS = 0x6f,
+ SCORPION_ITLB_IMPL_INV = 0x70,
+ SCORPION_ITLB_EXPL_INV = 0x71,
+ SCORPION_UTLB_D_MISS = 0x72,
+ SCORPION_UTLB_D_ACCESS = 0x73,
+ SCORPION_UTLB_I_MISS = 0x74,
+ SCORPION_UTLB_I_ACCESS = 0x75,
+ SCORPION_UTLB_INV_ASID = 0x76,
+ SCORPION_UTLB_INV_MVA = 0x77,
+ SCORPION_UTLB_INV_ALL = 0x78,
+ SCORPION_S2_HOLD_RDQ_UNAVAIL = 0x79,
+ SCORPION_S2_HOLD = 0x7a,
+ SCORPION_S2_HOLD_DEV_OP = 0x7b,
+ SCORPION_S2_HOLD_ORDER = 0x7c,
+ SCORPION_S2_HOLD_BARRIER = 0x7d,
+ SCORPION_VIU_DUAL_CYCLE = 0x7e,
+ SCORPION_VIU_SINGLE_CYCLE = 0x7f,
+ SCORPION_VX_PIPE_WAR_STALL_CYCLES = 0x80,
+ SCORPION_VX_PIPE_WAW_STALL_CYCLES = 0x81,
+ SCORPION_VX_PIPE_RAW_STALL_CYCLES = 0x82,
+ SCORPION_VX_PIPE_LOAD_USE_STALL = 0x83,
+ SCORPION_VS_PIPE_WAR_STALL_CYCLES = 0x84,
+ SCORPION_VS_PIPE_WAW_STALL_CYCLES = 0x85,
+ SCORPION_VS_PIPE_RAW_STALL_CYCLES = 0x86,
+ SCORPION_EXCEPTIONS_INV_OPERATION = 0x87,
+ SCORPION_EXCEPTIONS_DIV_BY_ZERO = 0x88,
+ SCORPION_COND_INST_FAIL_VX_PIPE = 0x89,
+ SCORPION_COND_INST_FAIL_VS_PIPE = 0x8a,
+ SCORPION_EXCEPTIONS_OVERFLOW = 0x8b,
+ SCORPION_EXCEPTIONS_UNDERFLOW = 0x8c,
+ SCORPION_EXCEPTIONS_DENORM = 0x8d,
+#ifdef CONFIG_ARCH_MSM_SCORPIONMP
+ SCORPIONMP_NUM_BARRIERS = 0x8e,
+ SCORPIONMP_BARRIER_CYCLES = 0x8f,
+#else
+ SCORPION_BANK_AB_HIT = 0x8e,
+ SCORPION_BANK_AB_ACCESS = 0x8f,
+ SCORPION_BANK_CD_HIT = 0x90,
+ SCORPION_BANK_CD_ACCESS = 0x91,
+ SCORPION_BANK_AB_DSIDE_HIT = 0x92,
+ SCORPION_BANK_AB_DSIDE_ACCESS = 0x93,
+ SCORPION_BANK_CD_DSIDE_HIT = 0x94,
+ SCORPION_BANK_CD_DSIDE_ACCESS = 0x95,
+ SCORPION_BANK_AB_ISIDE_HIT = 0x96,
+ SCORPION_BANK_AB_ISIDE_ACCESS = 0x97,
+ SCORPION_BANK_CD_ISIDE_HIT = 0x98,
+ SCORPION_BANK_CD_ISIDE_ACCESS = 0x99,
+ SCORPION_ISIDE_RD_WAIT = 0x9a,
+ SCORPION_DSIDE_RD_WAIT = 0x9b,
+ SCORPION_BANK_BYPASS_WRITE = 0x9c,
+ SCORPION_BANK_AB_NON_CASTOUT = 0x9d,
+ SCORPION_BANK_AB_L2_CASTOUT = 0x9e,
+ SCORPION_BANK_CD_NON_CASTOUT = 0x9f,
+ SCORPION_BANK_CD_L2_CASTOUT = 0xa0,
+#endif
+ MSM_MAX_EVT
+};
+
+struct scorp_evt {
+ u32 evt_type;
+ u32 val;
+ u8 grp;
+ u32 evt_type_act;
+};
+
+static const struct scorp_evt sc_evt[] = {
+ {SCORPION_ICACHE_EXPL_INV, 0x80000500, 0, 0x4d},
+ {SCORPION_ICACHE_MISS, 0x80050000, 0, 0x4e},
+ {SCORPION_ICACHE_ACCESS, 0x85000000, 0, 0x4f},
+ {SCORPION_ICACHE_CACHEREQ_L2, 0x86000000, 0, 0x4f},
+ {SCORPION_ICACHE_NOCACHE_L2, 0x87000000, 0, 0x4f},
+ {SCORPION_HIQUP_NOPED, 0x80080000, 0, 0x4e},
+ {SCORPION_DATA_ABORT, 0x8000000a, 0, 0x4c},
+ {SCORPION_IRQ, 0x80000a00, 0, 0x4d},
+ {SCORPION_FIQ, 0x800a0000, 0, 0x4e},
+ {SCORPION_ALL_EXCPT, 0x8a000000, 0, 0x4f},
+ {SCORPION_UNDEF, 0x8000000b, 0, 0x4c},
+ {SCORPION_SVC, 0x80000b00, 0, 0x4d},
+ {SCORPION_SMC, 0x800b0000, 0, 0x4e},
+ {SCORPION_PREFETCH_ABORT, 0x8b000000, 0, 0x4f},
+ {SCORPION_INDEX_CHECK, 0x8000000c, 0, 0x4c},
+ {SCORPION_NULL_CHECK, 0x80000c00, 0, 0x4d},
+ {SCORPION_EXPL_ICIALLU, 0x8000000d, 0, 0x4c},
+ {SCORPION_IMPL_ICIALLU, 0x80000d00, 0, 0x4d},
+ {SCORPION_NONICIALLU_BTAC_INV, 0x800d0000, 0, 0x4e},
+ {SCORPION_ICIMVAU_IMPL_ICIALLU, 0x8d000000, 0, 0x4f},
+
+ {SCORPION_SPIPE_ONLY_CYCLES, 0x80000600, 1, 0x51},
+ {SCORPION_XPIPE_ONLY_CYCLES, 0x80060000, 1, 0x52},
+ {SCORPION_DUAL_CYCLES, 0x86000000, 1, 0x53},
+ {SCORPION_DISPATCH_ANY_CYCLES, 0x89000000, 1, 0x53},
+ {SCORPION_FIFO_FULLBLK_CMT, 0x8000000d, 1, 0x50},
+ {SCORPION_FAIL_COND_INST, 0x800d0000, 1, 0x52},
+ {SCORPION_PASS_COND_INST, 0x8d000000, 1, 0x53},
+ {SCORPION_ALLOW_VU_CLK, 0x8000000e, 1, 0x50},
+ {SCORPION_VU_IDLE, 0x80000e00, 1, 0x51},
+ {SCORPION_ALLOW_L2_CLK, 0x800e0000, 1, 0x52},
+ {SCORPION_L2_IDLE, 0x8e000000, 1, 0x53},
+
+ {SCORPION_DTLB_IMPL_INV_SCTLR_DACR, 0x80000001, 2, 0x54},
+ {SCORPION_DTLB_EXPL_INV, 0x80000100, 2, 0x55},
+ {SCORPION_DTLB_MISS, 0x80010000, 2, 0x56},
+ {SCORPION_DTLB_ACCESS, 0x81000000, 2, 0x57},
+ {SCORPION_ITLB_MISS, 0x80000200, 2, 0x55},
+ {SCORPION_ITLB_IMPL_INV, 0x80020000, 2, 0x56},
+ {SCORPION_ITLB_EXPL_INV, 0x82000000, 2, 0x57},
+ {SCORPION_UTLB_D_MISS, 0x80000003, 2, 0x54},
+ {SCORPION_UTLB_D_ACCESS, 0x80000300, 2, 0x55},
+ {SCORPION_UTLB_I_MISS, 0x80030000, 2, 0x56},
+ {SCORPION_UTLB_I_ACCESS, 0x83000000, 2, 0x57},
+ {SCORPION_UTLB_INV_ASID, 0x80000400, 2, 0x55},
+ {SCORPION_UTLB_INV_MVA, 0x80040000, 2, 0x56},
+ {SCORPION_UTLB_INV_ALL, 0x84000000, 2, 0x57},
+ {SCORPION_S2_HOLD_RDQ_UNAVAIL, 0x80000800, 2, 0x55},
+ {SCORPION_S2_HOLD, 0x88000000, 2, 0x57},
+ {SCORPION_S2_HOLD_DEV_OP, 0x80000900, 2, 0x55},
+ {SCORPION_S2_HOLD_ORDER, 0x80090000, 2, 0x56},
+ {SCORPION_S2_HOLD_BARRIER, 0x89000000, 2, 0x57},
+
+ {SCORPION_VIU_DUAL_CYCLE, 0x80000001, 4, 0x5c},
+ {SCORPION_VIU_SINGLE_CYCLE, 0x80000100, 4, 0x5d},
+ {SCORPION_VX_PIPE_WAR_STALL_CYCLES, 0x80000005, 4, 0x5c},
+ {SCORPION_VX_PIPE_WAW_STALL_CYCLES, 0x80000500, 4, 0x5d},
+ {SCORPION_VX_PIPE_RAW_STALL_CYCLES, 0x80050000, 4, 0x5e},
+ {SCORPION_VX_PIPE_LOAD_USE_STALL, 0x80000007, 4, 0x5c},
+ {SCORPION_VS_PIPE_WAR_STALL_CYCLES, 0x80000008, 4, 0x5c},
+ {SCORPION_VS_PIPE_WAW_STALL_CYCLES, 0x80000800, 4, 0x5d},
+ {SCORPION_VS_PIPE_RAW_STALL_CYCLES, 0x80080000, 4, 0x5e},
+ {SCORPION_EXCEPTIONS_INV_OPERATION, 0x8000000b, 4, 0x5c},
+ {SCORPION_EXCEPTIONS_DIV_BY_ZERO, 0x80000b00, 4, 0x5d},
+ {SCORPION_COND_INST_FAIL_VX_PIPE, 0x800b0000, 4, 0x5e},
+ {SCORPION_COND_INST_FAIL_VS_PIPE, 0x8b000000, 4, 0x5f},
+ {SCORPION_EXCEPTIONS_OVERFLOW, 0x8000000c, 4, 0x5c},
+ {SCORPION_EXCEPTIONS_UNDERFLOW, 0x80000c00, 4, 0x5d},
+ {SCORPION_EXCEPTIONS_DENORM, 0x8c000000, 4, 0x5f},
+
+ {SCORPION_BANK_AB_HIT, 0x80000001, 3, 0x58},
+ {SCORPION_BANK_AB_ACCESS, 0x80000100, 3, 0x59},
+ {SCORPION_BANK_CD_HIT, 0x80010000, 3, 0x5a},
+ {SCORPION_BANK_CD_ACCESS, 0x81000000, 3, 0x5b},
+ {SCORPION_BANK_AB_DSIDE_HIT, 0x80000002, 3, 0x58},
+ {SCORPION_BANK_AB_DSIDE_ACCESS, 0x80000200, 3, 0x59},
+ {SCORPION_BANK_CD_DSIDE_HIT, 0x80020000, 3, 0x5a},
+ {SCORPION_BANK_CD_DSIDE_ACCESS, 0x82000000, 3, 0x5b},
+ {SCORPION_BANK_AB_ISIDE_HIT, 0x80000003, 3, 0x58},
+ {SCORPION_BANK_AB_ISIDE_ACCESS, 0x80000300, 3, 0x59},
+ {SCORPION_BANK_CD_ISIDE_HIT, 0x80030000, 3, 0x5a},
+ {SCORPION_BANK_CD_ISIDE_ACCESS, 0x83000000, 3, 0x5b},
+ {SCORPION_ISIDE_RD_WAIT, 0x80000009, 3, 0x58},
+ {SCORPION_DSIDE_RD_WAIT, 0x80090000, 3, 0x5a},
+ {SCORPION_BANK_BYPASS_WRITE, 0x8000000a, 3, 0x58},
+ {SCORPION_BANK_AB_NON_CASTOUT, 0x8000000c, 3, 0x58},
+ {SCORPION_BANK_AB_L2_CASTOUT, 0x80000c00, 3, 0x59},
+ {SCORPION_BANK_CD_NON_CASTOUT, 0x800c0000, 3, 0x5a},
+ {SCORPION_BANK_CD_L2_CASTOUT, 0x8c000000, 3, 0x5b},
+};
+
+static inline void scorpion_pmnc_write(u32 val)
+{
+ val &= PMNC_MASK;
+ asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r" (val));
+}
+
+static inline u32 scorpion_pmnc_read(void)
+{
+ u32 val;
+ asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val));
+ return val;
+}
+
+static inline u32 scorpion_ccnt_read(void)
+{
+ u32 val;
+ asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val));
+ return val;
+}
+
+static inline u32 scorpion_cntn_read(void)
+{
+ u32 val;
+ asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val));
+ return val;
+}
+
+static inline u32 scorpion_pmnc_enable_counter(unsigned int cnt)
+{
+ u32 val;
+
+ if (cnt >= CNTMAX) {
+ pr_err("gator: CPU%u enabling wrong PMNC counter %d\n", smp_processor_id(), cnt);
+ return -1;
+ }
+
+ if (cnt == CCNT)
+ val = CCNT_REG;
+ else
+ val = (1 << (cnt - CNT0));
+
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val));
+
+ return cnt;
+}
+
+static inline u32 scorpion_pmnc_disable_counter(unsigned int cnt)
+{
+ u32 val;
+
+ if (cnt >= CNTMAX) {
+ pr_err("gator: CPU%u disabling wrong PMNC counter %d\n", smp_processor_id(), cnt);
+ return -1;
+ }
+
+ if (cnt == CCNT)
+ val = CCNT_REG;
+ else
+ val = (1 << (cnt - CNT0));
+
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val));
+
+ return cnt;
+}
+
+static inline int scorpion_pmnc_select_counter(unsigned int cnt)
+{
+ u32 val;
+
+ if ((cnt == CCNT) || (cnt >= CNTMAX)) {
+ pr_err("gator: CPU%u selecting wrong PMNC counter %d\n", smp_processor_id(), cnt);
+ return -1;
+ }
+
+ val = (cnt - CNT0);
+ asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
+
+ return cnt;
+}
+
+static u32 scorpion_read_lpm0(void)
+{
+ u32 val;
+ asm volatile("mrc p15, 0, %0, c15, c0, 0" : "=r" (val));
+ return val;
+}
+
+static void scorpion_write_lpm0(u32 val)
+{
+ asm volatile("mcr p15, 0, %0, c15, c0, 0" : : "r" (val));
+}
+
+static u32 scorpion_read_lpm1(void)
+{
+ u32 val;
+ asm volatile("mrc p15, 1, %0, c15, c0, 0" : "=r" (val));
+ return val;
+}
+
+static void scorpion_write_lpm1(u32 val)
+{
+ asm volatile("mcr p15, 1, %0, c15, c0, 0" : : "r" (val));
+}
+
+static u32 scorpion_read_lpm2(void)
+{
+ u32 val;
+ asm volatile("mrc p15, 2, %0, c15, c0, 0" : "=r" (val));
+ return val;
+}
+
+static void scorpion_write_lpm2(u32 val)
+{
+ asm volatile("mcr p15, 2, %0, c15, c0, 0" : : "r" (val));
+}
+
+static u32 scorpion_read_l2lpm(void)
+{
+ u32 val;
+ asm volatile("mrc p15, 3, %0, c15, c2, 0" : "=r" (val));
+ return val;
+}
+
+static void scorpion_write_l2lpm(u32 val)
+{
+ asm volatile("mcr p15, 3, %0, c15, c2, 0" : : "r" (val));
+}
+
+static u32 scorpion_read_vlpm(void)
+{
+ u32 val;
+ asm volatile("mrc p10, 7, %0, c11, c0, 0" : "=r" (val));
+ return val;
+}
+
+static void scorpion_write_vlpm(u32 val)
+{
+ asm volatile("mcr p10, 7, %0, c11, c0, 0" : : "r" (val));
+}
+
+struct scorpion_access_funcs {
+ u32 (*read) (void);
+ void (*write) (u32);
+};
+
+struct scorpion_access_funcs scor_func[] = {
+ {scorpion_read_lpm0, scorpion_write_lpm0},
+ {scorpion_read_lpm1, scorpion_write_lpm1},
+ {scorpion_read_lpm2, scorpion_write_lpm2},
+ {scorpion_read_l2lpm, scorpion_write_l2lpm},
+ {scorpion_read_vlpm, scorpion_write_vlpm},
+};
+
+u32 venum_orig_val;
+u32 fp_orig_val;
+
+static void scorpion_pre_vlpm(void)
+{
+ u32 venum_new_val;
+ u32 fp_new_val;
+
+ /* CPACR Enable CP10 access*/
+ asm volatile("mrc p15, 0, %0, c1, c0, 2" : "=r" (venum_orig_val));
+ venum_new_val = venum_orig_val | 0x00300000;
+ asm volatile("mcr p15, 0, %0, c1, c0, 2" : : "r" (venum_new_val));
+ /* Enable FPEXC */
+ asm volatile("mrc p10, 7, %0, c8, c0, 0" : "=r" (fp_orig_val));
+ fp_new_val = fp_orig_val | 0x40000000;
+ asm volatile("mcr p10, 7, %0, c8, c0, 0" : : "r" (fp_new_val));
+}
+
+static void scorpion_post_vlpm(void)
+{
+ /* Restore FPEXC*/
+ asm volatile("mcr p10, 7, %0, c8, c0, 0" : : "r" (fp_orig_val));
+ /* Restore CPACR*/
+ asm volatile("mcr p15, 0, %0, c1, c0, 2" : : "r" (venum_orig_val));
+}
+
+#define COLMN0MASK 0x000000ff
+#define COLMN1MASK 0x0000ff00
+#define COLMN2MASK 0x00ff0000
+static u32 scorpion_get_columnmask(u32 setval)
+{
+ if (setval & COLMN0MASK)
+ return 0xffffff00;
+ else if (setval & COLMN1MASK)
+ return 0xffff00ff;
+ else if (setval & COLMN2MASK)
+ return 0xff00ffff;
+ else
+ return 0x80ffffff;
+}
+
+static void scorpion_evt_setup(u32 gr, u32 setval)
+{
+ u32 val;
+ if (gr == 4)
+ scorpion_pre_vlpm();
+ val = scorpion_get_columnmask(setval) & scor_func[gr].read();
+ val = val | setval;
+ scor_func[gr].write(val);
+ if (gr == 4)
+ scorpion_post_vlpm();
+}
+
+static int get_scorpion_evtinfo(unsigned int evt_type, struct scorp_evt *evtinfo)
+{
+ u32 idx;
+ if ((evt_type < 0x4c) || (evt_type >= MSM_MAX_EVT))
+ return 0;
+ idx = evt_type - 0x4c;
+ if (sc_evt[idx].evt_type == evt_type) {
+ evtinfo->val = sc_evt[idx].val;
+ evtinfo->grp = sc_evt[idx].grp;
+ evtinfo->evt_type_act = sc_evt[idx].evt_type_act;
+ return 1;
+ }
+ return 0;
+}
+
+static inline void scorpion_pmnc_write_evtsel(unsigned int cnt, u32 val)
+{
+ if (scorpion_pmnc_select_counter(cnt) == cnt) {
+ if (val < 0x40) {
+ asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val));
+ } else {
+ u32 zero = 0;
+ struct scorp_evt evtinfo;
+ // extract evtinfo.grp and evtinfo.tevt_type_act from val
+ if (get_scorpion_evtinfo(val, &evtinfo) == 0) return;
+ asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (evtinfo.evt_type_act));
+ asm volatile("mcr p15, 0, %0, c9, c15, 0" : : "r" (zero));
+ scorpion_evt_setup(evtinfo.grp, val);
+ }
+ }
+}
+
+static void scorpion_pmnc_reset_counter(unsigned int cnt)
+{
+ u32 val = 0;
+
+ if (cnt == CCNT) {
+ scorpion_pmnc_disable_counter(cnt);
+
+ asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (val));
+
+ if (pmnc_enabled[cnt] != 0)
+ scorpion_pmnc_enable_counter(cnt);
+
+ } else if (cnt >= CNTMAX) {
+ pr_err("gator: CPU%u resetting wrong PMNC counter %d\n", smp_processor_id(), cnt);
+ } else {
+ scorpion_pmnc_disable_counter(cnt);
+
+ if (scorpion_pmnc_select_counter(cnt) == cnt)
+ asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (val));
+
+ if (pmnc_enabled[cnt] != 0)
+ scorpion_pmnc_enable_counter(cnt);
+ }
+}
+
+static int gator_events_scorpion_create_files(struct super_block *sb, struct dentry *root)
+{
+ struct dentry *dir;
+ int i;
+
+ for (i = 0; i < pmnc_count; i++) {
+ char buf[40];
+ if (i == 0) {
+ snprintf(buf, sizeof buf, "%s_ccnt", pmnc_name);
+ } else {
+ snprintf(buf, sizeof buf, "%s_cnt%d", pmnc_name, i-1);
+ }
+ dir = gatorfs_mkdir(sb, root, buf);
+ if (!dir) {
+ return -1;
+ }
+ gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]);
+ if (i > 0) {
+ gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]);
+ }
+ gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]);
+ }
+
+ return 0;
+}
+
+static void gator_events_scorpion_online(void)
+{
+ unsigned int cnt;
+
+ if (scorpion_pmnc_read() & PMNC_E) {
+ scorpion_pmnc_write(scorpion_pmnc_read() & ~PMNC_E);
+ }
+
+ /* Initialize & Reset PMNC: C bit and P bit */
+ scorpion_pmnc_write(PMNC_P | PMNC_C);
+
+ for (cnt = CCNT; cnt < CNTMAX; cnt++) {
+ unsigned long event;
+
+ per_cpu(perfPrev, smp_processor_id())[cnt] = 0;
+
+ if (!pmnc_enabled[cnt])
+ continue;
+
+ // disable counter
+ scorpion_pmnc_disable_counter(cnt);
+
+ event = pmnc_event[cnt] & 255;
+
+ // Set event (if destined for PMNx counters), We don't need to set the event if it's a cycle count
+ if (cnt != CCNT)
+ scorpion_pmnc_write_evtsel(cnt, event);
+
+ // reset counter
+ scorpion_pmnc_reset_counter(cnt);
+
+ // Enable counter, do not enable interrupt for this counter
+ scorpion_pmnc_enable_counter(cnt);
+ }
+
+ // enable
+ scorpion_pmnc_write(scorpion_pmnc_read() | PMNC_E);
+}
+
+static void gator_events_scorpion_offline(void)
+{
+ scorpion_pmnc_write(scorpion_pmnc_read() & ~PMNC_E);
+
+ // investigate: need to do the clearpmu() here on each counter?
+}
+
+static void gator_events_scorpion_stop(void)
+{
+ unsigned int cnt;
+
+ for (cnt = CCNT; cnt < CNTMAX; cnt++) {
+ pmnc_enabled[cnt] = 0;
+ pmnc_event[cnt] = 0;
+ }
+}
+
+static int gator_events_scorpion_read(int **buffer)
+{
+ int cnt, len = 0;
+ int cpu = smp_processor_id();
+
+ if (!pmnc_count)
+ return 0;
+
+ for (cnt = 0; cnt < pmnc_count; cnt++) {
+ if (pmnc_enabled[cnt]) {
+ int value;
+ if (cnt == CCNT) {
+ value = scorpion_ccnt_read();
+ } else if (scorpion_pmnc_select_counter(cnt) == cnt) {
+ value = scorpion_cntn_read();
+ } else {
+ value = 0;
+ }
+ scorpion_pmnc_reset_counter(cnt);
+ if (value != per_cpu(perfPrev, cpu)[cnt]) {
+ per_cpu(perfPrev, cpu)[cnt] = value;
+ per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt];
+ per_cpu(perfCnt, cpu)[len++] = value;
+ }
+ }
+ }
+
+ // update or discard
+ if (buffer)
+ *buffer = per_cpu(perfCnt, cpu);
+
+ return len;
+}
+
+static struct gator_interface gator_events_scorpion_interface = {
+ .create_files = gator_events_scorpion_create_files,
+ .stop = gator_events_scorpion_stop,
+ .online = gator_events_scorpion_online,
+ .offline = gator_events_scorpion_offline,
+ .read = gator_events_scorpion_read,
+};
+
+
+static void scorpion_clear_pmuregs(void)
+{
+ scorpion_write_lpm0(0);
+ scorpion_write_lpm1(0);
+ scorpion_write_lpm2(0);
+ scorpion_write_l2lpm(0);
+ scorpion_pre_vlpm();
+ scorpion_write_vlpm(0);
+ scorpion_post_vlpm();
+}
+
+int gator_events_scorpion_init(void)
+{
+ unsigned int cnt;
+
+ switch (gator_cpuid()) {
+ case SCORPION:
+ pmnc_name = "Scorpion";
+ pmnc_count = 4;
+ break;
+ case SCORPIONMP:
+ pmnc_name = "ScorpionMP";
+ pmnc_count = 4;
+ break;
+ default:
+ return -1;
+ }
+
+ pmnc_count++; // CNT[n] + CCNT
+
+ for (cnt = CCNT; cnt < CNTMAX; cnt++) {
+ pmnc_enabled[cnt] = 0;
+ pmnc_event[cnt] = 0;
+ pmnc_key[cnt] = gator_events_get_key();
+ }
+
+ scorpion_clear_pmuregs();
+
+ return gator_events_install(&gator_events_scorpion_interface);
+}
+gator_events_init(gator_events_scorpion_init);
diff --git a/driver/gator_fs.c b/driver/gator_fs.c
index f7cbff2..8277c3a 100644
--- a/driver/gator_fs.c
+++ b/driver/gator_fs.c
@@ -20,8 +20,6 @@
#define TMPBUFSIZE 50
DEFINE_SPINLOCK(gatorfs_lock);
-void gator_op_create_files(struct super_block *sb, struct dentry *root);
-
static struct inode *gatorfs_get_inode(struct super_block *sb, int mode)
{
struct inode *inode = new_inode(sb);
diff --git a/driver/gator_main.c b/driver/gator_main.c
index a1ab776..340756e 100644
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
@@ -7,9 +7,8 @@
*
*/
-static unsigned long gator_protocol_version = 4;
+static unsigned long gator_protocol_version = 5;
-#include "gator.h"
#include <linux/slab.h>
#include <linux/cpu.h>
#include <linux/sched.h>
@@ -20,23 +19,26 @@ static unsigned long gator_protocol_version = 4;
#include <linux/pagemap.h>
#include <asm/uaccess.h>
+#include "gator.h"
+#include "gator_events.h"
+
#ifndef CONFIG_GENERIC_TRACER
#ifndef CONFIG_TRACING
-#warning gator requires the kernel to have CONFIG_GENERIC_TRACER or CONFIG_TRACING defined
+#error gator requires the kernel to have CONFIG_GENERIC_TRACER or CONFIG_TRACING defined
#endif
#endif
#ifndef CONFIG_PROFILING
-#warning gator requires the kernel to have CONFIG_PROFILING defined
+#error gator requires the kernel to have CONFIG_PROFILING defined
#endif
#ifndef CONFIG_HIGH_RES_TIMERS
-#warning gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined
+#error gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined
#endif
#ifdef CONFIG_SMP
#ifndef CONFIG_LOCAL_TIMERS
-#warning gator requires the kernel to have CONFIG_LOCAL_TIMERS defined on SMP systems
+#error gator requires the kernel to have CONFIG_LOCAL_TIMERS defined on SMP systems
#endif
#endif
@@ -80,7 +82,7 @@ static unsigned long gator_backtrace_depth;
static unsigned long gator_started;
static unsigned long gator_buffer_opened;
static unsigned long gator_timer_count;
-static unsigned long gator_sync_freq;
+static unsigned long gator_streaming;
static int gator_master_tick;
static DEFINE_MUTEX(start_mutex);
static DEFINE_MUTEX(gator_buffer_mutex);
@@ -104,6 +106,7 @@ static DEFINE_PER_CPU(int, gator_first_time);
******************************************************************************/
static void gator_buffer_write_packed_int(int cpu, unsigned int x);
static void gator_buffer_write_string(int cpu, char *x);
+static int gator_write_packed_int(char *buffer, unsigned int x);
static void gator_add_trace(int cpu, unsigned int address);
static uint64_t gator_get_time(void);
@@ -114,7 +117,6 @@ static uint64_t gator_get_time(void);
#include "gator_trace_sched.c"
#include "gator_backtrace.c"
#include "gator_annotate.c"
-#include "gator_events.c"
#include "gator_fs.c"
/******************************************************************************
@@ -204,6 +206,36 @@ static void gator_buffer_write_packed_int(int cpu, unsigned int x)
}
}
+static int gator_write_packed_int(char *buffer, unsigned int x)
+{
+ if ((x & 0xffffff80) == 0) {
+ buffer[0] = x & 0x7f;
+ return 1;
+ } else if ((x & 0xffffc000) == 0) {
+ buffer[0] = x | 0x80;
+ buffer[1] = (x>>7) & 0x7f;
+ return 2;
+ } else if ((x & 0xffe00000) == 0) {
+ buffer[0] = x | 0x80;
+ buffer[1] = (x>>7) | 0x80;
+ buffer[2] = (x>>14) & 0x7f;
+ return 3;
+ } else if ((x & 0xf0000000) == 0) {
+ buffer[0] = x | 0x80;
+ buffer[1] = (x>>7) | 0x80;
+ buffer[2] = (x>>14) | 0x80;
+ buffer[3] = (x>>21) & 0x7f;
+ return 4;
+ } else {
+ buffer[0] = x | 0x80;
+ buffer[1] = (x>>7) | 0x80;
+ buffer[2] = (x>>14) | 0x80;
+ buffer[3] = (x>>21) | 0x80;
+ buffer[4] = (x>>28) & 0x0f;
+ return 5;
+ }
+}
+
static void gator_buffer_write_bytes(int cpu, char *x, int len)
{
uint32_t write = per_cpu(use_buffer_write, cpu);
@@ -244,7 +276,7 @@ static void gator_buffer_commit(int cpu)
static void gator_buffer_check(int cpu, int tick)
{
- if (gator_sync_freq && !(tick % gator_sync_freq)) {
+ if (!(tick % gator_timer_count)) {
int c, sync;
spin_lock(&gator_commit_lock);
// synchronize, if all online cpus have the same tick waypoint
@@ -258,7 +290,6 @@ static void gator_buffer_check(int cpu, int tick)
if (sync) {
gator_buffer_write_packed_int(cpu, PROTOCOL_CPU_SYNC);
}
- // commit the buffer
gator_buffer_commit(cpu);
spin_unlock(&gator_commit_lock);
} else {
@@ -336,46 +367,27 @@ static void gator_write_packet(int cpu, int type, int len, int *buffer)
}
}
-static void gator_write_annotate(int cpu, int len, int *buffer)
-{
- int pos = 0;
-
- while (pos < len) {
- unsigned int tid = buffer[pos++];
- unsigned int bytes = buffer[pos++];
- unsigned int words = (bytes + 3) / 4;
- char *ptr = (char *)&buffer[pos];
- pos += words;
-
- gator_buffer_write_packed_int(cpu, PROTOCOL_ANNOTATE);
- gator_buffer_write_packed_int(cpu, tid);
- gator_buffer_write_packed_int(cpu, bytes);
- gator_buffer_write_bytes(cpu, ptr, bytes);
- }
-}
-
/******************************************************************************
* Interrupt Processing
******************************************************************************/
-static gator_interface *gi = NULL;
+static LIST_HEAD(gator_events);
static void gator_timer_interrupt(void)
{
struct pt_regs * const regs = get_irq_regs();
- int cpu = raw_smp_processor_id();
+ int cpu = smp_processor_id();
int *buffer, len, tick;
- gator_interface *i;
+ struct gator_interface *gi;
// check full backtrace has enough space, otherwise may
// have breaks between samples in the same callstack
if (per_cpu(gator_first_time, cpu)) {
per_cpu(gator_first_time, cpu) = 0;
- for (i = gi; i != NULL; i = i->next) {
- if (i->read) {
- i->read(NULL);
- }
- }
+ list_for_each_entry(gi, &gator_events, list)
+ if (gi->read)
+ gi->read(NULL);
+
return;
}
@@ -388,18 +400,12 @@ static void gator_timer_interrupt(void)
gator_write_packet(cpu, PROTOCOL_SCHEDULER_TRACE, len, buffer);
}
- // Output annotate
- len = gator_annotate_read(&buffer);
- if (len > 0)
- gator_write_annotate(cpu, len, buffer);
-
// Output counters
- for (i = gi; i != NULL; i = i->next) {
- if (i->read) {
- len = i->read(&buffer);
- if (len > 0) {
+ list_for_each_entry(gi, &gator_events, list) {
+ if (gi->read) {
+ len = gi->read(&buffer);
+ if (len > 0)
gator_write_packet(cpu, PROTOCOL_COUNTERS, len, buffer);
- }
}
}
@@ -444,18 +450,16 @@ static void __gator_timer_offline(void *unused)
{
int cpu = smp_processor_id();
if (per_cpu(hrtimer_is_active, cpu)) {
- gator_interface *i;
+ struct gator_interface *gi;
struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, cpu);
hrtimer_cancel(hrtimer);
per_cpu(hrtimer_is_active, cpu) = 0;
gator_buffer_commit(cpu);
// offline any events
- for (i = gi; i != NULL; i = i->next) {
- if (i->offline) {
- i->offline();
- }
- }
+ list_for_each_entry(gi, &gator_events, list)
+ if (gi->offline)
+ gi->offline();
}
}
@@ -476,7 +480,7 @@ static void __gator_timer_online(void *unused)
{
int cpu = smp_processor_id();
if (!per_cpu(hrtimer_is_active, cpu)) {
- gator_interface *i;
+ struct gator_interface *gi;
struct hrtimer *hrtimer = &per_cpu(percpu_hrtimer, cpu);
hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
hrtimer->function = gator_hrtimer_notify;
@@ -486,11 +490,9 @@ static void __gator_timer_online(void *unused)
per_cpu(hrtimer_is_active, cpu) = 1;
// online any events
- for (i = gi; i != NULL; i = i->next) {
- if (i->online) {
- i->online();
- }
- }
+ list_for_each_entry(gi, &gator_events, list)
+ if (gi->online)
+ gi->online();
}
}
@@ -566,46 +568,23 @@ static void gator_notifier_stop(void)
/******************************************************************************
* Main
******************************************************************************/
-int gator_event_install(int (*event_install)(gator_interface *))
+int gator_events_install(struct gator_interface *interface)
{
- gator_interface *ni = (gator_interface*)kmalloc(sizeof(gator_interface), GFP_KERNEL);
- if (ni == NULL) {
- return -1;
- }
-
- ni->create_files = NULL;
- ni->init = NULL;
- ni->start = NULL;
- ni->stop = NULL;
- ni->online = NULL;
- ni->offline = NULL;
- ni->read = NULL;
- ni->next = NULL;
-
- // Initialize ni gator interface
- if (!event_install(ni)) {
- if (gi == NULL) {
- // Set gi to point to the first gator interface
- gi = ni;
- } else {
- // Link the gator interfaces
- gator_interface *i = gi;
- while (i->next) {
- i = i->next;
- }
- i->next = ni;
- }
- } else {
- kfree(ni);
- }
+ list_add_tail(&interface->list, &gator_events);
return 0;
}
+int gator_events_get_key(void)
+{
+ static int key;
+
+ return key++;
+}
+
static int gator_init(void)
{
- gator_interface *i;
- int key = 0;
+ int i;
if (gator_timer_init())
return -1;
@@ -614,32 +593,33 @@ static int gator_init(void)
if (gator_annotate_init())
return -1;
- // set up gator interface linked list structure
- if (gator_events_install())
- return -1;
-
- // initialize all events
- for (i = gi; i != NULL; i = i->next) {
- if (i->init) {
- if (i->init(&key)) {
- return -1;
- }
- }
- }
+ // events sources (gator_events.h, generated by gator_events.sh)
+ for (i = 0; i < ARRAY_SIZE(gator_events_list); i++)
+ if (gator_events_list[i])
+ gator_events_list[i]();
return 0;
}
static int gator_start(void)
{
- gator_interface *i, *f;
+ struct gator_interface *gi;
// start all events
- for (i = gi; i != NULL; i = i->next) {
- if (i->start) {
- if (i->start()) {
- goto events_failure;
+ list_for_each_entry(gi, &gator_events, list) {
+ if (gi->start && gi->start() != 0) {
+ struct list_head *ptr = gi->list.prev;
+
+ while (ptr != &gator_events) {
+ gi = list_entry(ptr, struct gator_interface,
+ list);
+
+ if (gi->stop)
+ gi->stop();
+
+ ptr = ptr->prev;
}
+ goto events_failure;
}
}
@@ -662,23 +642,18 @@ sched_failure:
gator_annotate_stop();
annotate_failure:
events_failure:
- for (f = gi; f != i; f = f->next) {
- f->stop();
- }
return -1;
}
static void gator_stop(void)
{
- gator_interface *i;
+ struct gator_interface *gi;
// stop all events
- for (i = gi; i != NULL; i = i->next) {
- if (i->stop) {
- i->stop();
- }
- }
+ list_for_each_entry(gi, &gator_events, list)
+ if (gi->stop)
+ gi->stop();
gator_annotate_stop();
gator_trace_sched_stop();
@@ -690,13 +665,7 @@ static void gator_stop(void)
static void gator_exit(void)
{
- gator_interface *i = gi;
-
- while (i) {
- gator_interface *p = i;
- i = i->next;
- kfree(p);
- }
+ gator_annotate_exit();
}
/******************************************************************************
@@ -894,6 +863,7 @@ static ssize_t event_buffer_read(struct file *file, char __user *buf,
int retval = -EINVAL;
int commit, length1, length2, read;
char *buffer1, *buffer2;
+ char annotate_header[6];
int cpu;
/* do not handle partial reads */
@@ -902,34 +872,43 @@ static ssize_t event_buffer_read(struct file *file, char __user *buf,
// sleep until the condition is true or a signal is received
// the condition is checked each time gator_buffer_wait is woken up
- wait_event_interruptible(gator_buffer_wait, buffer_commit_ready() || !gator_started);
+ wait_event_interruptible(gator_buffer_wait, buffer_commit_ready() || gator_annotate_ready() || !gator_started);
if (signal_pending(current))
return -EINTR;
- if (!buffer_commit_ready())
- return 0;
-
- buffer_commit_read(&cpu, &read, &commit);
+ retval = -EFAULT;
mutex_lock(&gator_buffer_mutex);
- retval = -EFAULT;
+ if (buffer_commit_ready()) {
+ buffer_commit_read(&cpu, &read, &commit);
- /* May happen if the buffer is freed during pending reads. */
- if (!per_cpu(use_buffer, cpu)) {
- retval = -EFAULT;
- goto out;
- }
+ /* May happen if the buffer is freed during pending reads. */
+ if (!per_cpu(use_buffer, cpu)) {
+ retval = -EFAULT;
+ goto out;
+ }
- /* determine the size of two halves */
- length1 = commit - read;
- length2 = 0;
- buffer1 = &(per_cpu(use_buffer, cpu)[read]);
- buffer2 = &(per_cpu(use_buffer, cpu)[0]);
- if (length1 < 0) {
- length1 = use_buffer_size - read;
- length2 = commit;
+ /* determine the size of two halves */
+ length1 = commit - read;
+ length2 = 0;
+ buffer1 = &(per_cpu(use_buffer, cpu)[read]);
+ buffer2 = &(per_cpu(use_buffer, cpu)[0]);
+ if (length1 < 0) {
+ length1 = use_buffer_size - read;
+ length2 = commit;
+ }
+ } else if (gator_annotate_ready()) {
+ length2 = gator_annotate_read(&buffer2);
+ if (!length2)
+ goto out;
+ annotate_header[0] = PROTOCOL_ANNOTATE;
+ length1 = gator_write_packed_int(&annotate_header[1], length2) + 1;
+ buffer1 = annotate_header;
+ } else {
+ retval = 0;
+ goto out;
}
/* start, middle or end */
@@ -952,8 +931,8 @@ static ssize_t event_buffer_read(struct file *file, char __user *buf,
wake_up(&gator_buffer_wait);
out:
- // do not adjust network stats if in non-streaming buffer mode
- if (gator_sync_freq)
+ // only adjust network stats if in streaming mode
+ if (gator_streaming)
gator_net_traffic += retval;
mutex_unlock(&gator_buffer_mutex);
return retval;
@@ -1009,7 +988,7 @@ static const struct file_operations cpu_type_fops = {
void gator_op_create_files(struct super_block *sb, struct dentry *root)
{
struct dentry *dir;
- gator_interface *i;
+ struct gator_interface *gi;
int cpu;
/* reinitialize default values */
@@ -1018,7 +997,7 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root)
gator_cpu_cores++;
}
gator_buffer_size = BUFFER_SIZE_DEFAULT;
- gator_sync_freq = SYNC_FREQ_DEFAULT;
+ gator_streaming = 1;
gatorfs_create_file(sb, root, "enable", &enable_fops);
gatorfs_create_file(sb, root, "buffer", &gator_event_buffer_fops);
@@ -1027,7 +1006,7 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root)
gatorfs_create_ulong(sb, root, "cpu_cores", &gator_cpu_cores);
gatorfs_create_ulong(sb, root, "buffer_size", &gator_buffer_size);
gatorfs_create_ulong(sb, root, "tick", &gator_timer_count);
- gatorfs_create_ulong(sb, root, "sync_freq", &gator_sync_freq);
+ gatorfs_create_ulong(sb, root, "streaming", &gator_streaming);
gatorfs_create_ro_ulong(sb, root, "version", &gator_protocol_version);
// Annotate interface
@@ -1035,18 +1014,14 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root)
// Linux Events
dir = gatorfs_mkdir(sb, root, "events");
- for (i = gi; i != NULL; i = i->next) {
- if (i->create_files) {
- i->create_files(sb, dir);
- }
- }
+ list_for_each_entry(gi, &gator_events, list)
+ if (gi->create_files)
+ gi->create_files(sb, dir);
}
/******************************************************************************
* Module
******************************************************************************/
-static int gator_initialized;
-
static int __init gator_module_init(void)
{
if (gatorfs_register()) {
@@ -1058,7 +1033,6 @@ static int __init gator_module_init(void)
return -1;
}
- gator_initialized = 1;
#ifdef GATOR_DEBUG
pr_err("gator_module_init");
#endif
@@ -1072,10 +1046,7 @@ static void __exit gator_module_exit(void)
#endif
tracepoint_synchronize_unregister();
gatorfs_unregister();
- if (gator_initialized) {
- gator_initialized = 0;
- gator_exit();
- }
+ gator_exit();
}
module_init(gator_module_init);