/**************************************************************************** **+-----------------------------------------------------------------------+** **| |** **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |** **| All rights reserved. |** **| |** **| Redistribution and use in source and binary forms, with or without |** **| modification, are permitted provided that the following conditions |** **| are met: |** **| |** **| * Redistributions of source code must retain the above copyright |** **| notice, this list of conditions and the following disclaimer. |** **| * Redistributions in binary form must reproduce the above copyright |** **| notice, this list of conditions and the following disclaimer in |** **| the documentation and/or other materials provided with the |** **| distribution. |** **| * Neither the name Texas Instruments nor the names of its |** **| contributors may be used to endorse or promote products derived |** **| from this software without specific prior written permission. |** **| |** **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |** **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |** **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |** **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |** **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |** **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |** **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |** **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |** **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |** **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |** **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |** **| |** **+-----------------------------------------------------------------------+** ****************************************************************************/ #include #include #include #include #include #include "osApi.h" #include "esta_drv.h" #include "bmtrace.h" #define OS_READ_REG(drv,reg,p_val) \ os_hwReadMemRegisterUINT32(drv, (UINT32 *)((unsigned long)drv->acx_reg.va + reg), p_val) typedef struct { unsigned long loc;/* trace entry identification */ unsigned long ts;/* Timestamp */ unsigned long p1; /* Parameter 1 */ unsigned long p2; /* Parameter 2 */ } bm_entry_t; typedef struct { int pos; int count; int print_pos; int nusers; unsigned long self_delay; tiwlan_net_dev_t *drv; bm_entry_t entry[1]; /* Array of entries */ } bm_control_t; static bm_control_t *bm_control; static inline int bm_control_size(void) { return offsetof(bm_control_t, entry) + sizeof(bm_entry_t)*BM_NUM_ENTRIES; } static int bm_res_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int i; int len=0; int limit=count-80; int entry_count; unsigned long prev=0; int print_pos; print_pos = bm_control->print_pos++; /* It will disable tracing as well */ entry_count = (bm_control->count > BM_NUM_ENTRIES) ? BM_NUM_ENTRIES : bm_control->count; /* Skip off entries */ if ( print_pos >= entry_count) /* paranoid */ { bm_control->pos = bm_control->count = bm_control->print_pos = 0; *eof = 1; return 0; } if (!off) { len = sprintf(page, "Events stored: %u discarded: %u\n", entry_count, bm_control->count-entry_count); len += sprintf(page+len, "loc delta ts p1 p2\n"); } /* Initial index */ if (bm_control->count > BM_NUM_ENTRIES) i = (bm_control->pos+print_pos-1)%BM_NUM_ENTRIES; else i = bm_control->print_pos-1; for(; (print_posentry[i]; len += sprintf(page+len, "%-3lu %-10lu %-10lu %-10lu %-10lu\n", bme->loc, ((bme->ts-prev)>bm_control->self_delay)?bme->ts-prev-bm_control->self_delay:0, bme->ts, bme->p1, bme->p2); prev = bme->ts; ++i; i %= BM_NUM_ENTRIES; } if (print_pos >= entry_count) { *eof = 1; bm_control->pos = bm_control->count = bm_control->print_pos = 0; } else bm_control->print_pos = print_pos; return len; } /* Initialization */ int bm_init(struct tiwlan_net_dev *drv) { if (bm_control) { ++bm_control->nusers; return 0; } bm_control = (bm_control_t *)kmalloc(bm_control_size(), GFP_KERNEL); if (!bm_control) return -ENOMEM; memset(bm_control, 0, offsetof(bm_control_t, entry) + sizeof(bm_entry_t)*BM_NUM_ENTRIES); bm_control->nusers = 1; bm_control->drv = drv; create_proc_read_entry("bmtrace", 0, NULL, bm_res_read_proc, NULL); /* Measure self-delay */ bm_trace(0, 0, 0); bm_trace(0, 0, 0); bm_control->self_delay = bm_control->entry[1].ts - bm_control->entry[0].ts; bm_control->pos = bm_control->count = 0; print_info("%s: self_delay=%lu\n", __FUNCTION__, bm_control->self_delay); return 0; } /* De-initialization */ void bm_destroy(void) { if (--bm_control->nusers) return; remove_proc_entry("bmtrace", NULL); kfree( bm_control ); } /* Add trace entry. not safe, but will do */ void bm_trace(int loc, unsigned long p1, unsigned long p2) { int pos; if (!bm_control || bm_control->print_pos) return; pos = bm_control->pos; bm_control->pos = (pos+1) % BM_NUM_ENTRIES; ++bm_control->count; bm_control->entry[pos].ts = os_timeStampUs(NULL); bm_control->entry[pos].loc= loc; bm_control->entry[pos].p1 = p1; bm_control->entry[pos].p2 = p2; }