/*
* Misc useful os-independent macros and functions.
*
- * $Copyright Open Broadcom Corporation$
+ * 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.
*
- * $Id: bcmutils.h 504037 2014-09-22 19:03:15Z $
+ *
+ * <<Broadcom-WL-IPTag/Open:>>
+ *
+ * $Id: bcmutils.h 563776 2015-06-15 15:51:15Z $
*/
#ifndef _bcmutils_h_
#define _bcmutils_h_
-#define bcm_strcpy_s(dst, noOfElements, src) strcpy((dst), (src))
-#define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count))
-#define bcm_strcat_s(dst, noOfElements, src) strcat((dst), (src))
#ifdef __cplusplus
extern "C" {
#endif
-#ifdef PKTQ_LOG
-#include <wlioctl.h>
-#endif
+#define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count))
+#define bcm_strncat_s(dst, noOfElements, src, count) strncat((dst), (src), (count))
+#define bcm_snprintf_s snprintf
+#define bcm_sprintf_s snprintf
+
+/*
+ * #define bcm_strcpy_s(dst, count, src) strncpy((dst), (src), (count))
+ * Use bcm_strcpy_s instead as it is a safer option
+ * bcm_strcat_s: Use bcm_strncat_s as a safer option
+ *
+ */
/* ctype replacement */
#define _BCM_U 0x01 /* upper */
#define CIRCULAR_ARRAY_FULL(rd_idx, wr_idx, max) ((wr_idx + 1)%max == rd_idx)
+#define KB(bytes) (((bytes) + 1023) / 1024)
+
/* Buffer structure for collecting string-formatted data
* using bcm_bprintf() API.
* Use bcm_binit() to initialize before use
unsigned int origsize; /* unmodified orignal buffer size in bytes */
};
+#define BCMSTRBUF_LEN(b) (b->size)
+#define BCMSTRBUF_BUF(b) (b->buf)
+
/* ** driver-only section ** */
#ifdef BCMDRIVER
#include <osl.h>
#define BCM_RXCPL_CLR_VALID_INFO(a) ((a)->rxcpl_id.flags &= ~BCM_RXCPL_FLAGS_RXCPLVALID)
#define BCM_RXCPL_VALID_INFO(a) (((a)->rxcpl_id.flags & BCM_RXCPL_FLAGS_RXCPLVALID) ? TRUE : FALSE)
+#define UP_TABLE_MAX ((IPV4_TOS_DSCP_MASK >> IPV4_TOS_DSCP_SHIFT) + 1) /* 64 max */
struct reorder_rxcpl_id_list {
uint16 head;
extern uint pktsegcnt_war(osl_t *osh, void *p);
extern uint8 *pktdataoffset(osl_t *osh, void *p, uint offset);
extern void *pktoffset(osl_t *osh, void *p, uint offset);
+/* Add to adjust 802.1x priority */
+extern void pktset8021xprio(void *pkt, int prio);
/* Get priority from a packet and pass it back in scb (or equiv) */
#define PKTPRIO_VDSCP 0x100 /* DSCP prio found after VLAN tag */
#define DSCP_EF 0x2E
extern uint pktsetprio(void *pkt, bool update_vtag);
+extern uint pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag);
extern bool pktgetdscp(uint8 *pktdata, uint pktlen, uint8 *dscp);
/* string */
#define bcmtslog(tstamp, fmt, a1, a2)
#define bcmprinttslogs()
#define bcmprinttstamp(us)
-#define bcmdumptslog(buf, size)
+#define bcmdumptslog(b)
extern char *bcm_nvram_vars(uint *length);
extern int bcm_nvram_cache(void *sih);
#define BCME_MICERR -50 /* Integrity/MIC error */
#define BCME_REPLAY -51 /* Replay */
#define BCME_IE_NOTFOUND -52 /* IE not found */
-#define BCME_LAST BCME_IE_NOTFOUND
+#define BCME_DATA_NOTFOUND -53 /* Complete data not found in buffer */
+#define BCME_LAST BCME_DATA_NOTFOUND
#define BCME_NOTENABLED BCME_DISABLED
"MIC error", \
"Replay", \
"IE not found", \
+ "Data not found", \
}
#ifndef ABS
#define ETHER_ADDR_STR_LEN 18 /* 18-bytes of Ethernet address buffer length */
static INLINE uint32 /* 32bit word aligned xor-32 */
-bcm_compute_xor32(volatile uint32 *u32, int num_u32)
+bcm_compute_xor32(volatile uint32 *u32_val, int num_u32)
{
- int i;
+ int idx;
uint32 xor32 = 0;
- for (i = 0; i < num_u32; i++)
- xor32 ^= *(u32 + i);
+ for (idx = 0; idx < num_u32; idx++)
+ xor32 ^= *(u32_val + idx);
return xor32;
}
/* IE parsing */
+/* packing is required if struct is passed across the bus */
+#include <packed_section_start.h>
/* tag_ID/length/value_buffer tuple */
typedef struct bcm_tlv {
uint8 id;
} bcm_tlv_t;
/* bcm tlv w/ 16 bit id/len */
-typedef struct bcm_xtlv {
+typedef BWL_PRE_PACKED_STRUCT struct bcm_xtlv {
uint16 id;
uint16 len;
uint8 data[1];
-} bcm_xtlv_t;
+} BWL_POST_PACKED_STRUCT bcm_xtlv_t;
+#include <packed_section_end.h>
+
/* descriptor of xtlv data src or dst */
typedef struct {
void *ptr; /* ptr to memory location */
} xtlv_desc_t;
-/* set a var from xtlv buffer */
-typedef int
-(bcm_set_var_from_tlv_cbfn_t)(void *ctx, void **tlv_buf, uint16 type, uint16 len);
-
-struct bcm_tlvbuf {
- uint16 size;
- uint8 *head; /* point to head of buffer */
- uint8 *buf; /* current position of buffer */
- /* followed by the allocated buffer */
+/* xtlv options */
+#define BCM_XTLV_OPTION_NONE 0x0000
+#define BCM_XTLV_OPTION_ALIGN32 0x0001
+
+typedef uint16 bcm_xtlv_opts_t;
+struct bcm_xtlvbuf {
+ bcm_xtlv_opts_t opts;
+ uint16 size;
+ uint8 *head; /* point to head of buffer */
+ uint8 *buf; /* current position of buffer */
+ /* allocated buffer may follow, but not necessarily */
};
+typedef struct bcm_xtlvbuf bcm_xtlvbuf_t;
#define BCM_TLV_MAX_DATA_SIZE (255)
#define BCM_XTLV_MAX_DATA_SIZE (65535)
#define BCM_TLV_HDR_SIZE (OFFSETOF(bcm_tlv_t, data))
#define BCM_XTLV_HDR_SIZE (OFFSETOF(bcm_xtlv_t, data))
+/* LEN only stores the value's length without padding */
#define BCM_XTLV_LEN(elt) ltoh16_ua(&(elt->len))
#define BCM_XTLV_ID(elt) ltoh16_ua(&(elt->id))
-#define BCM_XTLV_SIZE(elt) (BCM_XTLV_HDR_SIZE + BCM_XTLV_LEN(elt))
+/* entire size of the XTLV including header, data, and optional padding */
+#define BCM_XTLV_SIZE(elt, opts) bcm_xtlv_size(elt, opts)
+#define bcm_valid_xtlv(elt, buflen, opts) (elt && ((int)(buflen) >= (int)BCM_XTLV_SIZE(elt, opts)))
/* Check that bcm_tlv_t fits into the given buflen */
#define bcm_valid_tlv(elt, buflen) (\
((int)(buflen) >= (int)BCM_TLV_HDR_SIZE) && \
((int)(buflen) >= (int)(BCM_TLV_HDR_SIZE + (elt)->len)))
-#define bcm_valid_xtlv(elt, buflen) (\
- ((int)(buflen) >= (int)BCM_XTLV_HDR_SIZE) && \
- ((int)(buflen) >= (int)BCM_XTLV_SIZE(elt)))
extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen);
extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key);
extern uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen);
/* xtlv */
-extern bcm_xtlv_t *bcm_next_xtlv(bcm_xtlv_t *elt, int *buflen);
-extern struct bcm_tlvbuf *bcm_xtlv_buf_alloc(void *osh, uint16 len);
-extern void bcm_xtlv_buf_free(void *osh, struct bcm_tlvbuf *tbuf);
-extern uint16 bcm_xtlv_buf_len(struct bcm_tlvbuf *tbuf);
-extern uint16 bcm_xtlv_buf_rlen(struct bcm_tlvbuf *tbuf);
-extern uint8 *bcm_xtlv_buf(struct bcm_tlvbuf *tbuf);
-extern uint8 *bcm_xtlv_head(struct bcm_tlvbuf *tbuf);
-extern int bcm_xtlv_put_data(struct bcm_tlvbuf *tbuf, uint16 type, const void *data, uint16 dlen);
-extern int bcm_xtlv_put_8(struct bcm_tlvbuf *tbuf, uint16 type, const int8 data);
-extern int bcm_xtlv_put_16(struct bcm_tlvbuf *tbuf, uint16 type, const int16 data);
-extern int bcm_xtlv_put_32(struct bcm_tlvbuf *tbuf, uint16 type, const int32 data);
-extern int bcm_unpack_xtlv_entry(void **tlv_buf, uint16 xpct_type, uint16 xpct_len, void *dst);
-extern int bcm_skip_xtlv(void **tlv_buf);
-extern int bcm_pack_xtlv_entry(void **tlv_buf, uint16 *buflen, uint16 type, uint16 len, void *src);
-extern int bcm_unpack_xtlv_buf(void *ctx,
- void *tlv_buf, uint16 buflen, bcm_set_var_from_tlv_cbfn_t *cbfn);
-extern int
-bcm_unpack_xtlv_buf_to_mem(void *tlv_buf, int *buflen, xtlv_desc_t *items);
-extern int
-bcm_pack_xtlv_buf_from_mem(void **tlv_buf, uint16 *buflen, xtlv_desc_t *items);
-extern int
-bcm_pack_xtlv_entry_from_hex_string(void **tlv_buf, uint16 *buflen, uint16 type, char *hex);
+
+/* return the next xtlv element, and update buffer len (remaining). Buffer length
+ * updated includes padding as specified by options
+ */
+extern bcm_xtlv_t *bcm_next_xtlv(bcm_xtlv_t *elt, int *buflen, bcm_xtlv_opts_t opts);
+
+/* initialize an xtlv buffer. Use options specified for packing/unpacking using
+ * the buffer. Caller is responsible for allocating both buffers.
+ */
+extern int bcm_xtlv_buf_init(bcm_xtlvbuf_t *tlv_buf, uint8 *buf, uint16 len,
+ bcm_xtlv_opts_t opts);
+
+extern uint16 bcm_xtlv_buf_len(struct bcm_xtlvbuf *tbuf);
+extern uint16 bcm_xtlv_buf_rlen(struct bcm_xtlvbuf *tbuf);
+extern uint8 *bcm_xtlv_buf(struct bcm_xtlvbuf *tbuf);
+extern uint8 *bcm_xtlv_head(struct bcm_xtlvbuf *tbuf);
+extern int bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const void *data, uint16 dlen);
+extern int bcm_xtlv_put_8(bcm_xtlvbuf_t *tbuf, uint16 type, const int8 data);
+extern int bcm_xtlv_put_16(bcm_xtlvbuf_t *tbuf, uint16 type, const int16 data);
+extern int bcm_xtlv_put_32(bcm_xtlvbuf_t *tbuf, uint16 type, const int32 data);
+extern int bcm_unpack_xtlv_entry(uint8 **buf, uint16 xpct_type, uint16 xpct_len,
+ void *dst, bcm_xtlv_opts_t opts);
+extern int bcm_pack_xtlv_entry(uint8 **buf, uint16 *buflen, uint16 type, uint16 len,
+ void *src, bcm_xtlv_opts_t opts);
+extern int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts);
+
+/* callback for unpacking xtlv from a buffer into context. */
+typedef int (bcm_xtlv_unpack_cbfn_t)(void *ctx, uint8 *buf, uint16 type, uint16 len);
+
+/* unpack a tlv buffer using buffer, options, and callback */
+extern int bcm_unpack_xtlv_buf(void *ctx, uint8 *buf, uint16 buflen,
+ bcm_xtlv_opts_t opts, bcm_xtlv_unpack_cbfn_t *cbfn);
+
+/* unpack a set of tlvs from the buffer using provided xtlv desc */
+extern int bcm_unpack_xtlv_buf_to_mem(void *buf, int *buflen, xtlv_desc_t *items,
+ bcm_xtlv_opts_t opts);
+
+/* pack a set of tlvs into buffer using provided xtlv desc */
+extern int bcm_pack_xtlv_buf_from_mem(void **buf, uint16 *buflen, xtlv_desc_t *items,
+ bcm_xtlv_opts_t opts);
+
+/* return data pointer of a given ID from xtlv buffer
+ * xtlv data length is given to *datalen_out, if the pointer is valid
+ */
+extern void *bcm_get_data_from_xtlv_buf(uint8 *tlv_buf, uint16 buflen, uint16 id,
+ uint16 *datalen_out, bcm_xtlv_opts_t opts);
+
+/* callback to return next tlv id and len to pack, if there is more tlvs to come and
+ * options e.g. alignment
+ */
+typedef bool (*bcm_pack_xtlv_next_info_cbfn_t)(void *ctx, uint16 *tlv_id, uint16 *tlv_len);
+
+/* callback to pack the tlv into length validated buffer */
+typedef void (*bcm_pack_xtlv_pack_next_cbfn_t)(void *ctx,
+ uint16 tlv_id, uint16 tlv_len, uint8* buf);
+
+/* pack a set of tlvs into buffer using get_next to interate */
+int bcm_pack_xtlv_buf(void *ctx, void *tlv_buf, uint16 buflen,
+ bcm_xtlv_opts_t opts, bcm_pack_xtlv_next_info_cbfn_t get_next,
+ bcm_pack_xtlv_pack_next_cbfn_t pack_next, int *outlen);
/* bcmerror */
extern const char *bcmerrorstr(int bcmerror);
/* generic datastruct to help dump routines */
struct fielddesc {
const char *nameandfmt;
- uint32 offset;
- uint32 len;
+ uint32 offset;
+ uint32 len;
};
extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size);
-extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, uint8 *buf, int len);
+extern void bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline,
+ const uint8 *buf, int len);
extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount);
extern int bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes);
/* power conversion */
extern uint16 bcm_qdbm_to_mw(uint8 qdbm);
extern uint8 bcm_mw_to_qdbm(uint16 mw);
-extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len);
+extern uint bcm_mkiovar(const char *name, char *data, uint datalen, char *buf, uint len);
unsigned int process_nvram_vars(char *varbuf, unsigned int len);
+/* trace any object allocation / free, with / without features (flags) set to the object */
+
+#define BCM_OBJDBG_ADD 1
+#define BCM_OBJDBG_REMOVE 2
+#define BCM_OBJDBG_ADD_PKT 3
+
+/* object feature: set or clear flags */
+#define BCM_OBJECT_FEATURE_FLAG 1
+#define BCM_OBJECT_FEATURE_PKT_STATE 2
+/* object feature: flag bits */
+#define BCM_OBJECT_FEATURE_0 (1 << 0)
+#define BCM_OBJECT_FEATURE_1 (1 << 1)
+#define BCM_OBJECT_FEATURE_2 (1 << 2)
+/* object feature: clear flag bits field set with this flag */
+#define BCM_OBJECT_FEATURE_CLEAR (1 << 31)
+#ifdef BCM_OBJECT_TRACE
+#define bcm_pkt_validate_chk(obj) do { \
+ void * pkttag; \
+ bcm_object_trace_chk(obj, 0, 0, \
+ __FUNCTION__, __LINE__); \
+ if ((pkttag = PKTTAG(obj))) { \
+ bcm_object_trace_chk(obj, 1, DHD_PKTTAG_SN(pkttag), \
+ __FUNCTION__, __LINE__); \
+ } \
+} while (0)
+extern void bcm_object_trace_opr(void *obj, uint32 opt, const char *caller, int line);
+extern void bcm_object_trace_upd(void *obj, void *obj_new);
+extern void bcm_object_trace_chk(void *obj, uint32 chksn, uint32 sn,
+ const char *caller, int line);
+extern void bcm_object_feature_set(void *obj, uint32 type, uint32 value);
+extern int bcm_object_feature_get(void *obj, uint32 type, uint32 value);
+extern void bcm_object_trace_init(void);
+extern void bcm_object_trace_deinit(void);
+#else
+#define bcm_pkt_validate_chk(obj)
+#define bcm_object_trace_opr(a, b, c, d)
+#define bcm_object_trace_upd(a, b)
+#define bcm_object_trace_chk(a, b, c, d, e)
+#define bcm_object_feature_set(a, b, c)
+#define bcm_object_feature_get(a, b, c)
+#define bcm_object_trace_init()
+#define bcm_object_trace_deinit()
+#endif /* BCM_OBJECT_TRACE */
+
/* calculate a * b + c */
extern void bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c);
/* calculate a / b */
};
static INLINE uint32 /* Uses table _CSBTBL for fast counting of 1's in a u32 */
-bcm_cntsetbits(const uint32 u32)
+bcm_cntsetbits(const uint32 u32arg)
{
/* function local scope declaration of const _CSBTBL[] */
- const uint8 * p = (const uint8 *)&u32;
+ const uint8 * p = (const uint8 *)&u32arg;
return (_CSBTBL[p[0]] + _CSBTBL[p[1]] + _CSBTBL[p[2]] + _CSBTBL[p[3]]);
}
static INLINE int /* C equivalent count of leading 0's in a u32 */
-C_bcm_count_leading_zeros(uint32 u32)
+C_bcm_count_leading_zeros(uint32 u32arg)
{
int shifts = 0;
- while (u32) {
- shifts++; u32 >>= 1;
+ while (u32arg) {
+ shifts++; u32arg >>= 1;
}
return (32U - shifts);
}
*/
#if defined(__arm__)
-
#if defined(__ARM_ARCH_7M__) /* Cortex M3 */
#define __USE_ASM_CLZ__
#endif /* __ARM_ARCH_7M__ */
-
#if defined(__ARM_ARCH_7R__) /* Cortex R4 */
#define __USE_ASM_CLZ__
#endif /* __ARM_ARCH_7R__ */
-
#endif /* __arm__ */
static INLINE int
-bcm_count_leading_zeros(uint32 u32)
+bcm_count_leading_zeros(uint32 u32arg)
{
#if defined(__USE_ASM_CLZ__)
int zeros;
- __asm__ volatile("clz %0, %1 \n" : "=r" (zeros) : "r" (u32));
+ __asm__ volatile("clz %0, %1 \n" : "=r" (zeros) : "r" (u32arg));
return zeros;
#else /* C equivalent */
- return C_bcm_count_leading_zeros(u32);
+ return C_bcm_count_leading_zeros(u32arg);
#endif /* C equivalent */
}
+/*
+ * Macro to count leading zeroes
+ *
+ */
+#if defined(__GNUC__)
+#define CLZ(x) __builtin_clzl(x)
+#elif defined(__arm__)
+#define CLZ(x) __clz(x)
+#else
+#define CLZ(x) bcm_count_leading_zeros(x)
+#endif /* __GNUC__ */
+
/* INTERFACE: Multiword bitmap based small id allocator. */
struct bcm_mwbmap; /* forward declaration for use as an opaque mwbmap handle */
/* INTERFACE: Simple unique 16bit Id Allocator using a stack implementation. */
#define ID16_INVALID ((uint16)(~0))
+#define ID16_UNDEFINED (ID16_INVALID)
/*
* Construct a 16bit id allocator, managing 16bit ids in the range:
/* Audit the 16bit id allocator state. */
extern bool id16_map_audit(void * id16_map_hndl);
/* End - Simple 16bit Id Allocator. */
-
#endif /* BCMDRIVER */
extern void bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b);
void counter_printlog(counter_tbl_t *ctr_tbl);
#endif /* DEBUG_COUNTER */
+/* Given a number 'n' returns 'm' that is next larger power of 2 after n */
+static INLINE uint32 next_larger_power2(uint32 num)
+{
+ num--;
+ num |= (num >> 1);
+ num |= (num >> 2);
+ num |= (num >> 4);
+ num |= (num >> 8);
+ num |= (num >> 16);
+ return (num + 1);
+}
+
#endif /* _bcmutils_h_ */