162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Copyright(c) 2009 - 2018 Intel Corporation. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/module.h>
762306a36Sopenharmony_ci#include <linux/types.h>
862306a36Sopenharmony_ci#include <linux/init.h>
962306a36Sopenharmony_ci#include <linux/pci.h>
1062306a36Sopenharmony_ci#include <linux/vmalloc.h>
1162306a36Sopenharmony_ci#include <linux/pagemap.h>
1262306a36Sopenharmony_ci#include <linux/delay.h>
1362306a36Sopenharmony_ci#include <linux/netdevice.h>
1462306a36Sopenharmony_ci#include <linux/tcp.h>
1562306a36Sopenharmony_ci#include <linux/ipv6.h>
1662306a36Sopenharmony_ci#include <linux/slab.h>
1762306a36Sopenharmony_ci#include <net/checksum.h>
1862306a36Sopenharmony_ci#include <net/ip6_checksum.h>
1962306a36Sopenharmony_ci#include <linux/mii.h>
2062306a36Sopenharmony_ci#include <linux/ethtool.h>
2162306a36Sopenharmony_ci#include <linux/if_vlan.h>
2262306a36Sopenharmony_ci#include <linux/prefetch.h>
2362306a36Sopenharmony_ci#include <linux/sctp.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#include "igbvf.h"
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cichar igbvf_driver_name[] = "igbvf";
2862306a36Sopenharmony_cistatic const char igbvf_driver_string[] =
2962306a36Sopenharmony_ci		  "Intel(R) Gigabit Virtual Function Network Driver";
3062306a36Sopenharmony_cistatic const char igbvf_copyright[] =
3162306a36Sopenharmony_ci		  "Copyright (c) 2009 - 2012 Intel Corporation.";
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK)
3462306a36Sopenharmony_cistatic int debug = -1;
3562306a36Sopenharmony_cimodule_param(debug, int, 0);
3662306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistatic int igbvf_poll(struct napi_struct *napi, int budget);
3962306a36Sopenharmony_cistatic void igbvf_reset(struct igbvf_adapter *);
4062306a36Sopenharmony_cistatic void igbvf_set_interrupt_capability(struct igbvf_adapter *);
4162306a36Sopenharmony_cistatic void igbvf_reset_interrupt_capability(struct igbvf_adapter *);
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic struct igbvf_info igbvf_vf_info = {
4462306a36Sopenharmony_ci	.mac		= e1000_vfadapt,
4562306a36Sopenharmony_ci	.flags		= 0,
4662306a36Sopenharmony_ci	.pba		= 10,
4762306a36Sopenharmony_ci	.init_ops	= e1000_init_function_pointers_vf,
4862306a36Sopenharmony_ci};
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic struct igbvf_info igbvf_i350_vf_info = {
5162306a36Sopenharmony_ci	.mac		= e1000_vfadapt_i350,
5262306a36Sopenharmony_ci	.flags		= 0,
5362306a36Sopenharmony_ci	.pba		= 10,
5462306a36Sopenharmony_ci	.init_ops	= e1000_init_function_pointers_vf,
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic const struct igbvf_info *igbvf_info_tbl[] = {
5862306a36Sopenharmony_ci	[board_vf]	= &igbvf_vf_info,
5962306a36Sopenharmony_ci	[board_i350_vf]	= &igbvf_i350_vf_info,
6062306a36Sopenharmony_ci};
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/**
6362306a36Sopenharmony_ci * igbvf_desc_unused - calculate if we have unused descriptors
6462306a36Sopenharmony_ci * @ring: address of receive ring structure
6562306a36Sopenharmony_ci **/
6662306a36Sopenharmony_cistatic int igbvf_desc_unused(struct igbvf_ring *ring)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	if (ring->next_to_clean > ring->next_to_use)
6962306a36Sopenharmony_ci		return ring->next_to_clean - ring->next_to_use - 1;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	return ring->count + ring->next_to_clean - ring->next_to_use - 1;
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/**
7562306a36Sopenharmony_ci * igbvf_receive_skb - helper function to handle Rx indications
7662306a36Sopenharmony_ci * @adapter: board private structure
7762306a36Sopenharmony_ci * @netdev: pointer to netdev struct
7862306a36Sopenharmony_ci * @skb: skb to indicate to stack
7962306a36Sopenharmony_ci * @status: descriptor status field as written by hardware
8062306a36Sopenharmony_ci * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
8162306a36Sopenharmony_ci * @skb: pointer to sk_buff to be indicated to stack
8262306a36Sopenharmony_ci **/
8362306a36Sopenharmony_cistatic void igbvf_receive_skb(struct igbvf_adapter *adapter,
8462306a36Sopenharmony_ci			      struct net_device *netdev,
8562306a36Sopenharmony_ci			      struct sk_buff *skb,
8662306a36Sopenharmony_ci			      u32 status, __le16 vlan)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	u16 vid;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	if (status & E1000_RXD_STAT_VP) {
9162306a36Sopenharmony_ci		if ((adapter->flags & IGBVF_FLAG_RX_LB_VLAN_BSWAP) &&
9262306a36Sopenharmony_ci		    (status & E1000_RXDEXT_STATERR_LB))
9362306a36Sopenharmony_ci			vid = be16_to_cpu((__force __be16)vlan) & E1000_RXD_SPC_VLAN_MASK;
9462306a36Sopenharmony_ci		else
9562306a36Sopenharmony_ci			vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
9662306a36Sopenharmony_ci		if (test_bit(vid, adapter->active_vlans))
9762306a36Sopenharmony_ci			__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid);
9862306a36Sopenharmony_ci	}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	napi_gro_receive(&adapter->rx_ring->napi, skb);
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
10462306a36Sopenharmony_ci					 u32 status_err, struct sk_buff *skb)
10562306a36Sopenharmony_ci{
10662306a36Sopenharmony_ci	skb_checksum_none_assert(skb);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	/* Ignore Checksum bit is set or checksum is disabled through ethtool */
10962306a36Sopenharmony_ci	if ((status_err & E1000_RXD_STAT_IXSM) ||
11062306a36Sopenharmony_ci	    (adapter->flags & IGBVF_FLAG_RX_CSUM_DISABLED))
11162306a36Sopenharmony_ci		return;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	/* TCP/UDP checksum error bit is set */
11462306a36Sopenharmony_ci	if (status_err &
11562306a36Sopenharmony_ci	    (E1000_RXDEXT_STATERR_TCPE | E1000_RXDEXT_STATERR_IPE)) {
11662306a36Sopenharmony_ci		/* let the stack verify checksum errors */
11762306a36Sopenharmony_ci		adapter->hw_csum_err++;
11862306a36Sopenharmony_ci		return;
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	/* It must be a TCP or UDP packet with a valid checksum */
12262306a36Sopenharmony_ci	if (status_err & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))
12362306a36Sopenharmony_ci		skb->ip_summed = CHECKSUM_UNNECESSARY;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	adapter->hw_csum_good++;
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci/**
12962306a36Sopenharmony_ci * igbvf_alloc_rx_buffers - Replace used receive buffers; packet split
13062306a36Sopenharmony_ci * @rx_ring: address of ring structure to repopulate
13162306a36Sopenharmony_ci * @cleaned_count: number of buffers to repopulate
13262306a36Sopenharmony_ci **/
13362306a36Sopenharmony_cistatic void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring,
13462306a36Sopenharmony_ci				   int cleaned_count)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	struct igbvf_adapter *adapter = rx_ring->adapter;
13762306a36Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
13862306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
13962306a36Sopenharmony_ci	union e1000_adv_rx_desc *rx_desc;
14062306a36Sopenharmony_ci	struct igbvf_buffer *buffer_info;
14162306a36Sopenharmony_ci	struct sk_buff *skb;
14262306a36Sopenharmony_ci	unsigned int i;
14362306a36Sopenharmony_ci	int bufsz;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	i = rx_ring->next_to_use;
14662306a36Sopenharmony_ci	buffer_info = &rx_ring->buffer_info[i];
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	if (adapter->rx_ps_hdr_size)
14962306a36Sopenharmony_ci		bufsz = adapter->rx_ps_hdr_size;
15062306a36Sopenharmony_ci	else
15162306a36Sopenharmony_ci		bufsz = adapter->rx_buffer_len;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	while (cleaned_count--) {
15462306a36Sopenharmony_ci		rx_desc = IGBVF_RX_DESC_ADV(*rx_ring, i);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci		if (adapter->rx_ps_hdr_size && !buffer_info->page_dma) {
15762306a36Sopenharmony_ci			if (!buffer_info->page) {
15862306a36Sopenharmony_ci				buffer_info->page = alloc_page(GFP_ATOMIC);
15962306a36Sopenharmony_ci				if (!buffer_info->page) {
16062306a36Sopenharmony_ci					adapter->alloc_rx_buff_failed++;
16162306a36Sopenharmony_ci					goto no_buffers;
16262306a36Sopenharmony_ci				}
16362306a36Sopenharmony_ci				buffer_info->page_offset = 0;
16462306a36Sopenharmony_ci			} else {
16562306a36Sopenharmony_ci				buffer_info->page_offset ^= PAGE_SIZE / 2;
16662306a36Sopenharmony_ci			}
16762306a36Sopenharmony_ci			buffer_info->page_dma =
16862306a36Sopenharmony_ci				dma_map_page(&pdev->dev, buffer_info->page,
16962306a36Sopenharmony_ci					     buffer_info->page_offset,
17062306a36Sopenharmony_ci					     PAGE_SIZE / 2,
17162306a36Sopenharmony_ci					     DMA_FROM_DEVICE);
17262306a36Sopenharmony_ci			if (dma_mapping_error(&pdev->dev,
17362306a36Sopenharmony_ci					      buffer_info->page_dma)) {
17462306a36Sopenharmony_ci				__free_page(buffer_info->page);
17562306a36Sopenharmony_ci				buffer_info->page = NULL;
17662306a36Sopenharmony_ci				dev_err(&pdev->dev, "RX DMA map failed\n");
17762306a36Sopenharmony_ci				break;
17862306a36Sopenharmony_ci			}
17962306a36Sopenharmony_ci		}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci		if (!buffer_info->skb) {
18262306a36Sopenharmony_ci			skb = netdev_alloc_skb_ip_align(netdev, bufsz);
18362306a36Sopenharmony_ci			if (!skb) {
18462306a36Sopenharmony_ci				adapter->alloc_rx_buff_failed++;
18562306a36Sopenharmony_ci				goto no_buffers;
18662306a36Sopenharmony_ci			}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci			buffer_info->skb = skb;
18962306a36Sopenharmony_ci			buffer_info->dma = dma_map_single(&pdev->dev, skb->data,
19062306a36Sopenharmony_ci							  bufsz,
19162306a36Sopenharmony_ci							  DMA_FROM_DEVICE);
19262306a36Sopenharmony_ci			if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
19362306a36Sopenharmony_ci				dev_kfree_skb(buffer_info->skb);
19462306a36Sopenharmony_ci				buffer_info->skb = NULL;
19562306a36Sopenharmony_ci				dev_err(&pdev->dev, "RX DMA map failed\n");
19662306a36Sopenharmony_ci				goto no_buffers;
19762306a36Sopenharmony_ci			}
19862306a36Sopenharmony_ci		}
19962306a36Sopenharmony_ci		/* Refresh the desc even if buffer_addrs didn't change because
20062306a36Sopenharmony_ci		 * each write-back erases this info.
20162306a36Sopenharmony_ci		 */
20262306a36Sopenharmony_ci		if (adapter->rx_ps_hdr_size) {
20362306a36Sopenharmony_ci			rx_desc->read.pkt_addr =
20462306a36Sopenharmony_ci			     cpu_to_le64(buffer_info->page_dma);
20562306a36Sopenharmony_ci			rx_desc->read.hdr_addr = cpu_to_le64(buffer_info->dma);
20662306a36Sopenharmony_ci		} else {
20762306a36Sopenharmony_ci			rx_desc->read.pkt_addr = cpu_to_le64(buffer_info->dma);
20862306a36Sopenharmony_ci			rx_desc->read.hdr_addr = 0;
20962306a36Sopenharmony_ci		}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci		i++;
21262306a36Sopenharmony_ci		if (i == rx_ring->count)
21362306a36Sopenharmony_ci			i = 0;
21462306a36Sopenharmony_ci		buffer_info = &rx_ring->buffer_info[i];
21562306a36Sopenharmony_ci	}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cino_buffers:
21862306a36Sopenharmony_ci	if (rx_ring->next_to_use != i) {
21962306a36Sopenharmony_ci		rx_ring->next_to_use = i;
22062306a36Sopenharmony_ci		if (i == 0)
22162306a36Sopenharmony_ci			i = (rx_ring->count - 1);
22262306a36Sopenharmony_ci		else
22362306a36Sopenharmony_ci			i--;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci		/* Force memory writes to complete before letting h/w
22662306a36Sopenharmony_ci		 * know there are new descriptors to fetch.  (Only
22762306a36Sopenharmony_ci		 * applicable for weak-ordered memory model archs,
22862306a36Sopenharmony_ci		 * such as IA-64).
22962306a36Sopenharmony_ci		*/
23062306a36Sopenharmony_ci		wmb();
23162306a36Sopenharmony_ci		writel(i, adapter->hw.hw_addr + rx_ring->tail);
23262306a36Sopenharmony_ci	}
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci/**
23662306a36Sopenharmony_ci * igbvf_clean_rx_irq - Send received data up the network stack; legacy
23762306a36Sopenharmony_ci * @adapter: board private structure
23862306a36Sopenharmony_ci * @work_done: output parameter used to indicate completed work
23962306a36Sopenharmony_ci * @work_to_do: input parameter setting limit of work
24062306a36Sopenharmony_ci *
24162306a36Sopenharmony_ci * the return value indicates whether actual cleaning was done, there
24262306a36Sopenharmony_ci * is no guarantee that everything was cleaned
24362306a36Sopenharmony_ci **/
24462306a36Sopenharmony_cistatic bool igbvf_clean_rx_irq(struct igbvf_adapter *adapter,
24562306a36Sopenharmony_ci			       int *work_done, int work_to_do)
24662306a36Sopenharmony_ci{
24762306a36Sopenharmony_ci	struct igbvf_ring *rx_ring = adapter->rx_ring;
24862306a36Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
24962306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
25062306a36Sopenharmony_ci	union e1000_adv_rx_desc *rx_desc, *next_rxd;
25162306a36Sopenharmony_ci	struct igbvf_buffer *buffer_info, *next_buffer;
25262306a36Sopenharmony_ci	struct sk_buff *skb;
25362306a36Sopenharmony_ci	bool cleaned = false;
25462306a36Sopenharmony_ci	int cleaned_count = 0;
25562306a36Sopenharmony_ci	unsigned int total_bytes = 0, total_packets = 0;
25662306a36Sopenharmony_ci	unsigned int i;
25762306a36Sopenharmony_ci	u32 length, hlen, staterr;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	i = rx_ring->next_to_clean;
26062306a36Sopenharmony_ci	rx_desc = IGBVF_RX_DESC_ADV(*rx_ring, i);
26162306a36Sopenharmony_ci	staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	while (staterr & E1000_RXD_STAT_DD) {
26462306a36Sopenharmony_ci		if (*work_done >= work_to_do)
26562306a36Sopenharmony_ci			break;
26662306a36Sopenharmony_ci		(*work_done)++;
26762306a36Sopenharmony_ci		rmb(); /* read descriptor and rx_buffer_info after status DD */
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci		buffer_info = &rx_ring->buffer_info[i];
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci		/* HW will not DMA in data larger than the given buffer, even
27262306a36Sopenharmony_ci		 * if it parses the (NFS, of course) header to be larger.  In
27362306a36Sopenharmony_ci		 * that case, it fills the header buffer and spills the rest
27462306a36Sopenharmony_ci		 * into the page.
27562306a36Sopenharmony_ci		 */
27662306a36Sopenharmony_ci		hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.hdr_info)
27762306a36Sopenharmony_ci		       & E1000_RXDADV_HDRBUFLEN_MASK) >>
27862306a36Sopenharmony_ci		       E1000_RXDADV_HDRBUFLEN_SHIFT;
27962306a36Sopenharmony_ci		if (hlen > adapter->rx_ps_hdr_size)
28062306a36Sopenharmony_ci			hlen = adapter->rx_ps_hdr_size;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci		length = le16_to_cpu(rx_desc->wb.upper.length);
28362306a36Sopenharmony_ci		cleaned = true;
28462306a36Sopenharmony_ci		cleaned_count++;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci		skb = buffer_info->skb;
28762306a36Sopenharmony_ci		prefetch(skb->data - NET_IP_ALIGN);
28862306a36Sopenharmony_ci		buffer_info->skb = NULL;
28962306a36Sopenharmony_ci		if (!adapter->rx_ps_hdr_size) {
29062306a36Sopenharmony_ci			dma_unmap_single(&pdev->dev, buffer_info->dma,
29162306a36Sopenharmony_ci					 adapter->rx_buffer_len,
29262306a36Sopenharmony_ci					 DMA_FROM_DEVICE);
29362306a36Sopenharmony_ci			buffer_info->dma = 0;
29462306a36Sopenharmony_ci			skb_put(skb, length);
29562306a36Sopenharmony_ci			goto send_up;
29662306a36Sopenharmony_ci		}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci		if (!skb_shinfo(skb)->nr_frags) {
29962306a36Sopenharmony_ci			dma_unmap_single(&pdev->dev, buffer_info->dma,
30062306a36Sopenharmony_ci					 adapter->rx_ps_hdr_size,
30162306a36Sopenharmony_ci					 DMA_FROM_DEVICE);
30262306a36Sopenharmony_ci			buffer_info->dma = 0;
30362306a36Sopenharmony_ci			skb_put(skb, hlen);
30462306a36Sopenharmony_ci		}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci		if (length) {
30762306a36Sopenharmony_ci			dma_unmap_page(&pdev->dev, buffer_info->page_dma,
30862306a36Sopenharmony_ci				       PAGE_SIZE / 2,
30962306a36Sopenharmony_ci				       DMA_FROM_DEVICE);
31062306a36Sopenharmony_ci			buffer_info->page_dma = 0;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci			skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
31362306a36Sopenharmony_ci					   buffer_info->page,
31462306a36Sopenharmony_ci					   buffer_info->page_offset,
31562306a36Sopenharmony_ci					   length);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci			if ((adapter->rx_buffer_len > (PAGE_SIZE / 2)) ||
31862306a36Sopenharmony_ci			    (page_count(buffer_info->page) != 1))
31962306a36Sopenharmony_ci				buffer_info->page = NULL;
32062306a36Sopenharmony_ci			else
32162306a36Sopenharmony_ci				get_page(buffer_info->page);
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci			skb->len += length;
32462306a36Sopenharmony_ci			skb->data_len += length;
32562306a36Sopenharmony_ci			skb->truesize += PAGE_SIZE / 2;
32662306a36Sopenharmony_ci		}
32762306a36Sopenharmony_cisend_up:
32862306a36Sopenharmony_ci		i++;
32962306a36Sopenharmony_ci		if (i == rx_ring->count)
33062306a36Sopenharmony_ci			i = 0;
33162306a36Sopenharmony_ci		next_rxd = IGBVF_RX_DESC_ADV(*rx_ring, i);
33262306a36Sopenharmony_ci		prefetch(next_rxd);
33362306a36Sopenharmony_ci		next_buffer = &rx_ring->buffer_info[i];
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci		if (!(staterr & E1000_RXD_STAT_EOP)) {
33662306a36Sopenharmony_ci			buffer_info->skb = next_buffer->skb;
33762306a36Sopenharmony_ci			buffer_info->dma = next_buffer->dma;
33862306a36Sopenharmony_ci			next_buffer->skb = skb;
33962306a36Sopenharmony_ci			next_buffer->dma = 0;
34062306a36Sopenharmony_ci			goto next_desc;
34162306a36Sopenharmony_ci		}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci		if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
34462306a36Sopenharmony_ci			dev_kfree_skb_irq(skb);
34562306a36Sopenharmony_ci			goto next_desc;
34662306a36Sopenharmony_ci		}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci		total_bytes += skb->len;
34962306a36Sopenharmony_ci		total_packets++;
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci		igbvf_rx_checksum_adv(adapter, staterr, skb);
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci		skb->protocol = eth_type_trans(skb, netdev);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci		igbvf_receive_skb(adapter, netdev, skb, staterr,
35662306a36Sopenharmony_ci				  rx_desc->wb.upper.vlan);
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_cinext_desc:
35962306a36Sopenharmony_ci		rx_desc->wb.upper.status_error = 0;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci		/* return some buffers to hardware, one at a time is too slow */
36262306a36Sopenharmony_ci		if (cleaned_count >= IGBVF_RX_BUFFER_WRITE) {
36362306a36Sopenharmony_ci			igbvf_alloc_rx_buffers(rx_ring, cleaned_count);
36462306a36Sopenharmony_ci			cleaned_count = 0;
36562306a36Sopenharmony_ci		}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci		/* use prefetched values */
36862306a36Sopenharmony_ci		rx_desc = next_rxd;
36962306a36Sopenharmony_ci		buffer_info = next_buffer;
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci		staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
37262306a36Sopenharmony_ci	}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	rx_ring->next_to_clean = i;
37562306a36Sopenharmony_ci	cleaned_count = igbvf_desc_unused(rx_ring);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	if (cleaned_count)
37862306a36Sopenharmony_ci		igbvf_alloc_rx_buffers(rx_ring, cleaned_count);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	adapter->total_rx_packets += total_packets;
38162306a36Sopenharmony_ci	adapter->total_rx_bytes += total_bytes;
38262306a36Sopenharmony_ci	netdev->stats.rx_bytes += total_bytes;
38362306a36Sopenharmony_ci	netdev->stats.rx_packets += total_packets;
38462306a36Sopenharmony_ci	return cleaned;
38562306a36Sopenharmony_ci}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_cistatic void igbvf_put_txbuf(struct igbvf_adapter *adapter,
38862306a36Sopenharmony_ci			    struct igbvf_buffer *buffer_info)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	if (buffer_info->dma) {
39162306a36Sopenharmony_ci		if (buffer_info->mapped_as_page)
39262306a36Sopenharmony_ci			dma_unmap_page(&adapter->pdev->dev,
39362306a36Sopenharmony_ci				       buffer_info->dma,
39462306a36Sopenharmony_ci				       buffer_info->length,
39562306a36Sopenharmony_ci				       DMA_TO_DEVICE);
39662306a36Sopenharmony_ci		else
39762306a36Sopenharmony_ci			dma_unmap_single(&adapter->pdev->dev,
39862306a36Sopenharmony_ci					 buffer_info->dma,
39962306a36Sopenharmony_ci					 buffer_info->length,
40062306a36Sopenharmony_ci					 DMA_TO_DEVICE);
40162306a36Sopenharmony_ci		buffer_info->dma = 0;
40262306a36Sopenharmony_ci	}
40362306a36Sopenharmony_ci	if (buffer_info->skb) {
40462306a36Sopenharmony_ci		dev_kfree_skb_any(buffer_info->skb);
40562306a36Sopenharmony_ci		buffer_info->skb = NULL;
40662306a36Sopenharmony_ci	}
40762306a36Sopenharmony_ci	buffer_info->time_stamp = 0;
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci/**
41162306a36Sopenharmony_ci * igbvf_setup_tx_resources - allocate Tx resources (Descriptors)
41262306a36Sopenharmony_ci * @adapter: board private structure
41362306a36Sopenharmony_ci * @tx_ring: ring being initialized
41462306a36Sopenharmony_ci *
41562306a36Sopenharmony_ci * Return 0 on success, negative on failure
41662306a36Sopenharmony_ci **/
41762306a36Sopenharmony_ciint igbvf_setup_tx_resources(struct igbvf_adapter *adapter,
41862306a36Sopenharmony_ci			     struct igbvf_ring *tx_ring)
41962306a36Sopenharmony_ci{
42062306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
42162306a36Sopenharmony_ci	int size;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	size = sizeof(struct igbvf_buffer) * tx_ring->count;
42462306a36Sopenharmony_ci	tx_ring->buffer_info = vzalloc(size);
42562306a36Sopenharmony_ci	if (!tx_ring->buffer_info)
42662306a36Sopenharmony_ci		goto err;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	/* round up to nearest 4K */
42962306a36Sopenharmony_ci	tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
43062306a36Sopenharmony_ci	tx_ring->size = ALIGN(tx_ring->size, 4096);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
43362306a36Sopenharmony_ci					   &tx_ring->dma, GFP_KERNEL);
43462306a36Sopenharmony_ci	if (!tx_ring->desc)
43562306a36Sopenharmony_ci		goto err;
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	tx_ring->adapter = adapter;
43862306a36Sopenharmony_ci	tx_ring->next_to_use = 0;
43962306a36Sopenharmony_ci	tx_ring->next_to_clean = 0;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	return 0;
44262306a36Sopenharmony_cierr:
44362306a36Sopenharmony_ci	vfree(tx_ring->buffer_info);
44462306a36Sopenharmony_ci	dev_err(&adapter->pdev->dev,
44562306a36Sopenharmony_ci		"Unable to allocate memory for the transmit descriptor ring\n");
44662306a36Sopenharmony_ci	return -ENOMEM;
44762306a36Sopenharmony_ci}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci/**
45062306a36Sopenharmony_ci * igbvf_setup_rx_resources - allocate Rx resources (Descriptors)
45162306a36Sopenharmony_ci * @adapter: board private structure
45262306a36Sopenharmony_ci * @rx_ring: ring being initialized
45362306a36Sopenharmony_ci *
45462306a36Sopenharmony_ci * Returns 0 on success, negative on failure
45562306a36Sopenharmony_ci **/
45662306a36Sopenharmony_ciint igbvf_setup_rx_resources(struct igbvf_adapter *adapter,
45762306a36Sopenharmony_ci			     struct igbvf_ring *rx_ring)
45862306a36Sopenharmony_ci{
45962306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
46062306a36Sopenharmony_ci	int size, desc_len;
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	size = sizeof(struct igbvf_buffer) * rx_ring->count;
46362306a36Sopenharmony_ci	rx_ring->buffer_info = vzalloc(size);
46462306a36Sopenharmony_ci	if (!rx_ring->buffer_info)
46562306a36Sopenharmony_ci		goto err;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	desc_len = sizeof(union e1000_adv_rx_desc);
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	/* Round up to nearest 4K */
47062306a36Sopenharmony_ci	rx_ring->size = rx_ring->count * desc_len;
47162306a36Sopenharmony_ci	rx_ring->size = ALIGN(rx_ring->size, 4096);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci	rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
47462306a36Sopenharmony_ci					   &rx_ring->dma, GFP_KERNEL);
47562306a36Sopenharmony_ci	if (!rx_ring->desc)
47662306a36Sopenharmony_ci		goto err;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	rx_ring->next_to_clean = 0;
47962306a36Sopenharmony_ci	rx_ring->next_to_use = 0;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	rx_ring->adapter = adapter;
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	return 0;
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cierr:
48662306a36Sopenharmony_ci	vfree(rx_ring->buffer_info);
48762306a36Sopenharmony_ci	rx_ring->buffer_info = NULL;
48862306a36Sopenharmony_ci	dev_err(&adapter->pdev->dev,
48962306a36Sopenharmony_ci		"Unable to allocate memory for the receive descriptor ring\n");
49062306a36Sopenharmony_ci	return -ENOMEM;
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci/**
49462306a36Sopenharmony_ci * igbvf_clean_tx_ring - Free Tx Buffers
49562306a36Sopenharmony_ci * @tx_ring: ring to be cleaned
49662306a36Sopenharmony_ci **/
49762306a36Sopenharmony_cistatic void igbvf_clean_tx_ring(struct igbvf_ring *tx_ring)
49862306a36Sopenharmony_ci{
49962306a36Sopenharmony_ci	struct igbvf_adapter *adapter = tx_ring->adapter;
50062306a36Sopenharmony_ci	struct igbvf_buffer *buffer_info;
50162306a36Sopenharmony_ci	unsigned long size;
50262306a36Sopenharmony_ci	unsigned int i;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	if (!tx_ring->buffer_info)
50562306a36Sopenharmony_ci		return;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	/* Free all the Tx ring sk_buffs */
50862306a36Sopenharmony_ci	for (i = 0; i < tx_ring->count; i++) {
50962306a36Sopenharmony_ci		buffer_info = &tx_ring->buffer_info[i];
51062306a36Sopenharmony_ci		igbvf_put_txbuf(adapter, buffer_info);
51162306a36Sopenharmony_ci	}
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	size = sizeof(struct igbvf_buffer) * tx_ring->count;
51462306a36Sopenharmony_ci	memset(tx_ring->buffer_info, 0, size);
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci	/* Zero out the descriptor ring */
51762306a36Sopenharmony_ci	memset(tx_ring->desc, 0, tx_ring->size);
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	tx_ring->next_to_use = 0;
52062306a36Sopenharmony_ci	tx_ring->next_to_clean = 0;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	writel(0, adapter->hw.hw_addr + tx_ring->head);
52362306a36Sopenharmony_ci	writel(0, adapter->hw.hw_addr + tx_ring->tail);
52462306a36Sopenharmony_ci}
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci/**
52762306a36Sopenharmony_ci * igbvf_free_tx_resources - Free Tx Resources per Queue
52862306a36Sopenharmony_ci * @tx_ring: ring to free resources from
52962306a36Sopenharmony_ci *
53062306a36Sopenharmony_ci * Free all transmit software resources
53162306a36Sopenharmony_ci **/
53262306a36Sopenharmony_civoid igbvf_free_tx_resources(struct igbvf_ring *tx_ring)
53362306a36Sopenharmony_ci{
53462306a36Sopenharmony_ci	struct pci_dev *pdev = tx_ring->adapter->pdev;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	igbvf_clean_tx_ring(tx_ring);
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	vfree(tx_ring->buffer_info);
53962306a36Sopenharmony_ci	tx_ring->buffer_info = NULL;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc,
54262306a36Sopenharmony_ci			  tx_ring->dma);
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	tx_ring->desc = NULL;
54562306a36Sopenharmony_ci}
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci/**
54862306a36Sopenharmony_ci * igbvf_clean_rx_ring - Free Rx Buffers per Queue
54962306a36Sopenharmony_ci * @rx_ring: ring structure pointer to free buffers from
55062306a36Sopenharmony_ci **/
55162306a36Sopenharmony_cistatic void igbvf_clean_rx_ring(struct igbvf_ring *rx_ring)
55262306a36Sopenharmony_ci{
55362306a36Sopenharmony_ci	struct igbvf_adapter *adapter = rx_ring->adapter;
55462306a36Sopenharmony_ci	struct igbvf_buffer *buffer_info;
55562306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
55662306a36Sopenharmony_ci	unsigned long size;
55762306a36Sopenharmony_ci	unsigned int i;
55862306a36Sopenharmony_ci
55962306a36Sopenharmony_ci	if (!rx_ring->buffer_info)
56062306a36Sopenharmony_ci		return;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	/* Free all the Rx ring sk_buffs */
56362306a36Sopenharmony_ci	for (i = 0; i < rx_ring->count; i++) {
56462306a36Sopenharmony_ci		buffer_info = &rx_ring->buffer_info[i];
56562306a36Sopenharmony_ci		if (buffer_info->dma) {
56662306a36Sopenharmony_ci			if (adapter->rx_ps_hdr_size) {
56762306a36Sopenharmony_ci				dma_unmap_single(&pdev->dev, buffer_info->dma,
56862306a36Sopenharmony_ci						 adapter->rx_ps_hdr_size,
56962306a36Sopenharmony_ci						 DMA_FROM_DEVICE);
57062306a36Sopenharmony_ci			} else {
57162306a36Sopenharmony_ci				dma_unmap_single(&pdev->dev, buffer_info->dma,
57262306a36Sopenharmony_ci						 adapter->rx_buffer_len,
57362306a36Sopenharmony_ci						 DMA_FROM_DEVICE);
57462306a36Sopenharmony_ci			}
57562306a36Sopenharmony_ci			buffer_info->dma = 0;
57662306a36Sopenharmony_ci		}
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci		if (buffer_info->skb) {
57962306a36Sopenharmony_ci			dev_kfree_skb(buffer_info->skb);
58062306a36Sopenharmony_ci			buffer_info->skb = NULL;
58162306a36Sopenharmony_ci		}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci		if (buffer_info->page) {
58462306a36Sopenharmony_ci			if (buffer_info->page_dma)
58562306a36Sopenharmony_ci				dma_unmap_page(&pdev->dev,
58662306a36Sopenharmony_ci					       buffer_info->page_dma,
58762306a36Sopenharmony_ci					       PAGE_SIZE / 2,
58862306a36Sopenharmony_ci					       DMA_FROM_DEVICE);
58962306a36Sopenharmony_ci			put_page(buffer_info->page);
59062306a36Sopenharmony_ci			buffer_info->page = NULL;
59162306a36Sopenharmony_ci			buffer_info->page_dma = 0;
59262306a36Sopenharmony_ci			buffer_info->page_offset = 0;
59362306a36Sopenharmony_ci		}
59462306a36Sopenharmony_ci	}
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	size = sizeof(struct igbvf_buffer) * rx_ring->count;
59762306a36Sopenharmony_ci	memset(rx_ring->buffer_info, 0, size);
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	/* Zero out the descriptor ring */
60062306a36Sopenharmony_ci	memset(rx_ring->desc, 0, rx_ring->size);
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci	rx_ring->next_to_clean = 0;
60362306a36Sopenharmony_ci	rx_ring->next_to_use = 0;
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	writel(0, adapter->hw.hw_addr + rx_ring->head);
60662306a36Sopenharmony_ci	writel(0, adapter->hw.hw_addr + rx_ring->tail);
60762306a36Sopenharmony_ci}
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci/**
61062306a36Sopenharmony_ci * igbvf_free_rx_resources - Free Rx Resources
61162306a36Sopenharmony_ci * @rx_ring: ring to clean the resources from
61262306a36Sopenharmony_ci *
61362306a36Sopenharmony_ci * Free all receive software resources
61462306a36Sopenharmony_ci **/
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_civoid igbvf_free_rx_resources(struct igbvf_ring *rx_ring)
61762306a36Sopenharmony_ci{
61862306a36Sopenharmony_ci	struct pci_dev *pdev = rx_ring->adapter->pdev;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	igbvf_clean_rx_ring(rx_ring);
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	vfree(rx_ring->buffer_info);
62362306a36Sopenharmony_ci	rx_ring->buffer_info = NULL;
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc,
62662306a36Sopenharmony_ci			  rx_ring->dma);
62762306a36Sopenharmony_ci	rx_ring->desc = NULL;
62862306a36Sopenharmony_ci}
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci/**
63162306a36Sopenharmony_ci * igbvf_update_itr - update the dynamic ITR value based on statistics
63262306a36Sopenharmony_ci * @adapter: pointer to adapter
63362306a36Sopenharmony_ci * @itr_setting: current adapter->itr
63462306a36Sopenharmony_ci * @packets: the number of packets during this measurement interval
63562306a36Sopenharmony_ci * @bytes: the number of bytes during this measurement interval
63662306a36Sopenharmony_ci *
63762306a36Sopenharmony_ci * Stores a new ITR value based on packets and byte counts during the last
63862306a36Sopenharmony_ci * interrupt.  The advantage of per interrupt computation is faster updates
63962306a36Sopenharmony_ci * and more accurate ITR for the current traffic pattern.  Constants in this
64062306a36Sopenharmony_ci * function were computed based on theoretical maximum wire speed and thresholds
64162306a36Sopenharmony_ci * were set based on testing data as well as attempting to minimize response
64262306a36Sopenharmony_ci * time while increasing bulk throughput.
64362306a36Sopenharmony_ci **/
64462306a36Sopenharmony_cistatic enum latency_range igbvf_update_itr(struct igbvf_adapter *adapter,
64562306a36Sopenharmony_ci					   enum latency_range itr_setting,
64662306a36Sopenharmony_ci					   int packets, int bytes)
64762306a36Sopenharmony_ci{
64862306a36Sopenharmony_ci	enum latency_range retval = itr_setting;
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	if (packets == 0)
65162306a36Sopenharmony_ci		goto update_itr_done;
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_ci	switch (itr_setting) {
65462306a36Sopenharmony_ci	case lowest_latency:
65562306a36Sopenharmony_ci		/* handle TSO and jumbo frames */
65662306a36Sopenharmony_ci		if (bytes/packets > 8000)
65762306a36Sopenharmony_ci			retval = bulk_latency;
65862306a36Sopenharmony_ci		else if ((packets < 5) && (bytes > 512))
65962306a36Sopenharmony_ci			retval = low_latency;
66062306a36Sopenharmony_ci		break;
66162306a36Sopenharmony_ci	case low_latency:  /* 50 usec aka 20000 ints/s */
66262306a36Sopenharmony_ci		if (bytes > 10000) {
66362306a36Sopenharmony_ci			/* this if handles the TSO accounting */
66462306a36Sopenharmony_ci			if (bytes/packets > 8000)
66562306a36Sopenharmony_ci				retval = bulk_latency;
66662306a36Sopenharmony_ci			else if ((packets < 10) || ((bytes/packets) > 1200))
66762306a36Sopenharmony_ci				retval = bulk_latency;
66862306a36Sopenharmony_ci			else if ((packets > 35))
66962306a36Sopenharmony_ci				retval = lowest_latency;
67062306a36Sopenharmony_ci		} else if (bytes/packets > 2000) {
67162306a36Sopenharmony_ci			retval = bulk_latency;
67262306a36Sopenharmony_ci		} else if (packets <= 2 && bytes < 512) {
67362306a36Sopenharmony_ci			retval = lowest_latency;
67462306a36Sopenharmony_ci		}
67562306a36Sopenharmony_ci		break;
67662306a36Sopenharmony_ci	case bulk_latency: /* 250 usec aka 4000 ints/s */
67762306a36Sopenharmony_ci		if (bytes > 25000) {
67862306a36Sopenharmony_ci			if (packets > 35)
67962306a36Sopenharmony_ci				retval = low_latency;
68062306a36Sopenharmony_ci		} else if (bytes < 6000) {
68162306a36Sopenharmony_ci			retval = low_latency;
68262306a36Sopenharmony_ci		}
68362306a36Sopenharmony_ci		break;
68462306a36Sopenharmony_ci	default:
68562306a36Sopenharmony_ci		break;
68662306a36Sopenharmony_ci	}
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ciupdate_itr_done:
68962306a36Sopenharmony_ci	return retval;
69062306a36Sopenharmony_ci}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_cistatic int igbvf_range_to_itr(enum latency_range current_range)
69362306a36Sopenharmony_ci{
69462306a36Sopenharmony_ci	int new_itr;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	switch (current_range) {
69762306a36Sopenharmony_ci	/* counts and packets in update_itr are dependent on these numbers */
69862306a36Sopenharmony_ci	case lowest_latency:
69962306a36Sopenharmony_ci		new_itr = IGBVF_70K_ITR;
70062306a36Sopenharmony_ci		break;
70162306a36Sopenharmony_ci	case low_latency:
70262306a36Sopenharmony_ci		new_itr = IGBVF_20K_ITR;
70362306a36Sopenharmony_ci		break;
70462306a36Sopenharmony_ci	case bulk_latency:
70562306a36Sopenharmony_ci		new_itr = IGBVF_4K_ITR;
70662306a36Sopenharmony_ci		break;
70762306a36Sopenharmony_ci	default:
70862306a36Sopenharmony_ci		new_itr = IGBVF_START_ITR;
70962306a36Sopenharmony_ci		break;
71062306a36Sopenharmony_ci	}
71162306a36Sopenharmony_ci	return new_itr;
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_cistatic void igbvf_set_itr(struct igbvf_adapter *adapter)
71562306a36Sopenharmony_ci{
71662306a36Sopenharmony_ci	u32 new_itr;
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	adapter->tx_ring->itr_range =
71962306a36Sopenharmony_ci			igbvf_update_itr(adapter,
72062306a36Sopenharmony_ci					 adapter->tx_ring->itr_val,
72162306a36Sopenharmony_ci					 adapter->total_tx_packets,
72262306a36Sopenharmony_ci					 adapter->total_tx_bytes);
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	/* conservative mode (itr 3) eliminates the lowest_latency setting */
72562306a36Sopenharmony_ci	if (adapter->requested_itr == 3 &&
72662306a36Sopenharmony_ci	    adapter->tx_ring->itr_range == lowest_latency)
72762306a36Sopenharmony_ci		adapter->tx_ring->itr_range = low_latency;
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	new_itr = igbvf_range_to_itr(adapter->tx_ring->itr_range);
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	if (new_itr != adapter->tx_ring->itr_val) {
73262306a36Sopenharmony_ci		u32 current_itr = adapter->tx_ring->itr_val;
73362306a36Sopenharmony_ci		/* this attempts to bias the interrupt rate towards Bulk
73462306a36Sopenharmony_ci		 * by adding intermediate steps when interrupt rate is
73562306a36Sopenharmony_ci		 * increasing
73662306a36Sopenharmony_ci		 */
73762306a36Sopenharmony_ci		new_itr = new_itr > current_itr ?
73862306a36Sopenharmony_ci			  min(current_itr + (new_itr >> 2), new_itr) :
73962306a36Sopenharmony_ci			  new_itr;
74062306a36Sopenharmony_ci		adapter->tx_ring->itr_val = new_itr;
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci		adapter->tx_ring->set_itr = 1;
74362306a36Sopenharmony_ci	}
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	adapter->rx_ring->itr_range =
74662306a36Sopenharmony_ci			igbvf_update_itr(adapter, adapter->rx_ring->itr_val,
74762306a36Sopenharmony_ci					 adapter->total_rx_packets,
74862306a36Sopenharmony_ci					 adapter->total_rx_bytes);
74962306a36Sopenharmony_ci	if (adapter->requested_itr == 3 &&
75062306a36Sopenharmony_ci	    adapter->rx_ring->itr_range == lowest_latency)
75162306a36Sopenharmony_ci		adapter->rx_ring->itr_range = low_latency;
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	new_itr = igbvf_range_to_itr(adapter->rx_ring->itr_range);
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci	if (new_itr != adapter->rx_ring->itr_val) {
75662306a36Sopenharmony_ci		u32 current_itr = adapter->rx_ring->itr_val;
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci		new_itr = new_itr > current_itr ?
75962306a36Sopenharmony_ci			  min(current_itr + (new_itr >> 2), new_itr) :
76062306a36Sopenharmony_ci			  new_itr;
76162306a36Sopenharmony_ci		adapter->rx_ring->itr_val = new_itr;
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci		adapter->rx_ring->set_itr = 1;
76462306a36Sopenharmony_ci	}
76562306a36Sopenharmony_ci}
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci/**
76862306a36Sopenharmony_ci * igbvf_clean_tx_irq - Reclaim resources after transmit completes
76962306a36Sopenharmony_ci * @tx_ring: ring structure to clean descriptors from
77062306a36Sopenharmony_ci *
77162306a36Sopenharmony_ci * returns true if ring is completely cleaned
77262306a36Sopenharmony_ci **/
77362306a36Sopenharmony_cistatic bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring)
77462306a36Sopenharmony_ci{
77562306a36Sopenharmony_ci	struct igbvf_adapter *adapter = tx_ring->adapter;
77662306a36Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
77762306a36Sopenharmony_ci	struct igbvf_buffer *buffer_info;
77862306a36Sopenharmony_ci	struct sk_buff *skb;
77962306a36Sopenharmony_ci	union e1000_adv_tx_desc *tx_desc, *eop_desc;
78062306a36Sopenharmony_ci	unsigned int total_bytes = 0, total_packets = 0;
78162306a36Sopenharmony_ci	unsigned int i, count = 0;
78262306a36Sopenharmony_ci	bool cleaned = false;
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_ci	i = tx_ring->next_to_clean;
78562306a36Sopenharmony_ci	buffer_info = &tx_ring->buffer_info[i];
78662306a36Sopenharmony_ci	eop_desc = buffer_info->next_to_watch;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	do {
78962306a36Sopenharmony_ci		/* if next_to_watch is not set then there is no work pending */
79062306a36Sopenharmony_ci		if (!eop_desc)
79162306a36Sopenharmony_ci			break;
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci		/* prevent any other reads prior to eop_desc */
79462306a36Sopenharmony_ci		smp_rmb();
79562306a36Sopenharmony_ci
79662306a36Sopenharmony_ci		/* if DD is not set pending work has not been completed */
79762306a36Sopenharmony_ci		if (!(eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD)))
79862306a36Sopenharmony_ci			break;
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci		/* clear next_to_watch to prevent false hangs */
80162306a36Sopenharmony_ci		buffer_info->next_to_watch = NULL;
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci		for (cleaned = false; !cleaned; count++) {
80462306a36Sopenharmony_ci			tx_desc = IGBVF_TX_DESC_ADV(*tx_ring, i);
80562306a36Sopenharmony_ci			cleaned = (tx_desc == eop_desc);
80662306a36Sopenharmony_ci			skb = buffer_info->skb;
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci			if (skb) {
80962306a36Sopenharmony_ci				unsigned int segs, bytecount;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci				/* gso_segs is currently only valid for tcp */
81262306a36Sopenharmony_ci				segs = skb_shinfo(skb)->gso_segs ?: 1;
81362306a36Sopenharmony_ci				/* multiply data chunks by size of headers */
81462306a36Sopenharmony_ci				bytecount = ((segs - 1) * skb_headlen(skb)) +
81562306a36Sopenharmony_ci					    skb->len;
81662306a36Sopenharmony_ci				total_packets += segs;
81762306a36Sopenharmony_ci				total_bytes += bytecount;
81862306a36Sopenharmony_ci			}
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci			igbvf_put_txbuf(adapter, buffer_info);
82162306a36Sopenharmony_ci			tx_desc->wb.status = 0;
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci			i++;
82462306a36Sopenharmony_ci			if (i == tx_ring->count)
82562306a36Sopenharmony_ci				i = 0;
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci			buffer_info = &tx_ring->buffer_info[i];
82862306a36Sopenharmony_ci		}
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci		eop_desc = buffer_info->next_to_watch;
83162306a36Sopenharmony_ci	} while (count < tx_ring->count);
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci	tx_ring->next_to_clean = i;
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci	if (unlikely(count && netif_carrier_ok(netdev) &&
83662306a36Sopenharmony_ci	    igbvf_desc_unused(tx_ring) >= IGBVF_TX_QUEUE_WAKE)) {
83762306a36Sopenharmony_ci		/* Make sure that anybody stopping the queue after this
83862306a36Sopenharmony_ci		 * sees the new next_to_clean.
83962306a36Sopenharmony_ci		 */
84062306a36Sopenharmony_ci		smp_mb();
84162306a36Sopenharmony_ci		if (netif_queue_stopped(netdev) &&
84262306a36Sopenharmony_ci		    !(test_bit(__IGBVF_DOWN, &adapter->state))) {
84362306a36Sopenharmony_ci			netif_wake_queue(netdev);
84462306a36Sopenharmony_ci			++adapter->restart_queue;
84562306a36Sopenharmony_ci		}
84662306a36Sopenharmony_ci	}
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	netdev->stats.tx_bytes += total_bytes;
84962306a36Sopenharmony_ci	netdev->stats.tx_packets += total_packets;
85062306a36Sopenharmony_ci	return count < tx_ring->count;
85162306a36Sopenharmony_ci}
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_cistatic irqreturn_t igbvf_msix_other(int irq, void *data)
85462306a36Sopenharmony_ci{
85562306a36Sopenharmony_ci	struct net_device *netdev = data;
85662306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
85762306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
85862306a36Sopenharmony_ci
85962306a36Sopenharmony_ci	adapter->int_counter1++;
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	hw->mac.get_link_status = 1;
86262306a36Sopenharmony_ci	if (!test_bit(__IGBVF_DOWN, &adapter->state))
86362306a36Sopenharmony_ci		mod_timer(&adapter->watchdog_timer, jiffies + 1);
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_ci	ew32(EIMS, adapter->eims_other);
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	return IRQ_HANDLED;
86862306a36Sopenharmony_ci}
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_cistatic irqreturn_t igbvf_intr_msix_tx(int irq, void *data)
87162306a36Sopenharmony_ci{
87262306a36Sopenharmony_ci	struct net_device *netdev = data;
87362306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
87462306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
87562306a36Sopenharmony_ci	struct igbvf_ring *tx_ring = adapter->tx_ring;
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	if (tx_ring->set_itr) {
87862306a36Sopenharmony_ci		writel(tx_ring->itr_val,
87962306a36Sopenharmony_ci		       adapter->hw.hw_addr + tx_ring->itr_register);
88062306a36Sopenharmony_ci		adapter->tx_ring->set_itr = 0;
88162306a36Sopenharmony_ci	}
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	adapter->total_tx_bytes = 0;
88462306a36Sopenharmony_ci	adapter->total_tx_packets = 0;
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	/* auto mask will automatically re-enable the interrupt when we write
88762306a36Sopenharmony_ci	 * EICS
88862306a36Sopenharmony_ci	 */
88962306a36Sopenharmony_ci	if (!igbvf_clean_tx_irq(tx_ring))
89062306a36Sopenharmony_ci		/* Ring was not completely cleaned, so fire another interrupt */
89162306a36Sopenharmony_ci		ew32(EICS, tx_ring->eims_value);
89262306a36Sopenharmony_ci	else
89362306a36Sopenharmony_ci		ew32(EIMS, tx_ring->eims_value);
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	return IRQ_HANDLED;
89662306a36Sopenharmony_ci}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_cistatic irqreturn_t igbvf_intr_msix_rx(int irq, void *data)
89962306a36Sopenharmony_ci{
90062306a36Sopenharmony_ci	struct net_device *netdev = data;
90162306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci	adapter->int_counter0++;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	/* Write the ITR value calculated at the end of the
90662306a36Sopenharmony_ci	 * previous interrupt.
90762306a36Sopenharmony_ci	 */
90862306a36Sopenharmony_ci	if (adapter->rx_ring->set_itr) {
90962306a36Sopenharmony_ci		writel(adapter->rx_ring->itr_val,
91062306a36Sopenharmony_ci		       adapter->hw.hw_addr + adapter->rx_ring->itr_register);
91162306a36Sopenharmony_ci		adapter->rx_ring->set_itr = 0;
91262306a36Sopenharmony_ci	}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	if (napi_schedule_prep(&adapter->rx_ring->napi)) {
91562306a36Sopenharmony_ci		adapter->total_rx_bytes = 0;
91662306a36Sopenharmony_ci		adapter->total_rx_packets = 0;
91762306a36Sopenharmony_ci		__napi_schedule(&adapter->rx_ring->napi);
91862306a36Sopenharmony_ci	}
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	return IRQ_HANDLED;
92162306a36Sopenharmony_ci}
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci#define IGBVF_NO_QUEUE -1
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_cistatic void igbvf_assign_vector(struct igbvf_adapter *adapter, int rx_queue,
92662306a36Sopenharmony_ci				int tx_queue, int msix_vector)
92762306a36Sopenharmony_ci{
92862306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
92962306a36Sopenharmony_ci	u32 ivar, index;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci	/* 82576 uses a table-based method for assigning vectors.
93262306a36Sopenharmony_ci	 * Each queue has a single entry in the table to which we write
93362306a36Sopenharmony_ci	 * a vector number along with a "valid" bit.  Sadly, the layout
93462306a36Sopenharmony_ci	 * of the table is somewhat counterintuitive.
93562306a36Sopenharmony_ci	 */
93662306a36Sopenharmony_ci	if (rx_queue > IGBVF_NO_QUEUE) {
93762306a36Sopenharmony_ci		index = (rx_queue >> 1);
93862306a36Sopenharmony_ci		ivar = array_er32(IVAR0, index);
93962306a36Sopenharmony_ci		if (rx_queue & 0x1) {
94062306a36Sopenharmony_ci			/* vector goes into third byte of register */
94162306a36Sopenharmony_ci			ivar = ivar & 0xFF00FFFF;
94262306a36Sopenharmony_ci			ivar |= (msix_vector | E1000_IVAR_VALID) << 16;
94362306a36Sopenharmony_ci		} else {
94462306a36Sopenharmony_ci			/* vector goes into low byte of register */
94562306a36Sopenharmony_ci			ivar = ivar & 0xFFFFFF00;
94662306a36Sopenharmony_ci			ivar |= msix_vector | E1000_IVAR_VALID;
94762306a36Sopenharmony_ci		}
94862306a36Sopenharmony_ci		adapter->rx_ring[rx_queue].eims_value = BIT(msix_vector);
94962306a36Sopenharmony_ci		array_ew32(IVAR0, index, ivar);
95062306a36Sopenharmony_ci	}
95162306a36Sopenharmony_ci	if (tx_queue > IGBVF_NO_QUEUE) {
95262306a36Sopenharmony_ci		index = (tx_queue >> 1);
95362306a36Sopenharmony_ci		ivar = array_er32(IVAR0, index);
95462306a36Sopenharmony_ci		if (tx_queue & 0x1) {
95562306a36Sopenharmony_ci			/* vector goes into high byte of register */
95662306a36Sopenharmony_ci			ivar = ivar & 0x00FFFFFF;
95762306a36Sopenharmony_ci			ivar |= (msix_vector | E1000_IVAR_VALID) << 24;
95862306a36Sopenharmony_ci		} else {
95962306a36Sopenharmony_ci			/* vector goes into second byte of register */
96062306a36Sopenharmony_ci			ivar = ivar & 0xFFFF00FF;
96162306a36Sopenharmony_ci			ivar |= (msix_vector | E1000_IVAR_VALID) << 8;
96262306a36Sopenharmony_ci		}
96362306a36Sopenharmony_ci		adapter->tx_ring[tx_queue].eims_value = BIT(msix_vector);
96462306a36Sopenharmony_ci		array_ew32(IVAR0, index, ivar);
96562306a36Sopenharmony_ci	}
96662306a36Sopenharmony_ci}
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci/**
96962306a36Sopenharmony_ci * igbvf_configure_msix - Configure MSI-X hardware
97062306a36Sopenharmony_ci * @adapter: board private structure
97162306a36Sopenharmony_ci *
97262306a36Sopenharmony_ci * igbvf_configure_msix sets up the hardware to properly
97362306a36Sopenharmony_ci * generate MSI-X interrupts.
97462306a36Sopenharmony_ci **/
97562306a36Sopenharmony_cistatic void igbvf_configure_msix(struct igbvf_adapter *adapter)
97662306a36Sopenharmony_ci{
97762306a36Sopenharmony_ci	u32 tmp;
97862306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
97962306a36Sopenharmony_ci	struct igbvf_ring *tx_ring = adapter->tx_ring;
98062306a36Sopenharmony_ci	struct igbvf_ring *rx_ring = adapter->rx_ring;
98162306a36Sopenharmony_ci	int vector = 0;
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci	adapter->eims_enable_mask = 0;
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci	igbvf_assign_vector(adapter, IGBVF_NO_QUEUE, 0, vector++);
98662306a36Sopenharmony_ci	adapter->eims_enable_mask |= tx_ring->eims_value;
98762306a36Sopenharmony_ci	writel(tx_ring->itr_val, hw->hw_addr + tx_ring->itr_register);
98862306a36Sopenharmony_ci	igbvf_assign_vector(adapter, 0, IGBVF_NO_QUEUE, vector++);
98962306a36Sopenharmony_ci	adapter->eims_enable_mask |= rx_ring->eims_value;
99062306a36Sopenharmony_ci	writel(rx_ring->itr_val, hw->hw_addr + rx_ring->itr_register);
99162306a36Sopenharmony_ci
99262306a36Sopenharmony_ci	/* set vector for other causes, i.e. link changes */
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	tmp = (vector++ | E1000_IVAR_VALID);
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	ew32(IVAR_MISC, tmp);
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	adapter->eims_enable_mask = GENMASK(vector - 1, 0);
99962306a36Sopenharmony_ci	adapter->eims_other = BIT(vector - 1);
100062306a36Sopenharmony_ci	e1e_flush();
100162306a36Sopenharmony_ci}
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_cistatic void igbvf_reset_interrupt_capability(struct igbvf_adapter *adapter)
100462306a36Sopenharmony_ci{
100562306a36Sopenharmony_ci	if (adapter->msix_entries) {
100662306a36Sopenharmony_ci		pci_disable_msix(adapter->pdev);
100762306a36Sopenharmony_ci		kfree(adapter->msix_entries);
100862306a36Sopenharmony_ci		adapter->msix_entries = NULL;
100962306a36Sopenharmony_ci	}
101062306a36Sopenharmony_ci}
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci/**
101362306a36Sopenharmony_ci * igbvf_set_interrupt_capability - set MSI or MSI-X if supported
101462306a36Sopenharmony_ci * @adapter: board private structure
101562306a36Sopenharmony_ci *
101662306a36Sopenharmony_ci * Attempt to configure interrupts using the best available
101762306a36Sopenharmony_ci * capabilities of the hardware and kernel.
101862306a36Sopenharmony_ci **/
101962306a36Sopenharmony_cistatic void igbvf_set_interrupt_capability(struct igbvf_adapter *adapter)
102062306a36Sopenharmony_ci{
102162306a36Sopenharmony_ci	int err = -ENOMEM;
102262306a36Sopenharmony_ci	int i;
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci	/* we allocate 3 vectors, 1 for Tx, 1 for Rx, one for PF messages */
102562306a36Sopenharmony_ci	adapter->msix_entries = kcalloc(3, sizeof(struct msix_entry),
102662306a36Sopenharmony_ci					GFP_KERNEL);
102762306a36Sopenharmony_ci	if (adapter->msix_entries) {
102862306a36Sopenharmony_ci		for (i = 0; i < 3; i++)
102962306a36Sopenharmony_ci			adapter->msix_entries[i].entry = i;
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci		err = pci_enable_msix_range(adapter->pdev,
103262306a36Sopenharmony_ci					    adapter->msix_entries, 3, 3);
103362306a36Sopenharmony_ci	}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	if (err < 0) {
103662306a36Sopenharmony_ci		/* MSI-X failed */
103762306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev,
103862306a36Sopenharmony_ci			"Failed to initialize MSI-X interrupts.\n");
103962306a36Sopenharmony_ci		igbvf_reset_interrupt_capability(adapter);
104062306a36Sopenharmony_ci	}
104162306a36Sopenharmony_ci}
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci/**
104462306a36Sopenharmony_ci * igbvf_request_msix - Initialize MSI-X interrupts
104562306a36Sopenharmony_ci * @adapter: board private structure
104662306a36Sopenharmony_ci *
104762306a36Sopenharmony_ci * igbvf_request_msix allocates MSI-X vectors and requests interrupts from the
104862306a36Sopenharmony_ci * kernel.
104962306a36Sopenharmony_ci **/
105062306a36Sopenharmony_cistatic int igbvf_request_msix(struct igbvf_adapter *adapter)
105162306a36Sopenharmony_ci{
105262306a36Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
105362306a36Sopenharmony_ci	int err = 0, vector = 0;
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci	if (strlen(netdev->name) < (IFNAMSIZ - 5)) {
105662306a36Sopenharmony_ci		sprintf(adapter->tx_ring->name, "%s-tx-0", netdev->name);
105762306a36Sopenharmony_ci		sprintf(adapter->rx_ring->name, "%s-rx-0", netdev->name);
105862306a36Sopenharmony_ci	} else {
105962306a36Sopenharmony_ci		memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ);
106062306a36Sopenharmony_ci		memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ);
106162306a36Sopenharmony_ci	}
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	err = request_irq(adapter->msix_entries[vector].vector,
106462306a36Sopenharmony_ci			  igbvf_intr_msix_tx, 0, adapter->tx_ring->name,
106562306a36Sopenharmony_ci			  netdev);
106662306a36Sopenharmony_ci	if (err)
106762306a36Sopenharmony_ci		goto out;
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	adapter->tx_ring->itr_register = E1000_EITR(vector);
107062306a36Sopenharmony_ci	adapter->tx_ring->itr_val = adapter->current_itr;
107162306a36Sopenharmony_ci	vector++;
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	err = request_irq(adapter->msix_entries[vector].vector,
107462306a36Sopenharmony_ci			  igbvf_intr_msix_rx, 0, adapter->rx_ring->name,
107562306a36Sopenharmony_ci			  netdev);
107662306a36Sopenharmony_ci	if (err)
107762306a36Sopenharmony_ci		goto free_irq_tx;
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	adapter->rx_ring->itr_register = E1000_EITR(vector);
108062306a36Sopenharmony_ci	adapter->rx_ring->itr_val = adapter->current_itr;
108162306a36Sopenharmony_ci	vector++;
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	err = request_irq(adapter->msix_entries[vector].vector,
108462306a36Sopenharmony_ci			  igbvf_msix_other, 0, netdev->name, netdev);
108562306a36Sopenharmony_ci	if (err)
108662306a36Sopenharmony_ci		goto free_irq_rx;
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	igbvf_configure_msix(adapter);
108962306a36Sopenharmony_ci	return 0;
109062306a36Sopenharmony_cifree_irq_rx:
109162306a36Sopenharmony_ci	free_irq(adapter->msix_entries[--vector].vector, netdev);
109262306a36Sopenharmony_cifree_irq_tx:
109362306a36Sopenharmony_ci	free_irq(adapter->msix_entries[--vector].vector, netdev);
109462306a36Sopenharmony_ciout:
109562306a36Sopenharmony_ci	return err;
109662306a36Sopenharmony_ci}
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_ci/**
109962306a36Sopenharmony_ci * igbvf_alloc_queues - Allocate memory for all rings
110062306a36Sopenharmony_ci * @adapter: board private structure to initialize
110162306a36Sopenharmony_ci **/
110262306a36Sopenharmony_cistatic int igbvf_alloc_queues(struct igbvf_adapter *adapter)
110362306a36Sopenharmony_ci{
110462306a36Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ci	adapter->tx_ring = kzalloc(sizeof(struct igbvf_ring), GFP_KERNEL);
110762306a36Sopenharmony_ci	if (!adapter->tx_ring)
110862306a36Sopenharmony_ci		return -ENOMEM;
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_ci	adapter->rx_ring = kzalloc(sizeof(struct igbvf_ring), GFP_KERNEL);
111162306a36Sopenharmony_ci	if (!adapter->rx_ring) {
111262306a36Sopenharmony_ci		kfree(adapter->tx_ring);
111362306a36Sopenharmony_ci		return -ENOMEM;
111462306a36Sopenharmony_ci	}
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ci	netif_napi_add(netdev, &adapter->rx_ring->napi, igbvf_poll);
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci	return 0;
111962306a36Sopenharmony_ci}
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci/**
112262306a36Sopenharmony_ci * igbvf_request_irq - initialize interrupts
112362306a36Sopenharmony_ci * @adapter: board private structure
112462306a36Sopenharmony_ci *
112562306a36Sopenharmony_ci * Attempts to configure interrupts using the best available
112662306a36Sopenharmony_ci * capabilities of the hardware and kernel.
112762306a36Sopenharmony_ci **/
112862306a36Sopenharmony_cistatic int igbvf_request_irq(struct igbvf_adapter *adapter)
112962306a36Sopenharmony_ci{
113062306a36Sopenharmony_ci	int err = -1;
113162306a36Sopenharmony_ci
113262306a36Sopenharmony_ci	/* igbvf supports msi-x only */
113362306a36Sopenharmony_ci	if (adapter->msix_entries)
113462306a36Sopenharmony_ci		err = igbvf_request_msix(adapter);
113562306a36Sopenharmony_ci
113662306a36Sopenharmony_ci	if (!err)
113762306a36Sopenharmony_ci		return err;
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	dev_err(&adapter->pdev->dev,
114062306a36Sopenharmony_ci		"Unable to allocate interrupt, Error: %d\n", err);
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_ci	return err;
114362306a36Sopenharmony_ci}
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_cistatic void igbvf_free_irq(struct igbvf_adapter *adapter)
114662306a36Sopenharmony_ci{
114762306a36Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
114862306a36Sopenharmony_ci	int vector;
114962306a36Sopenharmony_ci
115062306a36Sopenharmony_ci	if (adapter->msix_entries) {
115162306a36Sopenharmony_ci		for (vector = 0; vector < 3; vector++)
115262306a36Sopenharmony_ci			free_irq(adapter->msix_entries[vector].vector, netdev);
115362306a36Sopenharmony_ci	}
115462306a36Sopenharmony_ci}
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci/**
115762306a36Sopenharmony_ci * igbvf_irq_disable - Mask off interrupt generation on the NIC
115862306a36Sopenharmony_ci * @adapter: board private structure
115962306a36Sopenharmony_ci **/
116062306a36Sopenharmony_cistatic void igbvf_irq_disable(struct igbvf_adapter *adapter)
116162306a36Sopenharmony_ci{
116262306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	ew32(EIMC, ~0);
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	if (adapter->msix_entries)
116762306a36Sopenharmony_ci		ew32(EIAC, 0);
116862306a36Sopenharmony_ci}
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci/**
117162306a36Sopenharmony_ci * igbvf_irq_enable - Enable default interrupt generation settings
117262306a36Sopenharmony_ci * @adapter: board private structure
117362306a36Sopenharmony_ci **/
117462306a36Sopenharmony_cistatic void igbvf_irq_enable(struct igbvf_adapter *adapter)
117562306a36Sopenharmony_ci{
117662306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
117762306a36Sopenharmony_ci
117862306a36Sopenharmony_ci	ew32(EIAC, adapter->eims_enable_mask);
117962306a36Sopenharmony_ci	ew32(EIAM, adapter->eims_enable_mask);
118062306a36Sopenharmony_ci	ew32(EIMS, adapter->eims_enable_mask);
118162306a36Sopenharmony_ci}
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_ci/**
118462306a36Sopenharmony_ci * igbvf_poll - NAPI Rx polling callback
118562306a36Sopenharmony_ci * @napi: struct associated with this polling callback
118662306a36Sopenharmony_ci * @budget: amount of packets driver is allowed to process this poll
118762306a36Sopenharmony_ci **/
118862306a36Sopenharmony_cistatic int igbvf_poll(struct napi_struct *napi, int budget)
118962306a36Sopenharmony_ci{
119062306a36Sopenharmony_ci	struct igbvf_ring *rx_ring = container_of(napi, struct igbvf_ring, napi);
119162306a36Sopenharmony_ci	struct igbvf_adapter *adapter = rx_ring->adapter;
119262306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
119362306a36Sopenharmony_ci	int work_done = 0;
119462306a36Sopenharmony_ci
119562306a36Sopenharmony_ci	igbvf_clean_rx_irq(adapter, &work_done, budget);
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci	if (work_done == budget)
119862306a36Sopenharmony_ci		return budget;
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci	/* Exit the polling mode, but don't re-enable interrupts if stack might
120162306a36Sopenharmony_ci	 * poll us due to busy-polling
120262306a36Sopenharmony_ci	 */
120362306a36Sopenharmony_ci	if (likely(napi_complete_done(napi, work_done))) {
120462306a36Sopenharmony_ci		if (adapter->requested_itr & 3)
120562306a36Sopenharmony_ci			igbvf_set_itr(adapter);
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_ci		if (!test_bit(__IGBVF_DOWN, &adapter->state))
120862306a36Sopenharmony_ci			ew32(EIMS, adapter->rx_ring->eims_value);
120962306a36Sopenharmony_ci	}
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_ci	return work_done;
121262306a36Sopenharmony_ci}
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci/**
121562306a36Sopenharmony_ci * igbvf_set_rlpml - set receive large packet maximum length
121662306a36Sopenharmony_ci * @adapter: board private structure
121762306a36Sopenharmony_ci *
121862306a36Sopenharmony_ci * Configure the maximum size of packets that will be received
121962306a36Sopenharmony_ci */
122062306a36Sopenharmony_cistatic void igbvf_set_rlpml(struct igbvf_adapter *adapter)
122162306a36Sopenharmony_ci{
122262306a36Sopenharmony_ci	int max_frame_size;
122362306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
122462306a36Sopenharmony_ci
122562306a36Sopenharmony_ci	max_frame_size = adapter->max_frame_size + VLAN_TAG_SIZE;
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	spin_lock_bh(&hw->mbx_lock);
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_ci	e1000_rlpml_set_vf(hw, max_frame_size);
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	spin_unlock_bh(&hw->mbx_lock);
123262306a36Sopenharmony_ci}
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_cistatic int igbvf_vlan_rx_add_vid(struct net_device *netdev,
123562306a36Sopenharmony_ci				 __be16 proto, u16 vid)
123662306a36Sopenharmony_ci{
123762306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
123862306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	spin_lock_bh(&hw->mbx_lock);
124162306a36Sopenharmony_ci
124262306a36Sopenharmony_ci	if (hw->mac.ops.set_vfta(hw, vid, true)) {
124362306a36Sopenharmony_ci		dev_warn(&adapter->pdev->dev, "Vlan id %d\n is not added", vid);
124462306a36Sopenharmony_ci		spin_unlock_bh(&hw->mbx_lock);
124562306a36Sopenharmony_ci		return -EINVAL;
124662306a36Sopenharmony_ci	}
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	spin_unlock_bh(&hw->mbx_lock);
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	set_bit(vid, adapter->active_vlans);
125162306a36Sopenharmony_ci	return 0;
125262306a36Sopenharmony_ci}
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_cistatic int igbvf_vlan_rx_kill_vid(struct net_device *netdev,
125562306a36Sopenharmony_ci				  __be16 proto, u16 vid)
125662306a36Sopenharmony_ci{
125762306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
125862306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci	spin_lock_bh(&hw->mbx_lock);
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci	if (hw->mac.ops.set_vfta(hw, vid, false)) {
126362306a36Sopenharmony_ci		dev_err(&adapter->pdev->dev,
126462306a36Sopenharmony_ci			"Failed to remove vlan id %d\n", vid);
126562306a36Sopenharmony_ci		spin_unlock_bh(&hw->mbx_lock);
126662306a36Sopenharmony_ci		return -EINVAL;
126762306a36Sopenharmony_ci	}
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	spin_unlock_bh(&hw->mbx_lock);
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_ci	clear_bit(vid, adapter->active_vlans);
127262306a36Sopenharmony_ci	return 0;
127362306a36Sopenharmony_ci}
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_cistatic void igbvf_restore_vlan(struct igbvf_adapter *adapter)
127662306a36Sopenharmony_ci{
127762306a36Sopenharmony_ci	u16 vid;
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
128062306a36Sopenharmony_ci		igbvf_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid);
128162306a36Sopenharmony_ci}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci/**
128462306a36Sopenharmony_ci * igbvf_configure_tx - Configure Transmit Unit after Reset
128562306a36Sopenharmony_ci * @adapter: board private structure
128662306a36Sopenharmony_ci *
128762306a36Sopenharmony_ci * Configure the Tx unit of the MAC after a reset.
128862306a36Sopenharmony_ci **/
128962306a36Sopenharmony_cistatic void igbvf_configure_tx(struct igbvf_adapter *adapter)
129062306a36Sopenharmony_ci{
129162306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
129262306a36Sopenharmony_ci	struct igbvf_ring *tx_ring = adapter->tx_ring;
129362306a36Sopenharmony_ci	u64 tdba;
129462306a36Sopenharmony_ci	u32 txdctl, dca_txctrl;
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	/* disable transmits */
129762306a36Sopenharmony_ci	txdctl = er32(TXDCTL(0));
129862306a36Sopenharmony_ci	ew32(TXDCTL(0), txdctl & ~E1000_TXDCTL_QUEUE_ENABLE);
129962306a36Sopenharmony_ci	e1e_flush();
130062306a36Sopenharmony_ci	msleep(10);
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	/* Setup the HW Tx Head and Tail descriptor pointers */
130362306a36Sopenharmony_ci	ew32(TDLEN(0), tx_ring->count * sizeof(union e1000_adv_tx_desc));
130462306a36Sopenharmony_ci	tdba = tx_ring->dma;
130562306a36Sopenharmony_ci	ew32(TDBAL(0), (tdba & DMA_BIT_MASK(32)));
130662306a36Sopenharmony_ci	ew32(TDBAH(0), (tdba >> 32));
130762306a36Sopenharmony_ci	ew32(TDH(0), 0);
130862306a36Sopenharmony_ci	ew32(TDT(0), 0);
130962306a36Sopenharmony_ci	tx_ring->head = E1000_TDH(0);
131062306a36Sopenharmony_ci	tx_ring->tail = E1000_TDT(0);
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_ci	/* Turn off Relaxed Ordering on head write-backs.  The writebacks
131362306a36Sopenharmony_ci	 * MUST be delivered in order or it will completely screw up
131462306a36Sopenharmony_ci	 * our bookkeeping.
131562306a36Sopenharmony_ci	 */
131662306a36Sopenharmony_ci	dca_txctrl = er32(DCA_TXCTRL(0));
131762306a36Sopenharmony_ci	dca_txctrl &= ~E1000_DCA_TXCTRL_TX_WB_RO_EN;
131862306a36Sopenharmony_ci	ew32(DCA_TXCTRL(0), dca_txctrl);
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci	/* enable transmits */
132162306a36Sopenharmony_ci	txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
132262306a36Sopenharmony_ci	ew32(TXDCTL(0), txdctl);
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	/* Setup Transmit Descriptor Settings for eop descriptor */
132562306a36Sopenharmony_ci	adapter->txd_cmd = E1000_ADVTXD_DCMD_EOP | E1000_ADVTXD_DCMD_IFCS;
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_ci	/* enable Report Status bit */
132862306a36Sopenharmony_ci	adapter->txd_cmd |= E1000_ADVTXD_DCMD_RS;
132962306a36Sopenharmony_ci}
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci/**
133262306a36Sopenharmony_ci * igbvf_setup_srrctl - configure the receive control registers
133362306a36Sopenharmony_ci * @adapter: Board private structure
133462306a36Sopenharmony_ci **/
133562306a36Sopenharmony_cistatic void igbvf_setup_srrctl(struct igbvf_adapter *adapter)
133662306a36Sopenharmony_ci{
133762306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
133862306a36Sopenharmony_ci	u32 srrctl = 0;
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	srrctl &= ~(E1000_SRRCTL_DESCTYPE_MASK |
134162306a36Sopenharmony_ci		    E1000_SRRCTL_BSIZEHDR_MASK |
134262306a36Sopenharmony_ci		    E1000_SRRCTL_BSIZEPKT_MASK);
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci	/* Enable queue drop to avoid head of line blocking */
134562306a36Sopenharmony_ci	srrctl |= E1000_SRRCTL_DROP_EN;
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	/* Setup buffer sizes */
134862306a36Sopenharmony_ci	srrctl |= ALIGN(adapter->rx_buffer_len, 1024) >>
134962306a36Sopenharmony_ci		  E1000_SRRCTL_BSIZEPKT_SHIFT;
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci	if (adapter->rx_buffer_len < 2048) {
135262306a36Sopenharmony_ci		adapter->rx_ps_hdr_size = 0;
135362306a36Sopenharmony_ci		srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
135462306a36Sopenharmony_ci	} else {
135562306a36Sopenharmony_ci		adapter->rx_ps_hdr_size = 128;
135662306a36Sopenharmony_ci		srrctl |= adapter->rx_ps_hdr_size <<
135762306a36Sopenharmony_ci			  E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
135862306a36Sopenharmony_ci		srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
135962306a36Sopenharmony_ci	}
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	ew32(SRRCTL(0), srrctl);
136262306a36Sopenharmony_ci}
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci/**
136562306a36Sopenharmony_ci * igbvf_configure_rx - Configure Receive Unit after Reset
136662306a36Sopenharmony_ci * @adapter: board private structure
136762306a36Sopenharmony_ci *
136862306a36Sopenharmony_ci * Configure the Rx unit of the MAC after a reset.
136962306a36Sopenharmony_ci **/
137062306a36Sopenharmony_cistatic void igbvf_configure_rx(struct igbvf_adapter *adapter)
137162306a36Sopenharmony_ci{
137262306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
137362306a36Sopenharmony_ci	struct igbvf_ring *rx_ring = adapter->rx_ring;
137462306a36Sopenharmony_ci	u64 rdba;
137562306a36Sopenharmony_ci	u32 rxdctl;
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_ci	/* disable receives */
137862306a36Sopenharmony_ci	rxdctl = er32(RXDCTL(0));
137962306a36Sopenharmony_ci	ew32(RXDCTL(0), rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE);
138062306a36Sopenharmony_ci	e1e_flush();
138162306a36Sopenharmony_ci	msleep(10);
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	/* Setup the HW Rx Head and Tail Descriptor Pointers and
138462306a36Sopenharmony_ci	 * the Base and Length of the Rx Descriptor Ring
138562306a36Sopenharmony_ci	 */
138662306a36Sopenharmony_ci	rdba = rx_ring->dma;
138762306a36Sopenharmony_ci	ew32(RDBAL(0), (rdba & DMA_BIT_MASK(32)));
138862306a36Sopenharmony_ci	ew32(RDBAH(0), (rdba >> 32));
138962306a36Sopenharmony_ci	ew32(RDLEN(0), rx_ring->count * sizeof(union e1000_adv_rx_desc));
139062306a36Sopenharmony_ci	rx_ring->head = E1000_RDH(0);
139162306a36Sopenharmony_ci	rx_ring->tail = E1000_RDT(0);
139262306a36Sopenharmony_ci	ew32(RDH(0), 0);
139362306a36Sopenharmony_ci	ew32(RDT(0), 0);
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
139662306a36Sopenharmony_ci	rxdctl &= 0xFFF00000;
139762306a36Sopenharmony_ci	rxdctl |= IGBVF_RX_PTHRESH;
139862306a36Sopenharmony_ci	rxdctl |= IGBVF_RX_HTHRESH << 8;
139962306a36Sopenharmony_ci	rxdctl |= IGBVF_RX_WTHRESH << 16;
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci	igbvf_set_rlpml(adapter);
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci	/* enable receives */
140462306a36Sopenharmony_ci	ew32(RXDCTL(0), rxdctl);
140562306a36Sopenharmony_ci}
140662306a36Sopenharmony_ci
140762306a36Sopenharmony_ci/**
140862306a36Sopenharmony_ci * igbvf_set_multi - Multicast and Promiscuous mode set
140962306a36Sopenharmony_ci * @netdev: network interface device structure
141062306a36Sopenharmony_ci *
141162306a36Sopenharmony_ci * The set_multi entry point is called whenever the multicast address
141262306a36Sopenharmony_ci * list or the network interface flags are updated.  This routine is
141362306a36Sopenharmony_ci * responsible for configuring the hardware for proper multicast,
141462306a36Sopenharmony_ci * promiscuous mode, and all-multi behavior.
141562306a36Sopenharmony_ci **/
141662306a36Sopenharmony_cistatic void igbvf_set_multi(struct net_device *netdev)
141762306a36Sopenharmony_ci{
141862306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
141962306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
142062306a36Sopenharmony_ci	struct netdev_hw_addr *ha;
142162306a36Sopenharmony_ci	u8  *mta_list = NULL;
142262306a36Sopenharmony_ci	int i;
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci	if (!netdev_mc_empty(netdev)) {
142562306a36Sopenharmony_ci		mta_list = kmalloc_array(netdev_mc_count(netdev), ETH_ALEN,
142662306a36Sopenharmony_ci					 GFP_ATOMIC);
142762306a36Sopenharmony_ci		if (!mta_list)
142862306a36Sopenharmony_ci			return;
142962306a36Sopenharmony_ci	}
143062306a36Sopenharmony_ci
143162306a36Sopenharmony_ci	/* prepare a packed array of only addresses. */
143262306a36Sopenharmony_ci	i = 0;
143362306a36Sopenharmony_ci	netdev_for_each_mc_addr(ha, netdev)
143462306a36Sopenharmony_ci		memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci	spin_lock_bh(&hw->mbx_lock);
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci	hw->mac.ops.update_mc_addr_list(hw, mta_list, i, 0, 0);
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci	spin_unlock_bh(&hw->mbx_lock);
144162306a36Sopenharmony_ci	kfree(mta_list);
144262306a36Sopenharmony_ci}
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci/**
144562306a36Sopenharmony_ci * igbvf_set_uni - Configure unicast MAC filters
144662306a36Sopenharmony_ci * @netdev: network interface device structure
144762306a36Sopenharmony_ci *
144862306a36Sopenharmony_ci * This routine is responsible for configuring the hardware for proper
144962306a36Sopenharmony_ci * unicast filters.
145062306a36Sopenharmony_ci **/
145162306a36Sopenharmony_cistatic int igbvf_set_uni(struct net_device *netdev)
145262306a36Sopenharmony_ci{
145362306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
145462306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci	if (netdev_uc_count(netdev) > IGBVF_MAX_MAC_FILTERS) {
145762306a36Sopenharmony_ci		pr_err("Too many unicast filters - No Space\n");
145862306a36Sopenharmony_ci		return -ENOSPC;
145962306a36Sopenharmony_ci	}
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	spin_lock_bh(&hw->mbx_lock);
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	/* Clear all unicast MAC filters */
146462306a36Sopenharmony_ci	hw->mac.ops.set_uc_addr(hw, E1000_VF_MAC_FILTER_CLR, NULL);
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci	spin_unlock_bh(&hw->mbx_lock);
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci	if (!netdev_uc_empty(netdev)) {
146962306a36Sopenharmony_ci		struct netdev_hw_addr *ha;
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci		/* Add MAC filters one by one */
147262306a36Sopenharmony_ci		netdev_for_each_uc_addr(ha, netdev) {
147362306a36Sopenharmony_ci			spin_lock_bh(&hw->mbx_lock);
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci			hw->mac.ops.set_uc_addr(hw, E1000_VF_MAC_FILTER_ADD,
147662306a36Sopenharmony_ci						ha->addr);
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci			spin_unlock_bh(&hw->mbx_lock);
147962306a36Sopenharmony_ci			udelay(200);
148062306a36Sopenharmony_ci		}
148162306a36Sopenharmony_ci	}
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_ci	return 0;
148462306a36Sopenharmony_ci}
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_cistatic void igbvf_set_rx_mode(struct net_device *netdev)
148762306a36Sopenharmony_ci{
148862306a36Sopenharmony_ci	igbvf_set_multi(netdev);
148962306a36Sopenharmony_ci	igbvf_set_uni(netdev);
149062306a36Sopenharmony_ci}
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci/**
149362306a36Sopenharmony_ci * igbvf_configure - configure the hardware for Rx and Tx
149462306a36Sopenharmony_ci * @adapter: private board structure
149562306a36Sopenharmony_ci **/
149662306a36Sopenharmony_cistatic void igbvf_configure(struct igbvf_adapter *adapter)
149762306a36Sopenharmony_ci{
149862306a36Sopenharmony_ci	igbvf_set_rx_mode(adapter->netdev);
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_ci	igbvf_restore_vlan(adapter);
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	igbvf_configure_tx(adapter);
150362306a36Sopenharmony_ci	igbvf_setup_srrctl(adapter);
150462306a36Sopenharmony_ci	igbvf_configure_rx(adapter);
150562306a36Sopenharmony_ci	igbvf_alloc_rx_buffers(adapter->rx_ring,
150662306a36Sopenharmony_ci			       igbvf_desc_unused(adapter->rx_ring));
150762306a36Sopenharmony_ci}
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_ci/* igbvf_reset - bring the hardware into a known good state
151062306a36Sopenharmony_ci * @adapter: private board structure
151162306a36Sopenharmony_ci *
151262306a36Sopenharmony_ci * This function boots the hardware and enables some settings that
151362306a36Sopenharmony_ci * require a configuration cycle of the hardware - those cannot be
151462306a36Sopenharmony_ci * set/changed during runtime. After reset the device needs to be
151562306a36Sopenharmony_ci * properly configured for Rx, Tx etc.
151662306a36Sopenharmony_ci */
151762306a36Sopenharmony_cistatic void igbvf_reset(struct igbvf_adapter *adapter)
151862306a36Sopenharmony_ci{
151962306a36Sopenharmony_ci	struct e1000_mac_info *mac = &adapter->hw.mac;
152062306a36Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
152162306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci	spin_lock_bh(&hw->mbx_lock);
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ci	/* Allow time for pending master requests to run */
152662306a36Sopenharmony_ci	if (mac->ops.reset_hw(hw))
152762306a36Sopenharmony_ci		dev_info(&adapter->pdev->dev, "PF still resetting\n");
152862306a36Sopenharmony_ci
152962306a36Sopenharmony_ci	mac->ops.init_hw(hw);
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci	spin_unlock_bh(&hw->mbx_lock);
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci	if (is_valid_ether_addr(adapter->hw.mac.addr)) {
153462306a36Sopenharmony_ci		eth_hw_addr_set(netdev, adapter->hw.mac.addr);
153562306a36Sopenharmony_ci		memcpy(netdev->perm_addr, adapter->hw.mac.addr,
153662306a36Sopenharmony_ci		       netdev->addr_len);
153762306a36Sopenharmony_ci	}
153862306a36Sopenharmony_ci
153962306a36Sopenharmony_ci	adapter->last_reset = jiffies;
154062306a36Sopenharmony_ci}
154162306a36Sopenharmony_ci
154262306a36Sopenharmony_ciint igbvf_up(struct igbvf_adapter *adapter)
154362306a36Sopenharmony_ci{
154462306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
154562306a36Sopenharmony_ci
154662306a36Sopenharmony_ci	/* hardware has been reset, we need to reload some things */
154762306a36Sopenharmony_ci	igbvf_configure(adapter);
154862306a36Sopenharmony_ci
154962306a36Sopenharmony_ci	clear_bit(__IGBVF_DOWN, &adapter->state);
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	napi_enable(&adapter->rx_ring->napi);
155262306a36Sopenharmony_ci	if (adapter->msix_entries)
155362306a36Sopenharmony_ci		igbvf_configure_msix(adapter);
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	/* Clear any pending interrupts. */
155662306a36Sopenharmony_ci	er32(EICR);
155762306a36Sopenharmony_ci	igbvf_irq_enable(adapter);
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	/* start the watchdog */
156062306a36Sopenharmony_ci	hw->mac.get_link_status = 1;
156162306a36Sopenharmony_ci	mod_timer(&adapter->watchdog_timer, jiffies + 1);
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_ci	return 0;
156462306a36Sopenharmony_ci}
156562306a36Sopenharmony_ci
156662306a36Sopenharmony_civoid igbvf_down(struct igbvf_adapter *adapter)
156762306a36Sopenharmony_ci{
156862306a36Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
156962306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
157062306a36Sopenharmony_ci	u32 rxdctl, txdctl;
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_ci	/* signal that we're down so the interrupt handler does not
157362306a36Sopenharmony_ci	 * reschedule our watchdog timer
157462306a36Sopenharmony_ci	 */
157562306a36Sopenharmony_ci	set_bit(__IGBVF_DOWN, &adapter->state);
157662306a36Sopenharmony_ci
157762306a36Sopenharmony_ci	/* disable receives in the hardware */
157862306a36Sopenharmony_ci	rxdctl = er32(RXDCTL(0));
157962306a36Sopenharmony_ci	ew32(RXDCTL(0), rxdctl & ~E1000_RXDCTL_QUEUE_ENABLE);
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_ci	netif_carrier_off(netdev);
158262306a36Sopenharmony_ci	netif_stop_queue(netdev);
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci	/* disable transmits in the hardware */
158562306a36Sopenharmony_ci	txdctl = er32(TXDCTL(0));
158662306a36Sopenharmony_ci	ew32(TXDCTL(0), txdctl & ~E1000_TXDCTL_QUEUE_ENABLE);
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci	/* flush both disables and wait for them to finish */
158962306a36Sopenharmony_ci	e1e_flush();
159062306a36Sopenharmony_ci	msleep(10);
159162306a36Sopenharmony_ci
159262306a36Sopenharmony_ci	napi_disable(&adapter->rx_ring->napi);
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	igbvf_irq_disable(adapter);
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	del_timer_sync(&adapter->watchdog_timer);
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci	/* record the stats before reset*/
159962306a36Sopenharmony_ci	igbvf_update_stats(adapter);
160062306a36Sopenharmony_ci
160162306a36Sopenharmony_ci	adapter->link_speed = 0;
160262306a36Sopenharmony_ci	adapter->link_duplex = 0;
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci	igbvf_reset(adapter);
160562306a36Sopenharmony_ci	igbvf_clean_tx_ring(adapter->tx_ring);
160662306a36Sopenharmony_ci	igbvf_clean_rx_ring(adapter->rx_ring);
160762306a36Sopenharmony_ci}
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_civoid igbvf_reinit_locked(struct igbvf_adapter *adapter)
161062306a36Sopenharmony_ci{
161162306a36Sopenharmony_ci	might_sleep();
161262306a36Sopenharmony_ci	while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
161362306a36Sopenharmony_ci		usleep_range(1000, 2000);
161462306a36Sopenharmony_ci	igbvf_down(adapter);
161562306a36Sopenharmony_ci	igbvf_up(adapter);
161662306a36Sopenharmony_ci	clear_bit(__IGBVF_RESETTING, &adapter->state);
161762306a36Sopenharmony_ci}
161862306a36Sopenharmony_ci
161962306a36Sopenharmony_ci/**
162062306a36Sopenharmony_ci * igbvf_sw_init - Initialize general software structures (struct igbvf_adapter)
162162306a36Sopenharmony_ci * @adapter: board private structure to initialize
162262306a36Sopenharmony_ci *
162362306a36Sopenharmony_ci * igbvf_sw_init initializes the Adapter private data structure.
162462306a36Sopenharmony_ci * Fields are initialized based on PCI device information and
162562306a36Sopenharmony_ci * OS network device settings (MTU size).
162662306a36Sopenharmony_ci **/
162762306a36Sopenharmony_cistatic int igbvf_sw_init(struct igbvf_adapter *adapter)
162862306a36Sopenharmony_ci{
162962306a36Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
163062306a36Sopenharmony_ci	s32 rc;
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN;
163362306a36Sopenharmony_ci	adapter->rx_ps_hdr_size = 0;
163462306a36Sopenharmony_ci	adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
163562306a36Sopenharmony_ci	adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci	adapter->tx_int_delay = 8;
163862306a36Sopenharmony_ci	adapter->tx_abs_int_delay = 32;
163962306a36Sopenharmony_ci	adapter->rx_int_delay = 0;
164062306a36Sopenharmony_ci	adapter->rx_abs_int_delay = 8;
164162306a36Sopenharmony_ci	adapter->requested_itr = 3;
164262306a36Sopenharmony_ci	adapter->current_itr = IGBVF_START_ITR;
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci	/* Set various function pointers */
164562306a36Sopenharmony_ci	adapter->ei->init_ops(&adapter->hw);
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ci	rc = adapter->hw.mac.ops.init_params(&adapter->hw);
164862306a36Sopenharmony_ci	if (rc)
164962306a36Sopenharmony_ci		return rc;
165062306a36Sopenharmony_ci
165162306a36Sopenharmony_ci	rc = adapter->hw.mbx.ops.init_params(&adapter->hw);
165262306a36Sopenharmony_ci	if (rc)
165362306a36Sopenharmony_ci		return rc;
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci	igbvf_set_interrupt_capability(adapter);
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_ci	if (igbvf_alloc_queues(adapter))
165862306a36Sopenharmony_ci		return -ENOMEM;
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci	spin_lock_init(&adapter->tx_queue_lock);
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci	/* Explicitly disable IRQ since the NIC can be in any state. */
166362306a36Sopenharmony_ci	igbvf_irq_disable(adapter);
166462306a36Sopenharmony_ci
166562306a36Sopenharmony_ci	spin_lock_init(&adapter->stats_lock);
166662306a36Sopenharmony_ci	spin_lock_init(&adapter->hw.mbx_lock);
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci	set_bit(__IGBVF_DOWN, &adapter->state);
166962306a36Sopenharmony_ci	return 0;
167062306a36Sopenharmony_ci}
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_cistatic void igbvf_initialize_last_counter_stats(struct igbvf_adapter *adapter)
167362306a36Sopenharmony_ci{
167462306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
167562306a36Sopenharmony_ci
167662306a36Sopenharmony_ci	adapter->stats.last_gprc = er32(VFGPRC);
167762306a36Sopenharmony_ci	adapter->stats.last_gorc = er32(VFGORC);
167862306a36Sopenharmony_ci	adapter->stats.last_gptc = er32(VFGPTC);
167962306a36Sopenharmony_ci	adapter->stats.last_gotc = er32(VFGOTC);
168062306a36Sopenharmony_ci	adapter->stats.last_mprc = er32(VFMPRC);
168162306a36Sopenharmony_ci	adapter->stats.last_gotlbc = er32(VFGOTLBC);
168262306a36Sopenharmony_ci	adapter->stats.last_gptlbc = er32(VFGPTLBC);
168362306a36Sopenharmony_ci	adapter->stats.last_gorlbc = er32(VFGORLBC);
168462306a36Sopenharmony_ci	adapter->stats.last_gprlbc = er32(VFGPRLBC);
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ci	adapter->stats.base_gprc = er32(VFGPRC);
168762306a36Sopenharmony_ci	adapter->stats.base_gorc = er32(VFGORC);
168862306a36Sopenharmony_ci	adapter->stats.base_gptc = er32(VFGPTC);
168962306a36Sopenharmony_ci	adapter->stats.base_gotc = er32(VFGOTC);
169062306a36Sopenharmony_ci	adapter->stats.base_mprc = er32(VFMPRC);
169162306a36Sopenharmony_ci	adapter->stats.base_gotlbc = er32(VFGOTLBC);
169262306a36Sopenharmony_ci	adapter->stats.base_gptlbc = er32(VFGPTLBC);
169362306a36Sopenharmony_ci	adapter->stats.base_gorlbc = er32(VFGORLBC);
169462306a36Sopenharmony_ci	adapter->stats.base_gprlbc = er32(VFGPRLBC);
169562306a36Sopenharmony_ci}
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_ci/**
169862306a36Sopenharmony_ci * igbvf_open - Called when a network interface is made active
169962306a36Sopenharmony_ci * @netdev: network interface device structure
170062306a36Sopenharmony_ci *
170162306a36Sopenharmony_ci * Returns 0 on success, negative value on failure
170262306a36Sopenharmony_ci *
170362306a36Sopenharmony_ci * The open entry point is called when a network interface is made
170462306a36Sopenharmony_ci * active by the system (IFF_UP).  At this point all resources needed
170562306a36Sopenharmony_ci * for transmit and receive operations are allocated, the interrupt
170662306a36Sopenharmony_ci * handler is registered with the OS, the watchdog timer is started,
170762306a36Sopenharmony_ci * and the stack is notified that the interface is ready.
170862306a36Sopenharmony_ci **/
170962306a36Sopenharmony_cistatic int igbvf_open(struct net_device *netdev)
171062306a36Sopenharmony_ci{
171162306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
171262306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
171362306a36Sopenharmony_ci	int err;
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci	/* disallow open during test */
171662306a36Sopenharmony_ci	if (test_bit(__IGBVF_TESTING, &adapter->state))
171762306a36Sopenharmony_ci		return -EBUSY;
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci	/* allocate transmit descriptors */
172062306a36Sopenharmony_ci	err = igbvf_setup_tx_resources(adapter, adapter->tx_ring);
172162306a36Sopenharmony_ci	if (err)
172262306a36Sopenharmony_ci		goto err_setup_tx;
172362306a36Sopenharmony_ci
172462306a36Sopenharmony_ci	/* allocate receive descriptors */
172562306a36Sopenharmony_ci	err = igbvf_setup_rx_resources(adapter, adapter->rx_ring);
172662306a36Sopenharmony_ci	if (err)
172762306a36Sopenharmony_ci		goto err_setup_rx;
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	/* before we allocate an interrupt, we must be ready to handle it.
173062306a36Sopenharmony_ci	 * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
173162306a36Sopenharmony_ci	 * as soon as we call pci_request_irq, so we have to setup our
173262306a36Sopenharmony_ci	 * clean_rx handler before we do so.
173362306a36Sopenharmony_ci	 */
173462306a36Sopenharmony_ci	igbvf_configure(adapter);
173562306a36Sopenharmony_ci
173662306a36Sopenharmony_ci	err = igbvf_request_irq(adapter);
173762306a36Sopenharmony_ci	if (err)
173862306a36Sopenharmony_ci		goto err_req_irq;
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci	/* From here on the code is the same as igbvf_up() */
174162306a36Sopenharmony_ci	clear_bit(__IGBVF_DOWN, &adapter->state);
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_ci	napi_enable(&adapter->rx_ring->napi);
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	/* clear any pending interrupts */
174662306a36Sopenharmony_ci	er32(EICR);
174762306a36Sopenharmony_ci
174862306a36Sopenharmony_ci	igbvf_irq_enable(adapter);
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci	/* start the watchdog */
175162306a36Sopenharmony_ci	hw->mac.get_link_status = 1;
175262306a36Sopenharmony_ci	mod_timer(&adapter->watchdog_timer, jiffies + 1);
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci	return 0;
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_cierr_req_irq:
175762306a36Sopenharmony_ci	igbvf_free_rx_resources(adapter->rx_ring);
175862306a36Sopenharmony_cierr_setup_rx:
175962306a36Sopenharmony_ci	igbvf_free_tx_resources(adapter->tx_ring);
176062306a36Sopenharmony_cierr_setup_tx:
176162306a36Sopenharmony_ci	igbvf_reset(adapter);
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_ci	return err;
176462306a36Sopenharmony_ci}
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci/**
176762306a36Sopenharmony_ci * igbvf_close - Disables a network interface
176862306a36Sopenharmony_ci * @netdev: network interface device structure
176962306a36Sopenharmony_ci *
177062306a36Sopenharmony_ci * Returns 0, this is not allowed to fail
177162306a36Sopenharmony_ci *
177262306a36Sopenharmony_ci * The close entry point is called when an interface is de-activated
177362306a36Sopenharmony_ci * by the OS.  The hardware is still under the drivers control, but
177462306a36Sopenharmony_ci * needs to be disabled.  A global MAC reset is issued to stop the
177562306a36Sopenharmony_ci * hardware, and all transmit and receive resources are freed.
177662306a36Sopenharmony_ci **/
177762306a36Sopenharmony_cistatic int igbvf_close(struct net_device *netdev)
177862306a36Sopenharmony_ci{
177962306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_ci	WARN_ON(test_bit(__IGBVF_RESETTING, &adapter->state));
178262306a36Sopenharmony_ci	igbvf_down(adapter);
178362306a36Sopenharmony_ci
178462306a36Sopenharmony_ci	igbvf_free_irq(adapter);
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_ci	igbvf_free_tx_resources(adapter->tx_ring);
178762306a36Sopenharmony_ci	igbvf_free_rx_resources(adapter->rx_ring);
178862306a36Sopenharmony_ci
178962306a36Sopenharmony_ci	return 0;
179062306a36Sopenharmony_ci}
179162306a36Sopenharmony_ci
179262306a36Sopenharmony_ci/**
179362306a36Sopenharmony_ci * igbvf_set_mac - Change the Ethernet Address of the NIC
179462306a36Sopenharmony_ci * @netdev: network interface device structure
179562306a36Sopenharmony_ci * @p: pointer to an address structure
179662306a36Sopenharmony_ci *
179762306a36Sopenharmony_ci * Returns 0 on success, negative on failure
179862306a36Sopenharmony_ci **/
179962306a36Sopenharmony_cistatic int igbvf_set_mac(struct net_device *netdev, void *p)
180062306a36Sopenharmony_ci{
180162306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
180262306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
180362306a36Sopenharmony_ci	struct sockaddr *addr = p;
180462306a36Sopenharmony_ci
180562306a36Sopenharmony_ci	if (!is_valid_ether_addr(addr->sa_data))
180662306a36Sopenharmony_ci		return -EADDRNOTAVAIL;
180762306a36Sopenharmony_ci
180862306a36Sopenharmony_ci	memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
180962306a36Sopenharmony_ci
181062306a36Sopenharmony_ci	spin_lock_bh(&hw->mbx_lock);
181162306a36Sopenharmony_ci
181262306a36Sopenharmony_ci	hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci	spin_unlock_bh(&hw->mbx_lock);
181562306a36Sopenharmony_ci
181662306a36Sopenharmony_ci	if (!ether_addr_equal(addr->sa_data, hw->mac.addr))
181762306a36Sopenharmony_ci		return -EADDRNOTAVAIL;
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	eth_hw_addr_set(netdev, addr->sa_data);
182062306a36Sopenharmony_ci
182162306a36Sopenharmony_ci	return 0;
182262306a36Sopenharmony_ci}
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci#define UPDATE_VF_COUNTER(reg, name) \
182562306a36Sopenharmony_ci{ \
182662306a36Sopenharmony_ci	u32 current_counter = er32(reg); \
182762306a36Sopenharmony_ci	if (current_counter < adapter->stats.last_##name) \
182862306a36Sopenharmony_ci		adapter->stats.name += 0x100000000LL; \
182962306a36Sopenharmony_ci	adapter->stats.last_##name = current_counter; \
183062306a36Sopenharmony_ci	adapter->stats.name &= 0xFFFFFFFF00000000LL; \
183162306a36Sopenharmony_ci	adapter->stats.name |= current_counter; \
183262306a36Sopenharmony_ci}
183362306a36Sopenharmony_ci
183462306a36Sopenharmony_ci/**
183562306a36Sopenharmony_ci * igbvf_update_stats - Update the board statistics counters
183662306a36Sopenharmony_ci * @adapter: board private structure
183762306a36Sopenharmony_ci**/
183862306a36Sopenharmony_civoid igbvf_update_stats(struct igbvf_adapter *adapter)
183962306a36Sopenharmony_ci{
184062306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
184162306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_ci	/* Prevent stats update while adapter is being reset, link is down
184462306a36Sopenharmony_ci	 * or if the pci connection is down.
184562306a36Sopenharmony_ci	 */
184662306a36Sopenharmony_ci	if (adapter->link_speed == 0)
184762306a36Sopenharmony_ci		return;
184862306a36Sopenharmony_ci
184962306a36Sopenharmony_ci	if (test_bit(__IGBVF_RESETTING, &adapter->state))
185062306a36Sopenharmony_ci		return;
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci	if (pci_channel_offline(pdev))
185362306a36Sopenharmony_ci		return;
185462306a36Sopenharmony_ci
185562306a36Sopenharmony_ci	UPDATE_VF_COUNTER(VFGPRC, gprc);
185662306a36Sopenharmony_ci	UPDATE_VF_COUNTER(VFGORC, gorc);
185762306a36Sopenharmony_ci	UPDATE_VF_COUNTER(VFGPTC, gptc);
185862306a36Sopenharmony_ci	UPDATE_VF_COUNTER(VFGOTC, gotc);
185962306a36Sopenharmony_ci	UPDATE_VF_COUNTER(VFMPRC, mprc);
186062306a36Sopenharmony_ci	UPDATE_VF_COUNTER(VFGOTLBC, gotlbc);
186162306a36Sopenharmony_ci	UPDATE_VF_COUNTER(VFGPTLBC, gptlbc);
186262306a36Sopenharmony_ci	UPDATE_VF_COUNTER(VFGORLBC, gorlbc);
186362306a36Sopenharmony_ci	UPDATE_VF_COUNTER(VFGPRLBC, gprlbc);
186462306a36Sopenharmony_ci
186562306a36Sopenharmony_ci	/* Fill out the OS statistics structure */
186662306a36Sopenharmony_ci	adapter->netdev->stats.multicast = adapter->stats.mprc;
186762306a36Sopenharmony_ci}
186862306a36Sopenharmony_ci
186962306a36Sopenharmony_cistatic void igbvf_print_link_info(struct igbvf_adapter *adapter)
187062306a36Sopenharmony_ci{
187162306a36Sopenharmony_ci	dev_info(&adapter->pdev->dev, "Link is Up %d Mbps %s Duplex\n",
187262306a36Sopenharmony_ci		 adapter->link_speed,
187362306a36Sopenharmony_ci		 adapter->link_duplex == FULL_DUPLEX ? "Full" : "Half");
187462306a36Sopenharmony_ci}
187562306a36Sopenharmony_ci
187662306a36Sopenharmony_cistatic bool igbvf_has_link(struct igbvf_adapter *adapter)
187762306a36Sopenharmony_ci{
187862306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
187962306a36Sopenharmony_ci	s32 ret_val = E1000_SUCCESS;
188062306a36Sopenharmony_ci	bool link_active;
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_ci	/* If interface is down, stay link down */
188362306a36Sopenharmony_ci	if (test_bit(__IGBVF_DOWN, &adapter->state))
188462306a36Sopenharmony_ci		return false;
188562306a36Sopenharmony_ci
188662306a36Sopenharmony_ci	spin_lock_bh(&hw->mbx_lock);
188762306a36Sopenharmony_ci
188862306a36Sopenharmony_ci	ret_val = hw->mac.ops.check_for_link(hw);
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	spin_unlock_bh(&hw->mbx_lock);
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	link_active = !hw->mac.get_link_status;
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci	/* if check for link returns error we will need to reset */
189562306a36Sopenharmony_ci	if (ret_val && time_after(jiffies, adapter->last_reset + (10 * HZ)))
189662306a36Sopenharmony_ci		schedule_work(&adapter->reset_task);
189762306a36Sopenharmony_ci
189862306a36Sopenharmony_ci	return link_active;
189962306a36Sopenharmony_ci}
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci/**
190262306a36Sopenharmony_ci * igbvf_watchdog - Timer Call-back
190362306a36Sopenharmony_ci * @t: timer list pointer containing private struct
190462306a36Sopenharmony_ci **/
190562306a36Sopenharmony_cistatic void igbvf_watchdog(struct timer_list *t)
190662306a36Sopenharmony_ci{
190762306a36Sopenharmony_ci	struct igbvf_adapter *adapter = from_timer(adapter, t, watchdog_timer);
190862306a36Sopenharmony_ci
190962306a36Sopenharmony_ci	/* Do the rest outside of interrupt context */
191062306a36Sopenharmony_ci	schedule_work(&adapter->watchdog_task);
191162306a36Sopenharmony_ci}
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_cistatic void igbvf_watchdog_task(struct work_struct *work)
191462306a36Sopenharmony_ci{
191562306a36Sopenharmony_ci	struct igbvf_adapter *adapter = container_of(work,
191662306a36Sopenharmony_ci						     struct igbvf_adapter,
191762306a36Sopenharmony_ci						     watchdog_task);
191862306a36Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
191962306a36Sopenharmony_ci	struct e1000_mac_info *mac = &adapter->hw.mac;
192062306a36Sopenharmony_ci	struct igbvf_ring *tx_ring = adapter->tx_ring;
192162306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
192262306a36Sopenharmony_ci	u32 link;
192362306a36Sopenharmony_ci	int tx_pending = 0;
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_ci	link = igbvf_has_link(adapter);
192662306a36Sopenharmony_ci
192762306a36Sopenharmony_ci	if (link) {
192862306a36Sopenharmony_ci		if (!netif_carrier_ok(netdev)) {
192962306a36Sopenharmony_ci			mac->ops.get_link_up_info(&adapter->hw,
193062306a36Sopenharmony_ci						  &adapter->link_speed,
193162306a36Sopenharmony_ci						  &adapter->link_duplex);
193262306a36Sopenharmony_ci			igbvf_print_link_info(adapter);
193362306a36Sopenharmony_ci
193462306a36Sopenharmony_ci			netif_carrier_on(netdev);
193562306a36Sopenharmony_ci			netif_wake_queue(netdev);
193662306a36Sopenharmony_ci		}
193762306a36Sopenharmony_ci	} else {
193862306a36Sopenharmony_ci		if (netif_carrier_ok(netdev)) {
193962306a36Sopenharmony_ci			adapter->link_speed = 0;
194062306a36Sopenharmony_ci			adapter->link_duplex = 0;
194162306a36Sopenharmony_ci			dev_info(&adapter->pdev->dev, "Link is Down\n");
194262306a36Sopenharmony_ci			netif_carrier_off(netdev);
194362306a36Sopenharmony_ci			netif_stop_queue(netdev);
194462306a36Sopenharmony_ci		}
194562306a36Sopenharmony_ci	}
194662306a36Sopenharmony_ci
194762306a36Sopenharmony_ci	if (netif_carrier_ok(netdev)) {
194862306a36Sopenharmony_ci		igbvf_update_stats(adapter);
194962306a36Sopenharmony_ci	} else {
195062306a36Sopenharmony_ci		tx_pending = (igbvf_desc_unused(tx_ring) + 1 <
195162306a36Sopenharmony_ci			      tx_ring->count);
195262306a36Sopenharmony_ci		if (tx_pending) {
195362306a36Sopenharmony_ci			/* We've lost link, so the controller stops DMA,
195462306a36Sopenharmony_ci			 * but we've got queued Tx work that's never going
195562306a36Sopenharmony_ci			 * to get done, so reset controller to flush Tx.
195662306a36Sopenharmony_ci			 * (Do the reset outside of interrupt context).
195762306a36Sopenharmony_ci			 */
195862306a36Sopenharmony_ci			adapter->tx_timeout_count++;
195962306a36Sopenharmony_ci			schedule_work(&adapter->reset_task);
196062306a36Sopenharmony_ci		}
196162306a36Sopenharmony_ci	}
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci	/* Cause software interrupt to ensure Rx ring is cleaned */
196462306a36Sopenharmony_ci	ew32(EICS, adapter->rx_ring->eims_value);
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	/* Reset the timer */
196762306a36Sopenharmony_ci	if (!test_bit(__IGBVF_DOWN, &adapter->state))
196862306a36Sopenharmony_ci		mod_timer(&adapter->watchdog_timer,
196962306a36Sopenharmony_ci			  round_jiffies(jiffies + (2 * HZ)));
197062306a36Sopenharmony_ci}
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci#define IGBVF_TX_FLAGS_CSUM		0x00000001
197362306a36Sopenharmony_ci#define IGBVF_TX_FLAGS_VLAN		0x00000002
197462306a36Sopenharmony_ci#define IGBVF_TX_FLAGS_TSO		0x00000004
197562306a36Sopenharmony_ci#define IGBVF_TX_FLAGS_IPV4		0x00000008
197662306a36Sopenharmony_ci#define IGBVF_TX_FLAGS_VLAN_MASK	0xffff0000
197762306a36Sopenharmony_ci#define IGBVF_TX_FLAGS_VLAN_SHIFT	16
197862306a36Sopenharmony_ci
197962306a36Sopenharmony_cistatic void igbvf_tx_ctxtdesc(struct igbvf_ring *tx_ring, u32 vlan_macip_lens,
198062306a36Sopenharmony_ci			      u32 type_tucmd, u32 mss_l4len_idx)
198162306a36Sopenharmony_ci{
198262306a36Sopenharmony_ci	struct e1000_adv_tx_context_desc *context_desc;
198362306a36Sopenharmony_ci	struct igbvf_buffer *buffer_info;
198462306a36Sopenharmony_ci	u16 i = tx_ring->next_to_use;
198562306a36Sopenharmony_ci
198662306a36Sopenharmony_ci	context_desc = IGBVF_TX_CTXTDESC_ADV(*tx_ring, i);
198762306a36Sopenharmony_ci	buffer_info = &tx_ring->buffer_info[i];
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci	i++;
199062306a36Sopenharmony_ci	tx_ring->next_to_use = (i < tx_ring->count) ? i : 0;
199162306a36Sopenharmony_ci
199262306a36Sopenharmony_ci	/* set bits to identify this as an advanced context descriptor */
199362306a36Sopenharmony_ci	type_tucmd |= E1000_TXD_CMD_DEXT | E1000_ADVTXD_DTYP_CTXT;
199462306a36Sopenharmony_ci
199562306a36Sopenharmony_ci	context_desc->vlan_macip_lens	= cpu_to_le32(vlan_macip_lens);
199662306a36Sopenharmony_ci	context_desc->seqnum_seed	= 0;
199762306a36Sopenharmony_ci	context_desc->type_tucmd_mlhl	= cpu_to_le32(type_tucmd);
199862306a36Sopenharmony_ci	context_desc->mss_l4len_idx	= cpu_to_le32(mss_l4len_idx);
199962306a36Sopenharmony_ci
200062306a36Sopenharmony_ci	buffer_info->time_stamp = jiffies;
200162306a36Sopenharmony_ci	buffer_info->dma = 0;
200262306a36Sopenharmony_ci}
200362306a36Sopenharmony_ci
200462306a36Sopenharmony_cistatic int igbvf_tso(struct igbvf_ring *tx_ring,
200562306a36Sopenharmony_ci		     struct sk_buff *skb, u32 tx_flags, u8 *hdr_len)
200662306a36Sopenharmony_ci{
200762306a36Sopenharmony_ci	u32 vlan_macip_lens, type_tucmd, mss_l4len_idx;
200862306a36Sopenharmony_ci	union {
200962306a36Sopenharmony_ci		struct iphdr *v4;
201062306a36Sopenharmony_ci		struct ipv6hdr *v6;
201162306a36Sopenharmony_ci		unsigned char *hdr;
201262306a36Sopenharmony_ci	} ip;
201362306a36Sopenharmony_ci	union {
201462306a36Sopenharmony_ci		struct tcphdr *tcp;
201562306a36Sopenharmony_ci		unsigned char *hdr;
201662306a36Sopenharmony_ci	} l4;
201762306a36Sopenharmony_ci	u32 paylen, l4_offset;
201862306a36Sopenharmony_ci	int err;
201962306a36Sopenharmony_ci
202062306a36Sopenharmony_ci	if (skb->ip_summed != CHECKSUM_PARTIAL)
202162306a36Sopenharmony_ci		return 0;
202262306a36Sopenharmony_ci
202362306a36Sopenharmony_ci	if (!skb_is_gso(skb))
202462306a36Sopenharmony_ci		return 0;
202562306a36Sopenharmony_ci
202662306a36Sopenharmony_ci	err = skb_cow_head(skb, 0);
202762306a36Sopenharmony_ci	if (err < 0)
202862306a36Sopenharmony_ci		return err;
202962306a36Sopenharmony_ci
203062306a36Sopenharmony_ci	ip.hdr = skb_network_header(skb);
203162306a36Sopenharmony_ci	l4.hdr = skb_checksum_start(skb);
203262306a36Sopenharmony_ci
203362306a36Sopenharmony_ci	/* ADV DTYP TUCMD MKRLOC/ISCSIHEDLEN */
203462306a36Sopenharmony_ci	type_tucmd = E1000_ADVTXD_TUCMD_L4T_TCP;
203562306a36Sopenharmony_ci
203662306a36Sopenharmony_ci	/* initialize outer IP header fields */
203762306a36Sopenharmony_ci	if (ip.v4->version == 4) {
203862306a36Sopenharmony_ci		unsigned char *csum_start = skb_checksum_start(skb);
203962306a36Sopenharmony_ci		unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4);
204062306a36Sopenharmony_ci
204162306a36Sopenharmony_ci		/* IP header will have to cancel out any data that
204262306a36Sopenharmony_ci		 * is not a part of the outer IP header
204362306a36Sopenharmony_ci		 */
204462306a36Sopenharmony_ci		ip.v4->check = csum_fold(csum_partial(trans_start,
204562306a36Sopenharmony_ci						      csum_start - trans_start,
204662306a36Sopenharmony_ci						      0));
204762306a36Sopenharmony_ci		type_tucmd |= E1000_ADVTXD_TUCMD_IPV4;
204862306a36Sopenharmony_ci
204962306a36Sopenharmony_ci		ip.v4->tot_len = 0;
205062306a36Sopenharmony_ci	} else {
205162306a36Sopenharmony_ci		ip.v6->payload_len = 0;
205262306a36Sopenharmony_ci	}
205362306a36Sopenharmony_ci
205462306a36Sopenharmony_ci	/* determine offset of inner transport header */
205562306a36Sopenharmony_ci	l4_offset = l4.hdr - skb->data;
205662306a36Sopenharmony_ci
205762306a36Sopenharmony_ci	/* compute length of segmentation header */
205862306a36Sopenharmony_ci	*hdr_len = (l4.tcp->doff * 4) + l4_offset;
205962306a36Sopenharmony_ci
206062306a36Sopenharmony_ci	/* remove payload length from inner checksum */
206162306a36Sopenharmony_ci	paylen = skb->len - l4_offset;
206262306a36Sopenharmony_ci	csum_replace_by_diff(&l4.tcp->check, (__force __wsum)htonl(paylen));
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_ci	/* MSS L4LEN IDX */
206562306a36Sopenharmony_ci	mss_l4len_idx = (*hdr_len - l4_offset) << E1000_ADVTXD_L4LEN_SHIFT;
206662306a36Sopenharmony_ci	mss_l4len_idx |= skb_shinfo(skb)->gso_size << E1000_ADVTXD_MSS_SHIFT;
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci	/* VLAN MACLEN IPLEN */
206962306a36Sopenharmony_ci	vlan_macip_lens = l4.hdr - ip.hdr;
207062306a36Sopenharmony_ci	vlan_macip_lens |= (ip.hdr - skb->data) << E1000_ADVTXD_MACLEN_SHIFT;
207162306a36Sopenharmony_ci	vlan_macip_lens |= tx_flags & IGBVF_TX_FLAGS_VLAN_MASK;
207262306a36Sopenharmony_ci
207362306a36Sopenharmony_ci	igbvf_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx);
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci	return 1;
207662306a36Sopenharmony_ci}
207762306a36Sopenharmony_ci
207862306a36Sopenharmony_cistatic bool igbvf_tx_csum(struct igbvf_ring *tx_ring, struct sk_buff *skb,
207962306a36Sopenharmony_ci			  u32 tx_flags, __be16 protocol)
208062306a36Sopenharmony_ci{
208162306a36Sopenharmony_ci	u32 vlan_macip_lens = 0;
208262306a36Sopenharmony_ci	u32 type_tucmd = 0;
208362306a36Sopenharmony_ci
208462306a36Sopenharmony_ci	if (skb->ip_summed != CHECKSUM_PARTIAL) {
208562306a36Sopenharmony_cicsum_failed:
208662306a36Sopenharmony_ci		if (!(tx_flags & IGBVF_TX_FLAGS_VLAN))
208762306a36Sopenharmony_ci			return false;
208862306a36Sopenharmony_ci		goto no_csum;
208962306a36Sopenharmony_ci	}
209062306a36Sopenharmony_ci
209162306a36Sopenharmony_ci	switch (skb->csum_offset) {
209262306a36Sopenharmony_ci	case offsetof(struct tcphdr, check):
209362306a36Sopenharmony_ci		type_tucmd = E1000_ADVTXD_TUCMD_L4T_TCP;
209462306a36Sopenharmony_ci		fallthrough;
209562306a36Sopenharmony_ci	case offsetof(struct udphdr, check):
209662306a36Sopenharmony_ci		break;
209762306a36Sopenharmony_ci	case offsetof(struct sctphdr, checksum):
209862306a36Sopenharmony_ci		/* validate that this is actually an SCTP request */
209962306a36Sopenharmony_ci		if (skb_csum_is_sctp(skb)) {
210062306a36Sopenharmony_ci			type_tucmd = E1000_ADVTXD_TUCMD_L4T_SCTP;
210162306a36Sopenharmony_ci			break;
210262306a36Sopenharmony_ci		}
210362306a36Sopenharmony_ci		fallthrough;
210462306a36Sopenharmony_ci	default:
210562306a36Sopenharmony_ci		skb_checksum_help(skb);
210662306a36Sopenharmony_ci		goto csum_failed;
210762306a36Sopenharmony_ci	}
210862306a36Sopenharmony_ci
210962306a36Sopenharmony_ci	vlan_macip_lens = skb_checksum_start_offset(skb) -
211062306a36Sopenharmony_ci			  skb_network_offset(skb);
211162306a36Sopenharmony_cino_csum:
211262306a36Sopenharmony_ci	vlan_macip_lens |= skb_network_offset(skb) << E1000_ADVTXD_MACLEN_SHIFT;
211362306a36Sopenharmony_ci	vlan_macip_lens |= tx_flags & IGBVF_TX_FLAGS_VLAN_MASK;
211462306a36Sopenharmony_ci
211562306a36Sopenharmony_ci	igbvf_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, 0);
211662306a36Sopenharmony_ci	return true;
211762306a36Sopenharmony_ci}
211862306a36Sopenharmony_ci
211962306a36Sopenharmony_cistatic int igbvf_maybe_stop_tx(struct net_device *netdev, int size)
212062306a36Sopenharmony_ci{
212162306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
212262306a36Sopenharmony_ci
212362306a36Sopenharmony_ci	/* there is enough descriptors then we don't need to worry  */
212462306a36Sopenharmony_ci	if (igbvf_desc_unused(adapter->tx_ring) >= size)
212562306a36Sopenharmony_ci		return 0;
212662306a36Sopenharmony_ci
212762306a36Sopenharmony_ci	netif_stop_queue(netdev);
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_ci	/* Herbert's original patch had:
213062306a36Sopenharmony_ci	 *  smp_mb__after_netif_stop_queue();
213162306a36Sopenharmony_ci	 * but since that doesn't exist yet, just open code it.
213262306a36Sopenharmony_ci	 */
213362306a36Sopenharmony_ci	smp_mb();
213462306a36Sopenharmony_ci
213562306a36Sopenharmony_ci	/* We need to check again just in case room has been made available */
213662306a36Sopenharmony_ci	if (igbvf_desc_unused(adapter->tx_ring) < size)
213762306a36Sopenharmony_ci		return -EBUSY;
213862306a36Sopenharmony_ci
213962306a36Sopenharmony_ci	netif_wake_queue(netdev);
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci	++adapter->restart_queue;
214262306a36Sopenharmony_ci	return 0;
214362306a36Sopenharmony_ci}
214462306a36Sopenharmony_ci
214562306a36Sopenharmony_ci#define IGBVF_MAX_TXD_PWR	16
214662306a36Sopenharmony_ci#define IGBVF_MAX_DATA_PER_TXD	(1u << IGBVF_MAX_TXD_PWR)
214762306a36Sopenharmony_ci
214862306a36Sopenharmony_cistatic inline int igbvf_tx_map_adv(struct igbvf_adapter *adapter,
214962306a36Sopenharmony_ci				   struct igbvf_ring *tx_ring,
215062306a36Sopenharmony_ci				   struct sk_buff *skb)
215162306a36Sopenharmony_ci{
215262306a36Sopenharmony_ci	struct igbvf_buffer *buffer_info;
215362306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
215462306a36Sopenharmony_ci	unsigned int len = skb_headlen(skb);
215562306a36Sopenharmony_ci	unsigned int count = 0, i;
215662306a36Sopenharmony_ci	unsigned int f;
215762306a36Sopenharmony_ci
215862306a36Sopenharmony_ci	i = tx_ring->next_to_use;
215962306a36Sopenharmony_ci
216062306a36Sopenharmony_ci	buffer_info = &tx_ring->buffer_info[i];
216162306a36Sopenharmony_ci	BUG_ON(len >= IGBVF_MAX_DATA_PER_TXD);
216262306a36Sopenharmony_ci	buffer_info->length = len;
216362306a36Sopenharmony_ci	/* set time_stamp *before* dma to help avoid a possible race */
216462306a36Sopenharmony_ci	buffer_info->time_stamp = jiffies;
216562306a36Sopenharmony_ci	buffer_info->mapped_as_page = false;
216662306a36Sopenharmony_ci	buffer_info->dma = dma_map_single(&pdev->dev, skb->data, len,
216762306a36Sopenharmony_ci					  DMA_TO_DEVICE);
216862306a36Sopenharmony_ci	if (dma_mapping_error(&pdev->dev, buffer_info->dma))
216962306a36Sopenharmony_ci		goto dma_error;
217062306a36Sopenharmony_ci
217162306a36Sopenharmony_ci	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++) {
217262306a36Sopenharmony_ci		const skb_frag_t *frag;
217362306a36Sopenharmony_ci
217462306a36Sopenharmony_ci		count++;
217562306a36Sopenharmony_ci		i++;
217662306a36Sopenharmony_ci		if (i == tx_ring->count)
217762306a36Sopenharmony_ci			i = 0;
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_ci		frag = &skb_shinfo(skb)->frags[f];
218062306a36Sopenharmony_ci		len = skb_frag_size(frag);
218162306a36Sopenharmony_ci
218262306a36Sopenharmony_ci		buffer_info = &tx_ring->buffer_info[i];
218362306a36Sopenharmony_ci		BUG_ON(len >= IGBVF_MAX_DATA_PER_TXD);
218462306a36Sopenharmony_ci		buffer_info->length = len;
218562306a36Sopenharmony_ci		buffer_info->time_stamp = jiffies;
218662306a36Sopenharmony_ci		buffer_info->mapped_as_page = true;
218762306a36Sopenharmony_ci		buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag, 0, len,
218862306a36Sopenharmony_ci						    DMA_TO_DEVICE);
218962306a36Sopenharmony_ci		if (dma_mapping_error(&pdev->dev, buffer_info->dma))
219062306a36Sopenharmony_ci			goto dma_error;
219162306a36Sopenharmony_ci	}
219262306a36Sopenharmony_ci
219362306a36Sopenharmony_ci	tx_ring->buffer_info[i].skb = skb;
219462306a36Sopenharmony_ci
219562306a36Sopenharmony_ci	return ++count;
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_cidma_error:
219862306a36Sopenharmony_ci	dev_err(&pdev->dev, "TX DMA map failed\n");
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_ci	/* clear timestamp and dma mappings for failed buffer_info mapping */
220162306a36Sopenharmony_ci	buffer_info->dma = 0;
220262306a36Sopenharmony_ci	buffer_info->time_stamp = 0;
220362306a36Sopenharmony_ci	buffer_info->length = 0;
220462306a36Sopenharmony_ci	buffer_info->mapped_as_page = false;
220562306a36Sopenharmony_ci	if (count)
220662306a36Sopenharmony_ci		count--;
220762306a36Sopenharmony_ci
220862306a36Sopenharmony_ci	/* clear timestamp and dma mappings for remaining portion of packet */
220962306a36Sopenharmony_ci	while (count--) {
221062306a36Sopenharmony_ci		if (i == 0)
221162306a36Sopenharmony_ci			i += tx_ring->count;
221262306a36Sopenharmony_ci		i--;
221362306a36Sopenharmony_ci		buffer_info = &tx_ring->buffer_info[i];
221462306a36Sopenharmony_ci		igbvf_put_txbuf(adapter, buffer_info);
221562306a36Sopenharmony_ci	}
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_ci	return 0;
221862306a36Sopenharmony_ci}
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_cistatic inline void igbvf_tx_queue_adv(struct igbvf_adapter *adapter,
222162306a36Sopenharmony_ci				      struct igbvf_ring *tx_ring,
222262306a36Sopenharmony_ci				      int tx_flags, int count,
222362306a36Sopenharmony_ci				      unsigned int first, u32 paylen,
222462306a36Sopenharmony_ci				      u8 hdr_len)
222562306a36Sopenharmony_ci{
222662306a36Sopenharmony_ci	union e1000_adv_tx_desc *tx_desc = NULL;
222762306a36Sopenharmony_ci	struct igbvf_buffer *buffer_info;
222862306a36Sopenharmony_ci	u32 olinfo_status = 0, cmd_type_len;
222962306a36Sopenharmony_ci	unsigned int i;
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_ci	cmd_type_len = (E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_IFCS |
223262306a36Sopenharmony_ci			E1000_ADVTXD_DCMD_DEXT);
223362306a36Sopenharmony_ci
223462306a36Sopenharmony_ci	if (tx_flags & IGBVF_TX_FLAGS_VLAN)
223562306a36Sopenharmony_ci		cmd_type_len |= E1000_ADVTXD_DCMD_VLE;
223662306a36Sopenharmony_ci
223762306a36Sopenharmony_ci	if (tx_flags & IGBVF_TX_FLAGS_TSO) {
223862306a36Sopenharmony_ci		cmd_type_len |= E1000_ADVTXD_DCMD_TSE;
223962306a36Sopenharmony_ci
224062306a36Sopenharmony_ci		/* insert tcp checksum */
224162306a36Sopenharmony_ci		olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
224262306a36Sopenharmony_ci
224362306a36Sopenharmony_ci		/* insert ip checksum */
224462306a36Sopenharmony_ci		if (tx_flags & IGBVF_TX_FLAGS_IPV4)
224562306a36Sopenharmony_ci			olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_ci	} else if (tx_flags & IGBVF_TX_FLAGS_CSUM) {
224862306a36Sopenharmony_ci		olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
224962306a36Sopenharmony_ci	}
225062306a36Sopenharmony_ci
225162306a36Sopenharmony_ci	olinfo_status |= ((paylen - hdr_len) << E1000_ADVTXD_PAYLEN_SHIFT);
225262306a36Sopenharmony_ci
225362306a36Sopenharmony_ci	i = tx_ring->next_to_use;
225462306a36Sopenharmony_ci	while (count--) {
225562306a36Sopenharmony_ci		buffer_info = &tx_ring->buffer_info[i];
225662306a36Sopenharmony_ci		tx_desc = IGBVF_TX_DESC_ADV(*tx_ring, i);
225762306a36Sopenharmony_ci		tx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
225862306a36Sopenharmony_ci		tx_desc->read.cmd_type_len =
225962306a36Sopenharmony_ci			 cpu_to_le32(cmd_type_len | buffer_info->length);
226062306a36Sopenharmony_ci		tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
226162306a36Sopenharmony_ci		i++;
226262306a36Sopenharmony_ci		if (i == tx_ring->count)
226362306a36Sopenharmony_ci			i = 0;
226462306a36Sopenharmony_ci	}
226562306a36Sopenharmony_ci
226662306a36Sopenharmony_ci	tx_desc->read.cmd_type_len |= cpu_to_le32(adapter->txd_cmd);
226762306a36Sopenharmony_ci	/* Force memory writes to complete before letting h/w
226862306a36Sopenharmony_ci	 * know there are new descriptors to fetch.  (Only
226962306a36Sopenharmony_ci	 * applicable for weak-ordered memory model archs,
227062306a36Sopenharmony_ci	 * such as IA-64).
227162306a36Sopenharmony_ci	 */
227262306a36Sopenharmony_ci	wmb();
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_ci	tx_ring->buffer_info[first].next_to_watch = tx_desc;
227562306a36Sopenharmony_ci	tx_ring->next_to_use = i;
227662306a36Sopenharmony_ci	writel(i, adapter->hw.hw_addr + tx_ring->tail);
227762306a36Sopenharmony_ci}
227862306a36Sopenharmony_ci
227962306a36Sopenharmony_cistatic netdev_tx_t igbvf_xmit_frame_ring_adv(struct sk_buff *skb,
228062306a36Sopenharmony_ci					     struct net_device *netdev,
228162306a36Sopenharmony_ci					     struct igbvf_ring *tx_ring)
228262306a36Sopenharmony_ci{
228362306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
228462306a36Sopenharmony_ci	unsigned int first, tx_flags = 0;
228562306a36Sopenharmony_ci	u8 hdr_len = 0;
228662306a36Sopenharmony_ci	int count = 0;
228762306a36Sopenharmony_ci	int tso = 0;
228862306a36Sopenharmony_ci	__be16 protocol = vlan_get_protocol(skb);
228962306a36Sopenharmony_ci
229062306a36Sopenharmony_ci	if (test_bit(__IGBVF_DOWN, &adapter->state)) {
229162306a36Sopenharmony_ci		dev_kfree_skb_any(skb);
229262306a36Sopenharmony_ci		return NETDEV_TX_OK;
229362306a36Sopenharmony_ci	}
229462306a36Sopenharmony_ci
229562306a36Sopenharmony_ci	if (skb->len <= 0) {
229662306a36Sopenharmony_ci		dev_kfree_skb_any(skb);
229762306a36Sopenharmony_ci		return NETDEV_TX_OK;
229862306a36Sopenharmony_ci	}
229962306a36Sopenharmony_ci
230062306a36Sopenharmony_ci	/* need: count + 4 desc gap to keep tail from touching
230162306a36Sopenharmony_ci	 *       + 2 desc gap to keep tail from touching head,
230262306a36Sopenharmony_ci	 *       + 1 desc for skb->data,
230362306a36Sopenharmony_ci	 *       + 1 desc for context descriptor,
230462306a36Sopenharmony_ci	 * head, otherwise try next time
230562306a36Sopenharmony_ci	 */
230662306a36Sopenharmony_ci	if (igbvf_maybe_stop_tx(netdev, skb_shinfo(skb)->nr_frags + 4)) {
230762306a36Sopenharmony_ci		/* this is a hard error */
230862306a36Sopenharmony_ci		return NETDEV_TX_BUSY;
230962306a36Sopenharmony_ci	}
231062306a36Sopenharmony_ci
231162306a36Sopenharmony_ci	if (skb_vlan_tag_present(skb)) {
231262306a36Sopenharmony_ci		tx_flags |= IGBVF_TX_FLAGS_VLAN;
231362306a36Sopenharmony_ci		tx_flags |= (skb_vlan_tag_get(skb) <<
231462306a36Sopenharmony_ci			     IGBVF_TX_FLAGS_VLAN_SHIFT);
231562306a36Sopenharmony_ci	}
231662306a36Sopenharmony_ci
231762306a36Sopenharmony_ci	if (protocol == htons(ETH_P_IP))
231862306a36Sopenharmony_ci		tx_flags |= IGBVF_TX_FLAGS_IPV4;
231962306a36Sopenharmony_ci
232062306a36Sopenharmony_ci	first = tx_ring->next_to_use;
232162306a36Sopenharmony_ci
232262306a36Sopenharmony_ci	tso = igbvf_tso(tx_ring, skb, tx_flags, &hdr_len);
232362306a36Sopenharmony_ci	if (unlikely(tso < 0)) {
232462306a36Sopenharmony_ci		dev_kfree_skb_any(skb);
232562306a36Sopenharmony_ci		return NETDEV_TX_OK;
232662306a36Sopenharmony_ci	}
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_ci	if (tso)
232962306a36Sopenharmony_ci		tx_flags |= IGBVF_TX_FLAGS_TSO;
233062306a36Sopenharmony_ci	else if (igbvf_tx_csum(tx_ring, skb, tx_flags, protocol) &&
233162306a36Sopenharmony_ci		 (skb->ip_summed == CHECKSUM_PARTIAL))
233262306a36Sopenharmony_ci		tx_flags |= IGBVF_TX_FLAGS_CSUM;
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci	/* count reflects descriptors mapped, if 0 then mapping error
233562306a36Sopenharmony_ci	 * has occurred and we need to rewind the descriptor queue
233662306a36Sopenharmony_ci	 */
233762306a36Sopenharmony_ci	count = igbvf_tx_map_adv(adapter, tx_ring, skb);
233862306a36Sopenharmony_ci
233962306a36Sopenharmony_ci	if (count) {
234062306a36Sopenharmony_ci		igbvf_tx_queue_adv(adapter, tx_ring, tx_flags, count,
234162306a36Sopenharmony_ci				   first, skb->len, hdr_len);
234262306a36Sopenharmony_ci		/* Make sure there is space in the ring for the next send. */
234362306a36Sopenharmony_ci		igbvf_maybe_stop_tx(netdev, MAX_SKB_FRAGS + 4);
234462306a36Sopenharmony_ci	} else {
234562306a36Sopenharmony_ci		dev_kfree_skb_any(skb);
234662306a36Sopenharmony_ci		tx_ring->buffer_info[first].time_stamp = 0;
234762306a36Sopenharmony_ci		tx_ring->next_to_use = first;
234862306a36Sopenharmony_ci	}
234962306a36Sopenharmony_ci
235062306a36Sopenharmony_ci	return NETDEV_TX_OK;
235162306a36Sopenharmony_ci}
235262306a36Sopenharmony_ci
235362306a36Sopenharmony_cistatic netdev_tx_t igbvf_xmit_frame(struct sk_buff *skb,
235462306a36Sopenharmony_ci				    struct net_device *netdev)
235562306a36Sopenharmony_ci{
235662306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
235762306a36Sopenharmony_ci	struct igbvf_ring *tx_ring;
235862306a36Sopenharmony_ci
235962306a36Sopenharmony_ci	if (test_bit(__IGBVF_DOWN, &adapter->state)) {
236062306a36Sopenharmony_ci		dev_kfree_skb_any(skb);
236162306a36Sopenharmony_ci		return NETDEV_TX_OK;
236262306a36Sopenharmony_ci	}
236362306a36Sopenharmony_ci
236462306a36Sopenharmony_ci	tx_ring = &adapter->tx_ring[0];
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci	return igbvf_xmit_frame_ring_adv(skb, netdev, tx_ring);
236762306a36Sopenharmony_ci}
236862306a36Sopenharmony_ci
236962306a36Sopenharmony_ci/**
237062306a36Sopenharmony_ci * igbvf_tx_timeout - Respond to a Tx Hang
237162306a36Sopenharmony_ci * @netdev: network interface device structure
237262306a36Sopenharmony_ci * @txqueue: queue timing out (unused)
237362306a36Sopenharmony_ci **/
237462306a36Sopenharmony_cistatic void igbvf_tx_timeout(struct net_device *netdev, unsigned int __always_unused txqueue)
237562306a36Sopenharmony_ci{
237662306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_ci	/* Do the reset outside of interrupt context */
237962306a36Sopenharmony_ci	adapter->tx_timeout_count++;
238062306a36Sopenharmony_ci	schedule_work(&adapter->reset_task);
238162306a36Sopenharmony_ci}
238262306a36Sopenharmony_ci
238362306a36Sopenharmony_cistatic void igbvf_reset_task(struct work_struct *work)
238462306a36Sopenharmony_ci{
238562306a36Sopenharmony_ci	struct igbvf_adapter *adapter;
238662306a36Sopenharmony_ci
238762306a36Sopenharmony_ci	adapter = container_of(work, struct igbvf_adapter, reset_task);
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci	igbvf_reinit_locked(adapter);
239062306a36Sopenharmony_ci}
239162306a36Sopenharmony_ci
239262306a36Sopenharmony_ci/**
239362306a36Sopenharmony_ci * igbvf_change_mtu - Change the Maximum Transfer Unit
239462306a36Sopenharmony_ci * @netdev: network interface device structure
239562306a36Sopenharmony_ci * @new_mtu: new value for maximum frame size
239662306a36Sopenharmony_ci *
239762306a36Sopenharmony_ci * Returns 0 on success, negative on failure
239862306a36Sopenharmony_ci **/
239962306a36Sopenharmony_cistatic int igbvf_change_mtu(struct net_device *netdev, int new_mtu)
240062306a36Sopenharmony_ci{
240162306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
240262306a36Sopenharmony_ci	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
240362306a36Sopenharmony_ci
240462306a36Sopenharmony_ci	while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
240562306a36Sopenharmony_ci		usleep_range(1000, 2000);
240662306a36Sopenharmony_ci	/* igbvf_down has a dependency on max_frame_size */
240762306a36Sopenharmony_ci	adapter->max_frame_size = max_frame;
240862306a36Sopenharmony_ci	if (netif_running(netdev))
240962306a36Sopenharmony_ci		igbvf_down(adapter);
241062306a36Sopenharmony_ci
241162306a36Sopenharmony_ci	/* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
241262306a36Sopenharmony_ci	 * means we reserve 2 more, this pushes us to allocate from the next
241362306a36Sopenharmony_ci	 * larger slab size.
241462306a36Sopenharmony_ci	 * i.e. RXBUFFER_2048 --> size-4096 slab
241562306a36Sopenharmony_ci	 * However with the new *_jumbo_rx* routines, jumbo receives will use
241662306a36Sopenharmony_ci	 * fragmented skbs
241762306a36Sopenharmony_ci	 */
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_ci	if (max_frame <= 1024)
242062306a36Sopenharmony_ci		adapter->rx_buffer_len = 1024;
242162306a36Sopenharmony_ci	else if (max_frame <= 2048)
242262306a36Sopenharmony_ci		adapter->rx_buffer_len = 2048;
242362306a36Sopenharmony_ci	else
242462306a36Sopenharmony_ci#if (PAGE_SIZE / 2) > 16384
242562306a36Sopenharmony_ci		adapter->rx_buffer_len = 16384;
242662306a36Sopenharmony_ci#else
242762306a36Sopenharmony_ci		adapter->rx_buffer_len = PAGE_SIZE / 2;
242862306a36Sopenharmony_ci#endif
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_ci	/* adjust allocation if LPE protects us, and we aren't using SBP */
243162306a36Sopenharmony_ci	if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) ||
243262306a36Sopenharmony_ci	    (max_frame == ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN))
243362306a36Sopenharmony_ci		adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN +
243462306a36Sopenharmony_ci					 ETH_FCS_LEN;
243562306a36Sopenharmony_ci
243662306a36Sopenharmony_ci	netdev_dbg(netdev, "changing MTU from %d to %d\n",
243762306a36Sopenharmony_ci		   netdev->mtu, new_mtu);
243862306a36Sopenharmony_ci	netdev->mtu = new_mtu;
243962306a36Sopenharmony_ci
244062306a36Sopenharmony_ci	if (netif_running(netdev))
244162306a36Sopenharmony_ci		igbvf_up(adapter);
244262306a36Sopenharmony_ci	else
244362306a36Sopenharmony_ci		igbvf_reset(adapter);
244462306a36Sopenharmony_ci
244562306a36Sopenharmony_ci	clear_bit(__IGBVF_RESETTING, &adapter->state);
244662306a36Sopenharmony_ci
244762306a36Sopenharmony_ci	return 0;
244862306a36Sopenharmony_ci}
244962306a36Sopenharmony_ci
245062306a36Sopenharmony_cistatic int igbvf_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
245162306a36Sopenharmony_ci{
245262306a36Sopenharmony_ci	switch (cmd) {
245362306a36Sopenharmony_ci	default:
245462306a36Sopenharmony_ci		return -EOPNOTSUPP;
245562306a36Sopenharmony_ci	}
245662306a36Sopenharmony_ci}
245762306a36Sopenharmony_ci
245862306a36Sopenharmony_cistatic int igbvf_suspend(struct device *dev_d)
245962306a36Sopenharmony_ci{
246062306a36Sopenharmony_ci	struct net_device *netdev = dev_get_drvdata(dev_d);
246162306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
246262306a36Sopenharmony_ci
246362306a36Sopenharmony_ci	netif_device_detach(netdev);
246462306a36Sopenharmony_ci
246562306a36Sopenharmony_ci	if (netif_running(netdev)) {
246662306a36Sopenharmony_ci		WARN_ON(test_bit(__IGBVF_RESETTING, &adapter->state));
246762306a36Sopenharmony_ci		igbvf_down(adapter);
246862306a36Sopenharmony_ci		igbvf_free_irq(adapter);
246962306a36Sopenharmony_ci	}
247062306a36Sopenharmony_ci
247162306a36Sopenharmony_ci	return 0;
247262306a36Sopenharmony_ci}
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_cistatic int __maybe_unused igbvf_resume(struct device *dev_d)
247562306a36Sopenharmony_ci{
247662306a36Sopenharmony_ci	struct pci_dev *pdev = to_pci_dev(dev_d);
247762306a36Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
247862306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
247962306a36Sopenharmony_ci	u32 err;
248062306a36Sopenharmony_ci
248162306a36Sopenharmony_ci	pci_set_master(pdev);
248262306a36Sopenharmony_ci
248362306a36Sopenharmony_ci	if (netif_running(netdev)) {
248462306a36Sopenharmony_ci		err = igbvf_request_irq(adapter);
248562306a36Sopenharmony_ci		if (err)
248662306a36Sopenharmony_ci			return err;
248762306a36Sopenharmony_ci	}
248862306a36Sopenharmony_ci
248962306a36Sopenharmony_ci	igbvf_reset(adapter);
249062306a36Sopenharmony_ci
249162306a36Sopenharmony_ci	if (netif_running(netdev))
249262306a36Sopenharmony_ci		igbvf_up(adapter);
249362306a36Sopenharmony_ci
249462306a36Sopenharmony_ci	netif_device_attach(netdev);
249562306a36Sopenharmony_ci
249662306a36Sopenharmony_ci	return 0;
249762306a36Sopenharmony_ci}
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_cistatic void igbvf_shutdown(struct pci_dev *pdev)
250062306a36Sopenharmony_ci{
250162306a36Sopenharmony_ci	igbvf_suspend(&pdev->dev);
250262306a36Sopenharmony_ci}
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
250562306a36Sopenharmony_ci/* Polling 'interrupt' - used by things like netconsole to send skbs
250662306a36Sopenharmony_ci * without having to re-enable interrupts. It's not called while
250762306a36Sopenharmony_ci * the interrupt routine is executing.
250862306a36Sopenharmony_ci */
250962306a36Sopenharmony_cistatic void igbvf_netpoll(struct net_device *netdev)
251062306a36Sopenharmony_ci{
251162306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
251262306a36Sopenharmony_ci
251362306a36Sopenharmony_ci	disable_irq(adapter->pdev->irq);
251462306a36Sopenharmony_ci
251562306a36Sopenharmony_ci	igbvf_clean_tx_irq(adapter->tx_ring);
251662306a36Sopenharmony_ci
251762306a36Sopenharmony_ci	enable_irq(adapter->pdev->irq);
251862306a36Sopenharmony_ci}
251962306a36Sopenharmony_ci#endif
252062306a36Sopenharmony_ci
252162306a36Sopenharmony_ci/**
252262306a36Sopenharmony_ci * igbvf_io_error_detected - called when PCI error is detected
252362306a36Sopenharmony_ci * @pdev: Pointer to PCI device
252462306a36Sopenharmony_ci * @state: The current pci connection state
252562306a36Sopenharmony_ci *
252662306a36Sopenharmony_ci * This function is called after a PCI bus error affecting
252762306a36Sopenharmony_ci * this device has been detected.
252862306a36Sopenharmony_ci */
252962306a36Sopenharmony_cistatic pci_ers_result_t igbvf_io_error_detected(struct pci_dev *pdev,
253062306a36Sopenharmony_ci						pci_channel_state_t state)
253162306a36Sopenharmony_ci{
253262306a36Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
253362306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
253462306a36Sopenharmony_ci
253562306a36Sopenharmony_ci	netif_device_detach(netdev);
253662306a36Sopenharmony_ci
253762306a36Sopenharmony_ci	if (state == pci_channel_io_perm_failure)
253862306a36Sopenharmony_ci		return PCI_ERS_RESULT_DISCONNECT;
253962306a36Sopenharmony_ci
254062306a36Sopenharmony_ci	if (netif_running(netdev))
254162306a36Sopenharmony_ci		igbvf_down(adapter);
254262306a36Sopenharmony_ci	pci_disable_device(pdev);
254362306a36Sopenharmony_ci
254462306a36Sopenharmony_ci	/* Request a slot reset. */
254562306a36Sopenharmony_ci	return PCI_ERS_RESULT_NEED_RESET;
254662306a36Sopenharmony_ci}
254762306a36Sopenharmony_ci
254862306a36Sopenharmony_ci/**
254962306a36Sopenharmony_ci * igbvf_io_slot_reset - called after the pci bus has been reset.
255062306a36Sopenharmony_ci * @pdev: Pointer to PCI device
255162306a36Sopenharmony_ci *
255262306a36Sopenharmony_ci * Restart the card from scratch, as if from a cold-boot. Implementation
255362306a36Sopenharmony_ci * resembles the first-half of the igbvf_resume routine.
255462306a36Sopenharmony_ci */
255562306a36Sopenharmony_cistatic pci_ers_result_t igbvf_io_slot_reset(struct pci_dev *pdev)
255662306a36Sopenharmony_ci{
255762306a36Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
255862306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
255962306a36Sopenharmony_ci
256062306a36Sopenharmony_ci	if (pci_enable_device_mem(pdev)) {
256162306a36Sopenharmony_ci		dev_err(&pdev->dev,
256262306a36Sopenharmony_ci			"Cannot re-enable PCI device after reset.\n");
256362306a36Sopenharmony_ci		return PCI_ERS_RESULT_DISCONNECT;
256462306a36Sopenharmony_ci	}
256562306a36Sopenharmony_ci	pci_set_master(pdev);
256662306a36Sopenharmony_ci
256762306a36Sopenharmony_ci	igbvf_reset(adapter);
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_ci	return PCI_ERS_RESULT_RECOVERED;
257062306a36Sopenharmony_ci}
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_ci/**
257362306a36Sopenharmony_ci * igbvf_io_resume - called when traffic can start flowing again.
257462306a36Sopenharmony_ci * @pdev: Pointer to PCI device
257562306a36Sopenharmony_ci *
257662306a36Sopenharmony_ci * This callback is called when the error recovery driver tells us that
257762306a36Sopenharmony_ci * its OK to resume normal operation. Implementation resembles the
257862306a36Sopenharmony_ci * second-half of the igbvf_resume routine.
257962306a36Sopenharmony_ci */
258062306a36Sopenharmony_cistatic void igbvf_io_resume(struct pci_dev *pdev)
258162306a36Sopenharmony_ci{
258262306a36Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
258362306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
258462306a36Sopenharmony_ci
258562306a36Sopenharmony_ci	if (netif_running(netdev)) {
258662306a36Sopenharmony_ci		if (igbvf_up(adapter)) {
258762306a36Sopenharmony_ci			dev_err(&pdev->dev,
258862306a36Sopenharmony_ci				"can't bring device back up after reset\n");
258962306a36Sopenharmony_ci			return;
259062306a36Sopenharmony_ci		}
259162306a36Sopenharmony_ci	}
259262306a36Sopenharmony_ci
259362306a36Sopenharmony_ci	netif_device_attach(netdev);
259462306a36Sopenharmony_ci}
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci/**
259762306a36Sopenharmony_ci * igbvf_io_prepare - prepare device driver for PCI reset
259862306a36Sopenharmony_ci * @pdev: PCI device information struct
259962306a36Sopenharmony_ci */
260062306a36Sopenharmony_cistatic void igbvf_io_prepare(struct pci_dev *pdev)
260162306a36Sopenharmony_ci{
260262306a36Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
260362306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
260462306a36Sopenharmony_ci
260562306a36Sopenharmony_ci	while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
260662306a36Sopenharmony_ci		usleep_range(1000, 2000);
260762306a36Sopenharmony_ci	igbvf_down(adapter);
260862306a36Sopenharmony_ci}
260962306a36Sopenharmony_ci
261062306a36Sopenharmony_ci/**
261162306a36Sopenharmony_ci * igbvf_io_reset_done - PCI reset done, device driver reset can begin
261262306a36Sopenharmony_ci * @pdev: PCI device information struct
261362306a36Sopenharmony_ci */
261462306a36Sopenharmony_cistatic void igbvf_io_reset_done(struct pci_dev *pdev)
261562306a36Sopenharmony_ci{
261662306a36Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
261762306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
261862306a36Sopenharmony_ci
261962306a36Sopenharmony_ci	igbvf_up(adapter);
262062306a36Sopenharmony_ci	clear_bit(__IGBVF_RESETTING, &adapter->state);
262162306a36Sopenharmony_ci}
262262306a36Sopenharmony_ci
262362306a36Sopenharmony_cistatic void igbvf_print_device_info(struct igbvf_adapter *adapter)
262462306a36Sopenharmony_ci{
262562306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
262662306a36Sopenharmony_ci	struct net_device *netdev = adapter->netdev;
262762306a36Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
262862306a36Sopenharmony_ci
262962306a36Sopenharmony_ci	if (hw->mac.type == e1000_vfadapt_i350)
263062306a36Sopenharmony_ci		dev_info(&pdev->dev, "Intel(R) I350 Virtual Function\n");
263162306a36Sopenharmony_ci	else
263262306a36Sopenharmony_ci		dev_info(&pdev->dev, "Intel(R) 82576 Virtual Function\n");
263362306a36Sopenharmony_ci	dev_info(&pdev->dev, "Address: %pM\n", netdev->dev_addr);
263462306a36Sopenharmony_ci}
263562306a36Sopenharmony_ci
263662306a36Sopenharmony_cistatic int igbvf_set_features(struct net_device *netdev,
263762306a36Sopenharmony_ci			      netdev_features_t features)
263862306a36Sopenharmony_ci{
263962306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
264062306a36Sopenharmony_ci
264162306a36Sopenharmony_ci	if (features & NETIF_F_RXCSUM)
264262306a36Sopenharmony_ci		adapter->flags &= ~IGBVF_FLAG_RX_CSUM_DISABLED;
264362306a36Sopenharmony_ci	else
264462306a36Sopenharmony_ci		adapter->flags |= IGBVF_FLAG_RX_CSUM_DISABLED;
264562306a36Sopenharmony_ci
264662306a36Sopenharmony_ci	return 0;
264762306a36Sopenharmony_ci}
264862306a36Sopenharmony_ci
264962306a36Sopenharmony_ci#define IGBVF_MAX_MAC_HDR_LEN		127
265062306a36Sopenharmony_ci#define IGBVF_MAX_NETWORK_HDR_LEN	511
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_cistatic netdev_features_t
265362306a36Sopenharmony_ciigbvf_features_check(struct sk_buff *skb, struct net_device *dev,
265462306a36Sopenharmony_ci		     netdev_features_t features)
265562306a36Sopenharmony_ci{
265662306a36Sopenharmony_ci	unsigned int network_hdr_len, mac_hdr_len;
265762306a36Sopenharmony_ci
265862306a36Sopenharmony_ci	/* Make certain the headers can be described by a context descriptor */
265962306a36Sopenharmony_ci	mac_hdr_len = skb_network_header(skb) - skb->data;
266062306a36Sopenharmony_ci	if (unlikely(mac_hdr_len > IGBVF_MAX_MAC_HDR_LEN))
266162306a36Sopenharmony_ci		return features & ~(NETIF_F_HW_CSUM |
266262306a36Sopenharmony_ci				    NETIF_F_SCTP_CRC |
266362306a36Sopenharmony_ci				    NETIF_F_HW_VLAN_CTAG_TX |
266462306a36Sopenharmony_ci				    NETIF_F_TSO |
266562306a36Sopenharmony_ci				    NETIF_F_TSO6);
266662306a36Sopenharmony_ci
266762306a36Sopenharmony_ci	network_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);
266862306a36Sopenharmony_ci	if (unlikely(network_hdr_len >  IGBVF_MAX_NETWORK_HDR_LEN))
266962306a36Sopenharmony_ci		return features & ~(NETIF_F_HW_CSUM |
267062306a36Sopenharmony_ci				    NETIF_F_SCTP_CRC |
267162306a36Sopenharmony_ci				    NETIF_F_TSO |
267262306a36Sopenharmony_ci				    NETIF_F_TSO6);
267362306a36Sopenharmony_ci
267462306a36Sopenharmony_ci	/* We can only support IPV4 TSO in tunnels if we can mangle the
267562306a36Sopenharmony_ci	 * inner IP ID field, so strip TSO if MANGLEID is not supported.
267662306a36Sopenharmony_ci	 */
267762306a36Sopenharmony_ci	if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))
267862306a36Sopenharmony_ci		features &= ~NETIF_F_TSO;
267962306a36Sopenharmony_ci
268062306a36Sopenharmony_ci	return features;
268162306a36Sopenharmony_ci}
268262306a36Sopenharmony_ci
268362306a36Sopenharmony_cistatic const struct net_device_ops igbvf_netdev_ops = {
268462306a36Sopenharmony_ci	.ndo_open		= igbvf_open,
268562306a36Sopenharmony_ci	.ndo_stop		= igbvf_close,
268662306a36Sopenharmony_ci	.ndo_start_xmit		= igbvf_xmit_frame,
268762306a36Sopenharmony_ci	.ndo_set_rx_mode	= igbvf_set_rx_mode,
268862306a36Sopenharmony_ci	.ndo_set_mac_address	= igbvf_set_mac,
268962306a36Sopenharmony_ci	.ndo_change_mtu		= igbvf_change_mtu,
269062306a36Sopenharmony_ci	.ndo_eth_ioctl		= igbvf_ioctl,
269162306a36Sopenharmony_ci	.ndo_tx_timeout		= igbvf_tx_timeout,
269262306a36Sopenharmony_ci	.ndo_vlan_rx_add_vid	= igbvf_vlan_rx_add_vid,
269362306a36Sopenharmony_ci	.ndo_vlan_rx_kill_vid	= igbvf_vlan_rx_kill_vid,
269462306a36Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
269562306a36Sopenharmony_ci	.ndo_poll_controller	= igbvf_netpoll,
269662306a36Sopenharmony_ci#endif
269762306a36Sopenharmony_ci	.ndo_set_features	= igbvf_set_features,
269862306a36Sopenharmony_ci	.ndo_features_check	= igbvf_features_check,
269962306a36Sopenharmony_ci};
270062306a36Sopenharmony_ci
270162306a36Sopenharmony_ci/**
270262306a36Sopenharmony_ci * igbvf_probe - Device Initialization Routine
270362306a36Sopenharmony_ci * @pdev: PCI device information struct
270462306a36Sopenharmony_ci * @ent: entry in igbvf_pci_tbl
270562306a36Sopenharmony_ci *
270662306a36Sopenharmony_ci * Returns 0 on success, negative on failure
270762306a36Sopenharmony_ci *
270862306a36Sopenharmony_ci * igbvf_probe initializes an adapter identified by a pci_dev structure.
270962306a36Sopenharmony_ci * The OS initialization, configuring of the adapter private structure,
271062306a36Sopenharmony_ci * and a hardware reset occur.
271162306a36Sopenharmony_ci **/
271262306a36Sopenharmony_cistatic int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
271362306a36Sopenharmony_ci{
271462306a36Sopenharmony_ci	struct net_device *netdev;
271562306a36Sopenharmony_ci	struct igbvf_adapter *adapter;
271662306a36Sopenharmony_ci	struct e1000_hw *hw;
271762306a36Sopenharmony_ci	const struct igbvf_info *ei = igbvf_info_tbl[ent->driver_data];
271862306a36Sopenharmony_ci	static int cards_found;
271962306a36Sopenharmony_ci	int err;
272062306a36Sopenharmony_ci
272162306a36Sopenharmony_ci	err = pci_enable_device_mem(pdev);
272262306a36Sopenharmony_ci	if (err)
272362306a36Sopenharmony_ci		return err;
272462306a36Sopenharmony_ci
272562306a36Sopenharmony_ci	err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
272662306a36Sopenharmony_ci	if (err) {
272762306a36Sopenharmony_ci		dev_err(&pdev->dev,
272862306a36Sopenharmony_ci			"No usable DMA configuration, aborting\n");
272962306a36Sopenharmony_ci		goto err_dma;
273062306a36Sopenharmony_ci	}
273162306a36Sopenharmony_ci
273262306a36Sopenharmony_ci	err = pci_request_regions(pdev, igbvf_driver_name);
273362306a36Sopenharmony_ci	if (err)
273462306a36Sopenharmony_ci		goto err_pci_reg;
273562306a36Sopenharmony_ci
273662306a36Sopenharmony_ci	pci_set_master(pdev);
273762306a36Sopenharmony_ci
273862306a36Sopenharmony_ci	err = -ENOMEM;
273962306a36Sopenharmony_ci	netdev = alloc_etherdev(sizeof(struct igbvf_adapter));
274062306a36Sopenharmony_ci	if (!netdev)
274162306a36Sopenharmony_ci		goto err_alloc_etherdev;
274262306a36Sopenharmony_ci
274362306a36Sopenharmony_ci	SET_NETDEV_DEV(netdev, &pdev->dev);
274462306a36Sopenharmony_ci
274562306a36Sopenharmony_ci	pci_set_drvdata(pdev, netdev);
274662306a36Sopenharmony_ci	adapter = netdev_priv(netdev);
274762306a36Sopenharmony_ci	hw = &adapter->hw;
274862306a36Sopenharmony_ci	adapter->netdev = netdev;
274962306a36Sopenharmony_ci	adapter->pdev = pdev;
275062306a36Sopenharmony_ci	adapter->ei = ei;
275162306a36Sopenharmony_ci	adapter->pba = ei->pba;
275262306a36Sopenharmony_ci	adapter->flags = ei->flags;
275362306a36Sopenharmony_ci	adapter->hw.back = adapter;
275462306a36Sopenharmony_ci	adapter->hw.mac.type = ei->mac;
275562306a36Sopenharmony_ci	adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
275662306a36Sopenharmony_ci
275762306a36Sopenharmony_ci	/* PCI config space info */
275862306a36Sopenharmony_ci
275962306a36Sopenharmony_ci	hw->vendor_id = pdev->vendor;
276062306a36Sopenharmony_ci	hw->device_id = pdev->device;
276162306a36Sopenharmony_ci	hw->subsystem_vendor_id = pdev->subsystem_vendor;
276262306a36Sopenharmony_ci	hw->subsystem_device_id = pdev->subsystem_device;
276362306a36Sopenharmony_ci	hw->revision_id = pdev->revision;
276462306a36Sopenharmony_ci
276562306a36Sopenharmony_ci	err = -EIO;
276662306a36Sopenharmony_ci	adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0),
276762306a36Sopenharmony_ci				      pci_resource_len(pdev, 0));
276862306a36Sopenharmony_ci
276962306a36Sopenharmony_ci	if (!adapter->hw.hw_addr)
277062306a36Sopenharmony_ci		goto err_ioremap;
277162306a36Sopenharmony_ci
277262306a36Sopenharmony_ci	if (ei->get_variants) {
277362306a36Sopenharmony_ci		err = ei->get_variants(adapter);
277462306a36Sopenharmony_ci		if (err)
277562306a36Sopenharmony_ci			goto err_get_variants;
277662306a36Sopenharmony_ci	}
277762306a36Sopenharmony_ci
277862306a36Sopenharmony_ci	/* setup adapter struct */
277962306a36Sopenharmony_ci	err = igbvf_sw_init(adapter);
278062306a36Sopenharmony_ci	if (err)
278162306a36Sopenharmony_ci		goto err_sw_init;
278262306a36Sopenharmony_ci
278362306a36Sopenharmony_ci	/* construct the net_device struct */
278462306a36Sopenharmony_ci	netdev->netdev_ops = &igbvf_netdev_ops;
278562306a36Sopenharmony_ci
278662306a36Sopenharmony_ci	igbvf_set_ethtool_ops(netdev);
278762306a36Sopenharmony_ci	netdev->watchdog_timeo = 5 * HZ;
278862306a36Sopenharmony_ci	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
278962306a36Sopenharmony_ci
279062306a36Sopenharmony_ci	adapter->bd_number = cards_found++;
279162306a36Sopenharmony_ci
279262306a36Sopenharmony_ci	netdev->hw_features = NETIF_F_SG |
279362306a36Sopenharmony_ci			      NETIF_F_TSO |
279462306a36Sopenharmony_ci			      NETIF_F_TSO6 |
279562306a36Sopenharmony_ci			      NETIF_F_RXCSUM |
279662306a36Sopenharmony_ci			      NETIF_F_HW_CSUM |
279762306a36Sopenharmony_ci			      NETIF_F_SCTP_CRC;
279862306a36Sopenharmony_ci
279962306a36Sopenharmony_ci#define IGBVF_GSO_PARTIAL_FEATURES (NETIF_F_GSO_GRE | \
280062306a36Sopenharmony_ci				    NETIF_F_GSO_GRE_CSUM | \
280162306a36Sopenharmony_ci				    NETIF_F_GSO_IPXIP4 | \
280262306a36Sopenharmony_ci				    NETIF_F_GSO_IPXIP6 | \
280362306a36Sopenharmony_ci				    NETIF_F_GSO_UDP_TUNNEL | \
280462306a36Sopenharmony_ci				    NETIF_F_GSO_UDP_TUNNEL_CSUM)
280562306a36Sopenharmony_ci
280662306a36Sopenharmony_ci	netdev->gso_partial_features = IGBVF_GSO_PARTIAL_FEATURES;
280762306a36Sopenharmony_ci	netdev->hw_features |= NETIF_F_GSO_PARTIAL |
280862306a36Sopenharmony_ci			       IGBVF_GSO_PARTIAL_FEATURES;
280962306a36Sopenharmony_ci
281062306a36Sopenharmony_ci	netdev->features = netdev->hw_features | NETIF_F_HIGHDMA;
281162306a36Sopenharmony_ci
281262306a36Sopenharmony_ci	netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID;
281362306a36Sopenharmony_ci	netdev->mpls_features |= NETIF_F_HW_CSUM;
281462306a36Sopenharmony_ci	netdev->hw_enc_features |= netdev->vlan_features;
281562306a36Sopenharmony_ci
281662306a36Sopenharmony_ci	/* set this bit last since it cannot be part of vlan_features */
281762306a36Sopenharmony_ci	netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER |
281862306a36Sopenharmony_ci			    NETIF_F_HW_VLAN_CTAG_RX |
281962306a36Sopenharmony_ci			    NETIF_F_HW_VLAN_CTAG_TX;
282062306a36Sopenharmony_ci
282162306a36Sopenharmony_ci	/* MTU range: 68 - 9216 */
282262306a36Sopenharmony_ci	netdev->min_mtu = ETH_MIN_MTU;
282362306a36Sopenharmony_ci	netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
282462306a36Sopenharmony_ci
282562306a36Sopenharmony_ci	spin_lock_bh(&hw->mbx_lock);
282662306a36Sopenharmony_ci
282762306a36Sopenharmony_ci	/*reset the controller to put the device in a known good state */
282862306a36Sopenharmony_ci	err = hw->mac.ops.reset_hw(hw);
282962306a36Sopenharmony_ci	if (err) {
283062306a36Sopenharmony_ci		dev_info(&pdev->dev,
283162306a36Sopenharmony_ci			 "PF still in reset state. Is the PF interface up?\n");
283262306a36Sopenharmony_ci	} else {
283362306a36Sopenharmony_ci		err = hw->mac.ops.read_mac_addr(hw);
283462306a36Sopenharmony_ci		if (err)
283562306a36Sopenharmony_ci			dev_info(&pdev->dev, "Error reading MAC address.\n");
283662306a36Sopenharmony_ci		else if (is_zero_ether_addr(adapter->hw.mac.addr))
283762306a36Sopenharmony_ci			dev_info(&pdev->dev,
283862306a36Sopenharmony_ci				 "MAC address not assigned by administrator.\n");
283962306a36Sopenharmony_ci		eth_hw_addr_set(netdev, adapter->hw.mac.addr);
284062306a36Sopenharmony_ci	}
284162306a36Sopenharmony_ci
284262306a36Sopenharmony_ci	spin_unlock_bh(&hw->mbx_lock);
284362306a36Sopenharmony_ci
284462306a36Sopenharmony_ci	if (!is_valid_ether_addr(netdev->dev_addr)) {
284562306a36Sopenharmony_ci		dev_info(&pdev->dev, "Assigning random MAC address.\n");
284662306a36Sopenharmony_ci		eth_hw_addr_random(netdev);
284762306a36Sopenharmony_ci		memcpy(adapter->hw.mac.addr, netdev->dev_addr,
284862306a36Sopenharmony_ci		       netdev->addr_len);
284962306a36Sopenharmony_ci	}
285062306a36Sopenharmony_ci
285162306a36Sopenharmony_ci	timer_setup(&adapter->watchdog_timer, igbvf_watchdog, 0);
285262306a36Sopenharmony_ci
285362306a36Sopenharmony_ci	INIT_WORK(&adapter->reset_task, igbvf_reset_task);
285462306a36Sopenharmony_ci	INIT_WORK(&adapter->watchdog_task, igbvf_watchdog_task);
285562306a36Sopenharmony_ci
285662306a36Sopenharmony_ci	/* ring size defaults */
285762306a36Sopenharmony_ci	adapter->rx_ring->count = 1024;
285862306a36Sopenharmony_ci	adapter->tx_ring->count = 1024;
285962306a36Sopenharmony_ci
286062306a36Sopenharmony_ci	/* reset the hardware with the new settings */
286162306a36Sopenharmony_ci	igbvf_reset(adapter);
286262306a36Sopenharmony_ci
286362306a36Sopenharmony_ci	/* set hardware-specific flags */
286462306a36Sopenharmony_ci	if (adapter->hw.mac.type == e1000_vfadapt_i350)
286562306a36Sopenharmony_ci		adapter->flags |= IGBVF_FLAG_RX_LB_VLAN_BSWAP;
286662306a36Sopenharmony_ci
286762306a36Sopenharmony_ci	strcpy(netdev->name, "eth%d");
286862306a36Sopenharmony_ci	err = register_netdev(netdev);
286962306a36Sopenharmony_ci	if (err)
287062306a36Sopenharmony_ci		goto err_hw_init;
287162306a36Sopenharmony_ci
287262306a36Sopenharmony_ci	/* tell the stack to leave us alone until igbvf_open() is called */
287362306a36Sopenharmony_ci	netif_carrier_off(netdev);
287462306a36Sopenharmony_ci	netif_stop_queue(netdev);
287562306a36Sopenharmony_ci
287662306a36Sopenharmony_ci	igbvf_print_device_info(adapter);
287762306a36Sopenharmony_ci
287862306a36Sopenharmony_ci	igbvf_initialize_last_counter_stats(adapter);
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_ci	return 0;
288162306a36Sopenharmony_ci
288262306a36Sopenharmony_cierr_hw_init:
288362306a36Sopenharmony_ci	netif_napi_del(&adapter->rx_ring->napi);
288462306a36Sopenharmony_ci	kfree(adapter->tx_ring);
288562306a36Sopenharmony_ci	kfree(adapter->rx_ring);
288662306a36Sopenharmony_cierr_sw_init:
288762306a36Sopenharmony_ci	igbvf_reset_interrupt_capability(adapter);
288862306a36Sopenharmony_cierr_get_variants:
288962306a36Sopenharmony_ci	iounmap(adapter->hw.hw_addr);
289062306a36Sopenharmony_cierr_ioremap:
289162306a36Sopenharmony_ci	free_netdev(netdev);
289262306a36Sopenharmony_cierr_alloc_etherdev:
289362306a36Sopenharmony_ci	pci_release_regions(pdev);
289462306a36Sopenharmony_cierr_pci_reg:
289562306a36Sopenharmony_cierr_dma:
289662306a36Sopenharmony_ci	pci_disable_device(pdev);
289762306a36Sopenharmony_ci	return err;
289862306a36Sopenharmony_ci}
289962306a36Sopenharmony_ci
290062306a36Sopenharmony_ci/**
290162306a36Sopenharmony_ci * igbvf_remove - Device Removal Routine
290262306a36Sopenharmony_ci * @pdev: PCI device information struct
290362306a36Sopenharmony_ci *
290462306a36Sopenharmony_ci * igbvf_remove is called by the PCI subsystem to alert the driver
290562306a36Sopenharmony_ci * that it should release a PCI device.  The could be caused by a
290662306a36Sopenharmony_ci * Hot-Plug event, or because the driver is going to be removed from
290762306a36Sopenharmony_ci * memory.
290862306a36Sopenharmony_ci **/
290962306a36Sopenharmony_cistatic void igbvf_remove(struct pci_dev *pdev)
291062306a36Sopenharmony_ci{
291162306a36Sopenharmony_ci	struct net_device *netdev = pci_get_drvdata(pdev);
291262306a36Sopenharmony_ci	struct igbvf_adapter *adapter = netdev_priv(netdev);
291362306a36Sopenharmony_ci	struct e1000_hw *hw = &adapter->hw;
291462306a36Sopenharmony_ci
291562306a36Sopenharmony_ci	/* The watchdog timer may be rescheduled, so explicitly
291662306a36Sopenharmony_ci	 * disable it from being rescheduled.
291762306a36Sopenharmony_ci	 */
291862306a36Sopenharmony_ci	set_bit(__IGBVF_DOWN, &adapter->state);
291962306a36Sopenharmony_ci	del_timer_sync(&adapter->watchdog_timer);
292062306a36Sopenharmony_ci
292162306a36Sopenharmony_ci	cancel_work_sync(&adapter->reset_task);
292262306a36Sopenharmony_ci	cancel_work_sync(&adapter->watchdog_task);
292362306a36Sopenharmony_ci
292462306a36Sopenharmony_ci	unregister_netdev(netdev);
292562306a36Sopenharmony_ci
292662306a36Sopenharmony_ci	igbvf_reset_interrupt_capability(adapter);
292762306a36Sopenharmony_ci
292862306a36Sopenharmony_ci	/* it is important to delete the NAPI struct prior to freeing the
292962306a36Sopenharmony_ci	 * Rx ring so that you do not end up with null pointer refs
293062306a36Sopenharmony_ci	 */
293162306a36Sopenharmony_ci	netif_napi_del(&adapter->rx_ring->napi);
293262306a36Sopenharmony_ci	kfree(adapter->tx_ring);
293362306a36Sopenharmony_ci	kfree(adapter->rx_ring);
293462306a36Sopenharmony_ci
293562306a36Sopenharmony_ci	iounmap(hw->hw_addr);
293662306a36Sopenharmony_ci	if (hw->flash_address)
293762306a36Sopenharmony_ci		iounmap(hw->flash_address);
293862306a36Sopenharmony_ci	pci_release_regions(pdev);
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_ci	free_netdev(netdev);
294162306a36Sopenharmony_ci
294262306a36Sopenharmony_ci	pci_disable_device(pdev);
294362306a36Sopenharmony_ci}
294462306a36Sopenharmony_ci
294562306a36Sopenharmony_ci/* PCI Error Recovery (ERS) */
294662306a36Sopenharmony_cistatic const struct pci_error_handlers igbvf_err_handler = {
294762306a36Sopenharmony_ci	.error_detected = igbvf_io_error_detected,
294862306a36Sopenharmony_ci	.slot_reset = igbvf_io_slot_reset,
294962306a36Sopenharmony_ci	.resume = igbvf_io_resume,
295062306a36Sopenharmony_ci	.reset_prepare = igbvf_io_prepare,
295162306a36Sopenharmony_ci	.reset_done = igbvf_io_reset_done,
295262306a36Sopenharmony_ci};
295362306a36Sopenharmony_ci
295462306a36Sopenharmony_cistatic const struct pci_device_id igbvf_pci_tbl[] = {
295562306a36Sopenharmony_ci	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_VF), board_vf },
295662306a36Sopenharmony_ci	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_VF), board_i350_vf },
295762306a36Sopenharmony_ci	{ } /* terminate list */
295862306a36Sopenharmony_ci};
295962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, igbvf_pci_tbl);
296062306a36Sopenharmony_ci
296162306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(igbvf_pm_ops, igbvf_suspend, igbvf_resume);
296262306a36Sopenharmony_ci
296362306a36Sopenharmony_ci/* PCI Device API Driver */
296462306a36Sopenharmony_cistatic struct pci_driver igbvf_driver = {
296562306a36Sopenharmony_ci	.name		= igbvf_driver_name,
296662306a36Sopenharmony_ci	.id_table	= igbvf_pci_tbl,
296762306a36Sopenharmony_ci	.probe		= igbvf_probe,
296862306a36Sopenharmony_ci	.remove		= igbvf_remove,
296962306a36Sopenharmony_ci	.driver.pm	= &igbvf_pm_ops,
297062306a36Sopenharmony_ci	.shutdown	= igbvf_shutdown,
297162306a36Sopenharmony_ci	.err_handler	= &igbvf_err_handler
297262306a36Sopenharmony_ci};
297362306a36Sopenharmony_ci
297462306a36Sopenharmony_ci/**
297562306a36Sopenharmony_ci * igbvf_init_module - Driver Registration Routine
297662306a36Sopenharmony_ci *
297762306a36Sopenharmony_ci * igbvf_init_module is the first routine called when the driver is
297862306a36Sopenharmony_ci * loaded. All it does is register with the PCI subsystem.
297962306a36Sopenharmony_ci **/
298062306a36Sopenharmony_cistatic int __init igbvf_init_module(void)
298162306a36Sopenharmony_ci{
298262306a36Sopenharmony_ci	int ret;
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci	pr_info("%s\n", igbvf_driver_string);
298562306a36Sopenharmony_ci	pr_info("%s\n", igbvf_copyright);
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_ci	ret = pci_register_driver(&igbvf_driver);
298862306a36Sopenharmony_ci
298962306a36Sopenharmony_ci	return ret;
299062306a36Sopenharmony_ci}
299162306a36Sopenharmony_cimodule_init(igbvf_init_module);
299262306a36Sopenharmony_ci
299362306a36Sopenharmony_ci/**
299462306a36Sopenharmony_ci * igbvf_exit_module - Driver Exit Cleanup Routine
299562306a36Sopenharmony_ci *
299662306a36Sopenharmony_ci * igbvf_exit_module is called just before the driver is removed
299762306a36Sopenharmony_ci * from memory.
299862306a36Sopenharmony_ci **/
299962306a36Sopenharmony_cistatic void __exit igbvf_exit_module(void)
300062306a36Sopenharmony_ci{
300162306a36Sopenharmony_ci	pci_unregister_driver(&igbvf_driver);
300262306a36Sopenharmony_ci}
300362306a36Sopenharmony_cimodule_exit(igbvf_exit_module);
300462306a36Sopenharmony_ci
300562306a36Sopenharmony_ciMODULE_AUTHOR("Intel Corporation, <e1000-devel@lists.sourceforge.net>");
300662306a36Sopenharmony_ciMODULE_DESCRIPTION("Intel(R) Gigabit Virtual Function Network Driver");
300762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
300862306a36Sopenharmony_ci
300962306a36Sopenharmony_ci/* netdev.c */
3010