• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Misc utility routines used by kernel or app-level.
3  * Contents are wifi-specific, used by any kernel or app-level
4  * software that might want wifi things as it grows.
5  *
6  * Copyright (C) 1999-2019, Broadcom.
7  *
8  *      Unless you and Broadcom execute a separate written software license
9  * agreement governing use of this software, this software is licensed to you
10  * under the terms of the GNU General Public License version 2 (the "GPL"),
11  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
12  * following added to such license:
13  *
14  *      As a special exception, the copyright holders of this software give you
15  * permission to link this software with independent modules, and to copy and
16  * distribute the resulting executable under terms of your choice, provided that
17  * you also meet, for each linked independent module, the terms and conditions
18  * of the license of that module.  An independent module is a module which is
19  * not derived from this software.  The special exception does not apply to any
20  * modifications of the software.
21  *
22  *      Notwithstanding the above, under no circumstances may you combine this
23  * software in any way with any other Broadcom software provided under a license
24  * other than the GPL, without Broadcom's express prior written consent.
25  *
26  *
27  * <<Broadcom-WL-IPTag/Open:>>
28  *
29  * $Id: bcm_app_utils.c 667243 2016-10-26 11:37:48Z $
30  */
31 
32 #include <typedefs.h>
33 
34 #ifdef BCMDRIVER
35 #include <osl.h>
36 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
37 #define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c))
38 #else /* BCMDRIVER */
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <ctype.h>
43 #ifndef ASSERT
44 #define ASSERT(exp)
45 #endif // endif
46 #endif /* BCMDRIVER */
47 #include <bcmwifi_channels.h>
48 
49 #if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL))
50 #include <bcmstdlib.h> /* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */
51 #endif                 // endif
52 
53 #include <bcmutils.h>
54 #include <wlioctl.h>
55 #include <wlioctl_utils.h>
56 
57 #ifndef BCMDRIVER
58 /*	Take an array of measurments representing a single channel over time and
59    return a summary. Currently implemented as a simple average but could easily
60    evolve into more cpomplex alogrithms.
61 */
62 cca_congest_channel_req_t *
cca_per_chan_summary(cca_congest_channel_req_t * input,cca_congest_channel_req_t * avg,bool percent)63 cca_per_chan_summary(cca_congest_channel_req_t *input,
64                      cca_congest_channel_req_t *avg, bool percent)
65 {
66     int sec;
67     cca_congest_t totals;
68 
69     totals.duration = 0;
70     totals.congest_ibss = 0;
71     totals.congest_obss = 0;
72     totals.interference = 0;
73     avg->num_secs = 0;
74 
75     for (sec = 0; sec < input->num_secs; sec++) {
76         if (input->secs[sec].duration) {
77             totals.duration += input->secs[sec].duration;
78             totals.congest_ibss += input->secs[sec].congest_ibss;
79             totals.congest_obss += input->secs[sec].congest_obss;
80             totals.interference += input->secs[sec].interference;
81             avg->num_secs++;
82         }
83     }
84     avg->chanspec = input->chanspec;
85 
86     if (!avg->num_secs || !totals.duration) {
87         return (avg);
88     }
89 
90     if (percent) {
91         avg->secs[0].duration = totals.duration / avg->num_secs;
92         avg->secs[0].congest_ibss = totals.congest_ibss * 0x64 / totals.duration;
93         avg->secs[0].congest_obss = totals.congest_obss * 0x64 / totals.duration;
94         avg->secs[0].interference = totals.interference * 0x64 / totals.duration;
95     } else {
96         avg->secs[0].duration = totals.duration / avg->num_secs;
97         avg->secs[0].congest_ibss = totals.congest_ibss / avg->num_secs;
98         avg->secs[0].congest_obss = totals.congest_obss / avg->num_secs;
99         avg->secs[0].interference = totals.interference / avg->num_secs;
100     }
101 
102     return (avg);
103 }
104 
cca_info(uint8 * bitmap,int num_bits,int * left,int * bit_pos)105 static void cca_info(uint8 *bitmap, int num_bits, int *left, int *bit_pos)
106 {
107     int i;
108     for (*left = 0, i = 0; i < num_bits; i++) {
109         if (isset(bitmap, i)) {
110             (*left)++;
111             *bit_pos = i;
112         }
113     }
114 }
115 
spec_to_chan(chanspec_t chspec)116 static uint8 spec_to_chan(chanspec_t chspec)
117 {
118     uint8 center_ch, edge, primary, sb;
119 
120     center_ch = CHSPEC_CHANNEL(chspec);
121 
122     if (CHSPEC_BW_LE20(chspec)) {
123         return center_ch;
124     } else {
125         /* the lower edge of the wide channel is half the bw from
126          * the center channel.
127          */
128         if (CHSPEC_IS40(chspec)) {
129             edge = center_ch - CH_20MHZ_APART;
130         } else {
131             /* must be 80MHz (until we support more) */
132             ASSERT(CHSPEC_IS80(chspec));
133             edge = center_ch - CH_40MHZ_APART;
134         }
135 
136         /* find the channel number of the lowest 20MHz primary channel */
137         primary = edge + CH_10MHZ_APART;
138 
139         /* select the actual subband */
140         sb = (chspec & WL_CHANSPEC_CTL_SB_MASK) >> WL_CHANSPEC_CTL_SB_SHIFT;
141         primary = primary + sb * CH_20MHZ_APART;
142 
143         return primary;
144     }
145 }
146 
147 /*
148     Take an array of measumrements representing summaries of different channels.
149     Return a recomended channel.
150     Interference is evil, get rid of that first.
151     Then hunt for lowest Other bss traffic.
152     Don't forget that channels with low duration times may not have accurate
153    readings. For the moment, do not overwrite input array.
154 */
cca_analyze(cca_congest_channel_req_t * input[],int num_chans,uint flags,chanspec_t * answer)155 int cca_analyze(cca_congest_channel_req_t *input[], int num_chans, uint flags,
156                 chanspec_t *answer)
157 {
158     uint8 *bitmap = NULL; /* 38 Max channels needs 5 bytes  = 40 */
159     int i, left, winner, ret_val = 0;
160     uint32 min_obss = 1 << 30;
161     uint bitmap_sz;
162 
163     bitmap_sz = CEIL(num_chans, NBBY);
164     bitmap = (uint8 *)malloc(bitmap_sz);
165     if (bitmap == NULL) {
166         printf("unable to allocate memory\n");
167         return BCME_NOMEM;
168     }
169 
170     memset(bitmap, 0, bitmap_sz);
171     /* Initially, all channels are up for consideration */
172     for (i = 0; i < num_chans; i++) {
173         if (input[i]->chanspec) {
174             setbit(bitmap, i);
175         }
176     }
177     cca_info(bitmap, num_chans, &left, &i);
178     if (!left) {
179         ret_val = CCA_ERRNO_TOO_FEW;
180         goto f_exit;
181     }
182 
183     /* Filter for 2.4 GHz Band */
184     if (flags & CCA_FLAG_2G_ONLY) {
185         for (i = 0; i < num_chans; i++) {
186             if (!CHSPEC_IS2G(input[i]->chanspec)) {
187                 clrbit(bitmap, i);
188             }
189         }
190     }
191     cca_info(bitmap, num_chans, &left, &i);
192     if (!left) {
193         ret_val = CCA_ERRNO_BAND;
194         goto f_exit;
195     }
196 
197     /* Filter for 5 GHz Band */
198     if (flags & CCA_FLAG_5G_ONLY) {
199         for (i = 0; i < num_chans; i++) {
200             if (!CHSPEC_IS5G(input[i]->chanspec)) {
201                 clrbit(bitmap, i);
202             }
203         }
204     }
205     cca_info(bitmap, num_chans, &left, &i);
206     if (!left) {
207         ret_val = CCA_ERRNO_BAND;
208         goto f_exit;
209     }
210 
211     /* Filter for Duration */
212     if (!(flags & CCA_FLAG_IGNORE_DURATION)) {
213         for (i = 0; i < num_chans; i++) {
214             if (input[i]->secs[0].duration < CCA_THRESH_MILLI) {
215                 clrbit(bitmap, i);
216             }
217         }
218     }
219     cca_info(bitmap, num_chans, &left, &i);
220     if (!left) {
221         ret_val = CCA_ERRNO_DURATION;
222         goto f_exit;
223     }
224 
225     /* Filter for 1 6 11 on 2.4 Band */
226     if (flags & CCA_FLAGS_PREFER_1_6_11) {
227         int tmp_channel = spec_to_chan(input[i]->chanspec);
228         int is2g = CHSPEC_IS2G(input[i]->chanspec);
229         for (i = 0; i < num_chans; i++) {
230             if (is2g && tmp_channel != 1 && tmp_channel != 0x6 &&
231                 tmp_channel != 0xB) {
232                 clrbit(bitmap, i);
233             }
234         }
235     }
236     cca_info(bitmap, num_chans, &left, &i);
237     if (!left) {
238         ret_val = CCA_ERRNO_PREF_CHAN;
239         goto f_exit;
240     }
241 
242     /* Toss high interference interference */
243     if (!(flags & CCA_FLAG_IGNORE_INTERFER)) {
244         for (i = 0; i < num_chans; i++) {
245             if (input[i]->secs[0].interference > CCA_THRESH_INTERFERE) {
246                 clrbit(bitmap, i);
247             }
248         }
249         cca_info(bitmap, num_chans, &left, &i);
250         if (!left) {
251             ret_val = CCA_ERRNO_INTERFER;
252             goto f_exit;
253         }
254     }
255 
256     /* Now find lowest obss */
257     winner = 0;
258     for (i = 0; i < num_chans; i++) {
259         if (isset(bitmap, i) && input[i]->secs[0].congest_obss < min_obss) {
260             winner = i;
261             min_obss = input[i]->secs[0].congest_obss;
262         }
263     }
264     *answer = input[winner]->chanspec;
265 f_exit:
266     free(bitmap); /* free the allocated memory for bitmap */
267     return ret_val;
268 }
269 #endif /* !BCMDRIVER */
270 
271 /* offset of cntmember by sizeof(uint32) from the first cnt variable, txframe.
272  */
273 #define IDX_IN_WL_CNT_VER_6_T(cntmember)                                       \
274     ((OFFSETOF(wl_cnt_ver_6_t, cntmember) -                                    \
275       OFFSETOF(wl_cnt_ver_6_t, txframe)) /                                     \
276      sizeof(uint32))
277 
278 #define IDX_IN_WL_CNT_VER_11_T(cntmember)                                      \
279     ((OFFSETOF(wl_cnt_ver_11_t, cntmember) -                                   \
280       OFFSETOF(wl_cnt_ver_11_t, txframe)) /                                    \
281      sizeof(uint32))
282 
283 /* Exclude version and length fields */
284 #define NUM_OF_CNT_IN_WL_CNT_VER_6_T                                           \
285     ((sizeof(wl_cnt_ver_6_t) - 2 * sizeof(uint16)) / sizeof(uint32))
286 /* Exclude macstat cnt variables. wl_cnt_ver_6_t only has 62 macstat cnt
287  * variables. */
288 #define NUM_OF_WLCCNT_IN_WL_CNT_VER_6_T                                        \
289     (NUM_OF_CNT_IN_WL_CNT_VER_6_T - (WL_CNT_MCST_VAR_NUM - 2))
290 
291 /* Exclude version and length fields */
292 #define NUM_OF_CNT_IN_WL_CNT_VER_11_T                                          \
293     ((sizeof(wl_cnt_ver_11_t) - 2 * sizeof(uint16)) / sizeof(uint32))
294 /* Exclude 64 macstat cnt variables. */
295 #define NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T                                       \
296     ((sizeof(wl_cnt_wlc_t)) / sizeof(uint32))
297 
298 /* Index conversion table from wl_cnt_ver_6_t to wl_cnt_wlc_t */
299 static const uint8 wlcntver6t_to_wlcntwlct[NUM_OF_WLCCNT_IN_WL_CNT_VER_6_T] = {
300     IDX_IN_WL_CNT_VER_6_T(txframe),
301     IDX_IN_WL_CNT_VER_6_T(txbyte),
302     IDX_IN_WL_CNT_VER_6_T(txretrans),
303     IDX_IN_WL_CNT_VER_6_T(txerror),
304     IDX_IN_WL_CNT_VER_6_T(txctl),
305     IDX_IN_WL_CNT_VER_6_T(txprshort),
306     IDX_IN_WL_CNT_VER_6_T(txserr),
307     IDX_IN_WL_CNT_VER_6_T(txnobuf),
308     IDX_IN_WL_CNT_VER_6_T(txnoassoc),
309     IDX_IN_WL_CNT_VER_6_T(txrunt),
310     IDX_IN_WL_CNT_VER_6_T(txchit),
311     IDX_IN_WL_CNT_VER_6_T(txcmiss),
312     IDX_IN_WL_CNT_VER_6_T(txuflo),
313     IDX_IN_WL_CNT_VER_6_T(txphyerr),
314     IDX_IN_WL_CNT_VER_6_T(txphycrs),
315     IDX_IN_WL_CNT_VER_6_T(rxframe),
316     IDX_IN_WL_CNT_VER_6_T(rxbyte),
317     IDX_IN_WL_CNT_VER_6_T(rxerror),
318     IDX_IN_WL_CNT_VER_6_T(rxctl),
319     IDX_IN_WL_CNT_VER_6_T(rxnobuf),
320     IDX_IN_WL_CNT_VER_6_T(rxnondata),
321     IDX_IN_WL_CNT_VER_6_T(rxbadds),
322     IDX_IN_WL_CNT_VER_6_T(rxbadcm),
323     IDX_IN_WL_CNT_VER_6_T(rxfragerr),
324     IDX_IN_WL_CNT_VER_6_T(rxrunt),
325     IDX_IN_WL_CNT_VER_6_T(rxgiant),
326     IDX_IN_WL_CNT_VER_6_T(rxnoscb),
327     IDX_IN_WL_CNT_VER_6_T(rxbadproto),
328     IDX_IN_WL_CNT_VER_6_T(rxbadsrcmac),
329     IDX_IN_WL_CNT_VER_6_T(rxbadda),
330     IDX_IN_WL_CNT_VER_6_T(rxfilter),
331     IDX_IN_WL_CNT_VER_6_T(rxoflo),
332     IDX_IN_WL_CNT_VER_6_T(rxuflo),
333     IDX_IN_WL_CNT_VER_6_T(rxuflo) + 1,
334     IDX_IN_WL_CNT_VER_6_T(rxuflo) + 2,
335     IDX_IN_WL_CNT_VER_6_T(rxuflo) + 3,
336     IDX_IN_WL_CNT_VER_6_T(rxuflo) + 4,
337     IDX_IN_WL_CNT_VER_6_T(rxuflo) + 5,
338     IDX_IN_WL_CNT_VER_6_T(d11cnt_txrts_off),
339     IDX_IN_WL_CNT_VER_6_T(d11cnt_rxcrc_off),
340     IDX_IN_WL_CNT_VER_6_T(d11cnt_txnocts_off),
341     IDX_IN_WL_CNT_VER_6_T(dmade),
342     IDX_IN_WL_CNT_VER_6_T(dmada),
343     IDX_IN_WL_CNT_VER_6_T(dmape),
344     IDX_IN_WL_CNT_VER_6_T(reset),
345     IDX_IN_WL_CNT_VER_6_T(tbtt),
346     IDX_IN_WL_CNT_VER_6_T(txdmawar),
347     IDX_IN_WL_CNT_VER_6_T(pkt_callback_reg_fail),
348     IDX_IN_WL_CNT_VER_6_T(txfrag),
349     IDX_IN_WL_CNT_VER_6_T(txmulti),
350     IDX_IN_WL_CNT_VER_6_T(txfail),
351     IDX_IN_WL_CNT_VER_6_T(txretry),
352     IDX_IN_WL_CNT_VER_6_T(txretrie),
353     IDX_IN_WL_CNT_VER_6_T(rxdup),
354     IDX_IN_WL_CNT_VER_6_T(txrts),
355     IDX_IN_WL_CNT_VER_6_T(txnocts),
356     IDX_IN_WL_CNT_VER_6_T(txnoack),
357     IDX_IN_WL_CNT_VER_6_T(rxfrag),
358     IDX_IN_WL_CNT_VER_6_T(rxmulti),
359     IDX_IN_WL_CNT_VER_6_T(rxcrc),
360     IDX_IN_WL_CNT_VER_6_T(txfrmsnt),
361     IDX_IN_WL_CNT_VER_6_T(rxundec),
362     IDX_IN_WL_CNT_VER_6_T(tkipmicfaill),
363     IDX_IN_WL_CNT_VER_6_T(tkipcntrmsr),
364     IDX_IN_WL_CNT_VER_6_T(tkipreplay),
365     IDX_IN_WL_CNT_VER_6_T(ccmpfmterr),
366     IDX_IN_WL_CNT_VER_6_T(ccmpreplay),
367     IDX_IN_WL_CNT_VER_6_T(ccmpundec),
368     IDX_IN_WL_CNT_VER_6_T(fourwayfail),
369     IDX_IN_WL_CNT_VER_6_T(wepundec),
370     IDX_IN_WL_CNT_VER_6_T(wepicverr),
371     IDX_IN_WL_CNT_VER_6_T(decsuccess),
372     IDX_IN_WL_CNT_VER_6_T(tkipicverr),
373     IDX_IN_WL_CNT_VER_6_T(wepexcluded),
374     IDX_IN_WL_CNT_VER_6_T(txchanrej),
375     IDX_IN_WL_CNT_VER_6_T(psmwds),
376     IDX_IN_WL_CNT_VER_6_T(phywatchdog),
377     IDX_IN_WL_CNT_VER_6_T(prq_entries_handled),
378     IDX_IN_WL_CNT_VER_6_T(prq_undirected_entries),
379     IDX_IN_WL_CNT_VER_6_T(prq_bad_entries),
380     IDX_IN_WL_CNT_VER_6_T(atim_suppress_count),
381     IDX_IN_WL_CNT_VER_6_T(bcn_template_not_ready),
382     IDX_IN_WL_CNT_VER_6_T(bcn_template_not_ready_done),
383     IDX_IN_WL_CNT_VER_6_T(late_tbtt_dpc),
384     IDX_IN_WL_CNT_VER_6_T(rx1mbps),
385     IDX_IN_WL_CNT_VER_6_T(rx2mbps),
386     IDX_IN_WL_CNT_VER_6_T(rx5mbps5),
387     IDX_IN_WL_CNT_VER_6_T(rx6mbps),
388     IDX_IN_WL_CNT_VER_6_T(rx9mbps),
389     IDX_IN_WL_CNT_VER_6_T(rx11mbps),
390     IDX_IN_WL_CNT_VER_6_T(rx12mbps),
391     IDX_IN_WL_CNT_VER_6_T(rx18mbps),
392     IDX_IN_WL_CNT_VER_6_T(rx24mbps),
393     IDX_IN_WL_CNT_VER_6_T(rx36mbps),
394     IDX_IN_WL_CNT_VER_6_T(rx48mbps),
395     IDX_IN_WL_CNT_VER_6_T(rx54mbps),
396     IDX_IN_WL_CNT_VER_6_T(rx108mbps),
397     IDX_IN_WL_CNT_VER_6_T(rx162mbps),
398     IDX_IN_WL_CNT_VER_6_T(rx216mbps),
399     IDX_IN_WL_CNT_VER_6_T(rx270mbps),
400     IDX_IN_WL_CNT_VER_6_T(rx324mbps),
401     IDX_IN_WL_CNT_VER_6_T(rx378mbps),
402     IDX_IN_WL_CNT_VER_6_T(rx432mbps),
403     IDX_IN_WL_CNT_VER_6_T(rx486mbps),
404     IDX_IN_WL_CNT_VER_6_T(rx540mbps),
405     IDX_IN_WL_CNT_VER_6_T(rfdisable),
406     IDX_IN_WL_CNT_VER_6_T(txexptime),
407     IDX_IN_WL_CNT_VER_6_T(txmpdu_sgi),
408     IDX_IN_WL_CNT_VER_6_T(rxmpdu_sgi),
409     IDX_IN_WL_CNT_VER_6_T(txmpdu_stbc),
410     IDX_IN_WL_CNT_VER_6_T(rxmpdu_stbc),
411     IDX_IN_WL_CNT_VER_6_T(rxundec_mcst),
412     IDX_IN_WL_CNT_VER_6_T(tkipmicfaill_mcst),
413     IDX_IN_WL_CNT_VER_6_T(tkipcntrmsr_mcst),
414     IDX_IN_WL_CNT_VER_6_T(tkipreplay_mcst),
415     IDX_IN_WL_CNT_VER_6_T(ccmpfmterr_mcst),
416     IDX_IN_WL_CNT_VER_6_T(ccmpreplay_mcst),
417     IDX_IN_WL_CNT_VER_6_T(ccmpundec_mcst),
418     IDX_IN_WL_CNT_VER_6_T(fourwayfail_mcst),
419     IDX_IN_WL_CNT_VER_6_T(wepundec_mcst),
420     IDX_IN_WL_CNT_VER_6_T(wepicverr_mcst),
421     IDX_IN_WL_CNT_VER_6_T(decsuccess_mcst),
422     IDX_IN_WL_CNT_VER_6_T(tkipicverr_mcst),
423     IDX_IN_WL_CNT_VER_6_T(wepexcluded_mcst)};
424 
425 #define INVALID_IDX ((uint8)(-1))
426 
427 /* Index conversion table from wl_cnt_ver_11_t to wl_cnt_wlc_t */
428 static const uint8 wlcntver11t_to_wlcntwlct[NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T] = {
429     IDX_IN_WL_CNT_VER_11_T(txframe),
430     IDX_IN_WL_CNT_VER_11_T(txbyte),
431     IDX_IN_WL_CNT_VER_11_T(txretrans),
432     IDX_IN_WL_CNT_VER_11_T(txerror),
433     IDX_IN_WL_CNT_VER_11_T(txctl),
434     IDX_IN_WL_CNT_VER_11_T(txprshort),
435     IDX_IN_WL_CNT_VER_11_T(txserr),
436     IDX_IN_WL_CNT_VER_11_T(txnobuf),
437     IDX_IN_WL_CNT_VER_11_T(txnoassoc),
438     IDX_IN_WL_CNT_VER_11_T(txrunt),
439     IDX_IN_WL_CNT_VER_11_T(txchit),
440     IDX_IN_WL_CNT_VER_11_T(txcmiss),
441     IDX_IN_WL_CNT_VER_11_T(txuflo),
442     IDX_IN_WL_CNT_VER_11_T(txphyerr),
443     IDX_IN_WL_CNT_VER_11_T(txphycrs),
444     IDX_IN_WL_CNT_VER_11_T(rxframe),
445     IDX_IN_WL_CNT_VER_11_T(rxbyte),
446     IDX_IN_WL_CNT_VER_11_T(rxerror),
447     IDX_IN_WL_CNT_VER_11_T(rxctl),
448     IDX_IN_WL_CNT_VER_11_T(rxnobuf),
449     IDX_IN_WL_CNT_VER_11_T(rxnondata),
450     IDX_IN_WL_CNT_VER_11_T(rxbadds),
451     IDX_IN_WL_CNT_VER_11_T(rxbadcm),
452     IDX_IN_WL_CNT_VER_11_T(rxfragerr),
453     IDX_IN_WL_CNT_VER_11_T(rxrunt),
454     IDX_IN_WL_CNT_VER_11_T(rxgiant),
455     IDX_IN_WL_CNT_VER_11_T(rxnoscb),
456     IDX_IN_WL_CNT_VER_11_T(rxbadproto),
457     IDX_IN_WL_CNT_VER_11_T(rxbadsrcmac),
458     IDX_IN_WL_CNT_VER_11_T(rxbadda),
459     IDX_IN_WL_CNT_VER_11_T(rxfilter),
460     IDX_IN_WL_CNT_VER_11_T(rxoflo),
461     IDX_IN_WL_CNT_VER_11_T(rxuflo),
462     IDX_IN_WL_CNT_VER_11_T(rxuflo) + 1,
463     IDX_IN_WL_CNT_VER_11_T(rxuflo) + 2,
464     IDX_IN_WL_CNT_VER_11_T(rxuflo) + 3,
465     IDX_IN_WL_CNT_VER_11_T(rxuflo) + 4,
466     IDX_IN_WL_CNT_VER_11_T(rxuflo) + 5,
467     IDX_IN_WL_CNT_VER_11_T(d11cnt_txrts_off),
468     IDX_IN_WL_CNT_VER_11_T(d11cnt_rxcrc_off),
469     IDX_IN_WL_CNT_VER_11_T(d11cnt_txnocts_off),
470     IDX_IN_WL_CNT_VER_11_T(dmade),
471     IDX_IN_WL_CNT_VER_11_T(dmada),
472     IDX_IN_WL_CNT_VER_11_T(dmape),
473     IDX_IN_WL_CNT_VER_11_T(reset),
474     IDX_IN_WL_CNT_VER_11_T(tbtt),
475     IDX_IN_WL_CNT_VER_11_T(txdmawar),
476     IDX_IN_WL_CNT_VER_11_T(pkt_callback_reg_fail),
477     IDX_IN_WL_CNT_VER_11_T(txfrag),
478     IDX_IN_WL_CNT_VER_11_T(txmulti),
479     IDX_IN_WL_CNT_VER_11_T(txfail),
480     IDX_IN_WL_CNT_VER_11_T(txretry),
481     IDX_IN_WL_CNT_VER_11_T(txretrie),
482     IDX_IN_WL_CNT_VER_11_T(rxdup),
483     IDX_IN_WL_CNT_VER_11_T(txrts),
484     IDX_IN_WL_CNT_VER_11_T(txnocts),
485     IDX_IN_WL_CNT_VER_11_T(txnoack),
486     IDX_IN_WL_CNT_VER_11_T(rxfrag),
487     IDX_IN_WL_CNT_VER_11_T(rxmulti),
488     IDX_IN_WL_CNT_VER_11_T(rxcrc),
489     IDX_IN_WL_CNT_VER_11_T(txfrmsnt),
490     IDX_IN_WL_CNT_VER_11_T(rxundec),
491     IDX_IN_WL_CNT_VER_11_T(tkipmicfaill),
492     IDX_IN_WL_CNT_VER_11_T(tkipcntrmsr),
493     IDX_IN_WL_CNT_VER_11_T(tkipreplay),
494     IDX_IN_WL_CNT_VER_11_T(ccmpfmterr),
495     IDX_IN_WL_CNT_VER_11_T(ccmpreplay),
496     IDX_IN_WL_CNT_VER_11_T(ccmpundec),
497     IDX_IN_WL_CNT_VER_11_T(fourwayfail),
498     IDX_IN_WL_CNT_VER_11_T(wepundec),
499     IDX_IN_WL_CNT_VER_11_T(wepicverr),
500     IDX_IN_WL_CNT_VER_11_T(decsuccess),
501     IDX_IN_WL_CNT_VER_11_T(tkipicverr),
502     IDX_IN_WL_CNT_VER_11_T(wepexcluded),
503     IDX_IN_WL_CNT_VER_11_T(txchanrej),
504     IDX_IN_WL_CNT_VER_11_T(psmwds),
505     IDX_IN_WL_CNT_VER_11_T(phywatchdog),
506     IDX_IN_WL_CNT_VER_11_T(prq_entries_handled),
507     IDX_IN_WL_CNT_VER_11_T(prq_undirected_entries),
508     IDX_IN_WL_CNT_VER_11_T(prq_bad_entries),
509     IDX_IN_WL_CNT_VER_11_T(atim_suppress_count),
510     IDX_IN_WL_CNT_VER_11_T(bcn_template_not_ready),
511     IDX_IN_WL_CNT_VER_11_T(bcn_template_not_ready_done),
512     IDX_IN_WL_CNT_VER_11_T(late_tbtt_dpc),
513     IDX_IN_WL_CNT_VER_11_T(rx1mbps),
514     IDX_IN_WL_CNT_VER_11_T(rx2mbps),
515     IDX_IN_WL_CNT_VER_11_T(rx5mbps5),
516     IDX_IN_WL_CNT_VER_11_T(rx6mbps),
517     IDX_IN_WL_CNT_VER_11_T(rx9mbps),
518     IDX_IN_WL_CNT_VER_11_T(rx11mbps),
519     IDX_IN_WL_CNT_VER_11_T(rx12mbps),
520     IDX_IN_WL_CNT_VER_11_T(rx18mbps),
521     IDX_IN_WL_CNT_VER_11_T(rx24mbps),
522     IDX_IN_WL_CNT_VER_11_T(rx36mbps),
523     IDX_IN_WL_CNT_VER_11_T(rx48mbps),
524     IDX_IN_WL_CNT_VER_11_T(rx54mbps),
525     IDX_IN_WL_CNT_VER_11_T(rx108mbps),
526     IDX_IN_WL_CNT_VER_11_T(rx162mbps),
527     IDX_IN_WL_CNT_VER_11_T(rx216mbps),
528     IDX_IN_WL_CNT_VER_11_T(rx270mbps),
529     IDX_IN_WL_CNT_VER_11_T(rx324mbps),
530     IDX_IN_WL_CNT_VER_11_T(rx378mbps),
531     IDX_IN_WL_CNT_VER_11_T(rx432mbps),
532     IDX_IN_WL_CNT_VER_11_T(rx486mbps),
533     IDX_IN_WL_CNT_VER_11_T(rx540mbps),
534     IDX_IN_WL_CNT_VER_11_T(rfdisable),
535     IDX_IN_WL_CNT_VER_11_T(txexptime),
536     IDX_IN_WL_CNT_VER_11_T(txmpdu_sgi),
537     IDX_IN_WL_CNT_VER_11_T(rxmpdu_sgi),
538     IDX_IN_WL_CNT_VER_11_T(txmpdu_stbc),
539     IDX_IN_WL_CNT_VER_11_T(rxmpdu_stbc),
540     IDX_IN_WL_CNT_VER_11_T(rxundec_mcst),
541     IDX_IN_WL_CNT_VER_11_T(tkipmicfaill_mcst),
542     IDX_IN_WL_CNT_VER_11_T(tkipcntrmsr_mcst),
543     IDX_IN_WL_CNT_VER_11_T(tkipreplay_mcst),
544     IDX_IN_WL_CNT_VER_11_T(ccmpfmterr_mcst),
545     IDX_IN_WL_CNT_VER_11_T(ccmpreplay_mcst),
546     IDX_IN_WL_CNT_VER_11_T(ccmpundec_mcst),
547     IDX_IN_WL_CNT_VER_11_T(fourwayfail_mcst),
548     IDX_IN_WL_CNT_VER_11_T(wepundec_mcst),
549     IDX_IN_WL_CNT_VER_11_T(wepicverr_mcst),
550     IDX_IN_WL_CNT_VER_11_T(decsuccess_mcst),
551     IDX_IN_WL_CNT_VER_11_T(tkipicverr_mcst),
552     IDX_IN_WL_CNT_VER_11_T(wepexcluded_mcst),
553     IDX_IN_WL_CNT_VER_11_T(dma_hang),
554     IDX_IN_WL_CNT_VER_11_T(reinit),
555     IDX_IN_WL_CNT_VER_11_T(pstatxucast),
556     IDX_IN_WL_CNT_VER_11_T(pstatxnoassoc),
557     IDX_IN_WL_CNT_VER_11_T(pstarxucast),
558     IDX_IN_WL_CNT_VER_11_T(pstarxbcmc),
559     IDX_IN_WL_CNT_VER_11_T(pstatxbcmc),
560     IDX_IN_WL_CNT_VER_11_T(cso_passthrough),
561     IDX_IN_WL_CNT_VER_11_T(cso_normal),
562     IDX_IN_WL_CNT_VER_11_T(chained),
563     IDX_IN_WL_CNT_VER_11_T(chainedsz1),
564     IDX_IN_WL_CNT_VER_11_T(unchained),
565     IDX_IN_WL_CNT_VER_11_T(maxchainsz),
566     IDX_IN_WL_CNT_VER_11_T(currchainsz),
567     IDX_IN_WL_CNT_VER_11_T(pciereset),
568     IDX_IN_WL_CNT_VER_11_T(cfgrestore),
569     IDX_IN_WL_CNT_VER_11_T(reinitreason),
570     IDX_IN_WL_CNT_VER_11_T(reinitreason) + 1,
571     IDX_IN_WL_CNT_VER_11_T(reinitreason) + 2,
572     IDX_IN_WL_CNT_VER_11_T(reinitreason) + 3,
573     IDX_IN_WL_CNT_VER_11_T(reinitreason) + 4,
574     IDX_IN_WL_CNT_VER_11_T(reinitreason) + 5,
575     IDX_IN_WL_CNT_VER_11_T(reinitreason) + 6,
576     IDX_IN_WL_CNT_VER_11_T(reinitreason) + 7,
577     IDX_IN_WL_CNT_VER_11_T(rxrtry),
578     IDX_IN_WL_CNT_VER_11_T(rxmpdu_mu),
579     IDX_IN_WL_CNT_VER_11_T(txbar),
580     IDX_IN_WL_CNT_VER_11_T(rxbar),
581     IDX_IN_WL_CNT_VER_11_T(txpspoll),
582     IDX_IN_WL_CNT_VER_11_T(rxpspoll),
583     IDX_IN_WL_CNT_VER_11_T(txnull),
584     IDX_IN_WL_CNT_VER_11_T(rxnull),
585     IDX_IN_WL_CNT_VER_11_T(txqosnull),
586     IDX_IN_WL_CNT_VER_11_T(rxqosnull),
587     IDX_IN_WL_CNT_VER_11_T(txassocreq),
588     IDX_IN_WL_CNT_VER_11_T(rxassocreq),
589     IDX_IN_WL_CNT_VER_11_T(txreassocreq),
590     IDX_IN_WL_CNT_VER_11_T(rxreassocreq),
591     IDX_IN_WL_CNT_VER_11_T(txdisassoc),
592     IDX_IN_WL_CNT_VER_11_T(rxdisassoc),
593     IDX_IN_WL_CNT_VER_11_T(txassocrsp),
594     IDX_IN_WL_CNT_VER_11_T(rxassocrsp),
595     IDX_IN_WL_CNT_VER_11_T(txreassocrsp),
596     IDX_IN_WL_CNT_VER_11_T(rxreassocrsp),
597     IDX_IN_WL_CNT_VER_11_T(txauth),
598     IDX_IN_WL_CNT_VER_11_T(rxauth),
599     IDX_IN_WL_CNT_VER_11_T(txdeauth),
600     IDX_IN_WL_CNT_VER_11_T(rxdeauth),
601     IDX_IN_WL_CNT_VER_11_T(txprobereq),
602     IDX_IN_WL_CNT_VER_11_T(rxprobereq),
603     IDX_IN_WL_CNT_VER_11_T(txprobersp),
604     IDX_IN_WL_CNT_VER_11_T(rxprobersp),
605     IDX_IN_WL_CNT_VER_11_T(txaction),
606     IDX_IN_WL_CNT_VER_11_T(rxaction),
607     IDX_IN_WL_CNT_VER_11_T(ampdu_wds),
608     IDX_IN_WL_CNT_VER_11_T(txlost),
609     IDX_IN_WL_CNT_VER_11_T(txdatamcast),
610     IDX_IN_WL_CNT_VER_11_T(txdatabcast),
611     INVALID_IDX,
612     IDX_IN_WL_CNT_VER_11_T(rxback),
613     IDX_IN_WL_CNT_VER_11_T(txback),
614     INVALID_IDX,
615     INVALID_IDX,
616     INVALID_IDX,
617     INVALID_IDX,
618     IDX_IN_WL_CNT_VER_11_T(txbcast),
619     IDX_IN_WL_CNT_VER_11_T(txdropped),
620     IDX_IN_WL_CNT_VER_11_T(rxbcast),
621     IDX_IN_WL_CNT_VER_11_T(rxdropped)};
622 
623 /* Index conversion table from wl_cnt_ver_11_t to
624  * either wl_cnt_ge40mcst_v1_t or wl_cnt_lt40mcst_v1_t
625  */
626 static const uint8 wlcntver11t_to_wlcntXX40mcstv1t[WL_CNT_MCST_VAR_NUM] = {
627     IDX_IN_WL_CNT_VER_11_T(txallfrm),
628     IDX_IN_WL_CNT_VER_11_T(txrtsfrm),
629     IDX_IN_WL_CNT_VER_11_T(txctsfrm),
630     IDX_IN_WL_CNT_VER_11_T(txackfrm),
631     IDX_IN_WL_CNT_VER_11_T(txdnlfrm),
632     IDX_IN_WL_CNT_VER_11_T(txbcnfrm),
633     IDX_IN_WL_CNT_VER_11_T(txfunfl),
634     IDX_IN_WL_CNT_VER_11_T(txfunfl) + 1,
635     IDX_IN_WL_CNT_VER_11_T(txfunfl) + 2,
636     IDX_IN_WL_CNT_VER_11_T(txfunfl) + 3,
637     IDX_IN_WL_CNT_VER_11_T(txfunfl) + 4,
638     IDX_IN_WL_CNT_VER_11_T(txfunfl) + 5,
639     IDX_IN_WL_CNT_VER_11_T(txfbw),
640     IDX_IN_WL_CNT_VER_11_T(txmpdu),
641     IDX_IN_WL_CNT_VER_11_T(txtplunfl),
642     IDX_IN_WL_CNT_VER_11_T(txphyerror),
643     IDX_IN_WL_CNT_VER_11_T(pktengrxducast),
644     IDX_IN_WL_CNT_VER_11_T(pktengrxdmcast),
645     IDX_IN_WL_CNT_VER_11_T(rxfrmtoolong),
646     IDX_IN_WL_CNT_VER_11_T(rxfrmtooshrt),
647     IDX_IN_WL_CNT_VER_11_T(rxinvmachdr),
648     IDX_IN_WL_CNT_VER_11_T(rxbadfcs),
649     IDX_IN_WL_CNT_VER_11_T(rxbadplcp),
650     IDX_IN_WL_CNT_VER_11_T(rxcrsglitch),
651     IDX_IN_WL_CNT_VER_11_T(rxstrt),
652     IDX_IN_WL_CNT_VER_11_T(rxdfrmucastmbss),
653     IDX_IN_WL_CNT_VER_11_T(rxmfrmucastmbss),
654     IDX_IN_WL_CNT_VER_11_T(rxcfrmucast),
655     IDX_IN_WL_CNT_VER_11_T(rxrtsucast),
656     IDX_IN_WL_CNT_VER_11_T(rxctsucast),
657     IDX_IN_WL_CNT_VER_11_T(rxackucast),
658     IDX_IN_WL_CNT_VER_11_T(rxdfrmocast),
659     IDX_IN_WL_CNT_VER_11_T(rxmfrmocast),
660     IDX_IN_WL_CNT_VER_11_T(rxcfrmocast),
661     IDX_IN_WL_CNT_VER_11_T(rxrtsocast),
662     IDX_IN_WL_CNT_VER_11_T(rxctsocast),
663     IDX_IN_WL_CNT_VER_11_T(rxdfrmmcast),
664     IDX_IN_WL_CNT_VER_11_T(rxmfrmmcast),
665     IDX_IN_WL_CNT_VER_11_T(rxcfrmmcast),
666     IDX_IN_WL_CNT_VER_11_T(rxbeaconmbss),
667     IDX_IN_WL_CNT_VER_11_T(rxdfrmucastobss),
668     IDX_IN_WL_CNT_VER_11_T(rxbeaconobss),
669     IDX_IN_WL_CNT_VER_11_T(rxrsptmout),
670     IDX_IN_WL_CNT_VER_11_T(bcntxcancl),
671     IDX_IN_WL_CNT_VER_11_T(rxnodelim),
672     IDX_IN_WL_CNT_VER_11_T(rxf0ovfl),
673     IDX_IN_WL_CNT_VER_11_T(rxf1ovfl),
674     IDX_IN_WL_CNT_VER_11_T(rxf2ovfl),
675     IDX_IN_WL_CNT_VER_11_T(txsfovfl),
676     IDX_IN_WL_CNT_VER_11_T(pmqovfl),
677     IDX_IN_WL_CNT_VER_11_T(rxcgprqfrm),
678     IDX_IN_WL_CNT_VER_11_T(rxcgprsqovfl),
679     IDX_IN_WL_CNT_VER_11_T(txcgprsfail),
680     IDX_IN_WL_CNT_VER_11_T(txcgprssuc),
681     IDX_IN_WL_CNT_VER_11_T(prs_timeout),
682     IDX_IN_WL_CNT_VER_11_T(rxnack),
683     IDX_IN_WL_CNT_VER_11_T(frmscons),
684     IDX_IN_WL_CNT_VER_11_T(txnack),
685     IDX_IN_WL_CNT_VER_11_T(rxback),
686     IDX_IN_WL_CNT_VER_11_T(txback),
687     IDX_IN_WL_CNT_VER_11_T(bphy_rxcrsglitch),
688     IDX_IN_WL_CNT_VER_11_T(rxdrop20s),
689     IDX_IN_WL_CNT_VER_11_T(rxtoolate),
690     IDX_IN_WL_CNT_VER_11_T(bphy_badplcp)};
691 
692 /* For mcst offsets that were not used. (2 Pads) */
693 #define INVALID_MCST_IDX ((uint8)(-1))
694 /* Index conversion table from wl_cnt_ver_11_t to wl_cnt_v_le10_mcst_t */
695 static const uint8 wlcntver11t_to_wlcntvle10mcstt[WL_CNT_MCST_VAR_NUM] = {
696     IDX_IN_WL_CNT_VER_11_T(txallfrm),
697     IDX_IN_WL_CNT_VER_11_T(txrtsfrm),
698     IDX_IN_WL_CNT_VER_11_T(txctsfrm),
699     IDX_IN_WL_CNT_VER_11_T(txackfrm),
700     IDX_IN_WL_CNT_VER_11_T(txdnlfrm),
701     IDX_IN_WL_CNT_VER_11_T(txbcnfrm),
702     IDX_IN_WL_CNT_VER_11_T(txfunfl),
703     IDX_IN_WL_CNT_VER_11_T(txfunfl) + 1,
704     IDX_IN_WL_CNT_VER_11_T(txfunfl) + 2,
705     IDX_IN_WL_CNT_VER_11_T(txfunfl) + 3,
706     IDX_IN_WL_CNT_VER_11_T(txfunfl) + 4,
707     IDX_IN_WL_CNT_VER_11_T(txfunfl) + 5,
708     IDX_IN_WL_CNT_VER_11_T(txfbw),
709     INVALID_MCST_IDX,
710     IDX_IN_WL_CNT_VER_11_T(txtplunfl),
711     IDX_IN_WL_CNT_VER_11_T(txphyerror),
712     IDX_IN_WL_CNT_VER_11_T(pktengrxducast),
713     IDX_IN_WL_CNT_VER_11_T(pktengrxdmcast),
714     IDX_IN_WL_CNT_VER_11_T(rxfrmtoolong),
715     IDX_IN_WL_CNT_VER_11_T(rxfrmtooshrt),
716     IDX_IN_WL_CNT_VER_11_T(rxinvmachdr),
717     IDX_IN_WL_CNT_VER_11_T(rxbadfcs),
718     IDX_IN_WL_CNT_VER_11_T(rxbadplcp),
719     IDX_IN_WL_CNT_VER_11_T(rxcrsglitch),
720     IDX_IN_WL_CNT_VER_11_T(rxstrt),
721     IDX_IN_WL_CNT_VER_11_T(rxdfrmucastmbss),
722     IDX_IN_WL_CNT_VER_11_T(rxmfrmucastmbss),
723     IDX_IN_WL_CNT_VER_11_T(rxcfrmucast),
724     IDX_IN_WL_CNT_VER_11_T(rxrtsucast),
725     IDX_IN_WL_CNT_VER_11_T(rxctsucast),
726     IDX_IN_WL_CNT_VER_11_T(rxackucast),
727     IDX_IN_WL_CNT_VER_11_T(rxdfrmocast),
728     IDX_IN_WL_CNT_VER_11_T(rxmfrmocast),
729     IDX_IN_WL_CNT_VER_11_T(rxcfrmocast),
730     IDX_IN_WL_CNT_VER_11_T(rxrtsocast),
731     IDX_IN_WL_CNT_VER_11_T(rxctsocast),
732     IDX_IN_WL_CNT_VER_11_T(rxdfrmmcast),
733     IDX_IN_WL_CNT_VER_11_T(rxmfrmmcast),
734     IDX_IN_WL_CNT_VER_11_T(rxcfrmmcast),
735     IDX_IN_WL_CNT_VER_11_T(rxbeaconmbss),
736     IDX_IN_WL_CNT_VER_11_T(rxdfrmucastobss),
737     IDX_IN_WL_CNT_VER_11_T(rxbeaconobss),
738     IDX_IN_WL_CNT_VER_11_T(rxrsptmout),
739     IDX_IN_WL_CNT_VER_11_T(bcntxcancl),
740     INVALID_MCST_IDX,
741     IDX_IN_WL_CNT_VER_11_T(rxf0ovfl),
742     IDX_IN_WL_CNT_VER_11_T(rxf1ovfl),
743     IDX_IN_WL_CNT_VER_11_T(rxf2ovfl),
744     IDX_IN_WL_CNT_VER_11_T(txsfovfl),
745     IDX_IN_WL_CNT_VER_11_T(pmqovfl),
746     IDX_IN_WL_CNT_VER_11_T(rxcgprqfrm),
747     IDX_IN_WL_CNT_VER_11_T(rxcgprsqovfl),
748     IDX_IN_WL_CNT_VER_11_T(txcgprsfail),
749     IDX_IN_WL_CNT_VER_11_T(txcgprssuc),
750     IDX_IN_WL_CNT_VER_11_T(prs_timeout),
751     IDX_IN_WL_CNT_VER_11_T(rxnack),
752     IDX_IN_WL_CNT_VER_11_T(frmscons),
753     IDX_IN_WL_CNT_VER_11_T(txnack),
754     IDX_IN_WL_CNT_VER_11_T(rxback),
755     IDX_IN_WL_CNT_VER_11_T(txback),
756     IDX_IN_WL_CNT_VER_11_T(bphy_rxcrsglitch),
757     IDX_IN_WL_CNT_VER_11_T(rxdrop20s),
758     IDX_IN_WL_CNT_VER_11_T(rxtoolate),
759     IDX_IN_WL_CNT_VER_11_T(bphy_badplcp)};
760 
761 /* Index conversion table from wl_cnt_ver_6_t to wl_cnt_v_le10_mcst_t */
762 static const uint8 wlcntver6t_to_wlcntvle10mcstt[WL_CNT_MCST_VAR_NUM] = {
763     IDX_IN_WL_CNT_VER_6_T(txallfrm),
764     IDX_IN_WL_CNT_VER_6_T(txrtsfrm),
765     IDX_IN_WL_CNT_VER_6_T(txctsfrm),
766     IDX_IN_WL_CNT_VER_6_T(txackfrm),
767     IDX_IN_WL_CNT_VER_6_T(txdnlfrm),
768     IDX_IN_WL_CNT_VER_6_T(txbcnfrm),
769     IDX_IN_WL_CNT_VER_6_T(txfunfl),
770     IDX_IN_WL_CNT_VER_6_T(txfunfl) + 1,
771     IDX_IN_WL_CNT_VER_6_T(txfunfl) + 2,
772     IDX_IN_WL_CNT_VER_6_T(txfunfl) + 3,
773     IDX_IN_WL_CNT_VER_6_T(txfunfl) + 4,
774     IDX_IN_WL_CNT_VER_6_T(txfunfl) + 5,
775     IDX_IN_WL_CNT_VER_6_T(txfbw),
776     INVALID_MCST_IDX,
777     IDX_IN_WL_CNT_VER_6_T(txtplunfl),
778     IDX_IN_WL_CNT_VER_6_T(txphyerror),
779     IDX_IN_WL_CNT_VER_6_T(pktengrxducast),
780     IDX_IN_WL_CNT_VER_6_T(pktengrxdmcast),
781     IDX_IN_WL_CNT_VER_6_T(rxfrmtoolong),
782     IDX_IN_WL_CNT_VER_6_T(rxfrmtooshrt),
783     IDX_IN_WL_CNT_VER_6_T(rxinvmachdr),
784     IDX_IN_WL_CNT_VER_6_T(rxbadfcs),
785     IDX_IN_WL_CNT_VER_6_T(rxbadplcp),
786     IDX_IN_WL_CNT_VER_6_T(rxcrsglitch),
787     IDX_IN_WL_CNT_VER_6_T(rxstrt),
788     IDX_IN_WL_CNT_VER_6_T(rxdfrmucastmbss),
789     IDX_IN_WL_CNT_VER_6_T(rxmfrmucastmbss),
790     IDX_IN_WL_CNT_VER_6_T(rxcfrmucast),
791     IDX_IN_WL_CNT_VER_6_T(rxrtsucast),
792     IDX_IN_WL_CNT_VER_6_T(rxctsucast),
793     IDX_IN_WL_CNT_VER_6_T(rxackucast),
794     IDX_IN_WL_CNT_VER_6_T(rxdfrmocast),
795     IDX_IN_WL_CNT_VER_6_T(rxmfrmocast),
796     IDX_IN_WL_CNT_VER_6_T(rxcfrmocast),
797     IDX_IN_WL_CNT_VER_6_T(rxrtsocast),
798     IDX_IN_WL_CNT_VER_6_T(rxctsocast),
799     IDX_IN_WL_CNT_VER_6_T(rxdfrmmcast),
800     IDX_IN_WL_CNT_VER_6_T(rxmfrmmcast),
801     IDX_IN_WL_CNT_VER_6_T(rxcfrmmcast),
802     IDX_IN_WL_CNT_VER_6_T(rxbeaconmbss),
803     IDX_IN_WL_CNT_VER_6_T(rxdfrmucastobss),
804     IDX_IN_WL_CNT_VER_6_T(rxbeaconobss),
805     IDX_IN_WL_CNT_VER_6_T(rxrsptmout),
806     IDX_IN_WL_CNT_VER_6_T(bcntxcancl),
807     INVALID_MCST_IDX,
808     IDX_IN_WL_CNT_VER_6_T(rxf0ovfl),
809     IDX_IN_WL_CNT_VER_6_T(rxf1ovfl),
810     IDX_IN_WL_CNT_VER_6_T(rxf2ovfl),
811     IDX_IN_WL_CNT_VER_6_T(txsfovfl),
812     IDX_IN_WL_CNT_VER_6_T(pmqovfl),
813     IDX_IN_WL_CNT_VER_6_T(rxcgprqfrm),
814     IDX_IN_WL_CNT_VER_6_T(rxcgprsqovfl),
815     IDX_IN_WL_CNT_VER_6_T(txcgprsfail),
816     IDX_IN_WL_CNT_VER_6_T(txcgprssuc),
817     IDX_IN_WL_CNT_VER_6_T(prs_timeout),
818     IDX_IN_WL_CNT_VER_6_T(rxnack),
819     IDX_IN_WL_CNT_VER_6_T(frmscons),
820     IDX_IN_WL_CNT_VER_6_T(txnack),
821     IDX_IN_WL_CNT_VER_6_T(rxback),
822     IDX_IN_WL_CNT_VER_6_T(txback),
823     IDX_IN_WL_CNT_VER_6_T(bphy_rxcrsglitch),
824     IDX_IN_WL_CNT_VER_6_T(rxdrop20s),
825     IDX_IN_WL_CNT_VER_6_T(rxtoolate),
826     IDX_IN_WL_CNT_VER_6_T(bphy_badplcp)};
827 
828 /* copy wlc layer counters from old type cntbuf to wl_cnt_wlc_t type. */
wl_copy_wlccnt(uint16 cntver,uint32 * dst,uint32 * src,uint8 src_max_idx)829 static int wl_copy_wlccnt(uint16 cntver, uint32 *dst, uint32 *src,
830                           uint8 src_max_idx)
831 {
832     uint i;
833     if (dst == NULL || src == NULL) {
834         return BCME_ERROR;
835     }
836 
837     /* Init wlccnt with invalid value. Unchanged value will not be printed out
838      */
839     for (i = 0; i < (sizeof(wl_cnt_wlc_t) / sizeof(uint32)); i++) {
840         dst[i] = INVALID_CNT_VAL;
841     }
842 
843     if (cntver == WL_CNT_VERSION_6) {
844         for (i = 0; i < NUM_OF_WLCCNT_IN_WL_CNT_VER_6_T; i++) {
845             if (wlcntver6t_to_wlcntwlct[i] >= src_max_idx) {
846                 /* src buffer does not have counters from here */
847                 break;
848             }
849             dst[i] = src[wlcntver6t_to_wlcntwlct[i]];
850         }
851     } else {
852         for (i = 0; i < NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T; i++) {
853             if (wlcntver11t_to_wlcntwlct[i] >= src_max_idx) {
854                 if (wlcntver11t_to_wlcntwlct[i] == INVALID_IDX) {
855                     continue;
856                 } else {
857                     /* src buffer does not have counters from here */
858                     break;
859                 }
860             }
861             dst[i] = src[wlcntver11t_to_wlcntwlct[i]];
862         }
863     }
864     return BCME_OK;
865 }
866 
867 /* copy macstat counters from old type cntbuf to wl_cnt_v_le10_mcst_t type. */
wl_copy_macstat_upto_ver10(uint16 cntver,uint32 * dst,uint32 * src)868 static int wl_copy_macstat_upto_ver10(uint16 cntver, uint32 *dst, uint32 *src)
869 {
870     uint i;
871 
872     if (dst == NULL || src == NULL) {
873         return BCME_ERROR;
874     }
875 
876     if (cntver == WL_CNT_VERSION_6) {
877         for (i = 0; i < WL_CNT_MCST_VAR_NUM; i++) {
878             if (wlcntver6t_to_wlcntvle10mcstt[i] == INVALID_MCST_IDX) {
879                 /* This mcst counter does not exist in wl_cnt_ver_6_t */
880                 dst[i] = INVALID_CNT_VAL;
881             } else {
882                 dst[i] = src[wlcntver6t_to_wlcntvle10mcstt[i]];
883             }
884         }
885     } else {
886         for (i = 0; i < WL_CNT_MCST_VAR_NUM; i++) {
887             if (wlcntver11t_to_wlcntvle10mcstt[i] == INVALID_MCST_IDX) {
888                 /* This mcst counter does not exist in wl_cnt_ver_11_t */
889                 dst[i] = INVALID_CNT_VAL;
890             } else {
891                 dst[i] = src[wlcntver11t_to_wlcntvle10mcstt[i]];
892             }
893         }
894     }
895     return BCME_OK;
896 }
897 
wl_copy_macstat_ver11(uint32 * dst,uint32 * src)898 static int wl_copy_macstat_ver11(uint32 *dst, uint32 *src)
899 {
900     uint i;
901 
902     if (dst == NULL || src == NULL) {
903         return BCME_ERROR;
904     }
905 
906     for (i = 0; i < WL_CNT_MCST_VAR_NUM; i++) {
907         dst[i] = src[wlcntver11t_to_wlcntXX40mcstv1t[i]];
908     }
909     return BCME_OK;
910 }
911 
912 /**
913  * Translate non-xtlv 'wl counters' IOVar buffer received by old driver/FW to
914  * xtlv format. Parameters: cntbuf: pointer to non-xtlv 'wl counters' IOVar
915  * buffer received by old driver/FW. Newly translated xtlv format is written to
916  * this pointer. buflen: length of the "cntbuf" without any padding. corerev:
917  * chip core revision of the driver/FW.
918  */
wl_cntbuf_to_xtlv_format(void * ctx,void * cntbuf,int buflen,uint32 corerev)919 int wl_cntbuf_to_xtlv_format(void *ctx, void *cntbuf, int buflen,
920                              uint32 corerev)
921 {
922     wl_cnt_wlc_t *wlccnt = NULL;
923     uint32 *macstat = NULL;
924     xtlv_desc_t xtlv_desc[3];
925     uint16 mcst_xtlv_id;
926     int res = BCME_OK;
927     wl_cnt_info_t *cntinfo = cntbuf;
928     uint8 *xtlvbuf_p = cntinfo->data;
929     uint16 ver = cntinfo->version;
930     uint16 xtlvbuflen = (uint16)buflen;
931     uint16 src_max_idx;
932 #ifdef BCMDRIVER
933     osl_t *osh = ctx;
934 #else
935     BCM_REFERENCE(ctx);
936 #endif // endif
937 
938     if (ver >= WL_CNT_VERSION_XTLV) {
939         /* Already in xtlv format. */
940         goto exit;
941     }
942 
943 #ifdef BCMDRIVER
944     wlccnt = MALLOC(osh, sizeof(*wlccnt));
945     macstat = MALLOC(osh, WL_CNT_MCST_STRUCT_SZ);
946 #else
947     wlccnt = (wl_cnt_wlc_t *)malloc(sizeof(*wlccnt));
948     macstat = (uint32 *)malloc(WL_CNT_MCST_STRUCT_SZ);
949 #endif // endif
950     if (!wlccnt || !macstat) {
951         printf("%s: malloc fail!\n", __FUNCTION__);
952         res = BCME_NOMEM;
953         goto exit;
954     }
955 
956     /* Check if the max idx in the struct exceeds the boundary of uint8 */
957     if (NUM_OF_CNT_IN_WL_CNT_VER_6_T > ((uint8)(-1) + 1) ||
958         NUM_OF_CNT_IN_WL_CNT_VER_11_T > ((uint8)(-1) + 1)) {
959         printf("wlcntverXXt_to_wlcntwlct and src_max_idx need"
960                " to be of uint16 instead of uint8\n");
961         res = BCME_ERROR;
962         goto exit;
963     }
964 
965     /* Exclude version and length fields in either wlc_cnt_ver_6_t or
966      * wlc_cnt_ver_11_t */
967     src_max_idx =
968         (cntinfo->datalen - OFFSETOF(wl_cnt_info_t, data)) / sizeof(uint32);
969     if (src_max_idx > (uint8)(-1)) {
970         printf("wlcntverXXt_to_wlcntwlct and src_max_idx need"
971                " to be of uint16 instead of uint8\n"
972                "Try updating wl utility to the latest.\n");
973         src_max_idx = (uint8)(-1);
974     }
975 
976     /* Copy wlc layer counters to wl_cnt_wlc_t */
977     res = wl_copy_wlccnt(ver, (uint32 *)wlccnt, (uint32 *)cntinfo->data,
978                          (uint8)src_max_idx);
979     if (res != BCME_OK) {
980         printf("wl_copy_wlccnt fail!\n");
981         goto exit;
982     }
983 
984     /* Copy macstat counters to wl_cnt_wlc_t */
985     if (ver == WL_CNT_VERSION_11) {
986         res = wl_copy_macstat_ver11(macstat, (uint32 *)cntinfo->data);
987         if (res != BCME_OK) {
988             printf("wl_copy_macstat_ver11 fail!\n");
989             goto exit;
990         }
991         if (corerev >= 0x28) {
992             mcst_xtlv_id = WL_CNT_XTLV_GE40_UCODE_V1;
993         } else {
994             mcst_xtlv_id = WL_CNT_XTLV_LT40_UCODE_V1;
995         }
996     } else {
997         res = wl_copy_macstat_upto_ver10(ver, macstat, (uint32 *)cntinfo->data);
998         if (res != BCME_OK) {
999             printf("wl_copy_macstat_upto_ver10 fail!\n");
1000             goto exit;
1001         }
1002         mcst_xtlv_id = WL_CNT_XTLV_CNTV_LE10_UCODE;
1003     }
1004 
1005     xtlv_desc[0].type = WL_CNT_XTLV_WLC;
1006     xtlv_desc[0].len = sizeof(*wlccnt);
1007     xtlv_desc[0].ptr = wlccnt;
1008 
1009     xtlv_desc[1].type = mcst_xtlv_id;
1010     xtlv_desc[1].len = WL_CNT_MCST_STRUCT_SZ;
1011     xtlv_desc[1].ptr = macstat;
1012 
1013     xtlv_desc[0x2].type = 0;
1014     xtlv_desc[0x2].len = 0;
1015     xtlv_desc[0x2].ptr = NULL;
1016 
1017     memset(cntbuf, 0, buflen);
1018 
1019     res = bcm_pack_xtlv_buf_from_mem(&xtlvbuf_p, &xtlvbuflen, xtlv_desc,
1020                                      BCM_XTLV_OPTION_ALIGN32);
1021     cntinfo->datalen = (buflen - xtlvbuflen);
1022 exit:
1023 #ifdef BCMDRIVER
1024     if (wlccnt) {
1025         MFREE(osh, wlccnt, sizeof(*wlccnt));
1026     }
1027     if (macstat) {
1028         MFREE(osh, macstat, WL_CNT_MCST_STRUCT_SZ);
1029     }
1030 #else
1031     if (wlccnt) {
1032         free(wlccnt);
1033     }
1034     if (macstat) {
1035         free(macstat);
1036     }
1037 #endif // endif
1038     return res;
1039 }
1040