// SPDX-License-Identifier: GPL-2.0-only /* Copyright (C) 2023 Intel Corporation */ #include "idpf.h" #include "idpf_virtchnl.h" static const struct net_device_ops idpf_netdev_ops; /** * idpf_init_vector_stack - Fill the MSIX vector stack with vector index * @adapter: private data struct * * Return 0 on success, error on failure */ static int idpf_init_vector_stack(struct idpf_adapter *adapter) { … } /** * idpf_deinit_vector_stack - zero out the MSIX vector stack * @adapter: private data struct */ static void idpf_deinit_vector_stack(struct idpf_adapter *adapter) { … } /** * idpf_mb_intr_rel_irq - Free the IRQ association with the OS * @adapter: adapter structure * * This will also disable interrupt mode and queue up mailbox task. Mailbox * task will reschedule itself if not in interrupt mode. */ static void idpf_mb_intr_rel_irq(struct idpf_adapter *adapter) { … } /** * idpf_intr_rel - Release interrupt capabilities and free memory * @adapter: adapter to disable interrupts on */ void idpf_intr_rel(struct idpf_adapter *adapter) { … } /** * idpf_mb_intr_clean - Interrupt handler for the mailbox * @irq: interrupt number * @data: pointer to the adapter structure */ static irqreturn_t idpf_mb_intr_clean(int __always_unused irq, void *data) { … } /** * idpf_mb_irq_enable - Enable MSIX interrupt for the mailbox * @adapter: adapter to get the hardware address for register write */ static void idpf_mb_irq_enable(struct idpf_adapter *adapter) { … } /** * idpf_mb_intr_req_irq - Request irq for the mailbox interrupt * @adapter: adapter structure to pass to the mailbox irq handler */ static int idpf_mb_intr_req_irq(struct idpf_adapter *adapter) { … } /** * idpf_set_mb_vec_id - Set vector index for mailbox * @adapter: adapter structure to access the vector chunks * * The first vector id in the requested vector chunks from the CP is for * the mailbox */ static void idpf_set_mb_vec_id(struct idpf_adapter *adapter) { … } /** * idpf_mb_intr_init - Initialize the mailbox interrupt * @adapter: adapter structure to store the mailbox vector */ static int idpf_mb_intr_init(struct idpf_adapter *adapter) { … } /** * idpf_vector_lifo_push - push MSIX vector index onto stack * @adapter: private data struct * @vec_idx: vector index to store */ static int idpf_vector_lifo_push(struct idpf_adapter *adapter, u16 vec_idx) { … } /** * idpf_vector_lifo_pop - pop MSIX vector index from stack * @adapter: private data struct */ static int idpf_vector_lifo_pop(struct idpf_adapter *adapter) { … } /** * idpf_vector_stash - Store the vector indexes onto the stack * @adapter: private data struct * @q_vector_idxs: vector index array * @vec_info: info related to the number of vectors * * This function is a no-op if there are no vectors indexes to be stashed */ static void idpf_vector_stash(struct idpf_adapter *adapter, u16 *q_vector_idxs, struct idpf_vector_info *vec_info) { … } /** * idpf_req_rel_vector_indexes - Request or release MSIX vector indexes * @adapter: driver specific private structure * @q_vector_idxs: vector index array * @vec_info: info related to the number of vectors * * This is the core function to distribute the MSIX vectors acquired from the * OS. It expects the caller to pass the number of vectors required and * also previously allocated. First, it stashes previously allocated vector * indexes on to the stack and then figures out if it can allocate requested * vectors. It can wait on acquiring the mutex lock. If the caller passes 0 as * requested vectors, then this function just stashes the already allocated * vectors and returns 0. * * Returns actual number of vectors allocated on success, error value on failure * If 0 is returned, implies the stack has no vectors to allocate which is also * a failure case for the caller */ int idpf_req_rel_vector_indexes(struct idpf_adapter *adapter, u16 *q_vector_idxs, struct idpf_vector_info *vec_info) { … } /** * idpf_intr_req - Request interrupt capabilities * @adapter: adapter to enable interrupts on * * Returns 0 on success, negative on failure */ int idpf_intr_req(struct idpf_adapter *adapter) { … } /** * idpf_find_mac_filter - Search filter list for specific mac filter * @vconfig: Vport config structure * @macaddr: The MAC address * * Returns ptr to the filter object or NULL. Must be called while holding the * mac_filter_list_lock. **/ static struct idpf_mac_filter *idpf_find_mac_filter(struct idpf_vport_config *vconfig, const u8 *macaddr) { … } /** * __idpf_del_mac_filter - Delete a MAC filter from the filter list * @vport_config: Vport config structure * @macaddr: The MAC address * * Returns 0 on success, error value on failure **/ static int __idpf_del_mac_filter(struct idpf_vport_config *vport_config, const u8 *macaddr) { … } /** * idpf_del_mac_filter - Delete a MAC filter from the filter list * @vport: Main vport structure * @np: Netdev private structure * @macaddr: The MAC address * @async: Don't wait for return message * * Removes filter from list and if interface is up, tells hardware about the * removed filter. **/ static int idpf_del_mac_filter(struct idpf_vport *vport, struct idpf_netdev_priv *np, const u8 *macaddr, bool async) { … } /** * __idpf_add_mac_filter - Add mac filter helper function * @vport_config: Vport config structure * @macaddr: Address to add * * Takes mac_filter_list_lock spinlock to add new filter to list. */ static int __idpf_add_mac_filter(struct idpf_vport_config *vport_config, const u8 *macaddr) { … } /** * idpf_add_mac_filter - Add a mac filter to the filter list * @vport: Main vport structure * @np: Netdev private structure * @macaddr: The MAC address * @async: Don't wait for return message * * Returns 0 on success or error on failure. If interface is up, we'll also * send the virtchnl message to tell hardware about the filter. **/ static int idpf_add_mac_filter(struct idpf_vport *vport, struct idpf_netdev_priv *np, const u8 *macaddr, bool async) { … } /** * idpf_del_all_mac_filters - Delete all MAC filters in list * @vport: main vport struct * * Takes mac_filter_list_lock spinlock. Deletes all filters */ static void idpf_del_all_mac_filters(struct idpf_vport *vport) { … } /** * idpf_restore_mac_filters - Re-add all MAC filters in list * @vport: main vport struct * * Takes mac_filter_list_lock spinlock. Sets add field to true for filters to * resync filters back to HW. */ static void idpf_restore_mac_filters(struct idpf_vport *vport) { … } /** * idpf_remove_mac_filters - Remove all MAC filters in list * @vport: main vport struct * * Takes mac_filter_list_lock spinlock. Sets remove field to true for filters * to remove filters in HW. */ static void idpf_remove_mac_filters(struct idpf_vport *vport) { … } /** * idpf_deinit_mac_addr - deinitialize mac address for vport * @vport: main vport structure */ static void idpf_deinit_mac_addr(struct idpf_vport *vport) { … } /** * idpf_init_mac_addr - initialize mac address for vport * @vport: main vport structure * @netdev: pointer to netdev struct associated with this vport */ static int idpf_init_mac_addr(struct idpf_vport *vport, struct net_device *netdev) { … } /** * idpf_cfg_netdev - Allocate, configure and register a netdev * @vport: main vport structure * * Returns 0 on success, negative value on failure. */ static int idpf_cfg_netdev(struct idpf_vport *vport) { … } /** * idpf_get_free_slot - get the next non-NULL location index in array * @adapter: adapter in which to look for a free vport slot */ static int idpf_get_free_slot(struct idpf_adapter *adapter) { … } /** * idpf_remove_features - Turn off feature configs * @vport: virtual port structure */ static void idpf_remove_features(struct idpf_vport *vport) { … } /** * idpf_vport_stop - Disable a vport * @vport: vport to disable */ static void idpf_vport_stop(struct idpf_vport *vport) { … } /** * idpf_stop - Disables a network interface * @netdev: network interface device structure * * The stop entry point is called when an interface is de-activated by the OS, * and the netdevice enters the DOWN state. The hardware is still under the * driver's control, but the netdev interface is disabled. * * Returns success only - not allowed to fail */ static int idpf_stop(struct net_device *netdev) { … } /** * idpf_decfg_netdev - Unregister the netdev * @vport: vport for which netdev to be unregistered */ static void idpf_decfg_netdev(struct idpf_vport *vport) { … } /** * idpf_vport_rel - Delete a vport and free its resources * @vport: the vport being removed */ static void idpf_vport_rel(struct idpf_vport *vport) { … } /** * idpf_vport_dealloc - cleanup and release a given vport * @vport: pointer to idpf vport structure * * returns nothing */ static void idpf_vport_dealloc(struct idpf_vport *vport) { … } /** * idpf_is_hsplit_supported - check whether the header split is supported * @vport: virtual port to check the capability for * * Return: true if it's supported by the HW/FW, false if not. */ static bool idpf_is_hsplit_supported(const struct idpf_vport *vport) { … } /** * idpf_vport_get_hsplit - get the current header split feature state * @vport: virtual port to query the state for * * Return: ``ETHTOOL_TCP_DATA_SPLIT_UNKNOWN`` if not supported, * ``ETHTOOL_TCP_DATA_SPLIT_DISABLED`` if disabled, * ``ETHTOOL_TCP_DATA_SPLIT_ENABLED`` if active. */ u8 idpf_vport_get_hsplit(const struct idpf_vport *vport) { … } /** * idpf_vport_set_hsplit - enable or disable header split on a given vport * @vport: virtual port to configure * @val: Ethtool flag controlling the header split state * * Return: true on success, false if not supported by the HW. */ bool idpf_vport_set_hsplit(const struct idpf_vport *vport, u8 val) { … } /** * idpf_vport_alloc - Allocates the next available struct vport in the adapter * @adapter: board private structure * @max_q: vport max queue info * * returns a pointer to a vport on success, NULL on failure. */ static struct idpf_vport *idpf_vport_alloc(struct idpf_adapter *adapter, struct idpf_vport_max_q *max_q) { … } /** * idpf_get_stats64 - get statistics for network device structure * @netdev: network interface device structure * @stats: main device statistics structure */ static void idpf_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats) { … } /** * idpf_statistics_task - Delayed task to get statistics over mailbox * @work: work_struct handle to our data */ void idpf_statistics_task(struct work_struct *work) { … } /** * idpf_mbx_task - Delayed task to handle mailbox responses * @work: work_struct handle */ void idpf_mbx_task(struct work_struct *work) { … } /** * idpf_service_task - Delayed task for handling mailbox responses * @work: work_struct handle to our data * */ void idpf_service_task(struct work_struct *work) { … } /** * idpf_restore_features - Restore feature configs * @vport: virtual port structure */ static void idpf_restore_features(struct idpf_vport *vport) { … } /** * idpf_set_real_num_queues - set number of queues for netdev * @vport: virtual port structure * * Returns 0 on success, negative on failure. */ static int idpf_set_real_num_queues(struct idpf_vport *vport) { … } /** * idpf_up_complete - Complete interface up sequence * @vport: virtual port structure * * Returns 0 on success, negative on failure. */ static int idpf_up_complete(struct idpf_vport *vport) { … } /** * idpf_rx_init_buf_tail - Write initial buffer ring tail value * @vport: virtual port struct */ static void idpf_rx_init_buf_tail(struct idpf_vport *vport) { … } /** * idpf_vport_open - Bring up a vport * @vport: vport to bring up */ static int idpf_vport_open(struct idpf_vport *vport) { … } /** * idpf_init_task - Delayed initialization task * @work: work_struct handle to our data * * Init task finishes up pending work started in probe. Due to the asynchronous * nature in which the device communicates with hardware, we may have to wait * several milliseconds to get a response. Instead of busy polling in probe, * pulling it out into a delayed work task prevents us from bogging down the * whole system waiting for a response from hardware. */ void idpf_init_task(struct work_struct *work) { … } /** * idpf_sriov_ena - Enable or change number of VFs * @adapter: private data struct * @num_vfs: number of VFs to allocate */ static int idpf_sriov_ena(struct idpf_adapter *adapter, int num_vfs) { … } /** * idpf_sriov_configure - Configure the requested VFs * @pdev: pointer to a pci_dev structure * @num_vfs: number of vfs to allocate * * Enable or change the number of VFs. Called when the user updates the number * of VFs in sysfs. **/ int idpf_sriov_configure(struct pci_dev *pdev, int num_vfs) { … } /** * idpf_deinit_task - Device deinit routine * @adapter: Driver specific private structure * * Extended remove logic which will be used for * hard reset as well */ void idpf_deinit_task(struct idpf_adapter *adapter) { … } /** * idpf_check_reset_complete - check that reset is complete * @hw: pointer to hw struct * @reset_reg: struct with reset registers * * Returns 0 if device is ready to use, or -EBUSY if it's in reset. **/ static int idpf_check_reset_complete(struct idpf_hw *hw, struct idpf_reset_reg *reset_reg) { … } /** * idpf_set_vport_state - Set the vport state to be after the reset * @adapter: Driver specific private structure */ static void idpf_set_vport_state(struct idpf_adapter *adapter) { … } /** * idpf_init_hard_reset - Initiate a hardware reset * @adapter: Driver specific private structure * * Deallocate the vports and all the resources associated with them and * reallocate. Also reinitialize the mailbox. Return 0 on success, * negative on failure. */ static int idpf_init_hard_reset(struct idpf_adapter *adapter) { … } /** * idpf_vc_event_task - Handle virtchannel event logic * @work: work queue struct */ void idpf_vc_event_task(struct work_struct *work) { … } /** * idpf_initiate_soft_reset - Initiate a software reset * @vport: virtual port data struct * @reset_cause: reason for the soft reset * * Soft reset only reallocs vport queue resources. Returns 0 on success, * negative on failure. */ int idpf_initiate_soft_reset(struct idpf_vport *vport, enum idpf_vport_reset_cause reset_cause) { … } /** * idpf_addr_sync - Callback for dev_(mc|uc)_sync to add address * @netdev: the netdevice * @addr: address to add * * Called by __dev_(mc|uc)_sync when an address needs to be added. We call * __dev_(uc|mc)_sync from .set_rx_mode. Kernel takes addr_list_lock spinlock * meaning we cannot sleep in this context. Due to this, we have to add the * filter and send the virtchnl message asynchronously without waiting for the * response from the other side. We won't know whether or not the operation * actually succeeded until we get the message back. Returns 0 on success, * negative on failure. */ static int idpf_addr_sync(struct net_device *netdev, const u8 *addr) { … } /** * idpf_addr_unsync - Callback for dev_(mc|uc)_sync to remove address * @netdev: the netdevice * @addr: address to add * * Called by __dev_(mc|uc)_sync when an address needs to be added. We call * __dev_(uc|mc)_sync from .set_rx_mode. Kernel takes addr_list_lock spinlock * meaning we cannot sleep in this context. Due to this we have to delete the * filter and send the virtchnl message asynchronously without waiting for the * return from the other side. We won't know whether or not the operation * actually succeeded until we get the message back. Returns 0 on success, * negative on failure. */ static int idpf_addr_unsync(struct net_device *netdev, const u8 *addr) { … } /** * idpf_set_rx_mode - NDO callback to set the netdev filters * @netdev: network interface device structure * * Stack takes addr_list_lock spinlock before calling our .set_rx_mode. We * cannot sleep in this context. */ static void idpf_set_rx_mode(struct net_device *netdev) { … } /** * idpf_vport_manage_rss_lut - disable/enable RSS * @vport: the vport being changed * * In the event of disable request for RSS, this function will zero out RSS * LUT, while in the event of enable request for RSS, it will reconfigure RSS * LUT with the default LUT configuration. */ static int idpf_vport_manage_rss_lut(struct idpf_vport *vport) { … } /** * idpf_set_features - set the netdev feature flags * @netdev: ptr to the netdev being adjusted * @features: the feature set that the stack is suggesting */ static int idpf_set_features(struct net_device *netdev, netdev_features_t features) { … } /** * idpf_open - Called when a network interface becomes active * @netdev: network interface device structure * * The open entry point is called when a network interface is made * active by the system (IFF_UP). At this point all resources needed * for transmit and receive operations are allocated, the interrupt * handler is registered with the OS, the netdev watchdog is enabled, * and the stack is notified that the interface is ready. * * Returns 0 on success, negative value on failure */ static int idpf_open(struct net_device *netdev) { … } /** * idpf_change_mtu - NDO callback to change the MTU * @netdev: network interface device structure * @new_mtu: new value for maximum frame size * * Returns 0 on success, negative on failure */ static int idpf_change_mtu(struct net_device *netdev, int new_mtu) { … } /** * idpf_features_check - Validate packet conforms to limits * @skb: skb buffer * @netdev: This port's netdev * @features: Offload features that the stack believes apply */ static netdev_features_t idpf_features_check(struct sk_buff *skb, struct net_device *netdev, netdev_features_t features) { … } /** * idpf_set_mac - NDO callback to set port mac address * @netdev: network interface device structure * @p: pointer to an address structure * * Returns 0 on success, negative on failure **/ static int idpf_set_mac(struct net_device *netdev, void *p) { … } /** * idpf_alloc_dma_mem - Allocate dma memory * @hw: pointer to hw struct * @mem: pointer to dma_mem struct * @size: size of the memory to allocate */ void *idpf_alloc_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem, u64 size) { … } /** * idpf_free_dma_mem - Free the allocated dma memory * @hw: pointer to hw struct * @mem: pointer to dma_mem struct */ void idpf_free_dma_mem(struct idpf_hw *hw, struct idpf_dma_mem *mem) { … } static const struct net_device_ops idpf_netdev_ops = …;