162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2018 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci/****************************************************************************** 562306a36Sopenharmony_ci Copyright (c)2006 - 2007 Myricom, Inc. for some LRO specific code 662306a36Sopenharmony_ci******************************************************************************/ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/types.h> 1162306a36Sopenharmony_ci#include <linux/bitops.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/pci.h> 1462306a36Sopenharmony_ci#include <linux/netdevice.h> 1562306a36Sopenharmony_ci#include <linux/vmalloc.h> 1662306a36Sopenharmony_ci#include <linux/string.h> 1762306a36Sopenharmony_ci#include <linux/in.h> 1862306a36Sopenharmony_ci#include <linux/ip.h> 1962306a36Sopenharmony_ci#include <linux/tcp.h> 2062306a36Sopenharmony_ci#include <linux/sctp.h> 2162306a36Sopenharmony_ci#include <linux/ipv6.h> 2262306a36Sopenharmony_ci#include <linux/slab.h> 2362306a36Sopenharmony_ci#include <net/checksum.h> 2462306a36Sopenharmony_ci#include <net/ip6_checksum.h> 2562306a36Sopenharmony_ci#include <linux/ethtool.h> 2662306a36Sopenharmony_ci#include <linux/if.h> 2762306a36Sopenharmony_ci#include <linux/if_vlan.h> 2862306a36Sopenharmony_ci#include <linux/prefetch.h> 2962306a36Sopenharmony_ci#include <net/mpls.h> 3062306a36Sopenharmony_ci#include <linux/bpf.h> 3162306a36Sopenharmony_ci#include <linux/bpf_trace.h> 3262306a36Sopenharmony_ci#include <linux/atomic.h> 3362306a36Sopenharmony_ci#include <net/xfrm.h> 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include "ixgbevf.h" 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciconst char ixgbevf_driver_name[] = "ixgbevf"; 3862306a36Sopenharmony_cistatic const char ixgbevf_driver_string[] = 3962306a36Sopenharmony_ci "Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver"; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic char ixgbevf_copyright[] = 4262306a36Sopenharmony_ci "Copyright (c) 2009 - 2018 Intel Corporation."; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const struct ixgbevf_info *ixgbevf_info_tbl[] = { 4562306a36Sopenharmony_ci [board_82599_vf] = &ixgbevf_82599_vf_info, 4662306a36Sopenharmony_ci [board_82599_vf_hv] = &ixgbevf_82599_vf_hv_info, 4762306a36Sopenharmony_ci [board_X540_vf] = &ixgbevf_X540_vf_info, 4862306a36Sopenharmony_ci [board_X540_vf_hv] = &ixgbevf_X540_vf_hv_info, 4962306a36Sopenharmony_ci [board_X550_vf] = &ixgbevf_X550_vf_info, 5062306a36Sopenharmony_ci [board_X550_vf_hv] = &ixgbevf_X550_vf_hv_info, 5162306a36Sopenharmony_ci [board_X550EM_x_vf] = &ixgbevf_X550EM_x_vf_info, 5262306a36Sopenharmony_ci [board_X550EM_x_vf_hv] = &ixgbevf_X550EM_x_vf_hv_info, 5362306a36Sopenharmony_ci [board_x550em_a_vf] = &ixgbevf_x550em_a_vf_info, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci/* ixgbevf_pci_tbl - PCI Device ID Table 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * Wildcard entries (PCI_ANY_ID) should come last 5962306a36Sopenharmony_ci * Last entry must be all 0s 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, 6262306a36Sopenharmony_ci * Class, Class Mask, private data (not used) } 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_cistatic const struct pci_device_id ixgbevf_pci_tbl[] = { 6562306a36Sopenharmony_ci {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF), board_82599_vf }, 6662306a36Sopenharmony_ci {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF_HV), board_82599_vf_hv }, 6762306a36Sopenharmony_ci {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF), board_X540_vf }, 6862306a36Sopenharmony_ci {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF_HV), board_X540_vf_hv }, 6962306a36Sopenharmony_ci {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550_VF), board_X550_vf }, 7062306a36Sopenharmony_ci {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550_VF_HV), board_X550_vf_hv }, 7162306a36Sopenharmony_ci {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF), board_X550EM_x_vf }, 7262306a36Sopenharmony_ci {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF_HV), board_X550EM_x_vf_hv}, 7362306a36Sopenharmony_ci {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_VF), board_x550em_a_vf }, 7462306a36Sopenharmony_ci /* required last entry */ 7562306a36Sopenharmony_ci {0, } 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, ixgbevf_pci_tbl); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ciMODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); 8062306a36Sopenharmony_ciMODULE_DESCRIPTION("Intel(R) 10 Gigabit Virtual Function Network Driver"); 8162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) 8462306a36Sopenharmony_cistatic int debug = -1; 8562306a36Sopenharmony_cimodule_param(debug, int, 0); 8662306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic struct workqueue_struct *ixgbevf_wq; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic void ixgbevf_service_event_schedule(struct ixgbevf_adapter *adapter) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci if (!test_bit(__IXGBEVF_DOWN, &adapter->state) && 9362306a36Sopenharmony_ci !test_bit(__IXGBEVF_REMOVING, &adapter->state) && 9462306a36Sopenharmony_ci !test_and_set_bit(__IXGBEVF_SERVICE_SCHED, &adapter->state)) 9562306a36Sopenharmony_ci queue_work(ixgbevf_wq, &adapter->service_task); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic void ixgbevf_service_event_complete(struct ixgbevf_adapter *adapter) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci BUG_ON(!test_bit(__IXGBEVF_SERVICE_SCHED, &adapter->state)); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci /* flush memory to make sure state is correct before next watchdog */ 10362306a36Sopenharmony_ci smp_mb__before_atomic(); 10462306a36Sopenharmony_ci clear_bit(__IXGBEVF_SERVICE_SCHED, &adapter->state); 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci/* forward decls */ 10862306a36Sopenharmony_cistatic void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter); 10962306a36Sopenharmony_cistatic void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector); 11062306a36Sopenharmony_cistatic void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter); 11162306a36Sopenharmony_cistatic bool ixgbevf_can_reuse_rx_page(struct ixgbevf_rx_buffer *rx_buffer); 11262306a36Sopenharmony_cistatic void ixgbevf_reuse_rx_page(struct ixgbevf_ring *rx_ring, 11362306a36Sopenharmony_ci struct ixgbevf_rx_buffer *old_buff); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic void ixgbevf_remove_adapter(struct ixgbe_hw *hw) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = hw->back; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (!hw->hw_addr) 12062306a36Sopenharmony_ci return; 12162306a36Sopenharmony_ci hw->hw_addr = NULL; 12262306a36Sopenharmony_ci dev_err(&adapter->pdev->dev, "Adapter removed\n"); 12362306a36Sopenharmony_ci if (test_bit(__IXGBEVF_SERVICE_INITED, &adapter->state)) 12462306a36Sopenharmony_ci ixgbevf_service_event_schedule(adapter); 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic void ixgbevf_check_remove(struct ixgbe_hw *hw, u32 reg) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci u32 value; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* The following check not only optimizes a bit by not 13262306a36Sopenharmony_ci * performing a read on the status register when the 13362306a36Sopenharmony_ci * register just read was a status register read that 13462306a36Sopenharmony_ci * returned IXGBE_FAILED_READ_REG. It also blocks any 13562306a36Sopenharmony_ci * potential recursion. 13662306a36Sopenharmony_ci */ 13762306a36Sopenharmony_ci if (reg == IXGBE_VFSTATUS) { 13862306a36Sopenharmony_ci ixgbevf_remove_adapter(hw); 13962306a36Sopenharmony_ci return; 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci value = ixgbevf_read_reg(hw, IXGBE_VFSTATUS); 14262306a36Sopenharmony_ci if (value == IXGBE_FAILED_READ_REG) 14362306a36Sopenharmony_ci ixgbevf_remove_adapter(hw); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ciu32 ixgbevf_read_reg(struct ixgbe_hw *hw, u32 reg) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci u8 __iomem *reg_addr = READ_ONCE(hw->hw_addr); 14962306a36Sopenharmony_ci u32 value; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (IXGBE_REMOVED(reg_addr)) 15262306a36Sopenharmony_ci return IXGBE_FAILED_READ_REG; 15362306a36Sopenharmony_ci value = readl(reg_addr + reg); 15462306a36Sopenharmony_ci if (unlikely(value == IXGBE_FAILED_READ_REG)) 15562306a36Sopenharmony_ci ixgbevf_check_remove(hw, reg); 15662306a36Sopenharmony_ci return value; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/** 16062306a36Sopenharmony_ci * ixgbevf_set_ivar - set IVAR registers - maps interrupt causes to vectors 16162306a36Sopenharmony_ci * @adapter: pointer to adapter struct 16262306a36Sopenharmony_ci * @direction: 0 for Rx, 1 for Tx, -1 for other causes 16362306a36Sopenharmony_ci * @queue: queue to map the corresponding interrupt to 16462306a36Sopenharmony_ci * @msix_vector: the vector to map to the corresponding queue 16562306a36Sopenharmony_ci **/ 16662306a36Sopenharmony_cistatic void ixgbevf_set_ivar(struct ixgbevf_adapter *adapter, s8 direction, 16762306a36Sopenharmony_ci u8 queue, u8 msix_vector) 16862306a36Sopenharmony_ci{ 16962306a36Sopenharmony_ci u32 ivar, index; 17062306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci if (direction == -1) { 17362306a36Sopenharmony_ci /* other causes */ 17462306a36Sopenharmony_ci msix_vector |= IXGBE_IVAR_ALLOC_VAL; 17562306a36Sopenharmony_ci ivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR_MISC); 17662306a36Sopenharmony_ci ivar &= ~0xFF; 17762306a36Sopenharmony_ci ivar |= msix_vector; 17862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTIVAR_MISC, ivar); 17962306a36Sopenharmony_ci } else { 18062306a36Sopenharmony_ci /* Tx or Rx causes */ 18162306a36Sopenharmony_ci msix_vector |= IXGBE_IVAR_ALLOC_VAL; 18262306a36Sopenharmony_ci index = ((16 * (queue & 1)) + (8 * direction)); 18362306a36Sopenharmony_ci ivar = IXGBE_READ_REG(hw, IXGBE_VTIVAR(queue >> 1)); 18462306a36Sopenharmony_ci ivar &= ~(0xFF << index); 18562306a36Sopenharmony_ci ivar |= (msix_vector << index); 18662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTIVAR(queue >> 1), ivar); 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic u64 ixgbevf_get_tx_completed(struct ixgbevf_ring *ring) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci return ring->stats.packets; 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic u32 ixgbevf_get_tx_pending(struct ixgbevf_ring *ring) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(ring->netdev); 19862306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci u32 head = IXGBE_READ_REG(hw, IXGBE_VFTDH(ring->reg_idx)); 20162306a36Sopenharmony_ci u32 tail = IXGBE_READ_REG(hw, IXGBE_VFTDT(ring->reg_idx)); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (head != tail) 20462306a36Sopenharmony_ci return (head < tail) ? 20562306a36Sopenharmony_ci tail - head : (tail + ring->count - head); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci return 0; 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic inline bool ixgbevf_check_tx_hang(struct ixgbevf_ring *tx_ring) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci u32 tx_done = ixgbevf_get_tx_completed(tx_ring); 21362306a36Sopenharmony_ci u32 tx_done_old = tx_ring->tx_stats.tx_done_old; 21462306a36Sopenharmony_ci u32 tx_pending = ixgbevf_get_tx_pending(tx_ring); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci clear_check_for_tx_hang(tx_ring); 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci /* Check for a hung queue, but be thorough. This verifies 21962306a36Sopenharmony_ci * that a transmit has been completed since the previous 22062306a36Sopenharmony_ci * check AND there is at least one packet pending. The 22162306a36Sopenharmony_ci * ARMED bit is set to indicate a potential hang. 22262306a36Sopenharmony_ci */ 22362306a36Sopenharmony_ci if ((tx_done_old == tx_done) && tx_pending) { 22462306a36Sopenharmony_ci /* make sure it is true for two checks in a row */ 22562306a36Sopenharmony_ci return test_and_set_bit(__IXGBEVF_HANG_CHECK_ARMED, 22662306a36Sopenharmony_ci &tx_ring->state); 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci /* reset the countdown */ 22962306a36Sopenharmony_ci clear_bit(__IXGBEVF_HANG_CHECK_ARMED, &tx_ring->state); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci /* update completed stats and continue */ 23262306a36Sopenharmony_ci tx_ring->tx_stats.tx_done_old = tx_done; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci return false; 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic void ixgbevf_tx_timeout_reset(struct ixgbevf_adapter *adapter) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci /* Do the reset outside of interrupt context */ 24062306a36Sopenharmony_ci if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) { 24162306a36Sopenharmony_ci set_bit(__IXGBEVF_RESET_REQUESTED, &adapter->state); 24262306a36Sopenharmony_ci ixgbevf_service_event_schedule(adapter); 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/** 24762306a36Sopenharmony_ci * ixgbevf_tx_timeout - Respond to a Tx Hang 24862306a36Sopenharmony_ci * @netdev: network interface device structure 24962306a36Sopenharmony_ci * @txqueue: transmit queue hanging (unused) 25062306a36Sopenharmony_ci **/ 25162306a36Sopenharmony_cistatic void ixgbevf_tx_timeout(struct net_device *netdev, unsigned int __always_unused txqueue) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci ixgbevf_tx_timeout_reset(adapter); 25662306a36Sopenharmony_ci} 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci/** 25962306a36Sopenharmony_ci * ixgbevf_clean_tx_irq - Reclaim resources after transmit completes 26062306a36Sopenharmony_ci * @q_vector: board private structure 26162306a36Sopenharmony_ci * @tx_ring: tx ring to clean 26262306a36Sopenharmony_ci * @napi_budget: Used to determine if we are in netpoll 26362306a36Sopenharmony_ci **/ 26462306a36Sopenharmony_cistatic bool ixgbevf_clean_tx_irq(struct ixgbevf_q_vector *q_vector, 26562306a36Sopenharmony_ci struct ixgbevf_ring *tx_ring, int napi_budget) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = q_vector->adapter; 26862306a36Sopenharmony_ci struct ixgbevf_tx_buffer *tx_buffer; 26962306a36Sopenharmony_ci union ixgbe_adv_tx_desc *tx_desc; 27062306a36Sopenharmony_ci unsigned int total_bytes = 0, total_packets = 0, total_ipsec = 0; 27162306a36Sopenharmony_ci unsigned int budget = tx_ring->count / 2; 27262306a36Sopenharmony_ci unsigned int i = tx_ring->next_to_clean; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci if (test_bit(__IXGBEVF_DOWN, &adapter->state)) 27562306a36Sopenharmony_ci return true; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 27862306a36Sopenharmony_ci tx_desc = IXGBEVF_TX_DESC(tx_ring, i); 27962306a36Sopenharmony_ci i -= tx_ring->count; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci do { 28262306a36Sopenharmony_ci union ixgbe_adv_tx_desc *eop_desc = tx_buffer->next_to_watch; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci /* if next_to_watch is not set then there is no work pending */ 28562306a36Sopenharmony_ci if (!eop_desc) 28662306a36Sopenharmony_ci break; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* prevent any other reads prior to eop_desc */ 28962306a36Sopenharmony_ci smp_rmb(); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci /* if DD is not set pending work has not been completed */ 29262306a36Sopenharmony_ci if (!(eop_desc->wb.status & cpu_to_le32(IXGBE_TXD_STAT_DD))) 29362306a36Sopenharmony_ci break; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* clear next_to_watch to prevent false hangs */ 29662306a36Sopenharmony_ci tx_buffer->next_to_watch = NULL; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* update the statistics for this packet */ 29962306a36Sopenharmony_ci total_bytes += tx_buffer->bytecount; 30062306a36Sopenharmony_ci total_packets += tx_buffer->gso_segs; 30162306a36Sopenharmony_ci if (tx_buffer->tx_flags & IXGBE_TX_FLAGS_IPSEC) 30262306a36Sopenharmony_ci total_ipsec++; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci /* free the skb */ 30562306a36Sopenharmony_ci if (ring_is_xdp(tx_ring)) 30662306a36Sopenharmony_ci page_frag_free(tx_buffer->data); 30762306a36Sopenharmony_ci else 30862306a36Sopenharmony_ci napi_consume_skb(tx_buffer->skb, napi_budget); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci /* unmap skb header data */ 31162306a36Sopenharmony_ci dma_unmap_single(tx_ring->dev, 31262306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 31362306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 31462306a36Sopenharmony_ci DMA_TO_DEVICE); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* clear tx_buffer data */ 31762306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci /* unmap remaining buffers */ 32062306a36Sopenharmony_ci while (tx_desc != eop_desc) { 32162306a36Sopenharmony_ci tx_buffer++; 32262306a36Sopenharmony_ci tx_desc++; 32362306a36Sopenharmony_ci i++; 32462306a36Sopenharmony_ci if (unlikely(!i)) { 32562306a36Sopenharmony_ci i -= tx_ring->count; 32662306a36Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 32762306a36Sopenharmony_ci tx_desc = IXGBEVF_TX_DESC(tx_ring, 0); 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci /* unmap any remaining paged data */ 33162306a36Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) { 33262306a36Sopenharmony_ci dma_unmap_page(tx_ring->dev, 33362306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 33462306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 33562306a36Sopenharmony_ci DMA_TO_DEVICE); 33662306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 33762306a36Sopenharmony_ci } 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci /* move us one more past the eop_desc for start of next pkt */ 34162306a36Sopenharmony_ci tx_buffer++; 34262306a36Sopenharmony_ci tx_desc++; 34362306a36Sopenharmony_ci i++; 34462306a36Sopenharmony_ci if (unlikely(!i)) { 34562306a36Sopenharmony_ci i -= tx_ring->count; 34662306a36Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 34762306a36Sopenharmony_ci tx_desc = IXGBEVF_TX_DESC(tx_ring, 0); 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci /* issue prefetch for next Tx descriptor */ 35162306a36Sopenharmony_ci prefetch(tx_desc); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci /* update budget accounting */ 35462306a36Sopenharmony_ci budget--; 35562306a36Sopenharmony_ci } while (likely(budget)); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci i += tx_ring->count; 35862306a36Sopenharmony_ci tx_ring->next_to_clean = i; 35962306a36Sopenharmony_ci u64_stats_update_begin(&tx_ring->syncp); 36062306a36Sopenharmony_ci tx_ring->stats.bytes += total_bytes; 36162306a36Sopenharmony_ci tx_ring->stats.packets += total_packets; 36262306a36Sopenharmony_ci u64_stats_update_end(&tx_ring->syncp); 36362306a36Sopenharmony_ci q_vector->tx.total_bytes += total_bytes; 36462306a36Sopenharmony_ci q_vector->tx.total_packets += total_packets; 36562306a36Sopenharmony_ci adapter->tx_ipsec += total_ipsec; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci if (check_for_tx_hang(tx_ring) && ixgbevf_check_tx_hang(tx_ring)) { 36862306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 36962306a36Sopenharmony_ci union ixgbe_adv_tx_desc *eop_desc; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci eop_desc = tx_ring->tx_buffer_info[i].next_to_watch; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci pr_err("Detected Tx Unit Hang%s\n" 37462306a36Sopenharmony_ci " Tx Queue <%d>\n" 37562306a36Sopenharmony_ci " TDH, TDT <%x>, <%x>\n" 37662306a36Sopenharmony_ci " next_to_use <%x>\n" 37762306a36Sopenharmony_ci " next_to_clean <%x>\n" 37862306a36Sopenharmony_ci "tx_buffer_info[next_to_clean]\n" 37962306a36Sopenharmony_ci " next_to_watch <%p>\n" 38062306a36Sopenharmony_ci " eop_desc->wb.status <%x>\n" 38162306a36Sopenharmony_ci " time_stamp <%lx>\n" 38262306a36Sopenharmony_ci " jiffies <%lx>\n", 38362306a36Sopenharmony_ci ring_is_xdp(tx_ring) ? " XDP" : "", 38462306a36Sopenharmony_ci tx_ring->queue_index, 38562306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_VFTDH(tx_ring->reg_idx)), 38662306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_VFTDT(tx_ring->reg_idx)), 38762306a36Sopenharmony_ci tx_ring->next_to_use, i, 38862306a36Sopenharmony_ci eop_desc, (eop_desc ? eop_desc->wb.status : 0), 38962306a36Sopenharmony_ci tx_ring->tx_buffer_info[i].time_stamp, jiffies); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci if (!ring_is_xdp(tx_ring)) 39262306a36Sopenharmony_ci netif_stop_subqueue(tx_ring->netdev, 39362306a36Sopenharmony_ci tx_ring->queue_index); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci /* schedule immediate reset if we believe we hung */ 39662306a36Sopenharmony_ci ixgbevf_tx_timeout_reset(adapter); 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci return true; 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci if (ring_is_xdp(tx_ring)) 40262306a36Sopenharmony_ci return !!budget; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) 40562306a36Sopenharmony_ci if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) && 40662306a36Sopenharmony_ci (ixgbevf_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD))) { 40762306a36Sopenharmony_ci /* Make sure that anybody stopping the queue after this 40862306a36Sopenharmony_ci * sees the new next_to_clean. 40962306a36Sopenharmony_ci */ 41062306a36Sopenharmony_ci smp_mb(); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci if (__netif_subqueue_stopped(tx_ring->netdev, 41362306a36Sopenharmony_ci tx_ring->queue_index) && 41462306a36Sopenharmony_ci !test_bit(__IXGBEVF_DOWN, &adapter->state)) { 41562306a36Sopenharmony_ci netif_wake_subqueue(tx_ring->netdev, 41662306a36Sopenharmony_ci tx_ring->queue_index); 41762306a36Sopenharmony_ci ++tx_ring->tx_stats.restart_queue; 41862306a36Sopenharmony_ci } 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci return !!budget; 42262306a36Sopenharmony_ci} 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci/** 42562306a36Sopenharmony_ci * ixgbevf_rx_skb - Helper function to determine proper Rx method 42662306a36Sopenharmony_ci * @q_vector: structure containing interrupt and ring information 42762306a36Sopenharmony_ci * @skb: packet to send up 42862306a36Sopenharmony_ci **/ 42962306a36Sopenharmony_cistatic void ixgbevf_rx_skb(struct ixgbevf_q_vector *q_vector, 43062306a36Sopenharmony_ci struct sk_buff *skb) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci napi_gro_receive(&q_vector->napi, skb); 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci#define IXGBE_RSS_L4_TYPES_MASK \ 43662306a36Sopenharmony_ci ((1ul << IXGBE_RXDADV_RSSTYPE_IPV4_TCP) | \ 43762306a36Sopenharmony_ci (1ul << IXGBE_RXDADV_RSSTYPE_IPV4_UDP) | \ 43862306a36Sopenharmony_ci (1ul << IXGBE_RXDADV_RSSTYPE_IPV6_TCP) | \ 43962306a36Sopenharmony_ci (1ul << IXGBE_RXDADV_RSSTYPE_IPV6_UDP)) 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_cistatic inline void ixgbevf_rx_hash(struct ixgbevf_ring *ring, 44262306a36Sopenharmony_ci union ixgbe_adv_rx_desc *rx_desc, 44362306a36Sopenharmony_ci struct sk_buff *skb) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci u16 rss_type; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci if (!(ring->netdev->features & NETIF_F_RXHASH)) 44862306a36Sopenharmony_ci return; 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci rss_type = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) & 45162306a36Sopenharmony_ci IXGBE_RXDADV_RSSTYPE_MASK; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci if (!rss_type) 45462306a36Sopenharmony_ci return; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci skb_set_hash(skb, le32_to_cpu(rx_desc->wb.lower.hi_dword.rss), 45762306a36Sopenharmony_ci (IXGBE_RSS_L4_TYPES_MASK & (1ul << rss_type)) ? 45862306a36Sopenharmony_ci PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci/** 46262306a36Sopenharmony_ci * ixgbevf_rx_checksum - indicate in skb if hw indicated a good cksum 46362306a36Sopenharmony_ci * @ring: structure containig ring specific data 46462306a36Sopenharmony_ci * @rx_desc: current Rx descriptor being processed 46562306a36Sopenharmony_ci * @skb: skb currently being received and modified 46662306a36Sopenharmony_ci **/ 46762306a36Sopenharmony_cistatic inline void ixgbevf_rx_checksum(struct ixgbevf_ring *ring, 46862306a36Sopenharmony_ci union ixgbe_adv_rx_desc *rx_desc, 46962306a36Sopenharmony_ci struct sk_buff *skb) 47062306a36Sopenharmony_ci{ 47162306a36Sopenharmony_ci skb_checksum_none_assert(skb); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci /* Rx csum disabled */ 47462306a36Sopenharmony_ci if (!(ring->netdev->features & NETIF_F_RXCSUM)) 47562306a36Sopenharmony_ci return; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci /* if IP and error */ 47862306a36Sopenharmony_ci if (ixgbevf_test_staterr(rx_desc, IXGBE_RXD_STAT_IPCS) && 47962306a36Sopenharmony_ci ixgbevf_test_staterr(rx_desc, IXGBE_RXDADV_ERR_IPE)) { 48062306a36Sopenharmony_ci ring->rx_stats.csum_err++; 48162306a36Sopenharmony_ci return; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci if (!ixgbevf_test_staterr(rx_desc, IXGBE_RXD_STAT_L4CS)) 48562306a36Sopenharmony_ci return; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci if (ixgbevf_test_staterr(rx_desc, IXGBE_RXDADV_ERR_TCPE)) { 48862306a36Sopenharmony_ci ring->rx_stats.csum_err++; 48962306a36Sopenharmony_ci return; 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci /* It must be a TCP or UDP packet with a valid checksum */ 49362306a36Sopenharmony_ci skb->ip_summed = CHECKSUM_UNNECESSARY; 49462306a36Sopenharmony_ci} 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci/** 49762306a36Sopenharmony_ci * ixgbevf_process_skb_fields - Populate skb header fields from Rx descriptor 49862306a36Sopenharmony_ci * @rx_ring: rx descriptor ring packet is being transacted on 49962306a36Sopenharmony_ci * @rx_desc: pointer to the EOP Rx descriptor 50062306a36Sopenharmony_ci * @skb: pointer to current skb being populated 50162306a36Sopenharmony_ci * 50262306a36Sopenharmony_ci * This function checks the ring, descriptor, and packet information in 50362306a36Sopenharmony_ci * order to populate the checksum, VLAN, protocol, and other fields within 50462306a36Sopenharmony_ci * the skb. 50562306a36Sopenharmony_ci **/ 50662306a36Sopenharmony_cistatic void ixgbevf_process_skb_fields(struct ixgbevf_ring *rx_ring, 50762306a36Sopenharmony_ci union ixgbe_adv_rx_desc *rx_desc, 50862306a36Sopenharmony_ci struct sk_buff *skb) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci ixgbevf_rx_hash(rx_ring, rx_desc, skb); 51162306a36Sopenharmony_ci ixgbevf_rx_checksum(rx_ring, rx_desc, skb); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci if (ixgbevf_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { 51462306a36Sopenharmony_ci u16 vid = le16_to_cpu(rx_desc->wb.upper.vlan); 51562306a36Sopenharmony_ci unsigned long *active_vlans = netdev_priv(rx_ring->netdev); 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci if (test_bit(vid & VLAN_VID_MASK, active_vlans)) 51862306a36Sopenharmony_ci __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci if (ixgbevf_test_staterr(rx_desc, IXGBE_RXDADV_STAT_SECP)) 52262306a36Sopenharmony_ci ixgbevf_ipsec_rx(rx_ring, rx_desc, skb); 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci skb->protocol = eth_type_trans(skb, rx_ring->netdev); 52562306a36Sopenharmony_ci} 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cistatic 52862306a36Sopenharmony_cistruct ixgbevf_rx_buffer *ixgbevf_get_rx_buffer(struct ixgbevf_ring *rx_ring, 52962306a36Sopenharmony_ci const unsigned int size) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci struct ixgbevf_rx_buffer *rx_buffer; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; 53462306a36Sopenharmony_ci prefetchw(rx_buffer->page); 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci /* we are reusing so sync this buffer for CPU use */ 53762306a36Sopenharmony_ci dma_sync_single_range_for_cpu(rx_ring->dev, 53862306a36Sopenharmony_ci rx_buffer->dma, 53962306a36Sopenharmony_ci rx_buffer->page_offset, 54062306a36Sopenharmony_ci size, 54162306a36Sopenharmony_ci DMA_FROM_DEVICE); 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci rx_buffer->pagecnt_bias--; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci return rx_buffer; 54662306a36Sopenharmony_ci} 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistatic void ixgbevf_put_rx_buffer(struct ixgbevf_ring *rx_ring, 54962306a36Sopenharmony_ci struct ixgbevf_rx_buffer *rx_buffer, 55062306a36Sopenharmony_ci struct sk_buff *skb) 55162306a36Sopenharmony_ci{ 55262306a36Sopenharmony_ci if (ixgbevf_can_reuse_rx_page(rx_buffer)) { 55362306a36Sopenharmony_ci /* hand second half of page back to the ring */ 55462306a36Sopenharmony_ci ixgbevf_reuse_rx_page(rx_ring, rx_buffer); 55562306a36Sopenharmony_ci } else { 55662306a36Sopenharmony_ci if (IS_ERR(skb)) 55762306a36Sopenharmony_ci /* We are not reusing the buffer so unmap it and free 55862306a36Sopenharmony_ci * any references we are holding to it 55962306a36Sopenharmony_ci */ 56062306a36Sopenharmony_ci dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma, 56162306a36Sopenharmony_ci ixgbevf_rx_pg_size(rx_ring), 56262306a36Sopenharmony_ci DMA_FROM_DEVICE, 56362306a36Sopenharmony_ci IXGBEVF_RX_DMA_ATTR); 56462306a36Sopenharmony_ci __page_frag_cache_drain(rx_buffer->page, 56562306a36Sopenharmony_ci rx_buffer->pagecnt_bias); 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci /* clear contents of rx_buffer */ 56962306a36Sopenharmony_ci rx_buffer->page = NULL; 57062306a36Sopenharmony_ci} 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci/** 57362306a36Sopenharmony_ci * ixgbevf_is_non_eop - process handling of non-EOP buffers 57462306a36Sopenharmony_ci * @rx_ring: Rx ring being processed 57562306a36Sopenharmony_ci * @rx_desc: Rx descriptor for current buffer 57662306a36Sopenharmony_ci * 57762306a36Sopenharmony_ci * This function updates next to clean. If the buffer is an EOP buffer 57862306a36Sopenharmony_ci * this function exits returning false, otherwise it will place the 57962306a36Sopenharmony_ci * sk_buff in the next buffer to be chained and return true indicating 58062306a36Sopenharmony_ci * that this is in fact a non-EOP buffer. 58162306a36Sopenharmony_ci **/ 58262306a36Sopenharmony_cistatic bool ixgbevf_is_non_eop(struct ixgbevf_ring *rx_ring, 58362306a36Sopenharmony_ci union ixgbe_adv_rx_desc *rx_desc) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci u32 ntc = rx_ring->next_to_clean + 1; 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci /* fetch, update, and store next to clean */ 58862306a36Sopenharmony_ci ntc = (ntc < rx_ring->count) ? ntc : 0; 58962306a36Sopenharmony_ci rx_ring->next_to_clean = ntc; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci prefetch(IXGBEVF_RX_DESC(rx_ring, ntc)); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci if (likely(ixgbevf_test_staterr(rx_desc, IXGBE_RXD_STAT_EOP))) 59462306a36Sopenharmony_ci return false; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci return true; 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_cistatic inline unsigned int ixgbevf_rx_offset(struct ixgbevf_ring *rx_ring) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci return ring_uses_build_skb(rx_ring) ? IXGBEVF_SKB_PAD : 0; 60262306a36Sopenharmony_ci} 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_cistatic bool ixgbevf_alloc_mapped_page(struct ixgbevf_ring *rx_ring, 60562306a36Sopenharmony_ci struct ixgbevf_rx_buffer *bi) 60662306a36Sopenharmony_ci{ 60762306a36Sopenharmony_ci struct page *page = bi->page; 60862306a36Sopenharmony_ci dma_addr_t dma; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci /* since we are recycling buffers we should seldom need to alloc */ 61162306a36Sopenharmony_ci if (likely(page)) 61262306a36Sopenharmony_ci return true; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci /* alloc new page for storage */ 61562306a36Sopenharmony_ci page = dev_alloc_pages(ixgbevf_rx_pg_order(rx_ring)); 61662306a36Sopenharmony_ci if (unlikely(!page)) { 61762306a36Sopenharmony_ci rx_ring->rx_stats.alloc_rx_page_failed++; 61862306a36Sopenharmony_ci return false; 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci /* map page for use */ 62262306a36Sopenharmony_ci dma = dma_map_page_attrs(rx_ring->dev, page, 0, 62362306a36Sopenharmony_ci ixgbevf_rx_pg_size(rx_ring), 62462306a36Sopenharmony_ci DMA_FROM_DEVICE, IXGBEVF_RX_DMA_ATTR); 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci /* if mapping failed free memory back to system since 62762306a36Sopenharmony_ci * there isn't much point in holding memory we can't use 62862306a36Sopenharmony_ci */ 62962306a36Sopenharmony_ci if (dma_mapping_error(rx_ring->dev, dma)) { 63062306a36Sopenharmony_ci __free_pages(page, ixgbevf_rx_pg_order(rx_ring)); 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci rx_ring->rx_stats.alloc_rx_page_failed++; 63362306a36Sopenharmony_ci return false; 63462306a36Sopenharmony_ci } 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci bi->dma = dma; 63762306a36Sopenharmony_ci bi->page = page; 63862306a36Sopenharmony_ci bi->page_offset = ixgbevf_rx_offset(rx_ring); 63962306a36Sopenharmony_ci bi->pagecnt_bias = 1; 64062306a36Sopenharmony_ci rx_ring->rx_stats.alloc_rx_page++; 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci return true; 64362306a36Sopenharmony_ci} 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci/** 64662306a36Sopenharmony_ci * ixgbevf_alloc_rx_buffers - Replace used receive buffers; packet split 64762306a36Sopenharmony_ci * @rx_ring: rx descriptor ring (for a specific queue) to setup buffers on 64862306a36Sopenharmony_ci * @cleaned_count: number of buffers to replace 64962306a36Sopenharmony_ci **/ 65062306a36Sopenharmony_cistatic void ixgbevf_alloc_rx_buffers(struct ixgbevf_ring *rx_ring, 65162306a36Sopenharmony_ci u16 cleaned_count) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci union ixgbe_adv_rx_desc *rx_desc; 65462306a36Sopenharmony_ci struct ixgbevf_rx_buffer *bi; 65562306a36Sopenharmony_ci unsigned int i = rx_ring->next_to_use; 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci /* nothing to do or no valid netdev defined */ 65862306a36Sopenharmony_ci if (!cleaned_count || !rx_ring->netdev) 65962306a36Sopenharmony_ci return; 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci rx_desc = IXGBEVF_RX_DESC(rx_ring, i); 66262306a36Sopenharmony_ci bi = &rx_ring->rx_buffer_info[i]; 66362306a36Sopenharmony_ci i -= rx_ring->count; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci do { 66662306a36Sopenharmony_ci if (!ixgbevf_alloc_mapped_page(rx_ring, bi)) 66762306a36Sopenharmony_ci break; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci /* sync the buffer for use by the device */ 67062306a36Sopenharmony_ci dma_sync_single_range_for_device(rx_ring->dev, bi->dma, 67162306a36Sopenharmony_ci bi->page_offset, 67262306a36Sopenharmony_ci ixgbevf_rx_bufsz(rx_ring), 67362306a36Sopenharmony_ci DMA_FROM_DEVICE); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* Refresh the desc even if pkt_addr didn't change 67662306a36Sopenharmony_ci * because each write-back erases this info. 67762306a36Sopenharmony_ci */ 67862306a36Sopenharmony_ci rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci rx_desc++; 68162306a36Sopenharmony_ci bi++; 68262306a36Sopenharmony_ci i++; 68362306a36Sopenharmony_ci if (unlikely(!i)) { 68462306a36Sopenharmony_ci rx_desc = IXGBEVF_RX_DESC(rx_ring, 0); 68562306a36Sopenharmony_ci bi = rx_ring->rx_buffer_info; 68662306a36Sopenharmony_ci i -= rx_ring->count; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_ci /* clear the length for the next_to_use descriptor */ 69062306a36Sopenharmony_ci rx_desc->wb.upper.length = 0; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci cleaned_count--; 69362306a36Sopenharmony_ci } while (cleaned_count); 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci i += rx_ring->count; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci if (rx_ring->next_to_use != i) { 69862306a36Sopenharmony_ci /* record the next descriptor to use */ 69962306a36Sopenharmony_ci rx_ring->next_to_use = i; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci /* update next to alloc since we have filled the ring */ 70262306a36Sopenharmony_ci rx_ring->next_to_alloc = i; 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci /* Force memory writes to complete before letting h/w 70562306a36Sopenharmony_ci * know there are new descriptors to fetch. (Only 70662306a36Sopenharmony_ci * applicable for weak-ordered memory model archs, 70762306a36Sopenharmony_ci * such as IA-64). 70862306a36Sopenharmony_ci */ 70962306a36Sopenharmony_ci wmb(); 71062306a36Sopenharmony_ci ixgbevf_write_tail(rx_ring, i); 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci} 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci/** 71562306a36Sopenharmony_ci * ixgbevf_cleanup_headers - Correct corrupted or empty headers 71662306a36Sopenharmony_ci * @rx_ring: rx descriptor ring packet is being transacted on 71762306a36Sopenharmony_ci * @rx_desc: pointer to the EOP Rx descriptor 71862306a36Sopenharmony_ci * @skb: pointer to current skb being fixed 71962306a36Sopenharmony_ci * 72062306a36Sopenharmony_ci * Check for corrupted packet headers caused by senders on the local L2 72162306a36Sopenharmony_ci * embedded NIC switch not setting up their Tx Descriptors right. These 72262306a36Sopenharmony_ci * should be very rare. 72362306a36Sopenharmony_ci * 72462306a36Sopenharmony_ci * Also address the case where we are pulling data in on pages only 72562306a36Sopenharmony_ci * and as such no data is present in the skb header. 72662306a36Sopenharmony_ci * 72762306a36Sopenharmony_ci * In addition if skb is not at least 60 bytes we need to pad it so that 72862306a36Sopenharmony_ci * it is large enough to qualify as a valid Ethernet frame. 72962306a36Sopenharmony_ci * 73062306a36Sopenharmony_ci * Returns true if an error was encountered and skb was freed. 73162306a36Sopenharmony_ci **/ 73262306a36Sopenharmony_cistatic bool ixgbevf_cleanup_headers(struct ixgbevf_ring *rx_ring, 73362306a36Sopenharmony_ci union ixgbe_adv_rx_desc *rx_desc, 73462306a36Sopenharmony_ci struct sk_buff *skb) 73562306a36Sopenharmony_ci{ 73662306a36Sopenharmony_ci /* XDP packets use error pointer so abort at this point */ 73762306a36Sopenharmony_ci if (IS_ERR(skb)) 73862306a36Sopenharmony_ci return true; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci /* verify that the packet does not have any known errors */ 74162306a36Sopenharmony_ci if (unlikely(ixgbevf_test_staterr(rx_desc, 74262306a36Sopenharmony_ci IXGBE_RXDADV_ERR_FRAME_ERR_MASK))) { 74362306a36Sopenharmony_ci struct net_device *netdev = rx_ring->netdev; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci if (!(netdev->features & NETIF_F_RXALL)) { 74662306a36Sopenharmony_ci dev_kfree_skb_any(skb); 74762306a36Sopenharmony_ci return true; 74862306a36Sopenharmony_ci } 74962306a36Sopenharmony_ci } 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci /* if eth_skb_pad returns an error the skb was freed */ 75262306a36Sopenharmony_ci if (eth_skb_pad(skb)) 75362306a36Sopenharmony_ci return true; 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci return false; 75662306a36Sopenharmony_ci} 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci/** 75962306a36Sopenharmony_ci * ixgbevf_reuse_rx_page - page flip buffer and store it back on the ring 76062306a36Sopenharmony_ci * @rx_ring: rx descriptor ring to store buffers on 76162306a36Sopenharmony_ci * @old_buff: donor buffer to have page reused 76262306a36Sopenharmony_ci * 76362306a36Sopenharmony_ci * Synchronizes page for reuse by the adapter 76462306a36Sopenharmony_ci **/ 76562306a36Sopenharmony_cistatic void ixgbevf_reuse_rx_page(struct ixgbevf_ring *rx_ring, 76662306a36Sopenharmony_ci struct ixgbevf_rx_buffer *old_buff) 76762306a36Sopenharmony_ci{ 76862306a36Sopenharmony_ci struct ixgbevf_rx_buffer *new_buff; 76962306a36Sopenharmony_ci u16 nta = rx_ring->next_to_alloc; 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci new_buff = &rx_ring->rx_buffer_info[nta]; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci /* update, and store next to alloc */ 77462306a36Sopenharmony_ci nta++; 77562306a36Sopenharmony_ci rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci /* transfer page from old buffer to new buffer */ 77862306a36Sopenharmony_ci new_buff->page = old_buff->page; 77962306a36Sopenharmony_ci new_buff->dma = old_buff->dma; 78062306a36Sopenharmony_ci new_buff->page_offset = old_buff->page_offset; 78162306a36Sopenharmony_ci new_buff->pagecnt_bias = old_buff->pagecnt_bias; 78262306a36Sopenharmony_ci} 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_cistatic bool ixgbevf_can_reuse_rx_page(struct ixgbevf_rx_buffer *rx_buffer) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci unsigned int pagecnt_bias = rx_buffer->pagecnt_bias; 78762306a36Sopenharmony_ci struct page *page = rx_buffer->page; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci /* avoid re-using remote and pfmemalloc pages */ 79062306a36Sopenharmony_ci if (!dev_page_is_reusable(page)) 79162306a36Sopenharmony_ci return false; 79262306a36Sopenharmony_ci 79362306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 79462306a36Sopenharmony_ci /* if we are only owner of page we can reuse it */ 79562306a36Sopenharmony_ci if (unlikely((page_ref_count(page) - pagecnt_bias) > 1)) 79662306a36Sopenharmony_ci return false; 79762306a36Sopenharmony_ci#else 79862306a36Sopenharmony_ci#define IXGBEVF_LAST_OFFSET \ 79962306a36Sopenharmony_ci (SKB_WITH_OVERHEAD(PAGE_SIZE) - IXGBEVF_RXBUFFER_2048) 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci if (rx_buffer->page_offset > IXGBEVF_LAST_OFFSET) 80262306a36Sopenharmony_ci return false; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci#endif 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci /* If we have drained the page fragment pool we need to update 80762306a36Sopenharmony_ci * the pagecnt_bias and page count so that we fully restock the 80862306a36Sopenharmony_ci * number of references the driver holds. 80962306a36Sopenharmony_ci */ 81062306a36Sopenharmony_ci if (unlikely(!pagecnt_bias)) { 81162306a36Sopenharmony_ci page_ref_add(page, USHRT_MAX); 81262306a36Sopenharmony_ci rx_buffer->pagecnt_bias = USHRT_MAX; 81362306a36Sopenharmony_ci } 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci return true; 81662306a36Sopenharmony_ci} 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci/** 81962306a36Sopenharmony_ci * ixgbevf_add_rx_frag - Add contents of Rx buffer to sk_buff 82062306a36Sopenharmony_ci * @rx_ring: rx descriptor ring to transact packets on 82162306a36Sopenharmony_ci * @rx_buffer: buffer containing page to add 82262306a36Sopenharmony_ci * @skb: sk_buff to place the data into 82362306a36Sopenharmony_ci * @size: size of buffer to be added 82462306a36Sopenharmony_ci * 82562306a36Sopenharmony_ci * This function will add the data contained in rx_buffer->page to the skb. 82662306a36Sopenharmony_ci **/ 82762306a36Sopenharmony_cistatic void ixgbevf_add_rx_frag(struct ixgbevf_ring *rx_ring, 82862306a36Sopenharmony_ci struct ixgbevf_rx_buffer *rx_buffer, 82962306a36Sopenharmony_ci struct sk_buff *skb, 83062306a36Sopenharmony_ci unsigned int size) 83162306a36Sopenharmony_ci{ 83262306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 83362306a36Sopenharmony_ci unsigned int truesize = ixgbevf_rx_pg_size(rx_ring) / 2; 83462306a36Sopenharmony_ci#else 83562306a36Sopenharmony_ci unsigned int truesize = ring_uses_build_skb(rx_ring) ? 83662306a36Sopenharmony_ci SKB_DATA_ALIGN(IXGBEVF_SKB_PAD + size) : 83762306a36Sopenharmony_ci SKB_DATA_ALIGN(size); 83862306a36Sopenharmony_ci#endif 83962306a36Sopenharmony_ci skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page, 84062306a36Sopenharmony_ci rx_buffer->page_offset, size, truesize); 84162306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 84262306a36Sopenharmony_ci rx_buffer->page_offset ^= truesize; 84362306a36Sopenharmony_ci#else 84462306a36Sopenharmony_ci rx_buffer->page_offset += truesize; 84562306a36Sopenharmony_ci#endif 84662306a36Sopenharmony_ci} 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_cistatic 84962306a36Sopenharmony_cistruct sk_buff *ixgbevf_construct_skb(struct ixgbevf_ring *rx_ring, 85062306a36Sopenharmony_ci struct ixgbevf_rx_buffer *rx_buffer, 85162306a36Sopenharmony_ci struct xdp_buff *xdp, 85262306a36Sopenharmony_ci union ixgbe_adv_rx_desc *rx_desc) 85362306a36Sopenharmony_ci{ 85462306a36Sopenharmony_ci unsigned int size = xdp->data_end - xdp->data; 85562306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 85662306a36Sopenharmony_ci unsigned int truesize = ixgbevf_rx_pg_size(rx_ring) / 2; 85762306a36Sopenharmony_ci#else 85862306a36Sopenharmony_ci unsigned int truesize = SKB_DATA_ALIGN(xdp->data_end - 85962306a36Sopenharmony_ci xdp->data_hard_start); 86062306a36Sopenharmony_ci#endif 86162306a36Sopenharmony_ci unsigned int headlen; 86262306a36Sopenharmony_ci struct sk_buff *skb; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci /* prefetch first cache line of first page */ 86562306a36Sopenharmony_ci net_prefetch(xdp->data); 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_ci /* Note, we get here by enabling legacy-rx via: 86862306a36Sopenharmony_ci * 86962306a36Sopenharmony_ci * ethtool --set-priv-flags <dev> legacy-rx on 87062306a36Sopenharmony_ci * 87162306a36Sopenharmony_ci * In this mode, we currently get 0 extra XDP headroom as 87262306a36Sopenharmony_ci * opposed to having legacy-rx off, where we process XDP 87362306a36Sopenharmony_ci * packets going to stack via ixgbevf_build_skb(). 87462306a36Sopenharmony_ci * 87562306a36Sopenharmony_ci * For ixgbevf_construct_skb() mode it means that the 87662306a36Sopenharmony_ci * xdp->data_meta will always point to xdp->data, since 87762306a36Sopenharmony_ci * the helper cannot expand the head. Should this ever 87862306a36Sopenharmony_ci * changed in future for legacy-rx mode on, then lets also 87962306a36Sopenharmony_ci * add xdp->data_meta handling here. 88062306a36Sopenharmony_ci */ 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci /* allocate a skb to store the frags */ 88362306a36Sopenharmony_ci skb = napi_alloc_skb(&rx_ring->q_vector->napi, IXGBEVF_RX_HDR_SIZE); 88462306a36Sopenharmony_ci if (unlikely(!skb)) 88562306a36Sopenharmony_ci return NULL; 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci /* Determine available headroom for copy */ 88862306a36Sopenharmony_ci headlen = size; 88962306a36Sopenharmony_ci if (headlen > IXGBEVF_RX_HDR_SIZE) 89062306a36Sopenharmony_ci headlen = eth_get_headlen(skb->dev, xdp->data, 89162306a36Sopenharmony_ci IXGBEVF_RX_HDR_SIZE); 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci /* align pull length to size of long to optimize memcpy performance */ 89462306a36Sopenharmony_ci memcpy(__skb_put(skb, headlen), xdp->data, 89562306a36Sopenharmony_ci ALIGN(headlen, sizeof(long))); 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci /* update all of the pointers */ 89862306a36Sopenharmony_ci size -= headlen; 89962306a36Sopenharmony_ci if (size) { 90062306a36Sopenharmony_ci skb_add_rx_frag(skb, 0, rx_buffer->page, 90162306a36Sopenharmony_ci (xdp->data + headlen) - 90262306a36Sopenharmony_ci page_address(rx_buffer->page), 90362306a36Sopenharmony_ci size, truesize); 90462306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 90562306a36Sopenharmony_ci rx_buffer->page_offset ^= truesize; 90662306a36Sopenharmony_ci#else 90762306a36Sopenharmony_ci rx_buffer->page_offset += truesize; 90862306a36Sopenharmony_ci#endif 90962306a36Sopenharmony_ci } else { 91062306a36Sopenharmony_ci rx_buffer->pagecnt_bias++; 91162306a36Sopenharmony_ci } 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci return skb; 91462306a36Sopenharmony_ci} 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_cistatic inline void ixgbevf_irq_enable_queues(struct ixgbevf_adapter *adapter, 91762306a36Sopenharmony_ci u32 qmask) 91862306a36Sopenharmony_ci{ 91962306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, qmask); 92262306a36Sopenharmony_ci} 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_cistatic struct sk_buff *ixgbevf_build_skb(struct ixgbevf_ring *rx_ring, 92562306a36Sopenharmony_ci struct ixgbevf_rx_buffer *rx_buffer, 92662306a36Sopenharmony_ci struct xdp_buff *xdp, 92762306a36Sopenharmony_ci union ixgbe_adv_rx_desc *rx_desc) 92862306a36Sopenharmony_ci{ 92962306a36Sopenharmony_ci unsigned int metasize = xdp->data - xdp->data_meta; 93062306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 93162306a36Sopenharmony_ci unsigned int truesize = ixgbevf_rx_pg_size(rx_ring) / 2; 93262306a36Sopenharmony_ci#else 93362306a36Sopenharmony_ci unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + 93462306a36Sopenharmony_ci SKB_DATA_ALIGN(xdp->data_end - 93562306a36Sopenharmony_ci xdp->data_hard_start); 93662306a36Sopenharmony_ci#endif 93762306a36Sopenharmony_ci struct sk_buff *skb; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci /* Prefetch first cache line of first page. If xdp->data_meta 94062306a36Sopenharmony_ci * is unused, this points to xdp->data, otherwise, we likely 94162306a36Sopenharmony_ci * have a consumer accessing first few bytes of meta data, 94262306a36Sopenharmony_ci * and then actual data. 94362306a36Sopenharmony_ci */ 94462306a36Sopenharmony_ci net_prefetch(xdp->data_meta); 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci /* build an skb around the page buffer */ 94762306a36Sopenharmony_ci skb = napi_build_skb(xdp->data_hard_start, truesize); 94862306a36Sopenharmony_ci if (unlikely(!skb)) 94962306a36Sopenharmony_ci return NULL; 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci /* update pointers within the skb to store the data */ 95262306a36Sopenharmony_ci skb_reserve(skb, xdp->data - xdp->data_hard_start); 95362306a36Sopenharmony_ci __skb_put(skb, xdp->data_end - xdp->data); 95462306a36Sopenharmony_ci if (metasize) 95562306a36Sopenharmony_ci skb_metadata_set(skb, metasize); 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci /* update buffer offset */ 95862306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 95962306a36Sopenharmony_ci rx_buffer->page_offset ^= truesize; 96062306a36Sopenharmony_ci#else 96162306a36Sopenharmony_ci rx_buffer->page_offset += truesize; 96262306a36Sopenharmony_ci#endif 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci return skb; 96562306a36Sopenharmony_ci} 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci#define IXGBEVF_XDP_PASS 0 96862306a36Sopenharmony_ci#define IXGBEVF_XDP_CONSUMED 1 96962306a36Sopenharmony_ci#define IXGBEVF_XDP_TX 2 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_cistatic int ixgbevf_xmit_xdp_ring(struct ixgbevf_ring *ring, 97262306a36Sopenharmony_ci struct xdp_buff *xdp) 97362306a36Sopenharmony_ci{ 97462306a36Sopenharmony_ci struct ixgbevf_tx_buffer *tx_buffer; 97562306a36Sopenharmony_ci union ixgbe_adv_tx_desc *tx_desc; 97662306a36Sopenharmony_ci u32 len, cmd_type; 97762306a36Sopenharmony_ci dma_addr_t dma; 97862306a36Sopenharmony_ci u16 i; 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci len = xdp->data_end - xdp->data; 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci if (unlikely(!ixgbevf_desc_unused(ring))) 98362306a36Sopenharmony_ci return IXGBEVF_XDP_CONSUMED; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci dma = dma_map_single(ring->dev, xdp->data, len, DMA_TO_DEVICE); 98662306a36Sopenharmony_ci if (dma_mapping_error(ring->dev, dma)) 98762306a36Sopenharmony_ci return IXGBEVF_XDP_CONSUMED; 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci /* record the location of the first descriptor for this packet */ 99062306a36Sopenharmony_ci i = ring->next_to_use; 99162306a36Sopenharmony_ci tx_buffer = &ring->tx_buffer_info[i]; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, len); 99462306a36Sopenharmony_ci dma_unmap_addr_set(tx_buffer, dma, dma); 99562306a36Sopenharmony_ci tx_buffer->data = xdp->data; 99662306a36Sopenharmony_ci tx_buffer->bytecount = len; 99762306a36Sopenharmony_ci tx_buffer->gso_segs = 1; 99862306a36Sopenharmony_ci tx_buffer->protocol = 0; 99962306a36Sopenharmony_ci 100062306a36Sopenharmony_ci /* Populate minimal context descriptor that will provide for the 100162306a36Sopenharmony_ci * fact that we are expected to process Ethernet frames. 100262306a36Sopenharmony_ci */ 100362306a36Sopenharmony_ci if (!test_bit(__IXGBEVF_TX_XDP_RING_PRIMED, &ring->state)) { 100462306a36Sopenharmony_ci struct ixgbe_adv_tx_context_desc *context_desc; 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci set_bit(__IXGBEVF_TX_XDP_RING_PRIMED, &ring->state); 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci context_desc = IXGBEVF_TX_CTXTDESC(ring, 0); 100962306a36Sopenharmony_ci context_desc->vlan_macip_lens = 101062306a36Sopenharmony_ci cpu_to_le32(ETH_HLEN << IXGBE_ADVTXD_MACLEN_SHIFT); 101162306a36Sopenharmony_ci context_desc->fceof_saidx = 0; 101262306a36Sopenharmony_ci context_desc->type_tucmd_mlhl = 101362306a36Sopenharmony_ci cpu_to_le32(IXGBE_TXD_CMD_DEXT | 101462306a36Sopenharmony_ci IXGBE_ADVTXD_DTYP_CTXT); 101562306a36Sopenharmony_ci context_desc->mss_l4len_idx = 0; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci i = 1; 101862306a36Sopenharmony_ci } 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci /* put descriptor type bits */ 102162306a36Sopenharmony_ci cmd_type = IXGBE_ADVTXD_DTYP_DATA | 102262306a36Sopenharmony_ci IXGBE_ADVTXD_DCMD_DEXT | 102362306a36Sopenharmony_ci IXGBE_ADVTXD_DCMD_IFCS; 102462306a36Sopenharmony_ci cmd_type |= len | IXGBE_TXD_CMD; 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci tx_desc = IXGBEVF_TX_DESC(ring, i); 102762306a36Sopenharmony_ci tx_desc->read.buffer_addr = cpu_to_le64(dma); 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); 103062306a36Sopenharmony_ci tx_desc->read.olinfo_status = 103162306a36Sopenharmony_ci cpu_to_le32((len << IXGBE_ADVTXD_PAYLEN_SHIFT) | 103262306a36Sopenharmony_ci IXGBE_ADVTXD_CC); 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci /* Avoid any potential race with cleanup */ 103562306a36Sopenharmony_ci smp_wmb(); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci /* set next_to_watch value indicating a packet is present */ 103862306a36Sopenharmony_ci i++; 103962306a36Sopenharmony_ci if (i == ring->count) 104062306a36Sopenharmony_ci i = 0; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci tx_buffer->next_to_watch = tx_desc; 104362306a36Sopenharmony_ci ring->next_to_use = i; 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_ci return IXGBEVF_XDP_TX; 104662306a36Sopenharmony_ci} 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_cistatic struct sk_buff *ixgbevf_run_xdp(struct ixgbevf_adapter *adapter, 104962306a36Sopenharmony_ci struct ixgbevf_ring *rx_ring, 105062306a36Sopenharmony_ci struct xdp_buff *xdp) 105162306a36Sopenharmony_ci{ 105262306a36Sopenharmony_ci int result = IXGBEVF_XDP_PASS; 105362306a36Sopenharmony_ci struct ixgbevf_ring *xdp_ring; 105462306a36Sopenharmony_ci struct bpf_prog *xdp_prog; 105562306a36Sopenharmony_ci u32 act; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci xdp_prog = READ_ONCE(rx_ring->xdp_prog); 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci if (!xdp_prog) 106062306a36Sopenharmony_ci goto xdp_out; 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci act = bpf_prog_run_xdp(xdp_prog, xdp); 106362306a36Sopenharmony_ci switch (act) { 106462306a36Sopenharmony_ci case XDP_PASS: 106562306a36Sopenharmony_ci break; 106662306a36Sopenharmony_ci case XDP_TX: 106762306a36Sopenharmony_ci xdp_ring = adapter->xdp_ring[rx_ring->queue_index]; 106862306a36Sopenharmony_ci result = ixgbevf_xmit_xdp_ring(xdp_ring, xdp); 106962306a36Sopenharmony_ci if (result == IXGBEVF_XDP_CONSUMED) 107062306a36Sopenharmony_ci goto out_failure; 107162306a36Sopenharmony_ci break; 107262306a36Sopenharmony_ci default: 107362306a36Sopenharmony_ci bpf_warn_invalid_xdp_action(rx_ring->netdev, xdp_prog, act); 107462306a36Sopenharmony_ci fallthrough; 107562306a36Sopenharmony_ci case XDP_ABORTED: 107662306a36Sopenharmony_ciout_failure: 107762306a36Sopenharmony_ci trace_xdp_exception(rx_ring->netdev, xdp_prog, act); 107862306a36Sopenharmony_ci fallthrough; /* handle aborts by dropping packet */ 107962306a36Sopenharmony_ci case XDP_DROP: 108062306a36Sopenharmony_ci result = IXGBEVF_XDP_CONSUMED; 108162306a36Sopenharmony_ci break; 108262306a36Sopenharmony_ci } 108362306a36Sopenharmony_cixdp_out: 108462306a36Sopenharmony_ci return ERR_PTR(-result); 108562306a36Sopenharmony_ci} 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_cistatic unsigned int ixgbevf_rx_frame_truesize(struct ixgbevf_ring *rx_ring, 108862306a36Sopenharmony_ci unsigned int size) 108962306a36Sopenharmony_ci{ 109062306a36Sopenharmony_ci unsigned int truesize; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 109362306a36Sopenharmony_ci truesize = ixgbevf_rx_pg_size(rx_ring) / 2; /* Must be power-of-2 */ 109462306a36Sopenharmony_ci#else 109562306a36Sopenharmony_ci truesize = ring_uses_build_skb(rx_ring) ? 109662306a36Sopenharmony_ci SKB_DATA_ALIGN(IXGBEVF_SKB_PAD + size) + 109762306a36Sopenharmony_ci SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : 109862306a36Sopenharmony_ci SKB_DATA_ALIGN(size); 109962306a36Sopenharmony_ci#endif 110062306a36Sopenharmony_ci return truesize; 110162306a36Sopenharmony_ci} 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_cistatic void ixgbevf_rx_buffer_flip(struct ixgbevf_ring *rx_ring, 110462306a36Sopenharmony_ci struct ixgbevf_rx_buffer *rx_buffer, 110562306a36Sopenharmony_ci unsigned int size) 110662306a36Sopenharmony_ci{ 110762306a36Sopenharmony_ci unsigned int truesize = ixgbevf_rx_frame_truesize(rx_ring, size); 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 111062306a36Sopenharmony_ci rx_buffer->page_offset ^= truesize; 111162306a36Sopenharmony_ci#else 111262306a36Sopenharmony_ci rx_buffer->page_offset += truesize; 111362306a36Sopenharmony_ci#endif 111462306a36Sopenharmony_ci} 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_cistatic int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector, 111762306a36Sopenharmony_ci struct ixgbevf_ring *rx_ring, 111862306a36Sopenharmony_ci int budget) 111962306a36Sopenharmony_ci{ 112062306a36Sopenharmony_ci unsigned int total_rx_bytes = 0, total_rx_packets = 0, frame_sz = 0; 112162306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = q_vector->adapter; 112262306a36Sopenharmony_ci u16 cleaned_count = ixgbevf_desc_unused(rx_ring); 112362306a36Sopenharmony_ci struct sk_buff *skb = rx_ring->skb; 112462306a36Sopenharmony_ci bool xdp_xmit = false; 112562306a36Sopenharmony_ci struct xdp_buff xdp; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci /* Frame size depend on rx_ring setup when PAGE_SIZE=4K */ 112862306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 112962306a36Sopenharmony_ci frame_sz = ixgbevf_rx_frame_truesize(rx_ring, 0); 113062306a36Sopenharmony_ci#endif 113162306a36Sopenharmony_ci xdp_init_buff(&xdp, frame_sz, &rx_ring->xdp_rxq); 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci while (likely(total_rx_packets < budget)) { 113462306a36Sopenharmony_ci struct ixgbevf_rx_buffer *rx_buffer; 113562306a36Sopenharmony_ci union ixgbe_adv_rx_desc *rx_desc; 113662306a36Sopenharmony_ci unsigned int size; 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci /* return some buffers to hardware, one at a time is too slow */ 113962306a36Sopenharmony_ci if (cleaned_count >= IXGBEVF_RX_BUFFER_WRITE) { 114062306a36Sopenharmony_ci ixgbevf_alloc_rx_buffers(rx_ring, cleaned_count); 114162306a36Sopenharmony_ci cleaned_count = 0; 114262306a36Sopenharmony_ci } 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci rx_desc = IXGBEVF_RX_DESC(rx_ring, rx_ring->next_to_clean); 114562306a36Sopenharmony_ci size = le16_to_cpu(rx_desc->wb.upper.length); 114662306a36Sopenharmony_ci if (!size) 114762306a36Sopenharmony_ci break; 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci /* This memory barrier is needed to keep us from reading 115062306a36Sopenharmony_ci * any other fields out of the rx_desc until we know the 115162306a36Sopenharmony_ci * RXD_STAT_DD bit is set 115262306a36Sopenharmony_ci */ 115362306a36Sopenharmony_ci rmb(); 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ci rx_buffer = ixgbevf_get_rx_buffer(rx_ring, size); 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci /* retrieve a buffer from the ring */ 115862306a36Sopenharmony_ci if (!skb) { 115962306a36Sopenharmony_ci unsigned int offset = ixgbevf_rx_offset(rx_ring); 116062306a36Sopenharmony_ci unsigned char *hard_start; 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci hard_start = page_address(rx_buffer->page) + 116362306a36Sopenharmony_ci rx_buffer->page_offset - offset; 116462306a36Sopenharmony_ci xdp_prepare_buff(&xdp, hard_start, offset, size, true); 116562306a36Sopenharmony_ci#if (PAGE_SIZE > 4096) 116662306a36Sopenharmony_ci /* At larger PAGE_SIZE, frame_sz depend on len size */ 116762306a36Sopenharmony_ci xdp.frame_sz = ixgbevf_rx_frame_truesize(rx_ring, size); 116862306a36Sopenharmony_ci#endif 116962306a36Sopenharmony_ci skb = ixgbevf_run_xdp(adapter, rx_ring, &xdp); 117062306a36Sopenharmony_ci } 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci if (IS_ERR(skb)) { 117362306a36Sopenharmony_ci if (PTR_ERR(skb) == -IXGBEVF_XDP_TX) { 117462306a36Sopenharmony_ci xdp_xmit = true; 117562306a36Sopenharmony_ci ixgbevf_rx_buffer_flip(rx_ring, rx_buffer, 117662306a36Sopenharmony_ci size); 117762306a36Sopenharmony_ci } else { 117862306a36Sopenharmony_ci rx_buffer->pagecnt_bias++; 117962306a36Sopenharmony_ci } 118062306a36Sopenharmony_ci total_rx_packets++; 118162306a36Sopenharmony_ci total_rx_bytes += size; 118262306a36Sopenharmony_ci } else if (skb) { 118362306a36Sopenharmony_ci ixgbevf_add_rx_frag(rx_ring, rx_buffer, skb, size); 118462306a36Sopenharmony_ci } else if (ring_uses_build_skb(rx_ring)) { 118562306a36Sopenharmony_ci skb = ixgbevf_build_skb(rx_ring, rx_buffer, 118662306a36Sopenharmony_ci &xdp, rx_desc); 118762306a36Sopenharmony_ci } else { 118862306a36Sopenharmony_ci skb = ixgbevf_construct_skb(rx_ring, rx_buffer, 118962306a36Sopenharmony_ci &xdp, rx_desc); 119062306a36Sopenharmony_ci } 119162306a36Sopenharmony_ci 119262306a36Sopenharmony_ci /* exit if we failed to retrieve a buffer */ 119362306a36Sopenharmony_ci if (!skb) { 119462306a36Sopenharmony_ci rx_ring->rx_stats.alloc_rx_buff_failed++; 119562306a36Sopenharmony_ci rx_buffer->pagecnt_bias++; 119662306a36Sopenharmony_ci break; 119762306a36Sopenharmony_ci } 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci ixgbevf_put_rx_buffer(rx_ring, rx_buffer, skb); 120062306a36Sopenharmony_ci cleaned_count++; 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_ci /* fetch next buffer in frame if non-eop */ 120362306a36Sopenharmony_ci if (ixgbevf_is_non_eop(rx_ring, rx_desc)) 120462306a36Sopenharmony_ci continue; 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci /* verify the packet layout is correct */ 120762306a36Sopenharmony_ci if (ixgbevf_cleanup_headers(rx_ring, rx_desc, skb)) { 120862306a36Sopenharmony_ci skb = NULL; 120962306a36Sopenharmony_ci continue; 121062306a36Sopenharmony_ci } 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_ci /* probably a little skewed due to removing CRC */ 121362306a36Sopenharmony_ci total_rx_bytes += skb->len; 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci /* Workaround hardware that can't do proper VEPA multicast 121662306a36Sopenharmony_ci * source pruning. 121762306a36Sopenharmony_ci */ 121862306a36Sopenharmony_ci if ((skb->pkt_type == PACKET_BROADCAST || 121962306a36Sopenharmony_ci skb->pkt_type == PACKET_MULTICAST) && 122062306a36Sopenharmony_ci ether_addr_equal(rx_ring->netdev->dev_addr, 122162306a36Sopenharmony_ci eth_hdr(skb)->h_source)) { 122262306a36Sopenharmony_ci dev_kfree_skb_irq(skb); 122362306a36Sopenharmony_ci continue; 122462306a36Sopenharmony_ci } 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci /* populate checksum, VLAN, and protocol */ 122762306a36Sopenharmony_ci ixgbevf_process_skb_fields(rx_ring, rx_desc, skb); 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci ixgbevf_rx_skb(q_vector, skb); 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci /* reset skb pointer */ 123262306a36Sopenharmony_ci skb = NULL; 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci /* update budget accounting */ 123562306a36Sopenharmony_ci total_rx_packets++; 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci /* place incomplete frames back on ring for completion */ 123962306a36Sopenharmony_ci rx_ring->skb = skb; 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci if (xdp_xmit) { 124262306a36Sopenharmony_ci struct ixgbevf_ring *xdp_ring = 124362306a36Sopenharmony_ci adapter->xdp_ring[rx_ring->queue_index]; 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci /* Force memory writes to complete before letting h/w 124662306a36Sopenharmony_ci * know there are new descriptors to fetch. 124762306a36Sopenharmony_ci */ 124862306a36Sopenharmony_ci wmb(); 124962306a36Sopenharmony_ci ixgbevf_write_tail(xdp_ring, xdp_ring->next_to_use); 125062306a36Sopenharmony_ci } 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci u64_stats_update_begin(&rx_ring->syncp); 125362306a36Sopenharmony_ci rx_ring->stats.packets += total_rx_packets; 125462306a36Sopenharmony_ci rx_ring->stats.bytes += total_rx_bytes; 125562306a36Sopenharmony_ci u64_stats_update_end(&rx_ring->syncp); 125662306a36Sopenharmony_ci q_vector->rx.total_packets += total_rx_packets; 125762306a36Sopenharmony_ci q_vector->rx.total_bytes += total_rx_bytes; 125862306a36Sopenharmony_ci 125962306a36Sopenharmony_ci return total_rx_packets; 126062306a36Sopenharmony_ci} 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci/** 126362306a36Sopenharmony_ci * ixgbevf_poll - NAPI polling calback 126462306a36Sopenharmony_ci * @napi: napi struct with our devices info in it 126562306a36Sopenharmony_ci * @budget: amount of work driver is allowed to do this pass, in packets 126662306a36Sopenharmony_ci * 126762306a36Sopenharmony_ci * This function will clean more than one or more rings associated with a 126862306a36Sopenharmony_ci * q_vector. 126962306a36Sopenharmony_ci **/ 127062306a36Sopenharmony_cistatic int ixgbevf_poll(struct napi_struct *napi, int budget) 127162306a36Sopenharmony_ci{ 127262306a36Sopenharmony_ci struct ixgbevf_q_vector *q_vector = 127362306a36Sopenharmony_ci container_of(napi, struct ixgbevf_q_vector, napi); 127462306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = q_vector->adapter; 127562306a36Sopenharmony_ci struct ixgbevf_ring *ring; 127662306a36Sopenharmony_ci int per_ring_budget, work_done = 0; 127762306a36Sopenharmony_ci bool clean_complete = true; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci ixgbevf_for_each_ring(ring, q_vector->tx) { 128062306a36Sopenharmony_ci if (!ixgbevf_clean_tx_irq(q_vector, ring, budget)) 128162306a36Sopenharmony_ci clean_complete = false; 128262306a36Sopenharmony_ci } 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci if (budget <= 0) 128562306a36Sopenharmony_ci return budget; 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci /* attempt to distribute budget to each queue fairly, but don't allow 128862306a36Sopenharmony_ci * the budget to go below 1 because we'll exit polling 128962306a36Sopenharmony_ci */ 129062306a36Sopenharmony_ci if (q_vector->rx.count > 1) 129162306a36Sopenharmony_ci per_ring_budget = max(budget/q_vector->rx.count, 1); 129262306a36Sopenharmony_ci else 129362306a36Sopenharmony_ci per_ring_budget = budget; 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci ixgbevf_for_each_ring(ring, q_vector->rx) { 129662306a36Sopenharmony_ci int cleaned = ixgbevf_clean_rx_irq(q_vector, ring, 129762306a36Sopenharmony_ci per_ring_budget); 129862306a36Sopenharmony_ci work_done += cleaned; 129962306a36Sopenharmony_ci if (cleaned >= per_ring_budget) 130062306a36Sopenharmony_ci clean_complete = false; 130162306a36Sopenharmony_ci } 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci /* If all work not completed, return budget and keep polling */ 130462306a36Sopenharmony_ci if (!clean_complete) 130562306a36Sopenharmony_ci return budget; 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci /* Exit the polling mode, but don't re-enable interrupts if stack might 130862306a36Sopenharmony_ci * poll us due to busy-polling 130962306a36Sopenharmony_ci */ 131062306a36Sopenharmony_ci if (likely(napi_complete_done(napi, work_done))) { 131162306a36Sopenharmony_ci if (adapter->rx_itr_setting == 1) 131262306a36Sopenharmony_ci ixgbevf_set_itr(q_vector); 131362306a36Sopenharmony_ci if (!test_bit(__IXGBEVF_DOWN, &adapter->state) && 131462306a36Sopenharmony_ci !test_bit(__IXGBEVF_REMOVING, &adapter->state)) 131562306a36Sopenharmony_ci ixgbevf_irq_enable_queues(adapter, 131662306a36Sopenharmony_ci BIT(q_vector->v_idx)); 131762306a36Sopenharmony_ci } 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci return min(work_done, budget - 1); 132062306a36Sopenharmony_ci} 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci/** 132362306a36Sopenharmony_ci * ixgbevf_write_eitr - write VTEITR register in hardware specific way 132462306a36Sopenharmony_ci * @q_vector: structure containing interrupt and ring information 132562306a36Sopenharmony_ci **/ 132662306a36Sopenharmony_civoid ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector) 132762306a36Sopenharmony_ci{ 132862306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = q_vector->adapter; 132962306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 133062306a36Sopenharmony_ci int v_idx = q_vector->v_idx; 133162306a36Sopenharmony_ci u32 itr_reg = q_vector->itr & IXGBE_MAX_EITR; 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci /* set the WDIS bit to not clear the timer bits and cause an 133462306a36Sopenharmony_ci * immediate assertion of the interrupt 133562306a36Sopenharmony_ci */ 133662306a36Sopenharmony_ci itr_reg |= IXGBE_EITR_CNT_WDIS; 133762306a36Sopenharmony_ci 133862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTEITR(v_idx), itr_reg); 133962306a36Sopenharmony_ci} 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci/** 134262306a36Sopenharmony_ci * ixgbevf_configure_msix - Configure MSI-X hardware 134362306a36Sopenharmony_ci * @adapter: board private structure 134462306a36Sopenharmony_ci * 134562306a36Sopenharmony_ci * ixgbevf_configure_msix sets up the hardware to properly generate MSI-X 134662306a36Sopenharmony_ci * interrupts. 134762306a36Sopenharmony_ci **/ 134862306a36Sopenharmony_cistatic void ixgbevf_configure_msix(struct ixgbevf_adapter *adapter) 134962306a36Sopenharmony_ci{ 135062306a36Sopenharmony_ci struct ixgbevf_q_vector *q_vector; 135162306a36Sopenharmony_ci int q_vectors, v_idx; 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; 135462306a36Sopenharmony_ci adapter->eims_enable_mask = 0; 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci /* Populate the IVAR table and set the ITR values to the 135762306a36Sopenharmony_ci * corresponding register. 135862306a36Sopenharmony_ci */ 135962306a36Sopenharmony_ci for (v_idx = 0; v_idx < q_vectors; v_idx++) { 136062306a36Sopenharmony_ci struct ixgbevf_ring *ring; 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci q_vector = adapter->q_vector[v_idx]; 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci ixgbevf_for_each_ring(ring, q_vector->rx) 136562306a36Sopenharmony_ci ixgbevf_set_ivar(adapter, 0, ring->reg_idx, v_idx); 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci ixgbevf_for_each_ring(ring, q_vector->tx) 136862306a36Sopenharmony_ci ixgbevf_set_ivar(adapter, 1, ring->reg_idx, v_idx); 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci if (q_vector->tx.ring && !q_vector->rx.ring) { 137162306a36Sopenharmony_ci /* Tx only vector */ 137262306a36Sopenharmony_ci if (adapter->tx_itr_setting == 1) 137362306a36Sopenharmony_ci q_vector->itr = IXGBE_12K_ITR; 137462306a36Sopenharmony_ci else 137562306a36Sopenharmony_ci q_vector->itr = adapter->tx_itr_setting; 137662306a36Sopenharmony_ci } else { 137762306a36Sopenharmony_ci /* Rx or Rx/Tx vector */ 137862306a36Sopenharmony_ci if (adapter->rx_itr_setting == 1) 137962306a36Sopenharmony_ci q_vector->itr = IXGBE_20K_ITR; 138062306a36Sopenharmony_ci else 138162306a36Sopenharmony_ci q_vector->itr = adapter->rx_itr_setting; 138262306a36Sopenharmony_ci } 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci /* add q_vector eims value to global eims_enable_mask */ 138562306a36Sopenharmony_ci adapter->eims_enable_mask |= BIT(v_idx); 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci ixgbevf_write_eitr(q_vector); 138862306a36Sopenharmony_ci } 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci ixgbevf_set_ivar(adapter, -1, 1, v_idx); 139162306a36Sopenharmony_ci /* setup eims_other and add value to global eims_enable_mask */ 139262306a36Sopenharmony_ci adapter->eims_other = BIT(v_idx); 139362306a36Sopenharmony_ci adapter->eims_enable_mask |= adapter->eims_other; 139462306a36Sopenharmony_ci} 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_cienum latency_range { 139762306a36Sopenharmony_ci lowest_latency = 0, 139862306a36Sopenharmony_ci low_latency = 1, 139962306a36Sopenharmony_ci bulk_latency = 2, 140062306a36Sopenharmony_ci latency_invalid = 255 140162306a36Sopenharmony_ci}; 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci/** 140462306a36Sopenharmony_ci * ixgbevf_update_itr - update the dynamic ITR value based on statistics 140562306a36Sopenharmony_ci * @q_vector: structure containing interrupt and ring information 140662306a36Sopenharmony_ci * @ring_container: structure containing ring performance data 140762306a36Sopenharmony_ci * 140862306a36Sopenharmony_ci * Stores a new ITR value based on packets and byte 140962306a36Sopenharmony_ci * counts during the last interrupt. The advantage of per interrupt 141062306a36Sopenharmony_ci * computation is faster updates and more accurate ITR for the current 141162306a36Sopenharmony_ci * traffic pattern. Constants in this function were computed 141262306a36Sopenharmony_ci * based on theoretical maximum wire speed and thresholds were set based 141362306a36Sopenharmony_ci * on testing data as well as attempting to minimize response time 141462306a36Sopenharmony_ci * while increasing bulk throughput. 141562306a36Sopenharmony_ci **/ 141662306a36Sopenharmony_cistatic void ixgbevf_update_itr(struct ixgbevf_q_vector *q_vector, 141762306a36Sopenharmony_ci struct ixgbevf_ring_container *ring_container) 141862306a36Sopenharmony_ci{ 141962306a36Sopenharmony_ci int bytes = ring_container->total_bytes; 142062306a36Sopenharmony_ci int packets = ring_container->total_packets; 142162306a36Sopenharmony_ci u32 timepassed_us; 142262306a36Sopenharmony_ci u64 bytes_perint; 142362306a36Sopenharmony_ci u8 itr_setting = ring_container->itr; 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci if (packets == 0) 142662306a36Sopenharmony_ci return; 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci /* simple throttle rate management 142962306a36Sopenharmony_ci * 0-20MB/s lowest (100000 ints/s) 143062306a36Sopenharmony_ci * 20-100MB/s low (20000 ints/s) 143162306a36Sopenharmony_ci * 100-1249MB/s bulk (12000 ints/s) 143262306a36Sopenharmony_ci */ 143362306a36Sopenharmony_ci /* what was last interrupt timeslice? */ 143462306a36Sopenharmony_ci timepassed_us = q_vector->itr >> 2; 143562306a36Sopenharmony_ci if (timepassed_us == 0) 143662306a36Sopenharmony_ci return; 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci bytes_perint = bytes / timepassed_us; /* bytes/usec */ 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci switch (itr_setting) { 144162306a36Sopenharmony_ci case lowest_latency: 144262306a36Sopenharmony_ci if (bytes_perint > 10) 144362306a36Sopenharmony_ci itr_setting = low_latency; 144462306a36Sopenharmony_ci break; 144562306a36Sopenharmony_ci case low_latency: 144662306a36Sopenharmony_ci if (bytes_perint > 20) 144762306a36Sopenharmony_ci itr_setting = bulk_latency; 144862306a36Sopenharmony_ci else if (bytes_perint <= 10) 144962306a36Sopenharmony_ci itr_setting = lowest_latency; 145062306a36Sopenharmony_ci break; 145162306a36Sopenharmony_ci case bulk_latency: 145262306a36Sopenharmony_ci if (bytes_perint <= 20) 145362306a36Sopenharmony_ci itr_setting = low_latency; 145462306a36Sopenharmony_ci break; 145562306a36Sopenharmony_ci } 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_ci /* clear work counters since we have the values we need */ 145862306a36Sopenharmony_ci ring_container->total_bytes = 0; 145962306a36Sopenharmony_ci ring_container->total_packets = 0; 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci /* write updated itr to ring container */ 146262306a36Sopenharmony_ci ring_container->itr = itr_setting; 146362306a36Sopenharmony_ci} 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_cistatic void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector) 146662306a36Sopenharmony_ci{ 146762306a36Sopenharmony_ci u32 new_itr = q_vector->itr; 146862306a36Sopenharmony_ci u8 current_itr; 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci ixgbevf_update_itr(q_vector, &q_vector->tx); 147162306a36Sopenharmony_ci ixgbevf_update_itr(q_vector, &q_vector->rx); 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci current_itr = max(q_vector->rx.itr, q_vector->tx.itr); 147462306a36Sopenharmony_ci 147562306a36Sopenharmony_ci switch (current_itr) { 147662306a36Sopenharmony_ci /* counts and packets in update_itr are dependent on these numbers */ 147762306a36Sopenharmony_ci case lowest_latency: 147862306a36Sopenharmony_ci new_itr = IXGBE_100K_ITR; 147962306a36Sopenharmony_ci break; 148062306a36Sopenharmony_ci case low_latency: 148162306a36Sopenharmony_ci new_itr = IXGBE_20K_ITR; 148262306a36Sopenharmony_ci break; 148362306a36Sopenharmony_ci case bulk_latency: 148462306a36Sopenharmony_ci new_itr = IXGBE_12K_ITR; 148562306a36Sopenharmony_ci break; 148662306a36Sopenharmony_ci default: 148762306a36Sopenharmony_ci break; 148862306a36Sopenharmony_ci } 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci if (new_itr != q_vector->itr) { 149162306a36Sopenharmony_ci /* do an exponential smoothing */ 149262306a36Sopenharmony_ci new_itr = (10 * new_itr * q_vector->itr) / 149362306a36Sopenharmony_ci ((9 * new_itr) + q_vector->itr); 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci /* save the algorithm value here */ 149662306a36Sopenharmony_ci q_vector->itr = new_itr; 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci ixgbevf_write_eitr(q_vector); 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci} 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_cistatic irqreturn_t ixgbevf_msix_other(int irq, void *data) 150362306a36Sopenharmony_ci{ 150462306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = data; 150562306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ci hw->mac.get_link_status = 1; 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci ixgbevf_service_event_schedule(adapter); 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, adapter->eims_other); 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci return IRQ_HANDLED; 151462306a36Sopenharmony_ci} 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci/** 151762306a36Sopenharmony_ci * ixgbevf_msix_clean_rings - single unshared vector rx clean (all queues) 151862306a36Sopenharmony_ci * @irq: unused 151962306a36Sopenharmony_ci * @data: pointer to our q_vector struct for this interrupt vector 152062306a36Sopenharmony_ci **/ 152162306a36Sopenharmony_cistatic irqreturn_t ixgbevf_msix_clean_rings(int irq, void *data) 152262306a36Sopenharmony_ci{ 152362306a36Sopenharmony_ci struct ixgbevf_q_vector *q_vector = data; 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_ci /* EIAM disabled interrupts (on this vector) for us */ 152662306a36Sopenharmony_ci if (q_vector->rx.ring || q_vector->tx.ring) 152762306a36Sopenharmony_ci napi_schedule_irqoff(&q_vector->napi); 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci return IRQ_HANDLED; 153062306a36Sopenharmony_ci} 153162306a36Sopenharmony_ci 153262306a36Sopenharmony_ci/** 153362306a36Sopenharmony_ci * ixgbevf_request_msix_irqs - Initialize MSI-X interrupts 153462306a36Sopenharmony_ci * @adapter: board private structure 153562306a36Sopenharmony_ci * 153662306a36Sopenharmony_ci * ixgbevf_request_msix_irqs allocates MSI-X vectors and requests 153762306a36Sopenharmony_ci * interrupts from the kernel. 153862306a36Sopenharmony_ci **/ 153962306a36Sopenharmony_cistatic int ixgbevf_request_msix_irqs(struct ixgbevf_adapter *adapter) 154062306a36Sopenharmony_ci{ 154162306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 154262306a36Sopenharmony_ci int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; 154362306a36Sopenharmony_ci unsigned int ri = 0, ti = 0; 154462306a36Sopenharmony_ci int vector, err; 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci for (vector = 0; vector < q_vectors; vector++) { 154762306a36Sopenharmony_ci struct ixgbevf_q_vector *q_vector = adapter->q_vector[vector]; 154862306a36Sopenharmony_ci struct msix_entry *entry = &adapter->msix_entries[vector]; 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci if (q_vector->tx.ring && q_vector->rx.ring) { 155162306a36Sopenharmony_ci snprintf(q_vector->name, sizeof(q_vector->name), 155262306a36Sopenharmony_ci "%s-TxRx-%u", netdev->name, ri++); 155362306a36Sopenharmony_ci ti++; 155462306a36Sopenharmony_ci } else if (q_vector->rx.ring) { 155562306a36Sopenharmony_ci snprintf(q_vector->name, sizeof(q_vector->name), 155662306a36Sopenharmony_ci "%s-rx-%u", netdev->name, ri++); 155762306a36Sopenharmony_ci } else if (q_vector->tx.ring) { 155862306a36Sopenharmony_ci snprintf(q_vector->name, sizeof(q_vector->name), 155962306a36Sopenharmony_ci "%s-tx-%u", netdev->name, ti++); 156062306a36Sopenharmony_ci } else { 156162306a36Sopenharmony_ci /* skip this unused q_vector */ 156262306a36Sopenharmony_ci continue; 156362306a36Sopenharmony_ci } 156462306a36Sopenharmony_ci err = request_irq(entry->vector, &ixgbevf_msix_clean_rings, 0, 156562306a36Sopenharmony_ci q_vector->name, q_vector); 156662306a36Sopenharmony_ci if (err) { 156762306a36Sopenharmony_ci hw_dbg(&adapter->hw, 156862306a36Sopenharmony_ci "request_irq failed for MSIX interrupt Error: %d\n", 156962306a36Sopenharmony_ci err); 157062306a36Sopenharmony_ci goto free_queue_irqs; 157162306a36Sopenharmony_ci } 157262306a36Sopenharmony_ci } 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_ci err = request_irq(adapter->msix_entries[vector].vector, 157562306a36Sopenharmony_ci &ixgbevf_msix_other, 0, netdev->name, adapter); 157662306a36Sopenharmony_ci if (err) { 157762306a36Sopenharmony_ci hw_dbg(&adapter->hw, "request_irq for msix_other failed: %d\n", 157862306a36Sopenharmony_ci err); 157962306a36Sopenharmony_ci goto free_queue_irqs; 158062306a36Sopenharmony_ci } 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci return 0; 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_cifree_queue_irqs: 158562306a36Sopenharmony_ci while (vector) { 158662306a36Sopenharmony_ci vector--; 158762306a36Sopenharmony_ci free_irq(adapter->msix_entries[vector].vector, 158862306a36Sopenharmony_ci adapter->q_vector[vector]); 158962306a36Sopenharmony_ci } 159062306a36Sopenharmony_ci /* This failure is non-recoverable - it indicates the system is 159162306a36Sopenharmony_ci * out of MSIX vector resources and the VF driver cannot run 159262306a36Sopenharmony_ci * without them. Set the number of msix vectors to zero 159362306a36Sopenharmony_ci * indicating that not enough can be allocated. The error 159462306a36Sopenharmony_ci * will be returned to the user indicating device open failed. 159562306a36Sopenharmony_ci * Any further attempts to force the driver to open will also 159662306a36Sopenharmony_ci * fail. The only way to recover is to unload the driver and 159762306a36Sopenharmony_ci * reload it again. If the system has recovered some MSIX 159862306a36Sopenharmony_ci * vectors then it may succeed. 159962306a36Sopenharmony_ci */ 160062306a36Sopenharmony_ci adapter->num_msix_vectors = 0; 160162306a36Sopenharmony_ci return err; 160262306a36Sopenharmony_ci} 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci/** 160562306a36Sopenharmony_ci * ixgbevf_request_irq - initialize interrupts 160662306a36Sopenharmony_ci * @adapter: board private structure 160762306a36Sopenharmony_ci * 160862306a36Sopenharmony_ci * Attempts to configure interrupts using the best available 160962306a36Sopenharmony_ci * capabilities of the hardware and kernel. 161062306a36Sopenharmony_ci **/ 161162306a36Sopenharmony_cistatic int ixgbevf_request_irq(struct ixgbevf_adapter *adapter) 161262306a36Sopenharmony_ci{ 161362306a36Sopenharmony_ci int err = ixgbevf_request_msix_irqs(adapter); 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci if (err) 161662306a36Sopenharmony_ci hw_dbg(&adapter->hw, "request_irq failed, Error %d\n", err); 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci return err; 161962306a36Sopenharmony_ci} 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_cistatic void ixgbevf_free_irq(struct ixgbevf_adapter *adapter) 162262306a36Sopenharmony_ci{ 162362306a36Sopenharmony_ci int i, q_vectors; 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci if (!adapter->msix_entries) 162662306a36Sopenharmony_ci return; 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci q_vectors = adapter->num_msix_vectors; 162962306a36Sopenharmony_ci i = q_vectors - 1; 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ci free_irq(adapter->msix_entries[i].vector, adapter); 163262306a36Sopenharmony_ci i--; 163362306a36Sopenharmony_ci 163462306a36Sopenharmony_ci for (; i >= 0; i--) { 163562306a36Sopenharmony_ci /* free only the irqs that were actually requested */ 163662306a36Sopenharmony_ci if (!adapter->q_vector[i]->rx.ring && 163762306a36Sopenharmony_ci !adapter->q_vector[i]->tx.ring) 163862306a36Sopenharmony_ci continue; 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci free_irq(adapter->msix_entries[i].vector, 164162306a36Sopenharmony_ci adapter->q_vector[i]); 164262306a36Sopenharmony_ci } 164362306a36Sopenharmony_ci} 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci/** 164662306a36Sopenharmony_ci * ixgbevf_irq_disable - Mask off interrupt generation on the NIC 164762306a36Sopenharmony_ci * @adapter: board private structure 164862306a36Sopenharmony_ci **/ 164962306a36Sopenharmony_cistatic inline void ixgbevf_irq_disable(struct ixgbevf_adapter *adapter) 165062306a36Sopenharmony_ci{ 165162306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 165262306a36Sopenharmony_ci int i; 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, 0); 165562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTEIMC, ~0); 165662306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, 0); 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci for (i = 0; i < adapter->num_msix_vectors; i++) 166162306a36Sopenharmony_ci synchronize_irq(adapter->msix_entries[i].vector); 166262306a36Sopenharmony_ci} 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci/** 166562306a36Sopenharmony_ci * ixgbevf_irq_enable - Enable default interrupt generation settings 166662306a36Sopenharmony_ci * @adapter: board private structure 166762306a36Sopenharmony_ci **/ 166862306a36Sopenharmony_cistatic inline void ixgbevf_irq_enable(struct ixgbevf_adapter *adapter) 166962306a36Sopenharmony_ci{ 167062306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTEIAM, adapter->eims_enable_mask); 167362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTEIAC, adapter->eims_enable_mask); 167462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTEIMS, adapter->eims_enable_mask); 167562306a36Sopenharmony_ci} 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci/** 167862306a36Sopenharmony_ci * ixgbevf_configure_tx_ring - Configure 82599 VF Tx ring after Reset 167962306a36Sopenharmony_ci * @adapter: board private structure 168062306a36Sopenharmony_ci * @ring: structure containing ring specific data 168162306a36Sopenharmony_ci * 168262306a36Sopenharmony_ci * Configure the Tx descriptor ring after a reset. 168362306a36Sopenharmony_ci **/ 168462306a36Sopenharmony_cistatic void ixgbevf_configure_tx_ring(struct ixgbevf_adapter *adapter, 168562306a36Sopenharmony_ci struct ixgbevf_ring *ring) 168662306a36Sopenharmony_ci{ 168762306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 168862306a36Sopenharmony_ci u64 tdba = ring->dma; 168962306a36Sopenharmony_ci int wait_loop = 10; 169062306a36Sopenharmony_ci u32 txdctl = IXGBE_TXDCTL_ENABLE; 169162306a36Sopenharmony_ci u8 reg_idx = ring->reg_idx; 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci /* disable queue to avoid issues while updating state */ 169462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH); 169562306a36Sopenharmony_ci IXGBE_WRITE_FLUSH(hw); 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTDBAL(reg_idx), tdba & DMA_BIT_MASK(32)); 169862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTDBAH(reg_idx), tdba >> 32); 169962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTDLEN(reg_idx), 170062306a36Sopenharmony_ci ring->count * sizeof(union ixgbe_adv_tx_desc)); 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci /* disable head writeback */ 170362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTDWBAH(reg_idx), 0); 170462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTDWBAL(reg_idx), 0); 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci /* enable relaxed ordering */ 170762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFDCA_TXCTRL(reg_idx), 170862306a36Sopenharmony_ci (IXGBE_DCA_TXCTRL_DESC_RRO_EN | 170962306a36Sopenharmony_ci IXGBE_DCA_TXCTRL_DATA_RRO_EN)); 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci /* reset head and tail pointers */ 171262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTDH(reg_idx), 0); 171362306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTDT(reg_idx), 0); 171462306a36Sopenharmony_ci ring->tail = adapter->io_addr + IXGBE_VFTDT(reg_idx); 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci /* reset ntu and ntc to place SW in sync with hardwdare */ 171762306a36Sopenharmony_ci ring->next_to_clean = 0; 171862306a36Sopenharmony_ci ring->next_to_use = 0; 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci /* In order to avoid issues WTHRESH + PTHRESH should always be equal 172162306a36Sopenharmony_ci * to or less than the number of on chip descriptors, which is 172262306a36Sopenharmony_ci * currently 40. 172362306a36Sopenharmony_ci */ 172462306a36Sopenharmony_ci txdctl |= (8 << 16); /* WTHRESH = 8 */ 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci /* Setting PTHRESH to 32 both improves performance */ 172762306a36Sopenharmony_ci txdctl |= (1u << 8) | /* HTHRESH = 1 */ 172862306a36Sopenharmony_ci 32; /* PTHRESH = 32 */ 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci /* reinitialize tx_buffer_info */ 173162306a36Sopenharmony_ci memset(ring->tx_buffer_info, 0, 173262306a36Sopenharmony_ci sizeof(struct ixgbevf_tx_buffer) * ring->count); 173362306a36Sopenharmony_ci 173462306a36Sopenharmony_ci clear_bit(__IXGBEVF_HANG_CHECK_ARMED, &ring->state); 173562306a36Sopenharmony_ci clear_bit(__IXGBEVF_TX_XDP_RING_PRIMED, &ring->state); 173662306a36Sopenharmony_ci 173762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(reg_idx), txdctl); 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci /* poll to verify queue is enabled */ 174062306a36Sopenharmony_ci do { 174162306a36Sopenharmony_ci usleep_range(1000, 2000); 174262306a36Sopenharmony_ci txdctl = IXGBE_READ_REG(hw, IXGBE_VFTXDCTL(reg_idx)); 174362306a36Sopenharmony_ci } while (--wait_loop && !(txdctl & IXGBE_TXDCTL_ENABLE)); 174462306a36Sopenharmony_ci if (!wait_loop) 174562306a36Sopenharmony_ci hw_dbg(hw, "Could not enable Tx Queue %d\n", reg_idx); 174662306a36Sopenharmony_ci} 174762306a36Sopenharmony_ci 174862306a36Sopenharmony_ci/** 174962306a36Sopenharmony_ci * ixgbevf_configure_tx - Configure 82599 VF Transmit Unit after Reset 175062306a36Sopenharmony_ci * @adapter: board private structure 175162306a36Sopenharmony_ci * 175262306a36Sopenharmony_ci * Configure the Tx unit of the MAC after a reset. 175362306a36Sopenharmony_ci **/ 175462306a36Sopenharmony_cistatic void ixgbevf_configure_tx(struct ixgbevf_adapter *adapter) 175562306a36Sopenharmony_ci{ 175662306a36Sopenharmony_ci u32 i; 175762306a36Sopenharmony_ci 175862306a36Sopenharmony_ci /* Setup the HW Tx Head and Tail descriptor pointers */ 175962306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 176062306a36Sopenharmony_ci ixgbevf_configure_tx_ring(adapter, adapter->tx_ring[i]); 176162306a36Sopenharmony_ci for (i = 0; i < adapter->num_xdp_queues; i++) 176262306a36Sopenharmony_ci ixgbevf_configure_tx_ring(adapter, adapter->xdp_ring[i]); 176362306a36Sopenharmony_ci} 176462306a36Sopenharmony_ci 176562306a36Sopenharmony_ci#define IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT 2 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_cistatic void ixgbevf_configure_srrctl(struct ixgbevf_adapter *adapter, 176862306a36Sopenharmony_ci struct ixgbevf_ring *ring, int index) 176962306a36Sopenharmony_ci{ 177062306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 177162306a36Sopenharmony_ci u32 srrctl; 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci srrctl = IXGBE_SRRCTL_DROP_EN; 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci srrctl |= IXGBEVF_RX_HDR_SIZE << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT; 177662306a36Sopenharmony_ci if (ring_uses_large_buffer(ring)) 177762306a36Sopenharmony_ci srrctl |= IXGBEVF_RXBUFFER_3072 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; 177862306a36Sopenharmony_ci else 177962306a36Sopenharmony_ci srrctl |= IXGBEVF_RXBUFFER_2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT; 178062306a36Sopenharmony_ci srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFSRRCTL(index), srrctl); 178362306a36Sopenharmony_ci} 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_cistatic void ixgbevf_setup_psrtype(struct ixgbevf_adapter *adapter) 178662306a36Sopenharmony_ci{ 178762306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 178862306a36Sopenharmony_ci 178962306a36Sopenharmony_ci /* PSRTYPE must be initialized in 82599 */ 179062306a36Sopenharmony_ci u32 psrtype = IXGBE_PSRTYPE_TCPHDR | IXGBE_PSRTYPE_UDPHDR | 179162306a36Sopenharmony_ci IXGBE_PSRTYPE_IPV4HDR | IXGBE_PSRTYPE_IPV6HDR | 179262306a36Sopenharmony_ci IXGBE_PSRTYPE_L2HDR; 179362306a36Sopenharmony_ci 179462306a36Sopenharmony_ci if (adapter->num_rx_queues > 1) 179562306a36Sopenharmony_ci psrtype |= BIT(29); 179662306a36Sopenharmony_ci 179762306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFPSRTYPE, psrtype); 179862306a36Sopenharmony_ci} 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_ci#define IXGBEVF_MAX_RX_DESC_POLL 10 180162306a36Sopenharmony_cistatic void ixgbevf_disable_rx_queue(struct ixgbevf_adapter *adapter, 180262306a36Sopenharmony_ci struct ixgbevf_ring *ring) 180362306a36Sopenharmony_ci{ 180462306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 180562306a36Sopenharmony_ci int wait_loop = IXGBEVF_MAX_RX_DESC_POLL; 180662306a36Sopenharmony_ci u32 rxdctl; 180762306a36Sopenharmony_ci u8 reg_idx = ring->reg_idx; 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci if (IXGBE_REMOVED(hw->hw_addr)) 181062306a36Sopenharmony_ci return; 181162306a36Sopenharmony_ci rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); 181262306a36Sopenharmony_ci rxdctl &= ~IXGBE_RXDCTL_ENABLE; 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_ci /* write value back with RXDCTL.ENABLE bit cleared */ 181562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(reg_idx), rxdctl); 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci /* the hardware may take up to 100us to really disable the Rx queue */ 181862306a36Sopenharmony_ci do { 181962306a36Sopenharmony_ci udelay(10); 182062306a36Sopenharmony_ci rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); 182162306a36Sopenharmony_ci } while (--wait_loop && (rxdctl & IXGBE_RXDCTL_ENABLE)); 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci if (!wait_loop) 182462306a36Sopenharmony_ci pr_err("RXDCTL.ENABLE queue %d not cleared while polling\n", 182562306a36Sopenharmony_ci reg_idx); 182662306a36Sopenharmony_ci} 182762306a36Sopenharmony_ci 182862306a36Sopenharmony_cistatic void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter, 182962306a36Sopenharmony_ci struct ixgbevf_ring *ring) 183062306a36Sopenharmony_ci{ 183162306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 183262306a36Sopenharmony_ci int wait_loop = IXGBEVF_MAX_RX_DESC_POLL; 183362306a36Sopenharmony_ci u32 rxdctl; 183462306a36Sopenharmony_ci u8 reg_idx = ring->reg_idx; 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci if (IXGBE_REMOVED(hw->hw_addr)) 183762306a36Sopenharmony_ci return; 183862306a36Sopenharmony_ci do { 183962306a36Sopenharmony_ci usleep_range(1000, 2000); 184062306a36Sopenharmony_ci rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); 184162306a36Sopenharmony_ci } while (--wait_loop && !(rxdctl & IXGBE_RXDCTL_ENABLE)); 184262306a36Sopenharmony_ci 184362306a36Sopenharmony_ci if (!wait_loop) 184462306a36Sopenharmony_ci pr_err("RXDCTL.ENABLE queue %d not set while polling\n", 184562306a36Sopenharmony_ci reg_idx); 184662306a36Sopenharmony_ci} 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_ci/** 184962306a36Sopenharmony_ci * ixgbevf_init_rss_key - Initialize adapter RSS key 185062306a36Sopenharmony_ci * @adapter: device handle 185162306a36Sopenharmony_ci * 185262306a36Sopenharmony_ci * Allocates and initializes the RSS key if it is not allocated. 185362306a36Sopenharmony_ci **/ 185462306a36Sopenharmony_cistatic inline int ixgbevf_init_rss_key(struct ixgbevf_adapter *adapter) 185562306a36Sopenharmony_ci{ 185662306a36Sopenharmony_ci u32 *rss_key; 185762306a36Sopenharmony_ci 185862306a36Sopenharmony_ci if (!adapter->rss_key) { 185962306a36Sopenharmony_ci rss_key = kzalloc(IXGBEVF_RSS_HASH_KEY_SIZE, GFP_KERNEL); 186062306a36Sopenharmony_ci if (unlikely(!rss_key)) 186162306a36Sopenharmony_ci return -ENOMEM; 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_ci netdev_rss_key_fill(rss_key, IXGBEVF_RSS_HASH_KEY_SIZE); 186462306a36Sopenharmony_ci adapter->rss_key = rss_key; 186562306a36Sopenharmony_ci } 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci return 0; 186862306a36Sopenharmony_ci} 186962306a36Sopenharmony_ci 187062306a36Sopenharmony_cistatic void ixgbevf_setup_vfmrqc(struct ixgbevf_adapter *adapter) 187162306a36Sopenharmony_ci{ 187262306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 187362306a36Sopenharmony_ci u32 vfmrqc = 0, vfreta = 0; 187462306a36Sopenharmony_ci u16 rss_i = adapter->num_rx_queues; 187562306a36Sopenharmony_ci u8 i, j; 187662306a36Sopenharmony_ci 187762306a36Sopenharmony_ci /* Fill out hash function seeds */ 187862306a36Sopenharmony_ci for (i = 0; i < IXGBEVF_VFRSSRK_REGS; i++) 187962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFRSSRK(i), *(adapter->rss_key + i)); 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci for (i = 0, j = 0; i < IXGBEVF_X550_VFRETA_SIZE; i++, j++) { 188262306a36Sopenharmony_ci if (j == rss_i) 188362306a36Sopenharmony_ci j = 0; 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci adapter->rss_indir_tbl[i] = j; 188662306a36Sopenharmony_ci 188762306a36Sopenharmony_ci vfreta |= j << (i & 0x3) * 8; 188862306a36Sopenharmony_ci if ((i & 3) == 3) { 188962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFRETA(i >> 2), vfreta); 189062306a36Sopenharmony_ci vfreta = 0; 189162306a36Sopenharmony_ci } 189262306a36Sopenharmony_ci } 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci /* Perform hash on these packet types */ 189562306a36Sopenharmony_ci vfmrqc |= IXGBE_VFMRQC_RSS_FIELD_IPV4 | 189662306a36Sopenharmony_ci IXGBE_VFMRQC_RSS_FIELD_IPV4_TCP | 189762306a36Sopenharmony_ci IXGBE_VFMRQC_RSS_FIELD_IPV6 | 189862306a36Sopenharmony_ci IXGBE_VFMRQC_RSS_FIELD_IPV6_TCP; 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci vfmrqc |= IXGBE_VFMRQC_RSSEN; 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFMRQC, vfmrqc); 190362306a36Sopenharmony_ci} 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_cistatic void ixgbevf_configure_rx_ring(struct ixgbevf_adapter *adapter, 190662306a36Sopenharmony_ci struct ixgbevf_ring *ring) 190762306a36Sopenharmony_ci{ 190862306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 190962306a36Sopenharmony_ci union ixgbe_adv_rx_desc *rx_desc; 191062306a36Sopenharmony_ci u64 rdba = ring->dma; 191162306a36Sopenharmony_ci u32 rxdctl; 191262306a36Sopenharmony_ci u8 reg_idx = ring->reg_idx; 191362306a36Sopenharmony_ci 191462306a36Sopenharmony_ci /* disable queue to avoid issues while updating state */ 191562306a36Sopenharmony_ci rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(reg_idx)); 191662306a36Sopenharmony_ci ixgbevf_disable_rx_queue(adapter, ring); 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFRDBAL(reg_idx), rdba & DMA_BIT_MASK(32)); 191962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFRDBAH(reg_idx), rdba >> 32); 192062306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFRDLEN(reg_idx), 192162306a36Sopenharmony_ci ring->count * sizeof(union ixgbe_adv_rx_desc)); 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_ci#ifndef CONFIG_SPARC 192462306a36Sopenharmony_ci /* enable relaxed ordering */ 192562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFDCA_RXCTRL(reg_idx), 192662306a36Sopenharmony_ci IXGBE_DCA_RXCTRL_DESC_RRO_EN); 192762306a36Sopenharmony_ci#else 192862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFDCA_RXCTRL(reg_idx), 192962306a36Sopenharmony_ci IXGBE_DCA_RXCTRL_DESC_RRO_EN | 193062306a36Sopenharmony_ci IXGBE_DCA_RXCTRL_DATA_WRO_EN); 193162306a36Sopenharmony_ci#endif 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_ci /* reset head and tail pointers */ 193462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFRDH(reg_idx), 0); 193562306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFRDT(reg_idx), 0); 193662306a36Sopenharmony_ci ring->tail = adapter->io_addr + IXGBE_VFRDT(reg_idx); 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_ci /* initialize rx_buffer_info */ 193962306a36Sopenharmony_ci memset(ring->rx_buffer_info, 0, 194062306a36Sopenharmony_ci sizeof(struct ixgbevf_rx_buffer) * ring->count); 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ci /* initialize Rx descriptor 0 */ 194362306a36Sopenharmony_ci rx_desc = IXGBEVF_RX_DESC(ring, 0); 194462306a36Sopenharmony_ci rx_desc->wb.upper.length = 0; 194562306a36Sopenharmony_ci 194662306a36Sopenharmony_ci /* reset ntu and ntc to place SW in sync with hardwdare */ 194762306a36Sopenharmony_ci ring->next_to_clean = 0; 194862306a36Sopenharmony_ci ring->next_to_use = 0; 194962306a36Sopenharmony_ci ring->next_to_alloc = 0; 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ci ixgbevf_configure_srrctl(adapter, ring, reg_idx); 195262306a36Sopenharmony_ci 195362306a36Sopenharmony_ci /* RXDCTL.RLPML does not work on 82599 */ 195462306a36Sopenharmony_ci if (adapter->hw.mac.type != ixgbe_mac_82599_vf) { 195562306a36Sopenharmony_ci rxdctl &= ~(IXGBE_RXDCTL_RLPMLMASK | 195662306a36Sopenharmony_ci IXGBE_RXDCTL_RLPML_EN); 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci#if (PAGE_SIZE < 8192) 195962306a36Sopenharmony_ci /* Limit the maximum frame size so we don't overrun the skb */ 196062306a36Sopenharmony_ci if (ring_uses_build_skb(ring) && 196162306a36Sopenharmony_ci !ring_uses_large_buffer(ring)) 196262306a36Sopenharmony_ci rxdctl |= IXGBEVF_MAX_FRAME_BUILD_SKB | 196362306a36Sopenharmony_ci IXGBE_RXDCTL_RLPML_EN; 196462306a36Sopenharmony_ci#endif 196562306a36Sopenharmony_ci } 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME; 196862306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(reg_idx), rxdctl); 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci ixgbevf_rx_desc_queue_enable(adapter, ring); 197162306a36Sopenharmony_ci ixgbevf_alloc_rx_buffers(ring, ixgbevf_desc_unused(ring)); 197262306a36Sopenharmony_ci} 197362306a36Sopenharmony_ci 197462306a36Sopenharmony_cistatic void ixgbevf_set_rx_buffer_len(struct ixgbevf_adapter *adapter, 197562306a36Sopenharmony_ci struct ixgbevf_ring *rx_ring) 197662306a36Sopenharmony_ci{ 197762306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 197862306a36Sopenharmony_ci unsigned int max_frame = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; 197962306a36Sopenharmony_ci 198062306a36Sopenharmony_ci /* set build_skb and buffer size flags */ 198162306a36Sopenharmony_ci clear_ring_build_skb_enabled(rx_ring); 198262306a36Sopenharmony_ci clear_ring_uses_large_buffer(rx_ring); 198362306a36Sopenharmony_ci 198462306a36Sopenharmony_ci if (adapter->flags & IXGBEVF_FLAGS_LEGACY_RX) 198562306a36Sopenharmony_ci return; 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci if (PAGE_SIZE < 8192) 198862306a36Sopenharmony_ci if (max_frame > IXGBEVF_MAX_FRAME_BUILD_SKB) 198962306a36Sopenharmony_ci set_ring_uses_large_buffer(rx_ring); 199062306a36Sopenharmony_ci 199162306a36Sopenharmony_ci /* 82599 can't rely on RXDCTL.RLPML to restrict the size of the frame */ 199262306a36Sopenharmony_ci if (adapter->hw.mac.type == ixgbe_mac_82599_vf && !ring_uses_large_buffer(rx_ring)) 199362306a36Sopenharmony_ci return; 199462306a36Sopenharmony_ci 199562306a36Sopenharmony_ci set_ring_build_skb_enabled(rx_ring); 199662306a36Sopenharmony_ci} 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci/** 199962306a36Sopenharmony_ci * ixgbevf_configure_rx - Configure 82599 VF Receive Unit after Reset 200062306a36Sopenharmony_ci * @adapter: board private structure 200162306a36Sopenharmony_ci * 200262306a36Sopenharmony_ci * Configure the Rx unit of the MAC after a reset. 200362306a36Sopenharmony_ci **/ 200462306a36Sopenharmony_cistatic void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter) 200562306a36Sopenharmony_ci{ 200662306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 200762306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 200862306a36Sopenharmony_ci int i, ret; 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci ixgbevf_setup_psrtype(adapter); 201162306a36Sopenharmony_ci if (hw->mac.type >= ixgbe_mac_X550_vf) 201262306a36Sopenharmony_ci ixgbevf_setup_vfmrqc(adapter); 201362306a36Sopenharmony_ci 201462306a36Sopenharmony_ci spin_lock_bh(&adapter->mbx_lock); 201562306a36Sopenharmony_ci /* notify the PF of our intent to use this size of frame */ 201662306a36Sopenharmony_ci ret = hw->mac.ops.set_rlpml(hw, netdev->mtu + ETH_HLEN + ETH_FCS_LEN); 201762306a36Sopenharmony_ci spin_unlock_bh(&adapter->mbx_lock); 201862306a36Sopenharmony_ci if (ret) 201962306a36Sopenharmony_ci dev_err(&adapter->pdev->dev, 202062306a36Sopenharmony_ci "Failed to set MTU at %d\n", netdev->mtu); 202162306a36Sopenharmony_ci 202262306a36Sopenharmony_ci /* Setup the HW Rx Head and Tail Descriptor Pointers and 202362306a36Sopenharmony_ci * the Base and Length of the Rx Descriptor Ring 202462306a36Sopenharmony_ci */ 202562306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 202662306a36Sopenharmony_ci struct ixgbevf_ring *rx_ring = adapter->rx_ring[i]; 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci ixgbevf_set_rx_buffer_len(adapter, rx_ring); 202962306a36Sopenharmony_ci ixgbevf_configure_rx_ring(adapter, rx_ring); 203062306a36Sopenharmony_ci } 203162306a36Sopenharmony_ci} 203262306a36Sopenharmony_ci 203362306a36Sopenharmony_cistatic int ixgbevf_vlan_rx_add_vid(struct net_device *netdev, 203462306a36Sopenharmony_ci __be16 proto, u16 vid) 203562306a36Sopenharmony_ci{ 203662306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 203762306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 203862306a36Sopenharmony_ci int err; 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci spin_lock_bh(&adapter->mbx_lock); 204162306a36Sopenharmony_ci 204262306a36Sopenharmony_ci /* add VID to filter table */ 204362306a36Sopenharmony_ci err = hw->mac.ops.set_vfta(hw, vid, 0, true); 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci spin_unlock_bh(&adapter->mbx_lock); 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci if (err) { 204862306a36Sopenharmony_ci netdev_err(netdev, "VF could not set VLAN %d\n", vid); 204962306a36Sopenharmony_ci 205062306a36Sopenharmony_ci /* translate error return types so error makes sense */ 205162306a36Sopenharmony_ci if (err == IXGBE_ERR_MBX) 205262306a36Sopenharmony_ci return -EIO; 205362306a36Sopenharmony_ci 205462306a36Sopenharmony_ci if (err == IXGBE_ERR_INVALID_ARGUMENT) 205562306a36Sopenharmony_ci return -EACCES; 205662306a36Sopenharmony_ci } 205762306a36Sopenharmony_ci 205862306a36Sopenharmony_ci set_bit(vid, adapter->active_vlans); 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_ci return err; 206162306a36Sopenharmony_ci} 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_cistatic int ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, 206462306a36Sopenharmony_ci __be16 proto, u16 vid) 206562306a36Sopenharmony_ci{ 206662306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 206762306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 206862306a36Sopenharmony_ci int err; 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci spin_lock_bh(&adapter->mbx_lock); 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_ci /* remove VID from filter table */ 207362306a36Sopenharmony_ci err = hw->mac.ops.set_vfta(hw, vid, 0, false); 207462306a36Sopenharmony_ci 207562306a36Sopenharmony_ci spin_unlock_bh(&adapter->mbx_lock); 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci if (err) 207862306a36Sopenharmony_ci netdev_err(netdev, "Could not remove VLAN %d\n", vid); 207962306a36Sopenharmony_ci 208062306a36Sopenharmony_ci clear_bit(vid, adapter->active_vlans); 208162306a36Sopenharmony_ci 208262306a36Sopenharmony_ci return err; 208362306a36Sopenharmony_ci} 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_cistatic void ixgbevf_restore_vlan(struct ixgbevf_adapter *adapter) 208662306a36Sopenharmony_ci{ 208762306a36Sopenharmony_ci u16 vid; 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) 209062306a36Sopenharmony_ci ixgbevf_vlan_rx_add_vid(adapter->netdev, 209162306a36Sopenharmony_ci htons(ETH_P_8021Q), vid); 209262306a36Sopenharmony_ci} 209362306a36Sopenharmony_ci 209462306a36Sopenharmony_cistatic int ixgbevf_write_uc_addr_list(struct net_device *netdev) 209562306a36Sopenharmony_ci{ 209662306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 209762306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 209862306a36Sopenharmony_ci int count = 0; 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_ci if (!netdev_uc_empty(netdev)) { 210162306a36Sopenharmony_ci struct netdev_hw_addr *ha; 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_ci netdev_for_each_uc_addr(ha, netdev) { 210462306a36Sopenharmony_ci hw->mac.ops.set_uc_addr(hw, ++count, ha->addr); 210562306a36Sopenharmony_ci udelay(200); 210662306a36Sopenharmony_ci } 210762306a36Sopenharmony_ci } else { 210862306a36Sopenharmony_ci /* If the list is empty then send message to PF driver to 210962306a36Sopenharmony_ci * clear all MAC VLANs on this VF. 211062306a36Sopenharmony_ci */ 211162306a36Sopenharmony_ci hw->mac.ops.set_uc_addr(hw, 0, NULL); 211262306a36Sopenharmony_ci } 211362306a36Sopenharmony_ci 211462306a36Sopenharmony_ci return count; 211562306a36Sopenharmony_ci} 211662306a36Sopenharmony_ci 211762306a36Sopenharmony_ci/** 211862306a36Sopenharmony_ci * ixgbevf_set_rx_mode - Multicast and unicast set 211962306a36Sopenharmony_ci * @netdev: network interface device structure 212062306a36Sopenharmony_ci * 212162306a36Sopenharmony_ci * The set_rx_method entry point is called whenever the multicast address 212262306a36Sopenharmony_ci * list, unicast address list or the network interface flags are updated. 212362306a36Sopenharmony_ci * This routine is responsible for configuring the hardware for proper 212462306a36Sopenharmony_ci * multicast mode and configuring requested unicast filters. 212562306a36Sopenharmony_ci **/ 212662306a36Sopenharmony_cistatic void ixgbevf_set_rx_mode(struct net_device *netdev) 212762306a36Sopenharmony_ci{ 212862306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 212962306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 213062306a36Sopenharmony_ci unsigned int flags = netdev->flags; 213162306a36Sopenharmony_ci int xcast_mode; 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci /* request the most inclusive mode we need */ 213462306a36Sopenharmony_ci if (flags & IFF_PROMISC) 213562306a36Sopenharmony_ci xcast_mode = IXGBEVF_XCAST_MODE_PROMISC; 213662306a36Sopenharmony_ci else if (flags & IFF_ALLMULTI) 213762306a36Sopenharmony_ci xcast_mode = IXGBEVF_XCAST_MODE_ALLMULTI; 213862306a36Sopenharmony_ci else if (flags & (IFF_BROADCAST | IFF_MULTICAST)) 213962306a36Sopenharmony_ci xcast_mode = IXGBEVF_XCAST_MODE_MULTI; 214062306a36Sopenharmony_ci else 214162306a36Sopenharmony_ci xcast_mode = IXGBEVF_XCAST_MODE_NONE; 214262306a36Sopenharmony_ci 214362306a36Sopenharmony_ci spin_lock_bh(&adapter->mbx_lock); 214462306a36Sopenharmony_ci 214562306a36Sopenharmony_ci hw->mac.ops.update_xcast_mode(hw, xcast_mode); 214662306a36Sopenharmony_ci 214762306a36Sopenharmony_ci /* reprogram multicast list */ 214862306a36Sopenharmony_ci hw->mac.ops.update_mc_addr_list(hw, netdev); 214962306a36Sopenharmony_ci 215062306a36Sopenharmony_ci ixgbevf_write_uc_addr_list(netdev); 215162306a36Sopenharmony_ci 215262306a36Sopenharmony_ci spin_unlock_bh(&adapter->mbx_lock); 215362306a36Sopenharmony_ci} 215462306a36Sopenharmony_ci 215562306a36Sopenharmony_cistatic void ixgbevf_napi_enable_all(struct ixgbevf_adapter *adapter) 215662306a36Sopenharmony_ci{ 215762306a36Sopenharmony_ci int q_idx; 215862306a36Sopenharmony_ci struct ixgbevf_q_vector *q_vector; 215962306a36Sopenharmony_ci int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci for (q_idx = 0; q_idx < q_vectors; q_idx++) { 216262306a36Sopenharmony_ci q_vector = adapter->q_vector[q_idx]; 216362306a36Sopenharmony_ci napi_enable(&q_vector->napi); 216462306a36Sopenharmony_ci } 216562306a36Sopenharmony_ci} 216662306a36Sopenharmony_ci 216762306a36Sopenharmony_cistatic void ixgbevf_napi_disable_all(struct ixgbevf_adapter *adapter) 216862306a36Sopenharmony_ci{ 216962306a36Sopenharmony_ci int q_idx; 217062306a36Sopenharmony_ci struct ixgbevf_q_vector *q_vector; 217162306a36Sopenharmony_ci int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; 217262306a36Sopenharmony_ci 217362306a36Sopenharmony_ci for (q_idx = 0; q_idx < q_vectors; q_idx++) { 217462306a36Sopenharmony_ci q_vector = adapter->q_vector[q_idx]; 217562306a36Sopenharmony_ci napi_disable(&q_vector->napi); 217662306a36Sopenharmony_ci } 217762306a36Sopenharmony_ci} 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_cistatic int ixgbevf_configure_dcb(struct ixgbevf_adapter *adapter) 218062306a36Sopenharmony_ci{ 218162306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 218262306a36Sopenharmony_ci unsigned int def_q = 0; 218362306a36Sopenharmony_ci unsigned int num_tcs = 0; 218462306a36Sopenharmony_ci unsigned int num_rx_queues = adapter->num_rx_queues; 218562306a36Sopenharmony_ci unsigned int num_tx_queues = adapter->num_tx_queues; 218662306a36Sopenharmony_ci int err; 218762306a36Sopenharmony_ci 218862306a36Sopenharmony_ci spin_lock_bh(&adapter->mbx_lock); 218962306a36Sopenharmony_ci 219062306a36Sopenharmony_ci /* fetch queue configuration from the PF */ 219162306a36Sopenharmony_ci err = ixgbevf_get_queues(hw, &num_tcs, &def_q); 219262306a36Sopenharmony_ci 219362306a36Sopenharmony_ci spin_unlock_bh(&adapter->mbx_lock); 219462306a36Sopenharmony_ci 219562306a36Sopenharmony_ci if (err) 219662306a36Sopenharmony_ci return err; 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_ci if (num_tcs > 1) { 219962306a36Sopenharmony_ci /* we need only one Tx queue */ 220062306a36Sopenharmony_ci num_tx_queues = 1; 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ci /* update default Tx ring register index */ 220362306a36Sopenharmony_ci adapter->tx_ring[0]->reg_idx = def_q; 220462306a36Sopenharmony_ci 220562306a36Sopenharmony_ci /* we need as many queues as traffic classes */ 220662306a36Sopenharmony_ci num_rx_queues = num_tcs; 220762306a36Sopenharmony_ci } 220862306a36Sopenharmony_ci 220962306a36Sopenharmony_ci /* if we have a bad config abort request queue reset */ 221062306a36Sopenharmony_ci if ((adapter->num_rx_queues != num_rx_queues) || 221162306a36Sopenharmony_ci (adapter->num_tx_queues != num_tx_queues)) { 221262306a36Sopenharmony_ci /* force mailbox timeout to prevent further messages */ 221362306a36Sopenharmony_ci hw->mbx.timeout = 0; 221462306a36Sopenharmony_ci 221562306a36Sopenharmony_ci /* wait for watchdog to come around and bail us out */ 221662306a36Sopenharmony_ci set_bit(__IXGBEVF_QUEUE_RESET_REQUESTED, &adapter->state); 221762306a36Sopenharmony_ci } 221862306a36Sopenharmony_ci 221962306a36Sopenharmony_ci return 0; 222062306a36Sopenharmony_ci} 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_cistatic void ixgbevf_configure(struct ixgbevf_adapter *adapter) 222362306a36Sopenharmony_ci{ 222462306a36Sopenharmony_ci ixgbevf_configure_dcb(adapter); 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_ci ixgbevf_set_rx_mode(adapter->netdev); 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_ci ixgbevf_restore_vlan(adapter); 222962306a36Sopenharmony_ci ixgbevf_ipsec_restore(adapter); 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_ci ixgbevf_configure_tx(adapter); 223262306a36Sopenharmony_ci ixgbevf_configure_rx(adapter); 223362306a36Sopenharmony_ci} 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_cistatic void ixgbevf_save_reset_stats(struct ixgbevf_adapter *adapter) 223662306a36Sopenharmony_ci{ 223762306a36Sopenharmony_ci /* Only save pre-reset stats if there are some */ 223862306a36Sopenharmony_ci if (adapter->stats.vfgprc || adapter->stats.vfgptc) { 223962306a36Sopenharmony_ci adapter->stats.saved_reset_vfgprc += adapter->stats.vfgprc - 224062306a36Sopenharmony_ci adapter->stats.base_vfgprc; 224162306a36Sopenharmony_ci adapter->stats.saved_reset_vfgptc += adapter->stats.vfgptc - 224262306a36Sopenharmony_ci adapter->stats.base_vfgptc; 224362306a36Sopenharmony_ci adapter->stats.saved_reset_vfgorc += adapter->stats.vfgorc - 224462306a36Sopenharmony_ci adapter->stats.base_vfgorc; 224562306a36Sopenharmony_ci adapter->stats.saved_reset_vfgotc += adapter->stats.vfgotc - 224662306a36Sopenharmony_ci adapter->stats.base_vfgotc; 224762306a36Sopenharmony_ci adapter->stats.saved_reset_vfmprc += adapter->stats.vfmprc - 224862306a36Sopenharmony_ci adapter->stats.base_vfmprc; 224962306a36Sopenharmony_ci } 225062306a36Sopenharmony_ci} 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_cistatic void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter) 225362306a36Sopenharmony_ci{ 225462306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 225562306a36Sopenharmony_ci 225662306a36Sopenharmony_ci adapter->stats.last_vfgprc = IXGBE_READ_REG(hw, IXGBE_VFGPRC); 225762306a36Sopenharmony_ci adapter->stats.last_vfgorc = IXGBE_READ_REG(hw, IXGBE_VFGORC_LSB); 225862306a36Sopenharmony_ci adapter->stats.last_vfgorc |= 225962306a36Sopenharmony_ci (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGORC_MSB))) << 32); 226062306a36Sopenharmony_ci adapter->stats.last_vfgptc = IXGBE_READ_REG(hw, IXGBE_VFGPTC); 226162306a36Sopenharmony_ci adapter->stats.last_vfgotc = IXGBE_READ_REG(hw, IXGBE_VFGOTC_LSB); 226262306a36Sopenharmony_ci adapter->stats.last_vfgotc |= 226362306a36Sopenharmony_ci (((u64)(IXGBE_READ_REG(hw, IXGBE_VFGOTC_MSB))) << 32); 226462306a36Sopenharmony_ci adapter->stats.last_vfmprc = IXGBE_READ_REG(hw, IXGBE_VFMPRC); 226562306a36Sopenharmony_ci 226662306a36Sopenharmony_ci adapter->stats.base_vfgprc = adapter->stats.last_vfgprc; 226762306a36Sopenharmony_ci adapter->stats.base_vfgorc = adapter->stats.last_vfgorc; 226862306a36Sopenharmony_ci adapter->stats.base_vfgptc = adapter->stats.last_vfgptc; 226962306a36Sopenharmony_ci adapter->stats.base_vfgotc = adapter->stats.last_vfgotc; 227062306a36Sopenharmony_ci adapter->stats.base_vfmprc = adapter->stats.last_vfmprc; 227162306a36Sopenharmony_ci} 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_cistatic void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter) 227462306a36Sopenharmony_ci{ 227562306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 227662306a36Sopenharmony_ci static const int api[] = { 227762306a36Sopenharmony_ci ixgbe_mbox_api_15, 227862306a36Sopenharmony_ci ixgbe_mbox_api_14, 227962306a36Sopenharmony_ci ixgbe_mbox_api_13, 228062306a36Sopenharmony_ci ixgbe_mbox_api_12, 228162306a36Sopenharmony_ci ixgbe_mbox_api_11, 228262306a36Sopenharmony_ci ixgbe_mbox_api_10, 228362306a36Sopenharmony_ci ixgbe_mbox_api_unknown 228462306a36Sopenharmony_ci }; 228562306a36Sopenharmony_ci int err, idx = 0; 228662306a36Sopenharmony_ci 228762306a36Sopenharmony_ci spin_lock_bh(&adapter->mbx_lock); 228862306a36Sopenharmony_ci 228962306a36Sopenharmony_ci while (api[idx] != ixgbe_mbox_api_unknown) { 229062306a36Sopenharmony_ci err = hw->mac.ops.negotiate_api_version(hw, api[idx]); 229162306a36Sopenharmony_ci if (!err) 229262306a36Sopenharmony_ci break; 229362306a36Sopenharmony_ci idx++; 229462306a36Sopenharmony_ci } 229562306a36Sopenharmony_ci 229662306a36Sopenharmony_ci if (hw->api_version >= ixgbe_mbox_api_15) { 229762306a36Sopenharmony_ci hw->mbx.ops.init_params(hw); 229862306a36Sopenharmony_ci memcpy(&hw->mbx.ops, &ixgbevf_mbx_ops, 229962306a36Sopenharmony_ci sizeof(struct ixgbe_mbx_operations)); 230062306a36Sopenharmony_ci } 230162306a36Sopenharmony_ci 230262306a36Sopenharmony_ci spin_unlock_bh(&adapter->mbx_lock); 230362306a36Sopenharmony_ci} 230462306a36Sopenharmony_ci 230562306a36Sopenharmony_cistatic void ixgbevf_up_complete(struct ixgbevf_adapter *adapter) 230662306a36Sopenharmony_ci{ 230762306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 230862306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 230962306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 231062306a36Sopenharmony_ci bool state; 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci ixgbevf_configure_msix(adapter); 231362306a36Sopenharmony_ci 231462306a36Sopenharmony_ci spin_lock_bh(&adapter->mbx_lock); 231562306a36Sopenharmony_ci 231662306a36Sopenharmony_ci if (is_valid_ether_addr(hw->mac.addr)) 231762306a36Sopenharmony_ci hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0); 231862306a36Sopenharmony_ci else 231962306a36Sopenharmony_ci hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0); 232062306a36Sopenharmony_ci 232162306a36Sopenharmony_ci spin_unlock_bh(&adapter->mbx_lock); 232262306a36Sopenharmony_ci 232362306a36Sopenharmony_ci state = adapter->link_state; 232462306a36Sopenharmony_ci hw->mac.ops.get_link_state(hw, &adapter->link_state); 232562306a36Sopenharmony_ci if (state && state != adapter->link_state) 232662306a36Sopenharmony_ci dev_info(&pdev->dev, "VF is administratively disabled\n"); 232762306a36Sopenharmony_ci 232862306a36Sopenharmony_ci smp_mb__before_atomic(); 232962306a36Sopenharmony_ci clear_bit(__IXGBEVF_DOWN, &adapter->state); 233062306a36Sopenharmony_ci ixgbevf_napi_enable_all(adapter); 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci /* clear any pending interrupts, may auto mask */ 233362306a36Sopenharmony_ci IXGBE_READ_REG(hw, IXGBE_VTEICR); 233462306a36Sopenharmony_ci ixgbevf_irq_enable(adapter); 233562306a36Sopenharmony_ci 233662306a36Sopenharmony_ci /* enable transmits */ 233762306a36Sopenharmony_ci netif_tx_start_all_queues(netdev); 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_ci ixgbevf_save_reset_stats(adapter); 234062306a36Sopenharmony_ci ixgbevf_init_last_counter_stats(adapter); 234162306a36Sopenharmony_ci 234262306a36Sopenharmony_ci hw->mac.get_link_status = 1; 234362306a36Sopenharmony_ci mod_timer(&adapter->service_timer, jiffies); 234462306a36Sopenharmony_ci} 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_civoid ixgbevf_up(struct ixgbevf_adapter *adapter) 234762306a36Sopenharmony_ci{ 234862306a36Sopenharmony_ci ixgbevf_configure(adapter); 234962306a36Sopenharmony_ci 235062306a36Sopenharmony_ci ixgbevf_up_complete(adapter); 235162306a36Sopenharmony_ci} 235262306a36Sopenharmony_ci 235362306a36Sopenharmony_ci/** 235462306a36Sopenharmony_ci * ixgbevf_clean_rx_ring - Free Rx Buffers per Queue 235562306a36Sopenharmony_ci * @rx_ring: ring to free buffers from 235662306a36Sopenharmony_ci **/ 235762306a36Sopenharmony_cistatic void ixgbevf_clean_rx_ring(struct ixgbevf_ring *rx_ring) 235862306a36Sopenharmony_ci{ 235962306a36Sopenharmony_ci u16 i = rx_ring->next_to_clean; 236062306a36Sopenharmony_ci 236162306a36Sopenharmony_ci /* Free Rx ring sk_buff */ 236262306a36Sopenharmony_ci if (rx_ring->skb) { 236362306a36Sopenharmony_ci dev_kfree_skb(rx_ring->skb); 236462306a36Sopenharmony_ci rx_ring->skb = NULL; 236562306a36Sopenharmony_ci } 236662306a36Sopenharmony_ci 236762306a36Sopenharmony_ci /* Free all the Rx ring pages */ 236862306a36Sopenharmony_ci while (i != rx_ring->next_to_alloc) { 236962306a36Sopenharmony_ci struct ixgbevf_rx_buffer *rx_buffer; 237062306a36Sopenharmony_ci 237162306a36Sopenharmony_ci rx_buffer = &rx_ring->rx_buffer_info[i]; 237262306a36Sopenharmony_ci 237362306a36Sopenharmony_ci /* Invalidate cache lines that may have been written to by 237462306a36Sopenharmony_ci * device so that we avoid corrupting memory. 237562306a36Sopenharmony_ci */ 237662306a36Sopenharmony_ci dma_sync_single_range_for_cpu(rx_ring->dev, 237762306a36Sopenharmony_ci rx_buffer->dma, 237862306a36Sopenharmony_ci rx_buffer->page_offset, 237962306a36Sopenharmony_ci ixgbevf_rx_bufsz(rx_ring), 238062306a36Sopenharmony_ci DMA_FROM_DEVICE); 238162306a36Sopenharmony_ci 238262306a36Sopenharmony_ci /* free resources associated with mapping */ 238362306a36Sopenharmony_ci dma_unmap_page_attrs(rx_ring->dev, 238462306a36Sopenharmony_ci rx_buffer->dma, 238562306a36Sopenharmony_ci ixgbevf_rx_pg_size(rx_ring), 238662306a36Sopenharmony_ci DMA_FROM_DEVICE, 238762306a36Sopenharmony_ci IXGBEVF_RX_DMA_ATTR); 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci __page_frag_cache_drain(rx_buffer->page, 239062306a36Sopenharmony_ci rx_buffer->pagecnt_bias); 239162306a36Sopenharmony_ci 239262306a36Sopenharmony_ci i++; 239362306a36Sopenharmony_ci if (i == rx_ring->count) 239462306a36Sopenharmony_ci i = 0; 239562306a36Sopenharmony_ci } 239662306a36Sopenharmony_ci 239762306a36Sopenharmony_ci rx_ring->next_to_alloc = 0; 239862306a36Sopenharmony_ci rx_ring->next_to_clean = 0; 239962306a36Sopenharmony_ci rx_ring->next_to_use = 0; 240062306a36Sopenharmony_ci} 240162306a36Sopenharmony_ci 240262306a36Sopenharmony_ci/** 240362306a36Sopenharmony_ci * ixgbevf_clean_tx_ring - Free Tx Buffers 240462306a36Sopenharmony_ci * @tx_ring: ring to be cleaned 240562306a36Sopenharmony_ci **/ 240662306a36Sopenharmony_cistatic void ixgbevf_clean_tx_ring(struct ixgbevf_ring *tx_ring) 240762306a36Sopenharmony_ci{ 240862306a36Sopenharmony_ci u16 i = tx_ring->next_to_clean; 240962306a36Sopenharmony_ci struct ixgbevf_tx_buffer *tx_buffer = &tx_ring->tx_buffer_info[i]; 241062306a36Sopenharmony_ci 241162306a36Sopenharmony_ci while (i != tx_ring->next_to_use) { 241262306a36Sopenharmony_ci union ixgbe_adv_tx_desc *eop_desc, *tx_desc; 241362306a36Sopenharmony_ci 241462306a36Sopenharmony_ci /* Free all the Tx ring sk_buffs */ 241562306a36Sopenharmony_ci if (ring_is_xdp(tx_ring)) 241662306a36Sopenharmony_ci page_frag_free(tx_buffer->data); 241762306a36Sopenharmony_ci else 241862306a36Sopenharmony_ci dev_kfree_skb_any(tx_buffer->skb); 241962306a36Sopenharmony_ci 242062306a36Sopenharmony_ci /* unmap skb header data */ 242162306a36Sopenharmony_ci dma_unmap_single(tx_ring->dev, 242262306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 242362306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 242462306a36Sopenharmony_ci DMA_TO_DEVICE); 242562306a36Sopenharmony_ci 242662306a36Sopenharmony_ci /* check for eop_desc to determine the end of the packet */ 242762306a36Sopenharmony_ci eop_desc = tx_buffer->next_to_watch; 242862306a36Sopenharmony_ci tx_desc = IXGBEVF_TX_DESC(tx_ring, i); 242962306a36Sopenharmony_ci 243062306a36Sopenharmony_ci /* unmap remaining buffers */ 243162306a36Sopenharmony_ci while (tx_desc != eop_desc) { 243262306a36Sopenharmony_ci tx_buffer++; 243362306a36Sopenharmony_ci tx_desc++; 243462306a36Sopenharmony_ci i++; 243562306a36Sopenharmony_ci if (unlikely(i == tx_ring->count)) { 243662306a36Sopenharmony_ci i = 0; 243762306a36Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 243862306a36Sopenharmony_ci tx_desc = IXGBEVF_TX_DESC(tx_ring, 0); 243962306a36Sopenharmony_ci } 244062306a36Sopenharmony_ci 244162306a36Sopenharmony_ci /* unmap any remaining paged data */ 244262306a36Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) 244362306a36Sopenharmony_ci dma_unmap_page(tx_ring->dev, 244462306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 244562306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 244662306a36Sopenharmony_ci DMA_TO_DEVICE); 244762306a36Sopenharmony_ci } 244862306a36Sopenharmony_ci 244962306a36Sopenharmony_ci /* move us one more past the eop_desc for start of next pkt */ 245062306a36Sopenharmony_ci tx_buffer++; 245162306a36Sopenharmony_ci i++; 245262306a36Sopenharmony_ci if (unlikely(i == tx_ring->count)) { 245362306a36Sopenharmony_ci i = 0; 245462306a36Sopenharmony_ci tx_buffer = tx_ring->tx_buffer_info; 245562306a36Sopenharmony_ci } 245662306a36Sopenharmony_ci } 245762306a36Sopenharmony_ci 245862306a36Sopenharmony_ci /* reset next_to_use and next_to_clean */ 245962306a36Sopenharmony_ci tx_ring->next_to_use = 0; 246062306a36Sopenharmony_ci tx_ring->next_to_clean = 0; 246162306a36Sopenharmony_ci 246262306a36Sopenharmony_ci} 246362306a36Sopenharmony_ci 246462306a36Sopenharmony_ci/** 246562306a36Sopenharmony_ci * ixgbevf_clean_all_rx_rings - Free Rx Buffers for all queues 246662306a36Sopenharmony_ci * @adapter: board private structure 246762306a36Sopenharmony_ci **/ 246862306a36Sopenharmony_cistatic void ixgbevf_clean_all_rx_rings(struct ixgbevf_adapter *adapter) 246962306a36Sopenharmony_ci{ 247062306a36Sopenharmony_ci int i; 247162306a36Sopenharmony_ci 247262306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) 247362306a36Sopenharmony_ci ixgbevf_clean_rx_ring(adapter->rx_ring[i]); 247462306a36Sopenharmony_ci} 247562306a36Sopenharmony_ci 247662306a36Sopenharmony_ci/** 247762306a36Sopenharmony_ci * ixgbevf_clean_all_tx_rings - Free Tx Buffers for all queues 247862306a36Sopenharmony_ci * @adapter: board private structure 247962306a36Sopenharmony_ci **/ 248062306a36Sopenharmony_cistatic void ixgbevf_clean_all_tx_rings(struct ixgbevf_adapter *adapter) 248162306a36Sopenharmony_ci{ 248262306a36Sopenharmony_ci int i; 248362306a36Sopenharmony_ci 248462306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 248562306a36Sopenharmony_ci ixgbevf_clean_tx_ring(adapter->tx_ring[i]); 248662306a36Sopenharmony_ci for (i = 0; i < adapter->num_xdp_queues; i++) 248762306a36Sopenharmony_ci ixgbevf_clean_tx_ring(adapter->xdp_ring[i]); 248862306a36Sopenharmony_ci} 248962306a36Sopenharmony_ci 249062306a36Sopenharmony_civoid ixgbevf_down(struct ixgbevf_adapter *adapter) 249162306a36Sopenharmony_ci{ 249262306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 249362306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 249462306a36Sopenharmony_ci int i; 249562306a36Sopenharmony_ci 249662306a36Sopenharmony_ci /* signal that we are down to the interrupt handler */ 249762306a36Sopenharmony_ci if (test_and_set_bit(__IXGBEVF_DOWN, &adapter->state)) 249862306a36Sopenharmony_ci return; /* do nothing if already down */ 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci /* disable all enabled Rx queues */ 250162306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) 250262306a36Sopenharmony_ci ixgbevf_disable_rx_queue(adapter, adapter->rx_ring[i]); 250362306a36Sopenharmony_ci 250462306a36Sopenharmony_ci usleep_range(10000, 20000); 250562306a36Sopenharmony_ci 250662306a36Sopenharmony_ci netif_tx_stop_all_queues(netdev); 250762306a36Sopenharmony_ci 250862306a36Sopenharmony_ci /* call carrier off first to avoid false dev_watchdog timeouts */ 250962306a36Sopenharmony_ci netif_carrier_off(netdev); 251062306a36Sopenharmony_ci netif_tx_disable(netdev); 251162306a36Sopenharmony_ci 251262306a36Sopenharmony_ci ixgbevf_irq_disable(adapter); 251362306a36Sopenharmony_ci 251462306a36Sopenharmony_ci ixgbevf_napi_disable_all(adapter); 251562306a36Sopenharmony_ci 251662306a36Sopenharmony_ci del_timer_sync(&adapter->service_timer); 251762306a36Sopenharmony_ci 251862306a36Sopenharmony_ci /* disable transmits in the hardware now that interrupts are off */ 251962306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 252062306a36Sopenharmony_ci u8 reg_idx = adapter->tx_ring[i]->reg_idx; 252162306a36Sopenharmony_ci 252262306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(reg_idx), 252362306a36Sopenharmony_ci IXGBE_TXDCTL_SWFLSH); 252462306a36Sopenharmony_ci } 252562306a36Sopenharmony_ci 252662306a36Sopenharmony_ci for (i = 0; i < adapter->num_xdp_queues; i++) { 252762306a36Sopenharmony_ci u8 reg_idx = adapter->xdp_ring[i]->reg_idx; 252862306a36Sopenharmony_ci 252962306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VFTXDCTL(reg_idx), 253062306a36Sopenharmony_ci IXGBE_TXDCTL_SWFLSH); 253162306a36Sopenharmony_ci } 253262306a36Sopenharmony_ci 253362306a36Sopenharmony_ci if (!pci_channel_offline(adapter->pdev)) 253462306a36Sopenharmony_ci ixgbevf_reset(adapter); 253562306a36Sopenharmony_ci 253662306a36Sopenharmony_ci ixgbevf_clean_all_tx_rings(adapter); 253762306a36Sopenharmony_ci ixgbevf_clean_all_rx_rings(adapter); 253862306a36Sopenharmony_ci} 253962306a36Sopenharmony_ci 254062306a36Sopenharmony_civoid ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter) 254162306a36Sopenharmony_ci{ 254262306a36Sopenharmony_ci while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) 254362306a36Sopenharmony_ci msleep(1); 254462306a36Sopenharmony_ci 254562306a36Sopenharmony_ci ixgbevf_down(adapter); 254662306a36Sopenharmony_ci pci_set_master(adapter->pdev); 254762306a36Sopenharmony_ci ixgbevf_up(adapter); 254862306a36Sopenharmony_ci 254962306a36Sopenharmony_ci clear_bit(__IXGBEVF_RESETTING, &adapter->state); 255062306a36Sopenharmony_ci} 255162306a36Sopenharmony_ci 255262306a36Sopenharmony_civoid ixgbevf_reset(struct ixgbevf_adapter *adapter) 255362306a36Sopenharmony_ci{ 255462306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 255562306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 255662306a36Sopenharmony_ci 255762306a36Sopenharmony_ci if (hw->mac.ops.reset_hw(hw)) { 255862306a36Sopenharmony_ci hw_dbg(hw, "PF still resetting\n"); 255962306a36Sopenharmony_ci } else { 256062306a36Sopenharmony_ci hw->mac.ops.init_hw(hw); 256162306a36Sopenharmony_ci ixgbevf_negotiate_api(adapter); 256262306a36Sopenharmony_ci } 256362306a36Sopenharmony_ci 256462306a36Sopenharmony_ci if (is_valid_ether_addr(adapter->hw.mac.addr)) { 256562306a36Sopenharmony_ci eth_hw_addr_set(netdev, adapter->hw.mac.addr); 256662306a36Sopenharmony_ci ether_addr_copy(netdev->perm_addr, adapter->hw.mac.addr); 256762306a36Sopenharmony_ci } 256862306a36Sopenharmony_ci 256962306a36Sopenharmony_ci adapter->last_reset = jiffies; 257062306a36Sopenharmony_ci} 257162306a36Sopenharmony_ci 257262306a36Sopenharmony_cistatic int ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter, 257362306a36Sopenharmony_ci int vectors) 257462306a36Sopenharmony_ci{ 257562306a36Sopenharmony_ci int vector_threshold; 257662306a36Sopenharmony_ci 257762306a36Sopenharmony_ci /* We'll want at least 2 (vector_threshold): 257862306a36Sopenharmony_ci * 1) TxQ[0] + RxQ[0] handler 257962306a36Sopenharmony_ci * 2) Other (Link Status Change, etc.) 258062306a36Sopenharmony_ci */ 258162306a36Sopenharmony_ci vector_threshold = MIN_MSIX_COUNT; 258262306a36Sopenharmony_ci 258362306a36Sopenharmony_ci /* The more we get, the more we will assign to Tx/Rx Cleanup 258462306a36Sopenharmony_ci * for the separate queues...where Rx Cleanup >= Tx Cleanup. 258562306a36Sopenharmony_ci * Right now, we simply care about how many we'll get; we'll 258662306a36Sopenharmony_ci * set them up later while requesting irq's. 258762306a36Sopenharmony_ci */ 258862306a36Sopenharmony_ci vectors = pci_enable_msix_range(adapter->pdev, adapter->msix_entries, 258962306a36Sopenharmony_ci vector_threshold, vectors); 259062306a36Sopenharmony_ci 259162306a36Sopenharmony_ci if (vectors < 0) { 259262306a36Sopenharmony_ci dev_err(&adapter->pdev->dev, 259362306a36Sopenharmony_ci "Unable to allocate MSI-X interrupts\n"); 259462306a36Sopenharmony_ci kfree(adapter->msix_entries); 259562306a36Sopenharmony_ci adapter->msix_entries = NULL; 259662306a36Sopenharmony_ci return vectors; 259762306a36Sopenharmony_ci } 259862306a36Sopenharmony_ci 259962306a36Sopenharmony_ci /* Adjust for only the vectors we'll use, which is minimum 260062306a36Sopenharmony_ci * of max_msix_q_vectors + NON_Q_VECTORS, or the number of 260162306a36Sopenharmony_ci * vectors we were allocated. 260262306a36Sopenharmony_ci */ 260362306a36Sopenharmony_ci adapter->num_msix_vectors = vectors; 260462306a36Sopenharmony_ci 260562306a36Sopenharmony_ci return 0; 260662306a36Sopenharmony_ci} 260762306a36Sopenharmony_ci 260862306a36Sopenharmony_ci/** 260962306a36Sopenharmony_ci * ixgbevf_set_num_queues - Allocate queues for device, feature dependent 261062306a36Sopenharmony_ci * @adapter: board private structure to initialize 261162306a36Sopenharmony_ci * 261262306a36Sopenharmony_ci * This is the top level queue allocation routine. The order here is very 261362306a36Sopenharmony_ci * important, starting with the "most" number of features turned on at once, 261462306a36Sopenharmony_ci * and ending with the smallest set of features. This way large combinations 261562306a36Sopenharmony_ci * can be allocated if they're turned on, and smaller combinations are the 261662306a36Sopenharmony_ci * fall through conditions. 261762306a36Sopenharmony_ci * 261862306a36Sopenharmony_ci **/ 261962306a36Sopenharmony_cistatic void ixgbevf_set_num_queues(struct ixgbevf_adapter *adapter) 262062306a36Sopenharmony_ci{ 262162306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 262262306a36Sopenharmony_ci unsigned int def_q = 0; 262362306a36Sopenharmony_ci unsigned int num_tcs = 0; 262462306a36Sopenharmony_ci int err; 262562306a36Sopenharmony_ci 262662306a36Sopenharmony_ci /* Start with base case */ 262762306a36Sopenharmony_ci adapter->num_rx_queues = 1; 262862306a36Sopenharmony_ci adapter->num_tx_queues = 1; 262962306a36Sopenharmony_ci adapter->num_xdp_queues = 0; 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_ci spin_lock_bh(&adapter->mbx_lock); 263262306a36Sopenharmony_ci 263362306a36Sopenharmony_ci /* fetch queue configuration from the PF */ 263462306a36Sopenharmony_ci err = ixgbevf_get_queues(hw, &num_tcs, &def_q); 263562306a36Sopenharmony_ci 263662306a36Sopenharmony_ci spin_unlock_bh(&adapter->mbx_lock); 263762306a36Sopenharmony_ci 263862306a36Sopenharmony_ci if (err) 263962306a36Sopenharmony_ci return; 264062306a36Sopenharmony_ci 264162306a36Sopenharmony_ci /* we need as many queues as traffic classes */ 264262306a36Sopenharmony_ci if (num_tcs > 1) { 264362306a36Sopenharmony_ci adapter->num_rx_queues = num_tcs; 264462306a36Sopenharmony_ci } else { 264562306a36Sopenharmony_ci u16 rss = min_t(u16, num_online_cpus(), IXGBEVF_MAX_RSS_QUEUES); 264662306a36Sopenharmony_ci 264762306a36Sopenharmony_ci switch (hw->api_version) { 264862306a36Sopenharmony_ci case ixgbe_mbox_api_11: 264962306a36Sopenharmony_ci case ixgbe_mbox_api_12: 265062306a36Sopenharmony_ci case ixgbe_mbox_api_13: 265162306a36Sopenharmony_ci case ixgbe_mbox_api_14: 265262306a36Sopenharmony_ci case ixgbe_mbox_api_15: 265362306a36Sopenharmony_ci if (adapter->xdp_prog && 265462306a36Sopenharmony_ci hw->mac.max_tx_queues == rss) 265562306a36Sopenharmony_ci rss = rss > 3 ? 2 : 1; 265662306a36Sopenharmony_ci 265762306a36Sopenharmony_ci adapter->num_rx_queues = rss; 265862306a36Sopenharmony_ci adapter->num_tx_queues = rss; 265962306a36Sopenharmony_ci adapter->num_xdp_queues = adapter->xdp_prog ? rss : 0; 266062306a36Sopenharmony_ci break; 266162306a36Sopenharmony_ci default: 266262306a36Sopenharmony_ci break; 266362306a36Sopenharmony_ci } 266462306a36Sopenharmony_ci } 266562306a36Sopenharmony_ci} 266662306a36Sopenharmony_ci 266762306a36Sopenharmony_ci/** 266862306a36Sopenharmony_ci * ixgbevf_set_interrupt_capability - set MSI-X or FAIL if not supported 266962306a36Sopenharmony_ci * @adapter: board private structure to initialize 267062306a36Sopenharmony_ci * 267162306a36Sopenharmony_ci * Attempt to configure the interrupts using the best available 267262306a36Sopenharmony_ci * capabilities of the hardware and the kernel. 267362306a36Sopenharmony_ci **/ 267462306a36Sopenharmony_cistatic int ixgbevf_set_interrupt_capability(struct ixgbevf_adapter *adapter) 267562306a36Sopenharmony_ci{ 267662306a36Sopenharmony_ci int vector, v_budget; 267762306a36Sopenharmony_ci 267862306a36Sopenharmony_ci /* It's easy to be greedy for MSI-X vectors, but it really 267962306a36Sopenharmony_ci * doesn't do us much good if we have a lot more vectors 268062306a36Sopenharmony_ci * than CPU's. So let's be conservative and only ask for 268162306a36Sopenharmony_ci * (roughly) the same number of vectors as there are CPU's. 268262306a36Sopenharmony_ci * The default is to use pairs of vectors. 268362306a36Sopenharmony_ci */ 268462306a36Sopenharmony_ci v_budget = max(adapter->num_rx_queues, adapter->num_tx_queues); 268562306a36Sopenharmony_ci v_budget = min_t(int, v_budget, num_online_cpus()); 268662306a36Sopenharmony_ci v_budget += NON_Q_VECTORS; 268762306a36Sopenharmony_ci 268862306a36Sopenharmony_ci adapter->msix_entries = kcalloc(v_budget, 268962306a36Sopenharmony_ci sizeof(struct msix_entry), GFP_KERNEL); 269062306a36Sopenharmony_ci if (!adapter->msix_entries) 269162306a36Sopenharmony_ci return -ENOMEM; 269262306a36Sopenharmony_ci 269362306a36Sopenharmony_ci for (vector = 0; vector < v_budget; vector++) 269462306a36Sopenharmony_ci adapter->msix_entries[vector].entry = vector; 269562306a36Sopenharmony_ci 269662306a36Sopenharmony_ci /* A failure in MSI-X entry allocation isn't fatal, but the VF driver 269762306a36Sopenharmony_ci * does not support any other modes, so we will simply fail here. Note 269862306a36Sopenharmony_ci * that we clean up the msix_entries pointer else-where. 269962306a36Sopenharmony_ci */ 270062306a36Sopenharmony_ci return ixgbevf_acquire_msix_vectors(adapter, v_budget); 270162306a36Sopenharmony_ci} 270262306a36Sopenharmony_ci 270362306a36Sopenharmony_cistatic void ixgbevf_add_ring(struct ixgbevf_ring *ring, 270462306a36Sopenharmony_ci struct ixgbevf_ring_container *head) 270562306a36Sopenharmony_ci{ 270662306a36Sopenharmony_ci ring->next = head->ring; 270762306a36Sopenharmony_ci head->ring = ring; 270862306a36Sopenharmony_ci head->count++; 270962306a36Sopenharmony_ci} 271062306a36Sopenharmony_ci 271162306a36Sopenharmony_ci/** 271262306a36Sopenharmony_ci * ixgbevf_alloc_q_vector - Allocate memory for a single interrupt vector 271362306a36Sopenharmony_ci * @adapter: board private structure to initialize 271462306a36Sopenharmony_ci * @v_idx: index of vector in adapter struct 271562306a36Sopenharmony_ci * @txr_count: number of Tx rings for q vector 271662306a36Sopenharmony_ci * @txr_idx: index of first Tx ring to assign 271762306a36Sopenharmony_ci * @xdp_count: total number of XDP rings to allocate 271862306a36Sopenharmony_ci * @xdp_idx: index of first XDP ring to allocate 271962306a36Sopenharmony_ci * @rxr_count: number of Rx rings for q vector 272062306a36Sopenharmony_ci * @rxr_idx: index of first Rx ring to assign 272162306a36Sopenharmony_ci * 272262306a36Sopenharmony_ci * We allocate one q_vector. If allocation fails we return -ENOMEM. 272362306a36Sopenharmony_ci **/ 272462306a36Sopenharmony_cistatic int ixgbevf_alloc_q_vector(struct ixgbevf_adapter *adapter, int v_idx, 272562306a36Sopenharmony_ci int txr_count, int txr_idx, 272662306a36Sopenharmony_ci int xdp_count, int xdp_idx, 272762306a36Sopenharmony_ci int rxr_count, int rxr_idx) 272862306a36Sopenharmony_ci{ 272962306a36Sopenharmony_ci struct ixgbevf_q_vector *q_vector; 273062306a36Sopenharmony_ci int reg_idx = txr_idx + xdp_idx; 273162306a36Sopenharmony_ci struct ixgbevf_ring *ring; 273262306a36Sopenharmony_ci int ring_count, size; 273362306a36Sopenharmony_ci 273462306a36Sopenharmony_ci ring_count = txr_count + xdp_count + rxr_count; 273562306a36Sopenharmony_ci size = sizeof(*q_vector) + (sizeof(*ring) * ring_count); 273662306a36Sopenharmony_ci 273762306a36Sopenharmony_ci /* allocate q_vector and rings */ 273862306a36Sopenharmony_ci q_vector = kzalloc(size, GFP_KERNEL); 273962306a36Sopenharmony_ci if (!q_vector) 274062306a36Sopenharmony_ci return -ENOMEM; 274162306a36Sopenharmony_ci 274262306a36Sopenharmony_ci /* initialize NAPI */ 274362306a36Sopenharmony_ci netif_napi_add(adapter->netdev, &q_vector->napi, ixgbevf_poll); 274462306a36Sopenharmony_ci 274562306a36Sopenharmony_ci /* tie q_vector and adapter together */ 274662306a36Sopenharmony_ci adapter->q_vector[v_idx] = q_vector; 274762306a36Sopenharmony_ci q_vector->adapter = adapter; 274862306a36Sopenharmony_ci q_vector->v_idx = v_idx; 274962306a36Sopenharmony_ci 275062306a36Sopenharmony_ci /* initialize pointer to rings */ 275162306a36Sopenharmony_ci ring = q_vector->ring; 275262306a36Sopenharmony_ci 275362306a36Sopenharmony_ci while (txr_count) { 275462306a36Sopenharmony_ci /* assign generic ring traits */ 275562306a36Sopenharmony_ci ring->dev = &adapter->pdev->dev; 275662306a36Sopenharmony_ci ring->netdev = adapter->netdev; 275762306a36Sopenharmony_ci 275862306a36Sopenharmony_ci /* configure backlink on ring */ 275962306a36Sopenharmony_ci ring->q_vector = q_vector; 276062306a36Sopenharmony_ci 276162306a36Sopenharmony_ci /* update q_vector Tx values */ 276262306a36Sopenharmony_ci ixgbevf_add_ring(ring, &q_vector->tx); 276362306a36Sopenharmony_ci 276462306a36Sopenharmony_ci /* apply Tx specific ring traits */ 276562306a36Sopenharmony_ci ring->count = adapter->tx_ring_count; 276662306a36Sopenharmony_ci ring->queue_index = txr_idx; 276762306a36Sopenharmony_ci ring->reg_idx = reg_idx; 276862306a36Sopenharmony_ci 276962306a36Sopenharmony_ci /* assign ring to adapter */ 277062306a36Sopenharmony_ci adapter->tx_ring[txr_idx] = ring; 277162306a36Sopenharmony_ci 277262306a36Sopenharmony_ci /* update count and index */ 277362306a36Sopenharmony_ci txr_count--; 277462306a36Sopenharmony_ci txr_idx++; 277562306a36Sopenharmony_ci reg_idx++; 277662306a36Sopenharmony_ci 277762306a36Sopenharmony_ci /* push pointer to next ring */ 277862306a36Sopenharmony_ci ring++; 277962306a36Sopenharmony_ci } 278062306a36Sopenharmony_ci 278162306a36Sopenharmony_ci while (xdp_count) { 278262306a36Sopenharmony_ci /* assign generic ring traits */ 278362306a36Sopenharmony_ci ring->dev = &adapter->pdev->dev; 278462306a36Sopenharmony_ci ring->netdev = adapter->netdev; 278562306a36Sopenharmony_ci 278662306a36Sopenharmony_ci /* configure backlink on ring */ 278762306a36Sopenharmony_ci ring->q_vector = q_vector; 278862306a36Sopenharmony_ci 278962306a36Sopenharmony_ci /* update q_vector Tx values */ 279062306a36Sopenharmony_ci ixgbevf_add_ring(ring, &q_vector->tx); 279162306a36Sopenharmony_ci 279262306a36Sopenharmony_ci /* apply Tx specific ring traits */ 279362306a36Sopenharmony_ci ring->count = adapter->tx_ring_count; 279462306a36Sopenharmony_ci ring->queue_index = xdp_idx; 279562306a36Sopenharmony_ci ring->reg_idx = reg_idx; 279662306a36Sopenharmony_ci set_ring_xdp(ring); 279762306a36Sopenharmony_ci 279862306a36Sopenharmony_ci /* assign ring to adapter */ 279962306a36Sopenharmony_ci adapter->xdp_ring[xdp_idx] = ring; 280062306a36Sopenharmony_ci 280162306a36Sopenharmony_ci /* update count and index */ 280262306a36Sopenharmony_ci xdp_count--; 280362306a36Sopenharmony_ci xdp_idx++; 280462306a36Sopenharmony_ci reg_idx++; 280562306a36Sopenharmony_ci 280662306a36Sopenharmony_ci /* push pointer to next ring */ 280762306a36Sopenharmony_ci ring++; 280862306a36Sopenharmony_ci } 280962306a36Sopenharmony_ci 281062306a36Sopenharmony_ci while (rxr_count) { 281162306a36Sopenharmony_ci /* assign generic ring traits */ 281262306a36Sopenharmony_ci ring->dev = &adapter->pdev->dev; 281362306a36Sopenharmony_ci ring->netdev = adapter->netdev; 281462306a36Sopenharmony_ci 281562306a36Sopenharmony_ci /* configure backlink on ring */ 281662306a36Sopenharmony_ci ring->q_vector = q_vector; 281762306a36Sopenharmony_ci 281862306a36Sopenharmony_ci /* update q_vector Rx values */ 281962306a36Sopenharmony_ci ixgbevf_add_ring(ring, &q_vector->rx); 282062306a36Sopenharmony_ci 282162306a36Sopenharmony_ci /* apply Rx specific ring traits */ 282262306a36Sopenharmony_ci ring->count = adapter->rx_ring_count; 282362306a36Sopenharmony_ci ring->queue_index = rxr_idx; 282462306a36Sopenharmony_ci ring->reg_idx = rxr_idx; 282562306a36Sopenharmony_ci 282662306a36Sopenharmony_ci /* assign ring to adapter */ 282762306a36Sopenharmony_ci adapter->rx_ring[rxr_idx] = ring; 282862306a36Sopenharmony_ci 282962306a36Sopenharmony_ci /* update count and index */ 283062306a36Sopenharmony_ci rxr_count--; 283162306a36Sopenharmony_ci rxr_idx++; 283262306a36Sopenharmony_ci 283362306a36Sopenharmony_ci /* push pointer to next ring */ 283462306a36Sopenharmony_ci ring++; 283562306a36Sopenharmony_ci } 283662306a36Sopenharmony_ci 283762306a36Sopenharmony_ci return 0; 283862306a36Sopenharmony_ci} 283962306a36Sopenharmony_ci 284062306a36Sopenharmony_ci/** 284162306a36Sopenharmony_ci * ixgbevf_free_q_vector - Free memory allocated for specific interrupt vector 284262306a36Sopenharmony_ci * @adapter: board private structure to initialize 284362306a36Sopenharmony_ci * @v_idx: index of vector in adapter struct 284462306a36Sopenharmony_ci * 284562306a36Sopenharmony_ci * This function frees the memory allocated to the q_vector. In addition if 284662306a36Sopenharmony_ci * NAPI is enabled it will delete any references to the NAPI struct prior 284762306a36Sopenharmony_ci * to freeing the q_vector. 284862306a36Sopenharmony_ci **/ 284962306a36Sopenharmony_cistatic void ixgbevf_free_q_vector(struct ixgbevf_adapter *adapter, int v_idx) 285062306a36Sopenharmony_ci{ 285162306a36Sopenharmony_ci struct ixgbevf_q_vector *q_vector = adapter->q_vector[v_idx]; 285262306a36Sopenharmony_ci struct ixgbevf_ring *ring; 285362306a36Sopenharmony_ci 285462306a36Sopenharmony_ci ixgbevf_for_each_ring(ring, q_vector->tx) { 285562306a36Sopenharmony_ci if (ring_is_xdp(ring)) 285662306a36Sopenharmony_ci adapter->xdp_ring[ring->queue_index] = NULL; 285762306a36Sopenharmony_ci else 285862306a36Sopenharmony_ci adapter->tx_ring[ring->queue_index] = NULL; 285962306a36Sopenharmony_ci } 286062306a36Sopenharmony_ci 286162306a36Sopenharmony_ci ixgbevf_for_each_ring(ring, q_vector->rx) 286262306a36Sopenharmony_ci adapter->rx_ring[ring->queue_index] = NULL; 286362306a36Sopenharmony_ci 286462306a36Sopenharmony_ci adapter->q_vector[v_idx] = NULL; 286562306a36Sopenharmony_ci netif_napi_del(&q_vector->napi); 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_ci /* ixgbevf_get_stats() might access the rings on this vector, 286862306a36Sopenharmony_ci * we must wait a grace period before freeing it. 286962306a36Sopenharmony_ci */ 287062306a36Sopenharmony_ci kfree_rcu(q_vector, rcu); 287162306a36Sopenharmony_ci} 287262306a36Sopenharmony_ci 287362306a36Sopenharmony_ci/** 287462306a36Sopenharmony_ci * ixgbevf_alloc_q_vectors - Allocate memory for interrupt vectors 287562306a36Sopenharmony_ci * @adapter: board private structure to initialize 287662306a36Sopenharmony_ci * 287762306a36Sopenharmony_ci * We allocate one q_vector per queue interrupt. If allocation fails we 287862306a36Sopenharmony_ci * return -ENOMEM. 287962306a36Sopenharmony_ci **/ 288062306a36Sopenharmony_cistatic int ixgbevf_alloc_q_vectors(struct ixgbevf_adapter *adapter) 288162306a36Sopenharmony_ci{ 288262306a36Sopenharmony_ci int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; 288362306a36Sopenharmony_ci int rxr_remaining = adapter->num_rx_queues; 288462306a36Sopenharmony_ci int txr_remaining = adapter->num_tx_queues; 288562306a36Sopenharmony_ci int xdp_remaining = adapter->num_xdp_queues; 288662306a36Sopenharmony_ci int rxr_idx = 0, txr_idx = 0, xdp_idx = 0, v_idx = 0; 288762306a36Sopenharmony_ci int err; 288862306a36Sopenharmony_ci 288962306a36Sopenharmony_ci if (q_vectors >= (rxr_remaining + txr_remaining + xdp_remaining)) { 289062306a36Sopenharmony_ci for (; rxr_remaining; v_idx++, q_vectors--) { 289162306a36Sopenharmony_ci int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors); 289262306a36Sopenharmony_ci 289362306a36Sopenharmony_ci err = ixgbevf_alloc_q_vector(adapter, v_idx, 289462306a36Sopenharmony_ci 0, 0, 0, 0, rqpv, rxr_idx); 289562306a36Sopenharmony_ci if (err) 289662306a36Sopenharmony_ci goto err_out; 289762306a36Sopenharmony_ci 289862306a36Sopenharmony_ci /* update counts and index */ 289962306a36Sopenharmony_ci rxr_remaining -= rqpv; 290062306a36Sopenharmony_ci rxr_idx += rqpv; 290162306a36Sopenharmony_ci } 290262306a36Sopenharmony_ci } 290362306a36Sopenharmony_ci 290462306a36Sopenharmony_ci for (; q_vectors; v_idx++, q_vectors--) { 290562306a36Sopenharmony_ci int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors); 290662306a36Sopenharmony_ci int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors); 290762306a36Sopenharmony_ci int xqpv = DIV_ROUND_UP(xdp_remaining, q_vectors); 290862306a36Sopenharmony_ci 290962306a36Sopenharmony_ci err = ixgbevf_alloc_q_vector(adapter, v_idx, 291062306a36Sopenharmony_ci tqpv, txr_idx, 291162306a36Sopenharmony_ci xqpv, xdp_idx, 291262306a36Sopenharmony_ci rqpv, rxr_idx); 291362306a36Sopenharmony_ci 291462306a36Sopenharmony_ci if (err) 291562306a36Sopenharmony_ci goto err_out; 291662306a36Sopenharmony_ci 291762306a36Sopenharmony_ci /* update counts and index */ 291862306a36Sopenharmony_ci rxr_remaining -= rqpv; 291962306a36Sopenharmony_ci rxr_idx += rqpv; 292062306a36Sopenharmony_ci txr_remaining -= tqpv; 292162306a36Sopenharmony_ci txr_idx += tqpv; 292262306a36Sopenharmony_ci xdp_remaining -= xqpv; 292362306a36Sopenharmony_ci xdp_idx += xqpv; 292462306a36Sopenharmony_ci } 292562306a36Sopenharmony_ci 292662306a36Sopenharmony_ci return 0; 292762306a36Sopenharmony_ci 292862306a36Sopenharmony_cierr_out: 292962306a36Sopenharmony_ci while (v_idx) { 293062306a36Sopenharmony_ci v_idx--; 293162306a36Sopenharmony_ci ixgbevf_free_q_vector(adapter, v_idx); 293262306a36Sopenharmony_ci } 293362306a36Sopenharmony_ci 293462306a36Sopenharmony_ci return -ENOMEM; 293562306a36Sopenharmony_ci} 293662306a36Sopenharmony_ci 293762306a36Sopenharmony_ci/** 293862306a36Sopenharmony_ci * ixgbevf_free_q_vectors - Free memory allocated for interrupt vectors 293962306a36Sopenharmony_ci * @adapter: board private structure to initialize 294062306a36Sopenharmony_ci * 294162306a36Sopenharmony_ci * This function frees the memory allocated to the q_vectors. In addition if 294262306a36Sopenharmony_ci * NAPI is enabled it will delete any references to the NAPI struct prior 294362306a36Sopenharmony_ci * to freeing the q_vector. 294462306a36Sopenharmony_ci **/ 294562306a36Sopenharmony_cistatic void ixgbevf_free_q_vectors(struct ixgbevf_adapter *adapter) 294662306a36Sopenharmony_ci{ 294762306a36Sopenharmony_ci int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; 294862306a36Sopenharmony_ci 294962306a36Sopenharmony_ci while (q_vectors) { 295062306a36Sopenharmony_ci q_vectors--; 295162306a36Sopenharmony_ci ixgbevf_free_q_vector(adapter, q_vectors); 295262306a36Sopenharmony_ci } 295362306a36Sopenharmony_ci} 295462306a36Sopenharmony_ci 295562306a36Sopenharmony_ci/** 295662306a36Sopenharmony_ci * ixgbevf_reset_interrupt_capability - Reset MSIX setup 295762306a36Sopenharmony_ci * @adapter: board private structure 295862306a36Sopenharmony_ci * 295962306a36Sopenharmony_ci **/ 296062306a36Sopenharmony_cistatic void ixgbevf_reset_interrupt_capability(struct ixgbevf_adapter *adapter) 296162306a36Sopenharmony_ci{ 296262306a36Sopenharmony_ci if (!adapter->msix_entries) 296362306a36Sopenharmony_ci return; 296462306a36Sopenharmony_ci 296562306a36Sopenharmony_ci pci_disable_msix(adapter->pdev); 296662306a36Sopenharmony_ci kfree(adapter->msix_entries); 296762306a36Sopenharmony_ci adapter->msix_entries = NULL; 296862306a36Sopenharmony_ci} 296962306a36Sopenharmony_ci 297062306a36Sopenharmony_ci/** 297162306a36Sopenharmony_ci * ixgbevf_init_interrupt_scheme - Determine if MSIX is supported and init 297262306a36Sopenharmony_ci * @adapter: board private structure to initialize 297362306a36Sopenharmony_ci * 297462306a36Sopenharmony_ci **/ 297562306a36Sopenharmony_cistatic int ixgbevf_init_interrupt_scheme(struct ixgbevf_adapter *adapter) 297662306a36Sopenharmony_ci{ 297762306a36Sopenharmony_ci int err; 297862306a36Sopenharmony_ci 297962306a36Sopenharmony_ci /* Number of supported queues */ 298062306a36Sopenharmony_ci ixgbevf_set_num_queues(adapter); 298162306a36Sopenharmony_ci 298262306a36Sopenharmony_ci err = ixgbevf_set_interrupt_capability(adapter); 298362306a36Sopenharmony_ci if (err) { 298462306a36Sopenharmony_ci hw_dbg(&adapter->hw, 298562306a36Sopenharmony_ci "Unable to setup interrupt capabilities\n"); 298662306a36Sopenharmony_ci goto err_set_interrupt; 298762306a36Sopenharmony_ci } 298862306a36Sopenharmony_ci 298962306a36Sopenharmony_ci err = ixgbevf_alloc_q_vectors(adapter); 299062306a36Sopenharmony_ci if (err) { 299162306a36Sopenharmony_ci hw_dbg(&adapter->hw, "Unable to allocate memory for queue vectors\n"); 299262306a36Sopenharmony_ci goto err_alloc_q_vectors; 299362306a36Sopenharmony_ci } 299462306a36Sopenharmony_ci 299562306a36Sopenharmony_ci hw_dbg(&adapter->hw, "Multiqueue %s: Rx Queue count = %u, Tx Queue count = %u XDP Queue count %u\n", 299662306a36Sopenharmony_ci (adapter->num_rx_queues > 1) ? "Enabled" : "Disabled", 299762306a36Sopenharmony_ci adapter->num_rx_queues, adapter->num_tx_queues, 299862306a36Sopenharmony_ci adapter->num_xdp_queues); 299962306a36Sopenharmony_ci 300062306a36Sopenharmony_ci set_bit(__IXGBEVF_DOWN, &adapter->state); 300162306a36Sopenharmony_ci 300262306a36Sopenharmony_ci return 0; 300362306a36Sopenharmony_cierr_alloc_q_vectors: 300462306a36Sopenharmony_ci ixgbevf_reset_interrupt_capability(adapter); 300562306a36Sopenharmony_cierr_set_interrupt: 300662306a36Sopenharmony_ci return err; 300762306a36Sopenharmony_ci} 300862306a36Sopenharmony_ci 300962306a36Sopenharmony_ci/** 301062306a36Sopenharmony_ci * ixgbevf_clear_interrupt_scheme - Clear the current interrupt scheme settings 301162306a36Sopenharmony_ci * @adapter: board private structure to clear interrupt scheme on 301262306a36Sopenharmony_ci * 301362306a36Sopenharmony_ci * We go through and clear interrupt specific resources and reset the structure 301462306a36Sopenharmony_ci * to pre-load conditions 301562306a36Sopenharmony_ci **/ 301662306a36Sopenharmony_cistatic void ixgbevf_clear_interrupt_scheme(struct ixgbevf_adapter *adapter) 301762306a36Sopenharmony_ci{ 301862306a36Sopenharmony_ci adapter->num_tx_queues = 0; 301962306a36Sopenharmony_ci adapter->num_xdp_queues = 0; 302062306a36Sopenharmony_ci adapter->num_rx_queues = 0; 302162306a36Sopenharmony_ci 302262306a36Sopenharmony_ci ixgbevf_free_q_vectors(adapter); 302362306a36Sopenharmony_ci ixgbevf_reset_interrupt_capability(adapter); 302462306a36Sopenharmony_ci} 302562306a36Sopenharmony_ci 302662306a36Sopenharmony_ci/** 302762306a36Sopenharmony_ci * ixgbevf_sw_init - Initialize general software structures 302862306a36Sopenharmony_ci * @adapter: board private structure to initialize 302962306a36Sopenharmony_ci * 303062306a36Sopenharmony_ci * ixgbevf_sw_init initializes the Adapter private data structure. 303162306a36Sopenharmony_ci * Fields are initialized based on PCI device information and 303262306a36Sopenharmony_ci * OS network device settings (MTU size). 303362306a36Sopenharmony_ci **/ 303462306a36Sopenharmony_cistatic int ixgbevf_sw_init(struct ixgbevf_adapter *adapter) 303562306a36Sopenharmony_ci{ 303662306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 303762306a36Sopenharmony_ci struct pci_dev *pdev = adapter->pdev; 303862306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 303962306a36Sopenharmony_ci int err; 304062306a36Sopenharmony_ci 304162306a36Sopenharmony_ci /* PCI config space info */ 304262306a36Sopenharmony_ci hw->vendor_id = pdev->vendor; 304362306a36Sopenharmony_ci hw->device_id = pdev->device; 304462306a36Sopenharmony_ci hw->revision_id = pdev->revision; 304562306a36Sopenharmony_ci hw->subsystem_vendor_id = pdev->subsystem_vendor; 304662306a36Sopenharmony_ci hw->subsystem_device_id = pdev->subsystem_device; 304762306a36Sopenharmony_ci 304862306a36Sopenharmony_ci hw->mbx.ops.init_params(hw); 304962306a36Sopenharmony_ci 305062306a36Sopenharmony_ci if (hw->mac.type >= ixgbe_mac_X550_vf) { 305162306a36Sopenharmony_ci err = ixgbevf_init_rss_key(adapter); 305262306a36Sopenharmony_ci if (err) 305362306a36Sopenharmony_ci goto out; 305462306a36Sopenharmony_ci } 305562306a36Sopenharmony_ci 305662306a36Sopenharmony_ci /* assume legacy case in which PF would only give VF 2 queues */ 305762306a36Sopenharmony_ci hw->mac.max_tx_queues = 2; 305862306a36Sopenharmony_ci hw->mac.max_rx_queues = 2; 305962306a36Sopenharmony_ci 306062306a36Sopenharmony_ci /* lock to protect mailbox accesses */ 306162306a36Sopenharmony_ci spin_lock_init(&adapter->mbx_lock); 306262306a36Sopenharmony_ci 306362306a36Sopenharmony_ci err = hw->mac.ops.reset_hw(hw); 306462306a36Sopenharmony_ci if (err) { 306562306a36Sopenharmony_ci dev_info(&pdev->dev, 306662306a36Sopenharmony_ci "PF still in reset state. Is the PF interface up?\n"); 306762306a36Sopenharmony_ci } else { 306862306a36Sopenharmony_ci err = hw->mac.ops.init_hw(hw); 306962306a36Sopenharmony_ci if (err) { 307062306a36Sopenharmony_ci pr_err("init_shared_code failed: %d\n", err); 307162306a36Sopenharmony_ci goto out; 307262306a36Sopenharmony_ci } 307362306a36Sopenharmony_ci ixgbevf_negotiate_api(adapter); 307462306a36Sopenharmony_ci err = hw->mac.ops.get_mac_addr(hw, hw->mac.addr); 307562306a36Sopenharmony_ci if (err) 307662306a36Sopenharmony_ci dev_info(&pdev->dev, "Error reading MAC address\n"); 307762306a36Sopenharmony_ci else if (is_zero_ether_addr(adapter->hw.mac.addr)) 307862306a36Sopenharmony_ci dev_info(&pdev->dev, 307962306a36Sopenharmony_ci "MAC address not assigned by administrator.\n"); 308062306a36Sopenharmony_ci eth_hw_addr_set(netdev, hw->mac.addr); 308162306a36Sopenharmony_ci } 308262306a36Sopenharmony_ci 308362306a36Sopenharmony_ci if (!is_valid_ether_addr(netdev->dev_addr)) { 308462306a36Sopenharmony_ci dev_info(&pdev->dev, "Assigning random MAC address\n"); 308562306a36Sopenharmony_ci eth_hw_addr_random(netdev); 308662306a36Sopenharmony_ci ether_addr_copy(hw->mac.addr, netdev->dev_addr); 308762306a36Sopenharmony_ci ether_addr_copy(hw->mac.perm_addr, netdev->dev_addr); 308862306a36Sopenharmony_ci } 308962306a36Sopenharmony_ci 309062306a36Sopenharmony_ci /* Enable dynamic interrupt throttling rates */ 309162306a36Sopenharmony_ci adapter->rx_itr_setting = 1; 309262306a36Sopenharmony_ci adapter->tx_itr_setting = 1; 309362306a36Sopenharmony_ci 309462306a36Sopenharmony_ci /* set default ring sizes */ 309562306a36Sopenharmony_ci adapter->tx_ring_count = IXGBEVF_DEFAULT_TXD; 309662306a36Sopenharmony_ci adapter->rx_ring_count = IXGBEVF_DEFAULT_RXD; 309762306a36Sopenharmony_ci 309862306a36Sopenharmony_ci adapter->link_state = true; 309962306a36Sopenharmony_ci 310062306a36Sopenharmony_ci set_bit(__IXGBEVF_DOWN, &adapter->state); 310162306a36Sopenharmony_ci return 0; 310262306a36Sopenharmony_ci 310362306a36Sopenharmony_ciout: 310462306a36Sopenharmony_ci return err; 310562306a36Sopenharmony_ci} 310662306a36Sopenharmony_ci 310762306a36Sopenharmony_ci#define UPDATE_VF_COUNTER_32bit(reg, last_counter, counter) \ 310862306a36Sopenharmony_ci { \ 310962306a36Sopenharmony_ci u32 current_counter = IXGBE_READ_REG(hw, reg); \ 311062306a36Sopenharmony_ci if (current_counter < last_counter) \ 311162306a36Sopenharmony_ci counter += 0x100000000LL; \ 311262306a36Sopenharmony_ci last_counter = current_counter; \ 311362306a36Sopenharmony_ci counter &= 0xFFFFFFFF00000000LL; \ 311462306a36Sopenharmony_ci counter |= current_counter; \ 311562306a36Sopenharmony_ci } 311662306a36Sopenharmony_ci 311762306a36Sopenharmony_ci#define UPDATE_VF_COUNTER_36bit(reg_lsb, reg_msb, last_counter, counter) \ 311862306a36Sopenharmony_ci { \ 311962306a36Sopenharmony_ci u64 current_counter_lsb = IXGBE_READ_REG(hw, reg_lsb); \ 312062306a36Sopenharmony_ci u64 current_counter_msb = IXGBE_READ_REG(hw, reg_msb); \ 312162306a36Sopenharmony_ci u64 current_counter = (current_counter_msb << 32) | \ 312262306a36Sopenharmony_ci current_counter_lsb; \ 312362306a36Sopenharmony_ci if (current_counter < last_counter) \ 312462306a36Sopenharmony_ci counter += 0x1000000000LL; \ 312562306a36Sopenharmony_ci last_counter = current_counter; \ 312662306a36Sopenharmony_ci counter &= 0xFFFFFFF000000000LL; \ 312762306a36Sopenharmony_ci counter |= current_counter; \ 312862306a36Sopenharmony_ci } 312962306a36Sopenharmony_ci/** 313062306a36Sopenharmony_ci * ixgbevf_update_stats - Update the board statistics counters. 313162306a36Sopenharmony_ci * @adapter: board private structure 313262306a36Sopenharmony_ci **/ 313362306a36Sopenharmony_civoid ixgbevf_update_stats(struct ixgbevf_adapter *adapter) 313462306a36Sopenharmony_ci{ 313562306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 313662306a36Sopenharmony_ci u64 alloc_rx_page_failed = 0, alloc_rx_buff_failed = 0; 313762306a36Sopenharmony_ci u64 alloc_rx_page = 0, hw_csum_rx_error = 0; 313862306a36Sopenharmony_ci int i; 313962306a36Sopenharmony_ci 314062306a36Sopenharmony_ci if (test_bit(__IXGBEVF_DOWN, &adapter->state) || 314162306a36Sopenharmony_ci test_bit(__IXGBEVF_RESETTING, &adapter->state)) 314262306a36Sopenharmony_ci return; 314362306a36Sopenharmony_ci 314462306a36Sopenharmony_ci UPDATE_VF_COUNTER_32bit(IXGBE_VFGPRC, adapter->stats.last_vfgprc, 314562306a36Sopenharmony_ci adapter->stats.vfgprc); 314662306a36Sopenharmony_ci UPDATE_VF_COUNTER_32bit(IXGBE_VFGPTC, adapter->stats.last_vfgptc, 314762306a36Sopenharmony_ci adapter->stats.vfgptc); 314862306a36Sopenharmony_ci UPDATE_VF_COUNTER_36bit(IXGBE_VFGORC_LSB, IXGBE_VFGORC_MSB, 314962306a36Sopenharmony_ci adapter->stats.last_vfgorc, 315062306a36Sopenharmony_ci adapter->stats.vfgorc); 315162306a36Sopenharmony_ci UPDATE_VF_COUNTER_36bit(IXGBE_VFGOTC_LSB, IXGBE_VFGOTC_MSB, 315262306a36Sopenharmony_ci adapter->stats.last_vfgotc, 315362306a36Sopenharmony_ci adapter->stats.vfgotc); 315462306a36Sopenharmony_ci UPDATE_VF_COUNTER_32bit(IXGBE_VFMPRC, adapter->stats.last_vfmprc, 315562306a36Sopenharmony_ci adapter->stats.vfmprc); 315662306a36Sopenharmony_ci 315762306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 315862306a36Sopenharmony_ci struct ixgbevf_ring *rx_ring = adapter->rx_ring[i]; 315962306a36Sopenharmony_ci 316062306a36Sopenharmony_ci hw_csum_rx_error += rx_ring->rx_stats.csum_err; 316162306a36Sopenharmony_ci alloc_rx_page_failed += rx_ring->rx_stats.alloc_rx_page_failed; 316262306a36Sopenharmony_ci alloc_rx_buff_failed += rx_ring->rx_stats.alloc_rx_buff_failed; 316362306a36Sopenharmony_ci alloc_rx_page += rx_ring->rx_stats.alloc_rx_page; 316462306a36Sopenharmony_ci } 316562306a36Sopenharmony_ci 316662306a36Sopenharmony_ci adapter->hw_csum_rx_error = hw_csum_rx_error; 316762306a36Sopenharmony_ci adapter->alloc_rx_page_failed = alloc_rx_page_failed; 316862306a36Sopenharmony_ci adapter->alloc_rx_buff_failed = alloc_rx_buff_failed; 316962306a36Sopenharmony_ci adapter->alloc_rx_page = alloc_rx_page; 317062306a36Sopenharmony_ci} 317162306a36Sopenharmony_ci 317262306a36Sopenharmony_ci/** 317362306a36Sopenharmony_ci * ixgbevf_service_timer - Timer Call-back 317462306a36Sopenharmony_ci * @t: pointer to timer_list struct 317562306a36Sopenharmony_ci **/ 317662306a36Sopenharmony_cistatic void ixgbevf_service_timer(struct timer_list *t) 317762306a36Sopenharmony_ci{ 317862306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = from_timer(adapter, t, 317962306a36Sopenharmony_ci service_timer); 318062306a36Sopenharmony_ci 318162306a36Sopenharmony_ci /* Reset the timer */ 318262306a36Sopenharmony_ci mod_timer(&adapter->service_timer, (HZ * 2) + jiffies); 318362306a36Sopenharmony_ci 318462306a36Sopenharmony_ci ixgbevf_service_event_schedule(adapter); 318562306a36Sopenharmony_ci} 318662306a36Sopenharmony_ci 318762306a36Sopenharmony_cistatic void ixgbevf_reset_subtask(struct ixgbevf_adapter *adapter) 318862306a36Sopenharmony_ci{ 318962306a36Sopenharmony_ci if (!test_and_clear_bit(__IXGBEVF_RESET_REQUESTED, &adapter->state)) 319062306a36Sopenharmony_ci return; 319162306a36Sopenharmony_ci 319262306a36Sopenharmony_ci rtnl_lock(); 319362306a36Sopenharmony_ci /* If we're already down or resetting, just bail */ 319462306a36Sopenharmony_ci if (test_bit(__IXGBEVF_DOWN, &adapter->state) || 319562306a36Sopenharmony_ci test_bit(__IXGBEVF_REMOVING, &adapter->state) || 319662306a36Sopenharmony_ci test_bit(__IXGBEVF_RESETTING, &adapter->state)) { 319762306a36Sopenharmony_ci rtnl_unlock(); 319862306a36Sopenharmony_ci return; 319962306a36Sopenharmony_ci } 320062306a36Sopenharmony_ci 320162306a36Sopenharmony_ci adapter->tx_timeout_count++; 320262306a36Sopenharmony_ci 320362306a36Sopenharmony_ci ixgbevf_reinit_locked(adapter); 320462306a36Sopenharmony_ci rtnl_unlock(); 320562306a36Sopenharmony_ci} 320662306a36Sopenharmony_ci 320762306a36Sopenharmony_ci/** 320862306a36Sopenharmony_ci * ixgbevf_check_hang_subtask - check for hung queues and dropped interrupts 320962306a36Sopenharmony_ci * @adapter: pointer to the device adapter structure 321062306a36Sopenharmony_ci * 321162306a36Sopenharmony_ci * This function serves two purposes. First it strobes the interrupt lines 321262306a36Sopenharmony_ci * in order to make certain interrupts are occurring. Secondly it sets the 321362306a36Sopenharmony_ci * bits needed to check for TX hangs. As a result we should immediately 321462306a36Sopenharmony_ci * determine if a hang has occurred. 321562306a36Sopenharmony_ci **/ 321662306a36Sopenharmony_cistatic void ixgbevf_check_hang_subtask(struct ixgbevf_adapter *adapter) 321762306a36Sopenharmony_ci{ 321862306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 321962306a36Sopenharmony_ci u32 eics = 0; 322062306a36Sopenharmony_ci int i; 322162306a36Sopenharmony_ci 322262306a36Sopenharmony_ci /* If we're down or resetting, just bail */ 322362306a36Sopenharmony_ci if (test_bit(__IXGBEVF_DOWN, &adapter->state) || 322462306a36Sopenharmony_ci test_bit(__IXGBEVF_RESETTING, &adapter->state)) 322562306a36Sopenharmony_ci return; 322662306a36Sopenharmony_ci 322762306a36Sopenharmony_ci /* Force detection of hung controller */ 322862306a36Sopenharmony_ci if (netif_carrier_ok(adapter->netdev)) { 322962306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 323062306a36Sopenharmony_ci set_check_for_tx_hang(adapter->tx_ring[i]); 323162306a36Sopenharmony_ci for (i = 0; i < adapter->num_xdp_queues; i++) 323262306a36Sopenharmony_ci set_check_for_tx_hang(adapter->xdp_ring[i]); 323362306a36Sopenharmony_ci } 323462306a36Sopenharmony_ci 323562306a36Sopenharmony_ci /* get one bit for every active Tx/Rx interrupt vector */ 323662306a36Sopenharmony_ci for (i = 0; i < adapter->num_msix_vectors - NON_Q_VECTORS; i++) { 323762306a36Sopenharmony_ci struct ixgbevf_q_vector *qv = adapter->q_vector[i]; 323862306a36Sopenharmony_ci 323962306a36Sopenharmony_ci if (qv->rx.ring || qv->tx.ring) 324062306a36Sopenharmony_ci eics |= BIT(i); 324162306a36Sopenharmony_ci } 324262306a36Sopenharmony_ci 324362306a36Sopenharmony_ci /* Cause software interrupt to ensure rings are cleaned */ 324462306a36Sopenharmony_ci IXGBE_WRITE_REG(hw, IXGBE_VTEICS, eics); 324562306a36Sopenharmony_ci} 324662306a36Sopenharmony_ci 324762306a36Sopenharmony_ci/** 324862306a36Sopenharmony_ci * ixgbevf_watchdog_update_link - update the link status 324962306a36Sopenharmony_ci * @adapter: pointer to the device adapter structure 325062306a36Sopenharmony_ci **/ 325162306a36Sopenharmony_cistatic void ixgbevf_watchdog_update_link(struct ixgbevf_adapter *adapter) 325262306a36Sopenharmony_ci{ 325362306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 325462306a36Sopenharmony_ci u32 link_speed = adapter->link_speed; 325562306a36Sopenharmony_ci bool link_up = adapter->link_up; 325662306a36Sopenharmony_ci s32 err; 325762306a36Sopenharmony_ci 325862306a36Sopenharmony_ci spin_lock_bh(&adapter->mbx_lock); 325962306a36Sopenharmony_ci 326062306a36Sopenharmony_ci err = hw->mac.ops.check_link(hw, &link_speed, &link_up, false); 326162306a36Sopenharmony_ci 326262306a36Sopenharmony_ci spin_unlock_bh(&adapter->mbx_lock); 326362306a36Sopenharmony_ci 326462306a36Sopenharmony_ci /* if check for link returns error we will need to reset */ 326562306a36Sopenharmony_ci if (err && time_after(jiffies, adapter->last_reset + (10 * HZ))) { 326662306a36Sopenharmony_ci set_bit(__IXGBEVF_RESET_REQUESTED, &adapter->state); 326762306a36Sopenharmony_ci link_up = false; 326862306a36Sopenharmony_ci } 326962306a36Sopenharmony_ci 327062306a36Sopenharmony_ci adapter->link_up = link_up; 327162306a36Sopenharmony_ci adapter->link_speed = link_speed; 327262306a36Sopenharmony_ci} 327362306a36Sopenharmony_ci 327462306a36Sopenharmony_ci/** 327562306a36Sopenharmony_ci * ixgbevf_watchdog_link_is_up - update netif_carrier status and 327662306a36Sopenharmony_ci * print link up message 327762306a36Sopenharmony_ci * @adapter: pointer to the device adapter structure 327862306a36Sopenharmony_ci **/ 327962306a36Sopenharmony_cistatic void ixgbevf_watchdog_link_is_up(struct ixgbevf_adapter *adapter) 328062306a36Sopenharmony_ci{ 328162306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 328262306a36Sopenharmony_ci 328362306a36Sopenharmony_ci /* only continue if link was previously down */ 328462306a36Sopenharmony_ci if (netif_carrier_ok(netdev)) 328562306a36Sopenharmony_ci return; 328662306a36Sopenharmony_ci 328762306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, "NIC Link is Up %s\n", 328862306a36Sopenharmony_ci (adapter->link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? 328962306a36Sopenharmony_ci "10 Gbps" : 329062306a36Sopenharmony_ci (adapter->link_speed == IXGBE_LINK_SPEED_1GB_FULL) ? 329162306a36Sopenharmony_ci "1 Gbps" : 329262306a36Sopenharmony_ci (adapter->link_speed == IXGBE_LINK_SPEED_100_FULL) ? 329362306a36Sopenharmony_ci "100 Mbps" : 329462306a36Sopenharmony_ci "unknown speed"); 329562306a36Sopenharmony_ci 329662306a36Sopenharmony_ci netif_carrier_on(netdev); 329762306a36Sopenharmony_ci} 329862306a36Sopenharmony_ci 329962306a36Sopenharmony_ci/** 330062306a36Sopenharmony_ci * ixgbevf_watchdog_link_is_down - update netif_carrier status and 330162306a36Sopenharmony_ci * print link down message 330262306a36Sopenharmony_ci * @adapter: pointer to the adapter structure 330362306a36Sopenharmony_ci **/ 330462306a36Sopenharmony_cistatic void ixgbevf_watchdog_link_is_down(struct ixgbevf_adapter *adapter) 330562306a36Sopenharmony_ci{ 330662306a36Sopenharmony_ci struct net_device *netdev = adapter->netdev; 330762306a36Sopenharmony_ci 330862306a36Sopenharmony_ci adapter->link_speed = 0; 330962306a36Sopenharmony_ci 331062306a36Sopenharmony_ci /* only continue if link was up previously */ 331162306a36Sopenharmony_ci if (!netif_carrier_ok(netdev)) 331262306a36Sopenharmony_ci return; 331362306a36Sopenharmony_ci 331462306a36Sopenharmony_ci dev_info(&adapter->pdev->dev, "NIC Link is Down\n"); 331562306a36Sopenharmony_ci 331662306a36Sopenharmony_ci netif_carrier_off(netdev); 331762306a36Sopenharmony_ci} 331862306a36Sopenharmony_ci 331962306a36Sopenharmony_ci/** 332062306a36Sopenharmony_ci * ixgbevf_watchdog_subtask - worker thread to bring link up 332162306a36Sopenharmony_ci * @adapter: board private structure 332262306a36Sopenharmony_ci **/ 332362306a36Sopenharmony_cistatic void ixgbevf_watchdog_subtask(struct ixgbevf_adapter *adapter) 332462306a36Sopenharmony_ci{ 332562306a36Sopenharmony_ci /* if interface is down do nothing */ 332662306a36Sopenharmony_ci if (test_bit(__IXGBEVF_DOWN, &adapter->state) || 332762306a36Sopenharmony_ci test_bit(__IXGBEVF_RESETTING, &adapter->state)) 332862306a36Sopenharmony_ci return; 332962306a36Sopenharmony_ci 333062306a36Sopenharmony_ci ixgbevf_watchdog_update_link(adapter); 333162306a36Sopenharmony_ci 333262306a36Sopenharmony_ci if (adapter->link_up && adapter->link_state) 333362306a36Sopenharmony_ci ixgbevf_watchdog_link_is_up(adapter); 333462306a36Sopenharmony_ci else 333562306a36Sopenharmony_ci ixgbevf_watchdog_link_is_down(adapter); 333662306a36Sopenharmony_ci 333762306a36Sopenharmony_ci ixgbevf_update_stats(adapter); 333862306a36Sopenharmony_ci} 333962306a36Sopenharmony_ci 334062306a36Sopenharmony_ci/** 334162306a36Sopenharmony_ci * ixgbevf_service_task - manages and runs subtasks 334262306a36Sopenharmony_ci * @work: pointer to work_struct containing our data 334362306a36Sopenharmony_ci **/ 334462306a36Sopenharmony_cistatic void ixgbevf_service_task(struct work_struct *work) 334562306a36Sopenharmony_ci{ 334662306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = container_of(work, 334762306a36Sopenharmony_ci struct ixgbevf_adapter, 334862306a36Sopenharmony_ci service_task); 334962306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 335062306a36Sopenharmony_ci 335162306a36Sopenharmony_ci if (IXGBE_REMOVED(hw->hw_addr)) { 335262306a36Sopenharmony_ci if (!test_bit(__IXGBEVF_DOWN, &adapter->state)) { 335362306a36Sopenharmony_ci rtnl_lock(); 335462306a36Sopenharmony_ci ixgbevf_down(adapter); 335562306a36Sopenharmony_ci rtnl_unlock(); 335662306a36Sopenharmony_ci } 335762306a36Sopenharmony_ci return; 335862306a36Sopenharmony_ci } 335962306a36Sopenharmony_ci 336062306a36Sopenharmony_ci ixgbevf_queue_reset_subtask(adapter); 336162306a36Sopenharmony_ci ixgbevf_reset_subtask(adapter); 336262306a36Sopenharmony_ci ixgbevf_watchdog_subtask(adapter); 336362306a36Sopenharmony_ci ixgbevf_check_hang_subtask(adapter); 336462306a36Sopenharmony_ci 336562306a36Sopenharmony_ci ixgbevf_service_event_complete(adapter); 336662306a36Sopenharmony_ci} 336762306a36Sopenharmony_ci 336862306a36Sopenharmony_ci/** 336962306a36Sopenharmony_ci * ixgbevf_free_tx_resources - Free Tx Resources per Queue 337062306a36Sopenharmony_ci * @tx_ring: Tx descriptor ring for a specific queue 337162306a36Sopenharmony_ci * 337262306a36Sopenharmony_ci * Free all transmit software resources 337362306a36Sopenharmony_ci **/ 337462306a36Sopenharmony_civoid ixgbevf_free_tx_resources(struct ixgbevf_ring *tx_ring) 337562306a36Sopenharmony_ci{ 337662306a36Sopenharmony_ci ixgbevf_clean_tx_ring(tx_ring); 337762306a36Sopenharmony_ci 337862306a36Sopenharmony_ci vfree(tx_ring->tx_buffer_info); 337962306a36Sopenharmony_ci tx_ring->tx_buffer_info = NULL; 338062306a36Sopenharmony_ci 338162306a36Sopenharmony_ci /* if not set, then don't free */ 338262306a36Sopenharmony_ci if (!tx_ring->desc) 338362306a36Sopenharmony_ci return; 338462306a36Sopenharmony_ci 338562306a36Sopenharmony_ci dma_free_coherent(tx_ring->dev, tx_ring->size, tx_ring->desc, 338662306a36Sopenharmony_ci tx_ring->dma); 338762306a36Sopenharmony_ci 338862306a36Sopenharmony_ci tx_ring->desc = NULL; 338962306a36Sopenharmony_ci} 339062306a36Sopenharmony_ci 339162306a36Sopenharmony_ci/** 339262306a36Sopenharmony_ci * ixgbevf_free_all_tx_resources - Free Tx Resources for All Queues 339362306a36Sopenharmony_ci * @adapter: board private structure 339462306a36Sopenharmony_ci * 339562306a36Sopenharmony_ci * Free all transmit software resources 339662306a36Sopenharmony_ci **/ 339762306a36Sopenharmony_cistatic void ixgbevf_free_all_tx_resources(struct ixgbevf_adapter *adapter) 339862306a36Sopenharmony_ci{ 339962306a36Sopenharmony_ci int i; 340062306a36Sopenharmony_ci 340162306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) 340262306a36Sopenharmony_ci if (adapter->tx_ring[i]->desc) 340362306a36Sopenharmony_ci ixgbevf_free_tx_resources(adapter->tx_ring[i]); 340462306a36Sopenharmony_ci for (i = 0; i < adapter->num_xdp_queues; i++) 340562306a36Sopenharmony_ci if (adapter->xdp_ring[i]->desc) 340662306a36Sopenharmony_ci ixgbevf_free_tx_resources(adapter->xdp_ring[i]); 340762306a36Sopenharmony_ci} 340862306a36Sopenharmony_ci 340962306a36Sopenharmony_ci/** 341062306a36Sopenharmony_ci * ixgbevf_setup_tx_resources - allocate Tx resources (Descriptors) 341162306a36Sopenharmony_ci * @tx_ring: Tx descriptor ring (for a specific queue) to setup 341262306a36Sopenharmony_ci * 341362306a36Sopenharmony_ci * Return 0 on success, negative on failure 341462306a36Sopenharmony_ci **/ 341562306a36Sopenharmony_ciint ixgbevf_setup_tx_resources(struct ixgbevf_ring *tx_ring) 341662306a36Sopenharmony_ci{ 341762306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(tx_ring->netdev); 341862306a36Sopenharmony_ci int size; 341962306a36Sopenharmony_ci 342062306a36Sopenharmony_ci size = sizeof(struct ixgbevf_tx_buffer) * tx_ring->count; 342162306a36Sopenharmony_ci tx_ring->tx_buffer_info = vmalloc(size); 342262306a36Sopenharmony_ci if (!tx_ring->tx_buffer_info) 342362306a36Sopenharmony_ci goto err; 342462306a36Sopenharmony_ci 342562306a36Sopenharmony_ci u64_stats_init(&tx_ring->syncp); 342662306a36Sopenharmony_ci 342762306a36Sopenharmony_ci /* round up to nearest 4K */ 342862306a36Sopenharmony_ci tx_ring->size = tx_ring->count * sizeof(union ixgbe_adv_tx_desc); 342962306a36Sopenharmony_ci tx_ring->size = ALIGN(tx_ring->size, 4096); 343062306a36Sopenharmony_ci 343162306a36Sopenharmony_ci tx_ring->desc = dma_alloc_coherent(tx_ring->dev, tx_ring->size, 343262306a36Sopenharmony_ci &tx_ring->dma, GFP_KERNEL); 343362306a36Sopenharmony_ci if (!tx_ring->desc) 343462306a36Sopenharmony_ci goto err; 343562306a36Sopenharmony_ci 343662306a36Sopenharmony_ci return 0; 343762306a36Sopenharmony_ci 343862306a36Sopenharmony_cierr: 343962306a36Sopenharmony_ci vfree(tx_ring->tx_buffer_info); 344062306a36Sopenharmony_ci tx_ring->tx_buffer_info = NULL; 344162306a36Sopenharmony_ci hw_dbg(&adapter->hw, "Unable to allocate memory for the transmit descriptor ring\n"); 344262306a36Sopenharmony_ci return -ENOMEM; 344362306a36Sopenharmony_ci} 344462306a36Sopenharmony_ci 344562306a36Sopenharmony_ci/** 344662306a36Sopenharmony_ci * ixgbevf_setup_all_tx_resources - allocate all queues Tx resources 344762306a36Sopenharmony_ci * @adapter: board private structure 344862306a36Sopenharmony_ci * 344962306a36Sopenharmony_ci * If this function returns with an error, then it's possible one or 345062306a36Sopenharmony_ci * more of the rings is populated (while the rest are not). It is the 345162306a36Sopenharmony_ci * callers duty to clean those orphaned rings. 345262306a36Sopenharmony_ci * 345362306a36Sopenharmony_ci * Return 0 on success, negative on failure 345462306a36Sopenharmony_ci **/ 345562306a36Sopenharmony_cistatic int ixgbevf_setup_all_tx_resources(struct ixgbevf_adapter *adapter) 345662306a36Sopenharmony_ci{ 345762306a36Sopenharmony_ci int i, j = 0, err = 0; 345862306a36Sopenharmony_ci 345962306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 346062306a36Sopenharmony_ci err = ixgbevf_setup_tx_resources(adapter->tx_ring[i]); 346162306a36Sopenharmony_ci if (!err) 346262306a36Sopenharmony_ci continue; 346362306a36Sopenharmony_ci hw_dbg(&adapter->hw, "Allocation for Tx Queue %u failed\n", i); 346462306a36Sopenharmony_ci goto err_setup_tx; 346562306a36Sopenharmony_ci } 346662306a36Sopenharmony_ci 346762306a36Sopenharmony_ci for (j = 0; j < adapter->num_xdp_queues; j++) { 346862306a36Sopenharmony_ci err = ixgbevf_setup_tx_resources(adapter->xdp_ring[j]); 346962306a36Sopenharmony_ci if (!err) 347062306a36Sopenharmony_ci continue; 347162306a36Sopenharmony_ci hw_dbg(&adapter->hw, "Allocation for XDP Queue %u failed\n", j); 347262306a36Sopenharmony_ci goto err_setup_tx; 347362306a36Sopenharmony_ci } 347462306a36Sopenharmony_ci 347562306a36Sopenharmony_ci return 0; 347662306a36Sopenharmony_cierr_setup_tx: 347762306a36Sopenharmony_ci /* rewind the index freeing the rings as we go */ 347862306a36Sopenharmony_ci while (j--) 347962306a36Sopenharmony_ci ixgbevf_free_tx_resources(adapter->xdp_ring[j]); 348062306a36Sopenharmony_ci while (i--) 348162306a36Sopenharmony_ci ixgbevf_free_tx_resources(adapter->tx_ring[i]); 348262306a36Sopenharmony_ci 348362306a36Sopenharmony_ci return err; 348462306a36Sopenharmony_ci} 348562306a36Sopenharmony_ci 348662306a36Sopenharmony_ci/** 348762306a36Sopenharmony_ci * ixgbevf_setup_rx_resources - allocate Rx resources (Descriptors) 348862306a36Sopenharmony_ci * @adapter: board private structure 348962306a36Sopenharmony_ci * @rx_ring: Rx descriptor ring (for a specific queue) to setup 349062306a36Sopenharmony_ci * 349162306a36Sopenharmony_ci * Returns 0 on success, negative on failure 349262306a36Sopenharmony_ci **/ 349362306a36Sopenharmony_ciint ixgbevf_setup_rx_resources(struct ixgbevf_adapter *adapter, 349462306a36Sopenharmony_ci struct ixgbevf_ring *rx_ring) 349562306a36Sopenharmony_ci{ 349662306a36Sopenharmony_ci int size; 349762306a36Sopenharmony_ci 349862306a36Sopenharmony_ci size = sizeof(struct ixgbevf_rx_buffer) * rx_ring->count; 349962306a36Sopenharmony_ci rx_ring->rx_buffer_info = vmalloc(size); 350062306a36Sopenharmony_ci if (!rx_ring->rx_buffer_info) 350162306a36Sopenharmony_ci goto err; 350262306a36Sopenharmony_ci 350362306a36Sopenharmony_ci u64_stats_init(&rx_ring->syncp); 350462306a36Sopenharmony_ci 350562306a36Sopenharmony_ci /* Round up to nearest 4K */ 350662306a36Sopenharmony_ci rx_ring->size = rx_ring->count * sizeof(union ixgbe_adv_rx_desc); 350762306a36Sopenharmony_ci rx_ring->size = ALIGN(rx_ring->size, 4096); 350862306a36Sopenharmony_ci 350962306a36Sopenharmony_ci rx_ring->desc = dma_alloc_coherent(rx_ring->dev, rx_ring->size, 351062306a36Sopenharmony_ci &rx_ring->dma, GFP_KERNEL); 351162306a36Sopenharmony_ci 351262306a36Sopenharmony_ci if (!rx_ring->desc) 351362306a36Sopenharmony_ci goto err; 351462306a36Sopenharmony_ci 351562306a36Sopenharmony_ci /* XDP RX-queue info */ 351662306a36Sopenharmony_ci if (xdp_rxq_info_reg(&rx_ring->xdp_rxq, adapter->netdev, 351762306a36Sopenharmony_ci rx_ring->queue_index, 0) < 0) 351862306a36Sopenharmony_ci goto err; 351962306a36Sopenharmony_ci 352062306a36Sopenharmony_ci rx_ring->xdp_prog = adapter->xdp_prog; 352162306a36Sopenharmony_ci 352262306a36Sopenharmony_ci return 0; 352362306a36Sopenharmony_cierr: 352462306a36Sopenharmony_ci vfree(rx_ring->rx_buffer_info); 352562306a36Sopenharmony_ci rx_ring->rx_buffer_info = NULL; 352662306a36Sopenharmony_ci dev_err(rx_ring->dev, "Unable to allocate memory for the Rx descriptor ring\n"); 352762306a36Sopenharmony_ci return -ENOMEM; 352862306a36Sopenharmony_ci} 352962306a36Sopenharmony_ci 353062306a36Sopenharmony_ci/** 353162306a36Sopenharmony_ci * ixgbevf_setup_all_rx_resources - allocate all queues Rx resources 353262306a36Sopenharmony_ci * @adapter: board private structure 353362306a36Sopenharmony_ci * 353462306a36Sopenharmony_ci * If this function returns with an error, then it's possible one or 353562306a36Sopenharmony_ci * more of the rings is populated (while the rest are not). It is the 353662306a36Sopenharmony_ci * callers duty to clean those orphaned rings. 353762306a36Sopenharmony_ci * 353862306a36Sopenharmony_ci * Return 0 on success, negative on failure 353962306a36Sopenharmony_ci **/ 354062306a36Sopenharmony_cistatic int ixgbevf_setup_all_rx_resources(struct ixgbevf_adapter *adapter) 354162306a36Sopenharmony_ci{ 354262306a36Sopenharmony_ci int i, err = 0; 354362306a36Sopenharmony_ci 354462306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 354562306a36Sopenharmony_ci err = ixgbevf_setup_rx_resources(adapter, adapter->rx_ring[i]); 354662306a36Sopenharmony_ci if (!err) 354762306a36Sopenharmony_ci continue; 354862306a36Sopenharmony_ci hw_dbg(&adapter->hw, "Allocation for Rx Queue %u failed\n", i); 354962306a36Sopenharmony_ci goto err_setup_rx; 355062306a36Sopenharmony_ci } 355162306a36Sopenharmony_ci 355262306a36Sopenharmony_ci return 0; 355362306a36Sopenharmony_cierr_setup_rx: 355462306a36Sopenharmony_ci /* rewind the index freeing the rings as we go */ 355562306a36Sopenharmony_ci while (i--) 355662306a36Sopenharmony_ci ixgbevf_free_rx_resources(adapter->rx_ring[i]); 355762306a36Sopenharmony_ci return err; 355862306a36Sopenharmony_ci} 355962306a36Sopenharmony_ci 356062306a36Sopenharmony_ci/** 356162306a36Sopenharmony_ci * ixgbevf_free_rx_resources - Free Rx Resources 356262306a36Sopenharmony_ci * @rx_ring: ring to clean the resources from 356362306a36Sopenharmony_ci * 356462306a36Sopenharmony_ci * Free all receive software resources 356562306a36Sopenharmony_ci **/ 356662306a36Sopenharmony_civoid ixgbevf_free_rx_resources(struct ixgbevf_ring *rx_ring) 356762306a36Sopenharmony_ci{ 356862306a36Sopenharmony_ci ixgbevf_clean_rx_ring(rx_ring); 356962306a36Sopenharmony_ci 357062306a36Sopenharmony_ci rx_ring->xdp_prog = NULL; 357162306a36Sopenharmony_ci xdp_rxq_info_unreg(&rx_ring->xdp_rxq); 357262306a36Sopenharmony_ci vfree(rx_ring->rx_buffer_info); 357362306a36Sopenharmony_ci rx_ring->rx_buffer_info = NULL; 357462306a36Sopenharmony_ci 357562306a36Sopenharmony_ci dma_free_coherent(rx_ring->dev, rx_ring->size, rx_ring->desc, 357662306a36Sopenharmony_ci rx_ring->dma); 357762306a36Sopenharmony_ci 357862306a36Sopenharmony_ci rx_ring->desc = NULL; 357962306a36Sopenharmony_ci} 358062306a36Sopenharmony_ci 358162306a36Sopenharmony_ci/** 358262306a36Sopenharmony_ci * ixgbevf_free_all_rx_resources - Free Rx Resources for All Queues 358362306a36Sopenharmony_ci * @adapter: board private structure 358462306a36Sopenharmony_ci * 358562306a36Sopenharmony_ci * Free all receive software resources 358662306a36Sopenharmony_ci **/ 358762306a36Sopenharmony_cistatic void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter) 358862306a36Sopenharmony_ci{ 358962306a36Sopenharmony_ci int i; 359062306a36Sopenharmony_ci 359162306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) 359262306a36Sopenharmony_ci if (adapter->rx_ring[i]->desc) 359362306a36Sopenharmony_ci ixgbevf_free_rx_resources(adapter->rx_ring[i]); 359462306a36Sopenharmony_ci} 359562306a36Sopenharmony_ci 359662306a36Sopenharmony_ci/** 359762306a36Sopenharmony_ci * ixgbevf_open - Called when a network interface is made active 359862306a36Sopenharmony_ci * @netdev: network interface device structure 359962306a36Sopenharmony_ci * 360062306a36Sopenharmony_ci * Returns 0 on success, negative value on failure 360162306a36Sopenharmony_ci * 360262306a36Sopenharmony_ci * The open entry point is called when a network interface is made 360362306a36Sopenharmony_ci * active by the system (IFF_UP). At this point all resources needed 360462306a36Sopenharmony_ci * for transmit and receive operations are allocated, the interrupt 360562306a36Sopenharmony_ci * handler is registered with the OS, the watchdog timer is started, 360662306a36Sopenharmony_ci * and the stack is notified that the interface is ready. 360762306a36Sopenharmony_ci **/ 360862306a36Sopenharmony_ciint ixgbevf_open(struct net_device *netdev) 360962306a36Sopenharmony_ci{ 361062306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 361162306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 361262306a36Sopenharmony_ci int err; 361362306a36Sopenharmony_ci 361462306a36Sopenharmony_ci /* A previous failure to open the device because of a lack of 361562306a36Sopenharmony_ci * available MSIX vector resources may have reset the number 361662306a36Sopenharmony_ci * of msix vectors variable to zero. The only way to recover 361762306a36Sopenharmony_ci * is to unload/reload the driver and hope that the system has 361862306a36Sopenharmony_ci * been able to recover some MSIX vector resources. 361962306a36Sopenharmony_ci */ 362062306a36Sopenharmony_ci if (!adapter->num_msix_vectors) 362162306a36Sopenharmony_ci return -ENOMEM; 362262306a36Sopenharmony_ci 362362306a36Sopenharmony_ci if (hw->adapter_stopped) { 362462306a36Sopenharmony_ci ixgbevf_reset(adapter); 362562306a36Sopenharmony_ci /* if adapter is still stopped then PF isn't up and 362662306a36Sopenharmony_ci * the VF can't start. 362762306a36Sopenharmony_ci */ 362862306a36Sopenharmony_ci if (hw->adapter_stopped) { 362962306a36Sopenharmony_ci err = IXGBE_ERR_MBX; 363062306a36Sopenharmony_ci pr_err("Unable to start - perhaps the PF Driver isn't up yet\n"); 363162306a36Sopenharmony_ci goto err_setup_reset; 363262306a36Sopenharmony_ci } 363362306a36Sopenharmony_ci } 363462306a36Sopenharmony_ci 363562306a36Sopenharmony_ci /* disallow open during test */ 363662306a36Sopenharmony_ci if (test_bit(__IXGBEVF_TESTING, &adapter->state)) 363762306a36Sopenharmony_ci return -EBUSY; 363862306a36Sopenharmony_ci 363962306a36Sopenharmony_ci netif_carrier_off(netdev); 364062306a36Sopenharmony_ci 364162306a36Sopenharmony_ci /* allocate transmit descriptors */ 364262306a36Sopenharmony_ci err = ixgbevf_setup_all_tx_resources(adapter); 364362306a36Sopenharmony_ci if (err) 364462306a36Sopenharmony_ci goto err_setup_tx; 364562306a36Sopenharmony_ci 364662306a36Sopenharmony_ci /* allocate receive descriptors */ 364762306a36Sopenharmony_ci err = ixgbevf_setup_all_rx_resources(adapter); 364862306a36Sopenharmony_ci if (err) 364962306a36Sopenharmony_ci goto err_setup_rx; 365062306a36Sopenharmony_ci 365162306a36Sopenharmony_ci ixgbevf_configure(adapter); 365262306a36Sopenharmony_ci 365362306a36Sopenharmony_ci err = ixgbevf_request_irq(adapter); 365462306a36Sopenharmony_ci if (err) 365562306a36Sopenharmony_ci goto err_req_irq; 365662306a36Sopenharmony_ci 365762306a36Sopenharmony_ci /* Notify the stack of the actual queue counts. */ 365862306a36Sopenharmony_ci err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); 365962306a36Sopenharmony_ci if (err) 366062306a36Sopenharmony_ci goto err_set_queues; 366162306a36Sopenharmony_ci 366262306a36Sopenharmony_ci err = netif_set_real_num_rx_queues(netdev, adapter->num_rx_queues); 366362306a36Sopenharmony_ci if (err) 366462306a36Sopenharmony_ci goto err_set_queues; 366562306a36Sopenharmony_ci 366662306a36Sopenharmony_ci ixgbevf_up_complete(adapter); 366762306a36Sopenharmony_ci 366862306a36Sopenharmony_ci return 0; 366962306a36Sopenharmony_ci 367062306a36Sopenharmony_cierr_set_queues: 367162306a36Sopenharmony_ci ixgbevf_free_irq(adapter); 367262306a36Sopenharmony_cierr_req_irq: 367362306a36Sopenharmony_ci ixgbevf_free_all_rx_resources(adapter); 367462306a36Sopenharmony_cierr_setup_rx: 367562306a36Sopenharmony_ci ixgbevf_free_all_tx_resources(adapter); 367662306a36Sopenharmony_cierr_setup_tx: 367762306a36Sopenharmony_ci ixgbevf_reset(adapter); 367862306a36Sopenharmony_cierr_setup_reset: 367962306a36Sopenharmony_ci 368062306a36Sopenharmony_ci return err; 368162306a36Sopenharmony_ci} 368262306a36Sopenharmony_ci 368362306a36Sopenharmony_ci/** 368462306a36Sopenharmony_ci * ixgbevf_close_suspend - actions necessary to both suspend and close flows 368562306a36Sopenharmony_ci * @adapter: the private adapter struct 368662306a36Sopenharmony_ci * 368762306a36Sopenharmony_ci * This function should contain the necessary work common to both suspending 368862306a36Sopenharmony_ci * and closing of the device. 368962306a36Sopenharmony_ci */ 369062306a36Sopenharmony_cistatic void ixgbevf_close_suspend(struct ixgbevf_adapter *adapter) 369162306a36Sopenharmony_ci{ 369262306a36Sopenharmony_ci ixgbevf_down(adapter); 369362306a36Sopenharmony_ci ixgbevf_free_irq(adapter); 369462306a36Sopenharmony_ci ixgbevf_free_all_tx_resources(adapter); 369562306a36Sopenharmony_ci ixgbevf_free_all_rx_resources(adapter); 369662306a36Sopenharmony_ci} 369762306a36Sopenharmony_ci 369862306a36Sopenharmony_ci/** 369962306a36Sopenharmony_ci * ixgbevf_close - Disables a network interface 370062306a36Sopenharmony_ci * @netdev: network interface device structure 370162306a36Sopenharmony_ci * 370262306a36Sopenharmony_ci * Returns 0, this is not allowed to fail 370362306a36Sopenharmony_ci * 370462306a36Sopenharmony_ci * The close entry point is called when an interface is de-activated 370562306a36Sopenharmony_ci * by the OS. The hardware is still under the drivers control, but 370662306a36Sopenharmony_ci * needs to be disabled. A global MAC reset is issued to stop the 370762306a36Sopenharmony_ci * hardware, and all transmit and receive resources are freed. 370862306a36Sopenharmony_ci **/ 370962306a36Sopenharmony_ciint ixgbevf_close(struct net_device *netdev) 371062306a36Sopenharmony_ci{ 371162306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 371262306a36Sopenharmony_ci 371362306a36Sopenharmony_ci if (netif_device_present(netdev)) 371462306a36Sopenharmony_ci ixgbevf_close_suspend(adapter); 371562306a36Sopenharmony_ci 371662306a36Sopenharmony_ci return 0; 371762306a36Sopenharmony_ci} 371862306a36Sopenharmony_ci 371962306a36Sopenharmony_cistatic void ixgbevf_queue_reset_subtask(struct ixgbevf_adapter *adapter) 372062306a36Sopenharmony_ci{ 372162306a36Sopenharmony_ci struct net_device *dev = adapter->netdev; 372262306a36Sopenharmony_ci 372362306a36Sopenharmony_ci if (!test_and_clear_bit(__IXGBEVF_QUEUE_RESET_REQUESTED, 372462306a36Sopenharmony_ci &adapter->state)) 372562306a36Sopenharmony_ci return; 372662306a36Sopenharmony_ci 372762306a36Sopenharmony_ci /* if interface is down do nothing */ 372862306a36Sopenharmony_ci if (test_bit(__IXGBEVF_DOWN, &adapter->state) || 372962306a36Sopenharmony_ci test_bit(__IXGBEVF_RESETTING, &adapter->state)) 373062306a36Sopenharmony_ci return; 373162306a36Sopenharmony_ci 373262306a36Sopenharmony_ci /* Hardware has to reinitialize queues and interrupts to 373362306a36Sopenharmony_ci * match packet buffer alignment. Unfortunately, the 373462306a36Sopenharmony_ci * hardware is not flexible enough to do this dynamically. 373562306a36Sopenharmony_ci */ 373662306a36Sopenharmony_ci rtnl_lock(); 373762306a36Sopenharmony_ci 373862306a36Sopenharmony_ci if (netif_running(dev)) 373962306a36Sopenharmony_ci ixgbevf_close(dev); 374062306a36Sopenharmony_ci 374162306a36Sopenharmony_ci ixgbevf_clear_interrupt_scheme(adapter); 374262306a36Sopenharmony_ci ixgbevf_init_interrupt_scheme(adapter); 374362306a36Sopenharmony_ci 374462306a36Sopenharmony_ci if (netif_running(dev)) 374562306a36Sopenharmony_ci ixgbevf_open(dev); 374662306a36Sopenharmony_ci 374762306a36Sopenharmony_ci rtnl_unlock(); 374862306a36Sopenharmony_ci} 374962306a36Sopenharmony_ci 375062306a36Sopenharmony_cistatic void ixgbevf_tx_ctxtdesc(struct ixgbevf_ring *tx_ring, 375162306a36Sopenharmony_ci u32 vlan_macip_lens, u32 fceof_saidx, 375262306a36Sopenharmony_ci u32 type_tucmd, u32 mss_l4len_idx) 375362306a36Sopenharmony_ci{ 375462306a36Sopenharmony_ci struct ixgbe_adv_tx_context_desc *context_desc; 375562306a36Sopenharmony_ci u16 i = tx_ring->next_to_use; 375662306a36Sopenharmony_ci 375762306a36Sopenharmony_ci context_desc = IXGBEVF_TX_CTXTDESC(tx_ring, i); 375862306a36Sopenharmony_ci 375962306a36Sopenharmony_ci i++; 376062306a36Sopenharmony_ci tx_ring->next_to_use = (i < tx_ring->count) ? i : 0; 376162306a36Sopenharmony_ci 376262306a36Sopenharmony_ci /* set bits to identify this as an advanced context descriptor */ 376362306a36Sopenharmony_ci type_tucmd |= IXGBE_TXD_CMD_DEXT | IXGBE_ADVTXD_DTYP_CTXT; 376462306a36Sopenharmony_ci 376562306a36Sopenharmony_ci context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); 376662306a36Sopenharmony_ci context_desc->fceof_saidx = cpu_to_le32(fceof_saidx); 376762306a36Sopenharmony_ci context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); 376862306a36Sopenharmony_ci context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); 376962306a36Sopenharmony_ci} 377062306a36Sopenharmony_ci 377162306a36Sopenharmony_cistatic int ixgbevf_tso(struct ixgbevf_ring *tx_ring, 377262306a36Sopenharmony_ci struct ixgbevf_tx_buffer *first, 377362306a36Sopenharmony_ci u8 *hdr_len, 377462306a36Sopenharmony_ci struct ixgbevf_ipsec_tx_data *itd) 377562306a36Sopenharmony_ci{ 377662306a36Sopenharmony_ci u32 vlan_macip_lens, type_tucmd, mss_l4len_idx; 377762306a36Sopenharmony_ci struct sk_buff *skb = first->skb; 377862306a36Sopenharmony_ci union { 377962306a36Sopenharmony_ci struct iphdr *v4; 378062306a36Sopenharmony_ci struct ipv6hdr *v6; 378162306a36Sopenharmony_ci unsigned char *hdr; 378262306a36Sopenharmony_ci } ip; 378362306a36Sopenharmony_ci union { 378462306a36Sopenharmony_ci struct tcphdr *tcp; 378562306a36Sopenharmony_ci unsigned char *hdr; 378662306a36Sopenharmony_ci } l4; 378762306a36Sopenharmony_ci u32 paylen, l4_offset; 378862306a36Sopenharmony_ci u32 fceof_saidx = 0; 378962306a36Sopenharmony_ci int err; 379062306a36Sopenharmony_ci 379162306a36Sopenharmony_ci if (skb->ip_summed != CHECKSUM_PARTIAL) 379262306a36Sopenharmony_ci return 0; 379362306a36Sopenharmony_ci 379462306a36Sopenharmony_ci if (!skb_is_gso(skb)) 379562306a36Sopenharmony_ci return 0; 379662306a36Sopenharmony_ci 379762306a36Sopenharmony_ci err = skb_cow_head(skb, 0); 379862306a36Sopenharmony_ci if (err < 0) 379962306a36Sopenharmony_ci return err; 380062306a36Sopenharmony_ci 380162306a36Sopenharmony_ci if (eth_p_mpls(first->protocol)) 380262306a36Sopenharmony_ci ip.hdr = skb_inner_network_header(skb); 380362306a36Sopenharmony_ci else 380462306a36Sopenharmony_ci ip.hdr = skb_network_header(skb); 380562306a36Sopenharmony_ci l4.hdr = skb_checksum_start(skb); 380662306a36Sopenharmony_ci 380762306a36Sopenharmony_ci /* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */ 380862306a36Sopenharmony_ci type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP; 380962306a36Sopenharmony_ci 381062306a36Sopenharmony_ci /* initialize outer IP header fields */ 381162306a36Sopenharmony_ci if (ip.v4->version == 4) { 381262306a36Sopenharmony_ci unsigned char *csum_start = skb_checksum_start(skb); 381362306a36Sopenharmony_ci unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4); 381462306a36Sopenharmony_ci int len = csum_start - trans_start; 381562306a36Sopenharmony_ci 381662306a36Sopenharmony_ci /* IP header will have to cancel out any data that 381762306a36Sopenharmony_ci * is not a part of the outer IP header, so set to 381862306a36Sopenharmony_ci * a reverse csum if needed, else init check to 0. 381962306a36Sopenharmony_ci */ 382062306a36Sopenharmony_ci ip.v4->check = (skb_shinfo(skb)->gso_type & SKB_GSO_PARTIAL) ? 382162306a36Sopenharmony_ci csum_fold(csum_partial(trans_start, 382262306a36Sopenharmony_ci len, 0)) : 0; 382362306a36Sopenharmony_ci type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4; 382462306a36Sopenharmony_ci 382562306a36Sopenharmony_ci ip.v4->tot_len = 0; 382662306a36Sopenharmony_ci first->tx_flags |= IXGBE_TX_FLAGS_TSO | 382762306a36Sopenharmony_ci IXGBE_TX_FLAGS_CSUM | 382862306a36Sopenharmony_ci IXGBE_TX_FLAGS_IPV4; 382962306a36Sopenharmony_ci } else { 383062306a36Sopenharmony_ci ip.v6->payload_len = 0; 383162306a36Sopenharmony_ci first->tx_flags |= IXGBE_TX_FLAGS_TSO | 383262306a36Sopenharmony_ci IXGBE_TX_FLAGS_CSUM; 383362306a36Sopenharmony_ci } 383462306a36Sopenharmony_ci 383562306a36Sopenharmony_ci /* determine offset of inner transport header */ 383662306a36Sopenharmony_ci l4_offset = l4.hdr - skb->data; 383762306a36Sopenharmony_ci 383862306a36Sopenharmony_ci /* compute length of segmentation header */ 383962306a36Sopenharmony_ci *hdr_len = (l4.tcp->doff * 4) + l4_offset; 384062306a36Sopenharmony_ci 384162306a36Sopenharmony_ci /* remove payload length from inner checksum */ 384262306a36Sopenharmony_ci paylen = skb->len - l4_offset; 384362306a36Sopenharmony_ci csum_replace_by_diff(&l4.tcp->check, (__force __wsum)htonl(paylen)); 384462306a36Sopenharmony_ci 384562306a36Sopenharmony_ci /* update gso size and bytecount with header size */ 384662306a36Sopenharmony_ci first->gso_segs = skb_shinfo(skb)->gso_segs; 384762306a36Sopenharmony_ci first->bytecount += (first->gso_segs - 1) * *hdr_len; 384862306a36Sopenharmony_ci 384962306a36Sopenharmony_ci /* mss_l4len_id: use 1 as index for TSO */ 385062306a36Sopenharmony_ci mss_l4len_idx = (*hdr_len - l4_offset) << IXGBE_ADVTXD_L4LEN_SHIFT; 385162306a36Sopenharmony_ci mss_l4len_idx |= skb_shinfo(skb)->gso_size << IXGBE_ADVTXD_MSS_SHIFT; 385262306a36Sopenharmony_ci mss_l4len_idx |= (1u << IXGBE_ADVTXD_IDX_SHIFT); 385362306a36Sopenharmony_ci 385462306a36Sopenharmony_ci fceof_saidx |= itd->pfsa; 385562306a36Sopenharmony_ci type_tucmd |= itd->flags | itd->trailer_len; 385662306a36Sopenharmony_ci 385762306a36Sopenharmony_ci /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */ 385862306a36Sopenharmony_ci vlan_macip_lens = l4.hdr - ip.hdr; 385962306a36Sopenharmony_ci vlan_macip_lens |= (ip.hdr - skb->data) << IXGBE_ADVTXD_MACLEN_SHIFT; 386062306a36Sopenharmony_ci vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK; 386162306a36Sopenharmony_ci 386262306a36Sopenharmony_ci ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens, fceof_saidx, type_tucmd, 386362306a36Sopenharmony_ci mss_l4len_idx); 386462306a36Sopenharmony_ci 386562306a36Sopenharmony_ci return 1; 386662306a36Sopenharmony_ci} 386762306a36Sopenharmony_ci 386862306a36Sopenharmony_cistatic void ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring, 386962306a36Sopenharmony_ci struct ixgbevf_tx_buffer *first, 387062306a36Sopenharmony_ci struct ixgbevf_ipsec_tx_data *itd) 387162306a36Sopenharmony_ci{ 387262306a36Sopenharmony_ci struct sk_buff *skb = first->skb; 387362306a36Sopenharmony_ci u32 vlan_macip_lens = 0; 387462306a36Sopenharmony_ci u32 fceof_saidx = 0; 387562306a36Sopenharmony_ci u32 type_tucmd = 0; 387662306a36Sopenharmony_ci 387762306a36Sopenharmony_ci if (skb->ip_summed != CHECKSUM_PARTIAL) 387862306a36Sopenharmony_ci goto no_csum; 387962306a36Sopenharmony_ci 388062306a36Sopenharmony_ci switch (skb->csum_offset) { 388162306a36Sopenharmony_ci case offsetof(struct tcphdr, check): 388262306a36Sopenharmony_ci type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_TCP; 388362306a36Sopenharmony_ci fallthrough; 388462306a36Sopenharmony_ci case offsetof(struct udphdr, check): 388562306a36Sopenharmony_ci break; 388662306a36Sopenharmony_ci case offsetof(struct sctphdr, checksum): 388762306a36Sopenharmony_ci /* validate that this is actually an SCTP request */ 388862306a36Sopenharmony_ci if (skb_csum_is_sctp(skb)) { 388962306a36Sopenharmony_ci type_tucmd = IXGBE_ADVTXD_TUCMD_L4T_SCTP; 389062306a36Sopenharmony_ci break; 389162306a36Sopenharmony_ci } 389262306a36Sopenharmony_ci fallthrough; 389362306a36Sopenharmony_ci default: 389462306a36Sopenharmony_ci skb_checksum_help(skb); 389562306a36Sopenharmony_ci goto no_csum; 389662306a36Sopenharmony_ci } 389762306a36Sopenharmony_ci 389862306a36Sopenharmony_ci if (first->protocol == htons(ETH_P_IP)) 389962306a36Sopenharmony_ci type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4; 390062306a36Sopenharmony_ci 390162306a36Sopenharmony_ci /* update TX checksum flag */ 390262306a36Sopenharmony_ci first->tx_flags |= IXGBE_TX_FLAGS_CSUM; 390362306a36Sopenharmony_ci vlan_macip_lens = skb_checksum_start_offset(skb) - 390462306a36Sopenharmony_ci skb_network_offset(skb); 390562306a36Sopenharmony_cino_csum: 390662306a36Sopenharmony_ci /* vlan_macip_lens: MACLEN, VLAN tag */ 390762306a36Sopenharmony_ci vlan_macip_lens |= skb_network_offset(skb) << IXGBE_ADVTXD_MACLEN_SHIFT; 390862306a36Sopenharmony_ci vlan_macip_lens |= first->tx_flags & IXGBE_TX_FLAGS_VLAN_MASK; 390962306a36Sopenharmony_ci 391062306a36Sopenharmony_ci fceof_saidx |= itd->pfsa; 391162306a36Sopenharmony_ci type_tucmd |= itd->flags | itd->trailer_len; 391262306a36Sopenharmony_ci 391362306a36Sopenharmony_ci ixgbevf_tx_ctxtdesc(tx_ring, vlan_macip_lens, 391462306a36Sopenharmony_ci fceof_saidx, type_tucmd, 0); 391562306a36Sopenharmony_ci} 391662306a36Sopenharmony_ci 391762306a36Sopenharmony_cistatic __le32 ixgbevf_tx_cmd_type(u32 tx_flags) 391862306a36Sopenharmony_ci{ 391962306a36Sopenharmony_ci /* set type for advanced descriptor with frame checksum insertion */ 392062306a36Sopenharmony_ci __le32 cmd_type = cpu_to_le32(IXGBE_ADVTXD_DTYP_DATA | 392162306a36Sopenharmony_ci IXGBE_ADVTXD_DCMD_IFCS | 392262306a36Sopenharmony_ci IXGBE_ADVTXD_DCMD_DEXT); 392362306a36Sopenharmony_ci 392462306a36Sopenharmony_ci /* set HW VLAN bit if VLAN is present */ 392562306a36Sopenharmony_ci if (tx_flags & IXGBE_TX_FLAGS_VLAN) 392662306a36Sopenharmony_ci cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_VLE); 392762306a36Sopenharmony_ci 392862306a36Sopenharmony_ci /* set segmentation enable bits for TSO/FSO */ 392962306a36Sopenharmony_ci if (tx_flags & IXGBE_TX_FLAGS_TSO) 393062306a36Sopenharmony_ci cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_TSE); 393162306a36Sopenharmony_ci 393262306a36Sopenharmony_ci return cmd_type; 393362306a36Sopenharmony_ci} 393462306a36Sopenharmony_ci 393562306a36Sopenharmony_cistatic void ixgbevf_tx_olinfo_status(union ixgbe_adv_tx_desc *tx_desc, 393662306a36Sopenharmony_ci u32 tx_flags, unsigned int paylen) 393762306a36Sopenharmony_ci{ 393862306a36Sopenharmony_ci __le32 olinfo_status = cpu_to_le32(paylen << IXGBE_ADVTXD_PAYLEN_SHIFT); 393962306a36Sopenharmony_ci 394062306a36Sopenharmony_ci /* enable L4 checksum for TSO and TX checksum offload */ 394162306a36Sopenharmony_ci if (tx_flags & IXGBE_TX_FLAGS_CSUM) 394262306a36Sopenharmony_ci olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_POPTS_TXSM); 394362306a36Sopenharmony_ci 394462306a36Sopenharmony_ci /* enble IPv4 checksum for TSO */ 394562306a36Sopenharmony_ci if (tx_flags & IXGBE_TX_FLAGS_IPV4) 394662306a36Sopenharmony_ci olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_POPTS_IXSM); 394762306a36Sopenharmony_ci 394862306a36Sopenharmony_ci /* enable IPsec */ 394962306a36Sopenharmony_ci if (tx_flags & IXGBE_TX_FLAGS_IPSEC) 395062306a36Sopenharmony_ci olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_POPTS_IPSEC); 395162306a36Sopenharmony_ci 395262306a36Sopenharmony_ci /* use index 1 context for TSO/FSO/FCOE/IPSEC */ 395362306a36Sopenharmony_ci if (tx_flags & (IXGBE_TX_FLAGS_TSO | IXGBE_TX_FLAGS_IPSEC)) 395462306a36Sopenharmony_ci olinfo_status |= cpu_to_le32(1u << IXGBE_ADVTXD_IDX_SHIFT); 395562306a36Sopenharmony_ci 395662306a36Sopenharmony_ci /* Check Context must be set if Tx switch is enabled, which it 395762306a36Sopenharmony_ci * always is for case where virtual functions are running 395862306a36Sopenharmony_ci */ 395962306a36Sopenharmony_ci olinfo_status |= cpu_to_le32(IXGBE_ADVTXD_CC); 396062306a36Sopenharmony_ci 396162306a36Sopenharmony_ci tx_desc->read.olinfo_status = olinfo_status; 396262306a36Sopenharmony_ci} 396362306a36Sopenharmony_ci 396462306a36Sopenharmony_cistatic void ixgbevf_tx_map(struct ixgbevf_ring *tx_ring, 396562306a36Sopenharmony_ci struct ixgbevf_tx_buffer *first, 396662306a36Sopenharmony_ci const u8 hdr_len) 396762306a36Sopenharmony_ci{ 396862306a36Sopenharmony_ci struct sk_buff *skb = first->skb; 396962306a36Sopenharmony_ci struct ixgbevf_tx_buffer *tx_buffer; 397062306a36Sopenharmony_ci union ixgbe_adv_tx_desc *tx_desc; 397162306a36Sopenharmony_ci skb_frag_t *frag; 397262306a36Sopenharmony_ci dma_addr_t dma; 397362306a36Sopenharmony_ci unsigned int data_len, size; 397462306a36Sopenharmony_ci u32 tx_flags = first->tx_flags; 397562306a36Sopenharmony_ci __le32 cmd_type = ixgbevf_tx_cmd_type(tx_flags); 397662306a36Sopenharmony_ci u16 i = tx_ring->next_to_use; 397762306a36Sopenharmony_ci 397862306a36Sopenharmony_ci tx_desc = IXGBEVF_TX_DESC(tx_ring, i); 397962306a36Sopenharmony_ci 398062306a36Sopenharmony_ci ixgbevf_tx_olinfo_status(tx_desc, tx_flags, skb->len - hdr_len); 398162306a36Sopenharmony_ci 398262306a36Sopenharmony_ci size = skb_headlen(skb); 398362306a36Sopenharmony_ci data_len = skb->data_len; 398462306a36Sopenharmony_ci 398562306a36Sopenharmony_ci dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE); 398662306a36Sopenharmony_ci 398762306a36Sopenharmony_ci tx_buffer = first; 398862306a36Sopenharmony_ci 398962306a36Sopenharmony_ci for (frag = &skb_shinfo(skb)->frags[0];; frag++) { 399062306a36Sopenharmony_ci if (dma_mapping_error(tx_ring->dev, dma)) 399162306a36Sopenharmony_ci goto dma_error; 399262306a36Sopenharmony_ci 399362306a36Sopenharmony_ci /* record length, and DMA address */ 399462306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, size); 399562306a36Sopenharmony_ci dma_unmap_addr_set(tx_buffer, dma, dma); 399662306a36Sopenharmony_ci 399762306a36Sopenharmony_ci tx_desc->read.buffer_addr = cpu_to_le64(dma); 399862306a36Sopenharmony_ci 399962306a36Sopenharmony_ci while (unlikely(size > IXGBE_MAX_DATA_PER_TXD)) { 400062306a36Sopenharmony_ci tx_desc->read.cmd_type_len = 400162306a36Sopenharmony_ci cmd_type | cpu_to_le32(IXGBE_MAX_DATA_PER_TXD); 400262306a36Sopenharmony_ci 400362306a36Sopenharmony_ci i++; 400462306a36Sopenharmony_ci tx_desc++; 400562306a36Sopenharmony_ci if (i == tx_ring->count) { 400662306a36Sopenharmony_ci tx_desc = IXGBEVF_TX_DESC(tx_ring, 0); 400762306a36Sopenharmony_ci i = 0; 400862306a36Sopenharmony_ci } 400962306a36Sopenharmony_ci tx_desc->read.olinfo_status = 0; 401062306a36Sopenharmony_ci 401162306a36Sopenharmony_ci dma += IXGBE_MAX_DATA_PER_TXD; 401262306a36Sopenharmony_ci size -= IXGBE_MAX_DATA_PER_TXD; 401362306a36Sopenharmony_ci 401462306a36Sopenharmony_ci tx_desc->read.buffer_addr = cpu_to_le64(dma); 401562306a36Sopenharmony_ci } 401662306a36Sopenharmony_ci 401762306a36Sopenharmony_ci if (likely(!data_len)) 401862306a36Sopenharmony_ci break; 401962306a36Sopenharmony_ci 402062306a36Sopenharmony_ci tx_desc->read.cmd_type_len = cmd_type | cpu_to_le32(size); 402162306a36Sopenharmony_ci 402262306a36Sopenharmony_ci i++; 402362306a36Sopenharmony_ci tx_desc++; 402462306a36Sopenharmony_ci if (i == tx_ring->count) { 402562306a36Sopenharmony_ci tx_desc = IXGBEVF_TX_DESC(tx_ring, 0); 402662306a36Sopenharmony_ci i = 0; 402762306a36Sopenharmony_ci } 402862306a36Sopenharmony_ci tx_desc->read.olinfo_status = 0; 402962306a36Sopenharmony_ci 403062306a36Sopenharmony_ci size = skb_frag_size(frag); 403162306a36Sopenharmony_ci data_len -= size; 403262306a36Sopenharmony_ci 403362306a36Sopenharmony_ci dma = skb_frag_dma_map(tx_ring->dev, frag, 0, size, 403462306a36Sopenharmony_ci DMA_TO_DEVICE); 403562306a36Sopenharmony_ci 403662306a36Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 403762306a36Sopenharmony_ci } 403862306a36Sopenharmony_ci 403962306a36Sopenharmony_ci /* write last descriptor with RS and EOP bits */ 404062306a36Sopenharmony_ci cmd_type |= cpu_to_le32(size) | cpu_to_le32(IXGBE_TXD_CMD); 404162306a36Sopenharmony_ci tx_desc->read.cmd_type_len = cmd_type; 404262306a36Sopenharmony_ci 404362306a36Sopenharmony_ci /* set the timestamp */ 404462306a36Sopenharmony_ci first->time_stamp = jiffies; 404562306a36Sopenharmony_ci 404662306a36Sopenharmony_ci skb_tx_timestamp(skb); 404762306a36Sopenharmony_ci 404862306a36Sopenharmony_ci /* Force memory writes to complete before letting h/w know there 404962306a36Sopenharmony_ci * are new descriptors to fetch. (Only applicable for weak-ordered 405062306a36Sopenharmony_ci * memory model archs, such as IA-64). 405162306a36Sopenharmony_ci * 405262306a36Sopenharmony_ci * We also need this memory barrier (wmb) to make certain all of the 405362306a36Sopenharmony_ci * status bits have been updated before next_to_watch is written. 405462306a36Sopenharmony_ci */ 405562306a36Sopenharmony_ci wmb(); 405662306a36Sopenharmony_ci 405762306a36Sopenharmony_ci /* set next_to_watch value indicating a packet is present */ 405862306a36Sopenharmony_ci first->next_to_watch = tx_desc; 405962306a36Sopenharmony_ci 406062306a36Sopenharmony_ci i++; 406162306a36Sopenharmony_ci if (i == tx_ring->count) 406262306a36Sopenharmony_ci i = 0; 406362306a36Sopenharmony_ci 406462306a36Sopenharmony_ci tx_ring->next_to_use = i; 406562306a36Sopenharmony_ci 406662306a36Sopenharmony_ci /* notify HW of packet */ 406762306a36Sopenharmony_ci ixgbevf_write_tail(tx_ring, i); 406862306a36Sopenharmony_ci 406962306a36Sopenharmony_ci return; 407062306a36Sopenharmony_cidma_error: 407162306a36Sopenharmony_ci dev_err(tx_ring->dev, "TX DMA map failed\n"); 407262306a36Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 407362306a36Sopenharmony_ci 407462306a36Sopenharmony_ci /* clear dma mappings for failed tx_buffer_info map */ 407562306a36Sopenharmony_ci while (tx_buffer != first) { 407662306a36Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) 407762306a36Sopenharmony_ci dma_unmap_page(tx_ring->dev, 407862306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 407962306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 408062306a36Sopenharmony_ci DMA_TO_DEVICE); 408162306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 408262306a36Sopenharmony_ci 408362306a36Sopenharmony_ci if (i-- == 0) 408462306a36Sopenharmony_ci i += tx_ring->count; 408562306a36Sopenharmony_ci tx_buffer = &tx_ring->tx_buffer_info[i]; 408662306a36Sopenharmony_ci } 408762306a36Sopenharmony_ci 408862306a36Sopenharmony_ci if (dma_unmap_len(tx_buffer, len)) 408962306a36Sopenharmony_ci dma_unmap_single(tx_ring->dev, 409062306a36Sopenharmony_ci dma_unmap_addr(tx_buffer, dma), 409162306a36Sopenharmony_ci dma_unmap_len(tx_buffer, len), 409262306a36Sopenharmony_ci DMA_TO_DEVICE); 409362306a36Sopenharmony_ci dma_unmap_len_set(tx_buffer, len, 0); 409462306a36Sopenharmony_ci 409562306a36Sopenharmony_ci dev_kfree_skb_any(tx_buffer->skb); 409662306a36Sopenharmony_ci tx_buffer->skb = NULL; 409762306a36Sopenharmony_ci 409862306a36Sopenharmony_ci tx_ring->next_to_use = i; 409962306a36Sopenharmony_ci} 410062306a36Sopenharmony_ci 410162306a36Sopenharmony_cistatic int __ixgbevf_maybe_stop_tx(struct ixgbevf_ring *tx_ring, int size) 410262306a36Sopenharmony_ci{ 410362306a36Sopenharmony_ci netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); 410462306a36Sopenharmony_ci /* Herbert's original patch had: 410562306a36Sopenharmony_ci * smp_mb__after_netif_stop_queue(); 410662306a36Sopenharmony_ci * but since that doesn't exist yet, just open code it. 410762306a36Sopenharmony_ci */ 410862306a36Sopenharmony_ci smp_mb(); 410962306a36Sopenharmony_ci 411062306a36Sopenharmony_ci /* We need to check again in a case another CPU has just 411162306a36Sopenharmony_ci * made room available. 411262306a36Sopenharmony_ci */ 411362306a36Sopenharmony_ci if (likely(ixgbevf_desc_unused(tx_ring) < size)) 411462306a36Sopenharmony_ci return -EBUSY; 411562306a36Sopenharmony_ci 411662306a36Sopenharmony_ci /* A reprieve! - use start_queue because it doesn't call schedule */ 411762306a36Sopenharmony_ci netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index); 411862306a36Sopenharmony_ci ++tx_ring->tx_stats.restart_queue; 411962306a36Sopenharmony_ci 412062306a36Sopenharmony_ci return 0; 412162306a36Sopenharmony_ci} 412262306a36Sopenharmony_ci 412362306a36Sopenharmony_cistatic int ixgbevf_maybe_stop_tx(struct ixgbevf_ring *tx_ring, int size) 412462306a36Sopenharmony_ci{ 412562306a36Sopenharmony_ci if (likely(ixgbevf_desc_unused(tx_ring) >= size)) 412662306a36Sopenharmony_ci return 0; 412762306a36Sopenharmony_ci return __ixgbevf_maybe_stop_tx(tx_ring, size); 412862306a36Sopenharmony_ci} 412962306a36Sopenharmony_ci 413062306a36Sopenharmony_cistatic int ixgbevf_xmit_frame_ring(struct sk_buff *skb, 413162306a36Sopenharmony_ci struct ixgbevf_ring *tx_ring) 413262306a36Sopenharmony_ci{ 413362306a36Sopenharmony_ci struct ixgbevf_tx_buffer *first; 413462306a36Sopenharmony_ci int tso; 413562306a36Sopenharmony_ci u32 tx_flags = 0; 413662306a36Sopenharmony_ci u16 count = TXD_USE_COUNT(skb_headlen(skb)); 413762306a36Sopenharmony_ci struct ixgbevf_ipsec_tx_data ipsec_tx = { 0 }; 413862306a36Sopenharmony_ci#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD 413962306a36Sopenharmony_ci unsigned short f; 414062306a36Sopenharmony_ci#endif 414162306a36Sopenharmony_ci u8 hdr_len = 0; 414262306a36Sopenharmony_ci u8 *dst_mac = skb_header_pointer(skb, 0, 0, NULL); 414362306a36Sopenharmony_ci 414462306a36Sopenharmony_ci if (!dst_mac || is_link_local_ether_addr(dst_mac)) { 414562306a36Sopenharmony_ci dev_kfree_skb_any(skb); 414662306a36Sopenharmony_ci return NETDEV_TX_OK; 414762306a36Sopenharmony_ci } 414862306a36Sopenharmony_ci 414962306a36Sopenharmony_ci /* need: 1 descriptor per page * PAGE_SIZE/IXGBE_MAX_DATA_PER_TXD, 415062306a36Sopenharmony_ci * + 1 desc for skb_headlen/IXGBE_MAX_DATA_PER_TXD, 415162306a36Sopenharmony_ci * + 2 desc gap to keep tail from touching head, 415262306a36Sopenharmony_ci * + 1 desc for context descriptor, 415362306a36Sopenharmony_ci * otherwise try next time 415462306a36Sopenharmony_ci */ 415562306a36Sopenharmony_ci#if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD 415662306a36Sopenharmony_ci for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) { 415762306a36Sopenharmony_ci skb_frag_t *frag = &skb_shinfo(skb)->frags[f]; 415862306a36Sopenharmony_ci 415962306a36Sopenharmony_ci count += TXD_USE_COUNT(skb_frag_size(frag)); 416062306a36Sopenharmony_ci } 416162306a36Sopenharmony_ci#else 416262306a36Sopenharmony_ci count += skb_shinfo(skb)->nr_frags; 416362306a36Sopenharmony_ci#endif 416462306a36Sopenharmony_ci if (ixgbevf_maybe_stop_tx(tx_ring, count + 3)) { 416562306a36Sopenharmony_ci tx_ring->tx_stats.tx_busy++; 416662306a36Sopenharmony_ci return NETDEV_TX_BUSY; 416762306a36Sopenharmony_ci } 416862306a36Sopenharmony_ci 416962306a36Sopenharmony_ci /* record the location of the first descriptor for this packet */ 417062306a36Sopenharmony_ci first = &tx_ring->tx_buffer_info[tx_ring->next_to_use]; 417162306a36Sopenharmony_ci first->skb = skb; 417262306a36Sopenharmony_ci first->bytecount = skb->len; 417362306a36Sopenharmony_ci first->gso_segs = 1; 417462306a36Sopenharmony_ci 417562306a36Sopenharmony_ci if (skb_vlan_tag_present(skb)) { 417662306a36Sopenharmony_ci tx_flags |= skb_vlan_tag_get(skb); 417762306a36Sopenharmony_ci tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT; 417862306a36Sopenharmony_ci tx_flags |= IXGBE_TX_FLAGS_VLAN; 417962306a36Sopenharmony_ci } 418062306a36Sopenharmony_ci 418162306a36Sopenharmony_ci /* record initial flags and protocol */ 418262306a36Sopenharmony_ci first->tx_flags = tx_flags; 418362306a36Sopenharmony_ci first->protocol = vlan_get_protocol(skb); 418462306a36Sopenharmony_ci 418562306a36Sopenharmony_ci#ifdef CONFIG_IXGBEVF_IPSEC 418662306a36Sopenharmony_ci if (xfrm_offload(skb) && !ixgbevf_ipsec_tx(tx_ring, first, &ipsec_tx)) 418762306a36Sopenharmony_ci goto out_drop; 418862306a36Sopenharmony_ci#endif 418962306a36Sopenharmony_ci tso = ixgbevf_tso(tx_ring, first, &hdr_len, &ipsec_tx); 419062306a36Sopenharmony_ci if (tso < 0) 419162306a36Sopenharmony_ci goto out_drop; 419262306a36Sopenharmony_ci else if (!tso) 419362306a36Sopenharmony_ci ixgbevf_tx_csum(tx_ring, first, &ipsec_tx); 419462306a36Sopenharmony_ci 419562306a36Sopenharmony_ci ixgbevf_tx_map(tx_ring, first, hdr_len); 419662306a36Sopenharmony_ci 419762306a36Sopenharmony_ci ixgbevf_maybe_stop_tx(tx_ring, DESC_NEEDED); 419862306a36Sopenharmony_ci 419962306a36Sopenharmony_ci return NETDEV_TX_OK; 420062306a36Sopenharmony_ci 420162306a36Sopenharmony_ciout_drop: 420262306a36Sopenharmony_ci dev_kfree_skb_any(first->skb); 420362306a36Sopenharmony_ci first->skb = NULL; 420462306a36Sopenharmony_ci 420562306a36Sopenharmony_ci return NETDEV_TX_OK; 420662306a36Sopenharmony_ci} 420762306a36Sopenharmony_ci 420862306a36Sopenharmony_cistatic netdev_tx_t ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev) 420962306a36Sopenharmony_ci{ 421062306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 421162306a36Sopenharmony_ci struct ixgbevf_ring *tx_ring; 421262306a36Sopenharmony_ci 421362306a36Sopenharmony_ci if (skb->len <= 0) { 421462306a36Sopenharmony_ci dev_kfree_skb_any(skb); 421562306a36Sopenharmony_ci return NETDEV_TX_OK; 421662306a36Sopenharmony_ci } 421762306a36Sopenharmony_ci 421862306a36Sopenharmony_ci /* The minimum packet size for olinfo paylen is 17 so pad the skb 421962306a36Sopenharmony_ci * in order to meet this minimum size requirement. 422062306a36Sopenharmony_ci */ 422162306a36Sopenharmony_ci if (skb->len < 17) { 422262306a36Sopenharmony_ci if (skb_padto(skb, 17)) 422362306a36Sopenharmony_ci return NETDEV_TX_OK; 422462306a36Sopenharmony_ci skb->len = 17; 422562306a36Sopenharmony_ci } 422662306a36Sopenharmony_ci 422762306a36Sopenharmony_ci tx_ring = adapter->tx_ring[skb->queue_mapping]; 422862306a36Sopenharmony_ci return ixgbevf_xmit_frame_ring(skb, tx_ring); 422962306a36Sopenharmony_ci} 423062306a36Sopenharmony_ci 423162306a36Sopenharmony_ci/** 423262306a36Sopenharmony_ci * ixgbevf_set_mac - Change the Ethernet Address of the NIC 423362306a36Sopenharmony_ci * @netdev: network interface device structure 423462306a36Sopenharmony_ci * @p: pointer to an address structure 423562306a36Sopenharmony_ci * 423662306a36Sopenharmony_ci * Returns 0 on success, negative on failure 423762306a36Sopenharmony_ci **/ 423862306a36Sopenharmony_cistatic int ixgbevf_set_mac(struct net_device *netdev, void *p) 423962306a36Sopenharmony_ci{ 424062306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 424162306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 424262306a36Sopenharmony_ci struct sockaddr *addr = p; 424362306a36Sopenharmony_ci int err; 424462306a36Sopenharmony_ci 424562306a36Sopenharmony_ci if (!is_valid_ether_addr(addr->sa_data)) 424662306a36Sopenharmony_ci return -EADDRNOTAVAIL; 424762306a36Sopenharmony_ci 424862306a36Sopenharmony_ci spin_lock_bh(&adapter->mbx_lock); 424962306a36Sopenharmony_ci 425062306a36Sopenharmony_ci err = hw->mac.ops.set_rar(hw, 0, addr->sa_data, 0); 425162306a36Sopenharmony_ci 425262306a36Sopenharmony_ci spin_unlock_bh(&adapter->mbx_lock); 425362306a36Sopenharmony_ci 425462306a36Sopenharmony_ci if (err) 425562306a36Sopenharmony_ci return -EPERM; 425662306a36Sopenharmony_ci 425762306a36Sopenharmony_ci ether_addr_copy(hw->mac.addr, addr->sa_data); 425862306a36Sopenharmony_ci ether_addr_copy(hw->mac.perm_addr, addr->sa_data); 425962306a36Sopenharmony_ci eth_hw_addr_set(netdev, addr->sa_data); 426062306a36Sopenharmony_ci 426162306a36Sopenharmony_ci return 0; 426262306a36Sopenharmony_ci} 426362306a36Sopenharmony_ci 426462306a36Sopenharmony_ci/** 426562306a36Sopenharmony_ci * ixgbevf_change_mtu - Change the Maximum Transfer Unit 426662306a36Sopenharmony_ci * @netdev: network interface device structure 426762306a36Sopenharmony_ci * @new_mtu: new value for maximum frame size 426862306a36Sopenharmony_ci * 426962306a36Sopenharmony_ci * Returns 0 on success, negative on failure 427062306a36Sopenharmony_ci **/ 427162306a36Sopenharmony_cistatic int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu) 427262306a36Sopenharmony_ci{ 427362306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 427462306a36Sopenharmony_ci struct ixgbe_hw *hw = &adapter->hw; 427562306a36Sopenharmony_ci int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; 427662306a36Sopenharmony_ci int ret; 427762306a36Sopenharmony_ci 427862306a36Sopenharmony_ci /* prevent MTU being changed to a size unsupported by XDP */ 427962306a36Sopenharmony_ci if (adapter->xdp_prog) { 428062306a36Sopenharmony_ci dev_warn(&adapter->pdev->dev, "MTU cannot be changed while XDP program is loaded\n"); 428162306a36Sopenharmony_ci return -EPERM; 428262306a36Sopenharmony_ci } 428362306a36Sopenharmony_ci 428462306a36Sopenharmony_ci spin_lock_bh(&adapter->mbx_lock); 428562306a36Sopenharmony_ci /* notify the PF of our intent to use this size of frame */ 428662306a36Sopenharmony_ci ret = hw->mac.ops.set_rlpml(hw, max_frame); 428762306a36Sopenharmony_ci spin_unlock_bh(&adapter->mbx_lock); 428862306a36Sopenharmony_ci if (ret) 428962306a36Sopenharmony_ci return -EINVAL; 429062306a36Sopenharmony_ci 429162306a36Sopenharmony_ci hw_dbg(hw, "changing MTU from %d to %d\n", 429262306a36Sopenharmony_ci netdev->mtu, new_mtu); 429362306a36Sopenharmony_ci 429462306a36Sopenharmony_ci /* must set new MTU before calling down or up */ 429562306a36Sopenharmony_ci netdev->mtu = new_mtu; 429662306a36Sopenharmony_ci 429762306a36Sopenharmony_ci if (netif_running(netdev)) 429862306a36Sopenharmony_ci ixgbevf_reinit_locked(adapter); 429962306a36Sopenharmony_ci 430062306a36Sopenharmony_ci return 0; 430162306a36Sopenharmony_ci} 430262306a36Sopenharmony_ci 430362306a36Sopenharmony_cistatic int __maybe_unused ixgbevf_suspend(struct device *dev_d) 430462306a36Sopenharmony_ci{ 430562306a36Sopenharmony_ci struct net_device *netdev = dev_get_drvdata(dev_d); 430662306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 430762306a36Sopenharmony_ci 430862306a36Sopenharmony_ci rtnl_lock(); 430962306a36Sopenharmony_ci netif_device_detach(netdev); 431062306a36Sopenharmony_ci 431162306a36Sopenharmony_ci if (netif_running(netdev)) 431262306a36Sopenharmony_ci ixgbevf_close_suspend(adapter); 431362306a36Sopenharmony_ci 431462306a36Sopenharmony_ci ixgbevf_clear_interrupt_scheme(adapter); 431562306a36Sopenharmony_ci rtnl_unlock(); 431662306a36Sopenharmony_ci 431762306a36Sopenharmony_ci return 0; 431862306a36Sopenharmony_ci} 431962306a36Sopenharmony_ci 432062306a36Sopenharmony_cistatic int __maybe_unused ixgbevf_resume(struct device *dev_d) 432162306a36Sopenharmony_ci{ 432262306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(dev_d); 432362306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 432462306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 432562306a36Sopenharmony_ci u32 err; 432662306a36Sopenharmony_ci 432762306a36Sopenharmony_ci adapter->hw.hw_addr = adapter->io_addr; 432862306a36Sopenharmony_ci smp_mb__before_atomic(); 432962306a36Sopenharmony_ci clear_bit(__IXGBEVF_DISABLED, &adapter->state); 433062306a36Sopenharmony_ci pci_set_master(pdev); 433162306a36Sopenharmony_ci 433262306a36Sopenharmony_ci ixgbevf_reset(adapter); 433362306a36Sopenharmony_ci 433462306a36Sopenharmony_ci rtnl_lock(); 433562306a36Sopenharmony_ci err = ixgbevf_init_interrupt_scheme(adapter); 433662306a36Sopenharmony_ci if (!err && netif_running(netdev)) 433762306a36Sopenharmony_ci err = ixgbevf_open(netdev); 433862306a36Sopenharmony_ci rtnl_unlock(); 433962306a36Sopenharmony_ci if (err) 434062306a36Sopenharmony_ci return err; 434162306a36Sopenharmony_ci 434262306a36Sopenharmony_ci netif_device_attach(netdev); 434362306a36Sopenharmony_ci 434462306a36Sopenharmony_ci return err; 434562306a36Sopenharmony_ci} 434662306a36Sopenharmony_ci 434762306a36Sopenharmony_cistatic void ixgbevf_shutdown(struct pci_dev *pdev) 434862306a36Sopenharmony_ci{ 434962306a36Sopenharmony_ci ixgbevf_suspend(&pdev->dev); 435062306a36Sopenharmony_ci} 435162306a36Sopenharmony_ci 435262306a36Sopenharmony_cistatic void ixgbevf_get_tx_ring_stats(struct rtnl_link_stats64 *stats, 435362306a36Sopenharmony_ci const struct ixgbevf_ring *ring) 435462306a36Sopenharmony_ci{ 435562306a36Sopenharmony_ci u64 bytes, packets; 435662306a36Sopenharmony_ci unsigned int start; 435762306a36Sopenharmony_ci 435862306a36Sopenharmony_ci if (ring) { 435962306a36Sopenharmony_ci do { 436062306a36Sopenharmony_ci start = u64_stats_fetch_begin(&ring->syncp); 436162306a36Sopenharmony_ci bytes = ring->stats.bytes; 436262306a36Sopenharmony_ci packets = ring->stats.packets; 436362306a36Sopenharmony_ci } while (u64_stats_fetch_retry(&ring->syncp, start)); 436462306a36Sopenharmony_ci stats->tx_bytes += bytes; 436562306a36Sopenharmony_ci stats->tx_packets += packets; 436662306a36Sopenharmony_ci } 436762306a36Sopenharmony_ci} 436862306a36Sopenharmony_ci 436962306a36Sopenharmony_cistatic void ixgbevf_get_stats(struct net_device *netdev, 437062306a36Sopenharmony_ci struct rtnl_link_stats64 *stats) 437162306a36Sopenharmony_ci{ 437262306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 437362306a36Sopenharmony_ci unsigned int start; 437462306a36Sopenharmony_ci u64 bytes, packets; 437562306a36Sopenharmony_ci const struct ixgbevf_ring *ring; 437662306a36Sopenharmony_ci int i; 437762306a36Sopenharmony_ci 437862306a36Sopenharmony_ci ixgbevf_update_stats(adapter); 437962306a36Sopenharmony_ci 438062306a36Sopenharmony_ci stats->multicast = adapter->stats.vfmprc - adapter->stats.base_vfmprc; 438162306a36Sopenharmony_ci 438262306a36Sopenharmony_ci rcu_read_lock(); 438362306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 438462306a36Sopenharmony_ci ring = adapter->rx_ring[i]; 438562306a36Sopenharmony_ci do { 438662306a36Sopenharmony_ci start = u64_stats_fetch_begin(&ring->syncp); 438762306a36Sopenharmony_ci bytes = ring->stats.bytes; 438862306a36Sopenharmony_ci packets = ring->stats.packets; 438962306a36Sopenharmony_ci } while (u64_stats_fetch_retry(&ring->syncp, start)); 439062306a36Sopenharmony_ci stats->rx_bytes += bytes; 439162306a36Sopenharmony_ci stats->rx_packets += packets; 439262306a36Sopenharmony_ci } 439362306a36Sopenharmony_ci 439462306a36Sopenharmony_ci for (i = 0; i < adapter->num_tx_queues; i++) { 439562306a36Sopenharmony_ci ring = adapter->tx_ring[i]; 439662306a36Sopenharmony_ci ixgbevf_get_tx_ring_stats(stats, ring); 439762306a36Sopenharmony_ci } 439862306a36Sopenharmony_ci 439962306a36Sopenharmony_ci for (i = 0; i < adapter->num_xdp_queues; i++) { 440062306a36Sopenharmony_ci ring = adapter->xdp_ring[i]; 440162306a36Sopenharmony_ci ixgbevf_get_tx_ring_stats(stats, ring); 440262306a36Sopenharmony_ci } 440362306a36Sopenharmony_ci rcu_read_unlock(); 440462306a36Sopenharmony_ci} 440562306a36Sopenharmony_ci 440662306a36Sopenharmony_ci#define IXGBEVF_MAX_MAC_HDR_LEN 127 440762306a36Sopenharmony_ci#define IXGBEVF_MAX_NETWORK_HDR_LEN 511 440862306a36Sopenharmony_ci 440962306a36Sopenharmony_cistatic netdev_features_t 441062306a36Sopenharmony_ciixgbevf_features_check(struct sk_buff *skb, struct net_device *dev, 441162306a36Sopenharmony_ci netdev_features_t features) 441262306a36Sopenharmony_ci{ 441362306a36Sopenharmony_ci unsigned int network_hdr_len, mac_hdr_len; 441462306a36Sopenharmony_ci 441562306a36Sopenharmony_ci /* Make certain the headers can be described by a context descriptor */ 441662306a36Sopenharmony_ci mac_hdr_len = skb_network_header(skb) - skb->data; 441762306a36Sopenharmony_ci if (unlikely(mac_hdr_len > IXGBEVF_MAX_MAC_HDR_LEN)) 441862306a36Sopenharmony_ci return features & ~(NETIF_F_HW_CSUM | 441962306a36Sopenharmony_ci NETIF_F_SCTP_CRC | 442062306a36Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_TX | 442162306a36Sopenharmony_ci NETIF_F_TSO | 442262306a36Sopenharmony_ci NETIF_F_TSO6); 442362306a36Sopenharmony_ci 442462306a36Sopenharmony_ci network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb); 442562306a36Sopenharmony_ci if (unlikely(network_hdr_len > IXGBEVF_MAX_NETWORK_HDR_LEN)) 442662306a36Sopenharmony_ci return features & ~(NETIF_F_HW_CSUM | 442762306a36Sopenharmony_ci NETIF_F_SCTP_CRC | 442862306a36Sopenharmony_ci NETIF_F_TSO | 442962306a36Sopenharmony_ci NETIF_F_TSO6); 443062306a36Sopenharmony_ci 443162306a36Sopenharmony_ci /* We can only support IPV4 TSO in tunnels if we can mangle the 443262306a36Sopenharmony_ci * inner IP ID field, so strip TSO if MANGLEID is not supported. 443362306a36Sopenharmony_ci */ 443462306a36Sopenharmony_ci if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID)) 443562306a36Sopenharmony_ci features &= ~NETIF_F_TSO; 443662306a36Sopenharmony_ci 443762306a36Sopenharmony_ci return features; 443862306a36Sopenharmony_ci} 443962306a36Sopenharmony_ci 444062306a36Sopenharmony_cistatic int ixgbevf_xdp_setup(struct net_device *dev, struct bpf_prog *prog) 444162306a36Sopenharmony_ci{ 444262306a36Sopenharmony_ci int i, frame_size = dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; 444362306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(dev); 444462306a36Sopenharmony_ci struct bpf_prog *old_prog; 444562306a36Sopenharmony_ci 444662306a36Sopenharmony_ci /* verify ixgbevf ring attributes are sufficient for XDP */ 444762306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) { 444862306a36Sopenharmony_ci struct ixgbevf_ring *ring = adapter->rx_ring[i]; 444962306a36Sopenharmony_ci 445062306a36Sopenharmony_ci if (frame_size > ixgbevf_rx_bufsz(ring)) 445162306a36Sopenharmony_ci return -EINVAL; 445262306a36Sopenharmony_ci } 445362306a36Sopenharmony_ci 445462306a36Sopenharmony_ci old_prog = xchg(&adapter->xdp_prog, prog); 445562306a36Sopenharmony_ci 445662306a36Sopenharmony_ci /* If transitioning XDP modes reconfigure rings */ 445762306a36Sopenharmony_ci if (!!prog != !!old_prog) { 445862306a36Sopenharmony_ci /* Hardware has to reinitialize queues and interrupts to 445962306a36Sopenharmony_ci * match packet buffer alignment. Unfortunately, the 446062306a36Sopenharmony_ci * hardware is not flexible enough to do this dynamically. 446162306a36Sopenharmony_ci */ 446262306a36Sopenharmony_ci if (netif_running(dev)) 446362306a36Sopenharmony_ci ixgbevf_close(dev); 446462306a36Sopenharmony_ci 446562306a36Sopenharmony_ci ixgbevf_clear_interrupt_scheme(adapter); 446662306a36Sopenharmony_ci ixgbevf_init_interrupt_scheme(adapter); 446762306a36Sopenharmony_ci 446862306a36Sopenharmony_ci if (netif_running(dev)) 446962306a36Sopenharmony_ci ixgbevf_open(dev); 447062306a36Sopenharmony_ci } else { 447162306a36Sopenharmony_ci for (i = 0; i < adapter->num_rx_queues; i++) 447262306a36Sopenharmony_ci xchg(&adapter->rx_ring[i]->xdp_prog, adapter->xdp_prog); 447362306a36Sopenharmony_ci } 447462306a36Sopenharmony_ci 447562306a36Sopenharmony_ci if (old_prog) 447662306a36Sopenharmony_ci bpf_prog_put(old_prog); 447762306a36Sopenharmony_ci 447862306a36Sopenharmony_ci return 0; 447962306a36Sopenharmony_ci} 448062306a36Sopenharmony_ci 448162306a36Sopenharmony_cistatic int ixgbevf_xdp(struct net_device *dev, struct netdev_bpf *xdp) 448262306a36Sopenharmony_ci{ 448362306a36Sopenharmony_ci switch (xdp->command) { 448462306a36Sopenharmony_ci case XDP_SETUP_PROG: 448562306a36Sopenharmony_ci return ixgbevf_xdp_setup(dev, xdp->prog); 448662306a36Sopenharmony_ci default: 448762306a36Sopenharmony_ci return -EINVAL; 448862306a36Sopenharmony_ci } 448962306a36Sopenharmony_ci} 449062306a36Sopenharmony_ci 449162306a36Sopenharmony_cistatic const struct net_device_ops ixgbevf_netdev_ops = { 449262306a36Sopenharmony_ci .ndo_open = ixgbevf_open, 449362306a36Sopenharmony_ci .ndo_stop = ixgbevf_close, 449462306a36Sopenharmony_ci .ndo_start_xmit = ixgbevf_xmit_frame, 449562306a36Sopenharmony_ci .ndo_set_rx_mode = ixgbevf_set_rx_mode, 449662306a36Sopenharmony_ci .ndo_get_stats64 = ixgbevf_get_stats, 449762306a36Sopenharmony_ci .ndo_validate_addr = eth_validate_addr, 449862306a36Sopenharmony_ci .ndo_set_mac_address = ixgbevf_set_mac, 449962306a36Sopenharmony_ci .ndo_change_mtu = ixgbevf_change_mtu, 450062306a36Sopenharmony_ci .ndo_tx_timeout = ixgbevf_tx_timeout, 450162306a36Sopenharmony_ci .ndo_vlan_rx_add_vid = ixgbevf_vlan_rx_add_vid, 450262306a36Sopenharmony_ci .ndo_vlan_rx_kill_vid = ixgbevf_vlan_rx_kill_vid, 450362306a36Sopenharmony_ci .ndo_features_check = ixgbevf_features_check, 450462306a36Sopenharmony_ci .ndo_bpf = ixgbevf_xdp, 450562306a36Sopenharmony_ci}; 450662306a36Sopenharmony_ci 450762306a36Sopenharmony_cistatic void ixgbevf_assign_netdev_ops(struct net_device *dev) 450862306a36Sopenharmony_ci{ 450962306a36Sopenharmony_ci dev->netdev_ops = &ixgbevf_netdev_ops; 451062306a36Sopenharmony_ci ixgbevf_set_ethtool_ops(dev); 451162306a36Sopenharmony_ci dev->watchdog_timeo = 5 * HZ; 451262306a36Sopenharmony_ci} 451362306a36Sopenharmony_ci 451462306a36Sopenharmony_ci/** 451562306a36Sopenharmony_ci * ixgbevf_probe - Device Initialization Routine 451662306a36Sopenharmony_ci * @pdev: PCI device information struct 451762306a36Sopenharmony_ci * @ent: entry in ixgbevf_pci_tbl 451862306a36Sopenharmony_ci * 451962306a36Sopenharmony_ci * Returns 0 on success, negative on failure 452062306a36Sopenharmony_ci * 452162306a36Sopenharmony_ci * ixgbevf_probe initializes an adapter identified by a pci_dev structure. 452262306a36Sopenharmony_ci * The OS initialization, configuring of the adapter private structure, 452362306a36Sopenharmony_ci * and a hardware reset occur. 452462306a36Sopenharmony_ci **/ 452562306a36Sopenharmony_cistatic int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 452662306a36Sopenharmony_ci{ 452762306a36Sopenharmony_ci struct net_device *netdev; 452862306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = NULL; 452962306a36Sopenharmony_ci struct ixgbe_hw *hw = NULL; 453062306a36Sopenharmony_ci const struct ixgbevf_info *ii = ixgbevf_info_tbl[ent->driver_data]; 453162306a36Sopenharmony_ci bool disable_dev = false; 453262306a36Sopenharmony_ci int err; 453362306a36Sopenharmony_ci 453462306a36Sopenharmony_ci err = pci_enable_device(pdev); 453562306a36Sopenharmony_ci if (err) 453662306a36Sopenharmony_ci return err; 453762306a36Sopenharmony_ci 453862306a36Sopenharmony_ci err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); 453962306a36Sopenharmony_ci if (err) { 454062306a36Sopenharmony_ci dev_err(&pdev->dev, "No usable DMA configuration, aborting\n"); 454162306a36Sopenharmony_ci goto err_dma; 454262306a36Sopenharmony_ci } 454362306a36Sopenharmony_ci 454462306a36Sopenharmony_ci err = pci_request_regions(pdev, ixgbevf_driver_name); 454562306a36Sopenharmony_ci if (err) { 454662306a36Sopenharmony_ci dev_err(&pdev->dev, "pci_request_regions failed 0x%x\n", err); 454762306a36Sopenharmony_ci goto err_pci_reg; 454862306a36Sopenharmony_ci } 454962306a36Sopenharmony_ci 455062306a36Sopenharmony_ci pci_set_master(pdev); 455162306a36Sopenharmony_ci 455262306a36Sopenharmony_ci netdev = alloc_etherdev_mq(sizeof(struct ixgbevf_adapter), 455362306a36Sopenharmony_ci MAX_TX_QUEUES); 455462306a36Sopenharmony_ci if (!netdev) { 455562306a36Sopenharmony_ci err = -ENOMEM; 455662306a36Sopenharmony_ci goto err_alloc_etherdev; 455762306a36Sopenharmony_ci } 455862306a36Sopenharmony_ci 455962306a36Sopenharmony_ci SET_NETDEV_DEV(netdev, &pdev->dev); 456062306a36Sopenharmony_ci 456162306a36Sopenharmony_ci adapter = netdev_priv(netdev); 456262306a36Sopenharmony_ci 456362306a36Sopenharmony_ci adapter->netdev = netdev; 456462306a36Sopenharmony_ci adapter->pdev = pdev; 456562306a36Sopenharmony_ci hw = &adapter->hw; 456662306a36Sopenharmony_ci hw->back = adapter; 456762306a36Sopenharmony_ci adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); 456862306a36Sopenharmony_ci 456962306a36Sopenharmony_ci /* call save state here in standalone driver because it relies on 457062306a36Sopenharmony_ci * adapter struct to exist, and needs to call netdev_priv 457162306a36Sopenharmony_ci */ 457262306a36Sopenharmony_ci pci_save_state(pdev); 457362306a36Sopenharmony_ci 457462306a36Sopenharmony_ci hw->hw_addr = ioremap(pci_resource_start(pdev, 0), 457562306a36Sopenharmony_ci pci_resource_len(pdev, 0)); 457662306a36Sopenharmony_ci adapter->io_addr = hw->hw_addr; 457762306a36Sopenharmony_ci if (!hw->hw_addr) { 457862306a36Sopenharmony_ci err = -EIO; 457962306a36Sopenharmony_ci goto err_ioremap; 458062306a36Sopenharmony_ci } 458162306a36Sopenharmony_ci 458262306a36Sopenharmony_ci ixgbevf_assign_netdev_ops(netdev); 458362306a36Sopenharmony_ci 458462306a36Sopenharmony_ci /* Setup HW API */ 458562306a36Sopenharmony_ci memcpy(&hw->mac.ops, ii->mac_ops, sizeof(hw->mac.ops)); 458662306a36Sopenharmony_ci hw->mac.type = ii->mac; 458762306a36Sopenharmony_ci 458862306a36Sopenharmony_ci memcpy(&hw->mbx.ops, &ixgbevf_mbx_ops_legacy, 458962306a36Sopenharmony_ci sizeof(struct ixgbe_mbx_operations)); 459062306a36Sopenharmony_ci 459162306a36Sopenharmony_ci /* setup the private structure */ 459262306a36Sopenharmony_ci err = ixgbevf_sw_init(adapter); 459362306a36Sopenharmony_ci if (err) 459462306a36Sopenharmony_ci goto err_sw_init; 459562306a36Sopenharmony_ci 459662306a36Sopenharmony_ci /* The HW MAC address was set and/or determined in sw_init */ 459762306a36Sopenharmony_ci if (!is_valid_ether_addr(netdev->dev_addr)) { 459862306a36Sopenharmony_ci pr_err("invalid MAC address\n"); 459962306a36Sopenharmony_ci err = -EIO; 460062306a36Sopenharmony_ci goto err_sw_init; 460162306a36Sopenharmony_ci } 460262306a36Sopenharmony_ci 460362306a36Sopenharmony_ci netdev->hw_features = NETIF_F_SG | 460462306a36Sopenharmony_ci NETIF_F_TSO | 460562306a36Sopenharmony_ci NETIF_F_TSO6 | 460662306a36Sopenharmony_ci NETIF_F_RXCSUM | 460762306a36Sopenharmony_ci NETIF_F_HW_CSUM | 460862306a36Sopenharmony_ci NETIF_F_SCTP_CRC; 460962306a36Sopenharmony_ci 461062306a36Sopenharmony_ci#define IXGBEVF_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \ 461162306a36Sopenharmony_ci NETIF_F_GSO_GRE_CSUM | \ 461262306a36Sopenharmony_ci NETIF_F_GSO_IPXIP4 | \ 461362306a36Sopenharmony_ci NETIF_F_GSO_IPXIP6 | \ 461462306a36Sopenharmony_ci NETIF_F_GSO_UDP_TUNNEL | \ 461562306a36Sopenharmony_ci NETIF_F_GSO_UDP_TUNNEL_CSUM) 461662306a36Sopenharmony_ci 461762306a36Sopenharmony_ci netdev->gso_partial_features = IXGBEVF_GSO_PARTIAL_FEATURES; 461862306a36Sopenharmony_ci netdev->hw_features |= NETIF_F_GSO_PARTIAL | 461962306a36Sopenharmony_ci IXGBEVF_GSO_PARTIAL_FEATURES; 462062306a36Sopenharmony_ci 462162306a36Sopenharmony_ci netdev->features = netdev->hw_features | NETIF_F_HIGHDMA; 462262306a36Sopenharmony_ci 462362306a36Sopenharmony_ci netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID; 462462306a36Sopenharmony_ci netdev->mpls_features |= NETIF_F_SG | 462562306a36Sopenharmony_ci NETIF_F_TSO | 462662306a36Sopenharmony_ci NETIF_F_TSO6 | 462762306a36Sopenharmony_ci NETIF_F_HW_CSUM; 462862306a36Sopenharmony_ci netdev->mpls_features |= IXGBEVF_GSO_PARTIAL_FEATURES; 462962306a36Sopenharmony_ci netdev->hw_enc_features |= netdev->vlan_features; 463062306a36Sopenharmony_ci 463162306a36Sopenharmony_ci /* set this bit last since it cannot be part of vlan_features */ 463262306a36Sopenharmony_ci netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER | 463362306a36Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_RX | 463462306a36Sopenharmony_ci NETIF_F_HW_VLAN_CTAG_TX; 463562306a36Sopenharmony_ci 463662306a36Sopenharmony_ci netdev->priv_flags |= IFF_UNICAST_FLT; 463762306a36Sopenharmony_ci netdev->xdp_features = NETDEV_XDP_ACT_BASIC; 463862306a36Sopenharmony_ci 463962306a36Sopenharmony_ci /* MTU range: 68 - 1504 or 9710 */ 464062306a36Sopenharmony_ci netdev->min_mtu = ETH_MIN_MTU; 464162306a36Sopenharmony_ci switch (adapter->hw.api_version) { 464262306a36Sopenharmony_ci case ixgbe_mbox_api_11: 464362306a36Sopenharmony_ci case ixgbe_mbox_api_12: 464462306a36Sopenharmony_ci case ixgbe_mbox_api_13: 464562306a36Sopenharmony_ci case ixgbe_mbox_api_14: 464662306a36Sopenharmony_ci case ixgbe_mbox_api_15: 464762306a36Sopenharmony_ci netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - 464862306a36Sopenharmony_ci (ETH_HLEN + ETH_FCS_LEN); 464962306a36Sopenharmony_ci break; 465062306a36Sopenharmony_ci default: 465162306a36Sopenharmony_ci if (adapter->hw.mac.type != ixgbe_mac_82599_vf) 465262306a36Sopenharmony_ci netdev->max_mtu = IXGBE_MAX_JUMBO_FRAME_SIZE - 465362306a36Sopenharmony_ci (ETH_HLEN + ETH_FCS_LEN); 465462306a36Sopenharmony_ci else 465562306a36Sopenharmony_ci netdev->max_mtu = ETH_DATA_LEN + ETH_FCS_LEN; 465662306a36Sopenharmony_ci break; 465762306a36Sopenharmony_ci } 465862306a36Sopenharmony_ci 465962306a36Sopenharmony_ci if (IXGBE_REMOVED(hw->hw_addr)) { 466062306a36Sopenharmony_ci err = -EIO; 466162306a36Sopenharmony_ci goto err_sw_init; 466262306a36Sopenharmony_ci } 466362306a36Sopenharmony_ci 466462306a36Sopenharmony_ci timer_setup(&adapter->service_timer, ixgbevf_service_timer, 0); 466562306a36Sopenharmony_ci 466662306a36Sopenharmony_ci INIT_WORK(&adapter->service_task, ixgbevf_service_task); 466762306a36Sopenharmony_ci set_bit(__IXGBEVF_SERVICE_INITED, &adapter->state); 466862306a36Sopenharmony_ci clear_bit(__IXGBEVF_SERVICE_SCHED, &adapter->state); 466962306a36Sopenharmony_ci 467062306a36Sopenharmony_ci err = ixgbevf_init_interrupt_scheme(adapter); 467162306a36Sopenharmony_ci if (err) 467262306a36Sopenharmony_ci goto err_sw_init; 467362306a36Sopenharmony_ci 467462306a36Sopenharmony_ci strcpy(netdev->name, "eth%d"); 467562306a36Sopenharmony_ci 467662306a36Sopenharmony_ci err = register_netdev(netdev); 467762306a36Sopenharmony_ci if (err) 467862306a36Sopenharmony_ci goto err_register; 467962306a36Sopenharmony_ci 468062306a36Sopenharmony_ci pci_set_drvdata(pdev, netdev); 468162306a36Sopenharmony_ci netif_carrier_off(netdev); 468262306a36Sopenharmony_ci ixgbevf_init_ipsec_offload(adapter); 468362306a36Sopenharmony_ci 468462306a36Sopenharmony_ci ixgbevf_init_last_counter_stats(adapter); 468562306a36Sopenharmony_ci 468662306a36Sopenharmony_ci /* print the VF info */ 468762306a36Sopenharmony_ci dev_info(&pdev->dev, "%pM\n", netdev->dev_addr); 468862306a36Sopenharmony_ci dev_info(&pdev->dev, "MAC: %d\n", hw->mac.type); 468962306a36Sopenharmony_ci 469062306a36Sopenharmony_ci switch (hw->mac.type) { 469162306a36Sopenharmony_ci case ixgbe_mac_X550_vf: 469262306a36Sopenharmony_ci dev_info(&pdev->dev, "Intel(R) X550 Virtual Function\n"); 469362306a36Sopenharmony_ci break; 469462306a36Sopenharmony_ci case ixgbe_mac_X540_vf: 469562306a36Sopenharmony_ci dev_info(&pdev->dev, "Intel(R) X540 Virtual Function\n"); 469662306a36Sopenharmony_ci break; 469762306a36Sopenharmony_ci case ixgbe_mac_82599_vf: 469862306a36Sopenharmony_ci default: 469962306a36Sopenharmony_ci dev_info(&pdev->dev, "Intel(R) 82599 Virtual Function\n"); 470062306a36Sopenharmony_ci break; 470162306a36Sopenharmony_ci } 470262306a36Sopenharmony_ci 470362306a36Sopenharmony_ci return 0; 470462306a36Sopenharmony_ci 470562306a36Sopenharmony_cierr_register: 470662306a36Sopenharmony_ci ixgbevf_clear_interrupt_scheme(adapter); 470762306a36Sopenharmony_cierr_sw_init: 470862306a36Sopenharmony_ci ixgbevf_reset_interrupt_capability(adapter); 470962306a36Sopenharmony_ci iounmap(adapter->io_addr); 471062306a36Sopenharmony_ci kfree(adapter->rss_key); 471162306a36Sopenharmony_cierr_ioremap: 471262306a36Sopenharmony_ci disable_dev = !test_and_set_bit(__IXGBEVF_DISABLED, &adapter->state); 471362306a36Sopenharmony_ci free_netdev(netdev); 471462306a36Sopenharmony_cierr_alloc_etherdev: 471562306a36Sopenharmony_ci pci_release_regions(pdev); 471662306a36Sopenharmony_cierr_pci_reg: 471762306a36Sopenharmony_cierr_dma: 471862306a36Sopenharmony_ci if (!adapter || disable_dev) 471962306a36Sopenharmony_ci pci_disable_device(pdev); 472062306a36Sopenharmony_ci return err; 472162306a36Sopenharmony_ci} 472262306a36Sopenharmony_ci 472362306a36Sopenharmony_ci/** 472462306a36Sopenharmony_ci * ixgbevf_remove - Device Removal Routine 472562306a36Sopenharmony_ci * @pdev: PCI device information struct 472662306a36Sopenharmony_ci * 472762306a36Sopenharmony_ci * ixgbevf_remove is called by the PCI subsystem to alert the driver 472862306a36Sopenharmony_ci * that it should release a PCI device. The could be caused by a 472962306a36Sopenharmony_ci * Hot-Plug event, or because the driver is going to be removed from 473062306a36Sopenharmony_ci * memory. 473162306a36Sopenharmony_ci **/ 473262306a36Sopenharmony_cistatic void ixgbevf_remove(struct pci_dev *pdev) 473362306a36Sopenharmony_ci{ 473462306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 473562306a36Sopenharmony_ci struct ixgbevf_adapter *adapter; 473662306a36Sopenharmony_ci bool disable_dev; 473762306a36Sopenharmony_ci 473862306a36Sopenharmony_ci if (!netdev) 473962306a36Sopenharmony_ci return; 474062306a36Sopenharmony_ci 474162306a36Sopenharmony_ci adapter = netdev_priv(netdev); 474262306a36Sopenharmony_ci 474362306a36Sopenharmony_ci set_bit(__IXGBEVF_REMOVING, &adapter->state); 474462306a36Sopenharmony_ci cancel_work_sync(&adapter->service_task); 474562306a36Sopenharmony_ci 474662306a36Sopenharmony_ci if (netdev->reg_state == NETREG_REGISTERED) 474762306a36Sopenharmony_ci unregister_netdev(netdev); 474862306a36Sopenharmony_ci 474962306a36Sopenharmony_ci ixgbevf_stop_ipsec_offload(adapter); 475062306a36Sopenharmony_ci ixgbevf_clear_interrupt_scheme(adapter); 475162306a36Sopenharmony_ci ixgbevf_reset_interrupt_capability(adapter); 475262306a36Sopenharmony_ci 475362306a36Sopenharmony_ci iounmap(adapter->io_addr); 475462306a36Sopenharmony_ci pci_release_regions(pdev); 475562306a36Sopenharmony_ci 475662306a36Sopenharmony_ci hw_dbg(&adapter->hw, "Remove complete\n"); 475762306a36Sopenharmony_ci 475862306a36Sopenharmony_ci kfree(adapter->rss_key); 475962306a36Sopenharmony_ci disable_dev = !test_and_set_bit(__IXGBEVF_DISABLED, &adapter->state); 476062306a36Sopenharmony_ci free_netdev(netdev); 476162306a36Sopenharmony_ci 476262306a36Sopenharmony_ci if (disable_dev) 476362306a36Sopenharmony_ci pci_disable_device(pdev); 476462306a36Sopenharmony_ci} 476562306a36Sopenharmony_ci 476662306a36Sopenharmony_ci/** 476762306a36Sopenharmony_ci * ixgbevf_io_error_detected - called when PCI error is detected 476862306a36Sopenharmony_ci * @pdev: Pointer to PCI device 476962306a36Sopenharmony_ci * @state: The current pci connection state 477062306a36Sopenharmony_ci * 477162306a36Sopenharmony_ci * This function is called after a PCI bus error affecting 477262306a36Sopenharmony_ci * this device has been detected. 477362306a36Sopenharmony_ci **/ 477462306a36Sopenharmony_cistatic pci_ers_result_t ixgbevf_io_error_detected(struct pci_dev *pdev, 477562306a36Sopenharmony_ci pci_channel_state_t state) 477662306a36Sopenharmony_ci{ 477762306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 477862306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 477962306a36Sopenharmony_ci 478062306a36Sopenharmony_ci if (!test_bit(__IXGBEVF_SERVICE_INITED, &adapter->state)) 478162306a36Sopenharmony_ci return PCI_ERS_RESULT_DISCONNECT; 478262306a36Sopenharmony_ci 478362306a36Sopenharmony_ci rtnl_lock(); 478462306a36Sopenharmony_ci netif_device_detach(netdev); 478562306a36Sopenharmony_ci 478662306a36Sopenharmony_ci if (netif_running(netdev)) 478762306a36Sopenharmony_ci ixgbevf_close_suspend(adapter); 478862306a36Sopenharmony_ci 478962306a36Sopenharmony_ci if (state == pci_channel_io_perm_failure) { 479062306a36Sopenharmony_ci rtnl_unlock(); 479162306a36Sopenharmony_ci return PCI_ERS_RESULT_DISCONNECT; 479262306a36Sopenharmony_ci } 479362306a36Sopenharmony_ci 479462306a36Sopenharmony_ci if (!test_and_set_bit(__IXGBEVF_DISABLED, &adapter->state)) 479562306a36Sopenharmony_ci pci_disable_device(pdev); 479662306a36Sopenharmony_ci rtnl_unlock(); 479762306a36Sopenharmony_ci 479862306a36Sopenharmony_ci /* Request a slot reset. */ 479962306a36Sopenharmony_ci return PCI_ERS_RESULT_NEED_RESET; 480062306a36Sopenharmony_ci} 480162306a36Sopenharmony_ci 480262306a36Sopenharmony_ci/** 480362306a36Sopenharmony_ci * ixgbevf_io_slot_reset - called after the pci bus has been reset. 480462306a36Sopenharmony_ci * @pdev: Pointer to PCI device 480562306a36Sopenharmony_ci * 480662306a36Sopenharmony_ci * Restart the card from scratch, as if from a cold-boot. Implementation 480762306a36Sopenharmony_ci * resembles the first-half of the ixgbevf_resume routine. 480862306a36Sopenharmony_ci **/ 480962306a36Sopenharmony_cistatic pci_ers_result_t ixgbevf_io_slot_reset(struct pci_dev *pdev) 481062306a36Sopenharmony_ci{ 481162306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 481262306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = netdev_priv(netdev); 481362306a36Sopenharmony_ci 481462306a36Sopenharmony_ci if (pci_enable_device_mem(pdev)) { 481562306a36Sopenharmony_ci dev_err(&pdev->dev, 481662306a36Sopenharmony_ci "Cannot re-enable PCI device after reset.\n"); 481762306a36Sopenharmony_ci return PCI_ERS_RESULT_DISCONNECT; 481862306a36Sopenharmony_ci } 481962306a36Sopenharmony_ci 482062306a36Sopenharmony_ci adapter->hw.hw_addr = adapter->io_addr; 482162306a36Sopenharmony_ci smp_mb__before_atomic(); 482262306a36Sopenharmony_ci clear_bit(__IXGBEVF_DISABLED, &adapter->state); 482362306a36Sopenharmony_ci pci_set_master(pdev); 482462306a36Sopenharmony_ci 482562306a36Sopenharmony_ci ixgbevf_reset(adapter); 482662306a36Sopenharmony_ci 482762306a36Sopenharmony_ci return PCI_ERS_RESULT_RECOVERED; 482862306a36Sopenharmony_ci} 482962306a36Sopenharmony_ci 483062306a36Sopenharmony_ci/** 483162306a36Sopenharmony_ci * ixgbevf_io_resume - called when traffic can start flowing again. 483262306a36Sopenharmony_ci * @pdev: Pointer to PCI device 483362306a36Sopenharmony_ci * 483462306a36Sopenharmony_ci * This callback is called when the error recovery driver tells us that 483562306a36Sopenharmony_ci * its OK to resume normal operation. Implementation resembles the 483662306a36Sopenharmony_ci * second-half of the ixgbevf_resume routine. 483762306a36Sopenharmony_ci **/ 483862306a36Sopenharmony_cistatic void ixgbevf_io_resume(struct pci_dev *pdev) 483962306a36Sopenharmony_ci{ 484062306a36Sopenharmony_ci struct net_device *netdev = pci_get_drvdata(pdev); 484162306a36Sopenharmony_ci 484262306a36Sopenharmony_ci rtnl_lock(); 484362306a36Sopenharmony_ci if (netif_running(netdev)) 484462306a36Sopenharmony_ci ixgbevf_open(netdev); 484562306a36Sopenharmony_ci 484662306a36Sopenharmony_ci netif_device_attach(netdev); 484762306a36Sopenharmony_ci rtnl_unlock(); 484862306a36Sopenharmony_ci} 484962306a36Sopenharmony_ci 485062306a36Sopenharmony_ci/* PCI Error Recovery (ERS) */ 485162306a36Sopenharmony_cistatic const struct pci_error_handlers ixgbevf_err_handler = { 485262306a36Sopenharmony_ci .error_detected = ixgbevf_io_error_detected, 485362306a36Sopenharmony_ci .slot_reset = ixgbevf_io_slot_reset, 485462306a36Sopenharmony_ci .resume = ixgbevf_io_resume, 485562306a36Sopenharmony_ci}; 485662306a36Sopenharmony_ci 485762306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(ixgbevf_pm_ops, ixgbevf_suspend, ixgbevf_resume); 485862306a36Sopenharmony_ci 485962306a36Sopenharmony_cistatic struct pci_driver ixgbevf_driver = { 486062306a36Sopenharmony_ci .name = ixgbevf_driver_name, 486162306a36Sopenharmony_ci .id_table = ixgbevf_pci_tbl, 486262306a36Sopenharmony_ci .probe = ixgbevf_probe, 486362306a36Sopenharmony_ci .remove = ixgbevf_remove, 486462306a36Sopenharmony_ci 486562306a36Sopenharmony_ci /* Power Management Hooks */ 486662306a36Sopenharmony_ci .driver.pm = &ixgbevf_pm_ops, 486762306a36Sopenharmony_ci 486862306a36Sopenharmony_ci .shutdown = ixgbevf_shutdown, 486962306a36Sopenharmony_ci .err_handler = &ixgbevf_err_handler 487062306a36Sopenharmony_ci}; 487162306a36Sopenharmony_ci 487262306a36Sopenharmony_ci/** 487362306a36Sopenharmony_ci * ixgbevf_init_module - Driver Registration Routine 487462306a36Sopenharmony_ci * 487562306a36Sopenharmony_ci * ixgbevf_init_module is the first routine called when the driver is 487662306a36Sopenharmony_ci * loaded. All it does is register with the PCI subsystem. 487762306a36Sopenharmony_ci **/ 487862306a36Sopenharmony_cistatic int __init ixgbevf_init_module(void) 487962306a36Sopenharmony_ci{ 488062306a36Sopenharmony_ci int err; 488162306a36Sopenharmony_ci 488262306a36Sopenharmony_ci pr_info("%s\n", ixgbevf_driver_string); 488362306a36Sopenharmony_ci pr_info("%s\n", ixgbevf_copyright); 488462306a36Sopenharmony_ci ixgbevf_wq = create_singlethread_workqueue(ixgbevf_driver_name); 488562306a36Sopenharmony_ci if (!ixgbevf_wq) { 488662306a36Sopenharmony_ci pr_err("%s: Failed to create workqueue\n", ixgbevf_driver_name); 488762306a36Sopenharmony_ci return -ENOMEM; 488862306a36Sopenharmony_ci } 488962306a36Sopenharmony_ci 489062306a36Sopenharmony_ci err = pci_register_driver(&ixgbevf_driver); 489162306a36Sopenharmony_ci if (err) { 489262306a36Sopenharmony_ci destroy_workqueue(ixgbevf_wq); 489362306a36Sopenharmony_ci return err; 489462306a36Sopenharmony_ci } 489562306a36Sopenharmony_ci 489662306a36Sopenharmony_ci return 0; 489762306a36Sopenharmony_ci} 489862306a36Sopenharmony_ci 489962306a36Sopenharmony_cimodule_init(ixgbevf_init_module); 490062306a36Sopenharmony_ci 490162306a36Sopenharmony_ci/** 490262306a36Sopenharmony_ci * ixgbevf_exit_module - Driver Exit Cleanup Routine 490362306a36Sopenharmony_ci * 490462306a36Sopenharmony_ci * ixgbevf_exit_module is called just before the driver is removed 490562306a36Sopenharmony_ci * from memory. 490662306a36Sopenharmony_ci **/ 490762306a36Sopenharmony_cistatic void __exit ixgbevf_exit_module(void) 490862306a36Sopenharmony_ci{ 490962306a36Sopenharmony_ci pci_unregister_driver(&ixgbevf_driver); 491062306a36Sopenharmony_ci if (ixgbevf_wq) { 491162306a36Sopenharmony_ci destroy_workqueue(ixgbevf_wq); 491262306a36Sopenharmony_ci ixgbevf_wq = NULL; 491362306a36Sopenharmony_ci } 491462306a36Sopenharmony_ci} 491562306a36Sopenharmony_ci 491662306a36Sopenharmony_ci#ifdef DEBUG 491762306a36Sopenharmony_ci/** 491862306a36Sopenharmony_ci * ixgbevf_get_hw_dev_name - return device name string 491962306a36Sopenharmony_ci * used by hardware layer to print debugging information 492062306a36Sopenharmony_ci * @hw: pointer to private hardware struct 492162306a36Sopenharmony_ci **/ 492262306a36Sopenharmony_cichar *ixgbevf_get_hw_dev_name(struct ixgbe_hw *hw) 492362306a36Sopenharmony_ci{ 492462306a36Sopenharmony_ci struct ixgbevf_adapter *adapter = hw->back; 492562306a36Sopenharmony_ci 492662306a36Sopenharmony_ci return adapter->netdev->name; 492762306a36Sopenharmony_ci} 492862306a36Sopenharmony_ci 492962306a36Sopenharmony_ci#endif 493062306a36Sopenharmony_cimodule_exit(ixgbevf_exit_module); 493162306a36Sopenharmony_ci 493262306a36Sopenharmony_ci/* ixgbevf_main.c */ 4933