From patchwork Mon Mar 9 08:23:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alvin Zhang X-Patchwork-Id: 66381 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 701AEA052E; Mon, 9 Mar 2020 09:28:53 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 4A37B1C012; Mon, 9 Mar 2020 09:28:53 +0100 (CET) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 7F2CE1BFFB for ; Mon, 9 Mar 2020 09:28:51 +0100 (CET) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga106.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 09 Mar 2020 01:28:50 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,518,1574150400"; d="scan'208";a="260350685" Received: from unknown (HELO dpdk-zhangalvin-dev.sh.intel.com) ([10.240.179.50]) by orsmga002.jf.intel.com with ESMTP; 09 Mar 2020 01:28:48 -0700 From: alvinx.zhang@intel.com To: dev@dpdk.org Cc: haiyue.wang@intel.com, xiaolong.ye@intel.com, qi.z.zhang@intel.com, beilei.xing@intel.com, Alvin Zhang Date: Mon, 9 Mar 2020 16:23:55 +0800 Message-Id: <1583742247-370386-3-git-send-email-alvinx.zhang@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1583742247-370386-1-git-send-email-alvinx.zhang@intel.com> References: <1583742247-370386-1-git-send-email-alvinx.zhang@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v1 03/15] net/igc: device initialization X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Alvin Zhang Add functions and definitions that are OS specified. Add readme too. Signed-off-by: Alvin Zhang --- drivers/net/igc/Makefile | 46 +++++++ drivers/net/igc/base/README | 23 ++++ drivers/net/igc/base/e1000_osdep.c | 64 +++++++++ drivers/net/igc/base/e1000_osdep.h | 155 ++++++++++++++++++++++ drivers/net/igc/base/meson.build | 28 ++++ drivers/net/igc/igc_ethdev.c | 265 +++++++++++++++++++++++++++++++++++-- drivers/net/igc/igc_ethdev.h | 19 +++ drivers/net/igc/meson.build | 5 + 8 files changed, 595 insertions(+), 10 deletions(-) create mode 100644 drivers/net/igc/base/README create mode 100644 drivers/net/igc/base/e1000_osdep.c create mode 100644 drivers/net/igc/base/e1000_osdep.h create mode 100644 drivers/net/igc/base/meson.build diff --git a/drivers/net/igc/Makefile b/drivers/net/igc/Makefile index 7b51daf..7c8d00d 100644 --- a/drivers/net/igc/Makefile +++ b/drivers/net/igc/Makefile @@ -13,12 +13,58 @@ CFLAGS += $(WERROR_FLAGS) LDLIBS += -lrte_eal LDLIBS += -lrte_ethdev LDLIBS += -lrte_bus_pci +LDLIBS += -lrte_mbuf +LDLIBS += -lrte_mempool EXPORT_MAP := rte_pmd_igc_version.map # +# Add extra flags for base driver files (also known as shared code) +# to disable warnings +# +ifeq ($(CONFIG_RTE_TOOLCHAIN_ICC),y) +# +# CFLAGS for icc +# +CFLAGS_BASE_DRIVER = -diag-disable 177 -diag-disable 181 +CFLAGS_BASE_DRIVER += -diag-disable 869 -diag-disable 2259 +else +# +# CFLAGS for gcc/clang +# +CFLAGS_BASE_DRIVER = -Wno-unused-parameter +CFLAGS_BASE_DRIVER += -Wno-unused-variable +CFLAGS_BASE_DRIVER += -Wno-uninitialized +ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) +ifeq ($(shell test $(GCC_VERSION) -ge 60 && echo 1), 1) +CFLAGS_BASE_DRIVER += -Wno-misleading-indentation +ifeq ($(shell test $(GCC_VERSION) -ge 70 && echo 1), 1) +CFLAGS_BASE_DRIVER += -Wno-implicit-fallthrough +endif +endif +endif +endif + +# +# Add extra flags for base driver files (also known as shared code) +# to disable warnings in them +# +BASE_DRIVER_OBJS=$(sort $(patsubst %.c,%.o,$(notdir $(wildcard $(SRCDIR)/base/*.c)))) +$(foreach obj, $(BASE_DRIVER_OBJS), $(eval CFLAGS_$(obj)+=$(CFLAGS_BASE_DRIVER))) + +VPATH += $(SRCDIR)/base + +# # all source are stored in SRCS-y # +SRCS-$(CONFIG_RTE_LIBRTE_IGC_PMD) += e1000_api.c +SRCS-$(CONFIG_RTE_LIBRTE_IGC_PMD) += e1000_base.c +SRCS-$(CONFIG_RTE_LIBRTE_IGC_PMD) += e1000_i225.c +SRCS-$(CONFIG_RTE_LIBRTE_IGC_PMD) += e1000_mac.c +SRCS-$(CONFIG_RTE_LIBRTE_IGC_PMD) += e1000_manage.c +SRCS-$(CONFIG_RTE_LIBRTE_IGC_PMD) += e1000_nvm.c +SRCS-$(CONFIG_RTE_LIBRTE_IGC_PMD) += e1000_osdep.c +SRCS-$(CONFIG_RTE_LIBRTE_IGC_PMD) += e1000_phy.c SRCS-$(CONFIG_RTE_LIBRTE_IGC_PMD) += igc_logs.c SRCS-$(CONFIG_RTE_LIBRTE_IGC_PMD) += igc_ethdev.c diff --git a/drivers/net/igc/base/README b/drivers/net/igc/base/README new file mode 100644 index 0000000..31e2f26 --- /dev/null +++ b/drivers/net/igc/base/README @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2020 Intel Corporation + */ + +IntelĀ® IGC driver +================== + +This directory contains source code of FreeBSD igc driver of version +2019.10.18 released by the team which develops basic drivers for any +i225 NIC. +The directory of base/ contains the original source package. +This driver is valid for the product(s) listed below + +* IntelĀ® Ethernet Network Adapters I225 + +Updating the driver +=================== + +NOTE: The source code in this directory should not be modified apart from +the following file(s): + + e1000_osdep.h + e1000_osdep.c diff --git a/drivers/net/igc/base/e1000_osdep.c b/drivers/net/igc/base/e1000_osdep.c new file mode 100644 index 0000000..56703cb --- /dev/null +++ b/drivers/net/igc/base/e1000_osdep.c @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2001-2020 + */ + +#include "e1000_api.h" + +/* + * NOTE: the following routines using the igc + * naming style are provided to the shared + * code but are OS specific + */ + +void +igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value) +{ + (void)hw; + (void)reg; + (void)value; +} + +void +igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value) +{ + (void)hw; + (void)reg; + *value = 0; +} + +void +igc_pci_set_mwi(struct igc_hw *hw) +{ + (void)hw; +} + +void +igc_pci_clear_mwi(struct igc_hw *hw) +{ + (void)hw; +} + +/* + * Read the PCI Express capabilities + */ +int32_t +igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value) +{ + (void)hw; + (void)reg; + (void)value; + return IGC_NOT_IMPLEMENTED; +} + +/* + * Write the PCI Express capabilities + */ +int32_t +igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value) +{ + (void)hw; + (void)reg; + (void)value; + + return IGC_NOT_IMPLEMENTED; +} diff --git a/drivers/net/igc/base/e1000_osdep.h b/drivers/net/igc/base/e1000_osdep.h new file mode 100644 index 0000000..57d646e --- /dev/null +++ b/drivers/net/igc/base/e1000_osdep.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2001-2020 + */ + + +#ifndef _IGC_OSDEP_H_ +#define _IGC_OSDEP_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../igc_logs.h" + +#define DELAY(x) rte_delay_us(x) +#define usec_delay(x) DELAY(x) +#define usec_delay_irq(x) DELAY(x) +#define msec_delay(x) DELAY(1000 * (x)) +#define msec_delay_irq(x) DELAY(1000 * (x)) + +#define DEBUGFUNC(F) DEBUGOUT(F "\n") +#define DEBUGOUT(S, args...) PMD_DRV_LOG_RAW(DEBUG, S, ##args) +#define DEBUGOUT1(S, args...) DEBUGOUT(S, ##args) +#define DEBUGOUT2(S, args...) DEBUGOUT(S, ##args) +#define DEBUGOUT3(S, args...) DEBUGOUT(S, ##args) +#define DEBUGOUT6(S, args...) DEBUGOUT(S, ##args) +#define DEBUGOUT7(S, args...) DEBUGOUT(S, ##args) + +#define UNREFERENCED_PARAMETER(_p) +#define UNREFERENCED_1PARAMETER(_p) +#define UNREFERENCED_2PARAMETER(_p, _q) +#define UNREFERENCED_3PARAMETER(_p, _q, _r) +#define UNREFERENCED_4PARAMETER(_p, _q, _r, _s) + +#define FALSE 0 +#define TRUE 1 + +#define CMD_MEM_WRT_INVALIDATE 0x0010 /* BIT_4 */ + +/* Mutex used in the shared code */ +#define IGC_MUTEX uintptr_t +#define IGC_MUTEX_INIT(mutex) (*(mutex) = 0) +#define IGC_MUTEX_LOCK(mutex) (*(mutex) = 1) +#define IGC_MUTEX_UNLOCK(mutex) (*(mutex) = 0) + +typedef uint64_t u64; +typedef uint32_t u32; +typedef uint16_t u16; +typedef uint8_t u8; +typedef int64_t s64; +typedef int32_t s32; +typedef int16_t s16; +typedef int8_t s8; +typedef int bool; + +#define STATIC static +#define false FALSE +#define true TRUE + +#define __le16 u16 +#define __le32 u32 +#define __le64 u64 + +#define IGC_WRITE_FLUSH(a) IGC_READ_REG(a, IGC_STATUS) + +#define IGC_PCI_REG(reg) rte_read32(reg) + +#define IGC_PCI_REG16(reg) rte_read16(reg) + +#define IGC_PCI_REG_WRITE(reg, value) \ + rte_write32((rte_cpu_to_le_32(value)), reg) + +#define IGC_PCI_REG_WRITE_RELAXED(reg, value) \ + rte_write32_relaxed((rte_cpu_to_le_32(value)), reg) + +#define IGC_PCI_REG_WRITE16(reg, value) \ + rte_write16((rte_cpu_to_le_16(value)), reg) + +#define IGC_PCI_REG_ADDR(hw, reg) \ + ((volatile uint32_t *)((char *)(hw)->hw_addr + (reg))) + +#define IGC_PCI_REG_ARRAY_ADDR(hw, reg, index) \ + IGC_PCI_REG_ADDR((hw), (reg) + ((index) << 2)) + +#define IGC_PCI_REG_FLASH_ADDR(hw, reg) \ + ((volatile uint32_t *)((char *)(hw)->flash_address + (reg))) + +static inline uint32_t igc_read_addr(volatile void *addr) +{ + return rte_le_to_cpu_32(IGC_PCI_REG(addr)); +} + +static inline uint16_t igc_read_addr16(volatile void *addr) +{ + return rte_le_to_cpu_16(IGC_PCI_REG16(addr)); +} + +/* Register READ/WRITE macros */ + +#define IGC_READ_REG(hw, reg) \ + igc_read_addr(IGC_PCI_REG_ADDR((hw), (reg))) + +#define IGC_READ_REG_LE_VALUE(hw, reg) \ + rte_read32(IGC_PCI_REG_ADDR((hw), (reg))) + +#define IGC_WRITE_REG(hw, reg, value) \ + IGC_PCI_REG_WRITE(IGC_PCI_REG_ADDR((hw), (reg)), (value)) + +#define IGC_WRITE_REG_LE_VALUE(hw, reg, value) \ + rte_write32(value, IGC_PCI_REG_ADDR((hw), (reg))) + +#define IGC_READ_REG_ARRAY(hw, reg, index) \ + IGC_PCI_REG(IGC_PCI_REG_ARRAY_ADDR((hw), (reg), (index))) + +#define IGC_WRITE_REG_ARRAY(hw, reg, index, value) \ + IGC_PCI_REG_WRITE(IGC_PCI_REG_ARRAY_ADDR((hw), (reg), (index)), \ + (value)) + +#define IGC_READ_REG_ARRAY_DWORD IGC_READ_REG_ARRAY +#define IGC_WRITE_REG_ARRAY_DWORD IGC_WRITE_REG_ARRAY + +/* + * To be able to do IO write, we need to map IO BAR + * (bar 2/4 depending on device). + * Right now mapping multiple BARs is not supported by DPDK. + * Fortunatelly we need it only for legacy hw support. + */ + +#define IGC_WRITE_REG_IO(hw, reg, value) \ + IGC_WRITE_REG(hw, reg, value) + +/* + * Tested on I217/I218 chipset. + */ + +#define IGC_READ_FLASH_REG(hw, reg) \ + igc_read_addr(IGC_PCI_REG_FLASH_ADDR((hw), (reg))) + +#define IGC_READ_FLASH_REG16(hw, reg) \ + igc_read_addr16(IGC_PCI_REG_FLASH_ADDR((hw), (reg))) + +#define IGC_WRITE_FLASH_REG(hw, reg, value) \ + IGC_PCI_REG_WRITE(IGC_PCI_REG_FLASH_ADDR((hw), (reg)), (value)) + +#define IGC_WRITE_FLASH_REG16(hw, reg, value) \ + IGC_PCI_REG_WRITE16(IGC_PCI_REG_FLASH_ADDR((hw), (reg)), (value)) + +#endif /* _IGC_OSDEP_H_ */ diff --git a/drivers/net/igc/base/meson.build b/drivers/net/igc/base/meson.build new file mode 100644 index 0000000..f51026e --- /dev/null +++ b/drivers/net/igc/base/meson.build @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2020 Intel Corporation + +sources = [ + 'e1000_api.c', + 'e1000_base.c', + 'e1000_i225.c', + 'e1000_mac.c', + 'e1000_manage.c', + 'e1000_nvm.c', + 'e1000_osdep.c', + 'e1000_phy.c', +] + +error_cflags = ['-Wno-unused-parameter', '-Wno-unused-variable'] +c_args = cflags + +foreach flag: error_cflags + if cc.has_argument(flag) + c_args += flag + endif +endforeach + +base_lib = static_library('igc_base', sources, + dependencies: static_rte_eal, + c_args: c_args) + +base_objs = base_lib.extract_all_objects() diff --git a/drivers/net/igc/igc_ethdev.c b/drivers/net/igc/igc_ethdev.c index 2baba69..4d78f0e 100644 --- a/drivers/net/igc/igc_ethdev.c +++ b/drivers/net/igc/igc_ethdev.c @@ -11,11 +11,8 @@ #include "igc_ethdev.h" #define IGC_INTEL_VENDOR_ID 0x8086 -#define IGC_DEV_ID_I225_LM 0x15F2 -#define IGC_DEV_ID_I225_V 0x15F3 -#define IGC_DEV_ID_I225_K 0x3100 -#define IGC_DEV_ID_I225_I 0x15F8 -#define IGC_DEV_ID_I220_V 0x15F7 + +#define IGC_FC_PAUSE_TIME 0x0680 static const struct rte_pci_id pci_id_igc_map[] = { { RTE_PCI_DEVICE(IGC_INTEL_VENDOR_ID, IGC_DEV_ID_I225_LM) }, @@ -84,6 +81,90 @@ static int eth_igc_infos_get(struct rte_eth_dev *dev, RTE_SET_USED(dev); } +/* + * Get hardware rx-buffer size. + */ +static inline int +igc_get_rx_buffer_size(struct igc_hw *hw) +{ + return (IGC_READ_REG(hw, IGC_RXPBS) & 0x3f) << 10; +} + +/* + * igc_hw_control_acquire sets CTRL_EXT:DRV_LOAD bit. + * For ASF and Pass Through versions of f/w this means + * that the driver is loaded. + */ +static void +igc_hw_control_acquire(struct igc_hw *hw) +{ + uint32_t ctrl_ext; + + /* Let firmware know the driver has taken over */ + ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT); + IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext | IGC_CTRL_EXT_DRV_LOAD); +} + +/* + * igc_hw_control_release resets CTRL_EXT:DRV_LOAD bit. + * For ASF and Pass Through versions of f/w this means that the + * driver is no longer loaded. + */ +static void +igc_hw_control_release(struct igc_hw *hw) +{ + uint32_t ctrl_ext; + + /* Let firmware taken over control of h/w */ + ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT); + IGC_WRITE_REG(hw, IGC_CTRL_EXT, + ctrl_ext & ~IGC_CTRL_EXT_DRV_LOAD); +} + +static int +igc_hardware_init(struct igc_hw *hw) +{ + uint32_t rx_buf_size; + int diag; + + /* Let the firmware know the OS is in control */ + igc_hw_control_acquire(hw); + + /* Issue a global reset */ + igc_reset_hw(hw); + + /* disable all wake up */ + IGC_WRITE_REG(hw, IGC_WUC, 0); + + /* + * Hardware flow control + * - High water mark should allow for at least two standard size (1518) + * frames to be received after sending an XOFF. + * - Low water mark works best when it is very near the high water mark. + * This allows the receiver to restart by sending XON when it has + * drained a bit. Here we use an arbitrary value of 1500 which will + * restart after one full frame is pulled from the buffer. There + * could be several smaller frames in the buffer and if so they will + * not trigger the XON until their total number reduces the buffer + * by 1500. + */ + rx_buf_size = igc_get_rx_buffer_size(hw); + hw->fc.high_water = rx_buf_size - (RTE_ETHER_MAX_LEN * 2); + hw->fc.low_water = hw->fc.high_water - 1500; + hw->fc.pause_time = IGC_FC_PAUSE_TIME; + hw->fc.send_xon = 1; + hw->fc.requested_mode = igc_fc_full; + + diag = igc_init_hw(hw); + if (diag < 0) + return diag; + + igc_get_phy_info(hw); + igc_check_for_link(hw); + + return 0; +} + static int eth_igc_start(struct rte_eth_dev *dev) { @@ -92,17 +173,92 @@ static int eth_igc_infos_get(struct rte_eth_dev *dev, return 0; } +static int +igc_reset_swfw_lock(struct igc_hw *hw) +{ + int ret_val; + + /* + * Do mac ops initialization manually here, since we will need + * some function pointers set by this call. + */ + ret_val = igc_init_mac_params(hw); + if (ret_val) + return ret_val; + + /* + * SMBI lock should not fail in this early stage. If this is the case, + * it is due to an improper exit of the application. + * So force the release of the faulty lock. + */ + if (igc_get_hw_semaphore_generic(hw) < 0) + PMD_DRV_LOG(DEBUG, "SMBI lock released"); + + igc_put_hw_semaphore_generic(hw); + + if (hw->mac.ops.acquire_swfw_sync != NULL) { + uint16_t mask; + + /* + * Phy lock should not fail in this early stage. + * If this is the case, it is due to an improper exit of the + * application. So force the release of the faulty lock. + */ + mask = IGC_SWFW_PHY0_SM; + if (hw->mac.ops.acquire_swfw_sync(hw, mask) < 0) { + PMD_DRV_LOG(DEBUG, "SWFW phy%d lock released", + hw->bus.func); + } + hw->mac.ops.release_swfw_sync(hw, mask); + + /* + * This one is more tricky since it is common to all ports; but + * swfw_sync retries last long enough (1s) to be almost sure + * that if lock can not be taken it is due to an improper lock + * of the semaphore. + */ + mask = IGC_SWFW_EEP_SM; + if (hw->mac.ops.acquire_swfw_sync(hw, mask) < 0) + PMD_DRV_LOG(DEBUG, "SWFW common locks released"); + + hw->mac.ops.release_swfw_sync(hw, mask); + } + + return IGC_SUCCESS; +} + static void eth_igc_close(struct rte_eth_dev *dev) { + struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev); + PMD_INIT_FUNC_TRACE(); - RTE_SET_USED(dev); + + igc_phy_hw_reset(hw); + igc_hw_control_release(hw); + + /* Reset any pending lock */ + igc_reset_swfw_lock(hw); +} + +static void +igc_identify_hardware(struct rte_eth_dev *dev, struct rte_pci_device *pci_dev) +{ + struct igc_hw *hw = + IGC_DEV_PRIVATE_HW(dev); + + hw->vendor_id = pci_dev->id.vendor_id; + hw->device_id = pci_dev->id.device_id; + hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id; + hw->subsystem_device_id = pci_dev->id.subsystem_device_id; } static int eth_igc_dev_init(struct rte_eth_dev *dev) { struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct igc_hw *hw = IGC_DEV_PRIVATE_HW(dev); + int error = 0; PMD_INIT_FUNC_TRACE(); dev->dev_ops = ð_igc_ops; @@ -117,12 +273,89 @@ static int eth_igc_infos_get(struct rte_eth_dev *dev, rte_eth_copy_pci_info(dev, pci_dev); + hw->back = pci_dev; + hw->hw_addr = (void *)pci_dev->mem_resource[0].addr; + + igc_identify_hardware(dev, pci_dev); + if (igc_setup_init_funcs(hw, FALSE) != IGC_SUCCESS) { + error = -EIO; + goto err_late; + } + + igc_get_bus_info(hw); + + /* Reset any pending lock */ + if (igc_reset_swfw_lock(hw) != IGC_SUCCESS) { + error = -EIO; + goto err_late; + } + + /* Finish initialization */ + if (igc_setup_init_funcs(hw, TRUE) != IGC_SUCCESS) { + error = -EIO; + goto err_late; + } + + hw->mac.autoneg = 1; + hw->phy.autoneg_wait_to_complete = 0; + hw->phy.autoneg_advertised = IGC_ALL_SPEED_DUPLEX_2500; + + /* Copper options */ + if (hw->phy.media_type == igc_media_type_copper) { + hw->phy.mdix = 0; /* AUTO_ALL_MODES */ + hw->phy.disable_polarity_correction = 0; + hw->phy.ms_type = igc_ms_hw_default; + } + + /* + * Start from a known state, this is important in reading the nvm + * and mac from that. + */ + igc_reset_hw(hw); + + /* Make sure we have a good EEPROM before we read from it */ + if (igc_validate_nvm_checksum(hw) < 0) { + /* + * Some PCI-E parts fail the first check due to + * the link being in sleep state, call it again, + * if it fails a second time its a real issue. + */ + if (igc_validate_nvm_checksum(hw) < 0) { + PMD_INIT_LOG(ERR, "EEPROM checksum invalid"); + error = -EIO; + goto err_late; + } + } + + /* Read the permanent MAC address out of the EEPROM */ + if (igc_read_mac_addr(hw) != 0) { + PMD_INIT_LOG(ERR, "EEPROM error while reading MAC address"); + error = -EIO; + goto err_late; + } + + /* Allocate memory for storing MAC addresses */ dev->data->mac_addrs = rte_zmalloc("igc", - RTE_ETHER_ADDR_LEN, 0); + RTE_ETHER_ADDR_LEN * hw->mac.rar_entry_count, 0); if (dev->data->mac_addrs == NULL) { PMD_INIT_LOG(ERR, "Failed to allocate %d bytes needed to " - "store MAC addresses", RTE_ETHER_ADDR_LEN); - return -ENODEV; + "store MAC addresses", + RTE_ETHER_ADDR_LEN * hw->mac.rar_entry_count); + error = -ENOMEM; + goto err_late; + } + + /* Copy the permanent MAC address */ + rte_ether_addr_copy((struct rte_ether_addr *)hw->mac.addr, + &dev->data->mac_addrs[0]); + + /* Now initialize the hardware */ + if (igc_hardware_init(hw) != 0) { + PMD_INIT_LOG(ERR, "Hardware initialization failed"); + rte_free(dev->data->mac_addrs); + dev->data->mac_addrs = NULL; + error = -ENODEV; + goto err_late; } /* Pass the information to the rte_eth_dev_close() that it should also @@ -130,11 +363,22 @@ static int eth_igc_infos_get(struct rte_eth_dev *dev, */ dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE; + hw->mac.get_link_status = 1; + + /* Indicate SOL/IDER usage */ + if (igc_check_reset_block(hw) < 0) + PMD_INIT_LOG(ERR, "PHY reset is blocked due to" + " SOL/IDER session."); + PMD_INIT_LOG(DEBUG, "port_id %d vendorID=0x%x deviceID=0x%x", dev->data->port_id, pci_dev->id.vendor_id, pci_dev->id.device_id); return 0; + +err_late: + igc_hw_control_release(hw); + return error; } static int @@ -227,7 +471,8 @@ static int eth_igc_infos_get(struct rte_eth_dev *dev, struct rte_pci_device *pci_dev) { PMD_INIT_FUNC_TRACE(); - return rte_eth_dev_pci_generic_probe(pci_dev, 0, eth_igc_dev_init); + return rte_eth_dev_pci_generic_probe(pci_dev, + sizeof(struct igc_adapter), eth_igc_dev_init); } static int diff --git a/drivers/net/igc/igc_ethdev.h b/drivers/net/igc/igc_ethdev.h index a774413..c5d51f6 100644 --- a/drivers/net/igc/igc_ethdev.h +++ b/drivers/net/igc/igc_ethdev.h @@ -5,12 +5,31 @@ #ifndef _IGC_ETHDEV_H_ #define _IGC_ETHDEV_H_ +#include + +#include "base/e1000_osdep.h" +#include "base/e1000_hw.h" +#include "base/e1000_i225.h" +#include "base/e1000_api.h" + #ifdef __cplusplus extern "C" { #endif #define IGC_QUEUE_PAIRS_NUM 4 +/* + * Structure to store private data for each driver instance (for each port). + */ +struct igc_adapter { + struct igc_hw hw; +}; + +#define IGC_DEV_PRIVATE(_dev) ((_dev)->data->dev_private) + +#define IGC_DEV_PRIVATE_HW(_dev) \ + (&((struct igc_adapter *)(_dev)->data->dev_private)->hw) + #ifdef __cplusplus } #endif diff --git a/drivers/net/igc/meson.build b/drivers/net/igc/meson.build index 927938f..ffa62f1 100644 --- a/drivers/net/igc/meson.build +++ b/drivers/net/igc/meson.build @@ -1,7 +1,12 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2020 Intel Corporation +subdir('base') +objs = [base_objs] + sources = files( 'igc_logs.c', 'igc_ethdev.c' ) + +includes += include_directories('base')