// SPDX-License-Identifier: GPL-2.0-only /**************************************************************************** * Driver for Solarflare network controllers and boards * Copyright 2018 Solarflare Communications Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation, incorporated herein by reference. */ #include "net_driver.h" #include <linux/filter.h> #include <linux/module.h> #include <linux/netdevice.h> #include <net/gre.h> #include "efx_common.h" #include "efx_channels.h" #include "efx.h" #include "mcdi.h" #include "selftest.h" #include "rx_common.h" #include "tx_common.h" #include "nic.h" #include "mcdi_port_common.h" #include "io.h" #include "mcdi_pcol.h" #include "ef100_rep.h" static unsigned int debug = …; module_param(debug, uint, 0); MODULE_PARM_DESC(…) …; /* This is the time (in jiffies) between invocations of the hardware * monitor. */ static unsigned int efx_monitor_interval = …; /* How often and how many times to poll for a reset while waiting for a * BIST that another function started to complete. */ #define BIST_WAIT_DELAY_MS … #define BIST_WAIT_DELAY_COUNT … /* Default stats update time */ #define STATS_PERIOD_MS_DEFAULT … static const unsigned int efx_reset_type_max = …; static const char *const efx_reset_type_names[] = …; #define RESET_TYPE(type) … /* Loopback mode names (see LOOPBACK_MODE()) */ const unsigned int efx_loopback_mode_max = …; const char *const efx_loopback_mode_names[] = …; /* Reset workqueue. If any NIC has a hardware failure then a reset will be * queued onto this work queue. This is not a per-nic work queue, because * efx_reset_work() acquires the rtnl lock, so resets are naturally serialised. */ static struct workqueue_struct *reset_workqueue; int efx_create_reset_workqueue(void) { … } void efx_queue_reset_work(struct efx_nic *efx) { … } void efx_flush_reset_workqueue(struct efx_nic *efx) { … } void efx_destroy_reset_workqueue(void) { … } /* We assume that efx->type->reconfigure_mac will always try to sync RX * filters and therefore needs to read-lock the filter table against freeing */ void efx_mac_reconfigure(struct efx_nic *efx, bool mtu_only) { … } /* Asynchronous work item for changing MAC promiscuity and multicast * hash. Avoid a drain/rx_ingress enable by reconfiguring the current * MAC directly. */ static void efx_mac_work(struct work_struct *data) { … } int efx_set_mac_address(struct net_device *net_dev, void *data) { … } /* Context: netif_addr_lock held, BHs disabled. */ void efx_set_rx_mode(struct net_device *net_dev) { … } int efx_set_features(struct net_device *net_dev, netdev_features_t data) { … } /* This ensures that the kernel is kept informed (via * netif_carrier_on/off) of the link status, and also maintains the * link status's stop on the port's TX queue. */ void efx_link_status_changed(struct efx_nic *efx) { … } unsigned int efx_xdp_max_mtu(struct efx_nic *efx) { … } /* Context: process, rtnl_lock() held. */ int efx_change_mtu(struct net_device *net_dev, int new_mtu) { … } /************************************************************************** * * Hardware monitor * **************************************************************************/ /* Run periodically off the general workqueue */ static void efx_monitor(struct work_struct *data) { … } void efx_start_monitor(struct efx_nic *efx) { … } /************************************************************************** * * Event queue processing * *************************************************************************/ /* Channels are shutdown and reinitialised whilst the NIC is running * to propagate configuration changes (mtu, checksum offload), or * to clear hardware error conditions */ static void efx_start_datapath(struct efx_nic *efx) { … } static void efx_stop_datapath(struct efx_nic *efx) { … } /************************************************************************** * * Port handling * **************************************************************************/ /* Equivalent to efx_link_set_advertising with all-zeroes, except does not * force the Autoneg bit on. */ void efx_link_clear_advertising(struct efx_nic *efx) { … } void efx_link_set_wanted_fc(struct efx_nic *efx, u8 wanted_fc) { … } static void efx_start_port(struct efx_nic *efx) { … } /* Cancel work for MAC reconfiguration, periodic hardware monitoring * and the async self-test, wait for them to finish and prevent them * being scheduled again. This doesn't cover online resets, which * should only be cancelled when removing the device. */ static void efx_stop_port(struct efx_nic *efx) { … } /* If the interface is supposed to be running but is not, start * the hardware and software data path, regular activity for the port * (MAC statistics, link polling, etc.) and schedule the port to be * reconfigured. Interrupts must already be enabled. This function * is safe to call multiple times, so long as the NIC is not disabled. * Requires the RTNL lock. */ void efx_start_all(struct efx_nic *efx) { … } /* Quiesce the hardware and software data path, and regular activity * for the port without bringing the link down. Safe to call multiple * times with the NIC in almost any state, but interrupts should be * enabled. Requires the RTNL lock. */ void efx_stop_all(struct efx_nic *efx) { … } /* Context: process, rcu_read_lock or RTNL held, non-blocking. */ void efx_net_stats(struct net_device *net_dev, struct rtnl_link_stats64 *stats) { … } /* Push loopback/power/transmit disable settings to the PHY, and reconfigure * the MAC appropriately. All other PHY configuration changes are pushed * through phy_op->set_settings(), and pushed asynchronously to the MAC * through efx_monitor(). * * Callers must hold the mac_lock */ int __efx_reconfigure_port(struct efx_nic *efx) { … } /* Reinitialise the MAC to pick up new PHY settings, even if the port is * disabled. */ int efx_reconfigure_port(struct efx_nic *efx) { … } /************************************************************************** * * Device reset and suspend * **************************************************************************/ static void efx_wait_for_bist_end(struct efx_nic *efx) { … } /* Try recovery mechanisms. * For now only EEH is supported. * Returns 0 if the recovery mechanisms are unsuccessful. * Returns a non-zero value otherwise. */ int efx_try_recovery(struct efx_nic *efx) { … } /* Tears down the entire software state and most of the hardware state * before reset. */ void efx_reset_down(struct efx_nic *efx, enum reset_type method) { … } /* Context: netif_tx_lock held, BHs disabled. */ void efx_watchdog(struct net_device *net_dev, unsigned int txqueue) { … } /* This function will always ensure that the locks acquired in * efx_reset_down() are released. A failure return code indicates * that we were unable to reinitialise the hardware, and the * driver should be disabled. If ok is false, then the rx and tx * engines are not restarted, pending a RESET_DISABLE. */ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) { … } /* Reset the NIC using the specified method. Note that the reset may * fail, in which case the card will be left in an unusable state. * * Caller must hold the rtnl_lock. */ int efx_reset(struct efx_nic *efx, enum reset_type method) { … } /* The worker thread exists so that code that cannot sleep can * schedule a reset for later. */ static void efx_reset_work(struct work_struct *data) { … } void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) { … } /************************************************************************** * * Dummy NIC operations * * Can be used for some unimplemented operations * Needed so all function pointers are valid and do not have to be tested * before use * **************************************************************************/ int efx_port_dummy_op_int(struct efx_nic *efx) { … } void efx_port_dummy_op_void(struct efx_nic *efx) { … } /************************************************************************** * * Data housekeeping * **************************************************************************/ /* This zeroes out and then fills in the invariants in a struct * efx_nic (including all sub-structures). */ int efx_init_struct(struct efx_nic *efx, struct pci_dev *pci_dev) { … } void efx_fini_struct(struct efx_nic *efx) { … } /* This configures the PCI device to enable I/O and DMA. */ int efx_init_io(struct efx_nic *efx, int bar, dma_addr_t dma_mask, unsigned int mem_map_size) { … } void efx_fini_io(struct efx_nic *efx) { … } #ifdef CONFIG_SFC_MCDI_LOGGING static ssize_t mcdi_logging_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t mcdi_logging_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static DEVICE_ATTR_RW(mcdi_logging); void efx_init_mcdi_logging(struct efx_nic *efx) { … } void efx_fini_mcdi_logging(struct efx_nic *efx) { … } #endif /* A PCI error affecting this device was detected. * At this point MMIO and DMA may be disabled. * Stop the software path and request a slot reset. */ static pci_ers_result_t efx_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) { … } /* Fake a successful reset, which will be performed later in efx_io_resume. */ static pci_ers_result_t efx_io_slot_reset(struct pci_dev *pdev) { … } /* Perform the actual reset and resume I/O operations. */ static void efx_io_resume(struct pci_dev *pdev) { … } /* For simplicity and reliability, we always require a slot reset and try to * reset the hardware when a pci error affecting the device is detected. * We leave both the link_reset and mmio_enabled callback unimplemented: * with our request for slot reset the mmio_enabled callback will never be * called, and the link_reset callback is not used by AER or EEH mechanisms. */ const struct pci_error_handlers efx_err_handlers = …; /* Determine whether the NIC will be able to handle TX offloads for a given * encapsulated packet. */ static bool efx_can_encap_offloads(struct efx_nic *efx, struct sk_buff *skb) { … } netdev_features_t efx_features_check(struct sk_buff *skb, struct net_device *dev, netdev_features_t features) { … } int efx_get_phys_port_id(struct net_device *net_dev, struct netdev_phys_item_id *ppid) { … } int efx_get_phys_port_name(struct net_device *net_dev, char *name, size_t len) { … } void efx_detach_reps(struct efx_nic *efx) { … } void efx_attach_reps(struct efx_nic *efx) { … }