Merge branch 'igc_5.15' into 'stable-1.5'

Add igc for 5.15.40

See merge request etherlab.org/ethercat!128
This commit is contained in:
Florian Pose
2024-06-03 09:39:12 +00:00
49 changed files with 32483 additions and 0 deletions

View File

@@ -30,6 +30,8 @@ include $(top_srcdir)/Makefile.kbuild
EXTRA_DIST = \
igc-5.14-ethercat.h \
igc-5.14-orig.h \
igc-5.15-ethercat.h \
igc-5.15-orig.h \
igc-6.1-ethercat.h \
igc-6.1-orig.h \
igc-6.4-ethercat.h \
@@ -40,6 +42,11 @@ EXTRA_DIST = \
igc_base-5.14-ethercat.h \
igc_base-5.14-orig.c \
igc_base-5.14-orig.h \
igc_base-5.15-ethercat.c \
igc_base-5.15-ethercat.h \
igc_base-5.15-orig.h \
igc_base-5.15-orig.c \
igc_base-5.15-orig.h \
igc_base-6.1-ethercat.c \
igc_base-6.1-ethercat.h \
igc_base-6.1-orig.c \
@@ -54,6 +61,8 @@ EXTRA_DIST = \
igc_base-6.6-orig.h \
igc_defines-5.14-ethercat.h \
igc_defines-5.14-orig.h \
igc_defines-5.15-ethercat.h \
igc_defines-5.15-orig.h \
igc_defines-6.1-ethercat.h \
igc_defines-6.1-orig.h \
igc_defines-6.4-ethercat.h \
@@ -64,6 +73,10 @@ EXTRA_DIST = \
igc_diag-5.14-ethercat.h \
igc_diag-5.14-orig.c \
igc_diag-5.14-orig.h \
igc_diag-5.15-ethercat.c \
igc_diag-5.15-ethercat.h \
igc_diag-5.15-orig.c \
igc_diag-5.15-orig.h \
igc_diag-6.1-ethercat.c \
igc_diag-6.1-ethercat.h \
igc_diag-6.1-orig.c \
@@ -78,6 +91,8 @@ EXTRA_DIST = \
igc_diag-6.6-orig.h \
igc_dump-5.14-ethercat.c \
igc_dump-5.14-orig.c \
igc_dump-5.15-ethercat.c \
igc_dump-5.15-orig.c \
igc_dump-6.1-ethercat.c \
igc_dump-6.1-orig.c \
igc_dump-6.4-ethercat.c \
@@ -86,6 +101,8 @@ EXTRA_DIST = \
igc_dump-6.6-orig.c \
igc_ethtool-5.14-ethercat.c \
igc_ethtool-5.14-orig.c \
igc_ethtool-5.15-ethercat.c \
igc_ethtool-5.15-orig.c \
igc_ethtool-6.1-ethercat.c \
igc_ethtool-6.1-orig.c \
igc_ethtool-6.4-ethercat.c \
@@ -94,6 +111,8 @@ EXTRA_DIST = \
igc_ethtool-6.6-orig.c \
igc_hw-5.14-ethercat.h \
igc_hw-5.14-orig.h \
igc_hw-5.15-ethercat.h \
igc_hw-5.15-orig.h \
igc_hw-6.1-ethercat.h \
igc_hw-6.1-orig.h \
igc_hw-6.4-ethercat.h \
@@ -104,6 +123,10 @@ EXTRA_DIST = \
igc_i225-5.14-ethercat.h \
igc_i225-5.14-orig.c \
igc_i225-5.14-orig.h \
igc_i225-5.15-ethercat.c \
igc_i225-5.15-ethercat.h \
igc_i225-5.15-orig.c \
igc_i225-5.15-orig.h \
igc_i225-6.1-ethercat.c \
igc_i225-6.1-ethercat.h \
igc_i225-6.1-orig.c \
@@ -120,6 +143,10 @@ EXTRA_DIST = \
igc_mac-5.14-ethercat.h \
igc_mac-5.14-orig.c \
igc_mac-5.14-orig.h \
igc_mac-5.15-ethercat.c \
igc_mac-5.15-ethercat.h \
igc_mac-5.15-orig.c \
igc_mac-5.15-orig.h \
igc_mac-6.1-ethercat.c \
igc_mac-6.1-ethercat.h \
igc_mac-6.1-orig.c \
@@ -134,6 +161,8 @@ EXTRA_DIST = \
igc_mac-6.6-orig.h \
igc_main-5.14-ethercat.c \
igc_main-5.14-orig.c \
igc_main-5.15-ethercat.c \
igc_main-5.15-orig.c \
igc_main-6.1-ethercat.c \
igc_main-6.1-orig.c \
igc_main-6.4-ethercat.c \
@@ -144,6 +173,10 @@ EXTRA_DIST = \
igc_nvm-5.14-ethercat.h \
igc_nvm-5.14-orig.c \
igc_nvm-5.14-orig.h \
igc_nvm-5.15-ethercat.c \
igc_nvm-5.15-ethercat.h \
igc_nvm-5.15-orig.h \
igc_nvm-5.15-orig.c \
igc_nvm-6.1-ethercat.c \
igc_nvm-6.1-ethercat.h \
igc_nvm-6.1-orig.c \
@@ -160,6 +193,10 @@ EXTRA_DIST = \
igc_phy-5.14-ethercat.h \
igc_phy-5.14-orig.c \
igc_phy-5.14-orig.h \
igc_phy-5.15-ethercat.c \
igc_phy-5.15-ethercat.h \
igc_phy-5.15-orig.h \
igc_phy-5.15-orig.c \
igc_phy-6.1-ethercat.c \
igc_phy-6.1-ethercat.h \
igc_phy-6.1-orig.c \
@@ -174,6 +211,8 @@ EXTRA_DIST = \
igc_phy-6.6-orig.h \
igc_ptp-5.14-ethercat.c \
igc_ptp-5.14-orig.c \
igc_ptp-5.15-ethercat.c \
igc_ptp-5.15-orig.c \
igc_ptp-6.1-ethercat.c \
igc_ptp-6.1-orig.c \
igc_ptp-6.4-ethercat.c \
@@ -182,6 +221,8 @@ EXTRA_DIST = \
igc_ptp-6.6-orig.c \
igc_regs-5.14-ethercat.h \
igc_regs-5.14-orig.h \
igc_regs-5.15-ethercat.h \
igc_regs-5.15-orig.h \
igc_regs-6.1-ethercat.h \
igc_regs-6.1-orig.h \
igc_regs-6.4-ethercat.h \
@@ -192,6 +233,10 @@ EXTRA_DIST = \
igc_tsn-5.14-ethercat.h \
igc_tsn-5.14-orig.c \
igc_tsn-5.14-orig.h \
igc_tsn-5.15-ethercat.c \
igc_tsn-5.15-ethercat.h \
igc_tsn-5.15-orig.h \
igc_tsn-5.15-orig.c \
igc_tsn-6.1-ethercat.c \
igc_tsn-6.1-ethercat.h \
igc_tsn-6.1-orig.c \
@@ -208,6 +253,10 @@ EXTRA_DIST = \
igc_xdp-5.14-ethercat.h \
igc_xdp-5.14-orig.c \
igc_xdp-5.14-orig.h \
igc_xdp-5.15-ethercat.c \
igc_xdp-5.15-ethercat.h \
igc_xdp-5.15-orig.h \
igc_xdp-5.15-orig.c \
igc_xdp-6.1-ethercat.c \
igc_xdp-6.1-ethercat.h \
igc_xdp-6.1-orig.c \

File diff suppressed because it is too large Load Diff

647
devices/igc/igc-5.15-orig.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,425 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018 Intel Corporation */
#include <linux/delay.h>
#include "igc_hw-5.15-ethercat.h"
#include "igc_i225-5.15-ethercat.h"
#include "igc_mac-5.15-ethercat.h"
#include "igc_base-5.15-ethercat.h"
#include "igc-5.15-ethercat.h"
/**
* igc_reset_hw_base - Reset hardware
* @hw: pointer to the HW structure
*
* This resets the hardware into a known state. This is a
* function pointer entry point called by the api module.
*/
static s32 igc_reset_hw_base(struct igc_hw *hw)
{
s32 ret_val;
u32 ctrl;
/* Prevent the PCI-E bus from sticking if there is no TLP connection
* on the last TLP read/write transaction when MAC is reset.
*/
ret_val = igc_disable_pcie_master(hw);
if (ret_val)
hw_dbg("PCI-E Master disable polling has failed\n");
hw_dbg("Masking off all interrupts\n");
wr32(IGC_IMC, 0xffffffff);
wr32(IGC_RCTL, 0);
wr32(IGC_TCTL, IGC_TCTL_PSP);
wrfl();
usleep_range(10000, 20000);
ctrl = rd32(IGC_CTRL);
hw_dbg("Issuing a global reset to MAC\n");
wr32(IGC_CTRL, ctrl | IGC_CTRL_DEV_RST);
ret_val = igc_get_auto_rd_done(hw);
if (ret_val) {
/* When auto config read does not complete, do not
* return with an error. This can happen in situations
* where there is no eeprom and prevents getting link.
*/
hw_dbg("Auto Read Done did not complete\n");
}
/* Clear any pending interrupt events. */
wr32(IGC_IMC, 0xffffffff);
rd32(IGC_ICR);
return ret_val;
}
/**
* igc_init_nvm_params_base - Init NVM func ptrs.
* @hw: pointer to the HW structure
*/
static s32 igc_init_nvm_params_base(struct igc_hw *hw)
{
struct igc_nvm_info *nvm = &hw->nvm;
u32 eecd = rd32(IGC_EECD);
u16 size;
size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >>
IGC_EECD_SIZE_EX_SHIFT);
/* Added to a constant, "size" becomes the left-shift value
* for setting word_size.
*/
size += NVM_WORD_SIZE_BASE_SHIFT;
/* Just in case size is out of range, cap it to the largest
* EEPROM size supported
*/
if (size > 15)
size = 15;
nvm->type = igc_nvm_eeprom_spi;
nvm->word_size = BIT(size);
nvm->opcode_bits = 8;
nvm->delay_usec = 1;
nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8;
nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ?
16 : 8;
if (nvm->word_size == BIT(15))
nvm->page_size = 128;
return 0;
}
/**
* igc_setup_copper_link_base - Configure copper link settings
* @hw: pointer to the HW structure
*
* Configures the link for auto-neg or forced speed and duplex. Then we check
* for link, once link is established calls to configure collision distance
* and flow control are called.
*/
static s32 igc_setup_copper_link_base(struct igc_hw *hw)
{
s32 ret_val = 0;
u32 ctrl;
ctrl = rd32(IGC_CTRL);
ctrl |= IGC_CTRL_SLU;
ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
wr32(IGC_CTRL, ctrl);
ret_val = igc_setup_copper_link(hw);
return ret_val;
}
/**
* igc_init_mac_params_base - Init MAC func ptrs.
* @hw: pointer to the HW structure
*/
static s32 igc_init_mac_params_base(struct igc_hw *hw)
{
struct igc_dev_spec_base *dev_spec = &hw->dev_spec._base;
struct igc_mac_info *mac = &hw->mac;
/* Set mta register count */
mac->mta_reg_count = 128;
mac->rar_entry_count = IGC_RAR_ENTRIES;
/* reset */
mac->ops.reset_hw = igc_reset_hw_base;
mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225;
mac->ops.release_swfw_sync = igc_release_swfw_sync_i225;
/* Allow a single clear of the SW semaphore on I225 */
if (mac->type == igc_i225)
dev_spec->clear_semaphore_once = true;
/* physical interface link setup */
mac->ops.setup_physical_interface = igc_setup_copper_link_base;
return 0;
}
/**
* igc_init_phy_params_base - Init PHY func ptrs.
* @hw: pointer to the HW structure
*/
static s32 igc_init_phy_params_base(struct igc_hw *hw)
{
struct igc_phy_info *phy = &hw->phy;
s32 ret_val = 0;
if (hw->phy.media_type != igc_media_type_copper) {
phy->type = igc_phy_none;
goto out;
}
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500;
phy->reset_delay_us = 100;
/* set lan id */
hw->bus.func = (rd32(IGC_STATUS) & IGC_STATUS_FUNC_MASK) >>
IGC_STATUS_FUNC_SHIFT;
/* Make sure the PHY is in a good state. Several people have reported
* firmware leaving the PHY's page select register set to something
* other than the default of zero, which causes the PHY ID read to
* access something other than the intended register.
*/
ret_val = hw->phy.ops.reset(hw);
if (ret_val) {
hw_dbg("Error resetting the PHY\n");
goto out;
}
ret_val = igc_get_phy_id(hw);
if (ret_val)
return ret_val;
igc_check_for_copper_link(hw);
phy->type = igc_phy_i225;
out:
return ret_val;
}
static s32 igc_get_invariants_base(struct igc_hw *hw)
{
struct igc_mac_info *mac = &hw->mac;
s32 ret_val = 0;
switch (hw->device_id) {
case IGC_DEV_ID_I225_LM:
case IGC_DEV_ID_I225_V:
case IGC_DEV_ID_I225_I:
case IGC_DEV_ID_I220_V:
case IGC_DEV_ID_I225_K:
case IGC_DEV_ID_I225_K2:
case IGC_DEV_ID_I226_K:
case IGC_DEV_ID_I225_LMVP:
case IGC_DEV_ID_I225_IT:
case IGC_DEV_ID_I226_LM:
case IGC_DEV_ID_I226_V:
case IGC_DEV_ID_I226_IT:
case IGC_DEV_ID_I221_V:
case IGC_DEV_ID_I226_BLANK_NVM:
case IGC_DEV_ID_I225_BLANK_NVM:
mac->type = igc_i225;
break;
default:
return -IGC_ERR_MAC_INIT;
}
hw->phy.media_type = igc_media_type_copper;
/* mac initialization and operations */
ret_val = igc_init_mac_params_base(hw);
if (ret_val)
goto out;
/* NVM initialization */
ret_val = igc_init_nvm_params_base(hw);
switch (hw->mac.type) {
case igc_i225:
ret_val = igc_init_nvm_params_i225(hw);
break;
default:
break;
}
/* setup PHY parameters */
ret_val = igc_init_phy_params_base(hw);
if (ret_val)
goto out;
out:
return ret_val;
}
/**
* igc_acquire_phy_base - Acquire rights to access PHY
* @hw: pointer to the HW structure
*
* Acquire access rights to the correct PHY. This is a
* function pointer entry point called by the api module.
*/
static s32 igc_acquire_phy_base(struct igc_hw *hw)
{
u16 mask = IGC_SWFW_PHY0_SM;
return hw->mac.ops.acquire_swfw_sync(hw, mask);
}
/**
* igc_release_phy_base - Release rights to access PHY
* @hw: pointer to the HW structure
*
* A wrapper to release access rights to the correct PHY. This is a
* function pointer entry point called by the api module.
*/
static void igc_release_phy_base(struct igc_hw *hw)
{
u16 mask = IGC_SWFW_PHY0_SM;
hw->mac.ops.release_swfw_sync(hw, mask);
}
/**
* igc_init_hw_base - Initialize hardware
* @hw: pointer to the HW structure
*
* This inits the hardware readying it for operation.
*/
static s32 igc_init_hw_base(struct igc_hw *hw)
{
struct igc_mac_info *mac = &hw->mac;
u16 i, rar_count = mac->rar_entry_count;
s32 ret_val = 0;
/* Setup the receive address */
igc_init_rx_addrs(hw, rar_count);
/* Zero out the Multicast HASH table */
hw_dbg("Zeroing the MTA\n");
for (i = 0; i < mac->mta_reg_count; i++)
array_wr32(IGC_MTA, i, 0);
/* Zero out the Unicast HASH table */
hw_dbg("Zeroing the UTA\n");
for (i = 0; i < mac->uta_reg_count; i++)
array_wr32(IGC_UTA, i, 0);
/* Setup link and flow control */
ret_val = igc_setup_link(hw);
/* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
* because the symbol error count will increment wildly if there
* is no link.
*/
igc_clear_hw_cntrs_base(hw);
return ret_val;
}
/**
* igc_power_down_phy_copper_base - Remove link during PHY power down
* @hw: pointer to the HW structure
*
* In the case of a PHY power down to save power, or to turn off link during a
* driver unload, or wake on lan is not enabled, remove the link.
*/
void igc_power_down_phy_copper_base(struct igc_hw *hw)
{
/* If the management interface is not enabled, then power down */
if (!(igc_enable_mng_pass_thru(hw) || igc_check_reset_block(hw)))
igc_power_down_phy_copper(hw);
}
/**
* igc_rx_fifo_flush_base - Clean rx fifo after Rx enable
* @hw: pointer to the HW structure
*
* After Rx enable, if manageability is enabled then there is likely some
* bad data at the start of the fifo and possibly in the DMA fifo. This
* function clears the fifos and flushes any packets that came in as rx was
* being enabled.
*/
void igc_rx_fifo_flush_base(struct igc_hw *hw)
{
u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
int i, ms_wait;
/* disable IPv6 options as per hardware errata */
rfctl = rd32(IGC_RFCTL);
rfctl |= IGC_RFCTL_IPV6_EX_DIS;
wr32(IGC_RFCTL, rfctl);
if (!(rd32(IGC_MANC) & IGC_MANC_RCV_TCO_EN))
return;
/* Disable all Rx queues */
for (i = 0; i < 4; i++) {
rxdctl[i] = rd32(IGC_RXDCTL(i));
wr32(IGC_RXDCTL(i),
rxdctl[i] & ~IGC_RXDCTL_QUEUE_ENABLE);
}
/* Poll all queues to verify they have shut down */
for (ms_wait = 0; ms_wait < 10; ms_wait++) {
usleep_range(1000, 2000);
rx_enabled = 0;
for (i = 0; i < 4; i++)
rx_enabled |= rd32(IGC_RXDCTL(i));
if (!(rx_enabled & IGC_RXDCTL_QUEUE_ENABLE))
break;
}
if (ms_wait == 10)
hw_dbg("Queue disable timed out after 10ms\n");
/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
* incoming packets are rejected. Set enable and wait 2ms so that
* any packet that was coming in as RCTL.EN was set is flushed
*/
wr32(IGC_RFCTL, rfctl & ~IGC_RFCTL_LEF);
rlpml = rd32(IGC_RLPML);
wr32(IGC_RLPML, 0);
rctl = rd32(IGC_RCTL);
temp_rctl = rctl & ~(IGC_RCTL_EN | IGC_RCTL_SBP);
temp_rctl |= IGC_RCTL_LPE;
wr32(IGC_RCTL, temp_rctl);
wr32(IGC_RCTL, temp_rctl | IGC_RCTL_EN);
wrfl();
usleep_range(2000, 3000);
/* Enable Rx queues that were previously enabled and restore our
* previous state
*/
for (i = 0; i < 4; i++)
wr32(IGC_RXDCTL(i), rxdctl[i]);
wr32(IGC_RCTL, rctl);
wrfl();
wr32(IGC_RLPML, rlpml);
wr32(IGC_RFCTL, rfctl);
/* Flush receive errors generated by workaround */
rd32(IGC_ROC);
rd32(IGC_RNBC);
rd32(IGC_MPC);
}
static struct igc_mac_operations igc_mac_ops_base = {
.init_hw = igc_init_hw_base,
.check_for_link = igc_check_for_copper_link,
.rar_set = igc_rar_set,
.read_mac_addr = igc_read_mac_addr,
.get_speed_and_duplex = igc_get_speed_and_duplex_copper,
};
static const struct igc_phy_operations igc_phy_ops_base = {
.acquire = igc_acquire_phy_base,
.release = igc_release_phy_base,
.reset = igc_phy_hw_reset,
.read_reg = igc_read_phy_reg_gpy,
.write_reg = igc_write_phy_reg_gpy,
};
const struct igc_info igc_base_info = {
.get_invariants = igc_get_invariants_base,
.mac_ops = &igc_mac_ops_base,
.phy_ops = &igc_phy_ops_base,
};

View File

@@ -0,0 +1,92 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_BASE_H_
#define _IGC_BASE_H_
/* forward declaration */
void igc_rx_fifo_flush_base(struct igc_hw *hw);
void igc_power_down_phy_copper_base(struct igc_hw *hw);
/* Transmit Descriptor - Advanced */
union igc_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;
};
/* Context descriptors */
struct igc_adv_tx_context_desc {
__le32 vlan_macip_lens;
__le32 launch_time;
__le32 type_tucmd_mlhl;
__le32 mss_l4len_idx;
};
/* Adv Transmit Descriptor Config Masks */
#define IGC_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
#define IGC_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
#define IGC_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
#define IGC_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
#define IGC_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
#define IGC_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
#define IGC_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
#define IGC_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
#define IGC_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
#define IGC_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
#define IGC_RAR_ENTRIES 16
/* Receive Descriptor - Advanced */
union igc_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 type, Pkt type*/
/* Split Header, header buffer len */
__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 */
};
/* Additional Transmit Descriptor Control definitions */
#define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
#define IGC_TXDCTL_SWFLUSH 0x04000000 /* Transmit Software Flush */
/* Additional Receive Descriptor Control definitions */
#define IGC_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */
#define IGC_RXDCTL_SWFLUSH 0x04000000 /* Receive Software Flush */
/* SRRCTL bit definitions */
#define IGC_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
#define IGC_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
#define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
#endif /* _IGC_BASE_H */

View File

@@ -0,0 +1,425 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018 Intel Corporation */
#include <linux/delay.h>
#include "igc_hw.h"
#include "igc_i225.h"
#include "igc_mac.h"
#include "igc_base.h"
#include "igc.h"
/**
* igc_reset_hw_base - Reset hardware
* @hw: pointer to the HW structure
*
* This resets the hardware into a known state. This is a
* function pointer entry point called by the api module.
*/
static s32 igc_reset_hw_base(struct igc_hw *hw)
{
s32 ret_val;
u32 ctrl;
/* Prevent the PCI-E bus from sticking if there is no TLP connection
* on the last TLP read/write transaction when MAC is reset.
*/
ret_val = igc_disable_pcie_master(hw);
if (ret_val)
hw_dbg("PCI-E Master disable polling has failed\n");
hw_dbg("Masking off all interrupts\n");
wr32(IGC_IMC, 0xffffffff);
wr32(IGC_RCTL, 0);
wr32(IGC_TCTL, IGC_TCTL_PSP);
wrfl();
usleep_range(10000, 20000);
ctrl = rd32(IGC_CTRL);
hw_dbg("Issuing a global reset to MAC\n");
wr32(IGC_CTRL, ctrl | IGC_CTRL_DEV_RST);
ret_val = igc_get_auto_rd_done(hw);
if (ret_val) {
/* When auto config read does not complete, do not
* return with an error. This can happen in situations
* where there is no eeprom and prevents getting link.
*/
hw_dbg("Auto Read Done did not complete\n");
}
/* Clear any pending interrupt events. */
wr32(IGC_IMC, 0xffffffff);
rd32(IGC_ICR);
return ret_val;
}
/**
* igc_init_nvm_params_base - Init NVM func ptrs.
* @hw: pointer to the HW structure
*/
static s32 igc_init_nvm_params_base(struct igc_hw *hw)
{
struct igc_nvm_info *nvm = &hw->nvm;
u32 eecd = rd32(IGC_EECD);
u16 size;
size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >>
IGC_EECD_SIZE_EX_SHIFT);
/* Added to a constant, "size" becomes the left-shift value
* for setting word_size.
*/
size += NVM_WORD_SIZE_BASE_SHIFT;
/* Just in case size is out of range, cap it to the largest
* EEPROM size supported
*/
if (size > 15)
size = 15;
nvm->type = igc_nvm_eeprom_spi;
nvm->word_size = BIT(size);
nvm->opcode_bits = 8;
nvm->delay_usec = 1;
nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8;
nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ?
16 : 8;
if (nvm->word_size == BIT(15))
nvm->page_size = 128;
return 0;
}
/**
* igc_setup_copper_link_base - Configure copper link settings
* @hw: pointer to the HW structure
*
* Configures the link for auto-neg or forced speed and duplex. Then we check
* for link, once link is established calls to configure collision distance
* and flow control are called.
*/
static s32 igc_setup_copper_link_base(struct igc_hw *hw)
{
s32 ret_val = 0;
u32 ctrl;
ctrl = rd32(IGC_CTRL);
ctrl |= IGC_CTRL_SLU;
ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
wr32(IGC_CTRL, ctrl);
ret_val = igc_setup_copper_link(hw);
return ret_val;
}
/**
* igc_init_mac_params_base - Init MAC func ptrs.
* @hw: pointer to the HW structure
*/
static s32 igc_init_mac_params_base(struct igc_hw *hw)
{
struct igc_dev_spec_base *dev_spec = &hw->dev_spec._base;
struct igc_mac_info *mac = &hw->mac;
/* Set mta register count */
mac->mta_reg_count = 128;
mac->rar_entry_count = IGC_RAR_ENTRIES;
/* reset */
mac->ops.reset_hw = igc_reset_hw_base;
mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225;
mac->ops.release_swfw_sync = igc_release_swfw_sync_i225;
/* Allow a single clear of the SW semaphore on I225 */
if (mac->type == igc_i225)
dev_spec->clear_semaphore_once = true;
/* physical interface link setup */
mac->ops.setup_physical_interface = igc_setup_copper_link_base;
return 0;
}
/**
* igc_init_phy_params_base - Init PHY func ptrs.
* @hw: pointer to the HW structure
*/
static s32 igc_init_phy_params_base(struct igc_hw *hw)
{
struct igc_phy_info *phy = &hw->phy;
s32 ret_val = 0;
if (hw->phy.media_type != igc_media_type_copper) {
phy->type = igc_phy_none;
goto out;
}
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500;
phy->reset_delay_us = 100;
/* set lan id */
hw->bus.func = (rd32(IGC_STATUS) & IGC_STATUS_FUNC_MASK) >>
IGC_STATUS_FUNC_SHIFT;
/* Make sure the PHY is in a good state. Several people have reported
* firmware leaving the PHY's page select register set to something
* other than the default of zero, which causes the PHY ID read to
* access something other than the intended register.
*/
ret_val = hw->phy.ops.reset(hw);
if (ret_val) {
hw_dbg("Error resetting the PHY\n");
goto out;
}
ret_val = igc_get_phy_id(hw);
if (ret_val)
return ret_val;
igc_check_for_copper_link(hw);
phy->type = igc_phy_i225;
out:
return ret_val;
}
static s32 igc_get_invariants_base(struct igc_hw *hw)
{
struct igc_mac_info *mac = &hw->mac;
s32 ret_val = 0;
switch (hw->device_id) {
case IGC_DEV_ID_I225_LM:
case IGC_DEV_ID_I225_V:
case IGC_DEV_ID_I225_I:
case IGC_DEV_ID_I220_V:
case IGC_DEV_ID_I225_K:
case IGC_DEV_ID_I225_K2:
case IGC_DEV_ID_I226_K:
case IGC_DEV_ID_I225_LMVP:
case IGC_DEV_ID_I225_IT:
case IGC_DEV_ID_I226_LM:
case IGC_DEV_ID_I226_V:
case IGC_DEV_ID_I226_IT:
case IGC_DEV_ID_I221_V:
case IGC_DEV_ID_I226_BLANK_NVM:
case IGC_DEV_ID_I225_BLANK_NVM:
mac->type = igc_i225;
break;
default:
return -IGC_ERR_MAC_INIT;
}
hw->phy.media_type = igc_media_type_copper;
/* mac initialization and operations */
ret_val = igc_init_mac_params_base(hw);
if (ret_val)
goto out;
/* NVM initialization */
ret_val = igc_init_nvm_params_base(hw);
switch (hw->mac.type) {
case igc_i225:
ret_val = igc_init_nvm_params_i225(hw);
break;
default:
break;
}
/* setup PHY parameters */
ret_val = igc_init_phy_params_base(hw);
if (ret_val)
goto out;
out:
return ret_val;
}
/**
* igc_acquire_phy_base - Acquire rights to access PHY
* @hw: pointer to the HW structure
*
* Acquire access rights to the correct PHY. This is a
* function pointer entry point called by the api module.
*/
static s32 igc_acquire_phy_base(struct igc_hw *hw)
{
u16 mask = IGC_SWFW_PHY0_SM;
return hw->mac.ops.acquire_swfw_sync(hw, mask);
}
/**
* igc_release_phy_base - Release rights to access PHY
* @hw: pointer to the HW structure
*
* A wrapper to release access rights to the correct PHY. This is a
* function pointer entry point called by the api module.
*/
static void igc_release_phy_base(struct igc_hw *hw)
{
u16 mask = IGC_SWFW_PHY0_SM;
hw->mac.ops.release_swfw_sync(hw, mask);
}
/**
* igc_init_hw_base - Initialize hardware
* @hw: pointer to the HW structure
*
* This inits the hardware readying it for operation.
*/
static s32 igc_init_hw_base(struct igc_hw *hw)
{
struct igc_mac_info *mac = &hw->mac;
u16 i, rar_count = mac->rar_entry_count;
s32 ret_val = 0;
/* Setup the receive address */
igc_init_rx_addrs(hw, rar_count);
/* Zero out the Multicast HASH table */
hw_dbg("Zeroing the MTA\n");
for (i = 0; i < mac->mta_reg_count; i++)
array_wr32(IGC_MTA, i, 0);
/* Zero out the Unicast HASH table */
hw_dbg("Zeroing the UTA\n");
for (i = 0; i < mac->uta_reg_count; i++)
array_wr32(IGC_UTA, i, 0);
/* Setup link and flow control */
ret_val = igc_setup_link(hw);
/* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
* because the symbol error count will increment wildly if there
* is no link.
*/
igc_clear_hw_cntrs_base(hw);
return ret_val;
}
/**
* igc_power_down_phy_copper_base - Remove link during PHY power down
* @hw: pointer to the HW structure
*
* In the case of a PHY power down to save power, or to turn off link during a
* driver unload, or wake on lan is not enabled, remove the link.
*/
void igc_power_down_phy_copper_base(struct igc_hw *hw)
{
/* If the management interface is not enabled, then power down */
if (!(igc_enable_mng_pass_thru(hw) || igc_check_reset_block(hw)))
igc_power_down_phy_copper(hw);
}
/**
* igc_rx_fifo_flush_base - Clean rx fifo after Rx enable
* @hw: pointer to the HW structure
*
* After Rx enable, if manageability is enabled then there is likely some
* bad data at the start of the fifo and possibly in the DMA fifo. This
* function clears the fifos and flushes any packets that came in as rx was
* being enabled.
*/
void igc_rx_fifo_flush_base(struct igc_hw *hw)
{
u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
int i, ms_wait;
/* disable IPv6 options as per hardware errata */
rfctl = rd32(IGC_RFCTL);
rfctl |= IGC_RFCTL_IPV6_EX_DIS;
wr32(IGC_RFCTL, rfctl);
if (!(rd32(IGC_MANC) & IGC_MANC_RCV_TCO_EN))
return;
/* Disable all Rx queues */
for (i = 0; i < 4; i++) {
rxdctl[i] = rd32(IGC_RXDCTL(i));
wr32(IGC_RXDCTL(i),
rxdctl[i] & ~IGC_RXDCTL_QUEUE_ENABLE);
}
/* Poll all queues to verify they have shut down */
for (ms_wait = 0; ms_wait < 10; ms_wait++) {
usleep_range(1000, 2000);
rx_enabled = 0;
for (i = 0; i < 4; i++)
rx_enabled |= rd32(IGC_RXDCTL(i));
if (!(rx_enabled & IGC_RXDCTL_QUEUE_ENABLE))
break;
}
if (ms_wait == 10)
hw_dbg("Queue disable timed out after 10ms\n");
/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
* incoming packets are rejected. Set enable and wait 2ms so that
* any packet that was coming in as RCTL.EN was set is flushed
*/
wr32(IGC_RFCTL, rfctl & ~IGC_RFCTL_LEF);
rlpml = rd32(IGC_RLPML);
wr32(IGC_RLPML, 0);
rctl = rd32(IGC_RCTL);
temp_rctl = rctl & ~(IGC_RCTL_EN | IGC_RCTL_SBP);
temp_rctl |= IGC_RCTL_LPE;
wr32(IGC_RCTL, temp_rctl);
wr32(IGC_RCTL, temp_rctl | IGC_RCTL_EN);
wrfl();
usleep_range(2000, 3000);
/* Enable Rx queues that were previously enabled and restore our
* previous state
*/
for (i = 0; i < 4; i++)
wr32(IGC_RXDCTL(i), rxdctl[i]);
wr32(IGC_RCTL, rctl);
wrfl();
wr32(IGC_RLPML, rlpml);
wr32(IGC_RFCTL, rfctl);
/* Flush receive errors generated by workaround */
rd32(IGC_ROC);
rd32(IGC_RNBC);
rd32(IGC_MPC);
}
static struct igc_mac_operations igc_mac_ops_base = {
.init_hw = igc_init_hw_base,
.check_for_link = igc_check_for_copper_link,
.rar_set = igc_rar_set,
.read_mac_addr = igc_read_mac_addr,
.get_speed_and_duplex = igc_get_speed_and_duplex_copper,
};
static const struct igc_phy_operations igc_phy_ops_base = {
.acquire = igc_acquire_phy_base,
.release = igc_release_phy_base,
.reset = igc_phy_hw_reset,
.read_reg = igc_read_phy_reg_gpy,
.write_reg = igc_write_phy_reg_gpy,
};
const struct igc_info igc_base_info = {
.get_invariants = igc_get_invariants_base,
.mac_ops = &igc_mac_ops_base,
.phy_ops = &igc_phy_ops_base,
};

View File

