mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-10 09:22:44 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
47
drivers/net/ethernet/intel/i40e/Makefile
Normal file
47
drivers/net/ethernet/intel/i40e/Makefile
Normal file
|
@ -0,0 +1,47 @@
|
|||
################################################################################
|
||||
#
|
||||
# Intel Ethernet Controller XL710 Family Linux Driver
|
||||
# Copyright(c) 2013 - 2014 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# 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
|
||||
#
|
||||
################################################################################
|
||||
|
||||
#
|
||||
# Makefile for the Intel(R) Ethernet Connection XL710 (i40e.ko) driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_I40E) += i40e.o
|
||||
|
||||
i40e-objs := i40e_main.o \
|
||||
i40e_ethtool.o \
|
||||
i40e_adminq.o \
|
||||
i40e_common.o \
|
||||
i40e_hmc.o \
|
||||
i40e_lan_hmc.o \
|
||||
i40e_nvm.o \
|
||||
i40e_debugfs.o \
|
||||
i40e_diag.o \
|
||||
i40e_txrx.o \
|
||||
i40e_ptp.o \
|
||||
i40e_virtchnl_pf.o
|
||||
|
||||
i40e-$(CONFIG_I40E_DCB) += i40e_dcb.o i40e_dcb_nl.o
|
||||
i40e-$(CONFIG_I40E_FCOE) += i40e_fcoe.o
|
726
drivers/net/ethernet/intel/i40e/i40e.h
Normal file
726
drivers/net/ethernet/intel/i40e/i40e.h
Normal file
|
@ -0,0 +1,726 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_H_
|
||||
#define _I40E_H_
|
||||
|
||||
#include <net/tcp.h>
|
||||
#include <net/udp.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/aer.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/sctp.h>
|
||||
#include <linux/pkt_sched.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <net/checksum.h>
|
||||
#include <net/ip6_checksum.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include "i40e_type.h"
|
||||
#include "i40e_prototype.h"
|
||||
#ifdef I40E_FCOE
|
||||
#include "i40e_fcoe.h"
|
||||
#endif
|
||||
#include "i40e_virtchnl.h"
|
||||
#include "i40e_virtchnl_pf.h"
|
||||
#include "i40e_txrx.h"
|
||||
#include "i40e_dcb.h"
|
||||
|
||||
/* Useful i40e defaults */
|
||||
#define I40E_BASE_PF_SEID 16
|
||||
#define I40E_BASE_VSI_SEID 512
|
||||
#define I40E_BASE_VEB_SEID 288
|
||||
#define I40E_MAX_VEB 16
|
||||
|
||||
#define I40E_MAX_NUM_DESCRIPTORS 4096
|
||||
#define I40E_MAX_REGISTER 0x800000
|
||||
#define I40E_DEFAULT_NUM_DESCRIPTORS 512
|
||||
#define I40E_REQ_DESCRIPTOR_MULTIPLE 32
|
||||
#define I40E_MIN_NUM_DESCRIPTORS 64
|
||||
#define I40E_MIN_MSIX 2
|
||||
#define I40E_DEFAULT_NUM_VMDQ_VSI 8 /* max 256 VSIs */
|
||||
#define I40E_MIN_VSI_ALLOC 51 /* LAN, ATR, FCOE, 32 VF, 16 VMDQ */
|
||||
#define I40E_DEFAULT_QUEUES_PER_VMDQ 2 /* max 16 qps */
|
||||
#define I40E_DEFAULT_QUEUES_PER_VF 4
|
||||
#define I40E_DEFAULT_QUEUES_PER_TC 1 /* should be a power of 2 */
|
||||
#define I40E_MAX_QUEUES_PER_TC 64 /* should be a power of 2 */
|
||||
#define I40E_FDIR_RING 0
|
||||
#define I40E_FDIR_RING_COUNT 32
|
||||
#ifdef I40E_FCOE
|
||||
#define I40E_DEFAULT_FCOE 8 /* default number of QPs for FCoE */
|
||||
#define I40E_MINIMUM_FCOE 1 /* minimum number of QPs for FCoE */
|
||||
#endif /* I40E_FCOE */
|
||||
#define I40E_MAX_AQ_BUF_SIZE 4096
|
||||
#define I40E_AQ_LEN 32
|
||||
#define I40E_AQ_WORK_LIMIT 16
|
||||
#define I40E_MAX_USER_PRIORITY 8
|
||||
#define I40E_DEFAULT_MSG_ENABLE 4
|
||||
#define I40E_QUEUE_WAIT_RETRY_LIMIT 10
|
||||
|
||||
#define I40E_NVM_VERSION_LO_SHIFT 0
|
||||
#define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT)
|
||||
#define I40E_NVM_VERSION_HI_SHIFT 12
|
||||
#define I40E_NVM_VERSION_HI_MASK (0xf << I40E_NVM_VERSION_HI_SHIFT)
|
||||
|
||||
/* The values in here are decimal coded as hex as is the case in the NVM map*/
|
||||
#define I40E_CURRENT_NVM_VERSION_HI 0x2
|
||||
#define I40E_CURRENT_NVM_VERSION_LO 0x40
|
||||
|
||||
/* magic for getting defines into strings */
|
||||
#define STRINGIFY(foo) #foo
|
||||
#define XSTRINGIFY(bar) STRINGIFY(bar)
|
||||
|
||||
#define I40E_RX_DESC(R, i) \
|
||||
((ring_is_16byte_desc_enabled(R)) \
|
||||
? (union i40e_32byte_rx_desc *) \
|
||||
(&(((union i40e_16byte_rx_desc *)((R)->desc))[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 I40E_TX_FDIRDESC(R, i) \
|
||||
(&(((struct i40e_filter_program_desc *)((R)->desc))[i]))
|
||||
|
||||
/* default to trying for four seconds */
|
||||
#define I40E_TRY_LINK_TIMEOUT (4 * HZ)
|
||||
|
||||
/* driver state flags */
|
||||
enum i40e_state_t {
|
||||
__I40E_TESTING,
|
||||
__I40E_CONFIG_BUSY,
|
||||
__I40E_CONFIG_DONE,
|
||||
__I40E_DOWN,
|
||||
__I40E_NEEDS_RESTART,
|
||||
__I40E_SERVICE_SCHED,
|
||||
__I40E_ADMINQ_EVENT_PENDING,
|
||||
__I40E_MDD_EVENT_PENDING,
|
||||
__I40E_VFLR_EVENT_PENDING,
|
||||
__I40E_RESET_RECOVERY_PENDING,
|
||||
__I40E_RESET_INTR_RECEIVED,
|
||||
__I40E_REINIT_REQUESTED,
|
||||
__I40E_PF_RESET_REQUESTED,
|
||||
__I40E_CORE_RESET_REQUESTED,
|
||||
__I40E_GLOBAL_RESET_REQUESTED,
|
||||
__I40E_EMP_RESET_REQUESTED,
|
||||
__I40E_FILTER_OVERFLOW_PROMISC,
|
||||
__I40E_SUSPENDED,
|
||||
__I40E_PTP_TX_IN_PROGRESS,
|
||||
__I40E_BAD_EEPROM,
|
||||
__I40E_DOWN_REQUESTED,
|
||||
__I40E_FD_FLUSH_REQUESTED,
|
||||
__I40E_RESET_FAILED,
|
||||
};
|
||||
|
||||
enum i40e_interrupt_policy {
|
||||
I40E_INTERRUPT_BEST_CASE,
|
||||
I40E_INTERRUPT_MEDIUM,
|
||||
I40E_INTERRUPT_LOWEST
|
||||
};
|
||||
|
||||
struct i40e_lump_tracking {
|
||||
u16 num_entries;
|
||||
u16 search_hint;
|
||||
u16 list[0];
|
||||
#define I40E_PILE_VALID_BIT 0x8000
|
||||
};
|
||||
|
||||
#define I40E_DEFAULT_ATR_SAMPLE_RATE 20
|
||||
#define I40E_FDIR_MAX_RAW_PACKET_SIZE 512
|
||||
#define I40E_FDIR_BUFFER_FULL_MARGIN 10
|
||||
#define I40E_FDIR_BUFFER_HEAD_ROOM 32
|
||||
|
||||
enum i40e_fd_stat_idx {
|
||||
I40E_FD_STAT_ATR,
|
||||
I40E_FD_STAT_SB,
|
||||
I40E_FD_STAT_PF_COUNT
|
||||
};
|
||||
#define I40E_FD_STAT_PF_IDX(pf_id) ((pf_id) * I40E_FD_STAT_PF_COUNT)
|
||||
#define I40E_FD_ATR_STAT_IDX(pf_id) \
|
||||
(I40E_FD_STAT_PF_IDX(pf_id) + I40E_FD_STAT_ATR)
|
||||
#define I40E_FD_SB_STAT_IDX(pf_id) \
|
||||
(I40E_FD_STAT_PF_IDX(pf_id) + I40E_FD_STAT_SB)
|
||||
|
||||
struct i40e_fdir_filter {
|
||||
struct hlist_node fdir_node;
|
||||
/* filter ipnut set */
|
||||
u8 flow_type;
|
||||
u8 ip4_proto;
|
||||
/* TX packet view of src and dst */
|
||||
__be32 dst_ip[4];
|
||||
__be32 src_ip[4];
|
||||
__be16 src_port;
|
||||
__be16 dst_port;
|
||||
__be32 sctp_v_tag;
|
||||
/* filter control */
|
||||
u16 q_index;
|
||||
u8 flex_off;
|
||||
u8 pctype;
|
||||
u16 dest_vsi;
|
||||
u8 dest_ctl;
|
||||
u8 fd_status;
|
||||
u16 cnt_index;
|
||||
u32 fd_id;
|
||||
};
|
||||
|
||||
#define I40E_ETH_P_LLDP 0x88cc
|
||||
|
||||
#define I40E_DCB_PRIO_TYPE_STRICT 0
|
||||
#define I40E_DCB_PRIO_TYPE_ETS 1
|
||||
#define I40E_DCB_STRICT_PRIO_CREDITS 127
|
||||
#define I40E_MAX_USER_PRIORITY 8
|
||||
/* DCB per TC information data structure */
|
||||
struct i40e_tc_info {
|
||||
u16 qoffset; /* Queue offset from base queue */
|
||||
u16 qcount; /* Total Queues */
|
||||
u8 netdev_tc; /* Netdev TC index if netdev associated */
|
||||
};
|
||||
|
||||
/* TC configuration data structure */
|
||||
struct i40e_tc_configuration {
|
||||
u8 numtc; /* Total number of enabled TCs */
|
||||
u8 enabled_tc; /* TC map */
|
||||
struct i40e_tc_info tc_info[I40E_MAX_TRAFFIC_CLASS];
|
||||
};
|
||||
|
||||
/* struct that defines the Ethernet device */
|
||||
struct i40e_pf {
|
||||
struct pci_dev *pdev;
|
||||
struct i40e_hw hw;
|
||||
unsigned long state;
|
||||
unsigned long link_check_timeout;
|
||||
struct msix_entry *msix_entries;
|
||||
bool fc_autoneg_status;
|
||||
|
||||
u16 eeprom_version;
|
||||
u16 num_vmdq_vsis; /* num vmdq vsis this pf has set up */
|
||||
u16 num_vmdq_qps; /* num queue pairs per vmdq pool */
|
||||
u16 num_vmdq_msix; /* num queue vectors per vmdq pool */
|
||||
u16 num_req_vfs; /* num vfs requested for this vf */
|
||||
u16 num_vf_qps; /* num queue pairs per vf */
|
||||
#ifdef I40E_FCOE
|
||||
u16 num_fcoe_qps; /* num fcoe queues this pf has set up */
|
||||
u16 num_fcoe_msix; /* num queue vectors per fcoe pool */
|
||||
#endif /* I40E_FCOE */
|
||||
u16 num_lan_qps; /* num lan queues this pf has set up */
|
||||
u16 num_lan_msix; /* num queue vectors for the base pf vsi */
|
||||
int queues_left; /* queues left unclaimed */
|
||||
u16 rss_size; /* num queues in the RSS array */
|
||||
u16 rss_size_max; /* HW defined max RSS queues */
|
||||
u16 fdir_pf_filter_count; /* num of guaranteed filters for this PF */
|
||||
u16 num_alloc_vsi; /* num VSIs this driver supports */
|
||||
u8 atr_sample_rate;
|
||||
bool wol_en;
|
||||
|
||||
struct hlist_head fdir_filter_list;
|
||||
u16 fdir_pf_active_filters;
|
||||
u16 fd_sb_cnt_idx;
|
||||
u16 fd_atr_cnt_idx;
|
||||
unsigned long fd_flush_timestamp;
|
||||
u32 fd_flush_cnt;
|
||||
u32 fd_add_err;
|
||||
u32 fd_atr_cnt;
|
||||
u32 fd_tcp_rule;
|
||||
|
||||
#ifdef CONFIG_I40E_VXLAN
|
||||
__be16 vxlan_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];
|
||||
u16 pending_vxlan_bitmap;
|
||||
|
||||
#endif
|
||||
enum i40e_interrupt_policy int_policy;
|
||||
u16 rx_itr_default;
|
||||
u16 tx_itr_default;
|
||||
u16 msg_enable;
|
||||
char misc_int_name[IFNAMSIZ + 9];
|
||||
u16 adminq_work_limit; /* num of admin receive queue desc to process */
|
||||
int service_timer_period;
|
||||
struct timer_list service_timer;
|
||||
struct work_struct service_task;
|
||||
|
||||
u64 flags;
|
||||
#define I40E_FLAG_RX_CSUM_ENABLED (u64)(1 << 1)
|
||||
#define I40E_FLAG_MSI_ENABLED (u64)(1 << 2)
|
||||
#define I40E_FLAG_MSIX_ENABLED (u64)(1 << 3)
|
||||
#define I40E_FLAG_RX_1BUF_ENABLED (u64)(1 << 4)
|
||||
#define I40E_FLAG_RX_PS_ENABLED (u64)(1 << 5)
|
||||
#define I40E_FLAG_RSS_ENABLED (u64)(1 << 6)
|
||||
#define I40E_FLAG_VMDQ_ENABLED (u64)(1 << 7)
|
||||
#define I40E_FLAG_FDIR_REQUIRES_REINIT (u64)(1 << 8)
|
||||
#define I40E_FLAG_NEED_LINK_UPDATE (u64)(1 << 9)
|
||||
#ifdef I40E_FCOE
|
||||
#define I40E_FLAG_FCOE_ENABLED (u64)(1 << 11)
|
||||
#endif /* I40E_FCOE */
|
||||
#define I40E_FLAG_IN_NETPOLL (u64)(1 << 12)
|
||||
#define I40E_FLAG_16BYTE_RX_DESC_ENABLED (u64)(1 << 13)
|
||||
#define I40E_FLAG_CLEAN_ADMINQ (u64)(1 << 14)
|
||||
#define I40E_FLAG_FILTER_SYNC (u64)(1 << 15)
|
||||
#define I40E_FLAG_PROCESS_MDD_EVENT (u64)(1 << 17)
|
||||
#define I40E_FLAG_PROCESS_VFLR_EVENT (u64)(1 << 18)
|
||||
#define I40E_FLAG_SRIOV_ENABLED (u64)(1 << 19)
|
||||
#define I40E_FLAG_DCB_ENABLED (u64)(1 << 20)
|
||||
#define I40E_FLAG_FD_SB_ENABLED (u64)(1 << 21)
|
||||
#define I40E_FLAG_FD_ATR_ENABLED (u64)(1 << 22)
|
||||
#define I40E_FLAG_PTP (u64)(1 << 25)
|
||||
#define I40E_FLAG_MFP_ENABLED (u64)(1 << 26)
|
||||
#ifdef CONFIG_I40E_VXLAN
|
||||
#define I40E_FLAG_VXLAN_FILTER_SYNC (u64)(1 << 27)
|
||||
#endif
|
||||
#define I40E_FLAG_PORT_ID_VALID (u64)(1 << 28)
|
||||
#define I40E_FLAG_DCB_CAPABLE (u64)(1 << 29)
|
||||
|
||||
/* tracks features that get auto disabled by errors */
|
||||
u64 auto_disable_flags;
|
||||
|
||||
#ifdef I40E_FCOE
|
||||
struct i40e_fcoe fcoe;
|
||||
|
||||
#endif /* I40E_FCOE */
|
||||
bool stat_offsets_loaded;
|
||||
struct i40e_hw_port_stats stats;
|
||||
struct i40e_hw_port_stats stats_offsets;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_timeout_recovery_level;
|
||||
unsigned long tx_timeout_last_recovery;
|
||||
u32 tx_sluggish_count;
|
||||
u32 hw_csum_rx_error;
|
||||
u32 led_status;
|
||||
u16 corer_count; /* Core reset count */
|
||||
u16 globr_count; /* Global reset count */
|
||||
u16 empr_count; /* EMP reset count */
|
||||
u16 pfr_count; /* PF reset count */
|
||||
u16 sw_int_count; /* SW interrupt count */
|
||||
|
||||
struct mutex switch_mutex;
|
||||
u16 lan_vsi; /* our default LAN VSI */
|
||||
u16 lan_veb; /* initial relay, if exists */
|
||||
#define I40E_NO_VEB 0xffff
|
||||
#define I40E_NO_VSI 0xffff
|
||||
u16 next_vsi; /* Next unallocated VSI - 0-based! */
|
||||
struct i40e_vsi **vsi;
|
||||
struct i40e_veb *veb[I40E_MAX_VEB];
|
||||
|
||||
struct i40e_lump_tracking *qp_pile;
|
||||
struct i40e_lump_tracking *irq_pile;
|
||||
|
||||
/* switch config info */
|
||||
u16 pf_seid;
|
||||
u16 main_vsi_seid;
|
||||
u16 mac_seid;
|
||||
struct kobject *switch_kobj;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *i40e_dbg_pf;
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
u16 instance; /* A unique number per i40e_pf instance in the system */
|
||||
|
||||
/* sr-iov config info */
|
||||
struct i40e_vf *vf;
|
||||
int num_alloc_vfs; /* actual number of VFs allocated */
|
||||
u32 vf_aq_requests;
|
||||
|
||||
/* DCBx/DCBNL capability for PF that indicates
|
||||
* whether DCBx is managed by firmware or host
|
||||
* based agent (LLDPAD). Also, indicates what
|
||||
* flavor of DCBx protocol (IEEE/CEE) is supported
|
||||
* by the device. For now we're supporting IEEE
|
||||
* mode only.
|
||||
*/
|
||||
u16 dcbx_cap;
|
||||
|
||||
u32 fcoe_hmc_filt_num;
|
||||
u32 fcoe_hmc_cntx_num;
|
||||
struct i40e_filter_control_settings filter_settings;
|
||||
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct ptp_clock_info ptp_caps;
|
||||
struct sk_buff *ptp_tx_skb;
|
||||
struct hwtstamp_config tstamp_config;
|
||||
unsigned long last_rx_ptp_check;
|
||||
spinlock_t tmreg_lock; /* Used to protect the device time registers. */
|
||||
u64 ptp_base_adj;
|
||||
u32 tx_hwtstamp_timeouts;
|
||||
u32 rx_hwtstamp_cleared;
|
||||
bool ptp_tx;
|
||||
bool ptp_rx;
|
||||
u16 rss_table_size;
|
||||
};
|
||||
|
||||
struct i40e_mac_filter {
|
||||
struct list_head list;
|
||||
u8 macaddr[ETH_ALEN];
|
||||
#define I40E_VLAN_ANY -1
|
||||
s16 vlan;
|
||||
u8 counter; /* number of instances of this filter */
|
||||
bool is_vf; /* filter belongs to a VF */
|
||||
bool is_netdev; /* filter belongs to a netdev */
|
||||
bool changed; /* filter needs to be sync'd to the HW */
|
||||
bool is_laa; /* filter is a Locally Administered Address */
|
||||
};
|
||||
|
||||
struct i40e_veb {
|
||||
struct i40e_pf *pf;
|
||||
u16 idx;
|
||||
u16 veb_idx; /* index of VEB parent */
|
||||
u16 seid;
|
||||
u16 uplink_seid;
|
||||
u16 stats_idx; /* index of VEB parent */
|
||||
u8 enabled_tc;
|
||||
u16 flags;
|
||||
u16 bw_limit;
|
||||
u8 bw_max_quanta;
|
||||
bool is_abs_credits;
|
||||
u8 bw_tc_share_credits[I40E_MAX_TRAFFIC_CLASS];
|
||||
u16 bw_tc_limit_credits[I40E_MAX_TRAFFIC_CLASS];
|
||||
u8 bw_tc_max_quanta[I40E_MAX_TRAFFIC_CLASS];
|
||||
struct kobject *kobj;
|
||||
bool stat_offsets_loaded;
|
||||
struct i40e_eth_stats stats;
|
||||
struct i40e_eth_stats stats_offsets;
|
||||
};
|
||||
|
||||
/* struct that defines a VSI, associated with a dev */
|
||||
struct i40e_vsi {
|
||||
struct net_device *netdev;
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
bool netdev_registered;
|
||||
bool stat_offsets_loaded;
|
||||
|
||||
u32 current_netdev_flags;
|
||||
unsigned long state;
|
||||
#define I40E_VSI_FLAG_FILTER_CHANGED (1<<0)
|
||||
#define I40E_VSI_FLAG_VEB_OWNER (1<<1)
|
||||
unsigned long flags;
|
||||
|
||||
struct list_head mac_filter_list;
|
||||
|
||||
/* VSI stats */
|
||||
struct rtnl_link_stats64 net_stats;
|
||||
struct rtnl_link_stats64 net_stats_offsets;
|
||||
struct i40e_eth_stats eth_stats;
|
||||
struct i40e_eth_stats eth_stats_offsets;
|
||||
#ifdef I40E_FCOE
|
||||
struct i40e_fcoe_stats fcoe_stats;
|
||||
struct i40e_fcoe_stats fcoe_stats_offsets;
|
||||
bool fcoe_stat_offsets_loaded;
|
||||
#endif
|
||||
u32 tx_restart;
|
||||
u32 tx_busy;
|
||||
u32 rx_buf_failed;
|
||||
u32 rx_page_failed;
|
||||
|
||||
/* These are containers of ring pointers, allocated at run-time */
|
||||
struct i40e_ring **rx_rings;
|
||||
struct i40e_ring **tx_rings;
|
||||
|
||||
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;
|
||||
|
||||
u16 max_frame;
|
||||
u16 rx_hdr_len;
|
||||
u16 rx_buf_len;
|
||||
u8 dtype;
|
||||
|
||||
/* List of q_vectors allocated to this VSI */
|
||||
struct i40e_q_vector **q_vectors;
|
||||
int num_q_vectors;
|
||||
int base_vector;
|
||||
bool irqs_ready;
|
||||
|
||||
u16 seid; /* HW index of this VSI (absolute index) */
|
||||
u16 id; /* VSI number */
|
||||
u16 uplink_seid;
|
||||
|
||||
u16 base_queue; /* vsi's first queue in hw array */
|
||||
u16 alloc_queue_pairs; /* Allocated Tx/Rx queues */
|
||||
u16 num_queue_pairs; /* Used tx and rx pairs */
|
||||
u16 num_desc;
|
||||
enum i40e_vsi_type type; /* VSI type, e.g., LAN, FCoE, etc */
|
||||
u16 vf_id; /* Virtual function ID for SRIOV VSIs */
|
||||
|
||||
struct i40e_tc_configuration tc_config;
|
||||
struct i40e_aqc_vsi_properties_data info;
|
||||
|
||||
/* VSI BW limit (absolute across all TCs) */
|
||||
u16 bw_limit; /* VSI BW Limit (0 = disabled) */
|
||||
u8 bw_max_quanta; /* Max Quanta when BW limit is enabled */
|
||||
|
||||
/* Relative TC credits across VSIs */
|
||||
u8 bw_ets_share_credits[I40E_MAX_TRAFFIC_CLASS];
|
||||
/* TC BW limit credits within VSI */
|
||||
u16 bw_ets_limit_credits[I40E_MAX_TRAFFIC_CLASS];
|
||||
/* TC BW limit max quanta within VSI */
|
||||
u8 bw_ets_max_quanta[I40E_MAX_TRAFFIC_CLASS];
|
||||
|
||||
struct i40e_pf *back; /* Backreference to associated PF */
|
||||
u16 idx; /* index in pf->vsi[] */
|
||||
u16 veb_idx; /* index of VEB parent */
|
||||
struct kobject *kobj; /* sysfs object */
|
||||
|
||||
/* VSI specific handlers */
|
||||
irqreturn_t (*irq_handler)(int irq, void *data);
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
struct i40e_netdev_priv {
|
||||
struct i40e_vsi *vsi;
|
||||
};
|
||||
|
||||
/* struct that defines an interrupt vector */
|
||||
struct i40e_q_vector {
|
||||
struct i40e_vsi *vsi;
|
||||
|
||||
u16 v_idx; /* index in the vsi->q_vector array. */
|
||||
u16 reg_idx; /* register index of the interrupt */
|
||||
|
||||
struct napi_struct napi;
|
||||
|
||||
struct i40e_ring_container rx;
|
||||
struct i40e_ring_container tx;
|
||||
|
||||
u8 num_ringpairs; /* total number of ring pairs in vector */
|
||||
|
||||
cpumask_t affinity_mask;
|
||||
struct rcu_head rcu; /* to avoid race with update stats on free */
|
||||
char name[IFNAMSIZ + 9];
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
/* lan device */
|
||||
struct i40e_device {
|
||||
struct list_head list;
|
||||
struct i40e_pf *pf;
|
||||
};
|
||||
|
||||
/**
|
||||
* i40e_fw_version_str - format the FW and NVM version strings
|
||||
* @hw: ptr to the hardware info
|
||||
**/
|
||||
static inline char *i40e_fw_version_str(struct i40e_hw *hw)
|
||||
{
|
||||
static char buf[32];
|
||||
|
||||
snprintf(buf, sizeof(buf),
|
||||
"f%d.%d a%d.%d n%02x.%02x e%08x",
|
||||
hw->aq.fw_maj_ver, hw->aq.fw_min_ver,
|
||||
hw->aq.api_maj_ver, hw->aq.api_min_ver,
|
||||
(hw->nvm.version & I40E_NVM_VERSION_HI_MASK) >>
|
||||
I40E_NVM_VERSION_HI_SHIFT,
|
||||
(hw->nvm.version & I40E_NVM_VERSION_LO_MASK) >>
|
||||
I40E_NVM_VERSION_LO_SHIFT,
|
||||
hw->nvm.eetrack);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_netdev_to_pf: Retrieve the PF struct for given netdev
|
||||
* @netdev: the corresponding netdev
|
||||
*
|
||||
* Return the PF struct for the given netdev
|
||||
**/
|
||||
static inline struct i40e_pf *i40e_netdev_to_pf(struct net_device *netdev)
|
||||
{
|
||||
struct i40e_netdev_priv *np = netdev_priv(netdev);
|
||||
struct i40e_vsi *vsi = np->vsi;
|
||||
|
||||
return vsi->back;
|
||||
}
|
||||
|
||||
static inline void i40e_vsi_setup_irqhandler(struct i40e_vsi *vsi,
|
||||
irqreturn_t (*irq_handler)(int, void *))
|
||||
{
|
||||
vsi->irq_handler = irq_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_rx_is_programming_status - check for programming status descriptor
|
||||
* @qw: the first quad word of the program status descriptor
|
||||
*
|
||||
* The value of in the descriptor length field indicate if this
|
||||
* is a programming status descriptor for flow director or FCoE
|
||||
* by the value of I40E_RX_PROG_STATUS_DESC_LENGTH, otherwise
|
||||
* it is a packet descriptor.
|
||||
**/
|
||||
static inline bool i40e_rx_is_programming_status(u64 qw)
|
||||
{
|
||||
return I40E_RX_PROG_STATUS_DESC_LENGTH ==
|
||||
(qw >> I40E_RX_PROG_STATUS_DESC_LENGTH_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_get_fd_cnt_all - get the total FD filter space available
|
||||
* @pf: pointer to the pf struct
|
||||
**/
|
||||
static inline int i40e_get_fd_cnt_all(struct i40e_pf *pf)
|
||||
{
|
||||
return pf->hw.fdir_shared_filter_count + pf->fdir_pf_filter_count;
|
||||
}
|
||||
|
||||
/* needed by i40e_ethtool.c */
|
||||
int i40e_up(struct i40e_vsi *vsi);
|
||||
void i40e_down(struct i40e_vsi *vsi);
|
||||
extern const char i40e_driver_name[];
|
||||
extern const char i40e_driver_version_str[];
|
||||
void i40e_do_reset_safe(struct i40e_pf *pf, u32 reset_flags);
|
||||
void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags);
|
||||
void i40e_update_stats(struct i40e_vsi *vsi);
|
||||
void i40e_update_eth_stats(struct i40e_vsi *vsi);
|
||||
struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi);
|
||||
int i40e_fetch_switch_configuration(struct i40e_pf *pf,
|
||||
bool printconfig);
|
||||
|
||||
int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
|
||||
struct i40e_pf *pf, bool add);
|
||||
int i40e_add_del_fdir(struct i40e_vsi *vsi,
|
||||
struct i40e_fdir_filter *input, bool add);
|
||||
void i40e_fdir_check_and_reenable(struct i40e_pf *pf);
|
||||
int i40e_get_current_fd_count(struct i40e_pf *pf);
|
||||
int i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf);
|
||||
int i40e_get_current_atr_cnt(struct i40e_pf *pf);
|
||||
bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
|
||||
void i40e_set_ethtool_ops(struct net_device *netdev);
|
||||
struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
|
||||
u8 *macaddr, s16 vlan,
|
||||
bool is_vf, bool is_netdev);
|
||||
void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan,
|
||||
bool is_vf, bool is_netdev);
|
||||
int i40e_sync_vsi_filters(struct i40e_vsi *vsi);
|
||||
struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
|
||||
u16 uplink, u32 param1);
|
||||
int i40e_vsi_release(struct i40e_vsi *vsi);
|
||||
struct i40e_vsi *i40e_vsi_lookup(struct i40e_pf *pf, enum i40e_vsi_type type,
|
||||
struct i40e_vsi *start_vsi);
|
||||
#ifdef I40E_FCOE
|
||||
void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
|
||||
struct i40e_vsi_context *ctxt,
|
||||
u8 enabled_tc, bool is_add);
|
||||
#endif
|
||||
int i40e_vsi_control_rings(struct i40e_vsi *vsi, bool enable);
|
||||
int i40e_reconfig_rss_queues(struct i40e_pf *pf, int queue_count);
|
||||
struct i40e_veb *i40e_veb_setup(struct i40e_pf *pf, u16 flags, u16 uplink_seid,
|
||||
u16 downlink_seid, u8 enabled_tc);
|
||||
void i40e_veb_release(struct i40e_veb *veb);
|
||||
|
||||
int i40e_veb_config_tc(struct i40e_veb *veb, u8 enabled_tc);
|
||||
i40e_status i40e_vsi_add_pvid(struct i40e_vsi *vsi, u16 vid);
|
||||
void i40e_vsi_remove_pvid(struct i40e_vsi *vsi);
|
||||
void i40e_vsi_reset_stats(struct i40e_vsi *vsi);
|
||||
void i40e_pf_reset_stats(struct i40e_pf *pf);
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void i40e_dbg_pf_init(struct i40e_pf *pf);
|
||||
void i40e_dbg_pf_exit(struct i40e_pf *pf);
|
||||
void i40e_dbg_init(void);
|
||||
void i40e_dbg_exit(void);
|
||||
#else
|
||||
static inline void i40e_dbg_pf_init(struct i40e_pf *pf) {}
|
||||
static inline void i40e_dbg_pf_exit(struct i40e_pf *pf) {}
|
||||
static inline void i40e_dbg_init(void) {}
|
||||
static inline void i40e_dbg_exit(void) {}
|
||||
#endif /* CONFIG_DEBUG_FS*/
|
||||
void i40e_irq_dynamic_enable(struct i40e_vsi *vsi, int vector);
|
||||
void i40e_irq_dynamic_disable(struct i40e_vsi *vsi, int vector);
|
||||
void i40e_irq_dynamic_disable_icr0(struct i40e_pf *pf);
|
||||
void i40e_irq_dynamic_enable_icr0(struct i40e_pf *pf);
|
||||
#ifdef I40E_FCOE
|
||||
struct rtnl_link_stats64 *i40e_get_netdev_stats_struct(
|
||||
struct net_device *netdev,
|
||||
struct rtnl_link_stats64 *storage);
|
||||
int i40e_set_mac(struct net_device *netdev, void *p);
|
||||
void i40e_set_rx_mode(struct net_device *netdev);
|
||||
#endif
|
||||
int i40e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
|
||||
#ifdef I40E_FCOE
|
||||
void i40e_tx_timeout(struct net_device *netdev);
|
||||
int i40e_vlan_rx_add_vid(struct net_device *netdev,
|
||||
__always_unused __be16 proto, u16 vid);
|
||||
int i40e_vlan_rx_kill_vid(struct net_device *netdev,
|
||||
__always_unused __be16 proto, u16 vid);
|
||||
#endif
|
||||
int i40e_vsi_open(struct i40e_vsi *vsi);
|
||||
void i40e_vlan_stripping_disable(struct i40e_vsi *vsi);
|
||||
int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid);
|
||||
int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid);
|
||||
struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr,
|
||||
bool is_vf, bool is_netdev);
|
||||
bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
|
||||
struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr,
|
||||
bool is_vf, bool is_netdev);
|
||||
#ifdef I40E_FCOE
|
||||
int i40e_open(struct net_device *netdev);
|
||||
int i40e_close(struct net_device *netdev);
|
||||
int i40e_setup_tc(struct net_device *netdev, u8 tc);
|
||||
void i40e_netpoll(struct net_device *netdev);
|
||||
int i40e_fcoe_enable(struct net_device *netdev);
|
||||
int i40e_fcoe_disable(struct net_device *netdev);
|
||||
int i40e_fcoe_vsi_init(struct i40e_vsi *vsi, struct i40e_vsi_context *ctxt);
|
||||
u8 i40e_get_fcoe_tc_map(struct i40e_pf *pf);
|
||||
void i40e_fcoe_config_netdev(struct net_device *netdev, struct i40e_vsi *vsi);
|
||||
void i40e_fcoe_vsi_setup(struct i40e_pf *pf);
|
||||
int i40e_init_pf_fcoe(struct i40e_pf *pf);
|
||||
int i40e_fcoe_setup_ddp_resources(struct i40e_vsi *vsi);
|
||||
void i40e_fcoe_free_ddp_resources(struct i40e_vsi *vsi);
|
||||
int i40e_fcoe_handle_offload(struct i40e_ring *rx_ring,
|
||||
union i40e_rx_desc *rx_desc,
|
||||
struct sk_buff *skb);
|
||||
void i40e_fcoe_handle_status(struct i40e_ring *rx_ring,
|
||||
union i40e_rx_desc *rx_desc, u8 prog_id);
|
||||
#endif /* I40E_FCOE */
|
||||
void i40e_vlan_stripping_enable(struct i40e_vsi *vsi);
|
||||
#ifdef CONFIG_I40E_DCB
|
||||
void i40e_dcbnl_flush_apps(struct i40e_pf *pf,
|
||||
struct i40e_dcbx_config *new_cfg);
|
||||
void i40e_dcbnl_set_all(struct i40e_vsi *vsi);
|
||||
void i40e_dcbnl_setup(struct i40e_vsi *vsi);
|
||||
bool i40e_dcb_need_reconfig(struct i40e_pf *pf,
|
||||
struct i40e_dcbx_config *old_cfg,
|
||||
struct i40e_dcbx_config *new_cfg);
|
||||
#endif /* CONFIG_I40E_DCB */
|
||||
void i40e_ptp_rx_hang(struct i40e_vsi *vsi);
|
||||
void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf);
|
||||
void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index);
|
||||
void i40e_ptp_set_increment(struct i40e_pf *pf);
|
||||
int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
|
||||
int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr);
|
||||
void i40e_ptp_init(struct i40e_pf *pf);
|
||||
void i40e_ptp_stop(struct i40e_pf *pf);
|
||||
#endif /* _I40E_H_ */
|
1046
drivers/net/ethernet/intel/i40e/i40e_adminq.c
Normal file
1046
drivers/net/ethernet/intel/i40e/i40e_adminq.c
Normal file
File diff suppressed because it is too large
Load diff
149
drivers/net/ethernet/intel/i40e/i40e_adminq.h
Normal file
149
drivers/net/ethernet/intel/i40e/i40e_adminq.h
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_ADMINQ_H_
|
||||
#define _I40E_ADMINQ_H_
|
||||
|
||||
#include "i40e_osdep.h"
|
||||
#include "i40e_adminq_cmd.h"
|
||||
|
||||
#define I40E_ADMINQ_DESC(R, i) \
|
||||
(&(((struct i40e_aq_desc *)((R).desc_buf.va))[i]))
|
||||
|
||||
#define I40E_ADMINQ_DESC_ALIGNMENT 4096
|
||||
|
||||
struct i40e_adminq_ring {
|
||||
struct i40e_virt_mem dma_head; /* space for dma structures */
|
||||
struct i40e_dma_mem desc_buf; /* descriptor ring memory */
|
||||
struct i40e_virt_mem cmd_buf; /* command buffer memory */
|
||||
|
||||
union {
|
||||
struct i40e_dma_mem *asq_bi;
|
||||
struct i40e_dma_mem *arq_bi;
|
||||
} r;
|
||||
|
||||
u16 count; /* Number of descriptors */
|
||||
u16 rx_buf_len; /* Admin Receive Queue buffer length */
|
||||
|
||||
/* used for interrupt processing */
|
||||
u16 next_to_use;
|
||||
u16 next_to_clean;
|
||||
|
||||
/* used for queue tracking */
|
||||
u32 head;
|
||||
u32 tail;
|
||||
u32 len;
|
||||
u32 bah;
|
||||
u32 bal;
|
||||
};
|
||||
|
||||
/* ASQ transaction details */
|
||||
struct i40e_asq_cmd_details {
|
||||
void *callback; /* cast from type I40E_ADMINQ_CALLBACK */
|
||||
u64 cookie;
|
||||
u16 flags_ena;
|
||||
u16 flags_dis;
|
||||
bool async;
|
||||
bool postpone;
|
||||
};
|
||||
|
||||
#define I40E_ADMINQ_DETAILS(R, i) \
|
||||
(&(((struct i40e_asq_cmd_details *)((R).cmd_buf.va))[i]))
|
||||
|
||||
/* ARQ event information */
|
||||
struct i40e_arq_event_info {
|
||||
struct i40e_aq_desc desc;
|
||||
u16 msg_size;
|
||||
u8 *msg_buf;
|
||||
};
|
||||
|
||||
/* Admin Queue information */
|
||||
struct i40e_adminq_info {
|
||||
struct i40e_adminq_ring arq; /* receive queue */
|
||||
struct i40e_adminq_ring asq; /* send queue */
|
||||
u32 asq_cmd_timeout; /* send queue cmd write back timeout*/
|
||||
u16 num_arq_entries; /* receive queue depth */
|
||||
u16 num_asq_entries; /* send queue depth */
|
||||
u16 arq_buf_size; /* receive queue buffer size */
|
||||
u16 asq_buf_size; /* send queue buffer size */
|
||||
u16 fw_maj_ver; /* firmware major version */
|
||||
u16 fw_min_ver; /* firmware minor version */
|
||||
u16 api_maj_ver; /* api major version */
|
||||
u16 api_min_ver; /* api minor version */
|
||||
bool nvm_busy;
|
||||
bool nvm_release_on_done;
|
||||
|
||||
struct mutex asq_mutex; /* Send queue lock */
|
||||
struct mutex arq_mutex; /* Receive queue lock */
|
||||
|
||||
/* last status values on send and receive queues */
|
||||
enum i40e_admin_queue_err asq_last_status;
|
||||
enum i40e_admin_queue_err arq_last_status;
|
||||
};
|
||||
|
||||
/**
|
||||
* i40e_aq_rc_to_posix - convert errors to user-land codes
|
||||
* aq_rc: AdminQ error code to convert
|
||||
**/
|
||||
static inline int i40e_aq_rc_to_posix(u16 aq_rc)
|
||||
{
|
||||
int aq_to_posix[] = {
|
||||
0, /* I40E_AQ_RC_OK */
|
||||
-EPERM, /* I40E_AQ_RC_EPERM */
|
||||
-ENOENT, /* I40E_AQ_RC_ENOENT */
|
||||
-ESRCH, /* I40E_AQ_RC_ESRCH */
|
||||
-EINTR, /* I40E_AQ_RC_EINTR */
|
||||
-EIO, /* I40E_AQ_RC_EIO */
|
||||
-ENXIO, /* I40E_AQ_RC_ENXIO */
|
||||
-E2BIG, /* I40E_AQ_RC_E2BIG */
|
||||
-EAGAIN, /* I40E_AQ_RC_EAGAIN */
|
||||
-ENOMEM, /* I40E_AQ_RC_ENOMEM */
|
||||
-EACCES, /* I40E_AQ_RC_EACCES */
|
||||
-EFAULT, /* I40E_AQ_RC_EFAULT */
|
||||
-EBUSY, /* I40E_AQ_RC_EBUSY */
|
||||
-EEXIST, /* I40E_AQ_RC_EEXIST */
|
||||
-EINVAL, /* I40E_AQ_RC_EINVAL */
|
||||
-ENOTTY, /* I40E_AQ_RC_ENOTTY */
|
||||
-ENOSPC, /* I40E_AQ_RC_ENOSPC */
|
||||
-ENOSYS, /* I40E_AQ_RC_ENOSYS */
|
||||
-ERANGE, /* I40E_AQ_RC_ERANGE */
|
||||
-EPIPE, /* I40E_AQ_RC_EFLUSHED */
|
||||
-ESPIPE, /* I40E_AQ_RC_BAD_ADDR */
|
||||
-EROFS, /* I40E_AQ_RC_EMODE */
|
||||
-EFBIG, /* I40E_AQ_RC_EFBIG */
|
||||
};
|
||||
|
||||
return aq_to_posix[aq_rc];
|
||||
}
|
||||
|
||||
/* general information */
|
||||
#define I40E_AQ_LARGE_BUF 512
|
||||
#define I40E_ASQ_CMD_TIMEOUT 100000 /* usecs */
|
||||
|
||||
void i40e_fill_default_direct_cmd_desc(struct i40e_aq_desc *desc,
|
||||
u16 opcode);
|
||||
|
||||
#endif /* _I40E_ADMINQ_H_ */
|
2173
drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
Normal file
2173
drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h
Normal file
File diff suppressed because it is too large
Load diff
58
drivers/net/ethernet/intel/i40e/i40e_alloc.h
Normal file
58
drivers/net/ethernet/intel/i40e/i40e_alloc.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_ALLOC_H_
|
||||
#define _I40E_ALLOC_H_
|
||||
|
||||
struct i40e_hw;
|
||||
|
||||
/* Memory allocation types */
|
||||
enum i40e_memory_type {
|
||||
i40e_mem_arq_buf = 0, /* ARQ indirect command buffer */
|
||||
i40e_mem_asq_buf = 1,
|
||||
i40e_mem_atq_buf = 2, /* ATQ indirect command buffer */
|
||||
i40e_mem_arq_ring = 3, /* ARQ descriptor ring */
|
||||
i40e_mem_atq_ring = 4, /* ATQ descriptor ring */
|
||||
i40e_mem_pd = 5, /* Page Descriptor */
|
||||
i40e_mem_bp = 6, /* Backing Page - 4KB */
|
||||
i40e_mem_bp_jumbo = 7, /* Backing Page - > 4KB */
|
||||
i40e_mem_reserved
|
||||
};
|
||||
|
||||
/* prototype for functions used for dynamic memory allocation */
|
||||
i40e_status i40e_allocate_dma_mem(struct i40e_hw *hw,
|
||||
struct i40e_dma_mem *mem,
|
||||
enum i40e_memory_type type,
|
||||
u64 size, u32 alignment);
|
||||
i40e_status i40e_free_dma_mem(struct i40e_hw *hw,
|
||||
struct i40e_dma_mem *mem);
|
||||
i40e_status i40e_allocate_virt_mem(struct i40e_hw *hw,
|
||||
struct i40e_virt_mem *mem,
|
||||
u32 size);
|
||||
i40e_status i40e_free_virt_mem(struct i40e_hw *hw,
|
||||
struct i40e_virt_mem *mem);
|
||||
|
||||
#endif /* _I40E_ALLOC_H_ */
|
3234
drivers/net/ethernet/intel/i40e/i40e_common.c
Normal file
3234
drivers/net/ethernet/intel/i40e/i40e_common.c
Normal file
File diff suppressed because it is too large
Load diff
472
drivers/net/ethernet/intel/i40e/i40e_dcb.c
Normal file
472
drivers/net/ethernet/intel/i40e/i40e_dcb.c
Normal file
|
@ -0,0 +1,472 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "i40e_adminq.h"
|
||||
#include "i40e_prototype.h"
|
||||
#include "i40e_dcb.h"
|
||||
|
||||
/**
|
||||
* i40e_get_dcbx_status
|
||||
* @hw: pointer to the hw struct
|
||||
* @status: Embedded DCBX Engine Status
|
||||
*
|
||||
* Get the DCBX status from the Firmware
|
||||
**/
|
||||
i40e_status i40e_get_dcbx_status(struct i40e_hw *hw, u16 *status)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (!status)
|
||||
return I40E_ERR_PARAM;
|
||||
|
||||
reg = rd32(hw, I40E_PRTDCB_GENS);
|
||||
*status = (u16)((reg & I40E_PRTDCB_GENS_DCBX_STATUS_MASK) >>
|
||||
I40E_PRTDCB_GENS_DCBX_STATUS_SHIFT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_ieee_etscfg_tlv
|
||||
* @tlv: IEEE 802.1Qaz ETS CFG TLV
|
||||
* @dcbcfg: Local store to update ETS CFG data
|
||||
*
|
||||
* Parses IEEE 802.1Qaz ETS CFG TLV
|
||||
**/
|
||||
static void i40e_parse_ieee_etscfg_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
struct i40e_ieee_ets_config *etscfg;
|
||||
u8 *buf = tlv->tlvinfo;
|
||||
u16 offset = 0;
|
||||
u8 priority;
|
||||
int i;
|
||||
|
||||
/* First Octet post subtype
|
||||
* --------------------------
|
||||
* |will-|CBS | Re- | Max |
|
||||
* |ing | |served| TCs |
|
||||
* --------------------------
|
||||
* |1bit | 1bit|3 bits|3bits|
|
||||
*/
|
||||
etscfg = &dcbcfg->etscfg;
|
||||
etscfg->willing = (u8)((buf[offset] & I40E_IEEE_ETS_WILLING_MASK) >>
|
||||
I40E_IEEE_ETS_WILLING_SHIFT);
|
||||
etscfg->cbs = (u8)((buf[offset] & I40E_IEEE_ETS_CBS_MASK) >>
|
||||
I40E_IEEE_ETS_CBS_SHIFT);
|
||||
etscfg->maxtcs = (u8)((buf[offset] & I40E_IEEE_ETS_MAXTC_MASK) >>
|
||||
I40E_IEEE_ETS_MAXTC_SHIFT);
|
||||
|
||||
/* Move offset to Priority Assignment Table */
|
||||
offset++;
|
||||
|
||||
/* Priority Assignment Table (4 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 |
|
||||
* -----------------------------------------
|
||||
* |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
|
||||
* -----------------------------------------
|
||||
* Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
|
||||
* -----------------------------------------
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
|
||||
I40E_IEEE_ETS_PRIO_1_SHIFT);
|
||||
etscfg->prioritytable[i * 2] = priority;
|
||||
priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
|
||||
I40E_IEEE_ETS_PRIO_0_SHIFT);
|
||||
etscfg->prioritytable[i * 2 + 1] = priority;
|
||||
offset++;
|
||||
}
|
||||
|
||||
/* TC Bandwidth Table (8 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
* ---------------------------------
|
||||
* |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
|
||||
* ---------------------------------
|
||||
*/
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
|
||||
etscfg->tcbwtable[i] = buf[offset++];
|
||||
|
||||
/* TSA Assignment Table (8 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
* ---------------------------------
|
||||
* |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
|
||||
* ---------------------------------
|
||||
*/
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
|
||||
etscfg->tsatable[i] = buf[offset++];
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_ieee_etsrec_tlv
|
||||
* @tlv: IEEE 802.1Qaz ETS REC TLV
|
||||
* @dcbcfg: Local store to update ETS REC data
|
||||
*
|
||||
* Parses IEEE 802.1Qaz ETS REC TLV
|
||||
**/
|
||||
static void i40e_parse_ieee_etsrec_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u8 *buf = tlv->tlvinfo;
|
||||
u16 offset = 0;
|
||||
u8 priority;
|
||||
int i;
|
||||
|
||||
/* Move offset to priority table */
|
||||
offset++;
|
||||
|
||||
/* Priority Assignment Table (4 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 |
|
||||
* -----------------------------------------
|
||||
* |pri0|pri1|pri2|pri3|pri4|pri5|pri6|pri7|
|
||||
* -----------------------------------------
|
||||
* Bits:|7 4|3 0|7 4|3 0|7 4|3 0|7 4|3 0|
|
||||
* -----------------------------------------
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_1_MASK) >>
|
||||
I40E_IEEE_ETS_PRIO_1_SHIFT);
|
||||
dcbcfg->etsrec.prioritytable[i*2] = priority;
|
||||
priority = (u8)((buf[offset] & I40E_IEEE_ETS_PRIO_0_MASK) >>
|
||||
I40E_IEEE_ETS_PRIO_0_SHIFT);
|
||||
dcbcfg->etsrec.prioritytable[i*2 + 1] = priority;
|
||||
offset++;
|
||||
}
|
||||
|
||||
/* TC Bandwidth Table (8 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
* ---------------------------------
|
||||
* |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
|
||||
* ---------------------------------
|
||||
*/
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
|
||||
dcbcfg->etsrec.tcbwtable[i] = buf[offset++];
|
||||
|
||||
/* TSA Assignment Table (8 octets)
|
||||
* Octets:| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|
||||
* ---------------------------------
|
||||
* |tc0|tc1|tc2|tc3|tc4|tc5|tc6|tc7|
|
||||
* ---------------------------------
|
||||
*/
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++)
|
||||
dcbcfg->etsrec.tsatable[i] = buf[offset++];
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_ieee_pfccfg_tlv
|
||||
* @tlv: IEEE 802.1Qaz PFC CFG TLV
|
||||
* @dcbcfg: Local store to update PFC CFG data
|
||||
*
|
||||
* Parses IEEE 802.1Qaz PFC CFG TLV
|
||||
**/
|
||||
static void i40e_parse_ieee_pfccfg_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u8 *buf = tlv->tlvinfo;
|
||||
|
||||
/* ----------------------------------------
|
||||
* |will-|MBC | Re- | PFC | PFC Enable |
|
||||
* |ing | |served| cap | |
|
||||
* -----------------------------------------
|
||||
* |1bit | 1bit|2 bits|4bits| 1 octet |
|
||||
*/
|
||||
dcbcfg->pfc.willing = (u8)((buf[0] & I40E_IEEE_PFC_WILLING_MASK) >>
|
||||
I40E_IEEE_PFC_WILLING_SHIFT);
|
||||
dcbcfg->pfc.mbc = (u8)((buf[0] & I40E_IEEE_PFC_MBC_MASK) >>
|
||||
I40E_IEEE_PFC_MBC_SHIFT);
|
||||
dcbcfg->pfc.pfccap = (u8)((buf[0] & I40E_IEEE_PFC_CAP_MASK) >>
|
||||
I40E_IEEE_PFC_CAP_SHIFT);
|
||||
dcbcfg->pfc.pfcenable = buf[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_ieee_app_tlv
|
||||
* @tlv: IEEE 802.1Qaz APP TLV
|
||||
* @dcbcfg: Local store to update APP PRIO data
|
||||
*
|
||||
* Parses IEEE 802.1Qaz APP PRIO TLV
|
||||
**/
|
||||
static void i40e_parse_ieee_app_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u16 typelength;
|
||||
u16 offset = 0;
|
||||
u16 length;
|
||||
int i = 0;
|
||||
u8 *buf;
|
||||
|
||||
typelength = ntohs(tlv->typelength);
|
||||
length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
|
||||
I40E_LLDP_TLV_LEN_SHIFT);
|
||||
buf = tlv->tlvinfo;
|
||||
|
||||
/* The App priority table starts 5 octets after TLV header */
|
||||
length -= (sizeof(tlv->ouisubtype) + 1);
|
||||
|
||||
/* Move offset to App Priority Table */
|
||||
offset++;
|
||||
|
||||
/* Application Priority Table (3 octets)
|
||||
* Octets:| 1 | 2 | 3 |
|
||||
* -----------------------------------------
|
||||
* |Priority|Rsrvd| Sel | Protocol ID |
|
||||
* -----------------------------------------
|
||||
* Bits:|23 21|20 19|18 16|15 0|
|
||||
* -----------------------------------------
|
||||
*/
|
||||
while (offset < length) {
|
||||
dcbcfg->app[i].priority = (u8)((buf[offset] &
|
||||
I40E_IEEE_APP_PRIO_MASK) >>
|
||||
I40E_IEEE_APP_PRIO_SHIFT);
|
||||
dcbcfg->app[i].selector = (u8)((buf[offset] &
|
||||
I40E_IEEE_APP_SEL_MASK) >>
|
||||
I40E_IEEE_APP_SEL_SHIFT);
|
||||
dcbcfg->app[i].protocolid = (buf[offset + 1] << 0x8) |
|
||||
buf[offset + 2];
|
||||
/* Move to next app */
|
||||
offset += 3;
|
||||
i++;
|
||||
if (i >= I40E_DCBX_MAX_APPS)
|
||||
break;
|
||||
}
|
||||
|
||||
dcbcfg->numapps = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_ieee_etsrec_tlv
|
||||
* @tlv: IEEE 802.1Qaz TLV
|
||||
* @dcbcfg: Local store to update ETS REC data
|
||||
*
|
||||
* Get the TLV subtype and send it to parsing function
|
||||
* based on the subtype value
|
||||
**/
|
||||
static void i40e_parse_ieee_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u32 ouisubtype;
|
||||
u8 subtype;
|
||||
|
||||
ouisubtype = ntohl(tlv->ouisubtype);
|
||||
subtype = (u8)((ouisubtype & I40E_LLDP_TLV_SUBTYPE_MASK) >>
|
||||
I40E_LLDP_TLV_SUBTYPE_SHIFT);
|
||||
switch (subtype) {
|
||||
case I40E_IEEE_SUBTYPE_ETS_CFG:
|
||||
i40e_parse_ieee_etscfg_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
case I40E_IEEE_SUBTYPE_ETS_REC:
|
||||
i40e_parse_ieee_etsrec_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
case I40E_IEEE_SUBTYPE_PFC_CFG:
|
||||
i40e_parse_ieee_pfccfg_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
case I40E_IEEE_SUBTYPE_APP_PRI:
|
||||
i40e_parse_ieee_app_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_parse_org_tlv
|
||||
* @tlv: Organization specific TLV
|
||||
* @dcbcfg: Local store to update ETS REC data
|
||||
*
|
||||
* Currently only IEEE 802.1Qaz TLV is supported, all others
|
||||
* will be returned
|
||||
**/
|
||||
static void i40e_parse_org_tlv(struct i40e_lldp_org_tlv *tlv,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
u32 ouisubtype;
|
||||
u32 oui;
|
||||
|
||||
ouisubtype = ntohl(tlv->ouisubtype);
|
||||
oui = (u32)((ouisubtype & I40E_LLDP_TLV_OUI_MASK) >>
|
||||
I40E_LLDP_TLV_OUI_SHIFT);
|
||||
switch (oui) {
|
||||
case I40E_IEEE_8021QAZ_OUI:
|
||||
i40e_parse_ieee_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_lldp_to_dcb_config
|
||||
* @lldpmib: LLDPDU to be parsed
|
||||
* @dcbcfg: store for LLDPDU data
|
||||
*
|
||||
* Parse DCB configuration from the LLDPDU
|
||||
**/
|
||||
i40e_status i40e_lldp_to_dcb_config(u8 *lldpmib,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
i40e_status ret = 0;
|
||||
struct i40e_lldp_org_tlv *tlv;
|
||||
u16 type;
|
||||
u16 length;
|
||||
u16 typelength;
|
||||
u16 offset = 0;
|
||||
|
||||
if (!lldpmib || !dcbcfg)
|
||||
return I40E_ERR_PARAM;
|
||||
|
||||
/* set to the start of LLDPDU */
|
||||
lldpmib += ETH_HLEN;
|
||||
tlv = (struct i40e_lldp_org_tlv *)lldpmib;
|
||||
while (1) {
|
||||
typelength = ntohs(tlv->typelength);
|
||||
type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
|
||||
I40E_LLDP_TLV_TYPE_SHIFT);
|
||||
length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
|
||||
I40E_LLDP_TLV_LEN_SHIFT);
|
||||
offset += sizeof(typelength) + length;
|
||||
|
||||
/* END TLV or beyond LLDPDU size */
|
||||
if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
|
||||
break;
|
||||
|
||||
switch (type) {
|
||||
case I40E_TLV_TYPE_ORG:
|
||||
i40e_parse_org_tlv(tlv, dcbcfg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Move to next TLV */
|
||||
tlv = (struct i40e_lldp_org_tlv *)((char *)tlv +
|
||||
sizeof(tlv->typelength) +
|
||||
length);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_aq_get_dcb_config
|
||||
* @hw: pointer to the hw struct
|
||||
* @mib_type: mib type for the query
|
||||
* @bridgetype: bridge type for the query (remote)
|
||||
* @dcbcfg: store for LLDPDU data
|
||||
*
|
||||
* Query DCB configuration from the Firmware
|
||||
**/
|
||||
i40e_status i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
|
||||
u8 bridgetype,
|
||||
struct i40e_dcbx_config *dcbcfg)
|
||||
{
|
||||
i40e_status ret = 0;
|
||||
struct i40e_virt_mem mem;
|
||||
u8 *lldpmib;
|
||||
|
||||
/* Allocate the LLDPDU */
|
||||
ret = i40e_allocate_virt_mem(hw, &mem, I40E_LLDPDU_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
lldpmib = (u8 *)mem.va;
|
||||
ret = i40e_aq_get_lldp_mib(hw, bridgetype, mib_type,
|
||||
(void *)lldpmib, I40E_LLDPDU_SIZE,
|
||||
NULL, NULL, NULL);
|
||||
if (ret)
|
||||
goto free_mem;
|
||||
|
||||
/* Parse LLDP MIB to get dcb configuration */
|
||||
ret = i40e_lldp_to_dcb_config(lldpmib, dcbcfg);
|
||||
|
||||
free_mem:
|
||||
i40e_free_virt_mem(hw, &mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_get_dcb_config
|
||||
* @hw: pointer to the hw struct
|
||||
*
|
||||
* Get DCB configuration from the Firmware
|
||||
**/
|
||||
i40e_status i40e_get_dcb_config(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret = 0;
|
||||
|
||||
/* Get Local DCB Config */
|
||||
ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_LOCAL, 0,
|
||||
&hw->local_dcbx_config);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Get Remote DCB Config */
|
||||
ret = i40e_aq_get_dcb_config(hw, I40E_AQ_LLDP_MIB_REMOTE,
|
||||
I40E_AQ_LLDP_BRIDGE_TYPE_NEAREST_BRIDGE,
|
||||
&hw->remote_dcbx_config);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_init_dcb
|
||||
* @hw: pointer to the hw struct
|
||||
*
|
||||
* Update DCB configuration from the Firmware
|
||||
**/
|
||||
i40e_status i40e_init_dcb(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret = 0;
|
||||
|
||||
if (!hw->func_caps.dcb)
|
||||
return ret;
|
||||
|
||||
/* Get DCBX status */
|
||||
ret = i40e_get_dcbx_status(hw, &hw->dcbx_status);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Check the DCBX Status */
|
||||
switch (hw->dcbx_status) {
|
||||
case I40E_DCBX_STATUS_DONE:
|
||||
case I40E_DCBX_STATUS_IN_PROGRESS:
|
||||
/* Get current DCBX configuration */
|
||||
ret = i40e_get_dcb_config(hw);
|
||||
break;
|
||||
case I40E_DCBX_STATUS_DISABLED:
|
||||
return ret;
|
||||
case I40E_DCBX_STATUS_NOT_STARTED:
|
||||
case I40E_DCBX_STATUS_MULTIPLE_PEERS:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Configure the LLDP MIB change event */
|
||||
ret = i40e_aq_cfg_lldp_mib_change_event(hw, true, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
107
drivers/net/ethernet/intel/i40e/i40e_dcb.h
Normal file
107
drivers/net/ethernet/intel/i40e/i40e_dcb.h
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_DCB_H_
|
||||
#define _I40E_DCB_H_
|
||||
|
||||
#include "i40e_type.h"
|
||||
|
||||
#define I40E_DCBX_STATUS_NOT_STARTED 0
|
||||
#define I40E_DCBX_STATUS_IN_PROGRESS 1
|
||||
#define I40E_DCBX_STATUS_DONE 2
|
||||
#define I40E_DCBX_STATUS_MULTIPLE_PEERS 3
|
||||
#define I40E_DCBX_STATUS_DISABLED 7
|
||||
|
||||
#define I40E_TLV_TYPE_END 0
|
||||
#define I40E_TLV_TYPE_ORG 127
|
||||
|
||||
#define I40E_IEEE_8021QAZ_OUI 0x0080C2
|
||||
#define I40E_IEEE_SUBTYPE_ETS_CFG 9
|
||||
#define I40E_IEEE_SUBTYPE_ETS_REC 10
|
||||
#define I40E_IEEE_SUBTYPE_PFC_CFG 11
|
||||
#define I40E_IEEE_SUBTYPE_APP_PRI 12
|
||||
|
||||
/* Defines for LLDP TLV header */
|
||||
#define I40E_LLDP_TLV_LEN_SHIFT 0
|
||||
#define I40E_LLDP_TLV_LEN_MASK (0x01FF << I40E_LLDP_TLV_LEN_SHIFT)
|
||||
#define I40E_LLDP_TLV_TYPE_SHIFT 9
|
||||
#define I40E_LLDP_TLV_TYPE_MASK (0x7F << I40E_LLDP_TLV_TYPE_SHIFT)
|
||||
#define I40E_LLDP_TLV_SUBTYPE_SHIFT 0
|
||||
#define I40E_LLDP_TLV_SUBTYPE_MASK (0xFF << I40E_LLDP_TLV_SUBTYPE_SHIFT)
|
||||
#define I40E_LLDP_TLV_OUI_SHIFT 8
|
||||
#define I40E_LLDP_TLV_OUI_MASK (0xFFFFFF << I40E_LLDP_TLV_OUI_SHIFT)
|
||||
|
||||
/* Defines for IEEE ETS TLV */
|
||||
#define I40E_IEEE_ETS_MAXTC_SHIFT 0
|
||||
#define I40E_IEEE_ETS_MAXTC_MASK (0x7 << I40E_IEEE_ETS_MAXTC_SHIFT)
|
||||
#define I40E_IEEE_ETS_CBS_SHIFT 6
|
||||
#define I40E_IEEE_ETS_CBS_MASK (0x1 << I40E_IEEE_ETS_CBS_SHIFT)
|
||||
#define I40E_IEEE_ETS_WILLING_SHIFT 7
|
||||
#define I40E_IEEE_ETS_WILLING_MASK (0x1 << I40E_IEEE_ETS_WILLING_SHIFT)
|
||||
#define I40E_IEEE_ETS_PRIO_0_SHIFT 0
|
||||
#define I40E_IEEE_ETS_PRIO_0_MASK (0x7 << I40E_IEEE_ETS_PRIO_0_SHIFT)
|
||||
#define I40E_IEEE_ETS_PRIO_1_SHIFT 4
|
||||
#define I40E_IEEE_ETS_PRIO_1_MASK (0x7 << I40E_IEEE_ETS_PRIO_1_SHIFT)
|
||||
|
||||
/* Defines for IEEE TSA types */
|
||||
#define I40E_IEEE_TSA_STRICT 0
|
||||
#define I40E_IEEE_TSA_ETS 2
|
||||
|
||||
/* Defines for IEEE PFC TLV */
|
||||
#define I40E_IEEE_PFC_CAP_SHIFT 0
|
||||
#define I40E_IEEE_PFC_CAP_MASK (0xF << I40E_IEEE_PFC_CAP_SHIFT)
|
||||
#define I40E_IEEE_PFC_MBC_SHIFT 6
|
||||
#define I40E_IEEE_PFC_MBC_MASK (0x1 << I40E_IEEE_PFC_MBC_SHIFT)
|
||||
#define I40E_IEEE_PFC_WILLING_SHIFT 7
|
||||
#define I40E_IEEE_PFC_WILLING_MASK (0x1 << I40E_IEEE_PFC_WILLING_SHIFT)
|
||||
|
||||
/* Defines for IEEE APP TLV */
|
||||
#define I40E_IEEE_APP_SEL_SHIFT 0
|
||||
#define I40E_IEEE_APP_SEL_MASK (0x7 << I40E_IEEE_APP_SEL_SHIFT)
|
||||
#define I40E_IEEE_APP_PRIO_SHIFT 5
|
||||
#define I40E_IEEE_APP_PRIO_MASK (0x7 << I40E_IEEE_APP_PRIO_SHIFT)
|
||||
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/* IEEE 802.1AB LLDP Organization specific TLV */
|
||||
struct i40e_lldp_org_tlv {
|
||||
__be16 typelength;
|
||||
__be32 ouisubtype;
|
||||
u8 tlvinfo[1];
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
i40e_status i40e_get_dcbx_status(struct i40e_hw *hw,
|
||||
u16 *status);
|
||||
i40e_status i40e_lldp_to_dcb_config(u8 *lldpmib,
|
||||
struct i40e_dcbx_config *dcbcfg);
|
||||
i40e_status i40e_aq_get_dcb_config(struct i40e_hw *hw, u8 mib_type,
|
||||
u8 bridgetype,
|
||||
struct i40e_dcbx_config *dcbcfg);
|
||||
i40e_status i40e_get_dcb_config(struct i40e_hw *hw);
|
||||
i40e_status i40e_init_dcb(struct i40e_hw *hw);
|
||||
#endif /* _I40E_DCB_H_ */
|
316
drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c
Normal file
316
drivers/net/ethernet/intel/i40e/i40e_dcb_nl.c
Normal file
|
@ -0,0 +1,316 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef CONFIG_I40E_DCB
|
||||
#include "i40e.h"
|
||||
#include <net/dcbnl.h>
|
||||
|
||||
/**
|
||||
* i40e_get_pfc_delay - retrieve PFC Link Delay
|
||||
* @hw: pointer to hardware struct
|
||||
* @delay: holds the PFC Link delay value
|
||||
*
|
||||
* Returns PFC Link Delay from the PRTDCB_GENC.PFCLDA
|
||||
**/
|
||||
static void i40e_get_pfc_delay(struct i40e_hw *hw, u16 *delay)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = rd32(hw, I40E_PRTDCB_GENC);
|
||||
*delay = (u16)(val & I40E_PRTDCB_GENC_PFCLDA_MASK >>
|
||||
I40E_PRTDCB_GENC_PFCLDA_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_ieee_getets - retrieve local IEEE ETS configuration
|
||||
* @netdev: the corresponding netdev
|
||||
* @ets: structure to hold the ETS information
|
||||
*
|
||||
* Returns local IEEE ETS configuration
|
||||
**/
|
||||
static int i40e_dcbnl_ieee_getets(struct net_device *dev,
|
||||
struct ieee_ets *ets)
|
||||
{
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
struct i40e_dcbx_config *dcbxcfg;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
|
||||
if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
|
||||
return -EINVAL;
|
||||
|
||||
dcbxcfg = &hw->local_dcbx_config;
|
||||
ets->willing = dcbxcfg->etscfg.willing;
|
||||
ets->ets_cap = dcbxcfg->etscfg.maxtcs;
|
||||
ets->cbs = dcbxcfg->etscfg.cbs;
|
||||
memcpy(ets->tc_tx_bw, dcbxcfg->etscfg.tcbwtable,
|
||||
sizeof(ets->tc_tx_bw));
|
||||
memcpy(ets->tc_rx_bw, dcbxcfg->etscfg.tcbwtable,
|
||||
sizeof(ets->tc_rx_bw));
|
||||
memcpy(ets->tc_tsa, dcbxcfg->etscfg.tsatable,
|
||||
sizeof(ets->tc_tsa));
|
||||
memcpy(ets->prio_tc, dcbxcfg->etscfg.prioritytable,
|
||||
sizeof(ets->prio_tc));
|
||||
memcpy(ets->tc_reco_bw, dcbxcfg->etsrec.tcbwtable,
|
||||
sizeof(ets->tc_reco_bw));
|
||||
memcpy(ets->tc_reco_tsa, dcbxcfg->etsrec.tsatable,
|
||||
sizeof(ets->tc_reco_tsa));
|
||||
memcpy(ets->reco_prio_tc, dcbxcfg->etscfg.prioritytable,
|
||||
sizeof(ets->reco_prio_tc));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_ieee_getpfc - retrieve local IEEE PFC configuration
|
||||
* @netdev: the corresponding netdev
|
||||
* @ets: structure to hold the PFC information
|
||||
*
|
||||
* Returns local IEEE PFC configuration
|
||||
**/
|
||||
static int i40e_dcbnl_ieee_getpfc(struct net_device *dev,
|
||||
struct ieee_pfc *pfc)
|
||||
{
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
struct i40e_dcbx_config *dcbxcfg;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
int i;
|
||||
|
||||
if (!(pf->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
|
||||
return -EINVAL;
|
||||
|
||||
dcbxcfg = &hw->local_dcbx_config;
|
||||
pfc->pfc_cap = dcbxcfg->pfc.pfccap;
|
||||
pfc->pfc_en = dcbxcfg->pfc.pfcenable;
|
||||
pfc->mbc = dcbxcfg->pfc.mbc;
|
||||
i40e_get_pfc_delay(hw, &pfc->delay);
|
||||
|
||||
/* Get Requests/Indicatiosn */
|
||||
for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) {
|
||||
pfc->requests[i] = pf->stats.priority_xoff_tx[i];
|
||||
pfc->indications[i] = pf->stats.priority_xoff_rx[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_getdcbx - retrieve current DCBx capability
|
||||
* @netdev: the corresponding netdev
|
||||
*
|
||||
* Returns DCBx capability features
|
||||
**/
|
||||
static u8 i40e_dcbnl_getdcbx(struct net_device *dev)
|
||||
{
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
|
||||
return pf->dcbx_cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_get_perm_hw_addr - MAC address used by DCBx
|
||||
* @netdev: the corresponding netdev
|
||||
*
|
||||
* Returns the SAN MAC address used for LLDP exchange
|
||||
**/
|
||||
static void i40e_dcbnl_get_perm_hw_addr(struct net_device *dev,
|
||||
u8 *perm_addr)
|
||||
{
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
int i, j;
|
||||
|
||||
memset(perm_addr, 0xff, MAX_ADDR_LEN);
|
||||
|
||||
for (i = 0; i < dev->addr_len; i++)
|
||||
perm_addr[i] = pf->hw.mac.perm_addr[i];
|
||||
|
||||
for (j = 0; j < dev->addr_len; j++, i++)
|
||||
perm_addr[i] = pf->hw.mac.san_addr[j];
|
||||
}
|
||||
|
||||
static const struct dcbnl_rtnl_ops dcbnl_ops = {
|
||||
.ieee_getets = i40e_dcbnl_ieee_getets,
|
||||
.ieee_getpfc = i40e_dcbnl_ieee_getpfc,
|
||||
.getdcbx = i40e_dcbnl_getdcbx,
|
||||
.getpermhwaddr = i40e_dcbnl_get_perm_hw_addr,
|
||||
};
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_set_all - set all the apps and ieee data from DCBx config
|
||||
* @vsi: the corresponding vsi
|
||||
*
|
||||
* Set up all the IEEE APPs in the DCBNL App Table and generate event for
|
||||
* other settings
|
||||
**/
|
||||
void i40e_dcbnl_set_all(struct i40e_vsi *vsi)
|
||||
{
|
||||
struct net_device *dev = vsi->netdev;
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
struct i40e_dcbx_config *dcbxcfg;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
struct dcb_app sapp;
|
||||
u8 prio, tc_map;
|
||||
int i;
|
||||
|
||||
/* DCB not enabled */
|
||||
if (!(pf->flags & I40E_FLAG_DCB_ENABLED))
|
||||
return;
|
||||
|
||||
dcbxcfg = &hw->local_dcbx_config;
|
||||
|
||||
/* Set up all the App TLVs if DCBx is negotiated */
|
||||
for (i = 0; i < dcbxcfg->numapps; i++) {
|
||||
prio = dcbxcfg->app[i].priority;
|
||||
tc_map = (1 << dcbxcfg->etscfg.prioritytable[prio]);
|
||||
|
||||
/* Add APP only if the TC is enabled for this VSI */
|
||||
if (tc_map & vsi->tc_config.enabled_tc) {
|
||||
sapp.selector = dcbxcfg->app[i].selector;
|
||||
sapp.protocol = dcbxcfg->app[i].protocolid;
|
||||
sapp.priority = prio;
|
||||
dcb_ieee_setapp(dev, &sapp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Notify user-space of the changes */
|
||||
dcbnl_ieee_notify(dev, RTM_SETDCB, DCB_CMD_IEEE_SET, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_vsi_del_app - Delete APP for given VSI
|
||||
* @vsi: the corresponding vsi
|
||||
* @app: APP to delete
|
||||
*
|
||||
* Delete given APP from the DCBNL APP table for given
|
||||
* VSI
|
||||
**/
|
||||
static int i40e_dcbnl_vsi_del_app(struct i40e_vsi *vsi,
|
||||
struct i40e_ieee_app_priority_table *app)
|
||||
{
|
||||
struct net_device *dev = vsi->netdev;
|
||||
struct dcb_app sapp;
|
||||
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
sapp.selector = app->selector;
|
||||
sapp.protocol = app->protocolid;
|
||||
sapp.priority = app->priority;
|
||||
return dcb_ieee_delapp(dev, &sapp);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_del_app - Delete APP on all VSIs
|
||||
* @pf: the corresponding pf
|
||||
* @app: APP to delete
|
||||
*
|
||||
* Delete given APP from all the VSIs for given PF
|
||||
**/
|
||||
static void i40e_dcbnl_del_app(struct i40e_pf *pf,
|
||||
struct i40e_ieee_app_priority_table *app)
|
||||
{
|
||||
int v, err;
|
||||
for (v = 0; v < pf->num_alloc_vsi; v++) {
|
||||
if (pf->vsi[v] && pf->vsi[v]->netdev) {
|
||||
err = i40e_dcbnl_vsi_del_app(pf->vsi[v], app);
|
||||
if (err)
|
||||
dev_info(&pf->pdev->dev, "%s: Failed deleting app for VSI seid=%d err=%d sel=%d proto=0x%x prio=%d\n",
|
||||
__func__, pf->vsi[v]->seid,
|
||||
err, app->selector,
|
||||
app->protocolid, app->priority);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_find_app - Search APP in given DCB config
|
||||
* @cfg: DCBX configuration data
|
||||
* @app: APP to search for
|
||||
*
|
||||
* Find given APP in the DCB configuration
|
||||
**/
|
||||
static bool i40e_dcbnl_find_app(struct i40e_dcbx_config *cfg,
|
||||
struct i40e_ieee_app_priority_table *app)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cfg->numapps; i++) {
|
||||
if (app->selector == cfg->app[i].selector &&
|
||||
app->protocolid == cfg->app[i].protocolid &&
|
||||
app->priority == cfg->app[i].priority)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_flush_apps - Delete all removed APPs
|
||||
* @pf: the corresponding pf
|
||||
* @new_cfg: new DCBX configuration data
|
||||
*
|
||||
* Find and delete all APPs that are not present in the passed
|
||||
* DCB configuration
|
||||
**/
|
||||
void i40e_dcbnl_flush_apps(struct i40e_pf *pf,
|
||||
struct i40e_dcbx_config *new_cfg)
|
||||
{
|
||||
struct i40e_ieee_app_priority_table app;
|
||||
struct i40e_dcbx_config *dcbxcfg;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
int i;
|
||||
|
||||
dcbxcfg = &hw->local_dcbx_config;
|
||||
for (i = 0; i < dcbxcfg->numapps; i++) {
|
||||
app = dcbxcfg->app[i];
|
||||
/* The APP is not available anymore delete it */
|
||||
if (!i40e_dcbnl_find_app(new_cfg, &app))
|
||||
i40e_dcbnl_del_app(pf, &app);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_dcbnl_setup - DCBNL setup
|
||||
* @vsi: the corresponding vsi
|
||||
*
|
||||
* Set up DCBNL ops and initial APP TLVs
|
||||
**/
|
||||
void i40e_dcbnl_setup(struct i40e_vsi *vsi)
|
||||
{
|
||||
struct net_device *dev = vsi->netdev;
|
||||
struct i40e_pf *pf = i40e_netdev_to_pf(dev);
|
||||
|
||||
/* Not DCB capable */
|
||||
if (!(pf->flags & I40E_FLAG_DCB_CAPABLE))
|
||||
return;
|
||||
|
||||
/* Do not setup DCB NL ops for MFP mode */
|
||||
if (!(pf->flags & I40E_FLAG_MFP_ENABLED))
|
||||
dev->dcbnl_ops = &dcbnl_ops;
|
||||
|
||||
/* Set initial IEEE DCB settings */
|
||||
i40e_dcbnl_set_all(vsi);
|
||||
}
|
||||
#endif /* CONFIG_I40E_DCB */
|
2274
drivers/net/ethernet/intel/i40e/i40e_debugfs.c
Normal file
2274
drivers/net/ethernet/intel/i40e/i40e_debugfs.c
Normal file
File diff suppressed because it is too large
Load diff
154
drivers/net/ethernet/intel/i40e/i40e_diag.c
Normal file
154
drivers/net/ethernet/intel/i40e/i40e_diag.c
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "i40e_diag.h"
|
||||
#include "i40e_prototype.h"
|
||||
|
||||
/**
|
||||
* i40e_diag_reg_pattern_test
|
||||
* @hw: pointer to the hw struct
|
||||
* @reg: reg to be tested
|
||||
* @mask: bits to be touched
|
||||
**/
|
||||
static i40e_status i40e_diag_reg_pattern_test(struct i40e_hw *hw,
|
||||
u32 reg, u32 mask)
|
||||
{
|
||||
const u32 patterns[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
|
||||
u32 pat, val, orig_val;
|
||||
int i;
|
||||
|
||||
orig_val = rd32(hw, reg);
|
||||
for (i = 0; i < ARRAY_SIZE(patterns); i++) {
|
||||
pat = patterns[i];
|
||||
wr32(hw, reg, (pat & mask));
|
||||
val = rd32(hw, reg);
|
||||
if ((val & mask) != (pat & mask)) {
|
||||
i40e_debug(hw, I40E_DEBUG_DIAG,
|
||||
"%s: reg pattern test failed - reg 0x%08x pat 0x%08x val 0x%08x\n",
|
||||
__func__, reg, pat, val);
|
||||
return I40E_ERR_DIAG_TEST_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
wr32(hw, reg, orig_val);
|
||||
val = rd32(hw, reg);
|
||||
if (val != orig_val) {
|
||||
i40e_debug(hw, I40E_DEBUG_DIAG,
|
||||
"%s: reg restore test failed - reg 0x%08x orig_val 0x%08x val 0x%08x\n",
|
||||
__func__, reg, orig_val, val);
|
||||
return I40E_ERR_DIAG_TEST_FAILED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct i40e_diag_reg_test_info i40e_reg_list[] = {
|
||||
/* offset mask elements stride */
|
||||
{I40E_QTX_CTL(0), 0x0000FFBF, 1,
|
||||
I40E_QTX_CTL(1) - I40E_QTX_CTL(0)},
|
||||
{I40E_PFINT_ITR0(0), 0x00000FFF, 3,
|
||||
I40E_PFINT_ITR0(1) - I40E_PFINT_ITR0(0)},
|
||||
{I40E_PFINT_ITRN(0, 0), 0x00000FFF, 1,
|
||||
I40E_PFINT_ITRN(0, 1) - I40E_PFINT_ITRN(0, 0)},
|
||||
{I40E_PFINT_ITRN(1, 0), 0x00000FFF, 1,
|
||||
I40E_PFINT_ITRN(1, 1) - I40E_PFINT_ITRN(1, 0)},
|
||||
{I40E_PFINT_ITRN(2, 0), 0x00000FFF, 1,
|
||||
I40E_PFINT_ITRN(2, 1) - I40E_PFINT_ITRN(2, 0)},
|
||||
{I40E_PFINT_STAT_CTL0, 0x0000000C, 1, 0},
|
||||
{I40E_PFINT_LNKLST0, 0x00001FFF, 1, 0},
|
||||
{I40E_PFINT_LNKLSTN(0), 0x000007FF, 1,
|
||||
I40E_PFINT_LNKLSTN(1) - I40E_PFINT_LNKLSTN(0)},
|
||||
{I40E_QINT_TQCTL(0), 0x000000FF, 1,
|
||||
I40E_QINT_TQCTL(1) - I40E_QINT_TQCTL(0)},
|
||||
{I40E_QINT_RQCTL(0), 0x000000FF, 1,
|
||||
I40E_QINT_RQCTL(1) - I40E_QINT_RQCTL(0)},
|
||||
{I40E_PFINT_ICR0_ENA, 0xF7F20000, 1, 0},
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/**
|
||||
* i40e_diag_reg_test
|
||||
* @hw: pointer to the hw struct
|
||||
*
|
||||
* Perform registers diagnostic test
|
||||
**/
|
||||
i40e_status i40e_diag_reg_test(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret_code = 0;
|
||||
u32 reg, mask;
|
||||
u32 i, j;
|
||||
|
||||
for (i = 0; i40e_reg_list[i].offset != 0 &&
|
||||
!ret_code; i++) {
|
||||
|
||||
/* set actual reg range for dynamically allocated resources */
|
||||
if (i40e_reg_list[i].offset == I40E_QTX_CTL(0) &&
|
||||
hw->func_caps.num_tx_qp != 0)
|
||||
i40e_reg_list[i].elements = hw->func_caps.num_tx_qp;
|
||||
if ((i40e_reg_list[i].offset == I40E_PFINT_ITRN(0, 0) ||
|
||||
i40e_reg_list[i].offset == I40E_PFINT_ITRN(1, 0) ||
|
||||
i40e_reg_list[i].offset == I40E_PFINT_ITRN(2, 0) ||
|
||||
i40e_reg_list[i].offset == I40E_QINT_TQCTL(0) ||
|
||||
i40e_reg_list[i].offset == I40E_QINT_RQCTL(0)) &&
|
||||
hw->func_caps.num_msix_vectors != 0)
|
||||
i40e_reg_list[i].elements =
|
||||
hw->func_caps.num_msix_vectors - 1;
|
||||
|
||||
/* test register access */
|
||||
mask = i40e_reg_list[i].mask;
|
||||
for (j = 0; j < i40e_reg_list[i].elements && !ret_code; j++) {
|
||||
reg = i40e_reg_list[i].offset +
|
||||
(j * i40e_reg_list[i].stride);
|
||||
ret_code = i40e_diag_reg_pattern_test(hw, reg, mask);
|
||||
}
|
||||
}
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_diag_eeprom_test
|
||||
* @hw: pointer to the hw struct
|
||||
*
|
||||
* Perform EEPROM diagnostic test
|
||||
**/
|
||||
i40e_status i40e_diag_eeprom_test(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret_code;
|
||||
u16 reg_val;
|
||||
|
||||
/* read NVM control word and if NVM valid, validate EEPROM checksum*/
|
||||
ret_code = i40e_read_nvm_word(hw, I40E_SR_NVM_CONTROL_WORD, ®_val);
|
||||
if (!ret_code &&
|
||||
((reg_val & I40E_SR_CONTROL_WORD_1_MASK) ==
|
||||
(0x01 << I40E_SR_CONTROL_WORD_1_SHIFT))) {
|
||||
ret_code = i40e_validate_nvm_checksum(hw, NULL);
|
||||
} else {
|
||||
ret_code = I40E_ERR_DIAG_TEST_FAILED;
|
||||
}
|
||||
|
||||
return ret_code;
|
||||
}
|
51
drivers/net/ethernet/intel/i40e/i40e_diag.h
Normal file
51
drivers/net/ethernet/intel/i40e/i40e_diag.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_DIAG_H_
|
||||
#define _I40E_DIAG_H_
|
||||
|
||||
#include "i40e_type.h"
|
||||
|
||||
enum i40e_lb_mode {
|
||||
I40E_LB_MODE_NONE = 0x0,
|
||||
I40E_LB_MODE_PHY_LOCAL = I40E_AQ_LB_PHY_LOCAL,
|
||||
I40E_LB_MODE_PHY_REMOTE = I40E_AQ_LB_PHY_REMOTE,
|
||||
I40E_LB_MODE_MAC_LOCAL = I40E_AQ_LB_MAC_LOCAL,
|
||||
};
|
||||
|
||||
struct i40e_diag_reg_test_info {
|
||||
u32 offset; /* the base register */
|
||||
u32 mask; /* bits that can be tested */
|
||||
u32 elements; /* number of elements if array */
|
||||
u32 stride; /* bytes between each element */
|
||||
};
|
||||
|
||||
extern struct i40e_diag_reg_test_info i40e_reg_list[];
|
||||
|
||||
i40e_status i40e_diag_reg_test(struct i40e_hw *hw);
|
||||
i40e_status i40e_diag_eeprom_test(struct i40e_hw *hw);
|
||||
|
||||
#endif /* _I40E_DIAG_H_ */
|
2240
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
Normal file
2240
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
Normal file
File diff suppressed because it is too large
Load diff
1562
drivers/net/ethernet/intel/i40e/i40e_fcoe.c
Normal file
1562
drivers/net/ethernet/intel/i40e/i40e_fcoe.c
Normal file
File diff suppressed because it is too large
Load diff
128
drivers/net/ethernet/intel/i40e/i40e_fcoe.h
Normal file
128
drivers/net/ethernet/intel/i40e/i40e_fcoe.h
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_FCOE_H_
|
||||
#define _I40E_FCOE_H_
|
||||
|
||||
/* FCoE HW context helper macros */
|
||||
#define I40E_DDP_CONTEXT_DESC(R, i) \
|
||||
(&(((struct i40e_fcoe_ddp_context_desc *)((R)->desc))[i]))
|
||||
|
||||
#define I40E_QUEUE_CONTEXT_DESC(R, i) \
|
||||
(&(((struct i40e_fcoe_queue_context_desc *)((R)->desc))[i]))
|
||||
|
||||
#define I40E_FILTER_CONTEXT_DESC(R, i) \
|
||||
(&(((struct i40e_fcoe_filter_context_desc *)((R)->desc))[i]))
|
||||
|
||||
|
||||
/* receive queue descriptor filter status for FCoE */
|
||||
#define I40E_RX_DESC_FLTSTAT_FCMASK 0x3
|
||||
#define I40E_RX_DESC_FLTSTAT_NOMTCH 0x0 /* no ddp context match */
|
||||
#define I40E_RX_DESC_FLTSTAT_NODDP 0x1 /* no ddp due to error */
|
||||
#define I40E_RX_DESC_FLTSTAT_DDP 0x2 /* DDPed payload, post header */
|
||||
#define I40E_RX_DESC_FLTSTAT_FCPRSP 0x3 /* FCP_RSP */
|
||||
|
||||
/* receive queue descriptor error codes for FCoE */
|
||||
#define I40E_RX_DESC_FCOE_ERROR_MASK \
|
||||
(I40E_RX_DESC_ERROR_L3L4E_PROT | \
|
||||
I40E_RX_DESC_ERROR_L3L4E_FC | \
|
||||
I40E_RX_DESC_ERROR_L3L4E_DMAC_ERR | \
|
||||
I40E_RX_DESC_ERROR_L3L4E_DMAC_WARN)
|
||||
|
||||
/* receive queue descriptor programming error */
|
||||
#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL(e) \
|
||||
(((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT) & 0x1)
|
||||
|
||||
#define I40E_RX_PROG_FCOE_ERROR_CONFLICT(e) \
|
||||
(((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT) & 0x1)
|
||||
|
||||
#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT \
|
||||
(1 << I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT)
|
||||
#define I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT \
|
||||
(1 << I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT)
|
||||
|
||||
#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL(e) \
|
||||
I40E_RX_PROG_FCOE_ERROR_CONFLICT(e)
|
||||
#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT \
|
||||
I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT
|
||||
|
||||
/* FCoE DDP related definitions */
|
||||
#define I40E_FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */
|
||||
#define I40E_FCOE_MAX_XID 0x0FFF /* the max xid supported by fcoe_sw */
|
||||
#define I40E_FCOE_DDP_BUFFCNT_MAX 512 /* 9 bits bufcnt */
|
||||
#define I40E_FCOE_DDP_PTR_ALIGN 16
|
||||
#define I40E_FCOE_DDP_PTR_MAX (I40E_FCOE_DDP_BUFFCNT_MAX * sizeof(dma_addr_t))
|
||||
#define I40E_FCOE_DDP_BUF_MIN 4096
|
||||
#define I40E_FCOE_DDP_MAX 2048
|
||||
#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT 8
|
||||
|
||||
/* supported netdev features for FCoE */
|
||||
#define I40E_FCOE_NETIF_FEATURES (NETIF_F_ALL_FCOE | \
|
||||
NETIF_F_HW_VLAN_CTAG_TX | \
|
||||
NETIF_F_HW_VLAN_CTAG_RX | \
|
||||
NETIF_F_HW_VLAN_CTAG_FILTER)
|
||||
|
||||
/* DDP context flags */
|
||||
enum i40e_fcoe_ddp_flags {
|
||||
__I40E_FCOE_DDP_NONE = 1,
|
||||
__I40E_FCOE_DDP_TARGET,
|
||||
__I40E_FCOE_DDP_INITALIZED,
|
||||
__I40E_FCOE_DDP_PROGRAMMED,
|
||||
__I40E_FCOE_DDP_DONE,
|
||||
__I40E_FCOE_DDP_ABORTED,
|
||||
__I40E_FCOE_DDP_UNMAPPED,
|
||||
};
|
||||
|
||||
/* DDP SW context struct */
|
||||
struct i40e_fcoe_ddp {
|
||||
int len;
|
||||
u16 xid;
|
||||
u16 firstoff;
|
||||
u16 lastsize;
|
||||
u16 list_len;
|
||||
u8 fcerr;
|
||||
u8 prerr;
|
||||
unsigned long flags;
|
||||
unsigned int sgc;
|
||||
struct scatterlist *sgl;
|
||||
dma_addr_t udp;
|
||||
u64 *udl;
|
||||
struct dma_pool *pool;
|
||||
|
||||
};
|
||||
|
||||
struct i40e_fcoe_ddp_pool {
|
||||
struct dma_pool *pool;
|
||||
};
|
||||
|
||||
struct i40e_fcoe {
|
||||
unsigned long mode;
|
||||
atomic_t refcnt;
|
||||
struct i40e_fcoe_ddp_pool __percpu *ddp_pool;
|
||||
struct i40e_fcoe_ddp ddp[I40E_FCOE_DDP_MAX];
|
||||
};
|
||||
|
||||
#endif /* _I40E_FCOE_H_ */
|
360
drivers/net/ethernet/intel/i40e/i40e_hmc.c
Normal file
360
drivers/net/ethernet/intel/i40e/i40e_hmc.c
Normal file
|
@ -0,0 +1,360 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "i40e_osdep.h"
|
||||
#include "i40e_register.h"
|
||||
#include "i40e_status.h"
|
||||
#include "i40e_alloc.h"
|
||||
#include "i40e_hmc.h"
|
||||
#include "i40e_type.h"
|
||||
|
||||
/**
|
||||
* i40e_add_sd_table_entry - Adds a segment descriptor to the table
|
||||
* @hw: pointer to our hw struct
|
||||
* @hmc_info: pointer to the HMC configuration information struct
|
||||
* @sd_index: segment descriptor index to manipulate
|
||||
* @type: what type of segment descriptor we're manipulating
|
||||
* @direct_mode_sz: size to alloc in direct mode
|
||||
**/
|
||||
i40e_status i40e_add_sd_table_entry(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 sd_index,
|
||||
enum i40e_sd_entry_type type,
|
||||
u64 direct_mode_sz)
|
||||
{
|
||||
enum i40e_memory_type mem_type __attribute__((unused));
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
bool dma_mem_alloc_done = false;
|
||||
struct i40e_dma_mem mem;
|
||||
i40e_status ret_code;
|
||||
u64 alloc_len;
|
||||
|
||||
if (NULL == hmc_info->sd_table.sd_entry) {
|
||||
ret_code = I40E_ERR_BAD_PTR;
|
||||
hw_dbg(hw, "i40e_add_sd_table_entry: bad sd_entry\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (sd_index >= hmc_info->sd_table.sd_cnt) {
|
||||
ret_code = I40E_ERR_INVALID_SD_INDEX;
|
||||
hw_dbg(hw, "i40e_add_sd_table_entry: bad sd_index\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[sd_index];
|
||||
if (!sd_entry->valid) {
|
||||
if (I40E_SD_TYPE_PAGED == type) {
|
||||
mem_type = i40e_mem_pd;
|
||||
alloc_len = I40E_HMC_PAGED_BP_SIZE;
|
||||
} else {
|
||||
mem_type = i40e_mem_bp_jumbo;
|
||||
alloc_len = direct_mode_sz;
|
||||
}
|
||||
|
||||
/* allocate a 4K pd page or 2M backing page */
|
||||
ret_code = i40e_allocate_dma_mem(hw, &mem, mem_type, alloc_len,
|
||||
I40E_HMC_PD_BP_BUF_ALIGNMENT);
|
||||
if (ret_code)
|
||||
goto exit;
|
||||
dma_mem_alloc_done = true;
|
||||
if (I40E_SD_TYPE_PAGED == type) {
|
||||
ret_code = i40e_allocate_virt_mem(hw,
|
||||
&sd_entry->u.pd_table.pd_entry_virt_mem,
|
||||
sizeof(struct i40e_hmc_pd_entry) * 512);
|
||||
if (ret_code)
|
||||
goto exit;
|
||||
sd_entry->u.pd_table.pd_entry =
|
||||
(struct i40e_hmc_pd_entry *)
|
||||
sd_entry->u.pd_table.pd_entry_virt_mem.va;
|
||||
sd_entry->u.pd_table.pd_page_addr = mem;
|
||||
} else {
|
||||
sd_entry->u.bp.addr = mem;
|
||||
sd_entry->u.bp.sd_pd_index = sd_index;
|
||||
}
|
||||
/* initialize the sd entry */
|
||||
hmc_info->sd_table.sd_entry[sd_index].entry_type = type;
|
||||
|
||||
/* increment the ref count */
|
||||
I40E_INC_SD_REFCNT(&hmc_info->sd_table);
|
||||
}
|
||||
/* Increment backing page reference count */
|
||||
if (I40E_SD_TYPE_DIRECT == sd_entry->entry_type)
|
||||
I40E_INC_BP_REFCNT(&sd_entry->u.bp);
|
||||
exit:
|
||||
if (ret_code)
|
||||
if (dma_mem_alloc_done)
|
||||
i40e_free_dma_mem(hw, &mem);
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_add_pd_table_entry - Adds page descriptor to the specified table
|
||||
* @hw: pointer to our HW structure
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @pd_index: which page descriptor index to manipulate
|
||||
*
|
||||
* This function:
|
||||
* 1. Initializes the pd entry
|
||||
* 2. Adds pd_entry in the pd_table
|
||||
* 3. Mark the entry valid in i40e_hmc_pd_entry structure
|
||||
* 4. Initializes the pd_entry's ref count to 1
|
||||
* assumptions:
|
||||
* 1. The memory for pd should be pinned down, physically contiguous and
|
||||
* aligned on 4K boundary and zeroed memory.
|
||||
* 2. It should be 4K in size.
|
||||
**/
|
||||
i40e_status i40e_add_pd_table_entry(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 pd_index)
|
||||
{
|
||||
i40e_status ret_code = 0;
|
||||
struct i40e_hmc_pd_table *pd_table;
|
||||
struct i40e_hmc_pd_entry *pd_entry;
|
||||
struct i40e_dma_mem mem;
|
||||
u32 sd_idx, rel_pd_idx;
|
||||
u64 *pd_addr;
|
||||
u64 page_desc;
|
||||
|
||||
if (pd_index / I40E_HMC_PD_CNT_IN_SD >= hmc_info->sd_table.sd_cnt) {
|
||||
ret_code = I40E_ERR_INVALID_PAGE_DESC_INDEX;
|
||||
hw_dbg(hw, "i40e_add_pd_table_entry: bad pd_index\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* find corresponding sd */
|
||||
sd_idx = (pd_index / I40E_HMC_PD_CNT_IN_SD);
|
||||
if (I40E_SD_TYPE_PAGED !=
|
||||
hmc_info->sd_table.sd_entry[sd_idx].entry_type)
|
||||
goto exit;
|
||||
|
||||
rel_pd_idx = (pd_index % I40E_HMC_PD_CNT_IN_SD);
|
||||
pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
|
||||
pd_entry = &pd_table->pd_entry[rel_pd_idx];
|
||||
if (!pd_entry->valid) {
|
||||
/* allocate a 4K backing page */
|
||||
ret_code = i40e_allocate_dma_mem(hw, &mem, i40e_mem_bp,
|
||||
I40E_HMC_PAGED_BP_SIZE,
|
||||
I40E_HMC_PD_BP_BUF_ALIGNMENT);
|
||||
if (ret_code)
|
||||
goto exit;
|
||||
|
||||
pd_entry->bp.addr = mem;
|
||||
pd_entry->bp.sd_pd_index = pd_index;
|
||||
pd_entry->bp.entry_type = I40E_SD_TYPE_PAGED;
|
||||
/* Set page address and valid bit */
|
||||
page_desc = mem.pa | 0x1;
|
||||
|
||||
pd_addr = (u64 *)pd_table->pd_page_addr.va;
|
||||
pd_addr += rel_pd_idx;
|
||||
|
||||
/* Add the backing page physical address in the pd entry */
|
||||
memcpy(pd_addr, &page_desc, sizeof(u64));
|
||||
|
||||
pd_entry->sd_index = sd_idx;
|
||||
pd_entry->valid = true;
|
||||
I40E_INC_PD_REFCNT(pd_table);
|
||||
}
|
||||
I40E_INC_BP_REFCNT(&pd_entry->bp);
|
||||
exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_remove_pd_bp - remove a backing page from a page descriptor
|
||||
* @hw: pointer to our HW structure
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @idx: the page index
|
||||
* @is_pf: distinguishes a VF from a PF
|
||||
*
|
||||
* This function:
|
||||
* 1. Marks the entry in pd tabe (for paged address mode) or in sd table
|
||||
* (for direct address mode) invalid.
|
||||
* 2. Write to register PMPDINV to invalidate the backing page in FV cache
|
||||
* 3. Decrement the ref count for the pd _entry
|
||||
* assumptions:
|
||||
* 1. Caller can deallocate the memory used by backing storage after this
|
||||
* function returns.
|
||||
**/
|
||||
i40e_status i40e_remove_pd_bp(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx)
|
||||
{
|
||||
i40e_status ret_code = 0;
|
||||
struct i40e_hmc_pd_entry *pd_entry;
|
||||
struct i40e_hmc_pd_table *pd_table;
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
u32 sd_idx, rel_pd_idx;
|
||||
u64 *pd_addr;
|
||||
|
||||
/* calculate index */
|
||||
sd_idx = idx / I40E_HMC_PD_CNT_IN_SD;
|
||||
rel_pd_idx = idx % I40E_HMC_PD_CNT_IN_SD;
|
||||
if (sd_idx >= hmc_info->sd_table.sd_cnt) {
|
||||
ret_code = I40E_ERR_INVALID_PAGE_DESC_INDEX;
|
||||
hw_dbg(hw, "i40e_remove_pd_bp: bad idx\n");
|
||||
goto exit;
|
||||
}
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[sd_idx];
|
||||
if (I40E_SD_TYPE_PAGED != sd_entry->entry_type) {
|
||||
ret_code = I40E_ERR_INVALID_SD_TYPE;
|
||||
hw_dbg(hw, "i40e_remove_pd_bp: wrong sd_entry type\n");
|
||||
goto exit;
|
||||
}
|
||||
/* get the entry and decrease its ref counter */
|
||||
pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
|
||||
pd_entry = &pd_table->pd_entry[rel_pd_idx];
|
||||
I40E_DEC_BP_REFCNT(&pd_entry->bp);
|
||||
if (pd_entry->bp.ref_cnt)
|
||||
goto exit;
|
||||
|
||||
/* mark the entry invalid */
|
||||
pd_entry->valid = false;
|
||||
I40E_DEC_PD_REFCNT(pd_table);
|
||||
pd_addr = (u64 *)pd_table->pd_page_addr.va;
|
||||
pd_addr += rel_pd_idx;
|
||||
memset(pd_addr, 0, sizeof(u64));
|
||||
I40E_INVALIDATE_PF_HMC_PD(hw, sd_idx, idx);
|
||||
|
||||
/* free memory here */
|
||||
ret_code = i40e_free_dma_mem(hw, &(pd_entry->bp.addr));
|
||||
if (ret_code)
|
||||
goto exit;
|
||||
if (!pd_table->ref_cnt)
|
||||
i40e_free_virt_mem(hw, &pd_table->pd_entry_virt_mem);
|
||||
exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_prep_remove_sd_bp - Prepares to remove a backing page from a sd entry
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @idx: the page index
|
||||
**/
|
||||
i40e_status i40e_prep_remove_sd_bp(struct i40e_hmc_info *hmc_info,
|
||||
u32 idx)
|
||||
{
|
||||
i40e_status ret_code = 0;
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
|
||||
/* get the entry and decrease its ref counter */
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[idx];
|
||||
I40E_DEC_BP_REFCNT(&sd_entry->u.bp);
|
||||
if (sd_entry->u.bp.ref_cnt) {
|
||||
ret_code = I40E_ERR_NOT_READY;
|
||||
goto exit;
|
||||
}
|
||||
I40E_DEC_SD_REFCNT(&hmc_info->sd_table);
|
||||
|
||||
/* mark the entry invalid */
|
||||
sd_entry->valid = false;
|
||||
exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_remove_sd_bp_new - Removes a backing page from a segment descriptor
|
||||
* @hw: pointer to our hw struct
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @idx: the page index
|
||||
* @is_pf: used to distinguish between VF and PF
|
||||
**/
|
||||
i40e_status i40e_remove_sd_bp_new(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx, bool is_pf)
|
||||
{
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
i40e_status ret_code = 0;
|
||||
|
||||
/* get the entry and decrease its ref counter */
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[idx];
|
||||
if (is_pf) {
|
||||
I40E_CLEAR_PF_SD_ENTRY(hw, idx, I40E_SD_TYPE_DIRECT);
|
||||
} else {
|
||||
ret_code = I40E_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
ret_code = i40e_free_dma_mem(hw, &(sd_entry->u.bp.addr));
|
||||
if (ret_code)
|
||||
goto exit;
|
||||
exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_prep_remove_pd_page - Prepares to remove a PD page from sd entry.
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @idx: segment descriptor index to find the relevant page descriptor
|
||||
**/
|
||||
i40e_status i40e_prep_remove_pd_page(struct i40e_hmc_info *hmc_info,
|
||||
u32 idx)
|
||||
{
|
||||
i40e_status ret_code = 0;
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[idx];
|
||||
|
||||
if (sd_entry->u.pd_table.ref_cnt) {
|
||||
ret_code = I40E_ERR_NOT_READY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* mark the entry invalid */
|
||||
sd_entry->valid = false;
|
||||
|
||||
I40E_DEC_SD_REFCNT(&hmc_info->sd_table);
|
||||
exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_remove_pd_page_new - Removes a PD page from sd entry.
|
||||
* @hw: pointer to our hw struct
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @idx: segment descriptor index to find the relevant page descriptor
|
||||
* @is_pf: used to distinguish between VF and PF
|
||||
**/
|
||||
i40e_status i40e_remove_pd_page_new(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx, bool is_pf)
|
||||
{
|
||||
i40e_status ret_code = 0;
|
||||
struct i40e_hmc_sd_entry *sd_entry;
|
||||
|
||||
sd_entry = &hmc_info->sd_table.sd_entry[idx];
|
||||
if (is_pf) {
|
||||
I40E_CLEAR_PF_SD_ENTRY(hw, idx, I40E_SD_TYPE_PAGED);
|
||||
} else {
|
||||
ret_code = I40E_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
/* free memory here */
|
||||
ret_code = i40e_free_dma_mem(hw, &(sd_entry->u.pd_table.pd_page_addr));
|
||||
if (ret_code)
|
||||
goto exit;
|
||||
exit:
|
||||
return ret_code;
|
||||
}
|
236
drivers/net/ethernet/intel/i40e/i40e_hmc.h
Normal file
236
drivers/net/ethernet/intel/i40e/i40e_hmc.h
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_HMC_H_
|
||||
#define _I40E_HMC_H_
|
||||
|
||||
#define I40E_HMC_MAX_BP_COUNT 512
|
||||
|
||||
/* forward-declare the HW struct for the compiler */
|
||||
struct i40e_hw;
|
||||
|
||||
#define I40E_HMC_INFO_SIGNATURE 0x484D5347 /* HMSG */
|
||||
#define I40E_HMC_PD_CNT_IN_SD 512
|
||||
#define I40E_HMC_DIRECT_BP_SIZE 0x200000 /* 2M */
|
||||
#define I40E_HMC_PAGED_BP_SIZE 4096
|
||||
#define I40E_HMC_PD_BP_BUF_ALIGNMENT 4096
|
||||
#define I40E_FIRST_VF_FPM_ID 16
|
||||
|
||||
struct i40e_hmc_obj_info {
|
||||
u64 base; /* base addr in FPM */
|
||||
u32 max_cnt; /* max count available for this hmc func */
|
||||
u32 cnt; /* count of objects driver actually wants to create */
|
||||
u64 size; /* size in bytes of one object */
|
||||
};
|
||||
|
||||
enum i40e_sd_entry_type {
|
||||
I40E_SD_TYPE_INVALID = 0,
|
||||
I40E_SD_TYPE_PAGED = 1,
|
||||
I40E_SD_TYPE_DIRECT = 2
|
||||
};
|
||||
|
||||
struct i40e_hmc_bp {
|
||||
enum i40e_sd_entry_type entry_type;
|
||||
struct i40e_dma_mem addr; /* populate to be used by hw */
|
||||
u32 sd_pd_index;
|
||||
u32 ref_cnt;
|
||||
};
|
||||
|
||||
struct i40e_hmc_pd_entry {
|
||||
struct i40e_hmc_bp bp;
|
||||
u32 sd_index;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
struct i40e_hmc_pd_table {
|
||||
struct i40e_dma_mem pd_page_addr; /* populate to be used by hw */
|
||||
struct i40e_hmc_pd_entry *pd_entry; /* [512] for sw book keeping */
|
||||
struct i40e_virt_mem pd_entry_virt_mem; /* virt mem for pd_entry */
|
||||
|
||||
u32 ref_cnt;
|
||||
u32 sd_index;
|
||||
};
|
||||
|
||||
struct i40e_hmc_sd_entry {
|
||||
enum i40e_sd_entry_type entry_type;
|
||||
bool valid;
|
||||
|
||||
union {
|
||||
struct i40e_hmc_pd_table pd_table;
|
||||
struct i40e_hmc_bp bp;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct i40e_hmc_sd_table {
|
||||
struct i40e_virt_mem addr; /* used to track sd_entry allocations */
|
||||
u32 sd_cnt;
|
||||
u32 ref_cnt;
|
||||
struct i40e_hmc_sd_entry *sd_entry; /* (sd_cnt*512) entries max */
|
||||
};
|
||||
|
||||
struct i40e_hmc_info {
|
||||
u32 signature;
|
||||
/* equals to pci func num for PF and dynamically allocated for VFs */
|
||||
u8 hmc_fn_id;
|
||||
u16 first_sd_index; /* index of the first available SD */
|
||||
|
||||
/* hmc objects */
|
||||
struct i40e_hmc_obj_info *hmc_obj;
|
||||
struct i40e_virt_mem hmc_obj_virt_mem;
|
||||
struct i40e_hmc_sd_table sd_table;
|
||||
};
|
||||
|
||||
#define I40E_INC_SD_REFCNT(sd_table) ((sd_table)->ref_cnt++)
|
||||
#define I40E_INC_PD_REFCNT(pd_table) ((pd_table)->ref_cnt++)
|
||||
#define I40E_INC_BP_REFCNT(bp) ((bp)->ref_cnt++)
|
||||
|
||||
#define I40E_DEC_SD_REFCNT(sd_table) ((sd_table)->ref_cnt--)
|
||||
#define I40E_DEC_PD_REFCNT(pd_table) ((pd_table)->ref_cnt--)
|
||||
#define I40E_DEC_BP_REFCNT(bp) ((bp)->ref_cnt--)
|
||||
|
||||
/**
|
||||
* I40E_SET_PF_SD_ENTRY - marks the sd entry as valid in the hardware
|
||||
* @hw: pointer to our hw struct
|
||||
* @pa: pointer to physical address
|
||||
* @sd_index: segment descriptor index
|
||||
* @type: if sd entry is direct or paged
|
||||
**/
|
||||
#define I40E_SET_PF_SD_ENTRY(hw, pa, sd_index, type) \
|
||||
{ \
|
||||
u32 val1, val2, val3; \
|
||||
val1 = (u32)(upper_32_bits(pa)); \
|
||||
val2 = (u32)(pa) | (I40E_HMC_MAX_BP_COUNT << \
|
||||
I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | \
|
||||
((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \
|
||||
I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) | \
|
||||
(1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT); \
|
||||
val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
|
||||
wr32((hw), I40E_PFHMC_SDDATAHIGH, val1); \
|
||||
wr32((hw), I40E_PFHMC_SDDATALOW, val2); \
|
||||
wr32((hw), I40E_PFHMC_SDCMD, val3); \
|
||||
}
|
||||
|
||||
/**
|
||||
* I40E_CLEAR_PF_SD_ENTRY - marks the sd entry as invalid in the hardware
|
||||
* @hw: pointer to our hw struct
|
||||
* @sd_index: segment descriptor index
|
||||
* @type: if sd entry is direct or paged
|
||||
**/
|
||||
#define I40E_CLEAR_PF_SD_ENTRY(hw, sd_index, type) \
|
||||
{ \
|
||||
u32 val2, val3; \
|
||||
val2 = (I40E_HMC_MAX_BP_COUNT << \
|
||||
I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) | \
|
||||
((((type) == I40E_SD_TYPE_PAGED) ? 0 : 1) << \
|
||||
I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT); \
|
||||
val3 = (sd_index) | (1u << I40E_PFHMC_SDCMD_PMSDWR_SHIFT); \
|
||||
wr32((hw), I40E_PFHMC_SDDATAHIGH, 0); \
|
||||
wr32((hw), I40E_PFHMC_SDDATALOW, val2); \
|
||||
wr32((hw), I40E_PFHMC_SDCMD, val3); \
|
||||
}
|
||||
|
||||
/**
|
||||
* I40E_INVALIDATE_PF_HMC_PD - Invalidates the pd cache in the hardware
|
||||
* @hw: pointer to our hw struct
|
||||
* @sd_idx: segment descriptor index
|
||||
* @pd_idx: page descriptor index
|
||||
**/
|
||||
#define I40E_INVALIDATE_PF_HMC_PD(hw, sd_idx, pd_idx) \
|
||||
wr32((hw), I40E_PFHMC_PDINV, \
|
||||
(((sd_idx) << I40E_PFHMC_PDINV_PMSDIDX_SHIFT) | \
|
||||
((pd_idx) << I40E_PFHMC_PDINV_PMPDIDX_SHIFT)))
|
||||
|
||||
/**
|
||||
* I40E_FIND_SD_INDEX_LIMIT - finds segment descriptor index limit
|
||||
* @hmc_info: pointer to the HMC configuration information structure
|
||||
* @type: type of HMC resources we're searching
|
||||
* @index: starting index for the object
|
||||
* @cnt: number of objects we're trying to create
|
||||
* @sd_idx: pointer to return index of the segment descriptor in question
|
||||
* @sd_limit: pointer to return the maximum number of segment descriptors
|
||||
*
|
||||
* This function calculates the segment descriptor index and index limit
|
||||
* for the resource defined by i40e_hmc_rsrc_type.
|
||||
**/
|
||||
#define I40E_FIND_SD_INDEX_LIMIT(hmc_info, type, index, cnt, sd_idx, sd_limit)\
|
||||
{ \
|
||||
u64 fpm_addr, fpm_limit; \
|
||||
fpm_addr = (hmc_info)->hmc_obj[(type)].base + \
|
||||
(hmc_info)->hmc_obj[(type)].size * (index); \
|
||||
fpm_limit = fpm_addr + (hmc_info)->hmc_obj[(type)].size * (cnt);\
|
||||
*(sd_idx) = (u32)(fpm_addr / I40E_HMC_DIRECT_BP_SIZE); \
|
||||
*(sd_limit) = (u32)((fpm_limit - 1) / I40E_HMC_DIRECT_BP_SIZE); \
|
||||
/* add one more to the limit to correct our range */ \
|
||||
*(sd_limit) += 1; \
|
||||
}
|
||||
|
||||
/**
|
||||
* I40E_FIND_PD_INDEX_LIMIT - finds page descriptor index limit
|
||||
* @hmc_info: pointer to the HMC configuration information struct
|
||||
* @type: HMC resource type we're examining
|
||||
* @idx: starting index for the object
|
||||
* @cnt: number of objects we're trying to create
|
||||
* @pd_index: pointer to return page descriptor index
|
||||
* @pd_limit: pointer to return page descriptor index limit
|
||||
*
|
||||
* Calculates the page descriptor index and index limit for the resource
|
||||
* defined by i40e_hmc_rsrc_type.
|
||||
**/
|
||||
#define I40E_FIND_PD_INDEX_LIMIT(hmc_info, type, idx, cnt, pd_index, pd_limit)\
|
||||
{ \
|
||||
u64 fpm_adr, fpm_limit; \
|
||||
fpm_adr = (hmc_info)->hmc_obj[(type)].base + \
|
||||
(hmc_info)->hmc_obj[(type)].size * (idx); \
|
||||
fpm_limit = fpm_adr + (hmc_info)->hmc_obj[(type)].size * (cnt); \
|
||||
*(pd_index) = (u32)(fpm_adr / I40E_HMC_PAGED_BP_SIZE); \
|
||||
*(pd_limit) = (u32)((fpm_limit - 1) / I40E_HMC_PAGED_BP_SIZE); \
|
||||
/* add one more to the limit to correct our range */ \
|
||||
*(pd_limit) += 1; \
|
||||
}
|
||||
i40e_status i40e_add_sd_table_entry(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 sd_index,
|
||||
enum i40e_sd_entry_type type,
|
||||
u64 direct_mode_sz);
|
||||
|
||||
i40e_status i40e_add_pd_table_entry(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 pd_index);
|
||||
i40e_status i40e_remove_pd_bp(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx);
|
||||
i40e_status i40e_prep_remove_sd_bp(struct i40e_hmc_info *hmc_info,
|
||||
u32 idx);
|
||||
i40e_status i40e_remove_sd_bp_new(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx, bool is_pf);
|
||||
i40e_status i40e_prep_remove_pd_page(struct i40e_hmc_info *hmc_info,
|
||||
u32 idx);
|
||||
i40e_status i40e_remove_pd_page_new(struct i40e_hw *hw,
|
||||
struct i40e_hmc_info *hmc_info,
|
||||
u32 idx, bool is_pf);
|
||||
|
||||
#endif /* _I40E_HMC_H_ */
|
1143
drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
Normal file
1143
drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
Normal file
File diff suppressed because it is too large
Load diff
181
drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h
Normal file
181
drivers/net/ethernet/intel/i40e/i40e_lan_hmc.h
Normal file
|
@ -0,0 +1,181 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_LAN_HMC_H_
|
||||
#define _I40E_LAN_HMC_H_
|
||||
|
||||
/* forward-declare the HW struct for the compiler */
|
||||
struct i40e_hw;
|
||||
|
||||
/* HMC element context information */
|
||||
|
||||
/* Rx queue context data
|
||||
*
|
||||
* The sizes of the variables may be larger than needed due to crossing byte
|
||||
* boundaries. If we do not have the width of the variable set to the correct
|
||||
* size then we could end up shifting bits off the top of the variable when the
|
||||
* variable is at the top of a byte and crosses over into the next byte.
|
||||
*/
|
||||
struct i40e_hmc_obj_rxq {
|
||||
u16 head;
|
||||
u16 cpuid; /* bigger than needed, see above for reason */
|
||||
u64 base;
|
||||
u16 qlen;
|
||||
#define I40E_RXQ_CTX_DBUFF_SHIFT 7
|
||||
u16 dbuff; /* bigger than needed, see above for reason */
|
||||
#define I40E_RXQ_CTX_HBUFF_SHIFT 6
|
||||
u16 hbuff; /* bigger than needed, see above for reason */
|
||||
u8 dtype;
|
||||
u8 dsize;
|
||||
u8 crcstrip;
|
||||
u8 fc_ena;
|
||||
u8 l2tsel;
|
||||
u8 hsplit_0;
|
||||
u8 hsplit_1;
|
||||
u8 showiv;
|
||||
u32 rxmax; /* bigger than needed, see above for reason */
|
||||
u8 tphrdesc_ena;
|
||||
u8 tphwdesc_ena;
|
||||
u8 tphdata_ena;
|
||||
u8 tphhead_ena;
|
||||
u16 lrxqthresh; /* bigger than needed, see above for reason */
|
||||
u8 prefena; /* NOTE: normally must be set to 1 at init */
|
||||
};
|
||||
|
||||
/* Tx queue context data
|
||||
*
|
||||
* The sizes of the variables may be larger than needed due to crossing byte
|
||||
* boundaries. If we do not have the width of the variable set to the correct
|
||||
* size then we could end up shifting bits off the top of the variable when the
|
||||
* variable is at the top of a byte and crosses over into the next byte.
|
||||
*/
|
||||
struct i40e_hmc_obj_txq {
|
||||
u16 head;
|
||||
u8 new_context;
|
||||
u64 base;
|
||||
u8 fc_ena;
|
||||
u8 timesync_ena;
|
||||
u8 fd_ena;
|
||||
u8 alt_vlan_ena;
|
||||
u16 thead_wb;
|
||||
u8 cpuid;
|
||||
u8 head_wb_ena;
|
||||
u16 qlen;
|
||||
u8 tphrdesc_ena;
|
||||
u8 tphrpacket_ena;
|
||||
u8 tphwdesc_ena;
|
||||
u64 head_wb_addr;
|
||||
u32 crc;
|
||||
u16 rdylist;
|
||||
u8 rdylist_act;
|
||||
};
|
||||
|
||||
/* for hsplit_0 field of Rx HMC context */
|
||||
enum i40e_hmc_obj_rx_hsplit_0 {
|
||||
I40E_HMC_OBJ_RX_HSPLIT_0_NO_SPLIT = 0,
|
||||
I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_L2 = 1,
|
||||
I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_IP = 2,
|
||||
I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_TCP_UDP = 4,
|
||||
I40E_HMC_OBJ_RX_HSPLIT_0_SPLIT_SCTP = 8,
|
||||
};
|
||||
|
||||
/* fcoe_cntx and fcoe_filt are for debugging purpose only */
|
||||
struct i40e_hmc_obj_fcoe_cntx {
|
||||
u32 rsv[32];
|
||||
};
|
||||
|
||||
struct i40e_hmc_obj_fcoe_filt {
|
||||
u32 rsv[8];
|
||||
};
|
||||
|
||||
/* Context sizes for LAN objects */
|
||||
enum i40e_hmc_lan_object_size {
|
||||
I40E_HMC_LAN_OBJ_SZ_8 = 0x3,
|
||||
I40E_HMC_LAN_OBJ_SZ_16 = 0x4,
|
||||
I40E_HMC_LAN_OBJ_SZ_32 = 0x5,
|
||||
I40E_HMC_LAN_OBJ_SZ_64 = 0x6,
|
||||
I40E_HMC_LAN_OBJ_SZ_128 = 0x7,
|
||||
I40E_HMC_LAN_OBJ_SZ_256 = 0x8,
|
||||
I40E_HMC_LAN_OBJ_SZ_512 = 0x9,
|
||||
};
|
||||
|
||||
#define I40E_HMC_L2OBJ_BASE_ALIGNMENT 512
|
||||
#define I40E_HMC_OBJ_SIZE_TXQ 128
|
||||
#define I40E_HMC_OBJ_SIZE_RXQ 32
|
||||
#define I40E_HMC_OBJ_SIZE_FCOE_CNTX 64
|
||||
#define I40E_HMC_OBJ_SIZE_FCOE_FILT 64
|
||||
|
||||
enum i40e_hmc_lan_rsrc_type {
|
||||
I40E_HMC_LAN_FULL = 0,
|
||||
I40E_HMC_LAN_TX = 1,
|
||||
I40E_HMC_LAN_RX = 2,
|
||||
I40E_HMC_FCOE_CTX = 3,
|
||||
I40E_HMC_FCOE_FILT = 4,
|
||||
I40E_HMC_LAN_MAX = 5
|
||||
};
|
||||
|
||||
enum i40e_hmc_model {
|
||||
I40E_HMC_MODEL_DIRECT_PREFERRED = 0,
|
||||
I40E_HMC_MODEL_DIRECT_ONLY = 1,
|
||||
I40E_HMC_MODEL_PAGED_ONLY = 2,
|
||||
I40E_HMC_MODEL_UNKNOWN,
|
||||
};
|
||||
|
||||
struct i40e_hmc_lan_create_obj_info {
|
||||
struct i40e_hmc_info *hmc_info;
|
||||
u32 rsrc_type;
|
||||
u32 start_idx;
|
||||
u32 count;
|
||||
enum i40e_sd_entry_type entry_type;
|
||||
u64 direct_mode_sz;
|
||||
};
|
||||
|
||||
struct i40e_hmc_lan_delete_obj_info {
|
||||
struct i40e_hmc_info *hmc_info;
|
||||
u32 rsrc_type;
|
||||
u32 start_idx;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
i40e_status i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num,
|
||||
u32 rxq_num, u32 fcoe_cntx_num,
|
||||
u32 fcoe_filt_num);
|
||||
i40e_status i40e_configure_lan_hmc(struct i40e_hw *hw,
|
||||
enum i40e_hmc_model model);
|
||||
i40e_status i40e_shutdown_lan_hmc(struct i40e_hw *hw);
|
||||
|
||||
i40e_status i40e_clear_lan_tx_queue_context(struct i40e_hw *hw,
|
||||
u16 queue);
|
||||
i40e_status i40e_set_lan_tx_queue_context(struct i40e_hw *hw,
|
||||
u16 queue,
|
||||
struct i40e_hmc_obj_txq *s);
|
||||
i40e_status i40e_clear_lan_rx_queue_context(struct i40e_hw *hw,
|
||||
u16 queue);
|
||||
i40e_status i40e_set_lan_rx_queue_context(struct i40e_hw *hw,
|
||||
u16 queue,
|
||||
struct i40e_hmc_obj_rxq *s);
|
||||
|
||||
#endif /* _I40E_LAN_HMC_H_ */
|
9606
drivers/net/ethernet/intel/i40e/i40e_main.c
Normal file
9606
drivers/net/ethernet/intel/i40e/i40e_main.c
Normal file
File diff suppressed because it is too large
Load diff
859
drivers/net/ethernet/intel/i40e/i40e_nvm.c
Normal file
859
drivers/net/ethernet/intel/i40e/i40e_nvm.c
Normal file
|
@ -0,0 +1,859 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "i40e_prototype.h"
|
||||
|
||||
/**
|
||||
* i40e_init_nvm_ops - Initialize NVM function pointers
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Setup the function pointers and the NVM info structure. Should be called
|
||||
* once per NVM initialization, e.g. inside the i40e_init_shared_code().
|
||||
* Please notice that the NVM term is used here (& in all methods covered
|
||||
* in this file) as an equivalent of the FLASH part mapped into the SR.
|
||||
* We are accessing FLASH always thru the Shadow RAM.
|
||||
**/
|
||||
i40e_status i40e_init_nvm(struct i40e_hw *hw)
|
||||
{
|
||||
struct i40e_nvm_info *nvm = &hw->nvm;
|
||||
i40e_status ret_code = 0;
|
||||
u32 fla, gens;
|
||||
u8 sr_size;
|
||||
|
||||
/* The SR size is stored regardless of the nvm programming mode
|
||||
* as the blank mode may be used in the factory line.
|
||||
*/
|
||||
gens = rd32(hw, I40E_GLNVM_GENS);
|
||||
sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >>
|
||||
I40E_GLNVM_GENS_SR_SIZE_SHIFT);
|
||||
/* Switching to words (sr_size contains power of 2KB) */
|
||||
nvm->sr_size = (1 << sr_size) * I40E_SR_WORDS_IN_1KB;
|
||||
|
||||
/* Check if we are in the normal or blank NVM programming mode */
|
||||
fla = rd32(hw, I40E_GLNVM_FLA);
|
||||
if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */
|
||||
/* Max NVM timeout */
|
||||
nvm->timeout = I40E_MAX_NVM_TIMEOUT;
|
||||
nvm->blank_nvm_mode = false;
|
||||
} else { /* Blank programming mode */
|
||||
nvm->blank_nvm_mode = true;
|
||||
ret_code = I40E_ERR_NVM_BLANK_MODE;
|
||||
hw_dbg(hw, "NVM init error: unsupported blank mode.\n");
|
||||
}
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_acquire_nvm - Generic request for acquiring the NVM ownership
|
||||
* @hw: pointer to the HW structure
|
||||
* @access: NVM access type (read or write)
|
||||
*
|
||||
* This function will request NVM ownership for reading
|
||||
* via the proper Admin Command.
|
||||
**/
|
||||
i40e_status i40e_acquire_nvm(struct i40e_hw *hw,
|
||||
enum i40e_aq_resource_access_type access)
|
||||
{
|
||||
i40e_status ret_code = 0;
|
||||
u64 gtime, timeout;
|
||||
u64 time = 0;
|
||||
|
||||
if (hw->nvm.blank_nvm_mode)
|
||||
goto i40e_i40e_acquire_nvm_exit;
|
||||
|
||||
ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access,
|
||||
0, &time, NULL);
|
||||
/* Reading the Global Device Timer */
|
||||
gtime = rd32(hw, I40E_GLVFGEN_TIMER);
|
||||
|
||||
/* Store the timeout */
|
||||
hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time) + gtime;
|
||||
|
||||
if (ret_code) {
|
||||
/* Set the polling timeout */
|
||||
if (time > I40E_MAX_NVM_TIMEOUT)
|
||||
timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT)
|
||||
+ gtime;
|
||||
else
|
||||
timeout = hw->nvm.hw_semaphore_timeout;
|
||||
/* Poll until the current NVM owner timeouts */
|
||||
while (gtime < timeout) {
|
||||
usleep_range(10000, 20000);
|
||||
ret_code = i40e_aq_request_resource(hw,
|
||||
I40E_NVM_RESOURCE_ID,
|
||||
access, 0, &time,
|
||||
NULL);
|
||||
if (!ret_code) {
|
||||
hw->nvm.hw_semaphore_timeout =
|
||||
I40E_MS_TO_GTIME(time) + gtime;
|
||||
break;
|
||||
}
|
||||
gtime = rd32(hw, I40E_GLVFGEN_TIMER);
|
||||
}
|
||||
if (ret_code) {
|
||||
hw->nvm.hw_semaphore_timeout = 0;
|
||||
hw->nvm.hw_semaphore_wait =
|
||||
I40E_MS_TO_GTIME(time) + gtime;
|
||||
hw_dbg(hw, "NVM acquire timed out, wait %llu ms before trying again.\n",
|
||||
time);
|
||||
}
|
||||
}
|
||||
|
||||
i40e_i40e_acquire_nvm_exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_release_nvm - Generic request for releasing the NVM ownership
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This function will release NVM resource via the proper Admin Command.
|
||||
**/
|
||||
void i40e_release_nvm(struct i40e_hw *hw)
|
||||
{
|
||||
if (!hw->nvm.blank_nvm_mode)
|
||||
i40e_aq_release_resource(hw, I40E_NVM_RESOURCE_ID, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Polls the SRCTL Shadow RAM register done bit.
|
||||
**/
|
||||
static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret_code = I40E_ERR_TIMEOUT;
|
||||
u32 srctl, wait_cnt;
|
||||
|
||||
/* Poll the I40E_GLNVM_SRCTL until the done bit is set */
|
||||
for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) {
|
||||
srctl = rd32(hw, I40E_GLNVM_SRCTL);
|
||||
if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) {
|
||||
ret_code = 0;
|
||||
break;
|
||||
}
|
||||
udelay(5);
|
||||
}
|
||||
if (ret_code == I40E_ERR_TIMEOUT)
|
||||
hw_dbg(hw, "Done bit in GLNVM_SRCTL not set\n");
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_read_nvm_word - Reads Shadow RAM
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
|
||||
* @data: word read from the Shadow RAM
|
||||
*
|
||||
* Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
|
||||
**/
|
||||
i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
|
||||
u16 *data)
|
||||
{
|
||||
i40e_status ret_code = I40E_ERR_TIMEOUT;
|
||||
u32 sr_reg;
|
||||
|
||||
if (offset >= hw->nvm.sr_size) {
|
||||
hw_dbg(hw, "NVM read error: Offset beyond Shadow RAM limit.\n");
|
||||
ret_code = I40E_ERR_PARAM;
|
||||
goto read_nvm_exit;
|
||||
}
|
||||
|
||||
/* Poll the done bit first */
|
||||
ret_code = i40e_poll_sr_srctl_done_bit(hw);
|
||||
if (!ret_code) {
|
||||
/* Write the address and start reading */
|
||||
sr_reg = (u32)(offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |
|
||||
(1 << I40E_GLNVM_SRCTL_START_SHIFT);
|
||||
wr32(hw, I40E_GLNVM_SRCTL, sr_reg);
|
||||
|
||||
/* Poll I40E_GLNVM_SRCTL until the done bit is set */
|
||||
ret_code = i40e_poll_sr_srctl_done_bit(hw);
|
||||
if (!ret_code) {
|
||||
sr_reg = rd32(hw, I40E_GLNVM_SRDATA);
|
||||
*data = (u16)((sr_reg &
|
||||
I40E_GLNVM_SRDATA_RDDATA_MASK)
|
||||
>> I40E_GLNVM_SRDATA_RDDATA_SHIFT);
|
||||
}
|
||||
}
|
||||
if (ret_code)
|
||||
hw_dbg(hw, "NVM read error: Couldn't access Shadow RAM address: 0x%x\n",
|
||||
offset);
|
||||
|
||||
read_nvm_exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_read_nvm_buffer - Reads Shadow RAM buffer
|
||||
* @hw: pointer to the HW structure
|
||||
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
|
||||
* @words: (in) number of words to read; (out) number of words actually read
|
||||
* @data: words read from the Shadow RAM
|
||||
*
|
||||
* Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
|
||||
* method. The buffer read is preceded by the NVM ownership take
|
||||
* and followed by the release.
|
||||
**/
|
||||
i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
|
||||
u16 *words, u16 *data)
|
||||
{
|
||||
i40e_status ret_code = 0;
|
||||
u16 index, word;
|
||||
|
||||
/* Loop thru the selected region */
|
||||
for (word = 0; word < *words; word++) {
|
||||
index = offset + word;
|
||||
ret_code = i40e_read_nvm_word(hw, index, &data[word]);
|
||||
if (ret_code)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update the number of words read from the Shadow RAM */
|
||||
*words = word;
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_write_nvm_aq - Writes Shadow RAM.
|
||||
* @hw: pointer to the HW structure.
|
||||
* @module_pointer: module pointer location in words from the NVM beginning
|
||||
* @offset: offset in words from module start
|
||||
* @words: number of words to write
|
||||
* @data: buffer with words to write to the Shadow RAM
|
||||
* @last_command: tells the AdminQ that this is the last command
|
||||
*
|
||||
* Writes a 16 bit words buffer to the Shadow RAM using the admin command.
|
||||
**/
|
||||
static i40e_status i40e_write_nvm_aq(struct i40e_hw *hw, u8 module_pointer,
|
||||
u32 offset, u16 words, void *data,
|
||||
bool last_command)
|
||||
{
|
||||
i40e_status ret_code = I40E_ERR_NVM;
|
||||
|
||||
/* Here we are checking the SR limit only for the flat memory model.
|
||||
* We cannot do it for the module-based model, as we did not acquire
|
||||
* the NVM resource yet (we cannot get the module pointer value).
|
||||
* Firmware will check the module-based model.
|
||||
*/
|
||||
if ((offset + words) > hw->nvm.sr_size)
|
||||
hw_dbg(hw, "NVM write error: offset beyond Shadow RAM limit.\n");
|
||||
else if (words > I40E_SR_SECTOR_SIZE_IN_WORDS)
|
||||
/* We can write only up to 4KB (one sector), in one AQ write */
|
||||
hw_dbg(hw, "NVM write fail error: cannot write more than 4KB in a single write.\n");
|
||||
else if (((offset + (words - 1)) / I40E_SR_SECTOR_SIZE_IN_WORDS)
|
||||
!= (offset / I40E_SR_SECTOR_SIZE_IN_WORDS))
|
||||
/* A single write cannot spread over two sectors */
|
||||
hw_dbg(hw, "NVM write error: cannot spread over two sectors in a single write.\n");
|
||||
else
|
||||
ret_code = i40e_aq_update_nvm(hw, module_pointer,
|
||||
2 * offset, /*bytes*/
|
||||
2 * words, /*bytes*/
|
||||
data, last_command, NULL);
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_calc_nvm_checksum - Calculates and returns the checksum
|
||||
* @hw: pointer to hardware structure
|
||||
* @checksum: pointer to the checksum
|
||||
*
|
||||
* This function calculates SW Checksum that covers the whole 64kB shadow RAM
|
||||
* except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
|
||||
* is customer specific and unknown. Therefore, this function skips all maximum
|
||||
* possible size of VPD (1kB).
|
||||
**/
|
||||
static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw,
|
||||
u16 *checksum)
|
||||
{
|
||||
i40e_status ret_code = 0;
|
||||
u16 pcie_alt_module = 0;
|
||||
u16 checksum_local = 0;
|
||||
u16 vpd_module = 0;
|
||||
u16 word = 0;
|
||||
u32 i = 0;
|
||||
|
||||
/* read pointer to VPD area */
|
||||
ret_code = i40e_read_nvm_word(hw, I40E_SR_VPD_PTR, &vpd_module);
|
||||
if (ret_code) {
|
||||
ret_code = I40E_ERR_NVM_CHECKSUM;
|
||||
goto i40e_calc_nvm_checksum_exit;
|
||||
}
|
||||
|
||||
/* read pointer to PCIe Alt Auto-load module */
|
||||
ret_code = i40e_read_nvm_word(hw, I40E_SR_PCIE_ALT_AUTO_LOAD_PTR,
|
||||
&pcie_alt_module);
|
||||
if (ret_code) {
|
||||
ret_code = I40E_ERR_NVM_CHECKSUM;
|
||||
goto i40e_calc_nvm_checksum_exit;
|
||||
}
|
||||
|
||||
/* Calculate SW checksum that covers the whole 64kB shadow RAM
|
||||
* except the VPD and PCIe ALT Auto-load modules
|
||||
*/
|
||||
for (i = 0; i < hw->nvm.sr_size; i++) {
|
||||
/* Skip Checksum word */
|
||||
if (i == I40E_SR_SW_CHECKSUM_WORD)
|
||||
i++;
|
||||
/* Skip VPD module (convert byte size to word count) */
|
||||
if (i == (u32)vpd_module) {
|
||||
i += (I40E_SR_VPD_MODULE_MAX_SIZE / 2);
|
||||
if (i >= hw->nvm.sr_size)
|
||||
break;
|
||||
}
|
||||
/* Skip PCIe ALT module (convert byte size to word count) */
|
||||
if (i == (u32)pcie_alt_module) {
|
||||
i += (I40E_SR_PCIE_ALT_MODULE_MAX_SIZE / 2);
|
||||
if (i >= hw->nvm.sr_size)
|
||||
break;
|
||||
}
|
||||
|
||||
ret_code = i40e_read_nvm_word(hw, (u16)i, &word);
|
||||
if (ret_code) {
|
||||
ret_code = I40E_ERR_NVM_CHECKSUM;
|
||||
goto i40e_calc_nvm_checksum_exit;
|
||||
}
|
||||
checksum_local += word;
|
||||
}
|
||||
|
||||
*checksum = (u16)I40E_SR_SW_CHECKSUM_BASE - checksum_local;
|
||||
|
||||
i40e_calc_nvm_checksum_exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_update_nvm_checksum - Updates the NVM checksum
|
||||
* @hw: pointer to hardware structure
|
||||
*
|
||||
* NVM ownership must be acquired before calling this function and released
|
||||
* on ARQ completion event reception by caller.
|
||||
* This function will commit SR to NVM.
|
||||
**/
|
||||
i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw)
|
||||
{
|
||||
i40e_status ret_code = 0;
|
||||
u16 checksum;
|
||||
|
||||
ret_code = i40e_calc_nvm_checksum(hw, &checksum);
|
||||
if (!ret_code)
|
||||
ret_code = i40e_write_nvm_aq(hw, 0x00, I40E_SR_SW_CHECKSUM_WORD,
|
||||
1, &checksum, true);
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_validate_nvm_checksum - Validate EEPROM checksum
|
||||
* @hw: pointer to hardware structure
|
||||
* @checksum: calculated checksum
|
||||
*
|
||||
* Performs checksum calculation and validates the NVM SW checksum. If the
|
||||
* caller does not need checksum, the value can be NULL.
|
||||
**/
|
||||
i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
|
||||
u16 *checksum)
|
||||
{
|
||||
i40e_status ret_code = 0;
|
||||
u16 checksum_sr = 0;
|
||||
u16 checksum_local = 0;
|
||||
|
||||
ret_code = i40e_calc_nvm_checksum(hw, &checksum_local);
|
||||
if (ret_code)
|
||||
goto i40e_validate_nvm_checksum_exit;
|
||||
|
||||
/* Do not use i40e_read_nvm_word() because we do not want to take
|
||||
* the synchronization semaphores twice here.
|
||||
*/
|
||||
i40e_read_nvm_word(hw, I40E_SR_SW_CHECKSUM_WORD, &checksum_sr);
|
||||
|
||||
/* Verify read checksum from EEPROM is the same as
|
||||
* calculated checksum
|
||||
*/
|
||||
if (checksum_local != checksum_sr)
|
||||
ret_code = I40E_ERR_NVM_CHECKSUM;
|
||||
|
||||
/* If the user cares, return the calculated checksum */
|
||||
if (checksum)
|
||||
*checksum = checksum_local;
|
||||
|
||||
i40e_validate_nvm_checksum_exit:
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *errno);
|
||||
static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *errno);
|
||||
static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *errno);
|
||||
static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
int *errno);
|
||||
static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
int *errno);
|
||||
static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *errno);
|
||||
static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *errno);
|
||||
static inline u8 i40e_nvmupd_get_module(u32 val)
|
||||
{
|
||||
return (u8)(val & I40E_NVM_MOD_PNT_MASK);
|
||||
}
|
||||
static inline u8 i40e_nvmupd_get_transaction(u32 val)
|
||||
{
|
||||
return (u8)((val & I40E_NVM_TRANS_MASK) >> I40E_NVM_TRANS_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_nvmupd_command - Process an NVM update command
|
||||
* @hw: pointer to hardware structure
|
||||
* @cmd: pointer to nvm update command
|
||||
* @bytes: pointer to the data buffer
|
||||
* @errno: pointer to return error code
|
||||
*
|
||||
* Dispatches command depending on what update state is current
|
||||
**/
|
||||
i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *errno)
|
||||
{
|
||||
i40e_status status;
|
||||
|
||||
/* assume success */
|
||||
*errno = 0;
|
||||
|
||||
switch (hw->nvmupd_state) {
|
||||
case I40E_NVMUPD_STATE_INIT:
|
||||
status = i40e_nvmupd_state_init(hw, cmd, bytes, errno);
|
||||
break;
|
||||
|
||||
case I40E_NVMUPD_STATE_READING:
|
||||
status = i40e_nvmupd_state_reading(hw, cmd, bytes, errno);
|
||||
break;
|
||||
|
||||
case I40E_NVMUPD_STATE_WRITING:
|
||||
status = i40e_nvmupd_state_writing(hw, cmd, bytes, errno);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* invalid state, should never happen */
|
||||
status = I40E_NOT_SUPPORTED;
|
||||
*errno = -ESRCH;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_nvmupd_state_init - Handle NVM update state Init
|
||||
* @hw: pointer to hardware structure
|
||||
* @cmd: pointer to nvm update command buffer
|
||||
* @bytes: pointer to the data buffer
|
||||
* @errno: pointer to return error code
|
||||
*
|
||||
* Process legitimate commands of the Init state and conditionally set next
|
||||
* state. Reject all other commands.
|
||||
**/
|
||||
static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *errno)
|
||||
{
|
||||
i40e_status status = 0;
|
||||
enum i40e_nvmupd_cmd upd_cmd;
|
||||
|
||||
upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
|
||||
|
||||
switch (upd_cmd) {
|
||||
case I40E_NVMUPD_READ_SA:
|
||||
status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
|
||||
if (status) {
|
||||
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
|
||||
} else {
|
||||
status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
|
||||
i40e_release_nvm(hw);
|
||||
}
|
||||
break;
|
||||
|
||||
case I40E_NVMUPD_READ_SNT:
|
||||
status = i40e_acquire_nvm(hw, I40E_RESOURCE_READ);
|
||||
if (status) {
|
||||
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
|
||||
} else {
|
||||
status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
|
||||
hw->nvmupd_state = I40E_NVMUPD_STATE_READING;
|
||||
}
|
||||
break;
|
||||
|
||||
case I40E_NVMUPD_WRITE_ERA:
|
||||
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
|
||||
if (status) {
|
||||
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
|
||||
} else {
|
||||
status = i40e_nvmupd_nvm_erase(hw, cmd, errno);
|
||||
if (status)
|
||||
i40e_release_nvm(hw);
|
||||
else
|
||||
hw->aq.nvm_release_on_done = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case I40E_NVMUPD_WRITE_SA:
|
||||
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
|
||||
if (status) {
|
||||
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
|
||||
} else {
|
||||
status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
|
||||
if (status)
|
||||
i40e_release_nvm(hw);
|
||||
else
|
||||
hw->aq.nvm_release_on_done = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case I40E_NVMUPD_WRITE_SNT:
|
||||
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
|
||||
if (status) {
|
||||
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
|
||||
} else {
|
||||
status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
|
||||
hw->nvmupd_state = I40E_NVMUPD_STATE_WRITING;
|
||||
}
|
||||
break;
|
||||
|
||||
case I40E_NVMUPD_CSUM_SA:
|
||||
status = i40e_acquire_nvm(hw, I40E_RESOURCE_WRITE);
|
||||
if (status) {
|
||||
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
|
||||
} else {
|
||||
status = i40e_update_nvm_checksum(hw);
|
||||
if (status) {
|
||||
*errno = hw->aq.asq_last_status ?
|
||||
i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
|
||||
-EIO;
|
||||
i40e_release_nvm(hw);
|
||||
} else {
|
||||
hw->aq.nvm_release_on_done = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
status = I40E_ERR_NVM;
|
||||
*errno = -ESRCH;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_nvmupd_state_reading - Handle NVM update state Reading
|
||||
* @hw: pointer to hardware structure
|
||||
* @cmd: pointer to nvm update command buffer
|
||||
* @bytes: pointer to the data buffer
|
||||
* @errno: pointer to return error code
|
||||
*
|
||||
* NVM ownership is already held. Process legitimate commands and set any
|
||||
* change in state; reject all other commands.
|
||||
**/
|
||||
static i40e_status i40e_nvmupd_state_reading(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *errno)
|
||||
{
|
||||
i40e_status status;
|
||||
enum i40e_nvmupd_cmd upd_cmd;
|
||||
|
||||
upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
|
||||
|
||||
switch (upd_cmd) {
|
||||
case I40E_NVMUPD_READ_SA:
|
||||
case I40E_NVMUPD_READ_CON:
|
||||
status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
|
||||
break;
|
||||
|
||||
case I40E_NVMUPD_READ_LCB:
|
||||
status = i40e_nvmupd_nvm_read(hw, cmd, bytes, errno);
|
||||
i40e_release_nvm(hw);
|
||||
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = I40E_NOT_SUPPORTED;
|
||||
*errno = -ESRCH;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_nvmupd_state_writing - Handle NVM update state Writing
|
||||
* @hw: pointer to hardware structure
|
||||
* @cmd: pointer to nvm update command buffer
|
||||
* @bytes: pointer to the data buffer
|
||||
* @errno: pointer to return error code
|
||||
*
|
||||
* NVM ownership is already held. Process legitimate commands and set any
|
||||
* change in state; reject all other commands
|
||||
**/
|
||||
static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *errno)
|
||||
{
|
||||
i40e_status status;
|
||||
enum i40e_nvmupd_cmd upd_cmd;
|
||||
|
||||
upd_cmd = i40e_nvmupd_validate_command(hw, cmd, errno);
|
||||
|
||||
switch (upd_cmd) {
|
||||
case I40E_NVMUPD_WRITE_CON:
|
||||
status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
|
||||
break;
|
||||
|
||||
case I40E_NVMUPD_WRITE_LCB:
|
||||
status = i40e_nvmupd_nvm_write(hw, cmd, bytes, errno);
|
||||
if (!status) {
|
||||
hw->aq.nvm_release_on_done = true;
|
||||
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
|
||||
}
|
||||
break;
|
||||
|
||||
case I40E_NVMUPD_CSUM_CON:
|
||||
status = i40e_update_nvm_checksum(hw);
|
||||
if (status)
|
||||
*errno = hw->aq.asq_last_status ?
|
||||
i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
|
||||
-EIO;
|
||||
break;
|
||||
|
||||
case I40E_NVMUPD_CSUM_LCB:
|
||||
status = i40e_update_nvm_checksum(hw);
|
||||
if (status) {
|
||||
*errno = hw->aq.asq_last_status ?
|
||||
i40e_aq_rc_to_posix(hw->aq.asq_last_status) :
|
||||
-EIO;
|
||||
} else {
|
||||
hw->aq.nvm_release_on_done = true;
|
||||
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
status = I40E_NOT_SUPPORTED;
|
||||
*errno = -ESRCH;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_nvmupd_validate_command - Validate given command
|
||||
* @hw: pointer to hardware structure
|
||||
* @cmd: pointer to nvm update command buffer
|
||||
* @errno: pointer to return error code
|
||||
*
|
||||
* Return one of the valid command types or I40E_NVMUPD_INVALID
|
||||
**/
|
||||
static enum i40e_nvmupd_cmd i40e_nvmupd_validate_command(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
int *errno)
|
||||
{
|
||||
enum i40e_nvmupd_cmd upd_cmd;
|
||||
u8 transaction, module;
|
||||
|
||||
/* anything that doesn't match a recognized case is an error */
|
||||
upd_cmd = I40E_NVMUPD_INVALID;
|
||||
|
||||
transaction = i40e_nvmupd_get_transaction(cmd->config);
|
||||
module = i40e_nvmupd_get_module(cmd->config);
|
||||
|
||||
/* limits on data size */
|
||||
if ((cmd->data_size < 1) ||
|
||||
(cmd->data_size > I40E_NVMUPD_MAX_DATA)) {
|
||||
hw_dbg(hw, "i40e_nvmupd_validate_command data_size %d\n",
|
||||
cmd->data_size);
|
||||
*errno = -EFAULT;
|
||||
return I40E_NVMUPD_INVALID;
|
||||
}
|
||||
|
||||
switch (cmd->command) {
|
||||
case I40E_NVM_READ:
|
||||
switch (transaction) {
|
||||
case I40E_NVM_CON:
|
||||
upd_cmd = I40E_NVMUPD_READ_CON;
|
||||
break;
|
||||
case I40E_NVM_SNT:
|
||||
upd_cmd = I40E_NVMUPD_READ_SNT;
|
||||
break;
|
||||
case I40E_NVM_LCB:
|
||||
upd_cmd = I40E_NVMUPD_READ_LCB;
|
||||
break;
|
||||
case I40E_NVM_SA:
|
||||
upd_cmd = I40E_NVMUPD_READ_SA;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case I40E_NVM_WRITE:
|
||||
switch (transaction) {
|
||||
case I40E_NVM_CON:
|
||||
upd_cmd = I40E_NVMUPD_WRITE_CON;
|
||||
break;
|
||||
case I40E_NVM_SNT:
|
||||
upd_cmd = I40E_NVMUPD_WRITE_SNT;
|
||||
break;
|
||||
case I40E_NVM_LCB:
|
||||
upd_cmd = I40E_NVMUPD_WRITE_LCB;
|
||||
break;
|
||||
case I40E_NVM_SA:
|
||||
upd_cmd = I40E_NVMUPD_WRITE_SA;
|
||||
break;
|
||||
case I40E_NVM_ERA:
|
||||
upd_cmd = I40E_NVMUPD_WRITE_ERA;
|
||||
break;
|
||||
case I40E_NVM_CSUM:
|
||||
upd_cmd = I40E_NVMUPD_CSUM_CON;
|
||||
break;
|
||||
case (I40E_NVM_CSUM|I40E_NVM_SA):
|
||||
upd_cmd = I40E_NVMUPD_CSUM_SA;
|
||||
break;
|
||||
case (I40E_NVM_CSUM|I40E_NVM_LCB):
|
||||
upd_cmd = I40E_NVMUPD_CSUM_LCB;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (upd_cmd == I40E_NVMUPD_INVALID) {
|
||||
*errno = -EFAULT;
|
||||
hw_dbg(hw,
|
||||
"i40e_nvmupd_validate_command returns %d errno: %d\n",
|
||||
upd_cmd, *errno);
|
||||
}
|
||||
return upd_cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_nvmupd_nvm_read - Read NVM
|
||||
* @hw: pointer to hardware structure
|
||||
* @cmd: pointer to nvm update command buffer
|
||||
* @bytes: pointer to the data buffer
|
||||
* @errno: pointer to return error code
|
||||
*
|
||||
* cmd structure contains identifiers and data buffer
|
||||
**/
|
||||
static i40e_status i40e_nvmupd_nvm_read(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *errno)
|
||||
{
|
||||
i40e_status status;
|
||||
u8 module, transaction;
|
||||
bool last;
|
||||
|
||||
transaction = i40e_nvmupd_get_transaction(cmd->config);
|
||||
module = i40e_nvmupd_get_module(cmd->config);
|
||||
last = (transaction == I40E_NVM_LCB) || (transaction == I40E_NVM_SA);
|
||||
hw_dbg(hw, "i40e_nvmupd_nvm_read mod 0x%x off 0x%x len 0x%x\n",
|
||||
module, cmd->offset, cmd->data_size);
|
||||
|
||||
status = i40e_aq_read_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
|
||||
bytes, last, NULL);
|
||||
hw_dbg(hw, "i40e_nvmupd_nvm_read status %d\n", status);
|
||||
if (status)
|
||||
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_nvmupd_nvm_erase - Erase an NVM module
|
||||
* @hw: pointer to hardware structure
|
||||
* @cmd: pointer to nvm update command buffer
|
||||
* @errno: pointer to return error code
|
||||
*
|
||||
* module, offset, data_size and data are in cmd structure
|
||||
**/
|
||||
static i40e_status i40e_nvmupd_nvm_erase(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
int *errno)
|
||||
{
|
||||
i40e_status status = 0;
|
||||
u8 module, transaction;
|
||||
bool last;
|
||||
|
||||
transaction = i40e_nvmupd_get_transaction(cmd->config);
|
||||
module = i40e_nvmupd_get_module(cmd->config);
|
||||
last = (transaction & I40E_NVM_LCB);
|
||||
hw_dbg(hw, "i40e_nvmupd_nvm_erase mod 0x%x off 0x%x len 0x%x\n",
|
||||
module, cmd->offset, cmd->data_size);
|
||||
status = i40e_aq_erase_nvm(hw, module, cmd->offset, (u16)cmd->data_size,
|
||||
last, NULL);
|
||||
hw_dbg(hw, "i40e_nvmupd_nvm_erase status %d\n", status);
|
||||
if (status)
|
||||
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_nvmupd_nvm_write - Write NVM
|
||||
* @hw: pointer to hardware structure
|
||||
* @cmd: pointer to nvm update command buffer
|
||||
* @bytes: pointer to the data buffer
|
||||
* @errno: pointer to return error code
|
||||
*
|
||||
* module, offset, data_size and data are in cmd structure
|
||||
**/
|
||||
static i40e_status i40e_nvmupd_nvm_write(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *errno)
|
||||
{
|
||||
i40e_status status = 0;
|
||||
u8 module, transaction;
|
||||
bool last;
|
||||
|
||||
transaction = i40e_nvmupd_get_transaction(cmd->config);
|
||||
module = i40e_nvmupd_get_module(cmd->config);
|
||||
last = (transaction & I40E_NVM_LCB);
|
||||
hw_dbg(hw, "i40e_nvmupd_nvm_write mod 0x%x off 0x%x len 0x%x\n",
|
||||
module, cmd->offset, cmd->data_size);
|
||||
status = i40e_aq_update_nvm(hw, module, cmd->offset,
|
||||
(u16)cmd->data_size, bytes, last, NULL);
|
||||
hw_dbg(hw, "i40e_nvmupd_nvm_write status %d\n", status);
|
||||
if (status)
|
||||
*errno = i40e_aq_rc_to_posix(hw->aq.asq_last_status);
|
||||
|
||||
return status;
|
||||
}
|
84
drivers/net/ethernet/intel/i40e/i40e_osdep.h
Normal file
84
drivers/net/ethernet/intel/i40e/i40e_osdep.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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>
|
||||
#include <linux/highuid.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_GLGEN_STAT)
|
||||
|
||||
/* 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) \
|
||||
i40e_allocate_dma_mem_d(h, m, s, a)
|
||||
#define i40e_free_dma_mem(h, m) i40e_free_dma_mem_d(h, m)
|
||||
|
||||
struct i40e_virt_mem {
|
||||
void *va;
|
||||
u32 size;
|
||||
} __packed;
|
||||
|
||||
#define i40e_allocate_virt_mem(h, m, s) i40e_allocate_virt_mem_d(h, m, s)
|
||||
#define i40e_free_virt_mem(h, m) i40e_free_virt_mem_d(h, m)
|
||||
|
||||
#define i40e_debug(h, m, s, ...) \
|
||||
do { \
|
||||
if (((m) & (h)->debug_mask)) \
|
||||
pr_info("i40e %02x.%x " s, \
|
||||
(h)->bus.device, (h)->bus.func, \
|
||||
##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
typedef enum i40e_status_code i40e_status;
|
||||
#ifdef CONFIG_I40E_FCOE
|
||||
#define I40E_FCOE
|
||||
#endif
|
||||
#endif /* _I40E_OSDEP_H_ */
|
288
drivers/net/ethernet/intel/i40e/i40e_prototype.h
Normal file
288
drivers/net/ethernet/intel/i40e/i40e_prototype.h
Normal file
|
@ -0,0 +1,288 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_PROTOTYPE_H_
|
||||
#define _I40E_PROTOTYPE_H_
|
||||
|
||||
#include "i40e_type.h"
|
||||
#include "i40e_alloc.h"
|
||||
#include "i40e_virtchnl.h"
|
||||
|
||||
/* Prototypes for shared code functions that are not in
|
||||
* the standard function pointer structures. These are
|
||||
* mostly because they are needed even before the init
|
||||
* has happened and will assist in the early SW and FW
|
||||
* setup.
|
||||
*/
|
||||
|
||||
/* adminq functions */
|
||||
i40e_status i40e_init_adminq(struct i40e_hw *hw);
|
||||
i40e_status i40e_shutdown_adminq(struct i40e_hw *hw);
|
||||
void i40e_adminq_init_ring_data(struct i40e_hw *hw);
|
||||
i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
|
||||
struct i40e_arq_event_info *e,
|
||||
u16 *events_pending);
|
||||
i40e_status i40e_asq_send_command(struct i40e_hw *hw,
|
||||
struct i40e_aq_desc *desc,
|
||||
void *buff, /* can be NULL */
|
||||
u16 buff_size,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
|
||||
/* debug function for adminq */
|
||||
void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask,
|
||||
void *desc, void *buffer, u16 buf_len);
|
||||
|
||||
void i40e_idle_aq(struct i40e_hw *hw);
|
||||
bool i40e_check_asq_alive(struct i40e_hw *hw);
|
||||
i40e_status i40e_aq_queue_shutdown(struct i40e_hw *hw, bool unloading);
|
||||
|
||||
u32 i40e_led_get(struct i40e_hw *hw);
|
||||
void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink);
|
||||
|
||||
/* admin send queue commands */
|
||||
|
||||
i40e_status i40e_aq_get_firmware_version(struct i40e_hw *hw,
|
||||
u16 *fw_major_version, u16 *fw_minor_version,
|
||||
u16 *api_major_version, u16 *api_minor_version,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_debug_write_register(struct i40e_hw *hw,
|
||||
u32 reg_addr, u64 reg_val,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_phy_debug(struct i40e_hw *hw, u8 cmd_flags,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_default_vsi(struct i40e_hw *hw, u16 vsi_id,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
enum i40e_status_code i40e_aq_get_phy_capabilities(struct i40e_hw *hw,
|
||||
bool qualified_modules, bool report_init,
|
||||
struct i40e_aq_get_phy_abilities_resp *abilities,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw,
|
||||
struct i40e_aq_set_phy_config *config,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
|
||||
bool atomic_reset);
|
||||
i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_link_restart_an(struct i40e_hw *hw,
|
||||
bool enable_link,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,
|
||||
bool enable_lse, struct i40e_link_status *link,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_update_link_info(struct i40e_hw *hw, bool enable_lse);
|
||||
i40e_status i40e_aq_set_local_advt_reg(struct i40e_hw *hw,
|
||||
u64 advt_reg,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_send_driver_version(struct i40e_hw *hw,
|
||||
struct i40e_driver_version *dv,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_add_vsi(struct i40e_hw *hw,
|
||||
struct i40e_vsi_context *vsi_ctx,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_vsi_broadcast(struct i40e_hw *hw,
|
||||
u16 vsi_id, bool set_filter,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw,
|
||||
u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_vsi_multicast_promiscuous(struct i40e_hw *hw,
|
||||
u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_vsi_params(struct i40e_hw *hw,
|
||||
struct i40e_vsi_context *vsi_ctx,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_update_vsi_params(struct i40e_hw *hw,
|
||||
struct i40e_vsi_context *vsi_ctx,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid,
|
||||
u16 downlink_seid, u8 enabled_tc,
|
||||
bool default_port, bool enable_l2_filtering,
|
||||
u16 *pveb_seid,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_veb_parameters(struct i40e_hw *hw,
|
||||
u16 veb_seid, u16 *switch_id, bool *floating,
|
||||
u16 *statistic_index, u16 *vebs_used,
|
||||
u16 *vebs_free,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_add_macvlan(struct i40e_hw *hw, u16 vsi_id,
|
||||
struct i40e_aqc_add_macvlan_element_data *mv_list,
|
||||
u16 count, struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_remove_macvlan(struct i40e_hw *hw, u16 vsi_id,
|
||||
struct i40e_aqc_remove_macvlan_element_data *mv_list,
|
||||
u16 count, struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_send_msg_to_vf(struct i40e_hw *hw, u16 vfid,
|
||||
u32 v_opcode, u32 v_retval, u8 *msg, u16 msglen,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_switch_config(struct i40e_hw *hw,
|
||||
struct i40e_aqc_get_switch_config_resp *buf,
|
||||
u16 buf_size, u16 *start_seid,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_request_resource(struct i40e_hw *hw,
|
||||
enum i40e_aq_resources_ids resource,
|
||||
enum i40e_aq_resource_access_type access,
|
||||
u8 sdp_number, u64 *timeout,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_release_resource(struct i40e_hw *hw,
|
||||
enum i40e_aq_resources_ids resource,
|
||||
u8 sdp_number,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_read_nvm(struct i40e_hw *hw, u8 module_pointer,
|
||||
u32 offset, u16 length, void *data,
|
||||
bool last_command,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_erase_nvm(struct i40e_hw *hw, u8 module_pointer,
|
||||
u32 offset, u16 length, bool last_command,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_discover_capabilities(struct i40e_hw *hw,
|
||||
void *buff, u16 buff_size, u16 *data_size,
|
||||
enum i40e_admin_queue_opc list_type_opc,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_update_nvm(struct i40e_hw *hw, u8 module_pointer,
|
||||
u32 offset, u16 length, void *data,
|
||||
bool last_command,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_get_lldp_mib(struct i40e_hw *hw, u8 bridge_type,
|
||||
u8 mib_type, void *buff, u16 buff_size,
|
||||
u16 *local_len, u16 *remote_len,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_cfg_lldp_mib_change_event(struct i40e_hw *hw,
|
||||
bool enable_update,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_add_udp_tunnel(struct i40e_hw *hw,
|
||||
u16 udp_port, u8 protocol_index,
|
||||
u8 *filter_index,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_del_udp_tunnel(struct i40e_hw *hw, u8 index,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_delete_element(struct i40e_hw *hw, u16 seid,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_mac_address_write(struct i40e_hw *hw,
|
||||
u16 flags, u8 *mac_addr,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_config_vsi_bw_limit(struct i40e_hw *hw,
|
||||
u16 seid, u16 credit, u8 max_credit,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_dcb_updated(struct i40e_hw *hw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_set_hmc_resource_profile(struct i40e_hw *hw,
|
||||
enum i40e_aq_hmc_profile profile,
|
||||
u8 pe_vf_enabled_count,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_config_switch_comp_bw_limit(struct i40e_hw *hw,
|
||||
u16 seid, u16 credit, u8 max_bw,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_config_vsi_tc_bw(struct i40e_hw *hw, u16 seid,
|
||||
struct i40e_aqc_configure_vsi_tc_bw_data *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_config_switch_comp_ets(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_configure_switching_comp_ets_data *ets_data,
|
||||
enum i40e_admin_queue_opc opcode,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_config_switch_comp_bw_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_configure_switching_comp_bw_config_data *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_query_vsi_bw_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_query_vsi_bw_config_resp *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_query_vsi_ets_sla_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_query_vsi_ets_sla_config_resp *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_query_switch_comp_ets_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_query_switching_comp_ets_config_resp *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_query_port_ets_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_query_port_ets_config_resp *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_aq_query_switch_comp_bw_config(struct i40e_hw *hw,
|
||||
u16 seid,
|
||||
struct i40e_aqc_query_switching_comp_bw_config_resp *bw_data,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
/* i40e_common */
|
||||
i40e_status i40e_init_shared_code(struct i40e_hw *hw);
|
||||
i40e_status i40e_pf_reset(struct i40e_hw *hw);
|
||||
void i40e_clear_hw(struct i40e_hw *hw);
|
||||
void i40e_clear_pxe_mode(struct i40e_hw *hw);
|
||||
bool i40e_get_link_status(struct i40e_hw *hw);
|
||||
i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
|
||||
i40e_status i40e_get_port_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
|
||||
i40e_status i40e_validate_mac_addr(u8 *mac_addr);
|
||||
void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable);
|
||||
#ifdef I40E_FCOE
|
||||
i40e_status i40e_get_san_mac_addr(struct i40e_hw *hw, u8 *mac_addr);
|
||||
#endif
|
||||
/* prototype for functions used for NVM access */
|
||||
i40e_status i40e_init_nvm(struct i40e_hw *hw);
|
||||
i40e_status i40e_acquire_nvm(struct i40e_hw *hw,
|
||||
enum i40e_aq_resource_access_type access);
|
||||
void i40e_release_nvm(struct i40e_hw *hw);
|
||||
i40e_status i40e_read_nvm_srrd(struct i40e_hw *hw, u16 offset,
|
||||
u16 *data);
|
||||
i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
|
||||
u16 *data);
|
||||
i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
|
||||
u16 *words, u16 *data);
|
||||
i40e_status i40e_update_nvm_checksum(struct i40e_hw *hw);
|
||||
i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
|
||||
u16 *checksum);
|
||||
i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
|
||||
struct i40e_nvm_access *cmd,
|
||||
u8 *bytes, int *);
|
||||
void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status);
|
||||
|
||||
extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[];
|
||||
|
||||
static inline struct i40e_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype)
|
||||
{
|
||||
return i40e_ptype_lookup[ptype];
|
||||
}
|
||||
|
||||
/* prototype for functions used for SW locks */
|
||||
|
||||
/* i40e_common for VF drivers*/
|
||||
void i40e_vf_parse_hw_config(struct i40e_hw *hw,
|
||||
struct i40e_virtchnl_vf_resource *msg);
|
||||
i40e_status i40e_vf_reset(struct i40e_hw *hw);
|
||||
i40e_status i40e_aq_send_msg_to_pf(struct i40e_hw *hw,
|
||||
enum i40e_virtchnl_ops v_opcode,
|
||||
i40e_status v_retval,
|
||||
u8 *msg, u16 msglen,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
i40e_status i40e_set_filter_control(struct i40e_hw *hw,
|
||||
struct i40e_filter_control_settings *settings);
|
||||
i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw,
|
||||
u8 *mac_addr, u16 ethtype, u16 flags,
|
||||
u16 vsi_seid, u16 queue, bool is_add,
|
||||
struct i40e_control_filter_stats *stats,
|
||||
struct i40e_asq_cmd_details *cmd_details);
|
||||
#endif /* _I40E_PROTOTYPE_H_ */
|
694
drivers/net/ethernet/intel/i40e/i40e_ptp.c
Normal file
694
drivers/net/ethernet/intel/i40e/i40e_ptp.c
Normal file
|
@ -0,0 +1,694 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "i40e.h"
|
||||
#include <linux/ptp_classify.h>
|
||||
|
||||
/* The XL710 timesync is very much like Intel's 82599 design when it comes to
|
||||
* the fundamental clock design. However, the clock operations are much simpler
|
||||
* in the XL710 because the device supports a full 64 bits of nanoseconds.
|
||||
* Because the field is so wide, we can forgo the cycle counter and just
|
||||
* operate with the nanosecond field directly without fear of overflow.
|
||||
*
|
||||
* Much like the 82599, the update period is dependent upon the link speed:
|
||||
* At 40Gb link or no link, the period is 1.6ns.
|
||||
* At 10Gb link, the period is multiplied by 2. (3.2ns)
|
||||
* At 1Gb link, the period is multiplied by 20. (32ns)
|
||||
* 1588 functionality is not supported at 100Mbps.
|
||||
*/
|
||||
#define I40E_PTP_40GB_INCVAL 0x0199999999ULL
|
||||
#define I40E_PTP_10GB_INCVAL 0x0333333333ULL
|
||||
#define I40E_PTP_1GB_INCVAL 0x2000000000ULL
|
||||
|
||||
#define I40E_PRTTSYN_CTL1_TSYNTYPE_V1 (0x1 << \
|
||||
I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
|
||||
#define I40E_PRTTSYN_CTL1_TSYNTYPE_V2 (0x2 << \
|
||||
I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT)
|
||||
|
||||
/**
|
||||
* i40e_ptp_read - Read the PHC time from the device
|
||||
* @pf: Board private structure
|
||||
* @ts: timespec structure to hold the current time value
|
||||
*
|
||||
* This function reads the PRTTSYN_TIME registers and stores them in a
|
||||
* timespec. However, since the registers are 64 bits of nanoseconds, we must
|
||||
* convert the result to a timespec before we can return.
|
||||
**/
|
||||
static void i40e_ptp_read(struct i40e_pf *pf, struct timespec *ts)
|
||||
{
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u32 hi, lo;
|
||||
u64 ns;
|
||||
|
||||
/* The timer latches on the lowest register read. */
|
||||
lo = rd32(hw, I40E_PRTTSYN_TIME_L);
|
||||
hi = rd32(hw, I40E_PRTTSYN_TIME_H);
|
||||
|
||||
ns = (((u64)hi) << 32) | lo;
|
||||
|
||||
*ts = ns_to_timespec(ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_write - Write the PHC time to the device
|
||||
* @pf: Board private structure
|
||||
* @ts: timespec structure that holds the new time value
|
||||
*
|
||||
* This function writes the PRTTSYN_TIME registers with the user value. Since
|
||||
* we receive a timespec from the stack, we must convert that timespec into
|
||||
* nanoseconds before programming the registers.
|
||||
**/
|
||||
static void i40e_ptp_write(struct i40e_pf *pf, const struct timespec *ts)
|
||||
{
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u64 ns = timespec_to_ns(ts);
|
||||
|
||||
/* The timer will not update until the high register is written, so
|
||||
* write the low register first.
|
||||
*/
|
||||
wr32(hw, I40E_PRTTSYN_TIME_L, ns & 0xFFFFFFFF);
|
||||
wr32(hw, I40E_PRTTSYN_TIME_H, ns >> 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_convert_to_hwtstamp - Convert device clock to system time
|
||||
* @hwtstamps: Timestamp structure to update
|
||||
* @timestamp: Timestamp from the hardware
|
||||
*
|
||||
* We need to convert the NIC clock value into a hwtstamp which can be used by
|
||||
* the upper level timestamping functions. Since the timestamp is simply a 64-
|
||||
* bit nanosecond value, we can call ns_to_ktime directly to handle this.
|
||||
**/
|
||||
static void i40e_ptp_convert_to_hwtstamp(struct skb_shared_hwtstamps *hwtstamps,
|
||||
u64 timestamp)
|
||||
{
|
||||
memset(hwtstamps, 0, sizeof(*hwtstamps));
|
||||
|
||||
hwtstamps->hwtstamp = ns_to_ktime(timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_adjfreq - Adjust the PHC frequency
|
||||
* @ptp: The PTP clock structure
|
||||
* @ppb: Parts per billion adjustment from the base
|
||||
*
|
||||
* Adjust the frequency of the PHC by the indicated parts per billion from the
|
||||
* base frequency.
|
||||
**/
|
||||
static int i40e_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
|
||||
{
|
||||
struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u64 adj, freq, diff;
|
||||
int neg_adj = 0;
|
||||
|
||||
if (ppb < 0) {
|
||||
neg_adj = 1;
|
||||
ppb = -ppb;
|
||||
}
|
||||
|
||||
smp_mb(); /* Force any pending update before accessing. */
|
||||
adj = ACCESS_ONCE(pf->ptp_base_adj);
|
||||
|
||||
freq = adj;
|
||||
freq *= ppb;
|
||||
diff = div_u64(freq, 1000000000ULL);
|
||||
|
||||
if (neg_adj)
|
||||
adj -= diff;
|
||||
else
|
||||
adj += diff;
|
||||
|
||||
wr32(hw, I40E_PRTTSYN_INC_L, adj & 0xFFFFFFFF);
|
||||
wr32(hw, I40E_PRTTSYN_INC_H, adj >> 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_adjtime - Adjust the PHC time
|
||||
* @ptp: The PTP clock structure
|
||||
* @delta: Offset in nanoseconds to adjust the PHC time by
|
||||
*
|
||||
* Adjust the frequency of the PHC by the indicated parts per billion from the
|
||||
* base frequency.
|
||||
**/
|
||||
static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
|
||||
{
|
||||
struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
|
||||
struct timespec now, then = ns_to_timespec(delta);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pf->tmreg_lock, flags);
|
||||
|
||||
i40e_ptp_read(pf, &now);
|
||||
now = timespec_add(now, then);
|
||||
i40e_ptp_write(pf, (const struct timespec *)&now);
|
||||
|
||||
spin_unlock_irqrestore(&pf->tmreg_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_gettime - Get the time of the PHC
|
||||
* @ptp: The PTP clock structure
|
||||
* @ts: timespec structure to hold the current time value
|
||||
*
|
||||
* Read the device clock and return the correct value on ns, after converting it
|
||||
* into a timespec struct.
|
||||
**/
|
||||
static int i40e_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
|
||||
{
|
||||
struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pf->tmreg_lock, flags);
|
||||
i40e_ptp_read(pf, ts);
|
||||
spin_unlock_irqrestore(&pf->tmreg_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_settime - Set the time of the PHC
|
||||
* @ptp: The PTP clock structure
|
||||
* @ts: timespec structure that holds the new time value
|
||||
*
|
||||
* Set the device clock to the user input value. The conversion from timespec
|
||||
* to ns happens in the write function.
|
||||
**/
|
||||
static int i40e_ptp_settime(struct ptp_clock_info *ptp,
|
||||
const struct timespec *ts)
|
||||
{
|
||||
struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pf->tmreg_lock, flags);
|
||||
i40e_ptp_write(pf, ts);
|
||||
spin_unlock_irqrestore(&pf->tmreg_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_feature_enable - Enable/disable ancillary features of the PHC subsystem
|
||||
* @ptp: The PTP clock structure
|
||||
* @rq: The requested feature to change
|
||||
* @on: Enable/disable flag
|
||||
*
|
||||
* The XL710 does not support any of the ancillary features of the PHC
|
||||
* subsystem, so this function may just return.
|
||||
**/
|
||||
static int i40e_ptp_feature_enable(struct ptp_clock_info *ptp,
|
||||
struct ptp_clock_request *rq, int on)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_rx_hang - Detect error case when Rx timestamp registers are hung
|
||||
* @vsi: The VSI with the rings relevant to 1588
|
||||
*
|
||||
* This watchdog task is scheduled to detect error case where hardware has
|
||||
* dropped an Rx packet that was timestamped when the ring is full. The
|
||||
* particular error is rare but leaves the device in a state unable to timestamp
|
||||
* any future packets.
|
||||
**/
|
||||
void i40e_ptp_rx_hang(struct i40e_vsi *vsi)
|
||||
{
|
||||
struct i40e_pf *pf = vsi->back;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
struct i40e_ring *rx_ring;
|
||||
unsigned long rx_event;
|
||||
u32 prttsyn_stat;
|
||||
int n;
|
||||
|
||||
if (!(pf->flags & I40E_FLAG_PTP))
|
||||
return;
|
||||
|
||||
prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
|
||||
|
||||
/* Unless all four receive timestamp registers are latched, we are not
|
||||
* concerned about a possible PTP Rx hang, so just update the timeout
|
||||
* counter and exit.
|
||||
*/
|
||||
if (!(prttsyn_stat & ((I40E_PRTTSYN_STAT_1_RXT0_MASK <<
|
||||
I40E_PRTTSYN_STAT_1_RXT0_SHIFT) |
|
||||
(I40E_PRTTSYN_STAT_1_RXT1_MASK <<
|
||||
I40E_PRTTSYN_STAT_1_RXT1_SHIFT) |
|
||||
(I40E_PRTTSYN_STAT_1_RXT2_MASK <<
|
||||
I40E_PRTTSYN_STAT_1_RXT2_SHIFT) |
|
||||
(I40E_PRTTSYN_STAT_1_RXT3_MASK <<
|
||||
I40E_PRTTSYN_STAT_1_RXT3_SHIFT)))) {
|
||||
pf->last_rx_ptp_check = jiffies;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Determine the most recent watchdog or rx_timestamp event. */
|
||||
rx_event = pf->last_rx_ptp_check;
|
||||
for (n = 0; n < vsi->num_queue_pairs; n++) {
|
||||
rx_ring = vsi->rx_rings[n];
|
||||
if (time_after(rx_ring->last_rx_timestamp, rx_event))
|
||||
rx_event = rx_ring->last_rx_timestamp;
|
||||
}
|
||||
|
||||
/* Only need to read the high RXSTMP register to clear the lock */
|
||||
if (time_is_before_jiffies(rx_event + 5 * HZ)) {
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(0));
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(1));
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(2));
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(3));
|
||||
pf->last_rx_ptp_check = jiffies;
|
||||
pf->rx_hwtstamp_cleared++;
|
||||
dev_warn(&vsi->back->pdev->dev,
|
||||
"%s: clearing Rx timestamp hang\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_tx_hwtstamp - Utility function which returns the Tx timestamp
|
||||
* @pf: Board private structure
|
||||
*
|
||||
* Read the value of the Tx timestamp from the registers, convert it into a
|
||||
* value consumable by the stack, and store that result into the shhwtstamps
|
||||
* struct before returning it up the stack.
|
||||
**/
|
||||
void i40e_ptp_tx_hwtstamp(struct i40e_pf *pf)
|
||||
{
|
||||
struct skb_shared_hwtstamps shhwtstamps;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u32 hi, lo;
|
||||
u64 ns;
|
||||
|
||||
lo = rd32(hw, I40E_PRTTSYN_TXTIME_L);
|
||||
hi = rd32(hw, I40E_PRTTSYN_TXTIME_H);
|
||||
|
||||
ns = (((u64)hi) << 32) | lo;
|
||||
|
||||
i40e_ptp_convert_to_hwtstamp(&shhwtstamps, ns);
|
||||
skb_tstamp_tx(pf->ptp_tx_skb, &shhwtstamps);
|
||||
dev_kfree_skb_any(pf->ptp_tx_skb);
|
||||
pf->ptp_tx_skb = NULL;
|
||||
clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_rx_hwtstamp - Utility function which checks for an Rx timestamp
|
||||
* @pf: Board private structure
|
||||
* @skb: Particular skb to send timestamp with
|
||||
* @index: Index into the receive timestamp registers for the timestamp
|
||||
*
|
||||
* The XL710 receives a notification in the receive descriptor with an offset
|
||||
* into the set of RXTIME registers where the timestamp is for that skb. This
|
||||
* function goes and fetches the receive timestamp from that offset, if a valid
|
||||
* one exists. The RXTIME registers are in ns, so we must convert the result
|
||||
* first.
|
||||
**/
|
||||
void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index)
|
||||
{
|
||||
u32 prttsyn_stat, hi, lo;
|
||||
struct i40e_hw *hw;
|
||||
u64 ns;
|
||||
|
||||
/* Since we cannot turn off the Rx timestamp logic if the device is
|
||||
* doing Tx timestamping, check if Rx timestamping is configured.
|
||||
*/
|
||||
if (!pf->ptp_rx)
|
||||
return;
|
||||
|
||||
hw = &pf->hw;
|
||||
|
||||
prttsyn_stat = rd32(hw, I40E_PRTTSYN_STAT_1);
|
||||
|
||||
if (!(prttsyn_stat & (1 << index)))
|
||||
return;
|
||||
|
||||
lo = rd32(hw, I40E_PRTTSYN_RXTIME_L(index));
|
||||
hi = rd32(hw, I40E_PRTTSYN_RXTIME_H(index));
|
||||
|
||||
ns = (((u64)hi) << 32) | lo;
|
||||
|
||||
i40e_ptp_convert_to_hwtstamp(skb_hwtstamps(skb), ns);
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_set_increment - Utility function to update clock increment rate
|
||||
* @pf: Board private structure
|
||||
*
|
||||
* During a link change, the DMA frequency that drives the 1588 logic will
|
||||
* change. In order to keep the PRTTSYN_TIME registers in units of nanoseconds,
|
||||
* we must update the increment value per clock tick.
|
||||
**/
|
||||
void i40e_ptp_set_increment(struct i40e_pf *pf)
|
||||
{
|
||||
struct i40e_link_status *hw_link_info;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u64 incval;
|
||||
|
||||
hw_link_info = &hw->phy.link_info;
|
||||
|
||||
i40e_aq_get_link_info(&pf->hw, true, NULL, NULL);
|
||||
|
||||
switch (hw_link_info->link_speed) {
|
||||
case I40E_LINK_SPEED_10GB:
|
||||
incval = I40E_PTP_10GB_INCVAL;
|
||||
break;
|
||||
case I40E_LINK_SPEED_1GB:
|
||||
incval = I40E_PTP_1GB_INCVAL;
|
||||
break;
|
||||
case I40E_LINK_SPEED_100MB:
|
||||
dev_warn(&pf->pdev->dev,
|
||||
"%s: 1588 functionality is not supported at 100 Mbps. Stopping the PHC.\n",
|
||||
__func__);
|
||||
incval = 0;
|
||||
break;
|
||||
case I40E_LINK_SPEED_40GB:
|
||||
default:
|
||||
incval = I40E_PTP_40GB_INCVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Write the new increment value into the increment register. The
|
||||
* hardware will not update the clock until both registers have been
|
||||
* written.
|
||||
*/
|
||||
wr32(hw, I40E_PRTTSYN_INC_L, incval & 0xFFFFFFFF);
|
||||
wr32(hw, I40E_PRTTSYN_INC_H, incval >> 32);
|
||||
|
||||
/* Update the base adjustement value. */
|
||||
ACCESS_ONCE(pf->ptp_base_adj) = incval;
|
||||
smp_mb(); /* Force the above update. */
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_get_ts_config - ioctl interface to read the HW timestamping
|
||||
* @pf: Board private structure
|
||||
* @ifreq: ioctl data
|
||||
*
|
||||
* Obtain the current hardware timestamping settigs as requested. To do this,
|
||||
* keep a shadow copy of the timestamp settings rather than attempting to
|
||||
* deconstruct it from the registers.
|
||||
**/
|
||||
int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
|
||||
{
|
||||
struct hwtstamp_config *config = &pf->tstamp_config;
|
||||
|
||||
return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
|
||||
-EFAULT : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_set_timestamp_mode - setup hardware for requested timestamp mode
|
||||
* @pf: Board private structure
|
||||
* @config: hwtstamp settings requested or saved
|
||||
*
|
||||
* Control hardware registers to enter the specific mode requested by the
|
||||
* user. Also used during reset path to ensure that timestamp settings are
|
||||
* maintained.
|
||||
*
|
||||
* Note: modifies config in place, and may update the requested mode to be
|
||||
* more broad if the specific filter is not directly supported.
|
||||
**/
|
||||
static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf,
|
||||
struct hwtstamp_config *config)
|
||||
{
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
u32 pf_id, tsyntype, regval;
|
||||
|
||||
/* Reserved for future extensions. */
|
||||
if (config->flags)
|
||||
return -EINVAL;
|
||||
|
||||
/* Confirm that 1588 is supported on this PF. */
|
||||
pf_id = (rd32(hw, I40E_PRTTSYN_CTL0) & I40E_PRTTSYN_CTL0_PF_ID_MASK) >>
|
||||
I40E_PRTTSYN_CTL0_PF_ID_SHIFT;
|
||||
if (hw->pf_id != pf_id) {
|
||||
dev_err(&pf->pdev->dev,
|
||||
"PF %d attempted to control timestamp mode on port %d, which is owned by PF %d\n",
|
||||
hw->pf_id, hw->port, pf_id);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
switch (config->tx_type) {
|
||||
case HWTSTAMP_TX_OFF:
|
||||
pf->ptp_tx = false;
|
||||
break;
|
||||
case HWTSTAMP_TX_ON:
|
||||
pf->ptp_tx = true;
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
switch (config->rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
pf->ptp_rx = false;
|
||||
tsyntype = 0;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
||||
pf->ptp_rx = true;
|
||||
tsyntype = I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK |
|
||||
I40E_PRTTSYN_CTL1_TSYNTYPE_V1 |
|
||||
I40E_PRTTSYN_CTL1_UDP_ENA_MASK;
|
||||
config->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
|
||||
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
|
||||
pf->ptp_rx = true;
|
||||
tsyntype = I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK |
|
||||
I40E_PRTTSYN_CTL1_TSYNTYPE_V2 |
|
||||
I40E_PRTTSYN_CTL1_UDP_ENA_MASK;
|
||||
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_ALL:
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
/* Clear out all 1588-related registers to clear and unlatch them. */
|
||||
rd32(hw, I40E_PRTTSYN_STAT_0);
|
||||
rd32(hw, I40E_PRTTSYN_TXTIME_H);
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(0));
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(1));
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(2));
|
||||
rd32(hw, I40E_PRTTSYN_RXTIME_H(3));
|
||||
|
||||
/* Enable/disable the Tx timestamp interrupt based on user input. */
|
||||
regval = rd32(hw, I40E_PRTTSYN_CTL0);
|
||||
if (pf->ptp_tx)
|
||||
regval |= I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK;
|
||||
else
|
||||
regval &= ~I40E_PRTTSYN_CTL0_TXTIME_INT_ENA_MASK;
|
||||
wr32(hw, I40E_PRTTSYN_CTL0, regval);
|
||||
|
||||
regval = rd32(hw, I40E_PFINT_ICR0_ENA);
|
||||
if (pf->ptp_tx)
|
||||
regval |= I40E_PFINT_ICR0_ENA_TIMESYNC_MASK;
|
||||
else
|
||||
regval &= ~I40E_PFINT_ICR0_ENA_TIMESYNC_MASK;
|
||||
wr32(hw, I40E_PFINT_ICR0_ENA, regval);
|
||||
|
||||
/* There is no simple on/off switch for Rx. To "disable" Rx support,
|
||||
* ignore any received timestamps, rather than turn off the clock.
|
||||
*/
|
||||
if (pf->ptp_rx) {
|
||||
regval = rd32(hw, I40E_PRTTSYN_CTL1);
|
||||
/* clear everything but the enable bit */
|
||||
regval &= I40E_PRTTSYN_CTL1_TSYNENA_MASK;
|
||||
/* now enable bits for desired Rx timestamps */
|
||||
regval |= tsyntype;
|
||||
wr32(hw, I40E_PRTTSYN_CTL1, regval);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_set_ts_config - ioctl interface to control the HW timestamping
|
||||
* @pf: Board private structure
|
||||
* @ifreq: ioctl data
|
||||
*
|
||||
* Respond to the user filter requests and make the appropriate hardware
|
||||
* changes here. The XL710 cannot support splitting of the Tx/Rx timestamping
|
||||
* logic, so keep track in software of whether to indicate these timestamps
|
||||
* or not.
|
||||
*
|
||||
* It is permissible to "upgrade" the user request to a broader filter, as long
|
||||
* as the user receives the timestamps they care about and the user is notified
|
||||
* the filter has been broadened.
|
||||
**/
|
||||
int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
|
||||
{
|
||||
struct hwtstamp_config config;
|
||||
int err;
|
||||
|
||||
if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
|
||||
return -EFAULT;
|
||||
|
||||
err = i40e_ptp_set_timestamp_mode(pf, &config);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* save these settings for future reference */
|
||||
pf->tstamp_config = config;
|
||||
|
||||
return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
|
||||
-EFAULT : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_create_clock - Create PTP clock device for userspace
|
||||
* @pf: Board private structure
|
||||
*
|
||||
* This function creates a new PTP clock device. It only creates one if we
|
||||
* don't already have one, so it is safe to call. Will return error if it
|
||||
* can't create one, but success if we already have a device. Should be used
|
||||
* by i40e_ptp_init to create clock initially, and prevent global resets from
|
||||
* creating new clock devices.
|
||||
**/
|
||||
static long i40e_ptp_create_clock(struct i40e_pf *pf)
|
||||
{
|
||||
/* no need to create a clock device if we already have one */
|
||||
if (!IS_ERR_OR_NULL(pf->ptp_clock))
|
||||
return 0;
|
||||
|
||||
strncpy(pf->ptp_caps.name, i40e_driver_name, sizeof(pf->ptp_caps.name));
|
||||
pf->ptp_caps.owner = THIS_MODULE;
|
||||
pf->ptp_caps.max_adj = 999999999;
|
||||
pf->ptp_caps.n_ext_ts = 0;
|
||||
pf->ptp_caps.pps = 0;
|
||||
pf->ptp_caps.adjfreq = i40e_ptp_adjfreq;
|
||||
pf->ptp_caps.adjtime = i40e_ptp_adjtime;
|
||||
pf->ptp_caps.gettime = i40e_ptp_gettime;
|
||||
pf->ptp_caps.settime = i40e_ptp_settime;
|
||||
pf->ptp_caps.enable = i40e_ptp_feature_enable;
|
||||
|
||||
/* Attempt to register the clock before enabling the hardware. */
|
||||
pf->ptp_clock = ptp_clock_register(&pf->ptp_caps, &pf->pdev->dev);
|
||||
if (IS_ERR(pf->ptp_clock)) {
|
||||
return PTR_ERR(pf->ptp_clock);
|
||||
}
|
||||
|
||||
/* clear the hwtstamp settings here during clock create, instead of
|
||||
* during regular init, so that we can maintain settings across a
|
||||
* reset or suspend.
|
||||
*/
|
||||
pf->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
|
||||
pf->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_init - Initialize the 1588 support after device probe or reset
|
||||
* @pf: Board private structure
|
||||
*
|
||||
* This function sets device up for 1588 support. The first time it is run, it
|
||||
* will create a PHC clock device. It does not create a clock device if one
|
||||
* already exists. It also reconfigures the device after a reset.
|
||||
**/
|
||||
void i40e_ptp_init(struct i40e_pf *pf)
|
||||
{
|
||||
struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev;
|
||||
struct i40e_hw *hw = &pf->hw;
|
||||
long err;
|
||||
|
||||
/* we have to initialize the lock first, since we can't control
|
||||
* when the user will enter the PHC device entry points
|
||||
*/
|
||||
spin_lock_init(&pf->tmreg_lock);
|
||||
|
||||
/* ensure we have a clock device */
|
||||
err = i40e_ptp_create_clock(pf);
|
||||
if (err) {
|
||||
pf->ptp_clock = NULL;
|
||||
dev_err(&pf->pdev->dev, "%s: ptp_clock_register failed\n",
|
||||
__func__);
|
||||
} else {
|
||||
struct timespec ts;
|
||||
u32 regval;
|
||||
|
||||
dev_info(&pf->pdev->dev, "%s: added PHC on %s\n", __func__,
|
||||
netdev->name);
|
||||
pf->flags |= I40E_FLAG_PTP;
|
||||
|
||||
/* Ensure the clocks are running. */
|
||||
regval = rd32(hw, I40E_PRTTSYN_CTL0);
|
||||
regval |= I40E_PRTTSYN_CTL0_TSYNENA_MASK;
|
||||
wr32(hw, I40E_PRTTSYN_CTL0, regval);
|
||||
regval = rd32(hw, I40E_PRTTSYN_CTL1);
|
||||
regval |= I40E_PRTTSYN_CTL1_TSYNENA_MASK;
|
||||
wr32(hw, I40E_PRTTSYN_CTL1, regval);
|
||||
|
||||
/* Set the increment value per clock tick. */
|
||||
i40e_ptp_set_increment(pf);
|
||||
|
||||
/* reset timestamping mode */
|
||||
i40e_ptp_set_timestamp_mode(pf, &pf->tstamp_config);
|
||||
|
||||
/* Set the clock value. */
|
||||
ts = ktime_to_timespec(ktime_get_real());
|
||||
i40e_ptp_settime(&pf->ptp_caps, &ts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* i40e_ptp_stop - Disable the driver/hardware support and unregister the PHC
|
||||
* @pf: Board private structure
|
||||
*
|
||||
* This function handles the cleanup work required from the initialization by
|
||||
* clearing out the important information and unregistering the PHC.
|
||||
**/
|
||||
void i40e_ptp_stop(struct i40e_pf *pf)
|
||||
{
|
||||
pf->flags &= ~I40E_FLAG_PTP;
|
||||
pf->ptp_tx = false;
|
||||
pf->ptp_rx = false;
|
||||
|
||||
if (pf->ptp_tx_skb) {
|
||||
dev_kfree_skb_any(pf->ptp_tx_skb);
|
||||
pf->ptp_tx_skb = NULL;
|
||||
clear_bit_unlock(__I40E_PTP_TX_IN_PROGRESS, &pf->state);
|
||||
}
|
||||
|
||||
if (pf->ptp_clock) {
|
||||
ptp_clock_unregister(pf->ptp_clock);
|
||||
pf->ptp_clock = NULL;
|
||||
dev_info(&pf->pdev->dev, "%s: removed PHC on %s\n", __func__,
|
||||
pf->vsi[pf->lan_vsi]->netdev->name);
|
||||
}
|
||||
}
|
3369
drivers/net/ethernet/intel/i40e/i40e_register.h
Normal file
3369
drivers/net/ethernet/intel/i40e/i40e_register.h
Normal file
File diff suppressed because it is too large
Load diff
100
drivers/net/ethernet/intel/i40e/i40e_status.h
Normal file
100
drivers/net/ethernet/intel/i40e/i40e_status.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_STATUS_H_
|
||||
#define _I40E_STATUS_H_
|
||||
|
||||
/* Error Codes */
|
||||
enum i40e_status_code {
|
||||
I40E_SUCCESS = 0,
|
||||
I40E_ERR_NVM = -1,
|
||||
I40E_ERR_NVM_CHECKSUM = -2,
|
||||
I40E_ERR_PHY = -3,
|
||||
I40E_ERR_CONFIG = -4,
|
||||
I40E_ERR_PARAM = -5,
|
||||
I40E_ERR_MAC_TYPE = -6,
|
||||
I40E_ERR_UNKNOWN_PHY = -7,
|
||||
I40E_ERR_LINK_SETUP = -8,
|
||||
I40E_ERR_ADAPTER_STOPPED = -9,
|
||||
I40E_ERR_INVALID_MAC_ADDR = -10,
|
||||
I40E_ERR_DEVICE_NOT_SUPPORTED = -11,
|
||||
I40E_ERR_MASTER_REQUESTS_PENDING = -12,
|
||||
I40E_ERR_INVALID_LINK_SETTINGS = -13,
|
||||
I40E_ERR_AUTONEG_NOT_COMPLETE = -14,
|
||||
I40E_ERR_RESET_FAILED = -15,
|
||||
I40E_ERR_SWFW_SYNC = -16,
|
||||
I40E_ERR_NO_AVAILABLE_VSI = -17,
|
||||
I40E_ERR_NO_MEMORY = -18,
|
||||
I40E_ERR_BAD_PTR = -19,
|
||||
I40E_ERR_RING_FULL = -20,
|
||||
I40E_ERR_INVALID_PD_ID = -21,
|
||||
I40E_ERR_INVALID_QP_ID = -22,
|
||||
I40E_ERR_INVALID_CQ_ID = -23,
|
||||
I40E_ERR_INVALID_CEQ_ID = -24,
|
||||
I40E_ERR_INVALID_AEQ_ID = -25,
|
||||
I40E_ERR_INVALID_SIZE = -26,
|
||||
I40E_ERR_INVALID_ARP_INDEX = -27,
|
||||
I40E_ERR_INVALID_FPM_FUNC_ID = -28,
|
||||
I40E_ERR_QP_INVALID_MSG_SIZE = -29,
|
||||
I40E_ERR_QP_TOOMANY_WRS_POSTED = -30,
|
||||
I40E_ERR_INVALID_FRAG_COUNT = -31,
|
||||
I40E_ERR_QUEUE_EMPTY = -32,
|
||||
I40E_ERR_INVALID_ALIGNMENT = -33,
|
||||
I40E_ERR_FLUSHED_QUEUE = -34,
|
||||
I40E_ERR_INVALID_PUSH_PAGE_INDEX = -35,
|
||||
I40E_ERR_INVALID_IMM_DATA_SIZE = -36,
|
||||
I40E_ERR_TIMEOUT = -37,
|
||||
I40E_ERR_OPCODE_MISMATCH = -38,
|
||||
I40E_ERR_CQP_COMPL_ERROR = -39,
|
||||
I40E_ERR_INVALID_VF_ID = -40,
|
||||
I40E_ERR_INVALID_HMCFN_ID = -41,
|
||||
I40E_ERR_BACKING_PAGE_ERROR = -42,
|
||||
I40E_ERR_NO_PBLCHUNKS_AVAILABLE = -43,
|
||||
I40E_ERR_INVALID_PBLE_INDEX = -44,
|
||||
I40E_ERR_INVALID_SD_INDEX = -45,
|
||||
I40E_ERR_INVALID_PAGE_DESC_INDEX = -46,
|
||||
I40E_ERR_INVALID_SD_TYPE = -47,
|
||||
I40E_ERR_MEMCPY_FAILED = -48,
|
||||
I40E_ERR_INVALID_HMC_OBJ_INDEX = -49,
|
||||
I40E_ERR_INVALID_HMC_OBJ_COUNT = -50,
|
||||
I40E_ERR_INVALID_SRQ_ARM_LIMIT = -51,
|
||||
I40E_ERR_SRQ_ENABLED = -52,
|
||||
I40E_ERR_ADMIN_QUEUE_ERROR = -53,
|
||||
I40E_ERR_ADMIN_QUEUE_TIMEOUT = -54,
|
||||
I40E_ERR_BUF_TOO_SHORT = -55,
|
||||
I40E_ERR_ADMIN_QUEUE_FULL = -56,
|
||||
I40E_ERR_ADMIN_QUEUE_NO_WORK = -57,
|
||||
I40E_ERR_BAD_IWARP_CQE = -58,
|
||||
I40E_ERR_NVM_BLANK_MODE = -59,
|
||||
I40E_ERR_NOT_IMPLEMENTED = -60,
|
||||
I40E_ERR_PE_DOORBELL_NOT_ENABLED = -61,
|
||||
I40E_ERR_DIAG_TEST_FAILED = -62,
|
||||
I40E_ERR_NOT_READY = -63,
|
||||
I40E_NOT_SUPPORTED = -64,
|
||||
I40E_ERR_FIRMWARE_API_VERSION = -65,
|
||||
};
|
||||
|
||||
#endif /* _I40E_STATUS_H_ */
|
2410
drivers/net/ethernet/intel/i40e/i40e_txrx.c
Normal file
2410
drivers/net/ethernet/intel/i40e/i40e_txrx.c
Normal file
File diff suppressed because it is too large
Load diff
303
drivers/net/ethernet/intel/i40e/i40e_txrx.h
Normal file
303
drivers/net/ethernet/intel/i40e/i40e_txrx.h
Normal file
|
@ -0,0 +1,303 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 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_IPV4_UDP) | \
|
||||
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) | \
|
||||
((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_IPV6_UDP) | \
|
||||
((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 8192
|
||||
|
||||
/* 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 + 4)
|
||||
#define I40E_MIN_DESC_PENDING 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_TSYN (u32)(1 << 8)
|
||||
#define I40E_TX_FLAGS_FD_SB (u32)(1 << 9)
|
||||
#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;
|
||||
union {
|
||||
struct sk_buff *skb;
|
||||
void *raw_buf;
|
||||
};
|
||||
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_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_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;
|
||||
|
||||
unsigned long last_rx_timestamp;
|
||||
|
||||
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 i40e_alloc_rx_buffers(struct i40e_ring *rxr, u16 cleaned_count);
|
||||
netdev_tx_t i40e_lan_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
|
||||
void i40e_clean_tx_ring(struct i40e_ring *tx_ring);
|
||||
void i40e_clean_rx_ring(struct i40e_ring *rx_ring);
|
||||
int i40e_setup_tx_descriptors(struct i40e_ring *tx_ring);
|
||||
int i40e_setup_rx_descriptors(struct i40e_ring *rx_ring);
|
||||
void i40e_free_tx_resources(struct i40e_ring *tx_ring);
|
||||
void i40e_free_rx_resources(struct i40e_ring *rx_ring);
|
||||
int i40e_napi_poll(struct napi_struct *napi, int budget);
|
||||
#ifdef I40E_FCOE
|
||||
void i40e_tx_map(struct i40e_ring *tx_ring, struct sk_buff *skb,
|
||||
struct i40e_tx_buffer *first, u32 tx_flags,
|
||||
const u8 hdr_len, u32 td_cmd, u32 td_offset);
|
||||
int i40e_maybe_stop_tx(struct i40e_ring *tx_ring, int size);
|
||||
int i40e_xmit_descriptor_count(struct sk_buff *skb, struct i40e_ring *tx_ring);
|
||||
int i40e_tx_prepare_vlan_flags(struct sk_buff *skb,
|
||||
struct i40e_ring *tx_ring, u32 *flags);
|
||||
#endif
|
||||
#endif /* _I40E_TXRX_H_ */
|
1376
drivers/net/ethernet/intel/i40e/i40e_type.h
Normal file
1376
drivers/net/ethernet/intel/i40e/i40e_type.h
Normal file
File diff suppressed because it is too large
Load diff
363
drivers/net/ethernet/intel/i40e/i40e_virtchnl.h
Normal file
363
drivers/net/ethernet/intel/i40e/i40e_virtchnl.h
Normal file
|
@ -0,0 +1,363 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_VIRTCHNL_H_
|
||||
#define _I40E_VIRTCHNL_H_
|
||||
|
||||
#include "i40e_type.h"
|
||||
|
||||
/* Description:
|
||||
* This header file describes the VF-PF communication protocol used
|
||||
* by the various i40e drivers.
|
||||
*
|
||||
* Admin queue buffer usage:
|
||||
* desc->opcode is always i40e_aqc_opc_send_msg_to_pf
|
||||
* flags, retval, datalen, and data addr are all used normally.
|
||||
* Firmware copies the cookie fields when sending messages between the PF and
|
||||
* VF, but uses all other fields internally. Due to this limitation, we
|
||||
* must send all messages as "indirect", i.e. using an external buffer.
|
||||
*
|
||||
* All the vsi indexes are relative to the VF. Each VF can have maximum of
|
||||
* three VSIs. All the queue indexes are relative to the VSI. Each VF can
|
||||
* have a maximum of sixteen queues for all of its VSIs.
|
||||
*
|
||||
* The PF is required to return a status code in v_retval for all messages
|
||||
* except RESET_VF, which does not require any response. The return value is of
|
||||
* i40e_status_code type, defined in the i40e_type.h.
|
||||
*
|
||||
* In general, VF driver initialization should roughly follow the order of these
|
||||
* opcodes. The VF driver must first validate the API version of the PF driver,
|
||||
* then request a reset, then get resources, then configure queues and
|
||||
* interrupts. After these operations are complete, the VF driver may start
|
||||
* its queues, optionally add MAC and VLAN filters, and process traffic.
|
||||
*/
|
||||
|
||||
/* Opcodes for VF-PF communication. These are placed in the v_opcode field
|
||||
* of the virtchnl_msg structure.
|
||||
*/
|
||||
enum i40e_virtchnl_ops {
|
||||
/* VF sends req. to pf for the following
|
||||
* ops.
|
||||
*/
|
||||
I40E_VIRTCHNL_OP_UNKNOWN = 0,
|
||||
I40E_VIRTCHNL_OP_VERSION = 1, /* must ALWAYS be 1 */
|
||||
I40E_VIRTCHNL_OP_RESET_VF,
|
||||
I40E_VIRTCHNL_OP_GET_VF_RESOURCES,
|
||||
I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE,
|
||||
I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE,
|
||||
I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES,
|
||||
I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP,
|
||||
I40E_VIRTCHNL_OP_ENABLE_QUEUES,
|
||||
I40E_VIRTCHNL_OP_DISABLE_QUEUES,
|
||||
I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS,
|
||||
I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS,
|
||||
I40E_VIRTCHNL_OP_ADD_VLAN,
|
||||
I40E_VIRTCHNL_OP_DEL_VLAN,
|
||||
I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE,
|
||||
I40E_VIRTCHNL_OP_GET_STATS,
|
||||
I40E_VIRTCHNL_OP_FCOE,
|
||||
/* PF sends status change events to vfs using
|
||||
* the following op.
|
||||
*/
|
||||
I40E_VIRTCHNL_OP_EVENT,
|
||||
};
|
||||
|
||||
/* Virtual channel message descriptor. This overlays the admin queue
|
||||
* descriptor. All other data is passed in external buffers.
|
||||
*/
|
||||
|
||||
struct i40e_virtchnl_msg {
|
||||
u8 pad[8]; /* AQ flags/opcode/len/retval fields */
|
||||
enum i40e_virtchnl_ops v_opcode; /* avoid confusion with desc->opcode */
|
||||
i40e_status v_retval; /* ditto for desc->retval */
|
||||
u32 vfid; /* used by PF when sending to VF */
|
||||
};
|
||||
|
||||
/* Message descriptions and data structures.*/
|
||||
|
||||
/* I40E_VIRTCHNL_OP_VERSION
|
||||
* VF posts its version number to the PF. PF responds with its version number
|
||||
* in the same format, along with a return code.
|
||||
* Reply from PF has its major/minor versions also in param0 and param1.
|
||||
* If there is a major version mismatch, then the VF cannot operate.
|
||||
* If there is a minor version mismatch, then the VF can operate but should
|
||||
* add a warning to the system log.
|
||||
*
|
||||
* This enum element MUST always be specified as == 1, regardless of other
|
||||
* changes in the API. The PF must always respond to this message without
|
||||
* error regardless of version mismatch.
|
||||
*/
|
||||
#define I40E_VIRTCHNL_VERSION_MAJOR 1
|
||||
#define I40E_VIRTCHNL_VERSION_MINOR 0
|
||||
struct i40e_virtchnl_version_info {
|
||||
u32 major;
|
||||
u32 minor;
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_RESET_VF
|
||||
* VF sends this request to PF with no parameters
|
||||
* PF does NOT respond! VF driver must delay then poll VFGEN_RSTAT register
|
||||
* until reset completion is indicated. The admin queue must be reinitialized
|
||||
* after this operation.
|
||||
*
|
||||
* When reset is complete, PF must ensure that all queues in all VSIs associated
|
||||
* with the VF are stopped, all queue configurations in the HMC are set to 0,
|
||||
* and all MAC and VLAN filters (except the default MAC address) on all VSIs
|
||||
* are cleared.
|
||||
*/
|
||||
|
||||
/* I40E_VIRTCHNL_OP_GET_VF_RESOURCES
|
||||
* VF sends this request to PF with no parameters
|
||||
* PF responds with an indirect message containing
|
||||
* i40e_virtchnl_vf_resource and one or more
|
||||
* i40e_virtchnl_vsi_resource structures.
|
||||
*/
|
||||
|
||||
struct i40e_virtchnl_vsi_resource {
|
||||
u16 vsi_id;
|
||||
u16 num_queue_pairs;
|
||||
enum i40e_vsi_type vsi_type;
|
||||
u16 qset_handle;
|
||||
u8 default_mac_addr[ETH_ALEN];
|
||||
};
|
||||
/* VF offload flags */
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_L2 0x00000001
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_FCOE 0x00000004
|
||||
#define I40E_VIRTCHNL_VF_OFFLOAD_VLAN 0x00010000
|
||||
|
||||
struct i40e_virtchnl_vf_resource {
|
||||
u16 num_vsis;
|
||||
u16 num_queue_pairs;
|
||||
u16 max_vectors;
|
||||
u16 max_mtu;
|
||||
|
||||
u32 vf_offload_flags;
|
||||
u32 max_fcoe_contexts;
|
||||
u32 max_fcoe_filters;
|
||||
|
||||
struct i40e_virtchnl_vsi_resource vsi_res[1];
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_TX_QUEUE
|
||||
* VF sends this message to set up parameters for one TX queue.
|
||||
* External data buffer contains one instance of i40e_virtchnl_txq_info.
|
||||
* PF configures requested queue and returns a status code.
|
||||
*/
|
||||
|
||||
/* Tx queue config info */
|
||||
struct i40e_virtchnl_txq_info {
|
||||
u16 vsi_id;
|
||||
u16 queue_id;
|
||||
u16 ring_len; /* number of descriptors, multiple of 8 */
|
||||
u16 headwb_enabled;
|
||||
u64 dma_ring_addr;
|
||||
u64 dma_headwb_addr;
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_RX_QUEUE
|
||||
* VF sends this message to set up parameters for one RX queue.
|
||||
* External data buffer contains one instance of i40e_virtchnl_rxq_info.
|
||||
* PF configures requested queue and returns a status code.
|
||||
*/
|
||||
|
||||
/* Rx queue config info */
|
||||
struct i40e_virtchnl_rxq_info {
|
||||
u16 vsi_id;
|
||||
u16 queue_id;
|
||||
u32 ring_len; /* number of descriptors, multiple of 32 */
|
||||
u16 hdr_size;
|
||||
u16 splithdr_enabled;
|
||||
u32 databuffer_size;
|
||||
u32 max_pkt_size;
|
||||
u64 dma_ring_addr;
|
||||
enum i40e_hmc_obj_rx_hsplit_0 rx_split_pos;
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES
|
||||
* VF sends this message to set parameters for all active TX and RX queues
|
||||
* associated with the specified VSI.
|
||||
* PF configures queues and returns status.
|
||||
* If the number of queues specified is greater than the number of queues
|
||||
* associated with the VSI, an error is returned and no queues are configured.
|
||||
*/
|
||||
struct i40e_virtchnl_queue_pair_info {
|
||||
/* NOTE: vsi_id and queue_id should be identical for both queues. */
|
||||
struct i40e_virtchnl_txq_info txq;
|
||||
struct i40e_virtchnl_rxq_info rxq;
|
||||
};
|
||||
|
||||
struct i40e_virtchnl_vsi_queue_config_info {
|
||||
u16 vsi_id;
|
||||
u16 num_queue_pairs;
|
||||
struct i40e_virtchnl_queue_pair_info qpair[1];
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_IRQ_MAP
|
||||
* VF uses this message to map vectors to queues.
|
||||
* The rxq_map and txq_map fields are bitmaps used to indicate which queues
|
||||
* are to be associated with the specified vector.
|
||||
* The "other" causes are always mapped to vector 0.
|
||||
* PF configures interrupt mapping and returns status.
|
||||
*/
|
||||
struct i40e_virtchnl_vector_map {
|
||||
u16 vsi_id;
|
||||
u16 vector_id;
|
||||
u16 rxq_map;
|
||||
u16 txq_map;
|
||||
u16 rxitr_idx;
|
||||
u16 txitr_idx;
|
||||
};
|
||||
|
||||
struct i40e_virtchnl_irq_map_info {
|
||||
u16 num_vectors;
|
||||
struct i40e_virtchnl_vector_map vecmap[1];
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_ENABLE_QUEUES
|
||||
* I40E_VIRTCHNL_OP_DISABLE_QUEUES
|
||||
* VF sends these message to enable or disable TX/RX queue pairs.
|
||||
* The queues fields are bitmaps indicating which queues to act upon.
|
||||
* (Currently, we only support 16 queues per VF, but we make the field
|
||||
* u32 to allow for expansion.)
|
||||
* PF performs requested action and returns status.
|
||||
*/
|
||||
struct i40e_virtchnl_queue_select {
|
||||
u16 vsi_id;
|
||||
u16 pad;
|
||||
u32 rx_queues;
|
||||
u32 tx_queues;
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_ADD_ETHER_ADDRESS
|
||||
* VF sends this message in order to add one or more unicast or multicast
|
||||
* address filters for the specified VSI.
|
||||
* PF adds the filters and returns status.
|
||||
*/
|
||||
|
||||
/* I40E_VIRTCHNL_OP_DEL_ETHER_ADDRESS
|
||||
* VF sends this message in order to remove one or more unicast or multicast
|
||||
* filters for the specified VSI.
|
||||
* PF removes the filters and returns status.
|
||||
*/
|
||||
|
||||
struct i40e_virtchnl_ether_addr {
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 pad[2];
|
||||
};
|
||||
|
||||
struct i40e_virtchnl_ether_addr_list {
|
||||
u16 vsi_id;
|
||||
u16 num_elements;
|
||||
struct i40e_virtchnl_ether_addr list[1];
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_ADD_VLAN
|
||||
* VF sends this message to add one or more VLAN tag filters for receives.
|
||||
* PF adds the filters and returns status.
|
||||
* If a port VLAN is configured by the PF, this operation will return an
|
||||
* error to the VF.
|
||||
*/
|
||||
|
||||
/* I40E_VIRTCHNL_OP_DEL_VLAN
|
||||
* VF sends this message to remove one or more VLAN tag filters for receives.
|
||||
* PF removes the filters and returns status.
|
||||
* If a port VLAN is configured by the PF, this operation will return an
|
||||
* error to the VF.
|
||||
*/
|
||||
|
||||
struct i40e_virtchnl_vlan_filter_list {
|
||||
u16 vsi_id;
|
||||
u16 num_elements;
|
||||
u16 vlan_id[1];
|
||||
};
|
||||
|
||||
/* I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE
|
||||
* VF sends VSI id and flags.
|
||||
* PF returns status code in retval.
|
||||
* Note: we assume that broadcast accept mode is always enabled.
|
||||
*/
|
||||
struct i40e_virtchnl_promisc_info {
|
||||
u16 vsi_id;
|
||||
u16 flags;
|
||||
};
|
||||
|
||||
#define I40E_FLAG_VF_UNICAST_PROMISC 0x00000001
|
||||
#define I40E_FLAG_VF_MULTICAST_PROMISC 0x00000002
|
||||
|
||||
/* I40E_VIRTCHNL_OP_GET_STATS
|
||||
* VF sends this message to request stats for the selected VSI. VF uses
|
||||
* the i40e_virtchnl_queue_select struct to specify the VSI. The queue_id
|
||||
* field is ignored by the PF.
|
||||
*
|
||||
* PF replies with struct i40e_eth_stats in an external buffer.
|
||||
*/
|
||||
|
||||
/* I40E_VIRTCHNL_OP_EVENT
|
||||
* PF sends this message to inform the VF driver of events that may affect it.
|
||||
* No direct response is expected from the VF, though it may generate other
|
||||
* messages in response to this one.
|
||||
*/
|
||||
enum i40e_virtchnl_event_codes {
|
||||
I40E_VIRTCHNL_EVENT_UNKNOWN = 0,
|
||||
I40E_VIRTCHNL_EVENT_LINK_CHANGE,
|
||||
I40E_VIRTCHNL_EVENT_RESET_IMPENDING,
|
||||
I40E_VIRTCHNL_EVENT_PF_DRIVER_CLOSE,
|
||||
};
|
||||
#define I40E_PF_EVENT_SEVERITY_INFO 0
|
||||
#define I40E_PF_EVENT_SEVERITY_CERTAIN_DOOM 255
|
||||
|
||||
struct i40e_virtchnl_pf_event {
|
||||
enum i40e_virtchnl_event_codes event;
|
||||
union {
|
||||
struct {
|
||||
enum i40e_aq_link_speed link_speed;
|
||||
bool link_status;
|
||||
} link_event;
|
||||
} event_data;
|
||||
|
||||
int severity;
|
||||
};
|
||||
|
||||
/* VF reset states - these are written into the RSTAT register:
|
||||
* I40E_VFGEN_RSTAT1 on the PF
|
||||
* I40E_VFGEN_RSTAT on the VF
|
||||
* When the PF initiates a reset, it writes 0
|
||||
* When the reset is complete, it writes 1
|
||||
* When the PF detects that the VF has recovered, it writes 2
|
||||
* VF checks this register periodically to determine if a reset has occurred,
|
||||
* then polls it to know when the reset is complete.
|
||||
* If either the PF or VF reads the register while the hardware
|
||||
* is in a reset state, it will return DEADBEEF, which, when masked
|
||||
* will result in 3.
|
||||
*/
|
||||
enum i40e_vfr_states {
|
||||
I40E_VFR_INPROGRESS = 0,
|
||||
I40E_VFR_COMPLETED,
|
||||
I40E_VFR_VFACTIVE,
|
||||
I40E_VFR_UNKNOWN,
|
||||
};
|
||||
|
||||
#endif /* _I40E_VIRTCHNL_H_ */
|
2433
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
Normal file
2433
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
Normal file
File diff suppressed because it is too large
Load diff
130
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
Normal file
130
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*******************************************************************************
|
||||
*
|
||||
* Intel Ethernet Controller XL710 Family Linux Driver
|
||||
* Copyright(c) 2013 - 2014 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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_VIRTCHNL_PF_H_
|
||||
#define _I40E_VIRTCHNL_PF_H_
|
||||
|
||||
#include "i40e.h"
|
||||
|
||||
#define I40E_MAX_MACVLAN_FILTERS 256
|
||||
#define I40E_MAX_VLAN_FILTERS 256
|
||||
#define I40E_MAX_VLANID 4095
|
||||
|
||||
#define I40E_VIRTCHNL_SUPPORTED_QTYPES 2
|
||||
|
||||
#define I40E_DEFAULT_NUM_MDD_EVENTS_ALLOWED 3
|
||||
#define I40E_DEFAULT_NUM_INVALID_MSGS_ALLOWED 10
|
||||
|
||||
#define I40E_VLAN_PRIORITY_SHIFT 12
|
||||
#define I40E_VLAN_MASK 0xFFF
|
||||
#define I40E_PRIORITY_MASK 0x7000
|
||||
|
||||
/* Various queue ctrls */
|
||||
enum i40e_queue_ctrl {
|
||||
I40E_QUEUE_CTRL_UNKNOWN = 0,
|
||||
I40E_QUEUE_CTRL_ENABLE,
|
||||
I40E_QUEUE_CTRL_ENABLECHECK,
|
||||
I40E_QUEUE_CTRL_DISABLE,
|
||||
I40E_QUEUE_CTRL_DISABLECHECK,
|
||||
I40E_QUEUE_CTRL_FASTDISABLE,
|
||||
I40E_QUEUE_CTRL_FASTDISABLECHECK,
|
||||
};
|
||||
|
||||
/* VF states */
|
||||
enum i40e_vf_states {
|
||||
I40E_VF_STAT_INIT = 0,
|
||||
I40E_VF_STAT_ACTIVE,
|
||||
I40E_VF_STAT_FCOEENA,
|
||||
I40E_VF_STAT_DISABLED,
|
||||
};
|
||||
|
||||
/* VF capabilities */
|
||||
enum i40e_vf_capabilities {
|
||||
I40E_VIRTCHNL_VF_CAP_PRIVILEGE = 0,
|
||||
I40E_VIRTCHNL_VF_CAP_L2,
|
||||
};
|
||||
|
||||
/* VF information structure */
|
||||
struct i40e_vf {
|
||||
struct i40e_pf *pf;
|
||||
|
||||
/* vf id in the pf space */
|
||||
u16 vf_id;
|
||||
/* all vf vsis connect to the same parent */
|
||||
enum i40e_switch_element_types parent_type;
|
||||
|
||||
/* vf Port Extender (PE) stag if used */
|
||||
u16 stag;
|
||||
|
||||
struct i40e_virtchnl_ether_addr default_lan_addr;
|
||||
struct i40e_virtchnl_ether_addr default_fcoe_addr;
|
||||
u16 port_vlan_id;
|
||||
bool pf_set_mac; /* The VMM admin set the VF MAC address */
|
||||
|
||||
/* VSI indices - actual VSI pointers are maintained in the PF structure
|
||||
* When assigned, these will be non-zero, because VSI 0 is always
|
||||
* the main LAN VSI for the PF.
|
||||
*/
|
||||
u8 lan_vsi_index; /* index into PF struct */
|
||||
u8 lan_vsi_id; /* ID as used by firmware */
|
||||
|
||||
u8 num_queue_pairs; /* num of qps assigned to vf vsis */
|
||||
u64 num_mdd_events; /* num of mdd events detected */
|
||||
u64 num_invalid_msgs; /* num of malformed or invalid msgs detected */
|
||||
u64 num_valid_msgs; /* num of valid msgs detected */
|
||||
|
||||
unsigned long vf_caps; /* vf's adv. capabilities */
|
||||
unsigned long vf_states; /* vf's runtime states */
|
||||
unsigned int tx_rate; /* Tx bandwidth limit in Mbps */
|
||||
bool link_forced;
|
||||
bool link_up; /* only valid if vf link is forced */
|
||||
bool spoofchk;
|
||||
};
|
||||
|
||||
void i40e_free_vfs(struct i40e_pf *pf);
|
||||
int i40e_pci_sriov_configure(struct pci_dev *dev, int num_vfs);
|
||||
int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs);
|
||||
int i40e_vc_process_vf_msg(struct i40e_pf *pf, u16 vf_id, u32 v_opcode,
|
||||
u32 v_retval, u8 *msg, u16 msglen);
|
||||
int i40e_vc_process_vflr_event(struct i40e_pf *pf);
|
||||
void i40e_reset_vf(struct i40e_vf *vf, bool flr);
|
||||
void i40e_vc_notify_vf_reset(struct i40e_vf *vf);
|
||||
|
||||
/* vf configuration related iplink handlers */
|
||||
int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac);
|
||||
int i40e_ndo_set_vf_port_vlan(struct net_device *netdev,
|
||||
int vf_id, u16 vlan_id, u8 qos);
|
||||
int i40e_ndo_set_vf_bw(struct net_device *netdev, int vf_id, int min_tx_rate,
|
||||
int max_tx_rate);
|
||||
int i40e_ndo_get_vf_config(struct net_device *netdev,
|
||||
int vf_id, struct ifla_vf_info *ivi);
|
||||
int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link);
|
||||
int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable);
|
||||
|
||||
void i40e_vc_notify_link_state(struct i40e_pf *pf);
|
||||
void i40e_vc_notify_reset(struct i40e_pf *pf);
|
||||
|
||||
#endif /* _I40E_VIRTCHNL_PF_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue