Home | History | Annotate | Download | only in src
      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 
     38 #include "esta_drv.h"
     39 
     40 
     41 static void tiwlan_profile_bus_access_start (void *os, unsigned);
     42 static void tiwlan_profile_bus_access_end (void *os, unsigned);
     43 static void tiwlan_profile_driver_entry_start (void *os, unsigned);
     44 static void tiwlan_profile_driver_entry_end (void *os, unsigned);
     45 static void tiwlan_profile_memory_alloc (void *os, unsigned);
     46 static void tiwlan_profile_memory_free (void *os, unsigned);
     47 static void tiwlan_profile_buf_alloc (void * os, unsigned);
     48 static void tiwlan_profile_timer_create (void * os, unsigned);
     49 static void tiwlan_profile_timer_destroy (void * os, unsigned);
     50 
     51 
     52 int tiwlan_profile_create (tiwlan_net_dev_t *drv)
     53 {
     54     drv->fpro [0] = NULL;
     55     drv->fpro [1] = NULL;
     56     drv->fpro [2] = NULL;
     57     drv->fpro [3] = NULL;
     58     drv->fpro [4] = tiwlan_profile_memory_alloc;
     59     drv->fpro [5] = tiwlan_profile_memory_free;
     60     drv->fpro [6] = tiwlan_profile_timer_create;
     61     drv->fpro [7] = tiwlan_profile_timer_destroy;
     62     drv->fpro [8] = tiwlan_profile_buf_alloc;
     63 
     64     drv->cpu_usage_estimator_start_time = 0;
     65     drv->cpu_usage_estimator_stop_time = 0;
     66     drv->max_heap_bytes_allocated = 0;
     67     drv->max_buf_bytes_allocated = 0;
     68     drv->cur_heap_bytes_allocated = 0;
     69     drv->max_number_of_timers = 0;
     70     drv->cur_number_of_timers = 0;
     71 
     72     return 0;
     73 }
     74 
     75 
     76 /* Call register profiler banchmark */
     77 int tiwlan_profile (tiwlan_net_dev_t *drv, unsigned bm, unsigned par)
     78 {
     79     if (drv && bm < MAX_PROFILE_BM && drv->fpro [bm])
     80     {
     81         (*drv->fpro [bm]) (drv, par);
     82     }
     83 
     84     return 0;
     85 }
     86 
     87 
     88 /* Stop CPU estimation for a driver entry and maintains the resolution of the estimator */
     89 void tiwlan_profile_bus_access_start (void * os, unsigned par)
     90 {
     91     tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
     92 
     93     if (drv != NULL)
     94     {
     95         /* Save the current entry's start time */
     96         drv->bus_driver_entry_start_time = os_timeStampUs (drv);
     97     }
     98 }
     99 
    100 
    101 /* Starts CPU estimation for a bus driver entry */
    102 void tiwlan_profile_bus_access_end (void * os, unsigned par)
    103 {
    104     tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
    105     unsigned current_entry_cpu_usage;
    106 
    107     if (drv != NULL)
    108     {
    109         /* Save the current entry's start time */
    110         current_entry_cpu_usage = os_timeStampUs (drv) - drv->bus_driver_entry_start_time;
    111 
    112         /* Make sure that it is not a negative value */
    113         if ((int)current_entry_cpu_usage < 0)
    114         {
    115             printk("\n\n%s: cpu usage estimation corrupted. entry_start=%u, entry_cpu_time = %d\n\n\n",
    116                    __FUNCTION__, drv->bus_driver_entry_start_time,  current_entry_cpu_usage);
    117         }
    118         /* Update the total time of driver CPU usage */
    119         else
    120         {
    121             drv->total_us_of_bus_access_cpu_time += current_entry_cpu_usage;
    122         }
    123     }
    124 }
    125 
    126 
    127 /* Starts CPU estimation for a driver entry */
    128 void tiwlan_profile_driver_entry_start (void * os, unsigned par)
    129 {
    130     tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
    131 
    132     if (drv != NULL)
    133     {
    134         drv->driver_entry_start_time = os_timeStampUs (drv);
    135     }
    136 }
    137 
    138 
    139 /* Stop CPU estimation for a driver entry and maintains the resolution of the estimator */
    140 void tiwlan_profile_driver_entry_end (void * os, unsigned par)
    141 {
    142     tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
    143     unsigned current_entry_cpu_usage, driver_entry_end_time;
    144 
    145     if (drv == NULL)
    146         return;
    147 
    148     /* Get the current entry's end time */
    149     driver_entry_end_time = os_timeStampUs (drv);
    150 
    151     /* Calculate the current entries CPU run time */
    152     current_entry_cpu_usage = driver_entry_end_time - drv->driver_entry_start_time;
    153 
    154     /* Make sure that it is not a negative value */
    155     if ((int)current_entry_cpu_usage < 0)
    156     {
    157         printk("\n\n%s: cpu usage estimation corrupted. entry_start=%u, entry_end=%u, entry_cpu_time = %d\n\n\n",
    158                __FUNCTION__, drv->driver_entry_start_time, driver_entry_end_time, current_entry_cpu_usage);
    159     }
    160     /* Update the total time of driver CPU usage */
    161     else
    162     {
    163         drv->total_us_of_cpu_time += current_entry_cpu_usage;
    164     }
    165 }
    166 
    167 
    168 void tiwlan_profile_memory_alloc (void * os, unsigned size)
    169 {
    170     tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
    171 
    172     if (drv != NULL)
    173     {
    174         /* Increase current heap allocation counter */
    175         drv->cur_heap_bytes_allocated += size;
    176         /* Update maximum if execceded */
    177         if (drv->max_heap_bytes_allocated < drv->cur_heap_bytes_allocated)
    178         {
    179             drv->max_heap_bytes_allocated = drv->cur_heap_bytes_allocated;
    180         }
    181     }
    182 }
    183 
    184 
    185 void tiwlan_profile_memory_free (void * os, unsigned size)
    186 {
    187     tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
    188 
    189     if (drv != NULL)
    190     {
    191         /* Decrease amount from heap allocation counter */
    192         drv->cur_heap_bytes_allocated -= size;
    193         /* Check for overflow */
    194         if ((int)drv->cur_heap_bytes_allocated < 0)
    195         {
    196             printk("\n\n%s: memory heap allocation calculation corrupted. Size=%u, Current allocation = %d\n\n\n",
    197                    __FUNCTION__, size, drv->cur_heap_bytes_allocated);
    198             drv->cur_heap_bytes_allocated = 0;
    199         }
    200     }
    201 }
    202 
    203 
    204 void tiwlan_profile_buf_alloc (void * os, unsigned size)
    205 {
    206     tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
    207 
    208     if (drv != NULL)
    209     {
    210         drv->max_buf_bytes_allocated += size;
    211     }
    212 }
    213 
    214 
    215 void tiwlan_profile_timer_create (void * os, unsigned par)
    216 {
    217     tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
    218 
    219     if (drv)
    220     {
    221         /* Increase the current active timer counter */
    222         drv->cur_number_of_timers ++;
    223         /* Update maximum if execceded */
    224         if (drv->max_number_of_timers < drv->cur_number_of_timers)
    225         {
    226             drv->max_number_of_timers = drv->cur_number_of_timers;
    227         }
    228     }
    229 }
    230 
    231 
    232 void tiwlan_profile_timer_destroy (void * os, unsigned par)
    233 {
    234     tiwlan_net_dev_t * drv = (tiwlan_net_dev_t *) os;
    235 
    236     if (drv)
    237     {
    238         /* Decrease the current active timer counter */
    239         drv->cur_number_of_timers --;
    240     }
    241 }
    242 
    243 
    244 /*
    245  * Start CPU estimator
    246  * NOTE: this function does not run in a driver context
    247  */
    248 int tiwlan_profile_cpu_usage_estimator_start (tiwlan_net_dev_t * drv, unsigned int resolution)
    249 {
    250     /*
    251      *  Reset estimation parameters - no need for spin lock since
    252      *  estimator is not running
    253      */
    254     drv->total_us_of_cpu_time = 0;
    255     drv->total_us_of_bus_access_cpu_time = 0;
    256     drv->cpu_usage_estimator_start_time = os_timeStampUs (drv);
    257     drv->cpu_usage_estimator_stop_time = 0;
    258 
    259     /* Set the new resolution */
    260     drv->cpu_usage_estimator_resolution = resolution;
    261 
    262     /* Register profiler banchmarks */
    263     drv->fpro [0] = tiwlan_profile_driver_entry_start;
    264     drv->fpro [1] = tiwlan_profile_driver_entry_end;
    265     drv->fpro [2] = tiwlan_profile_bus_access_start;
    266     drv->fpro [3] = tiwlan_profile_bus_access_end;
    267 
    268     return 0;
    269 }
    270 
    271 
    272 /*
    273  * Stop CPU estimator and save the last CPU estimation
    274  * NOTE: this function does not run in a driver context
    275  */
    276 int tiwlan_profile_cpu_usage_estimator_stop (tiwlan_net_dev_t * drv)
    277 {
    278     drv->cpu_usage_estimator_stop_time = os_timeStampUs (drv);
    279 
    280     /* Unregister profiler banchmarks */
    281     drv->fpro [0] = NULL;
    282     drv->fpro [1] = NULL;
    283     drv->fpro [2] = NULL;
    284     drv->fpro [3] = NULL;
    285 
    286     return 0;
    287 }
    288 
    289 
    290 /*
    291  * Reset CPU estimation
    292  * NOTE: this function is not run in a driver context
    293  */
    294 int tiwlan_profile_cpu_usage_estimator_reset (tiwlan_net_dev_t * drv)
    295 {
    296     /* Reset accumulated driver time and the last estimation */
    297     drv->total_us_of_cpu_time = 0;
    298     drv->total_us_of_bus_access_cpu_time = 0;
    299     drv->cpu_usage_estimator_start_time = 0;
    300     drv->cpu_usage_estimator_stop_time = 0;
    301 
    302     return 0;
    303 }
    304 
    305 
    306 /* Print to the screen the latest resource usage and CPU estimation */
    307 int tiwlan_profile_report (tiwlan_net_dev_t *drv)
    308 {
    309     unsigned total_time, drv_cpu_usage = 0, bus_cpu_usage = 0;
    310 
    311     printk ("\nDriver Resource Usage");
    312     printk ("\n=====================");
    313     printk ("\nMaximum Heap Memory Allocated: %u (bytes)", drv->max_heap_bytes_allocated);
    314     printk ("\nCurrent Heap Memory Allocated: %u (bytes)", drv->cur_heap_bytes_allocated);
    315     printk ("\nBuffer Memory Allocated: %u (bytes)", drv->max_buf_bytes_allocated);
    316     printk ("\nFirmware Image Memory Allocated: %u (bytes)", (unsigned)drv->firmware_image.size);
    317     printk ("\nEEPROM Image Memory Allocated: %u (bytes)", (unsigned)drv->eeprom_image.size);
    318     printk ("\nMaximum Active Timers: %u", drv->max_number_of_timers);
    319     printk ("\nCurrent Active Timers: %u", drv->cur_number_of_timers);
    320 
    321     /* Check that the estimation has been started and stopped stopped */
    322     if (drv->cpu_usage_estimator_stop_time != 0)
    323     {
    324         total_time = drv->cpu_usage_estimator_stop_time - drv->cpu_usage_estimator_start_time;
    325 
    326         total_time /= 100;
    327 
    328         if ((int)total_time > 0)
    329         {
    330             drv_cpu_usage = drv->total_us_of_cpu_time / total_time;
    331             bus_cpu_usage = drv->total_us_of_bus_access_cpu_time / total_time;
    332 
    333             printk ("\nTotal Test Run Time: %u (usec)", total_time);
    334             printk ("\nTotal Driver Run Time: %u (usec)", drv->total_us_of_cpu_time);
    335             printk ("\nTotal Bus Access Time: %u (usec)", drv->total_us_of_bus_access_cpu_time);
    336             printk ("\nTotal CPU Usage: %u%%", drv_cpu_usage);
    337             printk ("\nBus Access CPU Usage: %u%%", bus_cpu_usage);
    338             printk ("\n");
    339         }
    340     }
    341 
    342     return 0;
    343 }
    344 
    345