// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) Meta Platforms, Inc. and affiliates. */ #include <linux/gfp.h> #include <linux/mm.h> #include <linux/once.h> #include <linux/random.h> #include <linux/string.h> #include <uapi/linux/if_ether.h> #include "fbnic_tlv.h" /** * fbnic_tlv_msg_alloc - Allocate page and initialize FW message header * @msg_id: Identifier for new message we are starting * * Return: pointer to start of message, or NULL on failure. * * Allocates a page and initializes message header at start of page. * Initial message size is 1 DWORD which is just the header. **/ struct fbnic_tlv_msg *fbnic_tlv_msg_alloc(u16 msg_id) { … } /** * fbnic_tlv_attr_put_flag - Add flag value to message * @msg: Message header we are adding flag attribute to * @attr_id: ID of flag attribute we are adding to message * * Return: -ENOSPC if there is no room for the attribute. Otherwise 0. * * Adds a 1 DWORD flag attribute to the message. The presence of this * attribute can be used as a boolean value indicating true, otherwise the * value is considered false. **/ int fbnic_tlv_attr_put_flag(struct fbnic_tlv_msg *msg, const u16 attr_id) { … } /** * fbnic_tlv_attr_put_value - Add data to message * @msg: Message header we are adding flag attribute to * @attr_id: ID of flag attribute we are adding to message * @value: Pointer to data to be stored * @len: Size of data to be stored. * * Return: -ENOSPC if there is no room for the attribute. Otherwise 0. * * Adds header and copies data pointed to by value into the message. The * result is rounded up to the nearest DWORD for sizing so that the * headers remain aligned. * * The assumption is that the value field is in a format where byte * ordering can be guaranteed such as a byte array or a little endian * format. **/ int fbnic_tlv_attr_put_value(struct fbnic_tlv_msg *msg, const u16 attr_id, const void *value, const int len) { … } /** * __fbnic_tlv_attr_put_int - Add integer to message * @msg: Message header we are adding flag attribute to * @attr_id: ID of flag attribute we are adding to message * @value: Data to be stored * @len: Size of data to be stored, either 4 or 8 bytes. * * Return: -ENOSPC if there is no room for the attribute. Otherwise 0. * * Adds header and copies data pointed to by value into the message. Will * format the data as little endian. **/ int __fbnic_tlv_attr_put_int(struct fbnic_tlv_msg *msg, const u16 attr_id, s64 value, const int len) { … } /** * fbnic_tlv_attr_put_mac_addr - Add mac_addr to message * @msg: Message header we are adding flag attribute to * @attr_id: ID of flag attribute we are adding to message * @mac_addr: Byte pointer to MAC address to be stored * * Return: -ENOSPC if there is no room for the attribute. Otherwise 0. * * Adds header and copies data pointed to by mac_addr into the message. Will * copy the address raw so it will be in big endian with start of MAC * address at start of attribute. **/ int fbnic_tlv_attr_put_mac_addr(struct fbnic_tlv_msg *msg, const u16 attr_id, const u8 *mac_addr) { … } /** * fbnic_tlv_attr_put_string - Add string to message * @msg: Message header we are adding flag attribute to * @attr_id: ID of flag attribute we are adding to message * @string: Byte pointer to null terminated string to be stored * * Return: -ENOSPC if there is no room for the attribute. Otherwise 0. * * Adds header and copies data pointed to by string into the message. Will * copy the address raw so it will be in byte order. **/ int fbnic_tlv_attr_put_string(struct fbnic_tlv_msg *msg, u16 attr_id, const char *string) { … } /** * fbnic_tlv_attr_get_unsigned - Retrieve unsigned value from result * @attr: Attribute to retrieve data from * * Return: unsigned 64b value containing integer value **/ u64 fbnic_tlv_attr_get_unsigned(struct fbnic_tlv_msg *attr) { … } /** * fbnic_tlv_attr_get_signed - Retrieve signed value from result * @attr: Attribute to retrieve data from * * Return: signed 64b value containing integer value **/ s64 fbnic_tlv_attr_get_signed(struct fbnic_tlv_msg *attr) { … } /** * fbnic_tlv_attr_get_string - Retrieve string value from result * @attr: Attribute to retrieve data from * @str: Pointer to an allocated string to store the data * @max_size: The maximum size which can be in str * * Return: the size of the string read from firmware **/ size_t fbnic_tlv_attr_get_string(struct fbnic_tlv_msg *attr, char *str, size_t max_size) { … } /** * fbnic_tlv_attr_nest_start - Add nested attribute header to message * @msg: Message header we are adding flag attribute to * @attr_id: ID of flag attribute we are adding to message * * Return: NULL if there is no room for the attribute. Otherwise a pointer * to the new attribute header. * * New header length is stored initially in DWORDs. **/ struct fbnic_tlv_msg *fbnic_tlv_attr_nest_start(struct fbnic_tlv_msg *msg, u16 attr_id) { … } /** * fbnic_tlv_attr_nest_stop - Close out nested attribute and add it to message * @msg: Message header we are adding flag attribute to * * Closes out nested attribute, adds length to message, and then bumps * length from DWORDs to bytes to match other attributes. **/ void fbnic_tlv_attr_nest_stop(struct fbnic_tlv_msg *msg) { … } static int fbnic_tlv_attr_validate(struct fbnic_tlv_msg *attr, const struct fbnic_tlv_index *tlv_index) { … } /** * fbnic_tlv_attr_parse_array - Parse array of attributes into results array * @attr: Start of attributes in the message * @len: Length of attributes in the message * @results: Array of pointers to store the results of parsing * @tlv_index: List of TLV attributes to be parsed from message * @tlv_attr_id: Specific ID that is repeated in array * @array_len: Number of results to store in results array * * Return: zero on success, or negative value on error. * * Will take a list of attributes and a parser definition and will capture * the results in the results array to have the data extracted later. **/ int fbnic_tlv_attr_parse_array(struct fbnic_tlv_msg *attr, int len, struct fbnic_tlv_msg **results, const struct fbnic_tlv_index *tlv_index, u16 tlv_attr_id, size_t array_len) { … } /** * fbnic_tlv_attr_parse - Parse attributes into a list of attribute results * @attr: Start of attributes in the message * @len: Length of attributes in the message * @results: Array of pointers to store the results of parsing * @tlv_index: List of TLV attributes to be parsed from message * * Return: zero on success, or negative value on error. * * Will take a list of attributes and a parser definition and will capture * the results in the results array to have the data extracted later. **/ int fbnic_tlv_attr_parse(struct fbnic_tlv_msg *attr, int len, struct fbnic_tlv_msg **results, const struct fbnic_tlv_index *tlv_index) { … } /** * fbnic_tlv_msg_parse - Parse message and process via predetermined functions * @opaque: Value passed to parser function to enable driver access * @msg: Message to be parsed. * @parser: TLV message parser definition. * * Return: zero on success, or negative value on error. * * Will take a message a number of message types via the attribute parsing * definitions and function provided for the parser array. **/ int fbnic_tlv_msg_parse(void *opaque, struct fbnic_tlv_msg *msg, const struct fbnic_tlv_parser *parser) { … } /** * fbnic_tlv_parser_error - called if message doesn't match known type * @opaque: (unused) * @results: (unused) * * Return: -EBADMSG to indicate the message is an unsupported type **/ int fbnic_tlv_parser_error(void *opaque, struct fbnic_tlv_msg **results) { … } void fbnic_tlv_attr_addr_copy(u8 *dest, struct fbnic_tlv_msg *src) { … }