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 * 107 fbnic_tlv_attr_get_value_ptr(struct fbnic_tlv_msg *attr) 108 { 109 return (void *)&attr->value[0]; 110 } 111 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