i40e_sw.h revision 9d26e4fc021e249c93c2861629cc665e4f5bd4d6
/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
*/
/*
* Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
* Copyright 2016 Joyent, Inc.
*/
/*
* Please see i40e_main.c for an introduction to the device driver, its layout,
* and more.
*/
#ifndef _I40E_SW_H
#define _I40E_SW_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/mac_provider.h>
#include <sys/mac_ether.h>
#include <sys/ethernet.h>
#include "i40e_type.h"
#include "i40e_osdep.h"
#include "i40e_prototype.h"
#include "i40e_xregs.h"
#define I40E_MODULE_NAME "i40e"
#define I40E_ADAPTER_REGSET 1
/*
* Configuration constants. Note that the hardware defines a minimum bound of 32
* descriptors and requires that the programming of the descriptor lengths be
* aligned in units of 32 descriptors.
*/
#define I40E_MIN_TX_RING_SIZE 64
#define I40E_MAX_TX_RING_SIZE 4096
#define I40E_DEF_TX_RING_SIZE 1024
#define I40E_MIN_RX_RING_SIZE 64
#define I40E_MAX_RX_RING_SIZE 4096
#define I40E_DEF_RX_RING_SIZE 1024
#define I40E_DESC_ALIGN 32
/*
* Sizes used for asynchronous processing of the adminq. We allocate a fixed
* size buffer for each instance of the device during attach time, rather than
* allocating and freeing one during interrupt processing.
*
* We also define the descriptor size of the admin queue here.
*/
#define I40E_ADMINQ_BUFSZ 4096
#define I40E_MAX_ADMINQ_SIZE 1024
#define I40E_DEF_ADMINQ_SIZE 256
/*
* Note, while the min and maximum values are based upon the sizing of the ring
* itself, the default is taken from ixgbe without much thought. It's basically
* been cargo culted. See i40e_transceiver.c for a bit more information.
*/
#define I40E_MIN_RX_LIMIT_PER_INTR 16
#define I40E_MAX_RX_LIMIT_PER_INTR 4096
#define I40E_DEF_RX_LIMIT_PER_INTR 256
/*
* Valid MTU ranges. Note that the XL710's maximum payload is actually 9728.
* However, we need to adjust for the ETHERFCSL (4 bytes) and the Ethernet VLAN
* header size (18 bytes) to get the actual maximum frame we can use. If
* different adapters end up with different sizes, we should make this value a
* bit more dynamic.
*/
#define I40E_MAX_MTU 9706
#define I40E_MIN_MTU ETHERMIN
#define I40E_DEF_MTU ETHERMTU
/*
* Interrupt throttling related values. Interrupt throttling values are defined
* in two microsecond increments. Note that a value of zero basically says do no
* ITR activity. A helpful way to think about these is that setting the ITR to a
* value will allow a certain number of interrupts per second.
*
* Our default values for RX allow 20k interrupts per second while our default
* values for TX allow for 5k interrupts per second. For other class interrupts,
* we limit ourselves to a rate of 2k/s.
*/
#define I40E_MIN_ITR 0x0000
#define I40E_MAX_ITR 0x0FF0
#define I40E_DEF_RX_ITR 0x0019
#define I40E_DEF_TX_ITR 0x0064
#define I40E_DEF_OTHER_ITR 0x00FA
/*
* Indexes into the three ITR registers that we have.
*/
typedef enum i40e_itr_index {
I40E_ITR_INDEX_RX = 0x0,
I40E_ITR_INDEX_TX = 0x1,
I40E_ITR_INDEX_OTHER = 0x2,
I40E_ITR_INDEX_NONE = 0x3
/*
* Table 1-5 of the PRM notes that LSO supports up to 256 KB.
*/
/*
* All the other queue types for are defined by the common code. However, this
* is the constant to indicate that it's terminated.
*/
#define I40E_QUEUE_TYPE_EOL 0x7FF
/*
* See the comments in i40e_transceiver.c as to the purpose of this value and
* how it's used to ensure that the IP header is eventually aligned when it's
* received by the OS.
*/
#define I40E_BUF_IPHDR_ALIGNMENT 2
/*
* The XL710 controller has a limit of eight buffers being allowed to be used
* for the transmission of a single frame. This is defined in 8.4.1 - Transmit
* Packet in System Memory.
*/
#define I40E_TX_MAX_COOKIE 8
/*
* Sizing to determine the amount of available descriptors at which we'll
* consider ourselves blocked. Also, when we have these available, we'll then
* consider ourselves available to transmit to MAC again. Strictly speaking, the
* MAX is based on the ring size. The default sizing is based on ixgbe.
*/
/*
* Sizing for DMA thresholds. These are used to indicate whether or not we
* should perform a bcopy or a DMA binding of a given message block. The range
* allows for setting things such that we'll always do a bcopy (a high value) or
* always perform a DMA binding (a low value).
*/
#define I40E_MIN_RX_DMA_THRESH 0
#define I40E_DEF_RX_DMA_THRESH 256
#define I40E_MAX_RX_DMA_THRESH INT32_MAX
#define I40E_MIN_TX_DMA_THRESH 0
#define I40E_DEF_TX_DMA_THRESH 256
#define I40E_MAX_TX_DMA_THRESH INT32_MAX
/*
* Resource sizing counts. There are various aspects of hardware where we may
* have some variable number of elements that we need to handle. Such as the
* hardware capabilities and switch capacities. We cannot know a priori how many
* elements to do, so instead we take a starting guess and then will grow it up
* to an upper bound on a number of elements, to limit memory consumption in
* case of a hardware bug.
*/
#define I40E_HW_CAP_DEFAULT 40
#define I40E_SWITCH_CAP_DEFAULT 25
/*
* Host Memory Context related constants.
*/
#define I40E_HMC_RX_CTX_UNIT 128
#define I40E_HMC_RX_DBUFF_MIN 1024
#define I40E_HMC_RX_DTYPE_NOSPLIT 0
#define I40E_HMC_RX_DSIZE_32BYTE 1
#define I40E_HMC_RX_CRCSTRIP_ENABLE 1
#define I40E_HMC_RX_FC_DISABLE 0
#define I40E_HMC_RX_L2TAGORDER 1
#define I40E_HMC_RX_HDRSPLIT_DISABLE 0
#define I40E_HMC_RX_INVLAN_DONTSTRIP 0
#define I40E_HMC_RX_TPH_DISABLE 0
#define I40E_HMC_RX_LOWRXQ_NOINTR 0
#define I40E_HMC_RX_PREFENA 1
#define I40E_HMC_TX_CTX_UNIT 128
#define I40E_HMC_TX_NEW_CONTEXT 1
#define I40E_HMC_TX_FC_DISABLE 0
#define I40E_HMC_TX_TS_DISABLE 0
#define I40E_HMC_TX_FD_DISABLE 0
#define I40E_HMC_TX_ALT_VLAN_DISABLE 0
#define I40E_HMC_TX_WB_ENABLE 1
#define I40E_HMC_TX_TPH_DISABLE 0
/*
* Whenever we establish and create a VSI, we need to assign some number of
* queues that it's allowed to access from the PF. Because we only have a single
* VSI per PF at this time, we assign it all the queues.
*
* Many of the devices support what's called Data-center Bridging. Which is a
* feature that we don't have much use of at this time. However, we still need
* to fill in this information. We follow the guidance of the note in Table 7-80
* which talks about bytes 62-77. It says that if we don't want to assign
* anything to traffic classes, we should set the field to zero. Effectively
* this means that everything in the system is assigned to traffic class zero.
*/
#define I40E_ASSIGN_ALL_QUEUES 0
#define I40E_TRAFFIC_CLASS_NO_QUEUES 0
/*
* This defines the error mask that we care about from rx descriptors. Currently
* we're only concerned with the general errors and oversize errors.
*/
/*
* Property sizing macros for firmware versions, etc. They need to be large
* enough to hold 32-bit quantities transformed to strings as %d.%d or %x.
*/
#define I40E_DDI_PROP_LEN 64
/*
* We currently consolidate some overrides that we use in the code here. These
* will be gone in the fullness of time, but as we're bringing up the device,
* this is what we use.
*/
#define I40E_GROUP_MAX 1
#define I40E_TRQPAIR_MAX 1
#define I40E_GROUP_NOMSIX 1
#define I40E_TRQPAIR_NOMSIX 1
/*
* It seems reasonable to cast this to void because the only reason that we
* should be getting a DDI_FAILURE is due to the fact that we specify addresses
* out of range. Because we specify no offset or address, it shouldn't happen.
*/
#ifdef DEBUG
(handle)->dmab_dma_handle, 0, 0, \
(flag)))
#else /* !DEBUG */
(handle)->dmab_dma_handle, 0, 0, \
(flag)))
#endif /* DEBUG */
/*
* Constants related to ring startup and teardown. These refer to the amount of
* time that we're willing to wait for a ring to spin up and spin down.
*/
#define I40E_RING_WAIT_NTRIES 10
/*
* Bit flags for attach_progress
*/
typedef enum i40e_attach_state {
/*
* State flags that what's going on in in the device. Some of these state flags
* indicate some aspirational work that needs to happen in the driver.
*
* I40E_UNKNOWN: The device has yet to be started.
* I40E_INITIALIZED: The device has been fully attached.
* I40E_STARTED: The device has come out of the GLDV3 start routine.
* I40E_SUSPENDED: The device is suspended and I/O among other things
* should not occur. This happens because of an actual
* DDI_SUSPEND or interrupt adjustments.
* I40E_STALL: The tx stall detection logic has found a stall.
* I40E_OVERTEMP: The device has encountered a temperature alarm.
* I40E_INTR_ADJUST: Our interrupts are being manipulated and therefore we
* shouldn't be manipulating their state.
* I40E_ERROR: We've detected an FM error and degraded the device.
*/
typedef enum i40e_state {
I40E_UNKNOWN = 0x00,
I40E_INITIALIZED = 0x01,
I40E_STARTED = 0x02,
I40E_SUSPENDED = 0x04,
I40E_STALL = 0x08,
I40E_OVERTEMP = 0x20,
I40E_INTR_ADJUST = 0x40,
I40E_ERROR = 0x80
} i40e_state_t;
/*
* Definitions for common Intel things that we use and some slightly more usable
* names.
*/
typedef struct i40e_aqc_switch_resource_alloc_element_resp i40e_switch_rsrc_t;
/*
* Handles and addresses of DMA buffers.
*/
typedef struct i40e_dma_buffer {
/*
* RX Control Block
*/
typedef struct i40e_rx_control_block {
struct i40e_rx_data *rcb_rxd;
typedef enum {
typedef struct i40e_tx_desc i40e_tx_desc_t;
typedef union i40e_32byte_rx_desc i40e_rx_desc_t;
typedef struct i40e_tx_control_block {
struct i40e_tx_control_block *tcb_next;
/*
* Receive ring data (used below).
*/
typedef struct i40e_rx_data {
/*
* RX descriptor ring definitions
*/
/*
* RX control block list definitions
*/
/*
* RX software ring settings
*/
/*
* RX outstanding data. This is used to keep track of outstanding loaned
* descriptors after we've shut down receiving information. Note these
* are protected by the i40e_t`i40e_rx_pending_lock.
*/
/*
* Structures for unicast and multicast addresses. Note that we keep the VSI id
* around for unicast addresses, since they may belong to different VSIs.
* However, since all multicast addresses belong to the default VSI, we don't
* duplicate that information.
*/
typedef struct i40e_uaddr {
int iua_vsi;
} i40e_uaddr_t;
typedef struct i40e_maddr {
} i40e_maddr_t;
/*
* Collection of RX statistics on a given queue.
*/
typedef struct i40e_rxq_stat {
/*
* The i40e hardware does not maintain statistics on a per-ring basis,
* only on a per-PF and per-VSI level. As such, to satisfy the GLDv3, we
* need to maintain our own stats for packets and bytes.
*/
/*
* The following set of stats cover non-checksum data path issues.
*/
/*
* The following set of statistics covers rx checksum related activity.
* These are all primarily set in i40e_rx_hcksum. If rx checksum
* activity is disabled, then these should all be zero.
*/
/*
* Collection of TX Statistics on a given queue
*/
typedef struct i40e_txq_stat {
/*
* Various failure conditions.
*/
/*
* represents a combination of both a transmit and receive ring, though they
* should really be split apart into separate logical structures. Unfortunately,
* during initial work we mistakenly joined them together.
*/
typedef struct i40e_trqpair {
/* Receive-side structures. */
/* Receive-side stats. */
/* Transmit-side structures. */
/*
* TX data sizing
*/
/*
* TX descriptor ring data
*/
/*
* TX control block (tcb) data
*/
/* Transmit-side stats. */
/*
* VSI statistics.
*
* This mirrors the i40e_eth_stats structure but transforms it into a kstat.
* Note that the stock statistic structure also includes entries for tx
* discards. However, this is not actually implemented for the VSI (see Table
* 7-221), hence why we don't include the member which would always have a value
* of zero. This choice was made to minimize confusion to someone looking at
* these, as a value of zero does not necessarily equate to the fact that it's
* not implemented.
*/
typedef struct i40e_vsi_stats {
typedef struct i40e_vsi_kstats {
/*
* For pf statistics, we opt not to use the standard statistics as defined by
* the Intel common code. This also currently combines statistics that are
* global across the entire device.
*/
typedef struct i40e_pf_stats {
typedef struct i40e_pf_kstats {
/*
* Resources that are pooled and specific to a given i40e_t.
*/
typedef struct i40e_func_rsrc {
/*
* Main i40e per-instance state.
*/
typedef struct i40e {
/*
* General Data and management
*/
int i40e_instance;
int i40e_fm_capabilities;
/*
* Pointers to common code data structures and memory for the common
* code.
*/
struct i40e_hw i40e_hw_space;
struct i40e_osdep i40e_osdep_space;
void *i40e_aqbuf;
/*
* Device state, switch information, and resources.
*/
int i40e_vsi_id;
struct i40e_device *i40e_device;
/*
* Transmit and receive information, tunables, and MAC info.
*/
int i40e_num_trqpairs;
int i40e_num_rx_groups;
int i40e_num_rx_descs;
int i40e_num_tx_descs;
/*
* Interrupt state
*
* Note that the use of a single boolean_t for i40e_intr_poll isn't
* really the best design. When we have more than a single ring on the
* device working, we'll transition to using something more
* sophisticated.
*/
int i40e_intr_cap;
/*
* DMA attributes. See i40e_transceiver.c for why we have copies of them
* in the i40e_t.
*/
/*
* The following two fields are used to protect and keep track of
* outstanding, loaned buffers to MAC. If we have these, we can't
* detach as we have active DMA memory outstanding.
*/
/*
* PF statistics and VSI statistics.
*/
/*
* Misc. stats and counters that should maybe one day be kstats.
*/
} i40e_t;
/*
* The i40e_device represents a PCI device which encapsulates multiple physical
* functions which are represented as an i40e_t. This is used to track the use
* of pooled resources throughout all of the various devices.
*/
typedef struct i40e_device {
/* Values for the interrupt forcing on the NIC. */
#define I40E_INTR_NONE 0
#define I40E_INTR_MSIX 1
#define I40E_INTR_MSI 2
#define I40E_INTR_LEGACY 3
/* Hint that we don't want to do any polling... */
#define I40E_POLL_NULL -1
/*
* Logging functions.
*/
/*PRINTFLIKE2*/
/*PRINTFLIKE2*/
/*PRINTFLIKE2*/
/*
* General link handling functions.
*/
extern void i40e_link_check(i40e_t *);
extern void i40e_update_mtu(i40e_t *);
/*
* FMA functions.
*/
extern int i40e_check_acc_handle(ddi_acc_handle_t);
extern int i40e_check_dma_handle(ddi_dma_handle_t);
extern void i40e_fm_ereport(i40e_t *, char *);
/*
* Interrupt handlers and interrupt handler setup.
*/
extern void i40e_intr_chip_init(i40e_t *);
extern void i40e_intr_chip_fini(i40e_t *);
extern uint_t i40e_intr_msix(void *, void *);
extern uint_t i40e_intr_msi(void *, void *);
extern uint_t i40e_intr_legacy(void *, void *);
extern void i40e_intr_io_enable_all(i40e_t *);
extern void i40e_intr_io_disable_all(i40e_t *);
extern void i40e_intr_io_clear_cause(i40e_t *);
/*
* Receive-side functions
*/
extern mblk_t *i40e_ring_rx_poll(void *, int);
extern void i40e_rx_recycle(caddr_t);
/*
* Transmit-side functions
*/
extern void i40e_tx_recycle_ring(i40e_trqpair_t *);
extern void i40e_tx_cleanup_ring(i40e_trqpair_t *);
/*
* Statistics functions.
*/
extern void i40e_stats_fini(i40e_t *);
extern void i40e_stat_vsi_fini(i40e_t *);
extern void i40e_stats_trqpair_fini(i40e_trqpair_t *);
/*
*/
/*
* DMA & buffer functions and attributes
*/
#ifdef __cplusplus
}
#endif
#endif /* _I40E_SW_H */