Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
# Copyright(c) 2009 - 2018 Intel Corporation.
#
# Makefile for the Intel(R) 82576 VF ethernet driver
#
obj-$(CONFIG_IGBVF) += igbvf.o
igbvf-y := vf.o mbx.o ethtool.o netdev.o
@@ -0,0 +1,98 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 1999 - 2018 Intel Corporation. */
#ifndef _E1000_DEFINES_H_
#define _E1000_DEFINES_H_
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
#define REQ_TX_DESCRIPTOR_MULTIPLE 8
#define REQ_RX_DESCRIPTOR_MULTIPLE 8
/* IVAR valid bit */
#define E1000_IVAR_VALID 0x80
/* Receive Descriptor bit definitions */
#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */
#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
#define E1000_RXDEXT_STATERR_LB 0x00040000
#define E1000_RXDEXT_STATERR_CE 0x01000000
#define E1000_RXDEXT_STATERR_SE 0x02000000
#define E1000_RXDEXT_STATERR_SEQ 0x04000000
#define E1000_RXDEXT_STATERR_CXE 0x10000000
#define E1000_RXDEXT_STATERR_TCPE 0x20000000
#define E1000_RXDEXT_STATERR_IPE 0x40000000
#define E1000_RXDEXT_STATERR_RXE 0x80000000
/* Same mask, but for extended and packet split descriptors */
#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
E1000_RXDEXT_STATERR_CE | \
E1000_RXDEXT_STATERR_SE | \
E1000_RXDEXT_STATERR_SEQ | \
E1000_RXDEXT_STATERR_CXE | \
E1000_RXDEXT_STATERR_RXE)
/* Device Control */
#define E1000_CTRL_RST 0x04000000 /* Global reset */
/* Device Status */
#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */
#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */
#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
#define SPEED_10 10
#define SPEED_100 100
#define SPEED_1000 1000
#define HALF_DUPLEX 1
#define FULL_DUPLEX 2
/* Transmit Descriptor bit definitions */
#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
#define E1000_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */
#define E1000_TXD_STAT_DD 0x00000001 /* Desc Done */
#define MAX_JUMBO_FRAME_SIZE 0x3F00
#define MAX_STD_JUMBO_FRAME_SIZE 9216
/* 802.1q VLAN Packet Size */
#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMA'd) */
/* Error Codes */
#define E1000_SUCCESS 0
#define E1000_ERR_CONFIG 3
#define E1000_ERR_MAC_INIT 5
#define E1000_ERR_MBX 15
/* SRRCTL bit definitions */
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
#define E1000_SRRCTL_BSIZEHDRSIZE_MASK 0x00000F00
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
#define E1000_SRRCTL_DROP_EN 0x80000000
#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
/* Additional Descriptor Control definitions */
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Que */
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Que */
/* Direct Cache Access (DCA) definitions */
#define E1000_DCA_TXCTRL_TX_WB_RO_EN BIT(11) /* Tx Desc writeback RO bit */
#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
#endif /* _E1000_DEFINES_H_ */
@@ -0,0 +1,465 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2009 - 2018 Intel Corporation. */
/* ethtool support for igbvf */
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include "igbvf.h"
#include <linux/if_vlan.h>
struct igbvf_stats {
char stat_string[ETH_GSTRING_LEN];
int sizeof_stat;
int stat_offset;
int base_stat_offset;
};
#define IGBVF_STAT(current, base) \
sizeof(((struct igbvf_adapter *)0)->current), \
offsetof(struct igbvf_adapter, current), \
offsetof(struct igbvf_adapter, base)
static const struct igbvf_stats igbvf_gstrings_stats[] = {
{ "rx_packets", IGBVF_STAT(stats.gprc, stats.base_gprc) },
{ "tx_packets", IGBVF_STAT(stats.gptc, stats.base_gptc) },
{ "rx_bytes", IGBVF_STAT(stats.gorc, stats.base_gorc) },
{ "tx_bytes", IGBVF_STAT(stats.gotc, stats.base_gotc) },
{ "multicast", IGBVF_STAT(stats.mprc, stats.base_mprc) },
{ "lbrx_packets", IGBVF_STAT(stats.gprlbc, stats.base_gprlbc) },
{ "lbtx_packets", IGBVF_STAT(stats.gptlbc, stats.base_gptlbc) },
{ "lbrx_bytes", IGBVF_STAT(stats.gorlbc, stats.base_gorlbc) },
{ "lbtx_bytes", IGBVF_STAT(stats.gotlbc, stats.base_gotlbc) },
{ "tx_restart_queue", IGBVF_STAT(restart_queue, zero_base) },
{ "tx_timeout_count", IGBVF_STAT(tx_timeout_count, zero_base) },
{ "rx_csum_offload_good", IGBVF_STAT(hw_csum_good, zero_base) },
{ "rx_csum_offload_errors", IGBVF_STAT(hw_csum_err, zero_base) },
{ "rx_header_split", IGBVF_STAT(rx_hdr_split, zero_base) },
{ "alloc_rx_buff_failed", IGBVF_STAT(alloc_rx_buff_failed, zero_base) },
};
#define IGBVF_GLOBAL_STATS_LEN ARRAY_SIZE(igbvf_gstrings_stats)
static const char igbvf_gstrings_test[][ETH_GSTRING_LEN] = {
"Link test (on/offline)"
};
#define IGBVF_TEST_LEN ARRAY_SIZE(igbvf_gstrings_test)
static int igbvf_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
u32 status;
ethtool_link_ksettings_zero_link_mode(cmd, supported);
ethtool_link_ksettings_add_link_mode(cmd, supported, 1000baseT_Full);
ethtool_link_ksettings_zero_link_mode(cmd, advertising);
ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Full);
cmd->base.port = -1;
status = er32(STATUS);
if (status & E1000_STATUS_LU) {
if (status & E1000_STATUS_SPEED_1000)
cmd->base.speed = SPEED_1000;
else if (status & E1000_STATUS_SPEED_100)
cmd->base.speed = SPEED_100;
else
cmd->base.speed = SPEED_10;
if (status & E1000_STATUS_FD)
cmd->base.duplex = DUPLEX_FULL;
else
cmd->base.duplex = DUPLEX_HALF;
} else {
cmd->base.speed = SPEED_UNKNOWN;
cmd->base.duplex = DUPLEX_UNKNOWN;
}
cmd->base.autoneg = AUTONEG_DISABLE;
return 0;
}
static int igbvf_set_link_ksettings(struct net_device *netdev,
const struct ethtool_link_ksettings *cmd)
{
return -EOPNOTSUPP;
}
static void igbvf_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
}
static int igbvf_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
return -EOPNOTSUPP;
}
static u32 igbvf_get_msglevel(struct net_device *netdev)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
return adapter->msg_enable;
}
static void igbvf_set_msglevel(struct net_device *netdev, u32 data)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
adapter->msg_enable = data;
}
static int igbvf_get_regs_len(struct net_device *netdev)
{
#define IGBVF_REGS_LEN 8
return IGBVF_REGS_LEN * sizeof(u32);
}
static void igbvf_get_regs(struct net_device *netdev,
struct ethtool_regs *regs, void *p)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
u32 *regs_buff = p;
memset(p, 0, IGBVF_REGS_LEN * sizeof(u32));
regs->version = (1u << 24) |
(adapter->pdev->revision << 16) |
adapter->pdev->device;
regs_buff[0] = er32(CTRL);
regs_buff[1] = er32(STATUS);
regs_buff[2] = er32(RDLEN(0));
regs_buff[3] = er32(RDH(0));
regs_buff[4] = er32(RDT(0));
regs_buff[5] = er32(TDLEN(0));
regs_buff[6] = er32(TDH(0));
regs_buff[7] = er32(TDT(0));
}
static int igbvf_get_eeprom_len(struct net_device *netdev)
{
return 0;
}
static int igbvf_get_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, u8 *bytes)
{
return -EOPNOTSUPP;
}
static int igbvf_set_eeprom(struct net_device *netdev,
struct ethtool_eeprom *eeprom, u8 *bytes)
{
return -EOPNOTSUPP;
}
static void igbvf_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
strscpy(drvinfo->driver, igbvf_driver_name, sizeof(drvinfo->driver));
strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info));
}
static void igbvf_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
struct igbvf_ring *tx_ring = adapter->tx_ring;
struct igbvf_ring *rx_ring = adapter->rx_ring;
ring->rx_max_pending = IGBVF_MAX_RXD;
ring->tx_max_pending = IGBVF_MAX_TXD;
ring->rx_pending = rx_ring->count;
ring->tx_pending = tx_ring->count;
}
static int igbvf_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
struct igbvf_ring *temp_ring;
int err = 0;
u32 new_rx_count, new_tx_count;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
new_rx_count = max_t(u32, ring->rx_pending, IGBVF_MIN_RXD);
new_rx_count = min_t(u32, new_rx_count, IGBVF_MAX_RXD);
new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
new_tx_count = max_t(u32, ring->tx_pending, IGBVF_MIN_TXD);
new_tx_count = min_t(u32, new_tx_count, IGBVF_MAX_TXD);
new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
if ((new_tx_count == adapter->tx_ring->count) &&
(new_rx_count == adapter->rx_ring->count)) {
/* nothing to do */
return 0;
}
while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
usleep_range(1000, 2000);
if (!netif_running(adapter->netdev)) {
adapter->tx_ring->count = new_tx_count;
adapter->rx_ring->count = new_rx_count;
goto clear_reset;
}
temp_ring = vmalloc(sizeof(struct igbvf_ring));
if (!temp_ring) {
err = -ENOMEM;
goto clear_reset;
}
igbvf_down(adapter);
/* We can't just free everything and then setup again,
* because the ISRs in MSI-X mode get passed pointers
* to the Tx and Rx ring structs.
*/
if (new_tx_count != adapter->tx_ring->count) {
memcpy(temp_ring, adapter->tx_ring, sizeof(struct igbvf_ring));
temp_ring->count = new_tx_count;
err = igbvf_setup_tx_resources(adapter, temp_ring);
if (err)
goto err_setup;
igbvf_free_tx_resources(adapter->tx_ring);
memcpy(adapter->tx_ring, temp_ring, sizeof(struct igbvf_ring));
}
if (new_rx_count != adapter->rx_ring->count) {
memcpy(temp_ring, adapter->rx_ring, sizeof(struct igbvf_ring));
temp_ring->count = new_rx_count;
err = igbvf_setup_rx_resources(adapter, temp_ring);
if (err)
goto err_setup;
igbvf_free_rx_resources(adapter->rx_ring);
memcpy(adapter->rx_ring, temp_ring, sizeof(struct igbvf_ring));
}
err_setup:
igbvf_up(adapter);
vfree(temp_ring);
clear_reset:
clear_bit(__IGBVF_RESETTING, &adapter->state);
return err;
}
static int igbvf_link_test(struct igbvf_adapter *adapter, u64 *data)
{
struct e1000_hw *hw = &adapter->hw;
*data = 0;
spin_lock_bh(&hw->mbx_lock);
hw->mac.ops.check_for_link(hw);
spin_unlock_bh(&hw->mbx_lock);
if (!(er32(STATUS) & E1000_STATUS_LU))
*data = 1;
return *data;
}
static void igbvf_diag_test(struct net_device *netdev,
struct ethtool_test *eth_test, u64 *data)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
set_bit(__IGBVF_TESTING, &adapter->state);
/* Link test performed before hardware reset so autoneg doesn't
* interfere with test result
*/
if (igbvf_link_test(adapter, &data[0]))
eth_test->flags |= ETH_TEST_FL_FAILED;
clear_bit(__IGBVF_TESTING, &adapter->state);
msleep_interruptible(4 * 1000);
}
static void igbvf_get_wol(struct net_device *netdev,
struct ethtool_wolinfo *wol)
{
wol->supported = 0;
wol->wolopts = 0;
}
static int igbvf_set_wol(struct net_device *netdev,
struct ethtool_wolinfo *wol)
{
return -EOPNOTSUPP;
}
static int igbvf_get_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec,
struct kernel_ethtool_coalesce *kernel_coal,
struct netlink_ext_ack *extack)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
if (adapter->requested_itr <= 3)
ec->rx_coalesce_usecs = adapter->requested_itr;
else
ec->rx_coalesce_usecs = adapter->current_itr >> 2;
return 0;
}
static int igbvf_set_coalesce(struct net_device *netdev,
struct ethtool_coalesce *ec,
struct kernel_ethtool_coalesce *kernel_coal,
struct netlink_ext_ack *extack)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
if ((ec->rx_coalesce_usecs >= IGBVF_MIN_ITR_USECS) &&
(ec->rx_coalesce_usecs <= IGBVF_MAX_ITR_USECS)) {
adapter->current_itr = ec->rx_coalesce_usecs << 2;
adapter->requested_itr = 1000000000 /
(adapter->current_itr * 256);
} else if ((ec->rx_coalesce_usecs == 3) ||
(ec->rx_coalesce_usecs == 2)) {
adapter->current_itr = IGBVF_START_ITR;
adapter->requested_itr = ec->rx_coalesce_usecs;
} else if (ec->rx_coalesce_usecs == 0) {
/* The user's desire is to turn off interrupt throttling
* altogether, but due to HW limitations, we can't do that.
* Instead we set a very small value in EITR, which would
* allow ~967k interrupts per second, but allow the adapter's
* internal clocking to still function properly.
*/
adapter->current_itr = 4;
adapter->requested_itr = 1000000000 /
(adapter->current_itr * 256);
} else {
return -EINVAL;
}
writel(adapter->current_itr,
hw->hw_addr + adapter->rx_ring->itr_register);
return 0;
}
static int igbvf_nway_reset(struct net_device *netdev)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
if (netif_running(netdev))
igbvf_reinit_locked(adapter);
return 0;
}
static void igbvf_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats,
u64 *data)
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
int i;
igbvf_update_stats(adapter);
for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
char *p = (char *)adapter +
igbvf_gstrings_stats[i].stat_offset;
char *b = (char *)adapter +
igbvf_gstrings_stats[i].base_stat_offset;
data[i] = ((igbvf_gstrings_stats[i].sizeof_stat ==
sizeof(u64)) ? (*(u64 *)p - *(u64 *)b) :
(*(u32 *)p - *(u32 *)b));
}
}
static int igbvf_get_sset_count(struct net_device *dev, int stringset)
{
switch (stringset) {
case ETH_SS_TEST:
return IGBVF_TEST_LEN;
case ETH_SS_STATS:
return IGBVF_GLOBAL_STATS_LEN;
default:
return -EINVAL;
}
}
static void igbvf_get_strings(struct net_device *netdev, u32 stringset,
u8 *data)
{
u8 *p = data;
int i;
switch (stringset) {
case ETH_SS_TEST:
memcpy(data, *igbvf_gstrings_test, sizeof(igbvf_gstrings_test));
break;
case ETH_SS_STATS:
for (i = 0; i < IGBVF_GLOBAL_STATS_LEN; i++) {
memcpy(p, igbvf_gstrings_stats[i].stat_string,
ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
break;
}
}
static const struct ethtool_ops igbvf_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS,
.get_drvinfo = igbvf_get_drvinfo,
.get_regs_len = igbvf_get_regs_len,
.get_regs = igbvf_get_regs,
.get_wol = igbvf_get_wol,
.set_wol = igbvf_set_wol,
.get_msglevel = igbvf_get_msglevel,
.set_msglevel = igbvf_set_msglevel,
.nway_reset = igbvf_nway_reset,
.get_link = ethtool_op_get_link,
.get_eeprom_len = igbvf_get_eeprom_len,
.get_eeprom = igbvf_get_eeprom,
.set_eeprom = igbvf_set_eeprom,
.get_ringparam = igbvf_get_ringparam,
.set_ringparam = igbvf_set_ringparam,
.get_pauseparam = igbvf_get_pauseparam,
.set_pauseparam = igbvf_set_pauseparam,
.self_test = igbvf_diag_test,
.get_sset_count = igbvf_get_sset_count,
.get_strings = igbvf_get_strings,
.get_ethtool_stats = igbvf_get_ethtool_stats,
.get_coalesce = igbvf_get_coalesce,
.set_coalesce = igbvf_set_coalesce,
.get_link_ksettings = igbvf_get_link_ksettings,
.set_link_ksettings = igbvf_set_link_ksettings,
};
void igbvf_set_ethtool_ops(struct net_device *netdev)
{
netdev->ethtool_ops = &igbvf_ethtool_ops;
}
@@ -0,0 +1,268 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2009 - 2018 Intel Corporation. */
/* Linux PRO/1000 Ethernet Driver main header file */
#ifndef _IGBVF_H_
#define _IGBVF_H_
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/io.h>
#include <linux/netdevice.h>
#include <linux/if_vlan.h>
#include "vf.h"
/* Forward declarations */
struct igbvf_info;
struct igbvf_adapter;
/* Interrupt defines */
#define IGBVF_START_ITR 488 /* ~8000 ints/sec */
#define IGBVF_4K_ITR 980
#define IGBVF_20K_ITR 196
#define IGBVF_70K_ITR 56
enum latency_range {
lowest_latency = 0,
low_latency = 1,
bulk_latency = 2,
latency_invalid = 255
};
/* Interrupt modes, as used by the IntMode parameter */
#define IGBVF_INT_MODE_LEGACY 0
#define IGBVF_INT_MODE_MSI 1
#define IGBVF_INT_MODE_MSIX 2
/* Tx/Rx descriptor defines */
#define IGBVF_DEFAULT_TXD 256
#define IGBVF_MAX_TXD 4096
#define IGBVF_MIN_TXD 64
#define IGBVF_DEFAULT_RXD 256
#define IGBVF_MAX_RXD 4096
#define IGBVF_MIN_RXD 64
#define IGBVF_MIN_ITR_USECS 10 /* 100000 irq/sec */
#define IGBVF_MAX_ITR_USECS 10000 /* 100 irq/sec */
/* RX descriptor control thresholds.
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
* descriptors available in its onboard memory.
* Setting this to 0 disables RX descriptor prefetch.
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
* available in host memory.
* If PTHRESH is 0, this should also be 0.
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
* descriptors until either it has this many to write back, or the
* ITR timer expires.
*/
#define IGBVF_RX_PTHRESH 16
#define IGBVF_RX_HTHRESH 8
#define IGBVF_RX_WTHRESH 1
/* this is the size past which hardware will drop packets when setting LPE=0 */
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
#define IGBVF_FC_PAUSE_TIME 0x0680 /* 858 usec */
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
#define IGBVF_TX_QUEUE_WAKE 32
/* How many Rx Buffers do we bundle into one write to the hardware ? */
#define IGBVF_RX_BUFFER_WRITE 16 /* Must be power of 2 */
#define AUTO_ALL_MODES 0
#define IGBVF_EEPROM_APME 0x0400
#define IGBVF_MNG_VLAN_NONE (-1)
#define IGBVF_MAX_MAC_FILTERS 3
/* Number of packet split data buffers (not including the header buffer) */
#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1)
enum igbvf_boards {
board_vf,
board_i350_vf,
};
struct igbvf_queue_stats {
u64 packets;
u64 bytes;
};
/* wrappers around a pointer to a socket buffer,
* so a DMA handle can be stored along with the buffer
*/
struct igbvf_buffer {
dma_addr_t dma;
struct sk_buff *skb;
union {
/* Tx */
struct {
unsigned long time_stamp;
union e1000_adv_tx_desc *next_to_watch;
u16 length;
u16 mapped_as_page;
};
/* Rx */
struct {
struct page *page;
u64 page_dma;
unsigned int page_offset;
};
};
};
union igbvf_desc {
union e1000_adv_rx_desc rx_desc;
union e1000_adv_tx_desc tx_desc;
struct e1000_adv_tx_context_desc tx_context_desc;
};
struct igbvf_ring {
struct igbvf_adapter *adapter; /* backlink */
union igbvf_desc *desc; /* pointer to ring memory */
dma_addr_t dma; /* phys address of ring */
unsigned int size; /* length of ring in bytes */
unsigned int count; /* number of desc. in ring */
u16 next_to_use;
u16 next_to_clean;
u16 head;
u16 tail;
/* array of buffer information structs */
struct igbvf_buffer *buffer_info;
struct napi_struct napi;
char name[IFNAMSIZ + 5];
u32 eims_value;
u32 itr_val;
enum latency_range itr_range;
u16 itr_register;
int set_itr;
struct sk_buff *rx_skb_top;
struct igbvf_queue_stats stats;
};
/* board specific private data structure */
struct igbvf_adapter {
struct timer_list watchdog_timer;
struct work_struct reset_task;
struct work_struct watchdog_task;
const struct igbvf_info *ei;
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u32 rx_buffer_len;
u16 link_speed;
u16 link_duplex;
/* track device up/down/testing state */
unsigned long state;
/* Interrupt Throttle Rate */
u32 requested_itr; /* ints/sec or adaptive */
u32 current_itr; /* Actual ITR register value, not ints/sec */
/* Tx */
struct igbvf_ring *tx_ring /* One per active queue */
____cacheline_aligned_in_smp;
unsigned int restart_queue;
u32 txd_cmd;
unsigned int total_tx_bytes;
unsigned int total_tx_packets;
unsigned int total_rx_bytes;
unsigned int total_rx_packets;
/* Tx stats */
u32 tx_timeout_count;
/* Rx */
struct igbvf_ring *rx_ring;
/* Rx stats */
u64 hw_csum_err;
u64 hw_csum_good;
u64 rx_hdr_split;
u32 alloc_rx_buff_failed;
unsigned int rx_ps_hdr_size;
u32 max_frame_size;
u32 min_frame_size;
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
/* structs defined in e1000_hw.h */
struct e1000_hw hw;
/* The VF counters don't clear on read so we have to get a base
* count on driver start up and always subtract that base on
* the first update, thus the flag..
*/
struct e1000_vf_stats stats;
u64 zero_base;
u32 msg_enable;
struct msix_entry *msix_entries;
u32 eims_enable_mask;
u32 eims_other;
u32 wol;
u32 pba;
unsigned int flags;
unsigned long last_reset;
};
struct igbvf_info {
enum e1000_mac_type mac;
unsigned int flags;
u32 pba;
void (*init_ops)(struct e1000_hw *);
s32 (*get_variants)(struct igbvf_adapter *);
};
/* hardware capability, feature, and workaround flags */
#define IGBVF_FLAG_RX_CSUM_DISABLED BIT(0)
#define IGBVF_FLAG_RX_LB_VLAN_BSWAP BIT(1)
#define IGBVF_RX_DESC_ADV(R, i) \
(&((((R).desc))[i].rx_desc))
#define IGBVF_TX_DESC_ADV(R, i) \
(&((((R).desc))[i].tx_desc))
#define IGBVF_TX_CTXTDESC_ADV(R, i) \
(&((((R).desc))[i].tx_context_desc))
enum igbvf_state_t {
__IGBVF_TESTING,
__IGBVF_RESETTING,
__IGBVF_DOWN
};
extern char igbvf_driver_name[];
void igbvf_set_ethtool_ops(struct net_device *);
int igbvf_up(struct igbvf_adapter *);
void igbvf_down(struct igbvf_adapter *);
void igbvf_reinit_locked(struct igbvf_adapter *);
int igbvf_setup_rx_resources(struct igbvf_adapter *, struct igbvf_ring *);
int igbvf_setup_tx_resources(struct igbvf_adapter *, struct igbvf_ring *);
void igbvf_free_rx_resources(struct igbvf_ring *);
void igbvf_free_tx_resources(struct igbvf_ring *);
void igbvf_update_stats(struct igbvf_adapter *);
extern unsigned int copybreak;
#endif /* _IGBVF_H_ */
@@ -0,0 +1,337 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2009 - 2018 Intel Corporation. */
#include <linux/bitfield.h>
#include "mbx.h"
/**
* e1000_poll_for_msg - Wait for message notification
* @hw: pointer to the HW structure
*
* returns SUCCESS if it successfully received a message notification
**/
static s32 e1000_poll_for_msg(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
int countdown = mbx->timeout;
if (!mbx->ops.check_for_msg)
goto out;
while (countdown && mbx->ops.check_for_msg(hw)) {
countdown--;
udelay(mbx->usec_delay);
}
/* if we failed, all future posted messages fail until reset */
if (!countdown)
mbx->timeout = 0;
out:
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
}
/**
* e1000_poll_for_ack - Wait for message acknowledgment
* @hw: pointer to the HW structure
*
* returns SUCCESS if it successfully received a message acknowledgment
**/
static s32 e1000_poll_for_ack(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
int countdown = mbx->timeout;
if (!mbx->ops.check_for_ack)
goto out;
while (countdown && mbx->ops.check_for_ack(hw)) {
countdown--;
udelay(mbx->usec_delay);
}
/* if we failed, all future posted messages fail until reset */
if (!countdown)
mbx->timeout = 0;
out:
return countdown ? E1000_SUCCESS : -E1000_ERR_MBX;
}
/**
* e1000_read_posted_mbx - Wait for message notification and receive message
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
*
* returns SUCCESS if it successfully received a message notification and
* copied it into the receive buffer.
**/
static s32 e1000_read_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX;
if (!mbx->ops.read)
goto out;
ret_val = e1000_poll_for_msg(hw);
/* if ack received read message, otherwise we timed out */
if (!ret_val)
ret_val = mbx->ops.read(hw, msg, size);
out:
return ret_val;
}
/**
* e1000_write_posted_mbx - Write a message to the mailbox, wait for ack
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
*
* returns SUCCESS if it successfully copied message into the buffer and
* received an ack to that message within delay * timeout period
**/
static s32 e1000_write_posted_mbx(struct e1000_hw *hw, u32 *msg, u16 size)
{
struct e1000_mbx_info *mbx = &hw->mbx;
s32 ret_val = -E1000_ERR_MBX;
/* exit if we either can't write or there isn't a defined timeout */
if (!mbx->ops.write || !mbx->timeout)
goto out;
/* send msg*/
ret_val = mbx->ops.write(hw, msg, size);
/* if msg sent wait until we receive an ack */
if (!ret_val)
ret_val = e1000_poll_for_ack(hw);
out:
return ret_val;
}
/**
* e1000_read_v2p_mailbox - read v2p mailbox
* @hw: pointer to the HW structure
*
* This function is used to read the v2p mailbox without losing the read to
* clear status bits.
**/
static u32 e1000_read_v2p_mailbox(struct e1000_hw *hw)
{
u32 v2p_mailbox = er32(V2PMAILBOX(0));
v2p_mailbox |= hw->dev_spec.vf.v2p_mailbox;
hw->dev_spec.vf.v2p_mailbox |= v2p_mailbox & E1000_V2PMAILBOX_R2C_BITS;
return v2p_mailbox;
}
/**
* e1000_check_for_bit_vf - Determine if a status bit was set
* @hw: pointer to the HW structure
* @mask: bitmask for bits to be tested and cleared
*
* This function is used to check for the read to clear bits within
* the V2P mailbox.
**/
static s32 e1000_check_for_bit_vf(struct e1000_hw *hw, u32 mask)
{
u32 v2p_mailbox = e1000_read_v2p_mailbox(hw);
s32 ret_val = -E1000_ERR_MBX;
if (v2p_mailbox & mask)
ret_val = E1000_SUCCESS;
hw->dev_spec.vf.v2p_mailbox &= ~mask;
return ret_val;
}
/**
* e1000_check_for_msg_vf - checks to see if the PF has sent mail
* @hw: pointer to the HW structure
*
* returns SUCCESS if the PF has set the Status bit or else ERR_MBX
**/
static s32 e1000_check_for_msg_vf(struct e1000_hw *hw)
{
s32 ret_val = -E1000_ERR_MBX;
if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFSTS)) {
ret_val = E1000_SUCCESS;
hw->mbx.stats.reqs++;
}
return ret_val;
}
/**
* e1000_check_for_ack_vf - checks to see if the PF has ACK'd
* @hw: pointer to the HW structure
*
* returns SUCCESS if the PF has set the ACK bit or else ERR_MBX
**/
static s32 e1000_check_for_ack_vf(struct e1000_hw *hw)
{
s32 ret_val = -E1000_ERR_MBX;
if (!e1000_check_for_bit_vf(hw, E1000_V2PMAILBOX_PFACK)) {
ret_val = E1000_SUCCESS;
hw->mbx.stats.acks++;
}
return ret_val;
}
/**
* e1000_check_for_rst_vf - checks to see if the PF has reset
* @hw: pointer to the HW structure
*
* returns true if the PF has set the reset done bit or else false
**/
static s32 e1000_check_for_rst_vf(struct e1000_hw *hw)
{
s32 ret_val = -E1000_ERR_MBX;
if (!e1000_check_for_bit_vf(hw, (E1000_V2PMAILBOX_RSTD |
E1000_V2PMAILBOX_RSTI))) {
ret_val = E1000_SUCCESS;
hw->mbx.stats.rsts++;
}
return ret_val;
}
/**
* e1000_obtain_mbx_lock_vf - obtain mailbox lock
* @hw: pointer to the HW structure
*
* return SUCCESS if we obtained the mailbox lock
**/
static s32 e1000_obtain_mbx_lock_vf(struct e1000_hw *hw)
{
s32 ret_val = -E1000_ERR_MBX;
int count = 10;
do {
/* Take ownership of the buffer */
ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_VFU);
/* reserve mailbox for VF use */
if (e1000_read_v2p_mailbox(hw) & E1000_V2PMAILBOX_VFU) {
ret_val = 0;
break;
}
udelay(1000);
} while (count-- > 0);
return ret_val;
}
/**
* e1000_write_mbx_vf - Write a message to the mailbox
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
*
* returns SUCCESS if it successfully copied message into the buffer
**/
static s32 e1000_write_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
{
s32 err;
u16 i;
lockdep_assert_held(&hw->mbx_lock);
/* lock the mailbox to prevent pf/vf race condition */
err = e1000_obtain_mbx_lock_vf(hw);
if (err)
goto out_no_write;
/* flush any ack or msg as we are going to overwrite mailbox */
e1000_check_for_ack_vf(hw);
e1000_check_for_msg_vf(hw);
/* copy the caller specified message to the mailbox memory buffer */
for (i = 0; i < size; i++)
array_ew32(VMBMEM(0), i, msg[i]);
/* update stats */
hw->mbx.stats.msgs_tx++;
/* Drop VFU and interrupt the PF to tell it a message has been sent */
ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_REQ);
out_no_write:
return err;
}
/**
* e1000_read_mbx_vf - Reads a message from the inbox intended for VF
* @hw: pointer to the HW structure
* @msg: The message buffer
* @size: Length of buffer
*
* returns SUCCESS if it successfully read message from buffer
**/
static s32 e1000_read_mbx_vf(struct e1000_hw *hw, u32 *msg, u16 size)
{
s32 err;
u16 i;
lockdep_assert_held(&hw->mbx_lock);
/* lock the mailbox to prevent pf/vf race condition */
err = e1000_obtain_mbx_lock_vf(hw);
if (err)
goto out_no_read;
/* copy the message from the mailbox memory buffer */
for (i = 0; i < size; i++)
msg[i] = array_er32(VMBMEM(0), i);
/* Acknowledge receipt and release mailbox, then we're done */
ew32(V2PMAILBOX(0), E1000_V2PMAILBOX_ACK);
/* update stats */
hw->mbx.stats.msgs_rx++;
out_no_read:
return err;
}
/**
* e1000_init_mbx_params_vf - set initial values for VF mailbox
* @hw: pointer to the HW structure
*
* Initializes the hw->mbx struct to correct values for VF mailbox
*/
s32 e1000_init_mbx_params_vf(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
/* start mailbox as timed out and let the reset_hw call set the timeout
* value to being communications
*/
mbx->timeout = 0;
mbx->usec_delay = E1000_VF_MBX_INIT_DELAY;
mbx->size = E1000_VFMAILBOX_SIZE;
mbx->ops.read = e1000_read_mbx_vf;
mbx->ops.write = e1000_write_mbx_vf;
mbx->ops.read_posted = e1000_read_posted_mbx;
mbx->ops.write_posted = e1000_write_posted_mbx;
mbx->ops.check_for_msg = e1000_check_for_msg_vf;
mbx->ops.check_for_ack = e1000_check_for_ack_vf;
mbx->ops.check_for_rst = e1000_check_for_rst_vf;
mbx->stats.msgs_tx = 0;
mbx->stats.msgs_rx = 0;
mbx->stats.reqs = 0;
mbx->stats.acks = 0;
mbx->stats.rsts = 0;
return E1000_SUCCESS;
}
@@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 1999 - 2018 Intel Corporation. */
#ifndef _E1000_MBX_H_
#define _E1000_MBX_H_
#include "vf.h"
#define E1000_V2PMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */
#define E1000_V2PMAILBOX_ACK 0x00000002 /* Ack PF message received */
#define E1000_V2PMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
#define E1000_V2PMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
#define E1000_V2PMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */
#define E1000_V2PMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */
#define E1000_V2PMAILBOX_RSTI 0x00000040 /* PF has reset indication */
#define E1000_V2PMAILBOX_RSTD 0x00000080 /* PF has indicated reset done */
#define E1000_V2PMAILBOX_R2C_BITS 0x000000B0 /* All read to clear bits */
#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
* PF. The reverse is true if it is E1000_PF_*.
* Message ACK's are the value or'd with 0xF0000000
*/
/* Messages below or'd with this are the ACK */
#define E1000_VT_MSGTYPE_ACK 0x80000000
/* Messages below or'd with this are the NACK */
#define E1000_VT_MSGTYPE_NACK 0x40000000
/* Indicates that VF is still clear to send requests */
#define E1000_VT_MSGTYPE_CTS 0x20000000
/* We have a total wait time of 1s for vf mailbox posted messages */
#define E1000_VF_MBX_INIT_TIMEOUT 2000 /* retry count for mbx timeout */
#define E1000_VF_MBX_INIT_DELAY 500 /* usec delay between retries */
#define E1000_VT_MSGINFO_SHIFT 16
/* bits 23:16 are used for exra info for certain messages */
#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_RESET 0x01 /* VF requests reset */
#define E1000_VF_SET_MAC_ADDR 0x02 /* VF requests PF to set MAC addr */
/* VF requests PF to clear all unicast MAC filters */
#define E1000_VF_MAC_FILTER_CLR (0x01 << E1000_VT_MSGINFO_SHIFT)
/* VF requests PF to add unicast MAC filter */
#define E1000_VF_MAC_FILTER_ADD (0x02 << E1000_VT_MSGINFO_SHIFT)
#define E1000_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */
#define E1000_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */
#define E1000_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */
#define E1000_PF_CONTROL_MSG 0x0100 /* PF control message */
s32 e1000_init_mbx_params_vf(struct e1000_hw *);
#endif /* _E1000_MBX_H_ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,84 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2009 - 2018 Intel Corporation. */
#ifndef _E1000_REGS_H_
#define _E1000_REGS_H_
#define E1000_CTRL 0x00000 /* Device Control - RW */
#define E1000_STATUS 0x00008 /* Device Status - RO */
#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */
#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
#define E1000_EITR(_n) (0x01680 + (0x4 * (_n)))
#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
#define E1000_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
#define E1000_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
#define E1000_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
#define E1000_EIAM 0x01530 /* Ext. Interrupt Ack Auto Clear Mask - RW */
#define E1000_IVAR0 0x01700 /* Interrupt Vector Allocation (array) - RW */
#define E1000_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
/* Convenience macros
*
* Note: "_n" is the queue number of the register to be written to.
*
* Example usage:
* E1000_RDBAL_REG(current_rx_queue)
*/
#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \
(0x0C000 + ((_n) * 0x40)))
#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \
(0x0C004 + ((_n) * 0x40)))
#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \
(0x0C008 + ((_n) * 0x40)))
#define E1000_SRRCTL(_n) ((_n) < 4 ? (0x0280C + ((_n) * 0x100)) : \
(0x0C00C + ((_n) * 0x40)))
#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \
(0x0C010 + ((_n) * 0x40)))
#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \
(0x0C018 + ((_n) * 0x40)))
#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \
(0x0C028 + ((_n) * 0x40)))
#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \
(0x0E000 + ((_n) * 0x40)))
#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \
(0x0E004 + ((_n) * 0x40)))
#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \
(0x0E008 + ((_n) * 0x40)))
#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \
(0x0E010 + ((_n) * 0x40)))
#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \
(0x0E018 + ((_n) * 0x40)))
#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \
(0x0E028 + ((_n) * 0x40)))
#define E1000_DCA_TXCTRL(_n) (0x03814 + (_n << 8))
#define E1000_DCA_RXCTRL(_n) (0x02814 + (_n << 8))
#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
(0x054E0 + ((_i - 16) * 8)))
#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
(0x054E4 + ((_i - 16) * 8)))
/* Statistics registers */
#define E1000_VFGPRC 0x00F10
#define E1000_VFGORC 0x00F18
#define E1000_VFMPRC 0x00F3C
#define E1000_VFGPTC 0x00F14
#define E1000_VFGOTC 0x00F34
#define E1000_VFGOTLBC 0x00F50
#define E1000_VFGPTLBC 0x00F44
#define E1000_VFGORLBC 0x00F48
#define E1000_VFGPRLBC 0x00F40
/* These act per VF so an array friendly macro is used */
#define E1000_V2PMAILBOX(_n) (0x00C40 + (4 * (_n)))
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
/* Define macros for handling registers */
#define er32(reg) readl(hw->hw_addr + E1000_##reg)
#define ew32(reg, val) writel((val), hw->hw_addr + E1000_##reg)
#define array_er32(reg, offset) \
readl(hw->hw_addr + E1000_##reg + (offset << 2))
#define array_ew32(reg, offset, val) \
writel((val), hw->hw_addr + E1000_##reg + (offset << 2))
#define e1e_flush() er32(STATUS)
#endif
@@ -0,0 +1,430 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2009 - 2018 Intel Corporation. */
#include <linux/etherdevice.h>
#include "vf.h"
static s32 e1000_check_for_link_vf(struct e1000_hw *hw);
static s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
u16 *duplex);
static s32 e1000_init_hw_vf(struct e1000_hw *hw);
static s32 e1000_reset_hw_vf(struct e1000_hw *hw);
static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw, u8 *,
u32, u32, u32);
static void e1000_rar_set_vf(struct e1000_hw *, u8 *, u32);
static s32 e1000_read_mac_addr_vf(struct e1000_hw *);
static s32 e1000_set_uc_addr_vf(struct e1000_hw *hw, u32 subcmd, u8 *addr);
static s32 e1000_set_vfta_vf(struct e1000_hw *, u16, bool);
/**
* e1000_init_mac_params_vf - Inits MAC params
* @hw: pointer to the HW structure
**/
static s32 e1000_init_mac_params_vf(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
/* VF's have no MTA Registers - PF feature only */
mac->mta_reg_count = 128;
/* VF's have no access to RAR entries */
mac->rar_entry_count = 1;
/* Function pointers */
/* reset */
mac->ops.reset_hw = e1000_reset_hw_vf;
/* hw initialization */
mac->ops.init_hw = e1000_init_hw_vf;
/* check for link */
mac->ops.check_for_link = e1000_check_for_link_vf;
/* link info */
mac->ops.get_link_up_info = e1000_get_link_up_info_vf;
/* multicast address update */
mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_vf;
/* set mac address */
mac->ops.rar_set = e1000_rar_set_vf;
/* read mac address */
mac->ops.read_mac_addr = e1000_read_mac_addr_vf;
/* set mac filter */
mac->ops.set_uc_addr = e1000_set_uc_addr_vf;
/* set vlan filter table array */
mac->ops.set_vfta = e1000_set_vfta_vf;
return E1000_SUCCESS;
}
/**
* e1000_init_function_pointers_vf - Inits function pointers
* @hw: pointer to the HW structure
**/
void e1000_init_function_pointers_vf(struct e1000_hw *hw)
{
hw->mac.ops.init_params = e1000_init_mac_params_vf;
hw->mbx.ops.init_params = e1000_init_mbx_params_vf;
}
/**
* e1000_get_link_up_info_vf - Gets link info.
* @hw: pointer to the HW structure
* @speed: pointer to 16 bit value to store link speed.
* @duplex: pointer to 16 bit value to store duplex.
*
* Since we cannot read the PHY and get accurate link info, we must rely upon
* the status register's data which is often stale and inaccurate.
**/
static s32 e1000_get_link_up_info_vf(struct e1000_hw *hw, u16 *speed,
u16 *duplex)
{
s32 status;
status = er32(STATUS);
if (status & E1000_STATUS_SPEED_1000)
*speed = SPEED_1000;
else if (status & E1000_STATUS_SPEED_100)
*speed = SPEED_100;
else
*speed = SPEED_10;
if (status & E1000_STATUS_FD)
*duplex = FULL_DUPLEX;
else
*duplex = HALF_DUPLEX;
return E1000_SUCCESS;
}
/**
* e1000_reset_hw_vf - Resets the HW
* @hw: pointer to the HW structure
*
* VF's provide a function level reset. This is done using bit 26 of ctrl_reg.
* This is all the reset we can perform on a VF.
**/
static s32 e1000_reset_hw_vf(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 timeout = E1000_VF_INIT_TIMEOUT;
u32 ret_val = -E1000_ERR_MAC_INIT;
u32 msgbuf[3];
u8 *addr = (u8 *)(&msgbuf[1]);
u32 ctrl;
/* assert VF queue/interrupt reset */
ctrl = er32(CTRL);
ew32(CTRL, ctrl | E1000_CTRL_RST);
/* we cannot initialize while the RSTI / RSTD bits are asserted */
while (!mbx->ops.check_for_rst(hw) && timeout) {
timeout--;
udelay(5);
}
if (timeout) {
/* mailbox timeout can now become active */
mbx->timeout = E1000_VF_MBX_INIT_TIMEOUT;
/* notify PF of VF reset completion */
msgbuf[0] = E1000_VF_RESET;
mbx->ops.write_posted(hw, msgbuf, 1);
mdelay(10);
/* set our "perm_addr" based on info provided by PF */
ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
if (!ret_val) {
switch (msgbuf[0]) {
case E1000_VF_RESET | E1000_VT_MSGTYPE_ACK:
memcpy(hw->mac.perm_addr, addr, ETH_ALEN);
break;
case E1000_VF_RESET | E1000_VT_MSGTYPE_NACK:
eth_zero_addr(hw->mac.perm_addr);
break;
default:
ret_val = -E1000_ERR_MAC_INIT;
}
}
}
return ret_val;
}
/**
* e1000_init_hw_vf - Inits the HW
* @hw: pointer to the HW structure
*
* Not much to do here except clear the PF Reset indication if there is one.
**/
static s32 e1000_init_hw_vf(struct e1000_hw *hw)
{
/* attempt to set and restore our mac address */
e1000_rar_set_vf(hw, hw->mac.addr, 0);
return E1000_SUCCESS;
}
/**
* e1000_hash_mc_addr_vf - Generate a multicast hash value
* @hw: pointer to the HW structure
* @mc_addr: pointer to a multicast address
*
* Generates a multicast address hash value which is used to determine
* the multicast filter table array address and new table value. See
* e1000_mta_set_generic()
**/
static u32 e1000_hash_mc_addr_vf(struct e1000_hw *hw, u8 *mc_addr)
{
u32 hash_value, hash_mask;
u8 bit_shift = 0;
/* Register count multiplied by bits per register */
hash_mask = (hw->mac.mta_reg_count * 32) - 1;
/* The bit_shift is the number of left-shifts
* where 0xFF would still fall within the hash mask.
*/
while (hash_mask >> bit_shift != 0xFF)
bit_shift++;
hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) |
(((u16)mc_addr[5]) << bit_shift)));
return hash_value;
}
/**
* e1000_update_mc_addr_list_vf - Update Multicast addresses
* @hw: pointer to the HW structure
* @mc_addr_list: array of multicast addresses to program
* @mc_addr_count: number of multicast addresses to program
* @rar_used_count: the first RAR register free to program
* @rar_count: total number of supported Receive Address Registers
*
* Updates the Receive Address Registers and Multicast Table Array.
* The caller must have a packed mc_addr_list of multicast addresses.
* The parameter rar_count will usually be hw->mac.rar_entry_count
* unless there are workarounds that change this.
**/
static void e1000_update_mc_addr_list_vf(struct e1000_hw *hw,
u8 *mc_addr_list, u32 mc_addr_count,
u32 rar_used_count, u32 rar_count)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[E1000_VFMAILBOX_SIZE];
u16 *hash_list = (u16 *)&msgbuf[1];
u32 hash_value;
u32 cnt, i;
s32 ret_val;
/* Each entry in the list uses 1 16 bit word. We have 30
* 16 bit words available in our HW msg buffer (minus 1 for the
* msg type). That's 30 hash values if we pack 'em right. If
* there are more than 30 MC addresses to add then punt the
* extras for now and then add code to handle more than 30 later.
* It would be unusual for a server to request that many multi-cast
* addresses except for in large enterprise network environments.
*/
cnt = (mc_addr_count > 30) ? 30 : mc_addr_count;
msgbuf[0] = E1000_VF_SET_MULTICAST;
msgbuf[0] |= cnt << E1000_VT_MSGINFO_SHIFT;
for (i = 0; i < cnt; i++) {
hash_value = e1000_hash_mc_addr_vf(hw, mc_addr_list);
hash_list[i] = hash_value & 0x0FFFF;
mc_addr_list += ETH_ALEN;
}
ret_val = mbx->ops.write_posted(hw, msgbuf, E1000_VFMAILBOX_SIZE);
if (!ret_val)
mbx->ops.read_posted(hw, msgbuf, 1);
}
/**
* e1000_set_vfta_vf - Set/Unset vlan filter table address
* @hw: pointer to the HW structure
* @vid: determines the vfta register and bit to set/unset
* @set: if true then set bit, else clear bit
**/
static s32 e1000_set_vfta_vf(struct e1000_hw *hw, u16 vid, bool set)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[2];
s32 err;
msgbuf[0] = E1000_VF_SET_VLAN;
msgbuf[1] = vid;
/* Setting the 8 bit field MSG INFO to true indicates "add" */
if (set)
msgbuf[0] |= BIT(E1000_VT_MSGINFO_SHIFT);
mbx->ops.write_posted(hw, msgbuf, 2);
err = mbx->ops.read_posted(hw, msgbuf, 2);
msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
/* if nacked the vlan was rejected */
if (!err && (msgbuf[0] == (E1000_VF_SET_VLAN | E1000_VT_MSGTYPE_NACK)))
err = -E1000_ERR_MAC_INIT;
return err;
}
/**
* e1000_rlpml_set_vf - Set the maximum receive packet length
* @hw: pointer to the HW structure
* @max_size: value to assign to max frame size
**/
void e1000_rlpml_set_vf(struct e1000_hw *hw, u16 max_size)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[2];
s32 ret_val;
msgbuf[0] = E1000_VF_SET_LPE;
msgbuf[1] = max_size;
ret_val = mbx->ops.write_posted(hw, msgbuf, 2);
if (!ret_val)
mbx->ops.read_posted(hw, msgbuf, 1);
}
/**
* e1000_rar_set_vf - set device MAC address
* @hw: pointer to the HW structure
* @addr: pointer to the receive address
* @index: receive address array register
**/
static void e1000_rar_set_vf(struct e1000_hw *hw, u8 *addr, u32 index)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[3];
u8 *msg_addr = (u8 *)(&msgbuf[1]);
s32 ret_val;
memset(msgbuf, 0, 12);
msgbuf[0] = E1000_VF_SET_MAC_ADDR;
memcpy(msg_addr, addr, ETH_ALEN);
ret_val = mbx->ops.write_posted(hw, msgbuf, 3);
if (!ret_val)
ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
/* if nacked the address was rejected, use "perm_addr" */
if (!ret_val &&
(msgbuf[0] == (E1000_VF_SET_MAC_ADDR | E1000_VT_MSGTYPE_NACK)))
e1000_read_mac_addr_vf(hw);
}
/**
* e1000_read_mac_addr_vf - Read device MAC address
* @hw: pointer to the HW structure
**/
static s32 e1000_read_mac_addr_vf(struct e1000_hw *hw)
{
memcpy(hw->mac.addr, hw->mac.perm_addr, ETH_ALEN);
return E1000_SUCCESS;
}
/**
* e1000_set_uc_addr_vf - Set or clear unicast filters
* @hw: pointer to the HW structure
* @sub_cmd: add or clear filters
* @addr: pointer to the filter MAC address
**/
static s32 e1000_set_uc_addr_vf(struct e1000_hw *hw, u32 sub_cmd, u8 *addr)
{
struct e1000_mbx_info *mbx = &hw->mbx;
u32 msgbuf[3], msgbuf_chk;
u8 *msg_addr = (u8 *)(&msgbuf[1]);
s32 ret_val;
memset(msgbuf, 0, sizeof(msgbuf));
msgbuf[0] |= sub_cmd;
msgbuf[0] |= E1000_VF_SET_MAC_ADDR;
msgbuf_chk = msgbuf[0];
if (addr)
memcpy(msg_addr, addr, ETH_ALEN);
ret_val = mbx->ops.write_posted(hw, msgbuf, 3);
if (!ret_val)
ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
if (!ret_val) {
msgbuf[0] &= ~E1000_VT_MSGTYPE_CTS;
if (msgbuf[0] == (msgbuf_chk | E1000_VT_MSGTYPE_NACK))
return -ENOSPC;
}
return ret_val;
}
/**
* e1000_check_for_link_vf - Check for link for a virtual interface
* @hw: pointer to the HW structure
*
* Checks to see if the underlying PF is still talking to the VF and
* if it is then it reports the link state to the hardware, otherwise
* it reports link down and returns an error.
**/
static s32 e1000_check_for_link_vf(struct e1000_hw *hw)
{
struct e1000_mbx_info *mbx = &hw->mbx;
struct e1000_mac_info *mac = &hw->mac;
s32 ret_val = E1000_SUCCESS;
u32 in_msg = 0;
/* We only want to run this if there has been a rst asserted.
* in this case that could mean a link change, device reset,
* or a virtual function reset
*/
/* If we were hit with a reset or timeout drop the link */
if (!mbx->ops.check_for_rst(hw) || !mbx->timeout)
mac->get_link_status = true;
if (!mac->get_link_status)
goto out;
/* if link status is down no point in checking to see if PF is up */
if (!(er32(STATUS) & E1000_STATUS_LU))
goto out;
/* if the read failed it could just be a mailbox collision, best wait
* until we are called again and don't report an error
*/
if (mbx->ops.read(hw, &in_msg, 1))
goto out;
/* if incoming message isn't clear to send we are waiting on response */
if (!(in_msg & E1000_VT_MSGTYPE_CTS)) {
/* msg is not CTS and is NACK we must have lost CTS status */
if (in_msg & E1000_VT_MSGTYPE_NACK)
ret_val = -E1000_ERR_MAC_INIT;
goto out;
}
/* the PF is talking, if we timed out in the past we reinit */
if (!mbx->timeout) {
ret_val = -E1000_ERR_MAC_INIT;
goto out;
}
/* if we passed all the tests above then the link is up and we no
* longer need to check for link
*/
mac->get_link_status = false;
out:
return ret_val;
}
@@ -0,0 +1,243 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright(c) 2009 - 2018 Intel Corporation. */
#ifndef _E1000_VF_H_
#define _E1000_VF_H_
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include "regs.h"
#include "defines.h"
struct e1000_hw;
#define E1000_DEV_ID_82576_VF 0x10CA
#define E1000_DEV_ID_I350_VF 0x1520
#define E1000_REVISION_0 0
#define E1000_REVISION_1 1
#define E1000_REVISION_2 2
#define E1000_REVISION_3 3
#define E1000_REVISION_4 4
#define E1000_FUNC_0 0
#define E1000_FUNC_1 1
/* Receive Address Register Count
* Number of high/low register pairs in the RAR. The RAR (Receive Address
* Registers) holds the directed and multicast addresses that we monitor.
* These entries are also used for MAC-based filtering.
*/
#define E1000_RAR_ENTRIES_VF 1
/* Receive Descriptor - Advanced */
union e1000_adv_rx_desc {
struct {
__le64 pkt_addr; /* Packet buffer address */
__le64 hdr_addr; /* Header buffer address */
} read;
struct {
struct {
union {
__le32 data;
struct {
__le16 pkt_info; /* RSS/Packet type */
/* Split Header, hdr buffer length */
__le16 hdr_info;
} hs_rss;
} lo_dword;
union {
__le32 rss; /* RSS Hash */
struct {
__le16 ip_id; /* IP id */
__le16 csum; /* Packet Checksum */
} csum_ip;
} hi_dword;
} lower;
struct {
__le32 status_error; /* ext status/error */
__le16 length; /* Packet length */
__le16 vlan; /* VLAN tag */
} upper;
} wb; /* writeback */
};
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
/* Transmit Descriptor - Advanced */
union e1000_adv_tx_desc {
struct {
__le64 buffer_addr; /* Address of descriptor's data buf */
__le32 cmd_type_len;
__le32 olinfo_status;
} read;
struct {
__le64 rsvd; /* Reserved */
__le32 nxtseq_seed;
__le32 status;
} wb;
};
/* Adv Transmit Descriptor Config Masks */
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
/* Context descriptors */
struct e1000_adv_tx_context_desc {
__le32 vlan_macip_lens;
__le32 seqnum_seed;
__le32 type_tucmd_mlhl;
__le32 mss_l4len_idx;
};
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
enum e1000_mac_type {
e1000_undefined = 0,
e1000_vfadapt,
e1000_vfadapt_i350,
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
};
struct e1000_vf_stats {
u64 base_gprc;
u64 base_gptc;
u64 base_gorc;
u64 base_gotc;
u64 base_mprc;
u64 base_gotlbc;
u64 base_gptlbc;
u64 base_gorlbc;
u64 base_gprlbc;
u32 last_gprc;
u32 last_gptc;
u32 last_gorc;
u32 last_gotc;
u32 last_mprc;
u32 last_gotlbc;
u32 last_gptlbc;
u32 last_gorlbc;
u32 last_gprlbc;
u64 gprc;
u64 gptc;
u64 gorc;
u64 gotc;
u64 mprc;
u64 gotlbc;
u64 gptlbc;
u64 gorlbc;
u64 gprlbc;
};
#include "mbx.h"
struct e1000_mac_operations {
/* Function pointers for the MAC. */
s32 (*init_params)(struct e1000_hw *);
s32 (*check_for_link)(struct e1000_hw *);
void (*clear_vfta)(struct e1000_hw *);
s32 (*get_bus_info)(struct e1000_hw *);
s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, u32);
s32 (*set_uc_addr)(struct e1000_hw *, u32, u8 *);
s32 (*reset_hw)(struct e1000_hw *);
s32 (*init_hw)(struct e1000_hw *);
s32 (*setup_link)(struct e1000_hw *);
void (*write_vfta)(struct e1000_hw *, u32, u32);
void (*mta_set)(struct e1000_hw *, u32);
void (*rar_set)(struct e1000_hw *, u8*, u32);
s32 (*read_mac_addr)(struct e1000_hw *);
s32 (*set_vfta)(struct e1000_hw *, u16, bool);
};
struct e1000_mac_info {
struct e1000_mac_operations ops;
u8 addr[6];
u8 perm_addr[6];
enum e1000_mac_type type;
u16 mta_reg_count;
u16 rar_entry_count;
bool get_link_status;
};
struct e1000_mbx_operations {
s32 (*init_params)(struct e1000_hw *hw);
s32 (*read)(struct e1000_hw *, u32 *, u16);
s32 (*write)(struct e1000_hw *, u32 *, u16);
s32 (*read_posted)(struct e1000_hw *, u32 *, u16);
s32 (*write_posted)(struct e1000_hw *, u32 *, u16);
s32 (*check_for_msg)(struct e1000_hw *);
s32 (*check_for_ack)(struct e1000_hw *);
s32 (*check_for_rst)(struct e1000_hw *);
};
struct e1000_mbx_stats {
u32 msgs_tx;
u32 msgs_rx;
u32 acks;
u32 reqs;
u32 rsts;
};
struct e1000_mbx_info {
struct e1000_mbx_operations ops;
struct e1000_mbx_stats stats;
u32 timeout;
u32 usec_delay;
u16 size;
};
struct e1000_dev_spec_vf {
u32 vf_number;
u32 v2p_mailbox;
};
struct e1000_hw {
void *back;
u8 __iomem *hw_addr;
u8 __iomem *flash_address;
unsigned long io_base;
struct e1000_mac_info mac;
struct e1000_mbx_info mbx;
spinlock_t mbx_lock; /* serializes mailbox ops */
union {
struct e1000_dev_spec_vf vf;
} dev_spec;
u16 device_id;
u16 subsystem_vendor_id;
u16 subsystem_device_id;
u16 vendor_id;
u8 revision_id;
};
/* These functions must be implemented by drivers */
void e1000_rlpml_set_vf(struct e1000_hw *, u16);
void e1000_init_function_pointers_vf(struct e1000_hw *hw);
#endif /* _E1000_VF_H_ */