Merge branch 'bjorn-start-stop-2.6.32' into release
[pandora-kernel.git] / drivers / staging / otus / 80211core / performance.c
1 /*
2  * Copyright (c) 2007-2008 Atheros Communications Inc.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 /*                                                                      */
17 /*  Module Name : performance.c                                         */
18 /*                                                                      */
19 /*  Abstract                                                            */
20 /*      This module performance evaluation functions.                   */
21 /*                                                                      */
22 /*  NOTES                                                               */
23 /*      None                                                            */
24 /*                                                                      */
25 /************************************************************************/
26 #include "cprecomp.h"
27 #ifdef ZM_ENABLE_PERFORMANCE_EVALUATION
28
29 #define ZM_TP_SIZE 50
30 static struct zsSummary zm_summary;
31 static struct zsVariation zm_var;
32 static struct zsThroughput zm_tp;
33
34 void zfiPerformanceInit(zdev_t* dev)
35 {
36     u16_t   i;
37
38     zmw_get_wlan_dev(dev);
39
40     zm_summary.tick_base = wd->tick;
41     zm_summary.tx_msdu_count = 0;
42     zm_summary.tx_mpdu_count = 0;
43     zm_summary.rx_msdu_count = 0;
44     zm_summary.rx_mpdu_count = 0;
45     zm_summary.rx_broken_seq = 0;
46     zm_summary.rx_broken_sum = 0;
47     zm_summary.rx_seq_base = 0;
48     zm_summary.rx_broken_seq_dis = 0;
49     zm_summary.rx_duplicate_seq = 0;
50     zm_summary.rx_old_seq = 0;
51     zm_summary.reset_count = 0;
52     zm_summary.reset_sum = 0;
53     zm_summary.rx_lost_sum = 0;
54     zm_summary.rx_duplicate_error = 0;
55     zm_summary.rx_free = 0;
56     zm_summary.rx_amsdu_len = 0;
57     zm_summary.rx_flush = 0;
58     zm_summary.rx_clear = 0;
59     zm_summary.rx_reorder = 0;
60
61     for (i=0; i<100; i++)
62     {
63         zm_var.tx_msdu_tick[i] = zm_var.tx_mpdu_tick[i] = 0;
64         zm_var.rx_msdu_tick[i] = zm_var.rx_mpdu_tick[i] = 0;
65     }
66
67     zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_PERFORMANCE, 100);
68
69     zm_tp.size = ZM_TP_SIZE;
70     zm_tp.head = zm_tp.size - 1;
71     zm_tp.tail = 0;
72     for (i=0; i<zm_tp.size; i++)
73     {
74         zm_tp.tx[i]=0;
75         zm_tp.rx[i]=0;
76     }
77 }
78
79 void zfiPerformanceGraph(zdev_t* dev)
80 {
81     s16_t   i,j;
82     u8_t    s[ZM_TP_SIZE+5];
83     zmw_get_wlan_dev(dev);
84
85     for (i=0; i<(zm_tp.size-1); i++)
86     {
87         zm_tp.tx[i] = zm_tp.tx[i+1];
88         zm_tp.rx[i] = zm_tp.rx[i+1];
89     }
90     zm_tp.tx[zm_tp.size-1] = zm_summary.tx_mpdu_count*1500*8/1000000;
91     zm_tp.rx[zm_tp.size-1] = zm_summary.rx_msdu_count*1500*8/1000000;
92
93     for (i=15; i>0; i--)
94     {
95         s[0] = (i/10) + '0';
96         s[1] = (i%10) + '0';
97         s[2] = '0';
98         s[3] = '|';
99         for (j=0; j<zm_tp.size; j++)
100         {
101             if ((zm_tp.tx[j]/10 == i) && (zm_tp.rx[j]/10 == i))
102             {
103                 s[4+j] = 'X';
104             }
105             else if (zm_tp.tx[j]/10 == i)
106             {
107                 s[4+j] = 'T';
108             }
109             else if (zm_tp.rx[j]/10 == i)
110             {
111                 s[4+j] = 'R';
112             }
113             else
114             {
115                 s[4+j] = ' ';
116             }
117         }
118         s[zm_tp.size+4] = '\0';
119         DbgPrint("%s",s);
120     }
121     DbgPrint("000|__________________________________________________");
122
123 }
124
125
126 void zfiPerformanceRefresh(zdev_t* dev)
127 {
128     u16_t   i;
129
130     zmw_get_wlan_dev(dev);
131
132     zfiDbgReadReg(dev, 0x11772c);
133
134     zm_var.tx_msdu_mean = zm_summary.tx_msdu_count / 100;
135     zm_var.tx_mpdu_mean = zm_summary.tx_mpdu_count / 100;
136     zm_var.rx_msdu_mean = zm_summary.rx_msdu_count / 100;
137     zm_var.rx_mpdu_mean = zm_summary.rx_mpdu_count / 100;
138
139     zm_var.tx_msdu_sum = zm_var.tx_mpdu_sum = 0;
140     zm_var.rx_msdu_sum = zm_var.rx_mpdu_sum = 0;
141     zm_summary.tx_idle_count = zm_summary.rx_idle_count = 0;
142     for (i=0; i<100; i++)
143     {
144         zm_var.tx_msdu_sum += (zm_var.tx_msdu_tick[i] * zm_var.tx_msdu_tick[i]);
145         zm_var.tx_mpdu_sum += (zm_var.tx_mpdu_tick[i] * zm_var.tx_mpdu_tick[i]);
146         zm_var.rx_msdu_sum += (zm_var.rx_msdu_tick[i] * zm_var.rx_msdu_tick[i]);
147         zm_var.rx_mpdu_sum += (zm_var.rx_mpdu_tick[i] * zm_var.rx_mpdu_tick[i]);
148
149         if (!zm_var.tx_mpdu_tick[i]) zm_summary.tx_idle_count++;
150         if (!zm_var.rx_mpdu_tick[i]) zm_summary.rx_idle_count++;
151     }
152     zm_var.tx_msdu_var = (zm_var.tx_msdu_sum / 100) - (zm_var.tx_msdu_mean * zm_var.tx_msdu_mean);
153     zm_var.tx_mpdu_var = (zm_var.tx_mpdu_sum / 100) - (zm_var.tx_mpdu_mean * zm_var.tx_mpdu_mean);
154     zm_var.rx_msdu_var = (zm_var.rx_msdu_sum / 100) - (zm_var.rx_msdu_mean * zm_var.rx_msdu_mean);
155     zm_var.rx_mpdu_var = (zm_var.rx_mpdu_sum / 100) - (zm_var.rx_mpdu_mean * zm_var.rx_mpdu_mean);
156
157     zm_summary.tick_base = wd->tick;
158     zm_summary.rx_broken_sum += zm_summary.rx_broken_seq;
159     zm_summary.rx_lost_sum += (zm_summary.rx_broken_seq - zm_summary.rx_duplicate_seq - zm_summary.rx_old_seq);
160
161     zfiPerformanceGraph(dev);
162
163     DbgPrint("******************************************************\n");
164     DbgPrint("* TX: MSDU=%5d, VAR=%5d; MPDU=%5d, VAR=%5d\n", zm_summary.tx_msdu_count,
165         zm_var.tx_msdu_var, zm_summary.tx_mpdu_count, zm_var.tx_mpdu_var);
166     DbgPrint("* TX: idle=%5d,TxRate=%3d,  PER=%5d\n", zm_summary.tx_idle_count,
167         wd->CurrentTxRateKbps/1000,
168         (u16_t)wd->PER[wd->sta.oppositeInfo[0].rcCell.currentRate]);
169     DbgPrint("* RX: MSDU=%5d, VAR=%5d; MPDU=%5d, VAR=%5d\n", zm_summary.rx_msdu_count,
170         zm_var.rx_msdu_var, zm_summary.rx_mpdu_count, zm_var.rx_mpdu_var);
171     DbgPrint("* RX: idle=%5d,RxRate=%3d,AMSDU=%5d\n", zm_summary.rx_idle_count,
172         wd->CurrentRxRateKbps/1000, zm_summary.rx_amsdu_len);
173     DbgPrint("* RX broken seq=%4d, distances=%4d, duplicates=%4d\n", zm_summary.rx_broken_seq,
174         zm_summary.rx_broken_seq_dis, zm_summary.rx_duplicate_seq);
175     DbgPrint("* RX    old seq=%4d,      lost=%4d, broken sum=%4d\n", zm_summary.rx_old_seq,
176         (zm_summary.rx_broken_seq - zm_summary.rx_duplicate_seq - zm_summary.rx_old_seq),
177         zm_summary.rx_broken_sum);
178     DbgPrint("* Rx   lost sum=%4d,dup. error=%4d, free count=%4d\n", zm_summary.rx_lost_sum,
179         zm_summary.rx_duplicate_error, zm_summary.rx_free);
180     DbgPrint("* Rx  flush sum=%4d, clear sum=%4d, reorder=%7d\n", zm_summary.rx_flush,
181         zm_summary.rx_clear, zm_summary.rx_reorder);
182     DbgPrint("* Firmware reset=%3d, reset sum=%4d\n", zm_summary.reset_count,
183         zm_summary.reset_sum);
184     DbgPrint("******************************************************\n\n");
185     //reset count 11772c
186     zm_summary.tx_msdu_count = 0;
187     zm_summary.tx_mpdu_count = 0;
188     zm_summary.rx_msdu_count = 0;
189     zm_summary.rx_mpdu_count = 0;
190     zm_summary.rx_broken_seq = 0;
191     zm_summary.rx_broken_seq_dis = 0;
192     zm_summary.rx_duplicate_seq = 0;
193     zm_summary.rx_old_seq = 0;
194     zm_summary.reset_count = 0;
195     zm_summary.rx_amsdu_len = 0;
196
197     for (i=0; i<100; i++)
198     {
199         zm_var.tx_msdu_tick[i] = zm_var.tx_mpdu_tick[i] = 0;
200         zm_var.rx_msdu_tick[i] = zm_var.rx_mpdu_tick[i] = 0;
201     }
202
203     zfTimerSchedule(dev, ZM_EVENT_TIMEOUT_PERFORMANCE, 100);
204 }
205
206 void zfiTxPerformanceMSDU(zdev_t* dev, u32_t tick)
207 {
208     u32_t   index;
209     zm_summary.tx_msdu_count++;
210
211     index = tick - zm_summary.tick_base;
212
213     if (index < 100)
214     {
215         zm_var.tx_msdu_tick[index]++;
216     }
217     else
218     {
219         //DbgPrint("wd->tick exceeded tick_base+100!\n");
220     }
221 }
222
223 void zfiRxPerformanceMSDU(zdev_t* dev, u32_t tick)
224 {
225     u32_t   index;
226     zm_summary.rx_msdu_count++;
227
228     index = tick - zm_summary.tick_base;
229
230     if (index < 100)
231     {
232         zm_var.rx_msdu_tick[index]++;
233     }
234     else
235     {
236         //DbgPrint("wd->tick exceeded tick_base+100!\n");
237     }
238 }
239
240 void zfiTxPerformanceMPDU(zdev_t* dev, u32_t tick)
241 {
242     u32_t   index;
243     zm_summary.tx_mpdu_count++;
244
245     index = tick - zm_summary.tick_base;
246
247     if (index < 100)
248     {
249         zm_var.tx_mpdu_tick[index]++;
250     }
251     else
252     {
253         //DbgPrint("wd->tick exceeded tick_base+100!\n");
254     }
255 }
256
257 #ifndef ZM_INT_USE_EP2_HEADER_SIZE
258 #define ZM_INT_USE_EP2_HEADER_SIZE   12
259 #endif
260 void zfiRxPerformanceMPDU(zdev_t* dev, zbuf_t* buf)
261 {
262     u32_t   index;
263     u16_t   frameType;
264     u16_t   frameCtrl;
265     u8_t    mpduInd;
266     u16_t   plcpHdrLen;
267     u16_t   len;
268
269     zmw_get_wlan_dev(dev);
270
271     len = zfwBufGetSize(dev, buf);
272     mpduInd = zmw_rx_buf_readb(dev, buf, len-1);
273     /* First MPDU or Single MPDU */
274     if(((mpduInd & 0x30) == 0x00) || ((mpduInd & 0x30) == 0x20))
275     //if ((mpduInd & 0x10) == 0x00)
276     {
277         plcpHdrLen = 12;        // PLCP header length
278     }
279     else
280     {
281         if (zmw_rx_buf_readh(dev, buf, 4) == wd->macAddr[0] &&
282             zmw_rx_buf_readh(dev, buf, 6) == wd->macAddr[1] &&
283             zmw_rx_buf_readh(dev, buf, 8) == wd->macAddr[2]) {
284             plcpHdrLen = 0;
285         }
286         else if (zmw_rx_buf_readh(dev, buf, 16) == wd->macAddr[0] &&
287                  zmw_rx_buf_readh(dev, buf, 18) == wd->macAddr[1] &&
288                  zmw_rx_buf_readh(dev, buf, 20) == wd->macAddr[2]){
289             plcpHdrLen = 12;
290         }
291         else {
292             plcpHdrLen = 0;
293         }
294     }
295
296     frameCtrl = zmw_rx_buf_readb(dev, buf, plcpHdrLen + 0);
297     frameType = frameCtrl & 0xf;
298
299     if (frameType != ZM_WLAN_DATA_FRAME)
300     {
301         return;
302     }
303
304     zm_summary.rx_mpdu_count++;
305
306     index = wd->tick - zm_summary.tick_base;
307
308     if (index < 100)
309     {
310         zm_var.rx_mpdu_tick[index]++;
311     }
312     else
313     {
314         //DbgPrint("wd->tick exceeded tick_base+100!\n");
315     }
316 }
317
318 void zfiRxPerformanceSeq(zdev_t* dev, zbuf_t* buf)
319 {
320     u16_t   seq_no;
321     u16_t   offset = 0;
322     u16_t   old_dis = zm_summary.rx_broken_seq_dis;
323     //sys_time = KeQueryPerformanceCounter(&freq);
324
325     seq_no = zmw_rx_buf_readh(dev, buf, offset+22) >> 4;
326
327     ZM_SEQ_DEBUG("Out   %5d\n", seq_no);
328
329     if (seq_no < zm_summary.rx_seq_base)
330     {
331         if (seq_no == 0)
332         {
333             if (zm_summary.rx_seq_base != 4095)
334             {
335                 zm_summary.rx_broken_seq++;
336                 ZM_SEQ_DEBUG("Broken seq");
337                 zm_summary.rx_broken_seq_dis+=(4096 - zm_summary.rx_seq_base);
338             }
339         }
340         else if ((seq_no < 300) && (zm_summary.rx_seq_base > 3800))
341         {
342             zm_summary.rx_broken_seq++;
343             ZM_SEQ_DEBUG("Broken seq");
344             zm_summary.rx_broken_seq_dis+=(4096 - zm_summary.rx_seq_base + seq_no);
345         }
346         else
347         {
348             zm_summary.rx_broken_seq++;
349             ZM_SEQ_DEBUG("Broken seq");
350             zm_summary.rx_broken_seq_dis+=(zm_summary.rx_seq_base - seq_no);
351             zm_summary.rx_old_seq++;
352         }
353     }
354     else
355     {
356         if (seq_no != (zm_summary.rx_seq_base + 1))
357         {
358             if ((seq_no > 3800) && (zm_summary.rx_seq_base < 300))
359             {
360                 zm_summary.rx_broken_seq++;
361                 ZM_SEQ_DEBUG("Broken seq");
362                 zm_summary.rx_broken_seq_dis+=(4096 - seq_no + zm_summary.rx_seq_base);
363                 zm_summary.rx_old_seq++;
364             }
365             else
366             {
367                 zm_summary.rx_broken_seq++;
368                 ZM_SEQ_DEBUG("Broken seq");
369                 zm_summary.rx_broken_seq_dis+=(seq_no - zm_summary.rx_seq_base);
370             }
371         }
372     }
373     if (seq_no == zm_summary.rx_seq_base)
374     {
375         zm_summary.rx_duplicate_seq++;
376     }
377
378     if ((zm_summary.rx_broken_seq_dis - old_dis) > 100)
379     {
380         DbgPrint("* seq_no=%4d, base_seq=%4d, dis_diff=%4d", seq_no,
381             zm_summary.rx_seq_base, zm_summary.rx_broken_seq_dis - old_dis);
382     }
383     zm_summary.rx_seq_base = seq_no;
384 }
385
386 void zfiRxPerformanceReg(zdev_t* dev, u32_t reg, u32_t rsp)
387 {
388     zm_summary.reset_count = (u16_t)rsp - zm_summary.reset_sum;
389     zm_summary.reset_sum = (u16_t)rsp;
390 }
391
392 void zfiRxPerformanceDup(zdev_t* dev, zbuf_t* buf1, zbuf_t* buf2)
393 {
394     u16_t   seq_no1, seq_no2;
395
396     seq_no1 = zmw_rx_buf_readh(dev, buf1, 22) >> 4;
397     seq_no2 = zmw_rx_buf_readh(dev, buf2, 22) >> 4;
398     if (seq_no1 != seq_no2)
399     {
400         zm_summary.rx_duplicate_error++;
401     }
402 }
403
404 void zfiRxPerformanceFree(zdev_t* dev, zbuf_t* buf)
405 {
406     zm_summary.rx_free++;
407 }
408
409 void zfiRxPerformanceAMSDU(zdev_t* dev, zbuf_t* buf, u16_t len)
410 {
411     if (zm_summary.rx_amsdu_len < len)
412     {
413         zm_summary.rx_amsdu_len = len;
414     }
415 }
416 void zfiRxPerformanceFlush(zdev_t* dev)
417 {
418     zm_summary.rx_flush++;
419 }
420
421 void zfiRxPerformanceClear(zdev_t* dev)
422 {
423     zm_summary.rx_clear++;
424     ZM_SEQ_DEBUG("RxClear");
425 }
426
427 void zfiRxPerformanceReorder(zdev_t* dev)
428 {
429     zm_summary.rx_reorder++;
430 }
431 #endif /* end of ZM_ENABLE_PERFORMANCE_EVALUATION */