@@ -0,0 +1,92 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_BASE_H_
#define _IGC_BASE_H_
/* forward declaration */
void igc_rx_fifo_flush_base(struct igc_hw *hw);
void igc_power_down_phy_copper_base(struct igc_hw *hw);
/* Transmit Descriptor - Advanced */
union igc_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;
};
/* Context descriptors */
struct igc_adv_tx_context_desc {
__le32 vlan_macip_lens;
__le32 launch_time;
__le32 type_tucmd_mlhl;
__le32 mss_l4len_idx;
};
/* Adv Transmit Descriptor Config Masks */
#define IGC_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
#define IGC_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
#define IGC_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
#define IGC_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
#define IGC_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
#define IGC_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
#define IGC_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
#define IGC_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
#define IGC_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
#define IGC_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
#define IGC_RAR_ENTRIES 16
/* Receive Descriptor - Advanced */
union igc_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 type, Pkt type*/
/* Split Header, header buffer len */
__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 */
};
/* Additional Transmit Descriptor Control definitions */
#define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
#define IGC_TXDCTL_SWFLUSH 0x04000000 /* Transmit Software Flush */
/* Additional Receive Descriptor Control definitions */
#define IGC_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */
#define IGC_RXDCTL_SWFLUSH 0x04000000 /* Receive Software Flush */
/* SRRCTL bit definitions */
#define IGC_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
#define IGC_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
#define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
#endif /* _IGC_BASE_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,186 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2020 Intel Corporation */
#include "igc-5.15-ethercat.h"
#include "igc_diag-5.15-ethercat.h"
static struct igc_reg_test reg_test[] = {
{ IGC_FCAL, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ IGC_FCAH, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
{ IGC_FCT, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
{ IGC_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ IGC_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
{ IGC_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
{ IGC_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ IGC_FCRTH, 1, PATTERN_TEST, 0x0003FFF0, 0x0003FFF0 },
{ IGC_FCTTV, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ IGC_TIPG, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
{ IGC_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ IGC_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
{ IGC_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
{ IGC_TDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ IGC_RCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0x003FFFFB },
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0xFFFFFFFF },
{ IGC_TCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ IGC_RA, 16, TABLE64_TEST_LO,
0xFFFFFFFF, 0xFFFFFFFF },
{ IGC_RA, 16, TABLE64_TEST_HI,
0x900FFFFF, 0xFFFFFFFF },
{ IGC_MTA, 128, TABLE32_TEST,
0xFFFFFFFF, 0xFFFFFFFF },
{ 0, 0, 0, 0}
};
static bool reg_pattern_test(struct igc_adapter *adapter, u64 *data, int reg,
u32 mask, u32 write)
{
struct igc_hw *hw = &adapter->hw;
u32 pat, val, before;
static const u32 test_pattern[] = {
0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
};
for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
before = rd32(reg);
wr32(reg, test_pattern[pat] & write);
val = rd32(reg);
if (val != (test_pattern[pat] & write & mask)) {
netdev_err(adapter->netdev,
"pattern test reg %04X failed: got 0x%08X expected 0x%08X",
reg, val, test_pattern[pat] & write & mask);
*data = reg;
wr32(reg, before);
return false;
}
wr32(reg, before);
}
return true;
}
static bool reg_set_and_check(struct igc_adapter *adapter, u64 *data, int reg,
u32 mask, u32 write)
{
struct igc_hw *hw = &adapter->hw;
u32 val, before;
before = rd32(reg);
wr32(reg, write & mask);
val = rd32(reg);
if ((write & mask) != (val & mask)) {
netdev_err(adapter->netdev,
"set/check reg %04X test failed: got 0x%08X expected 0x%08X",
reg, (val & mask), (write & mask));
*data = reg;
wr32(reg, before);
return false;
}
wr32(reg, before);
return true;
}
bool igc_reg_test(struct igc_adapter *adapter, u64 *data)
{
struct igc_reg_test *test = reg_test;
struct igc_hw *hw = &adapter->hw;
u32 value, before, after;
u32 i, toggle, b = false;
/* Because the status register is such a special case,
* we handle it separately from the rest of the register
* tests. Some bits are read-only, some toggle, and some
* are writeable.
*/
toggle = 0x6800D3;
before = rd32(IGC_STATUS);
value = before & toggle;
wr32(IGC_STATUS, toggle);
after = rd32(IGC_STATUS) & toggle;
if (value != after) {
netdev_err(adapter->netdev,
"failed STATUS register test got: 0x%08X expected: 0x%08X",
after, value);
*data = 1;
return false;
}
/* restore previous status */
wr32(IGC_STATUS, before);
/* Perform the remainder of the register test, looping through
* the test table until we either fail or reach the null entry.
*/
while (test->reg) {
for (i = 0; i < test->array_len; i++) {
switch (test->test_type) {
case PATTERN_TEST:
b = reg_pattern_test(adapter, data,
test->reg + (i * 0x40),
test->mask,
test->write);
break;
case SET_READ_TEST:
b = reg_set_and_check(adapter, data,
test->reg + (i * 0x40),
test->mask,
test->write);
break;
case TABLE64_TEST_LO:
b = reg_pattern_test(adapter, data,
test->reg + (i * 8),
test->mask,
test->write);
break;
case TABLE64_TEST_HI:
b = reg_pattern_test(adapter, data,
test->reg + 4 + (i * 8),
test->mask,
test->write);
break;
case TABLE32_TEST:
b = reg_pattern_test(adapter, data,
test->reg + (i * 4),
test->mask,
test->write);
break;
}
if (!b)
return false;
}
test++;
}
*data = 0;
return true;
}
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data)
{
struct igc_hw *hw = &adapter->hw;
*data = 0;
if (hw->nvm.ops.validate(hw) != IGC_SUCCESS) {
*data = 1;
return false;
}
return true;
}
bool igc_link_test(struct igc_adapter *adapter, u64 *data)
{
bool link_up;
*data = 0;
/* add delay to give enough time for autonegotioation to finish */
if (adapter->hw.mac.autoneg)
ssleep(5);
link_up = igc_has_link(adapter);
if (!link_up) {
*data = 1;
return false;
}
return true;
}

View File

@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2020 Intel Corporation */
bool igc_reg_test(struct igc_adapter *adapter, u64 *data);
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data);
bool igc_link_test(struct igc_adapter *adapter, u64 *data);
struct igc_reg_test {
u16 reg;
u8 array_len;
u8 test_type;
u32 mask;
u32 write;
};
/* In the hardware, registers are laid out either singly, in arrays
* spaced 0x40 bytes apart, or in contiguous tables. We assume
* most tests take place on arrays or single registers (handled
* as a single-element array) and special-case the tables.
* Table tests are always pattern tests.
*
* We also make provision for some required setup steps by specifying
* registers to be written without any read-back testing.
*/
#define PATTERN_TEST 1
#define SET_READ_TEST 2
#define TABLE32_TEST 3
#define TABLE64_TEST_LO 4
#define TABLE64_TEST_HI 5

View File

@@ -0,0 +1,186 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2020 Intel Corporation */
#include "igc.h"
#include "igc_diag.h"
static struct igc_reg_test reg_test[] = {
{ IGC_FCAL, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ IGC_FCAH, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
{ IGC_FCT, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
{ IGC_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ IGC_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
{ IGC_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
{ IGC_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ IGC_FCRTH, 1, PATTERN_TEST, 0x0003FFF0, 0x0003FFF0 },
{ IGC_FCTTV, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ IGC_TIPG, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
{ IGC_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
{ IGC_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
{ IGC_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
{ IGC_TDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
{ IGC_RCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0x003FFFFB },
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0xFFFFFFFF },
{ IGC_TCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
{ IGC_RA, 16, TABLE64_TEST_LO,
0xFFFFFFFF, 0xFFFFFFFF },
{ IGC_RA, 16, TABLE64_TEST_HI,
0x900FFFFF, 0xFFFFFFFF },
{ IGC_MTA, 128, TABLE32_TEST,
0xFFFFFFFF, 0xFFFFFFFF },
{ 0, 0, 0, 0}
};
static bool reg_pattern_test(struct igc_adapter *adapter, u64 *data, int reg,
u32 mask, u32 write)
{
struct igc_hw *hw = &adapter->hw;
u32 pat, val, before;
static const u32 test_pattern[] = {
0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
};
for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
before = rd32(reg);
wr32(reg, test_pattern[pat] & write);
val = rd32(reg);
if (val != (test_pattern[pat] & write & mask)) {
netdev_err(adapter->netdev,
"pattern test reg %04X failed: got 0x%08X expected 0x%08X",
reg, val, test_pattern[pat] & write & mask);
*data = reg;
wr32(reg, before);
return false;
}
wr32(reg, before);
}
return true;
}
static bool reg_set_and_check(struct igc_adapter *adapter, u64 *data, int reg,
u32 mask, u32 write)
{
struct igc_hw *hw = &adapter->hw;
u32 val, before;
before = rd32(reg);
wr32(reg, write & mask);
val = rd32(reg);
if ((write & mask) != (val & mask)) {
netdev_err(adapter->netdev,
"set/check reg %04X test failed: got 0x%08X expected 0x%08X",
reg, (val & mask), (write & mask));
*data = reg;
wr32(reg, before);
return false;
}
wr32(reg, before);
return true;
}
bool igc_reg_test(struct igc_adapter *adapter, u64 *data)
{
struct igc_reg_test *test = reg_test;
struct igc_hw *hw = &adapter->hw;
u32 value, before, after;
u32 i, toggle, b = false;
/* Because the status register is such a special case,
* we handle it separately from the rest of the register
* tests. Some bits are read-only, some toggle, and some
* are writeable.
*/
toggle = 0x6800D3;
before = rd32(IGC_STATUS);
value = before & toggle;
wr32(IGC_STATUS, toggle);
after = rd32(IGC_STATUS) & toggle;
if (value != after) {
netdev_err(adapter->netdev,
"failed STATUS register test got: 0x%08X expected: 0x%08X",
after, value);
*data = 1;
return false;
}
/* restore previous status */
wr32(IGC_STATUS, before);
/* Perform the remainder of the register test, looping through
* the test table until we either fail or reach the null entry.
*/
while (test->reg) {
for (i = 0; i < test->array_len; i++) {
switch (test->test_type) {
case PATTERN_TEST:
b = reg_pattern_test(adapter, data,
test->reg + (i * 0x40),
test->mask,
test->write);
break;
case SET_READ_TEST:
b = reg_set_and_check(adapter, data,
test->reg + (i * 0x40),
test->mask,
test->write);
break;
case TABLE64_TEST_LO:
b = reg_pattern_test(adapter, data,
test->reg + (i * 8),
test->mask,
test->write);
break;
case TABLE64_TEST_HI:
b = reg_pattern_test(adapter, data,
test->reg + 4 + (i * 8),
test->mask,
test->write);
break;
case TABLE32_TEST:
b = reg_pattern_test(adapter, data,
test->reg + (i * 4),
test->mask,
test->write);
break;
}
if (!b)
return false;
}
test++;
}
*data = 0;
return true;
}
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data)
{
struct igc_hw *hw = &adapter->hw;
*data = 0;
if (hw->nvm.ops.validate(hw) != IGC_SUCCESS) {
*data = 1;
return false;
}
return true;
}
bool igc_link_test(struct igc_adapter *adapter, u64 *data)
{
bool link_up;
*data = 0;
/* add delay to give enough time for autonegotioation to finish */
if (adapter->hw.mac.autoneg)
ssleep(5);
link_up = igc_has_link(adapter);
if (!link_up) {
*data = 1;
return false;
}
return true;
}

View File

@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2020 Intel Corporation */
bool igc_reg_test(struct igc_adapter *adapter, u64 *data);
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data);
bool igc_link_test(struct igc_adapter *adapter, u64 *data);
struct igc_reg_test {
u16 reg;
u8 array_len;
u8 test_type;
u32 mask;
u32 write;
};
/* In the hardware, registers are laid out either singly, in arrays
* spaced 0x40 bytes apart, or in contiguous tables. We assume
* most tests take place on arrays or single registers (handled
* as a single-element array) and special-case the tables.
* Table tests are always pattern tests.
*
* We also make provision for some required setup steps by specifying
* registers to be written without any read-back testing.
*/
#define PATTERN_TEST 1
#define SET_READ_TEST 2
#define TABLE32_TEST 3
#define TABLE64_TEST_LO 4
#define TABLE64_TEST_HI 5

View File

@@ -0,0 +1,318 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018 Intel Corporation */
#include "igc-5.15-ethercat.h"
struct igc_reg_info {
u32 ofs;
char *name;
};
static const struct igc_reg_info igc_reg_info_tbl[] = {
/* General Registers */
{IGC_CTRL, "CTRL"},
{IGC_STATUS, "STATUS"},
{IGC_CTRL_EXT, "CTRL_EXT"},
{IGC_MDIC, "MDIC"},
/* Interrupt Registers */
{IGC_ICR, "ICR"},
/* RX Registers */
{IGC_RCTL, "RCTL"},
{IGC_RDLEN(0), "RDLEN"},
{IGC_RDH(0), "RDH"},
{IGC_RDT(0), "RDT"},
{IGC_RXDCTL(0), "RXDCTL"},
{IGC_RDBAL(0), "RDBAL"},
{IGC_RDBAH(0), "RDBAH"},
/* TX Registers */
{IGC_TCTL, "TCTL"},
{IGC_TDBAL(0), "TDBAL"},
{IGC_TDBAH(0), "TDBAH"},
{IGC_TDLEN(0), "TDLEN"},
{IGC_TDH(0), "TDH"},
{IGC_TDT(0), "TDT"},
{IGC_TXDCTL(0), "TXDCTL"},
/* List Terminator */
{}
};
/* igc_regdump - register printout routine */
static void igc_regdump(struct igc_hw *hw, struct igc_reg_info *reginfo)
{
struct net_device *dev = igc_get_hw_dev(hw);
int n = 0;
char rname[16];
u32 regs[8];
switch (reginfo->ofs) {
case IGC_RDLEN(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RDLEN(n));
break;
case IGC_RDH(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RDH(n));
break;
case IGC_RDT(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RDT(n));
break;
case IGC_RXDCTL(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RXDCTL(n));
break;
case IGC_RDBAL(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RDBAL(n));
break;
case IGC_RDBAH(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RDBAH(n));
break;
case IGC_TDBAL(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TDBAL(n));
break;
case IGC_TDBAH(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TDBAH(n));
break;
case IGC_TDLEN(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TDLEN(n));
break;
case IGC_TDH(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TDH(n));
break;
case IGC_TDT(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TDT(n));
break;
case IGC_TXDCTL(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TXDCTL(n));
break;
default:
netdev_info(dev, "%-15s %08x\n", reginfo->name,
rd32(reginfo->ofs));
return;
}
snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]");
netdev_info(dev, "%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1],
regs[2], regs[3]);
}
/* igc_rings_dump - Tx-rings and Rx-rings */
void igc_rings_dump(struct igc_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct my_u0 { __le64 a; __le64 b; } *u0;
union igc_adv_tx_desc *tx_desc;
union igc_adv_rx_desc *rx_desc;
struct igc_ring *tx_ring;
struct igc_ring *rx_ring;
u32 staterr;
u16 i, n;
if (!netif_msg_hw(adapter))
return;
netdev_info(netdev, "Device info: state %016lX trans_start %016lX\n",
netdev->state, dev_trans_start(netdev));
/* Print TX Ring Summary */
if (!netif_running(netdev))
goto exit;
netdev_info(netdev, "TX Rings Summary\n");
netdev_info(netdev, "Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n");
for (n = 0; n < adapter->num_tx_queues; n++) {
struct igc_tx_buffer *buffer_info;
tx_ring = adapter->tx_ring[n];
buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean];
netdev_info(netdev, "%5d %5X %5X %016llX %04X %p %016llX\n",
n, tx_ring->next_to_use, tx_ring->next_to_clean,
(u64)dma_unmap_addr(buffer_info, dma),
dma_unmap_len(buffer_info, len),
buffer_info->next_to_watch,
(u64)buffer_info->time_stamp);
}
/* Print TX Rings */
if (!netif_msg_tx_done(adapter))
goto rx_ring_summary;
netdev_info(netdev, "TX Rings Dump\n");
/* Transmit Descriptor Formats
*
* Advanced Transmit Descriptor
* +--------------------------------------------------------------+
* 0 | Buffer Address [63:0] |
* +--------------------------------------------------------------+
* 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN |
* +--------------------------------------------------------------+
* 63 46 45 40 39 38 36 35 32 31 24 15 0
*/
for (n = 0; n < adapter->num_tx_queues; n++) {
tx_ring = adapter->tx_ring[n];
netdev_info(netdev, "------------------------------------\n");
netdev_info(netdev, "TX QUEUE INDEX = %d\n",
tx_ring->queue_index);
netdev_info(netdev, "------------------------------------\n");
netdev_info(netdev, "T [desc] [address 63:0 ] [PlPOCIStDDM Ln] [bi->dma ] leng ntw timestamp bi->skb\n");
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
const char *next_desc;
struct igc_tx_buffer *buffer_info;
tx_desc = IGC_TX_DESC(tx_ring, i);
buffer_info = &tx_ring->tx_buffer_info[i];
u0 = (struct my_u0 *)tx_desc;
if (i == tx_ring->next_to_use &&
i == tx_ring->next_to_clean)
next_desc = " NTC/U";
else if (i == tx_ring->next_to_use)
next_desc = " NTU";
else if (i == tx_ring->next_to_clean)
next_desc = " NTC";
else
next_desc = "";
netdev_info(netdev, "T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n",
i, le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
(u64)dma_unmap_addr(buffer_info, dma),
dma_unmap_len(buffer_info, len),
buffer_info->next_to_watch,
(u64)buffer_info->time_stamp,
buffer_info->skb, next_desc);
if (netif_msg_pktdata(adapter) && buffer_info->skb)
print_hex_dump(KERN_INFO, "",
DUMP_PREFIX_ADDRESS,
16, 1, buffer_info->skb->data,
dma_unmap_len(buffer_info, len),
true);
}
}
/* Print RX Rings Summary */
rx_ring_summary:
netdev_info(netdev, "RX Rings Summary\n");
netdev_info(netdev, "Queue [NTU] [NTC]\n");
for (n = 0; n < adapter->num_rx_queues; n++) {
rx_ring = adapter->rx_ring[n];
netdev_info(netdev, "%5d %5X %5X\n", n, rx_ring->next_to_use,
rx_ring->next_to_clean);
}
/* Print RX Rings */
if (!netif_msg_rx_status(adapter))
goto exit;
netdev_info(netdev, "RX Rings Dump\n");
/* Advanced Receive Descriptor (Read) Format
* 63 1 0
* +-----------------------------------------------------+
* 0 | Packet Buffer Address [63:1] |A0/NSE|
* +----------------------------------------------+------+
* 8 | Header Buffer Address [63:1] | DD |
* +-----------------------------------------------------+
*
*
* Advanced Receive Descriptor (Write-Back) Format
*
* 63 48 47 32 31 30 21 20 17 16 4 3 0
* +------------------------------------------------------+
* 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS |
* | Checksum Ident | | | | Type | Type |
* +------------------------------------------------------+
* 8 | VLAN Tag | Length | Extended Error | Extended Status |
* +------------------------------------------------------+
* 63 48 47 32 31 20 19 0
*/
for (n = 0; n < adapter->num_rx_queues; n++) {
rx_ring = adapter->rx_ring[n];
netdev_info(netdev, "------------------------------------\n");
netdev_info(netdev, "RX QUEUE INDEX = %d\n",
rx_ring->queue_index);
netdev_info(netdev, "------------------------------------\n");
netdev_info(netdev, "R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n");
netdev_info(netdev, "RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] ---------------- [bi->skb] <-- Adv Rx Write-Back format\n");
for (i = 0; i < rx_ring->count; i++) {
const char *next_desc;
struct igc_rx_buffer *buffer_info;
buffer_info = &rx_ring->rx_buffer_info[i];
rx_desc = IGC_RX_DESC(rx_ring, i);
u0 = (struct my_u0 *)rx_desc;
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
if (i == rx_ring->next_to_use)
next_desc = " NTU";
else if (i == rx_ring->next_to_clean)
next_desc = " NTC";
else
next_desc = "";
if (staterr & IGC_RXD_STAT_DD) {
/* Descriptor Done */
netdev_info(netdev, "%s[0x%03X] %016llX %016llX ---------------- %s\n",
"RWB", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
next_desc);
} else {
netdev_info(netdev, "%s[0x%03X] %016llX %016llX %016llX %s\n",
"R ", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
(u64)buffer_info->dma,
next_desc);
if (netif_msg_pktdata(adapter) &&
buffer_info->dma && buffer_info->page) {
print_hex_dump(KERN_INFO, "",
DUMP_PREFIX_ADDRESS,
16, 1,
page_address
(buffer_info->page) +
buffer_info->page_offset,
igc_rx_bufsz(rx_ring),
true);
}
}
}
}
exit:
return;
}
/* igc_regs_dump - registers dump */
void igc_regs_dump(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
struct igc_reg_info *reginfo;
/* Print Registers */
netdev_info(adapter->netdev, "Register Dump\n");
netdev_info(adapter->netdev, "Register Name Value\n");
for (reginfo = (struct igc_reg_info *)igc_reg_info_tbl;
reginfo->name; reginfo++) {
igc_regdump(hw, reginfo);
}
}

View File

@@ -0,0 +1,318 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018 Intel Corporation */
#include "igc.h"
struct igc_reg_info {
u32 ofs;
char *name;
};
static const struct igc_reg_info igc_reg_info_tbl[] = {
/* General Registers */
{IGC_CTRL, "CTRL"},
{IGC_STATUS, "STATUS"},
{IGC_CTRL_EXT, "CTRL_EXT"},
{IGC_MDIC, "MDIC"},
/* Interrupt Registers */
{IGC_ICR, "ICR"},
/* RX Registers */
{IGC_RCTL, "RCTL"},
{IGC_RDLEN(0), "RDLEN"},
{IGC_RDH(0), "RDH"},
{IGC_RDT(0), "RDT"},
{IGC_RXDCTL(0), "RXDCTL"},
{IGC_RDBAL(0), "RDBAL"},
{IGC_RDBAH(0), "RDBAH"},
/* TX Registers */
{IGC_TCTL, "TCTL"},
{IGC_TDBAL(0), "TDBAL"},
{IGC_TDBAH(0), "TDBAH"},
{IGC_TDLEN(0), "TDLEN"},
{IGC_TDH(0), "TDH"},
{IGC_TDT(0), "TDT"},
{IGC_TXDCTL(0), "TXDCTL"},
/* List Terminator */
{}
};
/* igc_regdump - register printout routine */
static void igc_regdump(struct igc_hw *hw, struct igc_reg_info *reginfo)
{
struct net_device *dev = igc_get_hw_dev(hw);
int n = 0;
char rname[16];
u32 regs[8];
switch (reginfo->ofs) {
case IGC_RDLEN(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RDLEN(n));
break;
case IGC_RDH(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RDH(n));
break;
case IGC_RDT(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RDT(n));
break;
case IGC_RXDCTL(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RXDCTL(n));
break;
case IGC_RDBAL(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RDBAL(n));
break;
case IGC_RDBAH(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_RDBAH(n));
break;
case IGC_TDBAL(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TDBAL(n));
break;
case IGC_TDBAH(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TDBAH(n));
break;
case IGC_TDLEN(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TDLEN(n));
break;
case IGC_TDH(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TDH(n));
break;
case IGC_TDT(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TDT(n));
break;
case IGC_TXDCTL(0):
for (n = 0; n < 4; n++)
regs[n] = rd32(IGC_TXDCTL(n));
break;
default:
netdev_info(dev, "%-15s %08x\n", reginfo->name,
rd32(reginfo->ofs));
return;
}
snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]");
netdev_info(dev, "%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1],
regs[2], regs[3]);
}
/* igc_rings_dump - Tx-rings and Rx-rings */
void igc_rings_dump(struct igc_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
struct my_u0 { __le64 a; __le64 b; } *u0;
union igc_adv_tx_desc *tx_desc;
union igc_adv_rx_desc *rx_desc;
struct igc_ring *tx_ring;
struct igc_ring *rx_ring;
u32 staterr;
u16 i, n;
if (!netif_msg_hw(adapter))
return;
netdev_info(netdev, "Device info: state %016lX trans_start %016lX\n",
netdev->state, dev_trans_start(netdev));
/* Print TX Ring Summary */
if (!netif_running(netdev))
goto exit;
netdev_info(netdev, "TX Rings Summary\n");
netdev_info(netdev, "Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n");
for (n = 0; n < adapter->num_tx_queues; n++) {
struct igc_tx_buffer *buffer_info;
tx_ring = adapter->tx_ring[n];
buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean];
netdev_info(netdev, "%5d %5X %5X %016llX %04X %p %016llX\n",
n, tx_ring->next_to_use, tx_ring->next_to_clean,
(u64)dma_unmap_addr(buffer_info, dma),
dma_unmap_len(buffer_info, len),
buffer_info->next_to_watch,
(u64)buffer_info->time_stamp);
}
/* Print TX Rings */
if (!netif_msg_tx_done(adapter))
goto rx_ring_summary;
netdev_info(netdev, "TX Rings Dump\n");
/* Transmit Descriptor Formats
*
* Advanced Transmit Descriptor
* +--------------------------------------------------------------+
* 0 | Buffer Address [63:0] |
* +--------------------------------------------------------------+
* 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN |
* +--------------------------------------------------------------+
* 63 46 45 40 39 38 36 35 32 31 24 15 0
*/
for (n = 0; n < adapter->num_tx_queues; n++) {
tx_ring = adapter->tx_ring[n];
netdev_info(netdev, "------------------------------------\n");
netdev_info(netdev, "TX QUEUE INDEX = %d\n",
tx_ring->queue_index);
netdev_info(netdev, "------------------------------------\n");
netdev_info(netdev, "T [desc] [address 63:0 ] [PlPOCIStDDM Ln] [bi->dma ] leng ntw timestamp bi->skb\n");
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
const char *next_desc;
struct igc_tx_buffer *buffer_info;
tx_desc = IGC_TX_DESC(tx_ring, i);
buffer_info = &tx_ring->tx_buffer_info[i];
u0 = (struct my_u0 *)tx_desc;
if (i == tx_ring->next_to_use &&
i == tx_ring->next_to_clean)
next_desc = " NTC/U";
else if (i == tx_ring->next_to_use)
next_desc = " NTU";
else if (i == tx_ring->next_to_clean)
next_desc = " NTC";
else
next_desc = "";
netdev_info(netdev, "T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n",
i, le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
(u64)dma_unmap_addr(buffer_info, dma),
dma_unmap_len(buffer_info, len),
buffer_info->next_to_watch,
(u64)buffer_info->time_stamp,
buffer_info->skb, next_desc);
if (netif_msg_pktdata(adapter) && buffer_info->skb)
print_hex_dump(KERN_INFO, "",
DUMP_PREFIX_ADDRESS,
16, 1, buffer_info->skb->data,
dma_unmap_len(buffer_info, len),
true);
}
}
/* Print RX Rings Summary */
rx_ring_summary:
netdev_info(netdev, "RX Rings Summary\n");
netdev_info(netdev, "Queue [NTU] [NTC]\n");
for (n = 0; n < adapter->num_rx_queues; n++) {
rx_ring = adapter->rx_ring[n];
netdev_info(netdev, "%5d %5X %5X\n", n, rx_ring->next_to_use,
rx_ring->next_to_clean);
}
/* Print RX Rings */
if (!netif_msg_rx_status(adapter))
goto exit;
netdev_info(netdev, "RX Rings Dump\n");
/* Advanced Receive Descriptor (Read) Format
* 63 1 0
* +-----------------------------------------------------+
* 0 | Packet Buffer Address [63:1] |A0/NSE|
* +----------------------------------------------+------+
* 8 | Header Buffer Address [63:1] | DD |
* +-----------------------------------------------------+
*
*
* Advanced Receive Descriptor (Write-Back) Format
*
* 63 48 47 32 31 30 21 20 17 16 4 3 0
* +------------------------------------------------------+
* 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS |
* | Checksum Ident | | | | Type | Type |
* +------------------------------------------------------+
* 8 | VLAN Tag | Length | Extended Error | Extended Status |
* +------------------------------------------------------+
* 63 48 47 32 31 20 19 0
*/
for (n = 0; n < adapter->num_rx_queues; n++) {
rx_ring = adapter->rx_ring[n];
netdev_info(netdev, "------------------------------------\n");
netdev_info(netdev, "RX QUEUE INDEX = %d\n",
rx_ring->queue_index);
netdev_info(netdev, "------------------------------------\n");
netdev_info(netdev, "R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n");
netdev_info(netdev, "RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] ---------------- [bi->skb] <-- Adv Rx Write-Back format\n");
for (i = 0; i < rx_ring->count; i++) {
const char *next_desc;
struct igc_rx_buffer *buffer_info;
buffer_info = &rx_ring->rx_buffer_info[i];
rx_desc = IGC_RX_DESC(rx_ring, i);
u0 = (struct my_u0 *)rx_desc;
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
if (i == rx_ring->next_to_use)
next_desc = " NTU";
else if (i == rx_ring->next_to_clean)
next_desc = " NTC";
else
next_desc = "";
if (staterr & IGC_RXD_STAT_DD) {
/* Descriptor Done */
netdev_info(netdev, "%s[0x%03X] %016llX %016llX ---------------- %s\n",
"RWB", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
next_desc);
} else {
netdev_info(netdev, "%s[0x%03X] %016llX %016llX %016llX %s\n",
"R ", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
(u64)buffer_info->dma,
next_desc);
if (netif_msg_pktdata(adapter) &&
buffer_info->dma && buffer_info->page) {
print_hex_dump(KERN_INFO, "",
DUMP_PREFIX_ADDRESS,
16, 1,
page_address
(buffer_info->page) +
buffer_info->page_offset,
igc_rx_bufsz(rx_ring),
true);
}
}
}
}
exit:
return;
}
/* igc_regs_dump - registers dump */
void igc_regs_dump(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
struct igc_reg_info *reginfo;
/* Print Registers */
netdev_info(adapter->netdev, "Register Dump\n");
netdev_info(adapter->netdev, "Register Name Value\n");
for (reginfo = (struct igc_reg_info *)igc_reg_info_tbl;
reginfo->name; reginfo++) {
igc_regdump(hw, reginfo);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,298 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_HW_H_
#define _IGC_HW_H_
#include <linux/types.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include "igc_regs-5.15-ethercat.h"
#include "igc_defines-5.15-ethercat.h"
#include "igc_mac-5.15-ethercat.h"
#include "igc_phy-5.15-ethercat.h"
#include "igc_nvm-5.15-ethercat.h"
#include "igc_i225-5.15-ethercat.h"
#include "igc_base-5.15-ethercat.h"
#define IGC_DEV_ID_I225_LM 0x15F2
#define IGC_DEV_ID_I225_V 0x15F3
#define IGC_DEV_ID_I225_I 0x15F8
#define IGC_DEV_ID_I220_V 0x15F7
#define IGC_DEV_ID_I225_K 0x3100
#define IGC_DEV_ID_I225_K2 0x3101
#define IGC_DEV_ID_I226_K 0x3102
#define IGC_DEV_ID_I225_LMVP 0x5502
#define IGC_DEV_ID_I225_IT 0x0D9F
#define IGC_DEV_ID_I226_LM 0x125B
#define IGC_DEV_ID_I226_V 0x125C
#define IGC_DEV_ID_I226_IT 0x125D
#define IGC_DEV_ID_I221_V 0x125E
#define IGC_DEV_ID_I226_BLANK_NVM 0x125F
#define IGC_DEV_ID_I225_BLANK_NVM 0x15FD
/* Function pointers for the MAC. */
struct igc_mac_operations {
s32 (*check_for_link)(struct igc_hw *hw);
s32 (*reset_hw)(struct igc_hw *hw);
s32 (*init_hw)(struct igc_hw *hw);
s32 (*setup_physical_interface)(struct igc_hw *hw);
void (*rar_set)(struct igc_hw *hw, u8 *address, u32 index);
s32 (*read_mac_addr)(struct igc_hw *hw);
s32 (*get_speed_and_duplex)(struct igc_hw *hw, u16 *speed,
u16 *duplex);
s32 (*acquire_swfw_sync)(struct igc_hw *hw, u16 mask);
void (*release_swfw_sync)(struct igc_hw *hw, u16 mask);
};
enum igc_mac_type {
igc_undefined = 0,
igc_i225,
igc_num_macs /* List is 1-based, so subtract 1 for true count. */
};
enum igc_phy_type {
igc_phy_unknown = 0,
igc_phy_none,
igc_phy_i225,
};
enum igc_media_type {
igc_media_type_unknown = 0,
igc_media_type_copper = 1,
igc_num_media_types
};
enum igc_nvm_type {
igc_nvm_unknown = 0,
igc_nvm_eeprom_spi,
igc_nvm_flash_hw,
igc_nvm_invm,
};
struct igc_info {
s32 (*get_invariants)(struct igc_hw *hw);
struct igc_mac_operations *mac_ops;
const struct igc_phy_operations *phy_ops;
struct igc_nvm_operations *nvm_ops;
};
extern const struct igc_info igc_base_info;
struct igc_mac_info {
struct igc_mac_operations ops;
u8 addr[ETH_ALEN];
u8 perm_addr[ETH_ALEN];
enum igc_mac_type type;
u32 mc_filter_type;
u16 mta_reg_count;
u16 uta_reg_count;
u32 mta_shadow[MAX_MTA_REG];
u16 rar_entry_count;
u8 forced_speed_duplex;
bool asf_firmware_present;
bool arc_subsystem_valid;
bool autoneg;
bool autoneg_failed;
bool get_link_status;
};
struct igc_nvm_operations {
s32 (*acquire)(struct igc_hw *hw);
s32 (*read)(struct igc_hw *hw, u16 offset, u16 i, u16 *data);
void (*release)(struct igc_hw *hw);
s32 (*write)(struct igc_hw *hw, u16 offset, u16 i, u16 *data);
s32 (*update)(struct igc_hw *hw);
s32 (*validate)(struct igc_hw *hw);
};
struct igc_phy_operations {
s32 (*acquire)(struct igc_hw *hw);
s32 (*check_reset_block)(struct igc_hw *hw);
s32 (*force_speed_duplex)(struct igc_hw *hw);
s32 (*get_phy_info)(struct igc_hw *hw);
s32 (*read_reg)(struct igc_hw *hw, u32 address, u16 *data);
void (*release)(struct igc_hw *hw);
s32 (*reset)(struct igc_hw *hw);
s32 (*write_reg)(struct igc_hw *hw, u32 address, u16 data);
};
struct igc_nvm_info {
struct igc_nvm_operations ops;
enum igc_nvm_type type;
u16 word_size;
u16 delay_usec;
u16 address_bits;
u16 opcode_bits;
u16 page_size;
};
struct igc_phy_info {
struct igc_phy_operations ops;
enum igc_phy_type type;
u32 addr;
u32 id;
u32 reset_delay_us; /* in usec */
u32 revision;
enum igc_media_type media_type;
u16 autoneg_advertised;
u16 autoneg_mask;
u8 mdix;
bool is_mdix;
bool speed_downgraded;
bool autoneg_wait_to_complete;
};
struct igc_bus_info {
u16 func;
u16 pci_cmd_word;
};
enum igc_fc_mode {
igc_fc_none = 0,
igc_fc_rx_pause,
igc_fc_tx_pause,
igc_fc_full,
igc_fc_default = 0xFF
};
struct igc_fc_info {
u32 high_water; /* Flow control high-water mark */
u32 low_water; /* Flow control low-water mark */
u16 pause_time; /* Flow control pause timer */
bool send_xon; /* Flow control send XON */
bool strict_ieee; /* Strict IEEE mode */
enum igc_fc_mode current_mode; /* Type of flow control */
enum igc_fc_mode requested_mode;
};
struct igc_dev_spec_base {
bool clear_semaphore_once;
bool eee_enable;
};
struct igc_hw {
void *back;
u8 __iomem *hw_addr;
unsigned long io_base;
struct igc_mac_info mac;
struct igc_fc_info fc;
struct igc_nvm_info nvm;
struct igc_phy_info phy;
struct igc_bus_info bus;
union {
struct igc_dev_spec_base _base;
} dev_spec;
u16 device_id;
u16 subsystem_vendor_id;
u16 subsystem_device_id;
u16 vendor_id;
u8 revision_id;
};
/* Statistics counters collected by the MAC */
struct igc_hw_stats {
u64 crcerrs;
u64 algnerrc;
u64 symerrs;
u64 rxerrc;
u64 mpc;
u64 scc;
u64 ecol;
u64 mcc;
u64 latecol;
u64 colc;
u64 dc;
u64 tncrs;
u64 sec;
u64 cexterr;
u64 rlec;
u64 xonrxc;
u64 xontxc;
u64 xoffrxc;
u64 xofftxc;
u64 fcruc;
u64 prc64;
u64 prc127;
u64 prc255;
u64 prc511;
u64 prc1023;
u64 prc1522;
u64 tlpic;
u64 rlpic;
u64 gprc;
u64 bprc;
u64 mprc;
u64 gptc;
u64 gorc;
u64 gotc;
u64 rnbc;
u64 ruc;
u64 rfc;
u64 roc;
u64 rjc;
u64 mgprc;
u64 mgpdc;
u64 mgptc;
u64 tor;
u64 tot;
u64 tpr;
u64 tpt;
u64 ptc64;
u64 ptc127;
u64 ptc255;
u64 ptc511;
u64 ptc1023;
u64 ptc1522;
u64 mptc;
u64 bptc;
u64 tsctc;
u64 tsctfc;
u64 iac;
u64 htdpmc;
u64 rpthc;
u64 hgptc;
u64 hgorc;
u64 hgotc;
u64 lenerrs;
u64 scvpc;
u64 hrmpc;
u64 doosync;
u64 o2bgptc;
u64 o2bspc;
u64 b2ospc;
u64 b2ogprc;
};
struct net_device *igc_get_hw_dev(struct igc_hw *hw);
#define hw_dbg(format, arg...) \
netdev_dbg(igc_get_hw_dev(hw), format, ##arg)
s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
#endif /* _IGC_HW_H_ */

View File

@@ -0,0 +1,298 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_HW_H_
#define _IGC_HW_H_
#include <linux/types.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include "igc_regs.h"
#include "igc_defines.h"
#include "igc_mac.h"
#include "igc_phy.h"
#include "igc_nvm.h"
#include "igc_i225.h"
#include "igc_base.h"
#define IGC_DEV_ID_I225_LM 0x15F2
#define IGC_DEV_ID_I225_V 0x15F3
#define IGC_DEV_ID_I225_I 0x15F8
#define IGC_DEV_ID_I220_V 0x15F7
#define IGC_DEV_ID_I225_K 0x3100
#define IGC_DEV_ID_I225_K2 0x3101
#define IGC_DEV_ID_I226_K 0x3102
#define IGC_DEV_ID_I225_LMVP 0x5502
#define IGC_DEV_ID_I225_IT 0x0D9F
#define IGC_DEV_ID_I226_LM 0x125B
#define IGC_DEV_ID_I226_V 0x125C
#define IGC_DEV_ID_I226_IT 0x125D
#define IGC_DEV_ID_I221_V 0x125E
#define IGC_DEV_ID_I226_BLANK_NVM 0x125F
#define IGC_DEV_ID_I225_BLANK_NVM 0x15FD
/* Function pointers for the MAC. */
struct igc_mac_operations {
s32 (*check_for_link)(struct igc_hw *hw);
s32 (*reset_hw)(struct igc_hw *hw);
s32 (*init_hw)(struct igc_hw *hw);
s32 (*setup_physical_interface)(struct igc_hw *hw);
void (*rar_set)(struct igc_hw *hw, u8 *address, u32 index);
s32 (*read_mac_addr)(struct igc_hw *hw);
s32 (*get_speed_and_duplex)(struct igc_hw *hw, u16 *speed,
u16 *duplex);
s32 (*acquire_swfw_sync)(struct igc_hw *hw, u16 mask);
void (*release_swfw_sync)(struct igc_hw *hw, u16 mask);
};
enum igc_mac_type {
igc_undefined = 0,
igc_i225,
igc_num_macs /* List is 1-based, so subtract 1 for true count. */
};
enum igc_phy_type {
igc_phy_unknown = 0,
igc_phy_none,
igc_phy_i225,
};
enum igc_media_type {
igc_media_type_unknown = 0,
igc_media_type_copper = 1,
igc_num_media_types
};
enum igc_nvm_type {
igc_nvm_unknown = 0,
igc_nvm_eeprom_spi,
igc_nvm_flash_hw,
igc_nvm_invm,
};
struct igc_info {
s32 (*get_invariants)(struct igc_hw *hw);
struct igc_mac_operations *mac_ops;
const struct igc_phy_operations *phy_ops;
struct igc_nvm_operations *nvm_ops;
};
extern const struct igc_info igc_base_info;
struct igc_mac_info {
struct igc_mac_operations ops;
u8 addr[ETH_ALEN];
u8 perm_addr[ETH_ALEN];
enum igc_mac_type type;
u32 mc_filter_type;
u16 mta_reg_count;
u16 uta_reg_count;
u32 mta_shadow[MAX_MTA_REG];
u16 rar_entry_count;
u8 forced_speed_duplex;
bool asf_firmware_present;
bool arc_subsystem_valid;
bool autoneg;
bool autoneg_failed;
bool get_link_status;
};
struct igc_nvm_operations {
s32 (*acquire)(struct igc_hw *hw);
s32 (*read)(struct igc_hw *hw, u16 offset, u16 i, u16 *data);
void (*release)(struct igc_hw *hw);
s32 (*write)(struct igc_hw *hw, u16 offset, u16 i, u16 *data);
s32 (*update)(struct igc_hw *hw);
s32 (*validate)(struct igc_hw *hw);
};
struct igc_phy_operations {
s32 (*acquire)(struct igc_hw *hw);
s32 (*check_reset_block)(struct igc_hw *hw);
s32 (*force_speed_duplex)(struct igc_hw *hw);
s32 (*get_phy_info)(struct igc_hw *hw);
s32 (*read_reg)(struct igc_hw *hw, u32 address, u16 *data);
void (*release)(struct igc_hw *hw);
s32 (*reset)(struct igc_hw *hw);
s32 (*write_reg)(struct igc_hw *hw, u32 address, u16 data);
};
struct igc_nvm_info {
struct igc_nvm_operations ops;
enum igc_nvm_type type;
u16 word_size;
u16 delay_usec;
u16 address_bits;
u16 opcode_bits;
u16 page_size;
};
struct igc_phy_info {
struct igc_phy_operations ops;
enum igc_phy_type type;
u32 addr;
u32 id;
u32 reset_delay_us; /* in usec */
u32 revision;
enum igc_media_type media_type;
u16 autoneg_advertised;
u16 autoneg_mask;
u8 mdix;
bool is_mdix;
bool speed_downgraded;
bool autoneg_wait_to_complete;
};
struct igc_bus_info {
u16 func;
u16 pci_cmd_word;
};
enum igc_fc_mode {
igc_fc_none = 0,
igc_fc_rx_pause,
igc_fc_tx_pause,
igc_fc_full,
igc_fc_default = 0xFF
};
struct igc_fc_info {
u32 high_water; /* Flow control high-water mark */
u32 low_water; /* Flow control low-water mark */
u16 pause_time; /* Flow control pause timer */
bool send_xon; /* Flow control send XON */
bool strict_ieee; /* Strict IEEE mode */
enum igc_fc_mode current_mode; /* Type of flow control */
enum igc_fc_mode requested_mode;
};
struct igc_dev_spec_base {
bool clear_semaphore_once;
bool eee_enable;
};
struct igc_hw {
void *back;
u8 __iomem *hw_addr;
unsigned long io_base;
struct igc_mac_info mac;
struct igc_fc_info fc;
struct igc_nvm_info nvm;
struct igc_phy_info phy;
struct igc_bus_info bus;
union {
struct igc_dev_spec_base _base;
} dev_spec;
u16 device_id;
u16 subsystem_vendor_id;
u16 subsystem_device_id;
u16 vendor_id;
u8 revision_id;
};
/* Statistics counters collected by the MAC */
struct igc_hw_stats {
u64 crcerrs;
u64 algnerrc;
u64 symerrs;
u64 rxerrc;
u64 mpc;
u64 scc;
u64 ecol;
u64 mcc;
u64 latecol;
u64 colc;
u64 dc;
u64 tncrs;
u64 sec;
u64 cexterr;
u64 rlec;
u64 xonrxc;
u64 xontxc;
u64 xoffrxc;
u64 xofftxc;
u64 fcruc;
u64 prc64;
u64 prc127;
u64 prc255;
u64 prc511;
u64 prc1023;
u64 prc1522;
u64 tlpic;
u64 rlpic;
u64 gprc;
u64 bprc;
u64 mprc;
u64 gptc;
u64 gorc;
u64 gotc;
u64 rnbc;
u64 ruc;
u64 rfc;
u64 roc;
u64 rjc;
u64 mgprc;
u64 mgpdc;
u64 mgptc;
u64 tor;
u64 tot;
u64 tpr;
u64 tpt;
u64 ptc64;
u64 ptc127;
u64 ptc255;
u64 ptc511;
u64 ptc1023;
u64 ptc1522;
u64 mptc;
u64 bptc;
u64 tsctc;
u64 tsctfc;
u64 iac;
u64 htdpmc;
u64 rpthc;
u64 hgptc;
u64 hgorc;
u64 hgotc;
u64 lenerrs;
u64 scvpc;
u64 hrmpc;
u64 doosync;
u64 o2bgptc;
u64 o2bspc;
u64 b2ospc;
u64 b2ogprc;
};
struct net_device *igc_get_hw_dev(struct igc_hw *hw);
#define hw_dbg(format, arg...) \
netdev_dbg(igc_get_hw_dev(hw), format, ##arg)
s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
#endif /* _IGC_HW_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_I225_H_
#define _IGC_I225_H_
s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask);
void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask);
s32 igc_init_nvm_params_i225(struct igc_hw *hw);
bool igc_get_flash_presence_i225(struct igc_hw *hw);
s32 igc_set_eee_i225(struct igc_hw *hw, bool adv2p5G, bool adv1G,
bool adv100M);
s32 igc_set_ltr_i225(struct igc_hw *hw, bool link);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_I225_H_
#define _IGC_I225_H_
s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask);
void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask);
s32 igc_init_nvm_params_i225(struct igc_hw *hw);
bool igc_get_flash_presence_i225(struct igc_hw *hw);
s32 igc_set_eee_i225(struct igc_hw *hw, bool adv2p5G, bool adv1G,
bool adv100M);
s32 igc_set_ltr_i225(struct igc_hw *hw, bool link);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_MAC_H_
#define _IGC_MAC_H_
#include "igc_hw-5.15-ethercat.h"
#include "igc_phy-5.15-ethercat.h"
#include "igc_defines-5.15-ethercat.h"
/* forward declaration */
s32 igc_disable_pcie_master(struct igc_hw *hw);
s32 igc_check_for_copper_link(struct igc_hw *hw);
s32 igc_config_fc_after_link_up(struct igc_hw *hw);
s32 igc_force_mac_fc(struct igc_hw *hw);
void igc_init_rx_addrs(struct igc_hw *hw, u16 rar_count);
s32 igc_setup_link(struct igc_hw *hw);
void igc_clear_hw_cntrs_base(struct igc_hw *hw);
s32 igc_get_auto_rd_done(struct igc_hw *hw);
void igc_put_hw_semaphore(struct igc_hw *hw);
void igc_rar_set(struct igc_hw *hw, u8 *addr, u32 index);
void igc_config_collision_dist(struct igc_hw *hw);
s32 igc_get_speed_and_duplex_copper(struct igc_hw *hw, u16 *speed,
u16 *duplex);
bool igc_enable_mng_pass_thru(struct igc_hw *hw);
void igc_update_mc_addr_list(struct igc_hw *hw,
u8 *mc_addr_list, u32 mc_addr_count);
enum igc_mng_mode {
igc_mng_mode_none = 0,
igc_mng_mode_asf,
igc_mng_mode_pt,
igc_mng_mode_ipmi,
igc_mng_mode_host_if_only
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_MAC_H_
#define _IGC_MAC_H_
#include "igc_hw.h"
#include "igc_phy.h"
#include "igc_defines.h"
/* forward declaration */
s32 igc_disable_pcie_master(struct igc_hw *hw);
s32 igc_check_for_copper_link(struct igc_hw *hw);
s32 igc_config_fc_after_link_up(struct igc_hw *hw);
s32 igc_force_mac_fc(struct igc_hw *hw);
void igc_init_rx_addrs(struct igc_hw *hw, u16 rar_count);
s32 igc_setup_link(struct igc_hw *hw);
void igc_clear_hw_cntrs_base(struct igc_hw *hw);
s32 igc_get_auto_rd_done(struct igc_hw *hw);
void igc_put_hw_semaphore(struct igc_hw *hw);
void igc_rar_set(struct igc_hw *hw, u8 *addr, u32 index);
void igc_config_collision_dist(struct igc_hw *hw);
s32 igc_get_speed_and_duplex_copper(struct igc_hw *hw, u16 *speed,
u16 *duplex);
bool igc_enable_mng_pass_thru(struct igc_hw *hw);
void igc_update_mc_addr_list(struct igc_hw *hw,
u8 *mc_addr_list, u32 mc_addr_count);
enum igc_mng_mode {
igc_mng_mode_none = 0,
igc_mng_mode_asf,
igc_mng_mode_pt,
igc_mng_mode_ipmi,
igc_mng_mode_host_if_only
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,215 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018 Intel Corporation */
#include "igc_mac-5.15-ethercat.h"
#include "igc_nvm-5.15-ethercat.h"
/**
* igc_poll_eerd_eewr_done - Poll for EEPROM read/write completion
* @hw: pointer to the HW structure
* @ee_reg: EEPROM flag for polling
*
* Polls the EEPROM status bit for either read or write completion based
* upon the value of 'ee_reg'.
*/
static s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg)
{
s32 ret_val = -IGC_ERR_NVM;
u32 attempts = 100000;
u32 i, reg = 0;
for (i = 0; i < attempts; i++) {
if (ee_reg == IGC_NVM_POLL_READ)
reg = rd32(IGC_EERD);
else
reg = rd32(IGC_EEWR);
if (reg & IGC_NVM_RW_REG_DONE) {
ret_val = 0;
break;
}
udelay(5);
}
return ret_val;
}
/**
* igc_acquire_nvm - Generic request for access to EEPROM
* @hw: pointer to the HW structure
*
* Set the EEPROM access request bit and wait for EEPROM access grant bit.
* Return successful if access grant bit set, else clear the request for
* EEPROM access and return -IGC_ERR_NVM (-1).
*/
s32 igc_acquire_nvm(struct igc_hw *hw)
{
s32 timeout = IGC_NVM_GRANT_ATTEMPTS;
u32 eecd = rd32(IGC_EECD);
s32 ret_val = 0;
wr32(IGC_EECD, eecd | IGC_EECD_REQ);
eecd = rd32(IGC_EECD);
while (timeout) {
if (eecd & IGC_EECD_GNT)
break;
udelay(5);
eecd = rd32(IGC_EECD);
timeout--;
}
if (!timeout) {
eecd &= ~IGC_EECD_REQ;
wr32(IGC_EECD, eecd);
hw_dbg("Could not acquire NVM grant\n");
ret_val = -IGC_ERR_NVM;
}
return ret_val;
}
/**
* igc_release_nvm - Release exclusive access to EEPROM
* @hw: pointer to the HW structure
*
* Stop any current commands to the EEPROM and clear the EEPROM request bit.
*/
void igc_release_nvm(struct igc_hw *hw)
{
u32 eecd;
eecd = rd32(IGC_EECD);
eecd &= ~IGC_EECD_REQ;
wr32(IGC_EECD, eecd);
}
/**
* igc_read_nvm_eerd - Reads EEPROM using EERD register
* @hw: pointer to the HW structure
* @offset: offset of word in the EEPROM to read
* @words: number of words to read
* @data: word read from the EEPROM
*
* Reads a 16 bit word from the EEPROM using the EERD register.
*/
s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
{
struct igc_nvm_info *nvm = &hw->nvm;
u32 i, eerd = 0;
s32 ret_val = 0;
/* A check for invalid values: offset too large, too many words,
* and not enough words.
*/
if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) ||
words == 0) {
hw_dbg("nvm parameter(s) out of bounds\n");
ret_val = -IGC_ERR_NVM;
goto out;
}
for (i = 0; i < words; i++) {
eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) +
IGC_NVM_RW_REG_START;
wr32(IGC_EERD, eerd);
ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ);
if (ret_val)
break;
data[i] = (rd32(IGC_EERD) >> IGC_NVM_RW_REG_DATA);
}
out:
return ret_val;
}
/**
* igc_read_mac_addr - Read device MAC address
* @hw: pointer to the HW structure
*/
s32 igc_read_mac_addr(struct igc_hw *hw)
{
u32 rar_high;
u32 rar_low;
u16 i;
rar_high = rd32(IGC_RAH(0));
rar_low = rd32(IGC_RAL(0));
for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++)
hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8));
for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++)
hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8));
for (i = 0; i < ETH_ALEN; i++)
hw->mac.addr[i] = hw->mac.perm_addr[i];
return 0;
}
/**
* igc_validate_nvm_checksum - Validate EEPROM checksum
* @hw: pointer to the HW structure
*
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
*/
s32 igc_validate_nvm_checksum(struct igc_hw *hw)
{
u16 checksum = 0;
u16 i, nvm_data;
s32 ret_val = 0;
for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
if (ret_val) {
hw_dbg("NVM Read Error\n");
goto out;
}
checksum += nvm_data;
}
if (checksum != (u16)NVM_SUM) {
hw_dbg("NVM Checksum Invalid\n");
ret_val = -IGC_ERR_NVM;
goto out;
}
out:
return ret_val;
}
/**
* igc_update_nvm_checksum - Update EEPROM checksum
* @hw: pointer to the HW structure
*
* Updates the EEPROM checksum by reading/adding each word of the EEPROM
* up to the checksum. Then calculates the EEPROM checksum and writes the
* value to the EEPROM.
*/
s32 igc_update_nvm_checksum(struct igc_hw *hw)
{
u16 checksum = 0;
u16 i, nvm_data;
s32 ret_val;
for (i = 0; i < NVM_CHECKSUM_REG; i++) {
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
if (ret_val) {
hw_dbg("NVM Read Error while updating checksum.\n");
goto out;
}
checksum += nvm_data;
}
checksum = (u16)NVM_SUM - checksum;
ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
if (ret_val)
hw_dbg("NVM Write Error while updating checksum.\n");
out:
return ret_val;
}

