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
bm_control_size(void)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
bm_res_read_proc(char * page,char ** start,off_t off,int count,int * eof,void * data)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 */
bm_init(struct tiwlan_net_dev * drv)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 */
bm_destroy(void)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 */
bm_trace(int loc,unsigned long p1,unsigned long p2)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