1/**************************************************************************** 2**+-----------------------------------------------------------------------+** 3**| |** 4**| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** 5**| All rights reserved. |** 6**| |** 7**| Redistribution and use in source and binary forms, with or without |** 8**| modification, are permitted provided that the following conditions |** 9**| are met: |** 10**| |** 11**| * Redistributions of source code must retain the above copyright |** 12**| notice, this list of conditions and the following disclaimer. |** 13**| * Redistributions in binary form must reproduce the above copyright |** 14**| notice, this list of conditions and the following disclaimer in |** 15**| the documentation and/or other materials provided with the |** 16**| distribution. |** 17**| * Neither the name Texas Instruments nor the names of its |** 18**| contributors may be used to endorse or promote products derived |** 19**| from this software without specific prior written permission. |** 20**| |** 21**| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** 22**| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** 23**| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** 24**| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** 25**| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** 26**| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** 27**| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** 28**| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** 29**| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** 30**| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** 31**| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** 32**| |** 33**+-----------------------------------------------------------------------+** 34****************************************************************************/ 35 36 37#include <linux/config.h> 38#include <linux/module.h> 39#include <linux/errno.h> 40#include <linux/string.h> 41#include <linux/proc_fs.h> 42 43#include "osApi.h" 44#include "esta_drv.h" 45#include "bmtrace.h" 46 47#define OS_READ_REG(drv,reg,p_val) \ 48 os_hwReadMemRegisterUINT32(drv, (UINT32 *)((unsigned long)drv->acx_reg.va + reg), p_val) 49 50typedef struct { 51 unsigned long loc;/* trace entry identification */ 52 unsigned long ts;/* Timestamp */ 53 unsigned long p1; /* Parameter 1 */ 54 unsigned long p2; /* Parameter 2 */ 55} bm_entry_t; 56 57typedef struct { 58 int pos; 59 int count; 60 int print_pos; 61 int nusers; 62 unsigned long self_delay; 63 tiwlan_net_dev_t *drv; 64 bm_entry_t entry[1]; /* Array of entries */ 65} bm_control_t; 66 67static bm_control_t *bm_control; 68 69static inline int bm_control_size(void) 70{ 71 return offsetof(bm_control_t, entry) + sizeof(bm_entry_t)*BM_NUM_ENTRIES; 72} 73 74static int bm_res_read_proc(char *page, char **start, off_t off, 75 int count, int *eof, void *data) 76{ 77 int i; 78 int len=0; 79 int limit=count-80; 80 int entry_count; 81 unsigned long prev=0; 82 int print_pos; 83 84 print_pos = bm_control->print_pos++; /* It will disable tracing as well */ 85 86 entry_count = (bm_control->count > BM_NUM_ENTRIES) ? BM_NUM_ENTRIES : bm_control->count; 87 88 /* Skip off entries */ 89 if ( print_pos >= entry_count) /* paranoid */ 90 { 91 bm_control->pos = bm_control->count = bm_control->print_pos = 0; 92 *eof = 1; 93 return 0; 94 } 95 96 if (!off) 97 { 98 len = sprintf(page, "Events stored: %u discarded: %u\n", 99 entry_count, bm_control->count-entry_count); 100 len += sprintf(page+len, "loc delta ts p1 p2\n"); 101 } 102 103 /* Initial index */ 104 if (bm_control->count > BM_NUM_ENTRIES) 105 i = (bm_control->pos+print_pos-1)%BM_NUM_ENTRIES; 106 else 107 i = bm_control->print_pos-1; 108 109 for(; (print_pos<entry_count) && (len<=limit); print_pos++) 110 { 111 bm_entry_t *bme= &bm_control->entry[i]; 112 len += sprintf(page+len, 113 "%-3lu %-10lu %-10lu %-10lu %-10lu\n", 114 bme->loc, 115 ((bme->ts-prev)>bm_control->self_delay)?bme->ts-prev-bm_control->self_delay:0, 116 bme->ts, 117 bme->p1, bme->p2); 118 prev = bme->ts; 119 ++i; 120 i %= BM_NUM_ENTRIES; 121 } 122 if (print_pos >= entry_count) 123 { 124 *eof = 1; 125 bm_control->pos = bm_control->count = bm_control->print_pos = 0; 126 } 127 else 128 bm_control->print_pos = print_pos; 129 return len; 130} 131 132 133/* Initialization */ 134int bm_init(struct tiwlan_net_dev *drv) 135{ 136 if (bm_control) 137 { 138 ++bm_control->nusers; 139 return 0; 140 } 141 bm_control = (bm_control_t *)kmalloc(bm_control_size(), GFP_KERNEL); 142 if (!bm_control) 143 return -ENOMEM; 144 memset(bm_control, 0, offsetof(bm_control_t, entry) + sizeof(bm_entry_t)*BM_NUM_ENTRIES); 145 bm_control->nusers = 1; 146 bm_control->drv = drv; 147 148 create_proc_read_entry("bmtrace", 0, NULL, bm_res_read_proc, NULL); 149 /* Measure self-delay */ 150 bm_trace(0, 0, 0); 151 bm_trace(0, 0, 0); 152 bm_control->self_delay = bm_control->entry[1].ts - bm_control->entry[0].ts; 153 bm_control->pos = bm_control->count = 0; 154 print_info("%s: self_delay=%lu\n", __FUNCTION__, bm_control->self_delay); 155 return 0; 156} 157 158/* De-initialization */ 159void bm_destroy(void) 160{ 161 if (--bm_control->nusers) 162 return; 163 remove_proc_entry("bmtrace", NULL); 164 kfree( bm_control ); 165} 166 167 168/* Add trace entry. not safe, but will do */ 169void bm_trace(int loc, unsigned long p1, unsigned long p2) 170{ 171 int pos; 172 if (!bm_control || bm_control->print_pos) 173 return; 174 pos = bm_control->pos; 175 bm_control->pos = (pos+1) % BM_NUM_ENTRIES; 176 ++bm_control->count; 177 178 bm_control->entry[pos].ts = os_timeStampUs(NULL); 179 bm_control->entry[pos].loc= loc; 180 bm_control->entry[pos].p1 = p1; 181 bm_control->entry[pos].p2 = p2; 182} 183 184