View File

@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_NVM_H_
#define _IGC_NVM_H_
s32 igc_acquire_nvm(struct igc_hw *hw);
void igc_release_nvm(struct igc_hw *hw);
s32 igc_read_mac_addr(struct igc_hw *hw);
s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data);
s32 igc_validate_nvm_checksum(struct igc_hw *hw);
s32 igc_update_nvm_checksum(struct igc_hw *hw);
#endif

View File

@@ -0,0 +1,215 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2018 Intel Corporation */
#include "igc_mac.h"
#include "igc_nvm.h"
/**
* igc_poll_eerd_eewr_done - Poll for EEPROM read/write completion
* @hw: pointer to the HW structure
* @ee_reg: EEPROM flag for polling
*
* Polls the EEPROM status bit for either read or write completion based
* upon the value of 'ee_reg'.
*/
static s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg)
{
s32 ret_val = -IGC_ERR_NVM;
u32 attempts = 100000;
u32 i, reg = 0;
for (i = 0; i < attempts; i++) {
if (ee_reg == IGC_NVM_POLL_READ)
reg = rd32(IGC_EERD);
else
reg = rd32(IGC_EEWR);
if (reg & IGC_NVM_RW_REG_DONE) {
ret_val = 0;
break;
}
udelay(5);
}
return ret_val;
}
/**
* igc_acquire_nvm - Generic request for access to EEPROM
* @hw: pointer to the HW structure
*
* Set the EEPROM access request bit and wait for EEPROM access grant bit.
* Return successful if access grant bit set, else clear the request for
* EEPROM access and return -IGC_ERR_NVM (-1).
*/
s32 igc_acquire_nvm(struct igc_hw *hw)
{
s32 timeout = IGC_NVM_GRANT_ATTEMPTS;
u32 eecd = rd32(IGC_EECD);
s32 ret_val = 0;
wr32(IGC_EECD, eecd | IGC_EECD_REQ);
eecd = rd32(IGC_EECD);
while (timeout) {
if (eecd & IGC_EECD_GNT)
break;
udelay(5);
eecd = rd32(IGC_EECD);
timeout--;
}
if (!timeout) {
eecd &= ~IGC_EECD_REQ;
wr32(IGC_EECD, eecd);
hw_dbg("Could not acquire NVM grant\n");
ret_val = -IGC_ERR_NVM;
}
return ret_val;
}
/**
* igc_release_nvm - Release exclusive access to EEPROM
* @hw: pointer to the HW structure
*
* Stop any current commands to the EEPROM and clear the EEPROM request bit.
*/
void igc_release_nvm(struct igc_hw *hw)
{
u32 eecd;
eecd = rd32(IGC_EECD);
eecd &= ~IGC_EECD_REQ;
wr32(IGC_EECD, eecd);
}
/**
* igc_read_nvm_eerd - Reads EEPROM using EERD register
* @hw: pointer to the HW structure
* @offset: offset of word in the EEPROM to read
* @words: number of words to read
* @data: word read from the EEPROM
*
* Reads a 16 bit word from the EEPROM using the EERD register.
*/
s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
{
struct igc_nvm_info *nvm = &hw->nvm;
u32 i, eerd = 0;
s32 ret_val = 0;
/* A check for invalid values: offset too large, too many words,
* and not enough words.
*/
if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) ||
words == 0) {
hw_dbg("nvm parameter(s) out of bounds\n");
ret_val = -IGC_ERR_NVM;
goto out;
}
for (i = 0; i < words; i++) {
eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) +
IGC_NVM_RW_REG_START;
wr32(IGC_EERD, eerd);
ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ);
if (ret_val)
break;
data[i] = (rd32(IGC_EERD) >> IGC_NVM_RW_REG_DATA);
}
out:
return ret_val;
}
/**
* igc_read_mac_addr - Read device MAC address
* @hw: pointer to the HW structure
*/
s32 igc_read_mac_addr(struct igc_hw *hw)
{
u32 rar_high;
u32 rar_low;
u16 i;
rar_high = rd32(IGC_RAH(0));
rar_low = rd32(IGC_RAL(0));
for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++)
hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8));
for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++)
hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8));
for (i = 0; i < ETH_ALEN; i++)
hw->mac.addr[i] = hw->mac.perm_addr[i];
return 0;
}
/**
* igc_validate_nvm_checksum - Validate EEPROM checksum
* @hw: pointer to the HW structure
*
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
*/
s32 igc_validate_nvm_checksum(struct igc_hw *hw)
{
u16 checksum = 0;
u16 i, nvm_data;
s32 ret_val = 0;
for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
if (ret_val) {
hw_dbg("NVM Read Error\n");
goto out;
}
checksum += nvm_data;
}
if (checksum != (u16)NVM_SUM) {
hw_dbg("NVM Checksum Invalid\n");
ret_val = -IGC_ERR_NVM;
goto out;
}
out:
return ret_val;
}
/**
* igc_update_nvm_checksum - Update EEPROM checksum
* @hw: pointer to the HW structure
*
* Updates the EEPROM checksum by reading/adding each word of the EEPROM
* up to the checksum. Then calculates the EEPROM checksum and writes the
* value to the EEPROM.
*/
s32 igc_update_nvm_checksum(struct igc_hw *hw)
{
u16 checksum = 0;
u16 i, nvm_data;
s32 ret_val;
for (i = 0; i < NVM_CHECKSUM_REG; i++) {
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
if (ret_val) {
hw_dbg("NVM Read Error while updating checksum.\n");
goto out;
}
checksum += nvm_data;
}
checksum = (u16)NVM_SUM - checksum;
ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
if (ret_val)
hw_dbg("NVM Write Error while updating checksum.\n");
out:
return ret_val;
}

