diff mbox series

[v1,03/15] net/igc: device initialization

Message ID 1583742247-370386-3-git-send-email-alvinx.zhang@intel.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers show
Series [v1,01/15] net/igc: add igc PMD | expand

Checks

Context Check Description
ci/Intel-compilation success Compilation OK
ci/checkpatch success coding style OK

Commit Message

Zhang, AlvinX March 9, 2020, 8:23 a.m. UTC
From: Alvin Zhang <alvinx.zhang@intel.com>

Add functions and definitions that are OS specified.
Add readme too.

Signed-off-by: Alvin Zhang <alvinx.zhang@intel.com>
---
 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

Comments

Xiaolong Ye March 12, 2020, 4:42 a.m. UTC | #1
Better to use imperative mode like "add device initialization" for the commit
subject.

And the subject doesn't match what this patch really does, it's more about
adding OS specific functions and definitions other than 'device initialization'.

On 03/09, alvinx.zhang@intel.com wrote:
>From: Alvin Zhang <alvinx.zhang@intel.com>
>
>Add functions and definitions that are OS specified.
>Add readme too.
>
>Signed-off-by: Alvin Zhang <alvinx.zhang@intel.com>
>---
> 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

If these makefile changes are for base, they should go with base code update
patch.

> 
>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 <stdint.h>
>+#include <stdio.h>
>+#include <stdarg.h>
>+#include <string.h>
>+#include <rte_common.h>
>+#include <rte_cycles.h>
>+#include <rte_log.h>
>+#include <rte_debug.h>
>+#include <rte_byteorder.h>
>+#include <rte_io.h>
>+
>+#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

Use stdbool.h instead of the customized 'true' and 'false'.

>+
>+#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);

No need to split into 2 lines.

>+
>+	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 = &eth_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 <rte_ethdev.h>
>+
>+#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')

Shouldn't this be included in the previous base code update patch?

>-- 
>1.8.3.1
>
diff mbox series

Patch

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 <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <rte_common.h>
+#include <rte_cycles.h>
+#include <rte_log.h>
+#include <rte_debug.h>
+#include <rte_byteorder.h>
+#include <rte_io.h>
+
+#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 = &eth_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 <rte_ethdev.h>
+
+#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')