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