staging: brcm80211: removed unused stuff from proto/802.11.h
[pohmelfs.git] / drivers / staging / brcm80211 / util / bcmutils.c
blobb78ce5425a2324aa80a083b4406f8f8a6bc632fc
1 /*
2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <linux/ctype.h>
18 #include <linux/kernel.h>
19 #include <linux/string.h>
20 #include <linux/module.h>
21 #include <linux/pci.h>
22 #include <linux/netdevice.h>
23 #include <linux/sched.h>
24 #include <linux/printk.h>
25 #include <bcmdefs.h>
26 #include <stdarg.h>
27 #include <bcmutils.h>
28 #include <bcmnvram.h>
29 #include <bcmdevs.h>
31 MODULE_AUTHOR("Broadcom Corporation");
32 MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN driver utilities.");
33 MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN cards");
34 MODULE_LICENSE("Dual BSD/GPL");
36 struct sk_buff *bcm_pkt_buf_get_skb(uint len)
38 struct sk_buff *skb;
40 skb = dev_alloc_skb(len);
41 if (skb) {
42 skb_put(skb, len);
43 skb->priority = 0;
46 return skb;
48 EXPORT_SYMBOL(bcm_pkt_buf_get_skb);
50 /* Free the driver packet. Free the tag if present */
51 void bcm_pkt_buf_free_skb(struct sk_buff *skb)
53 struct sk_buff *nskb;
54 int nest = 0;
56 /* perversion: we use skb->next to chain multi-skb packets */
57 while (skb) {
58 nskb = skb->next;
59 skb->next = NULL;
61 if (skb->destructor)
62 /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if
63 * destructor exists
65 dev_kfree_skb_any(skb);
66 else
67 /* can free immediately (even in_irq()) if destructor
68 * does not exist
70 dev_kfree_skb(skb);
72 nest++;
73 skb = nskb;
76 EXPORT_SYMBOL(bcm_pkt_buf_free_skb);
79 /* copy a buffer into a pkt buffer chain */
80 uint bcm_pktfrombuf(struct sk_buff *p, uint offset, int len,
81 unsigned char *buf)
83 uint n, ret = 0;
85 /* skip 'offset' bytes */
86 for (; p && offset; p = p->next) {
87 if (offset < (uint) (p->len))
88 break;
89 offset -= p->len;
92 if (!p)
93 return 0;
95 /* copy the data */
96 for (; p && len; p = p->next) {
97 n = min((uint) (p->len) - offset, (uint) len);
98 memcpy(p->data + offset, buf, n);
99 buf += n;
100 len -= n;
101 ret += n;
102 offset = 0;
105 return ret;
107 EXPORT_SYMBOL(bcm_pktfrombuf);
109 /* return total length of buffer chain */
110 uint bcm_pkttotlen(struct sk_buff *p)
112 uint total;
114 total = 0;
115 for (; p; p = p->next)
116 total += p->len;
117 return total;
119 EXPORT_SYMBOL(bcm_pkttotlen);
122 * osl multiple-precedence packet queue
123 * hi_prec is always >= the number of the highest non-empty precedence
125 struct sk_buff *bcm_pktq_penq(struct pktq *pq, int prec,
126 struct sk_buff *p)
128 struct pktq_prec *q;
130 if (pktq_full(pq) || pktq_pfull(pq, prec))
131 return NULL;
133 q = &pq->q[prec];
135 if (q->head)
136 q->tail->prev = p;
137 else
138 q->head = p;
140 q->tail = p;
141 q->len++;
143 pq->len++;
145 if (pq->hi_prec < prec)
146 pq->hi_prec = (u8) prec;
148 return p;
150 EXPORT_SYMBOL(bcm_pktq_penq);
152 struct sk_buff *bcm_pktq_penq_head(struct pktq *pq, int prec,
153 struct sk_buff *p)
155 struct pktq_prec *q;
157 if (pktq_full(pq) || pktq_pfull(pq, prec))
158 return NULL;
160 q = &pq->q[prec];
162 if (q->head == NULL)
163 q->tail = p;
165 p->prev = q->head;
166 q->head = p;
167 q->len++;
169 pq->len++;
171 if (pq->hi_prec < prec)
172 pq->hi_prec = (u8) prec;
174 return p;
176 EXPORT_SYMBOL(bcm_pktq_penq_head);
178 struct sk_buff *bcm_pktq_pdeq(struct pktq *pq, int prec)
180 struct pktq_prec *q;
181 struct sk_buff *p;
183 q = &pq->q[prec];
185 p = q->head;
186 if (p == NULL)
187 return NULL;
189 q->head = p->prev;
190 if (q->head == NULL)
191 q->tail = NULL;
193 q->len--;
195 pq->len--;
197 p->prev = NULL;
199 return p;
201 EXPORT_SYMBOL(bcm_pktq_pdeq);
203 struct sk_buff *bcm_pktq_pdeq_tail(struct pktq *pq, int prec)
205 struct pktq_prec *q;
206 struct sk_buff *p, *prev;
208 q = &pq->q[prec];
210 p = q->head;
211 if (p == NULL)
212 return NULL;
214 for (prev = NULL; p != q->tail; p = p->prev)
215 prev = p;
217 if (prev)
218 prev->prev = NULL;
219 else
220 q->head = NULL;
222 q->tail = prev;
223 q->len--;
225 pq->len--;
227 return p;
229 EXPORT_SYMBOL(bcm_pktq_pdeq_tail);
231 void
232 bcm_pktq_pflush(struct pktq *pq, int prec, bool dir,
233 ifpkt_cb_t fn, void *arg)
235 struct pktq_prec *q;
236 struct sk_buff *p, *prev = NULL;
238 q = &pq->q[prec];
239 p = q->head;
240 while (p) {
241 if (fn == NULL || (*fn) (p, arg)) {
242 bool head = (p == q->head);
243 if (head)
244 q->head = p->prev;
245 else
246 prev->prev = p->prev;
247 p->prev = NULL;
248 bcm_pkt_buf_free_skb(p);
249 q->len--;
250 pq->len--;
251 p = (head ? q->head : prev->prev);
252 } else {
253 prev = p;
254 p = p->prev;
258 if (q->head == NULL) {
259 q->tail = NULL;
262 EXPORT_SYMBOL(bcm_pktq_pflush);
264 void bcm_pktq_flush(struct pktq *pq, bool dir,
265 ifpkt_cb_t fn, void *arg)
267 int prec;
268 for (prec = 0; prec < pq->num_prec; prec++)
269 bcm_pktq_pflush(pq, prec, dir, fn, arg);
271 EXPORT_SYMBOL(bcm_pktq_flush);
273 void bcm_pktq_init(struct pktq *pq, int num_prec, int max_len)
275 int prec;
277 /* pq is variable size; only zero out what's requested */
278 memset(pq, 0,
279 offsetof(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec));
281 pq->num_prec = (u16) num_prec;
283 pq->max = (u16) max_len;
285 for (prec = 0; prec < num_prec; prec++)
286 pq->q[prec].max = pq->max;
288 EXPORT_SYMBOL(bcm_pktq_init);
290 struct sk_buff *bcm_pktq_peek_tail(struct pktq *pq, int *prec_out)
292 int prec;
294 if (pq->len == 0)
295 return NULL;
297 for (prec = 0; prec < pq->hi_prec; prec++)
298 if (pq->q[prec].head)
299 break;
301 if (prec_out)
302 *prec_out = prec;
304 return pq->q[prec].tail;
306 EXPORT_SYMBOL(bcm_pktq_peek_tail);
308 /* Return sum of lengths of a specific set of precedences */
309 int bcm_pktq_mlen(struct pktq *pq, uint prec_bmp)
311 int prec, len;
313 len = 0;
315 for (prec = 0; prec <= pq->hi_prec; prec++)
316 if (prec_bmp & (1 << prec))
317 len += pq->q[prec].len;
319 return len;
321 EXPORT_SYMBOL(bcm_pktq_mlen);
323 /* Priority dequeue from a specific set of precedences */
324 struct sk_buff *bcm_pktq_mdeq(struct pktq *pq, uint prec_bmp,
325 int *prec_out)
327 struct pktq_prec *q;
328 struct sk_buff *p;
329 int prec;
331 if (pq->len == 0)
332 return NULL;
334 while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL)
335 pq->hi_prec--;
337 while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL)
338 if (prec-- == 0)
339 return NULL;
341 q = &pq->q[prec];
343 p = q->head;
344 if (p == NULL)
345 return NULL;
347 q->head = p->prev;
348 if (q->head == NULL)
349 q->tail = NULL;
351 q->len--;
353 if (prec_out)
354 *prec_out = prec;
356 pq->len--;
358 p->prev = NULL;
360 return p;
362 EXPORT_SYMBOL(bcm_pktq_mdeq);
364 /* parse a xx:xx:xx:xx:xx:xx format ethernet address */
365 int bcm_ether_atoe(char *p, u8 *ea)
367 int i = 0;
369 for (;;) {
370 ea[i++] = (char)simple_strtoul(p, &p, 16);
371 if (!*p++ || i == 6)
372 break;
375 return i == 6;
377 EXPORT_SYMBOL(bcm_ether_atoe);
379 #if defined(BCMDBG)
380 /* pretty hex print a pkt buffer chain */
381 void bcm_prpkt(const char *msg, struct sk_buff *p0)
383 struct sk_buff *p;
385 if (msg && (msg[0] != '\0'))
386 printk(KERN_DEBUG "%s:\n", msg);
388 for (p = p0; p; p = p->next)
389 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, p->data, p->len);
391 EXPORT_SYMBOL(bcm_prpkt);
392 #endif /* defined(BCMDBG) */
394 /* iovar table lookup */
395 const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name)
397 const bcm_iovar_t *vi;
398 const char *lookup_name;
400 /* skip any ':' delimited option prefixes */
401 lookup_name = strrchr(name, ':');
402 if (lookup_name != NULL)
403 lookup_name++;
404 else
405 lookup_name = name;
407 for (vi = table; vi->name; vi++) {
408 if (!strcmp(vi->name, lookup_name))
409 return vi;
411 /* ran to end of table */
413 return NULL; /* var name not found */
415 EXPORT_SYMBOL(bcm_iovar_lookup);
417 int bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set)
419 int bcmerror = 0;
421 /* length check on io buf */
422 switch (vi->type) {
423 case IOVT_BOOL:
424 case IOVT_INT8:
425 case IOVT_INT16:
426 case IOVT_INT32:
427 case IOVT_UINT8:
428 case IOVT_UINT16:
429 case IOVT_UINT32:
430 /* all integers are s32 sized args at the ioctl interface */
431 if (len < (int)sizeof(int)) {
432 bcmerror = -EOVERFLOW;
434 break;
436 case IOVT_BUFFER:
437 /* buffer must meet minimum length requirement */
438 if (len < vi->minlen) {
439 bcmerror = -EOVERFLOW;
441 break;
443 case IOVT_VOID:
444 if (!set) {
445 /* Cannot return nil... */
446 bcmerror = -ENOTSUPP;
447 } else if (len) {
448 /* Set is an action w/o parameters */
449 bcmerror = -ENOBUFS;
451 break;
453 default:
454 /* unknown type for length check in iovar info */
455 bcmerror = -ENOTSUPP;
458 return bcmerror;
460 EXPORT_SYMBOL(bcm_iovar_lencheck);
462 /*******************************************************************************
463 * crc8
465 * Computes a crc8 over the input data using the polynomial:
467 * x^8 + x^7 +x^6 + x^4 + x^2 + 1
469 * The caller provides the initial value (either CRC8_INIT_VALUE
470 * or the previous returned value) to allow for processing of
471 * discontiguous blocks of data. When generating the CRC the
472 * caller is responsible for complementing the final return value
473 * and inserting it into the byte stream. When checking, a final
474 * return value of CRC8_GOOD_VALUE indicates a valid CRC.
476 * Reference: Dallas Semiconductor Application Note 27
477 * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms",
478 * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd.,
479 * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt
481 * ****************************************************************************
484 static const u8 crc8_table[256] = {
485 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B,
486 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21,
487 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF,
488 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5,
489 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14,
490 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E,
491 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80,
492 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA,
493 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95,
494 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF,
495 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01,
496 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B,
497 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA,
498 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0,
499 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E,
500 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34,
501 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0,
502 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A,
503 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54,
504 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E,
505 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF,
506 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5,
507 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B,
508 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61,
509 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E,
510 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74,
511 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA,
512 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0,
513 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41,
514 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B,
515 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5,
516 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F
519 u8 bcm_crc8(u8 *pdata, /* pointer to array of data to process */
520 uint nbytes, /* number of input data bytes to process */
521 u8 crc /* either CRC8_INIT_VALUE or previous return value */
523 /* loop over the buffer data */
524 while (nbytes-- > 0)
525 crc = crc8_table[(crc ^ *pdata++) & 0xff];
527 return crc;
529 EXPORT_SYMBOL(bcm_crc8);
532 * Traverse a string of 1-byte tag/1-byte length/variable-length value
533 * triples, returning a pointer to the substring whose first element
534 * matches tag
536 bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key)
538 bcm_tlv_t *elt;
539 int totlen;
541 elt = (bcm_tlv_t *) buf;
542 totlen = buflen;
544 /* find tagged parameter */
545 while (totlen >= 2) {
546 int len = elt->len;
548 /* validate remaining totlen */
549 if ((elt->id == key) && (totlen >= (len + 2)))
550 return elt;
552 elt = (bcm_tlv_t *) ((u8 *) elt + (len + 2));
553 totlen -= (len + 2);
556 return NULL;
558 EXPORT_SYMBOL(bcm_parse_tlvs);
561 #if defined(BCMDBG)
563 bcm_format_flags(const bcm_bit_desc_t *bd, u32 flags, char *buf, int len)
565 int i;
566 char *p = buf;
567 char hexstr[16];
568 int slen = 0, nlen = 0;
569 u32 bit;
570 const char *name;
572 if (len < 2 || !buf)
573 return 0;
575 buf[0] = '\0';
577 for (i = 0; flags != 0; i++) {
578 bit = bd[i].bit;
579 name = bd[i].name;
580 if (bit == 0 && flags != 0) {
581 /* print any unnamed bits */
582 snprintf(hexstr, 16, "0x%X", flags);
583 name = hexstr;
584 flags = 0; /* exit loop */
585 } else if ((flags & bit) == 0)
586 continue;
587 flags &= ~bit;
588 nlen = strlen(name);
589 slen += nlen;
590 /* count btwn flag space */
591 if (flags != 0)
592 slen += 1;
593 /* need NULL char as well */
594 if (len <= slen)
595 break;
596 /* copy NULL char but don't count it */
597 strncpy(p, name, nlen + 1);
598 p += nlen;
599 /* copy btwn flag space and NULL char */
600 if (flags != 0)
601 p += snprintf(p, 2, " ");
602 len -= slen;
605 /* indicate the str was too short */
606 if (flags != 0) {
607 if (len < 2)
608 p -= 2 - len; /* overwrite last char */
609 p += snprintf(p, 2, ">");
612 return (int)(p - buf);
614 EXPORT_SYMBOL(bcm_format_flags);
616 /* print bytes formatted as hex to a string. return the resulting string length */
617 int bcm_format_hex(char *str, const void *bytes, int len)
619 int i;
620 char *p = str;
621 const u8 *src = (const u8 *)bytes;
623 for (i = 0; i < len; i++) {
624 p += snprintf(p, 3, "%02X", *src);
625 src++;
627 return (int)(p - str);
629 EXPORT_SYMBOL(bcm_format_hex);
630 #endif /* defined(BCMDBG) */
632 char *bcm_chipname(uint chipid, char *buf, uint len)
634 const char *fmt;
636 fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x";
637 snprintf(buf, len, fmt, chipid);
638 return buf;
640 EXPORT_SYMBOL(bcm_chipname);
642 uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
644 uint len;
646 len = strlen(name) + 1;
648 if ((len + datalen) > buflen)
649 return 0;
651 strncpy(buf, name, buflen);
653 /* append data onto the end of the name string */
654 memcpy(&buf[len], data, datalen);
655 len += datalen;
657 return len;
659 EXPORT_SYMBOL(bcm_mkiovar);
661 /* Quarter dBm units to mW
662 * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153
663 * Table is offset so the last entry is largest mW value that fits in
664 * a u16.
667 #define QDBM_OFFSET 153 /* Offset for first entry */
668 #define QDBM_TABLE_LEN 40 /* Table size */
670 /* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
671 * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
673 #define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */
675 /* Largest mW value that will round down to the last table entry,
676 * QDBM_OFFSET + QDBM_TABLE_LEN-1.
677 * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) +
678 * mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2.
680 #define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */
682 static const u16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
683 /* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
684 /* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
685 /* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
686 /* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
687 /* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
688 /* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
691 u16 bcm_qdbm_to_mw(u8 qdbm)
693 uint factor = 1;
694 int idx = qdbm - QDBM_OFFSET;
696 if (idx >= QDBM_TABLE_LEN) {
697 /* clamp to max u16 mW value */
698 return 0xFFFF;
701 /* scale the qdBm index up to the range of the table 0-40
702 * where an offset of 40 qdBm equals a factor of 10 mW.
704 while (idx < 0) {
705 idx += 40;
706 factor *= 10;
709 /* return the mW value scaled down to the correct factor of 10,
710 * adding in factor/2 to get proper rounding.
712 return (nqdBm_to_mW_map[idx] + factor / 2) / factor;
714 EXPORT_SYMBOL(bcm_qdbm_to_mw);
716 u8 bcm_mw_to_qdbm(u16 mw)
718 u8 qdbm;
719 int offset;
720 uint mw_uint = mw;
721 uint boundary;
723 /* handle boundary case */
724 if (mw_uint <= 1)
725 return 0;
727 offset = QDBM_OFFSET;
729 /* move mw into the range of the table */
730 while (mw_uint < QDBM_TABLE_LOW_BOUND) {
731 mw_uint *= 10;
732 offset -= 40;
735 for (qdbm = 0; qdbm < QDBM_TABLE_LEN - 1; qdbm++) {
736 boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm + 1] -
737 nqdBm_to_mW_map[qdbm]) / 2;
738 if (mw_uint < boundary)
739 break;
742 qdbm += (u8) offset;
744 return qdbm;
746 EXPORT_SYMBOL(bcm_mw_to_qdbm);
748 uint bcm_bitcount(u8 *bitmap, uint length)
750 uint bitcount = 0, i;
751 u8 tmp;
752 for (i = 0; i < length; i++) {
753 tmp = bitmap[i];
754 while (tmp) {
755 bitcount++;
756 tmp &= (tmp - 1);
759 return bitcount;
761 EXPORT_SYMBOL(bcm_bitcount);
763 /* Initialization of bcmstrbuf structure */
764 void bcm_binit(struct bcmstrbuf *b, char *buf, uint size)
766 b->origsize = b->size = size;
767 b->origbuf = b->buf = buf;
769 EXPORT_SYMBOL(bcm_binit);
771 /* Buffer sprintf wrapper to guard against buffer overflow */
772 int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
774 va_list ap;
775 int r;
777 va_start(ap, fmt);
778 r = vsnprintf(b->buf, b->size, fmt, ap);
780 /* Non Ansi C99 compliant returns -1,
781 * Ansi compliant return r >= b->size,
782 * bcmstdlib returns 0, handle all
784 if ((r == -1) || (r >= (int)b->size) || (r == 0)) {
785 b->size = 0;
786 } else {
787 b->size -= r;
788 b->buf += r;
791 va_end(ap);
793 return r;
795 EXPORT_SYMBOL(bcm_bprintf);