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