2018-03-22 10:08:48 -07:00
// SPDX-License-Identifier: GPL-2.0
2018-04-26 08:08:09 -07:00
/* Copyright(c) 2013 - 2018 Intel Corporation. */
2013-12-21 06:12:45 +00:00
2024-04-18 13:36:15 +02:00
# include <linux/net/intel/libie/rx.h>
2018-09-14 17:37:48 -07:00
# include "iavf.h"
2018-09-14 17:37:56 -07:00
# include "iavf_prototype.h"
2018-09-14 17:37:46 -07:00
/* All iavf tracepoints are defined by the include below, which must
2017-04-13 04:45:44 -04:00
* be included exactly once across the whole kernel with
* CREATE_TRACE_POINTS defined
*/
# define CREATE_TRACE_POINTS
2018-09-14 17:37:54 -07:00
# include "iavf_trace.h"
2017-04-13 04:45:44 -04:00
2018-09-14 17:37:46 -07:00
static int iavf_setup_all_tx_resources ( struct iavf_adapter * adapter ) ;
static int iavf_setup_all_rx_resources ( struct iavf_adapter * adapter ) ;
static int iavf_close ( struct net_device * netdev ) ;
2021-08-19 08:47:49 +00:00
static void iavf_init_get_resources ( struct iavf_adapter * adapter ) ;
2019-05-14 10:37:07 -07:00
static int iavf_check_reset_complete ( struct iavf_hw * hw ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
char iavf_driver_name [ ] = " iavf " ;
static const char iavf_driver_string [ ] =
2018-09-14 17:37:44 -07:00
" Intel(R) Ethernet Adaptive Virtual Function Network Driver " ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
static const char iavf_copyright [ ] =
2018-09-14 17:37:44 -07:00
" Copyright (c) 2013 - 2018 Intel Corporation. " ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
/* iavf_pci_tbl - PCI Device ID Table
2013-12-21 06:12:45 +00:00
*
* Wildcard entries ( PCI_ANY_ID ) should come last
* Last entry must be all 0 s
*
* { Vendor ID , Device ID , SubVendor ID , SubDevice ID ,
* Class , Class Mask , private data ( not used ) }
*/
2018-09-14 17:37:46 -07:00
static const struct pci_device_id iavf_pci_tbl [ ] = {
2018-09-14 17:37:50 -07:00
{ PCI_VDEVICE ( INTEL , IAVF_DEV_ID_VF ) , 0 } ,
{ PCI_VDEVICE ( INTEL , IAVF_DEV_ID_VF_HV ) , 0 } ,
{ PCI_VDEVICE ( INTEL , IAVF_DEV_ID_X722_VF ) , 0 } ,
{ PCI_VDEVICE ( INTEL , IAVF_DEV_ID_ADAPTIVE_VF ) , 0 } ,
2013-12-21 06:12:45 +00:00
/* required last entry */
{ 0 , }
} ;
2018-09-14 17:37:46 -07:00
MODULE_DEVICE_TABLE ( pci , iavf_pci_tbl ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:44 -07:00
MODULE_ALIAS ( " i40evf " ) ;
2013-12-21 06:12:45 +00:00
MODULE_AUTHOR ( " Intel Corporation, <linux.nics@intel.com> " ) ;
2018-09-14 17:37:57 -07:00
MODULE_DESCRIPTION ( " Intel(R) Ethernet Adaptive Virtual Function Network Driver " ) ;
2024-04-18 13:36:15 +02:00
MODULE_IMPORT_NS ( LIBETH ) ;
net: intel: introduce {, Intel} Ethernet common library
Not a secret there's a ton of code duplication between two and more Intel
ethernet modules.
Before introducing new changes, which would need to be copied over again,
start decoupling the already existing duplicate functionality into a new
module, which will be shared between several Intel Ethernet drivers.
Add the lookup table which converts 8/10-bit hardware packet type into
a parsed bitfield structure for easy checking packet format parameters,
such as payload level, IP version, etc. This is currently used by i40e,
ice and iavf and it's all the same in all three drivers.
The only difference introduced in this implementation is that instead of
defining a 256 (or 1024 in case of ice) element array, add unlikely()
condition to limit the input to 154 (current maximum non-reserved packet
type). There's no reason to waste 600 (or even 3600) bytes only to not
hurt very unlikely exception packets.
The hash computation function now takes payload level directly as a
pkt_hash_type. There's a couple cases when non-IP ptypes are marked as
L3 payload and in the previous versions their hash level would be 2, not
3. But skb_set_hash() only sees difference between L4 and non-L4, thus
this won't change anything at all.
The module is behind the hidden Kconfig symbol, which the drivers will
select when needed. The exports are behind 'LIBIE' namespace to limit
the scope of the functions.
Not that non-HW-specific symbols will live in yet another module,
libeth. This is done to easily distinguish pretty generic code ready
for reusing by any other vendor and/or for moving the layer up from
the code useful in Intel's 1-100G drivers only.
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2024-04-18 13:36:07 +02:00
MODULE_IMPORT_NS ( LIBIE ) ;
2018-09-14 17:37:57 -07:00
MODULE_LICENSE ( " GPL v2 " ) ;
2013-12-21 06:12:45 +00:00
2019-05-14 10:37:07 -07:00
static const struct net_device_ops iavf_netdev_ops ;
2015-12-22 14:25:08 -08:00
2022-01-27 15:16:29 +01:00
int iavf_status_to_errno ( enum iavf_status status )
{
switch ( status ) {
case IAVF_SUCCESS :
return 0 ;
case IAVF_ERR_PARAM :
case IAVF_ERR_MAC_TYPE :
case IAVF_ERR_INVALID_MAC_ADDR :
case IAVF_ERR_INVALID_LINK_SETTINGS :
case IAVF_ERR_INVALID_PD_ID :
case IAVF_ERR_INVALID_QP_ID :
case IAVF_ERR_INVALID_CQ_ID :
case IAVF_ERR_INVALID_CEQ_ID :
case IAVF_ERR_INVALID_AEQ_ID :
case IAVF_ERR_INVALID_SIZE :
case IAVF_ERR_INVALID_ARP_INDEX :
case IAVF_ERR_INVALID_FPM_FUNC_ID :
case IAVF_ERR_QP_INVALID_MSG_SIZE :
case IAVF_ERR_INVALID_FRAG_COUNT :
case IAVF_ERR_INVALID_ALIGNMENT :
case IAVF_ERR_INVALID_PUSH_PAGE_INDEX :
case IAVF_ERR_INVALID_IMM_DATA_SIZE :
case IAVF_ERR_INVALID_VF_ID :
case IAVF_ERR_INVALID_HMCFN_ID :
case IAVF_ERR_INVALID_PBLE_INDEX :
case IAVF_ERR_INVALID_SD_INDEX :
case IAVF_ERR_INVALID_PAGE_DESC_INDEX :
case IAVF_ERR_INVALID_SD_TYPE :
case IAVF_ERR_INVALID_HMC_OBJ_INDEX :
case IAVF_ERR_INVALID_HMC_OBJ_COUNT :
case IAVF_ERR_INVALID_SRQ_ARM_LIMIT :
return - EINVAL ;
case IAVF_ERR_NVM :
case IAVF_ERR_NVM_CHECKSUM :
case IAVF_ERR_PHY :
case IAVF_ERR_CONFIG :
case IAVF_ERR_UNKNOWN_PHY :
case IAVF_ERR_LINK_SETUP :
case IAVF_ERR_ADAPTER_STOPPED :
2022-02-03 11:25:18 +01:00
case IAVF_ERR_PRIMARY_REQUESTS_PENDING :
2022-01-27 15:16:29 +01:00
case IAVF_ERR_AUTONEG_NOT_COMPLETE :
case IAVF_ERR_RESET_FAILED :
case IAVF_ERR_BAD_PTR :
case IAVF_ERR_SWFW_SYNC :
case IAVF_ERR_QP_TOOMANY_WRS_POSTED :
case IAVF_ERR_QUEUE_EMPTY :
case IAVF_ERR_FLUSHED_QUEUE :
case IAVF_ERR_OPCODE_MISMATCH :
case IAVF_ERR_CQP_COMPL_ERROR :
case IAVF_ERR_BACKING_PAGE_ERROR :
case IAVF_ERR_NO_PBLCHUNKS_AVAILABLE :
case IAVF_ERR_MEMCPY_FAILED :
case IAVF_ERR_SRQ_ENABLED :
case IAVF_ERR_ADMIN_QUEUE_ERROR :
case IAVF_ERR_ADMIN_QUEUE_FULL :
2022-12-16 12:06:58 -08:00
case IAVF_ERR_BAD_RDMA_CQE :
2022-01-27 15:16:29 +01:00
case IAVF_ERR_NVM_BLANK_MODE :
case IAVF_ERR_PE_DOORBELL_NOT_ENABLED :
case IAVF_ERR_DIAG_TEST_FAILED :
case IAVF_ERR_FIRMWARE_API_VERSION :
case IAVF_ERR_ADMIN_QUEUE_CRITICAL_ERROR :
return - EIO ;
case IAVF_ERR_DEVICE_NOT_SUPPORTED :
return - ENODEV ;
case IAVF_ERR_NO_AVAILABLE_VSI :
case IAVF_ERR_RING_FULL :
return - ENOSPC ;
case IAVF_ERR_NO_MEMORY :
return - ENOMEM ;
case IAVF_ERR_TIMEOUT :
case IAVF_ERR_ADMIN_QUEUE_TIMEOUT :
return - ETIMEDOUT ;
case IAVF_ERR_NOT_IMPLEMENTED :
case IAVF_NOT_SUPPORTED :
return - EOPNOTSUPP ;
case IAVF_ERR_ADMIN_QUEUE_NO_WORK :
return - EALREADY ;
case IAVF_ERR_NOT_READY :
return - EBUSY ;
case IAVF_ERR_BUF_TOO_SHORT :
return - EMSGSIZE ;
}
return - EIO ;
}
int virtchnl_status_to_errno ( enum virtchnl_status_code v_status )
{
switch ( v_status ) {
case VIRTCHNL_STATUS_SUCCESS :
return 0 ;
case VIRTCHNL_STATUS_ERR_PARAM :
case VIRTCHNL_STATUS_ERR_INVALID_VF_ID :
return - EINVAL ;
case VIRTCHNL_STATUS_ERR_NO_MEMORY :
return - ENOMEM ;
case VIRTCHNL_STATUS_ERR_OPCODE_MISMATCH :
case VIRTCHNL_STATUS_ERR_CQP_COMPL_ERROR :
case VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR :
return - EIO ;
case VIRTCHNL_STATUS_ERR_NOT_SUPPORTED :
return - EOPNOTSUPP ;
}
return - EIO ;
}
2021-09-15 08:41:23 +02:00
/**
* iavf_pdev_to_adapter - go from pci_dev to adapter
* @ pdev : pci_dev pointer
*/
static struct iavf_adapter * iavf_pdev_to_adapter ( struct pci_dev * pdev )
{
return netdev_priv ( pci_get_drvdata ( pdev ) ) ;
}
2023-06-05 10:52:22 -04:00
/**
* iavf_is_reset_in_progress - Check if a reset is in progress
* @ adapter : board private structure
*/
static bool iavf_is_reset_in_progress ( struct iavf_adapter * adapter )
{
if ( adapter - > state = = __IAVF_RESETTING | |
adapter - > flags & ( IAVF_FLAG_RESET_PENDING |
IAVF_FLAG_RESET_NEEDED ) )
return true ;
return false ;
}
/**
* iavf_wait_for_reset - Wait for reset to finish .
* @ adapter : board private structure
*
* Returns 0 if reset finished successfully , negative on timeout or interrupt .
*/
int iavf_wait_for_reset ( struct iavf_adapter * adapter )
{
int ret = wait_event_interruptible_timeout ( adapter - > reset_waitqueue ,
! iavf_is_reset_in_progress ( adapter ) ,
msecs_to_jiffies ( 5000 ) ) ;
/* If ret < 0 then it means wait was interrupted.
* If ret = = 0 then it means we got a timeout while waiting
* for reset to finish .
* If ret > 0 it means reset has finished .
*/
if ( ret > 0 )
return 0 ;
else if ( ret < 0 )
return - EINTR ;
else
return - EBUSY ;
}
2013-12-21 06:12:45 +00:00
/**
2018-09-14 17:37:46 -07:00
* iavf_allocate_dma_mem_d - OS specific memory alloc for shared code
2013-12-21 06:12:45 +00:00
* @ hw : pointer to the HW structure
* @ mem : ptr to mem struct to fill out
* @ size : size of memory requested
* @ alignment : what to align the allocation to
* */
2019-04-17 15:17:30 -07:00
enum iavf_status iavf_allocate_dma_mem_d ( struct iavf_hw * hw ,
struct iavf_dma_mem * mem ,
u64 size , u32 alignment )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = ( struct iavf_adapter * ) hw - > back ;
2013-12-21 06:12:45 +00:00
if ( ! mem )
2019-04-17 15:17:33 -07:00
return IAVF_ERR_PARAM ;
2013-12-21 06:12:45 +00:00
mem - > size = ALIGN ( size , alignment ) ;
mem - > va = dma_alloc_coherent ( & adapter - > pdev - > dev , mem - > size ,
( dma_addr_t * ) & mem - > pa , GFP_KERNEL ) ;
if ( mem - > va )
return 0 ;
else
2019-04-17 15:17:33 -07:00
return IAVF_ERR_NO_MEMORY ;
2013-12-21 06:12:45 +00:00
}
/**
2023-06-15 07:03:08 -04:00
* iavf_free_dma_mem - wrapper for DMA memory freeing
2013-12-21 06:12:45 +00:00
* @ hw : pointer to the HW structure
* @ mem : ptr to mem struct to free
* */
2023-06-15 07:03:08 -04:00
enum iavf_status iavf_free_dma_mem ( struct iavf_hw * hw , struct iavf_dma_mem * mem )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = ( struct iavf_adapter * ) hw - > back ;
2013-12-21 06:12:45 +00:00
if ( ! mem | | ! mem - > va )
2019-04-17 15:17:33 -07:00
return IAVF_ERR_PARAM ;
2013-12-21 06:12:45 +00:00
dma_free_coherent ( & adapter - > pdev - > dev , mem - > size ,
mem - > va , ( dma_addr_t ) mem - > pa ) ;
return 0 ;
}
/**
2023-06-15 07:03:08 -04:00
* iavf_allocate_virt_mem - virt memory alloc wrapper
2013-12-21 06:12:45 +00:00
* @ hw : pointer to the HW structure
* @ mem : ptr to mem struct to fill out
* @ size : size of memory requested
* */
2023-06-15 07:03:08 -04:00
enum iavf_status iavf_allocate_virt_mem ( struct iavf_hw * hw ,
struct iavf_virt_mem * mem , u32 size )
2013-12-21 06:12:45 +00:00
{
if ( ! mem )
2019-04-17 15:17:33 -07:00
return IAVF_ERR_PARAM ;
2013-12-21 06:12:45 +00:00
mem - > size = size ;
mem - > va = kzalloc ( size , GFP_KERNEL ) ;
if ( mem - > va )
return 0 ;
else
2019-04-17 15:17:33 -07:00
return IAVF_ERR_NO_MEMORY ;
2013-12-21 06:12:45 +00:00
}
/**
2023-06-15 07:03:08 -04:00
* iavf_free_virt_mem - virt memory free wrapper
2013-12-21 06:12:45 +00:00
* @ hw : pointer to the HW structure
* @ mem : ptr to mem struct to free
* */
2023-06-15 07:03:08 -04:00
void iavf_free_virt_mem ( struct iavf_hw * hw , struct iavf_virt_mem * mem )
2013-12-21 06:12:45 +00:00
{
kfree ( mem - > va ) ;
}
2016-01-15 14:33:10 -08:00
/**
2018-09-14 17:37:46 -07:00
* iavf_schedule_reset - Set the flags and schedule a reset event
2016-01-15 14:33:10 -08:00
* @ adapter : board private structure
2023-06-05 10:52:26 -04:00
* @ flags : IAVF_FLAG_RESET_PENDING or IAVF_FLAG_RESET_NEEDED
2016-01-15 14:33:10 -08:00
* */
2023-06-05 10:52:26 -04:00
void iavf_schedule_reset ( struct iavf_adapter * adapter , u64 flags )
2016-01-15 14:33:10 -08:00
{
2023-06-05 10:52:26 -04:00
if ( ! test_bit ( __IAVF_IN_REMOVE_TASK , & adapter - > crit_section ) & &
! ( adapter - > flags &
( IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED ) ) ) {
adapter - > flags | = flags ;
2022-12-15 23:50:48 +01:00
queue_work ( adapter - > wq , & adapter - > reset_task ) ;
2016-01-15 14:33:10 -08:00
}
}
2021-09-15 09:01:00 +00:00
/**
2023-09-07 17:02:50 +02:00
* iavf_schedule_aq_request - Set the flags and schedule aq request
2021-09-15 09:01:00 +00:00
* @ adapter : board private structure
2023-09-07 17:02:50 +02:00
* @ flags : requested aq flags
2021-09-15 09:01:00 +00:00
* */
2023-09-07 17:02:50 +02:00
void iavf_schedule_aq_request ( struct iavf_adapter * adapter , u64 flags )
2021-09-15 09:01:00 +00:00
{
2023-09-07 17:02:50 +02:00
adapter - > aq_required | = flags ;
2022-12-15 23:50:48 +01:00
mod_delayed_work ( adapter - > wq , & adapter - > watchdog_task , 0 ) ;
2021-09-15 09:01:00 +00:00
}
2013-12-21 06:12:45 +00:00
/**
2018-09-14 17:37:46 -07:00
* iavf_tx_timeout - Respond to a Tx Hang
2013-12-21 06:12:45 +00:00
* @ netdev : network interface device structure
2020-09-25 15:24:37 -07:00
* @ txqueue : queue number that is timing out
2013-12-21 06:12:45 +00:00
* */
netdev: pass the stuck queue to the timeout handler
This allows incrementing the correct timeout statistic without any mess.
Down the road, devices can learn to reset just the specific queue.
The patch was generated with the following script:
use strict;
use warnings;
our $^I = '.bak';
my @work = (
["arch/m68k/emu/nfeth.c", "nfeth_tx_timeout"],
["arch/um/drivers/net_kern.c", "uml_net_tx_timeout"],
["arch/um/drivers/vector_kern.c", "vector_net_tx_timeout"],
["arch/xtensa/platforms/iss/network.c", "iss_net_tx_timeout"],
["drivers/char/pcmcia/synclink_cs.c", "hdlcdev_tx_timeout"],
["drivers/infiniband/ulp/ipoib/ipoib_main.c", "ipoib_timeout"],
["drivers/infiniband/ulp/ipoib/ipoib_main.c", "ipoib_timeout"],
["drivers/message/fusion/mptlan.c", "mpt_lan_tx_timeout"],
["drivers/misc/sgi-xp/xpnet.c", "xpnet_dev_tx_timeout"],
["drivers/net/appletalk/cops.c", "cops_timeout"],
["drivers/net/arcnet/arcdevice.h", "arcnet_timeout"],
["drivers/net/arcnet/arcnet.c", "arcnet_timeout"],
["drivers/net/arcnet/com20020.c", "arcnet_timeout"],
["drivers/net/ethernet/3com/3c509.c", "el3_tx_timeout"],
["drivers/net/ethernet/3com/3c515.c", "corkscrew_timeout"],
["drivers/net/ethernet/3com/3c574_cs.c", "el3_tx_timeout"],
["drivers/net/ethernet/3com/3c589_cs.c", "el3_tx_timeout"],
["drivers/net/ethernet/3com/3c59x.c", "vortex_tx_timeout"],
["drivers/net/ethernet/3com/3c59x.c", "vortex_tx_timeout"],
["drivers/net/ethernet/3com/typhoon.c", "typhoon_tx_timeout"],
["drivers/net/ethernet/8390/8390.h", "ei_tx_timeout"],
["drivers/net/ethernet/8390/8390.h", "eip_tx_timeout"],
["drivers/net/ethernet/8390/8390.c", "ei_tx_timeout"],
["drivers/net/ethernet/8390/8390p.c", "eip_tx_timeout"],
["drivers/net/ethernet/8390/ax88796.c", "ax_ei_tx_timeout"],
["drivers/net/ethernet/8390/axnet_cs.c", "axnet_tx_timeout"],
["drivers/net/ethernet/8390/etherh.c", "__ei_tx_timeout"],
["drivers/net/ethernet/8390/hydra.c", "__ei_tx_timeout"],
["drivers/net/ethernet/8390/mac8390.c", "__ei_tx_timeout"],
["drivers/net/ethernet/8390/mcf8390.c", "__ei_tx_timeout"],
["drivers/net/ethernet/8390/lib8390.c", "__ei_tx_timeout"],
["drivers/net/ethernet/8390/ne2k-pci.c", "ei_tx_timeout"],
["drivers/net/ethernet/8390/pcnet_cs.c", "ei_tx_timeout"],
["drivers/net/ethernet/8390/smc-ultra.c", "ei_tx_timeout"],
["drivers/net/ethernet/8390/wd.c", "ei_tx_timeout"],
["drivers/net/ethernet/8390/zorro8390.c", "__ei_tx_timeout"],
["drivers/net/ethernet/adaptec/starfire.c", "tx_timeout"],
["drivers/net/ethernet/agere/et131x.c", "et131x_tx_timeout"],
["drivers/net/ethernet/allwinner/sun4i-emac.c", "emac_timeout"],
["drivers/net/ethernet/alteon/acenic.c", "ace_watchdog"],
["drivers/net/ethernet/amazon/ena/ena_netdev.c", "ena_tx_timeout"],
["drivers/net/ethernet/amd/7990.h", "lance_tx_timeout"],
["drivers/net/ethernet/amd/7990.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/a2065.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/am79c961a.c", "am79c961_timeout"],
["drivers/net/ethernet/amd/amd8111e.c", "amd8111e_tx_timeout"],
["drivers/net/ethernet/amd/ariadne.c", "ariadne_tx_timeout"],
["drivers/net/ethernet/amd/atarilance.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/au1000_eth.c", "au1000_tx_timeout"],
["drivers/net/ethernet/amd/declance.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/lance.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/mvme147.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/ni65.c", "ni65_timeout"],
["drivers/net/ethernet/amd/nmclan_cs.c", "mace_tx_timeout"],
["drivers/net/ethernet/amd/pcnet32.c", "pcnet32_tx_timeout"],
["drivers/net/ethernet/amd/sunlance.c", "lance_tx_timeout"],
["drivers/net/ethernet/amd/xgbe/xgbe-drv.c", "xgbe_tx_timeout"],
["drivers/net/ethernet/apm/xgene-v2/main.c", "xge_timeout"],
["drivers/net/ethernet/apm/xgene/xgene_enet_main.c", "xgene_enet_timeout"],
["drivers/net/ethernet/apple/macmace.c", "mace_tx_timeout"],
["drivers/net/ethernet/atheros/ag71xx.c", "ag71xx_tx_timeout"],
["drivers/net/ethernet/atheros/alx/main.c", "alx_tx_timeout"],
["drivers/net/ethernet/atheros/atl1c/atl1c_main.c", "atl1c_tx_timeout"],
["drivers/net/ethernet/atheros/atl1e/atl1e_main.c", "atl1e_tx_timeout"],
["drivers/net/ethernet/atheros/atlx/atl.c", "atlx_tx_timeout"],
["drivers/net/ethernet/atheros/atlx/atl1.c", "atlx_tx_timeout"],
["drivers/net/ethernet/atheros/atlx/atl2.c", "atl2_tx_timeout"],
["drivers/net/ethernet/broadcom/b44.c", "b44_tx_timeout"],
["drivers/net/ethernet/broadcom/bcmsysport.c", "bcm_sysport_tx_timeout"],
["drivers/net/ethernet/broadcom/bnx2.c", "bnx2_tx_timeout"],
["drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h", "bnx2x_tx_timeout"],
["drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c", "bnx2x_tx_timeout"],
["drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c", "bnx2x_tx_timeout"],
["drivers/net/ethernet/broadcom/bnxt/bnxt.c", "bnxt_tx_timeout"],
["drivers/net/ethernet/broadcom/genet/bcmgenet.c", "bcmgenet_timeout"],
["drivers/net/ethernet/broadcom/sb1250-mac.c", "sbmac_tx_timeout"],
["drivers/net/ethernet/broadcom/tg3.c", "tg3_tx_timeout"],
["drivers/net/ethernet/calxeda/xgmac.c", "xgmac_tx_timeout"],
["drivers/net/ethernet/cavium/liquidio/lio_main.c", "liquidio_tx_timeout"],
["drivers/net/ethernet/cavium/liquidio/lio_vf_main.c", "liquidio_tx_timeout"],
["drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c", "lio_vf_rep_tx_timeout"],
["drivers/net/ethernet/cavium/thunder/nicvf_main.c", "nicvf_tx_timeout"],
["drivers/net/ethernet/cirrus/cs89x0.c", "net_timeout"],
["drivers/net/ethernet/cisco/enic/enic_main.c", "enic_tx_timeout"],
["drivers/net/ethernet/cisco/enic/enic_main.c", "enic_tx_timeout"],
["drivers/net/ethernet/cortina/gemini.c", "gmac_tx_timeout"],
["drivers/net/ethernet/davicom/dm9000.c", "dm9000_timeout"],
["drivers/net/ethernet/dec/tulip/de2104x.c", "de_tx_timeout"],
["drivers/net/ethernet/dec/tulip/tulip_core.c", "tulip_tx_timeout"],
["drivers/net/ethernet/dec/tulip/winbond-840.c", "tx_timeout"],
["drivers/net/ethernet/dlink/dl2k.c", "rio_tx_timeout"],
["drivers/net/ethernet/dlink/sundance.c", "tx_timeout"],
["drivers/net/ethernet/emulex/benet/be_main.c", "be_tx_timeout"],
["drivers/net/ethernet/ethoc.c", "ethoc_tx_timeout"],
["drivers/net/ethernet/faraday/ftgmac100.c", "ftgmac100_tx_timeout"],
["drivers/net/ethernet/fealnx.c", "fealnx_tx_timeout"],
["drivers/net/ethernet/freescale/dpaa/dpaa_eth.c", "dpaa_tx_timeout"],
["drivers/net/ethernet/freescale/fec_main.c", "fec_timeout"],
["drivers/net/ethernet/freescale/fec_mpc52xx.c", "mpc52xx_fec_tx_timeout"],
["drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c", "fs_timeout"],
["drivers/net/ethernet/freescale/gianfar.c", "gfar_timeout"],
["drivers/net/ethernet/freescale/ucc_geth.c", "ucc_geth_timeout"],
["drivers/net/ethernet/fujitsu/fmvj18x_cs.c", "fjn_tx_timeout"],
["drivers/net/ethernet/google/gve/gve_main.c", "gve_tx_timeout"],
["drivers/net/ethernet/hisilicon/hip04_eth.c", "hip04_timeout"],
["drivers/net/ethernet/hisilicon/hix5hd2_gmac.c", "hix5hd2_net_timeout"],
["drivers/net/ethernet/hisilicon/hns/hns_enet.c", "hns_nic_net_timeout"],
["drivers/net/ethernet/hisilicon/hns3/hns3_enet.c", "hns3_nic_net_timeout"],
["drivers/net/ethernet/huawei/hinic/hinic_main.c", "hinic_tx_timeout"],
["drivers/net/ethernet/i825xx/82596.c", "i596_tx_timeout"],
["drivers/net/ethernet/i825xx/ether1.c", "ether1_timeout"],
["drivers/net/ethernet/i825xx/lib82596.c", "i596_tx_timeout"],
["drivers/net/ethernet/i825xx/sun3_82586.c", "sun3_82586_timeout"],
["drivers/net/ethernet/ibm/ehea/ehea_main.c", "ehea_tx_watchdog"],
["drivers/net/ethernet/ibm/emac/core.c", "emac_tx_timeout"],
["drivers/net/ethernet/ibm/emac/core.c", "emac_tx_timeout"],
["drivers/net/ethernet/ibm/ibmvnic.c", "ibmvnic_tx_timeout"],
["drivers/net/ethernet/intel/e100.c", "e100_tx_timeout"],
["drivers/net/ethernet/intel/e1000/e1000_main.c", "e1000_tx_timeout"],
["drivers/net/ethernet/intel/e1000e/netdev.c", "e1000_tx_timeout"],
["drivers/net/ethernet/intel/fm10k/fm10k_netdev.c", "fm10k_tx_timeout"],
["drivers/net/ethernet/intel/i40e/i40e_main.c", "i40e_tx_timeout"],
["drivers/net/ethernet/intel/iavf/iavf_main.c", "iavf_tx_timeout"],
["drivers/net/ethernet/intel/ice/ice_main.c", "ice_tx_timeout"],
["drivers/net/ethernet/intel/ice/ice_main.c", "ice_tx_timeout"],
["drivers/net/ethernet/intel/igb/igb_main.c", "igb_tx_timeout"],
["drivers/net/ethernet/intel/igbvf/netdev.c", "igbvf_tx_timeout"],
["drivers/net/ethernet/intel/ixgb/ixgb_main.c", "ixgb_tx_timeout"],
["drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c", "adapter->netdev->netdev_ops->ndo_tx_timeout(adapter->netdev);"],
["drivers/net/ethernet/intel/ixgbe/ixgbe_main.c", "ixgbe_tx_timeout"],
["drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c", "ixgbevf_tx_timeout"],
["drivers/net/ethernet/jme.c", "jme_tx_timeout"],
["drivers/net/ethernet/korina.c", "korina_tx_timeout"],
["drivers/net/ethernet/lantiq_etop.c", "ltq_etop_tx_timeout"],
["drivers/net/ethernet/marvell/mv643xx_eth.c", "mv643xx_eth_tx_timeout"],
["drivers/net/ethernet/marvell/pxa168_eth.c", "pxa168_eth_tx_timeout"],
["drivers/net/ethernet/marvell/skge.c", "skge_tx_timeout"],
["drivers/net/ethernet/marvell/sky2.c", "sky2_tx_timeout"],
["drivers/net/ethernet/marvell/sky2.c", "sky2_tx_timeout"],
["drivers/net/ethernet/mediatek/mtk_eth_soc.c", "mtk_tx_timeout"],
["drivers/net/ethernet/mellanox/mlx4/en_netdev.c", "mlx4_en_tx_timeout"],
["drivers/net/ethernet/mellanox/mlx4/en_netdev.c", "mlx4_en_tx_timeout"],
["drivers/net/ethernet/mellanox/mlx5/core/en_main.c", "mlx5e_tx_timeout"],
["drivers/net/ethernet/micrel/ks8842.c", "ks8842_tx_timeout"],
["drivers/net/ethernet/micrel/ksz884x.c", "netdev_tx_timeout"],
["drivers/net/ethernet/microchip/enc28j60.c", "enc28j60_tx_timeout"],
["drivers/net/ethernet/microchip/encx24j600.c", "encx24j600_tx_timeout"],
["drivers/net/ethernet/natsemi/sonic.h", "sonic_tx_timeout"],
["drivers/net/ethernet/natsemi/sonic.c", "sonic_tx_timeout"],
["drivers/net/ethernet/natsemi/jazzsonic.c", "sonic_tx_timeout"],
["drivers/net/ethernet/natsemi/macsonic.c", "sonic_tx_timeout"],
["drivers/net/ethernet/natsemi/natsemi.c", "ns_tx_timeout"],
["drivers/net/ethernet/natsemi/ns83820.c", "ns83820_tx_timeout"],
["drivers/net/ethernet/natsemi/xtsonic.c", "sonic_tx_timeout"],
["drivers/net/ethernet/neterion/s2io.h", "s2io_tx_watchdog"],
["drivers/net/ethernet/neterion/s2io.c", "s2io_tx_watchdog"],
["drivers/net/ethernet/neterion/vxge/vxge-main.c", "vxge_tx_watchdog"],
["drivers/net/ethernet/netronome/nfp/nfp_net_common.c", "nfp_net_tx_timeout"],
["drivers/net/ethernet/nvidia/forcedeth.c", "nv_tx_timeout"],
["drivers/net/ethernet/nvidia/forcedeth.c", "nv_tx_timeout"],
["drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c", "pch_gbe_tx_timeout"],
["drivers/net/ethernet/packetengines/hamachi.c", "hamachi_tx_timeout"],
["drivers/net/ethernet/packetengines/yellowfin.c", "yellowfin_tx_timeout"],
["drivers/net/ethernet/pensando/ionic/ionic_lif.c", "ionic_tx_timeout"],
["drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c", "netxen_tx_timeout"],
["drivers/net/ethernet/qlogic/qla3xxx.c", "ql3xxx_tx_timeout"],
["drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c", "qlcnic_tx_timeout"],
["drivers/net/ethernet/qualcomm/emac/emac.c", "emac_tx_timeout"],
["drivers/net/ethernet/qualcomm/qca_spi.c", "qcaspi_netdev_tx_timeout"],
["drivers/net/ethernet/qualcomm/qca_uart.c", "qcauart_netdev_tx_timeout"],
["drivers/net/ethernet/rdc/r6040.c", "r6040_tx_timeout"],
["drivers/net/ethernet/realtek/8139cp.c", "cp_tx_timeout"],
["drivers/net/ethernet/realtek/8139too.c", "rtl8139_tx_timeout"],
["drivers/net/ethernet/realtek/atp.c", "tx_timeout"],
["drivers/net/ethernet/realtek/r8169_main.c", "rtl8169_tx_timeout"],
["drivers/net/ethernet/renesas/ravb_main.c", "ravb_tx_timeout"],
["drivers/net/ethernet/renesas/sh_eth.c", "sh_eth_tx_timeout"],
["drivers/net/ethernet/renesas/sh_eth.c", "sh_eth_tx_timeout"],
["drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c", "sxgbe_tx_timeout"],
["drivers/net/ethernet/seeq/ether3.c", "ether3_timeout"],
["drivers/net/ethernet/seeq/sgiseeq.c", "timeout"],
["drivers/net/ethernet/sfc/efx.c", "efx_watchdog"],
["drivers/net/ethernet/sfc/falcon/efx.c", "ef4_watchdog"],
["drivers/net/ethernet/sgi/ioc3-eth.c", "ioc3_timeout"],
["drivers/net/ethernet/sgi/meth.c", "meth_tx_timeout"],
["drivers/net/ethernet/silan/sc92031.c", "sc92031_tx_timeout"],
["drivers/net/ethernet/sis/sis190.c", "sis190_tx_timeout"],
["drivers/net/ethernet/sis/sis900.c", "sis900_tx_timeout"],
["drivers/net/ethernet/smsc/epic100.c", "epic_tx_timeout"],
["drivers/net/ethernet/smsc/smc911x.c", "smc911x_timeout"],
["drivers/net/ethernet/smsc/smc9194.c", "smc_timeout"],
["drivers/net/ethernet/smsc/smc91c92_cs.c", "smc_tx_timeout"],
["drivers/net/ethernet/smsc/smc91x.c", "smc_timeout"],
["drivers/net/ethernet/stmicro/stmmac/stmmac_main.c", "stmmac_tx_timeout"],
["drivers/net/ethernet/sun/cassini.c", "cas_tx_timeout"],
["drivers/net/ethernet/sun/ldmvsw.c", "sunvnet_tx_timeout_common"],
["drivers/net/ethernet/sun/niu.c", "niu_tx_timeout"],
["drivers/net/ethernet/sun/sunbmac.c", "bigmac_tx_timeout"],
["drivers/net/ethernet/sun/sungem.c", "gem_tx_timeout"],
["drivers/net/ethernet/sun/sunhme.c", "happy_meal_tx_timeout"],
["drivers/net/ethernet/sun/sunqe.c", "qe_tx_timeout"],
["drivers/net/ethernet/sun/sunvnet.c", "sunvnet_tx_timeout_common"],
["drivers/net/ethernet/sun/sunvnet_common.c", "sunvnet_tx_timeout_common"],
["drivers/net/ethernet/sun/sunvnet_common.h", "sunvnet_tx_timeout_common"],
["drivers/net/ethernet/synopsys/dwc-xlgmac-net.c", "xlgmac_tx_timeout"],
["drivers/net/ethernet/ti/cpmac.c", "cpmac_tx_timeout"],
["drivers/net/ethernet/ti/cpsw.c", "cpsw_ndo_tx_timeout"],
["drivers/net/ethernet/ti/cpsw_priv.c", "cpsw_ndo_tx_timeout"],
["drivers/net/ethernet/ti/cpsw_priv.h", "cpsw_ndo_tx_timeout"],
["drivers/net/ethernet/ti/davinci_emac.c", "emac_dev_tx_timeout"],
["drivers/net/ethernet/ti/netcp_core.c", "netcp_ndo_tx_timeout"],
["drivers/net/ethernet/ti/tlan.c", "tlan_tx_timeout"],
["drivers/net/ethernet/toshiba/ps3_gelic_net.h", "gelic_net_tx_timeout"],
["drivers/net/ethernet/toshiba/ps3_gelic_net.c", "gelic_net_tx_timeout"],
["drivers/net/ethernet/toshiba/ps3_gelic_wireless.c", "gelic_net_tx_timeout"],
["drivers/net/ethernet/toshiba/spider_net.c", "spider_net_tx_timeout"],
["drivers/net/ethernet/toshiba/tc35815.c", "tc35815_tx_timeout"],
["drivers/net/ethernet/via/via-rhine.c", "rhine_tx_timeout"],
["drivers/net/ethernet/wiznet/w5100.c", "w5100_tx_timeout"],
["drivers/net/ethernet/wiznet/w5300.c", "w5300_tx_timeout"],
["drivers/net/ethernet/xilinx/xilinx_emaclite.c", "xemaclite_tx_timeout"],
["drivers/net/ethernet/xircom/xirc2ps_cs.c", "xirc_tx_timeout"],
["drivers/net/fjes/fjes_main.c", "fjes_tx_retry"],
["drivers/net/slip/slip.c", "sl_tx_timeout"],
["include/linux/usb/usbnet.h", "usbnet_tx_timeout"],
["drivers/net/usb/aqc111.c", "usbnet_tx_timeout"],
["drivers/net/usb/asix_devices.c", "usbnet_tx_timeout"],
["drivers/net/usb/asix_devices.c", "usbnet_tx_timeout"],
["drivers/net/usb/asix_devices.c", "usbnet_tx_timeout"],
["drivers/net/usb/ax88172a.c", "usbnet_tx_timeout"],
["drivers/net/usb/ax88179_178a.c", "usbnet_tx_timeout"],
["drivers/net/usb/catc.c", "catc_tx_timeout"],
["drivers/net/usb/cdc_mbim.c", "usbnet_tx_timeout"],
["drivers/net/usb/cdc_ncm.c", "usbnet_tx_timeout"],
["drivers/net/usb/dm9601.c", "usbnet_tx_timeout"],
["drivers/net/usb/hso.c", "hso_net_tx_timeout"],
["drivers/net/usb/int51x1.c", "usbnet_tx_timeout"],
["drivers/net/usb/ipheth.c", "ipheth_tx_timeout"],
["drivers/net/usb/kaweth.c", "kaweth_tx_timeout"],
["drivers/net/usb/lan78xx.c", "lan78xx_tx_timeout"],
["drivers/net/usb/mcs7830.c", "usbnet_tx_timeout"],
["drivers/net/usb/pegasus.c", "pegasus_tx_timeout"],
["drivers/net/usb/qmi_wwan.c", "usbnet_tx_timeout"],
["drivers/net/usb/r8152.c", "rtl8152_tx_timeout"],
["drivers/net/usb/rndis_host.c", "usbnet_tx_timeout"],
["drivers/net/usb/rtl8150.c", "rtl8150_tx_timeout"],
["drivers/net/usb/sierra_net.c", "usbnet_tx_timeout"],
["drivers/net/usb/smsc75xx.c", "usbnet_tx_timeout"],
["drivers/net/usb/smsc95xx.c", "usbnet_tx_timeout"],
["drivers/net/usb/sr9700.c", "usbnet_tx_timeout"],
["drivers/net/usb/sr9800.c", "usbnet_tx_timeout"],
["drivers/net/usb/usbnet.c", "usbnet_tx_timeout"],
["drivers/net/vmxnet3/vmxnet3_drv.c", "vmxnet3_tx_timeout"],
["drivers/net/wan/cosa.c", "cosa_net_timeout"],
["drivers/net/wan/farsync.c", "fst_tx_timeout"],
["drivers/net/wan/fsl_ucc_hdlc.c", "uhdlc_tx_timeout"],
["drivers/net/wan/lmc/lmc_main.c", "lmc_driver_timeout"],
["drivers/net/wan/x25_asy.c", "x25_asy_timeout"],
["drivers/net/wimax/i2400m/netdev.c", "i2400m_tx_timeout"],
["drivers/net/wireless/intel/ipw2x00/ipw2100.c", "ipw2100_tx_timeout"],
["drivers/net/wireless/intersil/hostap/hostap_main.c", "prism2_tx_timeout"],
["drivers/net/wireless/intersil/hostap/hostap_main.c", "prism2_tx_timeout"],
["drivers/net/wireless/intersil/hostap/hostap_main.c", "prism2_tx_timeout"],
["drivers/net/wireless/intersil/orinoco/main.c", "orinoco_tx_timeout"],
["drivers/net/wireless/intersil/orinoco/orinoco_usb.c", "orinoco_tx_timeout"],
["drivers/net/wireless/intersil/orinoco/orinoco.h", "orinoco_tx_timeout"],
["drivers/net/wireless/intersil/prism54/islpci_dev.c", "islpci_eth_tx_timeout"],
["drivers/net/wireless/intersil/prism54/islpci_eth.c", "islpci_eth_tx_timeout"],
["drivers/net/wireless/intersil/prism54/islpci_eth.h", "islpci_eth_tx_timeout"],
["drivers/net/wireless/marvell/mwifiex/main.c", "mwifiex_tx_timeout"],
["drivers/net/wireless/quantenna/qtnfmac/core.c", "qtnf_netdev_tx_timeout"],
["drivers/net/wireless/quantenna/qtnfmac/core.h", "qtnf_netdev_tx_timeout"],
["drivers/net/wireless/rndis_wlan.c", "usbnet_tx_timeout"],
["drivers/net/wireless/wl3501_cs.c", "wl3501_tx_timeout"],
["drivers/net/wireless/zydas/zd1201.c", "zd1201_tx_timeout"],
["drivers/s390/net/qeth_core.h", "qeth_tx_timeout"],
["drivers/s390/net/qeth_core_main.c", "qeth_tx_timeout"],
["drivers/s390/net/qeth_l2_main.c", "qeth_tx_timeout"],
["drivers/s390/net/qeth_l2_main.c", "qeth_tx_timeout"],
["drivers/s390/net/qeth_l3_main.c", "qeth_tx_timeout"],
["drivers/s390/net/qeth_l3_main.c", "qeth_tx_timeout"],
["drivers/staging/ks7010/ks_wlan_net.c", "ks_wlan_tx_timeout"],
["drivers/staging/qlge/qlge_main.c", "qlge_tx_timeout"],
["drivers/staging/rtl8192e/rtl8192e/rtl_core.c", "_rtl92e_tx_timeout"],
["drivers/staging/rtl8192u/r8192U_core.c", "tx_timeout"],
["drivers/staging/unisys/visornic/visornic_main.c", "visornic_xmit_timeout"],
["drivers/staging/wlan-ng/p80211netdev.c", "p80211knetdev_tx_timeout"],
["drivers/tty/n_gsm.c", "gsm_mux_net_tx_timeout"],
["drivers/tty/synclink.c", "hdlcdev_tx_timeout"],
["drivers/tty/synclink_gt.c", "hdlcdev_tx_timeout"],
["drivers/tty/synclinkmp.c", "hdlcdev_tx_timeout"],
["net/atm/lec.c", "lec_tx_timeout"],
["net/bluetooth/bnep/netdev.c", "bnep_net_timeout"]
);
for my $p (@work) {
my @pair = @$p;
my $file = $pair[0];
my $func = $pair[1];
print STDERR $file , ": ", $func,"\n";
our @ARGV = ($file);
while (<ARGV>) {
if (m/($func\s*\(struct\s+net_device\s+\*[A-Za-z_]?[A-Za-z-0-9_]*)(\))/) {
print STDERR "found $1+$2 in $file\n";
}
if (s/($func\s*\(struct\s+net_device\s+\*[A-Za-z_]?[A-Za-z-0-9_]*)(\))/$1, unsigned int txqueue$2/) {
print STDERR "$func found in $file\n";
}
print;
}
}
where the list of files and functions is simply from:
git grep ndo_tx_timeout, with manual addition of headers
in the rare cases where the function is from a header,
then manually changing the few places which actually
call ndo_tx_timeout.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Heiner Kallweit <hkallweit1@gmail.com>
Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Acked-by: Shannon Nelson <snelson@pensando.io>
Reviewed-by: Martin Habets <mhabets@solarflare.com>
changes from v9:
fixup a forward declaration
changes from v9:
more leftovers from v3 change
changes from v8:
fix up a missing direct call to timeout
rebased on net-next
changes from v7:
fixup leftovers from v3 change
changes from v6:
fix typo in rtl driver
changes from v5:
add missing files (allow any net device argument name)
changes from v4:
add a missing driver header
changes from v3:
change queue # to unsigned
Changes from v2:
added headers
Changes from v1:
Fix errors found by kbuild:
generalize the pattern a bit, to pick up
a couple of instances missed by the previous
version.
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-12-10 09:23:51 -05:00
static void iavf_tx_timeout ( struct net_device * netdev , unsigned int txqueue )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2013-12-21 06:12:45 +00:00
adapter - > tx_timeout_count + + ;
2023-06-05 10:52:26 -04:00
iavf_schedule_reset ( adapter , IAVF_FLAG_RESET_NEEDED ) ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_misc_irq_disable - Mask off interrupt generation on the NIC
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* */
2018-09-14 17:37:46 -07:00
static void iavf_misc_irq_disable ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2014-11-11 20:02:42 +00:00
2016-11-08 13:05:08 -08:00
if ( ! adapter - > msix_entries )
return ;
2018-09-14 17:37:49 -07:00
wr32 ( hw , IAVF_VFINT_DYN_CTL01 , 0 ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:49 -07:00
iavf_flush ( hw ) ;
2013-12-21 06:12:45 +00:00
synchronize_irq ( adapter - > msix_entries [ 0 ] . vector ) ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_misc_irq_enable - Enable default interrupt generation settings
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* */
2018-09-14 17:37:46 -07:00
static void iavf_misc_irq_enable ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2014-11-11 20:02:42 +00:00
2018-09-14 17:37:49 -07:00
wr32 ( hw , IAVF_VFINT_DYN_CTL01 , IAVF_VFINT_DYN_CTL01_INTENA_MASK |
IAVF_VFINT_DYN_CTL01_ITR_INDX_MASK ) ;
wr32 ( hw , IAVF_VFINT_ICR0_ENA1 , IAVF_VFINT_ICR0_ENA1_ADMINQ_MASK ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:49 -07:00
iavf_flush ( hw ) ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_irq_disable - Mask off interrupt generation on the NIC
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* */
2018-09-14 17:37:46 -07:00
static void iavf_irq_disable ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
int i ;
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2013-12-21 06:12:45 +00:00
2014-02-20 19:29:07 -08:00
if ( ! adapter - > msix_entries )
return ;
2013-12-21 06:12:45 +00:00
for ( i = 1 ; i < adapter - > num_msix_vectors ; i + + ) {
2018-09-14 17:37:49 -07:00
wr32 ( hw , IAVF_VFINT_DYN_CTLN1 ( i - 1 ) , 0 ) ;
2013-12-21 06:12:45 +00:00
synchronize_irq ( adapter - > msix_entries [ i ] . vector ) ;
}
2018-09-14 17:37:49 -07:00
iavf_flush ( hw ) ;
2013-12-21 06:12:45 +00:00
}
/**
2023-06-08 13:02:26 -07:00
* iavf_irq_enable_queues - Enable interrupt for all queues
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* */
2023-06-21 08:54:05 -07:00
static void iavf_irq_enable_queues ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2013-12-21 06:12:45 +00:00
int i ;
for ( i = 1 ; i < adapter - > num_msix_vectors ; i + + ) {
2023-06-08 13:02:26 -07:00
wr32 ( hw , IAVF_VFINT_DYN_CTLN1 ( i - 1 ) ,
IAVF_VFINT_DYN_CTLN1_INTENA_MASK |
IAVF_VFINT_DYN_CTLN1_ITR_INDX_MASK ) ;
2013-12-21 06:12:45 +00:00
}
}
/**
2018-09-14 17:37:46 -07:00
* iavf_irq_enable - Enable default interrupt generation settings
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
2015-10-13 01:06:27 -06:00
* @ flush : boolean value whether to run rd32 ( )
2013-12-21 06:12:45 +00:00
* */
2018-09-14 17:37:46 -07:00
void iavf_irq_enable ( struct iavf_adapter * adapter , bool flush )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
iavf_misc_irq_enable ( adapter ) ;
2023-06-08 13:02:26 -07:00
iavf_irq_enable_queues ( adapter ) ;
2013-12-21 06:12:45 +00:00
if ( flush )
2018-09-14 17:37:49 -07:00
iavf_flush ( hw ) ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_msix_aq - Interrupt handler for vector 0
2013-12-21 06:12:45 +00:00
* @ irq : interrupt number
* @ data : pointer to netdev
* */
2018-09-14 17:37:46 -07:00
static irqreturn_t iavf_msix_aq ( int irq , void * data )
2013-12-21 06:12:45 +00:00
{
struct net_device * netdev = data ;
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2013-12-21 06:12:45 +00:00
2015-10-04 01:09:49 -07:00
/* handle non-queue interrupts, these reads clear the registers */
2018-09-14 17:37:49 -07:00
rd32 ( hw , IAVF_VFINT_ICR01 ) ;
rd32 ( hw , IAVF_VFINT_ICR0_ENA1 ) ;
2013-12-21 06:12:45 +00:00
2022-02-23 13:35:49 +01:00
if ( adapter - > state ! = __IAVF_REMOVE )
/* schedule work on the private workqueue */
2022-12-15 23:50:48 +01:00
queue_work ( adapter - > wq , & adapter - > adminq_task ) ;
2013-12-21 06:12:45 +00:00
return IRQ_HANDLED ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_msix_clean_rings - MSIX mode Interrupt Handler
2013-12-21 06:12:45 +00:00
* @ irq : interrupt number
* @ data : pointer to a q_vector
* */
2018-09-14 17:37:46 -07:00
static irqreturn_t iavf_msix_clean_rings ( int irq , void * data )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:55 -07:00
struct iavf_q_vector * q_vector = data ;
2013-12-21 06:12:45 +00:00
if ( ! q_vector - > tx . ring & & ! q_vector - > rx . ring )
return IRQ_HANDLED ;
2015-09-29 15:19:50 -07:00
napi_schedule_irqoff ( & q_vector - > napi ) ;
2013-12-21 06:12:45 +00:00
return IRQ_HANDLED ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_map_vector_to_rxq - associate irqs with rx queues
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* @ v_idx : interrupt number
* @ r_idx : queue number
* */
static void
2018-09-14 17:37:46 -07:00
iavf_map_vector_to_rxq ( struct iavf_adapter * adapter , int v_idx , int r_idx )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:55 -07:00
struct iavf_q_vector * q_vector = & adapter - > q_vectors [ v_idx ] ;
struct iavf_ring * rx_ring = & adapter - > rx_rings [ r_idx ] ;
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2013-12-21 06:12:45 +00:00
rx_ring - > q_vector = q_vector ;
rx_ring - > next = q_vector - > rx . ring ;
rx_ring - > vsi = & adapter - > vsi ;
q_vector - > rx . ring = rx_ring ;
q_vector - > rx . count + + ;
2017-12-29 08:52:19 -05:00
q_vector - > rx . next_update = jiffies + 1 ;
2017-12-29 08:51:25 -05:00
q_vector - > rx . target_itr = ITR_TO_REG ( rx_ring - > itr_setting ) ;
2016-09-12 14:18:38 -07:00
q_vector - > ring_mask | = BIT ( r_idx ) ;
2018-09-14 17:37:55 -07:00
wr32 ( hw , IAVF_VFINT_ITRN1 ( IAVF_RX_ITR , q_vector - > reg_idx ) ,
2019-11-05 04:22:14 -08:00
q_vector - > rx . current_itr > > 1 ) ;
2017-12-29 08:51:25 -05:00
q_vector - > rx . current_itr = q_vector - > rx . target_itr ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_map_vector_to_txq - associate irqs with tx queues
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* @ v_idx : interrupt number
* @ t_idx : queue number
* */
static void
2018-09-14 17:37:46 -07:00
iavf_map_vector_to_txq ( struct iavf_adapter * adapter , int v_idx , int t_idx )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:55 -07:00
struct iavf_q_vector * q_vector = & adapter - > q_vectors [ v_idx ] ;
struct iavf_ring * tx_ring = & adapter - > tx_rings [ t_idx ] ;
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2013-12-21 06:12:45 +00:00
tx_ring - > q_vector = q_vector ;
tx_ring - > next = q_vector - > tx . ring ;
tx_ring - > vsi = & adapter - > vsi ;
q_vector - > tx . ring = tx_ring ;
q_vector - > tx . count + + ;
2017-12-29 08:52:19 -05:00
q_vector - > tx . next_update = jiffies + 1 ;
2017-12-29 08:51:25 -05:00
q_vector - > tx . target_itr = ITR_TO_REG ( tx_ring - > itr_setting ) ;
2013-12-21 06:12:45 +00:00
q_vector - > num_ringpairs + + ;
2018-09-14 17:37:55 -07:00
wr32 ( hw , IAVF_VFINT_ITRN1 ( IAVF_TX_ITR , q_vector - > reg_idx ) ,
2019-11-05 04:22:14 -08:00
q_vector - > tx . target_itr > > 1 ) ;
2017-12-29 08:51:25 -05:00
q_vector - > tx . current_itr = q_vector - > tx . target_itr ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_map_rings_to_vectors - Maps descriptor rings to vectors
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure to initialize
*
* This function maps descriptor rings to the queue - specific vectors
* we were allotted through the MSI - X enabling code . Ideally , we ' d have
* one vector per ring / queue , but on a constrained vector budget , we
* group the rings as " efficiently " as possible . You would add new
* mapping configurations in here .
* */
2018-09-14 17:37:46 -07:00
static void iavf_map_rings_to_vectors ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
i40evf: fix ring to vector mapping
The current implementation for mapping queues to vectors is broken
because it attempts to map each Tx and Rx ring to its own vector,
however we use combined queues so we should actually be mapping the
Tx/Rx rings together on one vector.
Also in the current implementation, in the case where we have more
queues than vectors, we attempt to group the queues together into
'chunks' and map each 'chunk' of queues to a vector. Chunking them
together would be more ideal if, and only if, we only had RSS because of
the way the hashing algorithm works but in the case of a future patch
that enables VF ADq, round robin assignment is better and still works
with RSS.
This patch resolves both those issues and simplifies the code needed to
accomplish this. Instead of treating the case where we have more queues
than vectors as special, if we notice our vector index is greater than
vectors, reset the vector index to zero and continue mapping. This
should ensure that in both cases, whether we have enough vectors for
each queue or not, the queues get appropriately mapped.
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2017-07-14 09:27:07 -04:00
int rings_remaining = adapter - > num_active_queues ;
int ridx = 0 , vidx = 0 ;
2013-12-21 06:12:45 +00:00
int q_vectors ;
q_vectors = adapter - > num_msix_vectors - NONQ_VECS ;
i40evf: fix ring to vector mapping
The current implementation for mapping queues to vectors is broken
because it attempts to map each Tx and Rx ring to its own vector,
however we use combined queues so we should actually be mapping the
Tx/Rx rings together on one vector.
Also in the current implementation, in the case where we have more
queues than vectors, we attempt to group the queues together into
'chunks' and map each 'chunk' of queues to a vector. Chunking them
together would be more ideal if, and only if, we only had RSS because of
the way the hashing algorithm works but in the case of a future patch
that enables VF ADq, round robin assignment is better and still works
with RSS.
This patch resolves both those issues and simplifies the code needed to
accomplish this. Instead of treating the case where we have more queues
than vectors as special, if we notice our vector index is greater than
vectors, reset the vector index to zero and continue mapping. This
should ensure that in both cases, whether we have enough vectors for
each queue or not, the queues get appropriately mapped.
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2017-07-14 09:27:07 -04:00
for ( ; ridx < rings_remaining ; ridx + + ) {
2018-09-14 17:37:46 -07:00
iavf_map_vector_to_rxq ( adapter , vidx , ridx ) ;
iavf_map_vector_to_txq ( adapter , vidx , ridx ) ;
2013-12-21 06:12:45 +00:00
i40evf: fix ring to vector mapping
The current implementation for mapping queues to vectors is broken
because it attempts to map each Tx and Rx ring to its own vector,
however we use combined queues so we should actually be mapping the
Tx/Rx rings together on one vector.
Also in the current implementation, in the case where we have more
queues than vectors, we attempt to group the queues together into
'chunks' and map each 'chunk' of queues to a vector. Chunking them
together would be more ideal if, and only if, we only had RSS because of
the way the hashing algorithm works but in the case of a future patch
that enables VF ADq, round robin assignment is better and still works
with RSS.
This patch resolves both those issues and simplifies the code needed to
accomplish this. Instead of treating the case where we have more queues
than vectors as special, if we notice our vector index is greater than
vectors, reset the vector index to zero and continue mapping. This
should ensure that in both cases, whether we have enough vectors for
each queue or not, the queues get appropriately mapped.
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2017-07-14 09:27:07 -04:00
/* In the case where we have more queues than vectors, continue
* round - robin on vectors until all queues are mapped .
*/
if ( + + vidx > = q_vectors )
vidx = 0 ;
2013-12-21 06:12:45 +00:00
}
2018-09-14 17:37:46 -07:00
adapter - > aq_required | = IAVF_FLAG_AQ_MAP_VECTORS ;
2013-12-21 06:12:45 +00:00
}
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
/**
2018-09-14 17:37:46 -07:00
* iavf_irq_affinity_notify - Callback for affinity changes
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
* @ notify : context as to what irq was changed
* @ mask : the new affinity mask
*
* This is a callback function used by the irq_set_affinity_notifier function
* so that we may register to receive changes to the irq affinity masks .
* */
2018-09-14 17:37:46 -07:00
static void iavf_irq_affinity_notify ( struct irq_affinity_notify * notify ,
const cpumask_t * mask )
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
{
2018-09-14 17:37:55 -07:00
struct iavf_q_vector * q_vector =
container_of ( notify , struct iavf_q_vector , affinity_notify ) ;
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
2017-07-12 05:46:05 -04:00
cpumask_copy ( & q_vector - > affinity_mask , mask ) ;
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_irq_affinity_release - Callback for affinity notifier release
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
* @ ref : internal core kernel usage
*
* This is a callback function used by the irq_set_affinity_notifier function
* to inform the current notification subscriber that they will no longer
* receive notifications .
* */
2018-09-14 17:37:46 -07:00
static void iavf_irq_affinity_release ( struct kref * ref ) { }
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
2013-12-21 06:12:45 +00:00
/**
2018-09-14 17:37:46 -07:00
* iavf_request_traffic_irqs - Initialize MSI - X interrupts
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
2018-04-20 01:41:33 -07:00
* @ basename : device basename
2013-12-21 06:12:45 +00:00
*
* Allocates MSI - X vectors for tx and rx handling , and requests
* interrupts from the kernel .
* */
static int
2018-09-14 17:37:46 -07:00
iavf_request_traffic_irqs ( struct iavf_adapter * adapter , char * basename )
2013-12-21 06:12:45 +00:00
{
2017-07-12 05:46:11 -04:00
unsigned int vector , q_vectors ;
unsigned int rx_int_idx = 0 , tx_int_idx = 0 ;
int irq_num , err ;
i40e/i40evf: spread CPU affinity hints across online CPUs only
Currently, when setting up the IRQ for a q_vector, we set an affinity
hint based on the v_idx of that q_vector. Meaning a loop iterates on
v_idx, which is an incremental value, and the cpumask is created based
on this value.
This is a problem in systems with multiple logical CPUs per core (like in
simultaneous multithreading (SMT) scenarios). If we disable some logical
CPUs, by turning SMT off for example, we will end up with a sparse
cpu_online_mask, i.e., only the first CPU in a core is online, and
incremental filling in q_vector cpumask might lead to multiple offline
CPUs being assigned to q_vectors.
Example: if we have a system with 8 cores each one containing 8 logical
CPUs (SMT == 8 in this case), we have 64 CPUs in total. But if SMT is
disabled, only the 1st CPU in each core remains online, so the
cpu_online_mask in this case would have only 8 bits set, in a sparse way.
In general case, when SMT is off the cpu_online_mask has only C bits set:
0, 1*N, 2*N, ..., C*(N-1) where
C == # of cores;
N == # of logical CPUs per core.
In our example, only bits 0, 8, 16, 24, 32, 40, 48, 56 would be set.
Instead, we should only assign hints for CPUs which are online. Even
better, the kernel already provides a function, cpumask_local_spread()
which takes an index and returns a CPU, spreading the interrupts across
local NUMA nodes first, and then remote ones if necessary.
Since we generally have a 1:1 mapping between vectors and CPUs, there
is no real advantage to spreading vectors to local CPUs first. In order
to avoid mismatch of the default XPS hints, we'll pass -1 so that it
spreads across all CPUs without regard to the node locality.
Note that we don't need to change the q_vector->affinity_mask as this is
initialized to cpu_possible_mask, until an actual affinity is set and
then notified back to us.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2017-08-29 05:32:31 -04:00
int cpu ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
iavf_irq_disable ( adapter ) ;
2013-12-21 06:12:45 +00:00
/* Decrement for Other and TCP Timer vectors */
q_vectors = adapter - > num_msix_vectors - NONQ_VECS ;
for ( vector = 0 ; vector < q_vectors ; vector + + ) {
2018-09-14 17:37:55 -07:00
struct iavf_q_vector * q_vector = & adapter - > q_vectors [ vector ] ;
2018-09-14 17:37:47 -07:00
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
irq_num = adapter - > msix_entries [ vector + NONQ_VECS ] . vector ;
2013-12-21 06:12:45 +00:00
if ( q_vector - > tx . ring & & q_vector - > rx . ring ) {
2017-07-12 05:46:11 -04:00
snprintf ( q_vector - > name , sizeof ( q_vector - > name ) ,
2021-08-31 13:39:01 +02:00
" iavf-%s-TxRx-%u " , basename , rx_int_idx + + ) ;
2013-12-21 06:12:45 +00:00
tx_int_idx + + ;
} else if ( q_vector - > rx . ring ) {
2017-07-12 05:46:11 -04:00
snprintf ( q_vector - > name , sizeof ( q_vector - > name ) ,
2021-08-31 13:39:01 +02:00
" iavf-%s-rx-%u " , basename , rx_int_idx + + ) ;
2013-12-21 06:12:45 +00:00
} else if ( q_vector - > tx . ring ) {
2017-07-12 05:46:11 -04:00
snprintf ( q_vector - > name , sizeof ( q_vector - > name ) ,
2021-08-31 13:39:01 +02:00
" iavf-%s-tx-%u " , basename , tx_int_idx + + ) ;
2013-12-21 06:12:45 +00:00
} else {
/* skip this unused q_vector */
continue ;
}
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
err = request_irq ( irq_num ,
2018-09-14 17:37:46 -07:00
iavf_msix_clean_rings ,
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
0 ,
q_vector - > name ,
q_vector ) ;
2013-12-21 06:12:45 +00:00
if ( err ) {
dev_info ( & adapter - > pdev - > dev ,
2015-08-26 15:14:17 -04:00
" Request_irq failed, error: %d \n " , err ) ;
2013-12-21 06:12:45 +00:00
goto free_queue_irqs ;
}
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
/* register for affinity change notifications */
2018-09-14 17:37:46 -07:00
q_vector - > affinity_notify . notify = iavf_irq_affinity_notify ;
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
q_vector - > affinity_notify . release =
2018-09-14 17:37:46 -07:00
iavf_irq_affinity_release ;
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
irq_set_affinity_notifier ( irq_num , & q_vector - > affinity_notify ) ;
i40e/i40evf: spread CPU affinity hints across online CPUs only
Currently, when setting up the IRQ for a q_vector, we set an affinity
hint based on the v_idx of that q_vector. Meaning a loop iterates on
v_idx, which is an incremental value, and the cpumask is created based
on this value.
This is a problem in systems with multiple logical CPUs per core (like in
simultaneous multithreading (SMT) scenarios). If we disable some logical
CPUs, by turning SMT off for example, we will end up with a sparse
cpu_online_mask, i.e., only the first CPU in a core is online, and
incremental filling in q_vector cpumask might lead to multiple offline
CPUs being assigned to q_vectors.
Example: if we have a system with 8 cores each one containing 8 logical
CPUs (SMT == 8 in this case), we have 64 CPUs in total. But if SMT is
disabled, only the 1st CPU in each core remains online, so the
cpu_online_mask in this case would have only 8 bits set, in a sparse way.
In general case, when SMT is off the cpu_online_mask has only C bits set:
0, 1*N, 2*N, ..., C*(N-1) where
C == # of cores;
N == # of logical CPUs per core.
In our example, only bits 0, 8, 16, 24, 32, 40, 48, 56 would be set.
Instead, we should only assign hints for CPUs which are online. Even
better, the kernel already provides a function, cpumask_local_spread()
which takes an index and returns a CPU, spreading the interrupts across
local NUMA nodes first, and then remote ones if necessary.
Since we generally have a 1:1 mapping between vectors and CPUs, there
is no real advantage to spreading vectors to local CPUs first. In order
to avoid mismatch of the default XPS hints, we'll pass -1 so that it
spreads across all CPUs without regard to the node locality.
Note that we don't need to change the q_vector->affinity_mask as this is
initialized to cpu_possible_mask, until an actual affinity is set and
then notified back to us.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2017-08-29 05:32:31 -04:00
/* Spread the IRQ affinity hints across online CPUs. Note that
* get_cpu_mask returns a mask with a permanent lifetime so
2021-09-03 11:24:18 -04:00
* it ' s safe to use as a hint for irq_update_affinity_hint .
2017-07-14 09:10:10 -04:00
*/
i40e/i40evf: spread CPU affinity hints across online CPUs only
Currently, when setting up the IRQ for a q_vector, we set an affinity
hint based on the v_idx of that q_vector. Meaning a loop iterates on
v_idx, which is an incremental value, and the cpumask is created based
on this value.
This is a problem in systems with multiple logical CPUs per core (like in
simultaneous multithreading (SMT) scenarios). If we disable some logical
CPUs, by turning SMT off for example, we will end up with a sparse
cpu_online_mask, i.e., only the first CPU in a core is online, and
incremental filling in q_vector cpumask might lead to multiple offline
CPUs being assigned to q_vectors.
Example: if we have a system with 8 cores each one containing 8 logical
CPUs (SMT == 8 in this case), we have 64 CPUs in total. But if SMT is
disabled, only the 1st CPU in each core remains online, so the
cpu_online_mask in this case would have only 8 bits set, in a sparse way.
In general case, when SMT is off the cpu_online_mask has only C bits set:
0, 1*N, 2*N, ..., C*(N-1) where
C == # of cores;
N == # of logical CPUs per core.
In our example, only bits 0, 8, 16, 24, 32, 40, 48, 56 would be set.
Instead, we should only assign hints for CPUs which are online. Even
better, the kernel already provides a function, cpumask_local_spread()
which takes an index and returns a CPU, spreading the interrupts across
local NUMA nodes first, and then remote ones if necessary.
Since we generally have a 1:1 mapping between vectors and CPUs, there
is no real advantage to spreading vectors to local CPUs first. In order
to avoid mismatch of the default XPS hints, we'll pass -1 so that it
spreads across all CPUs without regard to the node locality.
Note that we don't need to change the q_vector->affinity_mask as this is
initialized to cpu_possible_mask, until an actual affinity is set and
then notified back to us.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2017-08-29 05:32:31 -04:00
cpu = cpumask_local_spread ( q_vector - > v_idx , - 1 ) ;
2021-09-03 11:24:18 -04:00
irq_update_affinity_hint ( irq_num , get_cpu_mask ( cpu ) ) ;
2013-12-21 06:12:45 +00:00
}
return 0 ;
free_queue_irqs :
while ( vector ) {
vector - - ;
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
irq_num = adapter - > msix_entries [ vector + NONQ_VECS ] . vector ;
irq_set_affinity_notifier ( irq_num , NULL ) ;
2021-09-03 11:24:18 -04:00
irq_update_affinity_hint ( irq_num , NULL ) ;
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
free_irq ( irq_num , & adapter - > q_vectors [ vector ] ) ;
2013-12-21 06:12:45 +00:00
}
return err ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_request_misc_irq - Initialize MSI - X interrupts
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
*
* Allocates MSI - X vector 0 and requests interrupts from the kernel . This
* vector is only for the admin queue , and stays active even when the netdev
* is closed .
* */
2018-09-14 17:37:46 -07:00
static int iavf_request_misc_irq ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
struct net_device * netdev = adapter - > netdev ;
int err ;
2014-08-01 13:27:08 -07:00
snprintf ( adapter - > misc_vector_name ,
2018-09-14 17:37:46 -07:00
sizeof ( adapter - > misc_vector_name ) - 1 , " iavf-%s:mbx " ,
2015-02-06 08:52:20 +00:00
dev_name ( & adapter - > pdev - > dev ) ) ;
2013-12-21 06:12:45 +00:00
err = request_irq ( adapter - > msix_entries [ 0 ] . vector ,
2018-09-14 17:37:46 -07:00
& iavf_msix_aq , 0 ,
2014-02-13 03:48:51 -08:00
adapter - > misc_vector_name , netdev ) ;
2013-12-21 06:12:45 +00:00
if ( err ) {
dev_err ( & adapter - > pdev - > dev ,
2014-02-20 19:29:17 -08:00
" request_irq for %s failed: %d \n " ,
adapter - > misc_vector_name , err ) ;
2013-12-21 06:12:45 +00:00
free_irq ( adapter - > msix_entries [ 0 ] . vector , netdev ) ;
}
return err ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_free_traffic_irqs - Free MSI - X interrupts
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
*
* Frees all MSI - X vectors other than 0.
* */
2018-09-14 17:37:46 -07:00
static void iavf_free_traffic_irqs ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
int vector , irq_num , q_vectors ;
2014-11-11 20:02:42 +00:00
2016-11-08 13:05:05 -08:00
if ( ! adapter - > msix_entries )
return ;
2013-12-21 06:12:45 +00:00
q_vectors = adapter - > num_msix_vectors - NONQ_VECS ;
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
for ( vector = 0 ; vector < q_vectors ; vector + + ) {
irq_num = adapter - > msix_entries [ vector + NONQ_VECS ] . vector ;
irq_set_affinity_notifier ( irq_num , NULL ) ;
2021-09-03 11:24:18 -04:00
irq_update_affinity_hint ( irq_num , NULL ) ;
i40e/i40evf: fix interrupt affinity bug
There exists a bug in which a 'perfect storm' can occur and cause
interrupts to fail to be correctly affinitized. This causes unexpected
behavior and has a substantial impact on performance when it happens.
The bug occurs if there is heavy traffic, any number of CPUs that have
an i40e interrupt are pegged at 100%, and the interrupt afffinity for
those CPUs is changed. Instead of moving to the new CPU, the interrupt
continues to be polled while there is heavy traffic.
The bug is most readily realized as the driver is first brought up and
all interrupts start on CPU0. If there is heavy traffic and the
interrupt starts polling before the interrupt is affinitized, the
interrupt will be stuck on CPU0 until traffic stops. The bug, however,
can also be wrought out more simply by affinitizing all the interrupts
to a single CPU and then attempting to move any of those interrupts off
while there is heavy traffic.
This patch fixes the bug by registering for update notifications from
the kernel when the interrupt affinity changes. When that fires, we
cache the intended affinity mask. Then, while polling, if the cpu is
pegged at 100% and we failed to clean the rings, we check to make sure
we have the correct affinity and stop polling if we're firing on the
wrong CPU. When the kernel successfully moves the interrupt, it will
start polling on the correct CPU. The performance impact is minimal
since the only time this section gets executed is when performance is
already compromised by the CPU.
Change-ID: I4410a880159b9dba1f8297aa72bef36dca34e830
Signed-off-by: Alan Brady <alan.brady@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-14 16:24:38 -07:00
free_irq ( irq_num , & adapter - > q_vectors [ vector ] ) ;
2013-12-21 06:12:45 +00:00
}
}
/**
2018-09-14 17:37:46 -07:00
* iavf_free_misc_irq - Free MSI - X miscellaneous vector
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
*
* Frees MSI - X vector 0.
* */
2018-09-14 17:37:46 -07:00
static void iavf_free_misc_irq ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
struct net_device * netdev = adapter - > netdev ;
2016-11-08 13:05:08 -08:00
if ( ! adapter - > msix_entries )
return ;
2013-12-21 06:12:45 +00:00
free_irq ( adapter - > msix_entries [ 0 ] . vector , netdev ) ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_configure_tx - Configure Transmit Unit after Reset
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
*
* Configure the Tx unit of the MAC after a reset .
* */
2018-09-14 17:37:46 -07:00
static void iavf_configure_tx ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2013-12-21 06:12:45 +00:00
int i ;
2014-11-11 20:02:42 +00:00
2014-10-25 03:24:34 +00:00
for ( i = 0 ; i < adapter - > num_active_queues ; i + + )
2018-09-14 17:37:49 -07:00
adapter - > tx_rings [ i ] . tail = hw - > hw_addr + IAVF_QTX_TAIL1 ( i ) ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_configure_rx - Configure Receive Unit after Reset
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
*
* Configure the Rx unit of the MAC after a reset .
* */
2018-09-14 17:37:46 -07:00
static void iavf_configure_rx ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2017-03-14 10:15:27 -07:00
2024-04-18 13:36:09 +02:00
for ( u32 i = 0 ; i < adapter - > num_active_queues ; i + + )
2018-09-14 17:37:49 -07:00
adapter - > rx_rings [ i ] . tail = hw - > hw_addr + IAVF_QRX_TAIL1 ( i ) ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_find_vlan - Search filter list for specific vlan filter
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* @ vlan : vlan tag
*
2017-10-27 11:06:50 -04:00
* Returns ptr to the filter object or NULL . Must be called while holding the
* mac_vlan_list_lock .
2013-12-21 06:12:45 +00:00
* */
static struct
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
iavf_vlan_filter * iavf_find_vlan ( struct iavf_adapter * adapter ,
struct iavf_vlan vlan )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_vlan_filter * f ;
2013-12-21 06:12:45 +00:00
list_for_each_entry ( f , & adapter - > vlan_filter_list , list ) {
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
if ( f - > vlan . vid = = vlan . vid & &
f - > vlan . tpid = = vlan . tpid )
2013-12-21 06:12:45 +00:00
return f ;
}
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
2013-12-21 06:12:45 +00:00
return NULL ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_add_vlan - Add a vlan filter to the list
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* @ vlan : VLAN tag
*
* Returns ptr to the filter object or NULL when no memory available .
* */
static struct
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
iavf_vlan_filter * iavf_add_vlan ( struct iavf_adapter * adapter ,
struct iavf_vlan vlan )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_vlan_filter * f = NULL ;
2015-03-31 00:45:05 -07:00
2017-10-27 11:06:50 -04:00
spin_lock_bh ( & adapter - > mac_vlan_list_lock ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
f = iavf_find_vlan ( adapter , vlan ) ;
2014-11-11 20:02:52 +00:00
if ( ! f ) {
2019-05-14 10:37:02 -07:00
f = kzalloc ( sizeof ( * f ) , GFP_ATOMIC ) ;
2014-11-11 20:02:52 +00:00
if ( ! f )
2015-03-31 00:45:05 -07:00
goto clearout ;
2014-05-10 04:49:04 +00:00
2013-12-21 06:12:45 +00:00
f - > vlan = vlan ;
2019-05-14 10:36:59 -07:00
list_add_tail ( & f - > list , & adapter - > vlan_filter_list ) ;
2023-04-06 15:35:27 -06:00
f - > state = IAVF_VLAN_ADD ;
2023-04-06 15:35:28 -06:00
adapter - > num_vlan_filters + + ;
2023-09-07 17:02:51 +02:00
iavf_schedule_aq_request ( adapter , IAVF_FLAG_AQ_ADD_VLAN_FILTER ) ;
2013-12-21 06:12:45 +00:00
}
2015-03-31 00:45:05 -07:00
clearout :
2017-10-27 11:06:50 -04:00
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
2013-12-21 06:12:45 +00:00
return f ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_del_vlan - Remove a vlan filter from the list
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* @ vlan : VLAN tag
* */
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
static void iavf_del_vlan ( struct iavf_adapter * adapter , struct iavf_vlan vlan )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_vlan_filter * f ;
2015-03-31 00:45:05 -07:00
2017-10-27 11:06:50 -04:00
spin_lock_bh ( & adapter - > mac_vlan_list_lock ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
f = iavf_find_vlan ( adapter , vlan ) ;
2013-12-21 06:12:45 +00:00
if ( f ) {
2023-04-06 15:35:27 -06:00
f - > state = IAVF_VLAN_REMOVE ;
2023-09-07 17:02:51 +02:00
iavf_schedule_aq_request ( adapter , IAVF_FLAG_AQ_DEL_VLAN_FILTER ) ;
2013-12-21 06:12:45 +00:00
}
2017-10-27 11:06:50 -04:00
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
2013-12-21 06:12:45 +00:00
}
2021-06-04 09:53:27 -07:00
/**
* iavf_restore_filters
* @ adapter : board private structure
*
* Restore existing non MAC filters when VF netdev comes back up
* */
static void iavf_restore_filters ( struct iavf_adapter * adapter )
{
2023-04-06 15:35:28 -06:00
struct iavf_vlan_filter * f ;
2021-06-04 09:53:27 -07:00
iavf: Fix VLAN feature flags after VFR
When a VF goes through a reset, it's possible for the VF's feature set
to change. For example it may lose the VIRTCHNL_VF_OFFLOAD_VLAN
capability after VF reset. Unfortunately, the driver doesn't correctly
deal with this situation and errors are seen from downing/upping the
interface and/or moving the interface in/out of a network namespace.
When setting the interface down/up we see the following errors after the
VIRTCHNL_VF_OFFLOAD_VLAN capability was taken away from the VF:
ice 0000:51:00.1: VF 1 failed opcode 12, retval: -64 iavf 0000:51:09.1:
Failed to add VLAN filter, error IAVF_NOT_SUPPORTED ice 0000:51:00.1: VF
1 failed opcode 13, retval: -64 iavf 0000:51:09.1: Failed to delete VLAN
filter, error IAVF_NOT_SUPPORTED
These add/delete errors are happening because the VLAN filters are
tracked internally to the driver and regardless of the VLAN_ALLOWED()
setting the driver tries to delete/re-add them over virtchnl.
Fix the delete failure by making sure to delete any VLAN filter tracking
in the driver when a removal request is made, while preventing the
virtchnl request. This makes it so the driver's VLAN list is up to date
and the errors are
Fix the add failure by making sure the check for VLAN_ALLOWED() during
reset is done after the VF receives its capability list from the PF via
VIRTCHNL_OP_GET_VF_RESOURCES. If VLAN functionality is not allowed, then
prevent requesting re-adding the filters over virtchnl.
When moving the interface into a network namespace we see the following
errors after the VIRTCHNL_VF_OFFLOAD_VLAN capability was taken away from
the VF:
iavf 0000:51:09.1 enp81s0f1v1: NIC Link is Up Speed is 25 Gbps Full Duplex
iavf 0000:51:09.1 temp_27: renamed from enp81s0f1v1
iavf 0000:51:09.1 mgmt: renamed from temp_27
iavf 0000:51:09.1 dev27: set_features() failed (-22); wanted 0x020190001fd54833, left 0x020190001fd54bb3
These errors are happening because we aren't correctly updating the
netdev capabilities and dealing with ndo_fix_features() and
ndo_set_features() correctly.
Fix this by only reporting errors in the driver's ndo_set_features()
callback when VIRTCHNL_VF_OFFLOAD_VLAN is not allowed and any attempt to
enable the VLAN features is made. Also, make sure to disable VLAN
insertion, filtering, and stripping since the VIRTCHNL_VF_OFFLOAD_VLAN
flag applies to all of them and not just VLAN stripping.
Also, after we process the capabilities in the VF reset path, make sure
to call netdev_update_features() in case the capabilities have changed
in order to update the netdev's feature set to match the VF's actual
capabilities.
Lastly, make sure to always report success on VLAN filter delete when
VIRTCHNL_VF_OFFLOAD_VLAN is not supported. The changed flow in
iavf_del_vlans() allows the stack to delete previosly existing VLAN
filters even if VLAN filtering is not allowed. This makes it so the VLAN
filter list is up to date.
Fixes: 8774370d268f ("i40e/i40evf: support for VF VLAN tag stripping control")
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-05 09:20:25 -07:00
/* re-add all VLAN filters */
2023-04-06 15:35:28 -06:00
spin_lock_bh ( & adapter - > mac_vlan_list_lock ) ;
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
2023-04-06 15:35:28 -06:00
list_for_each_entry ( f , & adapter - > vlan_filter_list , list ) {
if ( f - > state = = IAVF_VLAN_INACTIVE )
f - > state = IAVF_VLAN_ADD ;
}
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
adapter - > aq_required | = IAVF_FLAG_AQ_ADD_VLAN_FILTER ;
2021-06-04 09:53:27 -07:00
}
2021-11-29 16:16:04 -08:00
/**
* iavf_get_num_vlans_added - get number of VLANs added
* @ adapter : board private structure
*/
2022-06-10 14:15:54 +02:00
u16 iavf_get_num_vlans_added ( struct iavf_adapter * adapter )
2021-11-29 16:16:04 -08:00
{
2023-04-06 15:35:28 -06:00
return adapter - > num_vlan_filters ;
2021-11-29 16:16:04 -08:00
}
/**
* iavf_get_max_vlans_allowed - get maximum VLANs allowed for this VF
* @ adapter : board private structure
*
* This depends on the negotiated VLAN capability . For VIRTCHNL_VF_OFFLOAD_VLAN ,
* do not impose a limit as that maintains current behavior and for
* VIRTCHNL_VF_OFFLOAD_VLAN_V2 , use the maximum allowed sent from the PF .
* */
static u16 iavf_get_max_vlans_allowed ( struct iavf_adapter * adapter )
{
/* don't impose any limit for VIRTCHNL_VF_OFFLOAD_VLAN since there has
* never been a limit on the VF driver side
*/
if ( VLAN_ALLOWED ( adapter ) )
return VLAN_N_VID ;
else if ( VLAN_V2_ALLOWED ( adapter ) )
return adapter - > vlan_v2_caps . filtering . max_filters ;
return 0 ;
}
/**
* iavf_max_vlans_added - check if maximum VLANs allowed already exist
* @ adapter : board private structure
* */
static bool iavf_max_vlans_added ( struct iavf_adapter * adapter )
{
if ( iavf_get_num_vlans_added ( adapter ) <
iavf_get_max_vlans_allowed ( adapter ) )
return false ;
return true ;
}
2013-12-21 06:12:45 +00:00
/**
2018-09-14 17:37:46 -07:00
* iavf_vlan_rx_add_vid - Add a VLAN filter to a device
2013-12-21 06:12:45 +00:00
* @ netdev : network device struct
2018-04-20 01:41:33 -07:00
* @ proto : unused protocol data
2013-12-21 06:12:45 +00:00
* @ vid : VLAN tag
* */
2018-09-14 17:37:46 -07:00
static int iavf_vlan_rx_add_vid ( struct net_device * netdev ,
__always_unused __be16 proto , u16 vid )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2013-12-21 06:12:45 +00:00
2023-03-15 13:59:25 -06:00
/* Do not track VLAN 0 filter, always added by the PF on VF init */
if ( ! vid )
return 0 ;
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
if ( ! VLAN_FILTERING_ALLOWED ( adapter ) )
2015-08-28 17:55:57 -04:00
return - EIO ;
2021-06-04 09:53:27 -07:00
2021-11-29 16:16:04 -08:00
if ( iavf_max_vlans_added ( adapter ) ) {
netdev_err ( netdev , " Max allowed VLAN filters %u. Remove existing VLANs or disable filtering via Ethtool if supported. \n " ,
iavf_get_max_vlans_allowed ( adapter ) ) ;
return - EIO ;
}
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
if ( ! iavf_add_vlan ( adapter , IAVF_VLAN ( vid , be16_to_cpu ( proto ) ) ) )
2013-12-21 06:12:45 +00:00
return - ENOMEM ;
2021-06-04 09:53:27 -07:00
2013-12-21 06:12:45 +00:00
return 0 ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_vlan_rx_kill_vid - Remove a VLAN filter from a device
2013-12-21 06:12:45 +00:00
* @ netdev : network device struct
2018-04-20 01:41:33 -07:00
* @ proto : unused protocol data
2013-12-21 06:12:45 +00:00
* @ vid : VLAN tag
* */
2018-09-14 17:37:46 -07:00
static int iavf_vlan_rx_kill_vid ( struct net_device * netdev ,
__always_unused __be16 proto , u16 vid )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2013-12-21 06:12:45 +00:00
2023-03-15 13:59:25 -06:00
/* We do not track VLAN 0 filter */
if ( ! vid )
return 0 ;
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
iavf_del_vlan ( adapter , IAVF_VLAN ( vid , be16_to_cpu ( proto ) ) ) ;
2021-06-04 09:53:27 -07:00
return 0 ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_find_filter - Search filter list for specific mac filter
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* @ macaddr : the MAC address
*
2017-10-27 11:06:50 -04:00
* Returns ptr to the filter object or NULL . Must be called while holding the
* mac_vlan_list_lock .
2013-12-21 06:12:45 +00:00
* */
static struct
2018-09-14 17:37:46 -07:00
iavf_mac_filter * iavf_find_filter ( struct iavf_adapter * adapter ,
const u8 * macaddr )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_mac_filter * f ;
2013-12-21 06:12:45 +00:00
if ( ! macaddr )
return NULL ;
list_for_each_entry ( f , & adapter - > mac_filter_list , list ) {
if ( ether_addr_equal ( macaddr , f - > macaddr ) )
return f ;
}
return NULL ;
}
/**
2018-09-14 17:37:55 -07:00
* iavf_add_filter - Add a mac filter to the filter list
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* @ macaddr : the MAC address
*
* Returns ptr to the filter object or NULL when no memory available .
* */
2019-12-17 11:29:23 +01:00
struct iavf_mac_filter * iavf_add_filter ( struct iavf_adapter * adapter ,
const u8 * macaddr )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_mac_filter * f ;
2013-12-21 06:12:45 +00:00
if ( ! macaddr )
return NULL ;
2018-09-14 17:37:46 -07:00
f = iavf_find_filter ( adapter , macaddr ) ;
2014-11-11 20:02:52 +00:00
if ( ! f ) {
2013-12-21 06:12:45 +00:00
f = kzalloc ( sizeof ( * f ) , GFP_ATOMIC ) ;
2017-10-27 11:06:50 -04:00
if ( ! f )
2018-02-05 13:03:36 -08:00
return f ;
2013-12-21 06:12:45 +00:00
2014-05-22 06:32:02 +00:00
ether_addr_copy ( f - > macaddr , macaddr ) ;
2013-12-21 06:12:45 +00:00
2016-05-16 10:26:42 -07:00
list_add_tail ( & f - > list , & adapter - > mac_filter_list ) ;
2013-12-21 06:12:45 +00:00
f - > add = true ;
2022-05-20 12:07:13 +02:00
f - > add_handled = false ;
2021-08-18 10:42:17 -07:00
f - > is_new_mac = true ;
2022-05-20 13:19:27 +02:00
f - > is_primary = ether_addr_equal ( macaddr , adapter - > hw . mac . addr ) ;
2018-09-14 17:37:46 -07:00
adapter - > aq_required | = IAVF_FLAG_AQ_ADD_MAC_FILTER ;
2017-09-07 08:05:47 -04:00
} else {
f - > remove = false ;
2013-12-21 06:12:45 +00:00
}
return f ;
}
/**
2022-05-20 12:07:13 +02:00
* iavf_replace_primary_mac - Replace current primary address
* @ adapter : board private structure
* @ new_mac : new MAC address to be applied
2013-12-21 06:12:45 +00:00
*
2022-05-20 12:07:13 +02:00
* Replace current dev_addr and send request to PF for removal of previous
* primary MAC address filter and addition of new primary MAC filter .
* Return 0 for success , - ENOMEM for failure .
*
* Do not call this with mac_vlan_list_lock !
2013-12-21 06:12:45 +00:00
* */
2023-06-21 08:54:05 -07:00
static int iavf_replace_primary_mac ( struct iavf_adapter * adapter ,
const u8 * new_mac )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2023-06-19 04:06:35 -04:00
struct iavf_mac_filter * new_f ;
struct iavf_mac_filter * old_f ;
2013-12-21 06:12:45 +00:00
2017-10-27 11:06:50 -04:00
spin_lock_bh ( & adapter - > mac_vlan_list_lock ) ;
2023-06-19 04:06:35 -04:00
new_f = iavf_add_filter ( adapter , new_mac ) ;
if ( ! new_f ) {
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
return - ENOMEM ;
2022-05-20 12:07:13 +02:00
}
2023-06-19 04:06:35 -04:00
old_f = iavf_find_filter ( adapter , hw - > mac . addr ) ;
if ( old_f ) {
old_f - > is_primary = false ;
old_f - > remove = true ;
2018-09-14 17:37:46 -07:00
adapter - > aq_required | = IAVF_FLAG_AQ_DEL_MAC_FILTER ;
2015-08-31 19:54:44 -04:00
}
2023-06-19 04:06:35 -04:00
/* Always send the request to add if changing primary MAC,
* even if filter is already present on the list
*/
new_f - > is_primary = true ;
new_f - > add = true ;
ether_addr_copy ( hw - > mac . addr , new_mac ) ;
2013-12-21 06:12:45 +00:00
2022-01-19 11:15:21 +01:00
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
/* schedule the watchdog task to immediately process the request */
2023-11-14 23:35:22 +01:00
iavf_schedule_aq_request ( adapter , IAVF_FLAG_AQ_ADD_MAC_FILTER ) ;
2023-06-19 04:06:35 -04:00
return 0 ;
2022-05-20 12:07:13 +02:00
}
/**
* iavf_is_mac_set_handled - wait for a response to set MAC from PF
* @ netdev : network interface device structure
* @ macaddr : MAC address to set
*
* Returns true on success , false on failure
*/
static bool iavf_is_mac_set_handled ( struct net_device * netdev ,
const u8 * macaddr )
{
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
struct iavf_mac_filter * f ;
bool ret = false ;
spin_lock_bh ( & adapter - > mac_vlan_list_lock ) ;
f = iavf_find_filter ( adapter , macaddr ) ;
if ( ! f | | ( ! f - > add & & f - > add_handled ) )
ret = true ;
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
return ret ;
}
/**
* iavf_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 iavf_set_mac ( struct net_device * netdev , void * p )
{
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
struct sockaddr * addr = p ;
int ret ;
2022-01-19 11:15:21 +01:00
2022-05-20 12:07:13 +02:00
if ( ! is_valid_ether_addr ( addr - > sa_data ) )
return - EADDRNOTAVAIL ;
ret = iavf_replace_primary_mac ( adapter , addr - > sa_data ) ;
if ( ret )
return ret ;
2022-09-01 16:32:06 +02:00
ret = wait_event_interruptible_timeout ( adapter - > vc_waitqueue ,
iavf_is_mac_set_handled ( netdev , addr - > sa_data ) ,
msecs_to_jiffies ( 2500 ) ) ;
2022-05-20 12:07:13 +02:00
/* If ret < 0 then it means wait was interrupted.
* If ret = = 0 then it means we got a timeout .
* else it means we got response for set MAC from PF ,
* check if netdev MAC was updated to requested MAC ,
* if yes then set MAC succeeded otherwise it failed return - EACCES
*/
if ( ret < 0 )
return ret ;
if ( ! ret )
return - EAGAIN ;
if ( ! ether_addr_equal ( netdev - > dev_addr , addr - > sa_data ) )
return - EACCES ;
return 0 ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_addr_sync - Callback for dev_ ( mc | uc ) _sync to add address
2018-01-22 12:00:38 -05:00
* @ 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 and guarantee to hold the hash lock .
*/
2018-09-14 17:37:46 -07:00
static int iavf_addr_sync ( struct net_device * netdev , const u8 * addr )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2015-08-26 15:14:20 -04:00
2018-09-14 17:37:46 -07:00
if ( iavf_add_filter ( adapter , addr ) )
2018-01-22 12:00:38 -05:00
return 0 ;
else
return - ENOMEM ;
}
2015-08-26 15:14:20 -04:00
2018-01-22 12:00:38 -05:00
/**
2018-09-14 17:37:46 -07:00
* iavf_addr_unsync - Callback for dev_ ( mc | uc ) _sync to remove address
2018-01-22 12:00:38 -05:00
* @ netdev : the netdevice
* @ addr : address to add
*
* Called by __dev_ ( mc | uc ) _sync when an address needs to be removed . We call
* __dev_ ( uc | mc ) _sync from . set_rx_mode and guarantee to hold the hash lock .
*/
2018-09-14 17:37:46 -07:00
static int iavf_addr_unsync ( struct net_device * netdev , const u8 * addr )
2018-01-22 12:00:38 -05:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
struct iavf_mac_filter * f ;
2015-08-26 15:14:20 -04:00
2018-01-22 12:00:38 -05:00
/* Under some circumstances, we might receive a request to delete
* our own device address from our uc list . Because we store the
* device address in the VSI ' s MAC / VLAN filter list , we need to ignore
* such requests and not delete our device address from this list .
*/
if ( ether_addr_equal ( addr , netdev - > dev_addr ) )
return 0 ;
2015-08-26 15:14:20 -04:00
2018-09-14 17:37:46 -07:00
f = iavf_find_filter ( adapter , addr ) ;
2018-01-22 12:00:38 -05:00
if ( f ) {
2015-08-26 15:14:20 -04:00
f - > remove = true ;
2018-09-14 17:37:46 -07:00
adapter - > aq_required | = IAVF_FLAG_AQ_DEL_MAC_FILTER ;
2013-12-21 06:12:45 +00:00
}
2018-01-22 12:00:38 -05:00
return 0 ;
}
2023-08-21 17:01:44 -06:00
/**
* iavf_promiscuous_mode_changed - check if promiscuous mode bits changed
* @ adapter : device specific adapter
*/
bool iavf_promiscuous_mode_changed ( struct iavf_adapter * adapter )
{
return ( adapter - > current_netdev_promisc_flags ^ adapter - > netdev - > flags ) &
( IFF_PROMISC | IFF_ALLMULTI ) ;
}
2018-01-22 12:00:38 -05:00
/**
2018-09-14 17:37:46 -07:00
* iavf_set_rx_mode - NDO callback to set the netdev filters
2018-01-22 12:00:38 -05:00
* @ netdev : network interface device structure
* */
2018-09-14 17:37:46 -07:00
static void iavf_set_rx_mode ( struct net_device * netdev )
2018-01-22 12:00:38 -05:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2018-01-22 12:00:38 -05:00
spin_lock_bh ( & adapter - > mac_vlan_list_lock ) ;
2018-09-14 17:37:46 -07:00
__dev_uc_sync ( netdev , iavf_addr_sync , iavf_addr_unsync ) ;
__dev_mc_sync ( netdev , iavf_addr_sync , iavf_addr_unsync ) ;
2018-01-22 12:00:38 -05:00
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
2016-04-12 08:30:52 -07:00
2023-08-21 17:01:44 -06:00
spin_lock_bh ( & adapter - > current_netdev_promisc_flags_lock ) ;
if ( iavf_promiscuous_mode_changed ( adapter ) )
adapter - > aq_required | = IAVF_FLAG_AQ_CONFIGURE_PROMISC_MODE ;
spin_unlock_bh ( & adapter - > current_netdev_promisc_flags_lock ) ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_napi_enable_all - enable NAPI on all queue vectors
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* */
2018-09-14 17:37:46 -07:00
static void iavf_napi_enable_all ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
int q_idx ;
2018-09-14 17:37:55 -07:00
struct iavf_q_vector * q_vector ;
2013-12-21 06:12:45 +00:00
int q_vectors = adapter - > num_msix_vectors - NONQ_VECS ;
for ( q_idx = 0 ; q_idx < q_vectors ; q_idx + + ) {
struct napi_struct * napi ;
2014-11-11 20:02:42 +00:00
2015-10-26 19:44:39 -04:00
q_vector = & adapter - > q_vectors [ q_idx ] ;
2013-12-21 06:12:45 +00:00
napi = & q_vector - > napi ;
napi_enable ( napi ) ;
}
}
/**
2018-09-14 17:37:46 -07:00
* iavf_napi_disable_all - disable NAPI on all queue vectors
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* */
2018-09-14 17:37:46 -07:00
static void iavf_napi_disable_all ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
int q_idx ;
2018-09-14 17:37:55 -07:00
struct iavf_q_vector * q_vector ;
2013-12-21 06:12:45 +00:00
int q_vectors = adapter - > num_msix_vectors - NONQ_VECS ;
for ( q_idx = 0 ; q_idx < q_vectors ; q_idx + + ) {
2015-10-26 19:44:39 -04:00
q_vector = & adapter - > q_vectors [ q_idx ] ;
2013-12-21 06:12:45 +00:00
napi_disable ( & q_vector - > napi ) ;
}
}
/**
2018-09-14 17:37:46 -07:00
* iavf_configure - set up transmit and receive data structures
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* */
2018-09-14 17:37:46 -07:00
static void iavf_configure ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
struct net_device * netdev = adapter - > netdev ;
int i ;
2018-09-14 17:37:46 -07:00
iavf_set_rx_mode ( netdev ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
iavf_configure_tx ( adapter ) ;
iavf_configure_rx ( adapter ) ;
adapter - > aq_required | = IAVF_FLAG_AQ_CONFIGURE_QUEUES ;
2013-12-21 06:12:45 +00:00
2014-10-25 03:24:34 +00:00
for ( i = 0 ; i < adapter - > num_active_queues ; i + + ) {
2018-09-14 17:37:55 -07:00
struct iavf_ring * ring = & adapter - > rx_rings [ i ] ;
2014-11-11 20:02:42 +00:00
2018-09-14 17:37:55 -07:00
iavf_alloc_rx_buffers ( ring , IAVF_DESC_UNUSED ( ring ) ) ;
2013-12-21 06:12:45 +00:00
}
}
/**
2018-09-14 17:37:46 -07:00
* iavf_up_complete - Finish the last steps of bringing up a connection
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
2017-10-27 11:06:52 -04:00
*
2023-10-27 10:59:34 -07:00
* Expects to be called while holding crit_lock .
2013-12-21 06:12:45 +00:00
* */
2018-09-14 17:37:46 -07:00
static void iavf_up_complete ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
2021-08-19 08:47:40 +00:00
iavf_change_state ( adapter , __IAVF_RUNNING ) ;
2018-09-14 17:37:55 -07:00
clear_bit ( __IAVF_VSI_DOWN , adapter - > vsi . state ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
iavf_napi_enable_all ( adapter ) ;
2013-12-21 06:12:45 +00:00
2023-11-14 23:35:22 +01:00
iavf_schedule_aq_request ( adapter , IAVF_FLAG_AQ_ENABLE_QUEUES ) ;
2013-12-21 06:12:45 +00:00
}
/**
2022-08-18 13:32:33 +02:00
* iavf_clear_mac_vlan_filters - Remove mac and vlan filters not sent to PF
* yet and mark other to be removed .
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* */
2022-08-18 13:32:33 +02:00
static void iavf_clear_mac_vlan_filters ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
2022-08-18 13:32:33 +02:00
struct iavf_vlan_filter * vlf , * vlftmp ;
struct iavf_mac_filter * f , * ftmp ;
2014-12-09 08:53:04 +00:00
2017-10-27 11:06:50 -04:00
spin_lock_bh ( & adapter - > mac_vlan_list_lock ) ;
2018-01-22 12:00:38 -05:00
/* clear the sync flag on all filters */
__dev_uc_unsync ( adapter - > netdev , NULL ) ;
__dev_mc_unsync ( adapter - > netdev , NULL ) ;
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
/* remove all MAC filters */
2022-08-18 13:32:33 +02:00
list_for_each_entry_safe ( f , ftmp , & adapter - > mac_filter_list ,
list ) {
if ( f - > add ) {
list_del ( & f - > list ) ;
kfree ( f ) ;
} else {
f - > remove = true ;
}
2013-12-21 06:12:45 +00:00
}
2018-01-22 12:00:38 -05:00
2023-04-06 15:35:28 -06:00
/* disable all VLAN filters */
2022-08-18 13:32:33 +02:00
list_for_each_entry_safe ( vlf , vlftmp , & adapter - > vlan_filter_list ,
2023-04-06 15:35:28 -06:00
list )
vlf - > state = IAVF_VLAN_DISABLE ;
2017-10-27 11:06:50 -04:00
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
2022-08-18 13:32:33 +02:00
}
/**
* iavf_clear_cloud_filters - Remove cloud filters not sent to PF yet and
* mark other to be removed .
* @ adapter : board private structure
* */
static void iavf_clear_cloud_filters ( struct iavf_adapter * adapter )
{
struct iavf_cloud_filter * cf , * cftmp ;
2017-10-27 11:06:50 -04:00
2018-01-23 08:51:05 -08:00
/* remove all cloud filters */
spin_lock_bh ( & adapter - > cloud_filter_list_lock ) ;
2022-08-18 13:32:33 +02:00
list_for_each_entry_safe ( cf , cftmp , & adapter - > cloud_filter_list ,
list ) {
if ( cf - > add ) {
list_del ( & cf - > list ) ;
kfree ( cf ) ;
adapter - > num_cloud_filters - - ;
} else {
cf - > del = true ;
}
2018-01-23 08:51:05 -08:00
}
spin_unlock_bh ( & adapter - > cloud_filter_list_lock ) ;
2022-08-18 13:32:33 +02:00
}
/**
* iavf_clear_fdir_filters - Remove fdir filters not sent to PF yet and mark
* other to be removed .
* @ adapter : board private structure
* */
static void iavf_clear_fdir_filters ( struct iavf_adapter * adapter )
{
iavf: Introduce new state machines for flow director
New states introduced:
IAVF_FDIR_FLTR_DIS_REQUEST
IAVF_FDIR_FLTR_DIS_PENDING
IAVF_FDIR_FLTR_INACTIVE
Current FDIR state machines (SM) are not adequate to handle a few
scenarios in the link DOWN/UP event, reset event and ntuple-feature.
For example, when VF link goes DOWN and comes back UP administratively,
the expectation is that previously installed filters should also be
restored. But with current SM, filters are not restored.
So with new SM, during link DOWN filters are marked as INACTIVE in
the iavf list but removed from PF. After link UP, SM will transition
from INACTIVE to ADD_REQUEST to restore the filter.
Similarly, with VF reset, filters will be removed from the PF, but
marked as INACTIVE in the iavf list. Filters will be restored after
reset completion.
Steps to reproduce:
-------------------
1. Create a VF. Here VF is enp8s0.
2. Assign IP addresses to VF and link partner and ping continuously
from remote. Here remote IP is 1.1.1.1.
3. Check default RX Queue of traffic.
ethtool -S enp8s0 | grep -E "rx-[[:digit:]]+\.packets"
4. Add filter - change default RX Queue (to 15 here)
ethtool -U ens8s0 flow-type ip4 src-ip 1.1.1.1 action 15 loc 5
5. Ensure filter gets added and traffic is received on RX queue 15 now.
Link event testing:
-------------------
6. Bring VF link down and up. If traffic flows to configured queue 15,
test is success, otherwise it is a failure.
Reset event testing:
--------------------
7. Reset the VF. If traffic flows to configured queue 15, test is success,
otherwise it is a failure.
Fixes: 0dbfbabb840d ("iavf: Add framework to enable ethtool ntuple filters")
Signed-off-by: Piotr Gardocki <piotrx.gardocki@intel.com>
Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
Signed-off-by: Ranganatha Rao <ranganatha.rao@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-11-21 22:47:15 -05:00
struct iavf_fdir_fltr * fdir ;
2018-01-23 08:51:05 -08:00
2021-03-09 11:08:11 +08:00
/* remove all Flow Director filters */
spin_lock_bh ( & adapter - > fdir_fltr_lock ) ;
iavf: Introduce new state machines for flow director
New states introduced:
IAVF_FDIR_FLTR_DIS_REQUEST
IAVF_FDIR_FLTR_DIS_PENDING
IAVF_FDIR_FLTR_INACTIVE
Current FDIR state machines (SM) are not adequate to handle a few
scenarios in the link DOWN/UP event, reset event and ntuple-feature.
For example, when VF link goes DOWN and comes back UP administratively,
the expectation is that previously installed filters should also be
restored. But with current SM, filters are not restored.
So with new SM, during link DOWN filters are marked as INACTIVE in
the iavf list but removed from PF. After link UP, SM will transition
from INACTIVE to ADD_REQUEST to restore the filter.
Similarly, with VF reset, filters will be removed from the PF, but
marked as INACTIVE in the iavf list. Filters will be restored after
reset completion.
Steps to reproduce:
-------------------
1. Create a VF. Here VF is enp8s0.
2. Assign IP addresses to VF and link partner and ping continuously
from remote. Here remote IP is 1.1.1.1.
3. Check default RX Queue of traffic.
ethtool -S enp8s0 | grep -E "rx-[[:digit:]]+\.packets"
4. Add filter - change default RX Queue (to 15 here)
ethtool -U ens8s0 flow-type ip4 src-ip 1.1.1.1 action 15 loc 5
5. Ensure filter gets added and traffic is received on RX queue 15 now.
Link event testing:
-------------------
6. Bring VF link down and up. If traffic flows to configured queue 15,
test is success, otherwise it is a failure.
Reset event testing:
--------------------
7. Reset the VF. If traffic flows to configured queue 15, test is success,
otherwise it is a failure.
Fixes: 0dbfbabb840d ("iavf: Add framework to enable ethtool ntuple filters")
Signed-off-by: Piotr Gardocki <piotrx.gardocki@intel.com>
Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
Signed-off-by: Ranganatha Rao <ranganatha.rao@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-11-21 22:47:15 -05:00
list_for_each_entry ( fdir , & adapter - > fdir_list_head , list ) {
2022-08-18 13:32:33 +02:00
if ( fdir - > state = = IAVF_FDIR_FLTR_ADD_REQUEST ) {
iavf: Introduce new state machines for flow director
New states introduced:
IAVF_FDIR_FLTR_DIS_REQUEST
IAVF_FDIR_FLTR_DIS_PENDING
IAVF_FDIR_FLTR_INACTIVE
Current FDIR state machines (SM) are not adequate to handle a few
scenarios in the link DOWN/UP event, reset event and ntuple-feature.
For example, when VF link goes DOWN and comes back UP administratively,
the expectation is that previously installed filters should also be
restored. But with current SM, filters are not restored.
So with new SM, during link DOWN filters are marked as INACTIVE in
the iavf list but removed from PF. After link UP, SM will transition
from INACTIVE to ADD_REQUEST to restore the filter.
Similarly, with VF reset, filters will be removed from the PF, but
marked as INACTIVE in the iavf list. Filters will be restored after
reset completion.
Steps to reproduce:
-------------------
1. Create a VF. Here VF is enp8s0.
2. Assign IP addresses to VF and link partner and ping continuously
from remote. Here remote IP is 1.1.1.1.
3. Check default RX Queue of traffic.
ethtool -S enp8s0 | grep -E "rx-[[:digit:]]+\.packets"
4. Add filter - change default RX Queue (to 15 here)
ethtool -U ens8s0 flow-type ip4 src-ip 1.1.1.1 action 15 loc 5
5. Ensure filter gets added and traffic is received on RX queue 15 now.
Link event testing:
-------------------
6. Bring VF link down and up. If traffic flows to configured queue 15,
test is success, otherwise it is a failure.
Reset event testing:
--------------------
7. Reset the VF. If traffic flows to configured queue 15, test is success,
otherwise it is a failure.
Fixes: 0dbfbabb840d ("iavf: Add framework to enable ethtool ntuple filters")
Signed-off-by: Piotr Gardocki <piotrx.gardocki@intel.com>
Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
Signed-off-by: Ranganatha Rao <ranganatha.rao@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-11-21 22:47:15 -05:00
/* Cancel a request, keep filter as inactive */
fdir - > state = IAVF_FDIR_FLTR_INACTIVE ;
} else if ( fdir - > state = = IAVF_FDIR_FLTR_ADD_PENDING | |
fdir - > state = = IAVF_FDIR_FLTR_ACTIVE ) {
/* Disable filters which are active or have a pending
* request to PF to be added
*/
fdir - > state = IAVF_FDIR_FLTR_DIS_REQUEST ;
2022-08-18 13:32:33 +02:00
}
2021-03-09 11:08:11 +08:00
}
spin_unlock_bh ( & adapter - > fdir_fltr_lock ) ;
2022-08-18 13:32:33 +02:00
}
/**
* iavf_clear_adv_rss_conf - Remove adv rss conf not sent to PF yet and mark
* other to be removed .
* @ adapter : board private structure
* */
static void iavf_clear_adv_rss_conf ( struct iavf_adapter * adapter )
{
struct iavf_adv_rss * rss , * rsstmp ;
2021-03-09 11:08:11 +08:00
2021-04-13 08:48:41 +08:00
/* remove all advance RSS configuration */
spin_lock_bh ( & adapter - > adv_rss_lock ) ;
2022-08-18 13:32:33 +02:00
list_for_each_entry_safe ( rss , rsstmp , & adapter - > adv_rss_list_head ,
list ) {
if ( rss - > state = = IAVF_ADV_RSS_ADD_REQUEST ) {
list_del ( & rss - > list ) ;
kfree ( rss ) ;
} else {
rss - > state = IAVF_ADV_RSS_DEL_REQUEST ;
}
}
2021-04-13 08:48:41 +08:00
spin_unlock_bh ( & adapter - > adv_rss_lock ) ;
2022-08-18 13:32:33 +02:00
}
/**
* iavf_down - Shutdown the connection processing
* @ adapter : board private structure
*
2023-10-27 10:59:34 -07:00
* Expects to be called while holding crit_lock .
2022-08-18 13:32:33 +02:00
* */
void iavf_down ( struct iavf_adapter * adapter )
{
struct net_device * netdev = adapter - > netdev ;
if ( adapter - > state < = __IAVF_DOWN_PENDING )
return ;
netif_carrier_off ( netdev ) ;
netif_tx_disable ( netdev ) ;
adapter - > link_up = false ;
iavf_napi_disable_all ( adapter ) ;
iavf_irq_disable ( adapter ) ;
iavf_clear_mac_vlan_filters ( adapter ) ;
iavf_clear_cloud_filters ( adapter ) ;
iavf_clear_fdir_filters ( adapter ) ;
iavf_clear_adv_rss_conf ( adapter ) ;
2021-04-13 08:48:41 +08:00
2023-10-27 10:59:36 -07:00
if ( adapter - > flags & IAVF_FLAG_PF_COMMS_FAILED )
return ;
if ( ! test_bit ( __IAVF_IN_REMOVE_TASK , & adapter - > crit_section ) ) {
2014-12-09 08:53:04 +00:00
/* cancel any current operation */
2017-05-11 11:23:11 -07:00
adapter - > current_op = VIRTCHNL_OP_UNKNOWN ;
2014-12-09 08:53:04 +00:00
/* Schedule operations to close down the HW. Don't wait
* here for this to complete . The watchdog is still running
* and it will take care of this .
*/
2022-08-18 13:32:33 +02:00
if ( ! list_empty ( & adapter - > mac_filter_list ) )
adapter - > aq_required | = IAVF_FLAG_AQ_DEL_MAC_FILTER ;
if ( ! list_empty ( & adapter - > vlan_filter_list ) )
adapter - > aq_required | = IAVF_FLAG_AQ_DEL_VLAN_FILTER ;
if ( ! list_empty ( & adapter - > cloud_filter_list ) )
adapter - > aq_required | = IAVF_FLAG_AQ_DEL_CLOUD_FILTER ;
if ( ! list_empty ( & adapter - > fdir_list_head ) )
adapter - > aq_required | = IAVF_FLAG_AQ_DEL_FDIR_FILTER ;
if ( ! list_empty ( & adapter - > adv_rss_list_head ) )
adapter - > aq_required | = IAVF_FLAG_AQ_DEL_ADV_RSS_CFG ;
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
}
2013-12-21 06:12:45 +00:00
2023-11-14 23:35:22 +01:00
iavf_schedule_aq_request ( adapter , IAVF_FLAG_AQ_DISABLE_QUEUES ) ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_acquire_msix_vectors - Setup the MSIX capability
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
* @ vectors : number of vectors to request
*
* Work with the OS to set up the MSIX vectors needed .
*
* Returns 0 on success , negative on failure
* */
static int
2018-09-14 17:37:46 -07:00
iavf_acquire_msix_vectors ( struct iavf_adapter * adapter , int vectors )
2013-12-21 06:12:45 +00:00
{
int err , vector_threshold ;
/* We'll want at least 3 (vector_threshold):
* 0 ) Other ( Admin Queue and link , mostly )
* 1 ) TxQ [ 0 ] Cleanup
* 2 ) RxQ [ 0 ] Cleanup
*/
vector_threshold = MIN_MSIX_COUNT ;
/* The more we get, the more we will assign to Tx/Rx Cleanup
* for the separate queues . . . where Rx Cleanup > = Tx Cleanup .
* Right now , we simply care about how many we ' ll get ; we ' ll
* set them up later while requesting irq ' s .
*/
2014-04-28 17:53:16 +00:00
err = pci_enable_msix_range ( adapter - > pdev , adapter - > msix_entries ,
vector_threshold , vectors ) ;
if ( err < 0 ) {
2014-05-10 04:49:06 +00:00
dev_err ( & adapter - > pdev - > dev , " Unable to allocate MSI-X interrupts \n " ) ;
2013-12-21 06:12:45 +00:00
kfree ( adapter - > msix_entries ) ;
adapter - > msix_entries = NULL ;
2014-04-28 17:53:16 +00:00
return err ;
2013-12-21 06:12:45 +00:00
}
2014-04-28 17:53:16 +00:00
/* Adjust for only the vectors we'll use, which is minimum
* of max_msix_q_vectors + NONQ_VECS , or the number of
* vectors we were allocated .
*/
adapter - > num_msix_vectors = err ;
return 0 ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_free_queues - Free memory for all rings
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure to initialize
*
* Free all of the memory associated with queue pairs .
* */
2018-09-14 17:37:46 -07:00
static void iavf_free_queues ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
if ( ! adapter - > vsi_res )
return ;
2017-06-07 05:43:01 -04:00
adapter - > num_active_queues = 0 ;
2015-10-26 19:44:40 -04:00
kfree ( adapter - > tx_rings ) ;
2015-12-09 15:50:30 -08:00
adapter - > tx_rings = NULL ;
2015-10-26 19:44:40 -04:00
kfree ( adapter - > rx_rings ) ;
2015-12-09 15:50:30 -08:00
adapter - > rx_rings = NULL ;
2013-12-21 06:12:45 +00:00
}
2021-11-29 16:16:02 -08:00
/**
* iavf_set_queue_vlan_tag_loc - set location for VLAN tag offload
* @ adapter : board private structure
*
* Based on negotiated capabilities , the VLAN tag needs to be inserted and / or
* stripped in certain descriptor fields . Instead of checking the offload
* capability bits in the hot path , cache the location the ring specific
* flags .
*/
void iavf_set_queue_vlan_tag_loc ( struct iavf_adapter * adapter )
{
int i ;
for ( i = 0 ; i < adapter - > num_active_queues ; i + + ) {
struct iavf_ring * tx_ring = & adapter - > tx_rings [ i ] ;
struct iavf_ring * rx_ring = & adapter - > rx_rings [ i ] ;
/* prevent multiple L2TAG bits being set after VFR */
tx_ring - > flags & =
~ ( IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1 |
IAVF_TXR_FLAGS_VLAN_TAG_LOC_L2TAG2 ) ;
rx_ring - > flags & =
~ ( IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1 |
IAVF_RXR_FLAGS_VLAN_TAG_LOC_L2TAG2_2 ) ;
if ( VLAN_ALLOWED ( adapter ) ) {
tx_ring - > flags | = IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1 ;
rx_ring - > flags | = IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1 ;
} else if ( VLAN_V2_ALLOWED ( adapter ) ) {
struct virtchnl_vlan_supported_caps * stripping_support ;
struct virtchnl_vlan_supported_caps * insertion_support ;
stripping_support =
& adapter - > vlan_v2_caps . offloads . stripping_support ;
insertion_support =
& adapter - > vlan_v2_caps . offloads . insertion_support ;
if ( stripping_support - > outer ) {
if ( stripping_support - > outer &
VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1 )
rx_ring - > flags | =
IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1 ;
else if ( stripping_support - > outer &
VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2 )
rx_ring - > flags | =
IAVF_RXR_FLAGS_VLAN_TAG_LOC_L2TAG2_2 ;
} else if ( stripping_support - > inner ) {
if ( stripping_support - > inner &
VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1 )
rx_ring - > flags | =
IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1 ;
else if ( stripping_support - > inner &
VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2 )
rx_ring - > flags | =
IAVF_RXR_FLAGS_VLAN_TAG_LOC_L2TAG2_2 ;
}
if ( insertion_support - > outer ) {
if ( insertion_support - > outer &
VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1 )
tx_ring - > flags | =
IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1 ;
else if ( insertion_support - > outer &
VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2 )
tx_ring - > flags | =
IAVF_TXR_FLAGS_VLAN_TAG_LOC_L2TAG2 ;
} else if ( insertion_support - > inner ) {
if ( insertion_support - > inner &
VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1 )
tx_ring - > flags | =
IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1 ;
else if ( insertion_support - > inner &
VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2 )
tx_ring - > flags | =
IAVF_TXR_FLAGS_VLAN_TAG_LOC_L2TAG2 ;
}
}
}
}
2013-12-21 06:12:45 +00:00
/**
2018-09-14 17:37:46 -07:00
* iavf_alloc_queues - Allocate memory for all rings
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure to initialize
*
* We allocate one ring per queue at run - time since we don ' t know the
* number of queues at compile - time . The polling_netdev array is
* intended for Multiqueue , but should work fine with a single queue .
* */
2018-09-14 17:37:46 -07:00
static int iavf_alloc_queues ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
2017-06-07 05:43:01 -04:00
int i , num_active_queues ;
2017-08-22 06:57:50 -04:00
/* If we're in reset reallocating queues we don't actually know yet for
* certain the PF gave us the number of queues we asked for but we ' ll
* assume it did . Once basic reset is finished we ' ll confirm once we
* start negotiating config with PF .
*/
if ( adapter - > num_req_queues )
num_active_queues = adapter - > num_req_queues ;
2018-01-23 08:50:59 -08:00
else if ( ( adapter - > vf_res - > vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ ) & &
adapter - > num_tc )
num_active_queues = adapter - > ch_config . total_qps ;
2017-08-22 06:57:50 -04:00
else
num_active_queues = min_t ( int ,
adapter - > vsi_res - > num_queue_pairs ,
( int ) ( num_online_cpus ( ) ) ) ;
2013-12-21 06:12:45 +00:00
2017-06-07 05:43:01 -04:00
adapter - > tx_rings = kcalloc ( num_active_queues ,
2018-09-14 17:37:55 -07:00
sizeof ( struct iavf_ring ) , GFP_KERNEL ) ;
2015-10-26 19:44:40 -04:00
if ( ! adapter - > tx_rings )
goto err_out ;
2017-06-07 05:43:01 -04:00
adapter - > rx_rings = kcalloc ( num_active_queues ,
2018-09-14 17:37:55 -07:00
sizeof ( struct iavf_ring ) , GFP_KERNEL ) ;
2015-10-26 19:44:40 -04:00
if ( ! adapter - > rx_rings )
goto err_out ;
2017-06-07 05:43:01 -04:00
for ( i = 0 ; i < num_active_queues ; i + + ) {
2018-09-14 17:37:55 -07:00
struct iavf_ring * tx_ring ;
struct iavf_ring * rx_ring ;
2013-12-21 06:12:45 +00:00
2015-10-26 19:44:40 -04:00
tx_ring = & adapter - > tx_rings [ i ] ;
2013-12-21 06:12:45 +00:00
tx_ring - > queue_index = i ;
tx_ring - > netdev = adapter - > netdev ;
tx_ring - > dev = & adapter - > pdev - > dev ;
2014-04-24 06:41:37 +00:00
tx_ring - > count = adapter - > tx_desc_count ;
2018-09-14 17:37:55 -07:00
tx_ring - > itr_setting = IAVF_ITR_TX_DEF ;
2018-09-14 17:37:46 -07:00
if ( adapter - > flags & IAVF_FLAG_WB_ON_ITR_CAPABLE )
2018-09-14 17:37:55 -07:00
tx_ring - > flags | = IAVF_TXR_FLAGS_WB_ON_ITR ;
2013-12-21 06:12:45 +00:00
2015-10-26 19:44:40 -04:00
rx_ring = & adapter - > rx_rings [ i ] ;
2013-12-21 06:12:45 +00:00
rx_ring - > queue_index = i ;
rx_ring - > netdev = adapter - > netdev ;
2014-04-24 06:41:37 +00:00
rx_ring - > count = adapter - > rx_desc_count ;
2018-09-14 17:37:55 -07:00
rx_ring - > itr_setting = IAVF_ITR_RX_DEF ;
2013-12-21 06:12:45 +00:00
}
2017-06-07 05:43:01 -04:00
adapter - > num_active_queues = num_active_queues ;
2021-11-29 16:16:02 -08:00
iavf_set_queue_vlan_tag_loc ( adapter ) ;
2013-12-21 06:12:45 +00:00
return 0 ;
err_out :
2018-09-14 17:37:46 -07:00
iavf_free_queues ( adapter ) ;
2013-12-21 06:12:45 +00:00
return - ENOMEM ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_set_interrupt_capability - set MSI - X or FAIL if not supported
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure to initialize
*
* Attempt to configure the interrupts using the best available
* capabilities of the hardware and the kernel .
* */
2018-09-14 17:37:46 -07:00
static int iavf_set_interrupt_capability ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
int vector , v_budget ;
int pairs = 0 ;
int err = 0 ;
if ( ! adapter - > vsi_res ) {
err = - EIO ;
goto out ;
}
2014-10-25 03:24:34 +00:00
pairs = adapter - > num_active_queues ;
2013-12-21 06:12:45 +00:00
2017-04-19 09:25:56 -04:00
/* It's easy to be greedy for MSI-X vectors, but it really doesn't do
* us much good if we have more vectors than CPUs . However , we already
* limit the total number of queues by the number of CPUs so we do not
* need any further limiting here .
2013-12-21 06:12:45 +00:00
*/
2017-04-19 09:25:56 -04:00
v_budget = min_t ( int , pairs + NONQ_VECS ,
( int ) adapter - > vf_res - > max_vectors ) ;
2013-12-21 06:12:45 +00:00
adapter - > msix_entries = kcalloc ( v_budget ,
sizeof ( struct msix_entry ) , GFP_KERNEL ) ;
if ( ! adapter - > msix_entries ) {
err = - ENOMEM ;
goto out ;
}
for ( vector = 0 ; vector < v_budget ; vector + + )
adapter - > msix_entries [ vector ] . entry = vector ;
2018-09-14 17:37:46 -07:00
err = iavf_acquire_msix_vectors ( adapter , v_budget ) ;
iavf: fix a deadlock caused by rtnl and driver's lock circular dependencies
A driver's lock (crit_lock) is used to serialize all the driver's tasks.
Lockdep, however, shows a circular dependency between rtnl and
crit_lock. This happens when an ndo that already holds the rtnl requests
the driver to reset, since the reset task (in some paths) tries to grab
rtnl to either change real number of queues of update netdev features.
[566.241851] ======================================================
[566.241893] WARNING: possible circular locking dependency detected
[566.241936] 6.2.14-100.fc36.x86_64+debug #1 Tainted: G OE
[566.241984] ------------------------------------------------------
[566.242025] repro.sh/2604 is trying to acquire lock:
[566.242061] ffff9280fc5ceee8 (&adapter->crit_lock){+.+.}-{3:3}, at: iavf_close+0x3c/0x240 [iavf]
[566.242167]
but task is already holding lock:
[566.242209] ffffffff9976d350 (rtnl_mutex){+.+.}-{3:3}, at: iavf_remove+0x6b5/0x730 [iavf]
[566.242300]
which lock already depends on the new lock.
[566.242353]
the existing dependency chain (in reverse order) is:
[566.242401]
-> #1 (rtnl_mutex){+.+.}-{3:3}:
[566.242451] __mutex_lock+0xc1/0xbb0
[566.242489] iavf_init_interrupt_scheme+0x179/0x440 [iavf]
[566.242560] iavf_watchdog_task+0x80b/0x1400 [iavf]
[566.242627] process_one_work+0x2b3/0x560
[566.242663] worker_thread+0x4f/0x3a0
[566.242696] kthread+0xf2/0x120
[566.242730] ret_from_fork+0x29/0x50
[566.242763]
-> #0 (&adapter->crit_lock){+.+.}-{3:3}:
[566.242815] __lock_acquire+0x15ff/0x22b0
[566.242869] lock_acquire+0xd2/0x2c0
[566.242901] __mutex_lock+0xc1/0xbb0
[566.242934] iavf_close+0x3c/0x240 [iavf]
[566.242997] __dev_close_many+0xac/0x120
[566.243036] dev_close_many+0x8b/0x140
[566.243071] unregister_netdevice_many_notify+0x165/0x7c0
[566.243116] unregister_netdevice_queue+0xd3/0x110
[566.243157] iavf_remove+0x6c1/0x730 [iavf]
[566.243217] pci_device_remove+0x33/0xa0
[566.243257] device_release_driver_internal+0x1bc/0x240
[566.243299] pci_stop_bus_device+0x6c/0x90
[566.243338] pci_stop_and_remove_bus_device+0xe/0x20
[566.243380] pci_iov_remove_virtfn+0xd1/0x130
[566.243417] sriov_disable+0x34/0xe0
[566.243448] ice_free_vfs+0x2da/0x330 [ice]
[566.244383] ice_sriov_configure+0x88/0xad0 [ice]
[566.245353] sriov_numvfs_store+0xde/0x1d0
[566.246156] kernfs_fop_write_iter+0x15e/0x210
[566.246921] vfs_write+0x288/0x530
[566.247671] ksys_write+0x74/0xf0
[566.248408] do_syscall_64+0x58/0x80
[566.249145] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[566.249886]
other info that might help us debug this:
[566.252014] Possible unsafe locking scenario:
[566.253432] CPU0 CPU1
[566.254118] ---- ----
[566.254800] lock(rtnl_mutex);
[566.255514] lock(&adapter->crit_lock);
[566.256233] lock(rtnl_mutex);
[566.256897] lock(&adapter->crit_lock);
[566.257388]
*** DEADLOCK ***
The deadlock can be triggered by a script that is continuously resetting
the VF adapter while doing other operations requiring RTNL, e.g:
while :; do
ip link set $VF up
ethtool --set-channels $VF combined 2
ip link set $VF down
ip link set $VF up
ethtool --set-channels $VF combined 4
ip link set $VF down
done
Any operation that triggers a reset can substitute "ethtool --set-channles"
As a fix, add a new task "finish_config" that do all the work which
needs rtnl lock. With the exception of iavf_remove(), all work that
require rtnl should be called from this task.
As for iavf_remove(), at the point where we need to call
unregister_netdevice() (and grab rtnl_lock), we make sure the finish_config
task is not running (cancel_work_sync()) to safely grab rtnl. Subsequent
finish_config work cannot restart after that since the task is guarded
by the __IAVF_IN_REMOVE_TASK bit in iavf_schedule_finish_config().
Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-06-05 10:52:25 -04:00
if ( ! err )
iavf_schedule_finish_config ( adapter ) ;
2013-12-21 06:12:45 +00:00
out :
return err ;
}
2015-06-23 19:00:04 -04:00
/**
2018-09-14 17:37:55 -07:00
* iavf_config_rss_aq - Configure RSS keys and lut by using AQ commands
2016-04-12 08:30:44 -07:00
* @ adapter : board private structure
2015-10-27 16:15:06 -04:00
*
* Return 0 on success , negative on failure
2015-06-23 19:00:04 -04:00
* */
2018-09-14 17:37:46 -07:00
static int iavf_config_rss_aq ( struct iavf_adapter * adapter )
2015-06-23 19:00:04 -04:00
{
2019-04-17 15:17:32 -07:00
struct iavf_aqc_get_set_rss_key_data * rss_key =
( struct iavf_aqc_get_set_rss_key_data * ) adapter - > rss_key ;
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2022-01-27 15:16:29 +01:00
enum iavf_status status ;
2015-06-23 19:00:04 -04:00
2017-05-11 11:23:11 -07:00
if ( adapter - > current_op ! = VIRTCHNL_OP_UNKNOWN ) {
2015-06-23 19:00:04 -04:00
/* bail because we already have a command pending */
2015-10-16 21:14:29 +09:00
dev_err ( & adapter - > pdev - > dev , " Cannot configure RSS, command %d pending \n " ,
2015-06-23 19:00:04 -04:00
adapter - > current_op ) ;
2015-10-27 16:15:06 -04:00
return - EBUSY ;
2015-06-23 19:00:04 -04:00
}
2022-01-27 15:16:29 +01:00
status = iavf_aq_set_rss_key ( hw , adapter - > vsi . id , rss_key ) ;
if ( status ) {
2016-04-12 08:30:44 -07:00
dev_err ( & adapter - > pdev - > dev , " Cannot set RSS key, err %s aq_err %s \n " ,
2022-01-27 15:16:29 +01:00
iavf_stat_str ( hw , status ) ,
2018-09-14 17:37:46 -07:00
iavf_aq_str ( hw , hw - > aq . asq_last_status ) ) ;
2022-01-27 15:16:29 +01:00
return iavf_status_to_errno ( status ) ;
2016-04-12 08:30:44 -07:00
2015-10-27 16:15:06 -04:00
}
2015-06-23 19:00:04 -04:00
2022-01-27 15:16:29 +01:00
status = iavf_aq_set_rss_lut ( hw , adapter - > vsi . id , false ,
adapter - > rss_lut , adapter - > rss_lut_size ) ;
if ( status ) {
2016-04-12 08:30:44 -07:00
dev_err ( & adapter - > pdev - > dev , " Cannot set RSS lut, err %s aq_err %s \n " ,
2022-01-27 15:16:29 +01:00
iavf_stat_str ( hw , status ) ,
2018-09-14 17:37:46 -07:00
iavf_aq_str ( hw , hw - > aq . asq_last_status ) ) ;
2022-01-27 15:16:29 +01:00
return iavf_status_to_errno ( status ) ;
2015-06-23 19:00:04 -04:00
}
2022-01-27 15:16:29 +01:00
return 0 ;
2016-04-12 08:30:44 -07:00
2015-06-23 19:00:04 -04:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_config_rss_reg - Configure RSS keys and lut by writing registers
2016-04-12 08:30:44 -07:00
* @ adapter : board private structure
2015-10-27 16:15:06 -04:00
*
* Returns 0 on success , negative on failure
2015-06-23 19:00:04 -04:00
* */
2018-09-14 17:37:46 -07:00
static int iavf_config_rss_reg ( struct iavf_adapter * adapter )
2015-06-23 19:00:04 -04:00
{
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2016-04-12 08:30:44 -07:00
u32 * dw ;
2015-10-27 16:15:06 -04:00
u16 i ;
2015-06-23 19:00:04 -04:00
2016-04-12 08:30:44 -07:00
dw = ( u32 * ) adapter - > rss_key ;
for ( i = 0 ; i < = adapter - > rss_key_size / 4 ; i + + )
2018-09-14 17:37:49 -07:00
wr32 ( hw , IAVF_VFQF_HKEY ( i ) , dw [ i ] ) ;
2015-10-27 16:15:06 -04:00
2016-04-12 08:30:44 -07:00
dw = ( u32 * ) adapter - > rss_lut ;
for ( i = 0 ; i < = adapter - > rss_lut_size / 4 ; i + + )
2018-09-14 17:37:49 -07:00
wr32 ( hw , IAVF_VFQF_HLUT ( i ) , dw [ i ] ) ;
2015-10-27 16:15:06 -04:00
2018-09-14 17:37:49 -07:00
iavf_flush ( hw ) ;
2015-10-27 16:15:06 -04:00
return 0 ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_config_rss - Configure RSS keys and lut
2016-04-12 08:30:44 -07:00
* @ adapter : board private structure
2015-10-26 19:44:33 -04:00
*
* Returns 0 on success , negative on failure
* */
2018-09-14 17:37:46 -07:00
int iavf_config_rss ( struct iavf_adapter * adapter )
2015-10-26 19:44:33 -04:00
{
2016-04-12 08:30:44 -07:00
if ( RSS_PF ( adapter ) ) {
2018-09-14 17:37:46 -07:00
adapter - > aq_required | = IAVF_FLAG_AQ_SET_RSS_LUT |
IAVF_FLAG_AQ_SET_RSS_KEY ;
2016-04-12 08:30:44 -07:00
return 0 ;
} else if ( RSS_AQ ( adapter ) ) {
2018-09-14 17:37:46 -07:00
return iavf_config_rss_aq ( adapter ) ;
2016-04-12 08:30:44 -07:00
} else {
2018-09-14 17:37:46 -07:00
return iavf_config_rss_reg ( adapter ) ;
2016-04-12 08:30:44 -07:00
}
2015-10-26 19:44:33 -04:00
}
2015-10-27 16:15:06 -04:00
/**
2018-09-14 17:37:46 -07:00
* iavf_fill_rss_lut - Fill the lut with default values
2016-04-12 08:30:44 -07:00
* @ adapter : board private structure
2015-10-27 16:15:06 -04:00
* */
2018-09-14 17:37:46 -07:00
static void iavf_fill_rss_lut ( struct iavf_adapter * adapter )
2015-10-27 16:15:06 -04:00
{
u16 i ;
2016-04-12 08:30:44 -07:00
for ( i = 0 ; i < adapter - > rss_lut_size ; i + + )
adapter - > rss_lut [ i ] = i % adapter - > num_active_queues ;
2015-06-23 19:00:04 -04:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_init_rss - Prepare for RSS
2015-06-23 19:00:04 -04:00
* @ adapter : board private structure
2015-10-27 16:15:06 -04:00
*
* Return 0 on success , negative on failure
2015-06-23 19:00:04 -04:00
* */
2018-09-14 17:37:46 -07:00
static int iavf_init_rss ( struct iavf_adapter * adapter )
2015-06-23 19:00:04 -04:00
{
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2015-06-23 19:00:04 -04:00
2016-04-12 08:30:44 -07:00
if ( ! RSS_PF ( adapter ) ) {
/* Enable PCTYPES for RSS, TCP/UDP with IPv4/IPv6 */
2017-06-29 15:12:24 +02:00
if ( adapter - > vf_res - > vf_cap_flags &
2017-05-11 11:23:11 -07:00
VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 )
2018-09-14 17:37:55 -07:00
adapter - > hena = IAVF_DEFAULT_RSS_HENA_EXPANDED ;
2016-04-12 08:30:44 -07:00
else
2018-09-14 17:37:55 -07:00
adapter - > hena = IAVF_DEFAULT_RSS_HENA ;
2015-06-23 19:00:04 -04:00
2018-09-14 17:37:49 -07:00
wr32 ( hw , IAVF_VFQF_HENA ( 0 ) , ( u32 ) adapter - > hena ) ;
wr32 ( hw , IAVF_VFQF_HENA ( 1 ) , ( u32 ) ( adapter - > hena > > 32 ) ) ;
2016-04-12 08:30:44 -07:00
}
2015-10-26 19:44:34 -04:00
2018-09-14 17:37:46 -07:00
iavf_fill_rss_lut ( adapter ) ;
2016-04-12 08:30:44 -07:00
netdev_rss_key_fill ( ( void * ) adapter - > rss_key , adapter - > rss_key_size ) ;
2015-10-27 16:15:06 -04:00
2022-01-10 10:46:56 +00:00
return iavf_config_rss ( adapter ) ;
2015-06-23 19:00:04 -04:00
}
2013-12-21 06:12:45 +00:00
/**
2018-09-14 17:37:46 -07:00
* iavf_alloc_q_vectors - Allocate memory for interrupt vectors
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure to initialize
*
* We allocate one q_vector per queue interrupt . If allocation fails we
* return - ENOMEM .
* */
2018-09-14 17:37:46 -07:00
static int iavf_alloc_q_vectors ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
2015-10-26 19:44:39 -04:00
int q_idx = 0 , num_q_vectors ;
2018-09-14 17:37:55 -07:00
struct iavf_q_vector * q_vector ;
2013-12-21 06:12:45 +00:00
num_q_vectors = adapter - > num_msix_vectors - NONQ_VECS ;
2015-10-26 19:44:40 -04:00
adapter - > q_vectors = kcalloc ( num_q_vectors , sizeof ( * q_vector ) ,
2015-10-26 19:44:39 -04:00
GFP_KERNEL ) ;
if ( ! adapter - > q_vectors )
2016-03-01 16:02:15 -08:00
return - ENOMEM ;
2013-12-21 06:12:45 +00:00
for ( q_idx = 0 ; q_idx < num_q_vectors ; q_idx + + ) {
2015-10-26 19:44:39 -04:00
q_vector = & adapter - > q_vectors [ q_idx ] ;
2013-12-21 06:12:45 +00:00
q_vector - > adapter = adapter ;
q_vector - > vsi = & adapter - > vsi ;
q_vector - > v_idx = q_idx ;
2017-12-29 08:48:53 -05:00
q_vector - > reg_idx = q_idx ;
2017-07-14 09:10:10 -04:00
cpumask_copy ( & q_vector - > affinity_mask , cpu_possible_mask ) ;
2013-12-21 06:12:45 +00:00
netif_napi_add ( adapter - > netdev , & q_vector - > napi ,
2022-09-27 06:27:53 -07:00
iavf_napi_poll ) ;
2013-12-21 06:12:45 +00:00
}
return 0 ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_free_q_vectors - Free memory allocated for interrupt vectors
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure to initialize
*
* This function frees the memory allocated to the q_vectors . In addition if
* NAPI is enabled it will delete any references to the NAPI struct prior
* to freeing the q_vector .
* */
2018-09-14 17:37:46 -07:00
static void iavf_free_q_vectors ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
int q_idx , num_q_vectors ;
2016-11-08 13:05:08 -08:00
if ( ! adapter - > q_vectors )
return ;
2013-12-21 06:12:45 +00:00
num_q_vectors = adapter - > num_msix_vectors - NONQ_VECS ;
for ( q_idx = 0 ; q_idx < num_q_vectors ; q_idx + + ) {
2018-09-14 17:37:55 -07:00
struct iavf_q_vector * q_vector = & adapter - > q_vectors [ q_idx ] ;
2018-09-14 17:37:47 -07:00
2023-05-09 19:11:47 +08:00
netif_napi_del ( & q_vector - > napi ) ;
2013-12-21 06:12:45 +00:00
}
2015-10-26 19:44:39 -04:00
kfree ( adapter - > q_vectors ) ;
2016-11-08 13:05:08 -08:00
adapter - > q_vectors = NULL ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_reset_interrupt_capability - Reset MSIX setup
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
*
* */
2023-06-21 08:54:05 -07:00
static void iavf_reset_interrupt_capability ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
2016-11-08 13:05:05 -08:00
if ( ! adapter - > msix_entries )
return ;
2013-12-21 06:12:45 +00:00
pci_disable_msix ( adapter - > pdev ) ;
kfree ( adapter - > msix_entries ) ;
adapter - > msix_entries = NULL ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_init_interrupt_scheme - Determine if MSIX is supported and init
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure to initialize
*
* */
2023-06-21 08:54:05 -07:00
static int iavf_init_interrupt_scheme ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
int err ;
2018-09-14 17:37:46 -07:00
err = iavf_alloc_queues ( adapter ) ;
2017-04-19 09:25:59 -04:00
if ( err ) {
dev_err ( & adapter - > pdev - > dev ,
" Unable to allocate memory for queues \n " ) ;
goto err_alloc_queues ;
}
2018-09-14 17:37:46 -07:00
err = iavf_set_interrupt_capability ( adapter ) ;
2013-12-21 06:12:45 +00:00
if ( err ) {
dev_err ( & adapter - > pdev - > dev ,
" Unable to setup interrupt capabilities \n " ) ;
goto err_set_interrupt ;
}
2018-09-14 17:37:46 -07:00
err = iavf_alloc_q_vectors ( adapter ) ;
2013-12-21 06:12:45 +00:00
if ( err ) {
dev_err ( & adapter - > pdev - > dev ,
" Unable to allocate memory for queue vectors \n " ) ;
goto err_alloc_q_vectors ;
}
2018-01-23 08:50:59 -08:00
/* If we've made it so far while ADq flag being ON, then we haven't
* bailed out anywhere in middle . And ADq isn ' t just enabled but actual
* resources have been allocated in the reset path .
* Now we can truly claim that ADq is enabled .
*/
if ( ( adapter - > vf_res - > vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ ) & &
adapter - > num_tc )
dev_info ( & adapter - > pdev - > dev , " ADq Enabled, %u TCs created " ,
adapter - > num_tc ) ;
2013-12-21 06:12:45 +00:00
dev_info ( & adapter - > pdev - > dev , " Multiqueue %s: Queue pair count = %u " ,
2014-11-11 20:02:42 +00:00
( adapter - > num_active_queues > 1 ) ? " Enabled " : " Disabled " ,
adapter - > num_active_queues ) ;
2013-12-21 06:12:45 +00:00
return 0 ;
err_alloc_q_vectors :
2018-09-14 17:37:46 -07:00
iavf_reset_interrupt_capability ( adapter ) ;
2013-12-21 06:12:45 +00:00
err_set_interrupt :
2018-09-14 17:37:46 -07:00
iavf_free_queues ( adapter ) ;
2017-04-19 09:25:59 -04:00
err_alloc_queues :
2013-12-21 06:12:45 +00:00
return err ;
}
2023-10-27 10:59:40 -07:00
/**
* iavf_free_interrupt_scheme - Undo what iavf_init_interrupt_scheme does
* @ adapter : board private structure
* */
static void iavf_free_interrupt_scheme ( struct iavf_adapter * adapter )
{
iavf_free_q_vectors ( adapter ) ;
iavf_reset_interrupt_capability ( adapter ) ;
iavf_free_queues ( adapter ) ;
}
2015-10-26 19:44:34 -04:00
/**
2018-09-14 17:37:46 -07:00
* iavf_free_rss - Free memory used by RSS structs
2016-04-12 08:30:44 -07:00
* @ adapter : board private structure
2015-10-26 19:44:34 -04:00
* */
2018-09-14 17:37:46 -07:00
static void iavf_free_rss ( struct iavf_adapter * adapter )
2015-10-26 19:44:34 -04:00
{
2016-04-12 08:30:44 -07:00
kfree ( adapter - > rss_key ) ;
adapter - > rss_key = NULL ;
2015-10-26 19:44:34 -04:00
2016-04-12 08:30:44 -07:00
kfree ( adapter - > rss_lut ) ;
adapter - > rss_lut = NULL ;
2015-10-26 19:44:34 -04:00
}
2017-08-22 06:57:50 -04:00
/**
2018-09-14 17:37:46 -07:00
* iavf_reinit_interrupt_scheme - Reallocate queues and vectors
2017-08-22 06:57:50 -04:00
* @ adapter : board private structure
2023-05-19 15:46:02 -06:00
* @ running : true if adapter - > state = = __IAVF_RUNNING
2017-08-22 06:57:50 -04:00
*
* Returns 0 on success , negative on failure
* */
2023-05-19 15:46:02 -06:00
static int iavf_reinit_interrupt_scheme ( struct iavf_adapter * adapter , bool running )
2017-08-22 06:57:50 -04:00
{
struct net_device * netdev = adapter - > netdev ;
int err ;
2023-05-19 15:46:02 -06:00
if ( running )
2018-09-14 17:37:46 -07:00
iavf_free_traffic_irqs ( adapter ) ;
iavf_free_misc_irq ( adapter ) ;
2023-10-27 10:59:40 -07:00
iavf_free_interrupt_scheme ( adapter ) ;
2017-08-22 06:57:50 -04:00
2023-10-27 10:59:40 -07:00
err = iavf_init_interrupt_scheme ( adapter ) ;
2017-08-22 06:57:50 -04:00
if ( err )
goto err ;
netif_tx_stop_all_queues ( netdev ) ;
2018-09-14 17:37:46 -07:00
err = iavf_request_misc_irq ( adapter ) ;
2017-08-22 06:57:50 -04:00
if ( err )
goto err ;
2018-09-14 17:37:55 -07:00
set_bit ( __IAVF_VSI_DOWN , adapter - > vsi . state ) ;
2017-08-22 06:57:50 -04:00
2018-09-14 17:37:46 -07:00
iavf_map_rings_to_vectors ( adapter ) ;
2017-08-22 06:57:50 -04:00
err :
return err ;
}
iavf: fix a deadlock caused by rtnl and driver's lock circular dependencies
A driver's lock (crit_lock) is used to serialize all the driver's tasks.
Lockdep, however, shows a circular dependency between rtnl and
crit_lock. This happens when an ndo that already holds the rtnl requests
the driver to reset, since the reset task (in some paths) tries to grab
rtnl to either change real number of queues of update netdev features.
[566.241851] ======================================================
[566.241893] WARNING: possible circular locking dependency detected
[566.241936] 6.2.14-100.fc36.x86_64+debug #1 Tainted: G OE
[566.241984] ------------------------------------------------------
[566.242025] repro.sh/2604 is trying to acquire lock:
[566.242061] ffff9280fc5ceee8 (&adapter->crit_lock){+.+.}-{3:3}, at: iavf_close+0x3c/0x240 [iavf]
[566.242167]
but task is already holding lock:
[566.242209] ffffffff9976d350 (rtnl_mutex){+.+.}-{3:3}, at: iavf_remove+0x6b5/0x730 [iavf]
[566.242300]
which lock already depends on the new lock.
[566.242353]
the existing dependency chain (in reverse order) is:
[566.242401]
-> #1 (rtnl_mutex){+.+.}-{3:3}:
[566.242451] __mutex_lock+0xc1/0xbb0
[566.242489] iavf_init_interrupt_scheme+0x179/0x440 [iavf]
[566.242560] iavf_watchdog_task+0x80b/0x1400 [iavf]
[566.242627] process_one_work+0x2b3/0x560
[566.242663] worker_thread+0x4f/0x3a0
[566.242696] kthread+0xf2/0x120
[566.242730] ret_from_fork+0x29/0x50
[566.242763]
-> #0 (&adapter->crit_lock){+.+.}-{3:3}:
[566.242815] __lock_acquire+0x15ff/0x22b0
[566.242869] lock_acquire+0xd2/0x2c0
[566.242901] __mutex_lock+0xc1/0xbb0
[566.242934] iavf_close+0x3c/0x240 [iavf]
[566.242997] __dev_close_many+0xac/0x120
[566.243036] dev_close_many+0x8b/0x140
[566.243071] unregister_netdevice_many_notify+0x165/0x7c0
[566.243116] unregister_netdevice_queue+0xd3/0x110
[566.243157] iavf_remove+0x6c1/0x730 [iavf]
[566.243217] pci_device_remove+0x33/0xa0
[566.243257] device_release_driver_internal+0x1bc/0x240
[566.243299] pci_stop_bus_device+0x6c/0x90
[566.243338] pci_stop_and_remove_bus_device+0xe/0x20
[566.243380] pci_iov_remove_virtfn+0xd1/0x130
[566.243417] sriov_disable+0x34/0xe0
[566.243448] ice_free_vfs+0x2da/0x330 [ice]
[566.244383] ice_sriov_configure+0x88/0xad0 [ice]
[566.245353] sriov_numvfs_store+0xde/0x1d0
[566.246156] kernfs_fop_write_iter+0x15e/0x210
[566.246921] vfs_write+0x288/0x530
[566.247671] ksys_write+0x74/0xf0
[566.248408] do_syscall_64+0x58/0x80
[566.249145] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[566.249886]
other info that might help us debug this:
[566.252014] Possible unsafe locking scenario:
[566.253432] CPU0 CPU1
[566.254118] ---- ----
[566.254800] lock(rtnl_mutex);
[566.255514] lock(&adapter->crit_lock);
[566.256233] lock(rtnl_mutex);
[566.256897] lock(&adapter->crit_lock);
[566.257388]
*** DEADLOCK ***
The deadlock can be triggered by a script that is continuously resetting
the VF adapter while doing other operations requiring RTNL, e.g:
while :; do
ip link set $VF up
ethtool --set-channels $VF combined 2
ip link set $VF down
ip link set $VF up
ethtool --set-channels $VF combined 4
ip link set $VF down
done
Any operation that triggers a reset can substitute "ethtool --set-channles"
As a fix, add a new task "finish_config" that do all the work which
needs rtnl lock. With the exception of iavf_remove(), all work that
require rtnl should be called from this task.
As for iavf_remove(), at the point where we need to call
unregister_netdevice() (and grab rtnl_lock), we make sure the finish_config
task is not running (cancel_work_sync()) to safely grab rtnl. Subsequent
finish_config work cannot restart after that since the task is guarded
by the __IAVF_IN_REMOVE_TASK bit in iavf_schedule_finish_config().
Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-06-05 10:52:25 -04:00
/**
* iavf_finish_config - do all netdev work that needs RTNL
* @ work : our work_struct
*
* Do work that needs both RTNL and crit_lock .
* */
static void iavf_finish_config ( struct work_struct * work )
{
struct iavf_adapter * adapter ;
int pairs , err ;
adapter = container_of ( work , struct iavf_adapter , finish_config ) ;
/* Always take RTNL first to prevent circular lock dependency */
rtnl_lock ( ) ;
mutex_lock ( & adapter - > crit_lock ) ;
if ( ( adapter - > flags & IAVF_FLAG_SETUP_NETDEV_FEATURES ) & &
2023-10-27 10:59:38 -07:00
adapter - > netdev - > reg_state = = NETREG_REGISTERED & &
iavf: fix a deadlock caused by rtnl and driver's lock circular dependencies
A driver's lock (crit_lock) is used to serialize all the driver's tasks.
Lockdep, however, shows a circular dependency between rtnl and
crit_lock. This happens when an ndo that already holds the rtnl requests
the driver to reset, since the reset task (in some paths) tries to grab
rtnl to either change real number of queues of update netdev features.
[566.241851] ======================================================
[566.241893] WARNING: possible circular locking dependency detected
[566.241936] 6.2.14-100.fc36.x86_64+debug #1 Tainted: G OE
[566.241984] ------------------------------------------------------
[566.242025] repro.sh/2604 is trying to acquire lock:
[566.242061] ffff9280fc5ceee8 (&adapter->crit_lock){+.+.}-{3:3}, at: iavf_close+0x3c/0x240 [iavf]
[566.242167]
but task is already holding lock:
[566.242209] ffffffff9976d350 (rtnl_mutex){+.+.}-{3:3}, at: iavf_remove+0x6b5/0x730 [iavf]
[566.242300]
which lock already depends on the new lock.
[566.242353]
the existing dependency chain (in reverse order) is:
[566.242401]
-> #1 (rtnl_mutex){+.+.}-{3:3}:
[566.242451] __mutex_lock+0xc1/0xbb0
[566.242489] iavf_init_interrupt_scheme+0x179/0x440 [iavf]
[566.242560] iavf_watchdog_task+0x80b/0x1400 [iavf]
[566.242627] process_one_work+0x2b3/0x560
[566.242663] worker_thread+0x4f/0x3a0
[566.242696] kthread+0xf2/0x120
[566.242730] ret_from_fork+0x29/0x50
[566.242763]
-> #0 (&adapter->crit_lock){+.+.}-{3:3}:
[566.242815] __lock_acquire+0x15ff/0x22b0
[566.242869] lock_acquire+0xd2/0x2c0
[566.242901] __mutex_lock+0xc1/0xbb0
[566.242934] iavf_close+0x3c/0x240 [iavf]
[566.242997] __dev_close_many+0xac/0x120
[566.243036] dev_close_many+0x8b/0x140
[566.243071] unregister_netdevice_many_notify+0x165/0x7c0
[566.243116] unregister_netdevice_queue+0xd3/0x110
[566.243157] iavf_remove+0x6c1/0x730 [iavf]
[566.243217] pci_device_remove+0x33/0xa0
[566.243257] device_release_driver_internal+0x1bc/0x240
[566.243299] pci_stop_bus_device+0x6c/0x90
[566.243338] pci_stop_and_remove_bus_device+0xe/0x20
[566.243380] pci_iov_remove_virtfn+0xd1/0x130
[566.243417] sriov_disable+0x34/0xe0
[566.243448] ice_free_vfs+0x2da/0x330 [ice]
[566.244383] ice_sriov_configure+0x88/0xad0 [ice]
[566.245353] sriov_numvfs_store+0xde/0x1d0
[566.246156] kernfs_fop_write_iter+0x15e/0x210
[566.246921] vfs_write+0x288/0x530
[566.247671] ksys_write+0x74/0xf0
[566.248408] do_syscall_64+0x58/0x80
[566.249145] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[566.249886]
other info that might help us debug this:
[566.252014] Possible unsafe locking scenario:
[566.253432] CPU0 CPU1
[566.254118] ---- ----
[566.254800] lock(rtnl_mutex);
[566.255514] lock(&adapter->crit_lock);
[566.256233] lock(rtnl_mutex);
[566.256897] lock(&adapter->crit_lock);
[566.257388]
*** DEADLOCK ***
The deadlock can be triggered by a script that is continuously resetting
the VF adapter while doing other operations requiring RTNL, e.g:
while :; do
ip link set $VF up
ethtool --set-channels $VF combined 2
ip link set $VF down
ip link set $VF up
ethtool --set-channels $VF combined 4
ip link set $VF down
done
Any operation that triggers a reset can substitute "ethtool --set-channles"
As a fix, add a new task "finish_config" that do all the work which
needs rtnl lock. With the exception of iavf_remove(), all work that
require rtnl should be called from this task.
As for iavf_remove(), at the point where we need to call
unregister_netdevice() (and grab rtnl_lock), we make sure the finish_config
task is not running (cancel_work_sync()) to safely grab rtnl. Subsequent
finish_config work cannot restart after that since the task is guarded
by the __IAVF_IN_REMOVE_TASK bit in iavf_schedule_finish_config().
Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-06-05 10:52:25 -04:00
! test_bit ( __IAVF_IN_REMOVE_TASK , & adapter - > crit_section ) ) {
netdev_update_features ( adapter - > netdev ) ;
adapter - > flags & = ~ IAVF_FLAG_SETUP_NETDEV_FEATURES ;
}
switch ( adapter - > state ) {
case __IAVF_DOWN :
2023-10-27 10:59:38 -07:00
if ( adapter - > netdev - > reg_state ! = NETREG_REGISTERED ) {
iavf: fix a deadlock caused by rtnl and driver's lock circular dependencies
A driver's lock (crit_lock) is used to serialize all the driver's tasks.
Lockdep, however, shows a circular dependency between rtnl and
crit_lock. This happens when an ndo that already holds the rtnl requests
the driver to reset, since the reset task (in some paths) tries to grab
rtnl to either change real number of queues of update netdev features.
[566.241851] ======================================================
[566.241893] WARNING: possible circular locking dependency detected
[566.241936] 6.2.14-100.fc36.x86_64+debug #1 Tainted: G OE
[566.241984] ------------------------------------------------------
[566.242025] repro.sh/2604 is trying to acquire lock:
[566.242061] ffff9280fc5ceee8 (&adapter->crit_lock){+.+.}-{3:3}, at: iavf_close+0x3c/0x240 [iavf]
[566.242167]
but task is already holding lock:
[566.242209] ffffffff9976d350 (rtnl_mutex){+.+.}-{3:3}, at: iavf_remove+0x6b5/0x730 [iavf]
[566.242300]
which lock already depends on the new lock.
[566.242353]
the existing dependency chain (in reverse order) is:
[566.242401]
-> #1 (rtnl_mutex){+.+.}-{3:3}:
[566.242451] __mutex_lock+0xc1/0xbb0
[566.242489] iavf_init_interrupt_scheme+0x179/0x440 [iavf]
[566.242560] iavf_watchdog_task+0x80b/0x1400 [iavf]
[566.242627] process_one_work+0x2b3/0x560
[566.242663] worker_thread+0x4f/0x3a0
[566.242696] kthread+0xf2/0x120
[566.242730] ret_from_fork+0x29/0x50
[566.242763]
-> #0 (&adapter->crit_lock){+.+.}-{3:3}:
[566.242815] __lock_acquire+0x15ff/0x22b0
[566.242869] lock_acquire+0xd2/0x2c0
[566.242901] __mutex_lock+0xc1/0xbb0
[566.242934] iavf_close+0x3c/0x240 [iavf]
[566.242997] __dev_close_many+0xac/0x120
[566.243036] dev_close_many+0x8b/0x140
[566.243071] unregister_netdevice_many_notify+0x165/0x7c0
[566.243116] unregister_netdevice_queue+0xd3/0x110
[566.243157] iavf_remove+0x6c1/0x730 [iavf]
[566.243217] pci_device_remove+0x33/0xa0
[566.243257] device_release_driver_internal+0x1bc/0x240
[566.243299] pci_stop_bus_device+0x6c/0x90
[566.243338] pci_stop_and_remove_bus_device+0xe/0x20
[566.243380] pci_iov_remove_virtfn+0xd1/0x130
[566.243417] sriov_disable+0x34/0xe0
[566.243448] ice_free_vfs+0x2da/0x330 [ice]
[566.244383] ice_sriov_configure+0x88/0xad0 [ice]
[566.245353] sriov_numvfs_store+0xde/0x1d0
[566.246156] kernfs_fop_write_iter+0x15e/0x210
[566.246921] vfs_write+0x288/0x530
[566.247671] ksys_write+0x74/0xf0
[566.248408] do_syscall_64+0x58/0x80
[566.249145] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[566.249886]
other info that might help us debug this:
[566.252014] Possible unsafe locking scenario:
[566.253432] CPU0 CPU1
[566.254118] ---- ----
[566.254800] lock(rtnl_mutex);
[566.255514] lock(&adapter->crit_lock);
[566.256233] lock(rtnl_mutex);
[566.256897] lock(&adapter->crit_lock);
[566.257388]
*** DEADLOCK ***
The deadlock can be triggered by a script that is continuously resetting
the VF adapter while doing other operations requiring RTNL, e.g:
while :; do
ip link set $VF up
ethtool --set-channels $VF combined 2
ip link set $VF down
ip link set $VF up
ethtool --set-channels $VF combined 4
ip link set $VF down
done
Any operation that triggers a reset can substitute "ethtool --set-channles"
As a fix, add a new task "finish_config" that do all the work which
needs rtnl lock. With the exception of iavf_remove(), all work that
require rtnl should be called from this task.
As for iavf_remove(), at the point where we need to call
unregister_netdevice() (and grab rtnl_lock), we make sure the finish_config
task is not running (cancel_work_sync()) to safely grab rtnl. Subsequent
finish_config work cannot restart after that since the task is guarded
by the __IAVF_IN_REMOVE_TASK bit in iavf_schedule_finish_config().
Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-06-05 10:52:25 -04:00
err = register_netdevice ( adapter - > netdev ) ;
if ( err ) {
dev_err ( & adapter - > pdev - > dev , " Unable to register netdev (%d) \n " ,
err ) ;
/* go back and try again.*/
iavf_free_rss ( adapter ) ;
iavf_free_misc_irq ( adapter ) ;
iavf_reset_interrupt_capability ( adapter ) ;
iavf_change_state ( adapter ,
__IAVF_INIT_CONFIG_ADAPTER ) ;
goto out ;
}
}
/* Set the real number of queues when reset occurs while
* state = = __IAVF_DOWN
*/
fallthrough ;
case __IAVF_RUNNING :
pairs = adapter - > num_active_queues ;
netif_set_real_num_rx_queues ( adapter - > netdev , pairs ) ;
netif_set_real_num_tx_queues ( adapter - > netdev , pairs ) ;
break ;
default :
break ;
}
out :
mutex_unlock ( & adapter - > crit_lock ) ;
rtnl_unlock ( ) ;
}
/**
* iavf_schedule_finish_config - Set the flags and schedule a reset event
* @ adapter : board private structure
* */
void iavf_schedule_finish_config ( struct iavf_adapter * adapter )
{
if ( ! test_bit ( __IAVF_IN_REMOVE_TASK , & adapter - > crit_section ) )
queue_work ( adapter - > wq , & adapter - > finish_config ) ;
}
2013-12-21 06:12:45 +00:00
/**
2019-05-14 10:37:04 -07:00
* iavf_process_aq_command - process aq_required flags
* and sends aq command
* @ adapter : pointer to iavf adapter structure
*
* Returns 0 on success
* Returns error code if no command was sent
* or error code if the command failed .
2013-12-21 06:12:45 +00:00
* */
2019-05-14 10:37:04 -07:00
static int iavf_process_aq_command ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
2019-05-14 10:37:04 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_GET_CONFIG )
return iavf_send_vf_config_msg ( adapter ) ;
2021-11-29 16:16:00 -08:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS )
return iavf_send_vf_offload_vlan_v2_msg ( adapter ) ;
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_DISABLE_QUEUES ) {
iavf_disable_queues ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2015-03-27 00:12:09 -07:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_MAP_VECTORS ) {
iavf_map_queues ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2013-12-21 06:12:45 +00:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_ADD_MAC_FILTER ) {
iavf_add_ether_addrs ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2013-12-21 06:12:45 +00:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_ADD_VLAN_FILTER ) {
iavf_add_vlans ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2013-12-21 06:12:45 +00:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_DEL_MAC_FILTER ) {
iavf_del_ether_addrs ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2013-12-21 06:12:45 +00:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_DEL_VLAN_FILTER ) {
iavf_del_vlans ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2013-12-21 06:12:45 +00:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_ENABLE_VLAN_STRIPPING ) {
iavf_enable_vlan_stripping ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2017-07-17 22:09:45 -07:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_DISABLE_VLAN_STRIPPING ) {
iavf_disable_vlan_stripping ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2017-07-17 22:09:45 -07:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_CONFIGURE_QUEUES ) {
iavf_configure_queues ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2013-12-21 06:12:45 +00:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_ENABLE_QUEUES ) {
iavf_enable_queues ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2013-12-21 06:12:45 +00:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_CONFIGURE_RSS ) {
2015-06-23 19:00:04 -04:00
/* This message goes straight to the firmware, not the
* PF , so we don ' t have to set current_op as we will
* not get a response through the ARQ .
*/
2018-09-14 17:37:46 -07:00
adapter - > aq_required & = ~ IAVF_FLAG_AQ_CONFIGURE_RSS ;
2019-05-14 10:37:04 -07:00
return 0 ;
2015-06-23 19:00:04 -04:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_GET_HENA ) {
iavf_get_hena ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2016-04-12 08:30:44 -07:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_SET_HENA ) {
iavf_set_hena ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2016-04-12 08:30:44 -07:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_SET_RSS_KEY ) {
iavf_set_rss_key ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2016-04-12 08:30:44 -07:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_SET_RSS_LUT ) {
iavf_set_rss_lut ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2016-04-12 08:30:44 -07:00
}
2023-12-12 17:33:21 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_SET_RSS_HFUNC ) {
iavf_set_rss_hfunc ( adapter ) ;
return 0 ;
}
2015-06-23 19:00:04 -04:00
2023-08-21 17:01:44 -06:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_CONFIGURE_PROMISC_MODE ) {
iavf_set_promiscuous ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2016-04-12 08:30:52 -07:00
}
2018-01-23 08:50:57 -08:00
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_ENABLE_CHANNELS ) {
iavf_enable_channels ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2018-01-23 08:50:57 -08:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_DISABLE_CHANNELS ) {
iavf_disable_channels ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2018-01-23 08:50:57 -08:00
}
2018-09-14 17:37:46 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_ADD_CLOUD_FILTER ) {
iavf_add_cloud_filter ( adapter ) ;
2019-05-14 10:37:04 -07:00
return 0 ;
2018-01-23 08:51:05 -08:00
}
2019-05-14 10:37:08 -07:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_DEL_CLOUD_FILTER ) {
iavf_del_cloud_filter ( adapter ) ;
return 0 ;
}
2021-03-09 11:08:11 +08:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_ADD_FDIR_FILTER ) {
iavf_add_fdir_filter ( adapter ) ;
return IAVF_SUCCESS ;
}
if ( adapter - > aq_required & IAVF_FLAG_AQ_DEL_FDIR_FILTER ) {
iavf_del_fdir_filter ( adapter ) ;
return IAVF_SUCCESS ;
}
2021-04-13 08:48:41 +08:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_ADD_ADV_RSS_CFG ) {
iavf_add_adv_rss_cfg ( adapter ) ;
return 0 ;
}
if ( adapter - > aq_required & IAVF_FLAG_AQ_DEL_ADV_RSS_CFG ) {
iavf_del_adv_rss_cfg ( adapter ) ;
return 0 ;
}
2021-11-29 16:16:03 -08:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_STRIPPING ) {
iavf_disable_vlan_stripping_v2 ( adapter , ETH_P_8021Q ) ;
return 0 ;
}
if ( adapter - > aq_required & IAVF_FLAG_AQ_DISABLE_STAG_VLAN_STRIPPING ) {
iavf_disable_vlan_stripping_v2 ( adapter , ETH_P_8021AD ) ;
return 0 ;
}
if ( adapter - > aq_required & IAVF_FLAG_AQ_ENABLE_CTAG_VLAN_STRIPPING ) {
iavf_enable_vlan_stripping_v2 ( adapter , ETH_P_8021Q ) ;
return 0 ;
}
if ( adapter - > aq_required & IAVF_FLAG_AQ_ENABLE_STAG_VLAN_STRIPPING ) {
iavf_enable_vlan_stripping_v2 ( adapter , ETH_P_8021AD ) ;
return 0 ;
}
if ( adapter - > aq_required & IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_INSERTION ) {
iavf_disable_vlan_insertion_v2 ( adapter , ETH_P_8021Q ) ;
return 0 ;
}
if ( adapter - > aq_required & IAVF_FLAG_AQ_DISABLE_STAG_VLAN_INSERTION ) {
iavf_disable_vlan_insertion_v2 ( adapter , ETH_P_8021AD ) ;
return 0 ;
}
if ( adapter - > aq_required & IAVF_FLAG_AQ_ENABLE_CTAG_VLAN_INSERTION ) {
iavf_enable_vlan_insertion_v2 ( adapter , ETH_P_8021Q ) ;
return 0 ;
}
if ( adapter - > aq_required & IAVF_FLAG_AQ_ENABLE_STAG_VLAN_INSERTION ) {
iavf_enable_vlan_insertion_v2 ( adapter , ETH_P_8021AD ) ;
return 0 ;
}
2021-09-15 09:01:00 +00:00
if ( adapter - > aq_required & IAVF_FLAG_AQ_REQUEST_STATS ) {
iavf_request_stats ( adapter ) ;
return 0 ;
}
2019-05-14 10:37:04 -07:00
return - EAGAIN ;
}
2021-11-29 16:16:03 -08:00
/**
* iavf_set_vlan_offload_features - set VLAN offload configuration
* @ adapter : board private structure
* @ prev_features : previous features used for comparison
* @ features : updated features used for configuration
*
* Set the aq_required bit ( s ) based on the requested features passed in to
* configure VLAN stripping and / or VLAN insertion if supported . Also , schedule
* the watchdog if any changes are requested to expedite the request via
* virtchnl .
* */
2023-06-21 08:54:05 -07:00
static void
2021-11-29 16:16:03 -08:00
iavf_set_vlan_offload_features ( struct iavf_adapter * adapter ,
netdev_features_t prev_features ,
netdev_features_t features )
{
bool enable_stripping = true , enable_insertion = true ;
u16 vlan_ethertype = 0 ;
u64 aq_required = 0 ;
/* keep cases separate because one ethertype for offloads can be
* disabled at the same time as another is disabled , so check for an
* enabled ethertype first , then check for disabled . Default to
* ETH_P_8021Q so an ethertype is specified if disabling insertion and
* stripping .
*/
if ( features & ( NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX ) )
vlan_ethertype = ETH_P_8021AD ;
else if ( features & ( NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX ) )
vlan_ethertype = ETH_P_8021Q ;
else if ( prev_features & ( NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX ) )
vlan_ethertype = ETH_P_8021AD ;
else if ( prev_features & ( NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX ) )
vlan_ethertype = ETH_P_8021Q ;
else
vlan_ethertype = ETH_P_8021Q ;
if ( ! ( features & ( NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_CTAG_RX ) ) )
enable_stripping = false ;
if ( ! ( features & ( NETIF_F_HW_VLAN_STAG_TX | NETIF_F_HW_VLAN_CTAG_TX ) ) )
enable_insertion = false ;
if ( VLAN_ALLOWED ( adapter ) ) {
/* VIRTCHNL_VF_OFFLOAD_VLAN only has support for toggling VLAN
* stripping via virtchnl . VLAN insertion can be toggled on the
* netdev , but it doesn ' t require a virtchnl message
*/
if ( enable_stripping )
aq_required | = IAVF_FLAG_AQ_ENABLE_VLAN_STRIPPING ;
else
aq_required | = IAVF_FLAG_AQ_DISABLE_VLAN_STRIPPING ;
} else if ( VLAN_V2_ALLOWED ( adapter ) ) {
switch ( vlan_ethertype ) {
case ETH_P_8021Q :
if ( enable_stripping )
aq_required | = IAVF_FLAG_AQ_ENABLE_CTAG_VLAN_STRIPPING ;
else
aq_required | = IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_STRIPPING ;
if ( enable_insertion )
aq_required | = IAVF_FLAG_AQ_ENABLE_CTAG_VLAN_INSERTION ;
else
aq_required | = IAVF_FLAG_AQ_DISABLE_CTAG_VLAN_INSERTION ;
break ;
case ETH_P_8021AD :
if ( enable_stripping )
aq_required | = IAVF_FLAG_AQ_ENABLE_STAG_VLAN_STRIPPING ;
else
aq_required | = IAVF_FLAG_AQ_DISABLE_STAG_VLAN_STRIPPING ;
if ( enable_insertion )
aq_required | = IAVF_FLAG_AQ_ENABLE_STAG_VLAN_INSERTION ;
else
aq_required | = IAVF_FLAG_AQ_DISABLE_STAG_VLAN_INSERTION ;
break ;
}
}
2023-11-14 23:35:22 +01:00
if ( aq_required )
iavf_schedule_aq_request ( adapter , aq_required ) ;
2021-11-29 16:16:03 -08:00
}
2019-05-14 10:37:07 -07:00
/**
* iavf_startup - first step of driver startup
* @ adapter : board private structure
*
* Function process __IAVF_STARTUP driver state .
* When success the state is changed to __IAVF_INIT_VERSION_CHECK
2021-08-19 08:47:49 +00:00
* when fails the state is changed to __IAVF_INIT_FAILED
2019-05-14 10:37:07 -07:00
* */
2021-08-19 08:47:49 +00:00
static void iavf_startup ( struct iavf_adapter * adapter )
2019-05-14 10:37:07 -07:00
{
struct pci_dev * pdev = adapter - > pdev ;
struct iavf_hw * hw = & adapter - > hw ;
2022-01-27 15:16:29 +01:00
enum iavf_status status ;
int ret ;
2019-05-14 10:37:07 -07:00
WARN_ON ( adapter - > state ! = __IAVF_STARTUP ) ;
/* driver loaded, probe complete */
adapter - > flags & = ~ IAVF_FLAG_PF_COMMS_FAILED ;
adapter - > flags & = ~ IAVF_FLAG_RESET_PENDING ;
2022-01-27 15:16:29 +01:00
ret = iavf_check_reset_complete ( hw ) ;
if ( ret ) {
2019-05-14 10:37:07 -07:00
dev_info ( & pdev - > dev , " Device is still in reset (%d), retrying \n " ,
2022-01-27 15:16:29 +01:00
ret ) ;
2019-05-14 10:37:07 -07:00
goto err ;
}
hw - > aq . num_arq_entries = IAVF_AQ_LEN ;
hw - > aq . num_asq_entries = IAVF_AQ_LEN ;
hw - > aq . arq_buf_size = IAVF_MAX_AQ_BUF_SIZE ;
hw - > aq . asq_buf_size = IAVF_MAX_AQ_BUF_SIZE ;
2022-01-27 15:16:29 +01:00
status = iavf_init_adminq ( hw ) ;
if ( status ) {
dev_err ( & pdev - > dev , " Failed to init Admin Queue (%d) \n " ,
status ) ;
2019-05-14 10:37:07 -07:00
goto err ;
}
2022-01-27 15:16:29 +01:00
ret = iavf_send_api_ver ( adapter ) ;
if ( ret ) {
dev_err ( & pdev - > dev , " Unable to send to PF (%d) \n " , ret ) ;
2019-05-14 10:37:07 -07:00
iavf_shutdown_adminq ( hw ) ;
goto err ;
}
2021-08-19 08:47:40 +00:00
iavf_change_state ( adapter , __IAVF_INIT_VERSION_CHECK ) ;
2021-08-19 08:47:49 +00:00
return ;
2019-05-14 10:37:07 -07:00
err :
2021-08-19 08:47:49 +00:00
iavf_change_state ( adapter , __IAVF_INIT_FAILED ) ;
2019-05-14 10:37:07 -07:00
}
/**
* iavf_init_version_check - second step of driver startup
* @ adapter : board private structure
*
* Function process __IAVF_INIT_VERSION_CHECK driver state .
* When success the state is changed to __IAVF_INIT_GET_RESOURCES
2021-08-19 08:47:49 +00:00
* when fails the state is changed to __IAVF_INIT_FAILED
2019-05-14 10:37:07 -07:00
* */
2021-08-19 08:47:49 +00:00
static void iavf_init_version_check ( struct iavf_adapter * adapter )
2019-05-14 10:37:07 -07:00
{
struct pci_dev * pdev = adapter - > pdev ;
struct iavf_hw * hw = & adapter - > hw ;
int err = - EAGAIN ;
WARN_ON ( adapter - > state ! = __IAVF_INIT_VERSION_CHECK ) ;
if ( ! iavf_asq_done ( hw ) ) {
dev_err ( & pdev - > dev , " Admin queue command never completed \n " ) ;
iavf_shutdown_adminq ( hw ) ;
2021-08-19 08:47:40 +00:00
iavf_change_state ( adapter , __IAVF_STARTUP ) ;
2019-05-14 10:37:07 -07:00
goto err ;
}
/* aq msg sent, awaiting reply */
err = iavf_verify_api_ver ( adapter ) ;
if ( err ) {
2022-01-27 15:16:29 +01:00
if ( err = = - EALREADY )
2019-05-14 10:37:07 -07:00
err = iavf_send_api_ver ( adapter ) ;
else
dev_err ( & pdev - > dev , " Unsupported PF API version %d.%d, expected %d.%d \n " ,
adapter - > pf_version . major ,
adapter - > pf_version . minor ,
VIRTCHNL_VERSION_MAJOR ,
VIRTCHNL_VERSION_MINOR ) ;
goto err ;
}
err = iavf_send_vf_config_msg ( adapter ) ;
if ( err ) {
dev_err ( & pdev - > dev , " Unable to send config request (%d) \n " ,
err ) ;
goto err ;
}
2021-08-19 08:47:40 +00:00
iavf_change_state ( adapter , __IAVF_INIT_GET_RESOURCES ) ;
2021-08-19 08:47:49 +00:00
return ;
2019-05-14 10:37:07 -07:00
err :
2021-08-19 08:47:49 +00:00
iavf_change_state ( adapter , __IAVF_INIT_FAILED ) ;
2019-05-14 10:37:07 -07:00
}
2021-11-29 16:16:00 -08:00
/**
* iavf_parse_vf_resource_msg - parse response from VIRTCHNL_OP_GET_VF_RESOURCES
* @ adapter : board private structure
*/
int iavf_parse_vf_resource_msg ( struct iavf_adapter * adapter )
{
int i , num_req_queues = adapter - > num_req_queues ;
struct iavf_vsi * vsi = & adapter - > vsi ;
for ( i = 0 ; i < adapter - > vf_res - > num_vsis ; i + + ) {
if ( adapter - > vf_res - > vsi_res [ i ] . vsi_type = = VIRTCHNL_VSI_SRIOV )
adapter - > vsi_res = & adapter - > vf_res - > vsi_res [ i ] ;
}
if ( ! adapter - > vsi_res ) {
dev_err ( & adapter - > pdev - > dev , " No LAN VSI found \n " ) ;
return - ENODEV ;
}
if ( num_req_queues & &
num_req_queues > adapter - > vsi_res - > num_queue_pairs ) {
/* Problem. The PF gave us fewer queues than what we had
* negotiated in our request . Need a reset to see if we can ' t
* get back to a working state .
*/
dev_err ( & adapter - > pdev - > dev ,
" Requested %d queues, but PF only gave us %d. \n " ,
num_req_queues ,
adapter - > vsi_res - > num_queue_pairs ) ;
2022-02-02 12:44:54 +00:00
adapter - > flags | = IAVF_FLAG_REINIT_MSIX_NEEDED ;
2021-11-29 16:16:00 -08:00
adapter - > num_req_queues = adapter - > vsi_res - > num_queue_pairs ;
2023-06-05 10:52:26 -04:00
iavf_schedule_reset ( adapter , IAVF_FLAG_RESET_NEEDED ) ;
2021-11-29 16:16:00 -08:00
return - EAGAIN ;
}
adapter - > num_req_queues = 0 ;
adapter - > vsi . id = adapter - > vsi_res - > vsi_id ;
adapter - > vsi . back = adapter ;
adapter - > vsi . base_vector = 1 ;
vsi - > netdev = adapter - > netdev ;
vsi - > qs_handle = adapter - > vsi_res - > qset_handle ;
if ( adapter - > vf_res - > vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF ) {
adapter - > rss_key_size = adapter - > vf_res - > rss_key_size ;
adapter - > rss_lut_size = adapter - > vf_res - > rss_lut_size ;
} else {
adapter - > rss_key_size = IAVF_HKEY_ARRAY_SIZE ;
adapter - > rss_lut_size = IAVF_HLUT_ARRAY_SIZE ;
}
return 0 ;
}
2019-05-14 10:37:07 -07:00
/**
* iavf_init_get_resources - third step of driver startup
* @ adapter : board private structure
*
* Function process __IAVF_INIT_GET_RESOURCES driver state and
* finishes driver initialization procedure .
* When success the state is changed to __IAVF_DOWN
2021-08-19 08:47:49 +00:00
* when fails the state is changed to __IAVF_INIT_FAILED
2019-05-14 10:37:07 -07:00
* */
2021-08-19 08:47:49 +00:00
static void iavf_init_get_resources ( struct iavf_adapter * adapter )
2019-05-14 10:37:07 -07:00
{
struct pci_dev * pdev = adapter - > pdev ;
struct iavf_hw * hw = & adapter - > hw ;
2020-06-05 10:09:43 -07:00
int err ;
2019-05-14 10:37:07 -07:00
WARN_ON ( adapter - > state ! = __IAVF_INIT_GET_RESOURCES ) ;
/* aq msg sent, awaiting reply */
if ( ! adapter - > vf_res ) {
2020-06-05 10:09:43 -07:00
adapter - > vf_res = kzalloc ( IAVF_VIRTCHNL_VF_RESOURCE_SIZE ,
GFP_KERNEL ) ;
if ( ! adapter - > vf_res ) {
err = - ENOMEM ;
2019-05-14 10:37:07 -07:00
goto err ;
2020-06-05 10:09:43 -07:00
}
2019-05-14 10:37:07 -07:00
}
err = iavf_get_vf_config ( adapter ) ;
2022-01-27 15:16:29 +01:00
if ( err = = - EALREADY ) {
2019-05-14 10:37:07 -07:00
err = iavf_send_vf_config_msg ( adapter ) ;
2022-07-19 11:16:53 +02:00
goto err ;
2022-01-27 15:16:29 +01:00
} else if ( err = = - EINVAL ) {
/* We only get -EINVAL if the device is in a very bad
2019-05-14 10:37:07 -07:00
* state or if we ' ve been disabled for previous bad
* behavior . Either way , we ' re done now .
*/
iavf_shutdown_adminq ( hw ) ;
dev_err ( & pdev - > dev , " Unable to get VF config due to PF error condition, not retrying \n " ) ;
2021-08-19 08:47:49 +00:00
return ;
2019-05-14 10:37:07 -07:00
}
if ( err ) {
dev_err ( & pdev - > dev , " Unable to get VF config (%d) \n " , err ) ;
goto err_alloc ;
}
2021-11-29 16:16:00 -08:00
err = iavf_parse_vf_resource_msg ( adapter ) ;
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
if ( err ) {
dev_err ( & pdev - > dev , " Failed to parse VF resource message from PF (%d) \n " ,
2021-11-29 16:16:00 -08:00
err ) ;
goto err_alloc ;
}
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
/* Some features require additional messages to negotiate extended
* capabilities . These are processed in sequence by the
* __IAVF_INIT_EXTENDED_CAPS driver state .
2021-11-29 16:16:00 -08:00
*/
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
adapter - > extended_caps = IAVF_EXTENDED_CAPS ;
iavf_change_state ( adapter , __IAVF_INIT_EXTENDED_CAPS ) ;
2021-11-29 16:16:00 -08:00
return ;
err_alloc :
kfree ( adapter - > vf_res ) ;
adapter - > vf_res = NULL ;
err :
iavf_change_state ( adapter , __IAVF_INIT_FAILED ) ;
}
/**
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
* iavf_init_send_offload_vlan_v2_caps - part of initializing VLAN V2 caps
* @ adapter : board private structure
*
* Function processes send of the extended VLAN V2 capability message to the
* PF . Must clear IAVF_EXTENDED_CAP_RECV_VLAN_V2 if the message is not sent ,
* e . g . due to PF not negotiating VIRTCHNL_VF_OFFLOAD_VLAN_V2 .
*/
static void iavf_init_send_offload_vlan_v2_caps ( struct iavf_adapter * adapter )
{
int ret ;
WARN_ON ( ! ( adapter - > extended_caps & IAVF_EXTENDED_CAP_SEND_VLAN_V2 ) ) ;
ret = iavf_send_vf_offload_vlan_v2_msg ( adapter ) ;
if ( ret & & ret = = - EOPNOTSUPP ) {
/* PF does not support VIRTCHNL_VF_OFFLOAD_V2. In this case,
* we did not send the capability exchange message and do not
* expect a response .
*/
adapter - > extended_caps & = ~ IAVF_EXTENDED_CAP_RECV_VLAN_V2 ;
}
/* We sent the message, so move on to the next step */
adapter - > extended_caps & = ~ IAVF_EXTENDED_CAP_SEND_VLAN_V2 ;
}
/**
* iavf_init_recv_offload_vlan_v2_caps - part of initializing VLAN V2 caps
2021-11-29 16:16:00 -08:00
* @ adapter : board private structure
*
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
* Function processes receipt of the extended VLAN V2 capability message from
* the PF .
2021-11-29 16:16:00 -08:00
* */
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
static void iavf_init_recv_offload_vlan_v2_caps ( struct iavf_adapter * adapter )
2021-11-29 16:16:00 -08:00
{
int ret ;
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
WARN_ON ( ! ( adapter - > extended_caps & IAVF_EXTENDED_CAP_RECV_VLAN_V2 ) ) ;
2021-11-29 16:16:00 -08:00
memset ( & adapter - > vlan_v2_caps , 0 , sizeof ( adapter - > vlan_v2_caps ) ) ;
ret = iavf_get_vf_vlan_v2_caps ( adapter ) ;
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
if ( ret )
2021-11-29 16:16:00 -08:00
goto err ;
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
/* We've processed receipt of the VLAN V2 caps message */
adapter - > extended_caps & = ~ IAVF_EXTENDED_CAP_RECV_VLAN_V2 ;
2021-11-29 16:16:00 -08:00
return ;
err :
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
/* We didn't receive a reply. Make sure we try sending again when
* __IAVF_INIT_FAILED attempts to recover .
*/
adapter - > extended_caps | = IAVF_EXTENDED_CAP_SEND_VLAN_V2 ;
2021-11-29 16:16:00 -08:00
iavf_change_state ( adapter , __IAVF_INIT_FAILED ) ;
}
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
/**
* iavf_init_process_extended_caps - Part of driver startup
* @ adapter : board private structure
*
* Function processes __IAVF_INIT_EXTENDED_CAPS driver state . This state
* handles negotiating capabilities for features which require an additional
* message .
*
* Once all extended capabilities exchanges are finished , the driver will
* transition into __IAVF_INIT_CONFIG_ADAPTER .
*/
static void iavf_init_process_extended_caps ( struct iavf_adapter * adapter )
{
WARN_ON ( adapter - > state ! = __IAVF_INIT_EXTENDED_CAPS ) ;
/* Process capability exchange for VLAN V2 */
if ( adapter - > extended_caps & IAVF_EXTENDED_CAP_SEND_VLAN_V2 ) {
iavf_init_send_offload_vlan_v2_caps ( adapter ) ;
return ;
} else if ( adapter - > extended_caps & IAVF_EXTENDED_CAP_RECV_VLAN_V2 ) {
iavf_init_recv_offload_vlan_v2_caps ( adapter ) ;
return ;
}
/* When we reach here, no further extended capabilities exchanges are
* necessary , so we finally transition into __IAVF_INIT_CONFIG_ADAPTER
*/
iavf_change_state ( adapter , __IAVF_INIT_CONFIG_ADAPTER ) ;
}
2021-11-29 16:16:00 -08:00
/**
* iavf_init_config_adapter - last part of driver startup
* @ adapter : board private structure
*
* After all the supported capabilities are negotiated , then the
* __IAVF_INIT_CONFIG_ADAPTER state will finish driver initialization .
*/
static void iavf_init_config_adapter ( struct iavf_adapter * adapter )
{
struct net_device * netdev = adapter - > netdev ;
struct pci_dev * pdev = adapter - > pdev ;
int err ;
WARN_ON ( adapter - > state ! = __IAVF_INIT_CONFIG_ADAPTER ) ;
if ( iavf_process_config ( adapter ) )
goto err ;
2019-05-14 10:37:07 -07:00
adapter - > current_op = VIRTCHNL_OP_UNKNOWN ;
adapter - > flags | = IAVF_FLAG_RX_CSUM_ENABLED ;
netdev - > netdev_ops = & iavf_netdev_ops ;
iavf_set_ethtool_ops ( netdev ) ;
netdev - > watchdog_timeo = 5 * HZ ;
netdev - > min_mtu = ETH_MIN_MTU ;
2024-04-18 13:36:15 +02:00
netdev - > max_mtu = LIBIE_MAX_MTU ;
2019-05-14 10:37:07 -07:00
if ( ! is_valid_ether_addr ( adapter - > hw . mac . addr ) ) {
dev_info ( & pdev - > dev , " Invalid MAC address %pM, using random \n " ,
adapter - > hw . mac . addr ) ;
eth_hw_addr_random ( netdev ) ;
ether_addr_copy ( adapter - > hw . mac . addr , netdev - > dev_addr ) ;
} else {
2021-10-01 14:32:23 -07:00
eth_hw_addr_set ( netdev , adapter - > hw . mac . addr ) ;
2019-05-14 10:37:07 -07:00
ether_addr_copy ( netdev - > perm_addr , adapter - > hw . mac . addr ) ;
}
adapter - > tx_desc_count = IAVF_DEFAULT_TXD ;
adapter - > rx_desc_count = IAVF_DEFAULT_RXD ;
err = iavf_init_interrupt_scheme ( adapter ) ;
if ( err )
goto err_sw_init ;
iavf_map_rings_to_vectors ( adapter ) ;
if ( adapter - > vf_res - > vf_cap_flags &
VIRTCHNL_VF_OFFLOAD_WB_ON_ITR )
adapter - > flags | = IAVF_FLAG_WB_ON_ITR_CAPABLE ;
err = iavf_request_misc_irq ( adapter ) ;
if ( err )
goto err_sw_init ;
netif_carrier_off ( netdev ) ;
adapter - > link_up = false ;
netif_tx_stop_all_queues ( netdev ) ;
iavf: fix a deadlock caused by rtnl and driver's lock circular dependencies
A driver's lock (crit_lock) is used to serialize all the driver's tasks.
Lockdep, however, shows a circular dependency between rtnl and
crit_lock. This happens when an ndo that already holds the rtnl requests
the driver to reset, since the reset task (in some paths) tries to grab
rtnl to either change real number of queues of update netdev features.
[566.241851] ======================================================
[566.241893] WARNING: possible circular locking dependency detected
[566.241936] 6.2.14-100.fc36.x86_64+debug #1 Tainted: G OE
[566.241984] ------------------------------------------------------
[566.242025] repro.sh/2604 is trying to acquire lock:
[566.242061] ffff9280fc5ceee8 (&adapter->crit_lock){+.+.}-{3:3}, at: iavf_close+0x3c/0x240 [iavf]
[566.242167]
but task is already holding lock:
[566.242209] ffffffff9976d350 (rtnl_mutex){+.+.}-{3:3}, at: iavf_remove+0x6b5/0x730 [iavf]
[566.242300]
which lock already depends on the new lock.
[566.242353]
the existing dependency chain (in reverse order) is:
[566.242401]
-> #1 (rtnl_mutex){+.+.}-{3:3}:
[566.242451] __mutex_lock+0xc1/0xbb0
[566.242489] iavf_init_interrupt_scheme+0x179/0x440 [iavf]
[566.242560] iavf_watchdog_task+0x80b/0x1400 [iavf]
[566.242627] process_one_work+0x2b3/0x560
[566.242663] worker_thread+0x4f/0x3a0
[566.242696] kthread+0xf2/0x120
[566.242730] ret_from_fork+0x29/0x50
[566.242763]
-> #0 (&adapter->crit_lock){+.+.}-{3:3}:
[566.242815] __lock_acquire+0x15ff/0x22b0
[566.242869] lock_acquire+0xd2/0x2c0
[566.242901] __mutex_lock+0xc1/0xbb0
[566.242934] iavf_close+0x3c/0x240 [iavf]
[566.242997] __dev_close_many+0xac/0x120
[566.243036] dev_close_many+0x8b/0x140
[566.243071] unregister_netdevice_many_notify+0x165/0x7c0
[566.243116] unregister_netdevice_queue+0xd3/0x110
[566.243157] iavf_remove+0x6c1/0x730 [iavf]
[566.243217] pci_device_remove+0x33/0xa0
[566.243257] device_release_driver_internal+0x1bc/0x240
[566.243299] pci_stop_bus_device+0x6c/0x90
[566.243338] pci_stop_and_remove_bus_device+0xe/0x20
[566.243380] pci_iov_remove_virtfn+0xd1/0x130
[566.243417] sriov_disable+0x34/0xe0
[566.243448] ice_free_vfs+0x2da/0x330 [ice]
[566.244383] ice_sriov_configure+0x88/0xad0 [ice]
[566.245353] sriov_numvfs_store+0xde/0x1d0
[566.246156] kernfs_fop_write_iter+0x15e/0x210
[566.246921] vfs_write+0x288/0x530
[566.247671] ksys_write+0x74/0xf0
[566.248408] do_syscall_64+0x58/0x80
[566.249145] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[566.249886]
other info that might help us debug this:
[566.252014] Possible unsafe locking scenario:
[566.253432] CPU0 CPU1
[566.254118] ---- ----
[566.254800] lock(rtnl_mutex);
[566.255514] lock(&adapter->crit_lock);
[566.256233] lock(rtnl_mutex);
[566.256897] lock(&adapter->crit_lock);
[566.257388]
*** DEADLOCK ***
The deadlock can be triggered by a script that is continuously resetting
the VF adapter while doing other operations requiring RTNL, e.g:
while :; do
ip link set $VF up
ethtool --set-channels $VF combined 2
ip link set $VF down
ip link set $VF up
ethtool --set-channels $VF combined 4
ip link set $VF down
done
Any operation that triggers a reset can substitute "ethtool --set-channles"
As a fix, add a new task "finish_config" that do all the work which
needs rtnl lock. With the exception of iavf_remove(), all work that
require rtnl should be called from this task.
As for iavf_remove(), at the point where we need to call
unregister_netdevice() (and grab rtnl_lock), we make sure the finish_config
task is not running (cancel_work_sync()) to safely grab rtnl. Subsequent
finish_config work cannot restart after that since the task is guarded
by the __IAVF_IN_REMOVE_TASK bit in iavf_schedule_finish_config().
Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-06-05 10:52:25 -04:00
2019-05-14 10:37:07 -07:00
dev_info ( & pdev - > dev , " MAC address: %pM \n " , adapter - > hw . mac . addr ) ;
if ( netdev - > features & NETIF_F_GRO )
dev_info ( & pdev - > dev , " GRO is enabled \n " ) ;
2021-08-19 08:47:40 +00:00
iavf_change_state ( adapter , __IAVF_DOWN ) ;
2019-05-14 10:37:07 -07:00
set_bit ( __IAVF_VSI_DOWN , adapter - > vsi . state ) ;
iavf_misc_irq_enable ( adapter ) ;
wake_up ( & adapter - > down_waitqueue ) ;
adapter - > rss_key = kzalloc ( adapter - > rss_key_size , GFP_KERNEL ) ;
adapter - > rss_lut = kzalloc ( adapter - > rss_lut_size , GFP_KERNEL ) ;
2020-06-18 14:19:53 +00:00
if ( ! adapter - > rss_key | | ! adapter - > rss_lut ) {
err = - ENOMEM ;
2019-05-14 10:37:07 -07:00
goto err_mem ;
2020-06-18 14:19:53 +00:00
}
2019-05-14 10:37:07 -07:00
if ( RSS_AQ ( adapter ) )
adapter - > aq_required | = IAVF_FLAG_AQ_CONFIGURE_RSS ;
else
iavf_init_rss ( adapter ) ;
2021-11-29 16:16:03 -08:00
if ( VLAN_V2_ALLOWED ( adapter ) )
/* request initial VLAN offload settings */
iavf_set_vlan_offload_features ( adapter , 0 , netdev - > features ) ;
iavf: fix a deadlock caused by rtnl and driver's lock circular dependencies
A driver's lock (crit_lock) is used to serialize all the driver's tasks.
Lockdep, however, shows a circular dependency between rtnl and
crit_lock. This happens when an ndo that already holds the rtnl requests
the driver to reset, since the reset task (in some paths) tries to grab
rtnl to either change real number of queues of update netdev features.
[566.241851] ======================================================
[566.241893] WARNING: possible circular locking dependency detected
[566.241936] 6.2.14-100.fc36.x86_64+debug #1 Tainted: G OE
[566.241984] ------------------------------------------------------
[566.242025] repro.sh/2604 is trying to acquire lock:
[566.242061] ffff9280fc5ceee8 (&adapter->crit_lock){+.+.}-{3:3}, at: iavf_close+0x3c/0x240 [iavf]
[566.242167]
but task is already holding lock:
[566.242209] ffffffff9976d350 (rtnl_mutex){+.+.}-{3:3}, at: iavf_remove+0x6b5/0x730 [iavf]
[566.242300]
which lock already depends on the new lock.
[566.242353]
the existing dependency chain (in reverse order) is:
[566.242401]
-> #1 (rtnl_mutex){+.+.}-{3:3}:
[566.242451] __mutex_lock+0xc1/0xbb0
[566.242489] iavf_init_interrupt_scheme+0x179/0x440 [iavf]
[566.242560] iavf_watchdog_task+0x80b/0x1400 [iavf]
[566.242627] process_one_work+0x2b3/0x560
[566.242663] worker_thread+0x4f/0x3a0
[566.242696] kthread+0xf2/0x120
[566.242730] ret_from_fork+0x29/0x50
[566.242763]
-> #0 (&adapter->crit_lock){+.+.}-{3:3}:
[566.242815] __lock_acquire+0x15ff/0x22b0
[566.242869] lock_acquire+0xd2/0x2c0
[566.242901] __mutex_lock+0xc1/0xbb0
[566.242934] iavf_close+0x3c/0x240 [iavf]
[566.242997] __dev_close_many+0xac/0x120
[566.243036] dev_close_many+0x8b/0x140
[566.243071] unregister_netdevice_many_notify+0x165/0x7c0
[566.243116] unregister_netdevice_queue+0xd3/0x110
[566.243157] iavf_remove+0x6c1/0x730 [iavf]
[566.243217] pci_device_remove+0x33/0xa0
[566.243257] device_release_driver_internal+0x1bc/0x240
[566.243299] pci_stop_bus_device+0x6c/0x90
[566.243338] pci_stop_and_remove_bus_device+0xe/0x20
[566.243380] pci_iov_remove_virtfn+0xd1/0x130
[566.243417] sriov_disable+0x34/0xe0
[566.243448] ice_free_vfs+0x2da/0x330 [ice]
[566.244383] ice_sriov_configure+0x88/0xad0 [ice]
[566.245353] sriov_numvfs_store+0xde/0x1d0
[566.246156] kernfs_fop_write_iter+0x15e/0x210
[566.246921] vfs_write+0x288/0x530
[566.247671] ksys_write+0x74/0xf0
[566.248408] do_syscall_64+0x58/0x80
[566.249145] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[566.249886]
other info that might help us debug this:
[566.252014] Possible unsafe locking scenario:
[566.253432] CPU0 CPU1
[566.254118] ---- ----
[566.254800] lock(rtnl_mutex);
[566.255514] lock(&adapter->crit_lock);
[566.256233] lock(rtnl_mutex);
[566.256897] lock(&adapter->crit_lock);
[566.257388]
*** DEADLOCK ***
The deadlock can be triggered by a script that is continuously resetting
the VF adapter while doing other operations requiring RTNL, e.g:
while :; do
ip link set $VF up
ethtool --set-channels $VF combined 2
ip link set $VF down
ip link set $VF up
ethtool --set-channels $VF combined 4
ip link set $VF down
done
Any operation that triggers a reset can substitute "ethtool --set-channles"
As a fix, add a new task "finish_config" that do all the work which
needs rtnl lock. With the exception of iavf_remove(), all work that
require rtnl should be called from this task.
As for iavf_remove(), at the point where we need to call
unregister_netdevice() (and grab rtnl_lock), we make sure the finish_config
task is not running (cancel_work_sync()) to safely grab rtnl. Subsequent
finish_config work cannot restart after that since the task is guarded
by the __IAVF_IN_REMOVE_TASK bit in iavf_schedule_finish_config().
Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-06-05 10:52:25 -04:00
iavf_schedule_finish_config ( adapter ) ;
2021-08-19 08:47:49 +00:00
return ;
iavf: fix a deadlock caused by rtnl and driver's lock circular dependencies
A driver's lock (crit_lock) is used to serialize all the driver's tasks.
Lockdep, however, shows a circular dependency between rtnl and
crit_lock. This happens when an ndo that already holds the rtnl requests
the driver to reset, since the reset task (in some paths) tries to grab
rtnl to either change real number of queues of update netdev features.
[566.241851] ======================================================
[566.241893] WARNING: possible circular locking dependency detected
[566.241936] 6.2.14-100.fc36.x86_64+debug #1 Tainted: G OE
[566.241984] ------------------------------------------------------
[566.242025] repro.sh/2604 is trying to acquire lock:
[566.242061] ffff9280fc5ceee8 (&adapter->crit_lock){+.+.}-{3:3}, at: iavf_close+0x3c/0x240 [iavf]
[566.242167]
but task is already holding lock:
[566.242209] ffffffff9976d350 (rtnl_mutex){+.+.}-{3:3}, at: iavf_remove+0x6b5/0x730 [iavf]
[566.242300]
which lock already depends on the new lock.
[566.242353]
the existing dependency chain (in reverse order) is:
[566.242401]
-> #1 (rtnl_mutex){+.+.}-{3:3}:
[566.242451] __mutex_lock+0xc1/0xbb0
[566.242489] iavf_init_interrupt_scheme+0x179/0x440 [iavf]
[566.242560] iavf_watchdog_task+0x80b/0x1400 [iavf]
[566.242627] process_one_work+0x2b3/0x560
[566.242663] worker_thread+0x4f/0x3a0
[566.242696] kthread+0xf2/0x120
[566.242730] ret_from_fork+0x29/0x50
[566.242763]
-> #0 (&adapter->crit_lock){+.+.}-{3:3}:
[566.242815] __lock_acquire+0x15ff/0x22b0
[566.242869] lock_acquire+0xd2/0x2c0
[566.242901] __mutex_lock+0xc1/0xbb0
[566.242934] iavf_close+0x3c/0x240 [iavf]
[566.242997] __dev_close_many+0xac/0x120
[566.243036] dev_close_many+0x8b/0x140
[566.243071] unregister_netdevice_many_notify+0x165/0x7c0
[566.243116] unregister_netdevice_queue+0xd3/0x110
[566.243157] iavf_remove+0x6c1/0x730 [iavf]
[566.243217] pci_device_remove+0x33/0xa0
[566.243257] device_release_driver_internal+0x1bc/0x240
[566.243299] pci_stop_bus_device+0x6c/0x90
[566.243338] pci_stop_and_remove_bus_device+0xe/0x20
[566.243380] pci_iov_remove_virtfn+0xd1/0x130
[566.243417] sriov_disable+0x34/0xe0
[566.243448] ice_free_vfs+0x2da/0x330 [ice]
[566.244383] ice_sriov_configure+0x88/0xad0 [ice]
[566.245353] sriov_numvfs_store+0xde/0x1d0
[566.246156] kernfs_fop_write_iter+0x15e/0x210
[566.246921] vfs_write+0x288/0x530
[566.247671] ksys_write+0x74/0xf0
[566.248408] do_syscall_64+0x58/0x80
[566.249145] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[566.249886]
other info that might help us debug this:
[566.252014] Possible unsafe locking scenario:
[566.253432] CPU0 CPU1
[566.254118] ---- ----
[566.254800] lock(rtnl_mutex);
[566.255514] lock(&adapter->crit_lock);
[566.256233] lock(rtnl_mutex);
[566.256897] lock(&adapter->crit_lock);
[566.257388]
*** DEADLOCK ***
The deadlock can be triggered by a script that is continuously resetting
the VF adapter while doing other operations requiring RTNL, e.g:
while :; do
ip link set $VF up
ethtool --set-channels $VF combined 2
ip link set $VF down
ip link set $VF up
ethtool --set-channels $VF combined 4
ip link set $VF down
done
Any operation that triggers a reset can substitute "ethtool --set-channles"
As a fix, add a new task "finish_config" that do all the work which
needs rtnl lock. With the exception of iavf_remove(), all work that
require rtnl should be called from this task.
As for iavf_remove(), at the point where we need to call
unregister_netdevice() (and grab rtnl_lock), we make sure the finish_config
task is not running (cancel_work_sync()) to safely grab rtnl. Subsequent
finish_config work cannot restart after that since the task is guarded
by the __IAVF_IN_REMOVE_TASK bit in iavf_schedule_finish_config().
Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-06-05 10:52:25 -04:00
2019-05-14 10:37:07 -07:00
err_mem :
iavf_free_rss ( adapter ) ;
iavf_free_misc_irq ( adapter ) ;
err_sw_init :
iavf_reset_interrupt_capability ( adapter ) ;
err :
2021-08-19 08:47:49 +00:00
iavf_change_state ( adapter , __IAVF_INIT_FAILED ) ;
2019-05-14 10:37:07 -07:00
}
2019-05-14 10:37:04 -07:00
/**
* iavf_watchdog_task - Periodic call - back task
* @ work : pointer to work_struct
* */
static void iavf_watchdog_task ( struct work_struct * work )
{
struct iavf_adapter * adapter = container_of ( work ,
struct iavf_adapter ,
2019-05-14 10:37:05 -07:00
watchdog_task . work ) ;
2019-05-14 10:37:04 -07:00
struct iavf_hw * hw = & adapter - > hw ;
u32 reg_val ;
2022-02-23 13:35:49 +01:00
if ( ! mutex_trylock ( & adapter - > crit_lock ) ) {
if ( adapter - > state = = __IAVF_REMOVE )
return ;
2019-05-14 10:37:04 -07:00
goto restart_watchdog ;
2022-02-23 13:35:49 +01:00
}
2019-05-14 10:37:04 -07:00
2019-05-14 10:37:06 -07:00
if ( adapter - > flags & IAVF_FLAG_PF_COMMS_FAILED )
2021-08-19 08:47:40 +00:00
iavf_change_state ( adapter , __IAVF_COMM_FAILED ) ;
2019-05-14 10:37:06 -07:00
switch ( adapter - > state ) {
2021-08-19 08:47:58 +00:00
case __IAVF_STARTUP :
iavf_startup ( adapter ) ;
mutex_unlock ( & adapter - > crit_lock ) ;
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq , & adapter - > watchdog_task ,
2021-08-19 08:47:58 +00:00
msecs_to_jiffies ( 30 ) ) ;
return ;
case __IAVF_INIT_VERSION_CHECK :
iavf_init_version_check ( adapter ) ;
mutex_unlock ( & adapter - > crit_lock ) ;
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq , & adapter - > watchdog_task ,
2021-08-19 08:47:58 +00:00
msecs_to_jiffies ( 30 ) ) ;
return ;
case __IAVF_INIT_GET_RESOURCES :
iavf_init_get_resources ( adapter ) ;
mutex_unlock ( & adapter - > crit_lock ) ;
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq , & adapter - > watchdog_task ,
2021-08-19 08:47:58 +00:00
msecs_to_jiffies ( 1 ) ) ;
return ;
iavf: refactor processing of VLAN V2 capability message
In order to handle the capability exchange necessary for
VIRTCHNL_VF_OFFLOAD_VLAN_V2, the driver must send
a VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS message. This must occur prior to
__IAVF_CONFIG_ADAPTER, and the driver must wait for the response from
the PF.
To handle this, the __IAVF_INIT_GET_OFFLOAD_VLAN_V2_CAPS state was
introduced. This state is intended to process the response from the VLAN
V2 caps message. This works ok, but is difficult to extend to adding
more extended capability exchange.
Existing (and future) AVF features are relying more and more on these
sort of extended ops for processing additional capabilities. Just like
VLAN V2, this exchange must happen prior to __IAVF_CONFIG_ADPATER.
Since we only send one outstanding AQ message at a time during init, it
is not clear where to place this state. Adding more capability specific
states becomes a mess. Instead of having the "previous" state send
a message and then transition into a capability-specific state,
introduce __IAVF_EXTENDED_CAPS state. This state will use a list of
extended_caps that determines what messages to send and receive. As long
as there are extended_caps bits still set, the driver will remain in
this state performing one send or one receive per state machine loop.
Refactor the VLAN V2 negotiation to use this new state, and remove the
capability-specific state. This makes it significantly easier to add
a new similar capability exchange going forward.
Extended capabilities are processed by having an associated SEND and
RECV extended capability bit. During __IAVF_EXTENDED_CAPS, the
driver checks these bits in order by feature, first the send bit for
a feature, then the recv bit for a feature. Each send flag will call
a function that sends the necessary response, while each receive flag
will wait for the response from the PF. If a given feature can't be
negotiated with the PF, the associated flags will be cleared in
order to skip processing of that feature.
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2022-01-14 10:36:36 +01:00
case __IAVF_INIT_EXTENDED_CAPS :
iavf_init_process_extended_caps ( adapter ) ;
2021-11-29 16:16:00 -08:00
mutex_unlock ( & adapter - > crit_lock ) ;
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq , & adapter - > watchdog_task ,
2021-11-29 16:16:00 -08:00
msecs_to_jiffies ( 1 ) ) ;
return ;
case __IAVF_INIT_CONFIG_ADAPTER :
iavf_init_config_adapter ( adapter ) ;
mutex_unlock ( & adapter - > crit_lock ) ;
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq , & adapter - > watchdog_task ,
2021-11-29 16:16:00 -08:00
msecs_to_jiffies ( 1 ) ) ;
return ;
2021-08-19 08:47:58 +00:00
case __IAVF_INIT_FAILED :
2022-02-23 13:37:10 +01:00
if ( test_bit ( __IAVF_IN_REMOVE_TASK ,
& adapter - > crit_section ) ) {
/* Do not update the state and do not reschedule
* watchdog task , iavf_remove should handle this state
* as it can loop forever
*/
mutex_unlock ( & adapter - > crit_lock ) ;
return ;
}
2021-08-19 08:47:58 +00:00
if ( + + adapter - > aq_wait_count > IAVF_AQ_MAX_ERR ) {
dev_err ( & adapter - > pdev - > dev ,
" Failed to communicate with PF; waiting before retry \n " ) ;
adapter - > flags | = IAVF_FLAG_PF_COMMS_FAILED ;
iavf_shutdown_adminq ( hw ) ;
mutex_unlock ( & adapter - > crit_lock ) ;
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq ,
2021-08-19 08:47:58 +00:00
& adapter - > watchdog_task , ( 5 * HZ ) ) ;
return ;
}
/* Try again from failed step*/
iavf_change_state ( adapter , adapter - > last_state ) ;
mutex_unlock ( & adapter - > crit_lock ) ;
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq , & adapter - > watchdog_task , HZ ) ;
2021-08-19 08:47:58 +00:00
return ;
2019-05-14 10:37:06 -07:00
case __IAVF_COMM_FAILED :
2022-02-23 13:37:10 +01:00
if ( test_bit ( __IAVF_IN_REMOVE_TASK ,
& adapter - > crit_section ) ) {
/* Set state to __IAVF_INIT_FAILED and perform remove
* steps . Remove IAVF_FLAG_PF_COMMS_FAILED so the task
* doesn ' t bring the state back to __IAVF_COMM_FAILED .
*/
iavf_change_state ( adapter , __IAVF_INIT_FAILED ) ;
adapter - > flags & = ~ IAVF_FLAG_PF_COMMS_FAILED ;
mutex_unlock ( & adapter - > crit_lock ) ;
return ;
}
2019-05-14 10:37:04 -07:00
reg_val = rd32 ( hw , IAVF_VFGEN_RSTAT ) &
IAVF_VFGEN_RSTAT_VFR_STATE_MASK ;
if ( reg_val = = VIRTCHNL_VFR_VFACTIVE | |
reg_val = = VIRTCHNL_VFR_COMPLETED ) {
/* A chance for redemption! */
2019-05-14 10:37:06 -07:00
dev_err ( & adapter - > pdev - > dev ,
" Hardware came out of reset. Attempting reinit. \n " ) ;
2021-08-19 08:47:58 +00:00
/* When init task contacts the PF and
2019-05-14 10:37:04 -07:00
* gets everything set up again , it ' ll restart the
* watchdog for us . Down , boy . Sit . Stay . Woof .
*/
2021-08-19 08:47:58 +00:00
iavf_change_state ( adapter , __IAVF_STARTUP ) ;
adapter - > flags & = ~ IAVF_FLAG_PF_COMMS_FAILED ;
2019-05-14 10:37:04 -07:00
}
adapter - > aq_required = 0 ;
adapter - > current_op = VIRTCHNL_OP_UNKNOWN ;
2021-11-10 11:13:50 +03:00
mutex_unlock ( & adapter - > crit_lock ) ;
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq ,
2019-05-14 10:37:06 -07:00
& adapter - > watchdog_task ,
msecs_to_jiffies ( 10 ) ) ;
2021-08-19 08:47:58 +00:00
return ;
2019-05-14 10:37:06 -07:00
case __IAVF_RESETTING :
2021-08-04 10:22:24 +02:00
mutex_unlock ( & adapter - > crit_lock ) ;
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq , & adapter - > watchdog_task ,
HZ * 2 ) ;
2019-05-14 10:37:06 -07:00
return ;
case __IAVF_DOWN :
case __IAVF_DOWN_PENDING :
case __IAVF_TESTING :
case __IAVF_RUNNING :
if ( adapter - > current_op ) {
if ( ! iavf_asq_done ( hw ) ) {
dev_dbg ( & adapter - > pdev - > dev ,
" Admin queue timeout \n " ) ;
iavf_send_api_ver ( adapter ) ;
}
} else {
2021-11-29 16:16:00 -08:00
int ret = iavf_process_aq_command ( adapter ) ;
2020-06-24 09:04:22 -07:00
/* An error will be returned if no commands were
* processed ; use this opportunity to update stats
2021-11-29 16:16:00 -08:00
* if the error isn ' t - ENOTSUPP
2020-06-24 09:04:22 -07:00
*/
2021-11-29 16:16:00 -08:00
if ( ret & & ret ! = - EOPNOTSUPP & &
2019-05-14 10:37:06 -07:00
adapter - > state = = __IAVF_RUNNING )
iavf_request_stats ( adapter ) ;
}
2021-08-19 08:47:58 +00:00
if ( adapter - > state = = __IAVF_RUNNING )
iavf_detect_recover_hung ( & adapter - > vsi ) ;
2019-05-14 10:37:06 -07:00
break ;
case __IAVF_REMOVE :
default :
2021-11-10 11:13:50 +03:00
mutex_unlock ( & adapter - > crit_lock ) ;
2021-08-19 08:47:58 +00:00
return ;
2018-01-23 08:51:05 -08:00
}
2021-08-19 08:47:40 +00:00
/* check for hw reset */
2019-05-14 10:37:04 -07:00
reg_val = rd32 ( hw , IAVF_VF_ARQLEN1 ) & IAVF_VF_ARQLEN1_ARQENABLE_MASK ;
2019-05-14 10:37:06 -07:00
if ( ! reg_val ) {
2019-05-14 10:37:04 -07:00
adapter - > aq_required = 0 ;
adapter - > current_op = VIRTCHNL_OP_UNKNOWN ;
2019-05-14 10:37:06 -07:00
dev_err ( & adapter - > pdev - > dev , " Hardware reset detected \n " ) ;
2023-06-05 10:52:26 -04:00
iavf_schedule_reset ( adapter , IAVF_FLAG_RESET_PENDING ) ;
2021-08-19 08:47:58 +00:00
mutex_unlock ( & adapter - > crit_lock ) ;
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq ,
2021-08-19 08:47:58 +00:00
& adapter - > watchdog_task , HZ * 2 ) ;
return ;
2019-05-14 10:37:04 -07:00
}
2021-08-04 10:22:24 +02:00
mutex_unlock ( & adapter - > crit_lock ) ;
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
restart_watchdog :
2022-02-23 13:38:01 +01:00
if ( adapter - > state > = __IAVF_DOWN )
2022-12-15 23:50:48 +01:00
queue_work ( adapter - > wq , & adapter - > adminq_task ) ;
2013-12-21 06:12:45 +00:00
if ( adapter - > aq_required )
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq , & adapter - > watchdog_task ,
2019-05-14 10:37:05 -07:00
msecs_to_jiffies ( 20 ) ) ;
2013-12-21 06:12:45 +00:00
else
2022-12-15 23:50:48 +01:00
queue_delayed_work ( adapter - > wq , & adapter - > watchdog_task ,
HZ * 2 ) ;
2013-12-21 06:12:45 +00:00
}
2022-03-09 16:37:39 +01:00
/**
* iavf_disable_vf - disable VF
* @ adapter : board private structure
*
* Set communication failed flag and free all resources .
* NOTE : This function is expected to be called with crit_lock being held .
* */
2018-09-14 17:37:46 -07:00
static void iavf_disable_vf ( struct iavf_adapter * adapter )
2016-11-01 15:35:14 -07:00
{
2018-09-14 17:37:46 -07:00
struct iavf_mac_filter * f , * ftmp ;
struct iavf_vlan_filter * fv , * fvtmp ;
struct iavf_cloud_filter * cf , * cftmp ;
2016-11-01 15:35:14 -07:00
2018-09-14 17:37:46 -07:00
adapter - > flags | = IAVF_FLAG_PF_COMMS_FAILED ;
2016-11-01 15:35:14 -07:00
2017-10-27 11:06:49 -04:00
/* We don't use netif_running() because it may be true prior to
* ndo_open ( ) returning , so we can ' t assume it means all our open
* tasks have finished , since we ' re not holding the rtnl_lock here .
*/
2018-09-14 17:37:46 -07:00
if ( adapter - > state = = __IAVF_RUNNING ) {
2018-09-14 17:37:55 -07:00
set_bit ( __IAVF_VSI_DOWN , adapter - > vsi . state ) ;
2016-11-01 15:35:14 -07:00
netif_carrier_off ( adapter - > netdev ) ;
netif_tx_disable ( adapter - > netdev ) ;
adapter - > link_up = false ;
2018-09-14 17:37:46 -07:00
iavf_napi_disable_all ( adapter ) ;
iavf_irq_disable ( adapter ) ;
iavf_free_traffic_irqs ( adapter ) ;
iavf_free_all_tx_resources ( adapter ) ;
iavf_free_all_rx_resources ( adapter ) ;
2016-11-01 15:35:14 -07:00
}
2017-10-27 11:06:50 -04:00
spin_lock_bh ( & adapter - > mac_vlan_list_lock ) ;
2018-01-23 08:51:05 -08:00
/* Delete all of the filters */
2016-11-01 15:35:14 -07:00
list_for_each_entry_safe ( f , ftmp , & adapter - > mac_filter_list , list ) {
list_del ( & f - > list ) ;
kfree ( f ) ;
}
list_for_each_entry_safe ( fv , fvtmp , & adapter - > vlan_filter_list , list ) {
list_del ( & fv - > list ) ;
kfree ( fv ) ;
}
2023-04-06 15:35:28 -06:00
adapter - > num_vlan_filters = 0 ;
2016-11-01 15:35:14 -07:00
2017-10-27 11:06:50 -04:00
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
2018-01-23 08:51:05 -08:00
spin_lock_bh ( & adapter - > cloud_filter_list_lock ) ;
list_for_each_entry_safe ( cf , cftmp , & adapter - > cloud_filter_list , list ) {
list_del ( & cf - > list ) ;
kfree ( cf ) ;
adapter - > num_cloud_filters - - ;
}
spin_unlock_bh ( & adapter - > cloud_filter_list_lock ) ;
2018-09-14 17:37:46 -07:00
iavf_free_misc_irq ( adapter ) ;
2023-10-27 10:59:40 -07:00
iavf_free_interrupt_scheme ( adapter ) ;
2020-06-05 10:09:43 -07:00
memset ( adapter - > vf_res , 0 , IAVF_VIRTCHNL_VF_RESOURCE_SIZE ) ;
2018-09-14 17:37:46 -07:00
iavf_shutdown_adminq ( & adapter - > hw ) ;
adapter - > flags & = ~ IAVF_FLAG_RESET_PENDING ;
2021-08-19 08:47:40 +00:00
iavf_change_state ( adapter , __IAVF_DOWN ) ;
2017-06-23 04:24:44 -04:00
wake_up ( & adapter - > down_waitqueue ) ;
2016-11-01 15:35:14 -07:00
dev_info ( & adapter - > pdev - > dev , " Reset task did not complete, VF disabled \n " ) ;
}
2013-12-21 06:12:45 +00:00
/**
2018-09-14 17:37:46 -07:00
* iavf_reset_task - Call - back task to handle hardware reset
2013-12-21 06:12:45 +00:00
* @ work : pointer to work_struct
*
* During reset we need to shut down and reinitialize the admin queue
* before we can use it to communicate with the PF again . We also clear
* and reinit the rings because that context is lost as well .
* */
2018-09-14 17:37:46 -07:00
static void iavf_reset_task ( struct work_struct * work )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = container_of ( work ,
struct iavf_adapter ,
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
reset_task ) ;
2018-01-23 08:51:05 -08:00
struct virtchnl_vf_resource * vfres = adapter - > vf_res ;
2015-01-29 07:17:19 +00:00
struct net_device * netdev = adapter - > netdev ;
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2019-12-17 11:29:23 +01:00
struct iavf_mac_filter * f , * ftmp ;
2018-09-14 17:37:46 -07:00
struct iavf_cloud_filter * cf ;
2022-01-27 15:16:29 +01:00
enum iavf_status status ;
2015-08-28 17:55:53 -04:00
u32 reg_val ;
2015-01-29 07:17:19 +00:00
int i = 0 , err ;
2017-10-27 11:06:49 -04:00
bool running ;
2013-12-21 06:12:45 +00:00
2017-12-18 05:16:43 -05:00
/* When device is being removed it doesn't make sense to run the reset
* task , just return in such a case .
*/
2022-02-23 13:35:49 +01:00
if ( ! mutex_trylock ( & adapter - > crit_lock ) ) {
if ( adapter - > state ! = __IAVF_REMOVE )
2022-12-15 23:50:48 +01:00
queue_work ( adapter - > wq , & adapter - > reset_task ) ;
2017-12-18 05:16:43 -05:00
2023-06-05 10:52:23 -04:00
return ;
2021-03-16 11:01:41 +01:00
}
2022-02-23 13:35:49 +01:00
2018-09-14 17:37:46 -07:00
iavf_misc_irq_disable ( adapter ) ;
if ( adapter - > flags & IAVF_FLAG_RESET_NEEDED ) {
adapter - > flags & = ~ IAVF_FLAG_RESET_NEEDED ;
2015-06-19 08:56:30 -07:00
/* Restart the AQ here. If we have been reset but didn't
* detect it , or if the PF had to reinit , our AQ will be hosed .
*/
2018-09-14 17:37:46 -07:00
iavf_shutdown_adminq ( hw ) ;
iavf_init_adminq ( hw ) ;
iavf_request_reset ( adapter ) ;
2014-03-06 08:59:56 +00:00
}
2018-09-14 17:37:46 -07:00
adapter - > flags | = IAVF_FLAG_RESET_PENDING ;
2014-03-06 08:59:56 +00:00
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
/* poll until we see the reset actually happen */
2020-06-05 10:09:46 -07:00
for ( i = 0 ; i < IAVF_RESET_WAIT_DETECTED_COUNT ; i + + ) {
2018-09-14 17:37:49 -07:00
reg_val = rd32 ( hw , IAVF_VF_ARQLEN1 ) &
IAVF_VF_ARQLEN1_ARQENABLE_MASK ;
2015-08-28 17:55:53 -04:00
if ( ! reg_val )
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
break ;
2015-08-28 17:55:53 -04:00
usleep_range ( 5000 , 10000 ) ;
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
}
2020-06-05 10:09:46 -07:00
if ( i = = IAVF_RESET_WAIT_DETECTED_COUNT ) {
2015-06-19 08:56:30 -07:00
dev_info ( & adapter - > pdev - > dev , " Never saw reset \n " ) ;
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
goto continue_reset ; /* act like the reset happened */
}
2013-12-21 06:12:45 +00:00
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
/* wait until the reset is complete and the PF is responding to us */
2020-06-05 10:09:46 -07:00
for ( i = 0 ; i < IAVF_RESET_WAIT_COMPLETE_COUNT ; i + + ) {
2016-10-05 09:30:45 -07:00
/* sleep first to make sure a minimum wait time is met */
2018-09-14 17:37:46 -07:00
msleep ( IAVF_RESET_WAIT_MS ) ;
2016-10-05 09:30:45 -07:00
2018-09-14 17:37:49 -07:00
reg_val = rd32 ( hw , IAVF_VFGEN_RSTAT ) &
IAVF_VFGEN_RSTAT_VFR_STATE_MASK ;
2017-05-11 11:23:11 -07:00
if ( reg_val = = VIRTCHNL_VFR_VFACTIVE )
2013-12-21 06:12:45 +00:00
break ;
}
2016-10-05 09:30:45 -07:00
2015-12-23 12:05:52 -08:00
pci_set_master ( adapter - > pdev ) ;
2021-06-04 09:53:28 -07:00
pci_restore_msi_state ( adapter - > pdev ) ;
2016-10-05 09:30:45 -07:00
2020-06-05 10:09:46 -07:00
if ( i = = IAVF_RESET_WAIT_COMPLETE_COUNT ) {
2014-05-10 04:49:06 +00:00
dev_err ( & adapter - > pdev - > dev , " Reset never finished (%x) \n " ,
2015-08-28 17:55:53 -04:00
reg_val ) ;
2018-09-14 17:37:46 -07:00
iavf_disable_vf ( adapter ) ;
2022-02-23 13:38:31 +01:00
mutex_unlock ( & adapter - > crit_lock ) ;
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
return ; /* Do not attempt to reinit. It's dead, Jim. */
2013-12-21 06:12:45 +00:00
}
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
continue_reset :
2017-10-27 11:06:49 -04:00
/* We don't use netif_running() because it may be true prior to
* ndo_open ( ) returning , so we can ' t assume it means all our open
* tasks have finished , since we ' re not holding the rtnl_lock here .
*/
2022-02-23 13:38:55 +01:00
running = adapter - > state = = __IAVF_RUNNING ;
2017-10-27 11:06:49 -04:00
if ( running ) {
2015-02-27 09:18:31 +00:00
netif_carrier_off ( netdev ) ;
2022-11-08 10:35:34 +01:00
netif_tx_stop_all_queues ( netdev ) ;
i40evf: Fix link state event handling
Currently disabling the link state from PF via
ip link set enp5s0f0 vf 0 state disable
doesn't disable the CARRIER on the VF.
This patch updates the carrier and starts/stops the tx queues based on the
link state notification from PF.
PF: enp5s0f0, VF: enp5s2
#modprobe i40e
#echo 2 > /sys/class/net/enp5s0f0/device/sriov_numvfs
#ip link set enp5s2 up
#ip -d link show enp5s2
175: enp5s2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether ea:4d:60:bc:6f:85 brd ff:ff:ff:ff:ff:ff promiscuity 0 addrgenmode eui64
#ip link set enp5s0f0 vf 0 state disable
#ip -d link show enp5s0f0
171: enp5s0f0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether 68:05:ca:2e:72:68 brd ff:ff:ff:ff:ff:ff promiscuity 0 addrgenmode eui64 numtxqueues 72 numrxqueues 72 portid 6805ca2e7268
vf 0 MAC 00:00:00:00:00:00, spoof checking on, link-state disable, trust off
vf 1 MAC 00:00:00:00:00:00, spoof checking on, link-state auto, trust off
#ip -d link show enp5s2
175: enp5s2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 1000
link/ether ea:4d:60:bc:6f:85 brd ff:ff:ff:ff:ff:ff promiscuity 0 addrgenmode eui64 numtxqueues 16 numrxqueues 16
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2016-09-01 22:27:27 +02:00
adapter - > link_up = false ;
2018-09-14 17:37:46 -07:00
iavf_napi_disable_all ( adapter ) ;
2015-02-27 09:18:31 +00:00
}
2018-09-14 17:37:46 -07:00
iavf_irq_disable ( adapter ) ;
2015-01-29 07:17:19 +00:00
2021-08-19 08:47:40 +00:00
iavf_change_state ( adapter , __IAVF_RESETTING ) ;
2018-09-14 17:37:46 -07:00
adapter - > flags & = ~ IAVF_FLAG_RESET_PENDING ;
2015-06-19 08:56:30 -07:00
/* free the Tx/Rx rings and descriptors, might be better to just
* re - use them sometime in the future
*/
2018-09-14 17:37:46 -07:00
iavf_free_all_rx_resources ( adapter ) ;
iavf_free_all_tx_resources ( adapter ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
adapter - > flags | = IAVF_FLAG_QUEUES_DISABLED ;
2013-12-21 06:12:45 +00:00
/* kill and reinit the admin queue */
2018-09-14 17:37:46 -07:00
iavf_shutdown_adminq ( hw ) ;
2017-05-11 11:23:11 -07:00
adapter - > current_op = VIRTCHNL_OP_UNKNOWN ;
2022-01-27 15:16:29 +01:00
status = iavf_init_adminq ( hw ) ;
if ( status ) {
2015-01-29 07:17:19 +00:00
dev_info ( & adapter - > pdev - > dev , " Failed to init adminq: %d \n " ,
2022-01-27 15:16:29 +01:00
status ) ;
goto reset_err ;
}
2017-08-22 06:57:50 -04:00
adapter - > aq_required = 0 ;
2022-02-02 12:44:54 +00:00
if ( ( adapter - > flags & IAVF_FLAG_REINIT_MSIX_NEEDED ) | |
( adapter - > flags & IAVF_FLAG_REINIT_ITR_NEEDED ) ) {
2023-05-19 15:46:02 -06:00
err = iavf_reinit_interrupt_scheme ( adapter , running ) ;
2017-08-22 06:57:50 -04:00
if ( err )
goto reset_err ;
}
2013-12-21 06:12:45 +00:00
2021-06-04 09:53:33 -07:00
if ( RSS_AQ ( adapter ) ) {
adapter - > aq_required | = IAVF_FLAG_AQ_CONFIGURE_RSS ;
} else {
err = iavf_init_rss ( adapter ) ;
if ( err )
goto reset_err ;
}
2018-09-14 17:37:46 -07:00
adapter - > aq_required | = IAVF_FLAG_AQ_GET_CONFIG ;
2021-11-29 16:16:00 -08:00
/* always set since VIRTCHNL_OP_GET_VF_RESOURCES has not been
* sent / received yet , so VLAN_V2_ALLOWED ( ) cannot is not reliable here ,
* however the VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS won ' t be sent until
* VIRTCHNL_OP_GET_VF_RESOURCES and VIRTCHNL_VF_OFFLOAD_VLAN_V2 have
* been successfully sent and negotiated
*/
adapter - > aq_required | = IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS ;
2018-09-14 17:37:46 -07:00
adapter - > aq_required | = IAVF_FLAG_AQ_MAP_VECTORS ;
2015-01-29 07:17:19 +00:00
2017-10-27 11:06:50 -04:00
spin_lock_bh ( & adapter - > mac_vlan_list_lock ) ;
2019-12-17 11:29:23 +01:00
/* Delete filter for the current MAC address, it could have
* been changed by the PF via administratively set MAC .
* Will be re - added via VIRTCHNL_OP_GET_VF_RESOURCES .
*/
list_for_each_entry_safe ( f , ftmp , & adapter - > mac_filter_list , list ) {
if ( ether_addr_equal ( f - > macaddr , adapter - > hw . mac . addr ) ) {
list_del ( & f - > list ) ;
kfree ( f ) ;
}
}
2015-01-29 07:17:19 +00:00
/* re-add all MAC filters */
list_for_each_entry ( f , & adapter - > mac_filter_list , list ) {
f - > add = true ;
}
2017-10-27 11:06:50 -04:00
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
2018-01-23 08:51:05 -08:00
/* check if TCs are running and re-add all cloud filters */
spin_lock_bh ( & adapter - > cloud_filter_list_lock ) ;
if ( ( vfres - > vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ ) & &
adapter - > num_tc ) {
list_for_each_entry ( cf , & adapter - > cloud_filter_list , list ) {
cf - > add = true ;
}
}
spin_unlock_bh ( & adapter - > cloud_filter_list_lock ) ;
2018-09-14 17:37:46 -07:00
adapter - > aq_required | = IAVF_FLAG_AQ_ADD_MAC_FILTER ;
adapter - > aq_required | = IAVF_FLAG_AQ_ADD_CLOUD_FILTER ;
iavf_misc_irq_enable ( adapter ) ;
2013-12-21 06:12:45 +00:00
2022-12-15 23:50:48 +01:00
mod_delayed_work ( adapter - > wq , & adapter - > watchdog_task , 2 ) ;
2013-12-21 06:12:45 +00:00
2017-10-27 11:06:49 -04:00
/* We were running when the reset started, so we need to restore some
* state here .
*/
if ( running ) {
2013-12-21 06:12:45 +00:00
/* allocate transmit descriptors */
2018-09-14 17:37:46 -07:00
err = iavf_setup_all_tx_resources ( adapter ) ;
2013-12-21 06:12:45 +00:00
if ( err )
goto reset_err ;
/* allocate receive descriptors */
2018-09-14 17:37:46 -07:00
err = iavf_setup_all_rx_resources ( adapter ) ;
2013-12-21 06:12:45 +00:00
if ( err )
goto reset_err ;
2022-02-02 12:44:54 +00:00
if ( ( adapter - > flags & IAVF_FLAG_REINIT_MSIX_NEEDED ) | |
( adapter - > flags & IAVF_FLAG_REINIT_ITR_NEEDED ) ) {
2018-09-14 17:37:46 -07:00
err = iavf_request_traffic_irqs ( adapter , netdev - > name ) ;
2017-08-22 06:57:50 -04:00
if ( err )
goto reset_err ;
2022-02-02 12:44:54 +00:00
adapter - > flags & = ~ IAVF_FLAG_REINIT_MSIX_NEEDED ;
2017-08-22 06:57:50 -04:00
}
2018-09-14 17:37:46 -07:00
iavf_configure ( adapter ) ;
2013-12-21 06:12:45 +00:00
2021-08-19 08:47:40 +00:00
/* iavf_up_complete() will switch device back
* to __IAVF_RUNNING
*/
2018-09-14 17:37:46 -07:00
iavf_up_complete ( adapter ) ;
2022-03-24 14:19:15 +01:00
2018-09-14 17:37:46 -07:00
iavf_irq_enable ( adapter , true ) ;
2015-06-19 08:56:30 -07:00
} else {
2021-08-19 08:47:40 +00:00
iavf_change_state ( adapter , __IAVF_DOWN ) ;
2017-06-23 04:24:44 -04:00
wake_up ( & adapter - > down_waitqueue ) ;
2013-12-21 06:12:45 +00:00
}
2022-02-02 12:44:54 +00:00
adapter - > flags & = ~ IAVF_FLAG_REINIT_ITR_NEEDED ;
2023-06-05 10:52:22 -04:00
wake_up ( & adapter - > reset_waitqueue ) ;
2021-08-04 10:22:24 +02:00
mutex_unlock ( & adapter - > crit_lock ) ;
2015-06-19 08:56:30 -07:00
2023-06-05 10:52:23 -04:00
return ;
2013-12-21 06:12:45 +00:00
reset_err :
2022-07-19 11:16:54 +02:00
if ( running ) {
set_bit ( __IAVF_VSI_DOWN , adapter - > vsi . state ) ;
iavf_free_traffic_irqs ( adapter ) ;
}
iavf_disable_vf ( adapter ) ;
2021-08-04 10:22:24 +02:00
mutex_unlock ( & adapter - > crit_lock ) ;
2014-05-10 04:49:06 +00:00
dev_err ( & adapter - > pdev - > dev , " failed to allocate resources during reinit \n " ) ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_adminq_task - worker thread to clean the admin queue
2013-12-21 06:12:45 +00:00
* @ work : pointer to work_struct containing our data
* */
2018-09-14 17:37:46 -07:00
static void iavf_adminq_task ( struct work_struct * work )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter =
container_of ( work , struct iavf_adapter , adminq_task ) ;
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = & adapter - > hw ;
2019-04-17 15:17:32 -07:00
struct iavf_arq_event_info event ;
2017-06-22 09:44:32 -07:00
enum virtchnl_ops v_op ;
2019-04-17 15:17:30 -07:00
enum iavf_status ret , v_ret ;
2014-05-22 06:32:07 +00:00
u32 val , oldval ;
2013-12-21 06:12:45 +00:00
u16 pending ;
2022-02-23 13:35:49 +01:00
if ( ! mutex_trylock ( & adapter - > crit_lock ) ) {
if ( adapter - > state = = __IAVF_REMOVE )
return ;
2022-12-15 23:50:48 +01:00
queue_work ( adapter - > wq , & adapter - > adminq_task ) ;
2022-02-23 13:35:49 +01:00
goto out ;
}
2023-07-10 13:41:28 -07:00
if ( adapter - > flags & IAVF_FLAG_PF_COMMS_FAILED )
goto unlock ;
2018-09-14 17:37:46 -07:00
event . buf_len = IAVF_MAX_AQ_BUF_SIZE ;
2014-11-11 20:02:19 +00:00
event . msg_buf = kzalloc ( event . buf_len , GFP_KERNEL ) ;
2014-05-10 04:49:04 +00:00
if ( ! event . msg_buf )
2023-07-10 13:41:27 -07:00
goto unlock ;
2014-05-10 04:49:04 +00:00
2013-12-21 06:12:45 +00:00
do {
2018-09-14 17:37:46 -07:00
ret = iavf_clean_arq_element ( hw , & event , & pending ) ;
2017-06-22 09:44:32 -07:00
v_op = ( enum virtchnl_ops ) le32_to_cpu ( event . desc . cookie_high ) ;
2019-04-17 15:17:30 -07:00
v_ret = ( enum iavf_status ) le32_to_cpu ( event . desc . cookie_low ) ;
2017-06-22 09:44:32 -07:00
if ( ret | | ! v_op )
2013-12-21 06:12:45 +00:00
break ; /* No event to process or error cleaning ARQ */
2018-09-14 17:37:46 -07:00
iavf_virtchnl_completion ( adapter , v_op , v_ret , event . msg_buf ,
event . msg_len ) ;
2014-11-11 20:02:42 +00:00
if ( pending ! = 0 )
2018-09-14 17:37:46 -07:00
memset ( event . msg_buf , 0 , IAVF_MAX_AQ_BUF_SIZE ) ;
2013-12-21 06:12:45 +00:00
} while ( pending ) ;
2023-06-05 10:52:26 -04:00
if ( iavf_is_reset_in_progress ( adapter ) )
2015-06-19 08:56:30 -07:00
goto freedom ;
2014-05-22 06:32:07 +00:00
/* check for error indications */
2023-10-26 10:39:32 +02:00
val = rd32 ( hw , IAVF_VF_ARQLEN1 ) ;
2021-06-04 09:48:59 -07:00
if ( val = = 0xdeadbeef | | val = = 0xffffffff ) /* device in reset */
2016-03-10 14:59:49 -08:00
goto freedom ;
2014-05-22 06:32:07 +00:00
oldval = val ;
2018-09-14 17:37:49 -07:00
if ( val & IAVF_VF_ARQLEN1_ARQVFE_MASK ) {
2014-05-22 06:32:07 +00:00
dev_info ( & adapter - > pdev - > dev , " ARQ VF Error detected \n " ) ;
2018-09-14 17:37:49 -07:00
val & = ~ IAVF_VF_ARQLEN1_ARQVFE_MASK ;
2014-05-22 06:32:07 +00:00
}
2018-09-14 17:37:49 -07:00
if ( val & IAVF_VF_ARQLEN1_ARQOVFL_MASK ) {
2014-05-22 06:32:07 +00:00
dev_info ( & adapter - > pdev - > dev , " ARQ Overflow Error detected \n " ) ;
2018-09-14 17:37:49 -07:00
val & = ~ IAVF_VF_ARQLEN1_ARQOVFL_MASK ;
2014-05-22 06:32:07 +00:00
}
2018-09-14 17:37:49 -07:00
if ( val & IAVF_VF_ARQLEN1_ARQCRIT_MASK ) {
2014-05-22 06:32:07 +00:00
dev_info ( & adapter - > pdev - > dev , " ARQ Critical Error detected \n " ) ;
2018-09-14 17:37:49 -07:00
val & = ~ IAVF_VF_ARQLEN1_ARQCRIT_MASK ;
2014-05-22 06:32:07 +00:00
}
if ( oldval ! = val )
2023-10-26 10:39:32 +02:00
wr32 ( hw , IAVF_VF_ARQLEN1 , val ) ;
2014-05-22 06:32:07 +00:00
2023-10-26 10:39:32 +02:00
val = rd32 ( hw , IAVF_VF_ATQLEN1 ) ;
2014-05-22 06:32:07 +00:00
oldval = val ;
2018-09-14 17:37:49 -07:00
if ( val & IAVF_VF_ATQLEN1_ATQVFE_MASK ) {
2014-05-22 06:32:07 +00:00
dev_info ( & adapter - > pdev - > dev , " ASQ VF Error detected \n " ) ;
2018-09-14 17:37:49 -07:00
val & = ~ IAVF_VF_ATQLEN1_ATQVFE_MASK ;
2014-05-22 06:32:07 +00:00
}
2018-09-14 17:37:49 -07:00
if ( val & IAVF_VF_ATQLEN1_ATQOVFL_MASK ) {
2014-05-22 06:32:07 +00:00
dev_info ( & adapter - > pdev - > dev , " ASQ Overflow Error detected \n " ) ;
2018-09-14 17:37:49 -07:00
val & = ~ IAVF_VF_ATQLEN1_ATQOVFL_MASK ;
2014-05-22 06:32:07 +00:00
}
2018-09-14 17:37:49 -07:00
if ( val & IAVF_VF_ATQLEN1_ATQCRIT_MASK ) {
2014-05-22 06:32:07 +00:00
dev_info ( & adapter - > pdev - > dev , " ASQ Critical Error detected \n " ) ;
2018-09-14 17:37:49 -07:00
val & = ~ IAVF_VF_ATQLEN1_ATQCRIT_MASK ;
2014-05-22 06:32:07 +00:00
}
if ( oldval ! = val )
2023-10-26 10:39:32 +02:00
wr32 ( hw , IAVF_VF_ATQLEN1 , val ) ;
2014-05-22 06:32:07 +00:00
2015-06-19 08:56:30 -07:00
freedom :
2014-12-09 08:53:07 +00:00
kfree ( event . msg_buf ) ;
2023-07-10 13:41:27 -07:00
unlock :
mutex_unlock ( & adapter - > crit_lock ) ;
2014-12-09 08:53:07 +00:00
out :
2013-12-21 06:12:45 +00:00
/* re-enable Admin queue interrupt cause */
2018-09-14 17:37:46 -07:00
iavf_misc_irq_enable ( adapter ) ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_free_all_tx_resources - Free Tx Resources for All Queues
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
*
* Free all transmit software resources
* */
2018-09-14 17:37:46 -07:00
void iavf_free_all_tx_resources ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
int i ;
2015-11-19 11:34:18 -08:00
if ( ! adapter - > tx_rings )
return ;
2014-10-25 03:24:34 +00:00
for ( i = 0 ; i < adapter - > num_active_queues ; i + + )
2015-10-26 19:44:40 -04:00
if ( adapter - > tx_rings [ i ] . desc )
2018-09-14 17:37:46 -07:00
iavf_free_tx_resources ( & adapter - > tx_rings [ i ] ) ;
2013-12-21 06:12:45 +00:00
}
/**
2018-09-14 17:37:46 -07:00
* iavf_setup_all_tx_resources - allocate all queues Tx resources
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
*
* If this function returns with an error , then it ' s possible one or
* more of the rings is populated ( while the rest are not ) . It is the
* callers duty to clean those orphaned rings .
*
* Return 0 on success , negative on failure
* */
2018-09-14 17:37:46 -07:00
static int iavf_setup_all_tx_resources ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
int i , err = 0 ;
2014-10-25 03:24:34 +00:00
for ( i = 0 ; i < adapter - > num_active_queues ; i + + ) {
2015-10-26 19:44:40 -04:00
adapter - > tx_rings [ i ] . count = adapter - > tx_desc_count ;
2018-09-14 17:37:46 -07:00
err = iavf_setup_tx_descriptors ( & adapter - > tx_rings [ i ] ) ;
2013-12-21 06:12:45 +00:00
if ( ! err )
continue ;
dev_err ( & adapter - > pdev - > dev ,
2015-08-26 15:14:17 -04:00
" Allocation for Tx Queue %u failed \n " , i ) ;
2013-12-21 06:12:45 +00:00
break ;
}
return err ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_setup_all_rx_resources - allocate all queues Rx resources
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
*
* If this function returns with an error , then it ' s possible one or
* more of the rings is populated ( while the rest are not ) . It is the
* callers duty to clean those orphaned rings .
*
* Return 0 on success , negative on failure
* */
2018-09-14 17:37:46 -07:00
static int iavf_setup_all_rx_resources ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
int i , err = 0 ;
2014-10-25 03:24:34 +00:00
for ( i = 0 ; i < adapter - > num_active_queues ; i + + ) {
2015-10-26 19:44:40 -04:00
adapter - > rx_rings [ i ] . count = adapter - > rx_desc_count ;
2018-09-14 17:37:46 -07:00
err = iavf_setup_rx_descriptors ( & adapter - > rx_rings [ i ] ) ;
2013-12-21 06:12:45 +00:00
if ( ! err )
continue ;
dev_err ( & adapter - > pdev - > dev ,
2015-08-26 15:14:17 -04:00
" Allocation for Rx Queue %u failed \n " , i ) ;
2013-12-21 06:12:45 +00:00
break ;
}
return err ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_free_all_rx_resources - Free Rx Resources for All Queues
2013-12-21 06:12:45 +00:00
* @ adapter : board private structure
*
* Free all receive software resources
* */
2018-09-14 17:37:46 -07:00
void iavf_free_all_rx_resources ( struct iavf_adapter * adapter )
2013-12-21 06:12:45 +00:00
{
int i ;
2015-11-19 11:34:18 -08:00
if ( ! adapter - > rx_rings )
return ;
2014-10-25 03:24:34 +00:00
for ( i = 0 ; i < adapter - > num_active_queues ; i + + )
2015-10-26 19:44:40 -04:00
if ( adapter - > rx_rings [ i ] . desc )
2018-09-14 17:37:46 -07:00
iavf_free_rx_resources ( & adapter - > rx_rings [ i ] ) ;
2013-12-21 06:12:45 +00:00
}
2018-01-23 08:51:01 -08:00
/**
2018-09-14 17:37:46 -07:00
* iavf_validate_tx_bandwidth - validate the max Tx bandwidth
2018-01-23 08:51:01 -08:00
* @ adapter : board private structure
* @ max_tx_rate : max Tx bw for a tc
* */
2018-09-14 17:37:46 -07:00
static int iavf_validate_tx_bandwidth ( struct iavf_adapter * adapter ,
u64 max_tx_rate )
2018-01-23 08:51:01 -08:00
{
int speed = 0 , ret = 0 ;
2020-06-05 10:09:43 -07:00
if ( ADV_LINK_SUPPORT ( adapter ) ) {
if ( adapter - > link_speed_mbps < U32_MAX ) {
speed = adapter - > link_speed_mbps ;
goto validate_bw ;
} else {
dev_err ( & adapter - > pdev - > dev , " Unknown link speed \n " ) ;
return - EINVAL ;
}
}
2018-01-23 08:51:01 -08:00
switch ( adapter - > link_speed ) {
2020-06-05 10:09:44 -07:00
case VIRTCHNL_LINK_SPEED_40GB :
2020-06-05 10:09:45 -07:00
speed = SPEED_40000 ;
2018-01-23 08:51:01 -08:00
break ;
2020-06-05 10:09:44 -07:00
case VIRTCHNL_LINK_SPEED_25GB :
2020-06-05 10:09:45 -07:00
speed = SPEED_25000 ;
2018-01-23 08:51:01 -08:00
break ;
2020-06-05 10:09:44 -07:00
case VIRTCHNL_LINK_SPEED_20GB :
2020-06-05 10:09:45 -07:00
speed = SPEED_20000 ;
2018-01-23 08:51:01 -08:00
break ;
2020-06-05 10:09:44 -07:00
case VIRTCHNL_LINK_SPEED_10GB :
2020-06-05 10:09:45 -07:00
speed = SPEED_10000 ;
break ;
case VIRTCHNL_LINK_SPEED_5GB :
speed = SPEED_5000 ;
break ;
case VIRTCHNL_LINK_SPEED_2_5GB :
speed = SPEED_2500 ;
2018-01-23 08:51:01 -08:00
break ;
2020-06-05 10:09:44 -07:00
case VIRTCHNL_LINK_SPEED_1GB :
2020-06-05 10:09:45 -07:00
speed = SPEED_1000 ;
2018-01-23 08:51:01 -08:00
break ;
2020-06-05 10:09:44 -07:00
case VIRTCHNL_LINK_SPEED_100MB :
2020-06-05 10:09:45 -07:00
speed = SPEED_100 ;
2018-01-23 08:51:01 -08:00
break ;
default :
break ;
}
2020-06-05 10:09:43 -07:00
validate_bw :
2018-01-23 08:51:01 -08:00
if ( max_tx_rate > speed ) {
dev_err ( & adapter - > pdev - > dev ,
" Invalid tx rate specified \n " ) ;
ret = - EINVAL ;
}
return ret ;
}
2018-01-23 08:50:57 -08:00
/**
2021-03-18 16:18:52 -07:00
* iavf_validate_ch_config - validate queue mapping info
2018-01-23 08:50:57 -08:00
* @ adapter : board private structure
* @ mqprio_qopt : queue parameters
*
* This function validates if the config provided by the user to
* configure queue channels is valid or not . Returns 0 on a valid
* config .
* */
2018-09-14 17:37:46 -07:00
static int iavf_validate_ch_config ( struct iavf_adapter * adapter ,
struct tc_mqprio_qopt_offload * mqprio_qopt )
2018-01-23 08:50:57 -08:00
{
2018-01-23 08:51:01 -08:00
u64 total_max_rate = 0 ;
2022-06-13 18:41:23 -04:00
u32 tx_rate_rem = 0 ;
2018-01-23 08:50:57 -08:00
int i , num_qps = 0 ;
2018-01-23 08:51:01 -08:00
u64 tx_rate = 0 ;
int ret = 0 ;
2018-01-23 08:50:57 -08:00
2018-09-14 17:37:46 -07:00
if ( mqprio_qopt - > qopt . num_tc > IAVF_MAX_TRAFFIC_CLASS | |
2018-01-23 08:50:57 -08:00
mqprio_qopt - > qopt . num_tc < 1 )
return - EINVAL ;
for ( i = 0 ; i < = mqprio_qopt - > qopt . num_tc - 1 ; i + + ) {
if ( ! mqprio_qopt - > qopt . count [ i ] | |
mqprio_qopt - > qopt . offset [ i ] ! = num_qps )
return - EINVAL ;
2018-01-23 08:51:01 -08:00
if ( mqprio_qopt - > min_rate [ i ] ) {
dev_err ( & adapter - > pdev - > dev ,
2022-06-13 18:41:23 -04:00
" Invalid min tx rate (greater than 0) specified for TC%d \n " ,
i ) ;
2018-01-23 08:51:01 -08:00
return - EINVAL ;
}
2022-06-13 18:41:23 -04:00
/* convert to Mbps */
2018-01-23 08:51:01 -08:00
tx_rate = div_u64 ( mqprio_qopt - > max_rate [ i ] ,
2018-09-14 17:37:46 -07:00
IAVF_MBPS_DIVISOR ) ;
2022-06-13 18:41:23 -04:00
if ( mqprio_qopt - > max_rate [ i ] & &
tx_rate < IAVF_MBPS_QUANTA ) {
dev_err ( & adapter - > pdev - > dev ,
" Invalid max tx rate for TC%d, minimum %dMbps \n " ,
i , IAVF_MBPS_QUANTA ) ;
return - EINVAL ;
}
( void ) div_u64_rem ( tx_rate , IAVF_MBPS_QUANTA , & tx_rate_rem ) ;
if ( tx_rate_rem ! = 0 ) {
dev_err ( & adapter - > pdev - > dev ,
" Invalid max tx rate for TC%d, not divisible by %d \n " ,
i , IAVF_MBPS_QUANTA ) ;
return - EINVAL ;
}
2018-01-23 08:51:01 -08:00
total_max_rate + = tx_rate ;
2018-01-23 08:50:57 -08:00
num_qps + = mqprio_qopt - > qopt . count [ i ] ;
}
2021-09-01 09:21:46 +02:00
if ( num_qps > adapter - > num_active_queues ) {
dev_err ( & adapter - > pdev - > dev ,
" Cannot support requested number of queues \n " ) ;
2018-01-23 08:50:57 -08:00
return - EINVAL ;
2021-09-01 09:21:46 +02:00
}
2018-01-23 08:50:57 -08:00
2018-09-14 17:37:46 -07:00
ret = iavf_validate_tx_bandwidth ( adapter , total_max_rate ) ;
2018-01-23 08:51:01 -08:00
return ret ;
2018-01-23 08:50:57 -08:00
}
2018-01-23 08:51:05 -08:00
/**
2020-09-25 15:24:37 -07:00
* iavf_del_all_cloud_filters - delete all cloud filters on the traffic classes
* @ adapter : board private structure
2018-01-23 08:51:05 -08:00
* */
2018-09-14 17:37:46 -07:00
static void iavf_del_all_cloud_filters ( struct iavf_adapter * adapter )
2018-01-23 08:51:05 -08:00
{
2018-09-14 17:37:46 -07:00
struct iavf_cloud_filter * cf , * cftmp ;
2018-01-23 08:51:05 -08:00
spin_lock_bh ( & adapter - > cloud_filter_list_lock ) ;
list_for_each_entry_safe ( cf , cftmp , & adapter - > cloud_filter_list ,
list ) {
list_del ( & cf - > list ) ;
kfree ( cf ) ;
adapter - > num_cloud_filters - - ;
}
spin_unlock_bh ( & adapter - > cloud_filter_list_lock ) ;
}
2024-04-23 11:27:19 -07:00
/**
* iavf_is_tc_config_same - Compare the mqprio TC config with the
* TC config already configured on this adapter .
* @ adapter : board private structure
* @ mqprio_qopt : TC config received from kernel .
*
* This function compares the TC config received from the kernel
* with the config already configured on the adapter .
*
* Return : True if configuration is same , false otherwise .
* */
static bool iavf_is_tc_config_same ( struct iavf_adapter * adapter ,
struct tc_mqprio_qopt * mqprio_qopt )
{
struct virtchnl_channel_info * ch = & adapter - > ch_config . ch_info [ 0 ] ;
int i ;
if ( adapter - > num_tc ! = mqprio_qopt - > num_tc )
return false ;
for ( i = 0 ; i < adapter - > num_tc ; i + + ) {
if ( ch [ i ] . count ! = mqprio_qopt - > count [ i ] | |
ch [ i ] . offset ! = mqprio_qopt - > offset [ i ] )
return false ;
}
return true ;
}
2018-01-23 08:50:57 -08:00
/**
2018-09-14 17:37:46 -07:00
* __iavf_setup_tc - configure multiple traffic classes
2018-01-23 08:50:57 -08:00
* @ netdev : network interface device structure
2020-09-25 15:24:37 -07:00
* @ type_data : tc offload data
2018-01-23 08:50:57 -08:00
*
* This function processes the config information provided by the
* user to configure traffic classes / queue channels and packages the
* information to request the PF to setup traffic classes .
*
* Returns 0 on success .
* */
2018-09-14 17:37:46 -07:00
static int __iavf_setup_tc ( struct net_device * netdev , void * type_data )
2018-01-23 08:50:57 -08:00
{
struct tc_mqprio_qopt_offload * mqprio_qopt = type_data ;
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2018-01-23 08:50:57 -08:00
struct virtchnl_vf_resource * vfres = adapter - > vf_res ;
u8 num_tc = 0 , total_qps = 0 ;
int ret = 0 , netdev_tc = 0 ;
2018-01-23 08:51:01 -08:00
u64 max_tx_rate ;
2018-01-23 08:50:57 -08:00
u16 mode ;
int i ;
num_tc = mqprio_qopt - > qopt . num_tc ;
mode = mqprio_qopt - > mode ;
/* delete queue_channel */
if ( ! mqprio_qopt - > qopt . hw ) {
2018-09-14 17:37:46 -07:00
if ( adapter - > ch_config . state = = __IAVF_TC_RUNNING ) {
2018-01-23 08:50:57 -08:00
/* reset the tc configuration */
netdev_reset_tc ( netdev ) ;
adapter - > num_tc = 0 ;
netif_tx_stop_all_queues ( netdev ) ;
netif_tx_disable ( netdev ) ;
2018-09-14 17:37:46 -07:00
iavf_del_all_cloud_filters ( adapter ) ;
adapter - > aq_required = IAVF_FLAG_AQ_DISABLE_CHANNELS ;
2022-06-15 15:36:29 +02:00
total_qps = adapter - > orig_num_active_queues ;
2018-01-23 08:50:57 -08:00
goto exit ;
} else {
return - EINVAL ;
}
}
/* add queue channel */
if ( mode = = TC_MQPRIO_MODE_CHANNEL ) {
if ( ! ( vfres - > vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ ) ) {
dev_err ( & adapter - > pdev - > dev , " ADq not supported \n " ) ;
return - EOPNOTSUPP ;
}
2018-09-14 17:37:46 -07:00
if ( adapter - > ch_config . state ! = __IAVF_TC_INVALID ) {
2018-01-23 08:50:57 -08:00
dev_err ( & adapter - > pdev - > dev , " TC configuration already exists \n " ) ;
return - EINVAL ;
}
2018-09-14 17:37:46 -07:00
ret = iavf_validate_ch_config ( adapter , mqprio_qopt ) ;
2018-01-23 08:50:57 -08:00
if ( ret )
return ret ;
/* Return if same TC config is requested */
2024-04-23 11:27:19 -07:00
if ( iavf_is_tc_config_same ( adapter , & mqprio_qopt - > qopt ) )
2018-01-23 08:50:57 -08:00
return 0 ;
adapter - > num_tc = num_tc ;
2018-09-14 17:37:46 -07:00
for ( i = 0 ; i < IAVF_MAX_TRAFFIC_CLASS ; i + + ) {
2018-01-23 08:50:57 -08:00
if ( i < num_tc ) {
adapter - > ch_config . ch_info [ i ] . count =
mqprio_qopt - > qopt . count [ i ] ;
adapter - > ch_config . ch_info [ i ] . offset =
mqprio_qopt - > qopt . offset [ i ] ;
total_qps + = mqprio_qopt - > qopt . count [ i ] ;
2018-01-23 08:51:01 -08:00
max_tx_rate = mqprio_qopt - > max_rate [ i ] ;
/* convert to Mbps */
max_tx_rate = div_u64 ( max_tx_rate ,
2018-09-14 17:37:46 -07:00
IAVF_MBPS_DIVISOR ) ;
2018-01-23 08:51:01 -08:00
adapter - > ch_config . ch_info [ i ] . max_tx_rate =
max_tx_rate ;
2018-01-23 08:50:57 -08:00
} else {
adapter - > ch_config . ch_info [ i ] . count = 1 ;
adapter - > ch_config . ch_info [ i ] . offset = 0 ;
}
}
2022-06-15 15:36:29 +02:00
/* Take snapshot of original config such as "num_active_queues"
* It is used later when delete ADQ flow is exercised , so that
* once delete ADQ flow completes , VF shall go back to its
* original queue configuration
*/
adapter - > orig_num_active_queues = adapter - > num_active_queues ;
/* Store queue info based on TC so that VF gets configured
* with correct number of queues when VF completes ADQ config
* flow
*/
2018-01-23 08:50:57 -08:00
adapter - > ch_config . total_qps = total_qps ;
2022-06-15 15:36:29 +02:00
2018-01-23 08:50:57 -08:00
netif_tx_stop_all_queues ( netdev ) ;
netif_tx_disable ( netdev ) ;
2018-09-14 17:37:46 -07:00
adapter - > aq_required | = IAVF_FLAG_AQ_ENABLE_CHANNELS ;
2018-01-23 08:50:57 -08:00
netdev_reset_tc ( netdev ) ;
/* Report the tc mapping up the stack */
netdev_set_num_tc ( adapter - > netdev , num_tc ) ;
2018-09-14 17:37:46 -07:00
for ( i = 0 ; i < IAVF_MAX_TRAFFIC_CLASS ; i + + ) {
2018-01-23 08:50:57 -08:00
u16 qcount = mqprio_qopt - > qopt . count [ i ] ;
u16 qoffset = mqprio_qopt - > qopt . offset [ i ] ;
if ( i < num_tc )
netdev_set_tc_queue ( netdev , netdev_tc + + , qcount ,
qoffset ) ;
}
}
exit :
2022-06-15 15:36:29 +02:00
if ( test_bit ( __IAVF_IN_REMOVE_TASK , & adapter - > crit_section ) )
return 0 ;
netif_set_real_num_rx_queues ( netdev , total_qps ) ;
netif_set_real_num_tx_queues ( netdev , total_qps ) ;
2018-01-23 08:50:57 -08:00
return ret ;
}
2018-01-23 08:51:05 -08:00
/**
2018-09-14 17:37:46 -07:00
* iavf_parse_cls_flower - Parse tc flower filters provided by kernel
2018-01-23 08:51:05 -08:00
* @ adapter : board private structure
2020-09-25 15:24:37 -07:00
* @ f : pointer to struct flow_cls_offload
2018-01-23 08:51:05 -08:00
* @ filter : pointer to cloud filter structure
*/
2018-09-14 17:37:46 -07:00
static int iavf_parse_cls_flower ( struct iavf_adapter * adapter ,
2019-07-09 22:55:49 +02:00
struct flow_cls_offload * f ,
2018-09-14 17:37:46 -07:00
struct iavf_cloud_filter * filter )
2018-01-23 08:51:05 -08:00
{
2019-07-09 22:55:49 +02:00
struct flow_rule * rule = flow_cls_offload_flow_rule ( f ) ;
2019-02-02 12:50:43 +01:00
struct flow_dissector * dissector = rule - > match . dissector ;
2018-01-23 08:51:05 -08:00
u16 n_proto_mask = 0 ;
u16 n_proto_key = 0 ;
u8 field_flags = 0 ;
u16 addr_type = 0 ;
u16 n_proto = 0 ;
int i = 0 ;
2018-02-19 10:23:30 +00:00
struct virtchnl_filter * vf = & filter - > f ;
2018-01-23 08:51:05 -08:00
2019-02-02 12:50:43 +01:00
if ( dissector - > used_keys &
2023-07-29 04:52:15 +05:30
~ ( BIT_ULL ( FLOW_DISSECTOR_KEY_CONTROL ) |
BIT_ULL ( FLOW_DISSECTOR_KEY_BASIC ) |
BIT_ULL ( FLOW_DISSECTOR_KEY_ETH_ADDRS ) |
BIT_ULL ( FLOW_DISSECTOR_KEY_VLAN ) |
BIT_ULL ( FLOW_DISSECTOR_KEY_IPV4_ADDRS ) |
BIT_ULL ( FLOW_DISSECTOR_KEY_IPV6_ADDRS ) |
BIT_ULL ( FLOW_DISSECTOR_KEY_PORTS ) |
BIT_ULL ( FLOW_DISSECTOR_KEY_ENC_KEYID ) ) ) {
dev_err ( & adapter - > pdev - > dev , " Unsupported key used: 0x%llx \n " ,
2019-02-02 12:50:43 +01:00
dissector - > used_keys ) ;
2018-01-23 08:51:05 -08:00
return - EOPNOTSUPP ;
}
2019-02-02 12:50:43 +01:00
if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_ENC_KEYID ) ) {
struct flow_match_enc_keyid match ;
2018-01-23 08:51:05 -08:00
2019-02-02 12:50:43 +01:00
flow_rule_match_enc_keyid ( rule , & match ) ;
if ( match . mask - > keyid ! = 0 )
2018-09-14 17:37:46 -07:00
field_flags | = IAVF_CLOUD_FIELD_TEN_ID ;
2018-01-23 08:51:05 -08:00
}
2019-02-02 12:50:43 +01:00
if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_BASIC ) ) {
struct flow_match_basic match ;
2018-01-23 08:51:05 -08:00
2019-02-02 12:50:43 +01:00
flow_rule_match_basic ( rule , & match ) ;
n_proto_key = ntohs ( match . key - > n_proto ) ;
n_proto_mask = ntohs ( match . mask - > n_proto ) ;
2018-01-23 08:51:05 -08:00
if ( n_proto_key = = ETH_P_ALL ) {
n_proto_key = 0 ;
n_proto_mask = 0 ;
}
n_proto = n_proto_key & n_proto_mask ;
if ( n_proto ! = ETH_P_IP & & n_proto ! = ETH_P_IPV6 )
return - EINVAL ;
if ( n_proto = = ETH_P_IPV6 ) {
/* specify flow type as TCP IPv6 */
2018-02-19 10:23:30 +00:00
vf - > flow_type = VIRTCHNL_TCP_V6_FLOW ;
2018-01-23 08:51:05 -08:00
}
2019-02-02 12:50:43 +01:00
if ( match . key - > ip_proto ! = IPPROTO_TCP ) {
2018-01-23 08:51:05 -08:00
dev_info ( & adapter - > pdev - > dev , " Only TCP transport is supported \n " ) ;
return - EINVAL ;
}
}
2019-02-02 12:50:43 +01:00
if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_ETH_ADDRS ) ) {
struct flow_match_eth_addrs match ;
flow_rule_match_eth_addrs ( rule , & match ) ;
2018-01-23 08:51:05 -08:00
/* use is_broadcast and is_zero to check for all 0xf or 0 */
2019-02-02 12:50:43 +01:00
if ( ! is_zero_ether_addr ( match . mask - > dst ) ) {
if ( is_broadcast_ether_addr ( match . mask - > dst ) ) {
2018-09-14 17:37:46 -07:00
field_flags | = IAVF_CLOUD_FIELD_OMAC ;
2018-01-23 08:51:05 -08:00
} else {
dev_err ( & adapter - > pdev - > dev , " Bad ether dest mask %pM \n " ,
2019-02-02 12:50:43 +01:00
match . mask - > dst ) ;
2021-06-04 09:53:34 -07:00
return - EINVAL ;
2018-01-23 08:51:05 -08:00
}
}
2019-02-02 12:50:43 +01:00
if ( ! is_zero_ether_addr ( match . mask - > src ) ) {
if ( is_broadcast_ether_addr ( match . mask - > src ) ) {
2018-09-14 17:37:46 -07:00
field_flags | = IAVF_CLOUD_FIELD_IMAC ;
2018-01-23 08:51:05 -08:00
} else {
dev_err ( & adapter - > pdev - > dev , " Bad ether src mask %pM \n " ,
2019-02-02 12:50:43 +01:00
match . mask - > src ) ;
2021-06-04 09:53:34 -07:00
return - EINVAL ;
2018-01-23 08:51:05 -08:00
}
}
2019-02-02 12:50:43 +01:00
if ( ! is_zero_ether_addr ( match . key - > dst ) )
if ( is_valid_ether_addr ( match . key - > dst ) | |
is_multicast_ether_addr ( match . key - > dst ) ) {
2018-01-23 08:51:05 -08:00
/* set the mask if a valid dst_mac address */
for ( i = 0 ; i < ETH_ALEN ; i + + )
2018-02-19 10:23:30 +00:00
vf - > mask . tcp_spec . dst_mac [ i ] | = 0xff ;
ether_addr_copy ( vf - > data . tcp_spec . dst_mac ,
2019-02-02 12:50:43 +01:00
match . key - > dst ) ;
2018-01-23 08:51:05 -08:00
}
2019-02-02 12:50:43 +01:00
if ( ! is_zero_ether_addr ( match . key - > src ) )
if ( is_valid_ether_addr ( match . key - > src ) | |
is_multicast_ether_addr ( match . key - > src ) ) {
2018-01-23 08:51:05 -08:00
/* set the mask if a valid dst_mac address */
for ( i = 0 ; i < ETH_ALEN ; i + + )
2018-02-19 10:23:30 +00:00
vf - > mask . tcp_spec . src_mac [ i ] | = 0xff ;
ether_addr_copy ( vf - > data . tcp_spec . src_mac ,
2019-02-02 12:50:43 +01:00
match . key - > src ) ;
2018-01-23 08:51:05 -08:00
}
}
2019-02-02 12:50:43 +01:00
if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_VLAN ) ) {
struct flow_match_vlan match ;
2018-01-23 08:51:05 -08:00
2019-02-02 12:50:43 +01:00
flow_rule_match_vlan ( rule , & match ) ;
if ( match . mask - > vlan_id ) {
if ( match . mask - > vlan_id = = VLAN_VID_MASK ) {
2018-09-14 17:37:46 -07:00
field_flags | = IAVF_CLOUD_FIELD_IVLAN ;
2018-01-23 08:51:05 -08:00
} else {
dev_err ( & adapter - > pdev - > dev , " Bad vlan mask %u \n " ,
2019-02-02 12:50:43 +01:00
match . mask - > vlan_id ) ;
2021-06-04 09:53:34 -07:00
return - EINVAL ;
2018-01-23 08:51:05 -08:00
}
}
2018-02-19 10:23:30 +00:00
vf - > mask . tcp_spec . vlan_id | = cpu_to_be16 ( 0xffff ) ;
2019-02-02 12:50:43 +01:00
vf - > data . tcp_spec . vlan_id = cpu_to_be16 ( match . key - > vlan_id ) ;
2018-01-23 08:51:05 -08:00
}
2019-02-02 12:50:43 +01:00
if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_CONTROL ) ) {
struct flow_match_control match ;
2018-01-23 08:51:05 -08:00
2019-02-02 12:50:43 +01:00
flow_rule_match_control ( rule , & match ) ;
addr_type = match . key - > addr_type ;
2024-04-16 14:43:25 +00:00
if ( flow_rule_has_control_flags ( match . mask - > flags ,
f - > common . extack ) )
return - EOPNOTSUPP ;
2018-01-23 08:51:05 -08:00
}
if ( addr_type = = FLOW_DISSECTOR_KEY_IPV4_ADDRS ) {
2019-02-02 12:50:43 +01:00
struct flow_match_ipv4_addrs match ;
flow_rule_match_ipv4_addrs ( rule , & match ) ;
if ( match . mask - > dst ) {
if ( match . mask - > dst = = cpu_to_be32 ( 0xffffffff ) ) {
2018-09-14 17:37:46 -07:00
field_flags | = IAVF_CLOUD_FIELD_IIP ;
2018-01-23 08:51:05 -08:00
} else {
dev_err ( & adapter - > pdev - > dev , " Bad ip dst mask 0x%08x \n " ,
2019-02-02 12:50:43 +01:00
be32_to_cpu ( match . mask - > dst ) ) ;
2021-06-04 09:53:34 -07:00
return - EINVAL ;
2018-01-23 08:51:05 -08:00
}
}
2019-02-02 12:50:43 +01:00
if ( match . mask - > src ) {
if ( match . mask - > src = = cpu_to_be32 ( 0xffffffff ) ) {
2018-09-14 17:37:46 -07:00
field_flags | = IAVF_CLOUD_FIELD_IIP ;
2018-01-23 08:51:05 -08:00
} else {
dev_err ( & adapter - > pdev - > dev , " Bad ip src mask 0x%08x \n " ,
2022-12-20 09:32:46 +03:00
be32_to_cpu ( match . mask - > src ) ) ;
2021-06-04 09:53:34 -07:00
return - EINVAL ;
2018-01-23 08:51:05 -08:00
}
}
2018-09-14 17:37:46 -07:00
if ( field_flags & IAVF_CLOUD_FIELD_TEN_ID ) {
2018-01-23 08:51:05 -08:00
dev_info ( & adapter - > pdev - > dev , " Tenant id not allowed for ip filter \n " ) ;
2021-06-04 09:53:34 -07:00
return - EINVAL ;
2018-01-23 08:51:05 -08:00
}
2019-02-02 12:50:43 +01:00
if ( match . key - > dst ) {
2018-02-19 10:23:30 +00:00
vf - > mask . tcp_spec . dst_ip [ 0 ] | = cpu_to_be32 ( 0xffffffff ) ;
2019-02-02 12:50:43 +01:00
vf - > data . tcp_spec . dst_ip [ 0 ] = match . key - > dst ;
2018-01-23 08:51:05 -08:00
}
2019-02-02 12:50:43 +01:00
if ( match . key - > src ) {
2018-02-19 10:23:30 +00:00
vf - > mask . tcp_spec . src_ip [ 0 ] | = cpu_to_be32 ( 0xffffffff ) ;
2019-02-02 12:50:43 +01:00
vf - > data . tcp_spec . src_ip [ 0 ] = match . key - > src ;
2018-01-23 08:51:05 -08:00
}
}
if ( addr_type = = FLOW_DISSECTOR_KEY_IPV6_ADDRS ) {
2019-02-02 12:50:43 +01:00
struct flow_match_ipv6_addrs match ;
flow_rule_match_ipv6_addrs ( rule , & match ) ;
2018-01-23 08:51:05 -08:00
/* validate mask, make sure it is not IPV6_ADDR_ANY */
2019-02-02 12:50:43 +01:00
if ( ipv6_addr_any ( & match . mask - > dst ) ) {
2018-01-23 08:51:05 -08:00
dev_err ( & adapter - > pdev - > dev , " Bad ipv6 dst mask 0x%02x \n " ,
IPV6_ADDR_ANY ) ;
2021-06-04 09:53:34 -07:00
return - EINVAL ;
2018-01-23 08:51:05 -08:00
}
/* src and dest IPv6 address should not be LOOPBACK
* ( 0 : 0 : 0 : 0 : 0 : 0 : 0 : 1 ) which can be represented as : : 1
*/
2019-02-02 12:50:43 +01:00
if ( ipv6_addr_loopback ( & match . key - > dst ) | |
ipv6_addr_loopback ( & match . key - > src ) ) {
2018-01-23 08:51:05 -08:00
dev_err ( & adapter - > pdev - > dev ,
" ipv6 addr should not be loopback \n " ) ;
2021-06-04 09:53:34 -07:00
return - EINVAL ;
2018-01-23 08:51:05 -08:00
}
2019-02-02 12:50:43 +01:00
if ( ! ipv6_addr_any ( & match . mask - > dst ) | |
! ipv6_addr_any ( & match . mask - > src ) )
2018-09-14 17:37:46 -07:00
field_flags | = IAVF_CLOUD_FIELD_IIP ;
2018-01-23 08:51:05 -08:00
2018-02-19 10:23:30 +00:00
for ( i = 0 ; i < 4 ; i + + )
vf - > mask . tcp_spec . dst_ip [ i ] | = cpu_to_be32 ( 0xffffffff ) ;
2019-02-02 12:50:43 +01:00
memcpy ( & vf - > data . tcp_spec . dst_ip , & match . key - > dst . s6_addr32 ,
2018-02-19 10:23:30 +00:00
sizeof ( vf - > data . tcp_spec . dst_ip ) ) ;
for ( i = 0 ; i < 4 ; i + + )
vf - > mask . tcp_spec . src_ip [ i ] | = cpu_to_be32 ( 0xffffffff ) ;
2019-02-02 12:50:43 +01:00
memcpy ( & vf - > data . tcp_spec . src_ip , & match . key - > src . s6_addr32 ,
2018-02-19 10:23:30 +00:00
sizeof ( vf - > data . tcp_spec . src_ip ) ) ;
2018-01-23 08:51:05 -08:00
}
2019-02-02 12:50:43 +01:00
if ( flow_rule_match_key ( rule , FLOW_DISSECTOR_KEY_PORTS ) ) {
struct flow_match_ports match ;
flow_rule_match_ports ( rule , & match ) ;
if ( match . mask - > src ) {
if ( match . mask - > src = = cpu_to_be16 ( 0xffff ) ) {
2018-09-14 17:37:46 -07:00
field_flags | = IAVF_CLOUD_FIELD_IIP ;
2018-01-23 08:51:05 -08:00
} else {
dev_err ( & adapter - > pdev - > dev , " Bad src port mask %u \n " ,
2019-02-02 12:50:43 +01:00
be16_to_cpu ( match . mask - > src ) ) ;
2021-06-04 09:53:34 -07:00
return - EINVAL ;
2018-01-23 08:51:05 -08:00
}
}
2019-02-02 12:50:43 +01:00
if ( match . mask - > dst ) {
if ( match . mask - > dst = = cpu_to_be16 ( 0xffff ) ) {
2018-09-14 17:37:46 -07:00
field_flags | = IAVF_CLOUD_FIELD_IIP ;
2018-01-23 08:51:05 -08:00
} else {
dev_err ( & adapter - > pdev - > dev , " Bad dst port mask %u \n " ,
2019-02-02 12:50:43 +01:00
be16_to_cpu ( match . mask - > dst ) ) ;
2021-06-04 09:53:34 -07:00
return - EINVAL ;
2018-01-23 08:51:05 -08:00
}
}
2019-02-02 12:50:43 +01:00
if ( match . key - > dst ) {
2018-02-19 10:23:30 +00:00
vf - > mask . tcp_spec . dst_port | = cpu_to_be16 ( 0xffff ) ;
2019-02-02 12:50:43 +01:00
vf - > data . tcp_spec . dst_port = match . key - > dst ;
2018-01-23 08:51:05 -08:00
}
2019-02-02 12:50:43 +01:00
if ( match . key - > src ) {
2018-02-19 10:23:30 +00:00
vf - > mask . tcp_spec . src_port | = cpu_to_be16 ( 0xffff ) ;
2019-02-02 12:50:43 +01:00
vf - > data . tcp_spec . src_port = match . key - > src ;
2018-01-23 08:51:05 -08:00
}
}
2018-02-19 10:23:30 +00:00
vf - > field_flags = field_flags ;
2018-01-23 08:51:05 -08:00
return 0 ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_handle_tclass - Forward to a traffic class on the device
2018-01-23 08:51:05 -08:00
* @ adapter : board private structure
* @ tc : traffic class index on the device
* @ filter : pointer to cloud filter structure
*/
2018-09-14 17:37:46 -07:00
static int iavf_handle_tclass ( struct iavf_adapter * adapter , u32 tc ,
struct iavf_cloud_filter * filter )
2018-01-23 08:51:05 -08:00
{
if ( tc = = 0 )
return 0 ;
if ( tc < adapter - > num_tc ) {
if ( ! filter - > f . data . tcp_spec . dst_port ) {
dev_err ( & adapter - > pdev - > dev ,
" Specify destination port to redirect to traffic class other than TC0 \n " ) ;
return - EINVAL ;
}
}
/* redirect to a traffic class on the same device */
filter - > f . action = VIRTCHNL_ACTION_TC_REDIRECT ;
filter - > f . action_meta = tc ;
return 0 ;
}
2022-06-21 14:39:33 -04:00
/**
* iavf_find_cf - Find the cloud filter in the list
* @ adapter : Board private structure
* @ cookie : filter specific cookie
*
* Returns ptr to the filter object or NULL . Must be called while holding the
* cloud_filter_list_lock .
*/
static struct iavf_cloud_filter * iavf_find_cf ( struct iavf_adapter * adapter ,
unsigned long * cookie )
{
struct iavf_cloud_filter * filter = NULL ;
if ( ! cookie )
return NULL ;
list_for_each_entry ( filter , & adapter - > cloud_filter_list , list ) {
if ( ! memcmp ( cookie , & filter - > cookie , sizeof ( filter - > cookie ) ) )
return filter ;
}
return NULL ;
}
2018-01-23 08:51:05 -08:00
/**
2018-09-14 17:37:46 -07:00
* iavf_configure_clsflower - Add tc flower filters
2018-01-23 08:51:05 -08:00
* @ adapter : board private structure
2019-07-09 22:55:49 +02:00
* @ cls_flower : Pointer to struct flow_cls_offload
2018-01-23 08:51:05 -08:00
*/
2018-09-14 17:37:46 -07:00
static int iavf_configure_clsflower ( struct iavf_adapter * adapter ,
2019-07-09 22:55:49 +02:00
struct flow_cls_offload * cls_flower )
2018-01-23 08:51:05 -08:00
{
int tc = tc_classid_to_hwtc ( adapter - > netdev , cls_flower - > classid ) ;
2018-09-14 17:37:46 -07:00
struct iavf_cloud_filter * filter = NULL ;
2018-03-19 09:28:03 -07:00
int err = - EINVAL , count = 50 ;
2018-01-23 08:51:05 -08:00
if ( tc < 0 ) {
dev_err ( & adapter - > pdev - > dev , " Invalid traffic class \n " ) ;
return - EINVAL ;
}
filter = kzalloc ( sizeof ( * filter ) , GFP_KERNEL ) ;
2018-03-19 09:28:03 -07:00
if ( ! filter )
return - ENOMEM ;
2021-08-04 10:22:24 +02:00
while ( ! mutex_trylock ( & adapter - > crit_lock ) ) {
2021-06-04 09:48:55 -07:00
if ( - - count = = 0 ) {
kfree ( filter ) ;
return err ;
}
2018-03-19 09:28:03 -07:00
udelay ( 1 ) ;
2018-01-23 08:51:05 -08:00
}
2018-03-19 09:28:03 -07:00
2018-01-23 08:51:05 -08:00
filter - > cookie = cls_flower - > cookie ;
2022-06-21 14:39:33 -04:00
/* bail out here if filter already exists */
spin_lock_bh ( & adapter - > cloud_filter_list_lock ) ;
if ( iavf_find_cf ( adapter , & cls_flower - > cookie ) ) {
dev_err ( & adapter - > pdev - > dev , " Failed to add TC Flower filter, it already exists \n " ) ;
err = - EEXIST ;
goto spin_unlock ;
}
spin_unlock_bh ( & adapter - > cloud_filter_list_lock ) ;
2018-01-23 08:51:05 -08:00
/* set the mask to all zeroes to begin with */
memset ( & filter - > f . mask . tcp_spec , 0 , sizeof ( struct virtchnl_l4_spec ) ) ;
/* start out with flow type and eth type IPv4 to begin with */
filter - > f . flow_type = VIRTCHNL_TCP_V4_FLOW ;
2018-09-14 17:37:46 -07:00
err = iavf_parse_cls_flower ( adapter , cls_flower , filter ) ;
2021-06-04 09:48:57 -07:00
if ( err )
2018-01-23 08:51:05 -08:00
goto err ;
2018-09-14 17:37:46 -07:00
err = iavf_handle_tclass ( adapter , tc , filter ) ;
2021-06-04 09:48:57 -07:00
if ( err )
2018-01-23 08:51:05 -08:00
goto err ;
/* add filter to the list */
spin_lock_bh ( & adapter - > cloud_filter_list_lock ) ;
list_add_tail ( & filter - > list , & adapter - > cloud_filter_list ) ;
adapter - > num_cloud_filters + + ;
filter - > add = true ;
2018-09-14 17:37:46 -07:00
adapter - > aq_required | = IAVF_FLAG_AQ_ADD_CLOUD_FILTER ;
2022-06-21 14:39:33 -04:00
spin_unlock :
2018-01-23 08:51:05 -08:00
spin_unlock_bh ( & adapter - > cloud_filter_list_lock ) ;
err :
if ( err )
kfree ( filter ) ;
2018-03-19 09:28:03 -07:00
2021-08-04 10:22:24 +02:00
mutex_unlock ( & adapter - > crit_lock ) ;
2018-01-23 08:51:05 -08:00
return err ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_delete_clsflower - Remove tc flower filters
2018-01-23 08:51:05 -08:00
* @ adapter : board private structure
2019-07-09 22:55:49 +02:00
* @ cls_flower : Pointer to struct flow_cls_offload
2018-01-23 08:51:05 -08:00
*/
2018-09-14 17:37:46 -07:00
static int iavf_delete_clsflower ( struct iavf_adapter * adapter ,
2019-07-09 22:55:49 +02:00
struct flow_cls_offload * cls_flower )
2018-01-23 08:51:05 -08:00
{
2018-09-14 17:37:46 -07:00
struct iavf_cloud_filter * filter = NULL ;
2018-01-23 08:51:05 -08:00
int err = 0 ;
spin_lock_bh ( & adapter - > cloud_filter_list_lock ) ;
2018-09-14 17:37:46 -07:00
filter = iavf_find_cf ( adapter , & cls_flower - > cookie ) ;
2018-01-23 08:51:05 -08:00
if ( filter ) {
filter - > del = true ;
2018-09-14 17:37:46 -07:00
adapter - > aq_required | = IAVF_FLAG_AQ_DEL_CLOUD_FILTER ;
2018-01-23 08:51:05 -08:00
} else {
err = - EINVAL ;
}
spin_unlock_bh ( & adapter - > cloud_filter_list_lock ) ;
return err ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_setup_tc_cls_flower - flower classifier offloads
2020-09-25 15:24:37 -07:00
* @ adapter : board private structure
* @ cls_flower : pointer to flow_cls_offload struct with flow info
2018-01-23 08:51:05 -08:00
*/
2018-09-14 17:37:46 -07:00
static int iavf_setup_tc_cls_flower ( struct iavf_adapter * adapter ,
2019-07-09 22:55:49 +02:00
struct flow_cls_offload * cls_flower )
2018-01-23 08:51:05 -08:00
{
switch ( cls_flower - > command ) {
2019-07-09 22:55:49 +02:00
case FLOW_CLS_REPLACE :
2018-09-14 17:37:46 -07:00
return iavf_configure_clsflower ( adapter , cls_flower ) ;
2019-07-09 22:55:49 +02:00
case FLOW_CLS_DESTROY :
2018-09-14 17:37:46 -07:00
return iavf_delete_clsflower ( adapter , cls_flower ) ;
2019-07-09 22:55:49 +02:00
case FLOW_CLS_STATS :
2018-01-23 08:51:05 -08:00
return - EOPNOTSUPP ;
default :
2018-06-24 10:38:39 +02:00
return - EOPNOTSUPP ;
2018-01-23 08:51:05 -08:00
}
}
/**
2018-09-14 17:37:46 -07:00
* iavf_setup_tc_block_cb - block callback for tc
2018-01-23 08:51:05 -08:00
* @ type : type of offload
* @ type_data : offload data
* @ cb_priv :
*
* This function is the block callback for traffic classes
* */
2018-09-14 17:37:46 -07:00
static int iavf_setup_tc_block_cb ( enum tc_setup_type type , void * type_data ,
void * cb_priv )
2018-01-23 08:51:05 -08:00
{
2020-02-26 09:21:57 +01:00
struct iavf_adapter * adapter = cb_priv ;
if ( ! tc_cls_can_offload_and_chain0 ( adapter - > netdev , type_data ) )
return - EOPNOTSUPP ;
2018-01-23 08:51:05 -08:00
switch ( type ) {
case TC_SETUP_CLSFLOWER :
2018-09-14 17:37:46 -07:00
return iavf_setup_tc_cls_flower ( cb_priv , type_data ) ;
2018-01-23 08:51:05 -08:00
default :
return - EOPNOTSUPP ;
}
}
2019-07-09 22:55:46 +02:00
static LIST_HEAD ( iavf_block_cb_list ) ;
2018-01-23 08:50:57 -08:00
/**
2018-09-14 17:37:46 -07:00
* iavf_setup_tc - configure multiple traffic classes
2018-01-23 08:50:57 -08:00
* @ netdev : network interface device structure
* @ type : type of offload
2020-09-25 15:24:37 -07:00
* @ type_data : tc offload data
2018-01-23 08:50:57 -08:00
*
* This function is the callback to ndo_setup_tc in the
* netdev_ops .
*
* Returns 0 on success
* */
2018-09-14 17:37:46 -07:00
static int iavf_setup_tc ( struct net_device * netdev , enum tc_setup_type type ,
void * type_data )
2018-01-23 08:50:57 -08:00
{
2019-07-09 22:55:39 +02:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2018-01-23 08:51:05 -08:00
switch ( type ) {
case TC_SETUP_QDISC_MQPRIO :
2018-09-14 17:37:46 -07:00
return __iavf_setup_tc ( netdev , type_data ) ;
2018-01-23 08:51:05 -08:00
case TC_SETUP_BLOCK :
2019-07-09 22:55:46 +02:00
return flow_block_cb_setup_simple ( type_data ,
& iavf_block_cb_list ,
2019-07-09 22:55:39 +02:00
iavf_setup_tc_block_cb ,
adapter , adapter , true ) ;
2018-01-23 08:51:05 -08:00
default :
2018-01-23 08:50:57 -08:00
return - EOPNOTSUPP ;
2018-01-23 08:51:05 -08:00
}
2018-01-23 08:50:57 -08:00
}
iavf: Introduce new state machines for flow director
New states introduced:
IAVF_FDIR_FLTR_DIS_REQUEST
IAVF_FDIR_FLTR_DIS_PENDING
IAVF_FDIR_FLTR_INACTIVE
Current FDIR state machines (SM) are not adequate to handle a few
scenarios in the link DOWN/UP event, reset event and ntuple-feature.
For example, when VF link goes DOWN and comes back UP administratively,
the expectation is that previously installed filters should also be
restored. But with current SM, filters are not restored.
So with new SM, during link DOWN filters are marked as INACTIVE in
the iavf list but removed from PF. After link UP, SM will transition
from INACTIVE to ADD_REQUEST to restore the filter.
Similarly, with VF reset, filters will be removed from the PF, but
marked as INACTIVE in the iavf list. Filters will be restored after
reset completion.
Steps to reproduce:
-------------------
1. Create a VF. Here VF is enp8s0.
2. Assign IP addresses to VF and link partner and ping continuously
from remote. Here remote IP is 1.1.1.1.
3. Check default RX Queue of traffic.
ethtool -S enp8s0 | grep -E "rx-[[:digit:]]+\.packets"
4. Add filter - change default RX Queue (to 15 here)
ethtool -U ens8s0 flow-type ip4 src-ip 1.1.1.1 action 15 loc 5
5. Ensure filter gets added and traffic is received on RX queue 15 now.
Link event testing:
-------------------
6. Bring VF link down and up. If traffic flows to configured queue 15,
test is success, otherwise it is a failure.
Reset event testing:
--------------------
7. Reset the VF. If traffic flows to configured queue 15, test is success,
otherwise it is a failure.
Fixes: 0dbfbabb840d ("iavf: Add framework to enable ethtool ntuple filters")
Signed-off-by: Piotr Gardocki <piotrx.gardocki@intel.com>
Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
Signed-off-by: Ranganatha Rao <ranganatha.rao@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-11-21 22:47:15 -05:00
/**
* iavf_restore_fdir_filters
* @ adapter : board private structure
*
* Restore existing FDIR filters when VF netdev comes back up .
* */
static void iavf_restore_fdir_filters ( struct iavf_adapter * adapter )
{
struct iavf_fdir_fltr * f ;
spin_lock_bh ( & adapter - > fdir_fltr_lock ) ;
list_for_each_entry ( f , & adapter - > fdir_list_head , list ) {
if ( f - > state = = IAVF_FDIR_FLTR_DIS_REQUEST ) {
/* Cancel a request, keep filter as active */
f - > state = IAVF_FDIR_FLTR_ACTIVE ;
} else if ( f - > state = = IAVF_FDIR_FLTR_DIS_PENDING | |
f - > state = = IAVF_FDIR_FLTR_INACTIVE ) {
/* Add filters which are inactive or have a pending
* request to PF to be deleted
*/
f - > state = IAVF_FDIR_FLTR_ADD_REQUEST ;
adapter - > aq_required | = IAVF_FLAG_AQ_ADD_FDIR_FILTER ;
}
}
spin_unlock_bh ( & adapter - > fdir_fltr_lock ) ;
}
2013-12-21 06:12:45 +00:00
/**
2018-09-14 17:37:46 -07:00
* iavf_open - Called when a network interface is made active
2013-12-21 06:12:45 +00:00
* @ netdev : network interface device structure
*
* Returns 0 on success , negative value on failure
*
* 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
2019-05-14 10:37:05 -07:00
* handler is registered with the OS , the watchdog is started ,
2013-12-21 06:12:45 +00:00
* and the stack is notified that the interface is ready .
* */
2018-09-14 17:37:46 -07:00
static int iavf_open ( struct net_device * netdev )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2013-12-21 06:12:45 +00:00
int err ;
2018-09-14 17:37:46 -07:00
if ( adapter - > flags & IAVF_FLAG_PF_COMMS_FAILED ) {
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
dev_err ( & adapter - > pdev - > dev , " Unable to open device due to PF driver failure. \n " ) ;
return - EIO ;
}
2015-12-09 15:50:27 -08:00
2022-08-08 19:58:45 +02:00
while ( ! mutex_trylock ( & adapter - > crit_lock ) ) {
/* If we are in __IAVF_INIT_CONFIG_ADAPTER state the crit_lock
* is already taken and iavf_open is called from an upper
* device ' s notifier reacting on NETDEV_REGISTER event .
* We have to leave here to avoid dead lock .
*/
if ( adapter - > state = = __IAVF_INIT_CONFIG_ADAPTER )
return - EBUSY ;
2017-10-27 11:06:52 -04:00
usleep_range ( 500 , 1000 ) ;
2022-08-08 19:58:45 +02:00
}
2017-10-27 11:06:52 -04:00
2018-09-14 17:37:46 -07:00
if ( adapter - > state ! = __IAVF_DOWN ) {
2017-10-27 11:06:52 -04:00
err = - EBUSY ;
goto err_unlock ;
}
2013-12-21 06:12:45 +00:00
iavf: Fix kernel BUG in free_msi_irqs
Fix driver not freeing VF's traffic irqs, prior to calling
pci_disable_msix in iavf_remove.
There were possible 2 erroneous states in which, iavf_close would
not be called.
One erroneous state is fixed by allowing netdev to register, when state
is already running. It was possible for VF adapter to enter state loop
from running to resetting, where iavf_open would subsequently fail.
If user would then unload driver/remove VF pci, iavf_close would not be
called, as the netdev was not registered, leaving traffic pcis still
allocated.
Fixed this by breaking loop, allowing netdev to open device when adapter
state is __IAVF_RUNNING and it is not explicitily downed.
Other possiblity is entering to iavf_remove from __IAVF_RESETTING state,
where iavf_close would not free irqs, but just return 0.
Fixed this by checking for last adapter state and then removing irqs.
Kernel panic:
[ 2773.628585] kernel BUG at drivers/pci/msi.c:375!
...
[ 2773.631567] RIP: 0010:free_msi_irqs+0x180/0x1b0
...
[ 2773.640939] Call Trace:
[ 2773.641572] pci_disable_msix+0xf7/0x120
[ 2773.642224] iavf_reset_interrupt_capability.part.41+0x15/0x30 [iavf]
[ 2773.642897] iavf_remove+0x12e/0x500 [iavf]
[ 2773.643578] pci_device_remove+0x3b/0xc0
[ 2773.644266] device_release_driver_internal+0x103/0x1f0
[ 2773.644948] pci_stop_bus_device+0x69/0x90
[ 2773.645576] pci_stop_and_remove_bus_device+0xe/0x20
[ 2773.646215] pci_iov_remove_virtfn+0xba/0x120
[ 2773.646862] sriov_disable+0x2f/0xe0
[ 2773.647531] ice_free_vfs+0x2f8/0x350 [ice]
[ 2773.648207] ice_sriov_configure+0x94/0x960 [ice]
[ 2773.648883] ? _kstrtoull+0x3b/0x90
[ 2773.649560] sriov_numvfs_store+0x10a/0x190
[ 2773.650249] kernfs_fop_write+0x116/0x190
[ 2773.650948] vfs_write+0xa5/0x1a0
[ 2773.651651] ksys_write+0x4f/0xb0
[ 2773.652358] do_syscall_64+0x5b/0x1a0
[ 2773.653075] entry_SYSCALL_64_after_hwframe+0x65/0xca
Fixes: 22ead37f8af8 ("i40evf: Add longer wait after remove module")
Signed-off-by: Przemyslaw Patynowski <przemyslawx.patynowski@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-10-22 10:30:14 +02:00
if ( adapter - > state = = __IAVF_RUNNING & &
! test_bit ( __IAVF_VSI_DOWN , adapter - > vsi . state ) ) {
dev_dbg ( & adapter - > pdev - > dev , " VF is already open. \n " ) ;
err = 0 ;
goto err_unlock ;
}
2013-12-21 06:12:45 +00:00
/* allocate transmit descriptors */
2018-09-14 17:37:46 -07:00
err = iavf_setup_all_tx_resources ( adapter ) ;
2013-12-21 06:12:45 +00:00
if ( err )
goto err_setup_tx ;
/* allocate receive descriptors */
2018-09-14 17:37:46 -07:00
err = iavf_setup_all_rx_resources ( adapter ) ;
2013-12-21 06:12:45 +00:00
if ( err )
goto err_setup_rx ;
/* clear any pending interrupts, may auto mask */
2018-09-14 17:37:46 -07:00
err = iavf_request_traffic_irqs ( adapter , netdev - > name ) ;
2013-12-21 06:12:45 +00:00
if ( err )
goto err_req_irq ;
2018-02-05 13:03:36 -08:00
spin_lock_bh ( & adapter - > mac_vlan_list_lock ) ;
2018-09-14 17:37:46 -07:00
iavf_add_filter ( adapter , adapter - > hw . mac . addr ) ;
2018-02-05 13:03:36 -08:00
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
iavf: Introduce new state machines for flow director
New states introduced:
IAVF_FDIR_FLTR_DIS_REQUEST
IAVF_FDIR_FLTR_DIS_PENDING
IAVF_FDIR_FLTR_INACTIVE
Current FDIR state machines (SM) are not adequate to handle a few
scenarios in the link DOWN/UP event, reset event and ntuple-feature.
For example, when VF link goes DOWN and comes back UP administratively,
the expectation is that previously installed filters should also be
restored. But with current SM, filters are not restored.
So with new SM, during link DOWN filters are marked as INACTIVE in
the iavf list but removed from PF. After link UP, SM will transition
from INACTIVE to ADD_REQUEST to restore the filter.
Similarly, with VF reset, filters will be removed from the PF, but
marked as INACTIVE in the iavf list. Filters will be restored after
reset completion.
Steps to reproduce:
-------------------
1. Create a VF. Here VF is enp8s0.
2. Assign IP addresses to VF and link partner and ping continuously
from remote. Here remote IP is 1.1.1.1.
3. Check default RX Queue of traffic.
ethtool -S enp8s0 | grep -E "rx-[[:digit:]]+\.packets"
4. Add filter - change default RX Queue (to 15 here)
ethtool -U ens8s0 flow-type ip4 src-ip 1.1.1.1 action 15 loc 5
5. Ensure filter gets added and traffic is received on RX queue 15 now.
Link event testing:
-------------------
6. Bring VF link down and up. If traffic flows to configured queue 15,
test is success, otherwise it is a failure.
Reset event testing:
--------------------
7. Reset the VF. If traffic flows to configured queue 15, test is success,
otherwise it is a failure.
Fixes: 0dbfbabb840d ("iavf: Add framework to enable ethtool ntuple filters")
Signed-off-by: Piotr Gardocki <piotrx.gardocki@intel.com>
Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
Signed-off-by: Ranganatha Rao <ranganatha.rao@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-11-21 22:47:15 -05:00
/* Restore filters that were removed with IFF_DOWN */
2021-06-04 09:53:27 -07:00
iavf_restore_filters ( adapter ) ;
iavf: Introduce new state machines for flow director
New states introduced:
IAVF_FDIR_FLTR_DIS_REQUEST
IAVF_FDIR_FLTR_DIS_PENDING
IAVF_FDIR_FLTR_INACTIVE
Current FDIR state machines (SM) are not adequate to handle a few
scenarios in the link DOWN/UP event, reset event and ntuple-feature.
For example, when VF link goes DOWN and comes back UP administratively,
the expectation is that previously installed filters should also be
restored. But with current SM, filters are not restored.
So with new SM, during link DOWN filters are marked as INACTIVE in
the iavf list but removed from PF. After link UP, SM will transition
from INACTIVE to ADD_REQUEST to restore the filter.
Similarly, with VF reset, filters will be removed from the PF, but
marked as INACTIVE in the iavf list. Filters will be restored after
reset completion.
Steps to reproduce:
-------------------
1. Create a VF. Here VF is enp8s0.
2. Assign IP addresses to VF and link partner and ping continuously
from remote. Here remote IP is 1.1.1.1.
3. Check default RX Queue of traffic.
ethtool -S enp8s0 | grep -E "rx-[[:digit:]]+\.packets"
4. Add filter - change default RX Queue (to 15 here)
ethtool -U ens8s0 flow-type ip4 src-ip 1.1.1.1 action 15 loc 5
5. Ensure filter gets added and traffic is received on RX queue 15 now.
Link event testing:
-------------------
6. Bring VF link down and up. If traffic flows to configured queue 15,
test is success, otherwise it is a failure.
Reset event testing:
--------------------
7. Reset the VF. If traffic flows to configured queue 15, test is success,
otherwise it is a failure.
Fixes: 0dbfbabb840d ("iavf: Add framework to enable ethtool ntuple filters")
Signed-off-by: Piotr Gardocki <piotrx.gardocki@intel.com>
Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
Signed-off-by: Ranganatha Rao <ranganatha.rao@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-11-21 22:47:15 -05:00
iavf_restore_fdir_filters ( adapter ) ;
2021-06-04 09:53:27 -07:00
2018-09-14 17:37:46 -07:00
iavf_configure ( adapter ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
iavf_up_complete ( adapter ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
iavf_irq_enable ( adapter , true ) ;
2013-12-21 06:12:45 +00:00
2021-08-04 10:22:24 +02:00
mutex_unlock ( & adapter - > crit_lock ) ;
2017-10-27 11:06:52 -04:00
2013-12-21 06:12:45 +00:00
return 0 ;
err_req_irq :
2018-09-14 17:37:46 -07:00
iavf_down ( adapter ) ;
iavf_free_traffic_irqs ( adapter ) ;
2013-12-21 06:12:45 +00:00
err_setup_rx :
2018-09-14 17:37:46 -07:00
iavf_free_all_rx_resources ( adapter ) ;
2013-12-21 06:12:45 +00:00
err_setup_tx :
2018-09-14 17:37:46 -07:00
iavf_free_all_tx_resources ( adapter ) ;
2017-10-27 11:06:52 -04:00
err_unlock :
2021-08-04 10:22:24 +02:00
mutex_unlock ( & adapter - > crit_lock ) ;
2013-12-21 06:12:45 +00:00
return err ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_close - Disables a network interface
2013-12-21 06:12:45 +00:00
* @ netdev : network interface device structure
*
* Returns 0 , this is not allowed to fail
*
* The close entry point is called when an interface is de - activated
* by the OS . The hardware is still under the drivers control , but
* needs to be disabled . All IRQs except vector 0 ( reserved for admin queue )
* are freed , along with all transmit and receive resources .
* */
2018-09-14 17:37:46 -07:00
static int iavf_close ( struct net_device * netdev )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2022-08-18 13:32:33 +02:00
u64 aq_to_restore ;
2017-06-23 04:24:44 -04:00
int status ;
2013-12-21 06:12:45 +00:00
2022-02-23 13:35:49 +01:00
mutex_lock ( & adapter - > crit_lock ) ;
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
2022-02-23 13:35:49 +01:00
if ( adapter - > state < = __IAVF_DOWN_PENDING ) {
mutex_unlock ( & adapter - > crit_lock ) ;
return 0 ;
}
i40evf: refactor reset handling
Respond better to a VF reset event. When a reset is signaled by the
PF, or detected by the watchdog task, prevent the watchdog from
processing admin queue requests, and schedule the reset task.
In the reset task, wait first for the reset to start, then for it to
complete, then reinit the driver.
If the reset never appears to complete after a long, long time (>10
seconds is possible depending on what's going on with the PF driver),
then set a flag to indicate that PF communications have failed.
If this flag is set, check for the reset to complete in the watchdog,
and attempt to do a full reinitialization of the driver from scratch.
With these changes the VF driver correctly handles a PF reset event
while running on bare metal, or in a VM.
Also update copyrights.
Change-ID: I93513efd0b50523a8345e7f6a33a5e4f8a2a5996
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2014-02-13 03:48:53 -08:00
2018-09-14 17:37:55 -07:00
set_bit ( __IAVF_VSI_DOWN , adapter - > vsi . state ) ;
2022-08-18 13:32:33 +02:00
/* We cannot send IAVF_FLAG_AQ_GET_OFFLOAD_VLAN_V2_CAPS before
* IAVF_FLAG_AQ_DISABLE_QUEUES because in such case there is rtnl
* deadlock with adminq_task ( ) until iavf_close timeouts . We must send
* IAVF_FLAG_AQ_GET_CONFIG before IAVF_FLAG_AQ_DISABLE_QUEUES to make
* disable queues possible for vf . Give only necessary flags to
* iavf_down and save other to set them right before iavf_close ( )
* returns , when IAVF_FLAG_AQ_DISABLE_QUEUES will be already sent and
* iavf will be in DOWN state .
*/
aq_to_restore = adapter - > aq_required ;
adapter - > aq_required & = IAVF_FLAG_AQ_GET_CONFIG ;
/* Remove flags which we do not want to send after close or we want to
* send before disable queues .
*/
aq_to_restore & = ~ ( IAVF_FLAG_AQ_GET_CONFIG |
IAVF_FLAG_AQ_ENABLE_QUEUES |
IAVF_FLAG_AQ_CONFIGURE_QUEUES |
IAVF_FLAG_AQ_ADD_VLAN_FILTER |
IAVF_FLAG_AQ_ADD_MAC_FILTER |
IAVF_FLAG_AQ_ADD_CLOUD_FILTER |
IAVF_FLAG_AQ_ADD_FDIR_FILTER |
IAVF_FLAG_AQ_ADD_ADV_RSS_CFG ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
iavf_down ( adapter ) ;
2021-08-19 08:47:40 +00:00
iavf_change_state ( adapter , __IAVF_DOWN_PENDING ) ;
2018-09-14 17:37:46 -07:00
iavf_free_traffic_irqs ( adapter ) ;
2013-12-21 06:12:45 +00:00
2021-08-04 10:22:24 +02:00
mutex_unlock ( & adapter - > crit_lock ) ;
2017-10-27 11:06:52 -04:00
2016-12-12 15:44:11 -08:00
/* We explicitly don't free resources here because the hardware is
* still active and can DMA into memory . Resources are cleared in
2018-09-14 17:37:46 -07:00
* iavf_virtchnl_completion ( ) after we get confirmation from the PF
2016-12-12 15:44:11 -08:00
* driver that the rings have been stopped .
2017-06-23 04:24:44 -04:00
*
2018-09-14 17:37:46 -07:00
* Also , we wait for state to transition to __IAVF_DOWN before
* returning . State change occurs in iavf_virtchnl_completion ( ) after
2017-06-23 04:24:44 -04:00
* VF resources are released ( which occurs after PF driver processes and
* responds to admin queue commands ) .
2016-12-12 15:44:11 -08:00
*/
2017-06-23 04:24:44 -04:00
status = wait_event_timeout ( adapter - > down_waitqueue ,
2018-09-14 17:37:46 -07:00
adapter - > state = = __IAVF_DOWN ,
2019-05-14 10:37:01 -07:00
msecs_to_jiffies ( 500 ) ) ;
2017-06-23 04:24:44 -04:00
if ( ! status )
netdev_warn ( netdev , " Device resources not yet released \n " ) ;
2022-08-18 13:32:33 +02:00
mutex_lock ( & adapter - > crit_lock ) ;
adapter - > aq_required | = aq_to_restore ;
mutex_unlock ( & adapter - > crit_lock ) ;
2013-12-21 06:12:45 +00:00
return 0 ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_change_mtu - Change the Maximum Transfer Unit
2013-12-21 06:12:45 +00:00
* @ netdev : network interface device structure
* @ new_mtu : new value for maximum frame size
*
* Returns 0 on success , negative on failure
* */
2018-09-14 17:37:46 -07:00
static int iavf_change_mtu ( struct net_device * netdev , int new_mtu )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2023-06-05 10:52:22 -04:00
int ret = 0 ;
2013-12-21 06:12:45 +00:00
2021-06-04 09:53:30 -07:00
netdev_dbg ( netdev , " changing MTU from %d to %d \n " ,
netdev - > mtu , new_mtu ) ;
2024-05-06 10:28:12 +00:00
WRITE_ONCE ( netdev - > mtu , new_mtu ) ;
2022-02-23 13:38:43 +01:00
if ( netif_running ( netdev ) ) {
2023-06-05 10:52:26 -04:00
iavf_schedule_reset ( adapter , IAVF_FLAG_RESET_NEEDED ) ;
2023-06-05 10:52:22 -04:00
ret = iavf_wait_for_reset ( adapter ) ;
if ( ret < 0 )
netdev_warn ( netdev , " MTU change interrupted waiting for reset " ) ;
else if ( ret )
netdev_warn ( netdev , " MTU change timed out waiting for reset " ) ;
2022-02-23 13:38:43 +01:00
}
2015-06-19 08:56:30 -07:00
2023-06-05 10:52:22 -04:00
return ret ;
2013-12-21 06:12:45 +00:00
}
2023-11-21 22:47:16 -05:00
/**
* iavf_disable_fdir - disable Flow Director and clear existing filters
* @ adapter : board private structure
* */
static void iavf_disable_fdir ( struct iavf_adapter * adapter )
{
struct iavf_fdir_fltr * fdir , * fdirtmp ;
bool del_filters = false ;
adapter - > flags & = ~ IAVF_FLAG_FDIR_ENABLED ;
/* remove all Flow Director filters */
spin_lock_bh ( & adapter - > fdir_fltr_lock ) ;
list_for_each_entry_safe ( fdir , fdirtmp , & adapter - > fdir_list_head ,
list ) {
if ( fdir - > state = = IAVF_FDIR_FLTR_ADD_REQUEST | |
fdir - > state = = IAVF_FDIR_FLTR_INACTIVE ) {
/* Delete filters not registered in PF */
list_del ( & fdir - > list ) ;
kfree ( fdir ) ;
adapter - > fdir_active_fltr - - ;
} else if ( fdir - > state = = IAVF_FDIR_FLTR_ADD_PENDING | |
fdir - > state = = IAVF_FDIR_FLTR_DIS_REQUEST | |
fdir - > state = = IAVF_FDIR_FLTR_ACTIVE ) {
/* Filters registered in PF, schedule their deletion */
fdir - > state = IAVF_FDIR_FLTR_DEL_REQUEST ;
del_filters = true ;
} else if ( fdir - > state = = IAVF_FDIR_FLTR_DIS_PENDING ) {
/* Request to delete filter already sent to PF, change
* state to DEL_PENDING to delete filter after PF ' s
* response , not set as INACTIVE
*/
fdir - > state = IAVF_FDIR_FLTR_DEL_PENDING ;
}
}
spin_unlock_bh ( & adapter - > fdir_fltr_lock ) ;
if ( del_filters ) {
adapter - > aq_required | = IAVF_FLAG_AQ_DEL_FDIR_FILTER ;
mod_delayed_work ( adapter - > wq , & adapter - > watchdog_task , 0 ) ;
}
}
2021-11-29 16:16:03 -08:00
# define NETIF_VLAN_OFFLOAD_FEATURES (NETIF_F_HW_VLAN_CTAG_RX | \
NETIF_F_HW_VLAN_CTAG_TX | \
NETIF_F_HW_VLAN_STAG_RX | \
NETIF_F_HW_VLAN_STAG_TX )
2017-07-17 22:09:45 -07:00
/**
2018-09-14 17:37:55 -07:00
* iavf_set_features - set the netdev feature flags
2017-07-17 22:09:45 -07:00
* @ netdev : ptr to the netdev being adjusted
* @ features : the feature set that the stack is suggesting
* Note : expects to be called while under rtnl_lock ( )
* */
2018-09-14 17:37:46 -07:00
static int iavf_set_features ( struct net_device * netdev ,
netdev_features_t features )
2017-07-17 22:09:45 -07:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2017-07-17 22:09:45 -07:00
2021-11-29 16:16:03 -08:00
/* trigger update on any VLAN feature change */
if ( ( netdev - > features & NETIF_VLAN_OFFLOAD_FEATURES ) ^
( features & NETIF_VLAN_OFFLOAD_FEATURES ) )
iavf_set_vlan_offload_features ( adapter , netdev - > features ,
features ) ;
2023-09-06 13:57:04 -06:00
if ( CRC_OFFLOAD_ALLOWED ( adapter ) & &
( ( netdev - > features & NETIF_F_RXFCS ) ^ ( features & NETIF_F_RXFCS ) ) )
iavf_schedule_reset ( adapter , IAVF_FLAG_RESET_NEEDED ) ;
2017-07-17 22:09:45 -07:00
2023-11-21 22:47:16 -05:00
if ( ( netdev - > features & NETIF_F_NTUPLE ) ^ ( features & NETIF_F_NTUPLE ) ) {
if ( features & NETIF_F_NTUPLE )
adapter - > flags | = IAVF_FLAG_FDIR_ENABLED ;
else
iavf_disable_fdir ( adapter ) ;
}
2017-07-17 22:09:45 -07:00
return 0 ;
}
2016-10-25 16:08:47 -07:00
/**
2018-09-14 17:37:46 -07:00
* iavf_features_check - Validate encapsulated packet conforms to limits
2016-10-25 16:08:47 -07:00
* @ skb : skb buff
2018-04-20 01:41:33 -07:00
* @ dev : This physical port ' s netdev
2016-10-25 16:08:47 -07:00
* @ features : Offload features that the stack believes apply
* */
2018-09-14 17:37:46 -07:00
static netdev_features_t iavf_features_check ( struct sk_buff * skb ,
struct net_device * dev ,
netdev_features_t features )
2016-10-25 16:08:47 -07:00
{
size_t len ;
/* No point in doing any of this if neither checksum nor GSO are
* being requested for this frame . We can rule out both by just
* checking for CHECKSUM_PARTIAL
*/
if ( skb - > ip_summed ! = CHECKSUM_PARTIAL )
return features ;
/* We cannot support GSO if the MSS is going to be less than
* 64 bytes . If it is then we need to drop support for GSO .
*/
if ( skb_is_gso ( skb ) & & ( skb_shinfo ( skb ) - > gso_size < 64 ) )
features & = ~ NETIF_F_GSO_MASK ;
/* MACLEN can support at most 63 words */
2024-02-29 09:39:07 +00:00
len = skb_network_offset ( skb ) ;
2016-10-25 16:08:47 -07:00
if ( len & ~ ( 63 * 2 ) )
goto out_err ;
/* IPLEN and EIPLEN can support at most 127 dwords */
2024-02-29 09:39:08 +00:00
len = skb_network_header_len ( skb ) ;
2016-10-25 16:08:47 -07:00
if ( len & ~ ( 127 * 4 ) )
goto out_err ;
if ( skb - > encapsulation ) {
/* L4TUNLEN can support 127 words */
len = skb_inner_network_header ( skb ) - skb_transport_header ( skb ) ;
if ( len & ~ ( 127 * 2 ) )
goto out_err ;
/* IPLEN can support at most 127 dwords */
len = skb_inner_transport_header ( skb ) -
skb_inner_network_header ( skb ) ;
if ( len & ~ ( 127 * 4 ) )
goto out_err ;
}
/* No need to validate L4LEN as TCP is the only protocol with a
2022-06-29 22:03:52 +08:00
* flexible value and we support all possible values supported
2016-10-25 16:08:47 -07:00
* by TCP , which is at most 15 dwords
*/
return features ;
out_err :
return features & ~ ( NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK ) ;
}
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
/**
* iavf_get_netdev_vlan_hw_features - get NETDEV VLAN features that can toggle on / off
* @ adapter : board private structure
*
* Depending on whether VIRTHCNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2
* were negotiated determine the VLAN features that can be toggled on and off .
* */
static netdev_features_t
iavf_get_netdev_vlan_hw_features ( struct iavf_adapter * adapter )
{
netdev_features_t hw_features = 0 ;
if ( ! adapter - > vf_res | | ! adapter - > vf_res - > vf_cap_flags )
return hw_features ;
/* Enable VLAN features if supported */
if ( VLAN_ALLOWED ( adapter ) ) {
hw_features | = ( NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX ) ;
} else if ( VLAN_V2_ALLOWED ( adapter ) ) {
struct virtchnl_vlan_caps * vlan_v2_caps =
& adapter - > vlan_v2_caps ;
struct virtchnl_vlan_supported_caps * stripping_support =
& vlan_v2_caps - > offloads . stripping_support ;
struct virtchnl_vlan_supported_caps * insertion_support =
& vlan_v2_caps - > offloads . insertion_support ;
if ( stripping_support - > outer ! = VIRTCHNL_VLAN_UNSUPPORTED & &
stripping_support - > outer & VIRTCHNL_VLAN_TOGGLE ) {
if ( stripping_support - > outer &
VIRTCHNL_VLAN_ETHERTYPE_8100 )
hw_features | = NETIF_F_HW_VLAN_CTAG_RX ;
if ( stripping_support - > outer &
VIRTCHNL_VLAN_ETHERTYPE_88A8 )
hw_features | = NETIF_F_HW_VLAN_STAG_RX ;
} else if ( stripping_support - > inner ! =
VIRTCHNL_VLAN_UNSUPPORTED & &
stripping_support - > inner & VIRTCHNL_VLAN_TOGGLE ) {
if ( stripping_support - > inner &
VIRTCHNL_VLAN_ETHERTYPE_8100 )
hw_features | = NETIF_F_HW_VLAN_CTAG_RX ;
}
if ( insertion_support - > outer ! = VIRTCHNL_VLAN_UNSUPPORTED & &
insertion_support - > outer & VIRTCHNL_VLAN_TOGGLE ) {
if ( insertion_support - > outer &
VIRTCHNL_VLAN_ETHERTYPE_8100 )
hw_features | = NETIF_F_HW_VLAN_CTAG_TX ;
if ( insertion_support - > outer &
VIRTCHNL_VLAN_ETHERTYPE_88A8 )
hw_features | = NETIF_F_HW_VLAN_STAG_TX ;
} else if ( insertion_support - > inner & &
insertion_support - > inner & VIRTCHNL_VLAN_TOGGLE ) {
if ( insertion_support - > inner &
VIRTCHNL_VLAN_ETHERTYPE_8100 )
hw_features | = NETIF_F_HW_VLAN_CTAG_TX ;
}
}
2023-09-06 13:57:04 -06:00
if ( CRC_OFFLOAD_ALLOWED ( adapter ) )
hw_features | = NETIF_F_RXFCS ;
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
return hw_features ;
}
/**
* iavf_get_netdev_vlan_features - get the enabled NETDEV VLAN fetures
* @ adapter : board private structure
*
* Depending on whether VIRTHCNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2
* were negotiated determine the VLAN features that are enabled by default .
* */
static netdev_features_t
iavf_get_netdev_vlan_features ( struct iavf_adapter * adapter )
{
netdev_features_t features = 0 ;
if ( ! adapter - > vf_res | | ! adapter - > vf_res - > vf_cap_flags )
return features ;
if ( VLAN_ALLOWED ( adapter ) ) {
features | = NETIF_F_HW_VLAN_CTAG_FILTER |
NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX ;
} else if ( VLAN_V2_ALLOWED ( adapter ) ) {
struct virtchnl_vlan_caps * vlan_v2_caps =
& adapter - > vlan_v2_caps ;
struct virtchnl_vlan_supported_caps * filtering_support =
& vlan_v2_caps - > filtering . filtering_support ;
struct virtchnl_vlan_supported_caps * stripping_support =
& vlan_v2_caps - > offloads . stripping_support ;
struct virtchnl_vlan_supported_caps * insertion_support =
& vlan_v2_caps - > offloads . insertion_support ;
u32 ethertype_init ;
/* give priority to outer stripping and don't support both outer
* and inner stripping
*/
ethertype_init = vlan_v2_caps - > offloads . ethertype_init ;
if ( stripping_support - > outer ! = VIRTCHNL_VLAN_UNSUPPORTED ) {
if ( stripping_support - > outer &
VIRTCHNL_VLAN_ETHERTYPE_8100 & &
ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100 )
features | = NETIF_F_HW_VLAN_CTAG_RX ;
else if ( stripping_support - > outer &
VIRTCHNL_VLAN_ETHERTYPE_88A8 & &
ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8 )
features | = NETIF_F_HW_VLAN_STAG_RX ;
} else if ( stripping_support - > inner ! =
VIRTCHNL_VLAN_UNSUPPORTED ) {
if ( stripping_support - > inner &
VIRTCHNL_VLAN_ETHERTYPE_8100 & &
ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100 )
features | = NETIF_F_HW_VLAN_CTAG_RX ;
}
/* give priority to outer insertion and don't support both outer
* and inner insertion
*/
if ( insertion_support - > outer ! = VIRTCHNL_VLAN_UNSUPPORTED ) {
if ( insertion_support - > outer &
VIRTCHNL_VLAN_ETHERTYPE_8100 & &
ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100 )
features | = NETIF_F_HW_VLAN_CTAG_TX ;
else if ( insertion_support - > outer &
VIRTCHNL_VLAN_ETHERTYPE_88A8 & &
ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8 )
features | = NETIF_F_HW_VLAN_STAG_TX ;
} else if ( insertion_support - > inner ! =
VIRTCHNL_VLAN_UNSUPPORTED ) {
if ( insertion_support - > inner &
VIRTCHNL_VLAN_ETHERTYPE_8100 & &
ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100 )
features | = NETIF_F_HW_VLAN_CTAG_TX ;
}
/* give priority to outer filtering and don't bother if both
* outer and inner filtering are enabled
*/
ethertype_init = vlan_v2_caps - > filtering . ethertype_init ;
if ( filtering_support - > outer ! = VIRTCHNL_VLAN_UNSUPPORTED ) {
if ( filtering_support - > outer &
VIRTCHNL_VLAN_ETHERTYPE_8100 & &
ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100 )
features | = NETIF_F_HW_VLAN_CTAG_FILTER ;
if ( filtering_support - > outer &
VIRTCHNL_VLAN_ETHERTYPE_88A8 & &
ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8 )
features | = NETIF_F_HW_VLAN_STAG_FILTER ;
} else if ( filtering_support - > inner ! =
VIRTCHNL_VLAN_UNSUPPORTED ) {
if ( filtering_support - > inner &
VIRTCHNL_VLAN_ETHERTYPE_8100 & &
ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_8100 )
features | = NETIF_F_HW_VLAN_CTAG_FILTER ;
if ( filtering_support - > inner &
VIRTCHNL_VLAN_ETHERTYPE_88A8 & &
ethertype_init & VIRTCHNL_VLAN_ETHERTYPE_88A8 )
features | = NETIF_F_HW_VLAN_STAG_FILTER ;
}
}
return features ;
}
# define IAVF_NETDEV_VLAN_FEATURE_ALLOWED(requested, allowed, feature_bit) \
( ! ( ( ( requested ) & ( feature_bit ) ) & & \
! ( ( allowed ) & ( feature_bit ) ) ) )
/**
* iavf_fix_netdev_vlan_features - fix NETDEV VLAN features based on support
* @ adapter : board private structure
* @ requested_features : stack requested NETDEV features
* */
static netdev_features_t
iavf_fix_netdev_vlan_features ( struct iavf_adapter * adapter ,
netdev_features_t requested_features )
{
netdev_features_t allowed_features ;
allowed_features = iavf_get_netdev_vlan_hw_features ( adapter ) |
iavf_get_netdev_vlan_features ( adapter ) ;
if ( ! IAVF_NETDEV_VLAN_FEATURE_ALLOWED ( requested_features ,
allowed_features ,
NETIF_F_HW_VLAN_CTAG_TX ) )
requested_features & = ~ NETIF_F_HW_VLAN_CTAG_TX ;
if ( ! IAVF_NETDEV_VLAN_FEATURE_ALLOWED ( requested_features ,
allowed_features ,
NETIF_F_HW_VLAN_CTAG_RX ) )
requested_features & = ~ NETIF_F_HW_VLAN_CTAG_RX ;
if ( ! IAVF_NETDEV_VLAN_FEATURE_ALLOWED ( requested_features ,
allowed_features ,
NETIF_F_HW_VLAN_STAG_TX ) )
requested_features & = ~ NETIF_F_HW_VLAN_STAG_TX ;
if ( ! IAVF_NETDEV_VLAN_FEATURE_ALLOWED ( requested_features ,
allowed_features ,
NETIF_F_HW_VLAN_STAG_RX ) )
requested_features & = ~ NETIF_F_HW_VLAN_STAG_RX ;
if ( ! IAVF_NETDEV_VLAN_FEATURE_ALLOWED ( requested_features ,
allowed_features ,
NETIF_F_HW_VLAN_CTAG_FILTER ) )
requested_features & = ~ NETIF_F_HW_VLAN_CTAG_FILTER ;
if ( ! IAVF_NETDEV_VLAN_FEATURE_ALLOWED ( requested_features ,
allowed_features ,
NETIF_F_HW_VLAN_STAG_FILTER ) )
requested_features & = ~ NETIF_F_HW_VLAN_STAG_FILTER ;
if ( ( requested_features &
( NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX ) ) & &
( requested_features &
( NETIF_F_HW_VLAN_STAG_RX | NETIF_F_HW_VLAN_STAG_TX ) ) & &
adapter - > vlan_v2_caps . offloads . ethertype_match = =
VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION ) {
netdev_warn ( adapter - > netdev , " cannot support CTAG and STAG VLAN stripping and/or insertion simultaneously since CTAG and STAG offloads are mutually exclusive, clearing STAG offload settings \n " ) ;
requested_features & = ~ ( NETIF_F_HW_VLAN_STAG_RX |
NETIF_F_HW_VLAN_STAG_TX ) ;
}
return requested_features ;
}
2023-09-06 13:57:04 -06:00
/**
* iavf_fix_strip_features - fix NETDEV CRC and VLAN strip features
* @ adapter : board private structure
* @ requested_features : stack requested NETDEV features
*
* Returns fixed - up features bits
* */
static netdev_features_t
iavf_fix_strip_features ( struct iavf_adapter * adapter ,
netdev_features_t requested_features )
{
struct net_device * netdev = adapter - > netdev ;
bool crc_offload_req , is_vlan_strip ;
netdev_features_t vlan_strip ;
int num_non_zero_vlan ;
crc_offload_req = CRC_OFFLOAD_ALLOWED ( adapter ) & &
( requested_features & NETIF_F_RXFCS ) ;
num_non_zero_vlan = iavf_get_num_vlans_added ( adapter ) ;
vlan_strip = ( NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX ) ;
is_vlan_strip = requested_features & vlan_strip ;
if ( ! crc_offload_req )
return requested_features ;
if ( ! num_non_zero_vlan & & ( netdev - > features & vlan_strip ) & &
! ( netdev - > features & NETIF_F_RXFCS ) & & is_vlan_strip ) {
requested_features & = ~ vlan_strip ;
netdev_info ( netdev , " Disabling VLAN stripping as FCS/CRC stripping is also disabled and there is no VLAN configured \n " ) ;
return requested_features ;
}
if ( ( netdev - > features & NETIF_F_RXFCS ) & & is_vlan_strip ) {
requested_features & = ~ vlan_strip ;
if ( ! ( netdev - > features & vlan_strip ) )
netdev_info ( netdev , " To enable VLAN stripping, first need to enable FCS/CRC stripping " ) ;
return requested_features ;
}
if ( num_non_zero_vlan & & is_vlan_strip & &
! ( netdev - > features & NETIF_F_RXFCS ) ) {
requested_features & = ~ NETIF_F_RXFCS ;
netdev_info ( netdev , " To disable FCS/CRC stripping, first need to disable VLAN stripping " ) ;
}
return requested_features ;
}
2016-03-18 12:18:07 -07:00
/**
2018-09-14 17:37:46 -07:00
* iavf_fix_features - fix up the netdev feature bits
2016-03-18 12:18:07 -07:00
* @ netdev : our net device
* @ features : desired feature bits
*
* Returns fixed - up features bits
* */
2018-09-14 17:37:46 -07:00
static netdev_features_t iavf_fix_features ( struct net_device * netdev ,
netdev_features_t features )
2016-03-18 12:18:07 -07:00
{
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2016-03-18 12:18:07 -07:00
2023-09-06 13:57:04 -06:00
features = iavf_fix_netdev_vlan_features ( adapter , features ) ;
2023-11-21 22:47:16 -05:00
if ( ! FDIR_FLTR_SUPPORT ( adapter ) )
features & = ~ NETIF_F_NTUPLE ;
2023-09-06 13:57:04 -06:00
return iavf_fix_strip_features ( adapter , features ) ;
2016-03-18 12:18:07 -07:00
}
2018-09-14 17:37:46 -07:00
static const struct net_device_ops iavf_netdev_ops = {
. ndo_open = iavf_open ,
. ndo_stop = iavf_close ,
. ndo_start_xmit = iavf_xmit_frame ,
. ndo_set_rx_mode = iavf_set_rx_mode ,
2013-12-21 06:12:45 +00:00
. ndo_validate_addr = eth_validate_addr ,
2018-09-14 17:37:46 -07:00
. ndo_set_mac_address = iavf_set_mac ,
. ndo_change_mtu = iavf_change_mtu ,
. ndo_tx_timeout = iavf_tx_timeout ,
. ndo_vlan_rx_add_vid = iavf_vlan_rx_add_vid ,
. ndo_vlan_rx_kill_vid = iavf_vlan_rx_kill_vid ,
. ndo_features_check = iavf_features_check ,
. ndo_fix_features = iavf_fix_features ,
. ndo_set_features = iavf_set_features ,
. ndo_setup_tc = iavf_setup_tc ,
2013-12-21 06:12:45 +00:00
} ;
/**
2018-09-14 17:37:46 -07:00
* iavf_check_reset_complete - check that VF reset is complete
2013-12-21 06:12:45 +00:00
* @ hw : pointer to hw struct
*
* Returns 0 if device is ready to use , or - EBUSY if it ' s in reset .
* */
2018-09-14 17:37:52 -07:00
static int iavf_check_reset_complete ( struct iavf_hw * hw )
2013-12-21 06:12:45 +00:00
{
u32 rstat ;
int i ;
2020-06-05 10:09:46 -07:00
for ( i = 0 ; i < IAVF_RESET_WAIT_COMPLETE_COUNT ; i + + ) {
2018-09-14 17:37:49 -07:00
rstat = rd32 ( hw , IAVF_VFGEN_RSTAT ) &
IAVF_VFGEN_RSTAT_VFR_STATE_MASK ;
2017-05-11 11:23:11 -07:00
if ( ( rstat = = VIRTCHNL_VFR_VFACTIVE ) | |
( rstat = = VIRTCHNL_VFR_COMPLETED ) )
2013-12-21 06:12:45 +00:00
return 0 ;
2023-10-27 10:59:37 -07:00
msleep ( IAVF_RESET_WAIT_MS ) ;
2013-12-21 06:12:45 +00:00
}
return - EBUSY ;
}
i40evf: handle big resets
The most common type of reset that the VF will encounter is a PF reset
that cascades down into a VF reset for each VF. In this case, the VF
will always be assigned the same VSI and recovery is fairly simple.
However, in the case of 'bigger' resets, such as a Core or EMP reset,
when the device is reinitialized, it's probable that the VF will NOT get
the same VSI. When this happens, the VF will not be able to recover, as
it will continue to request resources for its original VSI.
Add an extra state to the admin queue state machine so that the driver
can re-request its configuration information at runtime. During reset
recovery, set this bit in the aq_required field, and fetch the (possibly
new) configuration information before attempting to bring the driver
back up. Since the driver doesn't know what kind of reset it has
encountered, this step is done even for a PF reset, but it doesn't hurt
anything - it just gets the same VSI back.
Change-ID: I915d59ffb40375215117362f4ac7a37811aba748
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Tested-by: Jim Young <james.m.young@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2015-06-04 16:23:58 -04:00
/**
2018-09-14 17:37:46 -07:00
* iavf_process_config - Process the config information we got from the PF
i40evf: handle big resets
The most common type of reset that the VF will encounter is a PF reset
that cascades down into a VF reset for each VF. In this case, the VF
will always be assigned the same VSI and recovery is fairly simple.
However, in the case of 'bigger' resets, such as a Core or EMP reset,
when the device is reinitialized, it's probable that the VF will NOT get
the same VSI. When this happens, the VF will not be able to recover, as
it will continue to request resources for its original VSI.
Add an extra state to the admin queue state machine so that the driver
can re-request its configuration information at runtime. During reset
recovery, set this bit in the aq_required field, and fetch the (possibly
new) configuration information before attempting to bring the driver
back up. Since the driver doesn't know what kind of reset it has
encountered, this step is done even for a PF reset, but it doesn't hurt
anything - it just gets the same VSI back.
Change-ID: I915d59ffb40375215117362f4ac7a37811aba748
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Tested-by: Jim Young <james.m.young@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2015-06-04 16:23:58 -04:00
* @ adapter : board private structure
*
* Verify that we have a valid config struct , and set up our netdev features
* and our VSI struct .
* */
2018-09-14 17:37:46 -07:00
int iavf_process_config ( struct iavf_adapter * adapter )
i40evf: handle big resets
The most common type of reset that the VF will encounter is a PF reset
that cascades down into a VF reset for each VF. In this case, the VF
will always be assigned the same VSI and recovery is fairly simple.
However, in the case of 'bigger' resets, such as a Core or EMP reset,
when the device is reinitialized, it's probable that the VF will NOT get
the same VSI. When this happens, the VF will not be able to recover, as
it will continue to request resources for its original VSI.
Add an extra state to the admin queue state machine so that the driver
can re-request its configuration information at runtime. During reset
recovery, set this bit in the aq_required field, and fetch the (possibly
new) configuration information before attempting to bring the driver
back up. Since the driver doesn't know what kind of reset it has
encountered, this step is done even for a PF reset, but it doesn't hurt
anything - it just gets the same VSI back.
Change-ID: I915d59ffb40375215117362f4ac7a37811aba748
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Tested-by: Jim Young <james.m.young@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2015-06-04 16:23:58 -04:00
{
2017-05-11 11:23:11 -07:00
struct virtchnl_vf_resource * vfres = adapter - > vf_res ;
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
netdev_features_t hw_vlan_features , vlan_features ;
i40evf: handle big resets
The most common type of reset that the VF will encounter is a PF reset
that cascades down into a VF reset for each VF. In this case, the VF
will always be assigned the same VSI and recovery is fairly simple.
However, in the case of 'bigger' resets, such as a Core or EMP reset,
when the device is reinitialized, it's probable that the VF will NOT get
the same VSI. When this happens, the VF will not be able to recover, as
it will continue to request resources for its original VSI.
Add an extra state to the admin queue state machine so that the driver
can re-request its configuration information at runtime. During reset
recovery, set this bit in the aq_required field, and fetch the (possibly
new) configuration information before attempting to bring the driver
back up. Since the driver doesn't know what kind of reset it has
encountered, this step is done even for a PF reset, but it doesn't hurt
anything - it just gets the same VSI back.
Change-ID: I915d59ffb40375215117362f4ac7a37811aba748
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Tested-by: Jim Young <james.m.young@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2015-06-04 16:23:58 -04:00
struct net_device * netdev = adapter - > netdev ;
2017-03-27 14:43:18 -07:00
netdev_features_t hw_enc_features ;
netdev_features_t hw_features ;
i40evf: handle big resets
The most common type of reset that the VF will encounter is a PF reset
that cascades down into a VF reset for each VF. In this case, the VF
will always be assigned the same VSI and recovery is fairly simple.
However, in the case of 'bigger' resets, such as a Core or EMP reset,
when the device is reinitialized, it's probable that the VF will NOT get
the same VSI. When this happens, the VF will not be able to recover, as
it will continue to request resources for its original VSI.
Add an extra state to the admin queue state machine so that the driver
can re-request its configuration information at runtime. During reset
recovery, set this bit in the aq_required field, and fetch the (possibly
new) configuration information before attempting to bring the driver
back up. Since the driver doesn't know what kind of reset it has
encountered, this step is done even for a PF reset, but it doesn't hurt
anything - it just gets the same VSI back.
Change-ID: I915d59ffb40375215117362f4ac7a37811aba748
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Tested-by: Jim Young <james.m.young@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2015-06-04 16:23:58 -04:00
2017-03-27 14:43:18 -07:00
hw_enc_features = NETIF_F_SG |
NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM |
NETIF_F_HIGHDMA |
NETIF_F_SOFT_FEATURES |
NETIF_F_TSO |
NETIF_F_TSO_ECN |
NETIF_F_TSO6 |
NETIF_F_SCTP_CRC |
NETIF_F_RXHASH |
NETIF_F_RXCSUM |
0 ;
/* advertise to stack only if offloads for encapsulated packets is
* supported
*/
2017-06-29 15:12:24 +02:00
if ( vfres - > vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ENCAP ) {
2017-03-27 14:43:18 -07:00
hw_enc_features | = NETIF_F_GSO_UDP_TUNNEL |
2016-04-02 00:05:14 -07:00
NETIF_F_GSO_GRE |
2016-04-14 17:19:25 -04:00
NETIF_F_GSO_GRE_CSUM |
2016-05-18 09:06:10 -07:00
NETIF_F_GSO_IPXIP4 |
2016-05-18 10:44:53 -07:00
NETIF_F_GSO_IPXIP6 |
2016-04-02 00:05:14 -07:00
NETIF_F_GSO_UDP_TUNNEL_CSUM |
2016-04-14 17:19:25 -04:00
NETIF_F_GSO_PARTIAL |
2016-04-02 00:05:14 -07:00
0 ;
2017-06-29 15:12:24 +02:00
if ( ! ( vfres - > vf_cap_flags &
2017-05-11 11:23:11 -07:00
VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM ) )
2017-03-27 14:43:18 -07:00
netdev - > gso_partial_features | =
NETIF_F_GSO_UDP_TUNNEL_CSUM ;
2016-04-02 00:05:14 -07:00
2017-03-27 14:43:18 -07:00
netdev - > gso_partial_features | = NETIF_F_GSO_GRE_CSUM ;
netdev - > hw_enc_features | = NETIF_F_TSO_MANGLEID ;
netdev - > hw_enc_features | = hw_enc_features ;
}
2016-04-02 00:05:14 -07:00
/* record features VLANs can make use of */
2017-03-27 14:43:18 -07:00
netdev - > vlan_features | = hw_enc_features | NETIF_F_TSO_MANGLEID ;
2016-04-02 00:05:14 -07:00
/* Write features and hw_features separately to avoid polluting
2017-03-27 14:43:18 -07:00
* with , or dropping , features that are set when we registered .
2016-04-02 00:05:14 -07:00
*/
2017-03-27 14:43:18 -07:00
hw_features = hw_enc_features ;
2016-04-02 00:05:14 -07:00
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
/* get HW VLAN features that can be toggled */
hw_vlan_features = iavf_get_netdev_vlan_hw_features ( adapter ) ;
2018-01-23 08:51:05 -08:00
/* Enable cloud filter if ADQ is supported */
if ( vfres - > vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ )
hw_features | = NETIF_F_HW_TC ;
2021-03-02 10:12:13 -08:00
if ( vfres - > vf_cap_flags & VIRTCHNL_VF_OFFLOAD_USO )
hw_features | = NETIF_F_GSO_UDP_L4 ;
2017-08-29 05:32:41 -04:00
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
netdev - > hw_features | = hw_features | hw_vlan_features ;
vlan_features = iavf_get_netdev_vlan_features ( adapter ) ;
2016-04-02 00:05:14 -07:00
iavf: Add support VIRTCHNL_VF_OFFLOAD_VLAN_V2 during netdev config
Based on VIRTCHNL_VF_OFFLOAD_VLAN_V2, the VF can now support more VLAN
capabilities (i.e. 802.1AD offloads and filtering). In order to
communicate these capabilities to the netdev layer, the VF needs to
parse its VLAN capabilities based on whether it was able to negotiation
VIRTCHNL_VF_OFFLOAD_VLAN or VIRTCHNL_VF_OFFLOAD_VLAN_V2 or neither of
these.
In order to support this, add the following functionality:
iavf_get_netdev_vlan_hw_features() - This is used to determine the VLAN
features that the underlying hardware supports and that can be toggled
off/on based on the negotiated capabiltiies. For example, if
VIRTCHNL_VF_OFFLOAD_VLAN_V2 was negotiated, then any capability marked
with VIRTCHNL_VLAN_TOGGLE can be toggled on/off by the VF. If
VIRTCHNL_VF_OFFLOAD_VLAN was negotiated, then only VLAN insertion and/or
stripping can be toggled on/off.
iavf_get_netdev_vlan_features() - This is used to determine the VLAN
features that the underlying hardware supports and that should be
enabled by default. For example, if VIRTHCNL_VF_OFFLOAD_VLAN_V2 was
negotiated, then any supported capability that has its ethertype_init
filed set should be enabled by default. If VIRTCHNL_VF_OFFLOAD_VLAN was
negotiated, then filtering, stripping, and insertion should be enabled
by default.
Also, refactor iavf_fix_features() to take into account the new
capabilities. To do this, query all the supported features (enabled by
default and toggleable) and make sure the requested change is supported.
If VIRTCHNL_VF_OFFLOAD_VLAN_V2 is successfully negotiated, there is no
need to check VIRTCHNL_VLAN_TOGGLE here because the driver already told
the netdev layer which features can be toggled via netdev->hw_features
during iavf_process_config(), so only those features will be requested
to change.
Signed-off-by: Brett Creeley <brett.creeley@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-11-29 16:16:01 -08:00
netdev - > features | = hw_features | vlan_features ;
2017-08-29 05:32:41 -04:00
if ( vfres - > vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN )
netdev - > features | = NETIF_F_HW_VLAN_CTAG_FILTER ;
i40evf: handle big resets
The most common type of reset that the VF will encounter is a PF reset
that cascades down into a VF reset for each VF. In this case, the VF
will always be assigned the same VSI and recovery is fairly simple.
However, in the case of 'bigger' resets, such as a Core or EMP reset,
when the device is reinitialized, it's probable that the VF will NOT get
the same VSI. When this happens, the VF will not be able to recover, as
it will continue to request resources for its original VSI.
Add an extra state to the admin queue state machine so that the driver
can re-request its configuration information at runtime. During reset
recovery, set this bit in the aq_required field, and fetch the (possibly
new) configuration information before attempting to bring the driver
back up. Since the driver doesn't know what kind of reset it has
encountered, this step is done even for a PF reset, but it doesn't hurt
anything - it just gets the same VSI back.
Change-ID: I915d59ffb40375215117362f4ac7a37811aba748
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Tested-by: Jim Young <james.m.young@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2015-06-04 16:23:58 -04:00
2023-11-21 22:47:16 -05:00
if ( FDIR_FLTR_SUPPORT ( adapter ) ) {
netdev - > hw_features | = NETIF_F_NTUPLE ;
netdev - > features | = NETIF_F_NTUPLE ;
adapter - > flags | = IAVF_FLAG_FDIR_ENABLED ;
}
2018-08-20 08:12:31 -07:00
netdev - > priv_flags | = IFF_UNICAST_FLT ;
2018-04-20 01:41:36 -07:00
/* Do not turn on offloads when they are requested to be turned off.
* TSO needs minimum 576 bytes to work correctly .
*/
if ( netdev - > wanted_features ) {
if ( ! ( netdev - > wanted_features & NETIF_F_TSO ) | |
netdev - > mtu < 576 )
netdev - > features & = ~ NETIF_F_TSO ;
if ( ! ( netdev - > wanted_features & NETIF_F_TSO6 ) | |
netdev - > mtu < 576 )
netdev - > features & = ~ NETIF_F_TSO6 ;
if ( ! ( netdev - > wanted_features & NETIF_F_TSO_ECN ) )
netdev - > features & = ~ NETIF_F_TSO_ECN ;
if ( ! ( netdev - > wanted_features & NETIF_F_GRO ) )
netdev - > features & = ~ NETIF_F_GRO ;
if ( ! ( netdev - > wanted_features & NETIF_F_GSO ) )
netdev - > features & = ~ NETIF_F_GSO ;
}
i40evf: handle big resets
The most common type of reset that the VF will encounter is a PF reset
that cascades down into a VF reset for each VF. In this case, the VF
will always be assigned the same VSI and recovery is fairly simple.
However, in the case of 'bigger' resets, such as a Core or EMP reset,
when the device is reinitialized, it's probable that the VF will NOT get
the same VSI. When this happens, the VF will not be able to recover, as
it will continue to request resources for its original VSI.
Add an extra state to the admin queue state machine so that the driver
can re-request its configuration information at runtime. During reset
recovery, set this bit in the aq_required field, and fetch the (possibly
new) configuration information before attempting to bring the driver
back up. Since the driver doesn't know what kind of reset it has
encountered, this step is done even for a PF reset, but it doesn't hurt
anything - it just gets the same VSI back.
Change-ID: I915d59ffb40375215117362f4ac7a37811aba748
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Tested-by: Jim Young <james.m.young@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
2015-06-04 16:23:58 -04:00
return 0 ;
}
2013-12-21 06:12:45 +00:00
/**
2018-09-14 17:37:46 -07:00
* iavf_probe - Device Initialization Routine
2013-12-21 06:12:45 +00:00
* @ pdev : PCI device information struct
2018-09-14 17:37:46 -07:00
* @ ent : entry in iavf_pci_tbl
2013-12-21 06:12:45 +00:00
*
* Returns 0 on success , negative on failure
*
2018-09-14 17:37:46 -07:00
* iavf_probe initializes an adapter identified by a pci_dev structure .
2013-12-21 06:12:45 +00:00
* The OS initialization , configuring of the adapter private structure ,
* and a hardware reset occur .
* */
2018-09-14 17:37:46 -07:00
static int iavf_probe ( struct pci_dev * pdev , const struct pci_device_id * ent )
2013-12-21 06:12:45 +00:00
{
struct net_device * netdev ;
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = NULL ;
2018-09-14 17:37:52 -07:00
struct iavf_hw * hw = NULL ;
2014-02-20 19:29:08 -08:00
int err ;
2013-12-21 06:12:45 +00:00
err = pci_enable_device ( pdev ) ;
if ( err )
return err ;
2014-02-11 08:26:33 +00:00
err = dma_set_mask_and_coherent ( & pdev - > dev , DMA_BIT_MASK ( 64 ) ) ;
if ( err ) {
2022-01-09 19:24:08 +01:00
dev_err ( & pdev - > dev ,
" DMA configuration failed: 0x%x \n " , err ) ;
goto err_dma ;
2013-12-21 06:12:45 +00:00
}
2018-09-14 17:37:46 -07:00
err = pci_request_regions ( pdev , iavf_driver_name ) ;
2013-12-21 06:12:45 +00:00
if ( err ) {
dev_err ( & pdev - > dev ,
" pci_request_regions failed 0x%x \n " , err ) ;
goto err_pci_reg ;
}
pci_set_master ( pdev ) ;
2018-09-14 17:37:46 -07:00
netdev = alloc_etherdev_mq ( sizeof ( struct iavf_adapter ) ,
IAVF_MAX_REQ_QUEUES ) ;
2013-12-21 06:12:45 +00:00
if ( ! netdev ) {
err = - ENOMEM ;
goto err_alloc_etherdev ;
}
SET_NETDEV_DEV ( netdev , & pdev - > dev ) ;
pci_set_drvdata ( pdev , netdev ) ;
adapter = netdev_priv ( netdev ) ;
adapter - > netdev = netdev ;
adapter - > pdev = pdev ;
hw = & adapter - > hw ;
hw - > back = adapter ;
2022-12-15 23:50:48 +01:00
adapter - > wq = alloc_ordered_workqueue ( " %s " , WQ_MEM_RECLAIM ,
iavf_driver_name ) ;
if ( ! adapter - > wq ) {
err = - ENOMEM ;
goto err_alloc_wq ;
}
2015-06-04 16:24:02 -04:00
adapter - > msg_enable = BIT ( DEFAULT_DEBUG_LEVEL_SHIFT ) - 1 ;
2021-08-19 08:47:40 +00:00
iavf_change_state ( adapter , __IAVF_STARTUP ) ;
2013-12-21 06:12:45 +00:00
/* Call save state here because it relies on the adapter struct. */
pci_save_state ( pdev ) ;
hw - > hw_addr = ioremap ( pci_resource_start ( pdev , 0 ) ,
pci_resource_len ( pdev , 0 ) ) ;
if ( ! hw - > hw_addr ) {
err = - EIO ;
goto err_ioremap ;
}
hw - > vendor_id = pdev - > vendor ;
hw - > device_id = pdev - > device ;
pci_read_config_byte ( pdev , PCI_REVISION_ID , & hw - > revision_id ) ;
hw - > subsystem_vendor_id = pdev - > subsystem_vendor ;
hw - > subsystem_device_id = pdev - > subsystem_device ;
hw - > bus . device = PCI_SLOT ( pdev - > devfn ) ;
hw - > bus . func = PCI_FUNC ( pdev - > devfn ) ;
2017-02-09 23:58:22 -08:00
hw - > bus . bus_id = pdev - > bus - > number ;
2013-12-21 06:12:45 +00:00
2015-11-18 15:47:06 -08:00
/* set up the locks for the AQ, do this only once in probe
* and destroy them only once in remove
*/
2021-08-04 10:22:24 +02:00
mutex_init ( & adapter - > crit_lock ) ;
2015-11-18 15:47:06 -08:00
mutex_init ( & hw - > aq . asq_mutex ) ;
mutex_init ( & hw - > aq . arq_mutex ) ;
2017-10-27 11:06:50 -04:00
spin_lock_init ( & adapter - > mac_vlan_list_lock ) ;
2018-01-23 08:51:05 -08:00
spin_lock_init ( & adapter - > cloud_filter_list_lock ) ;
2021-03-09 11:08:11 +08:00
spin_lock_init ( & adapter - > fdir_fltr_lock ) ;
2021-04-13 08:48:41 +08:00
spin_lock_init ( & adapter - > adv_rss_lock ) ;
2023-08-21 17:01:44 -06:00
spin_lock_init ( & adapter - > current_netdev_promisc_flags_lock ) ;
2017-10-27 11:06:50 -04:00
2014-08-01 13:27:15 -07:00
INIT_LIST_HEAD ( & adapter - > mac_filter_list ) ;
INIT_LIST_HEAD ( & adapter - > vlan_filter_list ) ;
2018-01-23 08:51:05 -08:00
INIT_LIST_HEAD ( & adapter - > cloud_filter_list ) ;
2021-03-09 11:08:11 +08:00
INIT_LIST_HEAD ( & adapter - > fdir_list_head ) ;
2021-04-13 08:48:41 +08:00
INIT_LIST_HEAD ( & adapter - > adv_rss_list_head ) ;
2014-08-01 13:27:15 -07:00
2018-09-14 17:37:46 -07:00
INIT_WORK ( & adapter - > reset_task , iavf_reset_task ) ;
INIT_WORK ( & adapter - > adminq_task , iavf_adminq_task ) ;
iavf: fix a deadlock caused by rtnl and driver's lock circular dependencies
A driver's lock (crit_lock) is used to serialize all the driver's tasks.
Lockdep, however, shows a circular dependency between rtnl and
crit_lock. This happens when an ndo that already holds the rtnl requests
the driver to reset, since the reset task (in some paths) tries to grab
rtnl to either change real number of queues of update netdev features.
[566.241851] ======================================================
[566.241893] WARNING: possible circular locking dependency detected
[566.241936] 6.2.14-100.fc36.x86_64+debug #1 Tainted: G OE
[566.241984] ------------------------------------------------------
[566.242025] repro.sh/2604 is trying to acquire lock:
[566.242061] ffff9280fc5ceee8 (&adapter->crit_lock){+.+.}-{3:3}, at: iavf_close+0x3c/0x240 [iavf]
[566.242167]
but task is already holding lock:
[566.242209] ffffffff9976d350 (rtnl_mutex){+.+.}-{3:3}, at: iavf_remove+0x6b5/0x730 [iavf]
[566.242300]
which lock already depends on the new lock.
[566.242353]
the existing dependency chain (in reverse order) is:
[566.242401]
-> #1 (rtnl_mutex){+.+.}-{3:3}:
[566.242451] __mutex_lock+0xc1/0xbb0
[566.242489] iavf_init_interrupt_scheme+0x179/0x440 [iavf]
[566.242560] iavf_watchdog_task+0x80b/0x1400 [iavf]
[566.242627] process_one_work+0x2b3/0x560
[566.242663] worker_thread+0x4f/0x3a0
[566.242696] kthread+0xf2/0x120
[566.242730] ret_from_fork+0x29/0x50
[566.242763]
-> #0 (&adapter->crit_lock){+.+.}-{3:3}:
[566.242815] __lock_acquire+0x15ff/0x22b0
[566.242869] lock_acquire+0xd2/0x2c0
[566.242901] __mutex_lock+0xc1/0xbb0
[566.242934] iavf_close+0x3c/0x240 [iavf]
[566.242997] __dev_close_many+0xac/0x120
[566.243036] dev_close_many+0x8b/0x140
[566.243071] unregister_netdevice_many_notify+0x165/0x7c0
[566.243116] unregister_netdevice_queue+0xd3/0x110
[566.243157] iavf_remove+0x6c1/0x730 [iavf]
[566.243217] pci_device_remove+0x33/0xa0
[566.243257] device_release_driver_internal+0x1bc/0x240
[566.243299] pci_stop_bus_device+0x6c/0x90
[566.243338] pci_stop_and_remove_bus_device+0xe/0x20
[566.243380] pci_iov_remove_virtfn+0xd1/0x130
[566.243417] sriov_disable+0x34/0xe0
[566.243448] ice_free_vfs+0x2da/0x330 [ice]
[566.244383] ice_sriov_configure+0x88/0xad0 [ice]
[566.245353] sriov_numvfs_store+0xde/0x1d0
[566.246156] kernfs_fop_write_iter+0x15e/0x210
[566.246921] vfs_write+0x288/0x530
[566.247671] ksys_write+0x74/0xf0
[566.248408] do_syscall_64+0x58/0x80
[566.249145] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[566.249886]
other info that might help us debug this:
[566.252014] Possible unsafe locking scenario:
[566.253432] CPU0 CPU1
[566.254118] ---- ----
[566.254800] lock(rtnl_mutex);
[566.255514] lock(&adapter->crit_lock);
[566.256233] lock(rtnl_mutex);
[566.256897] lock(&adapter->crit_lock);
[566.257388]
*** DEADLOCK ***
The deadlock can be triggered by a script that is continuously resetting
the VF adapter while doing other operations requiring RTNL, e.g:
while :; do
ip link set $VF up
ethtool --set-channels $VF combined 2
ip link set $VF down
ip link set $VF up
ethtool --set-channels $VF combined 4
ip link set $VF down
done
Any operation that triggers a reset can substitute "ethtool --set-channles"
As a fix, add a new task "finish_config" that do all the work which
needs rtnl lock. With the exception of iavf_remove(), all work that
require rtnl should be called from this task.
As for iavf_remove(), at the point where we need to call
unregister_netdevice() (and grab rtnl_lock), we make sure the finish_config
task is not running (cancel_work_sync()) to safely grab rtnl. Subsequent
finish_config work cannot restart after that since the task is guarded
by the __IAVF_IN_REMOVE_TASK bit in iavf_schedule_finish_config().
Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-06-05 10:52:25 -04:00
INIT_WORK ( & adapter - > finish_config , iavf_finish_config ) ;
2019-05-14 10:37:05 -07:00
INIT_DELAYED_WORK ( & adapter - > watchdog_task , iavf_watchdog_task ) ;
2013-12-21 06:12:45 +00:00
2017-06-23 04:24:44 -04:00
/* Setup the wait queue for indicating transition to down status */
init_waitqueue_head ( & adapter - > down_waitqueue ) ;
2023-06-05 10:52:22 -04:00
/* Setup the wait queue for indicating transition to running state */
init_waitqueue_head ( & adapter - > reset_waitqueue ) ;
2022-05-20 12:07:13 +02:00
/* Setup the wait queue for indicating virtchannel events */
init_waitqueue_head ( & adapter - > vc_waitqueue ) ;
2023-10-19 09:13:46 +02:00
queue_delayed_work ( adapter - > wq , & adapter - > watchdog_task ,
msecs_to_jiffies ( 5 * ( pdev - > devfn & 0x07 ) ) ) ;
/* Initialization goes on in the work. Do not add more of it below. */
2013-12-21 06:12:45 +00:00
return 0 ;
err_ioremap :
2022-12-15 23:50:48 +01:00
destroy_workqueue ( adapter - > wq ) ;
err_alloc_wq :
2013-12-21 06:12:45 +00:00
free_netdev ( netdev ) ;
err_alloc_etherdev :
pci_release_regions ( pdev ) ;
err_pci_reg :
err_dma :
pci_disable_device ( pdev ) ;
return err ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_suspend - Power management suspend routine
2020-09-25 15:24:37 -07:00
* @ dev_d : device info pointer
2013-12-21 06:12:45 +00:00
*
* Called when the system ( VM ) is entering sleep / suspend .
* */
2024-03-05 18:50:22 -08:00
static int iavf_suspend ( struct device * dev_d )
2013-12-21 06:12:45 +00:00
{
2020-06-29 14:59:39 +05:30
struct net_device * netdev = dev_get_drvdata ( dev_d ) ;
2018-09-14 17:37:46 -07:00
struct iavf_adapter * adapter = netdev_priv ( netdev ) ;
2013-12-21 06:12:45 +00:00
netif_device_detach ( netdev ) ;
2023-10-27 10:59:35 -07:00
mutex_lock ( & adapter - > crit_lock ) ;
2017-10-27 11:06:52 -04:00
2013-12-21 06:12:45 +00:00
if ( netif_running ( netdev ) ) {
rtnl_lock ( ) ;
2018-09-14 17:37:46 -07:00
iavf_down ( adapter ) ;
2013-12-21 06:12:45 +00:00
rtnl_unlock ( ) ;
}
2018-09-14 17:37:46 -07:00
iavf_free_misc_irq ( adapter ) ;
iavf_reset_interrupt_capability ( adapter ) ;
2013-12-21 06:12:45 +00:00
2021-08-04 10:22:24 +02:00
mutex_unlock ( & adapter - > crit_lock ) ;
2017-10-27 11:06:52 -04:00
2013-12-21 06:12:45 +00:00
return 0 ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_resume - Power management resume routine
2020-09-25 15:24:37 -07:00
* @ dev_d : device info pointer
2013-12-21 06:12:45 +00:00
*
* Called when the system ( VM ) is resumed from sleep / suspend .
* */
2024-03-05 18:50:22 -08:00
static int iavf_resume ( struct device * dev_d )
2013-12-21 06:12:45 +00:00
{
2020-06-29 14:59:39 +05:30
struct pci_dev * pdev = to_pci_dev ( dev_d ) ;
2021-09-15 08:41:23 +02:00
struct iavf_adapter * adapter ;
2013-12-21 06:12:45 +00:00
u32 err ;
2021-09-15 08:41:23 +02:00
adapter = iavf_pdev_to_adapter ( pdev ) ;
2013-12-21 06:12:45 +00:00
pci_set_master ( pdev ) ;
rtnl_lock ( ) ;
2018-09-14 17:37:46 -07:00
err = iavf_set_interrupt_capability ( adapter ) ;
2013-12-21 06:12:45 +00:00
if ( err ) {
2015-07-07 18:53:38 +03:00
rtnl_unlock ( ) ;
2013-12-21 06:12:45 +00:00
dev_err ( & pdev - > dev , " Cannot enable MSI-X interrupts. \n " ) ;
return err ;
}
2018-09-14 17:37:46 -07:00
err = iavf_request_misc_irq ( adapter ) ;
2013-12-21 06:12:45 +00:00
rtnl_unlock ( ) ;
if ( err ) {
dev_err ( & pdev - > dev , " Cannot get interrupt vector. \n " ) ;
return err ;
}
2022-12-15 23:50:48 +01:00
queue_work ( adapter - > wq , & adapter - > reset_task ) ;
2013-12-21 06:12:45 +00:00
2021-09-15 08:41:23 +02:00
netif_device_attach ( adapter - > netdev ) ;
2013-12-21 06:12:45 +00:00
return err ;
}
/**
2018-09-14 17:37:46 -07:00
* iavf_remove - Device Removal Routine
2013-12-21 06:12:45 +00:00
* @ pdev : PCI device information struct
*
2018-09-14 17:37:46 -07:00
* iavf_remove is called by the PCI subsystem to alert the driver
2013-12-21 06:12:45 +00:00
* that it should release a PCI device . The could be caused by a
* Hot - Plug event , or because the driver is going to be removed from
* memory .
* */
2018-09-14 17:37:46 -07:00
static void iavf_remove ( struct pci_dev * pdev )
2013-12-21 06:12:45 +00:00
{
2021-03-09 11:08:11 +08:00
struct iavf_fdir_fltr * fdir , * fdirtmp ;
2018-09-14 17:37:46 -07:00
struct iavf_vlan_filter * vlf , * vlftmp ;
2022-11-03 14:00:03 +01:00
struct iavf_cloud_filter * cf , * cftmp ;
2021-04-13 08:48:41 +08:00
struct iavf_adv_rss * rss , * rsstmp ;
2018-09-14 17:37:46 -07:00
struct iavf_mac_filter * f , * ftmp ;
2023-11-29 10:35:26 -05:00
struct iavf_adapter * adapter ;
2022-11-03 14:00:03 +01:00
struct net_device * netdev ;
struct iavf_hw * hw ;
2022-02-23 13:35:49 +01:00
2023-11-29 10:35:26 -05:00
/* Don't proceed with remove if netdev is already freed */
netdev = pci_get_drvdata ( pdev ) ;
if ( ! netdev )
return ;
adapter = iavf_pdev_to_adapter ( pdev ) ;
2022-11-03 14:00:03 +01:00
hw = & adapter - > hw ;
if ( test_and_set_bit ( __IAVF_IN_REMOVE_TASK , & adapter - > crit_section ) )
2022-03-17 11:45:24 +01:00
return ;
2022-02-23 13:36:56 +01:00
/* Wait until port initialization is complete.
* There are flows where register / unregister netdev may race .
*/
while ( 1 ) {
mutex_lock ( & adapter - > crit_lock ) ;
if ( adapter - > state = = __IAVF_RUNNING | |
2022-02-23 13:37:10 +01:00
adapter - > state = = __IAVF_DOWN | |
adapter - > state = = __IAVF_INIT_FAILED ) {
2022-02-23 13:36:56 +01:00
mutex_unlock ( & adapter - > crit_lock ) ;
break ;
}
2023-03-13 17:06:45 +01:00
/* Simply return if we already went through iavf_shutdown */
if ( adapter - > state = = __IAVF_REMOVE ) {
mutex_unlock ( & adapter - > crit_lock ) ;
return ;
}
2022-02-23 13:36:56 +01:00
mutex_unlock ( & adapter - > crit_lock ) ;
usleep_range ( 500 , 1000 ) ;
}
2021-08-19 08:47:58 +00:00
cancel_delayed_work_sync ( & adapter - > watchdog_task ) ;
iavf: fix a deadlock caused by rtnl and driver's lock circular dependencies
A driver's lock (crit_lock) is used to serialize all the driver's tasks.
Lockdep, however, shows a circular dependency between rtnl and
crit_lock. This happens when an ndo that already holds the rtnl requests
the driver to reset, since the reset task (in some paths) tries to grab
rtnl to either change real number of queues of update netdev features.
[566.241851] ======================================================
[566.241893] WARNING: possible circular locking dependency detected
[566.241936] 6.2.14-100.fc36.x86_64+debug #1 Tainted: G OE
[566.241984] ------------------------------------------------------
[566.242025] repro.sh/2604 is trying to acquire lock:
[566.242061] ffff9280fc5ceee8 (&adapter->crit_lock){+.+.}-{3:3}, at: iavf_close+0x3c/0x240 [iavf]
[566.242167]
but task is already holding lock:
[566.242209] ffffffff9976d350 (rtnl_mutex){+.+.}-{3:3}, at: iavf_remove+0x6b5/0x730 [iavf]
[566.242300]
which lock already depends on the new lock.
[566.242353]
the existing dependency chain (in reverse order) is:
[566.242401]
-> #1 (rtnl_mutex){+.+.}-{3:3}:
[566.242451] __mutex_lock+0xc1/0xbb0
[566.242489] iavf_init_interrupt_scheme+0x179/0x440 [iavf]
[566.242560] iavf_watchdog_task+0x80b/0x1400 [iavf]
[566.242627] process_one_work+0x2b3/0x560
[566.242663] worker_thread+0x4f/0x3a0
[566.242696] kthread+0xf2/0x120
[566.242730] ret_from_fork+0x29/0x50
[566.242763]
-> #0 (&adapter->crit_lock){+.+.}-{3:3}:
[566.242815] __lock_acquire+0x15ff/0x22b0
[566.242869] lock_acquire+0xd2/0x2c0
[566.242901] __mutex_lock+0xc1/0xbb0
[566.242934] iavf_close+0x3c/0x240 [iavf]
[566.242997] __dev_close_many+0xac/0x120
[566.243036] dev_close_many+0x8b/0x140
[566.243071] unregister_netdevice_many_notify+0x165/0x7c0
[566.243116] unregister_netdevice_queue+0xd3/0x110
[566.243157] iavf_remove+0x6c1/0x730 [iavf]
[566.243217] pci_device_remove+0x33/0xa0
[566.243257] device_release_driver_internal+0x1bc/0x240
[566.243299] pci_stop_bus_device+0x6c/0x90
[566.243338] pci_stop_and_remove_bus_device+0xe/0x20
[566.243380] pci_iov_remove_virtfn+0xd1/0x130
[566.243417] sriov_disable+0x34/0xe0
[566.243448] ice_free_vfs+0x2da/0x330 [ice]
[566.244383] ice_sriov_configure+0x88/0xad0 [ice]
[566.245353] sriov_numvfs_store+0xde/0x1d0
[566.246156] kernfs_fop_write_iter+0x15e/0x210
[566.246921] vfs_write+0x288/0x530
[566.247671] ksys_write+0x74/0xf0
[566.248408] do_syscall_64+0x58/0x80
[566.249145] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[566.249886]
other info that might help us debug this:
[566.252014] Possible unsafe locking scenario:
[566.253432] CPU0 CPU1
[566.254118] ---- ----
[566.254800] lock(rtnl_mutex);
[566.255514] lock(&adapter->crit_lock);
[566.256233] lock(rtnl_mutex);
[566.256897] lock(&adapter->crit_lock);
[566.257388]
*** DEADLOCK ***
The deadlock can be triggered by a script that is continuously resetting
the VF adapter while doing other operations requiring RTNL, e.g:
while :; do
ip link set $VF up
ethtool --set-channels $VF combined 2
ip link set $VF down
ip link set $VF up
ethtool --set-channels $VF combined 4
ip link set $VF down
done
Any operation that triggers a reset can substitute "ethtool --set-channles"
As a fix, add a new task "finish_config" that do all the work which
needs rtnl lock. With the exception of iavf_remove(), all work that
require rtnl should be called from this task.
As for iavf_remove(), at the point where we need to call
unregister_netdevice() (and grab rtnl_lock), we make sure the finish_config
task is not running (cancel_work_sync()) to safely grab rtnl. Subsequent
finish_config work cannot restart after that since the task is guarded
by the __IAVF_IN_REMOVE_TASK bit in iavf_schedule_finish_config().
Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-06-05 10:52:25 -04:00
cancel_work_sync ( & adapter - > finish_config ) ;
2022-02-23 13:36:56 +01:00
2023-10-27 10:59:38 -07:00
if ( netdev - > reg_state = = NETREG_REGISTERED )
2023-10-27 10:59:39 -07:00
unregister_netdev ( netdev ) ;
iavf: fix a deadlock caused by rtnl and driver's lock circular dependencies
A driver's lock (crit_lock) is used to serialize all the driver's tasks.
Lockdep, however, shows a circular dependency between rtnl and
crit_lock. This happens when an ndo that already holds the rtnl requests
the driver to reset, since the reset task (in some paths) tries to grab
rtnl to either change real number of queues of update netdev features.
[566.241851] ======================================================
[566.241893] WARNING: possible circular locking dependency detected
[566.241936] 6.2.14-100.fc36.x86_64+debug #1 Tainted: G OE
[566.241984] ------------------------------------------------------
[566.242025] repro.sh/2604 is trying to acquire lock:
[566.242061] ffff9280fc5ceee8 (&adapter->crit_lock){+.+.}-{3:3}, at: iavf_close+0x3c/0x240 [iavf]
[566.242167]
but task is already holding lock:
[566.242209] ffffffff9976d350 (rtnl_mutex){+.+.}-{3:3}, at: iavf_remove+0x6b5/0x730 [iavf]
[566.242300]
which lock already depends on the new lock.
[566.242353]
the existing dependency chain (in reverse order) is:
[566.242401]
-> #1 (rtnl_mutex){+.+.}-{3:3}:
[566.242451] __mutex_lock+0xc1/0xbb0
[566.242489] iavf_init_interrupt_scheme+0x179/0x440 [iavf]
[566.242560] iavf_watchdog_task+0x80b/0x1400 [iavf]
[566.242627] process_one_work+0x2b3/0x560
[566.242663] worker_thread+0x4f/0x3a0
[566.242696] kthread+0xf2/0x120
[566.242730] ret_from_fork+0x29/0x50
[566.242763]
-> #0 (&adapter->crit_lock){+.+.}-{3:3}:
[566.242815] __lock_acquire+0x15ff/0x22b0
[566.242869] lock_acquire+0xd2/0x2c0
[566.242901] __mutex_lock+0xc1/0xbb0
[566.242934] iavf_close+0x3c/0x240 [iavf]
[566.242997] __dev_close_many+0xac/0x120
[566.243036] dev_close_many+0x8b/0x140
[566.243071] unregister_netdevice_many_notify+0x165/0x7c0
[566.243116] unregister_netdevice_queue+0xd3/0x110
[566.243157] iavf_remove+0x6c1/0x730 [iavf]
[566.243217] pci_device_remove+0x33/0xa0
[566.243257] device_release_driver_internal+0x1bc/0x240
[566.243299] pci_stop_bus_device+0x6c/0x90
[566.243338] pci_stop_and_remove_bus_device+0xe/0x20
[566.243380] pci_iov_remove_virtfn+0xd1/0x130
[566.243417] sriov_disable+0x34/0xe0
[566.243448] ice_free_vfs+0x2da/0x330 [ice]
[566.244383] ice_sriov_configure+0x88/0xad0 [ice]
[566.245353] sriov_numvfs_store+0xde/0x1d0
[566.246156] kernfs_fop_write_iter+0x15e/0x210
[566.246921] vfs_write+0x288/0x530
[566.247671] ksys_write+0x74/0xf0
[566.248408] do_syscall_64+0x58/0x80
[566.249145] entry_SYSCALL_64_after_hwframe+0x72/0xdc
[566.249886]
other info that might help us debug this:
[566.252014] Possible unsafe locking scenario:
[566.253432] CPU0 CPU1
[566.254118] ---- ----
[566.254800] lock(rtnl_mutex);
[566.255514] lock(&adapter->crit_lock);
[566.256233] lock(rtnl_mutex);
[566.256897] lock(&adapter->crit_lock);
[566.257388]
*** DEADLOCK ***
The deadlock can be triggered by a script that is continuously resetting
the VF adapter while doing other operations requiring RTNL, e.g:
while :; do
ip link set $VF up
ethtool --set-channels $VF combined 2
ip link set $VF down
ip link set $VF up
ethtool --set-channels $VF combined 4
ip link set $VF down
done
Any operation that triggers a reset can substitute "ethtool --set-channles"
As a fix, add a new task "finish_config" that do all the work which
needs rtnl lock. With the exception of iavf_remove(), all work that
require rtnl should be called from this task.
As for iavf_remove(), at the point where we need to call
unregister_netdevice() (and grab rtnl_lock), we make sure the finish_config
task is not running (cancel_work_sync()) to safely grab rtnl. Subsequent
finish_config work cannot restart after that since the task is guarded
by the __IAVF_IN_REMOVE_TASK bit in iavf_schedule_finish_config().
Fixes: 5ac49f3c2702 ("iavf: use mutexes for locking of critical sections")
Signed-off-by: Ahmed Zaki <ahmed.zaki@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2023-06-05 10:52:25 -04:00
2022-02-23 13:35:49 +01:00
mutex_lock ( & adapter - > crit_lock ) ;
2022-10-24 10:49:55 +02:00
dev_info ( & adapter - > pdev - > dev , " Removing device \n " ) ;
2022-02-23 13:35:49 +01:00
iavf_change_state ( adapter , __IAVF_REMOVE ) ;
2018-09-14 17:37:46 -07:00
iavf_request_reset ( adapter ) ;
2016-03-18 12:18:10 -07:00
msleep ( 50 ) ;
2015-01-09 11:18:16 +00:00
/* If the FW isn't responding, kick it once, but only once. */
2018-09-14 17:37:46 -07:00
if ( ! iavf_asq_done ( hw ) ) {
iavf_request_reset ( adapter ) ;
2016-03-18 12:18:10 -07:00
msleep ( 50 ) ;
2015-01-09 11:18:16 +00:00
}
2021-03-16 11:01:41 +01:00
2022-02-23 13:35:49 +01:00
iavf_misc_irq_disable ( adapter ) ;
2021-03-16 11:01:41 +01:00
/* Shut down all the garbage mashers on the detention level */
2022-02-23 13:35:49 +01:00
cancel_work_sync ( & adapter - > reset_task ) ;
cancel_delayed_work_sync ( & adapter - > watchdog_task ) ;
cancel_work_sync ( & adapter - > adminq_task ) ;
2021-03-16 11:01:41 +01:00
adapter - > aq_required = 0 ;
adapter - > flags & = ~ IAVF_FLAG_REINIT_ITR_NEEDED ;
iavf: Fix kernel BUG in free_msi_irqs
Fix driver not freeing VF's traffic irqs, prior to calling
pci_disable_msix in iavf_remove.
There were possible 2 erroneous states in which, iavf_close would
not be called.
One erroneous state is fixed by allowing netdev to register, when state
is already running. It was possible for VF adapter to enter state loop
from running to resetting, where iavf_open would subsequently fail.
If user would then unload driver/remove VF pci, iavf_close would not be
called, as the netdev was not registered, leaving traffic pcis still
allocated.
Fixed this by breaking loop, allowing netdev to open device when adapter
state is __IAVF_RUNNING and it is not explicitily downed.
Other possiblity is entering to iavf_remove from __IAVF_RESETTING state,
where iavf_close would not free irqs, but just return 0.
Fixed this by checking for last adapter state and then removing irqs.
Kernel panic:
[ 2773.628585] kernel BUG at drivers/pci/msi.c:375!
...
[ 2773.631567] RIP: 0010:free_msi_irqs+0x180/0x1b0
...
[ 2773.640939] Call Trace:
[ 2773.641572] pci_disable_msix+0xf7/0x120
[ 2773.642224] iavf_reset_interrupt_capability.part.41+0x15/0x30 [iavf]
[ 2773.642897] iavf_remove+0x12e/0x500 [iavf]
[ 2773.643578] pci_device_remove+0x3b/0xc0
[ 2773.644266] device_release_driver_internal+0x103/0x1f0
[ 2773.644948] pci_stop_bus_device+0x69/0x90
[ 2773.645576] pci_stop_and_remove_bus_device+0xe/0x20
[ 2773.646215] pci_iov_remove_virtfn+0xba/0x120
[ 2773.646862] sriov_disable+0x2f/0xe0
[ 2773.647531] ice_free_vfs+0x2f8/0x350 [ice]
[ 2773.648207] ice_sriov_configure+0x94/0x960 [ice]
[ 2773.648883] ? _kstrtoull+0x3b/0x90
[ 2773.649560] sriov_numvfs_store+0x10a/0x190
[ 2773.650249] kernfs_fop_write+0x116/0x190
[ 2773.650948] vfs_write+0xa5/0x1a0
[ 2773.651651] ksys_write+0x4f/0xb0
[ 2773.652358] do_syscall_64+0x5b/0x1a0
[ 2773.653075] entry_SYSCALL_64_after_hwframe+0x65/0xca
Fixes: 22ead37f8af8 ("i40evf: Add longer wait after remove module")
Signed-off-by: Przemyslaw Patynowski <przemyslawx.patynowski@intel.com>
Signed-off-by: Mateusz Palczewski <mateusz.palczewski@intel.com>
Tested-by: Konrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
2021-10-22 10:30:14 +02:00
2018-09-14 17:37:46 -07:00
iavf_free_all_tx_resources ( adapter ) ;
iavf_free_all_rx_resources ( adapter ) ;
iavf_free_misc_irq ( adapter ) ;
2023-10-27 10:59:40 -07:00
iavf_free_interrupt_scheme ( adapter ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
iavf_free_rss ( adapter ) ;
2015-10-26 19:44:34 -04:00
2013-12-21 06:12:45 +00:00
if ( hw - > aq . asq . count )
2018-09-14 17:37:46 -07:00
iavf_shutdown_adminq ( hw ) ;
2013-12-21 06:12:45 +00:00
2015-11-18 15:47:06 -08:00
/* destroy the locks only once, here */
mutex_destroy ( & hw - > aq . arq_mutex ) ;
mutex_destroy ( & hw - > aq . asq_mutex ) ;
2021-08-04 10:22:24 +02:00
mutex_unlock ( & adapter - > crit_lock ) ;
mutex_destroy ( & adapter - > crit_lock ) ;
2015-11-18 15:47:06 -08:00
2013-12-21 06:12:45 +00:00
iounmap ( hw - > hw_addr ) ;
pci_release_regions ( pdev ) ;
kfree ( adapter - > vf_res ) ;
2017-10-27 11:06:50 -04:00
spin_lock_bh ( & adapter - > mac_vlan_list_lock ) ;
2014-08-01 13:27:14 -07:00
/* If we got removed before an up/down sequence, we've got a filter
* hanging out there that we need to get rid of .
*/
list_for_each_entry_safe ( f , ftmp , & adapter - > mac_filter_list , list ) {
list_del ( & f - > list ) ;
kfree ( f ) ;
}
2018-01-22 12:00:34 -05:00
list_for_each_entry_safe ( vlf , vlftmp , & adapter - > vlan_filter_list ,
list ) {
list_del ( & vlf - > list ) ;
kfree ( vlf ) ;
2014-12-09 08:53:05 +00:00
}
2013-12-21 06:12:45 +00:00
2017-10-27 11:06:50 -04:00
spin_unlock_bh ( & adapter - > mac_vlan_list_lock ) ;
2018-01-23 08:51:05 -08:00
spin_lock_bh ( & adapter - > cloud_filter_list_lock ) ;
list_for_each_entry_safe ( cf , cftmp , & adapter - > cloud_filter_list , list ) {
list_del ( & cf - > list ) ;
kfree ( cf ) ;
}
spin_unlock_bh ( & adapter - > cloud_filter_list_lock ) ;
2021-03-09 11:08:11 +08:00
spin_lock_bh ( & adapter - > fdir_fltr_lock ) ;
list_for_each_entry_safe ( fdir , fdirtmp , & adapter - > fdir_list_head , list ) {
list_del ( & fdir - > list ) ;
kfree ( fdir ) ;
}
spin_unlock_bh ( & adapter - > fdir_fltr_lock ) ;
2021-04-13 08:48:41 +08:00
spin_lock_bh ( & adapter - > adv_rss_lock ) ;
list_for_each_entry_safe ( rss , rsstmp , & adapter - > adv_rss_list_head ,
list ) {
list_del ( & rss - > list ) ;
kfree ( rss ) ;
}
spin_unlock_bh ( & adapter - > adv_rss_lock ) ;
2022-12-15 23:50:48 +01:00
destroy_workqueue ( adapter - > wq ) ;
2023-11-29 10:35:26 -05:00
pci_set_drvdata ( pdev , NULL ) ;
2013-12-21 06:12:45 +00:00
free_netdev ( netdev ) ;
pci_disable_device ( pdev ) ;
}
2023-11-29 10:35:26 -05:00
/**
* iavf_shutdown - Shutdown the device in preparation for a reboot
* @ pdev : pci device structure
* */
static void iavf_shutdown ( struct pci_dev * pdev )
{
iavf_remove ( pdev ) ;
if ( system_state = = SYSTEM_POWER_OFF )
pci_set_power_state ( pdev , PCI_D3hot ) ;
}
2024-03-05 18:50:22 -08:00
static DEFINE_SIMPLE_DEV_PM_OPS ( iavf_pm_ops , iavf_suspend , iavf_resume ) ;
2020-06-29 14:59:39 +05:30
2018-09-14 17:37:46 -07:00
static struct pci_driver iavf_driver = {
2020-06-29 14:59:39 +05:30
. name = iavf_driver_name ,
. id_table = iavf_pci_tbl ,
. probe = iavf_probe ,
. remove = iavf_remove ,
2024-03-05 18:50:22 -08:00
. driver . pm = pm_sleep_ptr ( & iavf_pm_ops ) ,
2020-06-29 14:59:39 +05:30
. shutdown = iavf_shutdown ,
2013-12-21 06:12:45 +00:00
} ;
/**
2018-09-14 17:37:55 -07:00
* iavf_init_module - Driver Registration Routine
2013-12-21 06:12:45 +00:00
*
2018-09-14 17:37:55 -07:00
* iavf_init_module is the first routine called when the driver is
2013-12-21 06:12:45 +00:00
* loaded . All it does is register with the PCI subsystem .
* */
2018-09-14 17:37:46 -07:00
static int __init iavf_init_module ( void )
2013-12-21 06:12:45 +00:00
{
2020-05-29 00:18:33 -07:00
pr_info ( " iavf: %s \n " , iavf_driver_string ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
pr_info ( " %s \n " , iavf_copyright ) ;
2013-12-21 06:12:45 +00:00
2022-12-15 23:50:48 +01:00
return pci_register_driver ( & iavf_driver ) ;
2013-12-21 06:12:45 +00:00
}
2018-09-14 17:37:46 -07:00
module_init ( iavf_init_module ) ;
2013-12-21 06:12:45 +00:00
/**
2018-09-14 17:37:55 -07:00
* iavf_exit_module - Driver Exit Cleanup Routine
2013-12-21 06:12:45 +00:00
*
2018-09-14 17:37:55 -07:00
* iavf_exit_module is called just before the driver is removed
2013-12-21 06:12:45 +00:00
* from memory .
* */
2018-09-14 17:37:46 -07:00
static void __exit iavf_exit_module ( void )
2013-12-21 06:12:45 +00:00
{
2018-09-14 17:37:46 -07:00
pci_unregister_driver ( & iavf_driver ) ;
2013-12-21 06:12:45 +00:00
}
2018-09-14 17:37:46 -07:00
module_exit ( iavf_exit_module ) ;
2013-12-21 06:12:45 +00:00
2018-09-14 17:37:46 -07:00
/* iavf_main.c */