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