From 730ab7f66781e433083572fb9000092e172bec3c Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Thu, 30 Oct 2014 18:01:15 +0000 Subject: gator: Version 5.20 Signed-off-by: Jon Medhurst --- drivers/gator/Kconfig | 4 +- drivers/gator/Makefile | 22 +- drivers/gator/gator.h | 41 +- drivers/gator/gator_annotate.c | 67 +- drivers/gator/gator_annotate_kernel.c | 30 +- drivers/gator/gator_backtrace.c | 66 +- drivers/gator/gator_buffer.c | 71 +- drivers/gator/gator_buffer_write.c | 19 +- drivers/gator/gator_cookies.c | 67 +- drivers/gator/gator_events_armv6.c | 47 +- drivers/gator/gator_events_armv7.c | 90 +- drivers/gator/gator_events_block.c | 29 +- drivers/gator/gator_events_ccn-504.c | 346 -------- drivers/gator/gator_events_irq.c | 14 +- drivers/gator/gator_events_l2c-310.c | 6 +- drivers/gator/gator_events_mali_4xx.c | 181 ++-- drivers/gator/gator_events_mali_common.c | 21 +- drivers/gator/gator_events_mali_common.h | 17 +- drivers/gator/gator_events_mali_midgard.c | 562 ++++++++++++ drivers/gator/gator_events_mali_midgard_hw.c | 977 +++++++++++++++++++++ drivers/gator/gator_events_mali_midgard_hw_test.c | 55 ++ drivers/gator/gator_events_mali_t6xx.c | 567 ------------ drivers/gator/gator_events_mali_t6xx_hw.c | 913 ------------------- drivers/gator/gator_events_mali_t6xx_hw_test.c | 55 -- drivers/gator/gator_events_meminfo.c | 197 +++-- drivers/gator/gator_events_mmapped.c | 6 +- drivers/gator/gator_events_net.c | 22 +- drivers/gator/gator_events_perf_pmu.c | 207 ++--- drivers/gator/gator_events_sched.c | 14 +- drivers/gator/gator_events_scorpion.c | 81 +- drivers/gator/gator_events_threads.c | 115 --- drivers/gator/gator_fs.c | 9 +- drivers/gator/gator_hrtimer_gator.c | 8 +- drivers/gator/gator_iks.c | 22 +- drivers/gator/gator_main.c | 349 ++++---- drivers/gator/gator_marshaling.c | 75 +- drivers/gator/gator_trace_gpu.c | 88 +- drivers/gator/gator_trace_power.c | 61 +- drivers/gator/gator_trace_sched.c | 104 ++- drivers/gator/mali/mali_dd_gator_api.h | 40 - drivers/gator/mali/mali_kbase_gator_api.h | 219 +++++ .../gator/mali/mali_mjollnir_profiling_gator_api.h | 192 ++-- .../gator/mali/mali_utgard_profiling_gator_api.h | 214 +++-- drivers/gator/mali_midgard.mk | 39 + drivers/gator/mali_t6xx.mk | 39 - 45 files changed, 3100 insertions(+), 3268 deletions(-) delete mode 100644 drivers/gator/gator_events_ccn-504.c create mode 100644 drivers/gator/gator_events_mali_midgard.c create mode 100644 drivers/gator/gator_events_mali_midgard_hw.c create mode 100644 drivers/gator/gator_events_mali_midgard_hw_test.c delete mode 100644 drivers/gator/gator_events_mali_t6xx.c delete mode 100644 drivers/gator/gator_events_mali_t6xx_hw.c delete mode 100644 drivers/gator/gator_events_mali_t6xx_hw_test.c delete mode 100644 drivers/gator/gator_events_threads.c delete mode 100644 drivers/gator/mali/mali_dd_gator_api.h create mode 100644 drivers/gator/mali/mali_kbase_gator_api.h create mode 100644 drivers/gator/mali_midgard.mk delete mode 100644 drivers/gator/mali_t6xx.mk (limited to 'drivers') diff --git a/drivers/gator/Kconfig b/drivers/gator/Kconfig index e46ccb9b8064..b2358bbc1293 100644 --- a/drivers/gator/Kconfig +++ b/drivers/gator/Kconfig @@ -24,8 +24,8 @@ config GATOR_MALI_4XXMP bool "Mali-400MP or Mali-450MP" select GATOR_WITH_MALI_SUPPORT -config GATOR_MALI_T6XX - bool "Mali-T604 or Mali-T658" +config GATOR_MALI_MIDGARD + bool "Mali-T60x, Mali-T62x, Mali-T72x or Mali-T76x" select GATOR_WITH_MALI_SUPPORT endchoice diff --git a/drivers/gator/Makefile b/drivers/gator/Makefile index 2f86823313c6..28d2070b11d5 100644 --- a/drivers/gator/Makefile +++ b/drivers/gator/Makefile @@ -14,17 +14,16 @@ gator-y := gator_main.o \ gator_events_net.o \ gator_events_perf_pmu.o \ gator_events_sched.o \ - gator_events_threads.o \ # Convert the old GATOR_WITH_MALI_SUPPORT to the new kernel flags ifneq ($(GATOR_WITH_MALI_SUPPORT),) CONFIG_GATOR_WITH_MALI_SUPPORT := y - ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_T6xx) + ifeq ($(GATOR_WITH_MALI_SUPPORT),MALI_MIDGARD) CONFIG_GATOR_MALI_4XXMP := n - CONFIG_GATOR_MALI_T6XX := y + CONFIG_GATOR_MALI_MIDGARD := y else CONFIG_GATOR_MALI_4XXMP := y - CONFIG_GATOR_MALI_T6XX := n + CONFIG_GATOR_MALI_MIDGARD := n endif EXTRA_CFLAGS += -DMALI_SUPPORT=$(GATOR_WITH_MALI_SUPPORT) ifneq ($(GATOR_MALI_INTERFACE_STYLE),) @@ -33,10 +32,10 @@ ifneq ($(GATOR_WITH_MALI_SUPPORT),) endif ifeq ($(CONFIG_GATOR_WITH_MALI_SUPPORT),y) - ifeq ($(CONFIG_GATOR_MALI_T6XX),y) - gator-y += gator_events_mali_t6xx.o \ - gator_events_mali_t6xx_hw.o - include $(src)/mali_t6xx.mk + ifeq ($(CONFIG_GATOR_MALI_MIDGARD),y) + gator-y += gator_events_mali_midgard.o \ + gator_events_mali_midgard_hw.o + include $(src)/mali_midgard.mk else gator-y += gator_events_mali_4xx.o endif @@ -46,7 +45,7 @@ ifeq ($(CONFIG_GATOR_WITH_MALI_SUPPORT),y) ccflags-y += -I$(CONFIG_GATOR_MALI_PATH) endif ccflags-$(CONFIG_GATOR_MALI_4XXMP) += -DMALI_SUPPORT=MALI_4xx - ccflags-$(CONFIG_GATOR_MALI_T6XX) += -DMALI_SUPPORT=MALI_T6xx + ccflags-$(CONFIG_GATOR_MALI_MIDGARD) += -DMALI_SUPPORT=MALI_MIDGARD endif # GATOR_TEST controls whether to include (=1) or exclude (=0) test code. @@ -54,16 +53,15 @@ GATOR_TEST ?= 0 EXTRA_CFLAGS += -DGATOR_TEST=$(GATOR_TEST) # Should the original or new block_rq_complete API be used? -OLD_BLOCK_RQ_COMPLETE := $(shell grep -A3 block_rq_complete include/trace/events/block.h | grep nr_bytes > /dev/null; echo $$?) +OLD_BLOCK_RQ_COMPLETE := $(shell grep -A3 block_rq_complete $(srctree)/include/trace/events/block.h | grep nr_bytes -q; echo $$?) EXTRA_CFLAGS += -DOLD_BLOCK_RQ_COMPLETE=$(OLD_BLOCK_RQ_COMPLETE) gator-$(CONFIG_ARM) += gator_events_armv6.o \ gator_events_armv7.o \ - gator_events_ccn-504.o \ gator_events_l2c-310.o \ gator_events_scorpion.o -gator-$(CONFIG_ARM64) += gator_events_ccn-504.o +gator-$(CONFIG_ARM64) += else diff --git a/drivers/gator/gator.h b/drivers/gator/gator.h index 5ad0254d86a9..5cc73a388c4f 100644 --- a/drivers/gator/gator.h +++ b/drivers/gator/gator.h @@ -14,13 +14,13 @@ #include #include -#define GATOR_PERF_SUPPORT LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) -#define GATOR_PERF_PMU_SUPPORT GATOR_PERF_SUPPORT && defined(CONFIG_PERF_EVENTS) && (!(defined(__arm__) || defined(__aarch64__)) || defined(CONFIG_HW_PERF_EVENTS)) +#define GATOR_PERF_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) +#define GATOR_PERF_PMU_SUPPORT (GATOR_PERF_SUPPORT && defined(CONFIG_PERF_EVENTS) && (!(defined(__arm__) || defined(__aarch64__)) || defined(CONFIG_HW_PERF_EVENTS))) #define GATOR_NO_PERF_SUPPORT (!(GATOR_PERF_SUPPORT)) -#define GATOR_CPU_FREQ_SUPPORT (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ) +#define GATOR_CPU_FREQ_SUPPORT ((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)) && defined(CONFIG_CPU_FREQ)) #define GATOR_IKS_SUPPORT defined(CONFIG_BL_SWITCHER) -// cpu ids +/* cpu ids */ #define ARM1136 0xb36 #define ARM1156 0xb56 #define ARM1176 0xb76 @@ -29,7 +29,6 @@ #define CORTEX_A7 0xc07 #define CORTEX_A8 0xc08 #define CORTEX_A9 0xc09 -#define CORTEX_A12 0xc0d #define CORTEX_A15 0xc0f #define CORTEX_A17 0xc0e #define SCORPION 0x00f @@ -42,20 +41,20 @@ #define AARCH64 0xd0f #define OTHER 0xfff -// gpu enums +/* gpu enums */ #define MALI_4xx 1 -#define MALI_T6xx 2 +#define MALI_MIDGARD 2 #define MAXSIZE_CORE_NAME 32 struct gator_cpu { const int cpuid; - // Human readable name + /* Human readable name */ const char core_name[MAXSIZE_CORE_NAME]; - // gatorfs event and Perf PMU name - const char * const pmnc_name; - // compatible from Documentation/devicetree/bindings/arm/cpus.txt - const char * const dt_name; + /* gatorfs event and Perf PMU name */ + const char *const pmnc_name; + /* compatible from Documentation/devicetree/bindings/arm/cpus.txt */ + const char *const dt_name; const int pmnc_counters; }; @@ -98,7 +97,7 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, extern struct tracepoint *gator_tracepoint_##probe_name; \ static void probe_##probe_name(void *data, PARAMS(proto)) # define GATOR_REGISTER_TRACE(probe_name) \ - tracepoint_probe_register(gator_tracepoint_##probe_name, probe_##probe_name, NULL) + ((gator_tracepoint_##probe_name == NULL) || tracepoint_probe_register(gator_tracepoint_##probe_name, probe_##probe_name, NULL)) # define GATOR_UNREGISTER_TRACE(probe_name) \ tracepoint_probe_unregister(gator_tracepoint_##probe_name, probe_##probe_name, NULL) #endif @@ -107,15 +106,19 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, * Events ******************************************************************************/ struct gator_interface { - void (*shutdown)(void); // Complementary function to init + /* Complementary function to init */ + void (*shutdown)(void); int (*create_files)(struct super_block *sb, struct dentry *root); int (*start)(void); - void (*stop)(void); // Complementary function to start + /* Complementary function to start */ + void (*stop)(void); int (*online)(int **buffer, bool migrate); int (*offline)(int **buffer, bool migrate); - void (*online_dispatch)(int cpu, bool migrate); // called in process context but may not be running on core 'cpu' - void (*offline_dispatch)(int cpu, bool migrate); // called in process context but may not be running on core 'cpu' - int (*read)(int **buffer); + /* called in process context but may not be running on core 'cpu' */ + void (*online_dispatch)(int cpu, bool migrate); + /* called in process context but may not be running on core 'cpu' */ + void (*offline_dispatch)(int cpu, bool migrate); + int (*read)(int **buffer, bool sched_switch); int (*read64)(long long **buffer); int (*read_proc)(long long **buffer, struct task_struct *); struct list_head list; @@ -146,4 +149,4 @@ int pcpu_to_lcpu(const int pcpu); #define get_logical_cpu() smp_processor_id() #define on_primary_core() (get_logical_cpu() == 0) -#endif // GATOR_H_ +#endif /* GATOR_H_ */ diff --git a/drivers/gator/gator_annotate.c b/drivers/gator/gator_annotate.c index 7e2c6e5d8715..ff9a3cef7b2e 100644 --- a/drivers/gator/gator_annotate.c +++ b/drivers/gator/gator_annotate.c @@ -11,12 +11,12 @@ #include #include #include -#include +#include #include #include static DEFINE_SPINLOCK(annotate_lock); -static bool collect_annotations = false; +static bool collect_annotations; static int annotate_copy(struct file *file, char const __user *buf, size_t count) { @@ -24,10 +24,10 @@ static int annotate_copy(struct file *file, char const __user *buf, size_t count int write = per_cpu(gator_buffer_write, cpu)[ANNOTATE_BUF]; if (file == NULL) { - // copy from kernel + /* copy from kernel */ memcpy(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count); } else { - // copy from user space + /* copy from user space */ if (copy_from_user(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count) != 0) return -1; } @@ -41,70 +41,70 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t int pid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff; bool interrupt_context; - if (*offset) { + if (*offset) return -EINVAL; - } interrupt_context = in_interrupt(); - // Annotations are not supported in interrupt context, but may work if you comment out the the next four lines of code. - // By doing so, annotations in interrupt context can result in deadlocks and lost data. + /* Annotations are not supported in interrupt context, but may work + * if you comment out the the next four lines of code. By doing so, + * annotations in interrupt context can result in deadlocks and lost + * data. + */ if (interrupt_context) { - printk(KERN_WARNING "gator: Annotations are not supported in interrupt context. Edit gator_annotate.c in the gator driver to enable annotations in interrupt context.\n"); + pr_warning("gator: Annotations are not supported in interrupt context. Edit gator_annotate.c in the gator driver to enable annotations in interrupt context.\n"); return -EINVAL; } retry: - // synchronize between cores and with collect_annotations + /* synchronize between cores and with collect_annotations */ spin_lock(&annotate_lock); if (!collect_annotations) { - // Not collecting annotations, tell the caller everything was written + /* Not collecting annotations, tell the caller everything was written */ size = count_orig; goto annotate_write_out; } - // Annotation only uses a single per-cpu buffer as the data must be in order to the engine + /* Annotation only uses a single per-cpu buffer as the data must be in order to the engine */ cpu = 0; - if (current == NULL) { + if (current == NULL) pid = 0; - } else { + else pid = current->pid; - } - // determine total size of the payload + /* determine total size of the payload */ header_size = MAXSIZE_PACK32 * 3 + MAXSIZE_PACK64; available = buffer_bytes_available(cpu, ANNOTATE_BUF) - header_size; size = count < available ? count : available; if (size <= 0) { - // Buffer is full, wait until space is available + /* Buffer is full, wait until space is available */ spin_unlock(&annotate_lock); - // Drop the annotation as blocking is not allowed in interrupt context - if (interrupt_context) { + /* Drop the annotation as blocking is not allowed in interrupt context */ + if (interrupt_context) return -EINVAL; - } wait_event_interruptible(gator_annotate_wait, buffer_bytes_available(cpu, ANNOTATE_BUF) > header_size || !collect_annotations); - // Check to see if a signal is pending - if (signal_pending(current)) { + /* Check to see if a signal is pending */ + if (signal_pending(current)) return -EINTR; - } goto retry; } - // synchronize shared variables annotateBuf and annotatePos + /* synchronize shared variables annotateBuf and annotatePos */ if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) { u64 time = gator_get_time(); + gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, get_physical_cpu()); gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid); gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, time); gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, size); - // determine the sizes to capture, length1 + length2 will equal size + /* determine the sizes to capture, length1 + length2 will equal size */ contiguous = contiguous_space_available(cpu, ANNOTATE_BUF); if (size < contiguous) { length1 = size; @@ -124,14 +124,14 @@ static ssize_t annotate_write(struct file *file, char const __user *buf, size_t goto annotate_write_out; } - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, ANNOTATE_BUF, time); } annotate_write_out: spin_unlock(&annotate_lock); - // return the number of bytes written + /* return the number of bytes written */ return size; } @@ -141,18 +141,21 @@ static int annotate_release(struct inode *inode, struct file *file) { int cpu = 0; - // synchronize between cores + /* synchronize between cores */ spin_lock(&annotate_lock); if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) { uint32_t pid = current->pid; + gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, get_physical_cpu()); gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid); - gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); // time - gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); // size + /* time */ + gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0); + /* size */ + gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0); } - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, ANNOTATE_BUF, gator_get_time()); spin_unlock(&annotate_lock); @@ -178,7 +181,7 @@ static int gator_annotate_start(void) static void gator_annotate_stop(void) { - // the spinlock here will ensure that when this function exits, we are not in the middle of an annotation + /* the spinlock here will ensure that when this function exits, we are not in the middle of an annotation */ spin_lock(&annotate_lock); collect_annotations = false; wake_up(&gator_annotate_wait); diff --git a/drivers/gator/gator_annotate_kernel.c b/drivers/gator/gator_annotate_kernel.c index 010806825529..69471f99e5fb 100644 --- a/drivers/gator/gator_annotate_kernel.c +++ b/drivers/gator/gator_annotate_kernel.c @@ -19,10 +19,11 @@ static void kannotate_write(const char *ptr, unsigned int size) int retval; int pos = 0; loff_t offset = 0; + while (pos < size) { retval = annotate_write(NULL, &ptr[pos], size - pos, &offset); if (retval < 0) { - printk(KERN_WARNING "gator: kannotate_write failed with return value %d\n", retval); + pr_warning("gator: kannotate_write failed with return value %d\n", retval); return; } pos += retval; @@ -47,6 +48,7 @@ void gator_annotate_channel(int channel, const char *str) { const u16 str_size = strlen(str) & 0xffff; char header[8]; + header[0] = ESCAPE_CODE; header[1] = STRING_ANNOTATION; marshal_u32(header + 2, channel); @@ -54,20 +56,19 @@ void gator_annotate_channel(int channel, const char *str) kannotate_write(header, sizeof(header)); kannotate_write(str, str_size); } - EXPORT_SYMBOL(gator_annotate_channel); void gator_annotate(const char *str) { gator_annotate_channel(0, str); } - EXPORT_SYMBOL(gator_annotate); void gator_annotate_channel_color(int channel, int color, const char *str) { const u16 str_size = (strlen(str) + 4) & 0xffff; char header[12]; + header[0] = ESCAPE_CODE; header[1] = STRING_ANNOTATION; marshal_u32(header + 2, channel); @@ -76,39 +77,37 @@ void gator_annotate_channel_color(int channel, int color, const char *str) kannotate_write(header, sizeof(header)); kannotate_write(str, str_size - 4); } - EXPORT_SYMBOL(gator_annotate_channel_color); void gator_annotate_color(int color, const char *str) { gator_annotate_channel_color(0, color, str); } - EXPORT_SYMBOL(gator_annotate_color); void gator_annotate_channel_end(int channel) { char header[8]; + header[0] = ESCAPE_CODE; header[1] = STRING_ANNOTATION; marshal_u32(header + 2, channel); marshal_u16(header + 6, 0); kannotate_write(header, sizeof(header)); } - EXPORT_SYMBOL(gator_annotate_channel_end); void gator_annotate_end(void) { gator_annotate_channel_end(0); } - EXPORT_SYMBOL(gator_annotate_end); -void gator_annotate_name_channel(int channel, int group, const char* str) +void gator_annotate_name_channel(int channel, int group, const char *str) { const u16 str_size = strlen(str) & 0xffff; char header[12]; + header[0] = ESCAPE_CODE; header[1] = NAME_CHANNEL_ANNOTATION; marshal_u32(header + 2, channel); @@ -117,13 +116,13 @@ void gator_annotate_name_channel(int channel, int group, const char* str) kannotate_write(header, sizeof(header)); kannotate_write(str, str_size); } - EXPORT_SYMBOL(gator_annotate_name_channel); -void gator_annotate_name_group(int group, const char* str) +void gator_annotate_name_group(int group, const char *str) { const u16 str_size = strlen(str) & 0xffff; char header[8]; + header[0] = ESCAPE_CODE; header[1] = NAME_GROUP_ANNOTATION; marshal_u32(header + 2, group); @@ -131,7 +130,6 @@ void gator_annotate_name_group(int group, const char* str) kannotate_write(header, sizeof(header)); kannotate_write(str, str_size); } - EXPORT_SYMBOL(gator_annotate_name_group); void gator_annotate_visual(const char *data, unsigned int length, const char *str) @@ -139,6 +137,7 @@ void gator_annotate_visual(const char *data, unsigned int length, const char *st const u16 str_size = strlen(str) & 0xffff; char header[4]; char header_length[4]; + header[0] = ESCAPE_CODE; header[1] = VISUAL_ANNOTATION; marshal_u16(header + 2, str_size); @@ -148,49 +147,49 @@ void gator_annotate_visual(const char *data, unsigned int length, const char *st kannotate_write(header_length, sizeof(header_length)); kannotate_write(data, length); } - EXPORT_SYMBOL(gator_annotate_visual); void gator_annotate_marker(void) { char header[4]; + header[0] = ESCAPE_CODE; header[1] = MARKER_ANNOTATION; marshal_u16(header + 2, 0); kannotate_write(header, sizeof(header)); } - EXPORT_SYMBOL(gator_annotate_marker); void gator_annotate_marker_str(const char *str) { const u16 str_size = strlen(str) & 0xffff; char header[4]; + header[0] = ESCAPE_CODE; header[1] = MARKER_ANNOTATION; marshal_u16(header + 2, str_size); kannotate_write(header, sizeof(header)); kannotate_write(str, str_size); } - EXPORT_SYMBOL(gator_annotate_marker_str); void gator_annotate_marker_color(int color) { char header[8]; + header[0] = ESCAPE_CODE; header[1] = MARKER_ANNOTATION; marshal_u16(header + 2, 4); marshal_u32(header + 4, color); kannotate_write(header, sizeof(header)); } - EXPORT_SYMBOL(gator_annotate_marker_color); void gator_annotate_marker_color_str(int color, const char *str) { const u16 str_size = (strlen(str) + 4) & 0xffff; char header[8]; + header[0] = ESCAPE_CODE; header[1] = MARKER_ANNOTATION; marshal_u16(header + 2, str_size); @@ -198,5 +197,4 @@ void gator_annotate_marker_color_str(int color, const char *str) kannotate_write(header, sizeof(header)); kannotate_write(str, str_size - 4); } - EXPORT_SYMBOL(gator_annotate_marker_color_str); diff --git a/drivers/gator/gator_backtrace.c b/drivers/gator/gator_backtrace.c index e03c1653c5b5..76c941d009a9 100644 --- a/drivers/gator/gator_backtrace.c +++ b/drivers/gator/gator_backtrace.c @@ -14,17 +14,17 @@ struct stack_frame_eabi { union { struct { unsigned long fp; - // May be the fp in the case of a leaf function or clang + /* May be the fp in the case of a leaf function or clang */ unsigned long lr; - // If lr is really the fp, lr2 is the corresponding lr + /* If lr is really the fp, lr2 is the corresponding lr */ unsigned long lr2; }; - // Used to read 32 bit fp/lr from a 64 bit kernel + /* Used to read 32 bit fp/lr from a 64 bit kernel */ struct { u32 fp_32; - // same as lr above + /* same as lr above */ u32 lr_32; - // same as lr2 above + /* same as lr2 above */ u32 lr2_32; }; }; @@ -35,9 +35,8 @@ static void gator_add_trace(int cpu, unsigned long address) off_t offset = 0; unsigned long cookie = get_address_cookie(cpu, current, address & ~1, &offset); - if (cookie == NO_COOKIE || cookie == UNRESOLVED_COOKIE) { + if (cookie == NO_COOKIE || cookie == UNRESOLVED_COOKIE) offset = address; - } marshal_backtrace(offset & ~1, cookie, 0); } @@ -54,36 +53,34 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int unsigned long lr = regs->ARM_lr; const int gcc_frame_offset = sizeof(unsigned long); #else - // Is userspace aarch32 (32 bit) + /* Is userspace aarch32 (32 bit) */ const bool is_compat = compat_user_mode(regs); unsigned long fp = (is_compat ? regs->regs[11] : regs->regs[29]); unsigned long sp = (is_compat ? regs->compat_sp : regs->sp); unsigned long lr = (is_compat ? regs->compat_lr : regs->regs[30]); const int gcc_frame_offset = (is_compat ? sizeof(u32) : 0); #endif - // clang frame offset is always zero + /* clang frame offset is always zero */ int is_user_mode = user_mode(regs); - // pc (current function) has already been added + /* pc (current function) has already been added */ - if (!is_user_mode) { + if (!is_user_mode) return; - } - // Add the lr (parent function) - // entry preamble may not have executed + /* Add the lr (parent function), entry preamble may not have + * executed + */ gator_add_trace(cpu, lr); - // check fp is valid - if (fp == 0 || fp < sp) { + /* check fp is valid */ + if (fp == 0 || fp < sp) return; - } - // Get the current stack frame + /* Get the current stack frame */ curr = (struct stack_frame_eabi *)(fp - gcc_frame_offset); - if ((unsigned long)curr & 3) { + if ((unsigned long)curr & 3) return; - } while (depth-- && curr) { if (!access_ok(VERIFY_READ, curr, sizeof(struct stack_frame_eabi)) || @@ -95,13 +92,15 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int lr = (is_compat ? bufcurr.lr_32 : bufcurr.lr); #define calc_next(reg) ((reg) - gcc_frame_offset) - // Returns true if reg is a valid fp + /* Returns true if reg is a valid fp */ #define validate_next(reg, curr) \ ((reg) != 0 && (calc_next(reg) & 3) == 0 && (unsigned long)(curr) < calc_next(reg)) - // Try lr from the stack as the fp because gcc leaf functions do not push lr - // If gcc_frame_offset is non-zero, the lr will also be the clang fp - // This assumes code is at a lower address than the stack + /* Try lr from the stack as the fp because gcc leaf functions do + * not push lr. If gcc_frame_offset is non-zero, the lr will also + * be the clang fp. This assumes code is at a lower address than + * the stack + */ if (validate_next(lr, curr)) { fp = lr; lr = (is_compat ? bufcurr.lr2_32 : bufcurr.lr2); @@ -109,11 +108,10 @@ static void arm_backtrace_eabi(int cpu, struct pt_regs *const regs, unsigned int gator_add_trace(cpu, lr); - if (!validate_next(fp, curr)) { + if (!validate_next(fp, curr)) return; - } - // Move to the next stack frame + /* Move to the next stack frame */ curr = (struct stack_frame_eabi *)calc_next(fp); } #endif @@ -129,6 +127,7 @@ static int report_trace(struct stackframe *frame, void *d) #if defined(MODULE) unsigned int cpu = get_physical_cpu(); struct module *mod = __module_address(addr); + if (mod) { cookie = get_cookie(cpu, current, mod->name, false); addr = addr - (unsigned long)mod->module_core; @@ -142,13 +141,13 @@ static int report_trace(struct stackframe *frame, void *d) } #endif -// Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile -// #define GATOR_KERNEL_STACK_UNWINDING +/* Uncomment the following line to enable kernel stack unwinding within gator, note it can also be defined from the Makefile */ +/* #define GATOR_KERNEL_STACK_UNWINDING */ #if (defined(__arm__) || defined(__aarch64__)) && !defined(GATOR_KERNEL_STACK_UNWINDING) -// Disabled by default +/* Disabled by default */ MODULE_PARM_DESC(kernel_stack_unwinding, "Allow kernel stack unwinding."); -static bool kernel_stack_unwinding = 0; +static bool kernel_stack_unwinding; module_param(kernel_stack_unwinding, bool, 0644); #endif @@ -161,6 +160,7 @@ static void kernel_backtrace(int cpu, struct pt_regs *const regs) int depth = (kernel_stack_unwinding ? gator_backtrace_depth : 1); #endif struct stackframe frame; + if (depth == 0) depth = 1; #if defined(__arm__) @@ -196,10 +196,10 @@ static void gator_add_sample(int cpu, struct pt_regs *const regs, u64 time) if (in_kernel) { kernel_backtrace(cpu, regs); } else { - // Cookie+PC + /* Cookie+PC */ gator_add_trace(cpu, PC_REG); - // Backtrace + /* Backtrace */ if (gator_backtrace_depth) arm_backtrace_eabi(cpu, regs, gator_backtrace_depth); } diff --git a/drivers/gator/gator_buffer.c b/drivers/gator/gator_buffer.c index dfbc97d80221..910d5aa15066 100644 --- a/drivers/gator/gator_buffer.c +++ b/drivers/gator/gator_buffer.c @@ -10,55 +10,65 @@ static void marshal_frame(int cpu, int buftype) { int frame; + bool write_cpu; - if (!per_cpu(gator_buffer, cpu)[buftype]) { + if (!per_cpu(gator_buffer, cpu)[buftype]) return; - } switch (buftype) { case SUMMARY_BUF: + write_cpu = false; frame = FRAME_SUMMARY; break; case BACKTRACE_BUF: + write_cpu = true; frame = FRAME_BACKTRACE; break; case NAME_BUF: + write_cpu = true; frame = FRAME_NAME; break; case COUNTER_BUF: + write_cpu = false; frame = FRAME_COUNTER; break; case BLOCK_COUNTER_BUF: + write_cpu = true; frame = FRAME_BLOCK_COUNTER; break; case ANNOTATE_BUF: + write_cpu = false; frame = FRAME_ANNOTATE; break; case SCHED_TRACE_BUF: + write_cpu = true; frame = FRAME_SCHED_TRACE; break; case IDLE_BUF: + write_cpu = false; frame = FRAME_IDLE; break; case ACTIVITY_BUF: + write_cpu = false; frame = FRAME_ACTIVITY; break; default: + write_cpu = false; frame = -1; break; } - // add response type - if (gator_response_type > 0) { + /* add response type */ + if (gator_response_type > 0) gator_buffer_write_packed_int(cpu, buftype, gator_response_type); - } - // leave space for 4-byte unpacked length + /* leave space for 4-byte unpacked length */ per_cpu(gator_buffer_write, cpu)[buftype] = (per_cpu(gator_buffer_write, cpu)[buftype] + sizeof(s32)) & gator_buffer_mask[buftype]; - // add frame type and core number + /* add frame type and core number */ gator_buffer_write_packed_int(cpu, buftype, frame); - gator_buffer_write_packed_int(cpu, buftype, cpu); + if (write_cpu) + gator_buffer_write_packed_int(cpu, buftype, cpu); } static int buffer_bytes_available(int cpu, int buftype) @@ -66,19 +76,17 @@ static int buffer_bytes_available(int cpu, int buftype) int remaining, filled; filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_read, cpu)[buftype]; - if (filled < 0) { + if (filled < 0) filled += gator_buffer_size[buftype]; - } remaining = gator_buffer_size[buftype] - filled; - if (per_cpu(buffer_space_available, cpu)[buftype]) { - // Give some extra room; also allows space to insert the overflow error packet + if (per_cpu(buffer_space_available, cpu)[buftype]) + /* Give some extra room; also allows space to insert the overflow error packet */ remaining -= 200; - } else { - // Hysteresis, prevents multiple overflow messages + else + /* Hysteresis, prevents multiple overflow messages */ remaining -= 2000; - } return remaining; } @@ -87,11 +95,10 @@ static bool buffer_check_space(int cpu, int buftype, int bytes) { int remaining = buffer_bytes_available(cpu, buftype); - if (remaining < bytes) { + if (remaining < bytes) per_cpu(buffer_space_available, cpu)[buftype] = false; - } else { + else per_cpu(buffer_space_available, cpu)[buftype] = true; - } return per_cpu(buffer_space_available, cpu)[buftype]; } @@ -100,10 +107,10 @@ static int contiguous_space_available(int cpu, int buftype) { int remaining = buffer_bytes_available(cpu, buftype); int contiguous = gator_buffer_size[buftype] - per_cpu(gator_buffer_write, cpu)[buftype]; + if (remaining < contiguous) return remaining; - else - return contiguous; + return contiguous; } static void gator_commit_buffer(int cpu, int buftype, u64 time) @@ -114,41 +121,38 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time) if (!per_cpu(gator_buffer, cpu)[buftype]) return; - // post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload + /* post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload */ local_irq_save(flags); type_length = gator_response_type ? 1 : 0; commit = per_cpu(gator_buffer_commit, cpu)[buftype]; length = per_cpu(gator_buffer_write, cpu)[buftype] - commit; - if (length < 0) { + if (length < 0) length += gator_buffer_size[buftype]; - } length = length - type_length - sizeof(s32); if (length <= FRAME_HEADER_SIZE) { - // Nothing to write, only the frame header is present + /* Nothing to write, only the frame header is present */ local_irq_restore(flags); return; } - for (byte = 0; byte < sizeof(s32); byte++) { + for (byte = 0; byte < sizeof(s32); byte++) per_cpu(gator_buffer, cpu)[buftype][(commit + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF; - } per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype]; if (gator_live_rate > 0) { - while (time > per_cpu(gator_buffer_commit_time, cpu)) { + while (time > per_cpu(gator_buffer_commit_time, cpu)) per_cpu(gator_buffer_commit_time, cpu) += gator_live_rate; - } } marshal_frame(cpu, buftype); local_irq_restore(flags); - // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater + /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */ if (per_cpu(in_scheduler_context, cpu)) { #ifndef CONFIG_PREEMPT_RT_FULL - // mod_timer can not be used in interrupt context in RT-Preempt full + /* mod_timer can not be used in interrupt context in RT-Preempt full */ mod_timer(&gator_buffer_wake_up_timer, jiffies + 1); #endif } else { @@ -159,10 +163,9 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time) static void buffer_check(int cpu, int buftype, u64 time) { int filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_commit, cpu)[buftype]; - if (filled < 0) { + + if (filled < 0) filled += gator_buffer_size[buftype]; - } - if (filled >= ((gator_buffer_size[buftype] * 3) / 4)) { + if (filled >= ((gator_buffer_size[buftype] * 3) / 4)) gator_commit_buffer(cpu, buftype, time); - } } diff --git a/drivers/gator/gator_buffer_write.c b/drivers/gator/gator_buffer_write.c index b621ba93ee5e..654ec606cfad 100644 --- a/drivers/gator/gator_buffer_write.c +++ b/drivers/gator/gator_buffer_write.c @@ -14,16 +14,17 @@ static void gator_buffer_write_packed_int(int cpu, int buftype, int x) char *buffer = per_cpu(gator_buffer, cpu)[buftype]; int packedBytes = 0; int more = true; + while (more) { - // low order 7 bits of x + /* low order 7 bits of x */ char b = x & 0x7f; + x >>= 7; - if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) { + if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) more = false; - } else { + else b |= 0x80; - } buffer[(write + packedBytes) & mask] = b; packedBytes++; @@ -39,16 +40,17 @@ static void gator_buffer_write_packed_int64(int cpu, int buftype, long long x) char *buffer = per_cpu(gator_buffer, cpu)[buftype]; int packedBytes = 0; int more = true; + while (more) { - // low order 7 bits of x + /* low order 7 bits of x */ char b = x & 0x7f; + x >>= 7; - if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) { + if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) more = false; - } else { + else b |= 0x80; - } buffer[(write + packedBytes) & mask] = b; packedBytes++; @@ -75,6 +77,7 @@ static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int le static void gator_buffer_write_string(int cpu, int buftype, const char *x) { int len = strlen(x); + gator_buffer_write_packed_int(cpu, buftype, len); gator_buffer_write_bytes(cpu, buftype, x, len); } diff --git a/drivers/gator/gator_cookies.c b/drivers/gator/gator_cookies.c index 5c7d842070e0..c43cce815226 100644 --- a/drivers/gator/gator_cookies.c +++ b/drivers/gator/gator_cookies.c @@ -7,8 +7,10 @@ * */ -#define COOKIEMAP_ENTRIES 1024 /* must be power of 2 */ -#define TRANSLATE_BUFFER_SIZE 512 // must be a power of 2 - 512/4 = 128 entries +/* must be power of 2 */ +#define COOKIEMAP_ENTRIES 1024 +/* must be a power of 2 - 512/4 = 128 entries */ +#define TRANSLATE_BUFFER_SIZE 512 #define TRANSLATE_TEXT_SIZE 256 #define MAX_COLLISIONS 2 @@ -38,6 +40,7 @@ static uint32_t cookiemap_code(uint64_t value64) { uint32_t value = (uint32_t)((value64 >> 32) + value64); uint32_t cookiecode = (value >> 24) & 0xff; + cookiecode = cookiecode * 31 + ((value >> 16) & 0xff); cookiecode = cookiecode * 31 + ((value >> 8) & 0xff); cookiecode = cookiecode * 31 + ((value >> 0) & 0xff); @@ -52,9 +55,8 @@ static uint32_t gator_chksum_crc32(const char *data) int i, length = strlen(data); crc = 0xFFFFFFFF; - for (i = 0; i < length; i++) { + for (i = 0; i < length; i++) crc = ((crc >> 8) & 0x00FFFFFF) ^ gator_crc32_table[(crc ^ *block++) & 0xFF]; - } return (crc ^ 0xFFFFFFFF); } @@ -72,11 +74,12 @@ static uint32_t cookiemap_exists(uint64_t key) uint64_t *keys = &(per_cpu(cookie_keys, cpu)[cookiecode]); uint32_t *values = &(per_cpu(cookie_values, cpu)[cookiecode]); - // Can be called from interrupt handler or from work queue + /* Can be called from interrupt handler or from work queue */ local_irq_save(flags); for (x = 0; x < MAX_COLLISIONS; x++) { if (keys[x] == key) { uint32_t value = values[x]; + for (; x > 0; x--) { keys[x] = keys[x - 1]; values[x] = values[x - 1]; @@ -126,7 +129,7 @@ static void translate_buffer_write_args(int cpu, struct task_struct *task, const write = per_cpu(translate_buffer_write, cpu); next_write = (write + 1) & translate_buffer_mask; - // At least one entry must always remain available as when read == write, the queue is empty not full + /* At least one entry must always remain available as when read == write, the queue is empty not full */ if (next_write != per_cpu(translate_buffer_read, cpu)) { args = &per_cpu(translate_buffer, cpu)[write]; args->task = task; @@ -178,11 +181,11 @@ static void wq_cookie_handler(struct work_struct *unused) static void app_process_wake_up_handler(unsigned long unused_data) { - // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater + /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */ schedule_work(&cookie_work); } -// Retrieve full name from proc/pid/cmdline for java processes on Android +/* Retrieve full name from proc/pid/cmdline for java processes on Android */ static int translate_app_process(const char **text, int cpu, struct task_struct *task, bool from_wq) { void *maddr; @@ -195,12 +198,16 @@ static int translate_app_process(const char **text, int cpu, struct task_struct char *buf = per_cpu(translate_text, cpu); #ifndef CONFIG_PREEMPT_RT_FULL - // Push work into a work queue if in atomic context as the kernel functions below might sleep - // Rely on the in_interrupt variable rather than in_irq() or in_interrupt() kernel functions, as the value of these functions seems - // inconsistent during a context switch between android/linux versions + /* Push work into a work queue if in atomic context as the kernel + * functions below might sleep. Rely on the in_interrupt variable + * rather than in_irq() or in_interrupt() kernel functions, as the + * value of these functions seems inconsistent during a context + * switch between android/linux versions + */ if (!from_wq) { - // Check if already in buffer + /* Check if already in buffer */ int pos = per_cpu(translate_buffer_read, cpu); + while (pos != per_cpu(translate_buffer_write, cpu)) { if (per_cpu(translate_buffer, cpu)[pos].task == task) goto out; @@ -209,7 +216,7 @@ static int translate_app_process(const char **text, int cpu, struct task_struct translate_buffer_write_args(cpu, task, *text); - // Not safe to call in RT-Preempt full in schedule switch context + /* Not safe to call in RT-Preempt full in schedule switch context */ mod_timer(&app_process_wake_up_timer, jiffies + 1); goto out; } @@ -239,7 +246,8 @@ static int translate_app_process(const char **text, int cpu, struct task_struct copy_from_user_page(page_vma, page, addr, buf, maddr + offset, bytes); - kunmap(page); // release page allocated by get_user_pages() + /* release page allocated by get_user_pages() */ + kunmap(page); page_cache_release(page); len -= bytes; @@ -250,7 +258,7 @@ static int translate_app_process(const char **text, int cpu, struct task_struct retval = 1; } - // On app_process startup, /proc/pid/cmdline is initially "zygote" then "" but changes after an initial startup period + /* On app_process startup, /proc/pid/cmdline is initially "zygote" then "" but changes after an initial startup period */ if (strcmp(*text, "zygote") == 0 || strcmp(*text, "") == 0) retval = 0; @@ -262,6 +270,8 @@ out: return retval; } +static const char APP_PROCESS[] = "app_process"; + static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, bool from_wq) { unsigned long flags, cookie; @@ -271,16 +281,16 @@ static uint32_t get_cookie(int cpu, struct task_struct *task, const char *text, key = (key << 32) | (uint32_t)task->tgid; cookie = cookiemap_exists(key); - if (cookie) { + if (cookie) return cookie; - } - if (strcmp(text, "app_process") == 0) { + /* On 64-bit android app_process can be app_process32 or app_process64 */ + if (strncmp(text, APP_PROCESS, sizeof(APP_PROCESS) - 1) == 0) { if (!translate_app_process(&text, cpu, task, from_wq)) return UNRESOLVED_COOKIE; } - // Can be called from interrupt handler or from work queue or from scheduler trace + /* Can be called from interrupt handler or from work queue or from scheduler trace */ local_irq_save(flags); cookie = UNRESOLVED_COOKIE; @@ -300,7 +310,7 @@ static int get_exec_cookie(int cpu, struct task_struct *task) struct mm_struct *mm = task->mm; const char *text; - // kernel threads have no address space + /* kernel threads have no address space */ if (!mm) return NO_COOKIE; @@ -355,7 +365,7 @@ static int cookies_initialize(void) per_cpu(cookie_next_key, cpu) = nr_cpu_ids + cpu; size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint64_t); - per_cpu(cookie_keys, cpu) = (uint64_t *)kmalloc(size, GFP_KERNEL); + per_cpu(cookie_keys, cpu) = kmalloc(size, GFP_KERNEL); if (!per_cpu(cookie_keys, cpu)) { err = -ENOMEM; goto cookie_setup_error; @@ -363,14 +373,14 @@ static int cookies_initialize(void) memset(per_cpu(cookie_keys, cpu), 0, size); size = COOKIEMAP_ENTRIES * MAX_COLLISIONS * sizeof(uint32_t); - per_cpu(cookie_values, cpu) = (uint32_t *)kmalloc(size, GFP_KERNEL); + per_cpu(cookie_values, cpu) = kmalloc(size, GFP_KERNEL); if (!per_cpu(cookie_values, cpu)) { err = -ENOMEM; goto cookie_setup_error; } memset(per_cpu(cookie_values, cpu), 0, size); - per_cpu(translate_buffer, cpu) = (struct cookie_args *)kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL); + per_cpu(translate_buffer, cpu) = kmalloc(TRANSLATE_BUFFER_SIZE, GFP_KERNEL); if (!per_cpu(translate_buffer, cpu)) { err = -ENOMEM; goto cookie_setup_error; @@ -379,16 +389,16 @@ static int cookies_initialize(void) per_cpu(translate_buffer_write, cpu) = 0; per_cpu(translate_buffer_read, cpu) = 0; - per_cpu(translate_text, cpu) = (char *)kmalloc(TRANSLATE_TEXT_SIZE, GFP_KERNEL); + per_cpu(translate_text, cpu) = kmalloc(TRANSLATE_TEXT_SIZE, GFP_KERNEL); if (!per_cpu(translate_text, cpu)) { err = -ENOMEM; goto cookie_setup_error; } } - // build CRC32 table + /* build CRC32 table */ poly = 0x04c11db7; - gator_crc32_table = (uint32_t *)kmalloc(256 * sizeof(uint32_t), GFP_KERNEL); + gator_crc32_table = kmalloc(256 * sizeof(*gator_crc32_table), GFP_KERNEL); if (!gator_crc32_table) { err = -ENOMEM; goto cookie_setup_error; @@ -396,11 +406,10 @@ static int cookies_initialize(void) for (i = 0; i < 256; i++) { crc = i; for (j = 8; j > 0; j--) { - if (crc & 1) { + if (crc & 1) crc = (crc >> 1) ^ poly; - } else { + else crc >>= 1; - } } gator_crc32_table[i] = crc; } diff --git a/drivers/gator/gator_events_armv6.c b/drivers/gator/gator_events_armv6.c index 353645622306..a157a0013302 100644 --- a/drivers/gator/gator_events_armv6.c +++ b/drivers/gator/gator_events_armv6.c @@ -8,7 +8,7 @@ #include "gator.h" -// gator_events_perf_pmu.c is used if perf is supported +/* gator_events_perf_pmu.c is used if perf is supported */ #if GATOR_NO_PERF_SUPPORT static const char *pmnc_name; @@ -28,7 +28,7 @@ static const char *pmnc_name; #define CCNT 2 #define CNTMAX (CCNT+1) -static int pmnc_counters = 0; +static int pmnc_counters; static unsigned long pmnc_enabled[CNTMAX]; static unsigned long pmnc_event[CNTMAX]; static unsigned long pmnc_key[CNTMAX]; @@ -45,6 +45,7 @@ static inline void armv6_pmnc_write(u32 val) static inline u32 armv6_pmnc_read(void) { u32 val; + asm volatile("mrc p15, 0, %0, c15, c12, 0" : "=r" (val)); return val; } @@ -52,6 +53,7 @@ static inline u32 armv6_pmnc_read(void) static void armv6_pmnc_reset_counter(unsigned int cnt) { u32 val = 0; + switch (cnt) { case CCNT: asm volatile("mcr p15, 0, %0, c15, c12, 1" : : "r" (val)); @@ -74,20 +76,18 @@ int gator_events_armv6_create_files(struct super_block *sb, struct dentry *root) for (i = PMN0; i <= CCNT; i++) { char buf[40]; - if (i == CCNT) { - snprintf(buf, sizeof buf, "ARM_%s_ccnt", pmnc_name); - } else { - snprintf(buf, sizeof buf, "ARM_%s_cnt%d", pmnc_name, i); - } + + if (i == CCNT) + snprintf(buf, sizeof(buf), "ARM_%s_ccnt", pmnc_name); + else + snprintf(buf, sizeof(buf), "ARM_%s_cnt%d", pmnc_name, i); dir = gatorfs_mkdir(sb, root, buf); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]); gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]); - if (i != CCNT) { + if (i != CCNT) gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]); - } } return 0; @@ -98,9 +98,8 @@ static int gator_events_armv6_online(int **buffer, bool migrate) unsigned int cnt, len = 0, cpu = smp_processor_id(); u32 pmnc; - if (armv6_pmnc_read() & PMCR_E) { + if (armv6_pmnc_read() & PMCR_E) armv6_pmnc_write(armv6_pmnc_read() & ~PMCR_E); - } /* initialize PMNC, reset overflow, D bit, C bit and P bit. */ armv6_pmnc_write(PMCR_OFL_PMN0 | PMCR_OFL_PMN1 | PMCR_OFL_CCNT | @@ -115,19 +114,18 @@ static int gator_events_armv6_online(int **buffer, bool migrate) event = pmnc_event[cnt] & 255; - // Set event (if destined for PMNx counters) - if (cnt == PMN0) { + /* Set event (if destined for PMNx counters) */ + if (cnt == PMN0) pmnc |= event << 20; - } else if (cnt == PMN1) { + else if (cnt == PMN1) pmnc |= event << 12; - } - // Reset counter + /* Reset counter */ armv6_pmnc_reset_counter(cnt); } armv6_pmnc_write(pmnc | PMCR_E); - // return zero values, no need to read as the counters were just reset + /* return zero values, no need to read as the counters were just reset */ for (cnt = PMN0; cnt <= CCNT; cnt++) { if (pmnc_enabled[cnt]) { per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; @@ -146,9 +144,8 @@ static int gator_events_armv6_offline(int **buffer, bool migrate) unsigned int cnt; armv6_pmnc_write(armv6_pmnc_read() & ~PMCR_E); - for (cnt = PMN0; cnt <= CCNT; cnt++) { + for (cnt = PMN0; cnt <= CCNT; cnt++) armv6_pmnc_reset_counter(cnt); - } return 0; } @@ -163,19 +160,19 @@ static void gator_events_armv6_stop(void) } } -static int gator_events_armv6_read(int **buffer) +static int gator_events_armv6_read(int **buffer, bool sched_switch) { int cnt, len = 0; int cpu = smp_processor_id(); - // a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled - if (!(armv6_pmnc_read() & PMCR_E)) { + /* a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled */ + if (!(armv6_pmnc_read() & PMCR_E)) return 0; - } for (cnt = PMN0; cnt <= CCNT; cnt++) { if (pmnc_enabled[cnt]) { u32 value = 0; + switch (cnt) { case CCNT: asm volatile("mrc p15, 0, %0, c15, c12, 1" : "=r" (value)); diff --git a/drivers/gator/gator_events_armv7.c b/drivers/gator/gator_events_armv7.c index bd8a9ba24e99..09c94220114c 100644 --- a/drivers/gator/gator_events_armv7.c +++ b/drivers/gator/gator_events_armv7.c @@ -15,16 +15,16 @@ #include "gator.h" -// gator_events_perf_pmu.c is used if perf is supported +/* gator_events_perf_pmu.c is used if perf is supported */ #if GATOR_NO_PERF_SUPPORT -// 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_MASK 0x3f /* Mask for writable bits */ -// ccnt reg +/* ccnt reg */ #define CCNT_REG (1 << 31) #define CCNT 0 @@ -49,6 +49,7 @@ inline void armv7_pmnc_write(u32 val) inline u32 armv7_pmnc_read(void) { u32 val; + asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); return val; } @@ -61,10 +62,10 @@ inline u32 armv7_ccnt_read(u32 reset_value) u32 val; local_irq_save(flags); - 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" (newval)); // new value - asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable + 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" (newval)); /* new value */ + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); /* enable */ local_irq_restore(flags); return val; @@ -79,11 +80,11 @@ inline u32 armv7_cntn_read(unsigned int cnt, u32 reset_value) u32 oldval; local_irq_save(flags); - 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" (oldval)); // read - asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (newval)); // new value - asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); // enable + 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" (oldval)); /* read */ + asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (newval)); /* new value */ + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (den)); /* enable */ local_irq_restore(flags); return oldval; @@ -92,13 +93,15 @@ inline u32 armv7_cntn_read(unsigned int cnt, u32 reset_value) static inline void armv7_pmnc_disable_interrupt(unsigned int cnt) { u32 val = cnt ? (1 << (cnt - CNT0)) : (1 << 31); + asm volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (val)); } inline u32 armv7_pmnc_reset_interrupt(void) { - // Get and reset overflow status flags + /* Get and reset overflow status flags */ u32 flags; + asm volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (flags)); flags &= 0x8000003f; asm volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (flags)); @@ -108,6 +111,7 @@ inline u32 armv7_pmnc_reset_interrupt(void) static inline u32 armv7_pmnc_enable_counter(unsigned int cnt) { u32 val = cnt ? (1 << (cnt - CNT0)) : CCNT_REG; + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (val)); return cnt; } @@ -115,6 +119,7 @@ static inline u32 armv7_pmnc_enable_counter(unsigned int cnt) static inline u32 armv7_pmnc_disable_counter(unsigned int cnt) { u32 val = cnt ? (1 << (cnt - CNT0)) : CCNT_REG; + asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (val)); return cnt; } @@ -122,15 +127,15 @@ static inline u32 armv7_pmnc_disable_counter(unsigned int cnt) static inline int armv7_pmnc_select_counter(unsigned int cnt) { u32 val = (cnt - CNT0); + asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val)); return cnt; } static inline void armv7_pmnc_write_evtsel(unsigned int cnt, u32 val) { - if (armv7_pmnc_select_counter(cnt) == cnt) { + if (armv7_pmnc_select_counter(cnt) == cnt) asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (val)); - } } static int gator_events_armv7_create_files(struct super_block *sb, struct dentry *root) @@ -140,20 +145,18 @@ static int gator_events_armv7_create_files(struct super_block *sb, struct dentry for (i = 0; i < pmnc_counters; 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); - } + + 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) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]); gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]); - if (i > 0) { + if (i > 0) gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]); - } } return 0; @@ -163,14 +166,13 @@ static int gator_events_armv7_online(int **buffer, bool migrate) { unsigned int cnt, len = 0, cpu = smp_processor_id(); - if (armv7_pmnc_read() & PMNC_E) { + 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); - // Reset overflow flags + /* Reset overflow flags */ armv7_pmnc_reset_interrupt(); for (cnt = CCNT; cnt < CNTMAX; cnt++) { @@ -179,28 +181,28 @@ static int gator_events_armv7_online(int **buffer, bool migrate) 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); armv7_pmnc_disable_interrupt(cnt); - // Reset counter + /* Reset counter */ cnt ? armv7_cntn_read(cnt, 0) : armv7_ccnt_read(0); - // Enable counter + /* Enable counter */ armv7_pmnc_enable_counter(cnt); } - // enable + /* enable */ armv7_pmnc_write(armv7_pmnc_read() | PMNC_E); - // return zero values, no need to read as the counters were just reset + /* return zero values, no need to read as the counters were just reset */ for (cnt = 0; cnt < pmnc_counters; cnt++) { if (pmnc_enabled[cnt]) { per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; @@ -216,7 +218,7 @@ static int gator_events_armv7_online(int **buffer, bool migrate) static int gator_events_armv7_offline(int **buffer, bool migrate) { - // disable all counters, including PMCCNTR; overflow IRQs will not be signaled + /* disable all counters, including PMCCNTR; overflow IRQs will not be signaled */ armv7_pmnc_write(armv7_pmnc_read() & ~PMNC_E); return 0; @@ -232,24 +234,23 @@ static void gator_events_armv7_stop(void) } } -static int gator_events_armv7_read(int **buffer) +static int gator_events_armv7_read(int **buffer, bool sched_switch) { int cnt, len = 0; int cpu = smp_processor_id(); - // a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled - if (!(armv7_pmnc_read() & PMNC_E)) { + /* a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled */ + if (!(armv7_pmnc_read() & PMNC_E)) return 0; - } for (cnt = 0; cnt < pmnc_counters; cnt++) { if (pmnc_enabled[cnt]) { int value; - if (cnt == CCNT) { + + if (cnt == CCNT) value = armv7_ccnt_read(0); - } else { + else value = armv7_cntn_read(cnt, 0); - } per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; per_cpu(perfCnt, cpu)[len++] = value; } @@ -290,17 +291,16 @@ int gator_events_armv7_init(void) pmnc_name = "ARMv7_Cortex_A9"; pmnc_counters = 6; break; - // ARM Cortex A12 is not supported by version of Linux before 3.0 case CORTEX_A15: pmnc_name = "ARMv7_Cortex_A15"; pmnc_counters = 6; break; - // ARM Cortex A17 is not supported by version of Linux before 3.0 + /* ARM Cortex A17 is not supported by version of Linux before 3.0 */ default: return -1; } - pmnc_counters++; // CNT[n] + CCNT + pmnc_counters++; /* CNT[n] + CCNT */ for (cnt = CCNT; cnt < CNTMAX; cnt++) { pmnc_enabled[cnt] = 0; diff --git a/drivers/gator/gator_events_block.c b/drivers/gator/gator_events_block.c index 03eed4fb9ebb..a352a54afa02 100644 --- a/drivers/gator/gator_events_block.c +++ b/drivers/gator/gator_events_block.c @@ -28,7 +28,7 @@ static ulong block_rq_rd_key; static atomic_t blockCnt[BLOCK_TOTAL]; static int blockGet[BLOCK_TOTAL * 4]; -// Tracepoint changed in 3.15 backported to older kernels. The Makefile tries to autodetect the correct value, but if it fails change the #if below +/* Tracepoint changed in 3.15 backported to older kernels. The Makefile tries to autodetect the correct value, but if it fails change the #if below */ #if OLD_BLOCK_RQ_COMPLETE GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct request *rq)) #else @@ -52,13 +52,11 @@ GATOR_DEFINE_PROBE(block_rq_complete, TP_PROTO(struct request_queue *q, struct r return; if (write) { - if (block_rq_wr_enabled) { + if (block_rq_wr_enabled) atomic_add(size, &blockCnt[BLOCK_RQ_WR]); - } } else { - if (block_rq_rd_enabled) { + if (block_rq_rd_enabled) atomic_add(size, &blockCnt[BLOCK_RQ_RD]); - } } } @@ -68,17 +66,15 @@ static int gator_events_block_create_files(struct super_block *sb, struct dentry /* block_complete_wr */ dir = gatorfs_mkdir(sb, root, "Linux_block_rq_wr"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &block_rq_wr_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &block_rq_wr_key); /* block_complete_rd */ dir = gatorfs_mkdir(sb, root, "Linux_block_rq_rd"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &block_rq_rd_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &block_rq_rd_key); @@ -87,7 +83,7 @@ static int gator_events_block_create_files(struct super_block *sb, struct dentry static int gator_events_block_start(void) { - // register tracepoints + /* register tracepoints */ if (block_rq_wr_enabled || block_rq_rd_enabled) if (GATOR_REGISTER_TRACE(block_rq_complete)) goto fail_block_rq_exit; @@ -95,7 +91,7 @@ static int gator_events_block_start(void) return 0; - // unregister tracepoints on error + /* unregister tracepoints on error */ fail_block_rq_exit: pr_err("gator: block event tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n"); @@ -112,19 +108,19 @@ static void gator_events_block_stop(void) block_rq_rd_enabled = 0; } -static int gator_events_block_read(int **buffer) +static int gator_events_block_read(int **buffer, bool sched_switch) { int len, value, data = 0; - if (!on_primary_core()) { + if (!on_primary_core()) return 0; - } len = 0; if (block_rq_wr_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_WR])) > 0) { atomic_sub(value, &blockCnt[BLOCK_RQ_WR]); blockGet[len++] = block_rq_wr_key; - blockGet[len++] = 0; // indicates to Streamline that value bytes were written now, not since the last message + /* Indicates to Streamline that value bytes were written now, not since the last message */ + blockGet[len++] = 0; blockGet[len++] = block_rq_wr_key; blockGet[len++] = value; data += value; @@ -132,7 +128,8 @@ static int gator_events_block_read(int **buffer) if (block_rq_rd_enabled && (value = atomic_read(&blockCnt[BLOCK_RQ_RD])) > 0) { atomic_sub(value, &blockCnt[BLOCK_RQ_RD]); blockGet[len++] = block_rq_rd_key; - blockGet[len++] = 0; // indicates to Streamline that value bytes were read now, not since the last message + /* Indicates to Streamline that value bytes were read now, not since the last message */ + blockGet[len++] = 0; blockGet[len++] = block_rq_rd_key; blockGet[len++] = value; data += value; diff --git a/drivers/gator/gator_events_ccn-504.c b/drivers/gator/gator_events_ccn-504.c deleted file mode 100644 index 024ffc2856aa..000000000000 --- a/drivers/gator/gator_events_ccn-504.c +++ /dev/null @@ -1,346 +0,0 @@ -/** - * Copyright (C) ARM Limited 2013-2014. 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 -#include - -#include "gator.h" - -#define NUM_REGIONS 256 -#define REGION_SIZE (64*1024) -#define REGION_DEBUG 1 -#define REGION_XP 64 -#define NUM_XPS 11 - -// DT (Debug) region -#define PMEVCNTSR0 0x0150 -#define PMCCNTRSR 0x0190 -#define PMCR 0x01A8 -#define PMSR 0x01B0 -#define PMSR_REQ 0x01B8 -#define PMSR_CLR 0x01C0 - -// XP region -#define DT_CONFIG 0x0300 -#define DT_CONTROL 0x0370 - -// Multiple -#define PMU_EVENT_SEL 0x0600 -#define OLY_ID 0xFF00 - -#define CCNT 4 -#define CNTMAX (CCNT + 1) - -#define get_pmu_event_id(event) (((event) >> 0) & 0xFF) -#define get_node_type(event) (((event) >> 8) & 0xFF) -#define get_region(event) (((event) >> 16) & 0xFF) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) - -// From kernel/params.c -#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ - int param_set_##name(const char *val, struct kernel_param *kp) \ - { \ - tmptype l; \ - int ret; \ - \ - if (!val) return -EINVAL; \ - ret = strtolfn(val, 0, &l); \ - if (ret == -EINVAL || ((type)l != l)) \ - return -EINVAL; \ - *((type *)kp->arg) = l; \ - return 0; \ - } \ - int param_get_##name(char *buffer, struct kernel_param *kp) \ - { \ - return sprintf(buffer, format, *((type *)kp->arg)); \ - } - -#else - -// From kernel/params.c -#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ - int param_set_##name(const char *val, const struct kernel_param *kp) \ - { \ - tmptype l; \ - int ret; \ - \ - ret = strtolfn(val, 0, &l); \ - if (ret < 0 || ((type)l != l)) \ - return ret < 0 ? ret : -EINVAL; \ - *((type *)kp->arg) = l; \ - return 0; \ - } \ - int param_get_##name(char *buffer, const struct kernel_param *kp) \ - { \ - return scnprintf(buffer, PAGE_SIZE, format, \ - *((type *)kp->arg)); \ - } \ - struct kernel_param_ops param_ops_##name = { \ - .set = param_set_##name, \ - .get = param_get_##name, \ - }; \ - EXPORT_SYMBOL(param_set_##name); \ - EXPORT_SYMBOL(param_get_##name); \ - EXPORT_SYMBOL(param_ops_##name) - -#endif - -STANDARD_PARAM_DEF(u64, u64, "%llu", u64, strict_strtoull); - -// From include/linux/moduleparam.h -#define param_check_u64(name, p) __param_check(name, p, u64) - -MODULE_PARM_DESC(ccn504_addr, "CCN-504 physical base address"); -static u64 ccn504_addr = 0; -module_param(ccn504_addr, u64, 0444); - -static void __iomem *gator_events_ccn504_base; -static bool gator_events_ccn504_global_enabled; -static unsigned long gator_events_ccn504_enabled[CNTMAX]; -static unsigned long gator_events_ccn504_event[CNTMAX]; -static unsigned long gator_events_ccn504_key[CNTMAX]; -static int gator_events_ccn504_buffer[2*CNTMAX]; -static int gator_events_ccn504_prev[CNTMAX]; - -static void gator_events_ccn504_create_shutdown(void) -{ - if (gator_events_ccn504_base != NULL) { - iounmap(gator_events_ccn504_base); - } -} - -static int gator_events_ccn504_create_files(struct super_block *sb, struct dentry *root) -{ - struct dentry *dir; - int i; - char buf[32]; - - for (i = 0; i < CNTMAX; ++i) { - if (i == CCNT) { - snprintf(buf, sizeof(buf), "CCN-504_ccnt"); - } else { - snprintf(buf, sizeof(buf), "CCN-504_cnt%i", i); - } - dir = gatorfs_mkdir(sb, root, buf); - if (!dir) { - return -1; - } - - gatorfs_create_ulong(sb, dir, "enabled", &gator_events_ccn504_enabled[i]); - if (i != CCNT) { - gatorfs_create_ulong(sb, dir, "event", &gator_events_ccn504_event[i]); - } - gatorfs_create_ro_ulong(sb, dir, "key", &gator_events_ccn504_key[i]); - } - - return 0; -} - -static void gator_events_ccn504_set_dt_config(int xp_node_id, int event_num, int value) -{ - u32 dt_config; - - dt_config = readl(gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG); - dt_config |= (value + event_num) << (4*event_num); - writel(dt_config, gator_events_ccn504_base + (REGION_XP + xp_node_id)*REGION_SIZE + DT_CONFIG); -} - -static int gator_events_ccn504_start(void) -{ - int i; - - gator_events_ccn504_global_enabled = 0; - for (i = 0; i < CNTMAX; ++i) { - if (gator_events_ccn504_enabled[i]) { - gator_events_ccn504_global_enabled = 1; - break; - } - } - - if (!gator_events_ccn504_global_enabled) { - return 0; - } - - memset(&gator_events_ccn504_prev, 0x80, sizeof(gator_events_ccn504_prev)); - - // Disable INTREQ on overflow - // [6] ovfl_intr_en = 0 - // perhaps set to 1? - // [5] cntr_rst = 0 - // No register paring - // [4:1] cntcfg = 0 - // Enable PMU features - // [0] pmu_en = 1 - writel(0x1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMCR); - - // Configure the XPs - for (i = 0; i < NUM_XPS; ++i) { - int dt_control; - - // Pass on all events - writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG); - - // Enable PMU capability - // [0] dt_enable = 1 - dt_control = readl(gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL); - dt_control |= 0x1; - writel(dt_control, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONTROL); - } - - // Assume no other pmu_event_sel registers are set - - // cycle counter does not need to be enabled - for (i = 0; i < CCNT; ++i) { - int pmu_event_id; - int node_type; - int region; - u32 pmu_event_sel; - u32 oly_id_whole; - u32 oly_id; - u32 node_id; - - if (!gator_events_ccn504_enabled[i]) { - continue; - } - - pmu_event_id = get_pmu_event_id(gator_events_ccn504_event[i]); - node_type = get_node_type(gator_events_ccn504_event[i]); - region = get_region(gator_events_ccn504_event[i]); - - // Verify the node_type - oly_id_whole = readl(gator_events_ccn504_base + region*REGION_SIZE + OLY_ID); - oly_id = oly_id_whole & 0x1F; - node_id = (oly_id_whole >> 8) & 0x7F; - if ((oly_id != node_type) || - ((node_type == 0x16) && ((oly_id != 0x14) && (oly_id != 0x15) && (oly_id != 0x16) && (oly_id != 0x18) && (oly_id != 0x19) && (oly_id != 0x1A)))) { - printk(KERN_ERR "gator: oly_id is 0x%x expected 0x%x\n", oly_id, node_type); - return -1; - } - - // Set the control register - pmu_event_sel = readl(gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL); - switch (node_type) { - case 0x08: // XP - pmu_event_sel |= pmu_event_id << (7*i); - gator_events_ccn504_set_dt_config(node_id, i, 0x4); - break; - case 0x04: // HN-F - case 0x16: // RN-I - case 0x10: // SBAS - pmu_event_sel |= pmu_event_id << (4*i); - gator_events_ccn504_set_dt_config(node_id/2, i, (node_id & 1) == 0 ? 0x8 : 0xC); - break; - } - writel(pmu_event_sel, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL); - } - - return 0; -} - -static void gator_events_ccn504_stop(void) -{ - int i; - - if (!gator_events_ccn504_global_enabled) { - return; - } - - // cycle counter does not need to be disabled - for (i = 0; i < CCNT; ++i) { - int region; - - if (!gator_events_ccn504_enabled[i]) { - continue; - } - - region = get_region(gator_events_ccn504_event[i]); - - writel(0, gator_events_ccn504_base + region*REGION_SIZE + PMU_EVENT_SEL); - } - - // Clear dt_config - for (i = 0; i < NUM_XPS; ++i) { - writel(0, gator_events_ccn504_base + (REGION_XP + i)*REGION_SIZE + DT_CONFIG); - } -} - -static int gator_events_ccn504_read(int **buffer) -{ - int i; - int len = 0; - int value; - - if (!on_primary_core() || !gator_events_ccn504_global_enabled) { - return 0; - } - - // Verify the pmsr register is zero - while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) != 0); - - // Request a PMU snapshot - writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_REQ); - - // Wait for the snapshot - while (readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR) == 0); - - // Read the shadow registers - for (i = 0; i < CNTMAX; ++i) { - if (!gator_events_ccn504_enabled[i]) { - continue; - } - - value = readl(gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + (i == CCNT ? PMCCNTRSR : PMEVCNTSR0 + 8*i)); - if (gator_events_ccn504_prev[i] != 0x80808080) { - gator_events_ccn504_buffer[len++] = gator_events_ccn504_key[i]; - gator_events_ccn504_buffer[len++] = value - gator_events_ccn504_prev[i]; - } - gator_events_ccn504_prev[i] = value; - - // Are the counters registers cleared when read? Is that what the cntr_rst bit on the pmcr register does? - } - - // Clear the PMU snapshot status - writel(1, gator_events_ccn504_base + REGION_DEBUG*REGION_SIZE + PMSR_CLR); - - if (buffer) - *buffer = gator_events_ccn504_buffer; - - return len; -} - -static struct gator_interface gator_events_ccn504_interface = { - .shutdown = gator_events_ccn504_create_shutdown, - .create_files = gator_events_ccn504_create_files, - .start = gator_events_ccn504_start, - .stop = gator_events_ccn504_stop, - .read = gator_events_ccn504_read, -}; - -int gator_events_ccn504_init(void) -{ - int i; - - if (ccn504_addr == 0) { - return -1; - } - - gator_events_ccn504_base = ioremap(ccn504_addr, NUM_REGIONS*REGION_SIZE); - if (gator_events_ccn504_base == NULL) { - printk(KERN_ERR "gator: ioremap returned NULL\n"); - return -1; - } - - for (i = 0; i < CNTMAX; ++i) { - gator_events_ccn504_enabled[i] = 0; - gator_events_ccn504_event[i] = 0; - gator_events_ccn504_key[i] = gator_events_get_key(); - } - - return gator_events_install(&gator_events_ccn504_interface); -} diff --git a/drivers/gator/gator_events_irq.c b/drivers/gator/gator_events_irq.c index facbdd62325e..5221aac581b3 100644 --- a/drivers/gator/gator_events_irq.c +++ b/drivers/gator/gator_events_irq.c @@ -42,17 +42,15 @@ static int gator_events_irq_create_files(struct super_block *sb, struct dentry * /* irq */ dir = gatorfs_mkdir(sb, root, "Linux_irq_irq"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &hardirq_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &hardirq_key); /* soft irq */ dir = gatorfs_mkdir(sb, root, "Linux_irq_softirq"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &softirq_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &softirq_key); @@ -63,7 +61,7 @@ static int gator_events_irq_online(int **buffer, bool migrate) { int len = 0, cpu = get_physical_cpu(); - // synchronization with the irq_exit functions is not necessary as the values are being reset + /* synchronization with the irq_exit functions is not necessary as the values are being reset */ if (hardirq_enabled) { atomic_set(&per_cpu(irqCnt, cpu)[HARDIRQ], 0); per_cpu(irqGet, cpu)[len++] = hardirq_key; @@ -84,7 +82,7 @@ static int gator_events_irq_online(int **buffer, bool migrate) static int gator_events_irq_start(void) { - // register tracepoints + /* register tracepoints */ if (hardirq_enabled) if (GATOR_REGISTER_TRACE(irq_handler_exit)) goto fail_hardirq_exit; @@ -95,7 +93,7 @@ static int gator_events_irq_start(void) return 0; - // unregister tracepoints on error + /* unregister tracepoints on error */ fail_softirq_exit: if (hardirq_enabled) GATOR_UNREGISTER_TRACE(irq_handler_exit); @@ -117,7 +115,7 @@ static void gator_events_irq_stop(void) softirq_enabled = 0; } -static int gator_events_irq_read(int **buffer) +static int gator_events_irq_read(int **buffer, bool sched_switch) { int len, value; int cpu = get_physical_cpu(); diff --git a/drivers/gator/gator_events_l2c-310.c b/drivers/gator/gator_events_l2c-310.c index 553f9707bdbf..73aaac32327e 100644 --- a/drivers/gator/gator_events_l2c-310.c +++ b/drivers/gator/gator_events_l2c-310.c @@ -91,7 +91,7 @@ static void gator_events_l2c310_stop(void) writel(0, l2c310_base + L2X0_EVENT_CNT_CTRL); } -static int gator_events_l2c310_read(int **buffer) +static int gator_events_l2c310_read(int **buffer, bool sched_switch) { static const unsigned long l2x0_event_cntx_val[L2C310_COUNTERS_NUM] = { L2X0_EVENT_CNT0_VAL, @@ -149,8 +149,8 @@ static void __iomem *gator_events_l2c310_probe(void) 0xa0412000, #endif #if defined(CONFIG_ARCH_VEXPRESS) - 0x1e00a000, // A9x4 core tile (HBI-0191) - 0x2c0f0000, // New memory map tiles + 0x1e00a000, /* A9x4 core tile (HBI-0191) */ + 0x2c0f0000, /* New memory map tiles */ #endif }; int i; diff --git a/drivers/gator/gator_events_mali_4xx.c b/drivers/gator/gator_events_mali_4xx.c index 9e1c7064bd73..9cf43fe2c29b 100644 --- a/drivers/gator/gator_events_mali_4xx.c +++ b/drivers/gator/gator_events_mali_4xx.c @@ -36,7 +36,7 @@ #elif GATOR_MALI_INTERFACE_STYLE == 2 #error GATOR_MALI_INTERFACE_STYLE 2 is obsolete #elif GATOR_MALI_INTERFACE_STYLE >= 3 -// Valid GATOR_MALI_INTERFACE_STYLE +/* Valid GATOR_MALI_INTERFACE_STYLE */ #else #error Unknown GATOR_MALI_INTERFACE_STYLE option. #endif @@ -54,7 +54,7 @@ #error MALI_SUPPORT set to an invalid device code: expecting MALI_4xx #endif -static const char mali_name[] = "Mali-4xx"; +static const char mali_name[] = "4xx"; /* gatorfs variables for counter enable state, * the event the counter should count and the @@ -73,8 +73,8 @@ static u32 *counter_address[NUMBER_OF_EVENTS]; /* An array used to return the data we recorded * as key,value pairs hence the *2 */ -static unsigned long counter_dump[NUMBER_OF_EVENTS * 2]; -static unsigned long counter_prev[NUMBER_OF_EVENTS]; +static int counter_dump[NUMBER_OF_EVENTS * 2]; +static int counter_prev[NUMBER_OF_EVENTS]; static bool prev_set[NUMBER_OF_EVENTS]; /* Note whether tracepoints have been registered */ @@ -89,8 +89,8 @@ static unsigned int n_vp_cores = MAX_NUM_VP_CORES; static unsigned int n_l2_cores = MAX_NUM_L2_CACHE_CORES; static unsigned int n_fp_cores = MAX_NUM_FP_CORES; -extern mali_counter mali_activity[2]; -static const char* const mali_activity_names[] = { +extern struct mali_counter mali_activity[2]; +static const char *const mali_activity_names[] = { "fragment", "vertex", }; @@ -112,36 +112,11 @@ static inline int is_hw_counter(unsigned int event_id) return (event_id >= FIRST_HW_COUNTER && event_id <= LAST_HW_COUNTER); } -/* - * These are provided for utgard compatibility. - */ -typedef void _mali_profiling_get_mali_version_type(struct _mali_profiling_mali_version *values); -typedef u32 _mali_profiling_get_l2_counters_type(_mali_profiling_l2_counter_values *values); - -/* Probe for continuously sampled counter */ -#if 0 //WE_DONT_CURRENTLY_USE_THIS_SO_SUPPRESS_WARNING -GATOR_DEFINE_PROBE(mali_sample_address, TP_PROTO(unsigned int event_id, u32 *addr)) -{ - /* Turning on too many pr_debug statements in frequently called functions - * can cause stability and/or performance problems - */ - //pr_debug("gator: mali_sample_address %d %d\n", event_id, addr); - if (event_id >= ACTIVITY_VP && event_id <= COUNTER_FP3_C1) { - counter_address[event_id] = addr; - } -} -#endif - /* Probe for hardware counter events */ GATOR_DEFINE_PROBE(mali_hw_counter, TP_PROTO(unsigned int event_id, unsigned int value)) { - /* Turning on too many pr_debug statements in frequently called functions - * can cause stability and/or performance problems - */ - //pr_debug("gator: mali_hw_counter %d %d\n", event_id, value); - if (is_hw_counter(event_id)) { + if (is_hw_counter(event_id)) counter_data[event_id] = value; - } } GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surface_id, unsigned int *counters)) @@ -150,9 +125,8 @@ GATOR_DEFINE_PROBE(mali_sw_counters, TP_PROTO(pid_t pid, pid_t tid, void *surfac /* Copy over the values for those counters which are enabled. */ for (i = FIRST_SW_COUNTER; i <= LAST_SW_COUNTER; i++) { - if (counter_enabled[i]) { + if (counter_enabled[i]) counter_data[i] = (u32)(counters[i - FIRST_SW_COUNTER]); - } } } @@ -172,13 +146,11 @@ static int create_fs_entry(struct super_block *sb, struct dentry *root, const ch dir = gatorfs_mkdir(sb, root, name); - if (!dir) { + if (!dir) return -1; - } - if (create_event_item) { + if (create_event_item) gatorfs_create_ulong(sb, dir, "event", &counter_event[event]); - } gatorfs_create_ulong(sb, dir, "enabled", &counter_enabled[event]); gatorfs_create_ro_ulong(sb, dir, "key", &counter_key[event]); @@ -192,7 +164,7 @@ static int create_fs_entry(struct super_block *sb, struct dentry *root, const ch */ static void initialise_version_info(void) { - _mali_profiling_get_mali_version_type *mali_profiling_get_mali_version_symbol; + void (*mali_profiling_get_mali_version_symbol)(struct _mali_profiling_mali_version *values); mali_profiling_get_mali_version_symbol = symbol_get(_mali_profiling_get_mali_version); @@ -214,8 +186,8 @@ static void initialise_version_info(void) /* Release the function - we're done with it. */ symbol_put(_mali_profiling_get_mali_version); } else { - printk("gator: mali online _mali_profiling_get_mali_version symbol not found\n"); - printk("gator: check your Mali DDK version versus the GATOR_MALI_INTERFACE_STYLE setting\n"); + pr_err("gator: mali online _mali_profiling_get_mali_version symbol not found\n"); + pr_err("gator: check your Mali DDK version versus the GATOR_MALI_INTERFACE_STYLE setting\n"); } } #endif @@ -242,26 +214,24 @@ static int create_files(struct super_block *sb, struct dentry *root) mali_activity[0].cores = n_fp_cores; mali_activity[1].cores = n_vp_cores; for (event = 0; event < ARRAY_SIZE(mali_activity); event++) { - if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) { + if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) return -1; - } } /* Vertex processor counters */ for (core_id = 0; core_id < n_vp_cores; core_id++) { int activity_counter_id = ACTIVITY_VP_0; - snprintf(buf, sizeof buf, "ARM_%s_VP_%d_active", mali_name, core_id); - if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) { + + snprintf(buf, sizeof(buf), "ARM_Mali-%s_VP_%d_active", mali_name, core_id); + if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) return -1; - } for (counter_number = 0; counter_number < 2; counter_number++) { int counter_id = COUNTER_VP_0_C0 + (2 * core_id) + counter_number; - snprintf(buf, sizeof buf, "ARM_%s_VP_%d_cnt%d", mali_name, core_id, counter_number); - if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) { + snprintf(buf, sizeof(buf), "ARM_Mali-%s_VP_%d_cnt%d", mali_name, core_id, counter_number); + if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) return -1; - } } } @@ -269,18 +239,16 @@ static int create_files(struct super_block *sb, struct dentry *root) for (core_id = 0; core_id < n_fp_cores; core_id++) { int activity_counter_id = ACTIVITY_FP_0 + core_id; - snprintf(buf, sizeof buf, "ARM_%s_FP_%d_active", mali_name, core_id); - if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) { + snprintf(buf, sizeof(buf), "ARM_Mali-%s_FP_%d_active", mali_name, core_id); + if (create_fs_entry(sb, root, buf, activity_counter_id, 0) != 0) return -1; - } for (counter_number = 0; counter_number < 2; counter_number++) { int counter_id = COUNTER_FP_0_C0 + (2 * core_id) + counter_number; - snprintf(buf, sizeof buf, "ARM_%s_FP_%d_cnt%d", mali_name, core_id, counter_number); - if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) { + snprintf(buf, sizeof(buf), "ARM_Mali-%s_FP_%d_cnt%d", mali_name, core_id, counter_number); + if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) return -1; - } } } @@ -289,38 +257,33 @@ static int create_files(struct super_block *sb, struct dentry *root) for (counter_number = 0; counter_number < 2; counter_number++) { int counter_id = COUNTER_L2_0_C0 + (2 * core_id) + counter_number; - snprintf(buf, sizeof buf, "ARM_%s_L2_%d_cnt%d", mali_name, core_id, counter_number); - if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) { + snprintf(buf, sizeof(buf), "ARM_Mali-%s_L2_%d_cnt%d", mali_name, core_id, counter_number); + if (create_fs_entry(sb, root, buf, counter_id, 1) != 0) return -1; - } } } /* Now set up the software counter entries */ for (event = FIRST_SW_COUNTER; event <= LAST_SW_COUNTER; event++) { - snprintf(buf, sizeof(buf), "ARM_%s_SW_%d", mali_name, event - FIRST_SW_COUNTER); + snprintf(buf, sizeof(buf), "ARM_Mali-%s_SW_%d", mali_name, event - FIRST_SW_COUNTER); - if (create_fs_entry(sb, root, buf, event, 0) != 0) { + if (create_fs_entry(sb, root, buf, event, 0) != 0) return -1; - } } /* Now set up the special counter entries */ - snprintf(buf, sizeof(buf), "ARM_%s_Filmstrip_cnt0", mali_name); - if (create_fs_entry(sb, root, buf, COUNTER_FILMSTRIP, 1) != 0) { + snprintf(buf, sizeof(buf), "ARM_Mali-%s_Filmstrip_cnt0", mali_name); + if (create_fs_entry(sb, root, buf, COUNTER_FILMSTRIP, 1) != 0) return -1; - } #ifdef DVFS_REPORTED_BY_DDK - snprintf(buf, sizeof(buf), "ARM_%s_Frequency", mali_name); - if (create_fs_entry(sb, root, buf, COUNTER_FREQUENCY, 1) != 0) { + snprintf(buf, sizeof(buf), "ARM_Mali-%s_Frequency", mali_name); + if (create_fs_entry(sb, root, buf, COUNTER_FREQUENCY, 1) != 0) return -1; - } - snprintf(buf, sizeof(buf), "ARM_%s_Voltage", mali_name); - if (create_fs_entry(sb, root, buf, COUNTER_VOLTAGE, 1) != 0) { + snprintf(buf, sizeof(buf), "ARM_Mali-%s_Voltage", mali_name); + if (create_fs_entry(sb, root, buf, COUNTER_VOLTAGE, 1) != 0) return -1; - } #endif return 0; @@ -330,8 +293,8 @@ static int create_files(struct super_block *sb, struct dentry *root) * Local store for the get_counters entry point into the DDK. * This is stored here since it is used very regularly. */ -static mali_profiling_get_counters_type *mali_get_counters = NULL; -static _mali_profiling_get_l2_counters_type *mali_get_l2_counters = NULL; +static void (*mali_get_counters)(unsigned int *, unsigned int *, unsigned int *, unsigned int *); +static u32 (*mali_get_l2_counters)(struct _mali_profiling_l2_counter_values *values); /* * Examine list of counters between two index limits and determine if any one is enabled. @@ -342,9 +305,8 @@ static int is_any_counter_enabled(unsigned int first_counter, unsigned int last_ unsigned int i; for (i = first_counter; i <= last_counter; i++) { - if (counter_enabled[i]) { + if (counter_enabled[i]) return 1; /* At least one counter is enabled */ - } } return 0; /* No s/w counters enabled */ @@ -366,16 +328,15 @@ static void init_counters(unsigned int from_counter, unsigned int to_counter) pr_debug("gator: mali online _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event); for (counter_id = from_counter; counter_id <= to_counter; counter_id++) { - if (counter_enabled[counter_id]) { + if (counter_enabled[counter_id]) mali_set_hw_event(counter_id, counter_event[counter_id]); - } else { + else mali_set_hw_event(counter_id, 0xFFFFFFFF); - } } symbol_put(_mali_profiling_set_event); } else { - printk("gator: mali online _mali_profiling_set_event symbol not found\n"); + pr_err("gator: mali online _mali_profiling_set_event symbol not found\n"); } } @@ -407,27 +368,23 @@ static void mali_counter_initialize(void) symbol_put(_mali_profiling_control); } else { - printk("gator: mali online _mali_profiling_control symbol not found\n"); + pr_err("gator: mali online _mali_profiling_control symbol not found\n"); } mali_get_counters = symbol_get(_mali_profiling_get_counters); - if (mali_get_counters) { + if (mali_get_counters) pr_debug("gator: mali online _mali_profiling_get_counters symbol @ %p\n", mali_get_counters); - - } else { - pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined"); - } + else + pr_debug("gator WARNING: mali _mali_profiling_get_counters symbol not defined\n"); mali_get_l2_counters = symbol_get(_mali_profiling_get_l2_counters); - if (mali_get_l2_counters) { + if (mali_get_l2_counters) pr_debug("gator: mali online _mali_profiling_get_l2_counters symbol @ %p\n", mali_get_l2_counters); - - } else { - pr_debug("gator WARNING: mali _mali_profiling_get_l2_counters symbol not defined"); - } + else + pr_debug("gator WARNING: mali _mali_profiling_get_l2_counters symbol not defined\n"); if (!mali_get_counters && !mali_get_l2_counters) { - pr_debug("gator: WARNING: no L2 counters available"); + pr_debug("gator: WARNING: no L2 counters available\n"); n_l2_cores = 0; } @@ -449,13 +406,12 @@ static void mali_counter_deinitialize(void) int i; pr_debug("gator: mali offline _mali_profiling_set_event symbol @ %p\n", mali_set_hw_event); - for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) { + for (i = FIRST_HW_COUNTER; i <= LAST_HW_COUNTER; i++) mali_set_hw_event(i, 0xFFFFFFFF); - } symbol_put(_mali_profiling_set_event); } else { - printk("gator: mali offline _mali_profiling_set_event symbol not found\n"); + pr_err("gator: mali offline _mali_profiling_set_event symbol not found\n"); } /* Generic control interface for Mali DDK. */ @@ -471,29 +427,27 @@ static void mali_counter_deinitialize(void) symbol_put(_mali_profiling_control); } else { - printk("gator: mali offline _mali_profiling_control symbol not found\n"); + pr_err("gator: mali offline _mali_profiling_control symbol not found\n"); } - if (mali_get_counters) { + if (mali_get_counters) symbol_put(_mali_profiling_get_counters); - } - if (mali_get_l2_counters) { + if (mali_get_l2_counters) symbol_put(_mali_profiling_get_l2_counters); - } } static int start(void) { - // register tracepoints + /* register tracepoints */ if (GATOR_REGISTER_TRACE(mali_hw_counter)) { - printk("gator: mali_hw_counter tracepoint failed to activate\n"); + pr_err("gator: mali_hw_counter tracepoint failed to activate\n"); return -1; } /* For Mali drivers with built-in support. */ if (GATOR_REGISTER_TRACE(mali_sw_counters)) { - printk("gator: mali_sw_counters tracepoint failed to activate\n"); + pr_err("gator: mali_sw_counters tracepoint failed to activate\n"); return -1; } @@ -543,17 +497,17 @@ static void dump_counters(unsigned int from_counter, unsigned int to_counter, un } } -static int read(int **buffer) +static int read(int **buffer, bool sched_switch) { int len = 0; if (!on_primary_core()) return 0; - // Read the L2 C0 and C1 here. + /* Read the L2 C0 and C1 here. */ if (n_l2_cores > 0 && is_any_counter_enabled(COUNTER_L2_0_C0, COUNTER_L2_0_C0 + (2 * n_l2_cores))) { unsigned int unavailable_l2_caches = 0; - _mali_profiling_l2_counter_values cache_values; + struct _mali_profiling_l2_counter_values cache_values; unsigned int cache_id; struct _mali_profiling_core_counters *per_core; @@ -572,25 +526,24 @@ static int read(int **buffer) unsigned int counter_id_0 = COUNTER_L2_0_C0 + (2 * cache_id); unsigned int counter_id_1 = counter_id_0 + 1; - if ((1 << cache_id) & unavailable_l2_caches) { + if ((1 << cache_id) & unavailable_l2_caches) continue; /* This cache is unavailable (powered-off, possibly). */ - } per_core = &cache_values.cores[cache_id]; if (counter_enabled[counter_id_0] && prev_set[counter_id_0]) { - // Calculate and save src0's counter val0 + /* Calculate and save src0's counter val0 */ counter_dump[len++] = counter_key[counter_id_0]; counter_dump[len++] = per_core->value0 - counter_prev[counter_id_0]; } if (counter_enabled[counter_id_1] && prev_set[counter_id_1]) { - // Calculate and save src1's counter val1 + /* Calculate and save src1's counter val1 */ counter_dump[len++] = counter_key[counter_id_1]; counter_dump[len++] = per_core->value1 - counter_prev[counter_id_1]; } - // Save the previous values for the counters. + /* Save the previous values for the counters. */ counter_prev[counter_id_0] = per_core->value0; prev_set[counter_id_0] = true; counter_prev[counter_id_1] = per_core->value1; @@ -608,8 +561,9 @@ static int read(int **buffer) { int cnt; /* - * Add in the voltage and frequency counters if enabled. Note that, since these are - * actually passed as events, the counter value should not be cleared. + * Add in the voltage and frequency counters if enabled. Note + * that, since these are actually passed as events, the counter + * value should not be cleared. */ cnt = COUNTER_FREQUENCY; if (counter_enabled[cnt]) { @@ -625,9 +579,8 @@ static int read(int **buffer) } #endif - if (buffer) { - *buffer = (int *)counter_dump; - } + if (buffer) + *buffer = counter_dump; return len; } diff --git a/drivers/gator/gator_events_mali_common.c b/drivers/gator/gator_events_mali_common.c index 4f2cce4ce67b..1af87d649afe 100644 --- a/drivers/gator/gator_events_mali_common.c +++ b/drivers/gator/gator_events_mali_common.c @@ -8,7 +8,7 @@ */ #include "gator_events_mali_common.h" -extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter, unsigned long *event) +extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, struct mali_counter *counter, unsigned long *event) { int err; char buf[255]; @@ -17,36 +17,39 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even /* If the counter name is empty ignore it */ if (strlen(event_name) != 0) { /* Set up the filesystem entry for this event. */ - snprintf(buf, sizeof(buf), "ARM_%s_%s", mali_name, event_name); + if (mali_name == NULL) + snprintf(buf, sizeof(buf), "ARM_Mali-%s", event_name); + else + snprintf(buf, sizeof(buf), "ARM_Mali-%s_%s", mali_name, event_name); dir = gatorfs_mkdir(sb, root, buf); if (dir == NULL) { - pr_debug("gator: %s: error creating file system for: %s (%s)", mali_name, event_name, buf); + pr_debug("gator: %s: error creating file system for: %s (%s)\n", mali_name, event_name, buf); return -1; } err = gatorfs_create_ulong(sb, dir, "enabled", &counter->enabled); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ulong for: %s (%s)", mali_name, event_name, buf); + pr_debug("gator: %s: error calling gatorfs_create_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } err = gatorfs_create_ro_ulong(sb, dir, "key", &counter->key); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf); + pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } if (counter->cores != -1) { err = gatorfs_create_ro_ulong(sb, dir, "cores", &counter->cores); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf); + pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } } if (event != NULL) { err = gatorfs_create_ulong(sb, dir, "event", event); if (err != 0) { - pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)", mali_name, event_name, buf); + pr_debug("gator: %s: error calling gatorfs_create_ro_ulong for: %s (%s)\n", mali_name, event_name, buf); return -1; } } @@ -55,12 +58,12 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even return 0; } -extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int n_counters) +extern void gator_mali_initialise_counters(struct mali_counter counters[], unsigned int n_counters) { unsigned int cnt; for (cnt = 0; cnt < n_counters; cnt++) { - mali_counter *counter = &counters[cnt]; + struct mali_counter *counter = &counters[cnt]; counter->key = gator_events_get_key(); counter->enabled = 0; diff --git a/drivers/gator/gator_events_mali_common.h b/drivers/gator/gator_events_mali_common.h index 91d871bc915a..e7082e62fe88 100644 --- a/drivers/gator/gator_events_mali_common.h +++ b/drivers/gator/gator_events_mali_common.h @@ -16,7 +16,7 @@ #include #include #include -#include +#include /* Ensure that MALI_SUPPORT has been defined to something. */ #ifndef MALI_SUPPORT @@ -30,21 +30,20 @@ /* * Runtime state information for a counter. */ -typedef struct { - // 'key' (a unique id set by gatord and returned by gator.ko) +struct mali_counter { + /* 'key' (a unique id set by gatord and returned by gator.ko) */ unsigned long key; - // counter enable state + /* counter enable state */ unsigned long enabled; - // for activity counters, the number of cores, otherwise -1 + /* for activity counters, the number of cores, otherwise -1 */ unsigned long cores; -} mali_counter; +}; /* * Mali-4xx */ typedef int mali_profiling_set_event_type(unsigned int, int); typedef void mali_profiling_control_type(unsigned int, unsigned int); -typedef void mali_profiling_get_counters_type(unsigned int *, unsigned int *, unsigned int *, unsigned int *); /* * Driver entry points for functions called directly by gator. @@ -65,7 +64,7 @@ extern void _mali_profiling_get_counters(unsigned int *, unsigned int *, unsigne * * @return 0 if entry point was created, non-zero if not. */ -extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, mali_counter *counter, unsigned long *event); +extern int gator_mali_create_file_system(const char *mali_name, const char *event_name, struct super_block *sb, struct dentry *root, struct mali_counter *counter, unsigned long *event); /** * Initializes the counter array. @@ -73,6 +72,6 @@ extern int gator_mali_create_file_system(const char *mali_name, const char *even * @param keys The array of counters * @param n_counters The number of entries in each of the arrays. */ -extern void gator_mali_initialise_counters(mali_counter counters[], unsigned int n_counters); +extern void gator_mali_initialise_counters(struct mali_counter counters[], unsigned int n_counters); #endif /* GATOR_EVENTS_MALI_COMMON_H */ diff --git a/drivers/gator/gator_events_mali_midgard.c b/drivers/gator/gator_events_mali_midgard.c new file mode 100644 index 000000000000..0aec906d7ae5 --- /dev/null +++ b/drivers/gator/gator_events_mali_midgard.c @@ -0,0 +1,562 @@ +/** + * Copyright (C) ARM Limited 2011-2014. 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" + +#include +#include +#include +#include +#include + +#ifdef MALI_DIR_MIDGARD +/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/ +#include "mali_linux_trace.h" +#else +/* Old DDK Directory structure with kernel/drivers/gpu/arm/t6xx*/ +#include "linux/mali_linux_trace.h" +#endif + +#include "gator_events_mali_common.h" + +/* + * Check that the MALI_SUPPORT define is set to one of the allowable device codes. + */ +#if (MALI_SUPPORT != MALI_MIDGARD) +#error MALI_SUPPORT set to an invalid device code: expecting MALI_MIDGARD +#endif + +static const char mali_name[] = "Midgard"; + +/* Counters for Mali-Midgard: + * + * - Timeline events + * They are tracepoints, but instead of reporting a number they report a START/STOP event. + * They are reported in Streamline as number of microseconds while that particular counter was active. + * + * - SW counters + * They are tracepoints reporting a particular number. + * They are accumulated in sw_counter_data array until they are passed to Streamline, then they are zeroed. + * + * - Accumulators + * They are the same as software counters but their value is not zeroed. + */ + +/* Timeline (start/stop) activity */ +static const char *const timeline_event_names[] = { + "PM_SHADER_0", + "PM_SHADER_1", + "PM_SHADER_2", + "PM_SHADER_3", + "PM_SHADER_4", + "PM_SHADER_5", + "PM_SHADER_6", + "PM_SHADER_7", + "PM_TILER_0", + "PM_L2_0", + "PM_L2_1", + "MMU_AS_0", + "MMU_AS_1", + "MMU_AS_2", + "MMU_AS_3" +}; + +enum { + PM_SHADER_0 = 0, + PM_SHADER_1, + PM_SHADER_2, + PM_SHADER_3, + PM_SHADER_4, + PM_SHADER_5, + PM_SHADER_6, + PM_SHADER_7, + PM_TILER_0, + PM_L2_0, + PM_L2_1, + MMU_AS_0, + MMU_AS_1, + MMU_AS_2, + MMU_AS_3 +}; +/* The number of shader blocks in the enum above */ +#define NUM_PM_SHADER (8) + +/* Software Counters */ +static const char *const software_counter_names[] = { + "MMU_PAGE_FAULT_0", + "MMU_PAGE_FAULT_1", + "MMU_PAGE_FAULT_2", + "MMU_PAGE_FAULT_3" +}; + +enum { + MMU_PAGE_FAULT_0 = 0, + MMU_PAGE_FAULT_1, + MMU_PAGE_FAULT_2, + MMU_PAGE_FAULT_3 +}; + +/* Software Counters */ +static const char *const accumulators_names[] = { + "TOTAL_ALLOC_PAGES" +}; + +enum { + TOTAL_ALLOC_PAGES = 0 +}; + +#define FIRST_TIMELINE_EVENT (0) +#define NUMBER_OF_TIMELINE_EVENTS (sizeof(timeline_event_names) / sizeof(timeline_event_names[0])) +#define FIRST_SOFTWARE_COUNTER (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS) +#define NUMBER_OF_SOFTWARE_COUNTERS (sizeof(software_counter_names) / sizeof(software_counter_names[0])) +#define FIRST_ACCUMULATOR (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS) +#define NUMBER_OF_ACCUMULATORS (sizeof(accumulators_names) / sizeof(accumulators_names[0])) +#define FILMSTRIP (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS) +#define NUMBER_OF_EVENTS (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS + 1) + +/* + * gatorfs variables for counter enable state + */ +static struct mali_counter counters[NUMBER_OF_EVENTS]; +static unsigned long filmstrip_event; + +/* An array used to return the data we recorded + * as key,value pairs hence the *2 + */ +static int counter_dump[NUMBER_OF_EVENTS * 2]; + +/* + * Array holding counter start times (in ns) for each counter. A zero + * here indicates that the activity monitored by this counter is not + * running. + */ +static struct timespec timeline_event_starttime[NUMBER_OF_TIMELINE_EVENTS]; + +/* The data we have recorded */ +static unsigned int timeline_data[NUMBER_OF_TIMELINE_EVENTS]; +static unsigned int sw_counter_data[NUMBER_OF_SOFTWARE_COUNTERS]; +static unsigned int accumulators_data[NUMBER_OF_ACCUMULATORS]; + +/* Hold the previous timestamp, used to calculate the sample interval. */ +static struct timespec prev_timestamp; + +/** + * Returns the timespan (in microseconds) between the two specified timestamps. + * + * @param start Ptr to the start timestamp + * @param end Ptr to the end timestamp + * + * @return Number of microseconds between the two timestamps (can be negative if start follows end). + */ +static inline long get_duration_us(const struct timespec *start, const struct timespec *end) +{ + long event_duration_us = (end->tv_nsec - start->tv_nsec) / 1000; + + event_duration_us += (end->tv_sec - start->tv_sec) * 1000000; + + return event_duration_us; +} + +static void record_timeline_event(unsigned int timeline_index, unsigned int type) +{ + struct timespec event_timestamp; + struct timespec *event_start = &timeline_event_starttime[timeline_index]; + + switch (type) { + case ACTIVITY_START: + /* Get the event time... */ + getnstimeofday(&event_timestamp); + + /* Remember the start time if the activity is not already started */ + if (event_start->tv_sec == 0) + *event_start = event_timestamp; /* Structure copy */ + break; + + case ACTIVITY_STOP: + /* if the counter was started... */ + if (event_start->tv_sec != 0) { + /* Get the event time... */ + getnstimeofday(&event_timestamp); + + /* Accumulate the duration in us */ + timeline_data[timeline_index] += get_duration_us(event_start, &event_timestamp); + + /* Reset the start time to indicate the activity is stopped. */ + event_start->tv_sec = 0; + } + break; + + default: + /* Other activity events are ignored. */ + break; + } +} + +/* + * Documentation about the following tracepoints is in mali_linux_trace.h + */ + +GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long long value)) +{ +#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */ +#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */ +#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */ +#define BIT_AT(value, pos) ((value >> pos) & 1) + + static unsigned long long previous_shader_bitmask; + static unsigned long long previous_tiler_bitmask; + static unsigned long long previous_l2_bitmask; + + switch (event_id) { + case SHADER_PRESENT_LO: + { + unsigned long long changed_bitmask = previous_shader_bitmask ^ value; + int pos; + + for (pos = 0; pos < NUM_PM_SHADER; ++pos) { + if (BIT_AT(changed_bitmask, pos)) + record_timeline_event(PM_SHADER_0 + pos, BIT_AT(value, pos) ? ACTIVITY_START : ACTIVITY_STOP); + } + + previous_shader_bitmask = value; + break; + } + + case TILER_PRESENT_LO: + { + unsigned long long changed = previous_tiler_bitmask ^ value; + + if (BIT_AT(changed, 0)) + record_timeline_event(PM_TILER_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); + + previous_tiler_bitmask = value; + break; + } + + case L2_PRESENT_LO: + { + unsigned long long changed = previous_l2_bitmask ^ value; + + if (BIT_AT(changed, 0)) + record_timeline_event(PM_L2_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); + if (BIT_AT(changed, 4)) + record_timeline_event(PM_L2_1, BIT_AT(value, 4) ? ACTIVITY_START : ACTIVITY_STOP); + + previous_l2_bitmask = value; + break; + } + + default: + /* No other blocks are supported at present */ + break; + } + +#undef SHADER_PRESENT_LO +#undef TILER_PRESENT_LO +#undef L2_PRESENT_LO +#undef BIT_AT +} + +GATOR_DEFINE_PROBE(mali_page_fault_insert_pages, TP_PROTO(int event_id, unsigned long value)) +{ + /* We add to the previous since we may receive many tracepoints in one sample period */ + sw_counter_data[MMU_PAGE_FAULT_0 + event_id] += value; +} + +GATOR_DEFINE_PROBE(mali_mmu_as_in_use, TP_PROTO(int event_id)) +{ + record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_START); +} + +GATOR_DEFINE_PROBE(mali_mmu_as_released, TP_PROTO(int event_id)) +{ + record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_STOP); +} + +GATOR_DEFINE_PROBE(mali_total_alloc_pages_change, TP_PROTO(long long int event_id)) +{ + accumulators_data[TOTAL_ALLOC_PAGES] = event_id; +} + +static int create_files(struct super_block *sb, struct dentry *root) +{ + int event; + /* + * Create the filesystem for all events + */ + int counter_index = 0; + mali_profiling_control_type *mali_control; + + for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++) { + if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event], NULL) != 0) + return -1; + counter_index++; + } + counter_index = 0; + for (event = FIRST_SOFTWARE_COUNTER; event < FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS; event++) { + if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event], NULL) != 0) + return -1; + counter_index++; + } + counter_index = 0; + for (event = FIRST_ACCUMULATOR; event < FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS; event++) { + if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event], NULL) != 0) + return -1; + counter_index++; + } + + mali_control = symbol_get(_mali_profiling_control); + if (mali_control) { + if (gator_mali_create_file_system(mali_name, "Filmstrip_cnt0", sb, root, &counters[FILMSTRIP], &filmstrip_event) != 0) + return -1; + symbol_put(_mali_profiling_control); + } + + return 0; +} + +static int register_tracepoints(void) +{ + if (GATOR_REGISTER_TRACE(mali_pm_status)) { + pr_debug("gator: Mali-Midgard: mali_pm_status tracepoint failed to activate\n"); + return 0; + } + + if (GATOR_REGISTER_TRACE(mali_page_fault_insert_pages)) { + pr_debug("gator: Mali-Midgard: mali_page_fault_insert_pages tracepoint failed to activate\n"); + return 0; + } + + if (GATOR_REGISTER_TRACE(mali_mmu_as_in_use)) { + pr_debug("gator: Mali-Midgard: mali_mmu_as_in_use tracepoint failed to activate\n"); + return 0; + } + + if (GATOR_REGISTER_TRACE(mali_mmu_as_released)) { + pr_debug("gator: Mali-Midgard: mali_mmu_as_released tracepoint failed to activate\n"); + return 0; + } + + if (GATOR_REGISTER_TRACE(mali_total_alloc_pages_change)) { + pr_debug("gator: Mali-Midgard: mali_total_alloc_pages_change tracepoint failed to activate\n"); + return 0; + } + + pr_debug("gator: Mali-Midgard: start\n"); + pr_debug("gator: Mali-Midgard: mali_pm_status probe is at %p\n", &probe_mali_pm_status); + pr_debug("gator: Mali-Midgard: mali_page_fault_insert_pages probe is at %p\n", &probe_mali_page_fault_insert_pages); + pr_debug("gator: Mali-Midgard: mali_mmu_as_in_use probe is at %p\n", &probe_mali_mmu_as_in_use); + pr_debug("gator: Mali-Midgard: mali_mmu_as_released probe is at %p\n", &probe_mali_mmu_as_released); + pr_debug("gator: Mali-Midgard: mali_total_alloc_pages_change probe is at %p\n", &probe_mali_total_alloc_pages_change); + + return 1; +} + +static int start(void) +{ + unsigned int cnt; + mali_profiling_control_type *mali_control; + + /* Clean all data for the next capture */ + for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) { + timeline_event_starttime[cnt].tv_sec = timeline_event_starttime[cnt].tv_nsec = 0; + timeline_data[cnt] = 0; + } + + for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++) + sw_counter_data[cnt] = 0; + + for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++) + accumulators_data[cnt] = 0; + + /* Register tracepoints */ + if (register_tracepoints() == 0) + return -1; + + /* Generic control interface for Mali DDK. */ + mali_control = symbol_get(_mali_profiling_control); + if (mali_control) { + /* The event attribute in the XML file keeps the actual frame rate. */ + unsigned int enabled = counters[FILMSTRIP].enabled ? 1 : 0; + unsigned int rate = filmstrip_event & 0xff; + unsigned int resize_factor = (filmstrip_event >> 8) & 0xff; + + pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control); + +#define FBDUMP_CONTROL_ENABLE (1) +#define FBDUMP_CONTROL_RATE (2) +#define FBDUMP_CONTROL_RESIZE_FACTOR (4) + mali_control(FBDUMP_CONTROL_ENABLE, enabled); + mali_control(FBDUMP_CONTROL_RATE, rate); + mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor); + + pr_debug("gator: sent mali_control enabled=%d, rate=%d, resize_factor=%d\n", enabled, rate, resize_factor); + + symbol_put(_mali_profiling_control); + } else { + pr_err("gator: mali online _mali_profiling_control symbol not found\n"); + } + + /* + * Set the first timestamp for calculating the sample interval. The first interval could be quite long, + * since it will be the time between 'start' and the first 'read'. + * This means that timeline values will be divided by a big number for the first sample. + */ + getnstimeofday(&prev_timestamp); + + return 0; +} + +static void stop(void) +{ + mali_profiling_control_type *mali_control; + + pr_debug("gator: Mali-Midgard: stop\n"); + + /* + * It is safe to unregister traces even if they were not successfully + * registered, so no need to check. + */ + GATOR_UNREGISTER_TRACE(mali_pm_status); + pr_debug("gator: Mali-Midgard: mali_pm_status tracepoint deactivated\n"); + + GATOR_UNREGISTER_TRACE(mali_page_fault_insert_pages); + pr_debug("gator: Mali-Midgard: mali_page_fault_insert_pages tracepoint deactivated\n"); + + GATOR_UNREGISTER_TRACE(mali_mmu_as_in_use); + pr_debug("gator: Mali-Midgard: mali_mmu_as_in_use tracepoint deactivated\n"); + + GATOR_UNREGISTER_TRACE(mali_mmu_as_released); + pr_debug("gator: Mali-Midgard: mali_mmu_as_released tracepoint deactivated\n"); + + GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change); + pr_debug("gator: Mali-Midgard: mali_total_alloc_pages_change tracepoint deactivated\n"); + + /* Generic control interface for Mali DDK. */ + mali_control = symbol_get(_mali_profiling_control); + if (mali_control) { + pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_control); + + mali_control(FBDUMP_CONTROL_ENABLE, 0); + + symbol_put(_mali_profiling_control); + } else { + pr_err("gator: mali offline _mali_profiling_control symbol not found\n"); + } +} + +static int read(int **buffer, bool sched_switch) +{ + int cnt; + int len = 0; + long sample_interval_us = 0; + struct timespec read_timestamp; + + if (!on_primary_core()) + return 0; + + /* Get the start of this sample period. */ + getnstimeofday(&read_timestamp); + + /* + * Calculate the sample interval if the previous sample time is valid. + * We use tv_sec since it will not be 0. + */ + if (prev_timestamp.tv_sec != 0) + sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp); + + /* Structure copy. Update the previous timestamp. */ + prev_timestamp = read_timestamp; + + /* + * Report the timeline counters (ACTIVITY_START/STOP) + */ + for (cnt = FIRST_TIMELINE_EVENT; cnt < (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS); cnt++) { + struct mali_counter *counter = &counters[cnt]; + + if (counter->enabled) { + const int index = cnt - FIRST_TIMELINE_EVENT; + unsigned int value; + + /* If the activity is still running, reset its start time to the + * start of this sample period to correct the count. Add the + * time up to the end of the sample onto the count. + */ + if (timeline_event_starttime[index].tv_sec != 0) { + const long event_duration = get_duration_us(&timeline_event_starttime[index], &read_timestamp); + + timeline_data[index] += event_duration; + timeline_event_starttime[index] = read_timestamp; /* Activity is still running. */ + } + + if (sample_interval_us != 0) { + /* Convert the counter to a percent-of-sample value */ + value = (timeline_data[index] * 100) / sample_interval_us; + } else { + pr_debug("gator: Mali-Midgard: setting value to zero\n"); + value = 0; + } + + /* Clear the counter value ready for the next sample. */ + timeline_data[index] = 0; + + counter_dump[len++] = counter->key; + counter_dump[len++] = value; + } + } + + /* Report the software counters */ + for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++) { + const struct mali_counter *counter = &counters[cnt]; + + if (counter->enabled) { + const int index = cnt - FIRST_SOFTWARE_COUNTER; + + counter_dump[len++] = counter->key; + counter_dump[len++] = sw_counter_data[index]; + /* Set the value to zero for the next time */ + sw_counter_data[index] = 0; + } + } + + /* Report the accumulators */ + for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); cnt++) { + const struct mali_counter *counter = &counters[cnt]; + + if (counter->enabled) { + const int index = cnt - FIRST_ACCUMULATOR; + + counter_dump[len++] = counter->key; + counter_dump[len++] = accumulators_data[index]; + /* Do not zero the accumulator */ + } + } + + /* Update the buffer */ + if (buffer) + *buffer = counter_dump; + + return len; +} + +static struct gator_interface gator_events_mali_midgard_interface = { + .create_files = create_files, + .start = start, + .stop = stop, + .read = read +}; + +extern int gator_events_mali_midgard_init(void) +{ + pr_debug("gator: Mali-Midgard: sw_counters init\n"); + + gator_mali_initialise_counters(counters, NUMBER_OF_EVENTS); + + return gator_events_install(&gator_events_mali_midgard_interface); +} diff --git a/drivers/gator/gator_events_mali_midgard_hw.c b/drivers/gator/gator_events_mali_midgard_hw.c new file mode 100644 index 000000000000..c8065da56815 --- /dev/null +++ b/drivers/gator/gator_events_mali_midgard_hw.c @@ -0,0 +1,977 @@ +/** + * Copyright (C) ARM Limited 2012-2014. 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" + +#include +#include +#include +#include +#include + +/* Mali Midgard DDK includes */ +#if defined(MALI_SIMPLE_API) +/* Header with wrapper functions to kbase structures and functions */ +#include "mali/mali_kbase_gator_api.h" +#elif defined(MALI_DIR_MIDGARD) +/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard */ +#include "mali_linux_trace.h" +#include "mali_kbase.h" +#include "mali_kbase_mem_linux.h" +#else +/* Old DDK Directory structure with kernel/drivers/gpu/arm/t6xx */ +#include "linux/mali_linux_trace.h" +#include "kbase/src/common/mali_kbase.h" +#include "kbase/src/linux/mali_kbase_mem_linux.h" +#endif + +/* If API version is not specified then assume API version 1. */ +#ifndef MALI_DDK_GATOR_API_VERSION +#define MALI_DDK_GATOR_API_VERSION 1 +#endif + +#if (MALI_DDK_GATOR_API_VERSION != 1) && (MALI_DDK_GATOR_API_VERSION != 2) && (MALI_DDK_GATOR_API_VERSION != 3) +#error MALI_DDK_GATOR_API_VERSION is invalid (must be 1 for r1/r2 DDK, or 2 for r3/r4 DDK, or 3 for r5 and later DDK). +#endif + +#include "gator_events_mali_common.h" + +/* + * Mali-Midgard + */ +#if MALI_DDK_GATOR_API_VERSION == 3 +static uint32_t (*kbase_gator_instr_hwcnt_dump_irq_symbol)(struct kbase_gator_hwcnt_handles *); +static uint32_t (*kbase_gator_instr_hwcnt_dump_complete_symbol)(struct kbase_gator_hwcnt_handles *, uint32_t *const); +static struct kbase_gator_hwcnt_handles *(*kbase_gator_hwcnt_init_symbol)(struct kbase_gator_hwcnt_info *); +static void (*kbase_gator_hwcnt_term_symbol)(struct kbase_gator_hwcnt_info *, struct kbase_gator_hwcnt_handles *); + +#else +static struct kbase_device *(*kbase_find_device_symbol)(int); +static struct kbase_context *(*kbase_create_context_symbol)(struct kbase_device *); +static void (*kbase_destroy_context_symbol)(struct kbase_context *); + +#if MALI_DDK_GATOR_API_VERSION == 1 +static void *(*kbase_va_alloc_symbol)(struct kbase_context *, u32); +static void (*kbase_va_free_symbol)(struct kbase_context *, void *); +#elif MALI_DDK_GATOR_API_VERSION == 2 +static void *(*kbase_va_alloc_symbol)(struct kbase_context *, u32, struct kbase_hwc_dma_mapping *); +static void (*kbase_va_free_symbol)(struct kbase_context *, struct kbase_hwc_dma_mapping *); +#endif + +static mali_error (*kbase_instr_hwcnt_enable_symbol)(struct kbase_context *, struct kbase_uk_hwcnt_setup *); +static mali_error (*kbase_instr_hwcnt_disable_symbol)(struct kbase_context *); +static mali_error (*kbase_instr_hwcnt_clear_symbol)(struct kbase_context *); +static mali_error (*kbase_instr_hwcnt_dump_irq_symbol)(struct kbase_context *); +static mali_bool (*kbase_instr_hwcnt_dump_complete_symbol)(struct kbase_context *, mali_bool *); + +static long shader_present_low; +#endif + +/** The interval between reads, in ns. + * + * Earlier we introduced a 'hold off for 1ms after last read' to + * resolve MIDBASE-2178 and MALINE-724. However, the 1ms hold off is + * too long if no context switches occur as there is a race between + * this value and the tick of the read clock in gator which is also + * 1ms. If we 'miss' the current read, the counter values are + * effectively 'spread' over 2ms and the values seen are half what + * they should be (since Streamline averages over sample time). In the + * presence of context switches this spread can vary and markedly + * affect the counters. Currently there is no 'proper' solution to + * this, but empirically we have found that reducing the minimum read + * interval to 950us causes the counts to be much more stable. + */ +static const int READ_INTERVAL_NSEC = 950000; + +#if GATOR_TEST +#include "gator_events_mali_midgard_hw_test.c" +#endif + +#if MALI_DDK_GATOR_API_VERSION != 3 +/* Blocks for HW counters */ +enum { + JM_BLOCK = 0, + TILER_BLOCK, + SHADER_BLOCK, + MMU_BLOCK +}; +#endif + +static const char *mali_name; + +/* Counters for Mali-Midgard: + * + * For HW counters we need strings to create /dev/gator/events files. + * Enums are not needed because the position of the HW name in the array is the same + * of the corresponding value in the received block of memory. + * HW counters are requested by calculating a bitmask, passed then to the driver. + * Every millisecond a HW counters dump is requested, and if the previous has been completed they are read. + */ + +/* Hardware Counters */ +#if MALI_DDK_GATOR_API_VERSION == 3 + +static const char *const *hardware_counter_names; +static int number_of_hardware_counters; + +#else + +static const char *const hardware_counter_names[] = { + /* Job Manager */ + "", + "", + "", + "", + "MESSAGES_SENT", + "MESSAGES_RECEIVED", + "GPU_ACTIVE", /* 6 */ + "IRQ_ACTIVE", + "JS0_JOBS", + "JS0_TASKS", + "JS0_ACTIVE", + "", + "JS0_WAIT_READ", + "JS0_WAIT_ISSUE", + "JS0_WAIT_DEPEND", + "JS0_WAIT_FINISH", + "JS1_JOBS", + "JS1_TASKS", + "JS1_ACTIVE", + "", + "JS1_WAIT_READ", + "JS1_WAIT_ISSUE", + "JS1_WAIT_DEPEND", + "JS1_WAIT_FINISH", + "JS2_JOBS", + "JS2_TASKS", + "JS2_ACTIVE", + "", + "JS2_WAIT_READ", + "JS2_WAIT_ISSUE", + "JS2_WAIT_DEPEND", + "JS2_WAIT_FINISH", + "JS3_JOBS", + "JS3_TASKS", + "JS3_ACTIVE", + "", + "JS3_WAIT_READ", + "JS3_WAIT_ISSUE", + "JS3_WAIT_DEPEND", + "JS3_WAIT_FINISH", + "JS4_JOBS", + "JS4_TASKS", + "JS4_ACTIVE", + "", + "JS4_WAIT_READ", + "JS4_WAIT_ISSUE", + "JS4_WAIT_DEPEND", + "JS4_WAIT_FINISH", + "JS5_JOBS", + "JS5_TASKS", + "JS5_ACTIVE", + "", + "JS5_WAIT_READ", + "JS5_WAIT_ISSUE", + "JS5_WAIT_DEPEND", + "JS5_WAIT_FINISH", + "JS6_JOBS", + "JS6_TASKS", + "JS6_ACTIVE", + "", + "JS6_WAIT_READ", + "JS6_WAIT_ISSUE", + "JS6_WAIT_DEPEND", + "JS6_WAIT_FINISH", + + /*Tiler */ + "", + "", + "", + "JOBS_PROCESSED", + "TRIANGLES", + "QUADS", + "POLYGONS", + "POINTS", + "LINES", + "VCACHE_HIT", + "VCACHE_MISS", + "FRONT_FACING", + "BACK_FACING", + "PRIM_VISIBLE", + "PRIM_CULLED", + "PRIM_CLIPPED", + "LEVEL0", + "LEVEL1", + "LEVEL2", + "LEVEL3", + "LEVEL4", + "LEVEL5", + "LEVEL6", + "LEVEL7", + "COMMAND_1", + "COMMAND_2", + "COMMAND_3", + "COMMAND_4", + "COMMAND_4_7", + "COMMAND_8_15", + "COMMAND_16_63", + "COMMAND_64", + "COMPRESS_IN", + "COMPRESS_OUT", + "COMPRESS_FLUSH", + "TIMESTAMPS", + "PCACHE_HIT", + "PCACHE_MISS", + "PCACHE_LINE", + "PCACHE_STALL", + "WRBUF_HIT", + "WRBUF_MISS", + "WRBUF_LINE", + "WRBUF_PARTIAL", + "WRBUF_STALL", + "ACTIVE", + "LOADING_DESC", + "INDEX_WAIT", + "INDEX_RANGE_WAIT", + "VERTEX_WAIT", + "PCACHE_WAIT", + "WRBUF_WAIT", + "BUS_READ", + "BUS_WRITE", + "", + "", + "", + "", + "", + "UTLB_STALL", + "UTLB_REPLAY_MISS", + "UTLB_REPLAY_FULL", + "UTLB_NEW_MISS", + "UTLB_HIT", + + /* Shader Core */ + "", + "", + "", + "SHADER_CORE_ACTIVE", + "FRAG_ACTIVE", + "FRAG_PRIMATIVES", + "FRAG_PRIMATIVES_DROPPED", + "FRAG_CYCLE_DESC", + "FRAG_CYCLES_PLR", + "FRAG_CYCLES_VERT", + "FRAG_CYCLES_TRISETUP", + "FRAG_CYCLES_RAST", + "FRAG_THREADS", + "FRAG_DUMMY_THREADS", + "FRAG_QUADS_RAST", + "FRAG_QUADS_EZS_TEST", + "FRAG_QUADS_EZS_KILLED", + "FRAG_QUADS_LZS_TEST", + "FRAG_QUADS_LZS_KILLED", + "FRAG_CYCLE_NO_TILE", + "FRAG_NUM_TILES", + "FRAG_TRANS_ELIM", + "COMPUTE_ACTIVE", + "COMPUTE_TASKS", + "COMPUTE_THREADS", + "COMPUTE_CYCLES_DESC", + "TRIPIPE_ACTIVE", + "ARITH_WORDS", + "ARITH_CYCLES_REG", + "ARITH_CYCLES_L0", + "ARITH_FRAG_DEPEND", + "LS_WORDS", + "LS_ISSUES", + "LS_RESTARTS", + "LS_REISSUES_MISS", + "LS_REISSUES_VD", + "LS_REISSUE_ATTRIB_MISS", + "LS_NO_WB", + "TEX_WORDS", + "TEX_BUBBLES", + "TEX_WORDS_L0", + "TEX_WORDS_DESC", + "TEX_THREADS", + "TEX_RECIRC_FMISS", + "TEX_RECIRC_DESC", + "TEX_RECIRC_MULTI", + "TEX_RECIRC_PMISS", + "TEX_RECIRC_CONF", + "LSC_READ_HITS", + "LSC_READ_MISSES", + "LSC_WRITE_HITS", + "LSC_WRITE_MISSES", + "LSC_ATOMIC_HITS", + "LSC_ATOMIC_MISSES", + "LSC_LINE_FETCHES", + "LSC_DIRTY_LINE", + "LSC_SNOOPS", + "AXI_TLB_STALL", + "AXI_TLB_MIESS", + "AXI_TLB_TRANSACTION", + "LS_TLB_MISS", + "LS_TLB_HIT", + "AXI_BEATS_READ", + "AXI_BEATS_WRITTEN", + + /*L2 and MMU */ + "", + "", + "", + "", + "MMU_HIT", + "MMU_NEW_MISS", + "MMU_REPLAY_FULL", + "MMU_REPLAY_MISS", + "MMU_TABLE_WALK", + "", + "", + "", + "", + "", + "", + "", + "UTLB_HIT", + "UTLB_NEW_MISS", + "UTLB_REPLAY_FULL", + "UTLB_REPLAY_MISS", + "UTLB_STALL", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "L2_WRITE_BEATS", + "L2_READ_BEATS", + "L2_ANY_LOOKUP", + "L2_READ_LOOKUP", + "L2_SREAD_LOOKUP", + "L2_READ_REPLAY", + "L2_READ_SNOOP", + "L2_READ_HIT", + "L2_CLEAN_MISS", + "L2_WRITE_LOOKUP", + "L2_SWRITE_LOOKUP", + "L2_WRITE_REPLAY", + "L2_WRITE_SNOOP", + "L2_WRITE_HIT", + "L2_EXT_READ_FULL", + "L2_EXT_READ_HALF", + "L2_EXT_WRITE_FULL", + "L2_EXT_WRITE_HALF", + "L2_EXT_READ", + "L2_EXT_READ_LINE", + "L2_EXT_WRITE", + "L2_EXT_WRITE_LINE", + "L2_EXT_WRITE_SMALL", + "L2_EXT_BARRIER", + "L2_EXT_AR_STALL", + "L2_EXT_R_BUF_FULL", + "L2_EXT_RD_BUF_FULL", + "L2_EXT_R_RAW", + "L2_EXT_W_STALL", + "L2_EXT_W_BUF_FULL", + "L2_EXT_R_W_HAZARD", + "L2_TAG_HAZARD", + "L2_SNOOP_FULL", + "L2_REPLAY_FULL" +}; + +static const int number_of_hardware_counters = ARRAY_SIZE(hardware_counter_names); + +#endif + +#define GET_HW_BLOCK(c) (((c) >> 6) & 0x3) +#define GET_COUNTER_OFFSET(c) ((c) & 0x3f) + +#if MALI_DDK_GATOR_API_VERSION == 3 +/* Opaque handles for kbase_context and kbase_hwc_dma_mapping */ +static struct kbase_gator_hwcnt_handles *handles; + +/* Information about hardware counters */ +static struct kbase_gator_hwcnt_info *in_out_info; + +#else +/* Memory to dump hardware counters into */ +static void *kernel_dump_buffer; + +#if MALI_DDK_GATOR_API_VERSION == 2 +/* DMA state used to manage lifetime of the buffer */ +struct kbase_hwc_dma_mapping kernel_dump_buffer_handle; +#endif + +/* kbase context and device */ +static struct kbase_context *kbcontext; +static struct kbase_device *kbdevice; + +/* + * The following function has no external prototype in older DDK + * revisions. When the DDK is updated then this should be removed. + */ +struct kbase_device *kbase_find_device(int minor); +#endif + +static volatile bool kbase_device_busy; +static unsigned int num_hardware_counters_enabled; + +/* gatorfs variables for counter enable state */ +static struct mali_counter *counters; + +/* An array used to return the data we recorded as key,value pairs */ +static int *counter_dump; + +extern struct mali_counter mali_activity[3]; + +static const char *const mali_activity_names[] = { + "fragment", + "vertex", + "opencl", +}; + +#define SYMBOL_GET(FUNCTION, ERROR_COUNT) \ + do { \ + if (FUNCTION ## _symbol) { \ + pr_err("gator: mali " #FUNCTION " symbol was already registered\n"); \ + (ERROR_COUNT)++; \ + } else { \ + FUNCTION ## _symbol = symbol_get(FUNCTION); \ + if (!FUNCTION ## _symbol) { \ + pr_err("gator: mali online " #FUNCTION " symbol not found\n"); \ + (ERROR_COUNT)++; \ + } \ + } \ + } while (0) + +#define SYMBOL_CLEANUP(FUNCTION) \ + do { \ + if (FUNCTION ## _symbol) { \ + symbol_put(FUNCTION); \ + FUNCTION ## _symbol = NULL; \ + } \ + } while (0) + +/** + * Execute symbol_get for all the Mali symbols and check for success. + * @return the number of symbols not loaded. + */ +static int init_symbols(void) +{ + int error_count = 0; +#if MALI_DDK_GATOR_API_VERSION == 3 + SYMBOL_GET(kbase_gator_instr_hwcnt_dump_irq, error_count); + SYMBOL_GET(kbase_gator_instr_hwcnt_dump_complete, error_count); + SYMBOL_GET(kbase_gator_hwcnt_init, error_count); + SYMBOL_GET(kbase_gator_hwcnt_term, error_count); +#else + SYMBOL_GET(kbase_find_device, error_count); + SYMBOL_GET(kbase_create_context, error_count); + SYMBOL_GET(kbase_va_alloc, error_count); + SYMBOL_GET(kbase_instr_hwcnt_enable, error_count); + SYMBOL_GET(kbase_instr_hwcnt_clear, error_count); + SYMBOL_GET(kbase_instr_hwcnt_dump_irq, error_count); + SYMBOL_GET(kbase_instr_hwcnt_dump_complete, error_count); + SYMBOL_GET(kbase_instr_hwcnt_disable, error_count); + SYMBOL_GET(kbase_va_free, error_count); + SYMBOL_GET(kbase_destroy_context, error_count); +#endif + + return error_count; +} + +/** + * Execute symbol_put for all the registered Mali symbols. + */ +static void clean_symbols(void) +{ +#if MALI_DDK_GATOR_API_VERSION == 3 + SYMBOL_CLEANUP(kbase_gator_instr_hwcnt_dump_irq); + SYMBOL_CLEANUP(kbase_gator_instr_hwcnt_dump_complete); + SYMBOL_CLEANUP(kbase_gator_hwcnt_init); + SYMBOL_CLEANUP(kbase_gator_hwcnt_term); +#else + SYMBOL_CLEANUP(kbase_find_device); + SYMBOL_CLEANUP(kbase_create_context); + SYMBOL_CLEANUP(kbase_va_alloc); + SYMBOL_CLEANUP(kbase_instr_hwcnt_enable); + SYMBOL_CLEANUP(kbase_instr_hwcnt_clear); + SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_irq); + SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_complete); + SYMBOL_CLEANUP(kbase_instr_hwcnt_disable); + SYMBOL_CLEANUP(kbase_va_free); + SYMBOL_CLEANUP(kbase_destroy_context); +#endif +} + +/** + * Determines whether a read should take place + * @param current_time The current time, obtained from getnstimeofday() + * @param prev_time_s The number of seconds at the previous read attempt. + * @param next_read_time_ns The time (in ns) when the next read should be allowed. + * + * Note that this function has been separated out here to allow it to be tested. + */ +static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns) +{ + /* If the current ns count rolls over a second, roll the next read time too. */ + if (current_time->tv_sec != *prev_time_s) + *next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC; + + /* Abort the read if the next read time has not arrived. */ + if (current_time->tv_nsec < *next_read_time_ns) + return 0; + + /* Set the next read some fixed time after this one, and update the read timestamp. */ + *next_read_time_ns = current_time->tv_nsec + READ_INTERVAL_NSEC; + + *prev_time_s = current_time->tv_sec; + return 1; +} + +static int start(void) +{ +#if MALI_DDK_GATOR_API_VERSION != 3 + struct kbase_uk_hwcnt_setup setup; + unsigned long long shadersPresent = 0; + u16 bitmask[] = { 0, 0, 0, 0 }; + mali_error err; +#endif + int cnt; + +#if MALI_DDK_GATOR_API_VERSION == 3 + /* Setup HW counters */ + num_hardware_counters_enabled = 0; + + /* Declare and initialise kbase_gator_hwcnt_info structure */ + in_out_info = kmalloc(sizeof(*in_out_info), GFP_KERNEL); + for (cnt = 0; cnt < ARRAY_SIZE(in_out_info->bitmask); cnt++) + in_out_info->bitmask[cnt] = 0; + + /* Calculate enable bitmasks based on counters_enabled array */ + for (cnt = 0; cnt < number_of_hardware_counters; cnt++) { + if (counters[cnt].enabled) { + int block = GET_HW_BLOCK(cnt); + int enable_bit = GET_COUNTER_OFFSET(cnt) / 4; + + in_out_info->bitmask[block] |= (1 << enable_bit); + pr_debug("gator: Mali-Midgard: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt); + num_hardware_counters_enabled++; + } + } + + /* Create a kbase context for HW counters */ + if (num_hardware_counters_enabled > 0) { + if (init_symbols() > 0) { + clean_symbols(); + /* No Mali driver code entrypoints found - not a fault. */ + return 0; + } + + handles = kbase_gator_hwcnt_init_symbol(in_out_info); + + if (handles == NULL) + goto out; + + kbase_device_busy = false; + } + + return 0; +#else + /* Setup HW counters */ + num_hardware_counters_enabled = 0; + + /* Calculate enable bitmasks based on counters_enabled array */ + for (cnt = 0; cnt < number_of_hardware_counters; cnt++) { + const struct mali_counter *counter = &counters[cnt]; + + if (counter->enabled) { + int block = GET_HW_BLOCK(cnt); + int enable_bit = GET_COUNTER_OFFSET(cnt) / 4; + + bitmask[block] |= (1 << enable_bit); + pr_debug("gator: Mali-Midgard: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt); + num_hardware_counters_enabled++; + } + } + + /* Create a kbase context for HW counters */ + if (num_hardware_counters_enabled > 0) { + if (init_symbols() > 0) { + clean_symbols(); + /* No Mali driver code entrypoints found - not a fault. */ + return 0; + } + + kbdevice = kbase_find_device_symbol(-1); + + /* If we already got a context, fail */ + if (kbcontext) { + pr_debug("gator: Mali-Midgard: error context already present\n"); + goto out; + } + + /* kbcontext will only be valid after all the Mali symbols are loaded successfully */ + kbcontext = kbase_create_context_symbol(kbdevice); + if (!kbcontext) { + pr_debug("gator: Mali-Midgard: error creating kbase context\n"); + goto out; + } + + /* See if we can get the number of shader cores */ + shadersPresent = kbdevice->shader_present_bitmap; + shader_present_low = (unsigned long)shadersPresent; + + /* + * The amount of memory needed to store the dump (bytes) + * DUMP_SIZE = number of core groups + * * number of blocks (always 8 for midgard) + * * number of counters per block (always 64 for midgard) + * * number of bytes per counter (always 4 in midgard) + * For a Mali-Midgard with a single core group = 1 * 8 * 64 * 4 = 2048 + * For a Mali-Midgard with a dual core group = 2 * 8 * 64 * 4 = 4096 + */ +#if MALI_DDK_GATOR_API_VERSION == 1 + kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 4096); +#elif MALI_DDK_GATOR_API_VERSION == 2 + kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 4096, &kernel_dump_buffer_handle); +#endif + if (!kernel_dump_buffer) { + pr_debug("gator: Mali-Midgard: error trying to allocate va\n"); + goto destroy_context; + } + + setup.dump_buffer = (uintptr_t)kernel_dump_buffer; + setup.jm_bm = bitmask[JM_BLOCK]; + setup.tiler_bm = bitmask[TILER_BLOCK]; + setup.shader_bm = bitmask[SHADER_BLOCK]; + setup.mmu_l2_bm = bitmask[MMU_BLOCK]; + /* These counters do not exist on Mali-T60x */ + setup.l3_cache_bm = 0; + + /* Use kbase API to enable hardware counters and provide dump buffer */ + err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup); + if (err != MALI_ERROR_NONE) { + pr_debug("gator: Mali-Midgard: can't setup hardware counters\n"); + goto free_buffer; + } + pr_debug("gator: Mali-Midgard: hardware counters enabled\n"); + kbase_instr_hwcnt_clear_symbol(kbcontext); + pr_debug("gator: Mali-Midgard: hardware counters cleared\n"); + + kbase_device_busy = false; + } + + return 0; + +free_buffer: +#if MALI_DDK_GATOR_API_VERSION == 1 + kbase_va_free_symbol(kbcontext, kernel_dump_buffer); +#elif MALI_DDK_GATOR_API_VERSION == 2 + kbase_va_free_symbol(kbcontext, &kernel_dump_buffer_handle); +#endif + +destroy_context: + kbase_destroy_context_symbol(kbcontext); +#endif + +out: + clean_symbols(); + return -1; +} + +static void stop(void) +{ + unsigned int cnt; +#if MALI_DDK_GATOR_API_VERSION == 3 + struct kbase_gator_hwcnt_handles *temp_hand; +#else + struct kbase_context *temp_kbcontext; +#endif + + pr_debug("gator: Mali-Midgard: stop\n"); + + /* Set all counters as disabled */ + for (cnt = 0; cnt < number_of_hardware_counters; cnt++) + counters[cnt].enabled = 0; + + /* Destroy the context for HW counters */ +#if MALI_DDK_GATOR_API_VERSION == 3 + if (num_hardware_counters_enabled > 0 && handles != NULL) { + /* + * Set the global variable to NULL before destroying it, because + * other function will check this before using it. + */ + temp_hand = handles; + handles = NULL; + + kbase_gator_hwcnt_term_symbol(in_out_info, temp_hand); + + kfree(in_out_info); + +#else + if (num_hardware_counters_enabled > 0 && kbcontext != NULL) { + /* + * Set the global variable to NULL before destroying it, because + * other function will check this before using it. + */ + temp_kbcontext = kbcontext; + kbcontext = NULL; + + kbase_instr_hwcnt_disable_symbol(temp_kbcontext); + +#if MALI_DDK_GATOR_API_VERSION == 1 + kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer); +#elif MALI_DDK_GATOR_API_VERSION == 2 + kbase_va_free_symbol(temp_kbcontext, &kernel_dump_buffer_handle); +#endif + + kbase_destroy_context_symbol(temp_kbcontext); +#endif + + pr_debug("gator: Mali-Midgard: hardware counters stopped\n"); + + clean_symbols(); + } +} + +static int read_counter(const int cnt, const int len, const struct mali_counter *counter) +{ + const int block = GET_HW_BLOCK(cnt); + const int counter_offset = GET_COUNTER_OFFSET(cnt); + +#if MALI_DDK_GATOR_API_VERSION == 3 + const char *block_base_address = (char *)in_out_info->kernel_dump_buffer; + int i; + int shader_core_count = 0; + u32 value = 0; + + for (i = 0; i < in_out_info->nr_hwc_blocks; i++) { + if (block == in_out_info->hwc_layout[i]) { + value += *((u32 *)(block_base_address + (0x100 * i)) + counter_offset); + if (block == SHADER_BLOCK) + ++shader_core_count; + } + } + + if (shader_core_count > 1) + value /= shader_core_count; +#else + const char *block_base_address = (char *)kernel_dump_buffer + vithar_blocks[block]; + + /* If counter belongs to shader block need to take into account all cores */ + if (block == SHADER_BLOCK) { + int i = 0; + int shader_core_count = 0; + + value = 0; + + for (i = 0; i < 4; i++) { + if ((shader_present_low >> i) & 1) { + value += *((u32 *)(block_base_address + (0x100 * i)) + counter_offset); + shader_core_count++; + } + } + + for (i = 0; i < 4; i++) { + if ((shader_present_low >> (i+4)) & 1) { + value += *((u32 *)(block_base_address + (0x100 * i) + 0x800) + counter_offset); + shader_core_count++; + } + } + + /* Need to total by number of cores to produce an average */ + if (shader_core_count != 0) + value /= shader_core_count; + } else { + value = *((u32 *)block_base_address + counter_offset); + } +#endif + + counter_dump[len + 0] = counter->key; + counter_dump[len + 1] = value; + + return 2; +} + +static int read(int **buffer, bool sched_switch) +{ + int cnt; + int len = 0; + uint32_t success; + + struct timespec current_time; + static u32 prev_time_s; + static s32 next_read_time_ns; + + if (!on_primary_core() || sched_switch) + return 0; + + getnstimeofday(¤t_time); + + /* + * Discard reads unless a respectable time has passed. This + * reduces the load on the GPU without sacrificing accuracy on + * the Streamline display. + */ + if (!is_read_scheduled(¤t_time, &prev_time_s, &next_read_time_ns)) + return 0; + + /* + * Report the HW counters + * Only process hardware counters if at least one of the hardware counters is enabled. + */ + if (num_hardware_counters_enabled > 0) { +#if MALI_DDK_GATOR_API_VERSION != 3 + const unsigned int vithar_blocks[] = { + 0x700, /* VITHAR_JOB_MANAGER, Block 0 */ + 0x400, /* VITHAR_TILER, Block 1 */ + 0x000, /* VITHAR_SHADER_CORE, Block 2 */ + 0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */ + }; +#endif + +#if MALI_DDK_GATOR_API_VERSION == 3 + if (!handles) + return -1; + + /* Mali symbols can be called safely since a kbcontext is valid */ + if (kbase_gator_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) { +#else + if (!kbcontext) + return -1; + + /* Mali symbols can be called safely since a kbcontext is valid */ + if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) { +#endif + kbase_device_busy = false; + + if (success == MALI_TRUE) { + /* Cycle through hardware counters and accumulate totals */ + for (cnt = 0; cnt < number_of_hardware_counters; cnt++) { + const struct mali_counter *counter = &counters[cnt]; + + if (counter->enabled) + len += read_counter(cnt, len, counter); + } + } + } + + if (!kbase_device_busy) { + kbase_device_busy = true; +#if MALI_DDK_GATOR_API_VERSION == 3 + kbase_gator_instr_hwcnt_dump_irq_symbol(handles); +#else + kbase_instr_hwcnt_dump_irq_symbol(kbcontext); +#endif + } + } + + /* Update the buffer */ + if (buffer) + *buffer = counter_dump; + + return len; +} + +static int create_files(struct super_block *sb, struct dentry *root) +{ + unsigned int event; + /* + * Create the filesystem for all events + */ + for (event = 0; event < ARRAY_SIZE(mali_activity); event++) { + if (gator_mali_create_file_system("Midgard", mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) + return -1; + } + + for (event = 0; event < number_of_hardware_counters; event++) { + if (gator_mali_create_file_system(mali_name, hardware_counter_names[event], sb, root, &counters[event], NULL) != 0) + return -1; + } + + return 0; +} + +static void shutdown(void) +{ +#if MALI_DDK_GATOR_API_VERSION == 3 + void (*kbase_gator_hwcnt_term_names_symbol)(void) = NULL; + int error_count = 0; +#endif + + kfree(counters); + kfree(counter_dump); + +#if MALI_DDK_GATOR_API_VERSION == 3 + SYMBOL_GET(kbase_gator_hwcnt_term_names, error_count); + + number_of_hardware_counters = -1; + hardware_counter_names = NULL; + if (kbase_gator_hwcnt_term_names_symbol != NULL) { + kbase_gator_hwcnt_term_names_symbol(); + pr_err("Released symbols\n"); + } + + SYMBOL_CLEANUP(kbase_gator_hwcnt_term_names); +#endif +} + +static struct gator_interface gator_events_mali_midgard_interface = { + .shutdown = shutdown, + .create_files = create_files, + .start = start, + .stop = stop, + .read = read +}; + +int gator_events_mali_midgard_hw_init(void) +{ +#if MALI_DDK_GATOR_API_VERSION == 3 + const char *const *(*kbase_gator_hwcnt_init_names_symbol)(uint32_t *) = NULL; + int error_count = 0; +#endif + + pr_debug("gator: Mali-Midgard: sw_counters init\n"); + +#if GATOR_TEST + test_all_is_read_scheduled(); +#endif + +#if MALI_DDK_GATOR_API_VERSION == 3 + SYMBOL_GET(kbase_gator_hwcnt_init_names, error_count); + if (error_count > 0) { + SYMBOL_CLEANUP(kbase_gator_hwcnt_init_names); + return 1; + } + + number_of_hardware_counters = -1; + hardware_counter_names = kbase_gator_hwcnt_init_names_symbol(&number_of_hardware_counters); + + SYMBOL_CLEANUP(kbase_gator_hwcnt_init_names); + + if ((hardware_counter_names == NULL) || (number_of_hardware_counters <= 0)) { + pr_err("gator: Error reading hardware counters names: got %d names\n", number_of_hardware_counters); + return -1; + } +#else + mali_name = "Midgard"; +#endif + + counters = kmalloc(sizeof(*counters)*number_of_hardware_counters, GFP_KERNEL); + counter_dump = kmalloc(sizeof(*counter_dump)*number_of_hardware_counters*2, GFP_KERNEL); + + gator_mali_initialise_counters(mali_activity, ARRAY_SIZE(mali_activity)); + gator_mali_initialise_counters(counters, number_of_hardware_counters); + + return gator_events_install(&gator_events_mali_midgard_interface); +} diff --git a/drivers/gator/gator_events_mali_midgard_hw_test.c b/drivers/gator/gator_events_mali_midgard_hw_test.c new file mode 100644 index 000000000000..31a91e1c72b2 --- /dev/null +++ b/drivers/gator/gator_events_mali_midgard_hw_test.c @@ -0,0 +1,55 @@ +/** + * Copyright (C) ARM Limited 2012-2014. 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. + * + */ + +/** + * Test functions for mali_t600_hw code. + */ + +static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns); + +static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int expected_result, s32 expected_next_ns) +{ + struct timespec current_time; + u32 prev_time_s = prev_s; + s32 next_read_time_ns = next_ns; + + current_time.tv_sec = s; + current_time.tv_nsec = ns; + + if (is_read_scheduled(¤t_time, &prev_time_s, &next_read_time_ns) != expected_result) { + pr_err("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result); + return 0; + } + + if (next_read_time_ns != expected_next_ns) { + pr_err("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns); + return 0; + } + + return 1; +} + +static void test_all_is_read_scheduled(void) +{ + const int HIGHEST_NS = 999999999; + int n_tests_passed = 0; + + pr_err("gator: running tests on %s\n", __FILE__); + + n_tests_passed += test_is_read_scheduled(0, 0, 0, 0, 1, READ_INTERVAL_NSEC); /* Null time */ + n_tests_passed += test_is_read_scheduled(100, 1000, 0, 0, 1, READ_INTERVAL_NSEC + 1000); /* Initial values */ + + n_tests_passed += test_is_read_scheduled(100, HIGHEST_NS, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500); + n_tests_passed += test_is_read_scheduled(101, 0001, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500 - NSEC_PER_SEC); + n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500 - NSEC_PER_SEC, 1, 600 + READ_INTERVAL_NSEC); + + n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC); + + pr_err("gator: %d tests passed\n", n_tests_passed); +} diff --git a/drivers/gator/gator_events_mali_t6xx.c b/drivers/gator/gator_events_mali_t6xx.c deleted file mode 100644 index e56ba84aefb8..000000000000 --- a/drivers/gator/gator_events_mali_t6xx.c +++ /dev/null @@ -1,567 +0,0 @@ -/** - * Copyright (C) ARM Limited 2011-2014. 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" - -#include -#include -#include -#include -#include - -#ifdef MALI_DIR_MIDGARD -/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/ -#include "mali_linux_trace.h" -#else -/* Old DDK Directory structure with kernel/drivers/gpu/arm/t6xx*/ -#include "linux/mali_linux_trace.h" -#endif - -#include "gator_events_mali_common.h" - -/* - * Check that the MALI_SUPPORT define is set to one of the allowable device codes. - */ -#if (MALI_SUPPORT != MALI_T6xx) -#error MALI_SUPPORT set to an invalid device code: expecting MALI_T6xx -#endif - -static const char mali_name[] = "Mali-T6xx"; - -/* Counters for Mali-T6xx: - * - * - Timeline events - * They are tracepoints, but instead of reporting a number they report a START/STOP event. - * They are reported in Streamline as number of microseconds while that particular counter was active. - * - * - SW counters - * They are tracepoints reporting a particular number. - * They are accumulated in sw_counter_data array until they are passed to Streamline, then they are zeroed. - * - * - Accumulators - * They are the same as software counters but their value is not zeroed. - */ - -/* Timeline (start/stop) activity */ -static const char *timeline_event_names[] = { - "PM_SHADER_0", - "PM_SHADER_1", - "PM_SHADER_2", - "PM_SHADER_3", - "PM_SHADER_4", - "PM_SHADER_5", - "PM_SHADER_6", - "PM_SHADER_7", - "PM_TILER_0", - "PM_L2_0", - "PM_L2_1", - "MMU_AS_0", - "MMU_AS_1", - "MMU_AS_2", - "MMU_AS_3" -}; - -enum { - PM_SHADER_0 = 0, - PM_SHADER_1, - PM_SHADER_2, - PM_SHADER_3, - PM_SHADER_4, - PM_SHADER_5, - PM_SHADER_6, - PM_SHADER_7, - PM_TILER_0, - PM_L2_0, - PM_L2_1, - MMU_AS_0, - MMU_AS_1, - MMU_AS_2, - MMU_AS_3 -}; -/* The number of shader blocks in the enum above */ -#define NUM_PM_SHADER (8) - -/* Software Counters */ -static const char *software_counter_names[] = { - "MMU_PAGE_FAULT_0", - "MMU_PAGE_FAULT_1", - "MMU_PAGE_FAULT_2", - "MMU_PAGE_FAULT_3" -}; - -enum { - MMU_PAGE_FAULT_0 = 0, - MMU_PAGE_FAULT_1, - MMU_PAGE_FAULT_2, - MMU_PAGE_FAULT_3 -}; - -/* Software Counters */ -static const char *accumulators_names[] = { - "TOTAL_ALLOC_PAGES" -}; - -enum { - TOTAL_ALLOC_PAGES = 0 -}; - -#define FIRST_TIMELINE_EVENT (0) -#define NUMBER_OF_TIMELINE_EVENTS (sizeof(timeline_event_names) / sizeof(timeline_event_names[0])) -#define FIRST_SOFTWARE_COUNTER (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS) -#define NUMBER_OF_SOFTWARE_COUNTERS (sizeof(software_counter_names) / sizeof(software_counter_names[0])) -#define FIRST_ACCUMULATOR (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS) -#define NUMBER_OF_ACCUMULATORS (sizeof(accumulators_names) / sizeof(accumulators_names[0])) -#define FILMSTRIP (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS) -#define NUMBER_OF_EVENTS (NUMBER_OF_TIMELINE_EVENTS + NUMBER_OF_SOFTWARE_COUNTERS + NUMBER_OF_ACCUMULATORS + 1) - -/* - * gatorfs variables for counter enable state - */ -static mali_counter counters[NUMBER_OF_EVENTS]; -static unsigned long filmstrip_event; - -/* An array used to return the data we recorded - * as key,value pairs hence the *2 - */ -static unsigned long counter_dump[NUMBER_OF_EVENTS * 2]; - -/* - * Array holding counter start times (in ns) for each counter. A zero here - * indicates that the activity monitored by this counter is not running. - */ -static struct timespec timeline_event_starttime[NUMBER_OF_TIMELINE_EVENTS]; - -/* The data we have recorded */ -static unsigned int timeline_data[NUMBER_OF_TIMELINE_EVENTS]; -static unsigned int sw_counter_data[NUMBER_OF_SOFTWARE_COUNTERS]; -static unsigned int accumulators_data[NUMBER_OF_ACCUMULATORS]; - -/* Hold the previous timestamp, used to calculate the sample interval. */ -static struct timespec prev_timestamp; - -/** - * Returns the timespan (in microseconds) between the two specified timestamps. - * - * @param start Ptr to the start timestamp - * @param end Ptr to the end timestamp - * - * @return Number of microseconds between the two timestamps (can be negative if start follows end). - */ -static inline long get_duration_us(const struct timespec *start, const struct timespec *end) -{ - long event_duration_us = (end->tv_nsec - start->tv_nsec) / 1000; - event_duration_us += (end->tv_sec - start->tv_sec) * 1000000; - - return event_duration_us; -} - -static void record_timeline_event(unsigned int timeline_index, unsigned int type) -{ - struct timespec event_timestamp; - struct timespec *event_start = &timeline_event_starttime[timeline_index]; - - switch (type) { - case ACTIVITY_START: - /* Get the event time... */ - getnstimeofday(&event_timestamp); - - /* Remember the start time if the activity is not already started */ - if (event_start->tv_sec == 0) { - *event_start = event_timestamp; /* Structure copy */ - } - break; - - case ACTIVITY_STOP: - /* if the counter was started... */ - if (event_start->tv_sec != 0) { - /* Get the event time... */ - getnstimeofday(&event_timestamp); - - /* Accumulate the duration in us */ - timeline_data[timeline_index] += get_duration_us(event_start, &event_timestamp); - - /* Reset the start time to indicate the activity is stopped. */ - event_start->tv_sec = 0; - } - break; - - default: - /* Other activity events are ignored. */ - break; - } -} - -/* - * Documentation about the following tracepoints is in mali_linux_trace.h - */ - -GATOR_DEFINE_PROBE(mali_pm_status, TP_PROTO(unsigned int event_id, unsigned long long value)) -{ -#define SHADER_PRESENT_LO 0x100 /* (RO) Shader core present bitmap, low word */ -#define TILER_PRESENT_LO 0x110 /* (RO) Tiler core present bitmap, low word */ -#define L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */ -#define BIT_AT(value, pos) ((value >> pos) & 1) - - static unsigned long long previous_shader_bitmask = 0; - static unsigned long long previous_tiler_bitmask = 0; - static unsigned long long previous_l2_bitmask = 0; - - switch (event_id) { - case SHADER_PRESENT_LO: - { - unsigned long long changed_bitmask = previous_shader_bitmask ^ value; - int pos; - - for (pos = 0; pos < NUM_PM_SHADER; ++pos) { - if (BIT_AT(changed_bitmask, pos)) { - record_timeline_event(PM_SHADER_0 + pos, BIT_AT(value, pos) ? ACTIVITY_START : ACTIVITY_STOP); - } - } - - previous_shader_bitmask = value; - break; - } - - case TILER_PRESENT_LO: - { - unsigned long long changed = previous_tiler_bitmask ^ value; - - if (BIT_AT(changed, 0)) { - record_timeline_event(PM_TILER_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); - } - - previous_tiler_bitmask = value; - break; - } - - case L2_PRESENT_LO: - { - unsigned long long changed = previous_l2_bitmask ^ value; - - if (BIT_AT(changed, 0)) { - record_timeline_event(PM_L2_0, BIT_AT(value, 0) ? ACTIVITY_START : ACTIVITY_STOP); - } - if (BIT_AT(changed, 4)) { - record_timeline_event(PM_L2_1, BIT_AT(value, 4) ? ACTIVITY_START : ACTIVITY_STOP); - } - - previous_l2_bitmask = value; - break; - } - - default: - /* No other blocks are supported at present */ - break; - } - -#undef SHADER_PRESENT_LO -#undef TILER_PRESENT_LO -#undef L2_PRESENT_LO -#undef BIT_AT -} - -GATOR_DEFINE_PROBE(mali_page_fault_insert_pages, TP_PROTO(int event_id, unsigned long value)) -{ - /* We add to the previous since we may receive many tracepoints in one sample period */ - sw_counter_data[MMU_PAGE_FAULT_0 + event_id] += value; -} - -GATOR_DEFINE_PROBE(mali_mmu_as_in_use, TP_PROTO(int event_id)) -{ - record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_START); -} - -GATOR_DEFINE_PROBE(mali_mmu_as_released, TP_PROTO(int event_id)) -{ - record_timeline_event(MMU_AS_0 + event_id, ACTIVITY_STOP); -} - -GATOR_DEFINE_PROBE(mali_total_alloc_pages_change, TP_PROTO(long long int event_id)) -{ - accumulators_data[TOTAL_ALLOC_PAGES] = event_id; -} - -static int create_files(struct super_block *sb, struct dentry *root) -{ - int event; - /* - * Create the filesystem for all events - */ - int counter_index = 0; - mali_profiling_control_type *mali_control; - - for (event = FIRST_TIMELINE_EVENT; event < FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS; event++) { - if (gator_mali_create_file_system(mali_name, timeline_event_names[counter_index], sb, root, &counters[event], NULL) != 0) { - return -1; - } - counter_index++; - } - counter_index = 0; - for (event = FIRST_SOFTWARE_COUNTER; event < FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS; event++) { - if (gator_mali_create_file_system(mali_name, software_counter_names[counter_index], sb, root, &counters[event], NULL) != 0) { - return -1; - } - counter_index++; - } - counter_index = 0; - for (event = FIRST_ACCUMULATOR; event < FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS; event++) { - if (gator_mali_create_file_system(mali_name, accumulators_names[counter_index], sb, root, &counters[event], NULL) != 0) { - return -1; - } - counter_index++; - } - - mali_control = symbol_get(_mali_profiling_control); - if (mali_control) { - if (gator_mali_create_file_system(mali_name, "Filmstrip_cnt0", sb, root, &counters[FILMSTRIP], &filmstrip_event) != 0) { - return -1; - } - symbol_put(_mali_profiling_control); - } - - return 0; -} - -static int register_tracepoints(void) -{ - if (GATOR_REGISTER_TRACE(mali_pm_status)) { - pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint failed to activate\n"); - return 0; - } - - if (GATOR_REGISTER_TRACE(mali_page_fault_insert_pages)) { - pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint failed to activate\n"); - return 0; - } - - if (GATOR_REGISTER_TRACE(mali_mmu_as_in_use)) { - pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint failed to activate\n"); - return 0; - } - - if (GATOR_REGISTER_TRACE(mali_mmu_as_released)) { - pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint failed to activate\n"); - return 0; - } - - if (GATOR_REGISTER_TRACE(mali_total_alloc_pages_change)) { - pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint failed to activate\n"); - return 0; - } - - pr_debug("gator: Mali-T6xx: start\n"); - pr_debug("gator: Mali-T6xx: mali_pm_status probe is at %p\n", &probe_mali_pm_status); - pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages probe is at %p\n", &probe_mali_page_fault_insert_pages); - pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use probe is at %p\n", &probe_mali_mmu_as_in_use); - pr_debug("gator: Mali-T6xx: mali_mmu_as_released probe is at %p\n", &probe_mali_mmu_as_released); - pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change probe is at %p\n", &probe_mali_total_alloc_pages_change); - - return 1; -} - -static int start(void) -{ - unsigned int cnt; - mali_profiling_control_type *mali_control; - - /* Clean all data for the next capture */ - for (cnt = 0; cnt < NUMBER_OF_TIMELINE_EVENTS; cnt++) { - timeline_event_starttime[cnt].tv_sec = timeline_event_starttime[cnt].tv_nsec = 0; - timeline_data[cnt] = 0; - } - - for (cnt = 0; cnt < NUMBER_OF_SOFTWARE_COUNTERS; cnt++) { - sw_counter_data[cnt] = 0; - } - - for (cnt = 0; cnt < NUMBER_OF_ACCUMULATORS; cnt++) { - accumulators_data[cnt] = 0; - } - - /* Register tracepoints */ - if (register_tracepoints() == 0) { - return -1; - } - - /* Generic control interface for Mali DDK. */ - mali_control = symbol_get(_mali_profiling_control); - if (mali_control) { - /* The event attribute in the XML file keeps the actual frame rate. */ - unsigned int enabled = counters[FILMSTRIP].enabled ? 1 : 0; - unsigned int rate = filmstrip_event & 0xff; - unsigned int resize_factor = (filmstrip_event >> 8) & 0xff; - - pr_debug("gator: mali online _mali_profiling_control symbol @ %p\n", mali_control); - -#define FBDUMP_CONTROL_ENABLE (1) -#define FBDUMP_CONTROL_RATE (2) -#define FBDUMP_CONTROL_RESIZE_FACTOR (4) - mali_control(FBDUMP_CONTROL_ENABLE, enabled); - mali_control(FBDUMP_CONTROL_RATE, rate); - mali_control(FBDUMP_CONTROL_RESIZE_FACTOR, resize_factor); - - pr_debug("gator: sent mali_control enabled=%d, rate=%d, resize_factor=%d\n", enabled, rate, resize_factor); - - symbol_put(_mali_profiling_control); - } else { - printk("gator: mali online _mali_profiling_control symbol not found\n"); - } - - /* - * Set the first timestamp for calculating the sample interval. The first interval could be quite long, - * since it will be the time between 'start' and the first 'read'. - * This means that timeline values will be divided by a big number for the first sample. - */ - getnstimeofday(&prev_timestamp); - - return 0; -} - -static void stop(void) -{ - mali_profiling_control_type *mali_control; - - pr_debug("gator: Mali-T6xx: stop\n"); - - /* - * It is safe to unregister traces even if they were not successfully - * registered, so no need to check. - */ - GATOR_UNREGISTER_TRACE(mali_pm_status); - pr_debug("gator: Mali-T6xx: mali_pm_status tracepoint deactivated\n"); - - GATOR_UNREGISTER_TRACE(mali_page_fault_insert_pages); - pr_debug("gator: Mali-T6xx: mali_page_fault_insert_pages tracepoint deactivated\n"); - - GATOR_UNREGISTER_TRACE(mali_mmu_as_in_use); - pr_debug("gator: Mali-T6xx: mali_mmu_as_in_use tracepoint deactivated\n"); - - GATOR_UNREGISTER_TRACE(mali_mmu_as_released); - pr_debug("gator: Mali-T6xx: mali_mmu_as_released tracepoint deactivated\n"); - - GATOR_UNREGISTER_TRACE(mali_total_alloc_pages_change); - pr_debug("gator: Mali-T6xx: mali_total_alloc_pages_change tracepoint deactivated\n"); - - /* Generic control interface for Mali DDK. */ - mali_control = symbol_get(_mali_profiling_control); - if (mali_control) { - pr_debug("gator: mali offline _mali_profiling_control symbol @ %p\n", mali_control); - - mali_control(FBDUMP_CONTROL_ENABLE, 0); - - symbol_put(_mali_profiling_control); - } else { - printk("gator: mali offline _mali_profiling_control symbol not found\n"); - } -} - -static int read(int **buffer) -{ - int cnt; - int len = 0; - long sample_interval_us = 0; - struct timespec read_timestamp; - - if (!on_primary_core()) { - return 0; - } - - /* Get the start of this sample period. */ - getnstimeofday(&read_timestamp); - - /* - * Calculate the sample interval if the previous sample time is valid. - * We use tv_sec since it will not be 0. - */ - if (prev_timestamp.tv_sec != 0) { - sample_interval_us = get_duration_us(&prev_timestamp, &read_timestamp); - } - - /* Structure copy. Update the previous timestamp. */ - prev_timestamp = read_timestamp; - - /* - * Report the timeline counters (ACTIVITY_START/STOP) - */ - for (cnt = FIRST_TIMELINE_EVENT; cnt < (FIRST_TIMELINE_EVENT + NUMBER_OF_TIMELINE_EVENTS); cnt++) { - mali_counter *counter = &counters[cnt]; - if (counter->enabled) { - const int index = cnt - FIRST_TIMELINE_EVENT; - unsigned int value; - - /* If the activity is still running, reset its start time to the start of this sample period - * to correct the count. Add the time up to the end of the sample onto the count. */ - if (timeline_event_starttime[index].tv_sec != 0) { - const long event_duration = get_duration_us(&timeline_event_starttime[index], &read_timestamp); - timeline_data[index] += event_duration; - timeline_event_starttime[index] = read_timestamp; /* Activity is still running. */ - } - - if (sample_interval_us != 0) { - /* Convert the counter to a percent-of-sample value */ - value = (timeline_data[index] * 100) / sample_interval_us; - } else { - pr_debug("gator: Mali-T6xx: setting value to zero\n"); - value = 0; - } - - /* Clear the counter value ready for the next sample. */ - timeline_data[index] = 0; - - counter_dump[len++] = counter->key; - counter_dump[len++] = value; - } - } - - /* Report the software counters */ - for (cnt = FIRST_SOFTWARE_COUNTER; cnt < (FIRST_SOFTWARE_COUNTER + NUMBER_OF_SOFTWARE_COUNTERS); cnt++) { - const mali_counter *counter = &counters[cnt]; - if (counter->enabled) { - const int index = cnt - FIRST_SOFTWARE_COUNTER; - counter_dump[len++] = counter->key; - counter_dump[len++] = sw_counter_data[index]; - /* Set the value to zero for the next time */ - sw_counter_data[index] = 0; - } - } - - /* Report the accumulators */ - for (cnt = FIRST_ACCUMULATOR; cnt < (FIRST_ACCUMULATOR + NUMBER_OF_ACCUMULATORS); cnt++) { - const mali_counter *counter = &counters[cnt]; - if (counter->enabled) { - const int index = cnt - FIRST_ACCUMULATOR; - counter_dump[len++] = counter->key; - counter_dump[len++] = accumulators_data[index]; - /* Do not zero the accumulator */ - } - } - - /* Update the buffer */ - if (buffer) { - *buffer = (int *)counter_dump; - } - - return len; -} - -static struct gator_interface gator_events_mali_t6xx_interface = { - .create_files = create_files, - .start = start, - .stop = stop, - .read = read -}; - -extern int gator_events_mali_t6xx_init(void) -{ - pr_debug("gator: Mali-T6xx: sw_counters init\n"); - - gator_mali_initialise_counters(counters, NUMBER_OF_EVENTS); - - return gator_events_install(&gator_events_mali_t6xx_interface); -} diff --git a/drivers/gator/gator_events_mali_t6xx_hw.c b/drivers/gator/gator_events_mali_t6xx_hw.c deleted file mode 100644 index 3a072bb6ac06..000000000000 --- a/drivers/gator/gator_events_mali_t6xx_hw.c +++ /dev/null @@ -1,913 +0,0 @@ -/** - * Copyright (C) ARM Limited 2012-2014. 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" - -#include -#include -#include -#include -#include - -/* Mali T6xx DDK includes */ -#if defined(MALI_SIMPLE_API) -/* Header with wrapper functions to kbase structures and functions */ -#include "mali/mali_dd_gator_api.h" -#elif defined(MALI_DIR_MIDGARD) -/* New DDK Directory structure with kernel/drivers/gpu/arm/midgard*/ -#include "mali_linux_trace.h" -#include "mali_kbase.h" -#include "mali_kbase_mem_linux.h" -#else -/* Old DDK Directory structure with kernel/drivers/gpu/arm/t6xx*/ -#include "linux/mali_linux_trace.h" -#include "kbase/src/common/mali_kbase.h" -#include "kbase/src/linux/mali_kbase_mem_linux.h" -#endif - -/* If API version is not specified then assume API version 1. */ -#ifndef MALI_DDK_GATOR_API_VERSION -#define MALI_DDK_GATOR_API_VERSION 1 -#endif - -#if (MALI_DDK_GATOR_API_VERSION != 1) && (MALI_DDK_GATOR_API_VERSION != 2) && (MALI_DDK_GATOR_API_VERSION != 3) -#error MALI_DDK_GATOR_API_VERSION is invalid (must be 1 for r1/r2 DDK, or 2 for r3 DDK, or 3 for r? DDK). -#endif - -#include "gator_events_mali_common.h" - -/* - * Mali-T6xx - */ -#if MALI_DDK_GATOR_API_VERSION == 3 -typedef uint32_t kbase_dd_instr_hwcnt_dump_irq_type(struct mali_dd_hwcnt_handles *); -typedef uint32_t kbase_dd_instr_hwcnt_dump_complete_type(struct mali_dd_hwcnt_handles *, uint32_t *); -typedef struct mali_dd_hwcnt_handles* mali_dd_hwcnt_init_type(struct mali_dd_hwcnt_info *); -typedef void mali_dd_hwcnt_clear_type(struct mali_dd_hwcnt_info *, struct mali_dd_hwcnt_handles *); - -static kbase_dd_instr_hwcnt_dump_irq_type *kbase_dd_instr_hwcnt_dump_irq_symbol; -static kbase_dd_instr_hwcnt_dump_complete_type *kbase_dd_instr_hwcnt_dump_complete_symbol; -static mali_dd_hwcnt_init_type *mali_dd_hwcnt_init_symbol; -static mali_dd_hwcnt_clear_type *mali_dd_hwcnt_clear_symbol; - -#else -typedef struct kbase_device *kbase_find_device_type(int); -typedef struct kbase_context *kbase_create_context_type(struct kbase_device *); -typedef void kbase_destroy_context_type(struct kbase_context *); - -#if MALI_DDK_GATOR_API_VERSION == 1 -typedef void *kbase_va_alloc_type(struct kbase_context *, u32); -typedef void kbase_va_free_type(struct kbase_context *, void *); -#elif MALI_DDK_GATOR_API_VERSION == 2 -typedef void *kbase_va_alloc_type(struct kbase_context *, u32, kbase_hwc_dma_mapping * handle); -typedef void kbase_va_free_type(struct kbase_context *, kbase_hwc_dma_mapping * handle); -#endif - -typedef mali_error kbase_instr_hwcnt_enable_type(struct kbase_context *, struct kbase_uk_hwcnt_setup *); -typedef mali_error kbase_instr_hwcnt_disable_type(struct kbase_context *); -typedef mali_error kbase_instr_hwcnt_clear_type(struct kbase_context *); -typedef mali_error kbase_instr_hwcnt_dump_irq_type(struct kbase_context *); -typedef mali_bool kbase_instr_hwcnt_dump_complete_type(struct kbase_context *, mali_bool *); - -static kbase_find_device_type *kbase_find_device_symbol; -static kbase_create_context_type *kbase_create_context_symbol; -static kbase_va_alloc_type *kbase_va_alloc_symbol; -static kbase_instr_hwcnt_enable_type *kbase_instr_hwcnt_enable_symbol; -static kbase_instr_hwcnt_clear_type *kbase_instr_hwcnt_clear_symbol; -static kbase_instr_hwcnt_dump_irq_type *kbase_instr_hwcnt_dump_irq_symbol; -static kbase_instr_hwcnt_dump_complete_type *kbase_instr_hwcnt_dump_complete_symbol; -static kbase_instr_hwcnt_disable_type *kbase_instr_hwcnt_disable_symbol; -static kbase_va_free_type *kbase_va_free_symbol; -static kbase_destroy_context_type *kbase_destroy_context_symbol; -#endif - -static long shader_present_low = 0; - -/** The interval between reads, in ns. - * - * Earlier we introduced - * a 'hold off for 1ms after last read' to resolve MIDBASE-2178 and MALINE-724. - * However, the 1ms hold off is too long if no context switches occur as there is a race - * between this value and the tick of the read clock in gator which is also 1ms. If we 'miss' the - * current read, the counter values are effectively 'spread' over 2ms and the values seen are half - * what they should be (since Streamline averages over sample time). In the presence of context switches - * this spread can vary and markedly affect the counters. Currently there is no 'proper' solution to - * this, but empirically we have found that reducing the minimum read interval to 950us causes the - * counts to be much more stable. - */ -static const int READ_INTERVAL_NSEC = 950000; - -#if GATOR_TEST -#include "gator_events_mali_t6xx_hw_test.c" -#endif - -/* Blocks for HW counters */ -enum { - JM_BLOCK = 0, - TILER_BLOCK, - SHADER_BLOCK, - MMU_BLOCK -}; - -static const char mali_name[] = "Mali-T6xx"; - -/* Counters for Mali-T6xx: - * - * - HW counters, 4 blocks - * For HW counters we need strings to create /dev/gator/events files. - * Enums are not needed because the position of the HW name in the array is the same - * of the corresponding value in the received block of memory. - * HW counters are requested by calculating a bitmask, passed then to the driver. - * Every millisecond a HW counters dump is requested, and if the previous has been completed they are read. - */ - -/* Hardware Counters */ -static const char *const hardware_counter_names[] = { - /* Job Manager */ - "", - "", - "", - "", - "MESSAGES_SENT", - "MESSAGES_RECEIVED", - "GPU_ACTIVE", /* 6 */ - "IRQ_ACTIVE", - "JS0_JOBS", - "JS0_TASKS", - "JS0_ACTIVE", - "", - "JS0_WAIT_READ", - "JS0_WAIT_ISSUE", - "JS0_WAIT_DEPEND", - "JS0_WAIT_FINISH", - "JS1_JOBS", - "JS1_TASKS", - "JS1_ACTIVE", - "", - "JS1_WAIT_READ", - "JS1_WAIT_ISSUE", - "JS1_WAIT_DEPEND", - "JS1_WAIT_FINISH", - "JS2_JOBS", - "JS2_TASKS", - "JS2_ACTIVE", - "", - "JS2_WAIT_READ", - "JS2_WAIT_ISSUE", - "JS2_WAIT_DEPEND", - "JS2_WAIT_FINISH", - "JS3_JOBS", - "JS3_TASKS", - "JS3_ACTIVE", - "", - "JS3_WAIT_READ", - "JS3_WAIT_ISSUE", - "JS3_WAIT_DEPEND", - "JS3_WAIT_FINISH", - "JS4_JOBS", - "JS4_TASKS", - "JS4_ACTIVE", - "", - "JS4_WAIT_READ", - "JS4_WAIT_ISSUE", - "JS4_WAIT_DEPEND", - "JS4_WAIT_FINISH", - "JS5_JOBS", - "JS5_TASKS", - "JS5_ACTIVE", - "", - "JS5_WAIT_READ", - "JS5_WAIT_ISSUE", - "JS5_WAIT_DEPEND", - "JS5_WAIT_FINISH", - "JS6_JOBS", - "JS6_TASKS", - "JS6_ACTIVE", - "", - "JS6_WAIT_READ", - "JS6_WAIT_ISSUE", - "JS6_WAIT_DEPEND", - "JS6_WAIT_FINISH", - - /*Tiler */ - "", - "", - "", - "JOBS_PROCESSED", - "TRIANGLES", - "QUADS", - "POLYGONS", - "POINTS", - "LINES", - "VCACHE_HIT", - "VCACHE_MISS", - "FRONT_FACING", - "BACK_FACING", - "PRIM_VISIBLE", - "PRIM_CULLED", - "PRIM_CLIPPED", - "LEVEL0", - "LEVEL1", - "LEVEL2", - "LEVEL3", - "LEVEL4", - "LEVEL5", - "LEVEL6", - "LEVEL7", - "COMMAND_1", - "COMMAND_2", - "COMMAND_3", - "COMMAND_4", - "COMMAND_4_7", - "COMMAND_8_15", - "COMMAND_16_63", - "COMMAND_64", - "COMPRESS_IN", - "COMPRESS_OUT", - "COMPRESS_FLUSH", - "TIMESTAMPS", - "PCACHE_HIT", - "PCACHE_MISS", - "PCACHE_LINE", - "PCACHE_STALL", - "WRBUF_HIT", - "WRBUF_MISS", - "WRBUF_LINE", - "WRBUF_PARTIAL", - "WRBUF_STALL", - "ACTIVE", - "LOADING_DESC", - "INDEX_WAIT", - "INDEX_RANGE_WAIT", - "VERTEX_WAIT", - "PCACHE_WAIT", - "WRBUF_WAIT", - "BUS_READ", - "BUS_WRITE", - "", - "", - "", - "", - "", - "UTLB_STALL", - "UTLB_REPLAY_MISS", - "UTLB_REPLAY_FULL", - "UTLB_NEW_MISS", - "UTLB_HIT", - - /* Shader Core */ - "", - "", - "", - "SHADER_CORE_ACTIVE", - "FRAG_ACTIVE", - "FRAG_PRIMATIVES", - "FRAG_PRIMATIVES_DROPPED", - "FRAG_CYCLE_DESC", - "FRAG_CYCLES_PLR", - "FRAG_CYCLES_VERT", - "FRAG_CYCLES_TRISETUP", - "FRAG_CYCLES_RAST", - "FRAG_THREADS", - "FRAG_DUMMY_THREADS", - "FRAG_QUADS_RAST", - "FRAG_QUADS_EZS_TEST", - "FRAG_QUADS_EZS_KILLED", - "FRAG_QUADS_LZS_TEST", - "FRAG_QUADS_LZS_KILLED", - "FRAG_CYCLE_NO_TILE", - "FRAG_NUM_TILES", - "FRAG_TRANS_ELIM", - "COMPUTE_ACTIVE", - "COMPUTE_TASKS", - "COMPUTE_THREADS", - "COMPUTE_CYCLES_DESC", - "TRIPIPE_ACTIVE", - "ARITH_WORDS", - "ARITH_CYCLES_REG", - "ARITH_CYCLES_L0", - "ARITH_FRAG_DEPEND", - "LS_WORDS", - "LS_ISSUES", - "LS_RESTARTS", - "LS_REISSUES_MISS", - "LS_REISSUES_VD", - "LS_REISSUE_ATTRIB_MISS", - "LS_NO_WB", - "TEX_WORDS", - "TEX_BUBBLES", - "TEX_WORDS_L0", - "TEX_WORDS_DESC", - "TEX_THREADS", - "TEX_RECIRC_FMISS", - "TEX_RECIRC_DESC", - "TEX_RECIRC_MULTI", - "TEX_RECIRC_PMISS", - "TEX_RECIRC_CONF", - "LSC_READ_HITS", - "LSC_READ_MISSES", - "LSC_WRITE_HITS", - "LSC_WRITE_MISSES", - "LSC_ATOMIC_HITS", - "LSC_ATOMIC_MISSES", - "LSC_LINE_FETCHES", - "LSC_DIRTY_LINE", - "LSC_SNOOPS", - "AXI_TLB_STALL", - "AXI_TLB_MIESS", - "AXI_TLB_TRANSACTION", - "LS_TLB_MISS", - "LS_TLB_HIT", - "AXI_BEATS_READ", - "AXI_BEATS_WRITTEN", - - /*L2 and MMU */ - "", - "", - "", - "", - "MMU_HIT", - "MMU_NEW_MISS", - "MMU_REPLAY_FULL", - "MMU_REPLAY_MISS", - "MMU_TABLE_WALK", - "", - "", - "", - "", - "", - "", - "", - "UTLB_HIT", - "UTLB_NEW_MISS", - "UTLB_REPLAY_FULL", - "UTLB_REPLAY_MISS", - "UTLB_STALL", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "L2_WRITE_BEATS", - "L2_READ_BEATS", - "L2_ANY_LOOKUP", - "L2_READ_LOOKUP", - "L2_SREAD_LOOKUP", - "L2_READ_REPLAY", - "L2_READ_SNOOP", - "L2_READ_HIT", - "L2_CLEAN_MISS", - "L2_WRITE_LOOKUP", - "L2_SWRITE_LOOKUP", - "L2_WRITE_REPLAY", - "L2_WRITE_SNOOP", - "L2_WRITE_HIT", - "L2_EXT_READ_FULL", - "L2_EXT_READ_HALF", - "L2_EXT_WRITE_FULL", - "L2_EXT_WRITE_HALF", - "L2_EXT_READ", - "L2_EXT_READ_LINE", - "L2_EXT_WRITE", - "L2_EXT_WRITE_LINE", - "L2_EXT_WRITE_SMALL", - "L2_EXT_BARRIER", - "L2_EXT_AR_STALL", - "L2_EXT_R_BUF_FULL", - "L2_EXT_RD_BUF_FULL", - "L2_EXT_R_RAW", - "L2_EXT_W_STALL", - "L2_EXT_W_BUF_FULL", - "L2_EXT_R_W_HAZARD", - "L2_TAG_HAZARD", - "L2_SNOOP_FULL", - "L2_REPLAY_FULL" -}; - -#define NUMBER_OF_HARDWARE_COUNTERS (sizeof(hardware_counter_names) / sizeof(hardware_counter_names[0])) - -#define GET_HW_BLOCK(c) (((c) >> 6) & 0x3) -#define GET_COUNTER_OFFSET(c) ((c) & 0x3f) - -#if MALI_DDK_GATOR_API_VERSION == 3 -/* Opaque handles for kbase_context and kbase_hwc_dma_mapping */ -static struct mali_dd_hwcnt_handles *handles; - -/* Information about hardware counters */ -static struct mali_dd_hwcnt_info *in_out_info; - -#else -/* Memory to dump hardware counters into */ -static void *kernel_dump_buffer; - -#if MALI_DDK_GATOR_API_VERSION == 2 -/* DMA state used to manage lifetime of the buffer */ -kbase_hwc_dma_mapping kernel_dump_buffer_handle; -#endif - -/* kbase context and device */ -static struct kbase_context *kbcontext = NULL; -static struct kbase_device *kbdevice = NULL; -#endif - -static volatile bool kbase_device_busy = false; -static unsigned int num_hardware_counters_enabled; - -/* - * gatorfs variables for counter enable state - */ -static mali_counter counters[NUMBER_OF_HARDWARE_COUNTERS]; - -/* An array used to return the data we recorded - * as key,value pairs hence the *2 - */ -static unsigned long counter_dump[NUMBER_OF_HARDWARE_COUNTERS * 2]; - -extern mali_counter mali_activity[3]; -static const char* const mali_activity_names[] = { - "fragment", - "vertex", - "opencl", -}; - -#define SYMBOL_GET(FUNCTION, ERROR_COUNT) \ - if(FUNCTION ## _symbol) \ - { \ - printk("gator: mali " #FUNCTION " symbol was already registered\n"); \ - (ERROR_COUNT)++; \ - } \ - else \ - { \ - FUNCTION ## _symbol = symbol_get(FUNCTION); \ - if(! FUNCTION ## _symbol) \ - { \ - printk("gator: mali online " #FUNCTION " symbol not found\n"); \ - (ERROR_COUNT)++; \ - } \ - } - -#define SYMBOL_CLEANUP(FUNCTION) \ - if(FUNCTION ## _symbol) \ - { \ - symbol_put(FUNCTION); \ - FUNCTION ## _symbol = NULL; \ - } - -/** - * Execute symbol_get for all the Mali symbols and check for success. - * @return the number of symbols not loaded. - */ -static int init_symbols(void) -{ - int error_count = 0; -#if MALI_DDK_GATOR_API_VERSION == 3 - SYMBOL_GET(kbase_dd_instr_hwcnt_dump_irq, error_count); - SYMBOL_GET(kbase_dd_instr_hwcnt_dump_complete, error_count); - SYMBOL_GET(mali_dd_hwcnt_init, error_count); - SYMBOL_GET(mali_dd_hwcnt_clear, error_count); -#else - SYMBOL_GET(kbase_find_device, error_count); - SYMBOL_GET(kbase_create_context, error_count); - SYMBOL_GET(kbase_va_alloc, error_count); - SYMBOL_GET(kbase_instr_hwcnt_enable, error_count); - SYMBOL_GET(kbase_instr_hwcnt_clear, error_count); - SYMBOL_GET(kbase_instr_hwcnt_dump_irq, error_count); - SYMBOL_GET(kbase_instr_hwcnt_dump_complete, error_count); - SYMBOL_GET(kbase_instr_hwcnt_disable, error_count); - SYMBOL_GET(kbase_va_free, error_count); - SYMBOL_GET(kbase_destroy_context, error_count); -#endif - - return error_count; -} - -/** - * Execute symbol_put for all the registered Mali symbols. - */ -static void clean_symbols(void) -{ -#if MALI_DDK_GATOR_API_VERSION == 3 - SYMBOL_CLEANUP(kbase_dd_instr_hwcnt_dump_irq); - SYMBOL_CLEANUP(kbase_dd_instr_hwcnt_dump_complete); - SYMBOL_CLEANUP(mali_dd_hwcnt_init); - SYMBOL_CLEANUP(mali_dd_hwcnt_clear); -#else - SYMBOL_CLEANUP(kbase_find_device); - SYMBOL_CLEANUP(kbase_create_context); - SYMBOL_CLEANUP(kbase_va_alloc); - SYMBOL_CLEANUP(kbase_instr_hwcnt_enable); - SYMBOL_CLEANUP(kbase_instr_hwcnt_clear); - SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_irq); - SYMBOL_CLEANUP(kbase_instr_hwcnt_dump_complete); - SYMBOL_CLEANUP(kbase_instr_hwcnt_disable); - SYMBOL_CLEANUP(kbase_va_free); - SYMBOL_CLEANUP(kbase_destroy_context); -#endif -} - -/** - * Determines whether a read should take place - * @param current_time The current time, obtained from getnstimeofday() - * @param prev_time_s The number of seconds at the previous read attempt. - * @param next_read_time_ns The time (in ns) when the next read should be allowed. - * - * Note that this function has been separated out here to allow it to be tested. - */ -static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns) -{ - /* If the current ns count rolls over a second, roll the next read time too. */ - if (current_time->tv_sec != *prev_time_s) { - *next_read_time_ns = *next_read_time_ns - NSEC_PER_SEC; - } - - /* Abort the read if the next read time has not arrived. */ - if (current_time->tv_nsec < *next_read_time_ns) { - return 0; - } - - /* Set the next read some fixed time after this one, and update the read timestamp. */ - *next_read_time_ns = current_time->tv_nsec + READ_INTERVAL_NSEC; - - *prev_time_s = current_time->tv_sec; - return 1; -} - -static int start(void) -{ -#if MALI_DDK_GATOR_API_VERSION < 3 - struct kbase_uk_hwcnt_setup setup; - unsigned long long shadersPresent = 0; - u16 bitmask[] = { 0, 0, 0, 0 }; - mali_error err; -#endif - int cnt; - - /* Setup HW counters */ - num_hardware_counters_enabled = 0; - - if (NUMBER_OF_HARDWARE_COUNTERS != 256) { - pr_debug("Unexpected number of hardware counters defined: expecting 256, got %d\n", NUMBER_OF_HARDWARE_COUNTERS); - } - -#if MALI_DDK_GATOR_API_VERSION == 3 - /* Declare and initialise mali_dd_hwcnt_info structure */ - in_out_info = kmalloc(sizeof(struct mali_dd_hwcnt_info), GFP_KERNEL); - for (cnt = 0; cnt < 4; cnt++){ - in_out_info->bitmask[cnt] = 0; - } -#endif - /* Calculate enable bitmasks based on counters_enabled array */ - for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) { - const mali_counter *counter = &counters[cnt]; - if (counter->enabled) { - int block = GET_HW_BLOCK(cnt); - int enable_bit = GET_COUNTER_OFFSET(cnt) / 4; -#if MALI_DDK_GATOR_API_VERSION == 3 - in_out_info->bitmask[block] |= (1 << enable_bit); -#else - bitmask[block] |= (1 << enable_bit); -#endif - pr_debug("gator: Mali-T6xx: hardware counter %s selected [%d]\n", hardware_counter_names[cnt], cnt); - num_hardware_counters_enabled++; - } - } - -#if MALI_DDK_GATOR_API_VERSION == 3 - /* Create a kbase context for HW counters */ - if (num_hardware_counters_enabled > 0) { - if (init_symbols() > 0) { - clean_symbols(); - /* No Mali driver code entrypoints found - not a fault. */ - return 0; - } - - handles = mali_dd_hwcnt_init_symbol(in_out_info); - - if(handles == NULL) { - goto out; - } - - /* See if we can get the number of shader cores */ - shader_present_low = (unsigned long)in_out_info->shader_present_bitmap; - - kbase_device_busy = false; - } - - return 0; -#else - /* Create a kbase context for HW counters */ - if (num_hardware_counters_enabled > 0) { - if (init_symbols() > 0) { - clean_symbols(); - /* No Mali driver code entrypoints found - not a fault. */ - return 0; - } - - kbdevice = kbase_find_device_symbol(-1); - - /* If we already got a context, fail */ - if (kbcontext) { - pr_debug("gator: Mali-T6xx: error context already present\n"); - goto out; - } - - /* kbcontext will only be valid after all the Mali symbols are loaded successfully */ - kbcontext = kbase_create_context_symbol(kbdevice); - if (!kbcontext) { - pr_debug("gator: Mali-T6xx: error creating kbase context\n"); - goto out; - } - - - /* See if we can get the number of shader cores */ - shadersPresent = kbdevice->shader_present_bitmap; - shader_present_low = (unsigned long)shadersPresent; - - /* - * The amount of memory needed to store the dump (bytes) - * DUMP_SIZE = number of core groups - * * number of blocks (always 8 for midgard) - * * number of counters per block (always 64 for midgard) - * * number of bytes per counter (always 4 in midgard) - * For a Mali-T6xx with a single core group = 1 * 8 * 64 * 4 = 2048 - * For a Mali-T6xx with a dual core group = 2 * 8 * 64 * 4 = 4096 - */ -#if MALI_DDK_GATOR_API_VERSION == 1 - kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 4096); -#elif MALI_DDK_GATOR_API_VERSION == 2 - kernel_dump_buffer = kbase_va_alloc_symbol(kbcontext, 4096, &kernel_dump_buffer_handle); -#endif - if (!kernel_dump_buffer) { - pr_debug("gator: Mali-T6xx: error trying to allocate va\n"); - goto destroy_context; - } - - setup.dump_buffer = (uintptr_t)kernel_dump_buffer; - setup.jm_bm = bitmask[JM_BLOCK]; - setup.tiler_bm = bitmask[TILER_BLOCK]; - setup.shader_bm = bitmask[SHADER_BLOCK]; - setup.mmu_l2_bm = bitmask[MMU_BLOCK]; - /* These counters do not exist on Mali-T60x */ - setup.l3_cache_bm = 0; - - /* Use kbase API to enable hardware counters and provide dump buffer */ - err = kbase_instr_hwcnt_enable_symbol(kbcontext, &setup); - if (err != MALI_ERROR_NONE) { - pr_debug("gator: Mali-T6xx: can't setup hardware counters\n"); - goto free_buffer; - } - pr_debug("gator: Mali-T6xx: hardware counters enabled\n"); - kbase_instr_hwcnt_clear_symbol(kbcontext); - pr_debug("gator: Mali-T6xx: hardware counters cleared \n"); - - kbase_device_busy = false; - } - - return 0; - -free_buffer: -#if MALI_DDK_GATOR_API_VERSION == 1 - kbase_va_free_symbol(kbcontext, kernel_dump_buffer); -#elif MALI_DDK_GATOR_API_VERSION == 2 - kbase_va_free_symbol(kbcontext, &kernel_dump_buffer_handle); -#endif - -destroy_context: - kbase_destroy_context_symbol(kbcontext); -#endif - -out: - clean_symbols(); - return -1; -} - -static void stop(void) -{ - unsigned int cnt; -#if MALI_DDK_GATOR_API_VERSION == 3 - struct mali_dd_hwcnt_handles *temp_hand; -#else - struct kbase_context *temp_kbcontext; -#endif - - pr_debug("gator: Mali-T6xx: stop\n"); - - /* Set all counters as disabled */ - for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) { - counters[cnt].enabled = 0; - } - - /* Destroy the context for HW counters */ -#if MALI_DDK_GATOR_API_VERSION == 3 - if (num_hardware_counters_enabled > 0 && handles != NULL) { - /* - * Set the global variable to NULL before destroying it, because - * other function will check this before using it. - */ - temp_hand = handles; - handles = NULL; - - mali_dd_hwcnt_clear_symbol(in_out_info, temp_hand); - - kfree(in_out_info); - -#else - if (num_hardware_counters_enabled > 0 && kbcontext != NULL) { - /* - * Set the global variable to NULL before destroying it, because - * other function will check this before using it. - */ - temp_kbcontext = kbcontext; - kbcontext = NULL; - - kbase_instr_hwcnt_disable_symbol(temp_kbcontext); - -#if MALI_DDK_GATOR_API_VERSION == 1 - kbase_va_free_symbol(temp_kbcontext, kernel_dump_buffer); -#elif MALI_DDK_GATOR_API_VERSION == 2 - kbase_va_free_symbol(temp_kbcontext, &kernel_dump_buffer_handle); -#endif - - kbase_destroy_context_symbol(temp_kbcontext); -#endif - - pr_debug("gator: Mali-T6xx: hardware counters stopped\n"); - - clean_symbols(); - } -} - -static int read(int **buffer) -{ - int cnt; - int len = 0; - u32 value = 0; - uint32_t success; - - struct timespec current_time; - static u32 prev_time_s = 0; - static s32 next_read_time_ns = 0; - - if (!on_primary_core()) { - return 0; - } - - getnstimeofday(¤t_time); - - /* - * Discard reads unless a respectable time has passed. This reduces the load on the GPU without sacrificing - * accuracy on the Streamline display. - */ - if (!is_read_scheduled(¤t_time, &prev_time_s, &next_read_time_ns)) { - return 0; - } - - /* - * Report the HW counters - * Only process hardware counters if at least one of the hardware counters is enabled. - */ - if (num_hardware_counters_enabled > 0) { - const unsigned int vithar_blocks[] = { - 0x700, /* VITHAR_JOB_MANAGER, Block 0 */ - 0x400, /* VITHAR_TILER, Block 1 */ - 0x000, /* VITHAR_SHADER_CORE, Block 2 */ - 0x500 /* VITHAR_MEMORY_SYSTEM, Block 3 */ - }; - -#if MALI_DDK_GATOR_API_VERSION == 3 - if (!handles) { - return -1; - } - - /* Mali symbols can be called safely since a kbcontext is valid */ - if (kbase_dd_instr_hwcnt_dump_complete_symbol(handles, &success) == MALI_TRUE) { -#else - if (!kbcontext) { - return -1; - } - - /* Mali symbols can be called safely since a kbcontext is valid */ - if (kbase_instr_hwcnt_dump_complete_symbol(kbcontext, &success) == MALI_TRUE) { -#endif - kbase_device_busy = false; - - if (success == MALI_TRUE) { - /* Cycle through hardware counters and accumulate totals */ - for (cnt = 0; cnt < NUMBER_OF_HARDWARE_COUNTERS; cnt++) { - const mali_counter *counter = &counters[cnt]; - if (counter->enabled) { - const int block = GET_HW_BLOCK(cnt); - const int counter_offset = GET_COUNTER_OFFSET(cnt); - -#if MALI_DDK_GATOR_API_VERSION == 3 - const char* block_base_address = (char*)in_out_info->kernel_dump_buffer + vithar_blocks[block]; -#else - const char* block_base_address = (char*)kernel_dump_buffer + vithar_blocks[block]; -#endif - - /* If counter belongs to shader block need to take into account all cores */ - if (block == SHADER_BLOCK) { - int i = 0; - int shader_core_count = 0; - value = 0; - - for (i = 0; i < 4; i++) { - if ((shader_present_low >> i) & 1) { - value += *((u32*) (block_base_address + (0x100 * i)) + counter_offset); - shader_core_count++; - } - } - - for (i = 0; i < 4; i++) { - if((shader_present_low >> (i+4)) & 1) { - value += *((u32*)(block_base_address + (0x100 * i) + 0x800) + counter_offset); - shader_core_count++; - } - } - - /* Need to total by number of cores to produce an average */ - if (shader_core_count != 0) { - value /= shader_core_count; - } - } else { - value = *((u32*)block_base_address + counter_offset); - } - - counter_dump[len++] = counter->key; - counter_dump[len++] = value; - } - } - } - } - - if (!kbase_device_busy) { - kbase_device_busy = true; -#if MALI_DDK_GATOR_API_VERSION == 3 - kbase_dd_instr_hwcnt_dump_irq_symbol(handles); -#else - kbase_instr_hwcnt_dump_irq_symbol(kbcontext); -#endif - } - } - - /* Update the buffer */ - if (buffer) { - *buffer = (int *)counter_dump; - } - - return len; -} - -static int create_files(struct super_block *sb, struct dentry *root) -{ - unsigned int event; - /* - * Create the filesystem for all events - */ - int counter_index = 0; - - for (event = 0; event < ARRAY_SIZE(mali_activity); event++) { - if (gator_mali_create_file_system(mali_name, mali_activity_names[event], sb, root, &mali_activity[event], NULL) != 0) { - return -1; - } - } - - for (event = 0; event < NUMBER_OF_HARDWARE_COUNTERS; event++) { - if (gator_mali_create_file_system(mali_name, hardware_counter_names[counter_index], sb, root, &counters[event], NULL) != 0) - return -1; - counter_index++; - } - - return 0; -} - -static struct gator_interface gator_events_mali_t6xx_interface = { - .create_files = create_files, - .start = start, - .stop = stop, - .read = read -}; - -int gator_events_mali_t6xx_hw_init(void) -{ - pr_debug("gator: Mali-T6xx: sw_counters init\n"); - -#if GATOR_TEST - test_all_is_read_scheduled(); -#endif - - gator_mali_initialise_counters(mali_activity, ARRAY_SIZE(mali_activity)); - gator_mali_initialise_counters(counters, NUMBER_OF_HARDWARE_COUNTERS); - - return gator_events_install(&gator_events_mali_t6xx_interface); -} diff --git a/drivers/gator/gator_events_mali_t6xx_hw_test.c b/drivers/gator/gator_events_mali_t6xx_hw_test.c deleted file mode 100644 index ba6553f3540f..000000000000 --- a/drivers/gator/gator_events_mali_t6xx_hw_test.c +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (C) ARM Limited 2012-2014. 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. - * - */ - -/** - * Test functions for mali_t600_hw code. - */ - -static int is_read_scheduled(const struct timespec *current_time, u32 *prev_time_s, s32 *next_read_time_ns); - -static int test_is_read_scheduled(u32 s, u32 ns, u32 prev_s, s32 next_ns, int expected_result, s32 expected_next_ns) -{ - struct timespec current_time; - u32 prev_time_s = prev_s; - s32 next_read_time_ns = next_ns; - - current_time.tv_sec = s; - current_time.tv_nsec = ns; - - if (is_read_scheduled(¤t_time, &prev_time_s, &next_read_time_ns) != expected_result) { - printk("Failed do_read(%u, %u, %u, %d): expected %d\n", s, ns, prev_s, next_ns, expected_result); - return 0; - } - - if (next_read_time_ns != expected_next_ns) { - printk("Failed: next_read_ns expected=%d, actual=%d\n", expected_next_ns, next_read_time_ns); - return 0; - } - - return 1; -} - -static void test_all_is_read_scheduled(void) -{ - const int HIGHEST_NS = 999999999; - int n_tests_passed = 0; - - printk("gator: running tests on %s\n", __FILE__); - - n_tests_passed += test_is_read_scheduled(0, 0, 0, 0, 1, READ_INTERVAL_NSEC); /* Null time */ - n_tests_passed += test_is_read_scheduled(100, 1000, 0, 0, 1, READ_INTERVAL_NSEC + 1000); /* Initial values */ - - n_tests_passed += test_is_read_scheduled(100, HIGHEST_NS, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500); - n_tests_passed += test_is_read_scheduled(101, 0001, 100, HIGHEST_NS + 500, 0, HIGHEST_NS + 500 - NSEC_PER_SEC); - n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500 - NSEC_PER_SEC, 1, 600 + READ_INTERVAL_NSEC); - - n_tests_passed += test_is_read_scheduled(101, 600, 100, HIGHEST_NS + 500, 1, 600 + READ_INTERVAL_NSEC); - - printk("gator: %d tests passed\n", n_tests_passed); -} diff --git a/drivers/gator/gator_events_meminfo.c b/drivers/gator/gator_events_meminfo.c index c633dfdce306..c625ac5af9cd 100644 --- a/drivers/gator/gator_events_meminfo.c +++ b/drivers/gator/gator_events_meminfo.c @@ -16,6 +16,8 @@ #include #include +#define USE_THREAD defined(CONFIG_PREEMPT_RT_FULL) + enum { MEMINFO_MEMFREE, MEMINFO_MEMUSED, @@ -48,7 +50,7 @@ static bool meminfo_global_enabled; static ulong meminfo_enabled[MEMINFO_TOTAL]; static ulong meminfo_keys[MEMINFO_TOTAL]; static long long meminfo_buffer[2 * (MEMINFO_TOTAL + 2)]; -static int meminfo_length = 0; +static int meminfo_length; static bool new_data_avail; static bool proc_global_enabled; @@ -56,22 +58,44 @@ static ulong proc_enabled[PROC_COUNT]; static ulong proc_keys[PROC_COUNT]; static DEFINE_PER_CPU(long long, proc_buffer[2 * (PROC_COUNT + 3)]); +#if USE_THREAD + static int gator_meminfo_func(void *data); static bool gator_meminfo_run; -// Initialize semaphore unlocked to initialize memory values +/* Initialize semaphore unlocked to initialize memory values */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) static DECLARE_MUTEX(gator_meminfo_sem); #else static DEFINE_SEMAPHORE(gator_meminfo_sem); #endif +static void notify(void) +{ + up(&gator_meminfo_sem); +} + +#else + +static unsigned int mem_event; +static void wq_sched_handler(struct work_struct *wsptr); +DECLARE_WORK(work, wq_sched_handler); +static struct timer_list meminfo_wake_up_timer; +static void meminfo_wake_up_handler(unsigned long unused_data); + +static void notify(void) +{ + mem_event++; +} + +#endif + #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) GATOR_DEFINE_PROBE(mm_page_free_direct, TP_PROTO(struct page *page, unsigned int order)) #else GATOR_DEFINE_PROBE(mm_page_free, TP_PROTO(struct page *page, unsigned int order)) #endif { - up(&gator_meminfo_sem); + notify(); } #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) @@ -80,12 +104,12 @@ GATOR_DEFINE_PROBE(mm_pagevec_free, TP_PROTO(struct page *page, int cold)) GATOR_DEFINE_PROBE(mm_page_free_batched, TP_PROTO(struct page *page, int cold)) #endif { - up(&gator_meminfo_sem); + notify(); } GATOR_DEFINE_PROBE(mm_page_alloc, TP_PROTO(struct page *page, unsigned int order, gfp_t gfp_flags, int migratetype)) { - up(&gator_meminfo_sem); + notify(); } static int gator_events_meminfo_create_files(struct super_block *sb, struct dentry *root) @@ -95,18 +119,16 @@ static int gator_events_meminfo_create_files(struct super_block *sb, struct dent for (i = 0; i < MEMINFO_TOTAL; i++) { dir = gatorfs_mkdir(sb, root, meminfo_names[i]); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &meminfo_enabled[i]); gatorfs_create_ro_ulong(sb, dir, "key", &meminfo_keys[i]); } for (i = 0; i < PROC_COUNT; ++i) { dir = gatorfs_mkdir(sb, root, proc_names[i]); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &proc_enabled[i]); gatorfs_create_ro_ulong(sb, dir, "key", &proc_keys[i]); } @@ -134,9 +156,8 @@ static int gator_events_meminfo_start(void) break; } } - if (meminfo_enabled[MEMINFO_MEMUSED]) { + if (meminfo_enabled[MEMINFO_MEMUSED]) proc_global_enabled = 1; - } if (meminfo_global_enabled == 0) return 0; @@ -156,16 +177,22 @@ static int gator_events_meminfo_start(void) if (GATOR_REGISTER_TRACE(mm_page_alloc)) goto mm_page_alloc_exit; - // Start worker thread +#if USE_THREAD + /* Start worker thread */ gator_meminfo_run = true; - // Since the mutex starts unlocked, memory values will be initialized + /* Since the mutex starts unlocked, memory values will be initialized */ if (IS_ERR(kthread_run(gator_meminfo_func, NULL, "gator_meminfo"))) goto kthread_run_exit; +#else + setup_timer(&meminfo_wake_up_timer, meminfo_wake_up_handler, 0); +#endif return 0; +#if USE_THREAD kthread_run_exit: GATOR_UNREGISTER_TRACE(mm_page_alloc); +#endif mm_page_alloc_exit: #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) GATOR_UNREGISTER_TRACE(mm_pagevec_free); @@ -194,75 +221,111 @@ static void gator_events_meminfo_stop(void) #endif GATOR_UNREGISTER_TRACE(mm_page_alloc); - // Stop worker thread +#if USE_THREAD + /* Stop worker thread */ gator_meminfo_run = false; up(&gator_meminfo_sem); +#else + del_timer_sync(&meminfo_wake_up_timer); +#endif } } -// Must be run in process context as the kernel function si_meminfo() can sleep -static int gator_meminfo_func(void *data) +static void do_read(void) { struct sysinfo info; int i, len; unsigned long long value; - for (;;) { - if (down_killable(&gator_meminfo_sem)) { - break; + meminfo_length = len = 0; + + si_meminfo(&info); + for (i = 0; i < MEMINFO_TOTAL; i++) { + if (meminfo_enabled[i]) { + switch (i) { + case MEMINFO_MEMFREE: + value = info.freeram * PAGE_SIZE; + break; + case MEMINFO_MEMUSED: + /* pid -1 means system wide */ + meminfo_buffer[len++] = 1; + meminfo_buffer[len++] = -1; + /* Emit value */ + meminfo_buffer[len++] = meminfo_keys[MEMINFO_MEMUSED]; + meminfo_buffer[len++] = (info.totalram - info.freeram) * PAGE_SIZE; + /* Clear pid */ + meminfo_buffer[len++] = 1; + meminfo_buffer[len++] = 0; + continue; + case MEMINFO_BUFFERRAM: + value = info.bufferram * PAGE_SIZE; + break; + default: + value = 0; + break; + } + meminfo_buffer[len++] = meminfo_keys[i]; + meminfo_buffer[len++] = value; } + } - // Eat up any pending events - while (!down_trylock(&gator_meminfo_sem)); + meminfo_length = len; + new_data_avail = true; +} - if (!gator_meminfo_run) { +#if USE_THREAD + +static int gator_meminfo_func(void *data) +{ + for (;;) { + if (down_killable(&gator_meminfo_sem)) break; - } - meminfo_length = len = 0; - - si_meminfo(&info); - for (i = 0; i < MEMINFO_TOTAL; i++) { - if (meminfo_enabled[i]) { - switch (i) { - case MEMINFO_MEMFREE: - value = info.freeram * PAGE_SIZE; - break; - case MEMINFO_MEMUSED: - // pid -1 means system wide - meminfo_buffer[len++] = 1; - meminfo_buffer[len++] = -1; - // Emit value - meminfo_buffer[len++] = meminfo_keys[MEMINFO_MEMUSED]; - meminfo_buffer[len++] = (info.totalram - info.freeram) * PAGE_SIZE; - // Clear pid - meminfo_buffer[len++] = 1; - meminfo_buffer[len++] = 0; - continue; - case MEMINFO_BUFFERRAM: - value = info.bufferram * PAGE_SIZE; - break; - default: - value = 0; - break; - } - meminfo_buffer[len++] = meminfo_keys[i]; - meminfo_buffer[len++] = value; - } - } + /* Eat up any pending events */ + while (!down_trylock(&gator_meminfo_sem)) + ; + + if (!gator_meminfo_run) + break; - meminfo_length = len; - new_data_avail = true; + do_read(); } return 0; } +#else + +/* Must be run in process context as the kernel function si_meminfo() can sleep */ +static void wq_sched_handler(struct work_struct *wsptr) +{ + do_read(); +} + +static void meminfo_wake_up_handler(unsigned long unused_data) +{ + /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */ + schedule_work(&work); +} + +#endif + static int gator_events_meminfo_read(long long **buffer) { +#if !USE_THREAD + static unsigned int last_mem_event; +#endif + if (!on_primary_core() || !meminfo_global_enabled) return 0; +#if !USE_THREAD + if (last_mem_event != mem_event) { + last_mem_event = mem_event; + mod_timer(&meminfo_wake_up_timer, jiffies + 1); + } +#endif + if (!new_data_avail) return 0; @@ -280,6 +343,7 @@ static inline unsigned long gator_get_mm_counter(struct mm_struct *mm, int membe { #ifdef SPLIT_RSS_COUNTING long val = atomic_long_read(&mm->rss_stat.count[member]); + if (val < 0) val = 0; return (unsigned long)val; @@ -306,22 +370,19 @@ static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct int cpu = get_physical_cpu(); long long *buf = per_cpu(proc_buffer, cpu); - if (!proc_global_enabled) { + if (!proc_global_enabled) return 0; - } - // Collect the memory stats of the process instead of the thread - if (task->group_leader != NULL) { + /* Collect the memory stats of the process instead of the thread */ + if (task->group_leader != NULL) task = task->group_leader; - } - // get_task_mm/mmput is not needed in this context because the task and it's mm are required as part of the sched_switch + /* get_task_mm/mmput is not needed in this context because the task and it's mm are required as part of the sched_switch */ mm = task->mm; - if (mm == NULL) { + if (mm == NULL) return 0; - } - // Derived from task_statm in fs/proc/task_mmu.c + /* Derived from task_statm in fs/proc/task_mmu.c */ if (meminfo_enabled[MEMINFO_MEMUSED] || proc_enabled[PROC_SHARE]) { share = get_mm_counter(mm, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34) @@ -332,7 +393,7 @@ static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct ); } - // key of 1 indicates a pid + /* key of 1 indicates a pid */ buf[len++] = 1; buf[len++] = task->pid; @@ -366,12 +427,12 @@ static int gator_events_meminfo_read_proc(long long **buffer, struct task_struct MM_ANONPAGES #endif ); - // Send resident for this pid + /* Send resident for this pid */ buf[len++] = meminfo_keys[MEMINFO_MEMUSED]; buf[len++] = value * PAGE_SIZE; } - // Clear pid + /* Clear pid */ buf[len++] = 1; buf[len++] = 0; diff --git a/drivers/gator/gator_events_mmapped.c b/drivers/gator/gator_events_mmapped.c index 5bc01c42c3a2..6b2af995ed41 100644 --- a/drivers/gator/gator_events_mmapped.c +++ b/drivers/gator/gator_events_mmapped.c @@ -103,7 +103,7 @@ static int mmapped_simulate(int counter, int delta_in_us) switch (counter) { case 0: /* sort-of-sine */ { - static int t = 0; + static int t; int x; t += delta_in_us; @@ -140,7 +140,7 @@ static int mmapped_simulate(int counter, int delta_in_us) break; case 2: /* PWM signal */ { - static int dc, x, t = 0; + static int dc, x, t; t += delta_in_us; if (t > 1000000) @@ -157,7 +157,7 @@ static int mmapped_simulate(int counter, int delta_in_us) return result; } -static int gator_events_mmapped_read(int **buffer) +static int gator_events_mmapped_read(int **buffer, bool sched_switch) { int i; int len = 0; diff --git a/drivers/gator/gator_events_net.c b/drivers/gator/gator_events_net.c index 11c10e375511..d21b4db7b77c 100644 --- a/drivers/gator/gator_events_net.c +++ b/drivers/gator/gator_events_net.c @@ -25,7 +25,7 @@ static int netGet[TOTALNET * 4]; static struct timer_list net_wake_up_timer; -// Must be run in process context as the kernel function dev_get_stats() can sleep +/* Must be run in process context as the kernel function dev_get_stats() can sleep */ static void get_network_stats(struct work_struct *wsptr) { int rx = 0, tx = 0; @@ -49,7 +49,7 @@ DECLARE_WORK(wq_get_stats, get_network_stats); static void net_wake_up_handler(unsigned long unused_data) { - // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater + /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */ schedule_work(&wq_get_stats); } @@ -73,21 +73,19 @@ static void calculate_delta(int *rx, int *tx) static int gator_events_net_create_files(struct super_block *sb, struct dentry *root) { - // Network counters are not currently supported in RT-Preempt full because mod_timer is used + /* Network counters are not currently supported in RT-Preempt full because mod_timer is used */ #ifndef CONFIG_PREEMPT_RT_FULL struct dentry *dir; dir = gatorfs_mkdir(sb, root, "Linux_net_rx"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &netrx_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &netrx_key); dir = gatorfs_mkdir(sb, root, "Linux_net_tx"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &nettx_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &nettx_key); #endif @@ -115,10 +113,10 @@ static void gator_events_net_stop(void) nettx_enabled = 0; } -static int gator_events_net_read(int **buffer) +static int gator_events_net_read(int **buffer, bool sched_switch) { int len, rx_delta, tx_delta; - static int last_rx_delta = 0, last_tx_delta = 0; + static int last_rx_delta, last_tx_delta; if (!on_primary_core()) return 0; @@ -134,7 +132,8 @@ static int gator_events_net_read(int **buffer) if (netrx_enabled && last_rx_delta != rx_delta) { last_rx_delta = rx_delta; netGet[len++] = netrx_key; - netGet[len++] = 0; // indicates to Streamline that rx_delta bytes were transmitted now, not since the last message + /* indicates to Streamline that rx_delta bytes were transmitted now, not since the last message */ + netGet[len++] = 0; netGet[len++] = netrx_key; netGet[len++] = rx_delta; } @@ -142,7 +141,8 @@ static int gator_events_net_read(int **buffer) if (nettx_enabled && last_tx_delta != tx_delta) { last_tx_delta = tx_delta; netGet[len++] = nettx_key; - netGet[len++] = 0; // indicates to Streamline that tx_delta bytes were transmitted now, not since the last message + /* indicates to Streamline that tx_delta bytes were transmitted now, not since the last message */ + netGet[len++] = 0; netGet[len++] = nettx_key; netGet[len++] = tx_delta; } diff --git a/drivers/gator/gator_events_perf_pmu.c b/drivers/gator/gator_events_perf_pmu.c index 06bbad5b10c3..47cf278e508b 100644 --- a/drivers/gator/gator_events_perf_pmu.c +++ b/drivers/gator/gator_events_perf_pmu.c @@ -8,7 +8,7 @@ #include "gator.h" -// gator_events_armvX.c is used for Linux 2.6.x +/* gator_events_armvX.c is used for Linux 2.6.x */ #if GATOR_PERF_PMU_SUPPORT #include @@ -20,39 +20,41 @@ extern bool event_based_sampling; -// Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE +/* Maximum number of per-core counters - currently reserves enough space for two full hardware PMUs for big.LITTLE */ #define CNTMAX 16 #define CCI_400 4 -// Maximum number of uncore counters -// + 1 for the cci-400 cycles counter -#define UCCNT (CCI_400 + 1) +#define CCN_5XX 8 +/* Maximum number of uncore counters */ +/* + 1 for the cci-400 cycles counter */ +/* + 1 for the CCN-5xx cycles counter */ +#define UCCNT (CCI_400 + 1 + CCN_5XX + 1) -// Default to 0 if unable to probe the revision which was the previous behavior +/* Default to 0 if unable to probe the revision which was the previous behavior */ #define DEFAULT_CCI_REVISION 0 -// A gator_attr is needed for every counter +/* A gator_attr is needed for every counter */ struct gator_attr { - // Set once in gator_events_perf_pmu_*_init - the name of the event in the gatorfs + /* Set once in gator_events_perf_pmu_*_init - the name of the event in the gatorfs */ char name[40]; - // Exposed in gatorfs - set by gatord to enable this counter + /* Exposed in gatorfs - set by gatord to enable this counter */ unsigned long enabled; - // Set once in gator_events_perf_pmu_*_init - the perf type to use, see perf_type_id in the perf_event.h header file. + /* Set once in gator_events_perf_pmu_*_init - the perf type to use, see perf_type_id in the perf_event.h header file. */ unsigned long type; - // Exposed in gatorfs - set by gatord to select the event to collect + /* Exposed in gatorfs - set by gatord to select the event to collect */ unsigned long event; - // Exposed in gatorfs - set by gatord with the sample period to use and enable EBS for this counter + /* Exposed in gatorfs - set by gatord with the sample period to use and enable EBS for this counter */ unsigned long count; - // Exposed as read only in gatorfs - set once in __attr_init as the key to use in the APC data + /* Exposed as read only in gatorfs - set once in __attr_init as the key to use in the APC data */ unsigned long key; }; -// Per-core counter attributes +/* Per-core counter attributes */ static struct gator_attr attrs[CNTMAX]; -// Number of initialized per-core counters +/* Number of initialized per-core counters */ static int attr_count; -// Uncore counter attributes +/* Uncore counter attributes */ static struct gator_attr uc_attrs[UCCNT]; -// Number of initialized uncore counters +/* Number of initialized uncore counters */ static int uc_attr_count; struct gator_event { @@ -74,13 +76,11 @@ static int __create_files(struct super_block *sb, struct dentry *root, struct ga { struct dentry *dir; - if (attr->name[0] == '\0') { + if (attr->name[0] == '\0') return 0; - } dir = gatorfs_mkdir(sb, root, attr->name); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &attr->enabled); gatorfs_create_ulong(sb, dir, "count", &attr->count); gatorfs_create_ro_ulong(sb, dir, "key", &attr->key); @@ -94,15 +94,13 @@ static int gator_events_perf_pmu_create_files(struct super_block *sb, struct den int cnt; for (cnt = 0; cnt < attr_count; cnt++) { - if (__create_files(sb, root, &attrs[cnt]) != 0) { + if (__create_files(sb, root, &attrs[cnt]) != 0) return -1; - } } for (cnt = 0; cnt < uc_attr_count; cnt++) { - if (__create_files(sb, root, &uc_attrs[cnt]) != 0) { + if (__create_files(sb, root, &uc_attrs[cnt]) != 0) return -1; - } } return 0; @@ -123,14 +121,14 @@ static void dummy_handler(struct perf_event *event, int unused, struct perf_samp static void dummy_handler(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs) #endif { -// Required as perf_event_create_kernel_counter() requires an overflow handler, even though all we do is poll + /* Required as perf_event_create_kernel_counter() requires an overflow handler, even though all we do is poll */ } -static int gator_events_perf_pmu_read(int **buffer); +static int gator_events_perf_pmu_read(int **buffer, bool sched_switch); static int gator_events_perf_pmu_online(int **buffer, bool migrate) { - return gator_events_perf_pmu_read(buffer); + return gator_events_perf_pmu_read(buffer, false); } static void __online_dispatch(int cpu, bool migrate, struct gator_attr *const attr, struct gator_event *const event) @@ -139,15 +137,13 @@ static void __online_dispatch(int cpu, bool migrate, struct gator_attr *const at event->zero = true; - if (event->pevent != NULL || event->pevent_attr == 0 || migrate) { + if (event->pevent != NULL || event->pevent_attr == 0 || migrate) return; - } - if (attr->count > 0) { + if (attr->count > 0) handler = ebs_overflow_handler; - } else { + else handler = dummy_handler; - } #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) event->pevent = perf_event_create_kernel_counter(event->pevent_attr, cpu, 0, handler); @@ -174,14 +170,12 @@ static void gator_events_perf_pmu_online_dispatch(int cpu, bool migrate) cpu = pcpu_to_lcpu(cpu); - for (cnt = 0; cnt < attr_count; cnt++) { + for (cnt = 0; cnt < attr_count; cnt++) __online_dispatch(cpu, migrate, &attrs[cnt], &per_cpu(events, cpu)[cnt]); - } if (cpu == 0) { - for (cnt = 0; cnt < uc_attr_count; cnt++) { + for (cnt = 0; cnt < uc_attr_count; cnt++) __online_dispatch(cpu, migrate, &uc_attrs[cnt], &uc_events[cnt]); - } } } @@ -194,28 +188,24 @@ static void __offline_dispatch(int cpu, struct gator_event *const event) event->pevent = NULL; } - if (pe) { + if (pe) perf_event_release_kernel(pe); - } } static void gator_events_perf_pmu_offline_dispatch(int cpu, bool migrate) { int cnt; - if (migrate) { + if (migrate) return; - } cpu = pcpu_to_lcpu(cpu); - for (cnt = 0; cnt < attr_count; cnt++) { + for (cnt = 0; cnt < attr_count; cnt++) __offline_dispatch(cpu, &per_cpu(events, cpu)[cnt]); - } if (cpu == 0) { - for (cnt = 0; cnt < uc_attr_count; cnt++) { + for (cnt = 0; cnt < uc_attr_count; cnt++) __offline_dispatch(cpu, &uc_events[cnt]); - } } } @@ -225,7 +215,7 @@ static int __check_ebs(struct gator_attr *const attr) if (!event_based_sampling) { event_based_sampling = true; } else { - printk(KERN_WARNING "gator: Only one ebs counter is allowed\n"); + pr_warning("gator: Only one ebs counter is allowed\n"); return -1; } } @@ -238,9 +228,9 @@ static int __start(struct gator_attr *const attr, struct gator_event *const even u32 size = sizeof(struct perf_event_attr); event->pevent = NULL; - if (!attr->enabled) { // Skip disabled counters + /* Skip disabled counters */ + if (!attr->enabled) return 0; - } event->prev = 0; event->curr = 0; @@ -267,29 +257,25 @@ static int gator_events_perf_pmu_start(void) event_based_sampling = false; for (cnt = 0; cnt < attr_count; cnt++) { - if (__check_ebs(&attrs[cnt]) != 0) { + if (__check_ebs(&attrs[cnt]) != 0) return -1; - } } for (cnt = 0; cnt < uc_attr_count; cnt++) { - if (__check_ebs(&uc_attrs[cnt]) != 0) { + if (__check_ebs(&uc_attrs[cnt]) != 0) return -1; - } } for_each_present_cpu(cpu) { for (cnt = 0; cnt < attr_count; cnt++) { - if (__start(&attrs[cnt], &per_cpu(events, cpu)[cnt]) != 0) { + if (__start(&attrs[cnt], &per_cpu(events, cpu)[cnt]) != 0) return -1; - } } } for (cnt = 0; cnt < uc_attr_count; cnt++) { - if (__start(&uc_attrs[cnt], &uc_events[cnt]) != 0) { + if (__start(&uc_attrs[cnt], &uc_events[cnt]) != 0) return -1; - } } return 0; @@ -297,10 +283,8 @@ static int gator_events_perf_pmu_start(void) static void __event_stop(struct gator_event *const event) { - if (event->pevent_attr) { - kfree(event->pevent_attr); - event->pevent_attr = NULL; - } + kfree(event->pevent_attr); + event->pevent_attr = NULL; } static void __attr_stop(struct gator_attr *const attr) @@ -315,29 +299,25 @@ static void gator_events_perf_pmu_stop(void) unsigned int cnt, cpu; for_each_present_cpu(cpu) { - for (cnt = 0; cnt < attr_count; cnt++) { + for (cnt = 0; cnt < attr_count; cnt++) __event_stop(&per_cpu(events, cpu)[cnt]); - } } - for (cnt = 0; cnt < uc_attr_count; cnt++) { + for (cnt = 0; cnt < uc_attr_count; cnt++) __event_stop(&uc_events[cnt]); - } - for (cnt = 0; cnt < attr_count; cnt++) { + for (cnt = 0; cnt < attr_count; cnt++) __attr_stop(&attrs[cnt]); - } - for (cnt = 0; cnt < uc_attr_count; cnt++) { + for (cnt = 0; cnt < uc_attr_count; cnt++) __attr_stop(&uc_attrs[cnt]); - } } static void __read(int *const len, int cpu, struct gator_attr *const attr, struct gator_event *const event) { int delta; - struct perf_event *const ev = event->pevent; + if (ev != NULL && ev->state == PERF_EVENT_STATE_ACTIVE) { /* After creating the perf counter in __online_dispatch, there * is a race condition between gator_events_perf_pmu_online and @@ -361,33 +341,29 @@ static void __read(int *const len, int cpu, struct gator_attr *const attr, struc event->prev_delta = delta; event->prev = event->curr; per_cpu(perf_cnt, cpu)[(*len)++] = attr->key; - if (delta < 0) { + if (delta < 0) delta *= -1; - } per_cpu(perf_cnt, cpu)[(*len)++] = delta; } } } } -static int gator_events_perf_pmu_read(int **buffer) +static int gator_events_perf_pmu_read(int **buffer, bool sched_switch) { int cnt, len = 0; const int cpu = get_logical_cpu(); - for (cnt = 0; cnt < attr_count; cnt++) { + for (cnt = 0; cnt < attr_count; cnt++) __read(&len, cpu, &attrs[cnt], &per_cpu(events, cpu)[cnt]); - } if (cpu == 0) { - for (cnt = 0; cnt < uc_attr_count; cnt++) { + for (cnt = 0; cnt < uc_attr_count; cnt++) __read(&len, cpu, &uc_attrs[cnt], &uc_events[cnt]); - } } - if (buffer) { + if (buffer) *buffer = per_cpu(perf_cnt, cpu); - } return len; } @@ -428,23 +404,20 @@ static int probe_cci_revision(void) int ret = DEFAULT_CCI_REVISION; np = of_find_matching_node(NULL, arm_cci_matches); - if (!np) { + if (!np) return ret; - } - if (of_address_to_resource(np, 0, &res)) { + if (of_address_to_resource(np, 0, &res)) goto node_put; - } cci_ctrl_base = ioremap(res.start, resource_size(&res)); rev = (readl_relaxed(cci_ctrl_base + 0xfe8) >> 4) & 0xf; - if (rev <= 4) { + if (rev <= 4) ret = 0; - } else if (rev <= 6) { + else if (rev <= 6) ret = 1; - } iounmap(cci_ctrl_base); @@ -463,9 +436,24 @@ static int probe_cci_revision(void) #endif -static void gator_events_perf_pmu_cci_init(const int type) +static void gator_events_perf_pmu_uncore_init(const char *const name, const int type, const int count) { int cnt; + + snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", name); + uc_attrs[uc_attr_count].type = type; + ++uc_attr_count; + + for (cnt = 0; cnt < count; ++cnt, ++uc_attr_count) { + struct gator_attr *const attr = &uc_attrs[uc_attr_count]; + + snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", name, cnt); + attr->type = type; + } +} + +static void gator_events_perf_pmu_cci_init(const int type) +{ const char *cci_name; switch (probe_cci_revision()) { @@ -480,15 +468,7 @@ static void gator_events_perf_pmu_cci_init(const int type) return; } - snprintf(uc_attrs[uc_attr_count].name, sizeof(uc_attrs[uc_attr_count].name), "%s_ccnt", cci_name); - uc_attrs[uc_attr_count].type = type; - ++uc_attr_count; - - for (cnt = 0; cnt < CCI_400; ++cnt, ++uc_attr_count) { - struct gator_attr *const attr = &uc_attrs[uc_attr_count]; - snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", cci_name, cnt); - attr->type = type; - } + gator_events_perf_pmu_uncore_init(cci_name, type, CCI_400); } static void gator_events_perf_pmu_cpu_init(const struct gator_cpu *const gator_cpu, const int type) @@ -501,6 +481,7 @@ static void gator_events_perf_pmu_cpu_init(const struct gator_cpu *const gator_c for (cnt = 0; cnt < gator_cpu->pmnc_counters; ++cnt, ++attr_count) { struct gator_attr *const attr = &attrs[attr_count]; + snprintf(attr->name, sizeof(attr->name), "%s_cnt%d", gator_cpu->pmnc_name, cnt); attr->type = type; } @@ -516,12 +497,10 @@ int gator_events_perf_pmu_init(void) int cnt; bool found_cpu = false; - for (cnt = 0; cnt < CNTMAX; cnt++) { + for (cnt = 0; cnt < CNTMAX; cnt++) __attr_init(&attrs[cnt]); - } - for (cnt = 0; cnt < UCCNT; cnt++) { + for (cnt = 0; cnt < UCCNT; cnt++) __attr_init(&uc_attrs[cnt]); - } memset(&pea, 0, sizeof(pea)); pea.size = sizeof(pea); @@ -531,7 +510,7 @@ int gator_events_perf_pmu_init(void) for (type = PERF_TYPE_MAX; type < 0x20; ++type) { pea.type = type; - // A particular PMU may work on some but not all cores, so try on each core + /* A particular PMU may work on some but not all cores, so try on each core */ pe = NULL; for_each_present_cpu(cpu) { #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) @@ -539,23 +518,31 @@ int gator_events_perf_pmu_init(void) #else pe = perf_event_create_kernel_counter(&pea, cpu, 0, dummy_handler, 0); #endif - if (!IS_ERR(pe)) { + if (!IS_ERR(pe)) break; - } } - // Assume that valid PMUs are contiguous + /* Assume that valid PMUs are contiguous */ if (IS_ERR(pe)) { - break; + pea.config = 0xff00; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) + pe = perf_event_create_kernel_counter(&pea, 0, 0, dummy_handler); +#else + pe = perf_event_create_kernel_counter(&pea, 0, 0, dummy_handler, 0); +#endif + if (IS_ERR(pe)) + break; } if (pe->pmu != NULL && type == pe->pmu->type) { if (strcmp("CCI", pe->pmu->name) == 0 || strcmp("CCI_400", pe->pmu->name) == 0 || strcmp("CCI_400-r1", pe->pmu->name) == 0) { gator_events_perf_pmu_cci_init(type); + } else if (strcmp("ccn", pe->pmu->name) == 0) { + gator_events_perf_pmu_uncore_init("ARM_CCN_5XX", type, CCN_5XX); } else if ((gator_cpu = gator_find_cpu_by_pmu_name(pe->pmu->name)) != NULL) { found_cpu = true; gator_events_perf_pmu_cpu_init(gator_cpu, type); } - // Initialize gator_attrs for dynamic PMUs here + /* Initialize gator_attrs for dynamic PMUs here */ } perf_event_release_kernel(pe); @@ -563,21 +550,21 @@ int gator_events_perf_pmu_init(void) if (!found_cpu) { const struct gator_cpu *const gator_cpu = gator_find_cpu_by_cpuid(gator_cpuid()); - if (gator_cpu == NULL) { + + if (gator_cpu == NULL) return -1; - } gator_events_perf_pmu_cpu_init(gator_cpu, PERF_TYPE_RAW); } - // Initialize gator_attrs for non-dynamic PMUs here + /* Initialize gator_attrs for non-dynamic PMUs here */ if (attr_count > CNTMAX) { - printk(KERN_ERR "gator: Too many perf counters\n"); + pr_err("gator: Too many perf counters\n"); return -1; } if (uc_attr_count > UCCNT) { - printk(KERN_ERR "gator: Too many perf uncore counters\n"); + pr_err("gator: Too many perf uncore counters\n"); return -1; } diff --git a/drivers/gator/gator_events_sched.c b/drivers/gator/gator_events_sched.c index 9e3915830182..637107d6af1d 100644 --- a/drivers/gator/gator_events_sched.c +++ b/drivers/gator/gator_events_sched.c @@ -26,8 +26,9 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_ { unsigned long flags; - // disable interrupts to synchronize with gator_events_sched_read() - // spinlocks not needed since percpu buffers are used + /* disable interrupts to synchronize with gator_events_sched_read() + * spinlocks not needed since percpu buffers are used + */ local_irq_save(flags); per_cpu(schedCnt, get_physical_cpu())[SCHED_SWITCH]++; local_irq_restore(flags); @@ -39,9 +40,8 @@ static int gator_events_sched_create_files(struct super_block *sb, struct dentry /* switch */ dir = gatorfs_mkdir(sb, root, "Linux_sched_switch"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &sched_switch_enabled); gatorfs_create_ro_ulong(sb, dir, "key", &sched_switch_key); @@ -50,7 +50,7 @@ static int gator_events_sched_create_files(struct super_block *sb, struct dentry static int gator_events_sched_start(void) { - // register tracepoints + /* register tracepoints */ if (sched_switch_enabled) if (GATOR_REGISTER_TRACE(sched_switch)) goto sched_switch_exit; @@ -58,7 +58,7 @@ static int gator_events_sched_start(void) return 0; - // unregister tracepoints on error + /* unregister tracepoints on error */ sched_switch_exit: pr_err("gator: scheduler event tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n"); @@ -74,7 +74,7 @@ static void gator_events_sched_stop(void) sched_switch_enabled = 0; } -static int gator_events_sched_read(int **buffer) +static int gator_events_sched_read(int **buffer, bool sched_switch) { unsigned long flags; int len, value; diff --git a/drivers/gator/gator_events_scorpion.c b/drivers/gator/gator_events_scorpion.c index 2e5be8d50e9d..49219362db09 100644 --- a/drivers/gator/gator_events_scorpion.c +++ b/drivers/gator/gator_events_scorpion.c @@ -8,13 +8,13 @@ #include "gator.h" -// gator_events_perf_pmu.c is used if perf is supported +/* gator_events_perf_pmu.c is used if perf is supported */ #if GATOR_NO_PERF_SUPPORT static const char *pmnc_name; static int pmnc_counters; -// 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 */ @@ -23,7 +23,7 @@ static int pmnc_counters; #define PMNC_DP (1 << 5) /* Disable CCNT if non-invasive debug */ #define PMNC_MASK 0x3f /* Mask for writable bits */ -// ccnt reg +/* ccnt reg */ #define CCNT_REG (1 << 31) #define CCNT 0 @@ -243,6 +243,7 @@ static inline void scorpion_pmnc_write(u32 val) static inline u32 scorpion_pmnc_read(void) { u32 val; + asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); return val; } @@ -250,6 +251,7 @@ static inline u32 scorpion_pmnc_read(void) static inline u32 scorpion_ccnt_read(void) { u32 val; + asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); return val; } @@ -257,6 +259,7 @@ static inline u32 scorpion_ccnt_read(void) static inline u32 scorpion_cntn_read(void) { u32 val; + asm volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); return val; } @@ -317,6 +320,7 @@ static inline int scorpion_pmnc_select_counter(unsigned int cnt) static u32 scorpion_read_lpm0(void) { u32 val; + asm volatile("mrc p15, 0, %0, c15, c0, 0" : "=r" (val)); return val; } @@ -329,6 +333,7 @@ static void scorpion_write_lpm0(u32 val) static u32 scorpion_read_lpm1(void) { u32 val; + asm volatile("mrc p15, 1, %0, c15, c0, 0" : "=r" (val)); return val; } @@ -341,6 +346,7 @@ static void scorpion_write_lpm1(u32 val) static u32 scorpion_read_lpm2(void) { u32 val; + asm volatile("mrc p15, 2, %0, c15, c0, 0" : "=r" (val)); return val; } @@ -353,6 +359,7 @@ static void scorpion_write_lpm2(u32 val) static u32 scorpion_read_l2lpm(void) { u32 val; + asm volatile("mrc p15, 3, %0, c15, c2, 0" : "=r" (val)); return val; } @@ -365,6 +372,7 @@ static void scorpion_write_l2lpm(u32 val) static u32 scorpion_read_vlpm(void) { u32 val; + asm volatile("mrc p10, 7, %0, c11, c0, 0" : "=r" (val)); return val; } @@ -375,7 +383,7 @@ static void scorpion_write_vlpm(u32 val) } struct scorpion_access_funcs { - u32(*read)(void); + u32 (*read)(void); void (*write)(u32); }; @@ -420,17 +428,17 @@ static u32 scorpion_get_columnmask(u32 setval) { if (setval & COLMN0MASK) return 0xffffff00; - else if (setval & COLMN1MASK) + if (setval & COLMN1MASK) return 0xffff00ff; - else if (setval & COLMN2MASK) + if (setval & COLMN2MASK) return 0xff00ffff; - else - return 0x80ffffff; + 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(); @@ -443,6 +451,7 @@ static void scorpion_evt_setup(u32 gr, u32 setval) 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; @@ -463,7 +472,7 @@ static inline void scorpion_pmnc_write_evtsel(unsigned int cnt, u32 val) } else { u32 zero = 0; struct scorp_evt evtinfo; - // extract evtinfo.grp and evtinfo.tevt_type_act from val + /* 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)); @@ -505,20 +514,18 @@ static int gator_events_scorpion_create_files(struct super_block *sb, struct den for (i = 0; i < pmnc_counters; 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); - } + + 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) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &pmnc_enabled[i]); gatorfs_create_ro_ulong(sb, dir, "key", &pmnc_key[i]); - if (i > 0) { + if (i > 0) gatorfs_create_ulong(sb, dir, "event", &pmnc_event[i]); - } } return 0; @@ -528,9 +535,8 @@ static int gator_events_scorpion_online(int **buffer, bool migrate) { unsigned int cnt, len = 0, cpu = smp_processor_id(); - if (scorpion_pmnc_read() & PMNC_E) { + 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); @@ -541,33 +547,32 @@ static int gator_events_scorpion_online(int **buffer, bool migrate) if (!pmnc_enabled[cnt]) continue; - // disable counter + /* 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 + /* 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 + /* reset counter */ scorpion_pmnc_reset_counter(cnt); - // Enable counter, do not enable interrupt for this counter + /* Enable counter, do not enable interrupt for this counter */ scorpion_pmnc_enable_counter(cnt); } - // enable + /* enable */ scorpion_pmnc_write(scorpion_pmnc_read() | PMNC_E); - // read the counters and toss the invalid data, return zero instead + /* read the counters and toss the invalid data, return zero instead */ for (cnt = 0; cnt < pmnc_counters; cnt++) { if (pmnc_enabled[cnt]) { - if (cnt == CCNT) { + if (cnt == CCNT) scorpion_ccnt_read(); - } else if (scorpion_pmnc_select_counter(cnt) == cnt) { + else if (scorpion_pmnc_select_counter(cnt) == cnt) scorpion_cntn_read(); - } scorpion_pmnc_reset_counter(cnt); per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; @@ -597,26 +602,25 @@ static void gator_events_scorpion_stop(void) } } -static int gator_events_scorpion_read(int **buffer) +static int gator_events_scorpion_read(int **buffer, bool sched_switch) { int cnt, len = 0; int cpu = smp_processor_id(); - // a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled - if (!(scorpion_pmnc_read() & PMNC_E)) { + /* a context switch may occur before the online hotplug event, thus need to check that the pmu is enabled */ + if (!(scorpion_pmnc_read() & PMNC_E)) return 0; - } for (cnt = 0; cnt < pmnc_counters; cnt++) { if (pmnc_enabled[cnt]) { int value; - if (cnt == CCNT) { + + if (cnt == CCNT) value = scorpion_ccnt_read(); - } else if (scorpion_pmnc_select_counter(cnt) == cnt) { + else if (scorpion_pmnc_select_counter(cnt) == cnt) value = scorpion_cntn_read(); - } else { + else value = 0; - } scorpion_pmnc_reset_counter(cnt); per_cpu(perfCnt, cpu)[len++] = pmnc_key[cnt]; @@ -655,7 +659,8 @@ int gator_events_scorpion_init(void) return -1; } - pmnc_counters++; // CNT[n] + CCNT + /* CNT[n] + CCNT */ + pmnc_counters++; for (cnt = CCNT; cnt < CNTMAX; cnt++) { pmnc_enabled[cnt] = 0; diff --git a/drivers/gator/gator_events_threads.c b/drivers/gator/gator_events_threads.c deleted file mode 100644 index 9de85862fe6c..000000000000 --- a/drivers/gator/gator_events_threads.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Sample activity provider - * - * Copyright (C) ARM Limited 2014. 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. - * - * See gator_events_mmapped.c for additional directions and - * troubleshooting. - * - * For this sample to work these entries must be present in the - * events.xml file. So create an events-threads.xml in the gator - * daemon source directory with the following contents and rebuild - * gatord: - * - * - * - * - */ - -#include - -#include "gator.h" - -static ulong threads_enabled; -static ulong threads_key; -static ulong threads_cores; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) -GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct rq *rq, struct task_struct *prev, struct task_struct *next)) -#else -GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_struct *next)) -#endif -{ - int cpu = get_physical_cpu(); - int pid = next->pid; - if (pid == 0) { - // idle - gator_marshal_activity_switch(cpu, threads_key, 0, 0); - } else if (pid & 1) { - // odd - gator_marshal_activity_switch(cpu, threads_key, 1, pid); - } else { - // even - //gator_marshal_activity_switch(cpu, threads_key, 2, current->pid); - // Multiple activities are not yet supported so emit idle - gator_marshal_activity_switch(cpu, threads_key, 0, 0); - } -} - -// Adds Linux_threads directory and enabled, key, and cores files to /dev/gator/events -static int gator_events_threads_create_files(struct super_block *sb, struct dentry *root) -{ - struct dentry *dir; - - dir = gatorfs_mkdir(sb, root, "Linux_threads"); - if (!dir) { - return -1; - } - gatorfs_create_ulong(sb, dir, "enabled", &threads_enabled); - gatorfs_create_ro_ulong(sb, dir, "key", &threads_key); - // Number of cores associated with this activity - gatorfs_create_ro_ulong(sb, dir, "cores", &threads_cores); - - return 0; -} - -static int gator_events_threads_start(void) -{ - int cpu; - - if (threads_enabled) { - preempt_disable(); - for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { - gator_marshal_activity_switch(cpu, threads_key, 0, 0); - } - preempt_enable(); - - if (GATOR_REGISTER_TRACE(sched_switch)) { - goto fail_sched_switch; - } - } - - return 0; - -fail_sched_switch: - return -1; -} - -static void gator_events_threads_stop(void) -{ - if (threads_enabled) { - GATOR_UNREGISTER_TRACE(sched_switch); - } - - threads_enabled = 0; -} - -static struct gator_interface gator_events_threads_interface = { - .create_files = gator_events_threads_create_files, - .start = gator_events_threads_start, - .stop = gator_events_threads_stop, -}; - -// Must not be static. Ensure that this init function is added to GATOR_EVENTS_LIST in gator_main.c -int __init gator_events_threads_init(void) -{ - threads_enabled = 0; - threads_key = gator_events_get_key(); - threads_cores = nr_cpu_ids; - - return gator_events_install(&gator_events_threads_interface); -} diff --git a/drivers/gator/gator_fs.c b/drivers/gator/gator_fs.c index 166cfe7d681d..d8fb357b9eda 100644 --- a/drivers/gator/gator_fs.c +++ b/drivers/gator/gator_fs.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #define gatorfs_MAGIC 0x24051020 #define TMPBUFSIZE 50 @@ -43,6 +43,7 @@ static ssize_t gatorfs_ulong_to_user(unsigned long val, char __user *buf, size_t { char tmpbuf[TMPBUFSIZE]; size_t maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%lu\n", val); + if (maxlen > TMPBUFSIZE) maxlen = TMPBUFSIZE; return simple_read_from_buffer(buf, count, offset, tmpbuf, maxlen); @@ -52,6 +53,7 @@ static ssize_t gatorfs_u64_to_user(u64 val, char __user *buf, size_t count, loff { char tmpbuf[TMPBUFSIZE]; size_t maxlen = snprintf(tmpbuf, TMPBUFSIZE, "%llu\n", val); + if (maxlen > TMPBUFSIZE) maxlen = TMPBUFSIZE; return simple_read_from_buffer(buf, count, offset, tmpbuf, maxlen); @@ -104,12 +106,14 @@ static int gatorfs_u64_from_user(u64 *val, char const __user *buf, size_t count) static ssize_t ulong_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset) { unsigned long *val = file->private_data; + return gatorfs_ulong_to_user(*val, buf, count, offset); } static ssize_t u64_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset) { u64 *val = file->private_data; + return gatorfs_u64_to_user(*val, buf, count, offset); } @@ -231,7 +235,7 @@ int gatorfs_create_ro_ulong(struct super_block *sb, struct dentry *root, } static int gatorfs_create_ro_u64(struct super_block *sb, struct dentry *root, - char const *name, u64 * val) + char const *name, u64 *val) { struct dentry *d = __gatorfs_create_file(sb, root, name, &u64_ro_fops, 0444); @@ -245,6 +249,7 @@ static int gatorfs_create_ro_u64(struct super_block *sb, struct dentry *root, static ssize_t atomic_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset) { atomic_t *val = file->private_data; + return gatorfs_ulong_to_user(atomic_read(val), buf, count, offset); } diff --git a/drivers/gator/gator_hrtimer_gator.c b/drivers/gator/gator_hrtimer_gator.c index 76584554b00f..c1525e10a8da 100644 --- a/drivers/gator/gator_hrtimer_gator.c +++ b/drivers/gator/gator_hrtimer_gator.c @@ -18,6 +18,7 @@ static void gator_hrtimer_offline(void); static enum hrtimer_restart gator_hrtimer_notify(struct hrtimer *hrtimer) { int cpu = get_logical_cpu(); + hrtimer_forward(hrtimer, per_cpu(hrtimer_expire, cpu), profiling_interval); per_cpu(hrtimer_expire, cpu) = ktime_add(per_cpu(hrtimer_expire, cpu), profiling_interval); (*callback)(); @@ -64,12 +65,11 @@ static int gator_hrtimer_init(int interval, void (*func)(void)) per_cpu(hrtimer_is_active, cpu) = 0; } - // calculate profiling interval - if (interval > 0) { + /* calculate profiling interval */ + if (interval > 0) profiling_interval = ns_to_ktime(1000000000UL / interval); - } else { + else profiling_interval.tv64 = 0; - } return 0; } diff --git a/drivers/gator/gator_iks.c b/drivers/gator/gator_iks.c index 9180b874457a..fb78c10fd987 100644 --- a/drivers/gator/gator_iks.c +++ b/drivers/gator/gator_iks.c @@ -16,7 +16,7 @@ static bool map_cpuids; static int mpidr_cpuids[NR_CPUS]; -static const struct gator_cpu * mpidr_cpus[NR_CPUS]; +static const struct gator_cpu *mpidr_cpus[NR_CPUS]; static int __lcpu_to_pcpu[NR_CPUS]; static const struct gator_cpu *gator_find_cpu_by_dt_name(const char *const name) @@ -25,9 +25,9 @@ static const struct gator_cpu *gator_find_cpu_by_dt_name(const char *const name) for (i = 0; gator_cpus[i].cpuid != 0; ++i) { const struct gator_cpu *const gator_cpu = &gator_cpus[i]; - if (gator_cpu->dt_name != NULL && strcmp(gator_cpu->dt_name, name) == 0) { + + if (gator_cpu->dt_name != NULL && strcmp(gator_cpu->dt_name, name) == 0) return gator_cpu; - } } return NULL; @@ -41,7 +41,7 @@ static void calc_first_cluster_size(void) struct device_node *cn = NULL; int mpidr_cpuids_count = 0; - // Zero is a valid cpuid, so initialize the array to 0xff's + /* Zero is a valid cpuid, so initialize the array to 0xff's */ memset(&mpidr_cpuids, 0xff, sizeof(mpidr_cpuids)); memset(&mpidr_cpus, 0, sizeof(mpidr_cpus)); @@ -70,10 +70,10 @@ static void calc_first_cluster_size(void) static int linearize_mpidr(int mpidr) { int i; + for (i = 0; i < nr_cpu_ids; ++i) { - if (mpidr_cpuids[i] == mpidr) { + if (mpidr_cpuids[i] == mpidr) return i; - } } BUG(); @@ -113,6 +113,7 @@ static void gator_update_cpu_mapping(u32 cpu_hwid) { int lcpu = smp_processor_id(); int pcpu = linearize_mpidr(cpu_hwid & MPIDR_HWID_BITMASK); + BUG_ON(lcpu >= nr_cpu_ids || lcpu < 0); BUG_ON(pcpu >= nr_cpu_ids || pcpu < 0); __lcpu_to_pcpu[lcpu] = pcpu; @@ -132,7 +133,7 @@ GATOR_DEFINE_PROBE(cpu_migrate_finish, TP_PROTO(u64 timestamp, u32 cpu_hwid)) gator_update_cpu_mapping(cpu_hwid); - // get_physical_cpu must be called after gator_update_cpu_mapping + /* get_physical_cpu must be called after gator_update_cpu_mapping */ cpu = get_physical_cpu(); gator_timer_online_dispatch(cpu, true); gator_timer_online((void *)1); @@ -146,12 +147,11 @@ GATOR_DEFINE_PROBE(cpu_migrate_current, TP_PROTO(u64 timestamp, u32 cpu_hwid)) static void gator_send_iks_core_names(void) { int cpu; - // Send the cpu names + /* Send the cpu names */ preempt_disable(); for (cpu = 0; cpu < nr_cpu_ids; ++cpu) { - if (mpidr_cpus[cpu] != NULL) { + if (mpidr_cpus[cpu] != NULL) gator_send_core_name(cpu, mpidr_cpus[cpu]->cpuid); - } } preempt_enable(); } @@ -170,7 +170,7 @@ static int gator_migrate_start(void) if (retval == 0) retval = GATOR_REGISTER_TRACE(cpu_migrate_current); if (retval == 0) { - // Initialize the logical to physical cpu mapping + /* Initialize the logical to physical cpu mapping */ memset(&__lcpu_to_pcpu, 0xff, sizeof(__lcpu_to_pcpu)); bL_switcher_trace_trigger(); } diff --git a/drivers/gator/gator_main.c b/drivers/gator/gator_main.c index 0d867f22364f..30bf60d95286 100644 --- a/drivers/gator/gator_main.c +++ b/drivers/gator/gator_main.c @@ -7,8 +7,8 @@ * */ -// This version must match the gator daemon version -#define PROTOCOL_VERSION 19 +/* This version must match the gator daemon version */ +#define PROTOCOL_VERSION 20 static unsigned long gator_protocol_version = PROTOCOL_VERSION; #include @@ -25,7 +25,7 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; #include #include #include -#include +#include #include "gator.h" @@ -67,11 +67,11 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; #define SUMMARY_BUFFER_SIZE (1*1024) #define BACKTRACE_BUFFER_SIZE (128*1024) #define NAME_BUFFER_SIZE (64*1024) -#define COUNTER_BUFFER_SIZE (64*1024) // counters have the core as part of the data and the core value in the frame header may be discarded +#define COUNTER_BUFFER_SIZE (64*1024) /* counters have the core as part of the data and the core value in the frame header may be discarded */ #define BLOCK_COUNTER_BUFFER_SIZE (128*1024) -#define ANNOTATE_BUFFER_SIZE (128*1024) // annotate counters have the core as part of the data and the core value in the frame header may be discarded +#define ANNOTATE_BUFFER_SIZE (128*1024) /* annotate counters have the core as part of the data and the core value in the frame header may be discarded */ #define SCHED_TRACE_BUFFER_SIZE (128*1024) -#define IDLE_BUFFER_SIZE (32*1024) // idle counters have the core as part of the data and the core value in the frame header may be discarded +#define IDLE_BUFFER_SIZE (32*1024) /* idle counters have the core as part of the data and the core value in the frame header may be discarded */ #define ACTIVITY_BUFFER_SIZE (128*1024) #define NO_COOKIE 0U @@ -89,24 +89,24 @@ static unsigned long gator_protocol_version = PROTOCOL_VERSION; #define MESSAGE_END_BACKTRACE 1 -// Name Frame Messages +/* Name Frame Messages */ #define MESSAGE_COOKIE 1 #define MESSAGE_THREAD_NAME 2 #define MESSAGE_LINK 4 -// Scheduler Trace Frame Messages +/* Scheduler Trace Frame Messages */ #define MESSAGE_SCHED_SWITCH 1 #define MESSAGE_SCHED_EXIT 2 -// Idle Frame Messages +/* Idle Frame Messages */ #define MESSAGE_IDLE_ENTER 1 #define MESSAGE_IDLE_EXIT 2 -// Summary Frame Messages +/* Summary Frame Messages */ #define MESSAGE_SUMMARY 1 #define MESSAGE_CORE_NAME 3 -// Activity Frame Messages +/* Activity Frame Messages */ #define MESSAGE_SWITCH 2 #define MESSAGE_EXIT 3 @@ -140,14 +140,15 @@ enum { * Globals ******************************************************************************/ static unsigned long gator_cpu_cores; -// Size of the largest buffer. Effectively constant, set in gator_op_create_files +/* Size of the largest buffer. Effectively constant, set in gator_op_create_files */ static unsigned long userspace_buffer_size; static unsigned long gator_backtrace_depth; -// How often to commit the buffers for live in nanoseconds +/* How often to commit the buffers for live in nanoseconds */ static u64 gator_live_rate; static unsigned long gator_started; static u64 gator_monotonic_started; +static u64 gator_sync_time; static u64 gator_hibernate_time; static unsigned long gator_buffer_opened; static unsigned long gator_timer_count; @@ -161,7 +162,7 @@ static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait); static DECLARE_WAIT_QUEUE_HEAD(gator_annotate_wait); static struct timer_list gator_buffer_wake_up_timer; static bool gator_buffer_wake_run; -// Initialize semaphore unlocked to initialize memory values +/* Initialize semaphore unlocked to initialize memory values */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) static DECLARE_MUTEX(gator_buffer_wake_sem); #else @@ -183,33 +184,43 @@ static DEFINE_PER_CPU(bool, in_scheduler_context); * Prototypes ******************************************************************************/ static u64 gator_get_time(void); +static void gator_emit_perf_time(u64 time); static void gator_op_create_files(struct super_block *sb, struct dentry *root); -// gator_buffer is protected by being per_cpu and by having IRQs disabled when writing to it. -// Most marshal_* calls take care of this except for marshal_cookie*, marshal_backtrace* and marshal_frame where the caller is responsible for doing so. -// No synchronization is needed with the backtrace buffer as it is per cpu and is only used from the hrtimer. -// The annotate_lock must be held when using the annotation buffer as it is not per cpu. -// collect_counters which is the sole writer to the block counter frame is additionally protected by the per cpu collecting flag +/* gator_buffer is protected by being per_cpu and by having IRQs + * disabled when writing to it. Most marshal_* calls take care of this + * except for marshal_cookie*, marshal_backtrace* and marshal_frame + * where the caller is responsible for doing so. No synchronization is + * needed with the backtrace buffer as it is per cpu and is only used + * from the hrtimer. The annotate_lock must be held when using the + * annotation buffer as it is not per cpu. collect_counters which is + * the sole writer to the block counter frame is additionally + * protected by the per cpu collecting flag. + */ -// Size of the buffer, must be a power of 2. Effectively constant, set in gator_op_setup. +/* Size of the buffer, must be a power of 2. Effectively constant, set in gator_op_setup. */ static uint32_t gator_buffer_size[NUM_GATOR_BUFS]; -// gator_buffer_size - 1, bitwise and with pos to get offset into the array. Effectively constant, set in gator_op_setup. +/* gator_buffer_size - 1, bitwise and with pos to get offset into the array. Effectively constant, set in gator_op_setup. */ static uint32_t gator_buffer_mask[NUM_GATOR_BUFS]; -// Read position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are read by userspace in userspace_buffer_read +/* Read position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are read by userspace in userspace_buffer_read */ static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_read); -// Write position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are written to the buffer +/* Write position in the buffer. Initialized to zero in gator_op_setup and incremented after bytes are written to the buffer */ static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_write); -// Commit position in the buffer. Initialized to zero in gator_op_setup and incremented after a frame is ready to be read by userspace +/* Commit position in the buffer. Initialized to zero in gator_op_setup and incremented after a frame is ready to be read by userspace */ static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], gator_buffer_commit); -// If set to false, decreases the number of bytes returned by buffer_bytes_available. Set in buffer_check_space if no space is remaining. Initialized to true in gator_op_setup -// This means that if we run out of space, continue to report that no space is available until bytes are read by userspace +/* If set to false, decreases the number of bytes returned by + * buffer_bytes_available. Set in buffer_check_space if no space is + * remaining. Initialized to true in gator_op_setup. This means that + * if we run out of space, continue to report that no space is + * available until bytes are read by userspace + */ static DEFINE_PER_CPU(int[NUM_GATOR_BUFS], buffer_space_available); -// The buffer. Allocated in gator_op_setup +/* The buffer. Allocated in gator_op_setup */ static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer); -// The time after which the buffer should be committed for live display +/* The time after which the buffer should be committed for live display */ static DEFINE_PER_CPU(u64, gator_buffer_commit_time); -// List of all gator events - new events must be added to this list +/* List of all gator events - new events must be added to this list */ #define GATOR_EVENTS_LIST \ GATOR_EVENT(gator_events_armv6_init) \ GATOR_EVENT(gator_events_armv7_init) \ @@ -218,15 +229,14 @@ static DEFINE_PER_CPU(u64, gator_buffer_commit_time); GATOR_EVENT(gator_events_irq_init) \ GATOR_EVENT(gator_events_l2c310_init) \ GATOR_EVENT(gator_events_mali_init) \ - GATOR_EVENT(gator_events_mali_t6xx_hw_init) \ - GATOR_EVENT(gator_events_mali_t6xx_init) \ + GATOR_EVENT(gator_events_mali_midgard_hw_init) \ + GATOR_EVENT(gator_events_mali_midgard_init) \ GATOR_EVENT(gator_events_meminfo_init) \ GATOR_EVENT(gator_events_mmapped_init) \ GATOR_EVENT(gator_events_net_init) \ GATOR_EVENT(gator_events_perf_pmu_init) \ GATOR_EVENT(gator_events_sched_init) \ GATOR_EVENT(gator_events_scorpion_init) \ - GATOR_EVENT(gator_events_threads_init) \ #define GATOR_EVENT(EVENT_INIT) __weak int EVENT_INIT(void); GATOR_EVENTS_LIST @@ -314,13 +324,6 @@ static const struct gator_cpu gator_cpus[] = { .dt_name = "arm,cortex-a9", .pmnc_counters = 6, }, - { - .cpuid = CORTEX_A12, - .core_name = "Cortex-A12", - .pmnc_name = "ARMv7_Cortex_A12", - .dt_name = "arm,cortex-a12", - .pmnc_counters = 6, - }, { .cpuid = CORTEX_A15, .core_name = "Cortex-A15", @@ -400,23 +403,32 @@ const struct gator_cpu *gator_find_cpu_by_cpuid(const u32 cpuid) for (i = 0; gator_cpus[i].cpuid != 0; ++i) { const struct gator_cpu *const gator_cpu = &gator_cpus[i]; - if (gator_cpu->cpuid == cpuid) { + + if (gator_cpu->cpuid == cpuid) return gator_cpu; - } } return NULL; } +static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-"; +static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_"; + const struct gator_cpu *gator_find_cpu_by_pmu_name(const char *const name) { int i; for (i = 0; gator_cpus[i].cpuid != 0; ++i) { const struct gator_cpu *const gator_cpu = &gator_cpus[i]; - if (gator_cpu->pmnc_name != NULL && strcmp(gator_cpu->pmnc_name, name) == 0) { + + if (gator_cpu->pmnc_name != NULL && + /* Do the names match exactly? */ + (strcasecmp(gator_cpu->pmnc_name, name) == 0 || + /* Do these names match but have the old vs new prefix? */ + ((strncasecmp(name, OLD_PMU_PREFIX, sizeof(OLD_PMU_PREFIX) - 1) == 0 && + strncasecmp(gator_cpu->pmnc_name, NEW_PMU_PREFIX, sizeof(NEW_PMU_PREFIX) - 1) == 0 && + strcasecmp(name + sizeof(OLD_PMU_PREFIX) - 1, gator_cpu->pmnc_name + sizeof(NEW_PMU_PREFIX) - 1) == 0)))) return gator_cpu; - } } return NULL; @@ -445,16 +457,15 @@ static void gator_buffer_wake_up(unsigned long data) static int gator_buffer_wake_func(void *data) { for (;;) { - if (down_killable(&gator_buffer_wake_sem)) { + if (down_killable(&gator_buffer_wake_sem)) break; - } - // Eat up any pending events - while (!down_trylock(&gator_buffer_wake_sem)); + /* Eat up any pending events */ + while (!down_trylock(&gator_buffer_wake_sem)) + ; - if (!gator_buffer_wake_run) { + if (!gator_buffer_wake_run) break; - } gator_buffer_wake_up(0); } @@ -468,6 +479,7 @@ static int gator_buffer_wake_func(void *data) static bool buffer_commit_ready(int *cpu, int *buftype) { int cpu_x, x; + for_each_present_cpu(cpu_x) { for (x = 0; x < NUM_GATOR_BUFS; x++) if (per_cpu(gator_buffer_commit, cpu_x)[x] != per_cpu(gator_buffer_read, cpu_x)[x]) { @@ -487,6 +499,7 @@ static bool buffer_commit_ready(int *cpu, int *buftype) static void gator_timer_interrupt(void) { struct pt_regs *const regs = get_irq_regs(); + gator_backtrace_handler(regs); } @@ -495,15 +508,14 @@ void gator_backtrace_handler(struct pt_regs *const regs) u64 time = gator_get_time(); int cpu = get_physical_cpu(); - // Output backtrace + /* Output backtrace */ gator_add_sample(cpu, regs, time); - // Collect counters - if (!per_cpu(collecting, cpu)) { - collect_counters(time, NULL); - } + /* Collect counters */ + if (!per_cpu(collecting, cpu)) + collect_counters(time, current, false); - // No buffer flushing occurs during sched switch for RT-Preempt full. The block counter frame will be flushed by collect_counters, but the sched buffer needs to be explicitly flushed + /* No buffer flushing occurs during sched switch for RT-Preempt full. The block counter frame will be flushed by collect_counters, but the sched buffer needs to be explicitly flushed */ #ifdef CONFIG_PREEMPT_RT_FULL buffer_check(cpu, SCHED_TRACE_BUF, time); #endif @@ -511,7 +523,7 @@ void gator_backtrace_handler(struct pt_regs *const regs) static int gator_running; -// This function runs in interrupt context and on the appropriate core +/* This function runs in interrupt context and on the appropriate core */ static void gator_timer_offline(void *migrate) { struct gator_interface *gi; @@ -522,11 +534,10 @@ static void gator_timer_offline(void *migrate) gator_trace_sched_offline(); gator_trace_power_offline(); - if (!migrate) { + if (!migrate) gator_hrtimer_offline(); - } - // Offline any events and output counters + /* Offline any events and output counters */ time = gator_get_time(); if (marshal_event_header(time)) { list_for_each_entry(gi, &gator_events, list) { @@ -535,24 +546,23 @@ static void gator_timer_offline(void *migrate) marshal_event(len, buffer); } } - // Only check after writing all counters so that time and corresponding counters appear in the same frame + /* Only check after writing all counters so that time and corresponding counters appear in the same frame */ buffer_check(cpu, BLOCK_COUNTER_BUF, time); } - // Flush all buffers on this core + /* Flush all buffers on this core */ for (i = 0; i < NUM_GATOR_BUFS; i++) gator_commit_buffer(cpu, i, time); } -// This function runs in interrupt context and may be running on a core other than core 'cpu' +/* This function runs in interrupt context and may be running on a core other than core 'cpu' */ static void gator_timer_offline_dispatch(int cpu, bool migrate) { struct gator_interface *gi; list_for_each_entry(gi, &gator_events, list) { - if (gi->offline_dispatch) { + if (gi->offline_dispatch) gi->offline_dispatch(cpu, migrate); - } } } @@ -579,16 +589,15 @@ static void gator_send_core_name(const int cpu, const u32 cpuid) const char *core_name = NULL; char core_name_buf[32]; - // Save off this cpuid + /* Save off this cpuid */ gator_cpuids[cpu] = cpuid; if (gator_cpu != NULL) { core_name = gator_cpu->core_name; } else { - if (cpuid == -1) { + if (cpuid == -1) snprintf(core_name_buf, sizeof(core_name_buf), "Unknown"); - } else { + else snprintf(core_name_buf, sizeof(core_name_buf), "Unknown (0x%.3x)", cpuid); - } core_name = core_name_buf; } @@ -598,12 +607,12 @@ static void gator_send_core_name(const int cpu, const u32 cpuid) #endif } -static void gator_read_cpuid(void * arg) +static void gator_read_cpuid(void *arg) { gator_cpuids[get_physical_cpu()] = gator_cpuid(); } -// This function runs in interrupt context and on the appropriate core +/* This function runs in interrupt context and on the appropriate core */ static void gator_timer_online(void *migrate) { struct gator_interface *gi; @@ -611,12 +620,12 @@ static void gator_timer_online(void *migrate) int *buffer; u64 time; - // Send what is currently running on this core + /* Send what is currently running on this core */ marshal_sched_trace_switch(current->pid, 0); gator_trace_power_online(); - // online any events and output counters + /* online any events and output counters */ time = gator_get_time(); if (marshal_event_header(time)) { list_for_each_entry(gi, &gator_events, list) { @@ -625,26 +634,24 @@ static void gator_timer_online(void *migrate) marshal_event(len, buffer); } } - // Only check after writing all counters so that time and corresponding counters appear in the same frame + /* Only check after writing all counters so that time and corresponding counters appear in the same frame */ buffer_check(cpu, BLOCK_COUNTER_BUF, time); } - if (!migrate) { + if (!migrate) gator_hrtimer_online(); - } gator_send_core_name(cpu, gator_cpuid()); } -// This function runs in interrupt context and may be running on a core other than core 'cpu' +/* This function runs in interrupt context and may be running on a core other than core 'cpu' */ static void gator_timer_online_dispatch(int cpu, bool migrate) { struct gator_interface *gi; list_for_each_entry(gi, &gator_events, list) { - if (gi->online_dispatch) { + if (gi->online_dispatch) gi->online_dispatch(cpu, migrate); - } } } @@ -661,15 +668,14 @@ static int gator_timer_start(unsigned long sample_rate) gator_running = 1; - // event based sampling trumps hr timer based sampling - if (event_based_sampling) { + /* event based sampling trumps hr timer based sampling */ + if (event_based_sampling) sample_rate = 0; - } if (gator_hrtimer_init(sample_rate, gator_timer_interrupt) == -1) return -1; - // Send off the previously saved cpuids + /* Send off the previously saved cpuids */ for_each_present_cpu(cpu) { preempt_disable(); gator_send_core_name(cpu, gator_cpuids[cpu]); @@ -693,21 +699,24 @@ static u64 gator_get_time(void) u64 delta; int cpu = smp_processor_id(); - // Match clock_gettime(CLOCK_MONOTONIC_RAW, &ts) from userspace + /* Match clock_gettime(CLOCK_MONOTONIC_RAW, &ts) from userspace */ getrawmonotonic(&ts); timestamp = timespec_to_ns(&ts); - // getrawmonotonic is not monotonic on all systems. Detect and attempt to correct these cases. - // up to 0.5ms delta has been seen on some systems, which can skew Streamline data when viewing at high resolution. - // This doesn't work well with interrupts, but that it's OK - the real concern is to catch big jumps in time + /* getrawmonotonic is not monotonic on all systems. Detect and + * attempt to correct these cases. up to 0.5ms delta has been seen + * on some systems, which can skew Streamline data when viewing at + * high resolution. This doesn't work well with interrupts, but that + * it's OK - the real concern is to catch big jumps in time + */ prev_timestamp = per_cpu(last_timestamp, cpu); if (prev_timestamp <= timestamp) { per_cpu(last_timestamp, cpu) = timestamp; } else { delta = prev_timestamp - timestamp; - // Log the error once + /* Log the error once */ if (!printed_monotonic_warning && delta > 500000) { - printk(KERN_ERR "%s: getrawmonotonic is not monotonic cpu: %i delta: %lli\nSkew in Streamline data may be present at the fine zoom levels\n", __FUNCTION__, cpu, delta); + pr_err("%s: getrawmonotonic is not monotonic cpu: %i delta: %lli\nSkew in Streamline data may be present at the fine zoom levels\n", __func__, cpu, delta); printed_monotonic_warning = true; } timestamp = prev_timestamp; @@ -716,6 +725,19 @@ static u64 gator_get_time(void) return timestamp - gator_monotonic_started; } +static void gator_emit_perf_time(u64 time) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) + if (time >= gator_sync_time) { + int cpu = get_physical_cpu(); + + marshal_event_single64(0, -1, local_clock()); + gator_sync_time += NSEC_PER_SEC; + gator_commit_buffer(cpu, COUNTER_BUF, time); + } +#endif +} + /****************************************************************************** * cpu hotplug and pm notifiers ******************************************************************************/ @@ -743,8 +765,10 @@ static struct notifier_block __refdata gator_hotcpu_notifier = { .notifier_call = gator_hotcpu_notify, }; -// n.b. calling "on_each_cpu" only runs on those that are online -// Registered linux events are not disabled, so their counters will continue to collect +/* n.b. calling "on_each_cpu" only runs on those that are online. + * Registered linux events are not disabled, so their counters will + * continue to collect + */ static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) { int cpu; @@ -760,13 +784,13 @@ static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void gator_timer_offline_dispatch(lcpu_to_pcpu(cpu), false); } - // Record the wallclock hibernate time + /* Record the wallclock hibernate time */ getnstimeofday(&ts); gator_hibernate_time = timespec_to_ns(&ts) - gator_get_time(); break; case PM_POST_HIBERNATION: case PM_POST_SUSPEND: - // Adjust gator_monotonic_started for the time spent sleeping, as gator_get_time does not account for it + /* Adjust gator_monotonic_started for the time spent sleeping, as gator_get_time does not account for it */ if (gator_hibernate_time > 0) { getnstimeofday(&ts); gator_monotonic_started += gator_hibernate_time + gator_get_time() - timespec_to_ns(&ts); @@ -792,6 +816,7 @@ static struct notifier_block gator_pm_notifier = { static int gator_notifier_start(void) { int retval; + retval = register_hotcpu_notifier(&gator_hotcpu_notifier); if (retval == 0) retval = register_pm_notifier(&gator_pm_notifier); @@ -812,28 +837,37 @@ static void gator_summary(void) u64 timestamp, uptime; struct timespec ts; char uname_buf[512]; - void (*m2b)(struct timespec *ts); snprintf(uname_buf, sizeof(uname_buf), "%s %s %s %s %s GNU/Linux", utsname()->sysname, utsname()->nodename, utsname()->release, utsname()->version, utsname()->machine); getnstimeofday(&ts); timestamp = timespec_to_ns(&ts); - do_posix_clock_monotonic_gettime(&ts); - // monotonic_to_bootbased is not defined for some versions of Android - m2b = symbol_get(monotonic_to_bootbased); - if (m2b) { - m2b(&ts); + /* Similar to reading /proc/uptime from fs/proc/uptime.c, calculate uptime */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) + { + void (*m2b)(struct timespec *ts); + + do_posix_clock_monotonic_gettime(&ts); + /* monotonic_to_bootbased is not defined for some versions of Android */ + m2b = symbol_get(monotonic_to_bootbased); + if (m2b) + m2b(&ts); } +#else + get_monotonic_boottime(&ts); +#endif uptime = timespec_to_ns(&ts); - // Disable preemption as gator_get_time calls smp_processor_id to verify time is monotonic + /* Disable preemption as gator_get_time calls smp_processor_id to verify time is monotonic */ preempt_disable(); - // Set monotonic_started to zero as gator_get_time is uptime minus monotonic_started + /* Set monotonic_started to zero as gator_get_time is uptime minus monotonic_started */ gator_monotonic_started = 0; gator_monotonic_started = gator_get_time(); marshal_summary(timestamp, uptime, gator_monotonic_started, uname_buf); + gator_sync_time = 0; + gator_emit_perf_time(gator_monotonic_started); preempt_enable(); } @@ -846,12 +880,14 @@ int gator_events_install(struct gator_interface *interface) int gator_events_get_key(void) { - // key 0 is reserved as a timestamp - // key 1 is reserved as the marker for thread specific counters - // Odd keys are assigned by the driver, even keys by the daemon + /* key 0 is reserved as a timestamp. key 1 is reserved as the marker + * for thread specific counters. key 2 is reserved as the marker for + * core. Odd keys are assigned by the driver, even keys by the + * daemon. + */ static int key = 3; - const int ret = key; + key += 2; return ret; } @@ -862,7 +898,7 @@ static int gator_init(void) calc_first_cluster_size(); - // events sources + /* events sources */ for (i = 0; i < ARRAY_SIZE(gator_events_list); i++) if (gator_events_list[i]) gator_events_list[i](); @@ -888,26 +924,25 @@ static int gator_start(void) struct gator_interface *gi; gator_buffer_wake_run = true; - if (IS_ERR(gator_buffer_wake_thread = kthread_run(gator_buffer_wake_func, NULL, "gator_bwake"))) { + gator_buffer_wake_thread = kthread_run(gator_buffer_wake_func, NULL, "gator_bwake"); + if (IS_ERR(gator_buffer_wake_thread)) goto bwake_failure; - } if (gator_migrate_start()) goto migrate_failure; - // Initialize the buffer with the frame type and core + /* Initialize the buffer with the frame type and core */ for_each_present_cpu(cpu) { - for (i = 0; i < NUM_GATOR_BUFS; i++) { + for (i = 0; i < NUM_GATOR_BUFS; i++) marshal_frame(cpu, i); - } per_cpu(last_timestamp, cpu) = 0; } printed_monotonic_warning = false; - // Capture the start time + /* Capture the start time */ gator_summary(); - // start all events + /* start all events */ list_for_each_entry(gi, &gator_events, list) { if (gi->start && gi->start() != 0) { struct list_head *ptr = gi->list.prev; @@ -924,7 +959,7 @@ static int gator_start(void) } } - // cookies shall be initialized before trace_sched_start() and gator_timer_start() + /* cookies shall be initialized before trace_sched_start() and gator_timer_start() */ if (cookies_initialize()) goto cookies_failure; if (gator_annotate_start()) @@ -955,7 +990,7 @@ sched_failure: annotate_failure: cookies_release(); cookies_failure: - // stop all events + /* stop all events */ list_for_each_entry(gi, &gator_events, list) if (gi->stop) gi->stop(); @@ -979,11 +1014,11 @@ static void gator_stop(void) gator_trace_power_stop(); gator_trace_gpu_stop(); - // stop all interrupt callback reads before tearing down other interfaces - gator_notifier_stop(); // should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined + /* stop all interrupt callback reads before tearing down other interfaces */ + gator_notifier_stop(); /* should be called before gator_timer_stop to avoid re-enabling the hrtimer after it has been offlined */ gator_timer_stop(); - // stop all events + /* stop all events */ list_for_each_entry(gi, &gator_events, list) if (gi->stop) gi->stop(); @@ -1033,9 +1068,9 @@ static int gator_op_setup(void) gator_buffer_size[ACTIVITY_BUF] = ACTIVITY_BUFFER_SIZE; gator_buffer_mask[ACTIVITY_BUF] = ACTIVITY_BUFFER_SIZE - 1; - // Initialize percpu per buffer variables + /* Initialize percpu per buffer variables */ for (i = 0; i < NUM_GATOR_BUFS; i++) { - // Verify buffers are a power of 2 + /* Verify buffers are a power of 2 */ if (gator_buffer_size[i] & (gator_buffer_size[i] - 1)) { err = -ENOEXEC; goto setup_error; @@ -1048,7 +1083,7 @@ static int gator_op_setup(void) per_cpu(buffer_space_available, cpu)[i] = true; per_cpu(gator_buffer_commit_time, cpu) = gator_live_rate; - // Annotation is a special case that only uses a single buffer + /* Annotation is a special case that only uses a single buffer */ if (cpu > 0 && i == ANNOTATE_BUF) { per_cpu(gator_buffer, cpu)[i] = NULL; continue; @@ -1188,7 +1223,8 @@ static int userspace_buffer_open(struct inode *inode, struct file *file) if (test_and_set_bit_lock(0, &gator_buffer_opened)) return -EBUSY; - if ((err = gator_op_setup())) + err = gator_op_setup(); + if (err) goto fail; /* NB: the actual start happens from userspace @@ -1218,22 +1254,20 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf, size_t int cpu, buftype; int written = 0; - // ensure there is enough space for a whole frame - if (count < userspace_buffer_size || *offset) { + /* ensure there is enough space for a whole frame */ + if (count < userspace_buffer_size || *offset) return -EINVAL; - } - // sleep until the condition is true or a signal is received - // the condition is checked each time gator_buffer_wait is woken up + /* 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(&cpu, &buftype) || !gator_started); - if (signal_pending(current)) { + if (signal_pending(current)) return -EINTR; - } - if (buftype == -1 || cpu == -1) { + if (buftype == -1 || cpu == -1) return 0; - } mutex_lock(&gator_buffer_mutex); @@ -1241,12 +1275,11 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf, size_t read = per_cpu(gator_buffer_read, cpu)[buftype]; commit = per_cpu(gator_buffer_commit, cpu)[buftype]; - // May happen if the buffer is freed during pending reads. - if (!per_cpu(gator_buffer, cpu)[buftype]) { + /* May happen if the buffer is freed during pending reads. */ + if (!per_cpu(gator_buffer, cpu)[buftype]) break; - } - // determine the size of two halves + /* determine the size of two halves */ length1 = commit - read; length2 = 0; buffer1 = &(per_cpu(gator_buffer, cpu)[buftype][read]); @@ -1256,32 +1289,28 @@ static ssize_t userspace_buffer_read(struct file *file, char __user *buf, size_t length2 = commit; } - if (length1 + length2 > count - written) { + if (length1 + length2 > count - written) break; - } - // start, middle or end - if (length1 > 0 && copy_to_user(&buf[written], buffer1, length1)) { + /* start, middle or end */ + if (length1 > 0 && copy_to_user(&buf[written], buffer1, length1)) break; - } - // possible wrap around - if (length2 > 0 && copy_to_user(&buf[written + length1], buffer2, length2)) { + /* possible wrap around */ + if (length2 > 0 && copy_to_user(&buf[written + length1], buffer2, length2)) break; - } per_cpu(gator_buffer_read, cpu)[buftype] = commit; written += length1 + length2; - // Wake up annotate_write if more space is available - if (buftype == ANNOTATE_BUF) { + /* Wake up annotate_write if more space is available */ + if (buftype == ANNOTATE_BUF) wake_up(&gator_annotate_wait); - } } while (buffer_commit_ready(&cpu, &buftype)); mutex_unlock(&gator_buffer_mutex); - // kick just in case we've lost an SMP event + /* kick just in case we've lost an SMP event */ wake_up(&gator_buffer_wait); return written > 0 ? written : -EFAULT; @@ -1348,19 +1377,19 @@ static void gator_op_create_files(struct super_block *sb, struct dentry *root) gatorfs_create_ro_u64(sb, root, "started", &gator_monotonic_started); gatorfs_create_u64(sb, root, "live_rate", &gator_live_rate); - // Annotate interface + /* Annotate interface */ gator_annotate_create_files(sb, root); - // Linux Events + /* Linux Events */ dir = gatorfs_mkdir(sb, root, "events"); list_for_each_entry(gi, &gator_events, list) if (gi->create_files) gi->create_files(sb, dir); - // Sched Events + /* Sched Events */ sched_trace_create_files(sb, dir); - // Power interface + /* Power interface */ gator_trace_power_create_files(sb, dir); } @@ -1396,19 +1425,22 @@ static void gator_op_create_files(struct super_block *sb, struct dentry *root) GATOR_HANDLE_TRACEPOINT(sched_process_free); \ GATOR_HANDLE_TRACEPOINT(sched_switch); \ GATOR_HANDLE_TRACEPOINT(softirq_exit); \ + GATOR_HANDLE_TRACEPOINT(task_rename); \ #define GATOR_HANDLE_TRACEPOINT(probe_name) \ struct tracepoint *gator_tracepoint_##probe_name GATOR_TRACEPOINTS; #undef GATOR_HANDLE_TRACEPOINT -static void gator_fct(struct tracepoint *tp, void *priv) +static void gator_save_tracepoint(struct tracepoint *tp, void *priv) { #define GATOR_HANDLE_TRACEPOINT(probe_name) \ - if (strcmp(tp->name, #probe_name) == 0) { \ - gator_tracepoint_##probe_name = tp; \ - return; \ - } + do { \ + if (strcmp(tp->name, #probe_name) == 0) { \ + gator_tracepoint_##probe_name = tp; \ + return; \ + } \ + } while (0) GATOR_TRACEPOINTS; #undef GATOR_HANDLE_TRACEPOINT } @@ -1421,11 +1453,10 @@ GATOR_TRACEPOINTS; static int __init gator_module_init(void) { - for_each_kernel_tracepoint(gator_fct, NULL); + for_each_kernel_tracepoint(gator_save_tracepoint, NULL); - if (gatorfs_register()) { + if (gatorfs_register()) return -1; - } if (gator_init()) { gatorfs_unregister(); @@ -1434,7 +1465,7 @@ static int __init gator_module_init(void) setup_timer(&gator_buffer_wake_up_timer, gator_buffer_wake_up, 0); - // Initialize the list of cpuids + /* Initialize the list of cpuids */ memset(gator_cpuids, -1, sizeof(gator_cpuids)); on_each_cpu(gator_read_cpuid, NULL, 1); diff --git a/drivers/gator/gator_marshaling.c b/drivers/gator/gator_marshaling.c index 97b4ae6f9d4d..0d1167643642 100644 --- a/drivers/gator/gator_marshaling.c +++ b/drivers/gator/gator_marshaling.c @@ -23,7 +23,7 @@ #include "gator_events_mali_common.h" #endif -static void marshal_summary(long long timestamp, long long uptime, long long monotonic_delta, const char * uname) +static void marshal_summary(long long timestamp, long long uptime, long long monotonic_delta, const char *uname) { unsigned long flags; int cpu = 0; @@ -40,19 +40,27 @@ static void marshal_summary(long long timestamp, long long uptime, long long mon gator_buffer_write_string(cpu, SUMMARY_BUF, "iks"); gator_buffer_write_string(cpu, SUMMARY_BUF, ""); #endif - // Let Streamline know which GPU is used so that it can label the GPU Activity appropriately. This is a temporary fix, to be improved in a future release. +#ifdef CONFIG_PREEMPT_RTB + gator_buffer_write_string(cpu, SUMMARY_BUF, "preempt_rtb"); + gator_buffer_write_string(cpu, SUMMARY_BUF, ""); +#endif +#ifdef CONFIG_PREEMPT_RT_FULL + gator_buffer_write_string(cpu, SUMMARY_BUF, "preempt_rt_full"); + gator_buffer_write_string(cpu, SUMMARY_BUF, ""); +#endif + /* Let Streamline know which GPU is used so that it can label the GPU Activity appropriately. This is a temporary fix, to be improved in a future release. */ #ifdef MALI_SUPPORT gator_buffer_write_string(cpu, SUMMARY_BUF, "mali_type"); #if (MALI_SUPPORT == MALI_4xx) gator_buffer_write_string(cpu, SUMMARY_BUF, "4xx"); -#elif (MALI_SUPPORT == MALI_T6xx) +#elif (MALI_SUPPORT == MALI_MIDGARD) gator_buffer_write_string(cpu, SUMMARY_BUF, "6xx"); #else gator_buffer_write_string(cpu, SUMMARY_BUF, "unknown"); #endif #endif gator_buffer_write_string(cpu, SUMMARY_BUF, ""); - // Commit the buffer now so it can be one of the first frames read by Streamline + /* Commit the buffer now so it can be one of the first frames read by Streamline */ local_irq_restore(flags); gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time()); } @@ -60,13 +68,14 @@ static void marshal_summary(long long timestamp, long long uptime, long long mon static bool marshal_cookie_header(const char *text) { int cpu = get_physical_cpu(); + return buffer_check_space(cpu, NAME_BUF, strlen(text) + 3 * MAXSIZE_PACK32); } static void marshal_cookie(int cookie, const char *text) { int cpu = get_physical_cpu(); - // buffer_check_space already called by marshal_cookie_header + /* buffer_check_space already called by marshal_cookie_header */ gator_buffer_write_packed_int(cpu, NAME_BUF, MESSAGE_COOKIE); gator_buffer_write_packed_int(cpu, NAME_BUF, cookie); gator_buffer_write_string(cpu, NAME_BUF, text); @@ -77,6 +86,7 @@ static void marshal_thread_name(int pid, char *name) { unsigned long flags, cpu; u64 time; + local_irq_save(flags); cpu = get_physical_cpu(); time = gator_get_time(); @@ -105,15 +115,16 @@ static void marshal_link(int cookie, int tgid, int pid) gator_buffer_write_packed_int(cpu, NAME_BUF, pid); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, NAME_BUF, time); } static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, u64 time) { int cpu = get_physical_cpu(); + if (!buffer_check_space(cpu, BACKTRACE_BUF, MAXSIZE_PACK64 + 5 * MAXSIZE_PACK32 + gator_backtrace_depth * 2 * MAXSIZE_PACK32)) { - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, BACKTRACE_BUF, time); return false; @@ -130,9 +141,9 @@ static bool marshal_backtrace_header(int exec_cookie, int tgid, int pid, u64 tim static void marshal_backtrace(unsigned long address, int cookie, int in_kernel) { int cpu = get_physical_cpu(); - if (cookie == 0 && !in_kernel) { + + if (cookie == 0 && !in_kernel) cookie = UNRESOLVED_COOKIE; - } gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, cookie); gator_buffer_write_packed_int64(cpu, BACKTRACE_BUF, address); } @@ -140,9 +151,10 @@ static void marshal_backtrace(unsigned long address, int cookie, int in_kernel) static void marshal_backtrace_footer(u64 time) { int cpu = get_physical_cpu(); + gator_buffer_write_packed_int(cpu, BACKTRACE_BUF, MESSAGE_END_BACKTRACE); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, BACKTRACE_BUF, time); } @@ -153,7 +165,7 @@ static bool marshal_event_header(u64 time) local_irq_save(flags); if (buffer_check_space(cpu, BLOCK_COUNTER_BUF, MAXSIZE_PACK32 + MAXSIZE_PACK64)) { - gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); // key of zero indicates a timestamp + gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, 0); /* key of zero indicates a timestamp */ gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, time); retval = true; } @@ -169,18 +181,17 @@ static void marshal_event(int len, int *buffer) if (len <= 0) return; - // length must be even since all data is a (key, value) pair + /* length must be even since all data is a (key, value) pair */ if (len & 0x1) { - pr_err("gator: invalid counter data detected and discarded"); + pr_err("gator: invalid counter data detected and discarded\n"); return; } - // events must be written in key,value pairs + /* events must be written in key,value pairs */ local_irq_save(flags); for (i = 0; i < len; i += 2) { - if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK32)) { + if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK32)) break; - } gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i]); gator_buffer_write_packed_int(cpu, BLOCK_COUNTER_BUF, buffer[i + 1]); } @@ -194,26 +205,24 @@ static void marshal_event64(int len, long long *buffer64) if (len <= 0) return; - // length must be even since all data is a (key, value) pair + /* length must be even since all data is a (key, value) pair */ if (len & 0x1) { - pr_err("gator: invalid counter data detected and discarded"); + pr_err("gator: invalid counter data detected and discarded\n"); return; } - // events must be written in key,value pairs + /* events must be written in key,value pairs */ local_irq_save(flags); for (i = 0; i < len; i += 2) { - if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK64)) { + if (!buffer_check_space(cpu, BLOCK_COUNTER_BUF, 2 * MAXSIZE_PACK64)) break; - } gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i]); gator_buffer_write_packed_int64(cpu, BLOCK_COUNTER_BUF, buffer64[i + 1]); } local_irq_restore(flags); } -#if GATOR_CPU_FREQ_SUPPORT -static void marshal_event_single(int core, int key, int value) +static void __maybe_unused marshal_event_single(int core, int key, int value) { unsigned long flags, cpu; u64 time; @@ -228,11 +237,11 @@ static void marshal_event_single(int core, int key, int value) gator_buffer_write_packed_int(cpu, COUNTER_BUF, value); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, COUNTER_BUF, time); } -static void marshal_event_single64(int core, int key, long long value) +static void __maybe_unused marshal_event_single64(int core, int key, long long value) { unsigned long flags, cpu; u64 time; @@ -247,10 +256,9 @@ static void marshal_event_single64(int core, int key, long long value) gator_buffer_write_packed_int64(cpu, COUNTER_BUF, value); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, COUNTER_BUF, time); } -#endif static void marshal_sched_trace_switch(int pid, int state) { @@ -269,7 +277,7 @@ static void marshal_sched_trace_switch(int pid, int state) gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, state); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, SCHED_TRACE_BUF, time); } @@ -289,7 +297,7 @@ static void marshal_sched_trace_exit(int tgid, int pid) gator_buffer_write_packed_int(cpu, SCHED_TRACE_BUF, pid); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, SCHED_TRACE_BUF, time); } @@ -308,7 +316,7 @@ static void marshal_idle(int core, int state) gator_buffer_write_packed_int(cpu, IDLE_BUF, core); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, IDLE_BUF, time); } #endif @@ -318,6 +326,7 @@ static void marshal_core_name(const int core, const int cpuid, const char *name) { int cpu = get_physical_cpu(); unsigned long flags; + local_irq_save(flags); if (buffer_check_space(cpu, SUMMARY_BUF, MAXSIZE_PACK32 + MAXSIZE_CORE_NAME)) { gator_buffer_write_packed_int(cpu, SUMMARY_BUF, MESSAGE_CORE_NAME); @@ -325,7 +334,7 @@ static void marshal_core_name(const int core, const int cpuid, const char *name) gator_buffer_write_packed_int(cpu, SUMMARY_BUF, cpuid); gator_buffer_write_string(cpu, SUMMARY_BUF, name); } - // Commit core names now so that they can show up in live + /* Commit core names now so that they can show up in live */ local_irq_restore(flags); gator_commit_buffer(cpu, SUMMARY_BUF, gator_get_time()); } @@ -351,12 +360,12 @@ static void marshal_activity_switch(int core, int key, int activity, int pid, in gator_buffer_write_packed_int(cpu, ACTIVITY_BUF, state); } local_irq_restore(flags); - // Check and commit; commit is set to occur once buffer is 3/4 full + /* Check and commit; commit is set to occur once buffer is 3/4 full */ buffer_check(cpu, ACTIVITY_BUF, time); } void gator_marshal_activity_switch(int core, int key, int activity, int pid) { - // state is reserved for cpu use only + /* state is reserved for cpu use only */ marshal_activity_switch(core, key, activity, pid, 0); } diff --git a/drivers/gator/gator_trace_gpu.c b/drivers/gator/gator_trace_gpu.c index a8b9e7d61ece..5de9152e365a 100644 --- a/drivers/gator/gator_trace_gpu.c +++ b/drivers/gator/gator_trace_gpu.c @@ -58,11 +58,12 @@ struct mali_activity { static struct mali_activity mali_activities[NUMBER_OF_GPU_UNITS*NUMBER_OF_GPU_CORES]; static DEFINE_SPINLOCK(mali_activities_lock); -/* Only one event should be running on a unit and core at a time (ie, a start - * event can only be followed by a stop and vice versa), but because the kernel - * only knows when a job is enqueued and not started, it is possible for a - * start1, start2, stop1, stop2. Change it back into start1, stop1, start2, - * stop2 by queueing up start2 and releasing it when stop1 is received. +/* Only one event should be running on a unit and core at a time (ie, + * a start event can only be followed by a stop and vice versa), but + * because the kernel only knows when a job is enqueued and not + * started, it is possible for a start1, start2, stop1, stop2. Change + * it back into start1, stop1, start2, stop2 by queueing up start2 and + * releasing it when stop1 is received. */ static int mali_activity_index(int core, int key) @@ -70,9 +71,8 @@ static int mali_activity_index(int core, int key) int i; for (i = 0; i < ARRAY_SIZE(mali_activities); ++i) { - if ((mali_activities[i].core == core) && (mali_activities[i].key == key)) { + if ((mali_activities[i].core == core) && (mali_activities[i].key == key)) break; - } if ((mali_activities[i].core == 0) && (mali_activities[i].key == 0)) { mali_activities[i].core = core; mali_activities[i].key = key; @@ -101,9 +101,8 @@ static void mali_activity_enqueue(int core, int key, int activity, int pid) } spin_unlock(&mali_activities_lock); - if (!count) { + if (!count) gator_marshal_activity_switch(core, key, activity, pid); - } } static void mali_activity_stop(int core, int key) @@ -129,12 +128,11 @@ static void mali_activity_stop(int core, int key) spin_unlock(&mali_activities_lock); gator_marshal_activity_switch(core, key, 0, 0); - if (count) { + if (count) gator_marshal_activity_switch(core, key, last_activity, last_pid); - } } -void mali_activity_clear(mali_counter mali_activity[], size_t mali_activity_size) +void mali_activity_clear(struct mali_counter mali_activity[], size_t mali_activity_size) { int activity; int cores; @@ -142,12 +140,13 @@ void mali_activity_clear(mali_counter mali_activity[], size_t mali_activity_size for (activity = 0; activity < mali_activity_size; ++activity) { cores = mali_activity[activity].cores; - if (cores < 0) { + if (cores < 0) cores = 1; - } for (core = 0; core < cores; ++core) { if (mali_activity[activity].enabled) { + preempt_disable(); gator_marshal_activity_switch(core, mali_activity[activity].key, 0, 0); + preempt_enable(); } } } @@ -155,7 +154,7 @@ void mali_activity_clear(mali_counter mali_activity[], size_t mali_activity_size #endif -#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx) +#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD) #include "gator_events_mali_4xx.h" /* @@ -183,40 +182,36 @@ enum { EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE = 1, }; -mali_counter mali_activity[2]; +struct mali_counter mali_activity[2]; GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned int d0, unsigned int d1, unsigned int d2, unsigned int d3, unsigned int d4)) { unsigned int component, state; - // do as much work as possible before disabling interrupts - component = (event_id >> 16) & 0xFF; // component is an 8-bit field - state = (event_id >> 24) & 0xF; // state is a 4-bit field + /* do as much work as possible before disabling interrupts */ + component = (event_id >> 16) & 0xFF; /* component is an 8-bit field */ + state = (event_id >> 24) & 0xF; /* state is a 4-bit field */ switch (state) { case EVENT_TYPE_START: if (component == EVENT_CHANNEL_VP0) { /* tgid = d0; pid = d1; */ - if (mali_activity[1].enabled) { + if (mali_activity[1].enabled) mali_activity_enqueue(0, mali_activity[1].key, 1, d1); - } } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) { /* tgid = d0; pid = d1; */ - if (mali_activity[0].enabled) { + if (mali_activity[0].enabled) mali_activity_enqueue(component - EVENT_CHANNEL_FP0, mali_activity[0].key, 1, d1); - } } break; case EVENT_TYPE_STOP: if (component == EVENT_CHANNEL_VP0) { - if (mali_activity[1].enabled) { + if (mali_activity[1].enabled) mali_activity_stop(0, mali_activity[1].key); - } } else if (component >= EVENT_CHANNEL_FP0 && component <= EVENT_CHANNEL_FP7) { - if (mali_activity[0].enabled) { + if (mali_activity[0].enabled) mali_activity_stop(component - EVENT_CHANNEL_FP0, mali_activity[0].key); - } } break; @@ -224,9 +219,8 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned if (component == EVENT_CHANNEL_GPU) { unsigned int reason = (event_id & 0xffff); - if (reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE) { + if (reason == EVENT_REASON_SINGLE_GPU_FREQ_VOLT_CHANGE) gator_events_mali_log_dvfs_event(d0, d1); - } } break; @@ -236,9 +230,9 @@ GATOR_DEFINE_PROBE(mali_timeline_event, TP_PROTO(unsigned int event_id, unsigned } #endif -#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx) +#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD) -mali_counter mali_activity[3]; +struct mali_counter mali_activity[3]; #if defined(MALI_JOB_SLOTS_EVENT_CHANGED) GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigned int tgid, unsigned int pid, unsigned char job_id)) @@ -251,8 +245,8 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne unsigned char job_id = 0; #endif - component = (event_id >> 16) & 0xFF; // component is an 8-bit field - state = (event_id >> 24) & 0xF; // state is a 4-bit field + component = (event_id >> 16) & 0xFF; /* component is an 8-bit field */ + state = (event_id >> 24) & 0xF; /* state is a 4-bit field */ switch (component) { case 0: @@ -271,15 +265,13 @@ GATOR_DEFINE_PROBE(mali_job_slots_event, TP_PROTO(unsigned int event_id, unsigne if (unit != GPU_UNIT_NONE) { switch (state) { case EVENT_TYPE_START: - if (mali_activity[component].enabled) { + if (mali_activity[component].enabled) mali_activity_enqueue(0, mali_activity[component].key, 1, (pid != 0 ? pid : tgid)); - } break; case EVENT_TYPE_STOP: - default: // Some jobs can be soft-stopped, so ensure that this terminates the activity trace. - if (mali_activity[component].enabled) { + default: /* Some jobs can be soft-stopped, so ensure that this terminates the activity trace. */ + if (mali_activity[component].enabled) mali_activity_stop(0, mali_activity[component].key); - } break; } } @@ -298,18 +290,16 @@ static int gator_trace_gpu_start(void) #endif mali_timeline_trace_registered = mali_job_slots_trace_registered = 0; -#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx) +#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD) mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity)); - if (!GATOR_REGISTER_TRACE(mali_timeline_event)) { + if (!GATOR_REGISTER_TRACE(mali_timeline_event)) mali_timeline_trace_registered = 1; - } #endif -#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx) +#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD) mali_activity_clear(mali_activity, ARRAY_SIZE(mali_activity)); - if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) { + if (!GATOR_REGISTER_TRACE(mali_job_slots_event)) mali_job_slots_trace_registered = 1; - } #endif return 0; @@ -317,16 +307,14 @@ static int gator_trace_gpu_start(void) static void gator_trace_gpu_stop(void) { -#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_T6xx) - if (mali_timeline_trace_registered) { +#if defined(MALI_SUPPORT) && (MALI_SUPPORT != MALI_MIDGARD) + if (mali_timeline_trace_registered) GATOR_UNREGISTER_TRACE(mali_timeline_event); - } #endif -#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_T6xx) - if (mali_job_slots_trace_registered) { +#if defined(MALI_SUPPORT) && (MALI_SUPPORT == MALI_MIDGARD) + if (mali_job_slots_trace_registered) GATOR_UNREGISTER_TRACE(mali_job_slots_event); - } #endif mali_timeline_trace_registered = mali_job_slots_trace_registered = 0; diff --git a/drivers/gator/gator_trace_power.c b/drivers/gator/gator_trace_power.c index f2754b1c2b56..46e04b29a187 100644 --- a/drivers/gator/gator_trace_power.c +++ b/drivers/gator/gator_trace_power.c @@ -22,18 +22,20 @@ #endif -// cpu_frequency and cpu_idle trace points were introduced in Linux kernel v2.6.38 -// the now deprecated power_frequency trace point was available prior to 2.6.38, but only for x86 +/* cpu_frequency and cpu_idle trace points were introduced in Linux + * kernel v2.6.38 the now deprecated power_frequency trace point was + * available prior to 2.6.38, but only for x86 + */ #if GATOR_CPU_FREQ_SUPPORT enum { POWER_CPU_FREQ, - POWER_CPU_IDLE, POWER_TOTAL }; static DEFINE_PER_CPU(ulong, idle_prev_state); static ulong power_cpu_enabled[POWER_TOTAL]; static ulong power_cpu_key[POWER_TOTAL]; +static ulong power_cpu_cores; static int gator_trace_power_create_files(struct super_block *sb, struct dentry *root) { @@ -41,8 +43,9 @@ static int gator_trace_power_create_files(struct super_block *sb, struct dentry int cpu; bool found_nonzero_freq = false; - // Even if CONFIG_CPU_FREQ is defined, it still may not be used. Check - // for non-zero values from cpufreq_quick_get + /* Even if CONFIG_CPU_FREQ is defined, it still may not be + * used. Check for non-zero values from cpufreq_quick_get + */ for_each_online_cpu(cpu) { if (cpufreq_quick_get(cpu) > 0) { found_nonzero_freq = true; @@ -51,27 +54,18 @@ static int gator_trace_power_create_files(struct super_block *sb, struct dentry } if (found_nonzero_freq) { - // cpu_frequency + /* cpu_frequency */ dir = gatorfs_mkdir(sb, root, "Linux_power_cpu_freq"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &power_cpu_enabled[POWER_CPU_FREQ]); gatorfs_create_ro_ulong(sb, dir, "key", &power_cpu_key[POWER_CPU_FREQ]); } - // cpu_idle - dir = gatorfs_mkdir(sb, root, "Linux_power_cpu_idle"); - if (!dir) { - return -1; - } - gatorfs_create_ulong(sb, dir, "enabled", &power_cpu_enabled[POWER_CPU_IDLE]); - gatorfs_create_ro_ulong(sb, dir, "key", &power_cpu_key[POWER_CPU_IDLE]); - return 0; } -// 'cpu' may not equal smp_processor_id(), i.e. may not be running on the core that is having the freq/idle state change +/* 'cpu' may not equal smp_processor_id(), i.e. may not be running on the core that is having the freq/idle state change */ GATOR_DEFINE_PROBE(cpu_frequency, TP_PROTO(unsigned int frequency, unsigned int cpu)) { cpu = lcpu_to_pcpu(cpu); @@ -82,56 +76,50 @@ GATOR_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu)) { cpu = lcpu_to_pcpu(cpu); - if (state == per_cpu(idle_prev_state, cpu)) { + if (state == per_cpu(idle_prev_state, cpu)) return; - } if (implements_wfi()) { if (state == PWR_EVENT_EXIT) { - // transition from wfi to non-wfi + /* transition from wfi to non-wfi */ marshal_idle(cpu, MESSAGE_IDLE_EXIT); } else { - // transition from non-wfi to wfi + /* transition from non-wfi to wfi */ marshal_idle(cpu, MESSAGE_IDLE_ENTER); } } per_cpu(idle_prev_state, cpu) = state; - - if (power_cpu_enabled[POWER_CPU_IDLE]) { - // Increment state so that no negative numbers are sent - marshal_event_single(cpu, power_cpu_key[POWER_CPU_IDLE], state + 1); - } } static void gator_trace_power_online(void) { int pcpu = get_physical_cpu(); int lcpu = get_logical_cpu(); - if (power_cpu_enabled[POWER_CPU_FREQ]) { + + if (power_cpu_enabled[POWER_CPU_FREQ]) marshal_event_single64(pcpu, power_cpu_key[POWER_CPU_FREQ], cpufreq_quick_get(lcpu) * 1000L); - } } static void gator_trace_power_offline(void) { - // Set frequency to zero on an offline + /* Set frequency to zero on an offline */ int cpu = get_physical_cpu(); - if (power_cpu_enabled[POWER_CPU_FREQ]) { + + if (power_cpu_enabled[POWER_CPU_FREQ]) marshal_event_single(cpu, power_cpu_key[POWER_CPU_FREQ], 0); - } } static int gator_trace_power_start(void) { int cpu; - // register tracepoints + /* register tracepoints */ if (power_cpu_enabled[POWER_CPU_FREQ]) if (GATOR_REGISTER_TRACE(cpu_frequency)) goto fail_cpu_frequency_exit; - // Always register for cpu:idle for detecting WFI, independent of power_cpu_enabled[POWER_CPU_IDLE] + /* Always register for cpu_idle for detecting WFI */ if (GATOR_REGISTER_TRACE(cpu_idle)) goto fail_cpu_idle_exit; pr_debug("gator: registered power event tracepoints\n"); @@ -142,7 +130,7 @@ static int gator_trace_power_start(void) return 0; - // unregister tracepoints on error + /* unregister tracepoints on error */ fail_cpu_idle_exit: if (power_cpu_enabled[POWER_CPU_FREQ]) GATOR_UNREGISTER_TRACE(cpu_frequency); @@ -161,14 +149,15 @@ static void gator_trace_power_stop(void) GATOR_UNREGISTER_TRACE(cpu_idle); pr_debug("gator: unregistered power event tracepoints\n"); - for (i = 0; i < POWER_TOTAL; i++) { + for (i = 0; i < POWER_TOTAL; i++) power_cpu_enabled[i] = 0; - } } static void gator_trace_power_init(void) { int i; + + power_cpu_cores = nr_cpu_ids; for (i = 0; i < POWER_TOTAL; i++) { power_cpu_enabled[i] = 0; power_cpu_key[i] = gator_events_get_key(); diff --git a/drivers/gator/gator_trace_sched.c b/drivers/gator/gator_trace_sched.c index 655008628933..6d7cbd7348e1 100644 --- a/drivers/gator/gator_trace_sched.c +++ b/drivers/gator/gator_trace_sched.c @@ -8,6 +8,10 @@ */ #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +#include +#endif + #include "gator.h" #define TASK_MAP_ENTRIES 1024 /* must be power of 2 */ @@ -23,8 +27,10 @@ enum { static DEFINE_PER_CPU(uint64_t *, taskname_keys); static DEFINE_PER_CPU(int, collecting); -// this array is never read as the cpu wait charts are derived counters -// the files are needed, nonetheless, to show that these counters are available +/* this array is never read as the cpu wait charts are derived + * counters the files are needed, nonetheless, to show that these + * counters are available + */ static ulong cpu_wait_enabled[CPU_WAIT_TOTAL]; static ulong sched_cpu_key[CPU_WAIT_TOTAL]; @@ -32,26 +38,24 @@ static int sched_trace_create_files(struct super_block *sb, struct dentry *root) { struct dentry *dir; - // CPU Wait - Contention + /* CPU Wait - Contention */ dir = gatorfs_mkdir(sb, root, "Linux_cpu_wait_contention"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &cpu_wait_enabled[STATE_CONTENTION]); gatorfs_create_ro_ulong(sb, dir, "key", &sched_cpu_key[STATE_CONTENTION]); - // CPU Wait - I/O + /* CPU Wait - I/O */ dir = gatorfs_mkdir(sb, root, "Linux_cpu_wait_io"); - if (!dir) { + if (!dir) return -1; - } gatorfs_create_ulong(sb, dir, "enabled", &cpu_wait_enabled[STATE_WAIT_ON_IO]); gatorfs_create_ro_ulong(sb, dir, "key", &sched_cpu_key[STATE_WAIT_ON_IO]); return 0; } -static void emit_pid_name(struct task_struct *task) +static void emit_pid_name(const char *comm, struct task_struct *task) { bool found = false; char taskcomm[TASK_COMM_LEN + 3]; @@ -59,10 +63,10 @@ static void emit_pid_name(struct task_struct *task) uint64_t *keys = &(per_cpu(taskname_keys, cpu)[(task->pid & 0xFF) * TASK_MAX_COLLISIONS]); uint64_t value; - value = gator_chksum_crc32(task->comm); + value = gator_chksum_crc32(comm); value = (value << 32) | (uint32_t)task->pid; - // determine if the thread name was emitted already + /* determine if the thread name was emitted already */ for (x = 0; x < TASK_MAX_COLLISIONS; x++) { if (keys[x] == value) { found = true; @@ -71,17 +75,18 @@ static void emit_pid_name(struct task_struct *task) } if (!found) { - // shift values, new value always in front + /* shift values, new value always in front */ uint64_t oldv, newv = value; + for (x = 0; x < TASK_MAX_COLLISIONS; x++) { oldv = keys[x]; keys[x] = newv; newv = oldv; } - // emit pid names, cannot use get_task_comm, as it's not exported on all kernel versions - if (strlcpy(taskcomm, task->comm, TASK_COMM_LEN) == TASK_COMM_LEN - 1) { - // append ellipses if task->comm has length of TASK_COMM_LEN - 1 + /* emit pid names, cannot use get_task_comm, as it's not exported on all kernel versions */ + if (strlcpy(taskcomm, comm, TASK_COMM_LEN) == TASK_COMM_LEN - 1) { + /* append ellipses if comm has length of TASK_COMM_LEN - 1 */ strcat(taskcomm, "..."); } @@ -89,7 +94,7 @@ static void emit_pid_name(struct task_struct *task) } } -static void collect_counters(u64 time, struct task_struct *task) +static void collect_counters(u64 time, struct task_struct *task, bool sched_switch) { int *buffer, len, cpu = get_physical_cpu(); long long *buffer64; @@ -98,7 +103,7 @@ static void collect_counters(u64 time, struct task_struct *task) if (marshal_event_header(time)) { list_for_each_entry(gi, &gator_events, list) { if (gi->read) { - len = gi->read(&buffer); + len = gi->read(&buffer, sched_switch); marshal_event(len, buffer); } else if (gi->read64) { len = gi->read64(&buffer64); @@ -109,22 +114,26 @@ static void collect_counters(u64 time, struct task_struct *task) marshal_event64(len, buffer64); } } - // Only check after writing all counters so that time and corresponding counters appear in the same frame + if (cpu == 0) + gator_emit_perf_time(time); + /* Only check after writing all counters so that time and corresponding counters appear in the same frame */ buffer_check(cpu, BLOCK_COUNTER_BUF, time); - // Commit buffers on timeout + /* Commit buffers on timeout */ if (gator_live_rate > 0 && time >= per_cpu(gator_buffer_commit_time, cpu)) { static const int buftypes[] = { NAME_BUF, COUNTER_BUF, BLOCK_COUNTER_BUF, SCHED_TRACE_BUF, ACTIVITY_BUF }; int i; - for (i = 0; i < ARRAY_SIZE(buftypes); ++i) { + for (i = 0; i < ARRAY_SIZE(buftypes); ++i) gator_commit_buffer(cpu, buftypes[i], time); - } - // spinlocks are noops on uniprocessor machines and mutexes do not work in sched_switch context in - // RT-Preempt full, so disable proactive flushing of the annotate frame on uniprocessor machines. + /* spinlocks are noops on uniprocessor machines and mutexes do + * not work in sched_switch context in RT-Preempt full, so + * disable proactive flushing of the annotate frame on + * uniprocessor machines. + */ #ifdef CONFIG_SMP - // Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full + /* Try to preemptively flush the annotate buffer to reduce the chance of the buffer being full */ if (on_primary_core() && spin_trylock(&annotate_lock)) { gator_commit_buffer(0, ANNOTATE_BUF, time); spin_unlock(&annotate_lock); @@ -134,7 +143,7 @@ static void collect_counters(u64 time, struct task_struct *task) } } -// special case used during a suspend of the system +/* special case used during a suspend of the system */ static void trace_sched_insert_idle(void) { marshal_sched_trace_switch(0, 0); @@ -146,7 +155,7 @@ static void gator_trace_emit_link(struct task_struct *p) int cpu = get_physical_cpu(); cookie = get_exec_cookie(cpu, p); - emit_pid_name(p); + emit_pid_name(p->comm, p); marshal_link(cookie, p->tgid, p->pid); } @@ -161,6 +170,15 @@ GATOR_DEFINE_PROBE(sched_process_exec, TP_PROTO(struct task_struct *p, pid_t old { gator_trace_emit_link(p); } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0) +GATOR_DEFINE_PROBE(task_rename, TP_PROTO(struct task_struct *task, char *comm)) +#else +GATOR_DEFINE_PROBE(task_rename, TP_PROTO(struct task_struct *task, const char *comm)) +#endif +{ + emit_pid_name(comm, task); +} #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) @@ -174,17 +192,16 @@ GATOR_DEFINE_PROBE(sched_switch, TP_PROTO(struct task_struct *prev, struct task_ per_cpu(in_scheduler_context, cpu) = true; - // do as much work as possible before disabling interrupts - if (prev->state == TASK_RUNNING) { + /* do as much work as possible before disabling interrupts */ + if (prev->state == TASK_RUNNING) state = STATE_CONTENTION; - } else if (prev->in_iowait) { + else if (prev->in_iowait) state = STATE_WAIT_ON_IO; - } else { + else state = STATE_WAIT_ON_OTHER; - } per_cpu(collecting, cpu) = 1; - collect_counters(gator_get_time(), prev); + collect_counters(gator_get_time(), prev, true); per_cpu(collecting, cpu) = 0; #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) @@ -202,18 +219,20 @@ GATOR_DEFINE_PROBE(sched_process_free, TP_PROTO(struct task_struct *p)) static void do_nothing(void *info) { - // Intentionally do nothing + /* Intentionally do nothing */ (void)info; } static int register_scheduler_tracepoints(void) { - // register tracepoints + /* register tracepoints */ if (GATOR_REGISTER_TRACE(sched_process_fork)) goto fail_sched_process_fork; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) if (GATOR_REGISTER_TRACE(sched_process_exec)) goto fail_sched_process_exec; + if (GATOR_REGISTER_TRACE(task_rename)) + goto fail_task_rename; #endif if (GATOR_REGISTER_TRACE(sched_switch)) goto fail_sched_switch; @@ -221,21 +240,24 @@ static int register_scheduler_tracepoints(void) goto fail_sched_process_free; pr_debug("gator: registered tracepoints\n"); - // Now that the scheduler tracepoint is registered, force a context switch - // on all cpus to capture what is currently running. + /* Now that the scheduler tracepoint is registered, force a context + * switch on all cpus to capture what is currently running. + */ on_each_cpu(do_nothing, NULL, 0); return 0; - // unregister tracepoints on error + /* unregister tracepoints on error */ fail_sched_process_free: GATOR_UNREGISTER_TRACE(sched_switch); fail_sched_switch: - GATOR_UNREGISTER_TRACE(sched_process_fork); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -fail_sched_process_exec: + GATOR_UNREGISTER_TRACE(task_rename); +fail_task_rename: GATOR_UNREGISTER_TRACE(sched_process_exec); +fail_sched_process_exec: #endif + GATOR_UNREGISTER_TRACE(sched_process_fork); fail_sched_process_fork: pr_err("gator: tracepoints failed to activate, please verify that tracepoints are enabled in the linux kernel\n"); @@ -247,6 +269,7 @@ static void unregister_scheduler_tracepoints(void) GATOR_UNREGISTER_TRACE(sched_process_fork); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) GATOR_UNREGISTER_TRACE(sched_process_exec); + GATOR_UNREGISTER_TRACE(task_rename); #endif GATOR_UNREGISTER_TRACE(sched_switch); GATOR_UNREGISTER_TRACE(sched_process_free); @@ -271,7 +294,7 @@ static int gator_trace_sched_start(void) for_each_present_cpu(cpu) { size = TASK_MAP_ENTRIES * TASK_MAX_COLLISIONS * sizeof(uint64_t); - per_cpu(taskname_keys, cpu) = (uint64_t *)kmalloc(size, GFP_KERNEL); + per_cpu(taskname_keys, cpu) = kmalloc(size, GFP_KERNEL); if (!per_cpu(taskname_keys, cpu)) return -1; memset(per_cpu(taskname_keys, cpu), 0, size); @@ -290,6 +313,7 @@ static void gator_trace_sched_offline(void) static void gator_trace_sched_init(void) { int i; + for (i = 0; i < CPU_WAIT_TOTAL; i++) { cpu_wait_enabled[i] = 0; sched_cpu_key[i] = gator_events_get_key(); diff --git a/drivers/gator/mali/mali_dd_gator_api.h b/drivers/gator/mali/mali_dd_gator_api.h deleted file mode 100644 index 104b34f2d72a..000000000000 --- a/drivers/gator/mali/mali_dd_gator_api.h +++ /dev/null @@ -1,40 +0,0 @@ -#if !defined(MALI_DDK_GATOR_API_VERSION) - #define MALI_DDK_GATOR_API_VERSION 3 -#endif -#if !defined(MALI_TRUE) - #define MALI_TRUE ((unsigned int)1) -#endif - -#if !defined(MALI_FALSE) - #define MALI_FALSE ((unsigned int)0) -#endif - -struct mali_dd_hwcnt_info { - - /* Passed from Gator to kbase */ - //u32 in_mali_dd_hwcnt_version; - unsigned short int bitmask[4]; - - /* Passed from kbase to Gator */ - - /* ptr to counter dump memory */ - void *kernel_dump_buffer; - - /* size of counter dump memory */ - unsigned int size; - - unsigned int gpu_id; - - unsigned int nr_cores; - - unsigned int nr_core_groups; - - /* The cached present bitmaps - these are the same as the corresponding hardware registers*/ - unsigned long int shader_present_bitmap; -}; - -struct mali_dd_hwcnt_handles; -extern struct mali_dd_hwcnt_handles* mali_dd_hwcnt_init(struct mali_dd_hwcnt_info *in_out_info); -extern void mali_dd_hwcnt_clear(struct mali_dd_hwcnt_info *in_out_info, struct mali_dd_hwcnt_handles *opaque_handles); -extern unsigned int kbase_dd_instr_hwcnt_dump_complete(struct mali_dd_hwcnt_handles *opaque_handles, unsigned int * const success); -extern unsigned int kbase_dd_instr_hwcnt_dump_irq(struct mali_dd_hwcnt_handles *opaque_handles); diff --git a/drivers/gator/mali/mali_kbase_gator_api.h b/drivers/gator/mali/mali_kbase_gator_api.h new file mode 100644 index 000000000000..5ed069797e36 --- /dev/null +++ b/drivers/gator/mali/mali_kbase_gator_api.h @@ -0,0 +1,219 @@ +/** + * Copyright (C) ARM Limited 2014. 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. + * + */ + +#ifndef _KBASE_GATOR_API_H_ +#define _KBASE_GATOR_API_H_ + +/** + * @brief This file describes the API used by Gator to collect hardware counters data from a Mali device. + */ + +/* This define is used by the gator kernel module compile to select which DDK + * API calling convention to use. If not defined (legacy DDK) gator assumes + * version 1. The version to DDK release mapping is: + * Version 1 API: DDK versions r1px, r2px + * Version 2 API: DDK versions r3px, r4px + * Version 3 API: DDK version r5p0 and newer + * + * API Usage + * ========= + * + * 1] Call kbase_gator_hwcnt_init_names() to return the list of short counter + * names for the GPU present in this device. + * + * 2] Create a kbase_gator_hwcnt_info structure and set the counter enables for + * the counters you want enabled. The enables can all be set for simplicity in + * most use cases, but disabling some will let you minimize bandwidth impact. + * + * 3] Call kbase_gator_hwcnt_init() using the above structure, to create a + * counter context. On successful return the DDK will have populated the + * structure with a variety of useful information. + * + * 4] Call kbase_gator_hwcnt_dump_irq() to queue a non-blocking request for a + * counter dump. If this returns a non-zero value the request has been queued, + * otherwise the driver has been unable to do so (typically because of another + * user of the instrumentation exists concurrently). + * + * 5] Call kbase_gator_hwcnt_dump_complete() to test whether the previously + * requested dump has been succesful. If this returns non-zero the counter dump + * has resolved, but the value of *success must also be tested as the dump + * may have not been successful. If it returns zero the counter dump was + * abandoned due to the device being busy (typically because of another + * user of the instrumentation exists concurrently). + * + * 6] Process the counters stored in the buffer pointed to by ... + * + * kbase_gator_hwcnt_info->kernel_dump_buffer + * + * In pseudo code you can find all of the counters via this approach: + * + * + * hwcnt_info # pointer to kbase_gator_hwcnt_info structure + * hwcnt_name # pointer to name list + * + * u32 * hwcnt_data = (u32*)hwcnt_info->kernel_dump_buffer + * + * # Iterate over each 64-counter block in this GPU configuration + * for( i = 0; i < hwcnt_info->nr_hwc_blocks; i++) { + * hwc_type type = hwcnt_info->hwc_layout[i]; + * + * # Skip reserved type blocks - they contain no counters at all + * if( type == RESERVED_BLOCK ) { + * continue; + * } + * + * size_t name_offset = type * 64; + * size_t data_offset = i * 64; + * + * # Iterate over the names of the counters in this block type + * for( j = 0; j < 64; j++) { + * const char * name = hwcnt_name[name_offset+j]; + * + * # Skip empty name strings - there is no counter here + * if( name[0] == '\0' ) { + * continue; + * } + * + * u32 data = hwcnt_data[data_offset+j]; + * + * printk( "COUNTER: %s DATA: %u\n", name, data ); + * } + * } + * + * + * Note that in most implementations you typically want to either SUM or + * AVERAGE multiple instances of the same counter if, for example, you have + * multiple shader cores or multiple L2 caches. The most sensible view for + * analysis is to AVERAGE shader core counters, but SUM L2 cache and MMU + * counters. + * + * 7] Goto 4, repeating until you want to stop collecting counters. + * + * 8] Release the dump resources by calling kbase_gator_hwcnt_term(). + * + * 9] Release the name table resources by calling kbase_gator_hwcnt_term_names(). + * This function must only be called if init_names() returned a non-NULL value. + **/ + +#define MALI_DDK_GATOR_API_VERSION 3 + +#if !defined(MALI_TRUE) + #define MALI_TRUE ((uint32_t)1) +#endif + +#if !defined(MALI_FALSE) + #define MALI_FALSE ((uint32_t)0) +#endif + +enum hwc_type { + JM_BLOCK = 0, + TILER_BLOCK, + SHADER_BLOCK, + MMU_L2_BLOCK, + RESERVED_BLOCK +}; + +struct kbase_gator_hwcnt_info { + + /* Passed from Gator to kbase */ + + /* the bitmask of enabled hardware counters for each counter block */ + uint16_t bitmask[4]; + + /* Passed from kbase to Gator */ + + /* ptr to counter dump memory */ + void *kernel_dump_buffer; + + /* size of counter dump memory */ + uint32_t size; + + /* the ID of the Mali device */ + uint32_t gpu_id; + + /* the number of shader cores in the GPU */ + uint32_t nr_cores; + + /* the number of core groups */ + uint32_t nr_core_groups; + + /* the memory layout of the performance counters */ + enum hwc_type *hwc_layout; + + /* the total number of hardware couter blocks */ + uint32_t nr_hwc_blocks; +}; + +/** + * @brief Opaque block of Mali data which Gator needs to return to the API later. + */ +struct kbase_gator_hwcnt_handles; + +/** + * @brief Initialize the resources Gator needs for performance profiling. + * + * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the Mali + * specific information that will be returned to Gator. On entry Gator must have populated the + * 'bitmask' field with the counters it wishes to enable for each class of counter block. + * Each entry in the array corresponds to a single counter class based on the "hwc_type" + * enumeration, and each bit corresponds to an enable for 4 sequential counters (LSB enables + * the first 4 counters in the block, and so on). See the GPU counter array as returned by + * kbase_gator_hwcnt_get_names() for the index values of each counter for the curernt GPU. + * + * @return Pointer to an opaque handle block on success, NULL on error. + */ +extern struct kbase_gator_hwcnt_handles *kbase_gator_hwcnt_init(struct kbase_gator_hwcnt_info *in_out_info); + +/** + * @brief Free all resources once Gator has finished using performance counters. + * + * @param in_out_info A pointer to a structure containing the enabled counters passed from Gator and all the + * Mali specific information that will be returned to Gator. + * @param opaque_handles A wrapper structure for kbase structures. + */ +extern void kbase_gator_hwcnt_term(struct kbase_gator_hwcnt_info *in_out_info, struct kbase_gator_hwcnt_handles *opaque_handles); + +/** + * @brief Poll whether a counter dump is successful. + * + * @param opaque_handles A wrapper structure for kbase structures. + * @param[out] success Non-zero on success, zero on failure. + * + * @return Zero if the dump is still pending, non-zero if the dump has completed. Note that a + * completed dump may not have dumped succesfully, so the caller must test for both + * a completed and successful dump before processing counters. + */ +extern uint32_t kbase_gator_instr_hwcnt_dump_complete(struct kbase_gator_hwcnt_handles *opaque_handles, uint32_t * const success); + +/** + * @brief Request the generation of a new counter dump. + * + * @param opaque_handles A wrapper structure for kbase structures. + * + * @return Zero if the hardware device is busy and cannot handle the request, non-zero otherwise. + */ +extern uint32_t kbase_gator_instr_hwcnt_dump_irq(struct kbase_gator_hwcnt_handles *opaque_handles); + +/** + * @brief This function is used to fetch the names table based on the Mali device in use. + * + * @param[out] total_number_of_counters The total number of counters short names in the Mali devices' list. + * + * @return Pointer to an array of strings of length *total_number_of_counters. + */ +extern const char * const *kbase_gator_hwcnt_init_names(uint32_t *total_number_of_counters); + +/** + * @brief This function is used to terminate the use of the names table. + * + * This function must only be called if the initial call to kbase_gator_hwcnt_init_names returned a non-NULL value. + */ +extern void kbase_gator_hwcnt_term_names(void); + +#endif diff --git a/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h b/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h index ff00d90cee78..2bc0b037eee6 100644 --- a/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h +++ b/drivers/gator/mali/mali_mjollnir_profiling_gator_api.h @@ -23,83 +23,82 @@ extern "C" #define MAX_NUM_VP_CORES (1) #define MAX_NUM_L2_CACHE_CORES (1) -enum counters -{ - /* Timeline activity */ - ACTIVITY_VP_0 = 0, - ACTIVITY_FP_0, - ACTIVITY_FP_1, - ACTIVITY_FP_2, - ACTIVITY_FP_3, - - /* L2 cache counters */ - COUNTER_L2_0_C0, - COUNTER_L2_0_C1, - - /* Vertex processor counters */ - COUNTER_VP_0_C0, - COUNTER_VP_0_C1, - - /* Fragment processor counters */ - COUNTER_FP_0_C0, - COUNTER_FP_0_C1, - COUNTER_FP_1_C0, - COUNTER_FP_1_C1, - COUNTER_FP_2_C0, - COUNTER_FP_2_C1, - COUNTER_FP_3_C0, - COUNTER_FP_3_C1, - - /* EGL Software Counters */ - COUNTER_EGL_BLIT_TIME, - - /* GLES Software Counters */ - COUNTER_GLES_DRAW_ELEMENTS_CALLS, - COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, - COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_ARRAYS_CALLS, - COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_POINTS, - COUNTER_GLES_DRAW_LINES, - COUNTER_GLES_DRAW_LINE_LOOP, - COUNTER_GLES_DRAW_LINE_STRIP, - COUNTER_GLES_DRAW_TRIANGLES, - COUNTER_GLES_DRAW_TRIANGLE_STRIP, - COUNTER_GLES_DRAW_TRIANGLE_FAN, - COUNTER_GLES_NON_VBO_DATA_COPY_TIME, - COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, - COUNTER_GLES_UPLOAD_TEXTURE_TIME, - COUNTER_GLES_UPLOAD_VBO_TIME, - COUNTER_GLES_NUM_FLUSHES, - COUNTER_GLES_NUM_VSHADERS_GENERATED, - COUNTER_GLES_NUM_FSHADERS_GENERATED, - COUNTER_GLES_VSHADER_GEN_TIME, - COUNTER_GLES_FSHADER_GEN_TIME, - COUNTER_GLES_INPUT_TRIANGLES, - COUNTER_GLES_VXCACHE_HIT, - COUNTER_GLES_VXCACHE_MISS, - COUNTER_GLES_VXCACHE_COLLISION, - COUNTER_GLES_CULLED_TRIANGLES, - COUNTER_GLES_CULLED_LINES, - COUNTER_GLES_BACKFACE_TRIANGLES, - COUNTER_GLES_GBCLIP_TRIANGLES, - COUNTER_GLES_GBCLIP_LINES, - COUNTER_GLES_TRIANGLES_DRAWN, - COUNTER_GLES_DRAWCALL_TIME, - COUNTER_GLES_TRIANGLES_COUNT, - COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, - COUNTER_GLES_STRIP_TRIANGLES_COUNT, - COUNTER_GLES_FAN_TRIANGLES_COUNT, - COUNTER_GLES_LINES_COUNT, - COUNTER_GLES_INDEPENDENT_LINES_COUNT, - COUNTER_GLES_STRIP_LINES_COUNT, - COUNTER_GLES_LOOP_LINES_COUNT, - - COUNTER_FILMSTRIP, - COUNTER_FREQUENCY, - COUNTER_VOLTAGE, - - NUMBER_OF_EVENTS +enum counters { + /* Timeline activity */ + ACTIVITY_VP_0 = 0, + ACTIVITY_FP_0, + ACTIVITY_FP_1, + ACTIVITY_FP_2, + ACTIVITY_FP_3, + + /* L2 cache counters */ + COUNTER_L2_0_C0, + COUNTER_L2_0_C1, + + /* Vertex processor counters */ + COUNTER_VP_0_C0, + COUNTER_VP_0_C1, + + /* Fragment processor counters */ + COUNTER_FP_0_C0, + COUNTER_FP_0_C1, + COUNTER_FP_1_C0, + COUNTER_FP_1_C1, + COUNTER_FP_2_C0, + COUNTER_FP_2_C1, + COUNTER_FP_3_C0, + COUNTER_FP_3_C1, + + /* EGL Software Counters */ + COUNTER_EGL_BLIT_TIME, + + /* GLES Software Counters */ + COUNTER_GLES_DRAW_ELEMENTS_CALLS, + COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, + COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_ARRAYS_CALLS, + COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_POINTS, + COUNTER_GLES_DRAW_LINES, + COUNTER_GLES_DRAW_LINE_LOOP, + COUNTER_GLES_DRAW_LINE_STRIP, + COUNTER_GLES_DRAW_TRIANGLES, + COUNTER_GLES_DRAW_TRIANGLE_STRIP, + COUNTER_GLES_DRAW_TRIANGLE_FAN, + COUNTER_GLES_NON_VBO_DATA_COPY_TIME, + COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, + COUNTER_GLES_UPLOAD_TEXTURE_TIME, + COUNTER_GLES_UPLOAD_VBO_TIME, + COUNTER_GLES_NUM_FLUSHES, + COUNTER_GLES_NUM_VSHADERS_GENERATED, + COUNTER_GLES_NUM_FSHADERS_GENERATED, + COUNTER_GLES_VSHADER_GEN_TIME, + COUNTER_GLES_FSHADER_GEN_TIME, + COUNTER_GLES_INPUT_TRIANGLES, + COUNTER_GLES_VXCACHE_HIT, + COUNTER_GLES_VXCACHE_MISS, + COUNTER_GLES_VXCACHE_COLLISION, + COUNTER_GLES_CULLED_TRIANGLES, + COUNTER_GLES_CULLED_LINES, + COUNTER_GLES_BACKFACE_TRIANGLES, + COUNTER_GLES_GBCLIP_TRIANGLES, + COUNTER_GLES_GBCLIP_LINES, + COUNTER_GLES_TRIANGLES_DRAWN, + COUNTER_GLES_DRAWCALL_TIME, + COUNTER_GLES_TRIANGLES_COUNT, + COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, + COUNTER_GLES_STRIP_TRIANGLES_COUNT, + COUNTER_GLES_FAN_TRIANGLES_COUNT, + COUNTER_GLES_LINES_COUNT, + COUNTER_GLES_INDEPENDENT_LINES_COUNT, + COUNTER_GLES_STRIP_LINES_COUNT, + COUNTER_GLES_LOOP_LINES_COUNT, + + COUNTER_FILMSTRIP, + COUNTER_FREQUENCY, + COUNTER_VOLTAGE, + + NUMBER_OF_EVENTS }; #define FIRST_ACTIVITY_EVENT ACTIVITY_VP_0 @@ -117,34 +116,31 @@ enum counters /** * Structure to pass performance counter data of a Mali core */ -typedef struct _mali_profiling_core_counters -{ - u32 source0; - u32 value0; - u32 source1; - u32 value1; -} _mali_profiling_core_counters; +struct _mali_profiling_core_counters { + u32 source0; + u32 value0; + u32 source1; + u32 value1; +}; /* * For compatibility with utgard. */ -typedef struct _mali_profiling_l2_counter_values -{ - struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES]; -} _mali_profiling_l2_counter_values; +struct _mali_profiling_l2_counter_values { + struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES]; +}; -typedef struct _mali_profiling_mali_version -{ - u32 mali_product_id; - u32 mali_version_major; - u32 mali_version_minor; - u32 num_of_l2_cores; - u32 num_of_fp_cores; - u32 num_of_vp_cores; -} _mali_profiling_mali_version; +struct _mali_profiling_mali_version { + u32 mali_product_id; + u32 mali_version_major; + u32 mali_version_minor; + u32 num_of_l2_cores; + u32 num_of_fp_cores; + u32 num_of_vp_cores; +}; extern void _mali_profiling_get_mali_version(struct _mali_profiling_mali_version *values); -extern u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values); +extern u32 _mali_profiling_get_l2_counters(struct _mali_profiling_l2_counter_values *values); /* * List of possible actions allowing DDK to be controlled by Streamline. diff --git a/drivers/gator/mali/mali_utgard_profiling_gator_api.h b/drivers/gator/mali/mali_utgard_profiling_gator_api.h index 43c576042880..d6465312628e 100644 --- a/drivers/gator/mali/mali_utgard_profiling_gator_api.h +++ b/drivers/gator/mali/mali_utgard_profiling_gator_api.h @@ -22,105 +22,104 @@ extern "C" #define MAX_NUM_VP_CORES 1 /** The list of events supported by the Mali DDK. */ -typedef enum -{ - /* Vertex processor activity */ - ACTIVITY_VP_0 = 0, - - /* Fragment processor activity */ - ACTIVITY_FP_0, /* 1 */ - ACTIVITY_FP_1, - ACTIVITY_FP_2, - ACTIVITY_FP_3, - ACTIVITY_FP_4, - ACTIVITY_FP_5, - ACTIVITY_FP_6, - ACTIVITY_FP_7, - - /* L2 cache counters */ - COUNTER_L2_0_C0, - COUNTER_L2_0_C1, - COUNTER_L2_1_C0, - COUNTER_L2_1_C1, - COUNTER_L2_2_C0, - COUNTER_L2_2_C1, - - /* Vertex processor counters */ - COUNTER_VP_0_C0, /*15*/ - COUNTER_VP_0_C1, - - /* Fragment processor counters */ - COUNTER_FP_0_C0, - COUNTER_FP_0_C1, - COUNTER_FP_1_C0, - COUNTER_FP_1_C1, - COUNTER_FP_2_C0, - COUNTER_FP_2_C1, - COUNTER_FP_3_C0, - COUNTER_FP_3_C1, - COUNTER_FP_4_C0, - COUNTER_FP_4_C1, - COUNTER_FP_5_C0, - COUNTER_FP_5_C1, - COUNTER_FP_6_C0, - COUNTER_FP_6_C1, - COUNTER_FP_7_C0, - COUNTER_FP_7_C1, /* 32 */ - - /* - * If more hardware counters are added, the _mali_osk_hw_counter_table - * below should also be updated. - */ - - /* EGL software counters */ - COUNTER_EGL_BLIT_TIME, - - /* GLES software counters */ - COUNTER_GLES_DRAW_ELEMENTS_CALLS, - COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, - COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_ARRAYS_CALLS, - COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, - COUNTER_GLES_DRAW_POINTS, - COUNTER_GLES_DRAW_LINES, - COUNTER_GLES_DRAW_LINE_LOOP, - COUNTER_GLES_DRAW_LINE_STRIP, - COUNTER_GLES_DRAW_TRIANGLES, - COUNTER_GLES_DRAW_TRIANGLE_STRIP, - COUNTER_GLES_DRAW_TRIANGLE_FAN, - COUNTER_GLES_NON_VBO_DATA_COPY_TIME, - COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, - COUNTER_GLES_UPLOAD_TEXTURE_TIME, - COUNTER_GLES_UPLOAD_VBO_TIME, - COUNTER_GLES_NUM_FLUSHES, - COUNTER_GLES_NUM_VSHADERS_GENERATED, - COUNTER_GLES_NUM_FSHADERS_GENERATED, - COUNTER_GLES_VSHADER_GEN_TIME, - COUNTER_GLES_FSHADER_GEN_TIME, - COUNTER_GLES_INPUT_TRIANGLES, - COUNTER_GLES_VXCACHE_HIT, - COUNTER_GLES_VXCACHE_MISS, - COUNTER_GLES_VXCACHE_COLLISION, - COUNTER_GLES_CULLED_TRIANGLES, - COUNTER_GLES_CULLED_LINES, - COUNTER_GLES_BACKFACE_TRIANGLES, - COUNTER_GLES_GBCLIP_TRIANGLES, - COUNTER_GLES_GBCLIP_LINES, - COUNTER_GLES_TRIANGLES_DRAWN, - COUNTER_GLES_DRAWCALL_TIME, - COUNTER_GLES_TRIANGLES_COUNT, - COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, - COUNTER_GLES_STRIP_TRIANGLES_COUNT, - COUNTER_GLES_FAN_TRIANGLES_COUNT, - COUNTER_GLES_LINES_COUNT, - COUNTER_GLES_INDEPENDENT_LINES_COUNT, - COUNTER_GLES_STRIP_LINES_COUNT, - COUNTER_GLES_LOOP_LINES_COUNT, - - /* Framebuffer capture pseudo-counter */ - COUNTER_FILMSTRIP, - - NUMBER_OF_EVENTS +enum { + /* Vertex processor activity */ + ACTIVITY_VP_0 = 0, + + /* Fragment processor activity */ + ACTIVITY_FP_0, /* 1 */ + ACTIVITY_FP_1, + ACTIVITY_FP_2, + ACTIVITY_FP_3, + ACTIVITY_FP_4, + ACTIVITY_FP_5, + ACTIVITY_FP_6, + ACTIVITY_FP_7, + + /* L2 cache counters */ + COUNTER_L2_0_C0, + COUNTER_L2_0_C1, + COUNTER_L2_1_C0, + COUNTER_L2_1_C1, + COUNTER_L2_2_C0, + COUNTER_L2_2_C1, + + /* Vertex processor counters */ + COUNTER_VP_0_C0, /*15*/ + COUNTER_VP_0_C1, + + /* Fragment processor counters */ + COUNTER_FP_0_C0, + COUNTER_FP_0_C1, + COUNTER_FP_1_C0, + COUNTER_FP_1_C1, + COUNTER_FP_2_C0, + COUNTER_FP_2_C1, + COUNTER_FP_3_C0, + COUNTER_FP_3_C1, + COUNTER_FP_4_C0, + COUNTER_FP_4_C1, + COUNTER_FP_5_C0, + COUNTER_FP_5_C1, + COUNTER_FP_6_C0, + COUNTER_FP_6_C1, + COUNTER_FP_7_C0, + COUNTER_FP_7_C1, /* 32 */ + + /* + * If more hardware counters are added, the _mali_osk_hw_counter_table + * below should also be updated. + */ + + /* EGL software counters */ + COUNTER_EGL_BLIT_TIME, + + /* GLES software counters */ + COUNTER_GLES_DRAW_ELEMENTS_CALLS, + COUNTER_GLES_DRAW_ELEMENTS_NUM_INDICES, + COUNTER_GLES_DRAW_ELEMENTS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_ARRAYS_CALLS, + COUNTER_GLES_DRAW_ARRAYS_NUM_TRANSFORMED, + COUNTER_GLES_DRAW_POINTS, + COUNTER_GLES_DRAW_LINES, + COUNTER_GLES_DRAW_LINE_LOOP, + COUNTER_GLES_DRAW_LINE_STRIP, + COUNTER_GLES_DRAW_TRIANGLES, + COUNTER_GLES_DRAW_TRIANGLE_STRIP, + COUNTER_GLES_DRAW_TRIANGLE_FAN, + COUNTER_GLES_NON_VBO_DATA_COPY_TIME, + COUNTER_GLES_UNIFORM_BYTES_COPIED_TO_MALI, + COUNTER_GLES_UPLOAD_TEXTURE_TIME, + COUNTER_GLES_UPLOAD_VBO_TIME, + COUNTER_GLES_NUM_FLUSHES, + COUNTER_GLES_NUM_VSHADERS_GENERATED, + COUNTER_GLES_NUM_FSHADERS_GENERATED, + COUNTER_GLES_VSHADER_GEN_TIME, + COUNTER_GLES_FSHADER_GEN_TIME, + COUNTER_GLES_INPUT_TRIANGLES, + COUNTER_GLES_VXCACHE_HIT, + COUNTER_GLES_VXCACHE_MISS, + COUNTER_GLES_VXCACHE_COLLISION, + COUNTER_GLES_CULLED_TRIANGLES, + COUNTER_GLES_CULLED_LINES, + COUNTER_GLES_BACKFACE_TRIANGLES, + COUNTER_GLES_GBCLIP_TRIANGLES, + COUNTER_GLES_GBCLIP_LINES, + COUNTER_GLES_TRIANGLES_DRAWN, + COUNTER_GLES_DRAWCALL_TIME, + COUNTER_GLES_TRIANGLES_COUNT, + COUNTER_GLES_INDEPENDENT_TRIANGLES_COUNT, + COUNTER_GLES_STRIP_TRIANGLES_COUNT, + COUNTER_GLES_FAN_TRIANGLES_COUNT, + COUNTER_GLES_LINES_COUNT, + COUNTER_GLES_INDEPENDENT_LINES_COUNT, + COUNTER_GLES_STRIP_LINES_COUNT, + COUNTER_GLES_LOOP_LINES_COUNT, + + /* Framebuffer capture pseudo-counter */ + COUNTER_FILMSTRIP, + + NUMBER_OF_EVENTS } _mali_osk_counter_id; #define FIRST_ACTIVITY_EVENT ACTIVITY_VP_0 @@ -138,21 +137,19 @@ typedef enum /** * Structure to pass performance counter data of a Mali core */ -typedef struct _mali_profiling_core_counters -{ +struct _mali_profiling_core_counters { u32 source0; u32 value0; u32 source1; u32 value1; -} _mali_profiling_core_counters; +}; /** * Structure to pass performance counter data of Mali L2 cache cores */ -typedef struct _mali_profiling_l2_counter_values -{ +struct _mali_profiling_l2_counter_values { struct _mali_profiling_core_counters cores[MAX_NUM_L2_CACHE_CORES]; -} _mali_profiling_l2_counter_values; +}; /** * Structure to pass data defining Mali instance in use: @@ -164,15 +161,14 @@ typedef struct _mali_profiling_l2_counter_values * num_of_fp_cores - number of fragment processor cores * num_of_vp_cores - number of vertex processor cores */ -typedef struct _mali_profiling_mali_version -{ +struct _mali_profiling_mali_version { u32 mali_product_id; u32 mali_version_major; u32 mali_version_minor; u32 num_of_l2_cores; u32 num_of_fp_cores; u32 num_of_vp_cores; -} _mali_profiling_mali_version; +}; /* * List of possible actions to be controlled by Streamline. @@ -186,7 +182,7 @@ typedef struct _mali_profiling_mali_version void _mali_profiling_control(u32 action, u32 value); -u32 _mali_profiling_get_l2_counters(_mali_profiling_l2_counter_values *values); +u32 _mali_profiling_get_l2_counters(struct _mali_profiling_l2_counter_values *values); int _mali_profiling_set_event(u32 counter_id, s32 event_id); diff --git a/drivers/gator/mali_midgard.mk b/drivers/gator/mali_midgard.mk new file mode 100644 index 000000000000..1b784d5c3d58 --- /dev/null +++ b/drivers/gator/mali_midgard.mk @@ -0,0 +1,39 @@ +# Defines for Mali-Midgard driver +EXTRA_CFLAGS += -DMALI_USE_UMP=1 \ + -DMALI_LICENSE_IS_GPL=1 \ + -DMALI_BASE_TRACK_MEMLEAK=0 \ + -DMALI_DEBUG=0 \ + -DMALI_ERROR_INJECT_ON=0 \ + -DMALI_CUSTOMER_RELEASE=1 \ + -DMALI_UNIT_TEST=0 \ + -DMALI_BACKEND_KERNEL=1 \ + -DMALI_NO_MALI=0 + +DDK_DIR ?= . +ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/t6xx),) +KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase +OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase/osk +endif + +ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard),) +KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/midgard +OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/midgard/osk +EXTRA_CFLAGS += -DMALI_DIR_MIDGARD=1 +endif + +ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard/mali_kbase_gator_api.h),) +EXTRA_CFLAGS += -DMALI_SIMPLE_API=1 +endif + +UMP_DIR = $(DDK_DIR)/include/linux + +# Include directories in the DDK +EXTRA_CFLAGS += -I$(KBASE_DIR)/ \ + -I$(KBASE_DIR)/.. \ + -I$(OSK_DIR)/.. \ + -I$(UMP_DIR)/.. \ + -I$(DDK_DIR)/include \ + -I$(KBASE_DIR)/osk/src/linux/include \ + -I$(KBASE_DIR)/platform_dummy \ + -I$(KBASE_DIR)/src + diff --git a/drivers/gator/mali_t6xx.mk b/drivers/gator/mali_t6xx.mk deleted file mode 100644 index fa7571ded17b..000000000000 --- a/drivers/gator/mali_t6xx.mk +++ /dev/null @@ -1,39 +0,0 @@ -# Defines for Mali-T6xx driver -EXTRA_CFLAGS += -DMALI_USE_UMP=1 \ - -DMALI_LICENSE_IS_GPL=1 \ - -DMALI_BASE_TRACK_MEMLEAK=0 \ - -DMALI_DEBUG=0 \ - -DMALI_ERROR_INJECT_ON=0 \ - -DMALI_CUSTOMER_RELEASE=1 \ - -DMALI_UNIT_TEST=0 \ - -DMALI_BACKEND_KERNEL=1 \ - -DMALI_NO_MALI=0 - -DDK_DIR ?= . -ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/t6xx),) -KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase -OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/t6xx/kbase/osk -endif - -ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard),) -KBASE_DIR = $(DDK_DIR)/drivers/gpu/arm/midgard -OSK_DIR = $(DDK_DIR)/drivers/gpu/arm/midgard/osk -EXTRA_CFLAGS += -DMALI_DIR_MIDGARD=1 -endif - -ifneq ($(wildcard $(DDK_DIR)/drivers/gpu/arm/midgard/mali_dd_gator_api.h),) -EXTRA_CFLAGS += -DMALI_SIMPLE_API=1 -endif - -UMP_DIR = $(DDK_DIR)/include/linux - -# Include directories in the DDK -EXTRA_CFLAGS += -I$(KBASE_DIR)/ \ - -I$(KBASE_DIR)/.. \ - -I$(OSK_DIR)/.. \ - -I$(UMP_DIR)/.. \ - -I$(DDK_DIR)/include \ - -I$(KBASE_DIR)/osk/src/linux/include \ - -I$(KBASE_DIR)/platform_dummy \ - -I$(KBASE_DIR)/src - -- cgit v1.2.3 From d912ad02f8c0d0b9b56f043292a66476beaf0167 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Thu, 10 May 2012 17:35:03 +0100 Subject: gator: Add config for building the module in-tree Signed-off-by: Jon Medhurst Signed-off-by: Mark Brown Conflicts: drivers/Kconfig drivers/Makefile --- drivers/Kconfig | 2 ++ drivers/Makefile | 2 ++ drivers/gator/Kconfig | 1 - 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index b3138fbb46a4..c1e4021f4362 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -170,4 +170,6 @@ source "drivers/phy/Kconfig" source "drivers/powercap/Kconfig" +source "drivers/gator/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 8e3b8b06c0b2..7edd884f2b5a 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -155,3 +155,5 @@ obj-$(CONFIG_IPACK_BUS) += ipack/ obj-$(CONFIG_NTB) += ntb/ obj-$(CONFIG_FMC) += fmc/ obj-$(CONFIG_POWERCAP) += powercap/ + +obj-$(CONFIG_GATOR) += gator/ diff --git a/drivers/gator/Kconfig b/drivers/gator/Kconfig index b2358bbc1293..a9503a9a4e9f 100644 --- a/drivers/gator/Kconfig +++ b/drivers/gator/Kconfig @@ -3,7 +3,6 @@ config GATOR default m if (ARM || ARM64) depends on PROFILING depends on HIGH_RES_TIMERS - depends on LOCAL_TIMERS || !(ARM && SMP) depends on PERF_EVENTS depends on HW_PERF_EVENTS || !(ARM || ARM64) select TRACING -- cgit v1.2.3