/*
* Driver O/S-independent utility routines
*
- * $Copyright Open Broadcom Corporation$
- * $Id: bcmutils.c 496061 2014-08-11 06:14:48Z $
+ * Copyright (C) 1999-2016, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ *
+ * <<Broadcom-WL-IPTag/Open:>>
+ *
+ * $Id: bcmutils.c 591286 2015-10-07 11:59:26Z $
*/
#include <bcm_cfg.h>
void *_bcmutils_dummy_fn = NULL;
-#ifdef CUSTOM_DSCP_TO_PRIO_MAPPING
-#define CUST_IPV4_TOS_PREC_MASK 0x3F
-#define DCSP_MAX_VALUE 64
-/* 0:BE,1:BK,2:RESV(BK):,3:EE,:4:CL,5:VI,6:VO,7:NC */
-int dscp2priomap[DCSP_MAX_VALUE]=
-{
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, /* BK->BE */
- 2, 0, 0, 0, 0, 0, 0, 0,
- 3, 0, 0, 0, 0, 0, 0, 0,
- 4, 0, 0, 0, 0, 0, 0, 0,
- 5, 0, 0, 0, 0, 0, 0, 0,
- 6, 0, 0, 0, 0, 0, 0, 0,
- 7, 0, 0, 0, 0, 0, 0, 0
-};
-#endif /* CUSTOM_DSCP_TO_PRIO_MAPPING */
#ifdef BCMDRIVER
evh->vlan_tag = hton16(vlan_tag);
rc |= PKTPRIO_UPD;
}
+#ifdef DHD_LOSSLESS_ROAMING
+ } else if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
+ priority = PRIO_8021D_NC;
+ rc = PKTPRIO_DSCP;
+#endif /* DHD_LOSSLESS_ROAMING */
} else if ((eh->ether_type == hton16(ETHER_TYPE_IP)) ||
(eh->ether_type == hton16(ETHER_TYPE_IPV6))) {
uint8 *ip_body = pktdata + sizeof(struct ether_header);
priority = PRIO_8021D_EE;
break;
default:
-#ifndef CUSTOM_DSCP_TO_PRIO_MAPPING
priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT);
-#else
- priority = (int)dscp2priomap[((tos_tc >> IPV4_TOS_DSCP_SHIFT)
- & CUST_IPV4_TOS_PREC_MASK)];
-#endif
break;
}
return (rc | priority);
}
+/* lookup user priority for specified DSCP */
+static uint8
+dscp2up(uint8 *up_table, uint8 dscp)
+{
+ uint8 user_priority = 255;
+
+ /* lookup up from table if parameters valid */
+ if (up_table != NULL && dscp < UP_TABLE_MAX) {
+ user_priority = up_table[dscp];
+ }
+
+ /* 255 is unused value so return up from dscp */
+ if (user_priority == 255) {
+ user_priority = dscp >> (IPV4_TOS_PREC_SHIFT - IPV4_TOS_DSCP_SHIFT);
+ }
+
+ return user_priority;
+}
+
+/* set user priority by QoS Map Set table (UP table), table size is UP_TABLE_MAX */
+uint BCMFASTPATH
+pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag)
+{
+ if (up_table) {
+ uint8 *pktdata;
+ uint pktlen;
+ uint8 dscp;
+ uint user_priority = 0;
+ uint rc = 0;
+
+ pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
+ pktlen = PKTLEN(OSH_NULL, pkt);
+
+ if (pktgetdscp(pktdata, pktlen, &dscp)) {
+ rc = PKTPRIO_DSCP;
+ user_priority = dscp2up(up_table, dscp);
+ PKTSETPRIO(pkt, user_priority);
+ }
+
+ return (rc | user_priority);
+ } else {
+ return pktsetprio(pkt, update_vtag);
+ }
+}
+
/* Returns TRUE and DSCP if IP header found, FALSE otherwise.
*/
bool BCMFASTPATH
return rc;
}
+/* Add to adjust the 802.1x priority */
+void
+pktset8021xprio(void *pkt, int prio)
+{
+ struct ether_header *eh;
+ uint8 *pktdata;
+ if(prio == PKTPRIO(pkt))
+ return;
+ pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt);
+ ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16)));
+ eh = (struct ether_header *) pktdata;
+ if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) {
+ ASSERT(prio >= 0 && prio <= MAXPRIO);
+ PKTSETPRIO(pkt, prio);
+ }
+}
+
/* The 0.5KB string table is not removed by compiler even though it's unused */
static char bcm_undeferrstr[32];
#endif /* BCMDRIVER */
+#ifdef BCM_OBJECT_TRACE
+
+#define BCM_OBJECT_MERGE_SAME_OBJ 0
+
+/* some place may add / remove the object to trace list for Linux: */
+/* add: osl_alloc_skb dev_alloc_skb skb_realloc_headroom dhd_start_xmit */
+/* remove: osl_pktfree dev_kfree_skb netif_rx */
+
+#define BCM_OBJDBG_COUNT (1024 * 100)
+static spinlock_t dbgobj_lock;
+#define BCM_OBJDBG_LOCK_INIT() spin_lock_init(&dbgobj_lock)
+#define BCM_OBJDBG_LOCK_DESTROY()
+#define BCM_OBJDBG_LOCK spin_lock_irqsave
+#define BCM_OBJDBG_UNLOCK spin_unlock_irqrestore
+
+#define BCM_OBJDBG_ADDTOHEAD 0
+#define BCM_OBJDBG_ADDTOTAIL 1
+
+#define BCM_OBJDBG_CALLER_LEN 32
+struct bcm_dbgobj {
+ struct bcm_dbgobj *prior;
+ struct bcm_dbgobj *next;
+ uint32 flag;
+ void *obj;
+ uint32 obj_sn;
+ uint32 obj_state;
+ uint32 line;
+ char caller[BCM_OBJDBG_CALLER_LEN];
+};
+
+static struct bcm_dbgobj *dbgobj_freehead = NULL;
+static struct bcm_dbgobj *dbgobj_freetail = NULL;
+static struct bcm_dbgobj *dbgobj_objhead = NULL;
+static struct bcm_dbgobj *dbgobj_objtail = NULL;
+
+static uint32 dbgobj_sn = 0;
+static int dbgobj_count = 0;
+static struct bcm_dbgobj bcm_dbg_objs[BCM_OBJDBG_COUNT];
+
+void
+bcm_object_trace_init(void)
+{
+ int i = 0;
+ BCM_OBJDBG_LOCK_INIT();
+ memset(&bcm_dbg_objs, 0x00, sizeof(struct bcm_dbgobj) * BCM_OBJDBG_COUNT);
+ dbgobj_freehead = &bcm_dbg_objs[0];
+ dbgobj_freetail = &bcm_dbg_objs[BCM_OBJDBG_COUNT - 1];
+
+ for (i = 0; i < BCM_OBJDBG_COUNT; ++i) {
+ bcm_dbg_objs[i].next = (i == (BCM_OBJDBG_COUNT - 1)) ?
+ dbgobj_freehead : &bcm_dbg_objs[i + 1];
+ bcm_dbg_objs[i].prior = (i == 0) ?
+ dbgobj_freetail : &bcm_dbg_objs[i - 1];
+ }
+}
+
+void
+bcm_object_trace_deinit(void)
+{
+ if (dbgobj_objhead || dbgobj_objtail) {
+ printf("%s: not all objects are released\n", __FUNCTION__);
+ ASSERT(0);
+ }
+ BCM_OBJDBG_LOCK_DESTROY();
+}
+
+static void
+bcm_object_rm_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
+ struct bcm_dbgobj *dbgobj)
+{
+ if ((dbgobj == *head) && (dbgobj == *tail)) {
+ *head = NULL;
+ *tail = NULL;
+ } else if (dbgobj == *head) {
+ *head = (*head)->next;
+ } else if (dbgobj == *tail) {
+ *tail = (*tail)->prior;
+ }
+ dbgobj->next->prior = dbgobj->prior;
+ dbgobj->prior->next = dbgobj->next;
+}
+
+static void
+bcm_object_add_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
+ struct bcm_dbgobj *dbgobj, int addtotail)
+{
+ if (!(*head) && !(*tail)) {
+ *head = dbgobj;
+ *tail = dbgobj;
+ dbgobj->next = dbgobj;
+ dbgobj->prior = dbgobj;
+ } else if ((*head) && (*tail)) {
+ (*tail)->next = dbgobj;
+ (*head)->prior = dbgobj;
+ dbgobj->next = *head;
+ dbgobj->prior = *tail;
+ if (addtotail == BCM_OBJDBG_ADDTOTAIL)
+ *tail = dbgobj;
+ else
+ *head = dbgobj;
+ } else {
+ ASSERT(0); /* can't be this case */
+ }
+}
+
+static INLINE void
+bcm_object_movetoend(struct bcm_dbgobj **head, struct bcm_dbgobj **tail,
+ struct bcm_dbgobj *dbgobj, int movetotail)
+{
+ if ((*head) && (*tail)) {
+ if (movetotail == BCM_OBJDBG_ADDTOTAIL) {
+ if (dbgobj != (*tail)) {
+ bcm_object_rm_list(head, tail, dbgobj);
+ bcm_object_add_list(head, tail, dbgobj, movetotail);
+ }
+ } else {
+ if (dbgobj != (*head)) {
+ bcm_object_rm_list(head, tail, dbgobj);
+ bcm_object_add_list(head, tail, dbgobj, movetotail);
+ }
+ }
+ } else {
+ ASSERT(0); /* can't be this case */
+ }
+}
+
+void
+bcm_object_trace_opr(void *obj, uint32 opt, const char *caller, int line)
+{
+ struct bcm_dbgobj *dbgobj;
+ unsigned long flags;
+
+ BCM_REFERENCE(flags);
+ BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
+
+ if (opt == BCM_OBJDBG_ADD_PKT ||
+ opt == BCM_OBJDBG_ADD) {
+ dbgobj = dbgobj_objtail;
+ while (dbgobj) {
+ if (dbgobj->obj == obj) {
+ printf("%s: obj %p allocated from %s(%d),"
+ " allocate again from %s(%d)\n",
+ __FUNCTION__, dbgobj->obj,
+ dbgobj->caller, dbgobj->line,
+ caller, line);
+ ASSERT(0);
+ goto EXIT;
+ }
+ dbgobj = dbgobj->prior;
+ if (dbgobj == dbgobj_objtail)
+ break;
+ }
+
+#if BCM_OBJECT_MERGE_SAME_OBJ
+ dbgobj = dbgobj_freetail;
+ while (dbgobj) {
+ if (dbgobj->obj == obj) {
+ goto FREED_ENTRY_FOUND;
+ }
+ dbgobj = dbgobj->prior;
+ if (dbgobj == dbgobj_freetail)
+ break;
+ }
+#endif /* BCM_OBJECT_MERGE_SAME_OBJ */
+
+ dbgobj = dbgobj_freehead;
+#if BCM_OBJECT_MERGE_SAME_OBJ
+FREED_ENTRY_FOUND:
+#endif /* BCM_OBJECT_MERGE_SAME_OBJ */
+ if (!dbgobj) {
+ printf("%s: already got %d objects ?????????????????????\n",
+ __FUNCTION__, BCM_OBJDBG_COUNT);
+ ASSERT(0);
+ goto EXIT;
+ }
+
+ bcm_object_rm_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj);
+ dbgobj->obj = obj;
+ strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN);
+ dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0';
+ dbgobj->line = line;
+ dbgobj->flag = 0;
+ if (opt == BCM_OBJDBG_ADD_PKT) {
+ dbgobj->obj_sn = dbgobj_sn++;
+ dbgobj->obj_state = 0;
+ /* first 4 bytes is pkt sn */
+ if (((unsigned long)PKTTAG(obj)) & 0x3)
+ printf("pkt tag address not aligned by 4: %p\n", PKTTAG(obj));
+ *(uint32*)PKTTAG(obj) = dbgobj->obj_sn;
+ }
+ bcm_object_add_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj,
+ BCM_OBJDBG_ADDTOTAIL);
+
+ dbgobj_count++;
+
+ } else if (opt == BCM_OBJDBG_REMOVE) {
+ dbgobj = dbgobj_objtail;
+ while (dbgobj) {
+ if (dbgobj->obj == obj) {
+ if (dbgobj->flag) {
+ printf("%s: rm flagged obj %p flag 0x%08x from %s(%d)\n",
+ __FUNCTION__, obj, dbgobj->flag, caller, line);
+ }
+ bcm_object_rm_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj);
+ memset(dbgobj->caller, 0x00, BCM_OBJDBG_CALLER_LEN);
+ strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN);
+ dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0';
+ dbgobj->line = line;
+ bcm_object_add_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj,
+ BCM_OBJDBG_ADDTOTAIL);
+ dbgobj_count--;
+ goto EXIT;
+ }
+ dbgobj = dbgobj->prior;
+ if (dbgobj == dbgobj_objtail)
+ break;
+ }
+
+ dbgobj = dbgobj_freetail;
+ while (dbgobj && dbgobj->obj) {
+ if (dbgobj->obj == obj) {
+ printf("%s: obj %p already freed from from %s(%d),"
+ " try free again from %s(%d)\n",
+ __FUNCTION__, obj,
+ dbgobj->caller, dbgobj->line,
+ caller, line);
+ //ASSERT(0); /* release same obj more than one time? */
+ goto EXIT;
+ }
+ dbgobj = dbgobj->prior;
+ if (dbgobj == dbgobj_freetail)
+ break;
+ }
+
+ printf("%s: ################### release none-existing obj %p from %s(%d)\n",
+ __FUNCTION__, obj, caller, line);
+ //ASSERT(0); /* release same obj more than one time? */
+
+ }
+
+EXIT:
+ BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
+ return;
+}
+
+void
+bcm_object_trace_upd(void *obj, void *obj_new)
+{
+ struct bcm_dbgobj *dbgobj;
+ unsigned long flags;
+
+ BCM_REFERENCE(flags);
+ BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
+
+ dbgobj = dbgobj_objtail;
+ while (dbgobj) {
+ if (dbgobj->obj == obj) {
+ dbgobj->obj = obj_new;
+ if (dbgobj != dbgobj_objtail) {
+ bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
+ dbgobj, BCM_OBJDBG_ADDTOTAIL);
+ }
+ goto EXIT;
+ }
+ dbgobj = dbgobj->prior;
+ if (dbgobj == dbgobj_objtail)
+ break;
+ }
+
+EXIT:
+ BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
+ return;
+}
+
+void
+bcm_object_trace_chk(void *obj, uint32 chksn, uint32 sn,
+ const char *caller, int line)
+{
+ struct bcm_dbgobj *dbgobj;
+ unsigned long flags;
+
+ BCM_REFERENCE(flags);
+ BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
+
+ dbgobj = dbgobj_objtail;
+ while (dbgobj) {
+ if ((dbgobj->obj == obj) &&
+ ((!chksn) || (dbgobj->obj_sn == sn))) {
+ if (dbgobj != dbgobj_objtail) {
+ bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
+ dbgobj, BCM_OBJDBG_ADDTOTAIL);
+ }
+ goto EXIT;
+ }
+ dbgobj = dbgobj->prior;
+ if (dbgobj == dbgobj_objtail)
+ break;
+ }
+
+ dbgobj = dbgobj_freetail;
+ while (dbgobj) {
+ if ((dbgobj->obj == obj) &&
+ ((!chksn) || (dbgobj->obj_sn == sn))) {
+ printf("%s: (%s:%d) obj %p (sn %d state %d) was freed from %s(%d)\n",
+ __FUNCTION__, caller, line,
+ dbgobj->obj, dbgobj->obj_sn, dbgobj->obj_state,
+ dbgobj->caller, dbgobj->line);
+ goto EXIT;
+ }
+ else if (dbgobj->obj == NULL) {
+ break;
+ }
+ dbgobj = dbgobj->prior;
+ if (dbgobj == dbgobj_freetail)
+ break;
+ }
+
+ printf("%s: obj %p not found, check from %s(%d), chksn %s, sn %d\n",
+ __FUNCTION__, obj, caller, line, chksn ? "yes" : "no", sn);
+ dbgobj = dbgobj_objtail;
+ while (dbgobj) {
+ printf("%s: (%s:%d) obj %p sn %d was allocated from %s(%d)\n",
+ __FUNCTION__, caller, line,
+ dbgobj->obj, dbgobj->obj_sn, dbgobj->caller, dbgobj->line);
+ dbgobj = dbgobj->prior;
+ if (dbgobj == dbgobj_objtail)
+ break;
+ }
+
+EXIT:
+ BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
+ return;
+}
+
+void
+bcm_object_feature_set(void *obj, uint32 type, uint32 value)
+{
+ struct bcm_dbgobj *dbgobj;
+ unsigned long flags;
+
+ BCM_REFERENCE(flags);
+ BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
+
+ dbgobj = dbgobj_objtail;
+ while (dbgobj) {
+ if (dbgobj->obj == obj) {
+ if (type == BCM_OBJECT_FEATURE_FLAG) {
+ if (value & BCM_OBJECT_FEATURE_CLEAR)
+ dbgobj->flag &= ~(value);
+ else
+ dbgobj->flag |= (value);
+ } else if (type == BCM_OBJECT_FEATURE_PKT_STATE) {
+ dbgobj->obj_state = value;
+ }
+ if (dbgobj != dbgobj_objtail) {
+ bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
+ dbgobj, BCM_OBJDBG_ADDTOTAIL);
+ }
+ goto EXIT;
+ }
+ dbgobj = dbgobj->prior;
+ if (dbgobj == dbgobj_objtail)
+ break;
+ }
+
+ printf("%s: obj %p not found in active list\n", __FUNCTION__, obj);
+ ASSERT(0);
+
+EXIT:
+ BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
+ return;
+}
+
+int
+bcm_object_feature_get(void *obj, uint32 type, uint32 value)
+{
+ int rtn = 0;
+ struct bcm_dbgobj *dbgobj;
+ unsigned long flags;
+
+ BCM_REFERENCE(flags);
+ BCM_OBJDBG_LOCK(&dbgobj_lock, flags);
+
+ dbgobj = dbgobj_objtail;
+ while (dbgobj) {
+ if (dbgobj->obj == obj) {
+ if (type == BCM_OBJECT_FEATURE_FLAG) {
+ rtn = (dbgobj->flag & value) & (~BCM_OBJECT_FEATURE_CLEAR);
+ }
+ if (dbgobj != dbgobj_objtail) {
+ bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail,
+ dbgobj, BCM_OBJDBG_ADDTOTAIL);
+ }
+ goto EXIT;
+ }
+ dbgobj = dbgobj->prior;
+ if (dbgobj == dbgobj_objtail)
+ break;
+ }
+
+ printf("%s: obj %p not found in active list\n", __FUNCTION__, obj);
+ ASSERT(0);
+
+EXIT:
+ BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags);
+ return rtn;
+}
+
+#endif /* BCM_OBJECT_TRACE */
uint8 *
bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst)
bcm_tlv_t *elt;
int totlen;
- elt = (bcm_tlv_t*)buf;
+ if ((elt = (bcm_tlv_t*)buf) == NULL) {
+ return NULL;
+ }
totlen = buflen;
/* find tagged parameter */
/* indicate the str was too short */
if (flags != 0) {
- if (len < 2)
- p -= 2 - len; /* overwrite last char */
p += snprintf(p, 2, ">");
}
p = line;
for (i = 0; i < nbytes; i++) {
if (i % 16 == 0) {
- nchar = snprintf(p, len, " %04d: ", i); /* line prefix */
+ nchar = snprintf(p, len, " %04x: ", i); /* line prefix */
p += nchar;
len -= nchar;
}
"AES_CCM",
"AES_OCB_MSDU",
"AES_OCB_MPDU",
-#ifdef BCMCCX
- "CKIP",
- "CKIP_MMH",
- "WEP_MMH",
- "NALG",
-#else
"NALG",
"UNDEF",
"UNDEF",
"UNDEF",
-#endif /* BCMCCX */
- "WAPI",
+ "UNDEF"
"PMK",
"BIP",
"AES_GCM",
}
uint
-bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
+bcm_mkiovar(const char *name, char *data, uint datalen, char *buf, uint buflen)
{
uint len;
return bitcount;
}
-#ifdef BCMDRIVER
+#if defined(BCMDRIVER) || defined(WL_UNITTEST)
+
+/* triggers bcm_bprintf to print to kernel log */
+bool bcm_bprintf_bypass = FALSE;
/* Initialization of bcmstrbuf structure */
void
va_start(ap, fmt);
r = vsnprintf(b->buf, b->size, fmt, ap);
+ if (bcm_bprintf_bypass == TRUE) {
+ printf(b->buf);
+ goto exit;
+ }
/* Non Ansi C99 compliant returns -1,
* Ansi compliant return r >= b->size,
b->buf += r;
}
+exit:
va_end(ap);
return r;
}
void
-bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len)
+bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, const uint8 *buf, int len)
{
int i;
}
#endif
-#endif /* BCMDRIVER */
+#endif /* BCMDRIVER || WL_UNITTEST */
/*
* ProcessVars:Takes a buffer of "<var>=<value>\n" lines read from a file and ending in a NUL.
}
void
-bcm_bitprint32(const uint32 u32)
+bcm_bitprint32(const uint32 u32arg)
{
int i;
for (i = NBITS(uint32) - 1; i >= 0; i--) {
- isbitset(u32, i) ? printf("1") : printf("0");
+ isbitset(u32arg, i) ? printf("1") : printf("0");
if ((i % NBBY) == 0) printf(" ");
}
printf("\n");
return ((uint16)~sum);
}
-
-#ifdef BCMDRIVER
+#if defined(BCMDRIVER) && !defined(_CFEZ_)
/*
* Hierarchical Multiword bitmap based small id allocator.
*
* with savings in not having to use an indirect access, had it been dynamically
* allocated.
*/
-#define BCM_MWBMAP_ITEMS_MAX (4 * 1024) /* May increase to 16K */
+#define BCM_MWBMAP_ITEMS_MAX (64 * 1024) /* May increase to 64K */
#define BCM_MWBMAP_BITS_WORD (NBITS(uint32))
#define BCM_MWBMAP_WORDS_MAX (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD)
typedef struct bcm_mwbmap { /* Hierarchical multiword bitmap allocator */
uint16 wmaps; /* Total number of words in free wd bitmap */
uint16 imaps; /* Total number of words in free id bitmap */
- int16 ifree; /* Count of free indices. Used only in audits */
+ int32 ifree; /* Count of free indices. Used only in audits */
uint16 total; /* Total indices managed by multiword bitmap */
void * magic; /* Audit handle parameter from user */
/* Initialize runtime multiword bitmap state */
mwbmap_p->imaps = (uint16)words;
- mwbmap_p->ifree = (int16)items_max;
+ mwbmap_p->ifree = (int32)items_max;
mwbmap_p->total = (uint16)items_max;
/* Setup magic, for use in audit of handle */
/* Simple 16bit Id allocator using a stack implementation. */
typedef struct id16_map {
- uint16 total; /* total number of ids managed by allocator */
- uint16 start; /* start value of 16bit ids to be managed */
uint32 failures; /* count of failures */
void *dbg; /* debug placeholder */
+ uint16 total; /* total number of ids managed by allocator */
+ uint16 start; /* start value of 16bit ids to be managed */
int stack_idx; /* index into stack of available ids */
uint16 stack[0]; /* stack of 16 bit ids */
} id16_map_t;
id16_map_t * id16_map;
ASSERT(total_ids > 0);
- ASSERT((start_val16 + total_ids) < ID16_INVALID);
+
+ /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
+ * with random values.
+ */
+ ASSERT((start_val16 == ID16_UNDEFINED) ||
+ (start_val16 + total_ids) < ID16_INVALID);
id16_map = (id16_map_t *) MALLOC(osh, ID16_MAP_SZ(total_ids));
if (id16_map == NULL) {
id16_map->failures = 0;
id16_map->dbg = NULL;
- /* Populate stack with 16bit id values, commencing with start_val16 */
- id16_map->stack_idx = 0;
- val16 = start_val16;
+ /*
+ * Populate stack with 16bit id values, commencing with start_val16.
+ * if start_val16 is ID16_UNDEFINED, then do not populate the id16 map.
+ */
+ id16_map->stack_idx = -1;
+
+ if (id16_map->start != ID16_UNDEFINED) {
+ val16 = start_val16;
- for (idx = 0; idx < total_ids; idx++, val16++) {
- id16_map->stack_idx = idx;
- id16_map->stack[id16_map->stack_idx] = val16;
+ for (idx = 0; idx < total_ids; idx++, val16++) {
+ id16_map->stack_idx = idx;
+ id16_map->stack[id16_map->stack_idx] = val16;
+ }
}
#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
- id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids));
+ if (id16_map->start != ID16_UNDEFINED) {
+ id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids));
- if (id16_map->dbg) {
- id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
+ if (id16_map->dbg) {
+ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
- id16_map_dbg->total = total_ids;
- for (idx = 0; idx < total_ids; idx++) {
- id16_map_dbg->avail[idx] = TRUE;
+ id16_map_dbg->total = total_ids;
+ for (idx = 0; idx < total_ids; idx++) {
+ id16_map_dbg->avail[idx] = TRUE;
+ }
}
}
#endif /* BCM_DBG && BCM_DBG_ID16 */
id16_map_t * id16_map;
ASSERT(total_ids > 0);
- ASSERT((start_val16 + total_ids) < ID16_INVALID);
+ /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map
+ * with random values.
+ */
+ ASSERT((start_val16 == ID16_UNDEFINED) ||
+ (start_val16 + total_ids) < ID16_INVALID);
id16_map = (id16_map_t *)id16_map_hndl;
if (id16_map == NULL) {
id16_map->failures = 0;
/* Populate stack with 16bit id values, commencing with start_val16 */
- id16_map->stack_idx = 0;
- val16 = start_val16;
+ id16_map->stack_idx = -1;
- for (idx = 0; idx < total_ids; idx++, val16++) {
- id16_map->stack_idx = idx;
- id16_map->stack[id16_map->stack_idx] = val16;
+ if (id16_map->start != ID16_UNDEFINED) {
+ val16 = start_val16;
+
+ for (idx = 0; idx < total_ids; idx++, val16++) {
+ id16_map->stack_idx = idx;
+ id16_map->stack[id16_map->stack_idx] = val16;
+ }
}
#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
- if (id16_map->dbg) {
- id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
+ if (id16_map->start != ID16_UNDEFINED) {
+ if (id16_map->dbg) {
+ id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
- id16_map_dbg->total = total_ids;
- for (idx = 0; idx < total_ids; idx++) {
- id16_map_dbg->avail[idx] = TRUE;
+ id16_map_dbg->total = total_ids;
+ for (idx = 0; idx < total_ids; idx++) {
+ id16_map_dbg->avail[idx] = TRUE;
+ }
}
}
#endif /* BCM_DBG && BCM_DBG_ID16 */
id16_map->stack_idx--;
#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
-
- ASSERT(val16 < (id16_map->start + id16_map->total));
+ ASSERT((id16_map->start == ID16_UNDEFINED) ||
+ (val16 < (id16_map->start + id16_map->total)));
if (id16_map->dbg) { /* Validate val16 */
id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
id16_map = (id16_map_t *)id16_map_hndl;
#if defined(BCM_DBG) && defined(BCM_DBG_ID16)
-
- ASSERT(val16 < (id16_map->start + id16_map->total));
+ ASSERT((id16_map->start == ID16_UNDEFINED) ||
+ (val16 < (id16_map->start + id16_map->total)));
if (id16_map->dbg) { /* Validate val16 */
id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg;
id16_map = (id16_map_t *)id16_map_hndl;
- ASSERT((id16_map->stack_idx > 0) && (id16_map->stack_idx < id16_map->total));
+ ASSERT(id16_map->stack_idx >= -1);
+ ASSERT(id16_map->stack_idx < (int)id16_map->total);
+
+ if (id16_map->start == ID16_UNDEFINED)
+ goto done;
+
for (idx = 0; idx <= id16_map->stack_idx; idx++) {
ASSERT(id16_map->stack[idx] >= id16_map->start);
ASSERT(id16_map->stack[idx] < (id16_map->start + id16_map->total));
if (((id16_map_dbg_t *)(id16_map->dbg))->avail[val16] != TRUE) {
insane |= 1;
ID16_MAP_MSG(("id16_map<%p>: stack_idx %u invalid val16 %u\n",
- id16_map_hndl, idx, val16));
+ id16_map_hndl, idx, val16));
}
}
#endif /* BCM_DBG && BCM_DBG_ID16 */
if (avail && (avail != (id16_map->stack_idx + 1))) {
insane |= 1;
ID16_MAP_MSG(("id16_map<%p>: avail %u stack_idx %u\n",
- id16_map_hndl, avail, id16_map->stack_idx));
+ id16_map_hndl, avail, id16_map->stack_idx));
}
}
#endif /* BCM_DBG && BCM_DBG_ID16 */
+done:
+ /* invoke any other system audits */
return (!!insane);
}
/* END: Simple id16 allocator */
-#endif /* BCMDRIVER */
+#endif
/* calculate a >> b; and returns only lower 32 bits */
void
#endif /* OSL_SYSUPTIME_SUPPORT == TRUE */
#endif /* DEBUG_COUNTER */
-#ifdef BCMDRIVER
+#if defined(BCMDRIVER) && !defined(_CFEZ_)
void
dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size)
{
mem_size = sizeof(dll_pool_t) + (elems_max * elem_size);
- if ((dll_pool_p = (dll_pool_t *)MALLOC(osh, mem_size)) == NULL) {
+ if ((dll_pool_p = (dll_pool_t *)MALLOCZ(osh, mem_size)) == NULL) {
printf("dll_pool_init: elems_max<%u> elem_size<%u> malloc failure\n",
elems_max, elem_size);
ASSERT(0);
return dll_pool_p;
}
- bzero(dll_pool_p, mem_size);
-
dll_init(&dll_pool_p->free_list);
dll_pool_p->elems_max = elems_max;
dll_pool_p->elem_size = elem_size;
dll_pool_p->free_count += 1;
}
-#endif /* BCMDRIVER */
+#endif