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