.. | .. |
---|
1 | | -/* SPDX-License-Identifier: GPL-2.0 */ |
---|
2 | 1 | /* |
---|
3 | 2 | * Driver O/S-independent utility routines |
---|
4 | 3 | * |
---|
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 | + * |
---|
7 | 8 | * Unless you and Broadcom execute a separate written software license |
---|
8 | 9 | * agreement governing use of this software, this software is licensed to you |
---|
9 | 10 | * under the terms of the GNU General Public License version 2 (the "GPL"), |
---|
10 | 11 | * available at http://www.broadcom.com/licenses/GPLv2.php, with the |
---|
11 | 12 | * following added to such license: |
---|
12 | | - * |
---|
| 13 | + * |
---|
13 | 14 | * As a special exception, the copyright holders of this software give you |
---|
14 | 15 | * permission to link this software with independent modules, and to copy and |
---|
15 | 16 | * distribute the resulting executable under terms of your choice, provided that |
---|
.. | .. |
---|
17 | 18 | * the license of that module. An independent module is a module which is not |
---|
18 | 19 | * derived from this software. The special exception does not apply to any |
---|
19 | 20 | * modifications of the software. |
---|
20 | | - * |
---|
| 21 | + * |
---|
21 | 22 | * Notwithstanding the above, under no circumstances may you combine this |
---|
22 | 23 | * software in any way with any other Broadcom software provided under a license |
---|
23 | 24 | * other than the GPL, without Broadcom's express prior written consent. |
---|
.. | .. |
---|
25 | 26 | * |
---|
26 | 27 | * <<Broadcom-WL-IPTag/Open:>> |
---|
27 | 28 | * |
---|
28 | | - * $Id: bcmutils.c 692666 2018-07-30 08:58:07Z $ |
---|
| 29 | + * $Id: bcmutils.c 702105 2017-05-30 19:10:39Z $ |
---|
29 | 30 | */ |
---|
30 | 31 | |
---|
31 | 32 | #include <bcm_cfg.h> |
---|
.. | .. |
---|
33 | 34 | #include <bcmdefs.h> |
---|
34 | 35 | #include <stdarg.h> |
---|
35 | 36 | #ifdef BCMDRIVER |
---|
36 | | - |
---|
37 | 37 | #include <osl.h> |
---|
38 | 38 | #include <bcmutils.h> |
---|
39 | 39 | |
---|
.. | .. |
---|
41 | 41 | |
---|
42 | 42 | #include <stdio.h> |
---|
43 | 43 | #include <string.h> |
---|
| 44 | +#include <bcm_math.h> |
---|
44 | 45 | #include <bcmutils.h> |
---|
45 | 46 | |
---|
46 | 47 | #if defined(BCMEXTSUP) |
---|
47 | 48 | #include <bcm_osl.h> |
---|
48 | | -#endif |
---|
| 49 | +#endif // endif |
---|
49 | 50 | |
---|
50 | 51 | #ifndef ASSERT |
---|
51 | 52 | #define ASSERT(exp) |
---|
52 | | -#endif |
---|
| 53 | +#endif // endif |
---|
53 | 54 | |
---|
54 | 55 | #endif /* !BCMDRIVER */ |
---|
55 | 56 | |
---|
| 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> |
---|
56 | 65 | #include <bcmendian.h> |
---|
57 | 66 | #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> |
---|
69 | 75 | |
---|
70 | 76 | #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 | | - |
---|
137 | 77 | |
---|
138 | 78 | /* return total length of buffer chain */ |
---|
139 | 79 | uint BCMFASTPATH |
---|
.. | .. |
---|
145 | 85 | total = 0; |
---|
146 | 86 | for (; p; p = PKTNEXT(osh, p)) { |
---|
147 | 87 | len = PKTLEN(osh, p); |
---|
148 | | - total += len; |
---|
| 88 | + total += (uint)len; |
---|
149 | 89 | #ifdef BCMLFRAG |
---|
150 | 90 | if (BCMLFRAG_ENAB()) { |
---|
151 | 91 | if (PKTISFRAG(osh, p)) { |
---|
152 | 92 | total += PKTFRAGTOTLEN(osh, p); |
---|
153 | 93 | } |
---|
154 | 94 | } |
---|
155 | | -#endif |
---|
| 95 | +#endif // endif |
---|
156 | 96 | } |
---|
157 | 97 | |
---|
158 | 98 | return (total); |
---|
.. | .. |
---|
182 | 122 | cnt += PKTFRAGTOTNUM(osh, p); |
---|
183 | 123 | } |
---|
184 | 124 | } |
---|
185 | | -#endif |
---|
| 125 | +#endif // endif |
---|
186 | 126 | } |
---|
187 | 127 | |
---|
188 | 128 | return cnt; |
---|
189 | 129 | } |
---|
190 | 130 | |
---|
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) |
---|
195 | 134 | { |
---|
196 | | - uint cnt; |
---|
197 | | - uint8 *pktdata; |
---|
198 | | - uint len, remain, align64; |
---|
| 135 | + uint n, ret = 0; |
---|
199 | 136 | |
---|
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" */ |
---|
208 | 139 | |
---|
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); |
---|
217 | 145 | } |
---|
218 | 146 | |
---|
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; |
---|
220 | 190 | } |
---|
221 | 191 | |
---|
222 | 192 | uint8 * BCMFASTPATH |
---|
.. | .. |
---|
232 | 202 | for (; p; p = PKTNEXT(osh, p)) { |
---|
233 | 203 | pdata = (uint8 *) PKTDATA(osh, p); |
---|
234 | 204 | pkt_off = offset - len; |
---|
235 | | - len += PKTLEN(osh, p); |
---|
| 205 | + len += (uint)PKTLEN(osh, p); |
---|
236 | 206 | if (len > offset) |
---|
237 | 207 | break; |
---|
238 | 208 | } |
---|
239 | 209 | return (uint8*) (pdata+pkt_off); |
---|
240 | 210 | } |
---|
241 | | - |
---|
242 | 211 | |
---|
243 | 212 | /* given a offset in pdata, find the pkt seg hdr */ |
---|
244 | 213 | void * |
---|
.. | .. |
---|
251 | 220 | return NULL; |
---|
252 | 221 | |
---|
253 | 222 | for (; p; p = PKTNEXT(osh, p)) { |
---|
254 | | - len += PKTLEN(osh, p); |
---|
| 223 | + len += (uint)PKTLEN(osh, p); |
---|
255 | 224 | if (len > offset) |
---|
256 | 225 | break; |
---|
257 | 226 | } |
---|
258 | 227 | return p; |
---|
259 | 228 | } |
---|
260 | 229 | |
---|
| 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 | + |
---|
261 | 1422 | #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 | +} |
---|
262 | 1696 | |
---|
263 | 1697 | #if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS) |
---|
264 | 1698 | const unsigned char bcm_ctype[] = { |
---|
.. | .. |
---|
298 | 1732 | _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */ |
---|
299 | 1733 | }; |
---|
300 | 1734 | |
---|
301 | | -ulong |
---|
302 | | -bcm_strtoul(const char *cp, char **endp, uint base) |
---|
| 1735 | +uint64 |
---|
| 1736 | +bcm_strtoull(const char *cp, char **endp, uint base) |
---|
303 | 1737 | { |
---|
304 | | - ulong result, last_result = 0, value; |
---|
| 1738 | + uint64 result, last_result = 0, value; |
---|
305 | 1739 | bool minus; |
---|
306 | 1740 | |
---|
307 | 1741 | minus = FALSE; |
---|
.. | .. |
---|
334 | 1768 | result = 0; |
---|
335 | 1769 | |
---|
336 | 1770 | 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) { |
---|
338 | 1772 | result = result*base + value; |
---|
339 | 1773 | /* 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 | + } |
---|
341 | 1782 | return (ulong)-1; |
---|
| 1783 | + } |
---|
342 | 1784 | last_result = result; |
---|
343 | 1785 | cp++; |
---|
344 | 1786 | } |
---|
.. | .. |
---|
350 | 1792 | *endp = DISCARD_QUAL(cp, char); |
---|
351 | 1793 | |
---|
352 | 1794 | 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); |
---|
353 | 1801 | } |
---|
354 | 1802 | |
---|
355 | 1803 | int |
---|
.. | .. |
---|
372 | 1820 | len = (int)strlen(haystack) - nlen + 1; |
---|
373 | 1821 | |
---|
374 | 1822 | for (i = 0; i < len; i++) |
---|
375 | | - if (memcmp(needle, &haystack[i], nlen) == 0) |
---|
| 1823 | + if (memcmp(needle, &haystack[i], (size_t)nlen) == 0) |
---|
376 | 1824 | return DISCARD_QUAL(&haystack[i], char); |
---|
377 | 1825 | return (NULL); |
---|
378 | 1826 | } |
---|
.. | .. |
---|
414 | 1862 | |
---|
415 | 1863 | return (dest); |
---|
416 | 1864 | } |
---|
417 | | - |
---|
418 | 1865 | |
---|
419 | 1866 | /**************************************************************************** |
---|
420 | 1867 | * Function: bcmstrtok |
---|
.. | .. |
---|
477 | 1924 | for (; *str; str++) { |
---|
478 | 1925 | if (map[*str >> 5] & (1 << (*str & 31))) { |
---|
479 | 1926 | if (tokdelim != NULL) { |
---|
480 | | - *tokdelim = *str; |
---|
| 1927 | + *tokdelim = (char)*str; |
---|
481 | 1928 | } |
---|
482 | 1929 | |
---|
483 | 1930 | *str++ = '\0'; |
---|
.. | .. |
---|
496 | 1943 | } |
---|
497 | 1944 | } |
---|
498 | 1945 | |
---|
499 | | - |
---|
500 | 1946 | #define xToLower(C) \ |
---|
501 | 1947 | ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C) |
---|
502 | | - |
---|
503 | 1948 | |
---|
504 | 1949 | /**************************************************************************** |
---|
505 | 1950 | * Function: bcmstricmp |
---|
.. | .. |
---|
531 | 1976 | if (!*s1 && *s2) return -1; |
---|
532 | 1977 | return 0; |
---|
533 | 1978 | } |
---|
534 | | - |
---|
535 | 1979 | |
---|
536 | 1980 | /**************************************************************************** |
---|
537 | 1981 | * Function: bcmstrnicmp |
---|
.. | .. |
---|
576 | 2020 | char *ep; |
---|
577 | 2021 | |
---|
578 | 2022 | for (;;) { |
---|
579 | | - ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16); |
---|
| 2023 | + ea->octet[i++] = (uint8) bcm_strtoul(p, &ep, 16); |
---|
580 | 2024 | p = ep; |
---|
581 | 2025 | if (!*p++ || i == 6) |
---|
582 | 2026 | break; |
---|
.. | .. |
---|
600 | 2044 | return (i == IPV4_ADDR_LEN); |
---|
601 | 2045 | } |
---|
602 | 2046 | #endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */ |
---|
603 | | - |
---|
604 | 2047 | |
---|
605 | 2048 | #if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) |
---|
606 | 2049 | /* registry routine buffer preparation utility functions: |
---|
.. | .. |
---|
630 | 2073 | return copyct; |
---|
631 | 2074 | } |
---|
632 | 2075 | #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 */ |
---|
1087 | 2076 | |
---|
1088 | 2077 | #ifdef BCM_OBJECT_TRACE |
---|
1089 | 2078 | |
---|
.. | .. |
---|
1522 | 2511 | ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) && |
---|
1523 | 2512 | ((data != NULL) || (datalen == 0))) { |
---|
1524 | 2513 | |
---|
1525 | | - /* write type, len fields */ |
---|
| 2514 | + /* write type, len fields */ |
---|
1526 | 2515 | dst_tlv->id = (uint8)type; |
---|
1527 | | - dst_tlv->len = (uint8)datalen; |
---|
| 2516 | + dst_tlv->len = (uint8)datalen; |
---|
1528 | 2517 | |
---|
1529 | 2518 | /* if data is present, copy to the output buffer and update |
---|
1530 | 2519 | * pointer to output buffer |
---|
1531 | 2520 | */ |
---|
1532 | 2521 | if (datalen > 0) { |
---|
1533 | 2522 | |
---|
1534 | | - memcpy(dst_tlv->data, data, datalen); |
---|
| 2523 | + memcpy(dst_tlv->data, data, (size_t)datalen); |
---|
1535 | 2524 | } |
---|
1536 | 2525 | |
---|
1537 | 2526 | /* update the output destination poitner to point past |
---|
1538 | 2527 | * the TLV written |
---|
1539 | 2528 | */ |
---|
1540 | 2529 | 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; |
---|
1541 | 2578 | } |
---|
1542 | 2579 | |
---|
1543 | 2580 | return (new_dst); |
---|
.. | .. |
---|
1553 | 2590 | /* if len + tlv hdr len is more than destlen, don't do anything |
---|
1554 | 2591 | * just return the buffer untouched |
---|
1555 | 2592 | */ |
---|
1556 | | - if ((int)(datalen + BCM_TLV_HDR_SIZE) <= dst_maxlen) { |
---|
| 2593 | + if ((int)(datalen + (int)BCM_TLV_HDR_SIZE) <= dst_maxlen) { |
---|
1557 | 2594 | |
---|
1558 | 2595 | new_dst = bcm_write_tlv(type, data, datalen, dst); |
---|
1559 | 2596 | } |
---|
.. | .. |
---|
1580 | 2617 | return (new_dst); |
---|
1581 | 2618 | } |
---|
1582 | 2619 | |
---|
1583 | | - |
---|
1584 | 2620 | uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen) |
---|
1585 | 2621 | { |
---|
1586 | 2622 | uint8 *new_dst = dst; |
---|
.. | .. |
---|
1595 | 2631 | |
---|
1596 | 2632 | return (new_dst); |
---|
1597 | 2633 | } |
---|
1598 | | - |
---|
1599 | 2634 | |
---|
1600 | 2635 | #if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS) |
---|
1601 | 2636 | /******************************************************************************* |
---|
.. | .. |
---|
1660 | 2695 | |
---|
1661 | 2696 | uint8 |
---|
1662 | 2697 | hndcrc8( |
---|
1663 | | - uint8 *pdata, /* pointer to array of data to process */ |
---|
| 2698 | + const uint8 *pdata, /* pointer to array of data to process */ |
---|
1664 | 2699 | uint nbytes, /* number of input data bytes to process */ |
---|
1665 | 2700 | uint8 crc /* either CRC8_INIT_VALUE or previous return value */ |
---|
1666 | 2701 | ) |
---|
.. | .. |
---|
1733 | 2768 | |
---|
1734 | 2769 | uint16 |
---|
1735 | 2770 | hndcrc16( |
---|
1736 | | - uint8 *pdata, /* pointer to array of data to process */ |
---|
| 2771 | + const uint8 *pdata, /* pointer to array of data to process */ |
---|
1737 | 2772 | uint nbytes, /* number of input data bytes to process */ |
---|
1738 | 2773 | uint16 crc /* either CRC16_INIT_VALUE or previous return value */ |
---|
1739 | 2774 | ) |
---|
.. | .. |
---|
1815 | 2850 | * accumulating over multiple pieces. |
---|
1816 | 2851 | */ |
---|
1817 | 2852 | uint32 |
---|
1818 | | -hndcrc32(uint8 *pdata, uint nbytes, uint32 crc) |
---|
| 2853 | +hndcrc32(const uint8 *pdata, uint nbytes, uint32 crc) |
---|
1819 | 2854 | { |
---|
1820 | | - uint8 *pend; |
---|
| 2855 | + const uint8 *pend; |
---|
1821 | 2856 | pend = pdata + nbytes; |
---|
1822 | 2857 | while (pdata < pend) |
---|
1823 | 2858 | CRC_INNER_LOOP(32, crc, *pdata++); |
---|
.. | .. |
---|
1826 | 2861 | } |
---|
1827 | 2862 | |
---|
1828 | 2863 | #ifdef notdef |
---|
1829 | | -#define CLEN 1499 /* CRC Length */ |
---|
1830 | | -#define CBUFSIZ (CLEN+4) |
---|
| 2864 | +#define CLEN 1499 /* CRC Length */ |
---|
| 2865 | +#define CBUFSIZ (CLEN+4) |
---|
1831 | 2866 | #define CNBUFS 5 /* # of bufs */ |
---|
1832 | 2867 | |
---|
1833 | 2868 | void |
---|
.. | .. |
---|
1870 | 2905 | * by the TLV parameter's length if it is valid. |
---|
1871 | 2906 | */ |
---|
1872 | 2907 | bcm_tlv_t * |
---|
1873 | | -bcm_next_tlv(bcm_tlv_t *elt, int *buflen) |
---|
| 2908 | +bcm_next_tlv(const bcm_tlv_t *elt, uint *buflen) |
---|
1874 | 2909 | { |
---|
1875 | | - int len; |
---|
| 2910 | + uint len; |
---|
1876 | 2911 | |
---|
1877 | 2912 | /* validate current elt */ |
---|
1878 | 2913 | if (!bcm_valid_tlv(elt, *buflen)) { |
---|
.. | .. |
---|
1881 | 2916 | |
---|
1882 | 2917 | /* advance to next elt */ |
---|
1883 | 2918 | len = elt->len; |
---|
1884 | | - elt = (bcm_tlv_t*)(elt->data + len); |
---|
| 2919 | + elt = (const bcm_tlv_t*)(elt->data + len); |
---|
1885 | 2920 | *buflen -= (TLV_HDR_LEN + len); |
---|
1886 | 2921 | |
---|
1887 | 2922 | /* validate next elt */ |
---|
.. | .. |
---|
1889 | 2924 | return NULL; |
---|
1890 | 2925 | } |
---|
1891 | 2926 | |
---|
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; |
---|
1893 | 3033 | } |
---|
1894 | 3034 | |
---|
1895 | 3035 | /* |
---|
.. | .. |
---|
1898 | 3038 | * matches tag |
---|
1899 | 3039 | */ |
---|
1900 | 3040 | 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) |
---|
1902 | 3071 | { |
---|
1903 | 3072 | bcm_tlv_t *elt; |
---|
1904 | 3073 | int totlen; |
---|
1905 | 3074 | |
---|
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 | + |
---|
1909 | 3083 | totlen = buflen; |
---|
1910 | 3084 | |
---|
1911 | 3085 | /* find tagged parameter */ |
---|
1912 | 3086 | while (totlen >= TLV_HDR_LEN) { |
---|
1913 | 3087 | int len = elt->len; |
---|
1914 | 3088 | |
---|
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; |
---|
1917 | 3093 | |
---|
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); |
---|
1920 | 3103 | |
---|
1921 | 3104 | elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); |
---|
1922 | 3105 | totlen -= (len + TLV_HDR_LEN); |
---|
.. | .. |
---|
1932 | 3115 | * return NULL if not found or length field < min_varlen |
---|
1933 | 3116 | */ |
---|
1934 | 3117 | 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) |
---|
1936 | 3119 | { |
---|
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); |
---|
1938 | 3122 | if (ret == NULL || ret->len < min_bodylen) { |
---|
1939 | 3123 | return NULL; |
---|
1940 | 3124 | } |
---|
.. | .. |
---|
1947 | 3131 | * matches tag. Stop parsing when we see an element whose ID is greater |
---|
1948 | 3132 | * than the target key. |
---|
1949 | 3133 | */ |
---|
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) |
---|
1952 | 3136 | { |
---|
1953 | | - bcm_tlv_t *elt; |
---|
| 3137 | + const bcm_tlv_t *elt; |
---|
1954 | 3138 | int totlen; |
---|
1955 | 3139 | |
---|
1956 | | - elt = (bcm_tlv_t*)buf; |
---|
| 3140 | + elt = (const bcm_tlv_t*)buf; |
---|
1957 | 3141 | totlen = buflen; |
---|
1958 | 3142 | |
---|
1959 | 3143 | /* find tagged parameter */ |
---|
.. | .. |
---|
1971 | 3155 | return (elt); |
---|
1972 | 3156 | } |
---|
1973 | 3157 | |
---|
1974 | | - elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); |
---|
| 3158 | + elt = (const bcm_tlv_t*)((const uint8*)elt + (len + TLV_HDR_LEN)); |
---|
1975 | 3159 | totlen -= (len + TLV_HDR_LEN); |
---|
1976 | 3160 | } |
---|
1977 | 3161 | return NULL; |
---|
.. | .. |
---|
1996 | 3180 | bit = bd->bitfield[i].bit; |
---|
1997 | 3181 | if ((flags & mask) == bit) { |
---|
1998 | 3182 | 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); |
---|
2001 | 3185 | } |
---|
2002 | 3186 | break; |
---|
2003 | 3187 | } |
---|
.. | .. |
---|
2031 | 3215 | } else if ((flags & bit) == 0) |
---|
2032 | 3216 | continue; |
---|
2033 | 3217 | flags &= ~bit; |
---|
2034 | | - nlen = strlen(name); |
---|
| 3218 | + nlen = (int)strlen(name); |
---|
2035 | 3219 | slen += nlen; |
---|
2036 | 3220 | /* count btwn flag space */ |
---|
2037 | 3221 | if (flags != 0) |
---|
.. | .. |
---|
2040 | 3224 | if (len <= slen) |
---|
2041 | 3225 | break; |
---|
2042 | 3226 | /* copy NULL char but don't count it */ |
---|
2043 | | - strncpy(p, name, nlen + 1); |
---|
| 3227 | + strncpy(p, name, (size_t)nlen + 1); |
---|
2044 | 3228 | p += nlen; |
---|
2045 | 3229 | /* copy btwn flag space and NULL char */ |
---|
2046 | 3230 | if (flags != 0) |
---|
.. | .. |
---|
2054 | 3238 | |
---|
2055 | 3239 | return (int)(p - buf); |
---|
2056 | 3240 | } |
---|
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 |
---|
2058 | 3293 | |
---|
2059 | 3294 | /* print bytes formatted as hex to a string. return the resulting string length */ |
---|
2060 | 3295 | int |
---|
.. | .. |
---|
2073 | 3308 | |
---|
2074 | 3309 | /* pretty hex print a contiguous buffer */ |
---|
2075 | 3310 | void |
---|
2076 | | -prhex(const char *msg, uchar *buf, uint nbytes) |
---|
| 3311 | +prhex(const char *msg, const uchar *buf, uint nbytes) |
---|
2077 | 3312 | { |
---|
2078 | 3313 | char line[128], *p; |
---|
2079 | 3314 | int len = sizeof(line); |
---|
.. | .. |
---|
2086 | 3321 | p = line; |
---|
2087 | 3322 | for (i = 0; i < nbytes; i++) { |
---|
2088 | 3323 | if (i % 16 == 0) { |
---|
2089 | | - nchar = snprintf(p, len, " %04x: ", i); /* line prefix */ |
---|
| 3324 | + nchar = snprintf(p, (size_t)len, " %04x: ", i); /* line prefix */ |
---|
2090 | 3325 | p += nchar; |
---|
2091 | 3326 | len -= nchar; |
---|
2092 | 3327 | } |
---|
2093 | 3328 | if (len > 0) { |
---|
2094 | | - nchar = snprintf(p, len, "%02x ", buf[i]); |
---|
| 3329 | + nchar = snprintf(p, (size_t)len, "%02x ", buf[i]); |
---|
2095 | 3330 | p += nchar; |
---|
2096 | 3331 | len -= nchar; |
---|
2097 | 3332 | } |
---|
.. | .. |
---|
2116 | 3351 | "AES_CCM", |
---|
2117 | 3352 | "AES_OCB_MSDU", |
---|
2118 | 3353 | "AES_OCB_MPDU", |
---|
| 3354 | +#ifdef BCMCCX |
---|
| 3355 | + "CKIP", |
---|
| 3356 | + "CKIP_MMH", |
---|
| 3357 | + "WEP_MMH", |
---|
| 3358 | + "NALG", |
---|
| 3359 | +#else |
---|
2119 | 3360 | "NALG", |
---|
2120 | 3361 | "UNDEF", |
---|
2121 | 3362 | "UNDEF", |
---|
2122 | 3363 | "UNDEF", |
---|
| 3364 | +#endif /* BCMCCX */ |
---|
| 3365 | +#ifdef BCMWAPI_WAI |
---|
2123 | 3366 | "WAPI", |
---|
| 3367 | +#else |
---|
| 3368 | + "UNDEF", |
---|
| 3369 | +#endif // endif |
---|
2124 | 3370 | "PMK", |
---|
2125 | 3371 | "BIP", |
---|
2126 | 3372 | "AES_GCM", |
---|
.. | .. |
---|
2138 | 3384 | return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR"; |
---|
2139 | 3385 | } |
---|
2140 | 3386 | |
---|
2141 | | - |
---|
2142 | 3387 | char * |
---|
2143 | 3388 | bcm_chipname(uint chipid, char *buf, uint len) |
---|
2144 | 3389 | { |
---|
2145 | 3390 | const char *fmt; |
---|
2146 | 3391 | |
---|
2147 | 3392 | 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() |
---|
2148 | 3403 | snprintf(buf, len, fmt, chipid); |
---|
| 3404 | + CLANG_DIAGNOSTIC_POP() |
---|
2149 | 3405 | return buf; |
---|
2150 | 3406 | } |
---|
2151 | 3407 | |
---|
.. | .. |
---|
2203 | 3459 | while (bufsize > 1) { |
---|
2204 | 3460 | if (cur_ptr->nameandfmt == NULL) |
---|
2205 | 3461 | 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() |
---|
2206 | 3473 | 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() |
---|
2208 | 3476 | /* check for snprintf overflow or error */ |
---|
2209 | 3477 | if (len < 0 || (uint32)len >= bufsize) |
---|
2210 | | - len = bufsize - 1; |
---|
| 3478 | + len = (int)(bufsize - 1); |
---|
2211 | 3479 | buf += len; |
---|
2212 | | - bufsize -= len; |
---|
2213 | | - filled_len += len; |
---|
| 3480 | + bufsize -= (uint32)len; |
---|
| 3481 | + filled_len += (uint32)len; |
---|
2214 | 3482 | cur_ptr++; |
---|
2215 | 3483 | } |
---|
2216 | 3484 | return filled_len; |
---|
2217 | 3485 | } |
---|
2218 | 3486 | |
---|
2219 | 3487 | 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) |
---|
2221 | 3489 | { |
---|
2222 | 3490 | uint len; |
---|
2223 | 3491 | |
---|
.. | .. |
---|
2258 | 3526 | #define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ |
---|
2259 | 3527 | |
---|
2260 | 3528 | 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 */ |
---|
2262 | 3530 | /* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, |
---|
2263 | 3531 | /* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, |
---|
2264 | 3532 | /* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, |
---|
.. | .. |
---|
2288 | 3556 | /* return the mW value scaled down to the correct factor of 10, |
---|
2289 | 3557 | * adding in factor/2 to get proper rounding. |
---|
2290 | 3558 | */ |
---|
2291 | | - return ((nqdBm_to_mW_map[idx] + factor/2) / factor); |
---|
| 3559 | + return (uint16)((nqdBm_to_mW_map[idx] + factor/2) / factor); |
---|
2292 | 3560 | } |
---|
2293 | 3561 | |
---|
2294 | 3562 | uint8 |
---|
.. | .. |
---|
2322 | 3590 | return (qdbm); |
---|
2323 | 3591 | } |
---|
2324 | 3592 | |
---|
2325 | | - |
---|
2326 | 3593 | uint |
---|
2327 | 3594 | bcm_bitcount(uint8 *bitmap, uint length) |
---|
2328 | 3595 | { |
---|
.. | .. |
---|
2337 | 3604 | } |
---|
2338 | 3605 | return bitcount; |
---|
2339 | 3606 | } |
---|
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 */ |
---|
2509 | 3607 | |
---|
2510 | 3608 | /* |
---|
2511 | 3609 | * ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL. |
---|
.. | .. |
---|
2560 | 3658 | *dp++ = 0; |
---|
2561 | 3659 | |
---|
2562 | 3660 | 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; |
---|
2621 | 3661 | } |
---|
2622 | 3662 | |
---|
2623 | 3663 | #ifndef setbit /* As in the header file */ |
---|
.. | .. |
---|
2686 | 3726 | { |
---|
2687 | 3727 | int i; |
---|
2688 | 3728 | 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 | + |
---|
2690 | 3735 | if ((i % NBBY) == 0) printf(" "); |
---|
2691 | 3736 | } |
---|
2692 | 3737 | printf("\n"); |
---|
.. | .. |
---|
2697 | 3742 | bcm_ip_cksum(uint8 *buf, uint32 len, uint32 sum) |
---|
2698 | 3743 | { |
---|
2699 | 3744 | while (len > 1) { |
---|
2700 | | - sum += (buf[0] << 8) | buf[1]; |
---|
| 3745 | + sum += (uint32)((buf[0] << 8) | buf[1]); |
---|
2701 | 3746 | buf += 2; |
---|
2702 | 3747 | len -= 2; |
---|
2703 | 3748 | } |
---|
2704 | 3749 | |
---|
2705 | 3750 | if (len > 0) { |
---|
2706 | | - sum += (*buf) << 8; |
---|
| 3751 | + sum += (uint32)((*buf) << 8); |
---|
2707 | 3752 | } |
---|
2708 | 3753 | |
---|
2709 | 3754 | while (sum >> 16) { |
---|
.. | .. |
---|
2712 | 3757 | |
---|
2713 | 3758 | return ((uint16)~sum); |
---|
2714 | 3759 | } |
---|
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 */ |
---|
2748 | 3760 | |
---|
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) |
---|
2796 | 3763 | { |
---|
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)); |
---|
3506 | 3765 | } |
---|
3507 | 3766 | |
---|
3508 | 3767 | #ifdef DEBUG_COUNTER |
---|
.. | .. |
---|
3534 | 3793 | #define counter_printlog(a) do {} while (0) |
---|
3535 | 3794 | #endif /* OSL_SYSUPTIME_SUPPORT == TRUE */ |
---|
3536 | 3795 | #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 |
---|
3616 | 3796 | |
---|
3617 | 3797 | /* calculate partial checksum */ |
---|
3618 | 3798 | static uint32 |
---|
.. | .. |
---|
3674 | 3854 | ptr += OFFSETOF(struct ipv4_hdr, hdr_chksum) + 2; |
---|
3675 | 3855 | |
---|
3676 | 3856 | /* 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; |
---|
3678 | 4351 | } |
---|