forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
209 lines
5.4 KiB
209 lines
5.4 KiB
/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|
/* |
|
* drivers/net/ethernet/rocker/rocker_tlv.h - Rocker switch device driver |
|
* Copyright (c) 2014-2016 Jiri Pirko <[email protected]> |
|
* Copyright (c) 2014 Scott Feldman <[email protected]> |
|
*/ |
|
|
|
#ifndef _ROCKER_TLV_H |
|
#define _ROCKER_TLV_H |
|
|
|
#include <linux/types.h> |
|
|
|
#include "rocker_hw.h" |
|
#include "rocker.h" |
|
|
|
#define ROCKER_TLV_ALIGNTO 8U |
|
#define ROCKER_TLV_ALIGN(len) \ |
|
(((len) + ROCKER_TLV_ALIGNTO - 1) & ~(ROCKER_TLV_ALIGNTO - 1)) |
|
#define ROCKER_TLV_HDRLEN ROCKER_TLV_ALIGN(sizeof(struct rocker_tlv)) |
|
|
|
/* <------- ROCKER_TLV_HDRLEN -------> <--- ROCKER_TLV_ALIGN(payload) ---> |
|
* +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+ |
|
* | Header | Pad | Payload | Pad | |
|
* | (struct rocker_tlv) | ing | | ing | |
|
* +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+ |
|
* <--------------------------- tlv->len --------------------------> |
|
*/ |
|
|
|
static inline struct rocker_tlv *rocker_tlv_next(const struct rocker_tlv *tlv, |
|
int *remaining) |
|
{ |
|
int totlen = ROCKER_TLV_ALIGN(tlv->len); |
|
|
|
*remaining -= totlen; |
|
return (struct rocker_tlv *) ((char *) tlv + totlen); |
|
} |
|
|
|
static inline int rocker_tlv_ok(const struct rocker_tlv *tlv, int remaining) |
|
{ |
|
return remaining >= (int) ROCKER_TLV_HDRLEN && |
|
tlv->len >= ROCKER_TLV_HDRLEN && |
|
tlv->len <= remaining; |
|
} |
|
|
|
#define rocker_tlv_for_each(pos, head, len, rem) \ |
|
for (pos = head, rem = len; \ |
|
rocker_tlv_ok(pos, rem); \ |
|
pos = rocker_tlv_next(pos, &(rem))) |
|
|
|
#define rocker_tlv_for_each_nested(pos, tlv, rem) \ |
|
rocker_tlv_for_each(pos, rocker_tlv_data(tlv), \ |
|
rocker_tlv_len(tlv), rem) |
|
|
|
static inline int rocker_tlv_attr_size(int payload) |
|
{ |
|
return ROCKER_TLV_HDRLEN + payload; |
|
} |
|
|
|
static inline int rocker_tlv_total_size(int payload) |
|
{ |
|
return ROCKER_TLV_ALIGN(rocker_tlv_attr_size(payload)); |
|
} |
|
|
|
static inline int rocker_tlv_padlen(int payload) |
|
{ |
|
return rocker_tlv_total_size(payload) - rocker_tlv_attr_size(payload); |
|
} |
|
|
|
static inline int rocker_tlv_type(const struct rocker_tlv *tlv) |
|
{ |
|
return tlv->type; |
|
} |
|
|
|
static inline void *rocker_tlv_data(const struct rocker_tlv *tlv) |
|
{ |
|
return (char *) tlv + ROCKER_TLV_HDRLEN; |
|
} |
|
|
|
static inline int rocker_tlv_len(const struct rocker_tlv *tlv) |
|
{ |
|
return tlv->len - ROCKER_TLV_HDRLEN; |
|
} |
|
|
|
static inline u8 rocker_tlv_get_u8(const struct rocker_tlv *tlv) |
|
{ |
|
return *(u8 *) rocker_tlv_data(tlv); |
|
} |
|
|
|
static inline u16 rocker_tlv_get_u16(const struct rocker_tlv *tlv) |
|
{ |
|
return *(u16 *) rocker_tlv_data(tlv); |
|
} |
|
|
|
static inline __be16 rocker_tlv_get_be16(const struct rocker_tlv *tlv) |
|
{ |
|
return *(__be16 *) rocker_tlv_data(tlv); |
|
} |
|
|
|
static inline u32 rocker_tlv_get_u32(const struct rocker_tlv *tlv) |
|
{ |
|
return *(u32 *) rocker_tlv_data(tlv); |
|
} |
|
|
|
static inline u64 rocker_tlv_get_u64(const struct rocker_tlv *tlv) |
|
{ |
|
return *(u64 *) rocker_tlv_data(tlv); |
|
} |
|
|
|
void rocker_tlv_parse(const struct rocker_tlv **tb, int maxtype, |
|
const char *buf, int buf_len); |
|
|
|
static inline void rocker_tlv_parse_nested(const struct rocker_tlv **tb, |
|
int maxtype, |
|
const struct rocker_tlv *tlv) |
|
{ |
|
rocker_tlv_parse(tb, maxtype, rocker_tlv_data(tlv), |
|
rocker_tlv_len(tlv)); |
|
} |
|
|
|
static inline void |
|
rocker_tlv_parse_desc(const struct rocker_tlv **tb, int maxtype, |
|
const struct rocker_desc_info *desc_info) |
|
{ |
|
rocker_tlv_parse(tb, maxtype, desc_info->data, |
|
desc_info->desc->tlv_size); |
|
} |
|
|
|
static inline struct rocker_tlv * |
|
rocker_tlv_start(struct rocker_desc_info *desc_info) |
|
{ |
|
return (struct rocker_tlv *) ((char *) desc_info->data + |
|
desc_info->tlv_size); |
|
} |
|
|
|
int rocker_tlv_put(struct rocker_desc_info *desc_info, |
|
int attrtype, int attrlen, const void *data); |
|
|
|
static inline int |
|
rocker_tlv_put_u8(struct rocker_desc_info *desc_info, int attrtype, u8 value) |
|
{ |
|
u8 tmp = value; /* work around GCC PR81715 */ |
|
|
|
return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &tmp); |
|
} |
|
|
|
static inline int |
|
rocker_tlv_put_u16(struct rocker_desc_info *desc_info, int attrtype, u16 value) |
|
{ |
|
u16 tmp = value; |
|
|
|
return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &tmp); |
|
} |
|
|
|
static inline int |
|
rocker_tlv_put_be16(struct rocker_desc_info *desc_info, int attrtype, __be16 value) |
|
{ |
|
__be16 tmp = value; |
|
|
|
return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &tmp); |
|
} |
|
|
|
static inline int |
|
rocker_tlv_put_u32(struct rocker_desc_info *desc_info, int attrtype, u32 value) |
|
{ |
|
u32 tmp = value; |
|
|
|
return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &tmp); |
|
} |
|
|
|
static inline int |
|
rocker_tlv_put_be32(struct rocker_desc_info *desc_info, int attrtype, __be32 value) |
|
{ |
|
__be32 tmp = value; |
|
|
|
return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &tmp); |
|
} |
|
|
|
static inline int |
|
rocker_tlv_put_u64(struct rocker_desc_info *desc_info, int attrtype, u64 value) |
|
{ |
|
u64 tmp = value; |
|
|
|
return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &tmp); |
|
} |
|
|
|
static inline struct rocker_tlv * |
|
rocker_tlv_nest_start(struct rocker_desc_info *desc_info, int attrtype) |
|
{ |
|
struct rocker_tlv *start = rocker_tlv_start(desc_info); |
|
|
|
if (rocker_tlv_put(desc_info, attrtype, 0, NULL) < 0) |
|
return NULL; |
|
|
|
return start; |
|
} |
|
|
|
static inline void rocker_tlv_nest_end(struct rocker_desc_info *desc_info, |
|
struct rocker_tlv *start) |
|
{ |
|
start->len = (char *) rocker_tlv_start(desc_info) - (char *) start; |
|
} |
|
|
|
static inline void rocker_tlv_nest_cancel(struct rocker_desc_info *desc_info, |
|
const struct rocker_tlv *start) |
|
{ |
|
desc_info->tlv_size = (const char *) start - desc_info->data; |
|
} |
|
|
|
#endif
|
|
|