diff options
author | Greg Rose <gregory.v.rose@intel.com> | 2013-12-21 06:13:06 +0000 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2013-12-31 16:09:05 -0800 |
commit | 5321a21c1c4e3123faa7a6b0b3130bbb158f1c47 (patch) | |
tree | 769803bdd6c73d8262dc2d5e90339fd5cdeeb74b /drivers | |
parent | 62683ab51e487fb6b761ac15b9c0b78c7c3ad431 (diff) |
i40evf: driver core headers
This patch contains the main driver header files, containing structures
and data types specific to the linux driver.
i40e_osdep.h contains some code that helps us adapt our OS agnostic code
to Linux.
Signed-off-by: Mitch Williams <mitch.a.williams@intel.com>
Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40e_osdep.h | 72 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40e_txrx.h | 296 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/i40evf/i40evf.h | 321 |
3 files changed, 689 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/i40evf/i40e_osdep.h b/drivers/net/ethernet/intel/i40evf/i40e_osdep.h new file mode 100644 index 000000000000..622f373b745d --- /dev/null +++ b/drivers/net/ethernet/intel/i40evf/i40e_osdep.h @@ -0,0 +1,72 @@ +/******************************************************************************* + * + * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + ******************************************************************************/ + +#ifndef _I40E_OSDEP_H_ +#define _I40E_OSDEP_H_ + +#include <linux/types.h> +#include <linux/if_ether.h> +#include <linux/if_vlan.h> +#include <linux/tcp.h> +#include <linux/pci.h> + +/* get readq/writeq support for 32 bit kernels, use the low-first version */ +#include <asm-generic/io-64-nonatomic-lo-hi.h> + +/* File to be the magic between shared code and + * actual OS primitives + */ + +#define hw_dbg(hw, S, A...) do {} while (0) + +#define wr32(a, reg, value) writel((value), ((a)->hw_addr + (reg))) +#define rd32(a, reg) readl((a)->hw_addr + (reg)) + +#define wr64(a, reg, value) writeq((value), ((a)->hw_addr + (reg))) +#define rd64(a, reg) readq((a)->hw_addr + (reg)) +#define i40e_flush(a) readl((a)->hw_addr + I40E_VFGEN_RSTAT) + +/* memory allocation tracking */ +struct i40e_dma_mem { + void *va; + dma_addr_t pa; + u32 size; +} __packed; + +#define i40e_allocate_dma_mem(h, m, unused, s, a) \ + i40evf_allocate_dma_mem_d(h, m, s, a) +#define i40e_free_dma_mem(h, m) i40evf_free_dma_mem_d(h, m) + +struct i40e_virt_mem { + void *va; + u32 size; +} __packed; +#define i40e_allocate_virt_mem(h, m, s) i40evf_allocate_virt_mem_d(h, m, s) +#define i40e_free_virt_mem(h, m) i40evf_free_virt_mem_d(h, m) + +#define i40e_debug(h, m, s, ...) i40evf_debug_d(h, m, s, ##__VA_ARGS__) +extern void i40evf_debug_d(void *hw, u32 mask, char *fmt_str, ...) + __attribute__ ((format(gnu_printf, 3, 4))); + +typedef enum i40e_status_code i40e_status; +#endif /* _I40E_OSDEP_H_ */ diff --git a/drivers/net/ethernet/intel/i40evf/i40e_txrx.h b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h new file mode 100644 index 000000000000..10bf49e18d7f --- /dev/null +++ b/drivers/net/ethernet/intel/i40evf/i40e_txrx.h @@ -0,0 +1,296 @@ +/******************************************************************************* + * + * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + ******************************************************************************/ + +#ifndef _I40E_TXRX_H_ +#define _I40E_TXRX_H_ + +/* Interrupt Throttling and Rate Limiting (storm control) Goodies */ + +#define I40E_MAX_ITR 0x0FF0 /* reg uses 2 usec resolution */ +#define I40E_MIN_ITR 0x0004 /* reg uses 2 usec resolution */ +#define I40E_MAX_IRATE 0x03F +#define I40E_MIN_IRATE 0x001 +#define I40E_IRATE_USEC_RESOLUTION 4 +#define I40E_ITR_100K 0x0005 +#define I40E_ITR_20K 0x0019 +#define I40E_ITR_8K 0x003E +#define I40E_ITR_4K 0x007A +#define I40E_ITR_RX_DEF I40E_ITR_8K +#define I40E_ITR_TX_DEF I40E_ITR_4K +#define I40E_ITR_DYNAMIC 0x8000 /* use top bit as a flag */ +#define I40E_MIN_INT_RATE 250 /* ~= 1000000 / (I40E_MAX_ITR * 2) */ +#define I40E_MAX_INT_RATE 500000 /* == 1000000 / (I40E_MIN_ITR * 2) */ +#define I40E_DEFAULT_IRQ_WORK 256 +#define ITR_TO_REG(setting) ((setting & ~I40E_ITR_DYNAMIC) >> 1) +#define ITR_IS_DYNAMIC(setting) (!!(setting & I40E_ITR_DYNAMIC)) +#define ITR_REG_TO_USEC(itr_reg) (itr_reg << 1) + +#define I40E_QUEUE_END_OF_LIST 0x7FF + +/* this enum matches hardware bits and is meant to be used by DYN_CTLN + * registers and QINT registers or more generally anywhere in the manual + * mentioning ITR_INDX, ITR_NONE cannot be used as an index 'n' into any + * register but instead is a special value meaning "don't update" ITR0/1/2. + */ +enum i40e_dyn_idx_t { + I40E_IDX_ITR0 = 0, + I40E_IDX_ITR1 = 1, + I40E_IDX_ITR2 = 2, + I40E_ITR_NONE = 3 /* ITR_NONE must not be used as an index */ +}; + +/* these are indexes into ITRN registers */ +#define I40E_RX_ITR I40E_IDX_ITR0 +#define I40E_TX_ITR I40E_IDX_ITR1 +#define I40E_PE_ITR I40E_IDX_ITR2 + +/* Supported RSS offloads */ +#define I40E_DEFAULT_RSS_HENA ( \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) | \ + ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV4) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) | \ + ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | \ + ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6) | \ + ((u64)1 << I40E_FILTER_PCTYPE_L2_PAYLOAD)) + +/* Supported Rx Buffer Sizes */ +#define I40E_RXBUFFER_512 512 /* Used for packet split */ +#define I40E_RXBUFFER_2048 2048 +#define I40E_RXBUFFER_3072 3072 /* For FCoE MTU of 2158 */ +#define I40E_RXBUFFER_4096 4096 +#define I40E_RXBUFFER_8192 8192 +#define I40E_MAX_RXBUFFER 9728 /* largest size for single descriptor */ + +/* NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN means we + * reserve 2 more, and skb_shared_info adds an additional 384 bytes more, + * this adds up to 512 bytes of extra data meaning the smallest allocation + * we could have is 1K. + * i.e. RXBUFFER_512 --> size-1024 slab + */ +#define I40E_RX_HDR_SIZE I40E_RXBUFFER_512 + +/* How many Rx Buffers do we bundle into one write to the hardware ? */ +#define I40E_RX_BUFFER_WRITE 16 /* Must be power of 2 */ +#define I40E_RX_NEXT_DESC(r, i, n) \ + do { \ + (i)++; \ + if ((i) == (r)->count) \ + i = 0; \ + (n) = I40E_RX_DESC((r), (i)); \ + } while (0) + +#define I40E_RX_NEXT_DESC_PREFETCH(r, i, n) \ + do { \ + I40E_RX_NEXT_DESC((r), (i), (n)); \ + prefetch((n)); \ + } while (0) + +#define i40e_rx_desc i40e_32byte_rx_desc + +#define I40E_MIN_TX_LEN 17 +#define I40E_MAX_DATA_PER_TXD 16383 /* aka 16kB - 1 */ + +/* Tx Descriptors needed, worst case */ +#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), I40E_MAX_DATA_PER_TXD) +#define DESC_NEEDED ((MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE)) + 4) + +#define I40E_TX_FLAGS_CSUM (u32)(1) +#define I40E_TX_FLAGS_HW_VLAN (u32)(1 << 1) +#define I40E_TX_FLAGS_SW_VLAN (u32)(1 << 2) +#define I40E_TX_FLAGS_TSO (u32)(1 << 3) +#define I40E_TX_FLAGS_IPV4 (u32)(1 << 4) +#define I40E_TX_FLAGS_IPV6 (u32)(1 << 5) +#define I40E_TX_FLAGS_FCCRC (u32)(1 << 6) +#define I40E_TX_FLAGS_FSO (u32)(1 << 7) +#define I40E_TX_FLAGS_VLAN_MASK 0xffff0000 +#define I40E_TX_FLAGS_VLAN_PRIO_MASK 0xe0000000 +#define I40E_TX_FLAGS_VLAN_PRIO_SHIFT 29 +#define I40E_TX_FLAGS_VLAN_SHIFT 16 + +struct i40e_tx_buffer { + struct i40e_tx_desc *next_to_watch; + unsigned long time_stamp; + struct sk_buff *skb; + unsigned int bytecount; + unsigned short gso_segs; + DEFINE_DMA_UNMAP_ADDR(dma); + DEFINE_DMA_UNMAP_LEN(len); + u32 tx_flags; +}; + +struct i40e_rx_buffer { + struct sk_buff *skb; + dma_addr_t dma; + struct page *page; + dma_addr_t page_dma; + unsigned int page_offset; +}; + +struct i40e_queue_stats { + u64 packets; + u64 bytes; +}; + +struct i40e_tx_queue_stats { + u64 restart_queue; + u64 tx_busy; + u64 tx_done_old; +}; + +struct i40e_rx_queue_stats { + u64 non_eop_descs; + u64 alloc_page_failed; + u64 alloc_buff_failed; +}; + +enum i40e_ring_state_t { + __I40E_TX_FDIR_INIT_DONE, + __I40E_TX_XPS_INIT_DONE, + __I40E_TX_DETECT_HANG, + __I40E_HANG_CHECK_ARMED, + __I40E_RX_PS_ENABLED, + __I40E_RX_LRO_ENABLED, + __I40E_RX_16BYTE_DESC_ENABLED, +}; + +#define ring_is_ps_enabled(ring) \ + test_bit(__I40E_RX_PS_ENABLED, &(ring)->state) +#define set_ring_ps_enabled(ring) \ + set_bit(__I40E_RX_PS_ENABLED, &(ring)->state) +#define clear_ring_ps_enabled(ring) \ + clear_bit(__I40E_RX_PS_ENABLED, &(ring)->state) +#define check_for_tx_hang(ring) \ + test_bit(__I40E_TX_DETECT_HANG, &(ring)->state) +#define set_check_for_tx_hang(ring) \ + set_bit(__I40E_TX_DETECT_HANG, &(ring)->state) +#define clear_check_for_tx_hang(ring) \ + clear_bit(__I40E_TX_DETECT_HANG, &(ring)->state) +#define ring_is_lro_enabled(ring) \ + test_bit(__I40E_RX_LRO_ENABLED, &(ring)->state) +#define set_ring_lro_enabled(ring) \ + set_bit(__I40E_RX_LRO_ENABLED, &(ring)->state) +#define clear_ring_lro_enabled(ring) \ + clear_bit(__I40E_RX_LRO_ENABLED, &(ring)->state) +#define ring_is_16byte_desc_enabled(ring) \ + test_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state) +#define set_ring_16byte_desc_enabled(ring) \ + set_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state) +#define clear_ring_16byte_desc_enabled(ring) \ + clear_bit(__I40E_RX_16BYTE_DESC_ENABLED, &(ring)->state) + +/* struct that defines a descriptor ring, associated with a VSI */ +struct i40e_ring { + struct i40e_ring *next; /* pointer to next ring in q_vector */ + void *desc; /* Descriptor ring memory */ + struct device *dev; /* Used for DMA mapping */ + struct net_device *netdev; /* netdev ring maps to */ + union { + struct i40e_tx_buffer *tx_bi; + struct i40e_rx_buffer *rx_bi; + }; + unsigned long state; + u16 queue_index; /* Queue number of ring */ + u8 dcb_tc; /* Traffic class of ring */ + u8 __iomem *tail; + + u16 count; /* Number of descriptors */ + u16 reg_idx; /* HW register index of the ring */ + u16 rx_hdr_len; + u16 rx_buf_len; + u8 dtype; +#define I40E_RX_DTYPE_NO_SPLIT 0 +#define I40E_RX_DTYPE_SPLIT_ALWAYS 1 +#define I40E_RX_DTYPE_HEADER_SPLIT 2 + u8 hsplit; +#define I40E_RX_SPLIT_L2 0x1 +#define I40E_RX_SPLIT_IP 0x2 +#define I40E_RX_SPLIT_TCP_UDP 0x4 +#define I40E_RX_SPLIT_SCTP 0x8 + + /* used in interrupt processing */ + u16 next_to_use; + u16 next_to_clean; + + u8 atr_sample_rate; + u8 atr_count; + + bool ring_active; /* is ring online or not */ + + /* stats structs */ + struct i40e_queue_stats stats; + struct u64_stats_sync syncp; + union { + struct i40e_tx_queue_stats tx_stats; + struct i40e_rx_queue_stats rx_stats; + }; + + unsigned int size; /* length of descriptor ring in bytes */ + dma_addr_t dma; /* physical address of ring */ + + struct i40e_vsi *vsi; /* Backreference to associated VSI */ + struct i40e_q_vector *q_vector; /* Backreference to associated vector */ + + struct rcu_head rcu; /* to avoid race on free */ +} ____cacheline_internodealigned_in_smp; + +enum i40e_latency_range { + I40E_LOWEST_LATENCY = 0, + I40E_LOW_LATENCY = 1, + I40E_BULK_LATENCY = 2, +}; + +struct i40e_ring_container { + /* array of pointers to rings */ + struct i40e_ring *ring; + unsigned int total_bytes; /* total bytes processed this int */ + unsigned int total_packets; /* total packets processed this int */ + u16 count; + enum i40e_latency_range latency_range; + u16 itr; +}; + +/* iterator for handling rings in ring container */ +#define i40e_for_each_ring(pos, head) \ + for (pos = (head).ring; pos != NULL; pos = pos->next) + +void i40evf_alloc_rx_buffers(struct i40e_ring *rxr, u16 cleaned_count); +netdev_tx_t i40evf_xmit_frame(struct sk_buff *skb, struct net_device *netdev); +void i40evf_clean_tx_ring(struct i40e_ring *tx_ring); +void i40evf_clean_rx_ring(struct i40e_ring *rx_ring); +int i40evf_setup_tx_descriptors(struct i40e_ring *tx_ring); +int i40evf_setup_rx_descriptors(struct i40e_ring *rx_ring); +void i40evf_free_tx_resources(struct i40e_ring *tx_ring); +void i40evf_free_rx_resources(struct i40e_ring *rx_ring); +int i40evf_napi_poll(struct napi_struct *napi, int budget); +#endif /* _I40E_TXRX_H_ */ diff --git a/drivers/net/ethernet/intel/i40evf/i40evf.h b/drivers/net/ethernet/intel/i40evf/i40evf.h new file mode 100644 index 000000000000..ff6529b288a1 --- /dev/null +++ b/drivers/net/ethernet/intel/i40evf/i40evf.h @@ -0,0 +1,321 @@ +/******************************************************************************* + * + * Intel Ethernet Controller XL710 Family Linux Virtual Function Driver + * Copyright(c) 2013 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + ******************************************************************************/ + +#ifndef _I40EVF_H_ +#define _I40EVF_H_ + +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/aer.h> +#include <linux/netdevice.h> +#include <linux/vmalloc.h> +#include <linux/interrupt.h> +#include <linux/ethtool.h> +#include <linux/if_vlan.h> +#include <linux/ip.h> +#include <linux/tcp.h> +#include <linux/sctp.h> +#include <linux/ipv6.h> +#include <net/ip6_checksum.h> +#include <net/udp.h> +#include <linux/sctp.h> + + +#include "i40e_type.h" +#include "i40e_virtchnl.h" +#include "i40e_txrx.h" + +#define DEFAULT_DEBUG_LEVEL_SHIFT 3 +#define PFX "i40evf: " +#define DPRINTK(nlevel, klevel, fmt, args...) \ + ((void)((NETIF_MSG_##nlevel & adapter->msg_enable) && \ + printk(KERN_##klevel PFX "%s: %s: " fmt, adapter->netdev->name, \ + __func__ , ## args))) + +/* dummy struct to make common code less painful */ +struct i40e_vsi { + struct i40evf_adapter *back; + struct net_device *netdev; + unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; + u16 seid; + u16 id; + unsigned long state; + int base_vector; + u16 work_limit; + /* high bit set means dynamic, use accessor routines to read/write. + * hardware only supports 2us resolution for the ITR registers. + * these values always store the USER setting, and must be converted + * before programming to a register. + */ + u16 rx_itr_setting; + u16 tx_itr_setting; +}; + +/* How many Rx Buffers do we bundle into one write to the hardware ? */ +#define I40EVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */ +#define I40EVF_DEFAULT_TXD 512 +#define I40EVF_DEFAULT_RXD 512 +#define I40EVF_MAX_TXD 4096 +#define I40EVF_MIN_TXD 64 +#define I40EVF_MAX_RXD 4096 +#define I40EVF_MIN_RXD 64 +#define I40EVF_REQ_DESCRIPTOR_MULTIPLE 8 + +/* Supported Rx Buffer Sizes */ +#define I40EVF_RXBUFFER_64 64 /* Used for packet split */ +#define I40EVF_RXBUFFER_128 128 /* Used for packet split */ +#define I40EVF_RXBUFFER_256 256 /* Used for packet split */ +#define I40EVF_RXBUFFER_2048 2048 +#define I40EVF_MAX_RXBUFFER 16384 /* largest size for single descriptor */ +#define I40EVF_MAX_AQ_BUF_SIZE 4096 +#define I40EVF_AQ_LEN 32 +#define I40EVF_AQ_MAX_ERR 10 /* times to try before resetting AQ */ + +#define MAXIMUM_ETHERNET_VLAN_SIZE (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) + +#define I40E_RX_DESC(R, i) (&(((union i40e_32byte_rx_desc *)((R)->desc))[i])) +#define I40E_TX_DESC(R, i) (&(((struct i40e_tx_desc *)((R)->desc))[i])) +#define I40E_TX_CTXTDESC(R, i) \ + (&(((struct i40e_tx_context_desc *)((R)->desc))[i])) +#define MAX_RX_QUEUES 8 +#define MAX_TX_QUEUES MAX_RX_QUEUES + +/* MAX_MSIX_Q_VECTORS of these are allocated, + * but we only use one per queue-specific vector. + */ +struct i40e_q_vector { + struct i40evf_adapter *adapter; + struct i40e_vsi *vsi; + struct napi_struct napi; + unsigned long reg_idx; + struct i40e_ring_container rx; + struct i40e_ring_container tx; + u32 ring_mask; + u8 num_ringpairs; /* total number of ring pairs in vector */ + int v_idx; /* vector index in list */ + char name[IFNAMSIZ + 9]; + cpumask_var_t affinity_mask; +}; + +/* Helper macros to switch between ints/sec and what the register uses. + * And yes, it's the same math going both ways. The lowest value + * supported by all of the i40e hardware is 8. + */ +#define EITR_INTS_PER_SEC_TO_REG(_eitr) \ + ((_eitr) ? (1000000000 / ((_eitr) * 256)) : 8) +#define EITR_REG_TO_INTS_PER_SEC EITR_INTS_PER_SEC_TO_REG + +#define I40EVF_DESC_UNUSED(R) \ + ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ + (R)->next_to_clean - (R)->next_to_use - 1) + +#define I40EVF_RX_DESC_ADV(R, i) \ + (&(((union i40e_adv_rx_desc *)((R).desc))[i])) +#define I40EVF_TX_DESC_ADV(R, i) \ + (&(((union i40e_adv_tx_desc *)((R).desc))[i])) +#define I40EVF_TX_CTXTDESC_ADV(R, i) \ + (&(((struct i40e_adv_tx_context_desc *)((R).desc))[i])) + +#define OTHER_VECTOR 1 +#define NONQ_VECS (OTHER_VECTOR) + +#define MAX_MSIX_Q_VECTORS 4 +#define MAX_MSIX_COUNT 5 + +#define MIN_MSIX_Q_VECTORS 1 +#define MIN_MSIX_COUNT (MIN_MSIX_Q_VECTORS + NONQ_VECS) + +#define I40EVF_QUEUE_END_OF_LIST 0x7FF +#define I40EVF_FREE_VECTOR 0x7FFF +struct i40evf_mac_filter { + struct list_head list; + u8 macaddr[ETH_ALEN]; + bool remove; /* filter needs to be removed */ + bool add; /* filter needs to be added */ +}; + +struct i40evf_vlan_filter { + struct list_head list; + u16 vlan; + bool remove; /* filter needs to be removed */ + bool add; /* filter needs to be added */ +}; + +/* Driver state. The order of these is important! */ +enum i40evf_state_t { + __I40EVF_STARTUP, /* driver loaded, probe complete */ + __I40EVF_FAILED, /* PF communication failed. Fatal. */ + __I40EVF_REMOVE, /* driver is being unloaded */ + __I40EVF_INIT_VERSION_CHECK, /* aq msg sent, awaiting reply */ + __I40EVF_INIT_GET_RESOURCES, /* aq msg sent, awaiting reply */ + __I40EVF_INIT_SW, /* got resources, setting up structs */ + /* Below here, watchdog is running */ + __I40EVF_DOWN, /* ready, can be opened */ + __I40EVF_TESTING, /* in ethtool self-test */ + __I40EVF_RESETTING, /* in reset */ + __I40EVF_RUNNING, /* opened, working */ +}; + +enum i40evf_critical_section_t { + __I40EVF_IN_CRITICAL_TASK, /* cannot be interrupted */ +}; +/* make common code happy */ +#define __I40E_DOWN __I40EVF_DOWN + +/* board specific private data structure */ +struct i40evf_adapter { + struct timer_list watchdog_timer; + struct vlan_group *vlgrp; + struct work_struct reset_task; + struct work_struct adminq_task; + struct delayed_work init_task; + struct i40e_q_vector *q_vector[MAX_MSIX_Q_VECTORS]; + struct list_head vlan_filter_list; + char name[MAX_MSIX_COUNT][IFNAMSIZ + 9]; + + /* Interrupt Throttle Rate */ + u32 itr_setting; + u16 eitr_low; + u16 eitr_high; + + /* TX */ + struct i40e_ring *tx_rings[I40E_MAX_VSI_QP]; + u64 restart_queue; + u64 hw_csum_tx_good; + u64 lsc_int; + u64 hw_tso_ctxt; + u64 hw_tso6_ctxt; + u32 tx_timeout_count; + struct list_head mac_filter_list; +#ifdef DEBUG + bool detect_tx_hung; +#endif /* DEBUG */ + + /* RX */ + struct i40e_ring *rx_rings[I40E_MAX_VSI_QP]; + int txd_count; + int rxd_count; + u64 hw_csum_rx_error; + u64 hw_rx_no_dma_resources; + u64 hw_csum_rx_good; + u64 non_eop_descs; + int num_msix_vectors; + struct msix_entry *msix_entries; + + u64 rx_hdr_split; + + u32 init_state; + volatile unsigned long flags; +#define I40EVF_FLAG_RX_CSUM_ENABLED (u32)(1) +#define I40EVF_FLAG_RX_1BUF_CAPABLE (u32)(1 << 1) +#define I40EVF_FLAG_RX_PS_CAPABLE (u32)(1 << 2) +#define I40EVF_FLAG_RX_PS_ENABLED (u32)(1 << 3) +#define I40EVF_FLAG_IN_NETPOLL (u32)(1 << 4) +#define I40EVF_FLAG_IMIR_ENABLED (u32)(1 << 5) +#define I40EVF_FLAG_MQ_CAPABLE (u32)(1 << 6) +#define I40EVF_FLAG_NEED_LINK_UPDATE (u32)(1 << 7) +/* duplcates for common code */ +#define I40E_FLAG_FDIR_ATR_ENABLED 0 +#define I40E_FLAG_DCB_ENABLED 0 +#define I40E_FLAG_IN_NETPOLL I40EVF_FLAG_IN_NETPOLL +#define I40E_FLAG_RX_CSUM_ENABLED I40EVF_FLAG_RX_CSUM_ENABLED + /* flags for admin queue service task */ + u32 aq_required; + u32 aq_pending; +#define I40EVF_FLAG_AQ_ENABLE_QUEUES (u32)(1) +#define I40EVF_FLAG_AQ_DISABLE_QUEUES (u32)(1 << 1) +#define I40EVF_FLAG_AQ_ADD_MAC_FILTER (u32)(1 << 2) +#define I40EVF_FLAG_AQ_ADD_VLAN_FILTER (u32)(1 << 3) +#define I40EVF_FLAG_AQ_DEL_MAC_FILTER (u32)(1 << 4) +#define I40EVF_FLAG_AQ_DEL_VLAN_FILTER (u32)(1 << 5) +#define I40EVF_FLAG_AQ_CONFIGURE_QUEUES (u32)(1 << 6) +#define I40EVF_FLAG_AQ_MAP_VECTORS (u32)(1 << 7) +#define I40EVF_FLAG_AQ_HANDLE_RESET (u32)(1 << 8) + /* OS defined structs */ + struct net_device *netdev; + struct pci_dev *pdev; + struct net_device_stats net_stats; + + /* structs defined in i40e_vf.h */ + struct i40e_hw hw; + + enum i40evf_state_t state; + volatile unsigned long crit_section; + u64 tx_busy; + + struct work_struct watchdog_task; + bool netdev_registered; + bool dev_closed; + bool link_up; + enum i40e_virtchnl_ops current_op; + struct i40e_virtchnl_vf_resource *vf_res; /* incl. all VSIs */ + struct i40e_virtchnl_vsi_resource *vsi_res; /* our LAN VSI */ + u16 msg_enable; + struct i40e_eth_stats current_stats; + struct i40e_vsi vsi; + u32 aq_wait_count; +}; + +struct i40evf_info { + enum i40e_mac_type mac; + unsigned int flags; +}; + + +/* needed by i40evf_ethtool.c */ +extern char i40evf_driver_name[]; +extern const char i40evf_driver_version[]; + +int i40evf_up(struct i40evf_adapter *adapter); +void i40evf_down(struct i40evf_adapter *adapter); +void i40evf_reinit_locked(struct i40evf_adapter *adapter); +void i40evf_reset(struct i40evf_adapter *adapter); +void i40evf_set_ethtool_ops(struct net_device *netdev); +void i40evf_update_stats(struct i40evf_adapter *adapter); +void i40evf_reset_interrupt_capability(struct i40evf_adapter *adapter); +int i40evf_init_interrupt_scheme(struct i40evf_adapter *adapter); +void i40evf_irq_enable_queues(struct i40evf_adapter *adapter, u32 mask); + +void i40e_napi_add_all(struct i40evf_adapter *adapter); +void i40e_napi_del_all(struct i40evf_adapter *adapter); + +int i40evf_send_api_ver(struct i40evf_adapter *adapter); +int i40evf_verify_api_ver(struct i40evf_adapter *adapter); +int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter); +int i40evf_get_vf_config(struct i40evf_adapter *adapter); +void i40evf_irq_enable(struct i40evf_adapter *adapter, bool flush); +void i40evf_configure_queues(struct i40evf_adapter *adapter); +void i40evf_deconfigure_queues(struct i40evf_adapter *adapter); +void i40evf_enable_queues(struct i40evf_adapter *adapter); +void i40evf_disable_queues(struct i40evf_adapter *adapter); +void i40evf_map_queues(struct i40evf_adapter *adapter); +void i40evf_add_ether_addrs(struct i40evf_adapter *adapter); +void i40evf_del_ether_addrs(struct i40evf_adapter *adapter); +void i40evf_add_vlans(struct i40evf_adapter *adapter); +void i40evf_del_vlans(struct i40evf_adapter *adapter); +void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags); +void i40evf_request_stats(struct i40evf_adapter *adapter); +void i40evf_virtchnl_completion(struct i40evf_adapter *adapter, + enum i40e_virtchnl_ops v_opcode, + i40e_status v_retval, u8 *msg, u16 msglen); +#endif /* _I40EVF_H_ */ |