View File

@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_NVM_H_
#define _IGC_NVM_H_
s32 igc_acquire_nvm(struct igc_hw *hw);
void igc_release_nvm(struct igc_hw *hw);
s32 igc_read_mac_addr(struct igc_hw *hw);
s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data);
s32 igc_validate_nvm_checksum(struct igc_hw *hw);
s32 igc_update_nvm_checksum(struct igc_hw *hw);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_PHY_H_
#define _IGC_PHY_H_
#include "igc_mac-5.15-ethercat.h"
s32 igc_check_reset_block(struct igc_hw *hw);
s32 igc_phy_hw_reset(struct igc_hw *hw);
s32 igc_get_phy_id(struct igc_hw *hw);
s32 igc_phy_has_link(struct igc_hw *hw, u32 iterations,
u32 usec_interval, bool *success);
s32 igc_check_downshift(struct igc_hw *hw);
s32 igc_setup_copper_link(struct igc_hw *hw);
void igc_power_up_phy_copper(struct igc_hw *hw);
void igc_power_down_phy_copper(struct igc_hw *hw);
s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data);
s32 igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data);
u16 igc_read_phy_fw_version(struct igc_hw *hw);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_PHY_H_
#define _IGC_PHY_H_
#include "igc_mac.h"
s32 igc_check_reset_block(struct igc_hw *hw);
s32 igc_phy_hw_reset(struct igc_hw *hw);
s32 igc_get_phy_id(struct igc_hw *hw);
s32 igc_phy_has_link(struct igc_hw *hw, u32 iterations,
u32 usec_interval, bool *success);
s32 igc_check_downshift(struct igc_hw *hw);
s32 igc_setup_copper_link(struct igc_hw *hw);
void igc_power_up_phy_copper(struct igc_hw *hw);
void igc_power_down_phy_copper(struct igc_hw *hw);
s32 igc_write_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 data);
s32 igc_read_phy_reg_gpy(struct igc_hw *hw, u32 offset, u16 *data);
u16 igc_read_phy_fw_version(struct igc_hw *hw);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,321 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_REGS_H_
#define _IGC_REGS_H_
/* General Register Descriptions */
#define IGC_CTRL 0x00000 /* Device Control - RW */
#define IGC_STATUS 0x00008 /* Device Status - RO */
#define IGC_EECD 0x00010 /* EEPROM/Flash Control - RW */
#define IGC_CTRL_EXT 0x00018 /* Extended Device Control - RW */
#define IGC_MDIC 0x00020 /* MDI Control - RW */
#define IGC_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
#define IGC_VET 0x00038 /* VLAN Ether Type - RW */
#define IGC_I225_PHPM 0x00E14 /* I225 PHY Power Management */
#define IGC_GPHY_VERSION 0x0001E /* I225 gPHY Firmware Version */
/* Internal Packet Buffer Size Registers */
#define IGC_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
#define IGC_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */
/* NVM Register Descriptions */
#define IGC_EERD 0x12014 /* EEprom mode read - RW */
#define IGC_EEWR 0x12018 /* EEprom mode write - RW */
/* Flow Control Register Descriptions */
#define IGC_FCAL 0x00028 /* FC Address Low - RW */
#define IGC_FCAH 0x0002C /* FC Address High - RW */
#define IGC_FCT 0x00030 /* FC Type - RW */
#define IGC_FCTTV 0x00170 /* FC Transmit Timer - RW */
#define IGC_FCRTL 0x02160 /* FC Receive Threshold Low - RW */
#define IGC_FCRTH 0x02168 /* FC Receive Threshold High - RW */
#define IGC_FCRTV 0x02460 /* FC Refresh Timer Value - RW */
/* Semaphore registers */
#define IGC_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */
#define IGC_SWSM 0x05B50 /* SW Semaphore */
#define IGC_FWSM 0x05B54 /* FW Semaphore */
/* Function Active and Power State to MNG */
#define IGC_FACTPS 0x05B30
/* Interrupt Register Description */
#define IGC_EICR 0x01580 /* Ext. Interrupt Cause read - W0 */
#define IGC_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
#define IGC_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
#define IGC_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
#define IGC_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
#define IGC_EIAM 0x01530 /* Ext. Interrupt Auto Mask - RW */
#define IGC_ICR 0x01500 /* Intr Cause Read - RC/W1C */
#define IGC_ICS 0x01504 /* Intr Cause Set - WO */
#define IGC_IMS 0x01508 /* Intr Mask Set/Read - RW */
#define IGC_IMC 0x0150C /* Intr Mask Clear - WO */
#define IGC_IAM 0x01510 /* Intr Ack Auto Mask- RW */
/* Intr Throttle - RW */
#define IGC_EITR(_n) (0x01680 + (0x4 * (_n)))
/* Interrupt Vector Allocation - RW */
#define IGC_IVAR0 0x01700
#define IGC_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
#define IGC_GPIE 0x01514 /* General Purpose Intr Enable - RW */
/* MSI-X Table Register Descriptions */
#define IGC_PBACL 0x05B68 /* MSIx PBA Clear - R/W 1 to clear */
/* RSS registers */
#define IGC_MRQC 0x05818 /* Multiple Receive Control - RW */
/* Filtering Registers */
#define IGC_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
#define IGC_FHFT(_n) (0x09000 + (256 * (_n))) /* Flexible Host Filter */
#define IGC_FHFT_EXT(_n) (0x09A00 + (256 * (_n))) /* Flexible Host Filter Extended */
#define IGC_FHFTSL 0x05804 /* Flex Filter indirect table select */
/* ETQF register bit definitions */
#define IGC_ETQF_FILTER_ENABLE BIT(26)
#define IGC_ETQF_QUEUE_ENABLE BIT(31)
#define IGC_ETQF_QUEUE_SHIFT 16
#define IGC_ETQF_QUEUE_MASK 0x00070000
#define IGC_ETQF_ETYPE_MASK 0x0000FFFF
/* FHFT register bit definitions */
#define IGC_FHFT_LENGTH_MASK GENMASK(7, 0)
#define IGC_FHFT_QUEUE_SHIFT 8
#define IGC_FHFT_QUEUE_MASK GENMASK(10, 8)
#define IGC_FHFT_PRIO_SHIFT 16
#define IGC_FHFT_PRIO_MASK GENMASK(18, 16)
#define IGC_FHFT_IMM_INT BIT(24)
#define IGC_FHFT_DROP BIT(25)
/* FHFTSL register bit definitions */
#define IGC_FHFTSL_FTSL_SHIFT 0
#define IGC_FHFTSL_FTSL_MASK GENMASK(1, 0)
/* Redirection Table - RW Array */
#define IGC_RETA(_i) (0x05C00 + ((_i) * 4))
/* RSS Random Key - RW Array */
#define IGC_RSSRK(_i) (0x05C80 + ((_i) * 4))
/* Receive Register Descriptions */
#define IGC_RCTL 0x00100 /* Rx Control - RW */
#define IGC_SRRCTL(_n) (0x0C00C + ((_n) * 0x40))
#define IGC_PSRTYPE(_i) (0x05480 + ((_i) * 4))
#define IGC_RDBAL(_n) (0x0C000 + ((_n) * 0x40))
#define IGC_RDBAH(_n) (0x0C004 + ((_n) * 0x40))
#define IGC_RDLEN(_n) (0x0C008 + ((_n) * 0x40))
#define IGC_RDH(_n) (0x0C010 + ((_n) * 0x40))
#define IGC_RDT(_n) (0x0C018 + ((_n) * 0x40))
#define IGC_RXDCTL(_n) (0x0C028 + ((_n) * 0x40))
#define IGC_RQDPC(_n) (0x0C030 + ((_n) * 0x40))
#define IGC_RXCSUM 0x05000 /* Rx Checksum Control - RW */
#define IGC_RLPML 0x05004 /* Rx Long Packet Max Length */
#define IGC_RFCTL 0x05008 /* Receive Filter Control*/
#define IGC_MTA 0x05200 /* Multicast Table Array - RW Array */
#define IGC_RA 0x05400 /* Receive Address - RW Array */
#define IGC_UTA 0x0A000 /* Unicast Table Array - RW */
#define IGC_RAL(_n) (0x05400 + ((_n) * 0x08))
#define IGC_RAH(_n) (0x05404 + ((_n) * 0x08))
#define IGC_VLANPQF 0x055B0 /* VLAN Priority Queue Filter - RW */
/* Transmit Register Descriptions */
#define IGC_TCTL 0x00400 /* Tx Control - RW */
#define IGC_TIPG 0x00410 /* Tx Inter-packet gap - RW */
#define IGC_TDBAL(_n) (0x0E000 + ((_n) * 0x40))
#define IGC_TDBAH(_n) (0x0E004 + ((_n) * 0x40))
#define IGC_TDLEN(_n) (0x0E008 + ((_n) * 0x40))
#define IGC_TDH(_n) (0x0E010 + ((_n) * 0x40))
#define IGC_TDT(_n) (0x0E018 + ((_n) * 0x40))
#define IGC_TXDCTL(_n) (0x0E028 + ((_n) * 0x40))
/* MMD Register Descriptions */
#define IGC_MMDAC 13 /* MMD Access Control */
#define IGC_MMDAAD 14 /* MMD Access Address/Data */
/* Statistics Register Descriptions */
#define IGC_CRCERRS 0x04000 /* CRC Error Count - R/clr */
#define IGC_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
#define IGC_RXERRC 0x0400C /* Receive Error Count - R/clr */
#define IGC_MPC 0x04010 /* Missed Packet Count - R/clr */
#define IGC_SCC 0x04014 /* Single Collision Count - R/clr */
#define IGC_ECOL 0x04018 /* Excessive Collision Count - R/clr */
#define IGC_MCC 0x0401C /* Multiple Collision Count - R/clr */
#define IGC_LATECOL 0x04020 /* Late Collision Count - R/clr */
#define IGC_COLC 0x04028 /* Collision Count - R/clr */
#define IGC_RERC 0x0402C /* Receive Error Count - R/clr */
#define IGC_DC 0x04030 /* Defer Count - R/clr */
#define IGC_TNCRS 0x04034 /* Tx-No CRS - R/clr */
#define IGC_HTDPMC 0x0403C /* Host Transmit Discarded by MAC - R/clr */
#define IGC_RLEC 0x04040 /* Receive Length Error Count - R/clr */
#define IGC_XONRXC 0x04048 /* XON Rx Count - R/clr */
#define IGC_XONTXC 0x0404C /* XON Tx Count - R/clr */
#define IGC_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */
#define IGC_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */
#define IGC_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */
#define IGC_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */
#define IGC_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */
#define IGC_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */
#define IGC_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */
#define IGC_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */
#define IGC_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */
#define IGC_GPRC 0x04074 /* Good Packets Rx Count - R/clr */
#define IGC_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */
#define IGC_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */
#define IGC_GPTC 0x04080 /* Good Packets Tx Count - R/clr */
#define IGC_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */
#define IGC_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */
#define IGC_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */
#define IGC_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */
#define IGC_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */
#define IGC_RUC 0x040A4 /* Rx Undersize Count - R/clr */
#define IGC_RFC 0x040A8 /* Rx Fragment Count - R/clr */
#define IGC_ROC 0x040AC /* Rx Oversize Count - R/clr */
#define IGC_RJC 0x040B0 /* Rx Jabber Count - R/clr */
#define IGC_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */
#define IGC_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
#define IGC_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */
#define IGC_TORL 0x040C0 /* Total Octets Rx Low - R/clr */
#define IGC_TORH 0x040C4 /* Total Octets Rx High - R/clr */
#define IGC_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */
#define IGC_TOTH 0x040CC /* Total Octets Tx High - R/clr */
#define IGC_TPR 0x040D0 /* Total Packets Rx - R/clr */
#define IGC_TPT 0x040D4 /* Total Packets Tx - R/clr */
#define IGC_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */
#define IGC_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */
#define IGC_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */
#define IGC_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */
#define IGC_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */
#define IGC_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */
#define IGC_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */
#define IGC_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */
#define IGC_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */
#define IGC_IAC 0x04100 /* Interrupt Assertion Count */
#define IGC_RPTHC 0x04104 /* Rx Packets To Host */
#define IGC_TLPIC 0x04148 /* EEE Tx LPI Count */
#define IGC_RLPIC 0x0414C /* EEE Rx LPI Count */
#define IGC_HGPTC 0x04118 /* Host Good Packets Tx Count */
#define IGC_RXDMTC 0x04120 /* Rx Descriptor Minimum Threshold Count */
#define IGC_HGORCL 0x04128 /* Host Good Octets Received Count Low */
#define IGC_HGORCH 0x0412C /* Host Good Octets Received Count High */
#define IGC_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
#define IGC_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
#define IGC_LENERRS 0x04138 /* Length Errors Count */
/* Time sync registers */
#define IGC_TSICR 0x0B66C /* Time Sync Interrupt Cause */
#define IGC_TSIM 0x0B674 /* Time Sync Interrupt Mask Register */
#define IGC_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */
#define IGC_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
#define IGC_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
#define IGC_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
#define IGC_TSSDP 0x0003C /* Time Sync SDP Configuration Register - RW */
#define IGC_TRGTTIML0 0x0B644 /* Target Time Register 0 Low - RW */
#define IGC_TRGTTIMH0 0x0B648 /* Target Time Register 0 High - RW */
#define IGC_TRGTTIML1 0x0B64C /* Target Time Register 1 Low - RW */
#define IGC_TRGTTIMH1 0x0B650 /* Target Time Register 1 High - RW */
#define IGC_FREQOUT0 0x0B654 /* Frequency Out 0 Control Register - RW */
#define IGC_FREQOUT1 0x0B658 /* Frequency Out 1 Control Register - RW */
#define IGC_AUXSTMPL0 0x0B65C /* Auxiliary Time Stamp 0 Register Low - RO */
#define IGC_AUXSTMPH0 0x0B660 /* Auxiliary Time Stamp 0 Register High - RO */
#define IGC_AUXSTMPL1 0x0B664 /* Auxiliary Time Stamp 1 Register Low - RO */
#define IGC_AUXSTMPH1 0x0B668 /* Auxiliary Time Stamp 1 Register High - RO */
#define IGC_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
#define IGC_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate INTR Ext*/
#define IGC_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */
/* Transmit Scheduling Registers */
#define IGC_TQAVCTRL 0x3570
#define IGC_TXQCTL(_n) (0x3344 + 0x4 * (_n))
#define IGC_BASET_L 0x3314
#define IGC_BASET_H 0x3318
#define IGC_QBVCYCLET 0x331C
#define IGC_QBVCYCLET_S 0x3320
#define IGC_STQT(_n) (0x3324 + 0x4 * (_n))
#define IGC_ENDQT(_n) (0x3334 + 0x4 * (_n))
#define IGC_DTXMXPKTSZ 0x355C
#define IGC_TQAVCC(_n) (0x3004 + ((_n) * 0x40))
#define IGC_TQAVHC(_n) (0x300C + ((_n) * 0x40))
/* System Time Registers */
#define IGC_SYSTIML 0x0B600 /* System time register Low - RO */
#define IGC_SYSTIMH 0x0B604 /* System time register High - RO */
#define IGC_SYSTIMR 0x0B6F8 /* System time register Residue */
#define IGC_TIMINCA 0x0B608 /* Increment attributes register - RW */
#define IGC_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */
#define IGC_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */
#define IGC_TIMADJ 0x0B60C /* Time Adjustment Offset Register */
/* PCIe Registers */
#define IGC_PTM_CTRL 0x12540 /* PTM Control */
#define IGC_PTM_STAT 0x12544 /* PTM Status */
#define IGC_PTM_CYCLE_CTRL 0x1254C /* PTM Cycle Control */
/* PTM Time registers */
#define IGC_PTM_T1_TIM0_L 0x12558 /* T1 on Timer 0 Low */
#define IGC_PTM_T1_TIM0_H 0x1255C /* T1 on Timer 0 High */
#define IGC_PTM_CURR_T2_L 0x1258C /* Current T2 Low */
#define IGC_PTM_CURR_T2_H 0x12590 /* Current T2 High */
#define IGC_PTM_PREV_T2_L 0x12584 /* Previous T2 Low */
#define IGC_PTM_PREV_T2_H 0x12588 /* Previous T2 High */
#define IGC_PTM_PREV_T4M1 0x12578 /* T4 Minus T1 on previous PTM Cycle */
#define IGC_PTM_CURR_T4M1 0x1257C /* T4 Minus T1 on this PTM Cycle */
#define IGC_PTM_PREV_T3M2 0x12580 /* T3 Minus T2 on previous PTM Cycle */
#define IGC_PTM_TDELAY 0x12594 /* PTM PCIe Link Delay */
#define IGC_PCIE_DIG_DELAY 0x12550 /* PCIe Digital Delay */
#define IGC_PCIE_PHY_DELAY 0x12554 /* PCIe PHY Delay */
/* Management registers */
#define IGC_MANC 0x05820 /* Management Control - RW */
/* Shadow Ram Write Register - RW */
#define IGC_SRWR 0x12018
/* Wake Up registers */
#define IGC_WUC 0x05800 /* Wakeup Control - RW */
#define IGC_WUFC 0x05808 /* Wakeup Filter Control - RW */
#define IGC_WUS 0x05810 /* Wakeup Status - R/W1C */
#define IGC_WUPL 0x05900 /* Wakeup Packet Length - RW */
#define IGC_WUFC_EXT 0x0580C /* Wakeup Filter Control Register Extended - RW */
/* Wake Up packet memory */
#define IGC_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
/* Energy Efficient Ethernet "EEE" registers */
#define IGC_EEER 0x0E30 /* Energy Efficient Ethernet "EEE"*/
#define IGC_IPCNFG 0x0E38 /* Internal PHY Configuration */
#define IGC_EEE_SU 0x0E34 /* EEE Setup */
/* LTR registers */
#define IGC_LTRC 0x01A0 /* Latency Tolerance Reporting Control */
#define IGC_DMACR 0x02508 /* DMA Coalescing Control Register */
#define IGC_LTRMINV 0x5BB0 /* LTR Minimum Value */
#define IGC_LTRMAXV 0x5BB4 /* LTR Maximum Value */
/* forward declaration */
struct igc_hw;
u32 igc_rd32(struct igc_hw *hw, u32 reg);
/* write operations, indexed using DWORDS */
#define wr32(reg, val) \
do { \
u8 __iomem *hw_addr = READ_ONCE((hw)->hw_addr); \
writel((val), &hw_addr[(reg)]); \
} while (0)
#define rd32(reg) (igc_rd32(hw, reg))
#define wrfl() ((void)rd32(IGC_STATUS))
#define array_wr32(reg, offset, value) \
wr32((reg) + ((offset) << 2), (value))
#define array_rd32(reg, offset) (igc_rd32(hw, (reg) + ((offset) << 2)))
#endif

View File

@@ -0,0 +1,321 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Intel Corporation */
#ifndef _IGC_REGS_H_
#define _IGC_REGS_H_
/* General Register Descriptions */
#define IGC_CTRL 0x00000 /* Device Control - RW */
#define IGC_STATUS 0x00008 /* Device Status - RO */
#define IGC_EECD 0x00010 /* EEPROM/Flash Control - RW */
#define IGC_CTRL_EXT 0x00018 /* Extended Device Control - RW */
#define IGC_MDIC 0x00020 /* MDI Control - RW */
#define IGC_CONNSW 0x00034 /* Copper/Fiber switch control - RW */
#define IGC_VET 0x00038 /* VLAN Ether Type - RW */
#define IGC_I225_PHPM 0x00E14 /* I225 PHY Power Management */
#define IGC_GPHY_VERSION 0x0001E /* I225 gPHY Firmware Version */
/* Internal Packet Buffer Size Registers */
#define IGC_RXPBS 0x02404 /* Rx Packet Buffer Size - RW */
#define IGC_TXPBS 0x03404 /* Tx Packet Buffer Size - RW */
/* NVM Register Descriptions */
#define IGC_EERD 0x12014 /* EEprom mode read - RW */
#define IGC_EEWR 0x12018 /* EEprom mode write - RW */
/* Flow Control Register Descriptions */
#define IGC_FCAL 0x00028 /* FC Address Low - RW */
#define IGC_FCAH 0x0002C /* FC Address High - RW */
#define IGC_FCT 0x00030 /* FC Type - RW */
#define IGC_FCTTV 0x00170 /* FC Transmit Timer - RW */
#define IGC_FCRTL 0x02160 /* FC Receive Threshold Low - RW */
#define IGC_FCRTH 0x02168 /* FC Receive Threshold High - RW */
#define IGC_FCRTV 0x02460 /* FC Refresh Timer Value - RW */
/* Semaphore registers */
#define IGC_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */
#define IGC_SWSM 0x05B50 /* SW Semaphore */
#define IGC_FWSM 0x05B54 /* FW Semaphore */
/* Function Active and Power State to MNG */
#define IGC_FACTPS 0x05B30
/* Interrupt Register Description */
#define IGC_EICR 0x01580 /* Ext. Interrupt Cause read - W0 */
#define IGC_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
#define IGC_EIMS 0x01524 /* Ext. Interrupt Mask Set/Read - RW */
#define IGC_EIMC 0x01528 /* Ext. Interrupt Mask Clear - WO */
#define IGC_EIAC 0x0152C /* Ext. Interrupt Auto Clear - RW */
#define IGC_EIAM 0x01530 /* Ext. Interrupt Auto Mask - RW */
#define IGC_ICR 0x01500 /* Intr Cause Read - RC/W1C */
#define IGC_ICS 0x01504 /* Intr Cause Set - WO */
#define IGC_IMS 0x01508 /* Intr Mask Set/Read - RW */
#define IGC_IMC 0x0150C /* Intr Mask Clear - WO */
#define IGC_IAM 0x01510 /* Intr Ack Auto Mask- RW */
/* Intr Throttle - RW */
#define IGC_EITR(_n) (0x01680 + (0x4 * (_n)))
/* Interrupt Vector Allocation - RW */
#define IGC_IVAR0 0x01700
#define IGC_IVAR_MISC 0x01740 /* IVAR for "other" causes - RW */
#define IGC_GPIE 0x01514 /* General Purpose Intr Enable - RW */
/* MSI-X Table Register Descriptions */
#define IGC_PBACL 0x05B68 /* MSIx PBA Clear - R/W 1 to clear */
/* RSS registers */
#define IGC_MRQC 0x05818 /* Multiple Receive Control - RW */
/* Filtering Registers */
#define IGC_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
#define IGC_FHFT(_n) (0x09000 + (256 * (_n))) /* Flexible Host Filter */
#define IGC_FHFT_EXT(_n) (0x09A00 + (256 * (_n))) /* Flexible Host Filter Extended */
#define IGC_FHFTSL 0x05804 /* Flex Filter indirect table select */
/* ETQF register bit definitions */
#define IGC_ETQF_FILTER_ENABLE BIT(26)
#define IGC_ETQF_QUEUE_ENABLE BIT(31)
#define IGC_ETQF_QUEUE_SHIFT 16
#define IGC_ETQF_QUEUE_MASK 0x00070000
#define IGC_ETQF_ETYPE_MASK 0x0000FFFF
/* FHFT register bit definitions */
#define IGC_FHFT_LENGTH_MASK GENMASK(7, 0)
#define IGC_FHFT_QUEUE_SHIFT 8
#define IGC_FHFT_QUEUE_MASK GENMASK(10, 8)
#define IGC_FHFT_PRIO_SHIFT 16
#define IGC_FHFT_PRIO_MASK GENMASK(18, 16)
#define IGC_FHFT_IMM_INT BIT(24)
#define IGC_FHFT_DROP BIT(25)
/* FHFTSL register bit definitions */
#define IGC_FHFTSL_FTSL_SHIFT 0
#define IGC_FHFTSL_FTSL_MASK GENMASK(1, 0)
/* Redirection Table - RW Array */
#define IGC_RETA(_i) (0x05C00 + ((_i) * 4))
/* RSS Random Key - RW Array */
#define IGC_RSSRK(_i) (0x05C80 + ((_i) * 4))
/* Receive Register Descriptions */
#define IGC_RCTL 0x00100 /* Rx Control - RW */
#define IGC_SRRCTL(_n) (0x0C00C + ((_n) * 0x40))
#define IGC_PSRTYPE(_i) (0x05480 + ((_i) * 4))
#define IGC_RDBAL(_n) (0x0C000 + ((_n) * 0x40))
#define IGC_RDBAH(_n) (0x0C004 + ((_n) * 0x40))
#define IGC_RDLEN(_n) (0x0C008 + ((_n) * 0x40))
#define IGC_RDH(_n) (0x0C010 + ((_n) * 0x40))
#define IGC_RDT(_n) (0x0C018 + ((_n) * 0x40))
#define IGC_RXDCTL(_n) (0x0C028 + ((_n) * 0x40))
#define IGC_RQDPC(_n) (0x0C030 + ((_n) * 0x40))
#define IGC_RXCSUM 0x05000 /* Rx Checksum Control - RW */
#define IGC_RLPML 0x05004 /* Rx Long Packet Max Length */
#define IGC_RFCTL 0x05008 /* Receive Filter Control*/
#define IGC_MTA 0x05200 /* Multicast Table Array - RW Array */
#define IGC_RA 0x05400 /* Receive Address - RW Array */
#define IGC_UTA 0x0A000 /* Unicast Table Array - RW */
#define IGC_RAL(_n) (0x05400 + ((_n) * 0x08))
#define IGC_RAH(_n) (0x05404 + ((_n) * 0x08))
#define IGC_VLANPQF 0x055B0 /* VLAN Priority Queue Filter - RW */
/* Transmit Register Descriptions */
#define IGC_TCTL 0x00400 /* Tx Control - RW */
#define IGC_TIPG 0x00410 /* Tx Inter-packet gap - RW */
#define IGC_TDBAL(_n) (0x0E000 + ((_n) * 0x40))
#define IGC_TDBAH(_n) (0x0E004 + ((_n) * 0x40))
#define IGC_TDLEN(_n) (0x0E008 + ((_n) * 0x40))
#define IGC_TDH(_n) (0x0E010 + ((_n) * 0x40))
#define IGC_TDT(_n) (0x0E018 + ((_n) * 0x40))
#define IGC_TXDCTL(_n) (0x0E028 + ((_n) * 0x40))
/* MMD Register Descriptions */
#define IGC_MMDAC 13 /* MMD Access Control */
#define IGC_MMDAAD 14 /* MMD Access Address/Data */
/* Statistics Register Descriptions */
#define IGC_CRCERRS 0x04000 /* CRC Error Count - R/clr */
#define IGC_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
#define IGC_RXERRC 0x0400C /* Receive Error Count - R/clr */
#define IGC_MPC 0x04010 /* Missed Packet Count - R/clr */
#define IGC_SCC 0x04014 /* Single Collision Count - R/clr */
#define IGC_ECOL 0x04018 /* Excessive Collision Count - R/clr */
#define IGC_MCC 0x0401C /* Multiple Collision Count - R/clr */
#define IGC_LATECOL 0x04020 /* Late Collision Count - R/clr */
#define IGC_COLC 0x04028 /* Collision Count - R/clr */
#define IGC_RERC 0x0402C /* Receive Error Count - R/clr */
#define IGC_DC 0x04030 /* Defer Count - R/clr */
#define IGC_TNCRS 0x04034 /* Tx-No CRS - R/clr */
#define IGC_HTDPMC 0x0403C /* Host Transmit Discarded by MAC - R/clr */
#define IGC_RLEC 0x04040 /* Receive Length Error Count - R/clr */
#define IGC_XONRXC 0x04048 /* XON Rx Count - R/clr */
#define IGC_XONTXC 0x0404C /* XON Tx Count - R/clr */
#define IGC_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */
#define IGC_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */
#define IGC_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */
#define IGC_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */
#define IGC_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */
#define IGC_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */
#define IGC_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */
#define IGC_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */
#define IGC_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */
#define IGC_GPRC 0x04074 /* Good Packets Rx Count - R/clr */
#define IGC_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */
#define IGC_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */
#define IGC_GPTC 0x04080 /* Good Packets Tx Count - R/clr */
#define IGC_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */
#define IGC_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */
#define IGC_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */
#define IGC_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */
#define IGC_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */
#define IGC_RUC 0x040A4 /* Rx Undersize Count - R/clr */
#define IGC_RFC 0x040A8 /* Rx Fragment Count - R/clr */
#define IGC_ROC 0x040AC /* Rx Oversize Count - R/clr */
#define IGC_RJC 0x040B0 /* Rx Jabber Count - R/clr */
#define IGC_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */
#define IGC_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */
#define IGC_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */
#define IGC_TORL 0x040C0 /* Total Octets Rx Low - R/clr */
#define IGC_TORH 0x040C4 /* Total Octets Rx High - R/clr */
#define IGC_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */
#define IGC_TOTH 0x040CC /* Total Octets Tx High - R/clr */
#define IGC_TPR 0x040D0 /* Total Packets Rx - R/clr */
#define IGC_TPT 0x040D4 /* Total Packets Tx - R/clr */
#define IGC_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */
#define IGC_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */
#define IGC_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */
#define IGC_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */
#define IGC_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */
#define IGC_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */
#define IGC_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */
#define IGC_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */
#define IGC_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */
#define IGC_IAC 0x04100 /* Interrupt Assertion Count */
#define IGC_RPTHC 0x04104 /* Rx Packets To Host */
#define IGC_TLPIC 0x04148 /* EEE Tx LPI Count */
#define IGC_RLPIC 0x0414C /* EEE Rx LPI Count */
#define IGC_HGPTC 0x04118 /* Host Good Packets Tx Count */
#define IGC_RXDMTC 0x04120 /* Rx Descriptor Minimum Threshold Count */
#define IGC_HGORCL 0x04128 /* Host Good Octets Received Count Low */
#define IGC_HGORCH 0x0412C /* Host Good Octets Received Count High */
#define IGC_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */
#define IGC_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */
#define IGC_LENERRS 0x04138 /* Length Errors Count */
/* Time sync registers */
#define IGC_TSICR 0x0B66C /* Time Sync Interrupt Cause */
#define IGC_TSIM 0x0B674 /* Time Sync Interrupt Mask Register */
#define IGC_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */
#define IGC_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
#define IGC_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
#define IGC_TSYNCRXCFG 0x05F50 /* Time Sync Rx Configuration - RW */
#define IGC_TSSDP 0x0003C /* Time Sync SDP Configuration Register - RW */
#define IGC_TRGTTIML0 0x0B644 /* Target Time Register 0 Low - RW */
#define IGC_TRGTTIMH0 0x0B648 /* Target Time Register 0 High - RW */
#define IGC_TRGTTIML1 0x0B64C /* Target Time Register 1 Low - RW */
#define IGC_TRGTTIMH1 0x0B650 /* Target Time Register 1 High - RW */
#define IGC_FREQOUT0 0x0B654 /* Frequency Out 0 Control Register - RW */
#define IGC_FREQOUT1 0x0B658 /* Frequency Out 1 Control Register - RW */
#define IGC_AUXSTMPL0 0x0B65C /* Auxiliary Time Stamp 0 Register Low - RO */
#define IGC_AUXSTMPH0 0x0B660 /* Auxiliary Time Stamp 0 Register High - RO */
#define IGC_AUXSTMPL1 0x0B664 /* Auxiliary Time Stamp 1 Register Low - RO */
#define IGC_AUXSTMPH1 0x0B668 /* Auxiliary Time Stamp 1 Register High - RO */
#define IGC_IMIR(_i) (0x05A80 + ((_i) * 4)) /* Immediate Interrupt */
#define IGC_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* Immediate INTR Ext*/
#define IGC_FTQF(_n) (0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */
/* Transmit Scheduling Registers */
#define IGC_TQAVCTRL 0x3570
#define IGC_TXQCTL(_n) (0x3344 + 0x4 * (_n))
#define IGC_BASET_L 0x3314
#define IGC_BASET_H 0x3318
#define IGC_QBVCYCLET 0x331C
#define IGC_QBVCYCLET_S 0x3320
#define IGC_STQT(_n) (0x3324 + 0x4 * (_n))
#define IGC_ENDQT(_n) (0x3334 + 0x4 * (_n))
#define IGC_DTXMXPKTSZ 0x355C
#define IGC_TQAVCC(_n) (0x3004 + ((_n) * 0x40))
#define IGC_TQAVHC(_n) (0x300C + ((_n) * 0x40))
/* System Time Registers */
#define IGC_SYSTIML 0x0B600 /* System time register Low - RO */
#define IGC_SYSTIMH 0x0B604 /* System time register High - RO */
#define IGC_SYSTIMR 0x0B6F8 /* System time register Residue */
#define IGC_TIMINCA 0x0B608 /* Increment attributes register - RW */
#define IGC_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */
#define IGC_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */
#define IGC_TIMADJ 0x0B60C /* Time Adjustment Offset Register */
/* PCIe Registers */
#define IGC_PTM_CTRL 0x12540 /* PTM Control */
#define IGC_PTM_STAT 0x12544 /* PTM Status */
#define IGC_PTM_CYCLE_CTRL 0x1254C /* PTM Cycle Control */
/* PTM Time registers */
#define IGC_PTM_T1_TIM0_L 0x12558 /* T1 on Timer 0 Low */
#define IGC_PTM_T1_TIM0_H 0x1255C /* T1 on Timer 0 High */
#define IGC_PTM_CURR_T2_L 0x1258C /* Current T2 Low */
#define IGC_PTM_CURR_T2_H 0x12590 /* Current T2 High */
#define IGC_PTM_PREV_T2_L 0x12584 /* Previous T2 Low */
#define IGC_PTM_PREV_T2_H 0x12588 /* Previous T2 High */
#define IGC_PTM_PREV_T4M1 0x12578 /* T4 Minus T1 on previous PTM Cycle */
#define IGC_PTM_CURR_T4M1 0x1257C /* T4 Minus T1 on this PTM Cycle */
#define IGC_PTM_PREV_T3M2 0x12580 /* T3 Minus T2 on previous PTM Cycle */
#define IGC_PTM_TDELAY 0x12594 /* PTM PCIe Link Delay */
#define IGC_PCIE_DIG_DELAY 0x12550 /* PCIe Digital Delay */
#define IGC_PCIE_PHY_DELAY 0x12554 /* PCIe PHY Delay */
/* Management registers */
#define IGC_MANC 0x05820 /* Management Control - RW */
/* Shadow Ram Write Register - RW */
#define IGC_SRWR 0x12018
/* Wake Up registers */
#define IGC_WUC 0x05800 /* Wakeup Control - RW */
#define IGC_WUFC 0x05808 /* Wakeup Filter Control - RW */
#define IGC_WUS 0x05810 /* Wakeup Status - R/W1C */
#define IGC_WUPL 0x05900 /* Wakeup Packet Length - RW */
#define IGC_WUFC_EXT 0x0580C /* Wakeup Filter Control Register Extended - RW */
/* Wake Up packet memory */
#define IGC_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
/* Energy Efficient Ethernet "EEE" registers */
#define IGC_EEER 0x0E30 /* Energy Efficient Ethernet "EEE"*/
#define IGC_IPCNFG 0x0E38 /* Internal PHY Configuration */
#define IGC_EEE_SU 0x0E34 /* EEE Setup */
/* LTR registers */
#define IGC_LTRC 0x01A0 /* Latency Tolerance Reporting Control */
#define IGC_DMACR 0x02508 /* DMA Coalescing Control Register */
#define IGC_LTRMINV 0x5BB0 /* LTR Minimum Value */
#define IGC_LTRMAXV 0x5BB4 /* LTR Maximum Value */
/* forward declaration */
struct igc_hw;
u32 igc_rd32(struct igc_hw *hw, u32 reg);
/* write operations, indexed using DWORDS */
#define wr32(reg, val) \
do { \
u8 __iomem *hw_addr = READ_ONCE((hw)->hw_addr); \
writel((val), &hw_addr[(reg)]); \
} while (0)
#define rd32(reg) (igc_rd32(hw, reg))
#define wrfl() ((void)rd32(IGC_STATUS))
#define array_wr32(reg, offset, value) \
wr32((reg) + ((offset) << 2), (value))
#define array_rd32(reg, offset) (igc_rd32(hw, (reg) + ((offset) << 2)))
#endif

View File

@@ -0,0 +1,267 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2019 Intel Corporation */
#include "igc-5.15-ethercat.h"
#include "igc_tsn-5.15-ethercat.h"
static bool is_any_launchtime(struct igc_adapter *adapter)
{
int i;
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];
if (ring->launchtime_enable)
return true;
}
return false;
}
static bool is_cbs_enabled(struct igc_adapter *adapter)
{
int i;
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];
if (ring->cbs_enable)
return true;
}
return false;
}
static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
{
unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED;
if (adapter->base_time)
new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
if (is_any_launchtime(adapter))
new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
if (is_cbs_enabled(adapter))
new_flags |= IGC_FLAG_TSN_QAV_ENABLED;
return new_flags;
}
/* Returns the TSN specific registers to their default values after
* the adapter is reset.
*/
static int igc_tsn_disable_offload(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
u32 tqavctrl;
int i;
wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
tqavctrl = rd32(IGC_TQAVCTRL);
tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
IGC_TQAVCTRL_ENHANCED_QAV);
wr32(IGC_TQAVCTRL, tqavctrl);
for (i = 0; i < adapter->num_tx_queues; i++) {
wr32(IGC_TXQCTL(i), 0);
wr32(IGC_STQT(i), 0);
wr32(IGC_ENDQT(i), NSEC_PER_SEC);
}
wr32(IGC_QBVCYCLET_S, 0);
wr32(IGC_QBVCYCLET, NSEC_PER_SEC);
adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED;
return 0;
}
static int igc_tsn_enable_offload(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
u32 tqavctrl, baset_l, baset_h;
u32 sec, nsec, cycle;
ktime_t base_time, systim;
int i;
cycle = adapter->cycle_time;
base_time = adapter->base_time;
wr32(IGC_TSAUXC, 0);
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
tqavctrl = rd32(IGC_TQAVCTRL);
tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
wr32(IGC_TQAVCTRL, tqavctrl);
wr32(IGC_QBVCYCLET_S, cycle);
wr32(IGC_QBVCYCLET, cycle);
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];
u32 txqctl = 0;
u16 cbs_value;
u32 tqavcc;
wr32(IGC_STQT(i), ring->start_time);
wr32(IGC_ENDQT(i), ring->end_time);
if (adapter->base_time) {
/* If we have a base_time we are in "taprio"
* mode and we need to be strict about the
* cycles: only transmit a packet if it can be
* completed during that cycle.
*/
txqctl |= IGC_TXQCTL_STRICT_CYCLE |
IGC_TXQCTL_STRICT_END;
}
if (ring->launchtime_enable)
txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
/* Skip configuring CBS for Q2 and Q3 */
if (i > 1)
goto skip_cbs;
if (ring->cbs_enable) {
if (i == 0)
txqctl |= IGC_TXQCTL_QAV_SEL_CBS0;
else
txqctl |= IGC_TXQCTL_QAV_SEL_CBS1;
/* According to i225 datasheet section 7.5.2.7, we
* should set the 'idleSlope' field from TQAVCC
* register following the equation:
*
* value = link-speed 0x7736 * BW * 0.2
* ---------- * ----------------- (E1)
* 100Mbps 2.5
*
* Note that 'link-speed' is in Mbps.
*
* 'BW' is the percentage bandwidth out of full
* link speed which can be found with the
* following equation. Note that idleSlope here
* is the parameter from this function
* which is in kbps.
*
* BW = idleSlope
* ----------------- (E2)
* link-speed * 1000
*
* That said, we can come up with a generic
* equation to calculate the value we should set
* it TQAVCC register by replacing 'BW' in E1 by E2.
* The resulting equation is:
*
* value = link-speed * 0x7736 * idleSlope * 0.2
* ------------------------------------- (E3)
* 100 * 2.5 * link-speed * 1000
*
* 'link-speed' is present in both sides of the
* fraction so it is canceled out. The final
* equation is the following:
*
* value = idleSlope * 61036
* ----------------- (E4)
* 2500000
*
* NOTE: For i225, given the above, we can see
* that idleslope is represented in
* 40.959433 kbps units by the value at
* the TQAVCC register (2.5Gbps / 61036),
* which reduces the granularity for
* idleslope increments.
*
* In i225 controller, the sendSlope and loCredit
* parameters from CBS are not configurable
* by software so we don't do any
* 'controller configuration' in respect to
* these parameters.
*/
cbs_value = DIV_ROUND_UP_ULL(ring->idleslope
* 61036ULL, 2500000);
tqavcc = rd32(IGC_TQAVCC(i));
tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK;
tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS;
wr32(IGC_TQAVCC(i), tqavcc);
wr32(IGC_TQAVHC(i),
0x80000000 + ring->hicredit * 0x7735);
} else {
/* Disable any CBS for the queue */
txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK);
/* Set idleSlope to zero. */
tqavcc = rd32(IGC_TQAVCC(i));
tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK |
IGC_TQAVCC_KEEP_CREDITS);
wr32(IGC_TQAVCC(i), tqavcc);
/* Set hiCredit to zero. */
wr32(IGC_TQAVHC(i), 0);
}
skip_cbs:
wr32(IGC_TXQCTL(i), txqctl);
}
nsec = rd32(IGC_SYSTIML);
sec = rd32(IGC_SYSTIMH);
systim = ktime_set(sec, nsec);
if (ktime_compare(systim, base_time) > 0) {
s64 n;
n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
base_time = ktime_add_ns(base_time, (n + 1) * cycle);
}
baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
wr32(IGC_BASET_H, baset_h);
wr32(IGC_BASET_L, baset_l);
return 0;
}
int igc_tsn_reset(struct igc_adapter *adapter)
{
unsigned int new_flags;
int err = 0;
new_flags = igc_tsn_new_flags(adapter);
if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
return igc_tsn_disable_offload(adapter);
err = igc_tsn_enable_offload(adapter);
if (err < 0)
return err;
adapter->flags = new_flags;
return err;
}
int igc_tsn_offload_apply(struct igc_adapter *adapter)
{
int err;
if (netif_running(adapter->netdev)) {
schedule_work(&adapter->reset_task);
return 0;
}
err = igc_tsn_enable_offload(adapter);
if (err < 0)
return err;
adapter->flags = igc_tsn_new_flags(adapter);
return 0;
}

View File

@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2020 Intel Corporation */
#ifndef _IGC_TSN_H_
#define _IGC_TSN_H_
int igc_tsn_offload_apply(struct igc_adapter *adapter);
int igc_tsn_reset(struct igc_adapter *adapter);
#endif /* _IGC_BASE_H */

View File

@@ -0,0 +1,267 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2019 Intel Corporation */
#include "igc.h"
#include "igc_tsn.h"
static bool is_any_launchtime(struct igc_adapter *adapter)
{
int i;
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];
if (ring->launchtime_enable)
return true;
}
return false;
}
static bool is_cbs_enabled(struct igc_adapter *adapter)
{
int i;
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];
if (ring->cbs_enable)
return true;
}
return false;
}
static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
{
unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED;
if (adapter->base_time)
new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
if (is_any_launchtime(adapter))
new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
if (is_cbs_enabled(adapter))
new_flags |= IGC_FLAG_TSN_QAV_ENABLED;
return new_flags;
}
/* Returns the TSN specific registers to their default values after
* the adapter is reset.
*/
static int igc_tsn_disable_offload(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
u32 tqavctrl;
int i;
wr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);
tqavctrl = rd32(IGC_TQAVCTRL);
tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |
IGC_TQAVCTRL_ENHANCED_QAV);
wr32(IGC_TQAVCTRL, tqavctrl);
for (i = 0; i < adapter->num_tx_queues; i++) {
wr32(IGC_TXQCTL(i), 0);
wr32(IGC_STQT(i), 0);
wr32(IGC_ENDQT(i), NSEC_PER_SEC);
}
wr32(IGC_QBVCYCLET_S, 0);
wr32(IGC_QBVCYCLET, NSEC_PER_SEC);
adapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED;
return 0;
}
static int igc_tsn_enable_offload(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
u32 tqavctrl, baset_l, baset_h;
u32 sec, nsec, cycle;
ktime_t base_time, systim;
int i;
cycle = adapter->cycle_time;
base_time = adapter->base_time;
wr32(IGC_TSAUXC, 0);
wr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);
wr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);
tqavctrl = rd32(IGC_TQAVCTRL);
tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
wr32(IGC_TQAVCTRL, tqavctrl);
wr32(IGC_QBVCYCLET_S, cycle);
wr32(IGC_QBVCYCLET, cycle);
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igc_ring *ring = adapter->tx_ring[i];
u32 txqctl = 0;
u16 cbs_value;
u32 tqavcc;
wr32(IGC_STQT(i), ring->start_time);
wr32(IGC_ENDQT(i), ring->end_time);
if (adapter->base_time) {
/* If we have a base_time we are in "taprio"
* mode and we need to be strict about the
* cycles: only transmit a packet if it can be
* completed during that cycle.
*/
txqctl |= IGC_TXQCTL_STRICT_CYCLE |
IGC_TXQCTL_STRICT_END;
}
if (ring->launchtime_enable)
txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
/* Skip configuring CBS for Q2 and Q3 */
if (i > 1)
goto skip_cbs;
if (ring->cbs_enable) {
if (i == 0)
txqctl |= IGC_TXQCTL_QAV_SEL_CBS0;
else
txqctl |= IGC_TXQCTL_QAV_SEL_CBS1;
/* According to i225 datasheet section 7.5.2.7, we
* should set the 'idleSlope' field from TQAVCC
* register following the equation:
*
* value = link-speed 0x7736 * BW * 0.2
* ---------- * ----------------- (E1)
* 100Mbps 2.5
*
* Note that 'link-speed' is in Mbps.
*
* 'BW' is the percentage bandwidth out of full
* link speed which can be found with the
* following equation. Note that idleSlope here
* is the parameter from this function
* which is in kbps.
*
* BW = idleSlope
* ----------------- (E2)
* link-speed * 1000
*
* That said, we can come up with a generic
* equation to calculate the value we should set
* it TQAVCC register by replacing 'BW' in E1 by E2.
* The resulting equation is:
*
* value = link-speed * 0x7736 * idleSlope * 0.2
* ------------------------------------- (E3)
* 100 * 2.5 * link-speed * 1000
*
* 'link-speed' is present in both sides of the
* fraction so it is canceled out. The final
* equation is the following:
*
* value = idleSlope * 61036
* ----------------- (E4)
* 2500000
*
* NOTE: For i225, given the above, we can see
* that idleslope is represented in
* 40.959433 kbps units by the value at
* the TQAVCC register (2.5Gbps / 61036),
* which reduces the granularity for
* idleslope increments.
*
* In i225 controller, the sendSlope and loCredit
* parameters from CBS are not configurable
* by software so we don't do any
* 'controller configuration' in respect to
* these parameters.
*/
cbs_value = DIV_ROUND_UP_ULL(ring->idleslope
* 61036ULL, 2500000);
tqavcc = rd32(IGC_TQAVCC(i));
tqavcc &= ~IGC_TQAVCC_IDLESLOPE_MASK;
tqavcc |= cbs_value | IGC_TQAVCC_KEEP_CREDITS;
wr32(IGC_TQAVCC(i), tqavcc);
wr32(IGC_TQAVHC(i),
0x80000000 + ring->hicredit * 0x7735);
} else {
/* Disable any CBS for the queue */
txqctl &= ~(IGC_TXQCTL_QAV_SEL_MASK);
/* Set idleSlope to zero. */
tqavcc = rd32(IGC_TQAVCC(i));
tqavcc &= ~(IGC_TQAVCC_IDLESLOPE_MASK |
IGC_TQAVCC_KEEP_CREDITS);
wr32(IGC_TQAVCC(i), tqavcc);
/* Set hiCredit to zero. */
wr32(IGC_TQAVHC(i), 0);
}
skip_cbs:
wr32(IGC_TXQCTL(i), txqctl);
}
nsec = rd32(IGC_SYSTIML);
sec = rd32(IGC_SYSTIMH);
systim = ktime_set(sec, nsec);
if (ktime_compare(systim, base_time) > 0) {
s64 n;
n = div64_s64(ktime_sub_ns(systim, base_time), cycle);
base_time = ktime_add_ns(base_time, (n + 1) * cycle);
}
baset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);
wr32(IGC_BASET_H, baset_h);
wr32(IGC_BASET_L, baset_l);
return 0;
}
int igc_tsn_reset(struct igc_adapter *adapter)
{
unsigned int new_flags;
int err = 0;
new_flags = igc_tsn_new_flags(adapter);
if (!(new_flags & IGC_FLAG_TSN_ANY_ENABLED))
return igc_tsn_disable_offload(adapter);
err = igc_tsn_enable_offload(adapter);
if (err < 0)
return err;
adapter->flags = new_flags;
return err;
}
int igc_tsn_offload_apply(struct igc_adapter *adapter)
{
int err;
if (netif_running(adapter->netdev)) {
schedule_work(&adapter->reset_task);
return 0;
}
err = igc_tsn_enable_offload(adapter);
if (err < 0)
return err;
adapter->flags = igc_tsn_new_flags(adapter);
return 0;
}

View File

@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2020 Intel Corporation */
#ifndef _IGC_TSN_H_
#define _IGC_TSN_H_
int igc_tsn_offload_apply(struct igc_adapter *adapter);
int igc_tsn_reset(struct igc_adapter *adapter);
#endif /* _IGC_BASE_H */

View File

@@ -0,0 +1,146 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2020, Intel Corporation. */
#include <net/xdp_sock_drv.h>
#include <linux/if_vlan.h>
#include "igc-5.15-ethercat.h"
#include "igc_xdp-5.15-ethercat.h"
int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
struct netlink_ext_ack *extack)
{
struct net_device *dev = adapter->netdev;
bool if_running = netif_running(dev);
struct bpf_prog *old_prog;
if (dev->mtu > ETH_DATA_LEN) {
/* For now, the driver doesn't support XDP functionality with
* jumbo frames so we return error.
*/
NL_SET_ERR_MSG_MOD(extack, "Jumbo frames not supported");
return -EOPNOTSUPP;
}
if (if_running)
igc_close(dev);
old_prog = xchg(&adapter->xdp_prog, prog);
if (old_prog)
bpf_prog_put(old_prog);
if (if_running)
igc_open(dev);
return 0;
}
static int igc_xdp_enable_pool(struct igc_adapter *adapter,
struct xsk_buff_pool *pool, u16 queue_id)
{
struct net_device *ndev = adapter->netdev;
struct device *dev = &adapter->pdev->dev;
struct igc_ring *rx_ring, *tx_ring;
struct napi_struct *napi;
bool needs_reset;
u32 frame_size;
int err;
if (queue_id >= adapter->num_rx_queues ||
queue_id >= adapter->num_tx_queues)
return -EINVAL;
frame_size = xsk_pool_get_rx_frame_size(pool);
if (frame_size < ETH_FRAME_LEN + VLAN_HLEN * 2) {
/* When XDP is enabled, the driver doesn't support frames that
* span over multiple buffers. To avoid that, we check if xsk
* frame size is big enough to fit the max ethernet frame size
* + vlan double tagging.
*/
return -EOPNOTSUPP;
}
err = xsk_pool_dma_map(pool, dev, IGC_RX_DMA_ATTR);
if (err) {
netdev_err(ndev, "Failed to map xsk pool\n");
return err;
}
needs_reset = netif_running(adapter->netdev) && igc_xdp_is_enabled(adapter);
rx_ring = adapter->rx_ring[queue_id];
tx_ring = adapter->tx_ring[queue_id];
/* Rx and Tx rings share the same napi context. */
napi = &rx_ring->q_vector->napi;
if (needs_reset) {
igc_disable_rx_ring(rx_ring);
igc_disable_tx_ring(tx_ring);
napi_disable(napi);
}
set_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags);
set_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags);
if (needs_reset) {
napi_enable(napi);
igc_enable_rx_ring(rx_ring);
igc_enable_tx_ring(tx_ring);
err = igc_xsk_wakeup(ndev, queue_id, XDP_WAKEUP_RX);
if (err) {
xsk_pool_dma_unmap(pool, IGC_RX_DMA_ATTR);
return err;
}
}
return 0;
}
static int igc_xdp_disable_pool(struct igc_adapter *adapter, u16 queue_id)
{
struct igc_ring *rx_ring, *tx_ring;
struct xsk_buff_pool *pool;
struct napi_struct *napi;
bool needs_reset;
if (queue_id >= adapter->num_rx_queues ||
queue_id >= adapter->num_tx_queues)
return -EINVAL;
pool = xsk_get_pool_from_qid(adapter->netdev, queue_id);
if (!pool)
return -EINVAL;
needs_reset = netif_running(adapter->netdev) && igc_xdp_is_enabled(adapter);
rx_ring = adapter->rx_ring[queue_id];
tx_ring = adapter->tx_ring[queue_id];
/* Rx and Tx rings share the same napi context. */
napi = &rx_ring->q_vector->napi;
if (needs_reset) {
igc_disable_rx_ring(rx_ring);
igc_disable_tx_ring(tx_ring);
napi_disable(napi);
}
xsk_pool_dma_unmap(pool, IGC_RX_DMA_ATTR);
clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags);
clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags);
if (needs_reset) {
napi_enable(napi);
igc_enable_rx_ring(rx_ring);
igc_enable_tx_ring(tx_ring);
}
return 0;
}
int igc_xdp_setup_pool(struct igc_adapter *adapter, struct xsk_buff_pool *pool,
u16 queue_id)
{
return pool ? igc_xdp_enable_pool(adapter, pool, queue_id) :
igc_xdp_disable_pool(adapter, queue_id);
}

View File

@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2020, Intel Corporation. */
#ifndef _IGC_XDP_H_
#define _IGC_XDP_H_
int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
struct netlink_ext_ack *extack);
int igc_xdp_setup_pool(struct igc_adapter *adapter, struct xsk_buff_pool *pool,
u16 queue_id);
static inline bool igc_xdp_is_enabled(struct igc_adapter *adapter)
{
return !!adapter->xdp_prog;
}
#endif /* _IGC_XDP_H_ */

View File

@@ -0,0 +1,145 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2020, Intel Corporation. */
#include <net/xdp_sock_drv.h>
#include "igc.h"
#include "igc_xdp.h"
int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
struct netlink_ext_ack *extack)
{
struct net_device *dev = adapter->netdev;
bool if_running = netif_running(dev);
struct bpf_prog *old_prog;
if (dev->mtu > ETH_DATA_LEN) {
/* For now, the driver doesn't support XDP functionality with
* jumbo frames so we return error.
*/
NL_SET_ERR_MSG_MOD(extack, "Jumbo frames not supported");
return -EOPNOTSUPP;
}
if (if_running)
igc_close(dev);
old_prog = xchg(&adapter->xdp_prog, prog);
if (old_prog)
bpf_prog_put(old_prog);
if (if_running)
igc_open(dev);
return 0;
}
static int igc_xdp_enable_pool(struct igc_adapter *adapter,
struct xsk_buff_pool *pool, u16 queue_id)
{
struct net_device *ndev = adapter->netdev;
struct device *dev = &adapter->pdev->dev;
struct igc_ring *rx_ring, *tx_ring;
struct napi_struct *napi;
bool needs_reset;
u32 frame_size;
int err;
if (queue_id >= adapter->num_rx_queues ||
queue_id >= adapter->num_tx_queues)
return -EINVAL;
frame_size = xsk_pool_get_rx_frame_size(pool);
if (frame_size < ETH_FRAME_LEN + VLAN_HLEN * 2) {
/* When XDP is enabled, the driver doesn't support frames that
* span over multiple buffers. To avoid that, we check if xsk
* frame size is big enough to fit the max ethernet frame size
* + vlan double tagging.
*/
return -EOPNOTSUPP;
}
err = xsk_pool_dma_map(pool, dev, IGC_RX_DMA_ATTR);
if (err) {
netdev_err(ndev, "Failed to map xsk pool\n");
return err;
}
needs_reset = netif_running(adapter->netdev) && igc_xdp_is_enabled(adapter);
rx_ring = adapter->rx_ring[queue_id];
tx_ring = adapter->tx_ring[queue_id];
/* Rx and Tx rings share the same napi context. */
napi = &rx_ring->q_vector->napi;
if (needs_reset) {
igc_disable_rx_ring(rx_ring);
igc_disable_tx_ring(tx_ring);
napi_disable(napi);
}
set_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags);
set_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags);
if (needs_reset) {
napi_enable(napi);
igc_enable_rx_ring(rx_ring);
igc_enable_tx_ring(tx_ring);
err = igc_xsk_wakeup(ndev, queue_id, XDP_WAKEUP_RX);
if (err) {
xsk_pool_dma_unmap(pool, IGC_RX_DMA_ATTR);
return err;
}
}
return 0;
}
static int igc_xdp_disable_pool(struct igc_adapter *adapter, u16 queue_id)
{
struct igc_ring *rx_ring, *tx_ring;
struct xsk_buff_pool *pool;
struct napi_struct *napi;
bool needs_reset;
if (queue_id >= adapter->num_rx_queues ||
queue_id >= adapter->num_tx_queues)
return -EINVAL;
pool = xsk_get_pool_from_qid(adapter->netdev, queue_id);
if (!pool)
return -EINVAL;
needs_reset = netif_running(adapter->netdev) && igc_xdp_is_enabled(adapter);
rx_ring = adapter->rx_ring[queue_id];
tx_ring = adapter->tx_ring[queue_id];
/* Rx and Tx rings share the same napi context. */
napi = &rx_ring->q_vector->napi;
if (needs_reset) {
igc_disable_rx_ring(rx_ring);
igc_disable_tx_ring(tx_ring);
napi_disable(napi);
}
xsk_pool_dma_unmap(pool, IGC_RX_DMA_ATTR);
clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags);
clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags);
if (needs_reset) {
napi_enable(napi);
igc_enable_rx_ring(rx_ring);
igc_enable_tx_ring(tx_ring);
}
return 0;
}
int igc_xdp_setup_pool(struct igc_adapter *adapter, struct xsk_buff_pool *pool,
u16 queue_id)
{
return pool ? igc_xdp_enable_pool(adapter, pool, queue_id) :
igc_xdp_disable_pool(adapter, queue_id);
}

View File

@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2020, Intel Corporation. */
#ifndef _IGC_XDP_H_
#define _IGC_XDP_H_
int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
struct netlink_ext_ack *extack);
int igc_xdp_setup_pool(struct igc_adapter *adapter, struct xsk_buff_pool *pool,
u16 queue_id);
static inline bool igc_xdp_is_enabled(struct igc_adapter *adapter)
{
return !!adapter->xdp_prog;
}
#endif /* _IGC_XDP_H_ */