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 50 typedef 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 57 typedef 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 67 static bm_control_t *bm_control; 68 69 static inline int bm_control_size(void) 70 { 71 return offsetof(bm_control_t, entry) + sizeof(bm_entry_t)*BM_NUM_ENTRIES; 72 } 73 74 static 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 */ 134 int 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 */ 159 void 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 */ 169 void 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