/*------------------------------------------------------------------------------------------*\ * * Copyright (C) 2006 AVM GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \*------------------------------------------------------------------------------------------*/ #ifndef _avm_profile_h_ #define _avm_profile_h_ #define AVM_PROFILING_VERSION 3 #ifndef CONFIG_AVM_PROFILING_TRACE_MODE #define CONFIG_AVM_PROFILING_TRACE_MODE 50 #endif /*--- #ifndef CONFIG_AVM_PROFILING_TRACE_MODE ---*/ #define AVM_PROFILE_ACTIVITY_INCLUDED #define AVM_PROFILE_PAGE_FAULT_ID ((0x1 << 16) -2) #define AVM_PROFILE_IDLE_ID ((0x1 << 16) -1) enum _avm_profile_data_type { avm_profile_data_type_code_address_info = 0, avm_profile_data_type_trace_skb = 1, avm_profile_data_type_hw_irq_begin = 2, avm_profile_data_type_hw_irq_end = 3, avm_profile_data_type_sw_irq_begin = 4, avm_profile_data_type_sw_irq_end = 5, avm_profile_data_type_timer_begin = 6, avm_profile_data_type_timer_end = 7, avm_profile_data_type_tasklet_begin = 8, avm_profile_data_type_tasklet_end = 9, avm_profile_data_type_hi_tasklet_begin = 10, avm_profile_data_type_hi_tasklet_end = 11, avm_profile_data_type_workitem_begin = 12, avm_profile_data_type_workitem_end = 13, avm_profile_data_type_func_begin = 14, avm_profile_data_type_func_end = 15, avm_profile_data_type_trigger_tasklet_begin = 16, avm_profile_data_type_trigger_tasklet_end = 17, avm_profile_data_type_trigger_user_begin = 18, avm_profile_data_type_trigger_user_end = 19, avm_profile_data_type_code_address_yield = 20, avm_profile_data_type_unknown }; struct _avm_profile_data { enum _avm_profile_data_type type : 8; unsigned int cpu_id : 8; unsigned int id : 16; unsigned int addr; unsigned int time; #if defined(AVM_PROFILE_ACTIVITY_INCLUDED) unsigned int total_access; unsigned int total_activate; #endif/*--- #if defined(AVM_PROFILE_ACTIVITY_INCLUDED) ---*/ } __attribute__((packed)); #if defined(CONFIG_AVM_SIMPLE_PROFILING) #include #include #if defined(CONFIG_ARCH_PUMA5) || defined(CONFIG_MACH_PUMA6) #include static inline unsigned int avm_profile_counter(void) { return read_p15_cycle_counter() << 5; /*--- / 64 * 32 = takt / 2 -> wie get_cycle() auf dem MIPS ---*/ } static inline unsigned int avm_profile_sdramacess(void) { return read_p15_performance_counter_0(); } static inline unsigned int avm_profile_sdramactivate(void) { return read_p15_performance_counter_1(); } static inline void avm_profile_counter_init(void) { union __performance_monitor_control C; write_secure_debug_enable_register(0, 1); C.Register = read_p15_performance_monitor_control(); C.Bits.CycleCounterDivider = 1; /*--- / 64 * 32 = takt / 2 -> wie get_cycle() auf dem MIPS ---*/ C.Bits.EvtCount0 = 0xB; /*--- Data cache miss ---*/ C.Bits.EvtCount1 = 0x0; /*--- Instruction cache miss ---*/ C.Bits.EnableCounters = 1; write_p15_performance_monitor_control(C.Register); } static inline void avm_profile_counter_exit(void) { #if 0 union __performance_monitor_control C; C.Register = read_p15_performance_monitor_control(); C.Bits.EvtCount0 = 0xB; /*--- Data cache miss ---*/ C.Bits.EvtCount1 = 0x0; /*--- Instuction cache miss ---*/ write_p15_performance_monitor_control(C.Register); #endif } #include #endif #if defined(CONFIG_MIPS) #define avm_profile_counter() read_c0_count() /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ #if defined(CONFIG_MIPS_FUSIV) || defined(CONFIG_LANTIQ) || defined(CONFIG_MACH_ATHEROS) || defined(CONFIG_ATH79) #include static inline void avm_profile_counter_init(void) { } static inline void avm_profile_counter_exit(void) { } static inline unsigned int avm_profile_sdramacess(void) { return read_c0_perfcntr0(); } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline unsigned int avm_profile_sdramactivate(void) { return read_c0_perfcntr1(); } #endif /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if defined(CONFIG_MIPS_UR8) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) #include #include #else #include #include #endif static inline void avm_profile_counter_init(void) { } static inline void avm_profile_counter_exit(void) { } static inline unsigned int avm_profile_sdramacess(void) { struct EMIF_register_memory_map *UR8_EMIF_register_memory_map = (struct EMIF_register_memory_map *)UR8_EMIF_BASE; return UR8_EMIF_register_memory_map->TotalAccesses; } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline unsigned int avm_profile_sdramactivate(void) { struct EMIF_register_memory_map *UR8_EMIF_register_memory_map = (struct EMIF_register_memory_map *)UR8_EMIF_BASE; return UR8_EMIF_register_memory_map->TotalActivate; } #endif #endif /*--- #if defined(CONFIG_MIPS) ---*/ #define profile_DataSetsPerBlock ((1 << PAGE_SHIFT) / sizeof(struct _avm_profile_data)) extern unsigned int profile_BlockNeeded; #if defined(AVM_PROFILING_VERSION) struct _simple_profiling { void **data; volatile unsigned int pos; unsigned int len; unsigned int enabled; unsigned int mask; unsigned long start_time; unsigned long end_time; unsigned int wraparround; atomic_t busy; #ifdef CONFIG_AVM_SIMPLE_PROFILING_YIELD #define NO_YIELD_HANDLER -1 int yield_handler; void *yield_ref; int yield_signal; int yield_timer_no; #endif spinlock_t lock; }; #endif/*--- #if defined(AVM_PROFILING_VERSION) ---*/ extern struct _simple_profiling simple_profiling; #define avm_simple_profiling_is_enabled() unlikely(simple_profiling.enabled) extern void __avm_simple_profiling_skb(unsigned int addr, unsigned int where, struct sk_buff *skb); /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline void avm_simple_profiling_skb(unsigned int addr, unsigned int where, struct sk_buff *skb){ if(avm_simple_profiling_is_enabled()) { __avm_simple_profiling_skb(addr, where, skb); } } extern void __avm_simple_profiling_log(enum _avm_profile_data_type type, unsigned int addr, unsigned int id); /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline void avm_simple_profiling_log(enum _avm_profile_data_type type, unsigned int addr, unsigned int id){ if(avm_simple_profiling_is_enabled()) { __avm_simple_profiling_log(type, addr, id); } } extern unsigned int __avm_simple_profiling_irqcontext(unsigned int epc); /*--------------------------------------------------------------------------------*\ * switch to irq-context * addr = interrupted epc \*--------------------------------------------------------------------------------*/ static inline unsigned int avm_simple_profiling_enter_irqcontext(unsigned int epc){ if(avm_simple_profiling_is_enabled()) { return __avm_simple_profiling_irqcontext(epc); } return 0; } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline void avm_simple_profiling_schedule(void){ if(avm_simple_profiling_is_enabled()) { __avm_simple_profiling_log(avm_profile_data_type_code_address_info, 0, 0); } } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline void avm_simple_profiling_enter_idle(unsigned int addr){ if(avm_simple_profiling_is_enabled()) { __avm_simple_profiling_log(avm_profile_data_type_code_address_info, addr, AVM_PROFILE_IDLE_ID); } } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ static inline void avm_simple_profiling_unset_busy(void) { atomic_set(&simple_profiling.busy, 0); } /*--------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------*/ int avm_simple_profiling_enable(unsigned int on, unsigned int mask, unsigned int *count, unsigned long *timediff, unsigned int set_busy); void avm_simple_profiling_memresize(unsigned int BlockNeeded); struct _avm_profile_data *avm_simple_profiling_by_idx(unsigned int idx); void avm_simple_profiling_restart(void); #ifdef CONFIG_AVM_SIMPLE_PROFILING_YIELD_PCNT extern unsigned int ack_irqs_reload_counter(void); extern unsigned int read_c0_perfcnt(unsigned int count_reg, unsigned int tc); #endif #define avm_simple_profiling_disable() simple_profiling.enabled = 0, avm_profile_counter_exit() #else /*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/ #define avm_simple_profiling_enter_irqcontext(epc) 0 #define avm_simple_profiling_log(addr, id) #define avm_simple_profiling(regs) #define avm_simple_profiling_enable(on, count, timediff, setbusy) #define avm_simple_profiling_is_enabled() 0 #define avm_simple_profiling_disable() #endif /*--- #else ---*/ /*--- #if defined(CONFIG_AVM_SIMPLE_PROFILING) ---*/ #endif /*--- #ifndef _avm_profile_h_ ---*/