// SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2013 - 2018 Intel Corporation. */ /* ethtool support for i40e */ #include "i40e_devids.h" #include "i40e_diag.h" #include "i40e_txrx_common.h" #include "i40e_virtchnl_pf.h" /* ethtool statistics helpers */ /** * struct i40e_stats - definition for an ethtool statistic * @stat_string: statistic name to display in ethtool -S output * @sizeof_stat: the sizeof() the stat, must be no greater than sizeof(u64) * @stat_offset: offsetof() the stat from a base pointer * * This structure defines a statistic to be added to the ethtool stats buffer. * It defines a statistic as offset from a common base pointer. Stats should * be defined in constant arrays using the I40E_STAT macro, with every element * of the array using the same _type for calculating the sizeof_stat and * stat_offset. * * The @sizeof_stat is expected to be sizeof(u8), sizeof(u16), sizeof(u32) or * sizeof(u64). Other sizes are not expected and will produce a WARN_ONCE from * the i40e_add_ethtool_stat() helper function. * * The @stat_string is interpreted as a format string, allowing formatted * values to be inserted while looping over multiple structures for a given * statistics array. Thus, every statistic string in an array should have the * same type and number of format specifiers, to be formatted by variadic * arguments to the i40e_add_stat_string() helper function. **/ struct i40e_stats { … }; /* Helper macro to define an i40e_stat structure with proper size and type. * Use this when defining constant statistics arrays. Note that @_type expects * only a type name and is used multiple times. */ #define I40E_STAT(_type, _name, _stat) … /* Helper macro for defining some statistics directly copied from the netdev * stats structure. */ #define I40E_NETDEV_STAT(_net_stat) … /* Helper macro for defining some statistics related to queues */ #define I40E_QUEUE_STAT(_name, _stat) … /* Stats associated with a Tx or Rx ring */ static const struct i40e_stats i40e_gstrings_queue_stats[] = …; /** * i40e_add_one_ethtool_stat - copy the stat into the supplied buffer * @data: location to store the stat value * @pointer: basis for where to copy from * @stat: the stat definition * * Copies the stat data defined by the pointer and stat structure pair into * the memory supplied as data. Used to implement i40e_add_ethtool_stats and * i40e_add_queue_stats. If the pointer is null, data will be zero'd. */ static void i40e_add_one_ethtool_stat(u64 *data, void *pointer, const struct i40e_stats *stat) { … } /** * __i40e_add_ethtool_stats - copy stats into the ethtool supplied buffer * @data: ethtool stats buffer * @pointer: location to copy stats from * @stats: array of stats to copy * @size: the size of the stats definition * * Copy the stats defined by the stats array using the pointer as a base into * the data buffer supplied by ethtool. Updates the data pointer to point to * the next empty location for successive calls to __i40e_add_ethtool_stats. * If pointer is null, set the data values to zero and update the pointer to * skip these stats. **/ static void __i40e_add_ethtool_stats(u64 **data, void *pointer, const struct i40e_stats stats[], const unsigned int size) { … } /** * i40e_add_ethtool_stats - copy stats into ethtool supplied buffer * @data: ethtool stats buffer * @pointer: location where stats are stored * @stats: static const array of stat definitions * * Macro to ease the use of __i40e_add_ethtool_stats by taking a static * constant stats array and passing the ARRAY_SIZE(). This avoids typos by * ensuring that we pass the size associated with the given stats array. * * The parameter @stats is evaluated twice, so parameters with side effects * should be avoided. **/ #define i40e_add_ethtool_stats(data, pointer, stats) … /** * i40e_add_queue_stats - copy queue statistics into supplied buffer * @data: ethtool stats buffer * @ring: the ring to copy * * Queue statistics must be copied while protected by * u64_stats_fetch_begin, so we can't directly use i40e_add_ethtool_stats. * Assumes that queue stats are defined in i40e_gstrings_queue_stats. If the * ring pointer is null, zero out the queue stat values and update the data * pointer. Otherwise safely copy the stats from the ring into the supplied * buffer and update the data pointer when finished. * * This function expects to be called while under rcu_read_lock(). **/ static void i40e_add_queue_stats(u64 **data, struct i40e_ring *ring) { … } /** * __i40e_add_stat_strings - copy stat strings into ethtool buffer * @p: ethtool supplied buffer * @stats: stat definitions array * @size: size of the stats array * * Format and copy the strings described by stats into the buffer pointed at * by p. **/ static void __i40e_add_stat_strings(u8 **p, const struct i40e_stats stats[], const unsigned int size, ...) { … } /** * i40e_add_stat_strings - copy stat strings into ethtool buffer * @p: ethtool supplied buffer * @stats: stat definitions array * * Format and copy the strings described by the const static stats value into * the buffer pointed at by p. * * The parameter @stats is evaluated twice, so parameters with side effects * should be avoided. Additionally, stats must be an array such that * ARRAY_SIZE can be called on it. **/ #define i40e_add_stat_strings(p, stats, ...) … #define I40E_PF_STAT(_name, _stat) … #define I40E_VSI_STAT(_name, _stat) … #define I40E_VEB_STAT(_name, _stat) … #define I40E_VEB_TC_STAT(_name, _stat) … #define I40E_PFC_STAT(_name, _stat) … static const struct i40e_stats i40e_gstrings_net_stats[] = …; static const struct i40e_stats i40e_gstrings_veb_stats[] = …; struct i40e_cp_veb_tc_stats { … }; static const struct i40e_stats i40e_gstrings_veb_tc_stats[] = …; static const struct i40e_stats i40e_gstrings_misc_stats[] = …; /* These PF_STATs might look like duplicates of some NETDEV_STATs, * but they are separate. This device supports Virtualization, and * as such might have several netdevs supporting VMDq and FCoE going * through a single port. The NETDEV_STATs are for individual netdevs * seen at the top of the stack, and the PF_STATs are for the physical * function at the bottom of the stack hosting those netdevs. * * The PF_STATs are appended to the netdev stats only when ethtool -S * is queried on the base PF netdev, not on the VMDq or FCoE netdev. */ static const struct i40e_stats i40e_gstrings_stats[] = …; struct i40e_pfc_stats { … }; static const struct i40e_stats i40e_gstrings_pfc_stats[] = …; #define I40E_NETDEV_STATS_LEN … #define I40E_MISC_STATS_LEN … #define I40E_VSI_STATS_LEN … #define I40E_PFC_STATS_LEN … #define I40E_VEB_STATS_LEN … #define I40E_GLOBAL_STATS_LEN … #define I40E_PF_STATS_LEN … /* Length of stats for a single queue */ #define I40E_QUEUE_STATS_LEN … enum i40e_ethtool_test_id { … }; static const char i40e_gstrings_test[][ETH_GSTRING_LEN] = …; #define I40E_TEST_LEN … struct i40e_priv_flags { … }; #define I40E_PRIV_FLAG(_name, _bitno, _read_only) … static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = …; #define I40E_PRIV_FLAGS_STR_LEN … /* Private flags with a global effect, restricted to PF 0 */ static const struct i40e_priv_flags i40e_gl_gstrings_priv_flags[] = …; #define I40E_GL_PRIV_FLAGS_STR_LEN … /** * i40e_partition_setting_complaint - generic complaint for MFP restriction * @pf: the PF struct **/ static void i40e_partition_setting_complaint(struct i40e_pf *pf) { … } /** * i40e_phy_type_to_ethtool - convert the phy_types to ethtool link modes * @pf: PF struct with phy_types * @ks: ethtool link ksettings struct to fill out * **/ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, struct ethtool_link_ksettings *ks) { … } /** * i40e_get_settings_link_up_fec - Get the FEC mode encoding from mask * @req_fec_info: mask request FEC info * @ks: ethtool ksettings to fill in **/ static void i40e_get_settings_link_up_fec(u8 req_fec_info, struct ethtool_link_ksettings *ks) { … } /** * i40e_get_settings_link_up - Get the Link settings for when link is up * @hw: hw structure * @ks: ethtool ksettings to fill in * @netdev: network interface device structure * @pf: pointer to physical function struct **/ static void i40e_get_settings_link_up(struct i40e_hw *hw, struct ethtool_link_ksettings *ks, struct net_device *netdev, struct i40e_pf *pf) { … } /** * i40e_get_settings_link_down - Get the Link settings for when link is down * @hw: hw structure * @ks: ethtool ksettings to fill in * @pf: pointer to physical function struct * * Reports link settings that can be determined when link is down **/ static void i40e_get_settings_link_down(struct i40e_hw *hw, struct ethtool_link_ksettings *ks, struct i40e_pf *pf) { … } /** * i40e_get_link_ksettings - Get Link Speed and Duplex settings * @netdev: network interface device structure * @ks: ethtool ksettings * * Reports speed/duplex settings based on media_type **/ static int i40e_get_link_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *ks) { … } #define I40E_LBIT_SIZE … /** * i40e_speed_to_link_speed - Translate decimal speed to i40e_aq_link_speed * @speed: speed in decimal * @ks: ethtool ksettings * * Return i40e_aq_link_speed based on speed **/ static enum i40e_aq_link_speed i40e_speed_to_link_speed(__u32 speed, const struct ethtool_link_ksettings *ks) { … } #undef I40E_LBIT_SIZE /** * i40e_set_link_ksettings - Set Speed and Duplex * @netdev: network interface device structure * @ks: ethtool ksettings * * Set speed/duplex per media_types advertised/forced **/ static int i40e_set_link_ksettings(struct net_device *netdev, const struct ethtool_link_ksettings *ks) { … } static int i40e_set_fec_cfg(struct net_device *netdev, u8 fec_cfg) { … } static int i40e_get_fec_param(struct net_device *netdev, struct ethtool_fecparam *fecparam) { … } static int i40e_set_fec_param(struct net_device *netdev, struct ethtool_fecparam *fecparam) { … } static int i40e_nway_reset(struct net_device *netdev) { … } /** * i40e_get_pauseparam - Get Flow Control status * @netdev: netdevice structure * @pause: buffer to return pause parameters * * Return tx/rx-pause status **/ static void i40e_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { … } /** * i40e_set_pauseparam - Set Flow Control parameter * @netdev: network interface device structure * @pause: return tx/rx flow control status **/ static int i40e_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) { … } static u32 i40e_get_msglevel(struct net_device *netdev) { … } static void i40e_set_msglevel(struct net_device *netdev, u32 data) { … } static int i40e_get_regs_len(struct net_device *netdev) { … } static void i40e_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) { … } static int i40e_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) { … } static int i40e_get_eeprom_len(struct net_device *netdev) { … } static int i40e_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) { … } static void i40e_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { … } static u32 i40e_get_max_num_descriptors(struct i40e_pf *pf) { … } static void i40e_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring, struct kernel_ethtool_ringparam *kernel_ring, struct netlink_ext_ack *extack) { … } static bool i40e_active_tx_ring_index(struct i40e_vsi *vsi, u16 index) { … } static int i40e_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring, struct kernel_ethtool_ringparam *kernel_ring, struct netlink_ext_ack *extack) { … } /** * i40e_get_stats_count - return the stats count for a device * @netdev: the netdev to return the count for * * Returns the total number of statistics for this netdev. Note that even * though this is a function, it is required that the count for a specific * netdev must never change. Basing the count on static values such as the * maximum number of queues or the device type is ok. However, the API for * obtaining stats is *not* safe against changes based on non-static * values such as the *current* number of queues, or runtime flags. * * If a statistic is not always enabled, return it as part of the count * anyways, always return its string, and report its value as zero. **/ static int i40e_get_stats_count(struct net_device *netdev) { … } static int i40e_get_sset_count(struct net_device *netdev, int sset) { … } /** * i40e_get_veb_tc_stats - copy VEB TC statistics to formatted structure * @tc: the TC statistics in VEB structure (veb->tc_stats) * @i: the index of traffic class in (veb->tc_stats) structure to copy * * Copy VEB TC statistics from structure of arrays (veb->tc_stats) to * one dimensional structure i40e_cp_veb_tc_stats. * Produce formatted i40e_cp_veb_tc_stats structure of the VEB TC * statistics for the given TC. **/ static struct i40e_cp_veb_tc_stats i40e_get_veb_tc_stats(struct i40e_veb_tc_stats *tc, unsigned int i) { … } /** * i40e_get_pfc_stats - copy HW PFC statistics to formatted structure * @pf: the PF device structure * @i: the priority value to copy * * The PFC stats are found as arrays in pf->stats, which is not easy to pass * into i40e_add_ethtool_stats. Produce a formatted i40e_pfc_stats structure * of the PFC stats for the given priority. **/ static inline struct i40e_pfc_stats i40e_get_pfc_stats(struct i40e_pf *pf, unsigned int i) { … } /** * i40e_get_ethtool_stats - copy stat values into supplied buffer * @netdev: the netdev to collect stats for * @stats: ethtool stats command structure * @data: ethtool supplied buffer * * Copy the stats values for this netdev into the buffer. Expects data to be * pre-allocated to the size returned by i40e_get_stats_count.. Note that all * statistics must be copied in a static order, and the count must not change * for a given netdev. See i40e_get_stats_count for more details. * * If a statistic is not currently valid (such as a disabled queue), this * function reports its value as zero. **/ static void i40e_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) { … } /** * i40e_get_stat_strings - copy stat strings into supplied buffer * @netdev: the netdev to collect strings for * @data: supplied buffer to copy strings into * * Copy the strings related to stats for this netdev. Expects data to be * pre-allocated with the size reported by i40e_get_stats_count. Note that the * strings must be copied in a static order and the total count must not * change for a given netdev. See i40e_get_stats_count for more details. **/ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data) { … } static void i40e_get_priv_flag_strings(struct net_device *netdev, u8 *data) { … } static void i40e_get_strings(struct net_device *netdev, u32 stringset, u8 *data) { … } static int i40e_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts_info *info) { … } static u64 i40e_link_test(struct net_device *netdev, u64 *data) { … } static u64 i40e_reg_test(struct net_device *netdev, u64 *data) { … } static u64 i40e_eeprom_test(struct net_device *netdev, u64 *data) { … } static u64 i40e_intr_test(struct net_device *netdev, u64 *data) { … } static inline bool i40e_active_vfs(struct i40e_pf *pf) { … } static inline bool i40e_active_vmdqs(struct i40e_pf *pf) { … } static void i40e_diag_test(struct net_device *netdev, struct ethtool_test *eth_test, u64 *data) { … } static void i40e_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { … } /** * i40e_set_wol - set the WakeOnLAN configuration * @netdev: the netdev in question * @wol: the ethtool WoL setting data **/ static int i40e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) { … } static int i40e_set_phys_id(struct net_device *netdev, enum ethtool_phys_id_state state) { … } /* NOTE: i40e hardware uses a conversion factor of 2 for Interrupt * Throttle Rate (ITR) ie. ITR(1) = 2us ITR(10) = 20 us, and also * 125us (8000 interrupts per second) == ITR(62) */ /** * __i40e_get_coalesce - get per-queue coalesce settings * @netdev: the netdev to check * @ec: ethtool coalesce data structure * @queue: which queue to pick * * Gets the per-queue settings for coalescence. Specifically Rx and Tx usecs * are per queue. If queue is <0 then we default to queue 0 as the * representative value. **/ static int __i40e_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, int queue) { … } /** * i40e_get_coalesce - get a netdev's coalesce settings * @netdev: the netdev to check * @ec: ethtool coalesce data structure * @kernel_coal: ethtool CQE mode setting structure * @extack: extack for reporting error messages * * Gets the coalesce settings for a particular netdev. Note that if user has * modified per-queue settings, this only guarantees to represent queue 0. See * __i40e_get_coalesce for more details. **/ static int i40e_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, struct kernel_ethtool_coalesce *kernel_coal, struct netlink_ext_ack *extack) { … } /** * i40e_get_per_queue_coalesce - gets coalesce settings for particular queue * @netdev: netdev structure * @ec: ethtool's coalesce settings * @queue: the particular queue to read * * Will read a specific queue's coalesce settings **/ static int i40e_get_per_queue_coalesce(struct net_device *netdev, u32 queue, struct ethtool_coalesce *ec) { … } /** * i40e_set_itr_per_queue - set ITR values for specific queue * @vsi: the VSI to set values for * @ec: coalesce settings from ethtool * @queue: the queue to modify * * Change the ITR settings for a specific queue. **/ static void i40e_set_itr_per_queue(struct i40e_vsi *vsi, struct ethtool_coalesce *ec, int queue) { … } /** * __i40e_set_coalesce - set coalesce settings for particular queue * @netdev: the netdev to change * @ec: ethtool coalesce settings * @queue: the queue to change * * Sets the coalesce settings for a particular queue. **/ static int __i40e_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, int queue) { … } /** * i40e_set_coalesce - set coalesce settings for every queue on the netdev * @netdev: the netdev to change * @ec: ethtool coalesce settings * @kernel_coal: ethtool CQE mode setting structure * @extack: extack for reporting error messages * * This will set each queue to the same coalesce settings. **/ static int i40e_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ec, struct kernel_ethtool_coalesce *kernel_coal, struct netlink_ext_ack *extack) { … } /** * i40e_set_per_queue_coalesce - set specific queue's coalesce settings * @netdev: the netdev to change * @ec: ethtool's coalesce settings * @queue: the queue to change * * Sets the specified queue's coalesce settings. **/ static int i40e_set_per_queue_coalesce(struct net_device *netdev, u32 queue, struct ethtool_coalesce *ec) { … } /** * i40e_get_rss_hash_opts - Get RSS hash Input Set for each flow type * @pf: pointer to the physical function struct * @cmd: ethtool rxnfc command * * Returns Success if the flow is supported, else Invalid Input. **/ static int i40e_get_rss_hash_opts(struct i40e_pf *pf, struct ethtool_rxnfc *cmd) { … } /** * i40e_check_mask - Check whether a mask field is set * @mask: the full mask value * @field: mask of the field to check * * If the given mask is fully set, return positive value. If the mask for the * field is fully unset, return zero. Otherwise return a negative error code. **/ static int i40e_check_mask(u64 mask, u64 field) { … } /** * i40e_parse_rx_flow_user_data - Deconstruct user-defined data * @fsp: pointer to rx flow specification * @data: pointer to userdef data structure for storage * * Read the user-defined data and deconstruct the value into a structure. No * other code should read the user-defined data, so as to ensure that every * place consistently reads the value correctly. * * The user-defined field is a 64bit Big Endian format value, which we * deconstruct by reading bits or bit fields from it. Single bit flags shall * be defined starting from the highest bits, while small bit field values * shall be defined starting from the lowest bits. * * Returns 0 if the data is valid, and non-zero if the userdef data is invalid * and the filter should be rejected. The data structure will always be * modified even if FLOW_EXT is not set. * **/ static int i40e_parse_rx_flow_user_data(struct ethtool_rx_flow_spec *fsp, struct i40e_rx_flow_userdef *data) { … } /** * i40e_fill_rx_flow_user_data - Fill in user-defined data field * @fsp: pointer to rx_flow specification * @data: pointer to return userdef data * * Reads the userdef data structure and properly fills in the user defined * fields of the rx_flow_spec. **/ static void i40e_fill_rx_flow_user_data(struct ethtool_rx_flow_spec *fsp, struct i40e_rx_flow_userdef *data) { … } /** * i40e_get_ethtool_fdir_all - Populates the rule count of a command * @pf: Pointer to the physical function struct * @cmd: The command to get or set Rx flow classification rules * @rule_locs: Array of used rule locations * * This function populates both the total and actual rule count of * the ethtool flow classification command * * Returns 0 on success or -EMSGSIZE if entry not found **/ static int i40e_get_ethtool_fdir_all(struct i40e_pf *pf, struct ethtool_rxnfc *cmd, u32 *rule_locs) { … } /** * i40e_get_ethtool_fdir_entry - Look up a filter based on Rx flow * @pf: Pointer to the physical function struct * @cmd: The command to get or set Rx flow classification rules * * This function looks up a filter based on the Rx flow classification * command and fills the flow spec info for it if found * * Returns 0 on success or -EINVAL if filter not found **/ static int i40e_get_ethtool_fdir_entry(struct i40e_pf *pf, struct ethtool_rxnfc *cmd) { … } /** * i40e_get_rxnfc - command to get RX flow classification rules * @netdev: network interface device structure * @cmd: ethtool rxnfc command * @rule_locs: pointer to store rule data * * Returns Success if the command is supported. **/ static int i40e_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, u32 *rule_locs) { … } /** * i40e_get_rss_hash_bits - Read RSS Hash bits from register * @hw: hw structure * @nfc: pointer to user request * @i_setc: bits currently set * * Returns value of bits to be set per user request **/ static u64 i40e_get_rss_hash_bits(struct i40e_hw *hw, struct ethtool_rxnfc *nfc, u64 i_setc) { … } #define FLOW_PCTYPES_SIZE … /** * i40e_set_rss_hash_opt - Enable/Disable flow types for RSS hash * @pf: pointer to the physical function struct * @nfc: ethtool rxnfc command * * Returns Success if the flow input set is supported. **/ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc) { … } /** * i40e_update_ethtool_fdir_entry - Updates the fdir filter entry * @vsi: Pointer to the targeted VSI * @input: The filter to update or NULL to indicate deletion * @sw_idx: Software index to the filter * @cmd: The command to get or set Rx flow classification rules * * This function updates (or deletes) a Flow Director entry from * the hlist of the corresponding PF * * Returns 0 on success **/ static int i40e_update_ethtool_fdir_entry(struct i40e_vsi *vsi, struct i40e_fdir_filter *input, u16 sw_idx, struct ethtool_rxnfc *cmd) { … } /** * i40e_prune_flex_pit_list - Cleanup unused entries in FLX_PIT table * @pf: pointer to PF structure * * This function searches the list of filters and determines which FLX_PIT * entries are still required. It will prune any entries which are no longer * in use after the deletion. **/ static void i40e_prune_flex_pit_list(struct i40e_pf *pf) { … } /** * i40e_del_fdir_entry - Deletes a Flow Director filter entry * @vsi: Pointer to the targeted VSI * @cmd: The command to get or set Rx flow classification rules * * The function removes a Flow Director filter entry from the * hlist of the corresponding PF * * Returns 0 on success */ static int i40e_del_fdir_entry(struct i40e_vsi *vsi, struct ethtool_rxnfc *cmd) { … } /** * i40e_unused_pit_index - Find an unused PIT index for given list * @pf: the PF data structure * * Find the first unused flexible PIT index entry. We search both the L3 and * L4 flexible PIT lists so that the returned index is unique and unused by * either currently programmed L3 or L4 filters. We use a bit field as storage * to track which indexes are already used. **/ static u8 i40e_unused_pit_index(struct i40e_pf *pf) { … } /** * i40e_find_flex_offset - Find an existing flex src_offset * @flex_pit_list: L3 or L4 flex PIT list * @src_offset: new src_offset to find * * Searches the flex_pit_list for an existing offset. If no offset is * currently programmed, then this will return an ERR_PTR if there is no space * to add a new offset, otherwise it returns NULL. **/ static struct i40e_flex_pit *i40e_find_flex_offset(struct list_head *flex_pit_list, u16 src_offset) { … } /** * i40e_add_flex_offset - Add src_offset to flex PIT table list * @flex_pit_list: L3 or L4 flex PIT list * @src_offset: new src_offset to add * @pit_index: the PIT index to program * * This function programs the new src_offset to the list. It is expected that * i40e_find_flex_offset has already been tried and returned NULL, indicating * that this offset is not programmed, and that the list has enough space to * store another offset. * * Returns 0 on success, and negative value on error. **/ static int i40e_add_flex_offset(struct list_head *flex_pit_list, u16 src_offset, u8 pit_index) { … } /** * __i40e_reprogram_flex_pit - Re-program specific FLX_PIT table * @pf: Pointer to the PF structure * @flex_pit_list: list of flexible src offsets in use * @flex_pit_start: index to first entry for this section of the table * * In order to handle flexible data, the hardware uses a table of values * called the FLX_PIT table. This table is used to indicate which sections of * the input correspond to what PIT index values. Unfortunately, hardware is * very restrictive about programming this table. Entries must be ordered by * src_offset in ascending order, without duplicates. Additionally, unused * entries must be set to the unused index value, and must have valid size and * length according to the src_offset ordering. * * This function will reprogram the FLX_PIT register from a book-keeping * structure that we guarantee is already ordered correctly, and has no more * than 3 entries. * * To make things easier, we only support flexible values of one word length, * rather than allowing variable length flexible values. **/ static void __i40e_reprogram_flex_pit(struct i40e_pf *pf, struct list_head *flex_pit_list, int flex_pit_start) { … } /** * i40e_reprogram_flex_pit - Reprogram all FLX_PIT tables after input set change * @pf: pointer to the PF structure * * This function reprograms both the L3 and L4 FLX_PIT tables. See the * internal helper function for implementation details. **/ static void i40e_reprogram_flex_pit(struct i40e_pf *pf) { … } /** * i40e_flow_str - Converts a flow_type into a human readable string * @fsp: the flow specification * * Currently only flow types we support are included here, and the string * value attempts to match what ethtool would use to configure this flow type. **/ static const char *i40e_flow_str(struct ethtool_rx_flow_spec *fsp) { … } /** * i40e_pit_index_to_mask - Return the FLEX mask for a given PIT index * @pit_index: PIT index to convert * * Returns the mask for a given PIT index. Will return 0 if the pit_index is * of range. **/ static u64 i40e_pit_index_to_mask(int pit_index) { … } /** * i40e_print_input_set - Show changes between two input sets * @vsi: the vsi being configured * @old: the old input set * @new: the new input set * * Print the difference between old and new input sets by showing which series * of words are toggled on or off. Only displays the bits we actually support * changing. **/ static void i40e_print_input_set(struct i40e_vsi *vsi, u64 old, u64 new) { … } /** * i40e_check_fdir_input_set - Check that a given rx_flow_spec mask is valid * @vsi: pointer to the targeted VSI * @fsp: pointer to Rx flow specification * @userdef: userdefined data from flow specification * * Ensures that a given ethtool_rx_flow_spec has a valid mask. Some support * for partial matches exists with a few limitations. First, hardware only * supports masking by word boundary (2 bytes) and not per individual bit. * Second, hardware is limited to using one mask for a flow type and cannot * use a separate mask for each filter. * * To support these limitations, if we already have a configured filter for * the specified type, this function enforces that new filters of the type * match the configured input set. Otherwise, if we do not have a filter of * the specified type, we allow the input set to be updated to match the * desired filter. * * To help ensure that administrators understand why filters weren't displayed * as supported, we print a diagnostic message displaying how the input set * would change and warning to delete the preexisting filters if required. * * Returns 0 on successful input set match, and a negative return code on * failure. **/ static int i40e_check_fdir_input_set(struct i40e_vsi *vsi, struct ethtool_rx_flow_spec *fsp, struct i40e_rx_flow_userdef *userdef) { … } /** * i40e_match_fdir_filter - Return true of two filters match * @a: pointer to filter struct * @b: pointer to filter struct * * Returns true if the two filters match exactly the same criteria. I.e. they * match the same flow type and have the same parameters. We don't need to * check any input-set since all filters of the same flow type must use the * same input set. **/ static bool i40e_match_fdir_filter(struct i40e_fdir_filter *a, struct i40e_fdir_filter *b) { … } /** * i40e_disallow_matching_filters - Check that new filters differ * @vsi: pointer to the targeted VSI * @input: new filter to check * * Due to hardware limitations, it is not possible for two filters that match * similar criteria to be programmed at the same time. This is true for a few * reasons: * * (a) all filters matching a particular flow type must use the same input * set, that is they must match the same criteria. * (b) different flow types will never match the same packet, as the flow type * is decided by hardware before checking which rules apply. * (c) hardware has no way to distinguish which order filters apply in. * * Due to this, we can't really support using the location data to order * filters in the hardware parsing. It is technically possible for the user to * request two filters matching the same criteria but which select different * queues. In this case, rather than keep both filters in the list, we reject * the 2nd filter when the user requests adding it. * * This avoids needing to track location for programming the filter to * hardware, and ensures that we avoid some strange scenarios involving * deleting filters which match the same criteria. **/ static int i40e_disallow_matching_filters(struct i40e_vsi *vsi, struct i40e_fdir_filter *input) { … } /** * i40e_add_fdir_ethtool - Add/Remove Flow Director filters * @vsi: pointer to the targeted VSI * @cmd: command to get or set RX flow classification rules * * Add Flow Director filters for a specific flow spec based on their * protocol. Returns 0 if the filters were successfully added. **/ static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi, struct ethtool_rxnfc *cmd) { … } /** * i40e_set_rxnfc - command to set RX flow classification rules * @netdev: network interface device structure * @cmd: ethtool rxnfc command * * Returns Success if the command is supported. **/ static int i40e_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) { … } /** * i40e_max_channels - get Max number of combined channels supported * @vsi: vsi pointer **/ static unsigned int i40e_max_channels(struct i40e_vsi *vsi) { … } /** * i40e_get_channels - Get the current channels enabled and max supported etc. * @dev: network interface device structure * @ch: ethtool channels structure * * We don't support separate tx and rx queues as channels. The other count * represents how many queues are being used for control. max_combined counts * how many queue pairs we can support. They may not be mapped 1 to 1 with * q_vectors since we support a lot more queue pairs than q_vectors. **/ static void i40e_get_channels(struct net_device *dev, struct ethtool_channels *ch) { … } /** * i40e_set_channels - Set the new channels count. * @dev: network interface device structure * @ch: ethtool channels structure * * The new channels count may not be the same as requested by the user * since it gets rounded down to a power of 2 value. **/ static int i40e_set_channels(struct net_device *dev, struct ethtool_channels *ch) { … } /** * i40e_get_rxfh_key_size - get the RSS hash key size * @netdev: network interface device structure * * Returns the table size. **/ static u32 i40e_get_rxfh_key_size(struct net_device *netdev) { … } /** * i40e_get_rxfh_indir_size - get the rx flow hash indirection table size * @netdev: network interface device structure * * Returns the table size. **/ static u32 i40e_get_rxfh_indir_size(struct net_device *netdev) { … } /** * i40e_get_rxfh - get the rx flow hash indirection table * @netdev: network interface device structure * @rxfh: pointer to param struct (indir, key, hfunc) * * Reads the indirection table directly from the hardware. Returns 0 on * success. **/ static int i40e_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh) { … } /** * i40e_set_rxfh - set the rx flow hash indirection table * @netdev: network interface device structure * @rxfh: pointer to param struct (indir, key, hfunc) * @extack: extended ACK from the Netlink message * * Returns -EINVAL if the table specifies an invalid queue id, otherwise * returns 0 after programming the table. **/ static int i40e_set_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh, struct netlink_ext_ack *extack) { … } /** * i40e_get_priv_flags - report device private flags * @dev: network interface device structure * * The get string set count and the string set should be matched for each * flag returned. Add new strings for each flag to the i40e_gstrings_priv_flags * array. * * Returns a u32 bitmap of flags. **/ static u32 i40e_get_priv_flags(struct net_device *dev) { … } /** * i40e_set_priv_flags - set private flags * @dev: network interface device structure * @flags: bit flags to be set **/ static int i40e_set_priv_flags(struct net_device *dev, u32 flags) { … } /** * i40e_get_module_info - get (Q)SFP+ module type info * @netdev: network interface device structure * @modinfo: module EEPROM size and layout information structure **/ static int i40e_get_module_info(struct net_device *netdev, struct ethtool_modinfo *modinfo) { … } /** * i40e_get_module_eeprom - fills buffer with (Q)SFP+ module memory contents * @netdev: network interface device structure * @ee: EEPROM dump request structure * @data: buffer to be filled with EEPROM contents **/ static int i40e_get_module_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee, u8 *data) { … } static void i40e_eee_capability_to_kedata_supported(__le16 eee_capability_, unsigned long *supported) { … } static int i40e_get_eee(struct net_device *netdev, struct ethtool_keee *edata) { … } static int i40e_is_eee_param_supported(struct net_device *netdev, struct ethtool_keee *edata) { … } static int i40e_set_eee(struct net_device *netdev, struct ethtool_keee *edata) { … } static const struct ethtool_ops i40e_ethtool_recovery_mode_ops = …; static const struct ethtool_ops i40e_ethtool_ops = …; void i40e_set_ethtool_ops(struct net_device *netdev) { … }