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