forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/bcmutils.c
....@@ -1,15 +1,16 @@
1
-/* SPDX-License-Identifier: GPL-2.0 */
21 /*
32 * Driver O/S-independent utility routines
43 *
5
- * Copyright (C) 1999-2019, Broadcom Corporation
6
- *
4
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
5
+ *
6
+ * Copyright (C) 1999-2017, Broadcom Corporation
7
+ *
78 * Unless you and Broadcom execute a separate written software license
89 * agreement governing use of this software, this software is licensed to you
910 * under the terms of the GNU General Public License version 2 (the "GPL"),
1011 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
1112 * following added to such license:
12
- *
13
+ *
1314 * As a special exception, the copyright holders of this software give you
1415 * permission to link this software with independent modules, and to copy and
1516 * distribute the resulting executable under terms of your choice, provided that
....@@ -17,7 +18,7 @@
1718 * the license of that module. An independent module is a module which is not
1819 * derived from this software. The special exception does not apply to any
1920 * modifications of the software.
20
- *
21
+ *
2122 * Notwithstanding the above, under no circumstances may you combine this
2223 * software in any way with any other Broadcom software provided under a license
2324 * other than the GPL, without Broadcom's express prior written consent.
....@@ -25,7 +26,7 @@
2526 *
2627 * <<Broadcom-WL-IPTag/Open:>>
2728 *
28
- * $Id: bcmutils.c 692666 2018-07-30 08:58:07Z $
29
+ * $Id: bcmutils.c 702105 2017-05-30 19:10:39Z $
2930 */
3031
3132 #include <bcm_cfg.h>
....@@ -33,7 +34,6 @@
3334 #include <bcmdefs.h>
3435 #include <stdarg.h>
3536 #ifdef BCMDRIVER
36
-
3737 #include <osl.h>
3838 #include <bcmutils.h>
3939
....@@ -41,99 +41,39 @@
4141
4242 #include <stdio.h>
4343 #include <string.h>
44
+#include <bcm_math.h>
4445 #include <bcmutils.h>
4546
4647 #if defined(BCMEXTSUP)
4748 #include <bcm_osl.h>
48
-#endif
49
+#endif // endif
4950
5051 #ifndef ASSERT
5152 #define ASSERT(exp)
52
-#endif
53
+#endif // endif
5354
5455 #endif /* !BCMDRIVER */
5556
57
+#ifdef WL_UNITTEST
58
+#ifdef ASSERT
59
+#undef ASSERT
60
+#endif /* ASSERT */
61
+#define ASSERT(exp)
62
+#endif /* WL_UNITTEST */
63
+
64
+#include <bcmstdlib_s.h>
5665 #include <bcmendian.h>
5766 #include <bcmdevs.h>
58
-#include <proto/ethernet.h>
59
-#include <proto/vlan.h>
60
-#include <proto/bcmip.h>
61
-#include <proto/802.1d.h>
62
-#include <proto/802.11.h>
63
-
64
-
65
-void *_bcmutils_dummy_fn = NULL;
66
-
67
-
68
-
67
+#include <ethernet.h>
68
+#include <vlan.h>
69
+#include <bcmip.h>
70
+#include <802.1d.h>
71
+#include <802.11.h>
72
+#include <bcmip.h>
73
+#include <bcmipv6.h>
74
+#include <bcmtcp.h>
6975
7076 #ifdef BCMDRIVER
71
-
72
-
73
-
74
-/* copy a pkt buffer chain into a buffer */
75
-uint
76
-pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf)
77
-{
78
- uint n, ret = 0;
79
-
80
- if (len < 0)
81
- len = 4096; /* "infinite" */
82
-
83
- /* skip 'offset' bytes */
84
- for (; p && offset; p = PKTNEXT(osh, p)) {
85
- if (offset < (uint)PKTLEN(osh, p))
86
- break;
87
- offset -= PKTLEN(osh, p);
88
- }
89
-
90
- if (!p)
91
- return 0;
92
-
93
- /* copy the data */
94
- for (; p && len; p = PKTNEXT(osh, p)) {
95
- n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
96
- bcopy(PKTDATA(osh, p) + offset, buf, n);
97
- buf += n;
98
- len -= n;
99
- ret += n;
100
- offset = 0;
101
- }
102
-
103
- return ret;
104
-}
105
-
106
-/* copy a buffer into a pkt buffer chain */
107
-uint
108
-pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf)
109
-{
110
- uint n, ret = 0;
111
-
112
-
113
- /* skip 'offset' bytes */
114
- for (; p && offset; p = PKTNEXT(osh, p)) {
115
- if (offset < (uint)PKTLEN(osh, p))
116
- break;
117
- offset -= PKTLEN(osh, p);
118
- }
119
-
120
- if (!p)
121
- return 0;
122
-
123
- /* copy the data */
124
- for (; p && len; p = PKTNEXT(osh, p)) {
125
- n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
126
- bcopy(buf, PKTDATA(osh, p) + offset, n);
127
- buf += n;
128
- len -= n;
129
- ret += n;
130
- offset = 0;
131
- }
132
-
133
- return ret;
134
-}
135
-
136
-
13777
13878 /* return total length of buffer chain */
13979 uint BCMFASTPATH
....@@ -145,14 +85,14 @@
14585 total = 0;
14686 for (; p; p = PKTNEXT(osh, p)) {
14787 len = PKTLEN(osh, p);
148
- total += len;
88
+ total += (uint)len;
14989 #ifdef BCMLFRAG
15090 if (BCMLFRAG_ENAB()) {
15191 if (PKTISFRAG(osh, p)) {
15292 total += PKTFRAGTOTLEN(osh, p);
15393 }
15494 }
155
-#endif
95
+#endif // endif
15696 }
15797
15898 return (total);
....@@ -182,41 +122,71 @@
182122 cnt += PKTFRAGTOTNUM(osh, p);
183123 }
184124 }
185
-#endif
125
+#endif // endif
186126 }
187127
188128 return cnt;
189129 }
190130
191
-
192
-/* count segments of a chained packet */
193
-uint BCMFASTPATH
194
-pktsegcnt_war(osl_t *osh, void *p)
131
+/* copy a pkt buffer chain into a buffer */
132
+uint
133
+pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf)
195134 {
196
- uint cnt;
197
- uint8 *pktdata;
198
- uint len, remain, align64;
135
+ uint n, ret = 0;
199136
200
- for (cnt = 0; p; p = PKTNEXT(osh, p)) {
201
- cnt++;
202
- len = PKTLEN(osh, p);
203
- if (len > 128) {
204
- pktdata = (uint8 *)PKTDATA(osh, p); /* starting address of data */
205
- /* Check for page boundary straddle (2048B) */
206
- if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff))
207
- cnt++;
137
+ if (len < 0)
138
+ len = 4096; /* "infinite" */
208139
209
- align64 = (uint)((uintptr)pktdata & 0x3f); /* aligned to 64B */
210
- align64 = (64 - align64) & 0x3f;
211
- len -= align64; /* bytes from aligned 64B to end */
212
- /* if aligned to 128B, check for MOD 128 between 1 to 4B */
213
- remain = len % 128;
214
- if (remain > 0 && remain <= 4)
215
- cnt++; /* add extra seg */
216
- }
140
+ /* skip 'offset' bytes */
141
+ for (; p && offset; p = PKTNEXT(osh, p)) {
142
+ if (offset < (uint)PKTLEN(osh, p))
143
+ break;
144
+ offset -= (uint)PKTLEN(osh, p);
217145 }
218146
219
- return cnt;
147
+ if (!p)
148
+ return 0;
149
+
150
+ /* copy the data */
151
+ for (; p && len; p = PKTNEXT(osh, p)) {
152
+ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
153
+ bcopy(PKTDATA(osh, p) + offset, buf, n);
154
+ buf += n;
155
+ len -= n;
156
+ ret += n;
157
+ offset = 0;
158
+ }
159
+
160
+ return ret;
161
+}
162
+
163
+/* copy a buffer into a pkt buffer chain */
164
+uint
165
+pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf)
166
+{
167
+ uint n, ret = 0;
168
+
169
+ /* skip 'offset' bytes */
170
+ for (; p && offset; p = PKTNEXT(osh, p)) {
171
+ if (offset < (uint)PKTLEN(osh, p))
172
+ break;
173
+ offset -= (uint)PKTLEN(osh, p);
174
+ }
175
+
176
+ if (!p)
177
+ return 0;
178
+
179
+ /* copy the data */
180
+ for (; p && len; p = PKTNEXT(osh, p)) {
181
+ n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len);
182
+ bcopy(buf, PKTDATA(osh, p) + offset, n);
183
+ buf += n;
184
+ len -= n;
185
+ ret += n;
186
+ offset = 0;
187
+ }
188
+
189
+ return ret;
220190 }
221191
222192 uint8 * BCMFASTPATH
....@@ -232,13 +202,12 @@
232202 for (; p; p = PKTNEXT(osh, p)) {
233203 pdata = (uint8 *) PKTDATA(osh, p);
234204 pkt_off = offset - len;
235
- len += PKTLEN(osh, p);
205
+ len += (uint)PKTLEN(osh, p);
236206 if (len > offset)
237207 break;
238208 }
239209 return (uint8*) (pdata+pkt_off);
240210 }
241
-
242211
243212 /* given a offset in pdata, find the pkt seg hdr */
244213 void *
....@@ -251,14 +220,1479 @@
251220 return NULL;
252221
253222 for (; p; p = PKTNEXT(osh, p)) {
254
- len += PKTLEN(osh, p);
223
+ len += (uint)PKTLEN(osh, p);
255224 if (len > offset)
256225 break;
257226 }
258227 return p;
259228 }
260229
230
+void
231
+bcm_mdelay(uint ms)
232
+{
233
+ uint i;
234
+
235
+ for (i = 0; i < ms; i++) {
236
+ OSL_DELAY(1000);
237
+ }
238
+}
239
+
240
+#if defined(DHD_DEBUG)
241
+/* pretty hex print a pkt buffer chain */
242
+void
243
+prpkt(const char *msg, osl_t *osh, void *p0)
244
+{
245
+ void *p;
246
+
247
+ if (msg && (msg[0] != '\0'))
248
+ printf("%s:\n", msg);
249
+
250
+ for (p = p0; p; p = PKTNEXT(osh, p))
251
+ prhex(NULL, PKTDATA(osh, p), (uint)PKTLEN(osh, p));
252
+}
253
+#endif // endif
254
+
255
+/* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
256
+ * Also updates the inplace vlan tag if requested.
257
+ * For debugging, it returns an indication of what it did.
258
+ */
259
+uint BCMFASTPATH
260
+pktsetprio(void *pkt, bool update_vtag)
261
+{
262
+ struct ether_header *eh;
263
+ struct ethervlan_header *evh;
264
+ uint8 *pktdata;
265
+ uint priority = 0;
266
+ uint rc = 0;
267
+
268
+ pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
269
+ ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
270
+
271
+ eh = (struct ether_header *) pktdata;
272
+
273
+ if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) {
274
+ uint16 vlan_tag;
275
+ uint vlan_prio, dscp_prio = 0;
276
+
277
+ evh = (struct ethervlan_header *)eh;
278
+
279
+ vlan_tag = ntoh16(evh->vlan_tag);
280
+ vlan_prio = (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
281
+
282
+ if ((evh->ether_type == hton16(ETHER_TYPE_IP)) ||
283
+ (evh->ether_type == hton16(ETHER_TYPE_IPV6))) {
284
+ uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
285
+ uint8 tos_tc = (uint8)IP_TOS46(ip_body);
286
+ dscp_prio = tos_tc >> IPV4_TOS_PREC_SHIFT;
287
+ }
288
+
289
+ /* DSCP priority gets precedence over 802.1P (vlan tag) */
290
+ if (dscp_prio != 0) {
291
+ priority = dscp_prio;
292
+ rc |= PKTPRIO_VDSCP;
293
+ } else {
294
+ priority = vlan_prio;
295
+ rc |= PKTPRIO_VLAN;
296
+ }
297
+ /*
298
+ * If the DSCP priority is not the same as the VLAN priority,
299
+ * then overwrite the priority field in the vlan tag, with the
300
+ * DSCP priority value. This is required for Linux APs because
301
+ * the VLAN driver on Linux, overwrites the skb->priority field
302
+ * with the priority value in the vlan tag
303
+ */
304
+ if (update_vtag && (priority != vlan_prio)) {
305
+ vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
306
+ vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
307
+ evh->vlan_tag = hton16(vlan_tag);
308
+ rc |= PKTPRIO_UPD;
309
+ }
310
+#if defined(EAPOL_PKT_PRIO) || defined(DHD_LOSSLESS_ROAMING)
311
+ } else if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
312
+ priority = PRIO_8021D_NC;
313
+ rc = PKTPRIO_DSCP;
314
+#endif /* EAPOL_PKT_PRIO || DHD_LOSSLESS_ROAMING */
315
+ } else if ((eh->ether_type == hton16(ETHER_TYPE_IP)) ||
316
+ (eh->ether_type == hton16(ETHER_TYPE_IPV6))) {
317
+ uint8 *ip_body = pktdata + sizeof(struct ether_header);
318
+ uint8 tos_tc = (uint8)IP_TOS46(ip_body);
319
+ uint8 dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT;
320
+ switch (dscp) {
321
+ case DSCP_EF:
322
+ case DSCP_VA:
323
+ priority = PRIO_8021D_VO;
324
+ break;
325
+ case DSCP_AF31:
326
+ case DSCP_AF32:
327
+ case DSCP_AF33:
328
+ case DSCP_CS3:
329
+ priority = PRIO_8021D_CL;
330
+ break;
331
+ case DSCP_AF21:
332
+ case DSCP_AF22:
333
+ case DSCP_AF23:
334
+ priority = PRIO_8021D_EE;
335
+ break;
336
+ case DSCP_AF11:
337
+ case DSCP_AF12:
338
+ case DSCP_AF13:
339
+ case DSCP_CS2:
340
+ priority = PRIO_8021D_BE;
341
+ break;
342
+ case DSCP_CS6:
343
+ case DSCP_CS7:
344
+ priority = PRIO_8021D_NC;
345
+ break;
346
+ default:
347
+ priority = tos_tc >> IPV4_TOS_PREC_SHIFT;
348
+ break;
349
+ }
350
+
351
+ rc |= PKTPRIO_DSCP;
352
+ }
353
+
354
+ ASSERT(priority <= MAXPRIO);
355
+ PKTSETPRIO(pkt, (int)priority);
356
+ return (rc | priority);
357
+}
358
+
359
+/* lookup user priority for specified DSCP */
360
+static uint8
361
+dscp2up(uint8 *up_table, uint8 dscp)
362
+{
363
+ uint8 user_priority = 255;
364
+
365
+ /* lookup up from table if parameters valid */
366
+ if (up_table != NULL && dscp < UP_TABLE_MAX) {
367
+ user_priority = up_table[dscp];
368
+ }
369
+
370
+ /* 255 is unused value so return up from dscp */
371
+ if (user_priority == 255) {
372
+ user_priority = dscp >> (IPV4_TOS_PREC_SHIFT - IPV4_TOS_DSCP_SHIFT);
373
+ }
374
+
375
+ return user_priority;
376
+}
377
+
378
+/* set user priority by QoS Map Set table (UP table), table size is UP_TABLE_MAX */
379
+uint BCMFASTPATH
380
+pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag)
381
+{
382
+ if (up_table) {
383
+ uint8 *pktdata;
384
+ uint pktlen;
385
+ uint8 dscp;
386
+ uint user_priority = 0;
387
+ uint rc = 0;
388
+
389
+ pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
390
+ pktlen = (uint)PKTLEN(OSH_NULL, pkt);
391
+
392
+ if (pktgetdscp(pktdata, pktlen, &dscp)) {
393
+ rc = PKTPRIO_DSCP;
394
+ user_priority = dscp2up(up_table, dscp);
395
+ PKTSETPRIO(pkt, (int)user_priority);
396
+ }
397
+
398
+ return (rc | user_priority);
399
+ } else {
400
+ return pktsetprio(pkt, update_vtag);
401
+ }
402
+}
403
+
404
+/* Returns TRUE and DSCP if IP header found, FALSE otherwise.
405
+ */
406
+bool BCMFASTPATH
407
+pktgetdscp(uint8 *pktdata, uint pktlen, uint8 *dscp)
408
+{
409
+ struct ether_header *eh;
410
+ struct ethervlan_header *evh;
411
+ uint8 *ip_body;
412
+ bool rc = FALSE;
413
+
414
+ /* minimum length is ether header and IP header */
415
+ if (pktlen < sizeof(struct ether_header) + IPV4_MIN_HEADER_LEN)
416
+ return FALSE;
417
+
418
+ eh = (struct ether_header *) pktdata;
419
+
420
+ if (eh->ether_type == HTON16(ETHER_TYPE_IP)) {
421
+ ip_body = pktdata + sizeof(struct ether_header);
422
+ *dscp = (uint8)IP_DSCP46(ip_body);
423
+ rc = TRUE;
424
+ }
425
+ else if (eh->ether_type == HTON16(ETHER_TYPE_8021Q)) {
426
+ evh = (struct ethervlan_header *)eh;
427
+
428
+ /* minimum length is ethervlan header and IP header */
429
+ if (pktlen >= sizeof(struct ethervlan_header) + IPV4_MIN_HEADER_LEN &&
430
+ evh->ether_type == HTON16(ETHER_TYPE_IP)) {
431
+ ip_body = pktdata + sizeof(struct ethervlan_header);
432
+ *dscp = (uint8)IP_DSCP46(ip_body);
433
+ rc = TRUE;
434
+ }
435
+ }
436
+
437
+ return rc;
438
+}
439
+
440
+/* usr_prio range from low to high with usr_prio value */
441
+static bool
442
+up_table_set(uint8 *up_table, uint8 usr_prio, uint8 low, uint8 high)
443
+{
444
+ int i;
445
+
446
+ if (usr_prio > 7 || low > high || low >= UP_TABLE_MAX || high >= UP_TABLE_MAX) {
447
+ return FALSE;
448
+ }
449
+
450
+ for (i = low; i <= high; i++) {
451
+ up_table[i] = usr_prio;
452
+ }
453
+
454
+ return TRUE;
455
+}
456
+
457
+/* set user priority table */
458
+int BCMFASTPATH
459
+wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie)
460
+{
461
+ uint8 len;
462
+
463
+ if (up_table == NULL || qos_map_ie == NULL) {
464
+ return BCME_ERROR;
465
+ }
466
+
467
+ /* clear table to check table was set or not */
468
+ memset(up_table, 0xff, UP_TABLE_MAX);
469
+
470
+ /* length of QoS Map IE must be 16+n*2, n is number of exceptions */
471
+ if (qos_map_ie != NULL && qos_map_ie->id == DOT11_MNG_QOS_MAP_ID &&
472
+ (len = qos_map_ie->len) >= QOS_MAP_FIXED_LENGTH &&
473
+ (len % 2) == 0) {
474
+ uint8 *except_ptr = (uint8 *)qos_map_ie->data;
475
+ uint8 except_len = len - QOS_MAP_FIXED_LENGTH;
476
+ uint8 *range_ptr = except_ptr + except_len;
477
+ uint8 i;
478
+
479
+ /* fill in ranges */
480
+ for (i = 0; i < QOS_MAP_FIXED_LENGTH; i += 2) {
481
+ uint8 low = range_ptr[i];
482
+ uint8 high = range_ptr[i + 1];
483
+ if (low == 255 && high == 255) {
484
+ continue;
485
+ }
486
+
487
+ if (!up_table_set(up_table, i / 2, low, high)) {
488
+ /* clear the table on failure */
489
+ memset(up_table, 0xff, UP_TABLE_MAX);
490
+ return BCME_ERROR;
491
+ }
492
+ }
493
+
494
+ /* update exceptions */
495
+ for (i = 0; i < except_len; i += 2) {
496
+ uint8 dscp = except_ptr[i];
497
+ uint8 usr_prio = except_ptr[i+1];
498
+
499
+ /* exceptions with invalid dscp/usr_prio are ignored */
500
+ up_table_set(up_table, usr_prio, dscp, dscp);
501
+ }
502
+ }
503
+
504
+ return BCME_OK;
505
+}
506
+
507
+/* The 0.5KB string table is not removed by compiler even though it's unused */
508
+
509
+static char bcm_undeferrstr[32];
510
+static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
511
+
512
+/* Convert the error codes into related error strings */
513
+const char *
514
+BCMRAMFN(bcmerrorstr)(int bcmerror)
515
+{
516
+ /* check if someone added a bcmerror code but forgot to add errorstring */
517
+ ASSERT((uint)ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1));
518
+
519
+ if (bcmerror > 0 || bcmerror < BCME_LAST) {
520
+ snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror);
521
+ return bcm_undeferrstr;
522
+ }
523
+
524
+ ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN);
525
+
526
+ return bcmerrorstrtable[-bcmerror];
527
+}
528
+
529
+/* iovar table lookup */
530
+/* could mandate sorted tables and do a binary search */
531
+const bcm_iovar_t*
532
+bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
533
+{
534
+ const bcm_iovar_t *vi;
535
+ const char *lookup_name;
536
+
537
+ /* skip any ':' delimited option prefixes */
538
+ lookup_name = strrchr(name, ':');
539
+ if (lookup_name != NULL)
540
+ lookup_name++;
541
+ else
542
+ lookup_name = name;
543
+
544
+ ASSERT(table != NULL);
545
+
546
+ for (vi = table; vi->name; vi++) {
547
+ if (!strcmp(vi->name, lookup_name))
548
+ return vi;
549
+ }
550
+ /* ran to end of table */
551
+
552
+ return NULL; /* var name not found */
553
+}
554
+
555
+int
556
+bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
557
+{
558
+ int bcmerror = 0;
559
+ BCM_REFERENCE(arg);
560
+
561
+ /* length check on io buf */
562
+ switch (vi->type) {
563
+ case IOVT_BOOL:
564
+ case IOVT_INT8:
565
+ case IOVT_INT16:
566
+ case IOVT_INT32:
567
+ case IOVT_UINT8:
568
+ case IOVT_UINT16:
569
+ case IOVT_UINT32:
570
+ /* all integers are int32 sized args at the ioctl interface */
571
+ if (len < (int)sizeof(int)) {
572
+ bcmerror = BCME_BUFTOOSHORT;
573
+ }
574
+ break;
575
+
576
+ case IOVT_BUFFER:
577
+ /* buffer must meet minimum length requirement */
578
+ if (len < vi->minlen) {
579
+ bcmerror = BCME_BUFTOOSHORT;
580
+ }
581
+ break;
582
+
583
+ case IOVT_VOID:
584
+ if (!set) {
585
+ /* Cannot return nil... */
586
+ bcmerror = BCME_UNSUPPORTED;
587
+ }
588
+ break;
589
+
590
+ default:
591
+ /* unknown type for length check in iovar info */
592
+ ASSERT(0);
593
+ bcmerror = BCME_UNSUPPORTED;
594
+ }
595
+
596
+ return bcmerror;
597
+}
598
+
599
+#if !defined(_CFEZ_)
600
+/*
601
+ * Hierarchical Multiword bitmap based small id allocator.
602
+ *
603
+ * Multilevel hierarchy bitmap. (maximum 2 levels)
604
+ * First hierarchy uses a multiword bitmap to identify 32bit words in the
605
+ * second hierarchy that have at least a single bit set. Each bit in a word of
606
+ * the second hierarchy represents a unique ID that may be allocated.
607
+ *
608
+ * BCM_MWBMAP_ITEMS_MAX: Maximum number of IDs managed.
609
+ * BCM_MWBMAP_BITS_WORD: Number of bits in a bitmap word word
610
+ * BCM_MWBMAP_WORDS_MAX: Maximum number of bitmap words needed for free IDs.
611
+ * BCM_MWBMAP_WDMAP_MAX: Maximum number of bitmap wordss identifying first non
612
+ * non-zero bitmap word carrying at least one free ID.
613
+ * BCM_MWBMAP_SHIFT_OP: Used in MOD, DIV and MUL operations.
614
+ * BCM_MWBMAP_INVALID_IDX: Value ~0U is treated as an invalid ID
615
+ *
616
+ * Design Notes:
617
+ * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many
618
+ * bits are computed each time on allocation and deallocation, requiring 4
619
+ * array indexed access and 3 arithmetic operations. When not defined, a runtime
620
+ * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed.
621
+ * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation.
622
+ * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may
623
+ * be used by defining BCM_MWBMAP_USE_CNTSETBITS.
624
+ *
625
+ * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array
626
+ * size is fixed. No intention to support larger than 4K indice allocation. ID
627
+ * allocators for ranges smaller than 4K will have a wastage of only 12Bytes
628
+ * with savings in not having to use an indirect access, had it been dynamically
629
+ * allocated.
630
+ */
631
+#define BCM_MWBMAP_ITEMS_MAX (64 * 1024) /* May increase to 64K */
632
+
633
+#define BCM_MWBMAP_BITS_WORD (NBITS(uint32))
634
+#define BCM_MWBMAP_WORDS_MAX (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD)
635
+#define BCM_MWBMAP_WDMAP_MAX (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD)
636
+#define BCM_MWBMAP_SHIFT_OP (5)
637
+#define BCM_MWBMAP_MODOP(ix) ((ix) & (BCM_MWBMAP_BITS_WORD - 1))
638
+#define BCM_MWBMAP_DIVOP(ix) ((ix) >> BCM_MWBMAP_SHIFT_OP)
639
+#define BCM_MWBMAP_MULOP(ix) ((ix) << BCM_MWBMAP_SHIFT_OP)
640
+
641
+/* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */
642
+#define BCM_MWBMAP_PTR(hdl) ((struct bcm_mwbmap *)(hdl))
643
+#define BCM_MWBMAP_HDL(ptr) ((void *)(ptr))
644
+
645
+#if defined(BCM_MWBMAP_DEBUG)
646
+#define BCM_MWBMAP_AUDIT(mwb) \
647
+ do { \
648
+ ASSERT((mwb != NULL) && \
649
+ (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \
650
+ bcm_mwbmap_audit(mwb); \
651
+ } while (0)
652
+#define MWBMAP_ASSERT(exp) ASSERT(exp)
653
+#define MWBMAP_DBG(x) printf x
654
+#else /* !BCM_MWBMAP_DEBUG */
655
+#define BCM_MWBMAP_AUDIT(mwb) do {} while (0)
656
+#define MWBMAP_ASSERT(exp) do {} while (0)
657
+#define MWBMAP_DBG(x)
658
+#endif /* !BCM_MWBMAP_DEBUG */
659
+
660
+typedef struct bcm_mwbmap { /* Hierarchical multiword bitmap allocator */
661
+ uint16 wmaps; /* Total number of words in free wd bitmap */
662
+ uint16 imaps; /* Total number of words in free id bitmap */
663
+ int32 ifree; /* Count of free indices. Used only in audits */
664
+ uint16 total; /* Total indices managed by multiword bitmap */
665
+
666
+ void * magic; /* Audit handle parameter from user */
667
+
668
+ uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of */
669
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
670
+ int8 wd_count[BCM_MWBMAP_WORDS_MAX]; /* free id running count, 1st lvl */
671
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
672
+
673
+ uint32 id_bitmap[0]; /* Second level bitmap */
674
+} bcm_mwbmap_t;
675
+
676
+/* Incarnate a hierarchical multiword bitmap based small index allocator. */
677
+struct bcm_mwbmap *
678
+bcm_mwbmap_init(osl_t *osh, uint32 items_max)
679
+{
680
+ struct bcm_mwbmap * mwbmap_p;
681
+ uint32 wordix, size, words, extra;
682
+
683
+ /* Implementation Constraint: Uses 32bit word bitmap */
684
+ MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U);
685
+ MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U);
686
+ MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX));
687
+ MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U);
688
+
689
+ ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX);
690
+
691
+ /* Determine the number of words needed in the multiword bitmap */
692
+ extra = BCM_MWBMAP_MODOP(items_max);
693
+ words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U);
694
+
695
+ /* Allocate runtime state of multiword bitmap */
696
+ /* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */
697
+ size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words);
698
+ mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size);
699
+ if (mwbmap_p == (bcm_mwbmap_t *)NULL) {
700
+ ASSERT(0);
701
+ goto error1;
702
+ }
703
+ memset(mwbmap_p, 0, size);
704
+
705
+ /* Initialize runtime multiword bitmap state */
706
+ mwbmap_p->imaps = (uint16)words;
707
+ mwbmap_p->ifree = (int32)items_max;
708
+ mwbmap_p->total = (uint16)items_max;
709
+
710
+ /* Setup magic, for use in audit of handle */
711
+ mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p);
712
+
713
+ /* Setup the second level bitmap of free indices */
714
+ /* Mark all indices as available */
715
+ for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) {
716
+ mwbmap_p->id_bitmap[wordix] = (uint32)(~0U);
717
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
718
+ mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD;
719
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
720
+ }
721
+
722
+ /* Ensure that extra indices are tagged as un-available */
723
+ if (extra) { /* fixup the free ids in last bitmap and wd_count */
724
+ uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1];
725
+ *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
726
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
727
+ mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */
728
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
729
+ }
730
+
731
+ /* Setup the first level bitmap hierarchy */
732
+ extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps);
733
+ words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U);
734
+
735
+ mwbmap_p->wmaps = (uint16)words;
736
+
737
+ for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++)
738
+ mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U);
739
+ if (extra) {
740
+ uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1];
741
+ *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
742
+ }
743
+
744
+ return mwbmap_p;
745
+
746
+error1:
747
+ return BCM_MWBMAP_INVALID_HDL;
748
+}
749
+
750
+/* Release resources used by multiword bitmap based small index allocator. */
751
+void
752
+bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl)
753
+{
754
+ bcm_mwbmap_t * mwbmap_p;
755
+
756
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
757
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
758
+
759
+ MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap)
760
+ + (sizeof(uint32) * mwbmap_p->imaps));
761
+ return;
762
+}
763
+
764
+/* Allocate a unique small index using a multiword bitmap index allocator. */
765
+uint32 BCMFASTPATH
766
+bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl)
767
+{
768
+ bcm_mwbmap_t * mwbmap_p;
769
+ uint32 wordix, bitmap;
770
+
771
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
772
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
773
+
774
+ /* Start with the first hierarchy */
775
+ for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) {
776
+
777
+ bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */
778
+
779
+ if (bitmap != 0U) {
780
+
781
+ uint32 count, bitix, *bitmap_p;
782
+
783
+ bitmap_p = &mwbmap_p->wd_bitmap[wordix];
784
+
785
+ /* clear all except trailing 1 */
786
+ bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
787
+ MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
788
+ bcm_count_leading_zeros(bitmap));
789
+ bitix = (BCM_MWBMAP_BITS_WORD - 1)
790
+ - (uint32)bcm_count_leading_zeros(bitmap); /* use asm clz */
791
+ wordix = BCM_MWBMAP_MULOP(wordix) + bitix;
792
+
793
+ /* Clear bit if wd count is 0, without conditional branch */
794
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
795
+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1;
796
+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
797
+ mwbmap_p->wd_count[wordix]--;
798
+ count = (uint32)mwbmap_p->wd_count[wordix];
799
+ MWBMAP_ASSERT(count ==
800
+ (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1));
801
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
802
+ MWBMAP_ASSERT(count >= 0);
803
+
804
+ /* clear wd_bitmap bit if id_map count is 0 */
805
+ bitmap = ((uint32)(count == 0)) << BCM_MWBMAP_MODOP(bitix);
806
+
807
+ MWBMAP_DBG((
808
+ "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
809
+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count));
810
+
811
+ *bitmap_p ^= bitmap;
812
+
813
+ /* Use bitix in the second hierarchy */
814
+ bitmap_p = &mwbmap_p->id_bitmap[wordix];
815
+
816
+ bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */
817
+ MWBMAP_ASSERT(bitmap != 0U);
818
+
819
+ /* clear all except trailing 1 */
820
+ bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
821
+ MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
822
+ bcm_count_leading_zeros(bitmap));
823
+ bitix = BCM_MWBMAP_MULOP(wordix)
824
+ + (BCM_MWBMAP_BITS_WORD - 1)
825
+ - (uint32)bcm_count_leading_zeros(bitmap); /* use asm clz */
826
+
827
+ mwbmap_p->ifree--; /* decrement system wide free count */
828
+ MWBMAP_ASSERT(mwbmap_p->ifree >= 0);
829
+
830
+ MWBMAP_DBG((
831
+ "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d",
832
+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
833
+ mwbmap_p->ifree));
834
+
835
+ *bitmap_p ^= bitmap; /* mark as allocated = 1b0 */
836
+
837
+ return bitix;
838
+ }
839
+ }
840
+
841
+ ASSERT(mwbmap_p->ifree == 0);
842
+
843
+ return BCM_MWBMAP_INVALID_IDX;
844
+}
845
+
846
+/* Force an index at a specified position to be in use */
847
+void
848
+bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
849
+{
850
+ bcm_mwbmap_t * mwbmap_p;
851
+ uint32 count, wordix, bitmap, *bitmap_p;
852
+
853
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
854
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
855
+
856
+ ASSERT(bitix < mwbmap_p->total);
857
+
858
+ /* Start with second hierarchy */
859
+ wordix = BCM_MWBMAP_DIVOP(bitix);
860
+ bitmap = (uint32)(1U << BCM_MWBMAP_MODOP(bitix));
861
+ bitmap_p = &mwbmap_p->id_bitmap[wordix];
862
+
863
+ ASSERT((*bitmap_p & bitmap) == bitmap);
864
+
865
+ mwbmap_p->ifree--; /* update free count */
866
+ ASSERT(mwbmap_p->ifree >= 0);
867
+
868
+ MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d",
869
+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
870
+ mwbmap_p->ifree));
871
+
872
+ *bitmap_p ^= bitmap; /* mark as in use */
873
+
874
+ /* Update first hierarchy */
875
+ bitix = wordix;
876
+
877
+ wordix = BCM_MWBMAP_DIVOP(bitix);
878
+ bitmap_p = &mwbmap_p->wd_bitmap[wordix];
879
+
880
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
881
+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
882
+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
883
+ mwbmap_p->wd_count[bitix]--;
884
+ count = (uint32)mwbmap_p->wd_count[bitix];
885
+ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
886
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
887
+ MWBMAP_ASSERT(count >= 0);
888
+
889
+ bitmap = (uint32)(count == 0) << BCM_MWBMAP_MODOP(bitix);
890
+
891
+ MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
892
+ BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap,
893
+ (*bitmap_p) ^ bitmap, count));
894
+
895
+ *bitmap_p ^= bitmap; /* mark as in use */
896
+
897
+ return;
898
+}
899
+
900
+/* Free a previously allocated index back into the multiword bitmap allocator */
901
+void BCMFASTPATH
902
+bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
903
+{
904
+ bcm_mwbmap_t * mwbmap_p;
905
+ uint32 wordix, bitmap, *bitmap_p;
906
+
907
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
908
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
909
+
910
+ ASSERT(bitix < mwbmap_p->total);
911
+
912
+ /* Start with second level hierarchy */
913
+ wordix = BCM_MWBMAP_DIVOP(bitix);
914
+ bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
915
+ bitmap_p = &mwbmap_p->id_bitmap[wordix];
916
+
917
+ ASSERT((*bitmap_p & bitmap) == 0U); /* ASSERT not a double free */
918
+
919
+ mwbmap_p->ifree++; /* update free count */
920
+ ASSERT(mwbmap_p->ifree <= mwbmap_p->total);
921
+
922
+ MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d",
923
+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap,
924
+ mwbmap_p->ifree));
925
+
926
+ *bitmap_p |= bitmap; /* mark as available */
927
+
928
+ /* Now update first level hierarchy */
929
+
930
+ bitix = wordix;
931
+
932
+ wordix = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */
933
+ bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
934
+ bitmap_p = &mwbmap_p->wd_bitmap[wordix];
935
+
936
+#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
937
+ mwbmap_p->wd_count[bitix]++;
938
+#endif // endif
939
+
940
+#if defined(BCM_MWBMAP_DEBUG)
941
+ {
942
+ uint32 count;
943
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
944
+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
945
+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
946
+ count = mwbmap_p->wd_count[bitix];
947
+ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
948
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
949
+
950
+ MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD);
951
+
952
+ MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d",
953
+ bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count));
954
+ }
955
+#endif /* BCM_MWBMAP_DEBUG */
956
+
957
+ *bitmap_p |= bitmap;
958
+
959
+ return;
960
+}
961
+
962
+/* Fetch the toal number of free indices in the multiword bitmap allocator */
963
+uint32
964
+bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl)
965
+{
966
+ bcm_mwbmap_t * mwbmap_p;
967
+
968
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
969
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
970
+
971
+ ASSERT(mwbmap_p->ifree >= 0);
972
+
973
+ return (uint32)mwbmap_p->ifree;
974
+}
975
+
976
+/* Determine whether an index is inuse or free */
977
+bool
978
+bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
979
+{
980
+ bcm_mwbmap_t * mwbmap_p;
981
+ uint32 wordix, bitmap;
982
+
983
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
984
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
985
+
986
+ ASSERT(bitix < mwbmap_p->total);
987
+
988
+ wordix = BCM_MWBMAP_DIVOP(bitix);
989
+ bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
990
+
991
+ return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U);
992
+}
993
+
994
+/* Debug dump a multiword bitmap allocator */
995
+void
996
+bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl)
997
+{
998
+ uint32 ix, count;
999
+ bcm_mwbmap_t * mwbmap_p;
1000
+
1001
+ BCM_MWBMAP_AUDIT(mwbmap_hdl);
1002
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
1003
+
1004
+ printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n",
1005
+ OSL_OBFUSCATE_BUF((void *)mwbmap_p),
1006
+ mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total);
1007
+ for (ix = 0U; ix < mwbmap_p->wmaps; ix++) {
1008
+ printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]);
1009
+ bcm_bitprint32(mwbmap_p->wd_bitmap[ix]);
1010
+ printf("\n");
1011
+ }
1012
+ for (ix = 0U; ix < mwbmap_p->imaps; ix++) {
1013
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
1014
+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]);
1015
+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
1016
+ count = (uint32)mwbmap_p->wd_count[ix];
1017
+ MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix]));
1018
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
1019
+ printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count);
1020
+ bcm_bitprint32(mwbmap_p->id_bitmap[ix]);
1021
+ printf("\n");
1022
+ }
1023
+
1024
+ return;
1025
+}
1026
+
1027
+/* Audit a hierarchical multiword bitmap */
1028
+void
1029
+bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl)
1030
+{
1031
+ bcm_mwbmap_t * mwbmap_p;
1032
+ uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p;
1033
+
1034
+ mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
1035
+
1036
+ for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) {
1037
+
1038
+ bitmap_p = &mwbmap_p->wd_bitmap[wordix];
1039
+
1040
+ for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) {
1041
+ if ((*bitmap_p) & (1 << bitix)) {
1042
+ idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix;
1043
+#if defined(BCM_MWBMAP_USE_CNTSETBITS)
1044
+ count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]);
1045
+#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
1046
+ count = (uint32)mwbmap_p->wd_count[idmap_ix];
1047
+ ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]));
1048
+#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
1049
+ ASSERT(count != 0U);
1050
+ free_cnt += count;
1051
+ }
1052
+ }
1053
+ }
1054
+
1055
+ ASSERT((int)free_cnt == mwbmap_p->ifree);
1056
+}
1057
+/* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */
1058
+
1059
+/* Simple 16bit Id allocator using a stack implementation. */
1060
+typedef struct id16_map {
1061
+ uint32 failures; /* count of failures */
1062
+ void *dbg; /* debug placeholder */
1063
+ uint16 total; /* total number of ids managed by allocator */
1064
+ uint16 start; /* start value of 16bit ids to be managed */
1065
+ int stack_idx; /* index into stack of available ids */
1066
+ uint16 stack[0]; /* stack of 16 bit ids */
1067
+} id16_map_t;
1068
+
1069
+#define ID16_MAP_SZ(items) (sizeof(id16_map_t) + \
1070
+ (sizeof(uint16) * (items)))
1071
+
1072
+#if defined(BCM_DBG)
1073
+
1074
+/* Uncomment BCM_DBG_ID16 to debug double free */
1075
+/* #define BCM_DBG_ID16 */
1076
+
1077
+typedef struct id16_map_dbg {
1078
+ uint16 total;
1079
+ bool avail[0];
1080
+} id16_map_dbg_t;
1081
+#define ID16_MAP_DBG_SZ(items) (sizeof(id16_map_dbg_t) + \
1082
+ (sizeof(bool) * (items)))
1083
+#define ID16_MAP_MSG(x) print x
1084
+#else
1085
+#define ID16_MAP_MSG(x)
1086
+#endif /* BCM_DBG */
1087
+
1088
+void * /* Construct an id16 allocator: [start_val16 .. start_val16+total_ids) */
1089
+id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16)
1090
+{
1091
+ uint16 idx, val16;
1092
+ id16_map_t * id16_map;
1093
+
1094
+ ASSERT(total_ids > 0);
1095
+
1096
+ /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
1097
+ * with random values.
1098
+ */
1099
+ ASSERT((start_val16 == ID16_UNDEFINED) ||
1100
+ (start_val16 + total_ids) < ID16_INVALID);
1101
+
1102
+ id16_map = (id16_map_t *) MALLOC(osh, ID16_MAP_SZ(total_ids));
1103
+ if (id16_map == NULL) {
1104
+ return NULL;
1105
+ }
1106
+
1107
+ id16_map->total = total_ids;
1108
+ id16_map->start = start_val16;
1109
+ id16_map->failures = 0;
1110
+ id16_map->dbg = NULL;
1111
+
1112
+ /*
1113
+ * Populate stack with 16bit id values, commencing with start_val16.
1114
+ * if start_val16 is ID16_UNDEFINED, then do not populate the id16 map.
1115
+ */
1116
+ id16_map->stack_idx = -1;
1117
+
1118
+ if (id16_map->start != ID16_UNDEFINED) {
1119
+ val16 = start_val16;
1120
+
1121
+ for (idx = 0; idx < total_ids; idx++, val16++) {
1122
+ id16_map->stack_idx = idx;
1123
+ id16_map->stack[id16_map->stack_idx] = val16;
1124
+ }
1125
+ }
1126
+
1127
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
1128
+ if (id16_map->start != ID16_UNDEFINED) {
1129
+ id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids));
1130
+
1131
+ if (id16_map->dbg) {
1132
+ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
1133
+
1134
+ id16_map_dbg->total = total_ids;
1135
+ for (idx = 0; idx < total_ids; idx++) {
1136
+ id16_map_dbg->avail[idx] = TRUE;
1137
+ }
1138
+ }
1139
+ }
1140
+#endif /* BCM_DBG && BCM_DBG_ID16 */
1141
+
1142
+ return (void *)id16_map;
1143
+}
1144
+
1145
+void * /* Destruct an id16 allocator instance */
1146
+id16_map_fini(osl_t *osh, void * id16_map_hndl)
1147
+{
1148
+ uint16 total_ids;
1149
+ id16_map_t * id16_map;
1150
+
1151
+ if (id16_map_hndl == NULL)
1152
+ return NULL;
1153
+
1154
+ id16_map = (id16_map_t *)id16_map_hndl;
1155
+
1156
+ total_ids = id16_map->total;
1157
+ ASSERT(total_ids > 0);
1158
+
1159
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
1160
+ if (id16_map->dbg) {
1161
+ MFREE(osh, id16_map->dbg, ID16_MAP_DBG_SZ(total_ids));
1162
+ id16_map->dbg = NULL;
1163
+ }
1164
+#endif /* BCM_DBG && BCM_DBG_ID16 */
1165
+
1166
+ id16_map->total = 0;
1167
+ MFREE(osh, id16_map, ID16_MAP_SZ(total_ids));
1168
+
1169
+ return NULL;
1170
+}
1171
+
1172
+void
1173
+id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16)
1174
+{
1175
+ uint16 idx, val16;
1176
+ id16_map_t * id16_map;
1177
+
1178
+ ASSERT(total_ids > 0);
1179
+ /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
1180
+ * with random values.
1181
+ */
1182
+ ASSERT((start_val16 == ID16_UNDEFINED) ||
1183
+ (start_val16 + total_ids) < ID16_INVALID);
1184
+
1185
+ id16_map = (id16_map_t *)id16_map_hndl;
1186
+ if (id16_map == NULL) {
1187
+ return;
1188
+ }
1189
+
1190
+ id16_map->total = total_ids;
1191
+ id16_map->start = start_val16;
1192
+ id16_map->failures = 0;
1193
+
1194
+ /* Populate stack with 16bit id values, commencing with start_val16 */
1195
+ id16_map->stack_idx = -1;
1196
+
1197
+ if (id16_map->start != ID16_UNDEFINED) {
1198
+ val16 = start_val16;
1199
+
1200
+ for (idx = 0; idx < total_ids; idx++, val16++) {
1201
+ id16_map->stack_idx = idx;
1202
+ id16_map->stack[id16_map->stack_idx] = val16;
1203
+ }
1204
+ }
1205
+
1206
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
1207
+ if (id16_map->start != ID16_UNDEFINED) {
1208
+ if (id16_map->dbg) {
1209
+ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
1210
+
1211
+ id16_map_dbg->total = total_ids;
1212
+ for (idx = 0; idx < total_ids; idx++) {
1213
+ id16_map_dbg->avail[idx] = TRUE;
1214
+ }
1215
+ }
1216
+ }
1217
+#endif /* BCM_DBG && BCM_DBG_ID16 */
1218
+}
1219
+
1220
+uint16 BCMFASTPATH /* Allocate a unique 16bit id */
1221
+id16_map_alloc(void * id16_map_hndl)
1222
+{
1223
+ uint16 val16;
1224
+ id16_map_t * id16_map;
1225
+
1226
+ ASSERT(id16_map_hndl != NULL);
1227
+ if (!id16_map_hndl) {
1228
+ return ID16_INVALID;
1229
+ }
1230
+ id16_map = (id16_map_t *)id16_map_hndl;
1231
+
1232
+ ASSERT(id16_map->total > 0);
1233
+
1234
+ if (id16_map->stack_idx < 0) {
1235
+ id16_map->failures++;
1236
+ return ID16_INVALID;
1237
+ }
1238
+
1239
+ val16 = id16_map->stack[id16_map->stack_idx];
1240
+ id16_map->stack_idx--;
1241
+
1242
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
1243
+ ASSERT((id16_map->start == ID16_UNDEFINED) ||
1244
+ (val16 < (id16_map->start + id16_map->total)));
1245
+
1246
+ if (id16_map->dbg) { /* Validate val16 */
1247
+ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
1248
+
1249
+ ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == TRUE);
1250
+ id16_map_dbg->avail[val16 - id16_map->start] = FALSE;
1251
+ }
1252
+#endif /* BCM_DBG && BCM_DBG_ID16 */
1253
+
1254
+ return val16;
1255
+}
1256
+
1257
+void BCMFASTPATH /* Free a 16bit id value into the id16 allocator */
1258
+id16_map_free(void * id16_map_hndl, uint16 val16)
1259
+{
1260
+ id16_map_t * id16_map;
1261
+
1262
+ ASSERT(id16_map_hndl != NULL);
1263
+
1264
+ id16_map = (id16_map_t *)id16_map_hndl;
1265
+
1266
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
1267
+ ASSERT((id16_map->start == ID16_UNDEFINED) ||
1268
+ (val16 < (id16_map->start + id16_map->total)));
1269
+
1270
+ if (id16_map->dbg) { /* Validate val16 */
1271
+ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
1272
+
1273
+ ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == FALSE);
1274
+ id16_map_dbg->avail[val16 - id16_map->start] = TRUE;
1275
+ }
1276
+#endif /* BCM_DBG && BCM_DBG_ID16 */
1277
+
1278
+ id16_map->stack_idx++;
1279
+ id16_map->stack[id16_map->stack_idx] = val16;
1280
+}
1281
+
1282
+uint32 /* Returns number of failures to allocate an unique id16 */
1283
+id16_map_failures(void * id16_map_hndl)
1284
+{
1285
+ ASSERT(id16_map_hndl != NULL);
1286
+ return ((id16_map_t *)id16_map_hndl)->failures;
1287
+}
1288
+
1289
+bool
1290
+id16_map_audit(void * id16_map_hndl)
1291
+{
1292
+ int idx;
1293
+ int insane = 0;
1294
+ id16_map_t * id16_map;
1295
+
1296
+ ASSERT(id16_map_hndl != NULL);
1297
+ if (!id16_map_hndl) {
1298
+ goto done;
1299
+ }
1300
+ id16_map = (id16_map_t *)id16_map_hndl;
1301
+
1302
+ ASSERT(id16_map->stack_idx >= -1);
1303
+ ASSERT(id16_map->stack_idx < (int)id16_map->total);
1304
+
1305
+ if (id16_map->start == ID16_UNDEFINED)
1306
+ goto done;
1307
+
1308
+ for (idx = 0; idx <= id16_map->stack_idx; idx++) {
1309
+ ASSERT(id16_map->stack[idx] >= id16_map->start);
1310
+ ASSERT(id16_map->stack[idx] < (id16_map->start + id16_map->total));
1311
+
1312
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
1313
+ if (id16_map->dbg) {
1314
+ uint16 val16 = id16_map->stack[idx];
1315
+ if (((id16_map_dbg_t *)(id16_map->dbg))->avail[val16] != TRUE) {
1316
+ insane |= 1;
1317
+ ID16_MAP_MSG(("id16_map<%p>: stack_idx %u invalid val16 %u\n",
1318
+ OSL_OBFUSATE_BUF(id16_map_hndl), idx, val16));
1319
+ }
1320
+ }
1321
+#endif /* BCM_DBG && BCM_DBG_ID16 */
1322
+ }
1323
+
1324
+#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
1325
+ if (id16_map->dbg) {
1326
+ uint16 avail = 0; /* Audit available ids counts */
1327
+ for (idx = 0; idx < id16_map_dbg->total; idx++) {
1328
+ if (((id16_map_dbg_t *)(id16_map->dbg))->avail[idx16] == TRUE)
1329
+ avail++;
1330
+ }
1331
+ if (avail && (avail != (id16_map->stack_idx + 1))) {
1332
+ insane |= 1;
1333
+ ID16_MAP_MSG(("id16_map<%p>: avail %u stack_idx %u\n",
1334
+ OSL_OBFUSCATE_BUF(id16_map_hndl),
1335
+ avail, id16_map->stack_idx));
1336
+ }
1337
+ }
1338
+#endif /* BCM_DBG && BCM_DBG_ID16 */
1339
+
1340
+done:
1341
+ /* invoke any other system audits */
1342
+ return (!!insane);
1343
+}
1344
+/* END: Simple id16 allocator */
1345
+
1346
+void
1347
+dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size)
1348
+{
1349
+ uint32 memsize;
1350
+ memsize = sizeof(dll_pool_t) + (elems_max * elem_size);
1351
+ if (pool)
1352
+ MFREE(osh, pool, memsize);
1353
+}
1354
+dll_pool_t *
1355
+dll_pool_init(void * osh, uint16 elems_max, uint16 elem_size)
1356
+{
1357
+ uint32 memsize, i;
1358
+ dll_pool_t * dll_pool_p;
1359
+ dll_t * elem_p;
1360
+
1361
+ ASSERT(elem_size > sizeof(dll_t));
1362
+
1363
+ memsize = sizeof(dll_pool_t) + (elems_max * elem_size);
1364
+
1365
+ if ((dll_pool_p = (dll_pool_t *)MALLOCZ(osh, memsize)) == NULL) {
1366
+ printf("dll_pool_init: elems_max<%u> elem_size<%u> malloc failure\n",
1367
+ elems_max, elem_size);
1368
+ ASSERT(0);
1369
+ return dll_pool_p;
1370
+ }
1371
+
1372
+ dll_init(&dll_pool_p->free_list);
1373
+ dll_pool_p->elems_max = elems_max;
1374
+ dll_pool_p->elem_size = elem_size;
1375
+
1376
+ elem_p = dll_pool_p->elements;
1377
+ for (i = 0; i < elems_max; i++) {
1378
+ dll_append(&dll_pool_p->free_list, elem_p);
1379
+ elem_p = (dll_t *)((uintptr)elem_p + elem_size);
1380
+ }
1381
+
1382
+ dll_pool_p->free_count = elems_max;
1383
+
1384
+ return dll_pool_p;
1385
+}
1386
+
1387
+void *
1388
+dll_pool_alloc(dll_pool_t * dll_pool_p)
1389
+{
1390
+ dll_t * elem_p;
1391
+
1392
+ if (dll_pool_p->free_count == 0) {
1393
+ ASSERT(dll_empty(&dll_pool_p->free_list));
1394
+ return NULL;
1395
+ }
1396
+
1397
+ elem_p = dll_head_p(&dll_pool_p->free_list);
1398
+ dll_delete(elem_p);
1399
+ dll_pool_p->free_count -= 1;
1400
+
1401
+ return (void *)elem_p;
1402
+}
1403
+
1404
+void
1405
+dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p)
1406
+{
1407
+ dll_t * node_p = (dll_t *)elem_p;
1408
+ dll_prepend(&dll_pool_p->free_list, node_p);
1409
+ dll_pool_p->free_count += 1;
1410
+}
1411
+
1412
+void
1413
+dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p)
1414
+{
1415
+ dll_t * node_p = (dll_t *)elem_p;
1416
+ dll_append(&dll_pool_p->free_list, node_p);
1417
+ dll_pool_p->free_count += 1;
1418
+}
1419
+
1420
+#endif // endif
1421
+
2611422 #endif /* BCMDRIVER */
1423
+
1424
+#if defined(BCMDRIVER) || defined(WL_UNITTEST)
1425
+
1426
+/* triggers bcm_bprintf to print to kernel log */
1427
+bool bcm_bprintf_bypass = FALSE;
1428
+
1429
+/* Initialization of bcmstrbuf structure */
1430
+void
1431
+bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
1432
+{
1433
+ b->origsize = b->size = size;
1434
+ b->origbuf = b->buf = buf;
1435
+ if (size > 0) {
1436
+ buf[0] = '\0';
1437
+ }
1438
+}
1439
+
1440
+/* Buffer sprintf wrapper to guard against buffer overflow */
1441
+int
1442
+bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
1443
+{
1444
+ va_list ap;
1445
+ int r;
1446
+
1447
+ va_start(ap, fmt);
1448
+
1449
+ r = vsnprintf(b->buf, b->size, fmt, ap);
1450
+ if (bcm_bprintf_bypass == TRUE) {
1451
+ printf("%s", b->buf);
1452
+ goto exit;
1453
+ }
1454
+
1455
+ /* Non Ansi C99 compliant returns -1,
1456
+ * Ansi compliant return r >= b->size,
1457
+ * bcmstdlib returns 0, handle all
1458
+ */
1459
+ /* r == 0 is also the case when strlen(fmt) is zero.
1460
+ * typically the case when "" is passed as argument.
1461
+ */
1462
+ if ((r == -1) || (r >= (int)b->size)) {
1463
+ b->size = 0;
1464
+ } else {
1465
+ b->size -= (uint)r;
1466
+ b->buf += r;
1467
+ }
1468
+
1469
+exit:
1470
+ va_end(ap);
1471
+
1472
+ return r;
1473
+}
1474
+
1475
+void
1476
+bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, const uint8 *buf, int len)
1477
+{
1478
+ int i;
1479
+
1480
+ if (msg != NULL && msg[0] != '\0')
1481
+ bcm_bprintf(b, "%s", msg);
1482
+ for (i = 0; i < len; i ++)
1483
+ bcm_bprintf(b, "%02X", buf[i]);
1484
+ if (newline)
1485
+ bcm_bprintf(b, "\n");
1486
+}
1487
+
1488
+void
1489
+bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount)
1490
+{
1491
+ int i;
1492
+
1493
+ for (i = 0; i < num_bytes; i++) {
1494
+ num[i] += amount;
1495
+ if (num[i] >= amount)
1496
+ break;
1497
+ amount = 1;
1498
+ }
1499
+}
1500
+
1501
+int
1502
+bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes)
1503
+{
1504
+ int i;
1505
+
1506
+ for (i = nbytes - 1; i >= 0; i--) {
1507
+ if (arg1[i] != arg2[i])
1508
+ return (arg1[i] - arg2[i]);
1509
+ }
1510
+ return 0;
1511
+}
1512
+
1513
+void
1514
+bcm_print_bytes(const char *name, const uchar *data, int len)
1515
+{
1516
+ int i;
1517
+ int per_line = 0;
1518
+
1519
+ printf("%s: %d \n", name ? name : "", len);
1520
+ for (i = 0; i < len; i++) {
1521
+ printf("%02x ", *data++);
1522
+ per_line++;
1523
+ if (per_line == 16) {
1524
+ per_line = 0;
1525
+ printf("\n");
1526
+ }
1527
+ }
1528
+ printf("\n");
1529
+}
1530
+
1531
+/* Look for vendor-specific IE with specified OUI and optional type */
1532
+bcm_tlv_t *
1533
+bcm_find_vendor_ie(const void *tlvs, uint tlvs_len, const char *voui, uint8 *type, uint type_len)
1534
+{
1535
+ const bcm_tlv_t *ie;
1536
+ uint8 ie_len;
1537
+
1538
+ ie = (const bcm_tlv_t*)tlvs;
1539
+
1540
+ /* make sure we are looking at a valid IE */
1541
+ if (ie == NULL || !bcm_valid_tlv(ie, tlvs_len)) {
1542
+ return NULL;
1543
+ }
1544
+
1545
+ /* Walk through the IEs looking for an OUI match */
1546
+ do {
1547
+ ie_len = ie->len;
1548
+ if ((ie->id == DOT11_MNG_VS_ID) &&
1549
+ (ie_len >= (DOT11_OUI_LEN + type_len)) &&
1550
+ !bcmp(ie->data, voui, DOT11_OUI_LEN))
1551
+ {
1552
+ /* compare optional type */
1553
+ if (type_len == 0 ||
1554
+ !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) {
1555
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
1556
+ return (bcm_tlv_t *)(ie); /* a match */
1557
+ GCC_DIAGNOSTIC_POP();
1558
+ }
1559
+ }
1560
+ } while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL);
1561
+
1562
+ return NULL;
1563
+}
1564
+
1565
+#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
1566
+ defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
1567
+#define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1)
1568
+
1569
+int
1570
+bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len)
1571
+{
1572
+ uint i, c;
1573
+ char *p = buf;
1574
+ char *endp = buf + SSID_FMT_BUF_LEN;
1575
+
1576
+ if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN;
1577
+
1578
+ for (i = 0; i < ssid_len; i++) {
1579
+ c = (uint)ssid[i];
1580
+ if (c == '\\') {
1581
+ *p++ = '\\';
1582
+ *p++ = '\\';
1583
+ } else if (bcm_isprint((uchar)c)) {
1584
+ *p++ = (char)c;
1585
+ } else {
1586
+ p += snprintf(p, (size_t)(endp - p), "\\x%02X", c);
1587
+ }
1588
+ }
1589
+ *p = '\0';
1590
+ ASSERT(p < endp);
1591
+
1592
+ return (int)(p - buf);
1593
+}
1594
+#endif // endif
1595
+
1596
+#endif /* BCMDRIVER || WL_UNITTEST */
1597
+
1598
+char *
1599
+bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
1600
+{
1601
+ static const char hex[] =
1602
+ {
1603
+ '0', '1', '2', '3', '4', '5', '6', '7',
1604
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
1605
+ };
1606
+ const uint8 *octet = ea->octet;
1607
+ char *p = buf;
1608
+ int i;
1609
+
1610
+ for (i = 0; i < 6; i++, octet++) {
1611
+ *p++ = hex[(*octet >> 4) & 0xf];
1612
+ *p++ = hex[*octet & 0xf];
1613
+ *p++ = ':';
1614
+ }
1615
+
1616
+ *(p-1) = '\0';
1617
+
1618
+ return (buf);
1619
+}
1620
+
1621
+/* Find the position of first bit set
1622
+ * in the given number.
1623
+ */
1624
+int
1625
+bcm_find_fsb(uint32 num)
1626
+{
1627
+ uint8 pos = 0;
1628
+ if (!num)
1629
+ return pos;
1630
+ while (!(num & 1)) {
1631
+ num >>= 1;
1632
+ pos++;
1633
+ }
1634
+ return (pos+1);
1635
+}
1636
+
1637
+char *
1638
+bcm_ip_ntoa(struct ipv4_addr *ia, char *buf)
1639
+{
1640
+ snprintf(buf, 16, "%d.%d.%d.%d",
1641
+ ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]);
1642
+ return (buf);
1643
+}
1644
+
1645
+char *
1646
+bcm_ipv6_ntoa(void *ipv6, char *buf)
1647
+{
1648
+ /* Implementing RFC 5952 Sections 4 + 5 */
1649
+ /* Not thoroughly tested */
1650
+ uint16 tmp[8];
1651
+ uint16 *a = &tmp[0];
1652
+ char *p = buf;
1653
+ int i, i_max = -1, cnt = 0, cnt_max = 1;
1654
+ uint8 *a4 = NULL;
1655
+ memcpy((uint8 *)&tmp[0], (uint8 *)ipv6, IPV6_ADDR_LEN);
1656
+
1657
+ for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
1658
+ if (a[i]) {
1659
+ if (cnt > cnt_max) {
1660
+ cnt_max = cnt;
1661
+ i_max = i - cnt;
1662
+ }
1663
+ cnt = 0;
1664
+ } else
1665
+ cnt++;
1666
+ }
1667
+ if (cnt > cnt_max) {
1668
+ cnt_max = cnt;
1669
+ i_max = i - cnt;
1670
+ }
1671
+ if (i_max == 0 &&
1672
+ /* IPv4-translated: ::ffff:0:a.b.c.d */
1673
+ ((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) ||
1674
+ /* IPv4-mapped: ::ffff:a.b.c.d */
1675
+ (cnt_max == 5 && a[5] == 0xffff)))
1676
+ a4 = (uint8*) (a + 6);
1677
+
1678
+ for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
1679
+ if ((uint8*) (a + i) == a4) {
1680
+ snprintf(p, 16, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]);
1681
+ break;
1682
+ } else if (i == i_max) {
1683
+ *p++ = ':';
1684
+ i += cnt_max - 1;
1685
+ p[0] = ':';
1686
+ p[1] = '\0';
1687
+ } else {
1688
+ if (i)
1689
+ *p++ = ':';
1690
+ p += snprintf(p, 8, "%x", ntoh16(a[i]));
1691
+ }
1692
+ }
1693
+
1694
+ return buf;
1695
+}
2621696
2631697 #if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
2641698 const unsigned char bcm_ctype[] = {
....@@ -298,10 +1732,10 @@
2981732 _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */
2991733 };
3001734
301
-ulong
302
-bcm_strtoul(const char *cp, char **endp, uint base)
1735
+uint64
1736
+bcm_strtoull(const char *cp, char **endp, uint base)
3031737 {
304
- ulong result, last_result = 0, value;
1738
+ uint64 result, last_result = 0, value;
3051739 bool minus;
3061740
3071741 minus = FALSE;
....@@ -334,11 +1768,19 @@
3341768 result = 0;
3351769
3361770 while (bcm_isxdigit(*cp) &&
337
- (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) {
1771
+ (value = (uint64)(bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10)) < base) {
3381772 result = result*base + value;
3391773 /* Detected overflow */
340
- if (result < last_result && !minus)
1774
+ if (result < last_result && !minus) {
1775
+ if (endp) {
1776
+ /* Go to the end of current number */
1777
+ while (bcm_isxdigit(*cp)) {
1778
+ cp++;
1779
+ }
1780
+ *endp = DISCARD_QUAL(cp, char);
1781
+ }
3411782 return (ulong)-1;
1783
+ }
3421784 last_result = result;
3431785 cp++;
3441786 }
....@@ -350,6 +1792,12 @@
3501792 *endp = DISCARD_QUAL(cp, char);
3511793
3521794 return (result);
1795
+}
1796
+
1797
+ulong
1798
+bcm_strtoul(const char *cp, char **endp, uint base)
1799
+{
1800
+ return (ulong) bcm_strtoull(cp, endp, base);
3531801 }
3541802
3551803 int
....@@ -372,7 +1820,7 @@
3721820 len = (int)strlen(haystack) - nlen + 1;
3731821
3741822 for (i = 0; i < len; i++)
375
- if (memcmp(needle, &haystack[i], nlen) == 0)
1823
+ if (memcmp(needle, &haystack[i], (size_t)nlen) == 0)
3761824 return DISCARD_QUAL(&haystack[i], char);
3771825 return (NULL);
3781826 }
....@@ -414,7 +1862,6 @@
4141862
4151863 return (dest);
4161864 }
417
-
4181865
4191866 /****************************************************************************
4201867 * Function: bcmstrtok
....@@ -477,7 +1924,7 @@
4771924 for (; *str; str++) {
4781925 if (map[*str >> 5] & (1 << (*str & 31))) {
4791926 if (tokdelim != NULL) {
480
- *tokdelim = *str;
1927
+ *tokdelim = (char)*str;
4811928 }
4821929
4831930 *str++ = '\0';
....@@ -496,10 +1943,8 @@
4961943 }
4971944 }
4981945
499
-
5001946 #define xToLower(C) \
5011947 ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C)
502
-
5031948
5041949 /****************************************************************************
5051950 * Function: bcmstricmp
....@@ -531,7 +1976,6 @@
5311976 if (!*s1 && *s2) return -1;
5321977 return 0;
5331978 }
534
-
5351979
5361980 /****************************************************************************
5371981 * Function: bcmstrnicmp
....@@ -576,7 +2020,7 @@
5762020 char *ep;
5772021
5782022 for (;;) {
579
- ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16);
2023
+ ea->octet[i++] = (uint8) bcm_strtoul(p, &ep, 16);
5802024 p = ep;
5812025 if (!*p++ || i == 6)
5822026 break;
....@@ -600,7 +2044,6 @@
6002044 return (i == IPV4_ADDR_LEN);
6012045 }
6022046 #endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */
603
-
6042047
6052048 #if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER)
6062049 /* registry routine buffer preparation utility functions:
....@@ -630,460 +2073,6 @@
6302073 return copyct;
6312074 }
6322075 #endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */
633
-
634
-char *
635
-bcm_ether_ntoa(const struct ether_addr *ea, char *buf)
636
-{
637
- static const char hex[] =
638
- {
639
- '0', '1', '2', '3', '4', '5', '6', '7',
640
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
641
- };
642
- const uint8 *octet = ea->octet;
643
- char *p = buf;
644
- int i;
645
-
646
- for (i = 0; i < 6; i++, octet++) {
647
- *p++ = hex[(*octet >> 4) & 0xf];
648
- *p++ = hex[*octet & 0xf];
649
- *p++ = ':';
650
- }
651
-
652
- *(p-1) = '\0';
653
-
654
- return (buf);
655
-}
656
-
657
-char *
658
-bcm_ip_ntoa(struct ipv4_addr *ia, char *buf)
659
-{
660
- snprintf(buf, 16, "%d.%d.%d.%d",
661
- ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]);
662
- return (buf);
663
-}
664
-
665
-char *
666
-bcm_ipv6_ntoa(void *ipv6, char *buf)
667
-{
668
- /* Implementing RFC 5952 Sections 4 + 5 */
669
- /* Not thoroughly tested */
670
- uint16 tmp[8];
671
- uint16 *a = &tmp[0];
672
- char *p = buf;
673
- int i, i_max = -1, cnt = 0, cnt_max = 1;
674
- uint8 *a4 = NULL;
675
- memcpy((uint8 *)&tmp[0], (uint8 *)ipv6, IPV6_ADDR_LEN);
676
-
677
- for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
678
- if (a[i]) {
679
- if (cnt > cnt_max) {
680
- cnt_max = cnt;
681
- i_max = i - cnt;
682
- }
683
- cnt = 0;
684
- } else
685
- cnt++;
686
- }
687
- if (cnt > cnt_max) {
688
- cnt_max = cnt;
689
- i_max = i - cnt;
690
- }
691
- if (i_max == 0 &&
692
- /* IPv4-translated: ::ffff:0:a.b.c.d */
693
- ((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) ||
694
- /* IPv4-mapped: ::ffff:a.b.c.d */
695
- (cnt_max == 5 && a[5] == 0xffff)))
696
- a4 = (uint8*) (a + 6);
697
-
698
- for (i = 0; i < IPV6_ADDR_LEN/2; i++) {
699
- if ((uint8*) (a + i) == a4) {
700
- snprintf(p, 16, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]);
701
- break;
702
- } else if (i == i_max) {
703
- *p++ = ':';
704
- i += cnt_max - 1;
705
- p[0] = ':';
706
- p[1] = '\0';
707
- } else {
708
- if (i)
709
- *p++ = ':';
710
- p += snprintf(p, 8, "%x", ntoh16(a[i]));
711
- }
712
- }
713
-
714
- return buf;
715
-}
716
-#ifdef BCMDRIVER
717
-
718
-void
719
-bcm_mdelay(uint ms)
720
-{
721
- uint i;
722
-
723
- for (i = 0; i < ms; i++) {
724
- OSL_DELAY(1000);
725
- }
726
-}
727
-
728
-
729
-
730
-
731
-
732
-#if defined(DHD_DEBUG)
733
-/* pretty hex print a pkt buffer chain */
734
-void
735
-prpkt(const char *msg, osl_t *osh, void *p0)
736
-{
737
- void *p;
738
-
739
- if (msg && (msg[0] != '\0'))
740
- printf("%s:\n", msg);
741
-
742
- for (p = p0; p; p = PKTNEXT(osh, p))
743
- prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p));
744
-}
745
-#endif
746
-
747
-/* Takes an Ethernet frame and sets out-of-bound PKTPRIO.
748
- * Also updates the inplace vlan tag if requested.
749
- * For debugging, it returns an indication of what it did.
750
- */
751
-uint BCMFASTPATH
752
-pktsetprio(void *pkt, bool update_vtag)
753
-{
754
- struct ether_header *eh;
755
- struct ethervlan_header *evh;
756
- uint8 *pktdata;
757
- int priority = 0;
758
- int rc = 0;
759
-
760
- pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
761
- ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
762
-
763
- eh = (struct ether_header *) pktdata;
764
-
765
- if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) {
766
- uint16 vlan_tag;
767
- int vlan_prio, dscp_prio = 0;
768
-
769
- evh = (struct ethervlan_header *)eh;
770
-
771
- vlan_tag = ntoh16(evh->vlan_tag);
772
- vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
773
-
774
- if ((evh->ether_type == hton16(ETHER_TYPE_IP)) ||
775
- (evh->ether_type == hton16(ETHER_TYPE_IPV6))) {
776
- uint8 *ip_body = pktdata + sizeof(struct ethervlan_header);
777
- uint8 tos_tc = IP_TOS46(ip_body);
778
- dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
779
- }
780
-
781
- /* DSCP priority gets precedence over 802.1P (vlan tag) */
782
- if (dscp_prio != 0) {
783
- priority = dscp_prio;
784
- rc |= PKTPRIO_VDSCP;
785
- } else {
786
- priority = vlan_prio;
787
- rc |= PKTPRIO_VLAN;
788
- }
789
- /*
790
- * If the DSCP priority is not the same as the VLAN priority,
791
- * then overwrite the priority field in the vlan tag, with the
792
- * DSCP priority value. This is required for Linux APs because
793
- * the VLAN driver on Linux, overwrites the skb->priority field
794
- * with the priority value in the vlan tag
795
- */
796
- if (update_vtag && (priority != vlan_prio)) {
797
- vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT);
798
- vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT;
799
- evh->vlan_tag = hton16(vlan_tag);
800
- rc |= PKTPRIO_UPD;
801
- }
802
-#ifdef DHD_LOSSLESS_ROAMING
803
- } else if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
804
- priority = PRIO_8021D_NC;
805
- rc = PKTPRIO_DSCP;
806
-#endif /* DHD_LOSSLESS_ROAMING */
807
- } else if ((eh->ether_type == hton16(ETHER_TYPE_IP)) ||
808
- (eh->ether_type == hton16(ETHER_TYPE_IPV6))) {
809
- uint8 *ip_body = pktdata + sizeof(struct ether_header);
810
- uint8 tos_tc = IP_TOS46(ip_body);
811
- uint8 dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT;
812
- switch (dscp) {
813
- case DSCP_EF:
814
- priority = PRIO_8021D_VO;
815
- break;
816
- case DSCP_AF31:
817
- case DSCP_AF32:
818
- case DSCP_AF33:
819
- priority = PRIO_8021D_CL;
820
- break;
821
- case DSCP_AF21:
822
- case DSCP_AF22:
823
- case DSCP_AF23:
824
- case DSCP_AF11:
825
- case DSCP_AF12:
826
- case DSCP_AF13:
827
- priority = PRIO_8021D_EE;
828
- break;
829
- default:
830
- priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
831
- break;
832
- }
833
-
834
- rc |= PKTPRIO_DSCP;
835
- }
836
-
837
- ASSERT(priority >= 0 && priority <= MAXPRIO);
838
- PKTSETPRIO(pkt, priority);
839
- return (rc | priority);
840
-}
841
-
842
-/* lookup user priority for specified DSCP */
843
-static uint8
844
-dscp2up(uint8 *up_table, uint8 dscp)
845
-{
846
- uint8 user_priority = 255;
847
-
848
- /* lookup up from table if parameters valid */
849
- if (up_table != NULL && dscp < UP_TABLE_MAX) {
850
- user_priority = up_table[dscp];
851
- }
852
-
853
- /* 255 is unused value so return up from dscp */
854
- if (user_priority == 255) {
855
- user_priority = dscp >> (IPV4_TOS_PREC_SHIFT - IPV4_TOS_DSCP_SHIFT);
856
- }
857
-
858
- return user_priority;
859
-}
860
-
861
-/* set user priority by QoS Map Set table (UP table), table size is UP_TABLE_MAX */
862
-uint BCMFASTPATH
863
-pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag)
864
-{
865
- if (up_table) {
866
- uint8 *pktdata;
867
- uint pktlen;
868
- uint8 dscp;
869
- uint user_priority = 0;
870
- uint rc = 0;
871
-
872
- pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
873
- pktlen = PKTLEN(OSH_NULL, pkt);
874
-
875
- if (pktgetdscp(pktdata, pktlen, &dscp)) {
876
- rc = PKTPRIO_DSCP;
877
- user_priority = dscp2up(up_table, dscp);
878
- PKTSETPRIO(pkt, user_priority);
879
- }
880
-
881
- return (rc | user_priority);
882
- } else {
883
- return pktsetprio(pkt, update_vtag);
884
- }
885
-}
886
-
887
-/* Returns TRUE and DSCP if IP header found, FALSE otherwise.
888
- */
889
-bool BCMFASTPATH
890
-pktgetdscp(uint8 *pktdata, uint pktlen, uint8 *dscp)
891
-{
892
- struct ether_header *eh;
893
- struct ethervlan_header *evh;
894
- uint8 *ip_body;
895
- bool rc = FALSE;
896
-
897
- /* minimum length is ether header and IP header */
898
- if (pktlen < sizeof(struct ether_header) + IPV4_MIN_HEADER_LEN)
899
- return FALSE;
900
-
901
- eh = (struct ether_header *) pktdata;
902
-
903
- if (eh->ether_type == HTON16(ETHER_TYPE_IP)) {
904
- ip_body = pktdata + sizeof(struct ether_header);
905
- *dscp = IP_DSCP46(ip_body);
906
- rc = TRUE;
907
- }
908
- else if (eh->ether_type == HTON16(ETHER_TYPE_8021Q)) {
909
- evh = (struct ethervlan_header *)eh;
910
-
911
- /* minimum length is ethervlan header and IP header */
912
- if (pktlen >= sizeof(struct ethervlan_header) + IPV4_MIN_HEADER_LEN &&
913
- evh->ether_type == HTON16(ETHER_TYPE_IP)) {
914
- ip_body = pktdata + sizeof(struct ethervlan_header);
915
- *dscp = IP_DSCP46(ip_body);
916
- rc = TRUE;
917
- }
918
- }
919
-
920
- return rc;
921
-}
922
-
923
-/* usr_prio range from low to high with usr_prio value */
924
-static bool
925
-up_table_set(uint8 *up_table, uint8 usr_prio, uint8 low, uint8 high)
926
-{
927
- int i;
928
-
929
- if (usr_prio > 7 || low > high || low >= UP_TABLE_MAX || high >= UP_TABLE_MAX) {
930
- return FALSE;
931
- }
932
-
933
- for (i = low; i <= high; i++) {
934
- up_table[i] = usr_prio;
935
- }
936
-
937
- return TRUE;
938
-}
939
-
940
-/* set user priority table */
941
-int BCMFASTPATH
942
-wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie)
943
-{
944
- uint8 len;
945
-
946
- if (up_table == NULL || qos_map_ie == NULL) {
947
- return BCME_ERROR;
948
- }
949
-
950
- /* clear table to check table was set or not */
951
- memset(up_table, 0xff, UP_TABLE_MAX);
952
-
953
- /* length of QoS Map IE must be 16+n*2, n is number of exceptions */
954
- if (qos_map_ie != NULL && qos_map_ie->id == DOT11_MNG_QOS_MAP_ID &&
955
- (len = qos_map_ie->len) >= QOS_MAP_FIXED_LENGTH &&
956
- (len % 2) == 0) {
957
- uint8 *except_ptr = (uint8 *)qos_map_ie->data;
958
- uint8 except_len = len - QOS_MAP_FIXED_LENGTH;
959
- uint8 *range_ptr = except_ptr + except_len;
960
- int i;
961
-
962
- /* fill in ranges */
963
- for (i = 0; i < QOS_MAP_FIXED_LENGTH; i += 2) {
964
- uint8 low = range_ptr[i];
965
- uint8 high = range_ptr[i + 1];
966
- if (low == 255 && high == 255) {
967
- continue;
968
- }
969
-
970
- if (!up_table_set(up_table, i / 2, low, high)) {
971
- /* clear the table on failure */
972
- memset(up_table, 0xff, UP_TABLE_MAX);
973
- return BCME_ERROR;
974
- }
975
- }
976
-
977
- /* update exceptions */
978
- for (i = 0; i < except_len; i += 2) {
979
- uint8 dscp = except_ptr[i];
980
- uint8 usr_prio = except_ptr[i+1];
981
-
982
- /* exceptions with invalid dscp/usr_prio are ignored */
983
- up_table_set(up_table, usr_prio, dscp, dscp);
984
- }
985
- }
986
-
987
- return BCME_OK;
988
-}
989
-
990
-/* The 0.5KB string table is not removed by compiler even though it's unused */
991
-
992
-static char bcm_undeferrstr[32];
993
-static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE;
994
-
995
-/* Convert the error codes into related error strings */
996
-const char *
997
-bcmerrorstr(int bcmerror)
998
-{
999
- /* check if someone added a bcmerror code but forgot to add errorstring */
1000
- ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1));
1001
-
1002
- if (bcmerror > 0 || bcmerror < BCME_LAST) {
1003
- snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror);
1004
- return bcm_undeferrstr;
1005
- }
1006
-
1007
- ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN);
1008
-
1009
- return bcmerrorstrtable[-bcmerror];
1010
-}
1011
-
1012
-
1013
-
1014
-/* iovar table lookup */
1015
-/* could mandate sorted tables and do a binary search */
1016
-const bcm_iovar_t*
1017
-bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
1018
-{
1019
- const bcm_iovar_t *vi;
1020
- const char *lookup_name;
1021
-
1022
- /* skip any ':' delimited option prefixes */
1023
- lookup_name = strrchr(name, ':');
1024
- if (lookup_name != NULL)
1025
- lookup_name++;
1026
- else
1027
- lookup_name = name;
1028
-
1029
- ASSERT(table != NULL);
1030
-
1031
- for (vi = table; vi->name; vi++) {
1032
- if (!strcmp(vi->name, lookup_name))
1033
- return vi;
1034
- }
1035
- /* ran to end of table */
1036
-
1037
- return NULL; /* var name not found */
1038
-}
1039
-
1040
-int
1041
-bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
1042
-{
1043
- int bcmerror = 0;
1044
-
1045
- /* length check on io buf */
1046
- switch (vi->type) {
1047
- case IOVT_BOOL:
1048
- case IOVT_INT8:
1049
- case IOVT_INT16:
1050
- case IOVT_INT32:
1051
- case IOVT_UINT8:
1052
- case IOVT_UINT16:
1053
- case IOVT_UINT32:
1054
- /* all integers are int32 sized args at the ioctl interface */
1055
- if (len < (int)sizeof(int)) {
1056
- bcmerror = BCME_BUFTOOSHORT;
1057
- }
1058
- break;
1059
-
1060
- case IOVT_BUFFER:
1061
- /* buffer must meet minimum length requirement */
1062
- if (len < vi->minlen) {
1063
- bcmerror = BCME_BUFTOOSHORT;
1064
- }
1065
- break;
1066
-
1067
- case IOVT_VOID:
1068
- if (!set) {
1069
- /* Cannot return nil... */
1070
- bcmerror = BCME_UNSUPPORTED;
1071
- } else if (len) {
1072
- /* Set is an action w/o parameters */
1073
- bcmerror = BCME_BUFTOOLONG;
1074
- }
1075
- break;
1076
-
1077
- default:
1078
- /* unknown type for length check in iovar info */
1079
- ASSERT(0);
1080
- bcmerror = BCME_UNSUPPORTED;
1081
- }
1082
-
1083
- return bcmerror;
1084
-}
1085
-
1086
-#endif /* BCMDRIVER */
10872076
10882077 #ifdef BCM_OBJECT_TRACE
10892078
....@@ -1522,22 +2511,70 @@
15222511 ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) &&
15232512 ((data != NULL) || (datalen == 0))) {
15242513
1525
- /* write type, len fields */
2514
+ /* write type, len fields */
15262515 dst_tlv->id = (uint8)type;
1527
- dst_tlv->len = (uint8)datalen;
2516
+ dst_tlv->len = (uint8)datalen;
15282517
15292518 /* if data is present, copy to the output buffer and update
15302519 * pointer to output buffer
15312520 */
15322521 if (datalen > 0) {
15332522
1534
- memcpy(dst_tlv->data, data, datalen);
2523
+ memcpy(dst_tlv->data, data, (size_t)datalen);
15352524 }
15362525
15372526 /* update the output destination poitner to point past
15382527 * the TLV written
15392528 */
15402529 new_dst = dst + BCM_TLV_HDR_SIZE + datalen;
2530
+ }
2531
+
2532
+ return (new_dst);
2533
+}
2534
+
2535
+uint8 *
2536
+bcm_write_tlv_ext(uint8 type, uint8 ext, const void *data, uint8 datalen, uint8 *dst)
2537
+{
2538
+ uint8 *new_dst = dst;
2539
+ bcm_tlv_ext_t *dst_tlv = (bcm_tlv_ext_t *)dst;
2540
+
2541
+ /* dst buffer should always be valid */
2542
+ ASSERT(dst);
2543
+
2544
+ /* data len must be within valid range */
2545
+ ASSERT(datalen <= BCM_TLV_EXT_MAX_DATA_SIZE);
2546
+
2547
+ /* source data buffer pointer should be valid, unless datalen is 0
2548
+ * meaning no data with this TLV
2549
+ */
2550
+ ASSERT((data != NULL) || (datalen == 0));
2551
+
2552
+ /* only do work if the inputs are valid
2553
+ * - must have a dst to write to AND
2554
+ * - datalen must be within range AND
2555
+ * - the source data pointer must be non-NULL if datalen is non-zero
2556
+ * (this last condition detects datalen > 0 with a NULL data pointer)
2557
+ */
2558
+ if ((dst != NULL) &&
2559
+ (datalen <= BCM_TLV_EXT_MAX_DATA_SIZE) &&
2560
+ ((data != NULL) || (datalen == 0))) {
2561
+
2562
+ /* write type, len fields */
2563
+ dst_tlv->id = (uint8)type;
2564
+ dst_tlv->ext = ext;
2565
+ dst_tlv->len = 1 + (uint8)datalen;
2566
+
2567
+ /* if data is present, copy to the output buffer and update
2568
+ * pointer to output buffer
2569
+ */
2570
+ if (datalen > 0) {
2571
+ memcpy(dst_tlv->data, data, datalen);
2572
+ }
2573
+
2574
+ /* update the output destination poitner to point past
2575
+ * the TLV written
2576
+ */
2577
+ new_dst = dst + BCM_TLV_EXT_HDR_SIZE + datalen;
15412578 }
15422579
15432580 return (new_dst);
....@@ -1553,7 +2590,7 @@
15532590 /* if len + tlv hdr len is more than destlen, don't do anything
15542591 * just return the buffer untouched
15552592 */
1556
- if ((int)(datalen + BCM_TLV_HDR_SIZE) <= dst_maxlen) {
2593
+ if ((int)(datalen + (int)BCM_TLV_HDR_SIZE) <= dst_maxlen) {
15572594
15582595 new_dst = bcm_write_tlv(type, data, datalen, dst);
15592596 }
....@@ -1580,7 +2617,6 @@
15802617 return (new_dst);
15812618 }
15822619
1583
-
15842620 uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen)
15852621 {
15862622 uint8 *new_dst = dst;
....@@ -1595,7 +2631,6 @@
15952631
15962632 return (new_dst);
15972633 }
1598
-
15992634
16002635 #if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS)
16012636 /*******************************************************************************
....@@ -1660,7 +2695,7 @@
16602695
16612696 uint8
16622697 hndcrc8(
1663
- uint8 *pdata, /* pointer to array of data to process */
2698
+ const uint8 *pdata, /* pointer to array of data to process */
16642699 uint nbytes, /* number of input data bytes to process */
16652700 uint8 crc /* either CRC8_INIT_VALUE or previous return value */
16662701 )
....@@ -1733,7 +2768,7 @@
17332768
17342769 uint16
17352770 hndcrc16(
1736
- uint8 *pdata, /* pointer to array of data to process */
2771
+ const uint8 *pdata, /* pointer to array of data to process */
17372772 uint nbytes, /* number of input data bytes to process */
17382773 uint16 crc /* either CRC16_INIT_VALUE or previous return value */
17392774 )
....@@ -1815,9 +2850,9 @@
18152850 * accumulating over multiple pieces.
18162851 */
18172852 uint32
1818
-hndcrc32(uint8 *pdata, uint nbytes, uint32 crc)
2853
+hndcrc32(const uint8 *pdata, uint nbytes, uint32 crc)
18192854 {
1820
- uint8 *pend;
2855
+ const uint8 *pend;
18212856 pend = pdata + nbytes;
18222857 while (pdata < pend)
18232858 CRC_INNER_LOOP(32, crc, *pdata++);
....@@ -1826,8 +2861,8 @@
18262861 }
18272862
18282863 #ifdef notdef
1829
-#define CLEN 1499 /* CRC Length */
1830
-#define CBUFSIZ (CLEN+4)
2864
+#define CLEN 1499 /* CRC Length */
2865
+#define CBUFSIZ (CLEN+4)
18312866 #define CNBUFS 5 /* # of bufs */
18322867
18332868 void
....@@ -1870,9 +2905,9 @@
18702905 * by the TLV parameter's length if it is valid.
18712906 */
18722907 bcm_tlv_t *
1873
-bcm_next_tlv(bcm_tlv_t *elt, int *buflen)
2908
+bcm_next_tlv(const bcm_tlv_t *elt, uint *buflen)
18742909 {
1875
- int len;
2910
+ uint len;
18762911
18772912 /* validate current elt */
18782913 if (!bcm_valid_tlv(elt, *buflen)) {
....@@ -1881,7 +2916,7 @@
18812916
18822917 /* advance to next elt */
18832918 len = elt->len;
1884
- elt = (bcm_tlv_t*)(elt->data + len);
2919
+ elt = (const bcm_tlv_t*)(elt->data + len);
18852920 *buflen -= (TLV_HDR_LEN + len);
18862921
18872922 /* validate next elt */
....@@ -1889,7 +2924,112 @@
18892924 return NULL;
18902925 }
18912926
1892
- return elt;
2927
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
2928
+ return (bcm_tlv_t *)(elt);
2929
+ GCC_DIAGNOSTIC_POP();
2930
+}
2931
+
2932
+/**
2933
+ * Advance a const tlv buffer pointer and length up to the given tlv element pointer
2934
+ * 'elt'. The function checks that elt is a valid tlv; the elt pointer and data
2935
+ * are all in the range of the buffer/length.
2936
+ *
2937
+ * @param elt pointer to a valid bcm_tlv_t in the buffer
2938
+ * @param buffer pointer to a tlv buffer
2939
+ * @param buflen length of the buffer in bytes
2940
+ *
2941
+ * On return, if elt is not a tlv in the buffer bounds, the *buffer parameter
2942
+ * will be set to NULL and *buflen parameter will be set to zero. Otherwise,
2943
+ * *buffer will point to elt, and *buflen will have been adjusted by the the
2944
+ * difference between *buffer and elt.
2945
+ */
2946
+void
2947
+bcm_tlv_buffer_advance_to(const bcm_tlv_t *elt, const uint8 **buffer, uint *buflen)
2948
+{
2949
+ uint new_buflen;
2950
+ const uint8 *new_buffer;
2951
+
2952
+ new_buffer = (const uint8*)elt;
2953
+
2954
+ /* make sure the input buffer pointer is non-null, that (buffer + buflen) does not wrap,
2955
+ * and that the elt pointer is in the range of [buffer, buffer + buflen]
2956
+ */
2957
+ if ((*buffer != NULL) &&
2958
+ ((uintptr)*buffer < ((uintptr)*buffer + *buflen)) &&
2959
+ (new_buffer >= *buffer) &&
2960
+ (new_buffer < (*buffer + *buflen))) {
2961
+ /* delta between buffer and new_buffer is <= *buflen, so truncating cast to uint
2962
+ * from ptrdiff is ok
2963
+ */
2964
+ uint delta = (uint)(new_buffer - *buffer);
2965
+
2966
+ /* New buffer length is old len minus the delta from the buffer start to elt.
2967
+ * The check just above guarantees that the subtractions does not underflow.
2968
+ */
2969
+ new_buflen = *buflen - delta;
2970
+
2971
+ /* validate current elt */
2972
+ if (bcm_valid_tlv(elt, new_buflen)) {
2973
+ /* All good, so update the input/output parameters */
2974
+ *buffer = new_buffer;
2975
+ *buflen = new_buflen;
2976
+ return;
2977
+ }
2978
+ }
2979
+
2980
+ /* something did not check out, clear out the buffer info */
2981
+ *buffer = NULL;
2982
+ *buflen = 0;
2983
+
2984
+ return;
2985
+}
2986
+
2987
+/**
2988
+ * Advance a const tlv buffer pointer and length past the given tlv element pointer
2989
+ * 'elt'. The function checks that elt is a valid tlv; the elt pointer and data
2990
+ * are all in the range of the buffer/length. The function also checks that the
2991
+ * remaining buffer starts with a valid tlv.
2992
+ *
2993
+ * @param elt pointer to a valid bcm_tlv_t in the buffer
2994
+ * @param buffer pointer to a tlv buffer
2995
+ * @param buflen length of the buffer in bytes
2996
+ *
2997
+ * On return, if elt is not a tlv in the buffer bounds, or the remaining buffer
2998
+ * following the elt does not begin with a tlv in the buffer bounds, the *buffer
2999
+ * parameter will be set to NULL and *buflen parameter will be set to zero.
3000
+ * Otherwise, *buffer will point to the first byte past elt, and *buflen will
3001
+ * have the remaining buffer length.
3002
+ */
3003
+void
3004
+bcm_tlv_buffer_advance_past(const bcm_tlv_t *elt, const uint8 **buffer, uint *buflen)
3005
+{
3006
+ /* Start by advancing the buffer up to the given elt */
3007
+ bcm_tlv_buffer_advance_to(elt, buffer, buflen);
3008
+
3009
+ /* if that did not work, bail out */
3010
+ if (*buflen == 0) {
3011
+ return;
3012
+ }
3013
+
3014
+#if defined(__COVERITY__)
3015
+ /* The elt has been verified by bcm_tlv_buffer_advance_to() to be a valid element,
3016
+ * so its elt->len is in the bounds of the buffer. The following check prevents
3017
+ * Coverity from flagging the (elt->data + elt->len) statement below as using a
3018
+ * tainted elt->len to index into array 'elt->data'.
3019
+ */
3020
+ if (elt->len > *buflen) {
3021
+ return;
3022
+ }
3023
+#endif /* __COVERITY__ */
3024
+
3025
+ /* We know we are advanced up to a good tlv.
3026
+ * Now just advance to the following tlv.
3027
+ */
3028
+ elt = (const bcm_tlv_t*)(elt->data + elt->len);
3029
+
3030
+ bcm_tlv_buffer_advance_to(elt, buffer, buflen);
3031
+
3032
+ return;
18933033 }
18943034
18953035 /*
....@@ -1898,25 +3038,68 @@
18983038 * matches tag
18993039 */
19003040 bcm_tlv_t *
1901
-bcm_parse_tlvs(void *buf, int buflen, uint key)
3041
+bcm_parse_tlvs(const void *buf, uint buflen, uint key)
3042
+{
3043
+ const bcm_tlv_t *elt;
3044
+ int totlen;
3045
+
3046
+ if ((elt = (const bcm_tlv_t*)buf) == NULL) {
3047
+ return NULL;
3048
+ }
3049
+ totlen = (int)buflen;
3050
+
3051
+ /* find tagged parameter */
3052
+ while (totlen >= TLV_HDR_LEN) {
3053
+ uint len = elt->len;
3054
+
3055
+ /* validate remaining totlen */
3056
+ if ((elt->id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
3057
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
3058
+ return (bcm_tlv_t *)(elt);
3059
+ GCC_DIAGNOSTIC_POP();
3060
+ }
3061
+
3062
+ elt = (const bcm_tlv_t*)((const uint8*)elt + (len + TLV_HDR_LEN));
3063
+ totlen -= (len + TLV_HDR_LEN);
3064
+ }
3065
+
3066
+ return NULL;
3067
+}
3068
+
3069
+bcm_tlv_t *
3070
+bcm_parse_tlvs_dot11(const void *buf, int buflen, uint key, bool id_ext)
19023071 {
19033072 bcm_tlv_t *elt;
19043073 int totlen;
19053074
1906
- if ((elt = (bcm_tlv_t*)buf) == NULL) {
1907
- return NULL;
1908
- }
3075
+ /*
3076
+ ideally, we don't want to do that, but returning a const pointer
3077
+ from these parse function spreads casting everywhere in the code
3078
+ */
3079
+ GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
3080
+ elt = (bcm_tlv_t*)buf;
3081
+ GCC_DIAGNOSTIC_POP();
3082
+
19093083 totlen = buflen;
19103084
19113085 /* find tagged parameter */
19123086 while (totlen >= TLV_HDR_LEN) {
19133087 int len = elt->len;
19143088
1915
- /* validate remaining totlen */
1916
- if ((elt->id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) {
3089
+ do {
3090
+ /* validate remaining totlen */
3091
+ if (totlen < (int)(len + TLV_HDR_LEN))
3092
+ break;
19173093
1918
- return (elt);
1919
- }
3094
+ if (id_ext) {
3095
+ if (!DOT11_MNG_IE_ID_EXT_MATCH(elt, key))
3096
+ break;
3097
+ } else if (elt->id != key) {
3098
+ break;
3099
+ }
3100
+
3101
+ return (bcm_tlv_t *)(elt); /* a match */
3102
+ } while (0);
19203103
19213104 elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
19223105 totlen -= (len + TLV_HDR_LEN);
....@@ -1932,9 +3115,10 @@
19323115 * return NULL if not found or length field < min_varlen
19333116 */
19343117 bcm_tlv_t *
1935
-bcm_parse_tlvs_min_bodylen(void *buf, int buflen, uint key, int min_bodylen)
3118
+bcm_parse_tlvs_min_bodylen(const void *buf, int buflen, uint key, int min_bodylen)
19363119 {
1937
- bcm_tlv_t * ret = bcm_parse_tlvs(buf, buflen, key);
3120
+ bcm_tlv_t * ret;
3121
+ ret = bcm_parse_tlvs(buf, (uint)buflen, key);
19383122 if (ret == NULL || ret->len < min_bodylen) {
19393123 return NULL;
19403124 }
....@@ -1947,13 +3131,13 @@
19473131 * matches tag. Stop parsing when we see an element whose ID is greater
19483132 * than the target key.
19493133 */
1950
-bcm_tlv_t *
1951
-bcm_parse_ordered_tlvs(void *buf, int buflen, uint key)
3134
+const bcm_tlv_t *
3135
+bcm_parse_ordered_tlvs(const void *buf, int buflen, uint key)
19523136 {
1953
- bcm_tlv_t *elt;
3137
+ const bcm_tlv_t *elt;
19543138 int totlen;
19553139
1956
- elt = (bcm_tlv_t*)buf;
3140
+ elt = (const bcm_tlv_t*)buf;
19573141 totlen = buflen;
19583142
19593143 /* find tagged parameter */
....@@ -1971,7 +3155,7 @@
19713155 return (elt);
19723156 }
19733157
1974
- elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN));
3158
+ elt = (const bcm_tlv_t*)((const uint8*)elt + (len + TLV_HDR_LEN));
19753159 totlen -= (len + TLV_HDR_LEN);
19763160 }
19773161 return NULL;
....@@ -1996,8 +3180,8 @@
19963180 bit = bd->bitfield[i].bit;
19973181 if ((flags & mask) == bit) {
19983182 if (len > (int)strlen(name)) {
1999
- slen = strlen(name);
2000
- strncpy(buf, name, slen+1);
3183
+ slen = (int)strlen(name);
3184
+ strncpy(buf, name, (size_t)slen+1);
20013185 }
20023186 break;
20033187 }
....@@ -2031,7 +3215,7 @@
20313215 } else if ((flags & bit) == 0)
20323216 continue;
20333217 flags &= ~bit;
2034
- nlen = strlen(name);
3218
+ nlen = (int)strlen(name);
20353219 slen += nlen;
20363220 /* count btwn flag space */
20373221 if (flags != 0)
....@@ -2040,7 +3224,7 @@
20403224 if (len <= slen)
20413225 break;
20423226 /* copy NULL char but don't count it */
2043
- strncpy(p, name, nlen + 1);
3227
+ strncpy(p, name, (size_t)nlen + 1);
20443228 p += nlen;
20453229 /* copy btwn flag space and NULL char */
20463230 if (flags != 0)
....@@ -2054,7 +3238,58 @@
20543238
20553239 return (int)(p - buf);
20563240 }
2057
-#endif
3241
+
3242
+/* print out whcih bits in octet array 'addr' are set. bcm_bit_desc_t:bit is a bit offset. */
3243
+int
3244
+bcm_format_octets(const bcm_bit_desc_t *bd, uint bdsz,
3245
+ const uint8 *addr, uint size, char *buf, int len)
3246
+{
3247
+ uint i;
3248
+ char *p = buf;
3249
+ int slen = 0, nlen = 0;
3250
+ uint32 bit;
3251
+ const char* name;
3252
+ bool more = FALSE;
3253
+
3254
+ BCM_REFERENCE(size);
3255
+
3256
+ if (len < 2 || !buf)
3257
+ return 0;
3258
+
3259
+ buf[0] = '\0';
3260
+
3261
+ for (i = 0; i < bdsz; i++) {
3262
+ bit = bd[i].bit;
3263
+ name = bd[i].name;
3264
+ CLANG_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
3265
+ if (isset(addr, bit)) {
3266
+ CLANG_DIAGNOSTIC_POP();
3267
+ nlen = (int)strlen(name);
3268
+ slen += nlen;
3269
+ /* need SPACE - for simplicity */
3270
+ slen += 1;
3271
+ /* need NULL as well */
3272
+ if (len < slen + 1) {
3273
+ more = TRUE;
3274
+ break;
3275
+ }
3276
+ memcpy(p, name, (size_t)nlen);
3277
+ p += nlen;
3278
+ p[0] = ' ';
3279
+ p += 1;
3280
+ p[0] = '\0';
3281
+ }
3282
+ }
3283
+
3284
+ if (more) {
3285
+ p[0] = '>';
3286
+ p += 1;
3287
+ p[0] = '\0';
3288
+ }
3289
+
3290
+ return (int)(p - buf);
3291
+}
3292
+#endif // endif
20583293
20593294 /* print bytes formatted as hex to a string. return the resulting string length */
20603295 int
....@@ -2073,7 +3308,7 @@
20733308
20743309 /* pretty hex print a contiguous buffer */
20753310 void
2076
-prhex(const char *msg, uchar *buf, uint nbytes)
3311
+prhex(const char *msg, const uchar *buf, uint nbytes)
20773312 {
20783313 char line[128], *p;
20793314 int len = sizeof(line);
....@@ -2086,12 +3321,12 @@
20863321 p = line;
20873322 for (i = 0; i < nbytes; i++) {
20883323 if (i % 16 == 0) {
2089
- nchar = snprintf(p, len, " %04x: ", i); /* line prefix */
3324
+ nchar = snprintf(p, (size_t)len, " %04x: ", i); /* line prefix */
20903325 p += nchar;
20913326 len -= nchar;
20923327 }
20933328 if (len > 0) {
2094
- nchar = snprintf(p, len, "%02x ", buf[i]);
3329
+ nchar = snprintf(p, (size_t)len, "%02x ", buf[i]);
20953330 p += nchar;
20963331 len -= nchar;
20973332 }
....@@ -2116,11 +3351,22 @@
21163351 "AES_CCM",
21173352 "AES_OCB_MSDU",
21183353 "AES_OCB_MPDU",
3354
+#ifdef BCMCCX
3355
+ "CKIP",
3356
+ "CKIP_MMH",
3357
+ "WEP_MMH",
3358
+ "NALG",
3359
+#else
21193360 "NALG",
21203361 "UNDEF",
21213362 "UNDEF",
21223363 "UNDEF",
3364
+#endif /* BCMCCX */
3365
+#ifdef BCMWAPI_WAI
21233366 "WAPI",
3367
+#else
3368
+ "UNDEF",
3369
+#endif // endif
21243370 "PMK",
21253371 "BIP",
21263372 "AES_GCM",
....@@ -2138,14 +3384,24 @@
21383384 return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR";
21393385 }
21403386
2141
-
21423387 char *
21433388 bcm_chipname(uint chipid, char *buf, uint len)
21443389 {
21453390 const char *fmt;
21463391
21473392 fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
3393
+ /*
3394
+ * The following call to snprintf generates a compiler warning
3395
+ * due to -Wformat-nonliteral. However, the format string is coming
3396
+ * from internal callers rather than external data input, and is a
3397
+ * useful debugging tool serving a variety of diagnostics. Rather
3398
+ * than expand code size by replicating multiple functions with different
3399
+ * argument lists, or disabling the warning globally, let's consider
3400
+ * if we can just disable the warning for this one instance.
3401
+ */
3402
+ CLANG_DIAGNOSTIC_PUSH_SUPPRESS_FORMAT()
21483403 snprintf(buf, len, fmt, chipid);
3404
+ CLANG_DIAGNOSTIC_POP()
21493405 return buf;
21503406 }
21513407
....@@ -2203,21 +3459,33 @@
22033459 while (bufsize > 1) {
22043460 if (cur_ptr->nameandfmt == NULL)
22053461 break;
3462
+
3463
+ /*
3464
+ * The following call to snprintf generates a compiler warning
3465
+ * due to -Wformat-nonliteral. However, the format string is coming
3466
+ * from internal callers rather than external data input, and is a
3467
+ * useful debugging tool serving a variety of diagnostics. Rather
3468
+ * than expand code size by replicating multiple functions with different
3469
+ * argument lists, or disabling the warning globally, let's consider
3470
+ * if we can just disable the warning for this one instance.
3471
+ */
3472
+ CLANG_DIAGNOSTIC_PUSH_SUPPRESS_FORMAT()
22063473 len = snprintf(buf, bufsize, cur_ptr->nameandfmt,
2207
- read_rtn(arg0, arg1, cur_ptr->offset));
3474
+ read_rtn(arg0, arg1, cur_ptr->offset));
3475
+ CLANG_DIAGNOSTIC_POP()
22083476 /* check for snprintf overflow or error */
22093477 if (len < 0 || (uint32)len >= bufsize)
2210
- len = bufsize - 1;
3478
+ len = (int)(bufsize - 1);
22113479 buf += len;
2212
- bufsize -= len;
2213
- filled_len += len;
3480
+ bufsize -= (uint32)len;
3481
+ filled_len += (uint32)len;
22143482 cur_ptr++;
22153483 }
22163484 return filled_len;
22173485 }
22183486
22193487 uint
2220
-bcm_mkiovar(const char *name, char *data, uint datalen, char *buf, uint buflen)
3488
+bcm_mkiovar(const char *name, const char *data, uint datalen, char *buf, uint buflen)
22213489 {
22223490 uint len;
22233491
....@@ -2258,7 +3526,7 @@
22583526 #define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
22593527
22603528 static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
2261
-/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
3529
+/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
22623530 /* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
22633531 /* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
22643532 /* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
....@@ -2288,7 +3556,7 @@
22883556 /* return the mW value scaled down to the correct factor of 10,
22893557 * adding in factor/2 to get proper rounding.
22903558 */
2291
- return ((nqdBm_to_mW_map[idx] + factor/2) / factor);
3559
+ return (uint16)((nqdBm_to_mW_map[idx] + factor/2) / factor);
22923560 }
22933561
22943562 uint8
....@@ -2322,7 +3590,6 @@
23223590 return (qdbm);
23233591 }
23243592
2325
-
23263593 uint
23273594 bcm_bitcount(uint8 *bitmap, uint length)
23283595 {
....@@ -2337,175 +3604,6 @@
23373604 }
23383605 return bitcount;
23393606 }
2340
-
2341
-#if defined(BCMDRIVER) || defined(WL_UNITTEST)
2342
-
2343
-/* triggers bcm_bprintf to print to kernel log */
2344
-bool bcm_bprintf_bypass = FALSE;
2345
-
2346
-/* Initialization of bcmstrbuf structure */
2347
-void
2348
-bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
2349
-{
2350
- b->origsize = b->size = size;
2351
- b->origbuf = b->buf = buf;
2352
-}
2353
-
2354
-/* Buffer sprintf wrapper to guard against buffer overflow */
2355
-int
2356
-bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
2357
-{
2358
- va_list ap;
2359
- int r;
2360
-
2361
- va_start(ap, fmt);
2362
-
2363
- r = vsnprintf(b->buf, b->size, fmt, ap);
2364
- if (bcm_bprintf_bypass == TRUE) {
2365
- printf("%s\n", b->buf);
2366
- goto exit;
2367
- }
2368
-
2369
- /* Non Ansi C99 compliant returns -1,
2370
- * Ansi compliant return r >= b->size,
2371
- * bcmstdlib returns 0, handle all
2372
- */
2373
- /* r == 0 is also the case when strlen(fmt) is zero.
2374
- * typically the case when "" is passed as argument.
2375
- */
2376
- if ((r == -1) || (r >= (int)b->size)) {
2377
- b->size = 0;
2378
- } else {
2379
- b->size -= r;
2380
- b->buf += r;
2381
- }
2382
-
2383
-exit:
2384
- va_end(ap);
2385
-
2386
- return r;
2387
-}
2388
-
2389
-void
2390
-bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, const uint8 *buf, int len)
2391
-{
2392
- int i;
2393
-
2394
- if (msg != NULL && msg[0] != '\0')
2395
- bcm_bprintf(b, "%s", msg);
2396
- for (i = 0; i < len; i ++)
2397
- bcm_bprintf(b, "%02X", buf[i]);
2398
- if (newline)
2399
- bcm_bprintf(b, "\n");
2400
-}
2401
-
2402
-void
2403
-bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount)
2404
-{
2405
- int i;
2406
-
2407
- for (i = 0; i < num_bytes; i++) {
2408
- num[i] += amount;
2409
- if (num[i] >= amount)
2410
- break;
2411
- amount = 1;
2412
- }
2413
-}
2414
-
2415
-int
2416
-bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes)
2417
-{
2418
- int i;
2419
-
2420
- for (i = nbytes - 1; i >= 0; i--) {
2421
- if (arg1[i] != arg2[i])
2422
- return (arg1[i] - arg2[i]);
2423
- }
2424
- return 0;
2425
-}
2426
-
2427
-void
2428
-bcm_print_bytes(const char *name, const uchar *data, int len)
2429
-{
2430
- int i;
2431
- int per_line = 0;
2432
-
2433
- printf("%s: %d \n", name ? name : "", len);
2434
- for (i = 0; i < len; i++) {
2435
- printf("%02x ", *data++);
2436
- per_line++;
2437
- if (per_line == 16) {
2438
- per_line = 0;
2439
- printf("\n");
2440
- }
2441
- }
2442
- printf("\n");
2443
-}
2444
-
2445
-/* Look for vendor-specific IE with specified OUI and optional type */
2446
-bcm_tlv_t *
2447
-bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type, int type_len)
2448
-{
2449
- bcm_tlv_t *ie;
2450
- uint8 ie_len;
2451
-
2452
- ie = (bcm_tlv_t*)tlvs;
2453
-
2454
- /* make sure we are looking at a valid IE */
2455
- if (ie == NULL || !bcm_valid_tlv(ie, tlvs_len)) {
2456
- return NULL;
2457
- }
2458
-
2459
- /* Walk through the IEs looking for an OUI match */
2460
- do {
2461
- ie_len = ie->len;
2462
- if ((ie->id == DOT11_MNG_PROPR_ID) &&
2463
- (ie_len >= (DOT11_OUI_LEN + type_len)) &&
2464
- !bcmp(ie->data, voui, DOT11_OUI_LEN))
2465
- {
2466
- /* compare optional type */
2467
- if (type_len == 0 ||
2468
- !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) {
2469
- return (ie); /* a match */
2470
- }
2471
- }
2472
- } while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL);
2473
-
2474
- return NULL;
2475
-}
2476
-
2477
-#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \
2478
- defined(WLMSG_PRPKT) || defined(WLMSG_WSEC)
2479
-#define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1)
2480
-
2481
-int
2482
-bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len)
2483
-{
2484
- uint i, c;
2485
- char *p = buf;
2486
- char *endp = buf + SSID_FMT_BUF_LEN;
2487
-
2488
- if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN;
2489
-
2490
- for (i = 0; i < ssid_len; i++) {
2491
- c = (uint)ssid[i];
2492
- if (c == '\\') {
2493
- *p++ = '\\';
2494
- *p++ = '\\';
2495
- } else if (bcm_isprint((uchar)c)) {
2496
- *p++ = (char)c;
2497
- } else {
2498
- p += snprintf(p, (endp - p), "\\x%02X", c);
2499
- }
2500
- }
2501
- *p = '\0';
2502
- ASSERT(p < endp);
2503
-
2504
- return (int)(p - buf);
2505
-}
2506
-#endif
2507
-
2508
-#endif /* BCMDRIVER || WL_UNITTEST */
25093607
25103608 /*
25113609 * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL.
....@@ -2560,64 +3658,6 @@
25603658 *dp++ = 0;
25613659
25623660 return buf_len;
2563
-}
2564
-
2565
-/* calculate a * b + c */
2566
-void
2567
-bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c)
2568
-{
2569
-#define FORMALIZE(var) {cc += (var & 0x80000000) ? 1 : 0; var &= 0x7fffffff;}
2570
- uint32 r1, r0;
2571
- uint32 a1, a0, b1, b0, t, cc = 0;
2572
-
2573
- a1 = a >> 16;
2574
- a0 = a & 0xffff;
2575
- b1 = b >> 16;
2576
- b0 = b & 0xffff;
2577
-
2578
- r0 = a0 * b0;
2579
- FORMALIZE(r0);
2580
-
2581
- t = (a1 * b0) << 16;
2582
- FORMALIZE(t);
2583
-
2584
- r0 += t;
2585
- FORMALIZE(r0);
2586
-
2587
- t = (a0 * b1) << 16;
2588
- FORMALIZE(t);
2589
-
2590
- r0 += t;
2591
- FORMALIZE(r0);
2592
-
2593
- FORMALIZE(c);
2594
-
2595
- r0 += c;
2596
- FORMALIZE(r0);
2597
-
2598
- r0 |= (cc % 2) ? 0x80000000 : 0;
2599
- r1 = a1 * b1 + ((a1 * b0) >> 16) + ((b1 * a0) >> 16) + (cc / 2);
2600
-
2601
- *r_high = r1;
2602
- *r_low = r0;
2603
-}
2604
-
2605
-/* calculate a / b */
2606
-void
2607
-bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
2608
-{
2609
- uint32 a1 = a_high, a0 = a_low, r0 = 0;
2610
-
2611
- if (b < 2)
2612
- return;
2613
-
2614
- while (a1 != 0) {
2615
- r0 += (0xffffffff / b) * a1;
2616
- bcm_uint64_multiple_add(&a1, &a0, ((0xffffffff % b) + 1) % b, a1, a0);
2617
- }
2618
-
2619
- r0 += a0 / b;
2620
- *r = r0;
26213661 }
26223662
26233663 #ifndef setbit /* As in the header file */
....@@ -2686,7 +3726,12 @@
26863726 {
26873727 int i;
26883728 for (i = NBITS(uint32) - 1; i >= 0; i--) {
2689
- printf(isbitset(u32arg, i) ? "1" : "0");
3729
+ if (isbitset(u32arg, i)) {
3730
+ printf("1");
3731
+ } else {
3732
+ printf("0");
3733
+ }
3734
+
26903735 if ((i % NBBY) == 0) printf(" ");
26913736 }
26923737 printf("\n");
....@@ -2697,13 +3742,13 @@
26973742 bcm_ip_cksum(uint8 *buf, uint32 len, uint32 sum)
26983743 {
26993744 while (len > 1) {
2700
- sum += (buf[0] << 8) | buf[1];
3745
+ sum += (uint32)((buf[0] << 8) | buf[1]);
27013746 buf += 2;
27023747 len -= 2;
27033748 }
27043749
27053750 if (len > 0) {
2706
- sum += (*buf) << 8;
3751
+ sum += (uint32)((*buf) << 8);
27073752 }
27083753
27093754 while (sum >> 16) {
....@@ -2712,797 +3757,11 @@
27123757
27133758 return ((uint16)~sum);
27143759 }
2715
-#if defined(BCMDRIVER) && !defined(_CFEZ_)
2716
-/*
2717
- * Hierarchical Multiword bitmap based small id allocator.
2718
- *
2719
- * Multilevel hierarchy bitmap. (maximum 2 levels)
2720
- * First hierarchy uses a multiword bitmap to identify 32bit words in the
2721
- * second hierarchy that have at least a single bit set. Each bit in a word of
2722
- * the second hierarchy represents a unique ID that may be allocated.
2723
- *
2724
- * BCM_MWBMAP_ITEMS_MAX: Maximum number of IDs managed.
2725
- * BCM_MWBMAP_BITS_WORD: Number of bits in a bitmap word word
2726
- * BCM_MWBMAP_WORDS_MAX: Maximum number of bitmap words needed for free IDs.
2727
- * BCM_MWBMAP_WDMAP_MAX: Maximum number of bitmap wordss identifying first non
2728
- * non-zero bitmap word carrying at least one free ID.
2729
- * BCM_MWBMAP_SHIFT_OP: Used in MOD, DIV and MUL operations.
2730
- * BCM_MWBMAP_INVALID_IDX: Value ~0U is treated as an invalid ID
2731
- *
2732
- * Design Notes:
2733
- * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many
2734
- * bits are computed each time on allocation and deallocation, requiring 4
2735
- * array indexed access and 3 arithmetic operations. When not defined, a runtime
2736
- * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed.
2737
- * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation.
2738
- * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may
2739
- * be used by defining BCM_MWBMAP_USE_CNTSETBITS.
2740
- *
2741
- * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array
2742
- * size is fixed. No intention to support larger than 4K indice allocation. ID
2743
- * allocators for ranges smaller than 4K will have a wastage of only 12Bytes
2744
- * with savings in not having to use an indirect access, had it been dynamically
2745
- * allocated.
2746
- */
2747
-#define BCM_MWBMAP_ITEMS_MAX (64 * 1024) /* May increase to 64K */
27483760
2749
-#define BCM_MWBMAP_BITS_WORD (NBITS(uint32))
2750
-#define BCM_MWBMAP_WORDS_MAX (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD)
2751
-#define BCM_MWBMAP_WDMAP_MAX (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD)
2752
-#define BCM_MWBMAP_SHIFT_OP (5)
2753
-#define BCM_MWBMAP_MODOP(ix) ((ix) & (BCM_MWBMAP_BITS_WORD - 1))
2754
-#define BCM_MWBMAP_DIVOP(ix) ((ix) >> BCM_MWBMAP_SHIFT_OP)
2755
-#define BCM_MWBMAP_MULOP(ix) ((ix) << BCM_MWBMAP_SHIFT_OP)
2756
-
2757
-/* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */
2758
-#define BCM_MWBMAP_PTR(hdl) ((struct bcm_mwbmap *)(hdl))
2759
-#define BCM_MWBMAP_HDL(ptr) ((void *)(ptr))
2760
-
2761
-#if defined(BCM_MWBMAP_DEBUG)
2762
-#define BCM_MWBMAP_AUDIT(mwb) \
2763
- do { \
2764
- ASSERT((mwb != NULL) && \
2765
- (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \
2766
- bcm_mwbmap_audit(mwb); \
2767
- } while (0)
2768
-#define MWBMAP_ASSERT(exp) ASSERT(exp)
2769
-#define MWBMAP_DBG(x) printf x
2770
-#else /* !BCM_MWBMAP_DEBUG */
2771
-#define BCM_MWBMAP_AUDIT(mwb) do {} while (0)
2772
-#define MWBMAP_ASSERT(exp) do {} while (0)
2773
-#define MWBMAP_DBG(x)
2774
-#endif /* !BCM_MWBMAP_DEBUG */
2775
-
2776
-
2777
-typedef struct bcm_mwbmap { /* Hierarchical multiword bitmap allocator */
2778
- uint16 wmaps; /* Total number of words in free wd bitmap */
2779
- uint16 imaps; /* Total number of words in free id bitmap */
2780
- int32 ifree; /* Count of free indices. Used only in audits */
2781
- uint16 total; /* Total indices managed by multiword bitmap */
2782
-
2783
- void * magic; /* Audit handle parameter from user */
2784
-
2785
- uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of */
2786
-#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
2787
- int8 wd_count[BCM_MWBMAP_WORDS_MAX]; /* free id running count, 1st lvl */
2788
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
2789
-
2790
- uint32 id_bitmap[0]; /* Second level bitmap */
2791
-} bcm_mwbmap_t;
2792
-
2793
-/* Incarnate a hierarchical multiword bitmap based small index allocator. */
2794
-struct bcm_mwbmap *
2795
-bcm_mwbmap_init(osl_t *osh, uint32 items_max)
3761
+int
3762
+BCMRAMFN(valid_bcmerror)(int e)
27963763 {
2797
- struct bcm_mwbmap * mwbmap_p;
2798
- uint32 wordix, size, words, extra;
2799
-
2800
- /* Implementation Constraint: Uses 32bit word bitmap */
2801
- MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U);
2802
- MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U);
2803
- MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX));
2804
- MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U);
2805
-
2806
- ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX);
2807
-
2808
- /* Determine the number of words needed in the multiword bitmap */
2809
- extra = BCM_MWBMAP_MODOP(items_max);
2810
- words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U);
2811
-
2812
- /* Allocate runtime state of multiword bitmap */
2813
- /* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */
2814
- size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words);
2815
- mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size);
2816
- if (mwbmap_p == (bcm_mwbmap_t *)NULL) {
2817
- ASSERT(0);
2818
- goto error1;
2819
- }
2820
- memset(mwbmap_p, 0, size);
2821
-
2822
- /* Initialize runtime multiword bitmap state */
2823
- mwbmap_p->imaps = (uint16)words;
2824
- mwbmap_p->ifree = (int32)items_max;
2825
- mwbmap_p->total = (uint16)items_max;
2826
-
2827
- /* Setup magic, for use in audit of handle */
2828
- mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p);
2829
-
2830
- /* Setup the second level bitmap of free indices */
2831
- /* Mark all indices as available */
2832
- for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) {
2833
- mwbmap_p->id_bitmap[wordix] = (uint32)(~0U);
2834
-#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
2835
- mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD;
2836
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
2837
- }
2838
-
2839
- /* Ensure that extra indices are tagged as un-available */
2840
- if (extra) { /* fixup the free ids in last bitmap and wd_count */
2841
- uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1];
2842
- *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
2843
-#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
2844
- mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */
2845
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
2846
- }
2847
-
2848
- /* Setup the first level bitmap hierarchy */
2849
- extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps);
2850
- words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U);
2851
-
2852
- mwbmap_p->wmaps = (uint16)words;
2853
-
2854
- for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++)
2855
- mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U);
2856
- if (extra) {
2857
- uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1];
2858
- *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */
2859
- }
2860
-
2861
- return mwbmap_p;
2862
-
2863
-error1:
2864
- return BCM_MWBMAP_INVALID_HDL;
2865
-}
2866
-
2867
-/* Release resources used by multiword bitmap based small index allocator. */
2868
-void
2869
-bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl)
2870
-{
2871
- bcm_mwbmap_t * mwbmap_p;
2872
-
2873
- BCM_MWBMAP_AUDIT(mwbmap_hdl);
2874
- mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
2875
-
2876
- MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap)
2877
- + (sizeof(uint32) * mwbmap_p->imaps));
2878
- return;
2879
-}
2880
-
2881
-/* Allocate a unique small index using a multiword bitmap index allocator. */
2882
-uint32 BCMFASTPATH
2883
-bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl)
2884
-{
2885
- bcm_mwbmap_t * mwbmap_p;
2886
- uint32 wordix, bitmap;
2887
-
2888
- BCM_MWBMAP_AUDIT(mwbmap_hdl);
2889
- mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
2890
-
2891
- /* Start with the first hierarchy */
2892
- for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) {
2893
-
2894
- bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */
2895
-
2896
- if (bitmap != 0U) {
2897
-
2898
- uint32 count, bitix, *bitmap_p;
2899
-
2900
- bitmap_p = &mwbmap_p->wd_bitmap[wordix];
2901
-
2902
- /* clear all except trailing 1 */
2903
- bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
2904
- MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
2905
- bcm_count_leading_zeros(bitmap));
2906
- bitix = (BCM_MWBMAP_BITS_WORD - 1)
2907
- - bcm_count_leading_zeros(bitmap); /* use asm clz */
2908
- wordix = BCM_MWBMAP_MULOP(wordix) + bitix;
2909
-
2910
- /* Clear bit if wd count is 0, without conditional branch */
2911
-#if defined(BCM_MWBMAP_USE_CNTSETBITS)
2912
- count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1;
2913
-#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
2914
- mwbmap_p->wd_count[wordix]--;
2915
- count = mwbmap_p->wd_count[wordix];
2916
- MWBMAP_ASSERT(count ==
2917
- (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1));
2918
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
2919
- MWBMAP_ASSERT(count >= 0);
2920
-
2921
- /* clear wd_bitmap bit if id_map count is 0 */
2922
- bitmap = (count == 0) << bitix;
2923
-
2924
- MWBMAP_DBG((
2925
- "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
2926
- bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count));
2927
-
2928
- *bitmap_p ^= bitmap;
2929
-
2930
- /* Use bitix in the second hierarchy */
2931
- bitmap_p = &mwbmap_p->id_bitmap[wordix];
2932
-
2933
- bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */
2934
- MWBMAP_ASSERT(bitmap != 0U);
2935
-
2936
- /* clear all except trailing 1 */
2937
- bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap))));
2938
- MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) ==
2939
- bcm_count_leading_zeros(bitmap));
2940
- bitix = BCM_MWBMAP_MULOP(wordix)
2941
- + (BCM_MWBMAP_BITS_WORD - 1)
2942
- - bcm_count_leading_zeros(bitmap); /* use asm clz */
2943
-
2944
- mwbmap_p->ifree--; /* decrement system wide free count */
2945
- MWBMAP_ASSERT(mwbmap_p->ifree >= 0);
2946
-
2947
- MWBMAP_DBG((
2948
- "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d",
2949
- bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
2950
- mwbmap_p->ifree));
2951
-
2952
- *bitmap_p ^= bitmap; /* mark as allocated = 1b0 */
2953
-
2954
- return bitix;
2955
- }
2956
- }
2957
-
2958
- ASSERT(mwbmap_p->ifree == 0);
2959
-
2960
- return BCM_MWBMAP_INVALID_IDX;
2961
-}
2962
-
2963
-/* Force an index at a specified position to be in use */
2964
-void
2965
-bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
2966
-{
2967
- bcm_mwbmap_t * mwbmap_p;
2968
- uint32 count, wordix, bitmap, *bitmap_p;
2969
-
2970
- BCM_MWBMAP_AUDIT(mwbmap_hdl);
2971
- mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
2972
-
2973
- ASSERT(bitix < mwbmap_p->total);
2974
-
2975
- /* Start with second hierarchy */
2976
- wordix = BCM_MWBMAP_DIVOP(bitix);
2977
- bitmap = (uint32)(1U << BCM_MWBMAP_MODOP(bitix));
2978
- bitmap_p = &mwbmap_p->id_bitmap[wordix];
2979
-
2980
- ASSERT((*bitmap_p & bitmap) == bitmap);
2981
-
2982
- mwbmap_p->ifree--; /* update free count */
2983
- ASSERT(mwbmap_p->ifree >= 0);
2984
-
2985
- MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d",
2986
- bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap,
2987
- mwbmap_p->ifree));
2988
-
2989
- *bitmap_p ^= bitmap; /* mark as in use */
2990
-
2991
- /* Update first hierarchy */
2992
- bitix = wordix;
2993
-
2994
- wordix = BCM_MWBMAP_DIVOP(bitix);
2995
- bitmap_p = &mwbmap_p->wd_bitmap[wordix];
2996
-
2997
-#if defined(BCM_MWBMAP_USE_CNTSETBITS)
2998
- count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
2999
-#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
3000
- mwbmap_p->wd_count[bitix]--;
3001
- count = mwbmap_p->wd_count[bitix];
3002
- MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
3003
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
3004
- MWBMAP_ASSERT(count >= 0);
3005
-
3006
- bitmap = (count == 0) << BCM_MWBMAP_MODOP(bitix);
3007
-
3008
- MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d",
3009
- BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap,
3010
- (*bitmap_p) ^ bitmap, count));
3011
-
3012
- *bitmap_p ^= bitmap; /* mark as in use */
3013
-
3014
- return;
3015
-}
3016
-
3017
-/* Free a previously allocated index back into the multiword bitmap allocator */
3018
-void BCMFASTPATH
3019
-bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
3020
-{
3021
- bcm_mwbmap_t * mwbmap_p;
3022
- uint32 wordix, bitmap, *bitmap_p;
3023
-
3024
- BCM_MWBMAP_AUDIT(mwbmap_hdl);
3025
- mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
3026
-
3027
- ASSERT(bitix < mwbmap_p->total);
3028
-
3029
- /* Start with second level hierarchy */
3030
- wordix = BCM_MWBMAP_DIVOP(bitix);
3031
- bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
3032
- bitmap_p = &mwbmap_p->id_bitmap[wordix];
3033
-
3034
- ASSERT((*bitmap_p & bitmap) == 0U); /* ASSERT not a double free */
3035
-
3036
- mwbmap_p->ifree++; /* update free count */
3037
- ASSERT(mwbmap_p->ifree <= mwbmap_p->total);
3038
-
3039
- MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d",
3040
- bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap,
3041
- mwbmap_p->ifree));
3042
-
3043
- *bitmap_p |= bitmap; /* mark as available */
3044
-
3045
- /* Now update first level hierarchy */
3046
-
3047
- bitix = wordix;
3048
-
3049
- wordix = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */
3050
- bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
3051
- bitmap_p = &mwbmap_p->wd_bitmap[wordix];
3052
-
3053
-#if !defined(BCM_MWBMAP_USE_CNTSETBITS)
3054
- mwbmap_p->wd_count[bitix]++;
3055
-#endif
3056
-
3057
-#if defined(BCM_MWBMAP_DEBUG)
3058
- {
3059
- uint32 count;
3060
-#if defined(BCM_MWBMAP_USE_CNTSETBITS)
3061
- count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]);
3062
-#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
3063
- count = mwbmap_p->wd_count[bitix];
3064
- MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]));
3065
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
3066
-
3067
- MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD);
3068
-
3069
- MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d",
3070
- bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count));
3071
- }
3072
-#endif /* BCM_MWBMAP_DEBUG */
3073
-
3074
- *bitmap_p |= bitmap;
3075
-
3076
- return;
3077
-}
3078
-
3079
-/* Fetch the toal number of free indices in the multiword bitmap allocator */
3080
-uint32
3081
-bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl)
3082
-{
3083
- bcm_mwbmap_t * mwbmap_p;
3084
-
3085
- BCM_MWBMAP_AUDIT(mwbmap_hdl);
3086
- mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
3087
-
3088
- ASSERT(mwbmap_p->ifree >= 0);
3089
-
3090
- return mwbmap_p->ifree;
3091
-}
3092
-
3093
-/* Determine whether an index is inuse or free */
3094
-bool
3095
-bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix)
3096
-{
3097
- bcm_mwbmap_t * mwbmap_p;
3098
- uint32 wordix, bitmap;
3099
-
3100
- BCM_MWBMAP_AUDIT(mwbmap_hdl);
3101
- mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
3102
-
3103
- ASSERT(bitix < mwbmap_p->total);
3104
-
3105
- wordix = BCM_MWBMAP_DIVOP(bitix);
3106
- bitmap = (1U << BCM_MWBMAP_MODOP(bitix));
3107
-
3108
- return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U);
3109
-}
3110
-
3111
-/* Debug dump a multiword bitmap allocator */
3112
-void
3113
-bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl)
3114
-{
3115
- uint32 ix, count;
3116
- bcm_mwbmap_t * mwbmap_p;
3117
-
3118
- BCM_MWBMAP_AUDIT(mwbmap_hdl);
3119
- mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
3120
-
3121
- printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n", mwbmap_p,
3122
- mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total);
3123
- for (ix = 0U; ix < mwbmap_p->wmaps; ix++) {
3124
- printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]);
3125
- bcm_bitprint32(mwbmap_p->wd_bitmap[ix]);
3126
- printf("\n");
3127
- }
3128
- for (ix = 0U; ix < mwbmap_p->imaps; ix++) {
3129
-#if defined(BCM_MWBMAP_USE_CNTSETBITS)
3130
- count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]);
3131
-#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
3132
- count = mwbmap_p->wd_count[ix];
3133
- MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix]));
3134
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
3135
- printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count);
3136
- bcm_bitprint32(mwbmap_p->id_bitmap[ix]);
3137
- printf("\n");
3138
- }
3139
-
3140
- return;
3141
-}
3142
-
3143
-/* Audit a hierarchical multiword bitmap */
3144
-void
3145
-bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl)
3146
-{
3147
- bcm_mwbmap_t * mwbmap_p;
3148
- uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p;
3149
-
3150
- mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl);
3151
-
3152
- for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) {
3153
-
3154
- bitmap_p = &mwbmap_p->wd_bitmap[wordix];
3155
-
3156
- for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) {
3157
- if ((*bitmap_p) & (1 << bitix)) {
3158
- idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix;
3159
-#if defined(BCM_MWBMAP_USE_CNTSETBITS)
3160
- count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]);
3161
-#else /* ! BCM_MWBMAP_USE_CNTSETBITS */
3162
- count = mwbmap_p->wd_count[idmap_ix];
3163
- ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]));
3164
-#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */
3165
- ASSERT(count != 0U);
3166
- free_cnt += count;
3167
- }
3168
- }
3169
- }
3170
-
3171
- ASSERT((int)free_cnt == mwbmap_p->ifree);
3172
-}
3173
-/* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */
3174
-
3175
-/* Simple 16bit Id allocator using a stack implementation. */
3176
-typedef struct id16_map {
3177
- uint32 failures; /* count of failures */
3178
- void *dbg; /* debug placeholder */
3179
- uint16 total; /* total number of ids managed by allocator */
3180
- uint16 start; /* start value of 16bit ids to be managed */
3181
- int stack_idx; /* index into stack of available ids */
3182
- uint16 stack[0]; /* stack of 16 bit ids */
3183
-} id16_map_t;
3184
-
3185
-#define ID16_MAP_SZ(items) (sizeof(id16_map_t) + \
3186
- (sizeof(uint16) * (items)))
3187
-
3188
-#if defined(BCM_DBG)
3189
-
3190
-/* Uncomment BCM_DBG_ID16 to debug double free */
3191
-/* #define BCM_DBG_ID16 */
3192
-
3193
-typedef struct id16_map_dbg {
3194
- uint16 total;
3195
- bool avail[0];
3196
-} id16_map_dbg_t;
3197
-#define ID16_MAP_DBG_SZ(items) (sizeof(id16_map_dbg_t) + \
3198
- (sizeof(bool) * (items)))
3199
-#define ID16_MAP_MSG(x) print x
3200
-#else
3201
-#define ID16_MAP_MSG(x)
3202
-#endif /* BCM_DBG */
3203
-
3204
-void * /* Construct an id16 allocator: [start_val16 .. start_val16+total_ids) */
3205
-id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16)
3206
-{
3207
- uint16 idx, val16;
3208
- id16_map_t * id16_map;
3209
-
3210
- ASSERT(total_ids > 0);
3211
-
3212
- /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
3213
- * with random values.
3214
- */
3215
- ASSERT((start_val16 == ID16_UNDEFINED) ||
3216
- (start_val16 + total_ids) < ID16_INVALID);
3217
-
3218
- id16_map = (id16_map_t *) MALLOC(osh, ID16_MAP_SZ(total_ids));
3219
- if (id16_map == NULL) {
3220
- return NULL;
3221
- }
3222
-
3223
- id16_map->total = total_ids;
3224
- id16_map->start = start_val16;
3225
- id16_map->failures = 0;
3226
- id16_map->dbg = NULL;
3227
-
3228
- /*
3229
- * Populate stack with 16bit id values, commencing with start_val16.
3230
- * if start_val16 is ID16_UNDEFINED, then do not populate the id16 map.
3231
- */
3232
- id16_map->stack_idx = -1;
3233
-
3234
- if (id16_map->start != ID16_UNDEFINED) {
3235
- val16 = start_val16;
3236
-
3237
- for (idx = 0; idx < total_ids; idx++, val16++) {
3238
- id16_map->stack_idx = idx;
3239
- id16_map->stack[id16_map->stack_idx] = val16;
3240
- }
3241
- }
3242
-
3243
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3244
- if (id16_map->start != ID16_UNDEFINED) {
3245
- id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids));
3246
-
3247
- if (id16_map->dbg) {
3248
- id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
3249
-
3250
- id16_map_dbg->total = total_ids;
3251
- for (idx = 0; idx < total_ids; idx++) {
3252
- id16_map_dbg->avail[idx] = TRUE;
3253
- }
3254
- }
3255
- }
3256
-#endif /* BCM_DBG && BCM_DBG_ID16 */
3257
-
3258
- return (void *)id16_map;
3259
-}
3260
-
3261
-void * /* Destruct an id16 allocator instance */
3262
-id16_map_fini(osl_t *osh, void * id16_map_hndl)
3263
-{
3264
- uint16 total_ids;
3265
- id16_map_t * id16_map;
3266
-
3267
- if (id16_map_hndl == NULL)
3268
- return NULL;
3269
-
3270
- id16_map = (id16_map_t *)id16_map_hndl;
3271
-
3272
- total_ids = id16_map->total;
3273
- ASSERT(total_ids > 0);
3274
-
3275
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3276
- if (id16_map->dbg) {
3277
- MFREE(osh, id16_map->dbg, ID16_MAP_DBG_SZ(total_ids));
3278
- id16_map->dbg = NULL;
3279
- }
3280
-#endif /* BCM_DBG && BCM_DBG_ID16 */
3281
-
3282
- id16_map->total = 0;
3283
- MFREE(osh, id16_map, ID16_MAP_SZ(total_ids));
3284
-
3285
- return NULL;
3286
-}
3287
-
3288
-void
3289
-id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16)
3290
-{
3291
- uint16 idx, val16;
3292
- id16_map_t * id16_map;
3293
-
3294
- ASSERT(total_ids > 0);
3295
- /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
3296
- * with random values.
3297
- */
3298
- ASSERT((start_val16 == ID16_UNDEFINED) ||
3299
- (start_val16 + total_ids) < ID16_INVALID);
3300
-
3301
- id16_map = (id16_map_t *)id16_map_hndl;
3302
- if (id16_map == NULL) {
3303
- return;
3304
- }
3305
-
3306
- id16_map->total = total_ids;
3307
- id16_map->start = start_val16;
3308
- id16_map->failures = 0;
3309
-
3310
- /* Populate stack with 16bit id values, commencing with start_val16 */
3311
- id16_map->stack_idx = -1;
3312
-
3313
- if (id16_map->start != ID16_UNDEFINED) {
3314
- val16 = start_val16;
3315
-
3316
- for (idx = 0; idx < total_ids; idx++, val16++) {
3317
- id16_map->stack_idx = idx;
3318
- id16_map->stack[id16_map->stack_idx] = val16;
3319
- }
3320
- }
3321
-
3322
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3323
- if (id16_map->start != ID16_UNDEFINED) {
3324
- if (id16_map->dbg) {
3325
- id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
3326
-
3327
- id16_map_dbg->total = total_ids;
3328
- for (idx = 0; idx < total_ids; idx++) {
3329
- id16_map_dbg->avail[idx] = TRUE;
3330
- }
3331
- }
3332
- }
3333
-#endif /* BCM_DBG && BCM_DBG_ID16 */
3334
-}
3335
-
3336
-uint16 BCMFASTPATH /* Allocate a unique 16bit id */
3337
-id16_map_alloc(void * id16_map_hndl)
3338
-{
3339
- uint16 val16;
3340
- id16_map_t * id16_map;
3341
-
3342
- ASSERT(id16_map_hndl != NULL);
3343
-
3344
- id16_map = (id16_map_t *)id16_map_hndl;
3345
-
3346
- ASSERT(id16_map->total > 0);
3347
-
3348
- if (id16_map->stack_idx < 0) {
3349
- id16_map->failures++;
3350
- return ID16_INVALID;
3351
- }
3352
-
3353
- val16 = id16_map->stack[id16_map->stack_idx];
3354
- id16_map->stack_idx--;
3355
-
3356
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3357
- ASSERT((id16_map->start == ID16_UNDEFINED) ||
3358
- (val16 < (id16_map->start + id16_map->total)));
3359
-
3360
- if (id16_map->dbg) { /* Validate val16 */
3361
- id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
3362
-
3363
- ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == TRUE);
3364
- id16_map_dbg->avail[val16 - id16_map->start] = FALSE;
3365
- }
3366
-#endif /* BCM_DBG && BCM_DBG_ID16 */
3367
-
3368
- return val16;
3369
-}
3370
-
3371
-
3372
-void BCMFASTPATH /* Free a 16bit id value into the id16 allocator */
3373
-id16_map_free(void * id16_map_hndl, uint16 val16)
3374
-{
3375
- id16_map_t * id16_map;
3376
-
3377
- ASSERT(id16_map_hndl != NULL);
3378
-
3379
- id16_map = (id16_map_t *)id16_map_hndl;
3380
-
3381
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3382
- ASSERT((id16_map->start == ID16_UNDEFINED) ||
3383
- (val16 < (id16_map->start + id16_map->total)));
3384
-
3385
- if (id16_map->dbg) { /* Validate val16 */
3386
- id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
3387
-
3388
- ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == FALSE);
3389
- id16_map_dbg->avail[val16 - id16_map->start] = TRUE;
3390
- }
3391
-#endif /* BCM_DBG && BCM_DBG_ID16 */
3392
-
3393
- id16_map->stack_idx++;
3394
- id16_map->stack[id16_map->stack_idx] = val16;
3395
-}
3396
-
3397
-uint32 /* Returns number of failures to allocate an unique id16 */
3398
-id16_map_failures(void * id16_map_hndl)
3399
-{
3400
- ASSERT(id16_map_hndl != NULL);
3401
- return ((id16_map_t *)id16_map_hndl)->failures;
3402
-}
3403
-
3404
-bool
3405
-id16_map_audit(void * id16_map_hndl)
3406
-{
3407
- int idx;
3408
- int insane = 0;
3409
- id16_map_t * id16_map;
3410
-
3411
- ASSERT(id16_map_hndl != NULL);
3412
-
3413
- id16_map = (id16_map_t *)id16_map_hndl;
3414
-
3415
- ASSERT(id16_map->stack_idx >= -1);
3416
- ASSERT(id16_map->stack_idx < (int)id16_map->total);
3417
-
3418
- if (id16_map->start == ID16_UNDEFINED)
3419
- goto done;
3420
-
3421
- for (idx = 0; idx <= id16_map->stack_idx; idx++) {
3422
- ASSERT(id16_map->stack[idx] >= id16_map->start);
3423
- ASSERT(id16_map->stack[idx] < (id16_map->start + id16_map->total));
3424
-
3425
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3426
- if (id16_map->dbg) {
3427
- uint16 val16 = id16_map->stack[idx];
3428
- if (((id16_map_dbg_t *)(id16_map->dbg))->avail[val16] != TRUE) {
3429
- insane |= 1;
3430
- ID16_MAP_MSG(("id16_map<%p>: stack_idx %u invalid val16 %u\n",
3431
- id16_map_hndl, idx, val16));
3432
- }
3433
- }
3434
-#endif /* BCM_DBG && BCM_DBG_ID16 */
3435
- }
3436
-
3437
-#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
3438
- if (id16_map->dbg) {
3439
- uint16 avail = 0; /* Audit available ids counts */
3440
- for (idx = 0; idx < id16_map_dbg->total; idx++) {
3441
- if (((id16_map_dbg_t *)(id16_map->dbg))->avail[idx16] == TRUE)
3442
- avail++;
3443
- }
3444
- if (avail && (avail != (id16_map->stack_idx + 1))) {
3445
- insane |= 1;
3446
- ID16_MAP_MSG(("id16_map<%p>: avail %u stack_idx %u\n",
3447
- id16_map_hndl, avail, id16_map->stack_idx));
3448
- }
3449
- }
3450
-#endif /* BCM_DBG && BCM_DBG_ID16 */
3451
-
3452
-done:
3453
- /* invoke any other system audits */
3454
- return (!!insane);
3455
-}
3456
-/* END: Simple id16 allocator */
3457
-
3458
-
3459
-#endif
3460
-
3461
-/* calculate a >> b; and returns only lower 32 bits */
3462
-void
3463
-bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b)
3464
-{
3465
- uint32 a1 = a_high, a0 = a_low, r0 = 0;
3466
-
3467
- if (b == 0) {
3468
- r0 = a_low;
3469
- *r = r0;
3470
- return;
3471
- }
3472
-
3473
- if (b < 32) {
3474
- a0 = a0 >> b;
3475
- a1 = a1 & ((1 << b) - 1);
3476
- a1 = a1 << (32 - b);
3477
- r0 = a0 | a1;
3478
- *r = r0;
3479
- return;
3480
- } else {
3481
- r0 = a1 >> (b - 32);
3482
- *r = r0;
3483
- return;
3484
- }
3485
-
3486
-}
3487
-
3488
-/* calculate a + b where a is a 64 bit number and b is a 32 bit number */
3489
-void
3490
-bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset)
3491
-{
3492
- uint32 r1_lo = *r_lo;
3493
- (*r_lo) += offset;
3494
- if (*r_lo < r1_lo)
3495
- (*r_hi) ++;
3496
-}
3497
-
3498
-/* calculate a - b where a is a 64 bit number and b is a 32 bit number */
3499
-void
3500
-bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset)
3501
-{
3502
- uint32 r1_lo = *r_lo;
3503
- (*r_lo) -= offset;
3504
- if (*r_lo > r1_lo)
3505
- (*r_hi) --;
3764
+ return ((e <= 0) && (e >= BCME_LAST));
35063765 }
35073766
35083767 #ifdef DEBUG_COUNTER
....@@ -3534,85 +3793,6 @@
35343793 #define counter_printlog(a) do {} while (0)
35353794 #endif /* OSL_SYSUPTIME_SUPPORT == TRUE */
35363795 #endif /* DEBUG_COUNTER */
3537
-
3538
-#if defined(BCMDRIVER) && !defined(_CFEZ_)
3539
-void
3540
-dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size)
3541
-{
3542
- uint32 mem_size;
3543
- mem_size = sizeof(dll_pool_t) + (elems_max * elem_size);
3544
- if (pool)
3545
- MFREE(osh, pool, mem_size);
3546
-}
3547
-dll_pool_t *
3548
-dll_pool_init(void * osh, uint16 elems_max, uint16 elem_size)
3549
-{
3550
- uint32 mem_size, i;
3551
- dll_pool_t * dll_pool_p;
3552
- dll_t * elem_p;
3553
-
3554
- ASSERT(elem_size > sizeof(dll_t));
3555
-
3556
- mem_size = sizeof(dll_pool_t) + (elems_max * elem_size);
3557
-
3558
- if ((dll_pool_p = (dll_pool_t *)MALLOCZ(osh, mem_size)) == NULL) {
3559
- printf("dll_pool_init: elems_max<%u> elem_size<%u> malloc failure\n",
3560
- elems_max, elem_size);
3561
- ASSERT(0);
3562
- return dll_pool_p;
3563
- }
3564
-
3565
- dll_init(&dll_pool_p->free_list);
3566
- dll_pool_p->elems_max = elems_max;
3567
- dll_pool_p->elem_size = elem_size;
3568
-
3569
- elem_p = dll_pool_p->elements;
3570
- for (i = 0; i < elems_max; i++) {
3571
- dll_append(&dll_pool_p->free_list, elem_p);
3572
- elem_p = (dll_t *)((uintptr)elem_p + elem_size);
3573
- }
3574
-
3575
- dll_pool_p->free_count = elems_max;
3576
-
3577
- return dll_pool_p;
3578
-}
3579
-
3580
-
3581
-void *
3582
-dll_pool_alloc(dll_pool_t * dll_pool_p)
3583
-{
3584
- dll_t * elem_p;
3585
-
3586
- if (dll_pool_p->free_count == 0) {
3587
- ASSERT(dll_empty(&dll_pool_p->free_list));
3588
- return NULL;
3589
- }
3590
-
3591
- elem_p = dll_head_p(&dll_pool_p->free_list);
3592
- dll_delete(elem_p);
3593
- dll_pool_p->free_count -= 1;
3594
-
3595
- return (void *)elem_p;
3596
-}
3597
-
3598
-void
3599
-dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p)
3600
-{
3601
- dll_t * node_p = (dll_t *)elem_p;
3602
- dll_prepend(&dll_pool_p->free_list, node_p);
3603
- dll_pool_p->free_count += 1;
3604
-}
3605
-
3606
-
3607
-void
3608
-dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p)
3609
-{
3610
- dll_t * node_p = (dll_t *)elem_p;
3611
- dll_append(&dll_pool_p->free_list, node_p);
3612
- dll_pool_p->free_count += 1;
3613
-}
3614
-
3615
-#endif
36163796
36173797 /* calculate partial checksum */
36183798 static uint32
....@@ -3674,5 +3854,498 @@
36743854 ptr += OFFSETOF(struct ipv4_hdr, hdr_chksum) + 2;
36753855
36763856 /* return calculated chksum */
3677
- return ip_cksum(sum, ptr, ip_len - OFFSETOF(struct ipv4_hdr, src_ip));
3857
+ return ip_cksum(sum, ptr, (uint32)((uint)ip_len - OFFSETOF(struct ipv4_hdr, src_ip)));
3858
+}
3859
+
3860
+/* calculate TCP header checksum using partial sum */
3861
+static uint16
3862
+tcp_hdr_chksum(uint32 sum, uint8 *tcp_hdr, uint16 tcp_len)
3863
+{
3864
+ uint8 *ptr = tcp_hdr;
3865
+
3866
+ ASSERT(tcp_hdr != NULL);
3867
+ ASSERT(tcp_len >= TCP_MIN_HEADER_LEN);
3868
+
3869
+ /* partial TCP cksum skipping the chksum field */
3870
+ sum = ip_cksum_partial(sum, ptr, OFFSETOF(struct bcmtcp_hdr, chksum));
3871
+ ptr += OFFSETOF(struct bcmtcp_hdr, chksum) + 2;
3872
+
3873
+ /* return calculated chksum */
3874
+ return ip_cksum(sum, ptr, tcp_len - OFFSETOF(struct bcmtcp_hdr, urg_ptr));
3875
+}
3876
+
3877
+struct tcp_pseudo_hdr {
3878
+ uint8 src_ip[IPV4_ADDR_LEN]; /* Source IP Address */
3879
+ uint8 dst_ip[IPV4_ADDR_LEN]; /* Destination IP Address */
3880
+ uint8 zero;
3881
+ uint8 prot;
3882
+ uint16 tcp_size;
3883
+};
3884
+
3885
+/* calculate IPv4 TCP header checksum
3886
+ * - input ip and tcp points to IP and TCP header in network order
3887
+ * - output cksum is in network order
3888
+ */
3889
+uint16
3890
+ipv4_tcp_hdr_cksum(uint8 *ip, uint8 *tcp, uint16 tcp_len)
3891
+{
3892
+ struct ipv4_hdr *ip_hdr = (struct ipv4_hdr *)ip;
3893
+ struct tcp_pseudo_hdr tcp_ps;
3894
+ uint32 sum = 0;
3895
+
3896
+ ASSERT(ip != NULL);
3897
+ ASSERT(tcp != NULL);
3898
+ ASSERT(tcp_len >= TCP_MIN_HEADER_LEN);
3899
+
3900
+ if (!ip || !tcp || !(tcp_len >= TCP_MIN_HEADER_LEN))
3901
+ return 0;
3902
+ /* pseudo header cksum */
3903
+ memset(&tcp_ps, 0, sizeof(tcp_ps));
3904
+ memcpy(&tcp_ps.dst_ip, ip_hdr->dst_ip, IPV4_ADDR_LEN);
3905
+ memcpy(&tcp_ps.src_ip, ip_hdr->src_ip, IPV4_ADDR_LEN);
3906
+ tcp_ps.zero = 0;
3907
+ tcp_ps.prot = ip_hdr->prot;
3908
+ tcp_ps.tcp_size = hton16(tcp_len);
3909
+ sum = ip_cksum_partial(sum, (uint8 *)&tcp_ps, sizeof(tcp_ps));
3910
+
3911
+ /* return calculated TCP header chksum */
3912
+ return tcp_hdr_chksum(sum, tcp, tcp_len);
3913
+}
3914
+
3915
+struct ipv6_pseudo_hdr {
3916
+ uint8 saddr[IPV6_ADDR_LEN];
3917
+ uint8 daddr[IPV6_ADDR_LEN];
3918
+ uint16 payload_len;
3919
+ uint8 zero;
3920
+ uint8 next_hdr;
3921
+};
3922
+
3923
+/* calculate IPv6 TCP header checksum
3924
+ * - input ipv6 and tcp points to IPv6 and TCP header in network order
3925
+ * - output cksum is in network order
3926
+ */
3927
+uint16
3928
+ipv6_tcp_hdr_cksum(uint8 *ipv6, uint8 *tcp, uint16 tcp_len)
3929
+{
3930
+ struct ipv6_hdr *ipv6_hdr = (struct ipv6_hdr *)ipv6;
3931
+ struct ipv6_pseudo_hdr ipv6_pseudo;
3932
+ uint32 sum = 0;
3933
+
3934
+ ASSERT(ipv6 != NULL);
3935
+ ASSERT(tcp != NULL);
3936
+ ASSERT(tcp_len >= TCP_MIN_HEADER_LEN);
3937
+
3938
+ if (!ipv6 || !tcp || !(tcp_len >= TCP_MIN_HEADER_LEN))
3939
+ return 0;
3940
+ /* pseudo header cksum */
3941
+ memset((char *)&ipv6_pseudo, 0, sizeof(ipv6_pseudo));
3942
+ memcpy((char *)ipv6_pseudo.saddr, (char *)ipv6_hdr->saddr.addr,
3943
+ sizeof(ipv6_pseudo.saddr));
3944
+ memcpy((char *)ipv6_pseudo.daddr, (char *)ipv6_hdr->daddr.addr,
3945
+ sizeof(ipv6_pseudo.daddr));
3946
+ ipv6_pseudo.payload_len = ipv6_hdr->payload_len;
3947
+ ipv6_pseudo.next_hdr = ipv6_hdr->nexthdr;
3948
+ sum = ip_cksum_partial(sum, (uint8 *)&ipv6_pseudo, sizeof(ipv6_pseudo));
3949
+
3950
+ /* return calculated TCP header chksum */
3951
+ return tcp_hdr_chksum(sum, tcp, tcp_len);
3952
+}
3953
+
3954
+void *_bcmutils_dummy_fn = NULL;
3955
+
3956
+/* GROUP 1 --- start
3957
+ * These function under GROUP 1 are general purpose functions to do complex number
3958
+ * calculations and square root calculation.
3959
+ */
3960
+
3961
+uint32 sqrt_int(uint32 value)
3962
+{
3963
+ uint32 root = 0, shift = 0;
3964
+
3965
+ /* Compute integer nearest to square root of input integer value */
3966
+ for (shift = 0; shift < 32; shift += 2) {
3967
+ if (((0x40000000 >> shift) + root) <= value) {
3968
+ value -= ((0x40000000 >> shift) + root);
3969
+ root = (root >> 1) | (0x40000000 >> shift);
3970
+ }
3971
+ else {
3972
+ root = root >> 1;
3973
+ }
3974
+ }
3975
+
3976
+ /* round to the nearest integer */
3977
+ if (root < value) ++root;
3978
+
3979
+ return root;
3980
+}
3981
+/* GROUP 1 --- end */
3982
+
3983
+/* read/write field in a consecutive bits in an octet array.
3984
+ * 'addr' is the octet array's start byte address
3985
+ * 'size' is the octet array's byte size
3986
+ * 'stbit' is the value's start bit offset
3987
+ * 'nbits' is the value's bit size
3988
+ * This set of utilities are for convenience. Don't use them
3989
+ * in time critical/data path as there's a great overhead in them.
3990
+ */
3991
+void
3992
+setbits(uint8 *addr, uint size, uint stbit, uint nbits, uint32 val)
3993
+{
3994
+ uint fbyte = stbit >> 3; /* first byte */
3995
+ uint lbyte = (stbit + nbits - 1) >> 3; /* last byte */
3996
+ uint fbit = stbit & 7; /* first bit in the first byte */
3997
+ uint rbits = (nbits > 8 - fbit ?
3998
+ nbits - (8 - fbit) :
3999
+ 0) & 7; /* remaining bits of the last byte when not 0 */
4000
+ uint8 mask;
4001
+ uint byte;
4002
+
4003
+ BCM_REFERENCE(size);
4004
+
4005
+ ASSERT(fbyte < size);
4006
+ ASSERT(lbyte < size);
4007
+ ASSERT(nbits <= (sizeof(val) << 3));
4008
+
4009
+ /* all bits are in the same byte */
4010
+ if (fbyte == lbyte) {
4011
+ mask = (uint8)(((1 << nbits) - 1) << fbit);
4012
+ addr[fbyte] &= ~mask;
4013
+ addr[fbyte] |= (uint8)(val << fbit);
4014
+ return;
4015
+ }
4016
+
4017
+ /* first partial byte */
4018
+ if (fbit > 0) {
4019
+ mask = (uint8)(0xff << fbit);
4020
+ addr[fbyte] &= ~mask;
4021
+ addr[fbyte] |= (uint8)(val << fbit);
4022
+ val >>= (8 - fbit);
4023
+ nbits -= (8 - fbit);
4024
+ fbyte ++; /* first full byte */
4025
+ }
4026
+
4027
+ /* last partial byte */
4028
+ if (rbits > 0) {
4029
+ mask = (uint8)((1 << rbits) - 1);
4030
+ addr[lbyte] &= ~mask;
4031
+ addr[lbyte] |= (uint8)(val >> (nbits - rbits));
4032
+ lbyte --; /* last full byte */
4033
+ }
4034
+
4035
+ /* remaining full byte(s) */
4036
+ for (byte = fbyte; byte <= lbyte; byte ++) {
4037
+ addr[byte] = (uint8)val;
4038
+ val >>= 8;
4039
+ }
4040
+}
4041
+
4042
+uint32
4043
+getbits(const uint8 *addr, uint size, uint stbit, uint nbits)
4044
+{
4045
+ uint fbyte = stbit >> 3; /* first byte */
4046
+ uint lbyte = (stbit + nbits - 1) >> 3; /* last byte */
4047
+ uint fbit = stbit & 7; /* first bit in the first byte */
4048
+ uint rbits = (nbits > 8 - fbit ?
4049
+ nbits - (8 - fbit) :
4050
+ 0) & 7; /* remaining bits of the last byte when not 0 */
4051
+ uint32 val = 0;
4052
+ uint bits = 0; /* bits in first partial byte */
4053
+ uint8 mask;
4054
+ uint byte;
4055
+
4056
+ BCM_REFERENCE(size);
4057
+
4058
+ ASSERT(fbyte < size);
4059
+ ASSERT(lbyte < size);
4060
+ ASSERT(nbits <= (sizeof(val) << 3));
4061
+
4062
+ /* all bits are in the same byte */
4063
+ if (fbyte == lbyte) {
4064
+ mask = (uint8)(((1 << nbits) - 1) << fbit);
4065
+ val = (addr[fbyte] & mask) >> fbit;
4066
+ return val;
4067
+ }
4068
+
4069
+ /* first partial byte */
4070
+ if (fbit > 0) {
4071
+ bits = 8 - fbit;
4072
+ mask = (uint8)(0xFFu << fbit);
4073
+ val |= (addr[fbyte] & mask) >> fbit;
4074
+ fbyte ++; /* first full byte */
4075
+ }
4076
+
4077
+ /* last partial byte */
4078
+ if (rbits > 0) {
4079
+ mask = (uint8)((1 << rbits) - 1);
4080
+ val |= (uint32)((addr[lbyte] & mask) << (nbits - rbits));
4081
+ lbyte --; /* last full byte */
4082
+ }
4083
+
4084
+ /* remaining full byte(s) */
4085
+ for (byte = fbyte; byte <= lbyte; byte ++) {
4086
+ val |= (uint32)((addr[byte] << (((byte - fbyte) << 3) + bits)));
4087
+ }
4088
+
4089
+ return val;
4090
+}
4091
+
4092
+#ifdef BCMDRIVER
4093
+
4094
+/** allocate variable sized data with 'size' bytes. note: vld should NOT be null.
4095
+ */
4096
+int
4097
+bcm_vdata_alloc(osl_t *osh, var_len_data_t *vld, uint32 size)
4098
+{
4099
+ int ret = BCME_ERROR;
4100
+ uint8 *dat = NULL;
4101
+
4102
+ if (vld == NULL) {
4103
+ ASSERT(0);
4104
+ goto done;
4105
+ }
4106
+
4107
+ /* trying to allocate twice? */
4108
+ if (vld->vdata != NULL) {
4109
+ ASSERT(0);
4110
+ goto done;
4111
+ }
4112
+
4113
+ /* trying to allocate 0 size? */
4114
+ if (size == 0) {
4115
+ ASSERT(0);
4116
+ ret = BCME_BADARG;
4117
+ goto done;
4118
+ }
4119
+
4120
+ dat = MALLOCZ(osh, size);
4121
+ if (dat == NULL) {
4122
+ ret = BCME_NOMEM;
4123
+ goto done;
4124
+ }
4125
+ vld->vlen = size;
4126
+ vld->vdata = dat;
4127
+ ret = BCME_OK;
4128
+done:
4129
+ return ret;
4130
+}
4131
+
4132
+/** free memory associated with variable sized data. note: vld should NOT be null.
4133
+ */
4134
+int
4135
+bcm_vdata_free(osl_t *osh, var_len_data_t *vld)
4136
+{
4137
+ int ret = BCME_ERROR;
4138
+
4139
+ if (vld == NULL) {
4140
+ ASSERT(0);
4141
+ goto done;
4142
+ }
4143
+
4144
+ if (vld->vdata) {
4145
+ MFREE(osh, vld->vdata, vld->vlen);
4146
+ vld->vdata = NULL;
4147
+ vld->vlen = 0;
4148
+ ret = BCME_OK;
4149
+ }
4150
+done:
4151
+ return ret;
4152
+}
4153
+
4154
+#endif /* BCMDRIVER */
4155
+
4156
+/* Count the number of elements not matching a given value in a null terminated array */
4157
+int
4158
+array_value_mismatch_count(uint8 value, uint8 *array, int array_size)
4159
+{
4160
+ int i;
4161
+ int count = 0;
4162
+
4163
+ for (i = 0; i < array_size; i++) {
4164
+ /* exit if a null terminator is found */
4165
+ if (array[i] == 0) {
4166
+ break;
4167
+ }
4168
+ if (array[i] != value) {
4169
+ count++;
4170
+ }
4171
+ }
4172
+ return count;
4173
+}
4174
+
4175
+/* Count the number of non-zero elements in an uint8 array */
4176
+int
4177
+array_nonzero_count(uint8 *array, int array_size)
4178
+{
4179
+ return array_value_mismatch_count(0, array, array_size);
4180
+}
4181
+
4182
+/* Count the number of non-zero elements in an int16 array */
4183
+int
4184
+array_nonzero_count_int16(int16 *array, int array_size)
4185
+{
4186
+ int i;
4187
+ int count = 0;
4188
+
4189
+ for (i = 0; i < array_size; i++) {
4190
+ if (array[i] != 0) {
4191
+ count++;
4192
+ }
4193
+ }
4194
+ return count;
4195
+}
4196
+
4197
+/* Count the number of zero elements in an uint8 array */
4198
+int
4199
+array_zero_count(uint8 *array, int array_size)
4200
+{
4201
+ int i;
4202
+ int count = 0;
4203
+
4204
+ for (i = 0; i < array_size; i++) {
4205
+ if (array[i] == 0) {
4206
+ count++;
4207
+ }
4208
+ }
4209
+ return count;
4210
+}
4211
+
4212
+/* Validate an array that can be 1 of 2 data types.
4213
+ * One of array1 or array2 should be non-NULL. The other should be NULL.
4214
+ */
4215
+static int
4216
+verify_ordered_array(uint8 *array1, int16 *array2, int array_size,
4217
+ int range_lo, int range_hi, bool err_if_no_zero_term, bool is_ordered)
4218
+{
4219
+ int ret;
4220
+ int i;
4221
+ int val = 0;
4222
+ int prev_val = 0;
4223
+
4224
+ ret = err_if_no_zero_term ? BCME_NOTFOUND : BCME_OK;
4225
+
4226
+ /* Check that:
4227
+ * - values are in strict descending order.
4228
+ * - values are within the valid range.
4229
+ */
4230
+ for (i = 0; i < array_size; i++) {
4231
+ if (array1) {
4232
+ val = (int)array1[i];
4233
+ } else if (array2) {
4234
+ val = (int)array2[i];
4235
+ } else {
4236
+ /* both array parameters are NULL */
4237
+ return BCME_NOTFOUND;
4238
+ }
4239
+ if (val == 0) {
4240
+ /* array is zero-terminated */
4241
+ ret = BCME_OK;
4242
+ break;
4243
+ }
4244
+
4245
+ if (is_ordered && i > 0 && val >= prev_val) {
4246
+ /* array is not in descending order */
4247
+ ret = BCME_BADOPTION;
4248
+ break;
4249
+ }
4250
+ prev_val = val;
4251
+
4252
+ if (val < range_lo || val > range_hi) {
4253
+ /* array value out of range */
4254
+ ret = BCME_RANGE;
4255
+ break;
4256
+ }
4257
+ }
4258
+
4259
+ return ret;
4260
+}
4261
+
4262
+/* Validate an ordered uint8 configuration array */
4263
+int
4264
+verify_ordered_array_uint8(uint8 *array, int array_size,
4265
+ uint8 range_lo, uint8 range_hi)
4266
+{
4267
+ return verify_ordered_array(array, NULL, array_size, (int)range_lo, (int)range_hi,
4268
+ TRUE, TRUE);
4269
+}
4270
+
4271
+/* Validate an ordered int16 non-zero-terminated configuration array */
4272
+int
4273
+verify_ordered_array_int16(int16 *array, int array_size,
4274
+ int16 range_lo, int16 range_hi)
4275
+{
4276
+ return verify_ordered_array(NULL, array, array_size, (int)range_lo, (int)range_hi,
4277
+ FALSE, TRUE);
4278
+}
4279
+
4280
+/* Validate all values in an array are in range */
4281
+int
4282
+verify_array_values(uint8 *array, int array_size,
4283
+ int range_lo, int range_hi, bool zero_terminated)
4284
+{
4285
+ int ret = BCME_OK;
4286
+ int i;
4287
+ int val = 0;
4288
+
4289
+ /* Check that:
4290
+ * - values are in strict descending order.
4291
+ * - values are within the valid range.
4292
+ */
4293
+ for (i = 0; i < array_size; i++) {
4294
+ val = (int)array[i];
4295
+ if (val == 0 && zero_terminated) {
4296
+ ret = BCME_OK;
4297
+ break;
4298
+ }
4299
+ if (val < range_lo || val > range_hi) {
4300
+ /* array value out of range */
4301
+ ret = BCME_RANGE;
4302
+ break;
4303
+ }
4304
+ }
4305
+ return ret;
4306
+}
4307
+
4308
+/* Adds/replaces NVRAM variable with given value
4309
+ * varbuf[in,out] - Buffer with NVRAM variables (sequence of zero-terminated 'name=value' records,
4310
+ * terminated with additional zero)
4311
+ * buflen[in] - Length of buffer (may, even should, have some unused space)
4312
+ * variable[in] - Variable to add/replace in 'name=value' form
4313
+ * datalen[out,opt] - Optional output parameter - resulting length of data in buffer
4314
+ * Returns TRUE on success, FALSE if buffer too short or variable specified incorrectly
4315
+ */
4316
+bool
4317
+replace_nvram_variable(char *varbuf, unsigned int buflen, const char *variable,
4318
+ unsigned int *datalen)
4319
+{
4320
+ char *p;
4321
+ int variable_heading_len, record_len, variable_record_len = (int)strlen(variable) + 1;
4322
+ char *buf_end = varbuf + buflen;
4323
+ p = strchr(variable, '=');
4324
+ if (!p) {
4325
+ return FALSE;
4326
+ }
4327
+ /* Length of given variable name, followed by '=' */
4328
+ variable_heading_len = (int)((const char *)(p + 1) - variable);
4329
+ /* Scanning NVRAM, record by record up to trailing 0 */
4330
+ for (p = varbuf; *p; p += strlen(p) + 1) {
4331
+ /* If given variable found - remove it */
4332
+ if (!strncmp(p, variable, (size_t)variable_heading_len)) {
4333
+ record_len = (int)strlen(p) + 1;
4334
+ memmove_s(p, buf_end - p, p + record_len,
4335
+ (size_t)(buf_end - (p + record_len)));
4336
+ }
4337
+ }
4338
+ /* If buffer does not have space for given variable - return FALSE */
4339
+ if ((p + variable_record_len + 1) > buf_end) {
4340
+ return FALSE;
4341
+ }
4342
+ /* Copy given variable to end of buffer */
4343
+ memmove_s(p, buf_end - p, variable, (size_t)variable_record_len);
4344
+ /* Adding trailing 0 */
4345
+ p[variable_record_len] = 0;
4346
+ /* Setting optional output parameter - length of data in buffer */
4347
+ if (datalen) {
4348
+ *datalen = (unsigned int)(p + variable_record_len + 1 - varbuf);
4349
+ }
4350
+ return TRUE;
36784351 }