1*2874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 2de152192SJiri Pirko /* 3de152192SJiri Pirko * drivers/net/ethernet/rocker/rocker_tlv.h - Rocker switch device driver 4de152192SJiri Pirko * Copyright (c) 2014-2016 Jiri Pirko <jiri@mellanox.com> 5de152192SJiri Pirko * Copyright (c) 2014 Scott Feldman <sfeldma@gmail.com> 6de152192SJiri Pirko */ 7de152192SJiri Pirko 8de152192SJiri Pirko #ifndef _ROCKER_TLV_H 9de152192SJiri Pirko #define _ROCKER_TLV_H 10de152192SJiri Pirko 11de152192SJiri Pirko #include <linux/types.h> 12de152192SJiri Pirko 13de152192SJiri Pirko #include "rocker_hw.h" 14de152192SJiri Pirko #include "rocker.h" 15de152192SJiri Pirko 16de152192SJiri Pirko #define ROCKER_TLV_ALIGNTO 8U 17de152192SJiri Pirko #define ROCKER_TLV_ALIGN(len) \ 18de152192SJiri Pirko (((len) + ROCKER_TLV_ALIGNTO - 1) & ~(ROCKER_TLV_ALIGNTO - 1)) 19de152192SJiri Pirko #define ROCKER_TLV_HDRLEN ROCKER_TLV_ALIGN(sizeof(struct rocker_tlv)) 20de152192SJiri Pirko 21de152192SJiri Pirko /* <------- ROCKER_TLV_HDRLEN -------> <--- ROCKER_TLV_ALIGN(payload) ---> 22de152192SJiri Pirko * +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+ 23de152192SJiri Pirko * | Header | Pad | Payload | Pad | 24de152192SJiri Pirko * | (struct rocker_tlv) | ing | | ing | 25de152192SJiri Pirko * +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+ 26de152192SJiri Pirko * <--------------------------- tlv->len --------------------------> 27de152192SJiri Pirko */ 28de152192SJiri Pirko 29de152192SJiri Pirko static inline struct rocker_tlv *rocker_tlv_next(const struct rocker_tlv *tlv, 30de152192SJiri Pirko int *remaining) 31de152192SJiri Pirko { 32de152192SJiri Pirko int totlen = ROCKER_TLV_ALIGN(tlv->len); 33de152192SJiri Pirko 34de152192SJiri Pirko *remaining -= totlen; 35de152192SJiri Pirko return (struct rocker_tlv *) ((char *) tlv + totlen); 36de152192SJiri Pirko } 37de152192SJiri Pirko 38de152192SJiri Pirko static inline int rocker_tlv_ok(const struct rocker_tlv *tlv, int remaining) 39de152192SJiri Pirko { 40de152192SJiri Pirko return remaining >= (int) ROCKER_TLV_HDRLEN && 41de152192SJiri Pirko tlv->len >= ROCKER_TLV_HDRLEN && 42de152192SJiri Pirko tlv->len <= remaining; 43de152192SJiri Pirko } 44de152192SJiri Pirko 45de152192SJiri Pirko #define rocker_tlv_for_each(pos, head, len, rem) \ 46de152192SJiri Pirko for (pos = head, rem = len; \ 47de152192SJiri Pirko rocker_tlv_ok(pos, rem); \ 48de152192SJiri Pirko pos = rocker_tlv_next(pos, &(rem))) 49de152192SJiri Pirko 50de152192SJiri Pirko #define rocker_tlv_for_each_nested(pos, tlv, rem) \ 51de152192SJiri Pirko rocker_tlv_for_each(pos, rocker_tlv_data(tlv), \ 52de152192SJiri Pirko rocker_tlv_len(tlv), rem) 53de152192SJiri Pirko 54de152192SJiri Pirko static inline int rocker_tlv_attr_size(int payload) 55de152192SJiri Pirko { 56de152192SJiri Pirko return ROCKER_TLV_HDRLEN + payload; 57de152192SJiri Pirko } 58de152192SJiri Pirko 59de152192SJiri Pirko static inline int rocker_tlv_total_size(int payload) 60de152192SJiri Pirko { 61de152192SJiri Pirko return ROCKER_TLV_ALIGN(rocker_tlv_attr_size(payload)); 62de152192SJiri Pirko } 63de152192SJiri Pirko 64de152192SJiri Pirko static inline int rocker_tlv_padlen(int payload) 65de152192SJiri Pirko { 66de152192SJiri Pirko return rocker_tlv_total_size(payload) - rocker_tlv_attr_size(payload); 67de152192SJiri Pirko } 68de152192SJiri Pirko 69de152192SJiri Pirko static inline int rocker_tlv_type(const struct rocker_tlv *tlv) 70de152192SJiri Pirko { 71de152192SJiri Pirko return tlv->type; 72de152192SJiri Pirko } 73de152192SJiri Pirko 74de152192SJiri Pirko static inline void *rocker_tlv_data(const struct rocker_tlv *tlv) 75de152192SJiri Pirko { 76de152192SJiri Pirko return (char *) tlv + ROCKER_TLV_HDRLEN; 77de152192SJiri Pirko } 78de152192SJiri Pirko 79de152192SJiri Pirko static inline int rocker_tlv_len(const struct rocker_tlv *tlv) 80de152192SJiri Pirko { 81de152192SJiri Pirko return tlv->len - ROCKER_TLV_HDRLEN; 82de152192SJiri Pirko } 83de152192SJiri Pirko 84de152192SJiri Pirko static inline u8 rocker_tlv_get_u8(const struct rocker_tlv *tlv) 85de152192SJiri Pirko { 86de152192SJiri Pirko return *(u8 *) rocker_tlv_data(tlv); 87de152192SJiri Pirko } 88de152192SJiri Pirko 89de152192SJiri Pirko static inline u16 rocker_tlv_get_u16(const struct rocker_tlv *tlv) 90de152192SJiri Pirko { 91de152192SJiri Pirko return *(u16 *) rocker_tlv_data(tlv); 92de152192SJiri Pirko } 93de152192SJiri Pirko 94de152192SJiri Pirko static inline __be16 rocker_tlv_get_be16(const struct rocker_tlv *tlv) 95de152192SJiri Pirko { 96de152192SJiri Pirko return *(__be16 *) rocker_tlv_data(tlv); 97de152192SJiri Pirko } 98de152192SJiri Pirko 99de152192SJiri Pirko static inline u32 rocker_tlv_get_u32(const struct rocker_tlv *tlv) 100de152192SJiri Pirko { 101de152192SJiri Pirko return *(u32 *) rocker_tlv_data(tlv); 102de152192SJiri Pirko } 103de152192SJiri Pirko 104de152192SJiri Pirko static inline u64 rocker_tlv_get_u64(const struct rocker_tlv *tlv) 105de152192SJiri Pirko { 106de152192SJiri Pirko return *(u64 *) rocker_tlv_data(tlv); 107de152192SJiri Pirko } 108de152192SJiri Pirko 109de152192SJiri Pirko void rocker_tlv_parse(const struct rocker_tlv **tb, int maxtype, 110de152192SJiri Pirko const char *buf, int buf_len); 111de152192SJiri Pirko 112de152192SJiri Pirko static inline void rocker_tlv_parse_nested(const struct rocker_tlv **tb, 113de152192SJiri Pirko int maxtype, 114de152192SJiri Pirko const struct rocker_tlv *tlv) 115de152192SJiri Pirko { 116de152192SJiri Pirko rocker_tlv_parse(tb, maxtype, rocker_tlv_data(tlv), 117de152192SJiri Pirko rocker_tlv_len(tlv)); 118de152192SJiri Pirko } 119de152192SJiri Pirko 120de152192SJiri Pirko static inline void 121de152192SJiri Pirko rocker_tlv_parse_desc(const struct rocker_tlv **tb, int maxtype, 122de152192SJiri Pirko const struct rocker_desc_info *desc_info) 123de152192SJiri Pirko { 124de152192SJiri Pirko rocker_tlv_parse(tb, maxtype, desc_info->data, 125de152192SJiri Pirko desc_info->desc->tlv_size); 126de152192SJiri Pirko } 127de152192SJiri Pirko 128de152192SJiri Pirko static inline struct rocker_tlv * 129de152192SJiri Pirko rocker_tlv_start(struct rocker_desc_info *desc_info) 130de152192SJiri Pirko { 131de152192SJiri Pirko return (struct rocker_tlv *) ((char *) desc_info->data + 132de152192SJiri Pirko desc_info->tlv_size); 133de152192SJiri Pirko } 134de152192SJiri Pirko 135de152192SJiri Pirko int rocker_tlv_put(struct rocker_desc_info *desc_info, 136de152192SJiri Pirko int attrtype, int attrlen, const void *data); 137de152192SJiri Pirko 1386098d7ddSArnd Bergmann static inline int 1396098d7ddSArnd Bergmann rocker_tlv_put_u8(struct rocker_desc_info *desc_info, int attrtype, u8 value) 140de152192SJiri Pirko { 1416098d7ddSArnd Bergmann u8 tmp = value; /* work around GCC PR81715 */ 1426098d7ddSArnd Bergmann 1436098d7ddSArnd Bergmann return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &tmp); 144de152192SJiri Pirko } 145de152192SJiri Pirko 1466098d7ddSArnd Bergmann static inline int 1476098d7ddSArnd Bergmann rocker_tlv_put_u16(struct rocker_desc_info *desc_info, int attrtype, u16 value) 148de152192SJiri Pirko { 1496098d7ddSArnd Bergmann u16 tmp = value; 1506098d7ddSArnd Bergmann 1516098d7ddSArnd Bergmann return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &tmp); 152de152192SJiri Pirko } 153de152192SJiri Pirko 1546098d7ddSArnd Bergmann static inline int 1556098d7ddSArnd Bergmann rocker_tlv_put_be16(struct rocker_desc_info *desc_info, int attrtype, __be16 value) 156de152192SJiri Pirko { 1576098d7ddSArnd Bergmann __be16 tmp = value; 1586098d7ddSArnd Bergmann 1596098d7ddSArnd Bergmann return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &tmp); 160de152192SJiri Pirko } 161de152192SJiri Pirko 1626098d7ddSArnd Bergmann static inline int 1636098d7ddSArnd Bergmann rocker_tlv_put_u32(struct rocker_desc_info *desc_info, int attrtype, u32 value) 164de152192SJiri Pirko { 1656098d7ddSArnd Bergmann u32 tmp = value; 1666098d7ddSArnd Bergmann 1676098d7ddSArnd Bergmann return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &tmp); 168de152192SJiri Pirko } 169de152192SJiri Pirko 1706098d7ddSArnd Bergmann static inline int 1716098d7ddSArnd Bergmann rocker_tlv_put_be32(struct rocker_desc_info *desc_info, int attrtype, __be32 value) 172de152192SJiri Pirko { 1736098d7ddSArnd Bergmann __be32 tmp = value; 1746098d7ddSArnd Bergmann 1756098d7ddSArnd Bergmann return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &tmp); 176de152192SJiri Pirko } 177de152192SJiri Pirko 1786098d7ddSArnd Bergmann static inline int 1796098d7ddSArnd Bergmann rocker_tlv_put_u64(struct rocker_desc_info *desc_info, int attrtype, u64 value) 180de152192SJiri Pirko { 1816098d7ddSArnd Bergmann u64 tmp = value; 1826098d7ddSArnd Bergmann 1836098d7ddSArnd Bergmann return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &tmp); 184de152192SJiri Pirko } 185de152192SJiri Pirko 186de152192SJiri Pirko static inline struct rocker_tlv * 187de152192SJiri Pirko rocker_tlv_nest_start(struct rocker_desc_info *desc_info, int attrtype) 188de152192SJiri Pirko { 189de152192SJiri Pirko struct rocker_tlv *start = rocker_tlv_start(desc_info); 190de152192SJiri Pirko 191de152192SJiri Pirko if (rocker_tlv_put(desc_info, attrtype, 0, NULL) < 0) 192de152192SJiri Pirko return NULL; 193de152192SJiri Pirko 194de152192SJiri Pirko return start; 195de152192SJiri Pirko } 196de152192SJiri Pirko 197de152192SJiri Pirko static inline void rocker_tlv_nest_end(struct rocker_desc_info *desc_info, 198de152192SJiri Pirko struct rocker_tlv *start) 199de152192SJiri Pirko { 200de152192SJiri Pirko start->len = (char *) rocker_tlv_start(desc_info) - (char *) start; 201de152192SJiri Pirko } 202de152192SJiri Pirko 203de152192SJiri Pirko static inline void rocker_tlv_nest_cancel(struct rocker_desc_info *desc_info, 204de152192SJiri Pirko const struct rocker_tlv *start) 205de152192SJiri Pirko { 206de152192SJiri Pirko desc_info->tlv_size = (const char *) start - desc_info->data; 207de152192SJiri Pirko } 208de152192SJiri Pirko 209de152192SJiri Pirko #endif 210