/*------------------------------------------------------------------------------------------*\ * * 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 \*------------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------------*\ * In dieser Datei werden die moeglichen Blinkmodi definiert bzw. erzeugt. * \*------------------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) #include #endif #include #include "avm_sammel.h" #include "avm_led.h" /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) #include #else #endif /*------------------------------------------------------------------------------------------*\ * avm_led_profile.c \*------------------------------------------------------------------------------------------*/ int avm_led_profile_init(unsigned int table_index, struct _avm_virt_led *V) { switch(table_index) { case 0: /* off */ printk("[avm_led] profile_init: disable\n"); return 1; case 1: /* on */ printk("[avm_led] profile_init: enable\n"); return 2; case 2: /* write CSV File */ printk("[avm_led] profile_init: write CSV file\n"); return 3; case 3: /* write ASCII File */ printk("[avm_led] profile_init: write ASCII file\n"); return 4; case 4: /* display ASCII*/ printk("[avm_led] profile_init: display ASCII\n"); return 4; default: printk("[avm_led] profile_init: other %u\n", table_index); return 33; } } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_led_profile_exit(int handle) { return; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_led_profile_stop(int handle) { return; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_led_profile_timer(unsigned long handle) { return; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ char *avm_profile_data_short_names[] = { "FREE", /*--- avm_profile_data_type_free, ---*/ "TEXT", /*--- avm_profile_data_type_text, ---*/ "CODE", /*--- avm_profile_data_type_code_address_info, ---*/ "DATA", /*--- avm_profile_data_type_data_address_info, ---*/ "SKB", /*--- avm_profile_data_type_trace_skb, ---*/ "BIRQ", /*--- avm_profile_data_type_hw_irq_begin, ---*/ "EIRQ", /*--- avm_profile_data_type_hw_irq_end, ---*/ "BSWI", /*--- avm_profile_data_type_sw_irq_begin, ---*/ "ESWI", /*--- avm_profile_data_type_sw_irq_end, ---*/ "BTIM", /*--- avm_profile_data_type_timer_begin, ---*/ "ETIM", /*--- avm_profile_data_type_timer_end, ---*/ "BLET", /*--- avm_profile_data_type_tasklet_begin, ---*/ "ELET", /*--- avm_profile_data_type_tasklet_end, ---*/ "BWRK", /*--- avm_profile_data_type_workitem_begin, ---*/ "EWRK", /*--- avm_profile_data_type_workitem_end, ---*/ "ERROR", /*--- avm_profile_data_type_unknown ---*/ NULL }; char *avm_profile_data_long_names[] = { "free", /*--- avm_profile_data_type_free, ---*/ "text", /*--- avm_profile_data_type_text, ---*/ "code", /*--- avm_profile_data_type_code_address_info, ---*/ "data", /*--- avm_profile_data_type_data_address_info, ---*/ "skb", /*--- avm_profile_data_type_trace_skb, ---*/ "begin hw irq", /*--- avm_profile_data_type_hw_irq_begin, ---*/ "end hw irq", /*--- avm_profile_data_type_hw_irq_end, ---*/ "begin sw irq", /*--- avm_profile_data_type_sw_irq_begin, ---*/ "end sw irq", /*--- avm_profile_data_type_sw_irq_end, ---*/ "begin timer", /*--- avm_profile_data_type_timer_begin, ---*/ "end timer", /*--- avm_profile_data_type_timer_end, ---*/ "begin tasklet", /*--- avm_profile_data_type_tasklet_begin, ---*/ "end tasklet", /*--- avm_profile_data_type_tasklet_end, ---*/ "begin workitem", /*--- avm_profile_data_type_workitem_begin, ---*/ "end workitem", /*--- avm_profile_data_type_workitem_end, ---*/ "unknown", /*--- avm_profile_data_type_unknown ---*/ NULL }; /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_led_profile_action(int handle, unsigned int param1, unsigned int param2) { extern struct _avm_profile_data *avm_simple_profiling_enable(unsigned int on, unsigned int *count); unsigned int len, i; struct _avm_profile_data *data; static unsigned char Buffer[512], Symbols[256]; static struct file *fp; mm_segment_t oldfs; size_t bytesWritten; /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ int open_output_file(char *name) { fp = filp_open(name, O_WRONLY | O_CREAT, 0666); if(IS_ERR(fp)) { printk(KERN_ERR "[avm_led] Failed: Could not open \"/var/profile.log\"\n"); return; } /* Lesezugriff auf File(system) erlaubt? */ if (fp->f_op->write == NULL) { printk(KERN_ERR "[avm_led] Failed: Could not write \"/var/profile.log\"\n"); return; } /* Von Anfang an lesen */ fp->f_pos = 0; } void close_output_file(void) { filp_close(fp, NULL); } printk("[avm_led_profile_action] handle %u\n", handle); /*--------------------------------------------------------------------------------------*\ \*--------------------------------------------------------------------------------------*/ switch(handle) { default: break; case 1: /* disable */ data = avm_simple_profiling_enable(0, &len); printk("[avm_led] profile_action: disable, %u entries recorded (output: 2: CSV, 3: ASCII)\n", len); return; case 2: /* enable */ data = avm_simple_profiling_enable(1, &len); printk("[avm_led] profile_action: enable\n"); return; case 3: /* write CSV file */ data = avm_simple_profiling_enable(0, &len); printk("[avm_led] profile_action: %u entries recorded, write CSV file\n", len); open_output_file("/var/profile.csv"); goto write_file; return; case 4: /* write ASCII file */ data = avm_simple_profiling_enable(0, &len); printk("[avm_led] profile_action: %u entries recorded, write ASCII file\n", len); open_output_file("/var/profile.txt"); write_file: for(i = 0 ; i < len ; i++) { unsigned int _addr; unsigned int len; char *_text; char *description; switch(data[i].type) { case avm_profile_data_type_free: case avm_profile_data_type_unknown: default: printk("x"); break; case avm_profile_data_type_code_address_info: __sprint_symbol(Symbols, data[i].addr); switch(handle) { case 3: sprintf(Buffer, "0x%08X;CODE;0x%08x;%s;%.*s;%u\n", data[i].time, data[i].addr, Symbols, TASK_COMM_LEN, data[i].curr->comm, data[i].id); printk("c"); break; case 4: sprintf(Buffer, "0x%08X: CODE 0x%08x %s (%.*s interrupted by irq %u)\n", data[i].time, data[i].addr, Symbols, TASK_COMM_LEN, data[i].curr->comm, data[i].id); printk("c"); break; case 5: printk("0x%08X: CODE 0x%08x %s (%.*s interrupted by irq %u)\n", data[i].time, data[i].addr, Symbols, TASK_COMM_LEN, data[i].curr->comm, data[i].id); break; } break; case avm_profile_data_type_data_address_info: __sprint_symbol(Symbols, data[i].addr); switch(handle) { case 3: sprintf(Buffer, "0x%08X;DATA;0x%08x;%s;%.*s;%u\n", data[i].time, data[i].addr, Symbols, TASK_COMM_LEN, data[i].curr->comm, data[i].id); printk("d"); break; case 4: sprintf(Buffer, "0x%08X: DATA 0x%08x %s (%.*s interrupted by irq %u)\n", data[i].time, data[i].addr, Symbols, TASK_COMM_LEN, data[i].curr->comm, data[i].id); printk("d"); break; case 5: printk("0x%08X: DATA 0x%08x %s (%.*s interrupted by irq %u)\n", data[i].time, data[i].addr, Symbols, TASK_COMM_LEN, data[i].curr->comm, data[i].id); break; } break; case avm_profile_data_type_trace_skb: printk("s"); break; case avm_profile_data_type_text: printk("t"); break; case avm_profile_data_type_hw_irq_begin: case avm_profile_data_type_hw_irq_end: description = "interrupted by irq"; goto print_work_trace; case avm_profile_data_type_sw_irq_begin: case avm_profile_data_type_sw_irq_end: description = "id:"; goto print_work_trace; case avm_profile_data_type_timer_begin: case avm_profile_data_type_timer_end: description = "id:"; goto print_work_trace; case avm_profile_data_type_tasklet_begin: case avm_profile_data_type_tasklet_end: description = "id:"; goto print_work_trace; case avm_profile_data_type_workitem_begin: case avm_profile_data_type_workitem_end: description = "id:"; goto print_work_trace; print_work_trace: __sprint_symbol(Symbols, data[i].addr); switch(handle) { case 3: sprintf(Buffer, "0x%08X;%s;0x%08x;%s;%.*s;%u\n", data[i].time, avm_profile_data_short_names[data[i].type], data[i].addr, Symbols, TASK_COMM_LEN, data[i].curr->comm, data[i].id); printk("d"); break; case 4: sprintf(Buffer, "0x%08X: %s 0x%08x %s (%.*s %s %u)\n", data[i].time, avm_profile_data_short_names[data[i].type], data[i].addr, Symbols, TASK_COMM_LEN, data[i].curr->comm, description, data[i].id); printk("d"); break; case 5: printk("0x%08X: %s 0x%08x %s (%.*s %s %u)\n", data[i].time, avm_profile_data_long_names[data[i].type], data[i].addr, Symbols, TASK_COMM_LEN, data[i].curr->comm, description, data[i].id); break; } } if(handle != 5) { len = strlen(Buffer); oldfs = get_fs(); set_fs(KERNEL_DS); bytesWritten = fp->f_op->write(fp, Buffer, len, &fp->f_pos); if(bytesWritten != len) { printk(KERN_ERR "memory full (abort writing file)\n"); set_fs(oldfs); break; } set_fs(oldfs); } } if(handle != 5) { close_output_file(); printk("[avm_led] file closed\n"); } return; } return; } /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ void avm_led_profile_sync(int virt_led_handle) { return; }