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