xref: /linux/drivers/net/ethernet/meta/fbnic/fbnic_tlv.h (revision 91a4855d6c03e770e42f17c798a36a3c46e63de2)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (c) Meta Platforms, Inc. and affiliates. */
3 
4 #ifndef _FBNIC_TLV_H_
5 #define _FBNIC_TLV_H_
6 
7 #include <asm/byteorder.h>
8 #include <linux/bits.h>
9 #include <linux/const.h>
10 #include <linux/types.h>
11 
12 struct fbnic_dev;
13 
14 #define FBNIC_TLV_MSG_ALIGN(len)	ALIGN(len, sizeof(u32))
15 #define FBNIC_TLV_MSG_SIZE(len)		\
16 		(FBNIC_TLV_MSG_ALIGN(len) / sizeof(u32))
17 
18 /* TLV Header Format
19  *    3			  2		      1
20  *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
21  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22  * |		Length		   |M|I|RSV|	   Type / ID	   |
23  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24  *
25  * The TLV header format described above will be used for transferring
26  * messages between the host and the firmware. To ensure byte ordering
27  * we have defined all fields as being little endian.
28  * Type/ID: Identifier for message and/or attribute
29  * RSV: Reserved field for future use, likely as additional flags
30  * I: cannot_ignore flag, identifies if unrecognized attribute can be ignored
31  * M: is_msg, indicates that this is the start of a new message
32  * Length: Total length of message in dwords including header
33  *		or
34  *	   Total length of attribute in bytes including header
35  */
36 struct fbnic_tlv_hdr {
37 #if defined(__LITTLE_ENDIAN_BITFIELD)
38 	u16 type		: 12; /* 0 .. 11  Type / ID */
39 	u16 rsvd		: 2;  /* 12 .. 13 Reserved for future use */
40 	u16 cannot_ignore	: 1;  /* 14	  Attribute can be ignored */
41 	u16 is_msg		: 1;  /* 15	  Header belongs to message */
42 #elif defined(__BIG_ENDIAN_BITFIELD)
43 	u16 is_msg		: 1;  /* 15	  Header belongs to message */
44 	u16 cannot_ignore	: 1;  /* 14	  Attribute can be ignored */
45 	u16 rsvd		: 2;  /* 13 .. 12 Reserved for future use */
46 	u16 type		: 12; /* 11 .. 0  Type / ID */
47 #else
48 #error "Missing defines from byteorder.h"
49 #endif
50 	__le16 len;		/* 16 .. 32	length including TLV header */
51 };
52 
53 #define FBNIC_TLV_RESULTS_MAX		32
54 
55 struct fbnic_tlv_msg {
56 	struct fbnic_tlv_hdr	hdr;
57 	__le32			value[];
58 };
59 
60 #define FBNIC_TLV_MSG_ID_UNKNOWN		USHRT_MAX
61 
62 enum fbnic_tlv_type {
63 	FBNIC_TLV_STRING,
64 	FBNIC_TLV_FLAG,
65 	FBNIC_TLV_UNSIGNED,
66 	FBNIC_TLV_SIGNED,
67 	FBNIC_TLV_BINARY,
68 	FBNIC_TLV_NESTED,
69 	FBNIC_TLV_ARRAY,
70 	__FBNIC_TLV_MAX_TYPE
71 };
72 
73 /* TLV Index
74  * Defines the relationship between the attribute IDs and their types.
75  * For each entry in the index there will be a size and type associated
76  * with it so that we can use this to parse the data and verify it matches
77  * the expected layout.
78  */
79 struct fbnic_tlv_index {
80 	u16			id;
81 	u16			len;
82 	enum fbnic_tlv_type	type;
83 };
84 
85 #define TLV_MAX_DATA			((PAGE_SIZE - 512) & 0xFFFF)
86 #define FBNIC_TLV_ATTR_ID_UNKNOWN	USHRT_MAX
87 #define FBNIC_TLV_ATTR_STRING(id, len)	{ id, len, FBNIC_TLV_STRING }
88 #define FBNIC_TLV_ATTR_FLAG(id)		{ id, 0, FBNIC_TLV_FLAG }
89 #define FBNIC_TLV_ATTR_U32(id)		{ id, sizeof(u32), FBNIC_TLV_UNSIGNED }
90 #define FBNIC_TLV_ATTR_U64(id)		{ id, sizeof(u64), FBNIC_TLV_UNSIGNED }
91 #define FBNIC_TLV_ATTR_S32(id)		{ id, sizeof(s32), FBNIC_TLV_SIGNED }
92 #define FBNIC_TLV_ATTR_S64(id)		{ id, sizeof(s64), FBNIC_TLV_SIGNED }
93 #define FBNIC_TLV_ATTR_MAC_ADDR(id)	{ id, ETH_ALEN, FBNIC_TLV_BINARY }
94 #define FBNIC_TLV_ATTR_NESTED(id)	{ id, 0, FBNIC_TLV_NESTED }
95 #define FBNIC_TLV_ATTR_ARRAY(id)	{ id, 0, FBNIC_TLV_ARRAY }
96 #define FBNIC_TLV_ATTR_RAW_DATA(id)	{ id, TLV_MAX_DATA, FBNIC_TLV_BINARY }
97 #define FBNIC_TLV_ATTR_LAST		{ FBNIC_TLV_ATTR_ID_UNKNOWN, 0, 0 }
98 
99 struct fbnic_tlv_parser {
100 	u16				id;
101 	const struct fbnic_tlv_index	*attr;
102 	int				(*func)(void *opaque,
103 						struct fbnic_tlv_msg **results);
104 };
105 
106 #define FBNIC_TLV_PARSER(id, attr, func) { FBNIC_TLV_MSG_ID_##id, attr, func }
107 
108 static inline void *
109 fbnic_tlv_attr_get_value_ptr(struct fbnic_tlv_msg *attr)
110 {
111 	return (void *)&attr->value[0];
112 }
113 
114 static inline bool fbnic_tlv_attr_get_bool(struct fbnic_tlv_msg *attr)
115 {
116 	return !!attr;
117 }
118 
119 u64 fbnic_tlv_attr_get_unsigned(struct fbnic_tlv_msg *attr, u64 def);
120 s64 fbnic_tlv_attr_get_signed(struct fbnic_tlv_msg *attr, s64 def);
121 ssize_t fbnic_tlv_attr_get_string(struct fbnic_tlv_msg *attr, char *dst,
122 				  size_t dstsize);
123 struct fbnic_tlv_msg *fbnic_tlv_msg_alloc(u16 msg_id);
124 int fbnic_tlv_attr_put_flag(struct fbnic_tlv_msg *msg, const u16 attr_id);
125 int fbnic_tlv_attr_put_value(struct fbnic_tlv_msg *msg, const u16 attr_id,
126 			     const void *value, const int len);
127 int __fbnic_tlv_attr_put_int(struct fbnic_tlv_msg *msg, const u16 attr_id,
128 			     s64 value, const int len);
129 #define fbnic_tlv_attr_put_int(msg, attr_id, value) \
130 	__fbnic_tlv_attr_put_int(msg, attr_id, value, \
131 				 FBNIC_TLV_MSG_ALIGN(sizeof(value)))
132 int fbnic_tlv_attr_put_mac_addr(struct fbnic_tlv_msg *msg, const u16 attr_id,
133 				const u8 *mac_addr);
134 int fbnic_tlv_attr_put_string(struct fbnic_tlv_msg *msg, u16 attr_id,
135 			      const char *string);
136 struct fbnic_tlv_msg *fbnic_tlv_attr_nest_start(struct fbnic_tlv_msg *msg,
137 						u16 attr_id);
138 void fbnic_tlv_attr_nest_stop(struct fbnic_tlv_msg *msg);
139 void fbnic_tlv_attr_addr_copy(u8 *dest, struct fbnic_tlv_msg *src);
140 int fbnic_tlv_attr_parse_array(struct fbnic_tlv_msg *attr, int len,
141 			       struct fbnic_tlv_msg **results,
142 			       const struct fbnic_tlv_index *tlv_index,
143 			       u16 tlv_attr_id, size_t array_len);
144 int fbnic_tlv_attr_parse(struct fbnic_tlv_msg *attr, int len,
145 			 struct fbnic_tlv_msg **results,
146 			 const struct fbnic_tlv_index *tlv_index);
147 int fbnic_tlv_msg_parse(void *opaque, struct fbnic_tlv_msg *msg,
148 			const struct fbnic_tlv_parser *parser);
149 int fbnic_tlv_parser_error(void *opaque, struct fbnic_tlv_msg **results);
150 
151 #define fta_get_uint(_results, _id) \
152 	fbnic_tlv_attr_get_unsigned(_results[_id], 0)
153 #define fta_get_sint(_results, _id) \
154 	fbnic_tlv_attr_get_signed(_results[_id], 0)
155 #define fta_get_str(_results, _id, _dst, _dstsize) \
156 	fbnic_tlv_attr_get_string(_results[_id], _dst, _dstsize)
157 
158 #define FBNIC_TLV_MSG_ID_TEST	0
159 
160 enum fbnic_tlv_test_attr_id {
161 	FBNIC_TLV_TEST_MSG_U64,
162 	FBNIC_TLV_TEST_MSG_S64,
163 	FBNIC_TLV_TEST_MSG_U32,
164 	FBNIC_TLV_TEST_MSG_S32,
165 	FBNIC_TLV_TEST_MSG_U16,
166 	FBNIC_TLV_TEST_MSG_S16,
167 	FBNIC_TLV_TEST_MSG_MAC_ADDR,
168 	FBNIC_TLV_TEST_MSG_FLAG_TRUE,
169 	FBNIC_TLV_TEST_MSG_FLAG_FALSE,
170 	FBNIC_TLV_TEST_MSG_STRING,
171 	FBNIC_TLV_TEST_MSG_NESTED,
172 	FBNIC_TLV_TEST_MSG_ARRAY,
173 	FBNIC_TLV_TEST_MSG_MAX
174 };
175 
176 extern const struct fbnic_tlv_index fbnic_tlv_test_index[];
177 struct fbnic_tlv_msg *fbnic_tlv_test_create(struct fbnic_dev *fbd);
178 int fbnic_tlv_parser_test(void *opaque, struct fbnic_tlv_msg **results);
179 
180 #define FBNIC_TLV_MSG_TEST \
181 	FBNIC_TLV_PARSER(TEST, fbnic_tlv_test_index, \
182 			 fbnic_tlv_parser_test)
183 #define FBNIC_TLV_MSG_ERROR \
184 	FBNIC_TLV_PARSER(UNKNOWN, NULL, fbnic_tlv_parser_error)
185 #endif /* _FBNIC_TLV_H_ */
186