// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2018, Intel Corporation. */ #include "ice.h" #include "ice_vf_lib_private.h" #include "ice_base.h" #include "ice_lib.h" #include "ice_fltr.h" #include "ice_dcb_lib.h" #include "ice_flow.h" #include "ice_eswitch.h" #include "ice_virtchnl_allowlist.h" #include "ice_flex_pipe.h" #include "ice_vf_vsi_vlan_ops.h" #include "ice_vlan.h" /** * ice_free_vf_entries - Free all VF entries from the hash table * @pf: pointer to the PF structure * * Iterate over the VF hash table, removing and releasing all VF entries. * Called during VF teardown or as cleanup during failed VF initialization. */ static void ice_free_vf_entries(struct ice_pf *pf) { … } /** * ice_free_vf_res - Free a VF's resources * @vf: pointer to the VF info */ static void ice_free_vf_res(struct ice_vf *vf) { … } /** * ice_dis_vf_mappings * @vf: pointer to the VF structure */ static void ice_dis_vf_mappings(struct ice_vf *vf) { … } /** * ice_sriov_free_msix_res - Reset/free any used MSIX resources * @pf: pointer to the PF structure * * Since no MSIX entries are taken from the pf->irq_tracker then just clear * the pf->sriov_base_vector. * * Returns 0 on success, and -EINVAL on error. */ static int ice_sriov_free_msix_res(struct ice_pf *pf) { … } /** * ice_free_vfs - Free all VFs * @pf: pointer to the PF structure */ void ice_free_vfs(struct ice_pf *pf) { … } /** * ice_vf_vsi_setup - Set up a VF VSI * @vf: VF to setup VSI for * * Returns pointer to the successfully allocated VSI struct on success, * otherwise returns NULL on failure. */ static struct ice_vsi *ice_vf_vsi_setup(struct ice_vf *vf) { … } /** * ice_ena_vf_msix_mappings - enable VF MSIX mappings in hardware * @vf: VF to enable MSIX mappings for * * Some of the registers need to be indexed/configured using hardware global * device values and other registers need 0-based values, which represent PF * based values. */ static void ice_ena_vf_msix_mappings(struct ice_vf *vf) { … } /** * ice_ena_vf_q_mappings - enable Rx/Tx queue mappings for a VF * @vf: VF to enable the mappings for * @max_txq: max Tx queues allowed on the VF's VSI * @max_rxq: max Rx queues allowed on the VF's VSI */ static void ice_ena_vf_q_mappings(struct ice_vf *vf, u16 max_txq, u16 max_rxq) { … } /** * ice_ena_vf_mappings - enable VF MSIX and queue mapping * @vf: pointer to the VF structure */ static void ice_ena_vf_mappings(struct ice_vf *vf) { … } /** * ice_calc_vf_reg_idx - Calculate the VF's register index in the PF space * @vf: VF to calculate the register index for * @q_vector: a q_vector associated to the VF */ void ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector) { … } /** * ice_sriov_set_msix_res - Set any used MSIX resources * @pf: pointer to PF structure * @num_msix_needed: number of MSIX vectors needed for all SR-IOV VFs * * This function allows SR-IOV resources to be taken from the end of the PF's * allowed HW MSIX vectors so that the irq_tracker will not be affected. We * just set the pf->sriov_base_vector and return success. * * If there are not enough resources available, return an error. This should * always be caught by ice_set_per_vf_res(). * * Return 0 on success, and -EINVAL when there are not enough MSIX vectors * in the PF's space available for SR-IOV. */ static int ice_sriov_set_msix_res(struct ice_pf *pf, u16 num_msix_needed) { … } /** * ice_set_per_vf_res - check if vectors and queues are available * @pf: pointer to the PF structure * @num_vfs: the number of SR-IOV VFs being configured * * First, determine HW interrupts from common pool. If we allocate fewer VFs, we * get more vectors and can enable more queues per VF. Note that this does not * grab any vectors from the SW pool already allocated. Also note, that all * vector counts include one for each VF's miscellaneous interrupt vector * (i.e. OICR). * * Minimum VFs - 2 vectors, 1 queue pair * Small VFs - 5 vectors, 4 queue pairs * Medium VFs - 17 vectors, 16 queue pairs * * Second, determine number of queue pairs per VF by starting with a pre-defined * maximum each VF supports. If this is not possible, then we adjust based on * queue pairs available on the device. * * Lastly, set queue and MSI-X VF variables tracked by the PF so it can be used * by each VF during VF initialization and reset. */ static int ice_set_per_vf_res(struct ice_pf *pf, u16 num_vfs) { … } /** * ice_sriov_get_irqs - get irqs for SR-IOV usacase * @pf: pointer to PF structure * @needed: number of irqs to get * * This returns the first MSI-X vector index in PF space that is used by this * VF. This index is used when accessing PF relative registers such as * GLINT_VECT2FUNC and GLINT_DYN_CTL. * This will always be the OICR index in the AVF driver so any functionality * using vf->first_vector_idx for queue configuration_id: id of VF which will * use this irqs * * Only SRIOV specific vectors are tracked in sriov_irq_bm. SRIOV vectors are * allocated from the end of global irq index. First bit in sriov_irq_bm means * last irq index etc. It simplifies extension of SRIOV vectors. * They will be always located from sriov_base_vector to the last irq * index. While increasing/decreasing sriov_base_vector can be moved. */ static int ice_sriov_get_irqs(struct ice_pf *pf, u16 needed) { … } /** * ice_sriov_free_irqs - free irqs used by the VF * @pf: pointer to PF structure * @vf: pointer to VF structure */ static void ice_sriov_free_irqs(struct ice_pf *pf, struct ice_vf *vf) { … } /** * ice_init_vf_vsi_res - initialize/setup VF VSI resources * @vf: VF to initialize/setup the VSI for * * This function creates a VSI for the VF, adds a VLAN 0 filter, and sets up the * VF VSI's broadcast filter and is only used during initial VF creation. */ static int ice_init_vf_vsi_res(struct ice_vf *vf) { … } /** * ice_start_vfs - start VFs so they are ready to be used by SR-IOV * @pf: PF the VFs are associated with */ static int ice_start_vfs(struct ice_pf *pf) { … } /** * ice_sriov_free_vf - Free VF memory after all references are dropped * @vf: pointer to VF to free * * Called by ice_put_vf through ice_release_vf once the last reference to a VF * structure has been dropped. */ static void ice_sriov_free_vf(struct ice_vf *vf) { … } /** * ice_sriov_clear_reset_state - clears VF Reset status register * @vf: the vf to configure */ static void ice_sriov_clear_reset_state(struct ice_vf *vf) { … } /** * ice_sriov_clear_mbx_register - clears SRIOV VF's mailbox registers * @vf: the vf to configure */ static void ice_sriov_clear_mbx_register(struct ice_vf *vf) { … } /** * ice_sriov_trigger_reset_register - trigger VF reset for SRIOV VF * @vf: pointer to VF structure * @is_vflr: true if reset occurred due to VFLR * * Trigger and cleanup after a VF reset for a SR-IOV VF. */ static void ice_sriov_trigger_reset_register(struct ice_vf *vf, bool is_vflr) { … } /** * ice_sriov_poll_reset_status - poll SRIOV VF reset status * @vf: pointer to VF structure * * Returns true when reset is successful, else returns false */ static bool ice_sriov_poll_reset_status(struct ice_vf *vf) { … } /** * ice_sriov_clear_reset_trigger - enable VF to access hardware * @vf: VF to enabled hardware access for */ static void ice_sriov_clear_reset_trigger(struct ice_vf *vf) { … } /** * ice_sriov_post_vsi_rebuild - tasks to do after the VF's VSI have been rebuilt * @vf: VF to perform tasks on */ static void ice_sriov_post_vsi_rebuild(struct ice_vf *vf) { … } static const struct ice_vf_ops ice_sriov_vf_ops = …; /** * ice_create_vf_entries - Allocate and insert VF entries * @pf: pointer to the PF structure * @num_vfs: the number of VFs to allocate * * Allocate new VF entries and insert them into the hash table. Set some * basic default fields for initializing the new VFs. * * After this function exits, the hash table will have num_vfs entries * inserted. * * Returns 0 on success or an integer error code on failure. */ static int ice_create_vf_entries(struct ice_pf *pf, u16 num_vfs) { … } /** * ice_ena_vfs - enable VFs so they are ready to be used * @pf: pointer to the PF structure * @num_vfs: number of VFs to enable */ static int ice_ena_vfs(struct ice_pf *pf, u16 num_vfs) { … } /** * ice_pci_sriov_ena - Enable or change number of VFs * @pf: pointer to the PF structure * @num_vfs: number of VFs to allocate * * Returns 0 on success and negative on failure */ static int ice_pci_sriov_ena(struct ice_pf *pf, int num_vfs) { … } /** * ice_check_sriov_allowed - check if SR-IOV is allowed based on various checks * @pf: PF to enabled SR-IOV on */ static int ice_check_sriov_allowed(struct ice_pf *pf) { … } /** * ice_sriov_get_vf_total_msix - return number of MSI-X used by VFs * @pdev: pointer to pci_dev struct * * The function is called via sysfs ops */ u32 ice_sriov_get_vf_total_msix(struct pci_dev *pdev) { … } static int ice_sriov_move_base_vector(struct ice_pf *pf, int move) { … } static void ice_sriov_remap_vectors(struct ice_pf *pf, u16 restricted_id) { … } /** * ice_sriov_set_msix_vec_count * @vf_dev: pointer to pci_dev struct of VF device * @msix_vec_count: new value for MSI-X amount on this VF * * Set requested MSI-X, queues and registers for @vf_dev. * * First do some sanity checks like if there are any VFs, if the new value * is correct etc. Then disable old mapping (MSI-X and queues registers), change * MSI-X and queues, rebuild VSI and enable new mapping. * * If it is possible (driver not binded to VF) try to remap also other VFs to * linearize irqs register usage. */ int ice_sriov_set_msix_vec_count(struct pci_dev *vf_dev, int msix_vec_count) { … } /** * ice_sriov_configure - Enable or change number of VFs via sysfs * @pdev: pointer to a pci_dev structure * @num_vfs: number of VFs to allocate or 0 to free VFs * * This function is called when the user updates the number of VFs in sysfs. On * success return whatever num_vfs was set to by the caller. Return negative on * failure. */ int ice_sriov_configure(struct pci_dev *pdev, int num_vfs) { … } /** * ice_process_vflr_event - Free VF resources via IRQ calls * @pf: pointer to the PF structure * * called from the VFLR IRQ handler to * free up VF resources and state variables */ void ice_process_vflr_event(struct ice_pf *pf) { … } /** * ice_get_vf_from_pfq - get the VF who owns the PF space queue passed in * @pf: PF used to index all VFs * @pfq: queue index relative to the PF's function space * * If no VF is found who owns the pfq then return NULL, otherwise return a * pointer to the VF who owns the pfq * * If this function returns non-NULL, it acquires a reference count of the VF * structure. The caller is responsible for calling ice_put_vf() to drop this * reference. */ static struct ice_vf *ice_get_vf_from_pfq(struct ice_pf *pf, u16 pfq) { … } /** * ice_globalq_to_pfq - convert from global queue index to PF space queue index * @pf: PF used for conversion * @globalq: global queue index used to convert to PF space queue index */ static u32 ice_globalq_to_pfq(struct ice_pf *pf, u32 globalq) { … } /** * ice_vf_lan_overflow_event - handle LAN overflow event for a VF * @pf: PF that the LAN overflow event happened on * @event: structure holding the event information for the LAN overflow event * * Determine if the LAN overflow event was caused by a VF queue. If it was not * caused by a VF, do nothing. If a VF caused this LAN overflow event trigger a * reset on the offending VF. */ void ice_vf_lan_overflow_event(struct ice_pf *pf, struct ice_rq_event_info *event) { … } /** * ice_set_vf_spoofchk * @netdev: network interface device structure * @vf_id: VF identifier * @ena: flag to enable or disable feature * * Enable or disable VF spoof checking */ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena) { … } /** * ice_get_vf_cfg * @netdev: network interface device structure * @vf_id: VF identifier * @ivi: VF configuration structure * * return VF configuration */ int ice_get_vf_cfg(struct net_device *netdev, int vf_id, struct ifla_vf_info *ivi) { … } /** * __ice_set_vf_mac - program VF MAC address * @pf: PF to be configure * @vf_id: VF identifier * @mac: MAC address * * program VF MAC address * Return: zero on success or an error code on failure */ int __ice_set_vf_mac(struct ice_pf *pf, u16 vf_id, const u8 *mac) { … } /** * ice_set_vf_mac - .ndo_set_vf_mac handler * @netdev: network interface device structure * @vf_id: VF identifier * @mac: MAC address * * program VF MAC address * Return: zero on success or an error code on failure */ int ice_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) { … } /** * ice_set_vf_trust * @netdev: network interface device structure * @vf_id: VF identifier * @trusted: Boolean value to enable/disable trusted VF * * Enable or disable a given VF as trusted */ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted) { … } /** * ice_set_vf_link_state * @netdev: network interface device structure * @vf_id: VF identifier * @link_state: required link state * * Set VF's link state, irrespective of physical link state status */ int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state) { … } /** * ice_calc_all_vfs_min_tx_rate - calculate cumulative min Tx rate on all VFs * @pf: PF associated with VFs */ static int ice_calc_all_vfs_min_tx_rate(struct ice_pf *pf) { … } /** * ice_min_tx_rate_oversubscribed - check if min Tx rate causes oversubscription * @vf: VF trying to configure min_tx_rate * @min_tx_rate: min Tx rate in Mbps * * Check if the min_tx_rate being passed in will cause oversubscription of total * min_tx_rate based on the current link speed and all other VFs configured * min_tx_rate * * Return true if the passed min_tx_rate would cause oversubscription, else * return false */ static bool ice_min_tx_rate_oversubscribed(struct ice_vf *vf, int min_tx_rate) { … } /** * ice_set_vf_bw - set min/max VF bandwidth * @netdev: network interface device structure * @vf_id: VF identifier * @min_tx_rate: Minimum Tx rate in Mbps * @max_tx_rate: Maximum Tx rate in Mbps */ int ice_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate, int max_tx_rate) { … } /** * ice_get_vf_stats - populate some stats for the VF * @netdev: the netdev of the PF * @vf_id: the host OS identifier (0-255) * @vf_stats: pointer to the OS memory to be initialized */ int ice_get_vf_stats(struct net_device *netdev, int vf_id, struct ifla_vf_stats *vf_stats) { … } /** * ice_is_supported_port_vlan_proto - make sure the vlan_proto is supported * @hw: hardware structure used to check the VLAN mode * @vlan_proto: VLAN TPID being checked * * If the device is configured in Double VLAN Mode (DVM), then both ETH_P_8021Q * and ETH_P_8021AD are supported. If the device is configured in Single VLAN * Mode (SVM), then only ETH_P_8021Q is supported. */ static bool ice_is_supported_port_vlan_proto(struct ice_hw *hw, u16 vlan_proto) { … } /** * ice_set_vf_port_vlan * @netdev: network interface device structure * @vf_id: VF identifier * @vlan_id: VLAN ID being set * @qos: priority setting * @vlan_proto: VLAN protocol * * program VF Port VLAN ID and/or QoS */ int ice_set_vf_port_vlan(struct net_device *netdev, int vf_id, u16 vlan_id, u8 qos, __be16 vlan_proto) { … } /** * ice_print_vf_rx_mdd_event - print VF Rx malicious driver detect event * @vf: pointer to the VF structure */ void ice_print_vf_rx_mdd_event(struct ice_vf *vf) { … } /** * ice_print_vf_tx_mdd_event - print VF Tx malicious driver detect event * @vf: pointer to the VF structure */ void ice_print_vf_tx_mdd_event(struct ice_vf *vf) { … } /** * ice_print_vfs_mdd_events - print VFs malicious driver detect event * @pf: pointer to the PF structure * * Called from ice_handle_mdd_event to rate limit and print VFs MDD events. */ void ice_print_vfs_mdd_events(struct ice_pf *pf) { … } /** * ice_restore_all_vfs_msi_state - restore VF MSI state after PF FLR * @pf: pointer to the PF structure * * Called when recovering from a PF FLR to restore interrupt capability to * the VFs. */ void ice_restore_all_vfs_msi_state(struct ice_pf *pf) { … }