162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/**************************************************************************** 362306a36Sopenharmony_ci * Driver for Solarflare network controllers and boards 462306a36Sopenharmony_ci * Copyright 2018 Solarflare Communications Inc. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it 762306a36Sopenharmony_ci * under the terms of the GNU General Public License version 2 as published 862306a36Sopenharmony_ci * by the Free Software Foundation, incorporated herein by reference. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "net_driver.h" 1262306a36Sopenharmony_ci#include <linux/filter.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/netdevice.h> 1562306a36Sopenharmony_ci#include <net/gre.h> 1662306a36Sopenharmony_ci#include "efx_common.h" 1762306a36Sopenharmony_ci#include "efx_channels.h" 1862306a36Sopenharmony_ci#include "efx.h" 1962306a36Sopenharmony_ci#include "mcdi.h" 2062306a36Sopenharmony_ci#include "selftest.h" 2162306a36Sopenharmony_ci#include "rx_common.h" 2262306a36Sopenharmony_ci#include "tx_common.h" 2362306a36Sopenharmony_ci#include "nic.h" 2462306a36Sopenharmony_ci#include "mcdi_port_common.h" 2562306a36Sopenharmony_ci#include "io.h" 2662306a36Sopenharmony_ci#include "mcdi_pcol.h" 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic unsigned int debug = (NETIF_MSG_DRV | NETIF_MSG_PROBE | 2962306a36Sopenharmony_ci NETIF_MSG_LINK | NETIF_MSG_IFDOWN | 3062306a36Sopenharmony_ci NETIF_MSG_IFUP | NETIF_MSG_RX_ERR | 3162306a36Sopenharmony_ci NETIF_MSG_TX_ERR | NETIF_MSG_HW); 3262306a36Sopenharmony_cimodule_param(debug, uint, 0); 3362306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "Bitmapped debugging message enable value"); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* This is the time (in jiffies) between invocations of the hardware 3662306a36Sopenharmony_ci * monitor. 3762306a36Sopenharmony_ci * On Falcon-based NICs, this will: 3862306a36Sopenharmony_ci * - Check the on-board hardware monitor; 3962306a36Sopenharmony_ci * - Poll the link state and reconfigure the hardware as necessary. 4062306a36Sopenharmony_ci * On Siena-based NICs for power systems with EEH support, this will give EEH a 4162306a36Sopenharmony_ci * chance to start. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_cistatic unsigned int efx_monitor_interval = 1 * HZ; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* How often and how many times to poll for a reset while waiting for a 4662306a36Sopenharmony_ci * BIST that another function started to complete. 4762306a36Sopenharmony_ci */ 4862306a36Sopenharmony_ci#define BIST_WAIT_DELAY_MS 100 4962306a36Sopenharmony_ci#define BIST_WAIT_DELAY_COUNT 100 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* Default stats update time */ 5262306a36Sopenharmony_ci#define STATS_PERIOD_MS_DEFAULT 1000 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistatic const unsigned int efx_reset_type_max = RESET_TYPE_MAX; 5562306a36Sopenharmony_cistatic const char *const efx_reset_type_names[] = { 5662306a36Sopenharmony_ci [RESET_TYPE_INVISIBLE] = "INVISIBLE", 5762306a36Sopenharmony_ci [RESET_TYPE_ALL] = "ALL", 5862306a36Sopenharmony_ci [RESET_TYPE_RECOVER_OR_ALL] = "RECOVER_OR_ALL", 5962306a36Sopenharmony_ci [RESET_TYPE_WORLD] = "WORLD", 6062306a36Sopenharmony_ci [RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE", 6162306a36Sopenharmony_ci [RESET_TYPE_DATAPATH] = "DATAPATH", 6262306a36Sopenharmony_ci [RESET_TYPE_MC_BIST] = "MC_BIST", 6362306a36Sopenharmony_ci [RESET_TYPE_DISABLE] = "DISABLE", 6462306a36Sopenharmony_ci [RESET_TYPE_TX_WATCHDOG] = "TX_WATCHDOG", 6562306a36Sopenharmony_ci [RESET_TYPE_INT_ERROR] = "INT_ERROR", 6662306a36Sopenharmony_ci [RESET_TYPE_DMA_ERROR] = "DMA_ERROR", 6762306a36Sopenharmony_ci [RESET_TYPE_TX_SKIP] = "TX_SKIP", 6862306a36Sopenharmony_ci [RESET_TYPE_MC_FAILURE] = "MC_FAILURE", 6962306a36Sopenharmony_ci [RESET_TYPE_MCDI_TIMEOUT] = "MCDI_TIMEOUT (FLR)", 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci#define RESET_TYPE(type) \ 7362306a36Sopenharmony_ci STRING_TABLE_LOOKUP(type, efx_reset_type) 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/* Loopback mode names (see LOOPBACK_MODE()) */ 7662306a36Sopenharmony_ciconst unsigned int efx_siena_loopback_mode_max = LOOPBACK_MAX; 7762306a36Sopenharmony_ciconst char *const efx_siena_loopback_mode_names[] = { 7862306a36Sopenharmony_ci [LOOPBACK_NONE] = "NONE", 7962306a36Sopenharmony_ci [LOOPBACK_DATA] = "DATAPATH", 8062306a36Sopenharmony_ci [LOOPBACK_GMAC] = "GMAC", 8162306a36Sopenharmony_ci [LOOPBACK_XGMII] = "XGMII", 8262306a36Sopenharmony_ci [LOOPBACK_XGXS] = "XGXS", 8362306a36Sopenharmony_ci [LOOPBACK_XAUI] = "XAUI", 8462306a36Sopenharmony_ci [LOOPBACK_GMII] = "GMII", 8562306a36Sopenharmony_ci [LOOPBACK_SGMII] = "SGMII", 8662306a36Sopenharmony_ci [LOOPBACK_XGBR] = "XGBR", 8762306a36Sopenharmony_ci [LOOPBACK_XFI] = "XFI", 8862306a36Sopenharmony_ci [LOOPBACK_XAUI_FAR] = "XAUI_FAR", 8962306a36Sopenharmony_ci [LOOPBACK_GMII_FAR] = "GMII_FAR", 9062306a36Sopenharmony_ci [LOOPBACK_SGMII_FAR] = "SGMII_FAR", 9162306a36Sopenharmony_ci [LOOPBACK_XFI_FAR] = "XFI_FAR", 9262306a36Sopenharmony_ci [LOOPBACK_GPHY] = "GPHY", 9362306a36Sopenharmony_ci [LOOPBACK_PHYXS] = "PHYXS", 9462306a36Sopenharmony_ci [LOOPBACK_PCS] = "PCS", 9562306a36Sopenharmony_ci [LOOPBACK_PMAPMD] = "PMA/PMD", 9662306a36Sopenharmony_ci [LOOPBACK_XPORT] = "XPORT", 9762306a36Sopenharmony_ci [LOOPBACK_XGMII_WS] = "XGMII_WS", 9862306a36Sopenharmony_ci [LOOPBACK_XAUI_WS] = "XAUI_WS", 9962306a36Sopenharmony_ci [LOOPBACK_XAUI_WS_FAR] = "XAUI_WS_FAR", 10062306a36Sopenharmony_ci [LOOPBACK_XAUI_WS_NEAR] = "XAUI_WS_NEAR", 10162306a36Sopenharmony_ci [LOOPBACK_GMII_WS] = "GMII_WS", 10262306a36Sopenharmony_ci [LOOPBACK_XFI_WS] = "XFI_WS", 10362306a36Sopenharmony_ci [LOOPBACK_XFI_WS_FAR] = "XFI_WS_FAR", 10462306a36Sopenharmony_ci [LOOPBACK_PHYXS_WS] = "PHYXS_WS", 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci/* Reset workqueue. If any NIC has a hardware failure then a reset will be 10862306a36Sopenharmony_ci * queued onto this work queue. This is not a per-nic work queue, because 10962306a36Sopenharmony_ci * efx_reset_work() acquires the rtnl lock, so resets are naturally serialised. 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_cistatic struct workqueue_struct *reset_workqueue; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ciint efx_siena_create_reset_workqueue(void) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci reset_workqueue = create_singlethread_workqueue("sfc_siena_reset"); 11662306a36Sopenharmony_ci if (!reset_workqueue) { 11762306a36Sopenharmony_ci printk(KERN_ERR "Failed to create reset workqueue\n"); 11862306a36Sopenharmony_ci return -ENOMEM; 11962306a36Sopenharmony_ci } 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci return 0; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_civoid efx_siena_queue_reset_work(struct efx_nic *efx) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci queue_work(reset_workqueue, &efx->reset_work); 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_civoid efx_siena_flush_reset_workqueue(struct efx_nic *efx) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci cancel_work_sync(&efx->reset_work); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_civoid efx_siena_destroy_reset_workqueue(void) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci if (reset_workqueue) { 13762306a36Sopenharmony_ci destroy_workqueue(reset_workqueue); 13862306a36Sopenharmony_ci reset_workqueue = NULL; 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci/* We assume that efx->type->reconfigure_mac will always try to sync RX 14362306a36Sopenharmony_ci * filters and therefore needs to read-lock the filter table against freeing 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_civoid efx_siena_mac_reconfigure(struct efx_nic *efx, bool mtu_only) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci if (efx->type->reconfigure_mac) { 14862306a36Sopenharmony_ci down_read(&efx->filter_sem); 14962306a36Sopenharmony_ci efx->type->reconfigure_mac(efx, mtu_only); 15062306a36Sopenharmony_ci up_read(&efx->filter_sem); 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci/* Asynchronous work item for changing MAC promiscuity and multicast 15562306a36Sopenharmony_ci * hash. Avoid a drain/rx_ingress enable by reconfiguring the current 15662306a36Sopenharmony_ci * MAC directly. 15762306a36Sopenharmony_ci */ 15862306a36Sopenharmony_cistatic void efx_mac_work(struct work_struct *data) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci struct efx_nic *efx = container_of(data, struct efx_nic, mac_work); 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci mutex_lock(&efx->mac_lock); 16362306a36Sopenharmony_ci if (efx->port_enabled) 16462306a36Sopenharmony_ci efx_siena_mac_reconfigure(efx, false); 16562306a36Sopenharmony_ci mutex_unlock(&efx->mac_lock); 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ciint efx_siena_set_mac_address(struct net_device *net_dev, void *data) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci struct efx_nic *efx = netdev_priv(net_dev); 17162306a36Sopenharmony_ci struct sockaddr *addr = data; 17262306a36Sopenharmony_ci u8 *new_addr = addr->sa_data; 17362306a36Sopenharmony_ci u8 old_addr[6]; 17462306a36Sopenharmony_ci int rc; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci if (!is_valid_ether_addr(new_addr)) { 17762306a36Sopenharmony_ci netif_err(efx, drv, efx->net_dev, 17862306a36Sopenharmony_ci "invalid ethernet MAC address requested: %pM\n", 17962306a36Sopenharmony_ci new_addr); 18062306a36Sopenharmony_ci return -EADDRNOTAVAIL; 18162306a36Sopenharmony_ci } 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci /* save old address */ 18462306a36Sopenharmony_ci ether_addr_copy(old_addr, net_dev->dev_addr); 18562306a36Sopenharmony_ci eth_hw_addr_set(net_dev, new_addr); 18662306a36Sopenharmony_ci if (efx->type->set_mac_address) { 18762306a36Sopenharmony_ci rc = efx->type->set_mac_address(efx); 18862306a36Sopenharmony_ci if (rc) { 18962306a36Sopenharmony_ci eth_hw_addr_set(net_dev, old_addr); 19062306a36Sopenharmony_ci return rc; 19162306a36Sopenharmony_ci } 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci /* Reconfigure the MAC */ 19562306a36Sopenharmony_ci mutex_lock(&efx->mac_lock); 19662306a36Sopenharmony_ci efx_siena_mac_reconfigure(efx, false); 19762306a36Sopenharmony_ci mutex_unlock(&efx->mac_lock); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci return 0; 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci/* Context: netif_addr_lock held, BHs disabled. */ 20362306a36Sopenharmony_civoid efx_siena_set_rx_mode(struct net_device *net_dev) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci struct efx_nic *efx = netdev_priv(net_dev); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci if (efx->port_enabled) 20862306a36Sopenharmony_ci queue_work(efx->workqueue, &efx->mac_work); 20962306a36Sopenharmony_ci /* Otherwise efx_start_port() will do this */ 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ciint efx_siena_set_features(struct net_device *net_dev, netdev_features_t data) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci struct efx_nic *efx = netdev_priv(net_dev); 21562306a36Sopenharmony_ci int rc; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* If disabling RX n-tuple filtering, clear existing filters */ 21862306a36Sopenharmony_ci if (net_dev->features & ~data & NETIF_F_NTUPLE) { 21962306a36Sopenharmony_ci rc = efx->type->filter_clear_rx(efx, EFX_FILTER_PRI_MANUAL); 22062306a36Sopenharmony_ci if (rc) 22162306a36Sopenharmony_ci return rc; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci /* If Rx VLAN filter is changed, update filters via mac_reconfigure. 22562306a36Sopenharmony_ci * If rx-fcs is changed, mac_reconfigure updates that too. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ci if ((net_dev->features ^ data) & (NETIF_F_HW_VLAN_CTAG_FILTER | 22862306a36Sopenharmony_ci NETIF_F_RXFCS)) { 22962306a36Sopenharmony_ci /* efx_siena_set_rx_mode() will schedule MAC work to update filters 23062306a36Sopenharmony_ci * when a new features are finally set in net_dev. 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_ci efx_siena_set_rx_mode(net_dev); 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci return 0; 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci/* This ensures that the kernel is kept informed (via 23962306a36Sopenharmony_ci * netif_carrier_on/off) of the link status, and also maintains the 24062306a36Sopenharmony_ci * link status's stop on the port's TX queue. 24162306a36Sopenharmony_ci */ 24262306a36Sopenharmony_civoid efx_siena_link_status_changed(struct efx_nic *efx) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci struct efx_link_state *link_state = &efx->link_state; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci /* SFC Bug 5356: A net_dev notifier is registered, so we must ensure 24762306a36Sopenharmony_ci * that no events are triggered between unregister_netdev() and the 24862306a36Sopenharmony_ci * driver unloading. A more general condition is that NETDEV_CHANGE 24962306a36Sopenharmony_ci * can only be generated between NETDEV_UP and NETDEV_DOWN 25062306a36Sopenharmony_ci */ 25162306a36Sopenharmony_ci if (!netif_running(efx->net_dev)) 25262306a36Sopenharmony_ci return; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if (link_state->up != netif_carrier_ok(efx->net_dev)) { 25562306a36Sopenharmony_ci efx->n_link_state_changes++; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if (link_state->up) 25862306a36Sopenharmony_ci netif_carrier_on(efx->net_dev); 25962306a36Sopenharmony_ci else 26062306a36Sopenharmony_ci netif_carrier_off(efx->net_dev); 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* Status message for kernel log */ 26462306a36Sopenharmony_ci if (link_state->up) 26562306a36Sopenharmony_ci netif_info(efx, link, efx->net_dev, 26662306a36Sopenharmony_ci "link up at %uMbps %s-duplex (MTU %d)\n", 26762306a36Sopenharmony_ci link_state->speed, link_state->fd ? "full" : "half", 26862306a36Sopenharmony_ci efx->net_dev->mtu); 26962306a36Sopenharmony_ci else 27062306a36Sopenharmony_ci netif_info(efx, link, efx->net_dev, "link down\n"); 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ciunsigned int efx_siena_xdp_max_mtu(struct efx_nic *efx) 27462306a36Sopenharmony_ci{ 27562306a36Sopenharmony_ci /* The maximum MTU that we can fit in a single page, allowing for 27662306a36Sopenharmony_ci * framing, overhead and XDP headroom + tailroom. 27762306a36Sopenharmony_ci */ 27862306a36Sopenharmony_ci int overhead = EFX_MAX_FRAME_LEN(0) + sizeof(struct efx_rx_page_state) + 27962306a36Sopenharmony_ci efx->rx_prefix_size + efx->type->rx_buffer_padding + 28062306a36Sopenharmony_ci efx->rx_ip_align + EFX_XDP_HEADROOM + EFX_XDP_TAILROOM; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci return PAGE_SIZE - overhead; 28362306a36Sopenharmony_ci} 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci/* Context: process, rtnl_lock() held. */ 28662306a36Sopenharmony_ciint efx_siena_change_mtu(struct net_device *net_dev, int new_mtu) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci struct efx_nic *efx = netdev_priv(net_dev); 28962306a36Sopenharmony_ci int rc; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci rc = efx_check_disabled(efx); 29262306a36Sopenharmony_ci if (rc) 29362306a36Sopenharmony_ci return rc; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci if (rtnl_dereference(efx->xdp_prog) && 29662306a36Sopenharmony_ci new_mtu > efx_siena_xdp_max_mtu(efx)) { 29762306a36Sopenharmony_ci netif_err(efx, drv, efx->net_dev, 29862306a36Sopenharmony_ci "Requested MTU of %d too big for XDP (max: %d)\n", 29962306a36Sopenharmony_ci new_mtu, efx_siena_xdp_max_mtu(efx)); 30062306a36Sopenharmony_ci return -EINVAL; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci efx_device_detach_sync(efx); 30662306a36Sopenharmony_ci efx_siena_stop_all(efx); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci mutex_lock(&efx->mac_lock); 30962306a36Sopenharmony_ci net_dev->mtu = new_mtu; 31062306a36Sopenharmony_ci efx_siena_mac_reconfigure(efx, true); 31162306a36Sopenharmony_ci mutex_unlock(&efx->mac_lock); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci efx_siena_start_all(efx); 31462306a36Sopenharmony_ci efx_device_attach_if_not_resetting(efx); 31562306a36Sopenharmony_ci return 0; 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci/************************************************************************** 31962306a36Sopenharmony_ci * 32062306a36Sopenharmony_ci * Hardware monitor 32162306a36Sopenharmony_ci * 32262306a36Sopenharmony_ci **************************************************************************/ 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci/* Run periodically off the general workqueue */ 32562306a36Sopenharmony_cistatic void efx_monitor(struct work_struct *data) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci struct efx_nic *efx = container_of(data, struct efx_nic, 32862306a36Sopenharmony_ci monitor_work.work); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci netif_vdbg(efx, timer, efx->net_dev, 33162306a36Sopenharmony_ci "hardware monitor executing on CPU %d\n", 33262306a36Sopenharmony_ci raw_smp_processor_id()); 33362306a36Sopenharmony_ci BUG_ON(efx->type->monitor == NULL); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci /* If the mac_lock is already held then it is likely a port 33662306a36Sopenharmony_ci * reconfiguration is already in place, which will likely do 33762306a36Sopenharmony_ci * most of the work of monitor() anyway. 33862306a36Sopenharmony_ci */ 33962306a36Sopenharmony_ci if (mutex_trylock(&efx->mac_lock)) { 34062306a36Sopenharmony_ci if (efx->port_enabled && efx->type->monitor) 34162306a36Sopenharmony_ci efx->type->monitor(efx); 34262306a36Sopenharmony_ci mutex_unlock(&efx->mac_lock); 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci efx_siena_start_monitor(efx); 34662306a36Sopenharmony_ci} 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_civoid efx_siena_start_monitor(struct efx_nic *efx) 34962306a36Sopenharmony_ci{ 35062306a36Sopenharmony_ci if (efx->type->monitor) 35162306a36Sopenharmony_ci queue_delayed_work(efx->workqueue, &efx->monitor_work, 35262306a36Sopenharmony_ci efx_monitor_interval); 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci/************************************************************************** 35662306a36Sopenharmony_ci * 35762306a36Sopenharmony_ci * Event queue processing 35862306a36Sopenharmony_ci * 35962306a36Sopenharmony_ci *************************************************************************/ 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci/* Channels are shutdown and reinitialised whilst the NIC is running 36262306a36Sopenharmony_ci * to propagate configuration changes (mtu, checksum offload), or 36362306a36Sopenharmony_ci * to clear hardware error conditions 36462306a36Sopenharmony_ci */ 36562306a36Sopenharmony_cistatic void efx_start_datapath(struct efx_nic *efx) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci netdev_features_t old_features = efx->net_dev->features; 36862306a36Sopenharmony_ci bool old_rx_scatter = efx->rx_scatter; 36962306a36Sopenharmony_ci size_t rx_buf_len; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci /* Calculate the rx buffer allocation parameters required to 37262306a36Sopenharmony_ci * support the current MTU, including padding for header 37362306a36Sopenharmony_ci * alignment and overruns. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_ci efx->rx_dma_len = (efx->rx_prefix_size + 37662306a36Sopenharmony_ci EFX_MAX_FRAME_LEN(efx->net_dev->mtu) + 37762306a36Sopenharmony_ci efx->type->rx_buffer_padding); 37862306a36Sopenharmony_ci rx_buf_len = (sizeof(struct efx_rx_page_state) + EFX_XDP_HEADROOM + 37962306a36Sopenharmony_ci efx->rx_ip_align + efx->rx_dma_len + EFX_XDP_TAILROOM); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci if (rx_buf_len <= PAGE_SIZE) { 38262306a36Sopenharmony_ci efx->rx_scatter = efx->type->always_rx_scatter; 38362306a36Sopenharmony_ci efx->rx_buffer_order = 0; 38462306a36Sopenharmony_ci } else if (efx->type->can_rx_scatter) { 38562306a36Sopenharmony_ci BUILD_BUG_ON(EFX_RX_USR_BUF_SIZE % L1_CACHE_BYTES); 38662306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct efx_rx_page_state) + 38762306a36Sopenharmony_ci 2 * ALIGN(NET_IP_ALIGN + EFX_RX_USR_BUF_SIZE, 38862306a36Sopenharmony_ci EFX_RX_BUF_ALIGNMENT) > 38962306a36Sopenharmony_ci PAGE_SIZE); 39062306a36Sopenharmony_ci efx->rx_scatter = true; 39162306a36Sopenharmony_ci efx->rx_dma_len = EFX_RX_USR_BUF_SIZE; 39262306a36Sopenharmony_ci efx->rx_buffer_order = 0; 39362306a36Sopenharmony_ci } else { 39462306a36Sopenharmony_ci efx->rx_scatter = false; 39562306a36Sopenharmony_ci efx->rx_buffer_order = get_order(rx_buf_len); 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci efx_siena_rx_config_page_split(efx); 39962306a36Sopenharmony_ci if (efx->rx_buffer_order) 40062306a36Sopenharmony_ci netif_dbg(efx, drv, efx->net_dev, 40162306a36Sopenharmony_ci "RX buf len=%u; page order=%u batch=%u\n", 40262306a36Sopenharmony_ci efx->rx_dma_len, efx->rx_buffer_order, 40362306a36Sopenharmony_ci efx->rx_pages_per_batch); 40462306a36Sopenharmony_ci else 40562306a36Sopenharmony_ci netif_dbg(efx, drv, efx->net_dev, 40662306a36Sopenharmony_ci "RX buf len=%u step=%u bpp=%u; page batch=%u\n", 40762306a36Sopenharmony_ci efx->rx_dma_len, efx->rx_page_buf_step, 40862306a36Sopenharmony_ci efx->rx_bufs_per_page, efx->rx_pages_per_batch); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci /* Restore previously fixed features in hw_features and remove 41162306a36Sopenharmony_ci * features which are fixed now 41262306a36Sopenharmony_ci */ 41362306a36Sopenharmony_ci efx->net_dev->hw_features |= efx->net_dev->features; 41462306a36Sopenharmony_ci efx->net_dev->hw_features &= ~efx->fixed_features; 41562306a36Sopenharmony_ci efx->net_dev->features |= efx->fixed_features; 41662306a36Sopenharmony_ci if (efx->net_dev->features != old_features) 41762306a36Sopenharmony_ci netdev_features_change(efx->net_dev); 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci /* RX filters may also have scatter-enabled flags */ 42062306a36Sopenharmony_ci if ((efx->rx_scatter != old_rx_scatter) && 42162306a36Sopenharmony_ci efx->type->filter_update_rx_scatter) 42262306a36Sopenharmony_ci efx->type->filter_update_rx_scatter(efx); 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci /* We must keep at least one descriptor in a TX ring empty. 42562306a36Sopenharmony_ci * We could avoid this when the queue size does not exactly 42662306a36Sopenharmony_ci * match the hardware ring size, but it's not that important. 42762306a36Sopenharmony_ci * Therefore we stop the queue when one more skb might fill 42862306a36Sopenharmony_ci * the ring completely. We wake it when half way back to 42962306a36Sopenharmony_ci * empty. 43062306a36Sopenharmony_ci */ 43162306a36Sopenharmony_ci efx->txq_stop_thresh = efx->txq_entries - efx_siena_tx_max_skb_descs(efx); 43262306a36Sopenharmony_ci efx->txq_wake_thresh = efx->txq_stop_thresh / 2; 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci /* Initialise the channels */ 43562306a36Sopenharmony_ci efx_siena_start_channels(efx); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci efx_siena_ptp_start_datapath(efx); 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci if (netif_device_present(efx->net_dev)) 44062306a36Sopenharmony_ci netif_tx_wake_all_queues(efx->net_dev); 44162306a36Sopenharmony_ci} 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_cistatic void efx_stop_datapath(struct efx_nic *efx) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci EFX_ASSERT_RESET_SERIALISED(efx); 44662306a36Sopenharmony_ci BUG_ON(efx->port_enabled); 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci efx_siena_ptp_stop_datapath(efx); 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci efx_siena_stop_channels(efx); 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci/************************************************************************** 45462306a36Sopenharmony_ci * 45562306a36Sopenharmony_ci * Port handling 45662306a36Sopenharmony_ci * 45762306a36Sopenharmony_ci **************************************************************************/ 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci/* Equivalent to efx_siena_link_set_advertising with all-zeroes, except does not 46062306a36Sopenharmony_ci * force the Autoneg bit on. 46162306a36Sopenharmony_ci */ 46262306a36Sopenharmony_civoid efx_siena_link_clear_advertising(struct efx_nic *efx) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci bitmap_zero(efx->link_advertising, __ETHTOOL_LINK_MODE_MASK_NBITS); 46562306a36Sopenharmony_ci efx->wanted_fc &= ~(EFX_FC_TX | EFX_FC_RX); 46662306a36Sopenharmony_ci} 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_civoid efx_siena_link_set_wanted_fc(struct efx_nic *efx, u8 wanted_fc) 46962306a36Sopenharmony_ci{ 47062306a36Sopenharmony_ci efx->wanted_fc = wanted_fc; 47162306a36Sopenharmony_ci if (efx->link_advertising[0]) { 47262306a36Sopenharmony_ci if (wanted_fc & EFX_FC_RX) 47362306a36Sopenharmony_ci efx->link_advertising[0] |= (ADVERTISED_Pause | 47462306a36Sopenharmony_ci ADVERTISED_Asym_Pause); 47562306a36Sopenharmony_ci else 47662306a36Sopenharmony_ci efx->link_advertising[0] &= ~(ADVERTISED_Pause | 47762306a36Sopenharmony_ci ADVERTISED_Asym_Pause); 47862306a36Sopenharmony_ci if (wanted_fc & EFX_FC_TX) 47962306a36Sopenharmony_ci efx->link_advertising[0] ^= ADVERTISED_Asym_Pause; 48062306a36Sopenharmony_ci } 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_cistatic void efx_start_port(struct efx_nic *efx) 48462306a36Sopenharmony_ci{ 48562306a36Sopenharmony_ci netif_dbg(efx, ifup, efx->net_dev, "start port\n"); 48662306a36Sopenharmony_ci BUG_ON(efx->port_enabled); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci mutex_lock(&efx->mac_lock); 48962306a36Sopenharmony_ci efx->port_enabled = true; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci /* Ensure MAC ingress/egress is enabled */ 49262306a36Sopenharmony_ci efx_siena_mac_reconfigure(efx, false); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci mutex_unlock(&efx->mac_lock); 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci/* Cancel work for MAC reconfiguration, periodic hardware monitoring 49862306a36Sopenharmony_ci * and the async self-test, wait for them to finish and prevent them 49962306a36Sopenharmony_ci * being scheduled again. This doesn't cover online resets, which 50062306a36Sopenharmony_ci * should only be cancelled when removing the device. 50162306a36Sopenharmony_ci */ 50262306a36Sopenharmony_cistatic void efx_stop_port(struct efx_nic *efx) 50362306a36Sopenharmony_ci{ 50462306a36Sopenharmony_ci netif_dbg(efx, ifdown, efx->net_dev, "stop port\n"); 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci EFX_ASSERT_RESET_SERIALISED(efx); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci mutex_lock(&efx->mac_lock); 50962306a36Sopenharmony_ci efx->port_enabled = false; 51062306a36Sopenharmony_ci mutex_unlock(&efx->mac_lock); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci /* Serialise against efx_set_multicast_list() */ 51362306a36Sopenharmony_ci netif_addr_lock_bh(efx->net_dev); 51462306a36Sopenharmony_ci netif_addr_unlock_bh(efx->net_dev); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci cancel_delayed_work_sync(&efx->monitor_work); 51762306a36Sopenharmony_ci efx_siena_selftest_async_cancel(efx); 51862306a36Sopenharmony_ci cancel_work_sync(&efx->mac_work); 51962306a36Sopenharmony_ci} 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci/* If the interface is supposed to be running but is not, start 52262306a36Sopenharmony_ci * the hardware and software data path, regular activity for the port 52362306a36Sopenharmony_ci * (MAC statistics, link polling, etc.) and schedule the port to be 52462306a36Sopenharmony_ci * reconfigured. Interrupts must already be enabled. This function 52562306a36Sopenharmony_ci * is safe to call multiple times, so long as the NIC is not disabled. 52662306a36Sopenharmony_ci * Requires the RTNL lock. 52762306a36Sopenharmony_ci */ 52862306a36Sopenharmony_civoid efx_siena_start_all(struct efx_nic *efx) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci EFX_ASSERT_RESET_SERIALISED(efx); 53162306a36Sopenharmony_ci BUG_ON(efx->state == STATE_DISABLED); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci /* Check that it is appropriate to restart the interface. All 53462306a36Sopenharmony_ci * of these flags are safe to read under just the rtnl lock 53562306a36Sopenharmony_ci */ 53662306a36Sopenharmony_ci if (efx->port_enabled || !netif_running(efx->net_dev) || 53762306a36Sopenharmony_ci efx->reset_pending) 53862306a36Sopenharmony_ci return; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci efx_start_port(efx); 54162306a36Sopenharmony_ci efx_start_datapath(efx); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci /* Start the hardware monitor if there is one */ 54462306a36Sopenharmony_ci efx_siena_start_monitor(efx); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci /* Link state detection is normally event-driven; we have 54762306a36Sopenharmony_ci * to poll now because we could have missed a change 54862306a36Sopenharmony_ci */ 54962306a36Sopenharmony_ci mutex_lock(&efx->mac_lock); 55062306a36Sopenharmony_ci if (efx_siena_mcdi_phy_poll(efx)) 55162306a36Sopenharmony_ci efx_siena_link_status_changed(efx); 55262306a36Sopenharmony_ci mutex_unlock(&efx->mac_lock); 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci if (efx->type->start_stats) { 55562306a36Sopenharmony_ci efx->type->start_stats(efx); 55662306a36Sopenharmony_ci efx->type->pull_stats(efx); 55762306a36Sopenharmony_ci spin_lock_bh(&efx->stats_lock); 55862306a36Sopenharmony_ci efx->type->update_stats(efx, NULL, NULL); 55962306a36Sopenharmony_ci spin_unlock_bh(&efx->stats_lock); 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci} 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci/* Quiesce the hardware and software data path, and regular activity 56462306a36Sopenharmony_ci * for the port without bringing the link down. Safe to call multiple 56562306a36Sopenharmony_ci * times with the NIC in almost any state, but interrupts should be 56662306a36Sopenharmony_ci * enabled. Requires the RTNL lock. 56762306a36Sopenharmony_ci */ 56862306a36Sopenharmony_civoid efx_siena_stop_all(struct efx_nic *efx) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci EFX_ASSERT_RESET_SERIALISED(efx); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci /* port_enabled can be read safely under the rtnl lock */ 57362306a36Sopenharmony_ci if (!efx->port_enabled) 57462306a36Sopenharmony_ci return; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci if (efx->type->update_stats) { 57762306a36Sopenharmony_ci /* update stats before we go down so we can accurately count 57862306a36Sopenharmony_ci * rx_nodesc_drops 57962306a36Sopenharmony_ci */ 58062306a36Sopenharmony_ci efx->type->pull_stats(efx); 58162306a36Sopenharmony_ci spin_lock_bh(&efx->stats_lock); 58262306a36Sopenharmony_ci efx->type->update_stats(efx, NULL, NULL); 58362306a36Sopenharmony_ci spin_unlock_bh(&efx->stats_lock); 58462306a36Sopenharmony_ci efx->type->stop_stats(efx); 58562306a36Sopenharmony_ci } 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci efx_stop_port(efx); 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci /* Stop the kernel transmit interface. This is only valid if 59062306a36Sopenharmony_ci * the device is stopped or detached; otherwise the watchdog 59162306a36Sopenharmony_ci * may fire immediately. 59262306a36Sopenharmony_ci */ 59362306a36Sopenharmony_ci WARN_ON(netif_running(efx->net_dev) && 59462306a36Sopenharmony_ci netif_device_present(efx->net_dev)); 59562306a36Sopenharmony_ci netif_tx_disable(efx->net_dev); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci efx_stop_datapath(efx); 59862306a36Sopenharmony_ci} 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic size_t efx_siena_update_stats_atomic(struct efx_nic *efx, u64 *full_stats, 60162306a36Sopenharmony_ci struct rtnl_link_stats64 *core_stats) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci if (efx->type->update_stats_atomic) 60462306a36Sopenharmony_ci return efx->type->update_stats_atomic(efx, full_stats, core_stats); 60562306a36Sopenharmony_ci return efx->type->update_stats(efx, full_stats, core_stats); 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci/* Context: process, dev_base_lock or RTNL held, non-blocking. */ 60962306a36Sopenharmony_civoid efx_siena_net_stats(struct net_device *net_dev, 61062306a36Sopenharmony_ci struct rtnl_link_stats64 *stats) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci struct efx_nic *efx = netdev_priv(net_dev); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci spin_lock_bh(&efx->stats_lock); 61562306a36Sopenharmony_ci efx_siena_update_stats_atomic(efx, NULL, stats); 61662306a36Sopenharmony_ci spin_unlock_bh(&efx->stats_lock); 61762306a36Sopenharmony_ci} 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci/* Push loopback/power/transmit disable settings to the PHY, and reconfigure 62062306a36Sopenharmony_ci * the MAC appropriately. All other PHY configuration changes are pushed 62162306a36Sopenharmony_ci * through phy_op->set_settings(), and pushed asynchronously to the MAC 62262306a36Sopenharmony_ci * through efx_monitor(). 62362306a36Sopenharmony_ci * 62462306a36Sopenharmony_ci * Callers must hold the mac_lock 62562306a36Sopenharmony_ci */ 62662306a36Sopenharmony_ciint __efx_siena_reconfigure_port(struct efx_nic *efx) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci enum efx_phy_mode phy_mode; 62962306a36Sopenharmony_ci int rc = 0; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci WARN_ON(!mutex_is_locked(&efx->mac_lock)); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci /* Disable PHY transmit in mac level loopbacks */ 63462306a36Sopenharmony_ci phy_mode = efx->phy_mode; 63562306a36Sopenharmony_ci if (LOOPBACK_INTERNAL(efx)) 63662306a36Sopenharmony_ci efx->phy_mode |= PHY_MODE_TX_DISABLED; 63762306a36Sopenharmony_ci else 63862306a36Sopenharmony_ci efx->phy_mode &= ~PHY_MODE_TX_DISABLED; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci if (efx->type->reconfigure_port) 64162306a36Sopenharmony_ci rc = efx->type->reconfigure_port(efx); 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci if (rc) 64462306a36Sopenharmony_ci efx->phy_mode = phy_mode; 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci return rc; 64762306a36Sopenharmony_ci} 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci/* Reinitialise the MAC to pick up new PHY settings, even if the port is 65062306a36Sopenharmony_ci * disabled. 65162306a36Sopenharmony_ci */ 65262306a36Sopenharmony_ciint efx_siena_reconfigure_port(struct efx_nic *efx) 65362306a36Sopenharmony_ci{ 65462306a36Sopenharmony_ci int rc; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci EFX_ASSERT_RESET_SERIALISED(efx); 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci mutex_lock(&efx->mac_lock); 65962306a36Sopenharmony_ci rc = __efx_siena_reconfigure_port(efx); 66062306a36Sopenharmony_ci mutex_unlock(&efx->mac_lock); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci return rc; 66362306a36Sopenharmony_ci} 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci/************************************************************************** 66662306a36Sopenharmony_ci * 66762306a36Sopenharmony_ci * Device reset and suspend 66862306a36Sopenharmony_ci * 66962306a36Sopenharmony_ci **************************************************************************/ 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_cistatic void efx_wait_for_bist_end(struct efx_nic *efx) 67262306a36Sopenharmony_ci{ 67362306a36Sopenharmony_ci int i; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci for (i = 0; i < BIST_WAIT_DELAY_COUNT; ++i) { 67662306a36Sopenharmony_ci if (efx_siena_mcdi_poll_reboot(efx)) 67762306a36Sopenharmony_ci goto out; 67862306a36Sopenharmony_ci msleep(BIST_WAIT_DELAY_MS); 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci netif_err(efx, drv, efx->net_dev, "Warning: No MC reboot after BIST mode\n"); 68262306a36Sopenharmony_ciout: 68362306a36Sopenharmony_ci /* Either way unset the BIST flag. If we found no reboot we probably 68462306a36Sopenharmony_ci * won't recover, but we should try. 68562306a36Sopenharmony_ci */ 68662306a36Sopenharmony_ci efx->mc_bist_for_other_fn = false; 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci/* Try recovery mechanisms. 69062306a36Sopenharmony_ci * For now only EEH is supported. 69162306a36Sopenharmony_ci * Returns 0 if the recovery mechanisms are unsuccessful. 69262306a36Sopenharmony_ci * Returns a non-zero value otherwise. 69362306a36Sopenharmony_ci */ 69462306a36Sopenharmony_ciint efx_siena_try_recovery(struct efx_nic *efx) 69562306a36Sopenharmony_ci{ 69662306a36Sopenharmony_ci#ifdef CONFIG_EEH 69762306a36Sopenharmony_ci /* A PCI error can occur and not be seen by EEH because nothing 69862306a36Sopenharmony_ci * happens on the PCI bus. In this case the driver may fail and 69962306a36Sopenharmony_ci * schedule a 'recover or reset', leading to this recovery handler. 70062306a36Sopenharmony_ci * Manually call the eeh failure check function. 70162306a36Sopenharmony_ci */ 70262306a36Sopenharmony_ci struct eeh_dev *eehdev = pci_dev_to_eeh_dev(efx->pci_dev); 70362306a36Sopenharmony_ci if (eeh_dev_check_failure(eehdev)) { 70462306a36Sopenharmony_ci /* The EEH mechanisms will handle the error and reset the 70562306a36Sopenharmony_ci * device if necessary. 70662306a36Sopenharmony_ci */ 70762306a36Sopenharmony_ci return 1; 70862306a36Sopenharmony_ci } 70962306a36Sopenharmony_ci#endif 71062306a36Sopenharmony_ci return 0; 71162306a36Sopenharmony_ci} 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci/* Tears down the entire software state and most of the hardware state 71462306a36Sopenharmony_ci * before reset. 71562306a36Sopenharmony_ci */ 71662306a36Sopenharmony_civoid efx_siena_reset_down(struct efx_nic *efx, enum reset_type method) 71762306a36Sopenharmony_ci{ 71862306a36Sopenharmony_ci EFX_ASSERT_RESET_SERIALISED(efx); 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci if (method == RESET_TYPE_MCDI_TIMEOUT) 72162306a36Sopenharmony_ci efx->type->prepare_flr(efx); 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci efx_siena_stop_all(efx); 72462306a36Sopenharmony_ci efx_siena_disable_interrupts(efx); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci mutex_lock(&efx->mac_lock); 72762306a36Sopenharmony_ci down_write(&efx->filter_sem); 72862306a36Sopenharmony_ci mutex_lock(&efx->rss_lock); 72962306a36Sopenharmony_ci efx->type->fini(efx); 73062306a36Sopenharmony_ci} 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci/* Context: netif_tx_lock held, BHs disabled. */ 73362306a36Sopenharmony_civoid efx_siena_watchdog(struct net_device *net_dev, unsigned int txqueue) 73462306a36Sopenharmony_ci{ 73562306a36Sopenharmony_ci struct efx_nic *efx = netdev_priv(net_dev); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci netif_err(efx, tx_err, efx->net_dev, 73862306a36Sopenharmony_ci "TX stuck with port_enabled=%d: resetting channels\n", 73962306a36Sopenharmony_ci efx->port_enabled); 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci efx_siena_schedule_reset(efx, RESET_TYPE_TX_WATCHDOG); 74262306a36Sopenharmony_ci} 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci/* This function will always ensure that the locks acquired in 74562306a36Sopenharmony_ci * efx_siena_reset_down() are released. A failure return code indicates 74662306a36Sopenharmony_ci * that we were unable to reinitialise the hardware, and the 74762306a36Sopenharmony_ci * driver should be disabled. If ok is false, then the rx and tx 74862306a36Sopenharmony_ci * engines are not restarted, pending a RESET_DISABLE. 74962306a36Sopenharmony_ci */ 75062306a36Sopenharmony_ciint efx_siena_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) 75162306a36Sopenharmony_ci{ 75262306a36Sopenharmony_ci int rc; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci EFX_ASSERT_RESET_SERIALISED(efx); 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci if (method == RESET_TYPE_MCDI_TIMEOUT) 75762306a36Sopenharmony_ci efx->type->finish_flr(efx); 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci /* Ensure that SRAM is initialised even if we're disabling the device */ 76062306a36Sopenharmony_ci rc = efx->type->init(efx); 76162306a36Sopenharmony_ci if (rc) { 76262306a36Sopenharmony_ci netif_err(efx, drv, efx->net_dev, "failed to initialise NIC\n"); 76362306a36Sopenharmony_ci goto fail; 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci if (!ok) 76762306a36Sopenharmony_ci goto fail; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci if (efx->port_initialized && method != RESET_TYPE_INVISIBLE && 77062306a36Sopenharmony_ci method != RESET_TYPE_DATAPATH) { 77162306a36Sopenharmony_ci rc = efx_siena_mcdi_port_reconfigure(efx); 77262306a36Sopenharmony_ci if (rc && rc != -EPERM) 77362306a36Sopenharmony_ci netif_err(efx, drv, efx->net_dev, 77462306a36Sopenharmony_ci "could not restore PHY settings\n"); 77562306a36Sopenharmony_ci } 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci rc = efx_siena_enable_interrupts(efx); 77862306a36Sopenharmony_ci if (rc) 77962306a36Sopenharmony_ci goto fail; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci#ifdef CONFIG_SFC_SIENA_SRIOV 78262306a36Sopenharmony_ci rc = efx->type->vswitching_restore(efx); 78362306a36Sopenharmony_ci if (rc) /* not fatal; the PF will still work fine */ 78462306a36Sopenharmony_ci netif_warn(efx, probe, efx->net_dev, 78562306a36Sopenharmony_ci "failed to restore vswitching rc=%d;" 78662306a36Sopenharmony_ci " VFs may not function\n", rc); 78762306a36Sopenharmony_ci#endif 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci if (efx->type->rx_restore_rss_contexts) 79062306a36Sopenharmony_ci efx->type->rx_restore_rss_contexts(efx); 79162306a36Sopenharmony_ci mutex_unlock(&efx->rss_lock); 79262306a36Sopenharmony_ci efx->type->filter_table_restore(efx); 79362306a36Sopenharmony_ci up_write(&efx->filter_sem); 79462306a36Sopenharmony_ci if (efx->type->sriov_reset) 79562306a36Sopenharmony_ci efx->type->sriov_reset(efx); 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci mutex_unlock(&efx->mac_lock); 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci efx_siena_start_all(efx); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci if (efx->type->udp_tnl_push_ports) 80262306a36Sopenharmony_ci efx->type->udp_tnl_push_ports(efx); 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci return 0; 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_cifail: 80762306a36Sopenharmony_ci efx->port_initialized = false; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci mutex_unlock(&efx->rss_lock); 81062306a36Sopenharmony_ci up_write(&efx->filter_sem); 81162306a36Sopenharmony_ci mutex_unlock(&efx->mac_lock); 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci return rc; 81462306a36Sopenharmony_ci} 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci/* Reset the NIC using the specified method. Note that the reset may 81762306a36Sopenharmony_ci * fail, in which case the card will be left in an unusable state. 81862306a36Sopenharmony_ci * 81962306a36Sopenharmony_ci * Caller must hold the rtnl_lock. 82062306a36Sopenharmony_ci */ 82162306a36Sopenharmony_ciint efx_siena_reset(struct efx_nic *efx, enum reset_type method) 82262306a36Sopenharmony_ci{ 82362306a36Sopenharmony_ci int rc, rc2 = 0; 82462306a36Sopenharmony_ci bool disabled; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci netif_info(efx, drv, efx->net_dev, "resetting (%s)\n", 82762306a36Sopenharmony_ci RESET_TYPE(method)); 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci efx_device_detach_sync(efx); 83062306a36Sopenharmony_ci /* efx_siena_reset_down() grabs locks that prevent recovery on EF100. 83162306a36Sopenharmony_ci * EF100 reset is handled in the efx_nic_type callback below. 83262306a36Sopenharmony_ci */ 83362306a36Sopenharmony_ci if (efx_nic_rev(efx) != EFX_REV_EF100) 83462306a36Sopenharmony_ci efx_siena_reset_down(efx, method); 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci rc = efx->type->reset(efx, method); 83762306a36Sopenharmony_ci if (rc) { 83862306a36Sopenharmony_ci netif_err(efx, drv, efx->net_dev, "failed to reset hardware\n"); 83962306a36Sopenharmony_ci goto out; 84062306a36Sopenharmony_ci } 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci /* Clear flags for the scopes we covered. We assume the NIC and 84362306a36Sopenharmony_ci * driver are now quiescent so that there is no race here. 84462306a36Sopenharmony_ci */ 84562306a36Sopenharmony_ci if (method < RESET_TYPE_MAX_METHOD) 84662306a36Sopenharmony_ci efx->reset_pending &= -(1 << (method + 1)); 84762306a36Sopenharmony_ci else /* it doesn't fit into the well-ordered scope hierarchy */ 84862306a36Sopenharmony_ci __clear_bit(method, &efx->reset_pending); 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci /* Reinitialise bus-mastering, which may have been turned off before 85162306a36Sopenharmony_ci * the reset was scheduled. This is still appropriate, even in the 85262306a36Sopenharmony_ci * RESET_TYPE_DISABLE since this driver generally assumes the hardware 85362306a36Sopenharmony_ci * can respond to requests. 85462306a36Sopenharmony_ci */ 85562306a36Sopenharmony_ci pci_set_master(efx->pci_dev); 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ciout: 85862306a36Sopenharmony_ci /* Leave device stopped if necessary */ 85962306a36Sopenharmony_ci disabled = rc || 86062306a36Sopenharmony_ci method == RESET_TYPE_DISABLE || 86162306a36Sopenharmony_ci method == RESET_TYPE_RECOVER_OR_DISABLE; 86262306a36Sopenharmony_ci if (efx_nic_rev(efx) != EFX_REV_EF100) 86362306a36Sopenharmony_ci rc2 = efx_siena_reset_up(efx, method, !disabled); 86462306a36Sopenharmony_ci if (rc2) { 86562306a36Sopenharmony_ci disabled = true; 86662306a36Sopenharmony_ci if (!rc) 86762306a36Sopenharmony_ci rc = rc2; 86862306a36Sopenharmony_ci } 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci if (disabled) { 87162306a36Sopenharmony_ci dev_close(efx->net_dev); 87262306a36Sopenharmony_ci netif_err(efx, drv, efx->net_dev, "has been disabled\n"); 87362306a36Sopenharmony_ci efx->state = STATE_DISABLED; 87462306a36Sopenharmony_ci } else { 87562306a36Sopenharmony_ci netif_dbg(efx, drv, efx->net_dev, "reset complete\n"); 87662306a36Sopenharmony_ci efx_device_attach_if_not_resetting(efx); 87762306a36Sopenharmony_ci } 87862306a36Sopenharmony_ci return rc; 87962306a36Sopenharmony_ci} 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci/* The worker thread exists so that code that cannot sleep can 88262306a36Sopenharmony_ci * schedule a reset for later. 88362306a36Sopenharmony_ci */ 88462306a36Sopenharmony_cistatic void efx_reset_work(struct work_struct *data) 88562306a36Sopenharmony_ci{ 88662306a36Sopenharmony_ci struct efx_nic *efx = container_of(data, struct efx_nic, reset_work); 88762306a36Sopenharmony_ci unsigned long pending; 88862306a36Sopenharmony_ci enum reset_type method; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci pending = READ_ONCE(efx->reset_pending); 89162306a36Sopenharmony_ci method = fls(pending) - 1; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci if (method == RESET_TYPE_MC_BIST) 89462306a36Sopenharmony_ci efx_wait_for_bist_end(efx); 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci if ((method == RESET_TYPE_RECOVER_OR_DISABLE || 89762306a36Sopenharmony_ci method == RESET_TYPE_RECOVER_OR_ALL) && 89862306a36Sopenharmony_ci efx_siena_try_recovery(efx)) 89962306a36Sopenharmony_ci return; 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci if (!pending) 90262306a36Sopenharmony_ci return; 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci rtnl_lock(); 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci /* We checked the state in efx_siena_schedule_reset() but it may 90762306a36Sopenharmony_ci * have changed by now. Now that we have the RTNL lock, 90862306a36Sopenharmony_ci * it cannot change again. 90962306a36Sopenharmony_ci */ 91062306a36Sopenharmony_ci if (efx->state == STATE_READY) 91162306a36Sopenharmony_ci (void)efx_siena_reset(efx, method); 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci rtnl_unlock(); 91462306a36Sopenharmony_ci} 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_civoid efx_siena_schedule_reset(struct efx_nic *efx, enum reset_type type) 91762306a36Sopenharmony_ci{ 91862306a36Sopenharmony_ci enum reset_type method; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci if (efx->state == STATE_RECOVERY) { 92162306a36Sopenharmony_ci netif_dbg(efx, drv, efx->net_dev, 92262306a36Sopenharmony_ci "recovering: skip scheduling %s reset\n", 92362306a36Sopenharmony_ci RESET_TYPE(type)); 92462306a36Sopenharmony_ci return; 92562306a36Sopenharmony_ci } 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci switch (type) { 92862306a36Sopenharmony_ci case RESET_TYPE_INVISIBLE: 92962306a36Sopenharmony_ci case RESET_TYPE_ALL: 93062306a36Sopenharmony_ci case RESET_TYPE_RECOVER_OR_ALL: 93162306a36Sopenharmony_ci case RESET_TYPE_WORLD: 93262306a36Sopenharmony_ci case RESET_TYPE_DISABLE: 93362306a36Sopenharmony_ci case RESET_TYPE_RECOVER_OR_DISABLE: 93462306a36Sopenharmony_ci case RESET_TYPE_DATAPATH: 93562306a36Sopenharmony_ci case RESET_TYPE_MC_BIST: 93662306a36Sopenharmony_ci case RESET_TYPE_MCDI_TIMEOUT: 93762306a36Sopenharmony_ci method = type; 93862306a36Sopenharmony_ci netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", 93962306a36Sopenharmony_ci RESET_TYPE(method)); 94062306a36Sopenharmony_ci break; 94162306a36Sopenharmony_ci default: 94262306a36Sopenharmony_ci method = efx->type->map_reset_reason(type); 94362306a36Sopenharmony_ci netif_dbg(efx, drv, efx->net_dev, 94462306a36Sopenharmony_ci "scheduling %s reset for %s\n", 94562306a36Sopenharmony_ci RESET_TYPE(method), RESET_TYPE(type)); 94662306a36Sopenharmony_ci break; 94762306a36Sopenharmony_ci } 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci set_bit(method, &efx->reset_pending); 95062306a36Sopenharmony_ci smp_mb(); /* ensure we change reset_pending before checking state */ 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci /* If we're not READY then just leave the flags set as the cue 95362306a36Sopenharmony_ci * to abort probing or reschedule the reset later. 95462306a36Sopenharmony_ci */ 95562306a36Sopenharmony_ci if (READ_ONCE(efx->state) != STATE_READY) 95662306a36Sopenharmony_ci return; 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci /* efx_process_channel() will no longer read events once a 95962306a36Sopenharmony_ci * reset is scheduled. So switch back to poll'd MCDI completions. 96062306a36Sopenharmony_ci */ 96162306a36Sopenharmony_ci efx_siena_mcdi_mode_poll(efx); 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci efx_siena_queue_reset_work(efx); 96462306a36Sopenharmony_ci} 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci/************************************************************************** 96762306a36Sopenharmony_ci * 96862306a36Sopenharmony_ci * Dummy NIC operations 96962306a36Sopenharmony_ci * 97062306a36Sopenharmony_ci * Can be used for some unimplemented operations 97162306a36Sopenharmony_ci * Needed so all function pointers are valid and do not have to be tested 97262306a36Sopenharmony_ci * before use 97362306a36Sopenharmony_ci * 97462306a36Sopenharmony_ci **************************************************************************/ 97562306a36Sopenharmony_ciint efx_siena_port_dummy_op_int(struct efx_nic *efx) 97662306a36Sopenharmony_ci{ 97762306a36Sopenharmony_ci return 0; 97862306a36Sopenharmony_ci} 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_civoid efx_siena_port_dummy_op_void(struct efx_nic *efx) {} 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci/************************************************************************** 98362306a36Sopenharmony_ci * 98462306a36Sopenharmony_ci * Data housekeeping 98562306a36Sopenharmony_ci * 98662306a36Sopenharmony_ci **************************************************************************/ 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_ci/* This zeroes out and then fills in the invariants in a struct 98962306a36Sopenharmony_ci * efx_nic (including all sub-structures). 99062306a36Sopenharmony_ci */ 99162306a36Sopenharmony_ciint efx_siena_init_struct(struct efx_nic *efx, 99262306a36Sopenharmony_ci struct pci_dev *pci_dev, struct net_device *net_dev) 99362306a36Sopenharmony_ci{ 99462306a36Sopenharmony_ci int rc = -ENOMEM; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci /* Initialise common structures */ 99762306a36Sopenharmony_ci INIT_LIST_HEAD(&efx->node); 99862306a36Sopenharmony_ci INIT_LIST_HEAD(&efx->secondary_list); 99962306a36Sopenharmony_ci spin_lock_init(&efx->biu_lock); 100062306a36Sopenharmony_ci#ifdef CONFIG_SFC_SIENA_MTD 100162306a36Sopenharmony_ci INIT_LIST_HEAD(&efx->mtd_list); 100262306a36Sopenharmony_ci#endif 100362306a36Sopenharmony_ci INIT_WORK(&efx->reset_work, efx_reset_work); 100462306a36Sopenharmony_ci INIT_DELAYED_WORK(&efx->monitor_work, efx_monitor); 100562306a36Sopenharmony_ci efx_siena_selftest_async_init(efx); 100662306a36Sopenharmony_ci efx->pci_dev = pci_dev; 100762306a36Sopenharmony_ci efx->msg_enable = debug; 100862306a36Sopenharmony_ci efx->state = STATE_UNINIT; 100962306a36Sopenharmony_ci strscpy(efx->name, pci_name(pci_dev), sizeof(efx->name)); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci efx->net_dev = net_dev; 101262306a36Sopenharmony_ci efx->rx_prefix_size = efx->type->rx_prefix_size; 101362306a36Sopenharmony_ci efx->rx_ip_align = 101462306a36Sopenharmony_ci NET_IP_ALIGN ? (efx->rx_prefix_size + NET_IP_ALIGN) % 4 : 0; 101562306a36Sopenharmony_ci efx->rx_packet_hash_offset = 101662306a36Sopenharmony_ci efx->type->rx_hash_offset - efx->type->rx_prefix_size; 101762306a36Sopenharmony_ci efx->rx_packet_ts_offset = 101862306a36Sopenharmony_ci efx->type->rx_ts_offset - efx->type->rx_prefix_size; 101962306a36Sopenharmony_ci INIT_LIST_HEAD(&efx->rss_context.list); 102062306a36Sopenharmony_ci efx->rss_context.context_id = EFX_MCDI_RSS_CONTEXT_INVALID; 102162306a36Sopenharmony_ci mutex_init(&efx->rss_lock); 102262306a36Sopenharmony_ci efx->vport_id = EVB_PORT_ID_ASSIGNED; 102362306a36Sopenharmony_ci spin_lock_init(&efx->stats_lock); 102462306a36Sopenharmony_ci efx->vi_stride = EFX_DEFAULT_VI_STRIDE; 102562306a36Sopenharmony_ci efx->num_mac_stats = MC_CMD_MAC_NSTATS; 102662306a36Sopenharmony_ci BUILD_BUG_ON(MC_CMD_MAC_NSTATS - 1 != MC_CMD_MAC_GENERATION_END); 102762306a36Sopenharmony_ci mutex_init(&efx->mac_lock); 102862306a36Sopenharmony_ci init_rwsem(&efx->filter_sem); 102962306a36Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL 103062306a36Sopenharmony_ci mutex_init(&efx->rps_mutex); 103162306a36Sopenharmony_ci spin_lock_init(&efx->rps_hash_lock); 103262306a36Sopenharmony_ci /* Failure to allocate is not fatal, but may degrade ARFS performance */ 103362306a36Sopenharmony_ci efx->rps_hash_table = kcalloc(EFX_ARFS_HASH_TABLE_SIZE, 103462306a36Sopenharmony_ci sizeof(*efx->rps_hash_table), GFP_KERNEL); 103562306a36Sopenharmony_ci#endif 103662306a36Sopenharmony_ci efx->mdio.dev = net_dev; 103762306a36Sopenharmony_ci INIT_WORK(&efx->mac_work, efx_mac_work); 103862306a36Sopenharmony_ci init_waitqueue_head(&efx->flush_wq); 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci efx->tx_queues_per_channel = 1; 104162306a36Sopenharmony_ci efx->rxq_entries = EFX_DEFAULT_DMAQ_SIZE; 104262306a36Sopenharmony_ci efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci efx->mem_bar = UINT_MAX; 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci rc = efx_siena_init_channels(efx); 104762306a36Sopenharmony_ci if (rc) 104862306a36Sopenharmony_ci goto fail; 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci /* Would be good to use the net_dev name, but we're too early */ 105162306a36Sopenharmony_ci snprintf(efx->workqueue_name, sizeof(efx->workqueue_name), "sfc%s", 105262306a36Sopenharmony_ci pci_name(pci_dev)); 105362306a36Sopenharmony_ci efx->workqueue = create_singlethread_workqueue(efx->workqueue_name); 105462306a36Sopenharmony_ci if (!efx->workqueue) { 105562306a36Sopenharmony_ci rc = -ENOMEM; 105662306a36Sopenharmony_ci goto fail; 105762306a36Sopenharmony_ci } 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci return 0; 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_cifail: 106262306a36Sopenharmony_ci efx_siena_fini_struct(efx); 106362306a36Sopenharmony_ci return rc; 106462306a36Sopenharmony_ci} 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_civoid efx_siena_fini_struct(struct efx_nic *efx) 106762306a36Sopenharmony_ci{ 106862306a36Sopenharmony_ci#ifdef CONFIG_RFS_ACCEL 106962306a36Sopenharmony_ci kfree(efx->rps_hash_table); 107062306a36Sopenharmony_ci#endif 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci efx_siena_fini_channels(efx); 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci kfree(efx->vpd_sn); 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci if (efx->workqueue) { 107762306a36Sopenharmony_ci destroy_workqueue(efx->workqueue); 107862306a36Sopenharmony_ci efx->workqueue = NULL; 107962306a36Sopenharmony_ci } 108062306a36Sopenharmony_ci} 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci/* This configures the PCI device to enable I/O and DMA. */ 108362306a36Sopenharmony_ciint efx_siena_init_io(struct efx_nic *efx, int bar, dma_addr_t dma_mask, 108462306a36Sopenharmony_ci unsigned int mem_map_size) 108562306a36Sopenharmony_ci{ 108662306a36Sopenharmony_ci struct pci_dev *pci_dev = efx->pci_dev; 108762306a36Sopenharmony_ci int rc; 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci efx->mem_bar = UINT_MAX; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci netif_dbg(efx, probe, efx->net_dev, "initialising I/O bar=%d\n", bar); 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci rc = pci_enable_device(pci_dev); 109462306a36Sopenharmony_ci if (rc) { 109562306a36Sopenharmony_ci netif_err(efx, probe, efx->net_dev, 109662306a36Sopenharmony_ci "failed to enable PCI device\n"); 109762306a36Sopenharmony_ci goto fail1; 109862306a36Sopenharmony_ci } 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci pci_set_master(pci_dev); 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci rc = dma_set_mask_and_coherent(&pci_dev->dev, dma_mask); 110362306a36Sopenharmony_ci if (rc) { 110462306a36Sopenharmony_ci netif_err(efx, probe, efx->net_dev, 110562306a36Sopenharmony_ci "could not find a suitable DMA mask\n"); 110662306a36Sopenharmony_ci goto fail2; 110762306a36Sopenharmony_ci } 110862306a36Sopenharmony_ci netif_dbg(efx, probe, efx->net_dev, 110962306a36Sopenharmony_ci "using DMA mask %llx\n", (unsigned long long)dma_mask); 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci efx->membase_phys = pci_resource_start(efx->pci_dev, bar); 111262306a36Sopenharmony_ci if (!efx->membase_phys) { 111362306a36Sopenharmony_ci netif_err(efx, probe, efx->net_dev, 111462306a36Sopenharmony_ci "ERROR: No BAR%d mapping from the BIOS. " 111562306a36Sopenharmony_ci "Try pci=realloc on the kernel command line\n", bar); 111662306a36Sopenharmony_ci rc = -ENODEV; 111762306a36Sopenharmony_ci goto fail3; 111862306a36Sopenharmony_ci } 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci rc = pci_request_region(pci_dev, bar, "sfc"); 112162306a36Sopenharmony_ci if (rc) { 112262306a36Sopenharmony_ci netif_err(efx, probe, efx->net_dev, 112362306a36Sopenharmony_ci "request for memory BAR[%d] failed\n", bar); 112462306a36Sopenharmony_ci rc = -EIO; 112562306a36Sopenharmony_ci goto fail3; 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci efx->mem_bar = bar; 112862306a36Sopenharmony_ci efx->membase = ioremap(efx->membase_phys, mem_map_size); 112962306a36Sopenharmony_ci if (!efx->membase) { 113062306a36Sopenharmony_ci netif_err(efx, probe, efx->net_dev, 113162306a36Sopenharmony_ci "could not map memory BAR[%d] at %llx+%x\n", bar, 113262306a36Sopenharmony_ci (unsigned long long)efx->membase_phys, mem_map_size); 113362306a36Sopenharmony_ci rc = -ENOMEM; 113462306a36Sopenharmony_ci goto fail4; 113562306a36Sopenharmony_ci } 113662306a36Sopenharmony_ci netif_dbg(efx, probe, efx->net_dev, 113762306a36Sopenharmony_ci "memory BAR[%d] at %llx+%x (virtual %p)\n", bar, 113862306a36Sopenharmony_ci (unsigned long long)efx->membase_phys, mem_map_size, 113962306a36Sopenharmony_ci efx->membase); 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci return 0; 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_cifail4: 114462306a36Sopenharmony_ci pci_release_region(efx->pci_dev, bar); 114562306a36Sopenharmony_cifail3: 114662306a36Sopenharmony_ci efx->membase_phys = 0; 114762306a36Sopenharmony_cifail2: 114862306a36Sopenharmony_ci pci_disable_device(efx->pci_dev); 114962306a36Sopenharmony_cifail1: 115062306a36Sopenharmony_ci return rc; 115162306a36Sopenharmony_ci} 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_civoid efx_siena_fini_io(struct efx_nic *efx) 115462306a36Sopenharmony_ci{ 115562306a36Sopenharmony_ci netif_dbg(efx, drv, efx->net_dev, "shutting down I/O\n"); 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci if (efx->membase) { 115862306a36Sopenharmony_ci iounmap(efx->membase); 115962306a36Sopenharmony_ci efx->membase = NULL; 116062306a36Sopenharmony_ci } 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci if (efx->membase_phys) { 116362306a36Sopenharmony_ci pci_release_region(efx->pci_dev, efx->mem_bar); 116462306a36Sopenharmony_ci efx->membase_phys = 0; 116562306a36Sopenharmony_ci efx->mem_bar = UINT_MAX; 116662306a36Sopenharmony_ci } 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci /* Don't disable bus-mastering if VFs are assigned */ 116962306a36Sopenharmony_ci if (!pci_vfs_assigned(efx->pci_dev)) 117062306a36Sopenharmony_ci pci_disable_device(efx->pci_dev); 117162306a36Sopenharmony_ci} 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci#ifdef CONFIG_SFC_SIENA_MCDI_LOGGING 117462306a36Sopenharmony_cistatic ssize_t mcdi_logging_show(struct device *dev, 117562306a36Sopenharmony_ci struct device_attribute *attr, 117662306a36Sopenharmony_ci char *buf) 117762306a36Sopenharmony_ci{ 117862306a36Sopenharmony_ci struct efx_nic *efx = dev_get_drvdata(dev); 117962306a36Sopenharmony_ci struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", mcdi->logging_enabled); 118262306a36Sopenharmony_ci} 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_cistatic ssize_t mcdi_logging_store(struct device *dev, 118562306a36Sopenharmony_ci struct device_attribute *attr, 118662306a36Sopenharmony_ci const char *buf, size_t count) 118762306a36Sopenharmony_ci{ 118862306a36Sopenharmony_ci struct efx_nic *efx = dev_get_drvdata(dev); 118962306a36Sopenharmony_ci struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 119062306a36Sopenharmony_ci bool enable = count > 0 && *buf != '0'; 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci mcdi->logging_enabled = enable; 119362306a36Sopenharmony_ci return count; 119462306a36Sopenharmony_ci} 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_cistatic DEVICE_ATTR_RW(mcdi_logging); 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_civoid efx_siena_init_mcdi_logging(struct efx_nic *efx) 119962306a36Sopenharmony_ci{ 120062306a36Sopenharmony_ci int rc = device_create_file(&efx->pci_dev->dev, &dev_attr_mcdi_logging); 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci if (rc) { 120362306a36Sopenharmony_ci netif_warn(efx, drv, efx->net_dev, 120462306a36Sopenharmony_ci "failed to init net dev attributes\n"); 120562306a36Sopenharmony_ci } 120662306a36Sopenharmony_ci} 120762306a36Sopenharmony_ci 120862306a36Sopenharmony_civoid efx_siena_fini_mcdi_logging(struct efx_nic *efx) 120962306a36Sopenharmony_ci{ 121062306a36Sopenharmony_ci device_remove_file(&efx->pci_dev->dev, &dev_attr_mcdi_logging); 121162306a36Sopenharmony_ci} 121262306a36Sopenharmony_ci#endif 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci/* A PCI error affecting this device was detected. 121562306a36Sopenharmony_ci * At this point MMIO and DMA may be disabled. 121662306a36Sopenharmony_ci * Stop the software path and request a slot reset. 121762306a36Sopenharmony_ci */ 121862306a36Sopenharmony_cistatic pci_ers_result_t efx_io_error_detected(struct pci_dev *pdev, 121962306a36Sopenharmony_ci pci_channel_state_t state) 122062306a36Sopenharmony_ci{ 122162306a36Sopenharmony_ci pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; 122262306a36Sopenharmony_ci struct efx_nic *efx = pci_get_drvdata(pdev); 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci if (state == pci_channel_io_perm_failure) 122562306a36Sopenharmony_ci return PCI_ERS_RESULT_DISCONNECT; 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci rtnl_lock(); 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci if (efx->state != STATE_DISABLED) { 123062306a36Sopenharmony_ci efx->state = STATE_RECOVERY; 123162306a36Sopenharmony_ci efx->reset_pending = 0; 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci efx_device_detach_sync(efx); 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci efx_siena_stop_all(efx); 123662306a36Sopenharmony_ci efx_siena_disable_interrupts(efx); 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci status = PCI_ERS_RESULT_NEED_RESET; 123962306a36Sopenharmony_ci } else { 124062306a36Sopenharmony_ci /* If the interface is disabled we don't want to do anything 124162306a36Sopenharmony_ci * with it. 124262306a36Sopenharmony_ci */ 124362306a36Sopenharmony_ci status = PCI_ERS_RESULT_RECOVERED; 124462306a36Sopenharmony_ci } 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci rtnl_unlock(); 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci pci_disable_device(pdev); 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci return status; 125162306a36Sopenharmony_ci} 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci/* Fake a successful reset, which will be performed later in efx_io_resume. */ 125462306a36Sopenharmony_cistatic pci_ers_result_t efx_io_slot_reset(struct pci_dev *pdev) 125562306a36Sopenharmony_ci{ 125662306a36Sopenharmony_ci struct efx_nic *efx = pci_get_drvdata(pdev); 125762306a36Sopenharmony_ci pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci if (pci_enable_device(pdev)) { 126062306a36Sopenharmony_ci netif_err(efx, hw, efx->net_dev, 126162306a36Sopenharmony_ci "Cannot re-enable PCI device after reset.\n"); 126262306a36Sopenharmony_ci status = PCI_ERS_RESULT_DISCONNECT; 126362306a36Sopenharmony_ci } 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci return status; 126662306a36Sopenharmony_ci} 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci/* Perform the actual reset and resume I/O operations. */ 126962306a36Sopenharmony_cistatic void efx_io_resume(struct pci_dev *pdev) 127062306a36Sopenharmony_ci{ 127162306a36Sopenharmony_ci struct efx_nic *efx = pci_get_drvdata(pdev); 127262306a36Sopenharmony_ci int rc; 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci rtnl_lock(); 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci if (efx->state == STATE_DISABLED) 127762306a36Sopenharmony_ci goto out; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci rc = efx_siena_reset(efx, RESET_TYPE_ALL); 128062306a36Sopenharmony_ci if (rc) { 128162306a36Sopenharmony_ci netif_err(efx, hw, efx->net_dev, 128262306a36Sopenharmony_ci "efx_siena_reset failed after PCI error (%d)\n", rc); 128362306a36Sopenharmony_ci } else { 128462306a36Sopenharmony_ci efx->state = STATE_READY; 128562306a36Sopenharmony_ci netif_dbg(efx, hw, efx->net_dev, 128662306a36Sopenharmony_ci "Done resetting and resuming IO after PCI error.\n"); 128762306a36Sopenharmony_ci } 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ciout: 129062306a36Sopenharmony_ci rtnl_unlock(); 129162306a36Sopenharmony_ci} 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci/* For simplicity and reliability, we always require a slot reset and try to 129462306a36Sopenharmony_ci * reset the hardware when a pci error affecting the device is detected. 129562306a36Sopenharmony_ci * We leave both the link_reset and mmio_enabled callback unimplemented: 129662306a36Sopenharmony_ci * with our request for slot reset the mmio_enabled callback will never be 129762306a36Sopenharmony_ci * called, and the link_reset callback is not used by AER or EEH mechanisms. 129862306a36Sopenharmony_ci */ 129962306a36Sopenharmony_ciconst struct pci_error_handlers efx_siena_err_handlers = { 130062306a36Sopenharmony_ci .error_detected = efx_io_error_detected, 130162306a36Sopenharmony_ci .slot_reset = efx_io_slot_reset, 130262306a36Sopenharmony_ci .resume = efx_io_resume, 130362306a36Sopenharmony_ci}; 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci/* Determine whether the NIC will be able to handle TX offloads for a given 130662306a36Sopenharmony_ci * encapsulated packet. 130762306a36Sopenharmony_ci */ 130862306a36Sopenharmony_cistatic bool efx_can_encap_offloads(struct efx_nic *efx, struct sk_buff *skb) 130962306a36Sopenharmony_ci{ 131062306a36Sopenharmony_ci struct gre_base_hdr *greh; 131162306a36Sopenharmony_ci __be16 dst_port; 131262306a36Sopenharmony_ci u8 ipproto; 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_ci /* Does the NIC support encap offloads? 131562306a36Sopenharmony_ci * If not, we should never get here, because we shouldn't have 131662306a36Sopenharmony_ci * advertised encap offload feature flags in the first place. 131762306a36Sopenharmony_ci */ 131862306a36Sopenharmony_ci if (WARN_ON_ONCE(!efx->type->udp_tnl_has_port)) 131962306a36Sopenharmony_ci return false; 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci /* Determine encapsulation protocol in use */ 132262306a36Sopenharmony_ci switch (skb->protocol) { 132362306a36Sopenharmony_ci case htons(ETH_P_IP): 132462306a36Sopenharmony_ci ipproto = ip_hdr(skb)->protocol; 132562306a36Sopenharmony_ci break; 132662306a36Sopenharmony_ci case htons(ETH_P_IPV6): 132762306a36Sopenharmony_ci /* If there are extension headers, this will cause us to 132862306a36Sopenharmony_ci * think we can't offload something that we maybe could have. 132962306a36Sopenharmony_ci */ 133062306a36Sopenharmony_ci ipproto = ipv6_hdr(skb)->nexthdr; 133162306a36Sopenharmony_ci break; 133262306a36Sopenharmony_ci default: 133362306a36Sopenharmony_ci /* Not IP, so can't offload it */ 133462306a36Sopenharmony_ci return false; 133562306a36Sopenharmony_ci } 133662306a36Sopenharmony_ci switch (ipproto) { 133762306a36Sopenharmony_ci case IPPROTO_GRE: 133862306a36Sopenharmony_ci /* We support NVGRE but not IP over GRE or random gretaps. 133962306a36Sopenharmony_ci * Specifically, the NIC will accept GRE as encapsulated if 134062306a36Sopenharmony_ci * the inner protocol is Ethernet, but only handle it 134162306a36Sopenharmony_ci * correctly if the GRE header is 8 bytes long. Moreover, 134262306a36Sopenharmony_ci * it will not update the Checksum or Sequence Number fields 134362306a36Sopenharmony_ci * if they are present. (The Routing Present flag, 134462306a36Sopenharmony_ci * GRE_ROUTING, cannot be set else the header would be more 134562306a36Sopenharmony_ci * than 8 bytes long; so we don't have to worry about it.) 134662306a36Sopenharmony_ci */ 134762306a36Sopenharmony_ci if (skb->inner_protocol_type != ENCAP_TYPE_ETHER) 134862306a36Sopenharmony_ci return false; 134962306a36Sopenharmony_ci if (ntohs(skb->inner_protocol) != ETH_P_TEB) 135062306a36Sopenharmony_ci return false; 135162306a36Sopenharmony_ci if (skb_inner_mac_header(skb) - skb_transport_header(skb) != 8) 135262306a36Sopenharmony_ci return false; 135362306a36Sopenharmony_ci greh = (struct gre_base_hdr *)skb_transport_header(skb); 135462306a36Sopenharmony_ci return !(greh->flags & (GRE_CSUM | GRE_SEQ)); 135562306a36Sopenharmony_ci case IPPROTO_UDP: 135662306a36Sopenharmony_ci /* If the port is registered for a UDP tunnel, we assume the 135762306a36Sopenharmony_ci * packet is for that tunnel, and the NIC will handle it as 135862306a36Sopenharmony_ci * such. If not, the NIC won't know what to do with it. 135962306a36Sopenharmony_ci */ 136062306a36Sopenharmony_ci dst_port = udp_hdr(skb)->dest; 136162306a36Sopenharmony_ci return efx->type->udp_tnl_has_port(efx, dst_port); 136262306a36Sopenharmony_ci default: 136362306a36Sopenharmony_ci return false; 136462306a36Sopenharmony_ci } 136562306a36Sopenharmony_ci} 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_cinetdev_features_t efx_siena_features_check(struct sk_buff *skb, 136862306a36Sopenharmony_ci struct net_device *dev, 136962306a36Sopenharmony_ci netdev_features_t features) 137062306a36Sopenharmony_ci{ 137162306a36Sopenharmony_ci struct efx_nic *efx = netdev_priv(dev); 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci if (skb->encapsulation) { 137462306a36Sopenharmony_ci if (features & NETIF_F_GSO_MASK) 137562306a36Sopenharmony_ci /* Hardware can only do TSO with at most 208 bytes 137662306a36Sopenharmony_ci * of headers. 137762306a36Sopenharmony_ci */ 137862306a36Sopenharmony_ci if (skb_inner_transport_offset(skb) > 137962306a36Sopenharmony_ci EFX_TSO2_MAX_HDRLEN) 138062306a36Sopenharmony_ci features &= ~(NETIF_F_GSO_MASK); 138162306a36Sopenharmony_ci if (features & (NETIF_F_GSO_MASK | NETIF_F_CSUM_MASK)) 138262306a36Sopenharmony_ci if (!efx_can_encap_offloads(efx, skb)) 138362306a36Sopenharmony_ci features &= ~(NETIF_F_GSO_MASK | 138462306a36Sopenharmony_ci NETIF_F_CSUM_MASK); 138562306a36Sopenharmony_ci } 138662306a36Sopenharmony_ci return features; 138762306a36Sopenharmony_ci} 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ciint efx_siena_get_phys_port_id(struct net_device *net_dev, 139062306a36Sopenharmony_ci struct netdev_phys_item_id *ppid) 139162306a36Sopenharmony_ci{ 139262306a36Sopenharmony_ci struct efx_nic *efx = netdev_priv(net_dev); 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_ci if (efx->type->get_phys_port_id) 139562306a36Sopenharmony_ci return efx->type->get_phys_port_id(efx, ppid); 139662306a36Sopenharmony_ci else 139762306a36Sopenharmony_ci return -EOPNOTSUPP; 139862306a36Sopenharmony_ci} 139962306a36Sopenharmony_ci 140062306a36Sopenharmony_ciint efx_siena_get_phys_port_name(struct net_device *net_dev, 140162306a36Sopenharmony_ci char *name, size_t len) 140262306a36Sopenharmony_ci{ 140362306a36Sopenharmony_ci struct efx_nic *efx = netdev_priv(net_dev); 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci if (snprintf(name, len, "p%u", efx->port_num) >= len) 140662306a36Sopenharmony_ci return -EINVAL; 140762306a36Sopenharmony_ci return 0; 140862306a36Sopenharmony_ci} 1409