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