The branch main has been updated by grehan:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=517904de5ccac643589c71ac0d2751797f89e4f9

commit 517904de5ccac643589c71ac0d2751797f89e4f9
Author:     Peter Grehan <gre...@freebsd.org>
AuthorDate: 2021-07-12 04:50:15 +0000
Commit:     Peter Grehan <gre...@freebsd.org>
CommitDate: 2021-07-12 04:57:18 +0000

    igc(4): Introduce new driver for the Intel I225 Ethernet controller.
    
    This controller supports 2.5G/1G/100MB/10MB speeds, and allows
    tx/rx checksum offload, TSO, LRO, and multi-queue operation.
    
    The driver was derived from code contributed by Intel, and modified
    by Netgate to fit into the iflib framework.
    
    Thanks to Mike Karels for testing and feedback on the driver.
    
    Reviewed by:    bcr (manpages), kbowling, scottl, erj
    MFC after:      1 month
    Relnotes:       yes
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D30668
---
 share/man/man4/Makefile   |    2 +
 share/man/man4/igc.4      |  167 +++
 sys/amd64/conf/GENERIC    |    1 +
 sys/amd64/conf/NOTES      |    2 +
 sys/conf/files            |    8 +
 sys/dev/igc/if_igc.c      | 2984 +++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/igc/if_igc.h      |  430 +++++++
 sys/dev/igc/igc_api.c     |  735 +++++++++++
 sys/dev/igc/igc_api.h     |   58 +
 sys/dev/igc/igc_base.c    |  188 +++
 sys/dev/igc/igc_base.h    |  131 ++
 sys/dev/igc/igc_defines.h | 1347 ++++++++++++++++++++
 sys/dev/igc/igc_hw.h      |  548 +++++++++
 sys/dev/igc/igc_i225.c    | 1232 +++++++++++++++++++
 sys/dev/igc/igc_i225.h    |  112 ++
 sys/dev/igc/igc_mac.c     | 1050 ++++++++++++++++
 sys/dev/igc/igc_mac.h     |   48 +
 sys/dev/igc/igc_nvm.c     |  721 +++++++++++
 sys/dev/igc/igc_nvm.h     |   32 +
 sys/dev/igc/igc_osdep.h   |  133 ++
 sys/dev/igc/igc_phy.c     | 1109 +++++++++++++++++
 sys/dev/igc/igc_phy.h     |  134 ++
 sys/dev/igc/igc_regs.h    |  424 +++++++
 sys/dev/igc/igc_txrx.c    |  580 +++++++++
 sys/i386/conf/GENERIC     |    1 +
 sys/i386/conf/NOTES       |    2 +
 sys/modules/Makefile      |    2 +
 sys/modules/igc/Makefile  |   11 +
 28 files changed, 12192 insertions(+)

diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index 9027fe7df841..71a0d37631c5 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -224,6 +224,7 @@ MAN=        aac.4 \
        iicmux.4 \
        iicsmb.4 \
        iir.4 \
+       ${_igc.4} \
        ${_imcsmb.4} \
        inet.4 \
        inet6.4 \
@@ -814,6 +815,7 @@ _if_nfe.4=  if_nfe.4
 _if_urtw.4=    if_urtw.4
 _if_vmx.4=     if_vmx.4
 _if_wpi.4=     if_wpi.4
+_igc.4=                igc.4
 _imcsmb.4=     imcsmb.4
 _ipmi.4=       ipmi.4
 _io.4=         io.4
diff --git a/share/man/man4/igc.4 b/share/man/man4/igc.4
new file mode 100644
index 000000000000..bb79fbe5a8fa
--- /dev/null
+++ b/share/man/man4/igc.4
@@ -0,0 +1,167 @@
+.\"-
+.\" Copyright 2021 Intel Corp
+.\" Copyright 2021 Rubicon Communications, LLC (Netgate)
+.\" SPDX-License-Identifier: BSD-3-Clause
+.\"
+.\" $FreeBSD$
+.\"
+.Dd May 10, 2021
+.Dt IGC
+.Os
+.Sh NAME
+.Nm igc
+.Nd "Intel Ethernet Controller I225 driver"
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device iflib"
+.Cd "device igc"
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+if_igc_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for any PCI Express adapter or LOM (LAN
+On Motherboard) based on the Intel I225 Multi Gigabit Controller.
+The driver supports Transmit/Receive checksum offload, Jumbo Frames,
+MSI/MSI-X, TSO, and RSS.
+.Pp
+Support for Jumbo Frames is provided via the interface MTU setting.
+Selecting an MTU larger than 1500 bytes with the
+.Xr ifconfig 8
+utility
+configures the adapter to receive and transmit Jumbo Frames.
+The maximum MTU size for Jumbo Frames is 9216 bytes.
+.Pp
+This driver version supports VLAN hardware insertion / extraction, and
+VLAN checksum offload.
+For information on enabling VLANs, see
+.Xr ifconfig 8 .
+The
+.Nm
+driver supports the following media types:
+.Bl -tag -width ".Cm 10baseT/UTP"
+.It Cm autoselect
+Enables auto-negotiation for speed and duplex.
+.It Cm 10baseT/UTP
+Sets 10Mbps operation.
+Use the
+.Cm mediaopt
+option to select
+.Cm half-duplex
+mode.
+.It Cm 100baseTX
+Sets 100Mbps operation.
+Use the
+.Cm mediaopt
+option to select
+.Cm half-duplex
+mode.
+.It Cm 1000baseT
+Sets 1000Mbps operation.
+Only
+.Cm full-duplex
+mode is supported at this speed.
+.It Cm 2500baseT
+Sets 2500Mbps operation.
+Only
+.Cm full-duplex
+mode is supported at this speed.
+.El
+.Pp
+.Sh HARDWARE
+The
+.Nm
+driver supports the following models:
+.Pp
+.Bl -bullet -compact
+.It
+I225-LM
+.It
+I225-V
+.It
+I225-IT
+.It
+I225-K
+.El
+.Sh LOADER TUNABLES
+Tunables can be set at the
+.Xr loader 8
+prompt before booting the kernel or stored in
+.Xr loader.conf 5 .
+.Bl -tag -width indent
+.It Va hw.igc.igc_disable_crc_stripping
+Disable or enable hardware stripping of CRC field.
+This is mostly useful on BMC/IPMI shared interfaces where stripping the
+CRC causes remote access over IPMI to fail.
+Default 0 (enabled).
+.It Va hw.igc.rx_int_delay
+This value delays the generation of receive interrupts in units
+of 1.024 microseconds.
+The default value is 0, since adapters may hang with this feature being
+enabled.
+.It Va hw.igc.rx_abs_int_delay
+If hw.igc.rx_int_delay is non-zero, this tunable limits the
+maximum delay in which a receive interrupt is generated.
+.It Va hw.igc.tx_int_delay
+This value delays the generation of transmit interrupts in units
+of 1.024 microseconds.
+The default value is 64.
+.It Va hw.igc.tx_abs_int_delay
+If hw.igc.tx_int_delay is non-zero, this tunable limits the
+maximum delay in which a transmit interrupt is generated.
+.It Va hw.igc.sbp
+Show bad packets when in promiscuous mode.
+Default is false.
+.It Va hw.igc.rx_process_limit
+Maximum number of received packets to process at a time.
+Default is 100.
+A value of -1 means unlimited.
+.It Va hw.igc.eee_setting
+Disable or enable Energy Efficient Ethernet.
+Default 1 (disabled).
+.It Va hw.igc.max_interrupt_rate
+Maximum device interrupts per second.
+The default is 8000.
+.El
+.Sh DIAGNOSTICS
+.Bl -diag
+.It "igc%d: Hardware Initialization Failed"
+A fatal initialization error has occurred.
+.It "igc%d: Unable to allocate bus resource: memory"
+A fatal initialization error has occurred.
+.It "igc%d: Invalid MAC address"
+The MAC address programmed into the EEPROM is either empty or a 
multicast/broadcast
+address.
+.El
+.Sh SEE ALSO
+.Xr altq 4 ,
+.Xr arp 4 ,
+.Xr iflib 4 ,
+.Xr netintro 4 ,
+.Xr ng_ether 4 ,
+.Xr vlan 4 ,
+.Xr ifconfig 8
+.Sh HISTORY
+The
+.Nm
+device driver first appeared in
+.Fx 14.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+was originally written by
+.An Intel Corporation
+and converted to the
+.Xr iflib 4
+framework by
+.An Netgate .
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 2b49dd4726ec..7ea749e28e33 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -249,6 +249,7 @@ device              puc                     # Multi I/O 
cards and multi-channel UARTs
 # PCI/PCI-X/PCIe Ethernet NICs that use iflib infrastructure
 device         iflib
 device         em                      # Intel PRO/1000 Gigabit Ethernet Family
+device         igc                     # Intel I225 2.5G Ethernet
 device         ix                      # Intel PRO/10GbE PCIE PF Ethernet
 device         ixv                     # Intel PRO/10GbE PCIE VF Ethernet
 device         ixl                     # Intel 700 Series Physical Function
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index 79c92a679414..f5bdf15ebb08 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -287,6 +287,7 @@ device              cpufreq
 #       adapters.
 # ice: Intel 800 Series Physical Function
 #      Requires the ice_ddp module for full functionality
+# igc: Intel I225 2.5Gb Ethernet adapter
 # ipw: Intel PRO/Wireless 2100 IEEE 802.11 adapter
 #      Requires the ipw firmware module
 # iwi: Intel PRO/Wireless 2200BG/2225BG/2915ABG IEEE 802.11 adapters
@@ -309,6 +310,7 @@ device              bxe             # Broadcom NetXtreme II 
BCM5771X/BCM578XX 10GbE
 options        ED_3C503
 options        ED_HPP
 options        ED_SIC
+device         igc             # Intel I225 2.5G Ethernet
 device         ipw             # Intel 2100 wireless NICs.
 device         iwi             # Intel 2200BG/2225BG/2915ABG wireless NICs.
 device         iwn             # Intel 4965/1000/5000/6000 wireless NICs.
diff --git a/sys/conf/files b/sys/conf/files
index 22cf4db11695..33b57f98e199 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1885,6 +1885,14 @@ dev/iicbus/pmic/fan53555.c       optional fan53555 
ext_resources fdt
 dev/iir/iir.c                  optional iir
 dev/iir/iir_ctrl.c             optional iir
 dev/iir/iir_pci.c              optional iir pci
+dev/igc/if_igc.c               optional igc iflib pci
+dev/igc/igc_api.c              optional igc iflib pci
+dev/igc/igc_base.c             optional igc iflib pci
+dev/igc/igc_i225.c             optional igc iflib pci
+dev/igc/igc_mac.c              optional igc iflib pci
+dev/igc/igc_nvm.c              optional igc iflib pci
+dev/igc/igc_phy.c              optional igc iflib pci
+dev/igc/igc_txrx.c             optional igc iflib pci
 dev/intpm/intpm.c              optional intpm pci
 # XXX Work around clang warning, until maintainer approves fix.
 dev/ips/ips.c                  optional ips \
diff --git a/sys/dev/igc/if_igc.c b/sys/dev/igc/if_igc.c
new file mode 100644
index 000000000000..6d94a7c223c7
--- /dev/null
+++ b/sys/dev/igc/if_igc.c
@@ -0,0 +1,2984 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2016 Nicole Graziano <nic...@nextbsd.org>
+ * All rights reserved.
+ * Copyright (c) 2021 Rubicon Communications, LLC (Netgate)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "if_igc.h"
+#include <sys/sbuf.h>
+#include <machine/_inttypes.h>
+
+#ifdef RSS
+#include <net/rss_config.h>
+#include <netinet/in_rss.h>
+#endif
+
+/*********************************************************************
+ *  PCI Device ID Table
+ *
+ *  Used by probe to select devices to load on
+ *  Last entry must be all 0s
+ *
+ *  { Vendor ID, Device ID, String }
+ *********************************************************************/
+
+static pci_vendor_info_t igc_vendor_info_array[] =
+{
+       /* Intel(R) PRO/1000 Network Connection - igc */
+       PVID(0x8086, IGC_DEV_ID_I225_LM, "Intel(R) Ethernet Controller 
I225-LM"),
+       PVID(0x8086, IGC_DEV_ID_I225_V, "Intel(R) Ethernet Controller I225-V"),
+       PVID(0x8086, IGC_DEV_ID_I225_K, "Intel(R) Ethernet Controller I225-K"),
+       PVID(0x8086, IGC_DEV_ID_I225_I, "Intel(R) Ethernet Controller I225-I"),
+       PVID(0x8086, IGC_DEV_ID_I220_V, "Intel(R) Ethernet Controller I220-V"),
+       PVID(0x8086, IGC_DEV_ID_I225_K2, "Intel(R) Ethernet Controller 
I225-K(2)"),
+       PVID(0x8086, IGC_DEV_ID_I225_LMVP, "Intel(R) Ethernet Controller 
I225-LMvP(2)"),
+       PVID(0x8086, IGC_DEV_ID_I226_K, "Intel(R) Ethernet Controller I226-K"),
+       PVID(0x8086, IGC_DEV_ID_I225_IT, "Intel(R) Ethernet Controller 
I225-IT(2)"),
+       PVID(0x8086, IGC_DEV_ID_I226_LM, "Intel(R) Ethernet Controller 
I226-LM"),
+       PVID(0x8086, IGC_DEV_ID_I226_V, "Intel(R) Ethernet Controller I226-V"),
+       PVID(0x8086, IGC_DEV_ID_I226_IT, "Intel(R) Ethernet Controller 
I226-IT"),
+       PVID(0x8086, IGC_DEV_ID_I221_V, "Intel(R) Ethernet Controller I221-V"),
+       PVID(0x8086, IGC_DEV_ID_I226_BLANK_NVM, "Intel(R) Ethernet Controller 
I226(blankNVM)"),
+       PVID(0x8086, IGC_DEV_ID_I225_BLANK_NVM, "Intel(R) Ethernet Controller 
I225(blankNVM)"),
+       /* required last entry */
+       PVID_END
+};
+
+/*********************************************************************
+ *  Function prototypes
+ *********************************************************************/
+static void    *igc_register(device_t dev);
+static int     igc_if_attach_pre(if_ctx_t ctx);
+static int     igc_if_attach_post(if_ctx_t ctx);
+static int     igc_if_detach(if_ctx_t ctx);
+static int     igc_if_shutdown(if_ctx_t ctx);
+static int     igc_if_suspend(if_ctx_t ctx);
+static int     igc_if_resume(if_ctx_t ctx);
+
+static int     igc_if_tx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t 
*paddrs, int ntxqs, int ntxqsets);
+static int     igc_if_rx_queues_alloc(if_ctx_t ctx, caddr_t *vaddrs, uint64_t 
*paddrs, int nrxqs, int nrxqsets);
+static void    igc_if_queues_free(if_ctx_t ctx);
+
+static uint64_t        igc_if_get_counter(if_ctx_t, ift_counter);
+static void    igc_if_init(if_ctx_t ctx);
+static void    igc_if_stop(if_ctx_t ctx);
+static void    igc_if_media_status(if_ctx_t, struct ifmediareq *);
+static int     igc_if_media_change(if_ctx_t ctx);
+static int     igc_if_mtu_set(if_ctx_t ctx, uint32_t mtu);
+static void    igc_if_timer(if_ctx_t ctx, uint16_t qid);
+static void    igc_if_vlan_register(if_ctx_t ctx, u16 vtag);
+static void    igc_if_vlan_unregister(if_ctx_t ctx, u16 vtag);
+static void    igc_if_watchdog_reset(if_ctx_t ctx);
+static bool    igc_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event 
event);
+
+static void    igc_identify_hardware(if_ctx_t ctx);
+static int     igc_allocate_pci_resources(if_ctx_t ctx);
+static void    igc_free_pci_resources(if_ctx_t ctx);
+static void    igc_reset(if_ctx_t ctx);
+static int     igc_setup_interface(if_ctx_t ctx);
+static int     igc_setup_msix(if_ctx_t ctx);
+
+static void    igc_initialize_transmit_unit(if_ctx_t ctx);
+static void    igc_initialize_receive_unit(if_ctx_t ctx);
+
+static void    igc_if_intr_enable(if_ctx_t ctx);
+static void    igc_if_intr_disable(if_ctx_t ctx);
+static int     igc_if_rx_queue_intr_enable(if_ctx_t ctx, uint16_t rxqid);
+static int     igc_if_tx_queue_intr_enable(if_ctx_t ctx, uint16_t txqid);
+static void    igc_if_multi_set(if_ctx_t ctx);
+static void    igc_if_update_admin_status(if_ctx_t ctx);
+static void    igc_if_debug(if_ctx_t ctx);
+static void    igc_update_stats_counters(struct igc_adapter *);
+static void    igc_add_hw_stats(struct igc_adapter *adapter);
+static int     igc_if_set_promisc(if_ctx_t ctx, int flags);
+static void    igc_setup_vlan_hw_support(struct igc_adapter *);
+static int     igc_sysctl_nvm_info(SYSCTL_HANDLER_ARGS);
+static void    igc_print_nvm_info(struct igc_adapter *);
+static int     igc_sysctl_debug_info(SYSCTL_HANDLER_ARGS);
+static int     igc_get_rs(SYSCTL_HANDLER_ARGS);
+static void    igc_print_debug_info(struct igc_adapter *);
+static int     igc_is_valid_ether_addr(u8 *);
+static int     igc_sysctl_int_delay(SYSCTL_HANDLER_ARGS);
+static void    igc_add_int_delay_sysctl(struct igc_adapter *, const char *,
+                   const char *, struct igc_int_delay_info *, int, int);
+/* Management and WOL Support */
+static void    igc_get_hw_control(struct igc_adapter *);
+static void    igc_release_hw_control(struct igc_adapter *);
+static void    igc_get_wakeup(if_ctx_t ctx);
+static void    igc_enable_wakeup(if_ctx_t ctx);
+
+int            igc_intr(void *arg);
+
+/* MSI-X handlers */
+static int     igc_if_msix_intr_assign(if_ctx_t, int);
+static int     igc_msix_link(void *);
+static void    igc_handle_link(void *context);
+
+static int     igc_set_flowcntl(SYSCTL_HANDLER_ARGS);
+static int     igc_sysctl_eee(SYSCTL_HANDLER_ARGS);
+
+static int     igc_get_regs(SYSCTL_HANDLER_ARGS);
+
+static void    igc_configure_queues(struct igc_adapter *adapter);
+
+
+/*********************************************************************
+ *  FreeBSD Device Interface Entry Points
+ *********************************************************************/
+static device_method_t igc_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_register, igc_register),
+       DEVMETHOD(device_probe, iflib_device_probe),
+       DEVMETHOD(device_attach, iflib_device_attach),
+       DEVMETHOD(device_detach, iflib_device_detach),
+       DEVMETHOD(device_shutdown, iflib_device_shutdown),
+       DEVMETHOD(device_suspend, iflib_device_suspend),
+       DEVMETHOD(device_resume, iflib_device_resume),
+       DEVMETHOD_END
+};
+
+static driver_t igc_driver = {
+       "igc", igc_methods, sizeof(struct igc_adapter),
+};
+
+static devclass_t igc_devclass;
+DRIVER_MODULE(igc, pci, igc_driver, igc_devclass, 0, 0);
+
+MODULE_DEPEND(igc, pci, 1, 1, 1);
+MODULE_DEPEND(igc, ether, 1, 1, 1);
+MODULE_DEPEND(igc, iflib, 1, 1, 1);
+
+IFLIB_PNP_INFO(pci, igc, igc_vendor_info_array);
+
+static device_method_t igc_if_methods[] = {
+       DEVMETHOD(ifdi_attach_pre, igc_if_attach_pre),
+       DEVMETHOD(ifdi_attach_post, igc_if_attach_post),
+       DEVMETHOD(ifdi_detach, igc_if_detach),
+       DEVMETHOD(ifdi_shutdown, igc_if_shutdown),
+       DEVMETHOD(ifdi_suspend, igc_if_suspend),
+       DEVMETHOD(ifdi_resume, igc_if_resume),
+       DEVMETHOD(ifdi_init, igc_if_init),
+       DEVMETHOD(ifdi_stop, igc_if_stop),
+       DEVMETHOD(ifdi_msix_intr_assign, igc_if_msix_intr_assign),
+       DEVMETHOD(ifdi_intr_enable, igc_if_intr_enable),
+       DEVMETHOD(ifdi_intr_disable, igc_if_intr_disable),
+       DEVMETHOD(ifdi_tx_queues_alloc, igc_if_tx_queues_alloc),
+       DEVMETHOD(ifdi_rx_queues_alloc, igc_if_rx_queues_alloc),
+       DEVMETHOD(ifdi_queues_free, igc_if_queues_free),
+       DEVMETHOD(ifdi_update_admin_status, igc_if_update_admin_status),
+       DEVMETHOD(ifdi_multi_set, igc_if_multi_set),
+       DEVMETHOD(ifdi_media_status, igc_if_media_status),
+       DEVMETHOD(ifdi_media_change, igc_if_media_change),
+       DEVMETHOD(ifdi_mtu_set, igc_if_mtu_set),
+       DEVMETHOD(ifdi_promisc_set, igc_if_set_promisc),
+       DEVMETHOD(ifdi_timer, igc_if_timer),
+       DEVMETHOD(ifdi_watchdog_reset, igc_if_watchdog_reset),
+       DEVMETHOD(ifdi_vlan_register, igc_if_vlan_register),
+       DEVMETHOD(ifdi_vlan_unregister, igc_if_vlan_unregister),
+       DEVMETHOD(ifdi_get_counter, igc_if_get_counter),
+       DEVMETHOD(ifdi_rx_queue_intr_enable, igc_if_rx_queue_intr_enable),
+       DEVMETHOD(ifdi_tx_queue_intr_enable, igc_if_tx_queue_intr_enable),
+       DEVMETHOD(ifdi_debug, igc_if_debug),
+       DEVMETHOD(ifdi_needs_restart, igc_if_needs_restart),
+       DEVMETHOD_END
+};
+
+static driver_t igc_if_driver = {
+       "igc_if", igc_if_methods, sizeof(struct igc_adapter)
+};
+
+/*********************************************************************
+ *  Tunable default values.
+ *********************************************************************/
+
+#define IGC_TICKS_TO_USECS(ticks)      ((1024 * (ticks) + 500) / 1000)
+#define IGC_USECS_TO_TICKS(usecs)      ((1000 * (usecs) + 512) / 1024)
+
+#define MAX_INTS_PER_SEC       8000
+#define DEFAULT_ITR            (1000000000/(MAX_INTS_PER_SEC * 256))
+
+/* Allow common code without TSO */
+#ifndef CSUM_TSO
+#define CSUM_TSO       0
+#endif
+
+static SYSCTL_NODE(_hw, OID_AUTO, igc, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
+    "igc driver parameters");
+
+static int igc_disable_crc_stripping = 0;
+SYSCTL_INT(_hw_igc, OID_AUTO, disable_crc_stripping, CTLFLAG_RDTUN,
+    &igc_disable_crc_stripping, 0, "Disable CRC Stripping");
+
+static int igc_tx_int_delay_dflt = IGC_TICKS_TO_USECS(IGC_TIDV_VAL);
+static int igc_rx_int_delay_dflt = IGC_TICKS_TO_USECS(IGC_RDTR_VAL);
+SYSCTL_INT(_hw_igc, OID_AUTO, tx_int_delay, CTLFLAG_RDTUN, 
&igc_tx_int_delay_dflt,
+    0, "Default transmit interrupt delay in usecs");
+SYSCTL_INT(_hw_igc, OID_AUTO, rx_int_delay, CTLFLAG_RDTUN, 
&igc_rx_int_delay_dflt,
+    0, "Default receive interrupt delay in usecs");
+
+static int igc_tx_abs_int_delay_dflt = IGC_TICKS_TO_USECS(IGC_TADV_VAL);
+static int igc_rx_abs_int_delay_dflt = IGC_TICKS_TO_USECS(IGC_RADV_VAL);
+SYSCTL_INT(_hw_igc, OID_AUTO, tx_abs_int_delay, CTLFLAG_RDTUN,
+    &igc_tx_abs_int_delay_dflt, 0,
+    "Default transmit interrupt delay limit in usecs");
+SYSCTL_INT(_hw_igc, OID_AUTO, rx_abs_int_delay, CTLFLAG_RDTUN,
+    &igc_rx_abs_int_delay_dflt, 0,
+    "Default receive interrupt delay limit in usecs");
+
+static int igc_smart_pwr_down = false;
+SYSCTL_INT(_hw_igc, OID_AUTO, smart_pwr_down, CTLFLAG_RDTUN, 
&igc_smart_pwr_down,
+    0, "Set to true to leave smart power down enabled on newer adapters");
+
+/* Controls whether promiscuous also shows bad packets */
+static int igc_debug_sbp = true;
+SYSCTL_INT(_hw_igc, OID_AUTO, sbp, CTLFLAG_RDTUN, &igc_debug_sbp, 0,
+    "Show bad packets in promiscuous mode");
+
+/* How many packets rxeof tries to clean at a time */
+static int igc_rx_process_limit = 100;
+SYSCTL_INT(_hw_igc, OID_AUTO, rx_process_limit, CTLFLAG_RDTUN,
+    &igc_rx_process_limit, 0,
+    "Maximum number of received packets to process "
+    "at a time, -1 means unlimited");
+
+/* Energy efficient ethernet - default to OFF */
+static int igc_eee_setting = 1;
+SYSCTL_INT(_hw_igc, OID_AUTO, eee_setting, CTLFLAG_RDTUN, &igc_eee_setting, 0,
+    "Enable Energy Efficient Ethernet");
+
+/*
+** Tuneable Interrupt rate
+*/
+static int igc_max_interrupt_rate = 8000;
+SYSCTL_INT(_hw_igc, OID_AUTO, max_interrupt_rate, CTLFLAG_RDTUN,
+    &igc_max_interrupt_rate, 0, "Maximum interrupts per second");
+
+extern struct if_txrx igc_txrx;
+
+static struct if_shared_ctx igc_sctx_init = {
+       .isc_magic = IFLIB_MAGIC,
+       .isc_q_align = PAGE_SIZE,
+       .isc_tx_maxsize = IGC_TSO_SIZE + sizeof(struct ether_vlan_header),
+       .isc_tx_maxsegsize = PAGE_SIZE,
+       .isc_tso_maxsize = IGC_TSO_SIZE + sizeof(struct ether_vlan_header),
+       .isc_tso_maxsegsize = IGC_TSO_SEG_SIZE,
+       .isc_rx_maxsize = MAX_JUMBO_FRAME_SIZE,
+       .isc_rx_nsegments = 1,
+       .isc_rx_maxsegsize = MJUM9BYTES,
+       .isc_nfl = 1,
+       .isc_nrxqs = 1,
+       .isc_ntxqs = 1,
+       .isc_admin_intrcnt = 1,
+       .isc_vendor_info = igc_vendor_info_array,
+       .isc_driver_version = "1",
+       .isc_driver = &igc_if_driver,
+       .isc_flags = IFLIB_NEED_SCRATCH | IFLIB_TSO_INIT_IP | 
IFLIB_NEED_ZERO_CSUM,
+
+       .isc_nrxd_min = {IGC_MIN_RXD},
+       .isc_ntxd_min = {IGC_MIN_TXD},
+       .isc_nrxd_max = {IGC_MAX_RXD},
+       .isc_ntxd_max = {IGC_MAX_TXD},
+       .isc_nrxd_default = {IGC_DEFAULT_RXD},
+       .isc_ntxd_default = {IGC_DEFAULT_TXD},
+};
+
+/*****************************************************************
+ *
+ * Dump Registers
+ *
+ ****************************************************************/
+#define IGC_REGS_LEN 739
+
+static int igc_get_regs(SYSCTL_HANDLER_ARGS)
+{
+       struct igc_adapter *adapter = (struct igc_adapter *)arg1;
+       struct igc_hw *hw = &adapter->hw;
+       struct sbuf *sb;
+       u32 *regs_buff;
+       int rc;
+
+       regs_buff = malloc(sizeof(u32) * IGC_REGS_LEN, M_DEVBUF, M_WAITOK);
+       memset(regs_buff, 0, IGC_REGS_LEN * sizeof(u32));
+
+       rc = sysctl_wire_old_buffer(req, 0);
+       MPASS(rc == 0);
+       if (rc != 0) {
+               free(regs_buff, M_DEVBUF);
+               return (rc);
+       }
+
+       sb = sbuf_new_for_sysctl(NULL, NULL, 32*400, req);
+       MPASS(sb != NULL);
+       if (sb == NULL) {
+               free(regs_buff, M_DEVBUF);
+               return (ENOMEM);
+       }
+
+       /* General Registers */
+       regs_buff[0] = IGC_READ_REG(hw, IGC_CTRL);
+       regs_buff[1] = IGC_READ_REG(hw, IGC_STATUS);
+       regs_buff[2] = IGC_READ_REG(hw, IGC_CTRL_EXT);
+       regs_buff[3] = IGC_READ_REG(hw, IGC_ICR);
+       regs_buff[4] = IGC_READ_REG(hw, IGC_RCTL);
+       regs_buff[5] = IGC_READ_REG(hw, IGC_RDLEN(0));
+       regs_buff[6] = IGC_READ_REG(hw, IGC_RDH(0));
+       regs_buff[7] = IGC_READ_REG(hw, IGC_RDT(0));
+       regs_buff[8] = IGC_READ_REG(hw, IGC_RXDCTL(0));
+       regs_buff[9] = IGC_READ_REG(hw, IGC_RDBAL(0));
+       regs_buff[10] = IGC_READ_REG(hw, IGC_RDBAH(0));
+       regs_buff[11] = IGC_READ_REG(hw, IGC_TCTL);
+       regs_buff[12] = IGC_READ_REG(hw, IGC_TDBAL(0));
+       regs_buff[13] = IGC_READ_REG(hw, IGC_TDBAH(0));
+       regs_buff[14] = IGC_READ_REG(hw, IGC_TDLEN(0));
+       regs_buff[15] = IGC_READ_REG(hw, IGC_TDH(0));
+       regs_buff[16] = IGC_READ_REG(hw, IGC_TDT(0));
+       regs_buff[17] = IGC_READ_REG(hw, IGC_TXDCTL(0));
+
+       sbuf_printf(sb, "General Registers\n");
+       sbuf_printf(sb, "\tCTRL\t %08x\n", regs_buff[0]);
+       sbuf_printf(sb, "\tSTATUS\t %08x\n", regs_buff[1]);
+       sbuf_printf(sb, "\tCTRL_EXIT\t %08x\n\n", regs_buff[2]);
+
+       sbuf_printf(sb, "Interrupt Registers\n");
+       sbuf_printf(sb, "\tICR\t %08x\n\n", regs_buff[3]);
+
+       sbuf_printf(sb, "RX Registers\n");
+       sbuf_printf(sb, "\tRCTL\t %08x\n", regs_buff[4]);
+       sbuf_printf(sb, "\tRDLEN\t %08x\n", regs_buff[5]);
+       sbuf_printf(sb, "\tRDH\t %08x\n", regs_buff[6]);
+       sbuf_printf(sb, "\tRDT\t %08x\n", regs_buff[7]);
+       sbuf_printf(sb, "\tRXDCTL\t %08x\n", regs_buff[8]);
+       sbuf_printf(sb, "\tRDBAL\t %08x\n", regs_buff[9]);
+       sbuf_printf(sb, "\tRDBAH\t %08x\n\n", regs_buff[10]);
+
+       sbuf_printf(sb, "TX Registers\n");
+       sbuf_printf(sb, "\tTCTL\t %08x\n", regs_buff[11]);
+       sbuf_printf(sb, "\tTDBAL\t %08x\n", regs_buff[12]);
+       sbuf_printf(sb, "\tTDBAH\t %08x\n", regs_buff[13]);
+       sbuf_printf(sb, "\tTDLEN\t %08x\n", regs_buff[14]);
+       sbuf_printf(sb, "\tTDH\t %08x\n", regs_buff[15]);
+       sbuf_printf(sb, "\tTDT\t %08x\n", regs_buff[16]);
+       sbuf_printf(sb, "\tTXDCTL\t %08x\n", regs_buff[17]);
+       sbuf_printf(sb, "\tTDFH\t %08x\n", regs_buff[18]);
+       sbuf_printf(sb, "\tTDFT\t %08x\n", regs_buff[19]);
+       sbuf_printf(sb, "\tTDFHS\t %08x\n", regs_buff[20]);
+       sbuf_printf(sb, "\tTDFPC\t %08x\n\n", regs_buff[21]);
+
+       free(regs_buff, M_DEVBUF);
+
+#ifdef DUMP_DESCS
+       {
+               if_softc_ctx_t scctx = adapter->shared;
+               struct rx_ring *rxr = &rx_que->rxr;
+               struct tx_ring *txr = &tx_que->txr;
+               int ntxd = scctx->isc_ntxd[0];
+               int nrxd = scctx->isc_nrxd[0];
+               int j;
+
+       for (j = 0; j < nrxd; j++) {
+               u32 staterr = le32toh(rxr->rx_base[j].wb.upper.status_error);
+               u32 length =  le32toh(rxr->rx_base[j].wb.upper.length);
+               sbuf_printf(sb, "\tReceive Descriptor Address %d: %08" PRIx64 " 
 Error:%d  Length:%d\n", j, rxr->rx_base[j].read.buffer_addr, staterr, length);
+       }
+
+       for (j = 0; j < min(ntxd, 256); j++) {
+               unsigned int *ptr = (unsigned int *)&txr->tx_base[j];
+
+               sbuf_printf(sb, "\tTXD[%03d] [0]: %08x [1]: %08x [2]: %08x [3]: 
%08x  eop: %d DD=%d\n",
+                           j, ptr[0], ptr[1], ptr[2], ptr[3], buf->eop,
+                           buf->eop != -1 ? 
txr->tx_base[buf->eop].upper.fields.status & IGC_TXD_STAT_DD : 0);
+
+       }
+       }
+#endif
+
+       rc = sbuf_finish(sb);
+       sbuf_delete(sb);
+       return(rc);
+}
+
+static void *
+igc_register(device_t dev)
+{
+       return (&igc_sctx_init);
+}
+
+static int
+igc_set_num_queues(if_ctx_t ctx)
+{
+       int maxqueues;
+
+       maxqueues = 4;
+
+       return (maxqueues);
+}
+
+#define        IGC_CAPS                                                        
\
+    IFCAP_HWCSUM | IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING |             \
+    IFCAP_VLAN_HWCSUM | IFCAP_WOL | IFCAP_VLAN_HWFILTER | IFCAP_TSO4 | \
+    IFCAP_LRO | IFCAP_VLAN_HWTSO | IFCAP_JUMBO_MTU | IFCAP_HWCSUM_IPV6 |\
+    IFCAP_TSO6
+
+/*********************************************************************
+ *  Device initialization routine
+ *
+ *  The attach entry point is called when the driver is being loaded.
+ *  This routine identifies the type of hardware, allocates all resources
+ *  and initializes the hardware.
+ *
+ *  return 0 on success, positive on failure
+ *********************************************************************/
+static int
+igc_if_attach_pre(if_ctx_t ctx)
+{
+       struct igc_adapter *adapter;
+       if_softc_ctx_t scctx;
+       device_t dev;
+       struct igc_hw *hw;
+       int error = 0;
+
+       INIT_DEBUGOUT("igc_if_attach_pre: begin");
+       dev = iflib_get_dev(ctx);
+       adapter = iflib_get_softc(ctx);
+
+       adapter->ctx = adapter->osdep.ctx = ctx;
+       adapter->dev = adapter->osdep.dev = dev;
+       scctx = adapter->shared = iflib_get_softc_ctx(ctx);
+       adapter->media = iflib_get_media(ctx);
+       hw = &adapter->hw;
+
+       adapter->tx_process_limit = scctx->isc_ntxd[0];
+
+       /* SYSCTL stuff */
+       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+           OID_AUTO, "nvm", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
+           adapter, 0, igc_sysctl_nvm_info, "I", "NVM Information");
+
+       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+           OID_AUTO, "debug", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
+           adapter, 0, igc_sysctl_debug_info, "I", "Debug Information");
+
+       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+           OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
+           adapter, 0, igc_set_flowcntl, "I", "Flow Control");
+
+       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+           OID_AUTO, "reg_dump",
+           CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, adapter, 0,
+           igc_get_regs, "A", "Dump Registers");
+
+       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+           OID_AUTO, "rs_dump",
+           CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, adapter, 0,
+           igc_get_rs, "I", "Dump RS indexes");
+
+       /* Determine hardware and mac info */
+       igc_identify_hardware(ctx);
+
+       scctx->isc_tx_nsegments = IGC_MAX_SCATTER;
+       scctx->isc_nrxqsets_max = scctx->isc_ntxqsets_max = 
igc_set_num_queues(ctx);
+       if (bootverbose)
+               device_printf(dev, "attach_pre capping queues at %d\n",
+                   scctx->isc_ntxqsets_max);
+
+       scctx->isc_txqsizes[0] = roundup2(scctx->isc_ntxd[0] * sizeof(union 
igc_adv_tx_desc), IGC_DBA_ALIGN);
+       scctx->isc_rxqsizes[0] = roundup2(scctx->isc_nrxd[0] * sizeof(union 
igc_adv_rx_desc), IGC_DBA_ALIGN);
+       scctx->isc_txd_size[0] = sizeof(union igc_adv_tx_desc);
+       scctx->isc_rxd_size[0] = sizeof(union igc_adv_rx_desc);
+       scctx->isc_txrx = &igc_txrx;
+       scctx->isc_tx_tso_segments_max = IGC_MAX_SCATTER;
+       scctx->isc_tx_tso_size_max = IGC_TSO_SIZE;
+       scctx->isc_tx_tso_segsize_max = IGC_TSO_SEG_SIZE;
+       scctx->isc_capabilities = scctx->isc_capenable = IGC_CAPS;
+       scctx->isc_tx_csum_flags = CSUM_TCP | CSUM_UDP | CSUM_TSO |
+               CSUM_IP6_TCP | CSUM_IP6_UDP | CSUM_SCTP | CSUM_IP6_SCTP;
+
+       /*
+       ** Some new devices, as with ixgbe, now may
+       ** use a different BAR, so we need to keep
+       ** track of which is used.
+       */
+       scctx->isc_msix_bar = PCIR_BAR(IGC_MSIX_BAR);
+       if (pci_read_config(dev, scctx->isc_msix_bar, 4) == 0)
+               scctx->isc_msix_bar += 4;
+
+       /* Setup PCI resources */
+       if (igc_allocate_pci_resources(ctx)) {
+               device_printf(dev, "Allocation of PCI resources failed\n");
+               error = ENXIO;
+               goto err_pci;
+       }
+
+       /* Do Shared Code initialization */
+       error = igc_setup_init_funcs(hw, true);
+       if (error) {
+               device_printf(dev, "Setup of Shared code failed, error %d\n",
+                   error);
+               error = ENXIO;
+               goto err_pci;
+       }
+
+       igc_setup_msix(ctx);
+       igc_get_bus_info(hw);
+
+       /* Set up some sysctls for the tunable interrupt delays */
+       igc_add_int_delay_sysctl(adapter, "rx_int_delay",
+           "receive interrupt delay in usecs", &adapter->rx_int_delay,
+           IGC_REGISTER(hw, IGC_RDTR), igc_rx_int_delay_dflt);
+       igc_add_int_delay_sysctl(adapter, "tx_int_delay",
+           "transmit interrupt delay in usecs", &adapter->tx_int_delay,
+           IGC_REGISTER(hw, IGC_TIDV), igc_tx_int_delay_dflt);
+       igc_add_int_delay_sysctl(adapter, "rx_abs_int_delay",
+           "receive interrupt delay limit in usecs",
+           &adapter->rx_abs_int_delay,
+           IGC_REGISTER(hw, IGC_RADV),
+           igc_rx_abs_int_delay_dflt);
+       igc_add_int_delay_sysctl(adapter, "tx_abs_int_delay",
+           "transmit interrupt delay limit in usecs",
+           &adapter->tx_abs_int_delay,
+           IGC_REGISTER(hw, IGC_TADV),
+           igc_tx_abs_int_delay_dflt);
+       igc_add_int_delay_sysctl(adapter, "itr",
+           "interrupt delay limit in usecs/4",
+           &adapter->tx_itr,
+           IGC_REGISTER(hw, IGC_ITR),
+           DEFAULT_ITR);
+
+       hw->mac.autoneg = DO_AUTO_NEG;
+       hw->phy.autoneg_wait_to_complete = false;
+       hw->phy.autoneg_advertised = AUTONEG_ADV_DEFAULT;
+
+       /* Copper options */
+       if (hw->phy.media_type == igc_media_type_copper) {
+               hw->phy.mdix = AUTO_ALL_MODES;
+       }
+
+       /*
+        * Set the frame limits assuming
+        * standard ethernet sized frames.
+        */
+       scctx->isc_max_frame_size = adapter->hw.mac.max_frame_size =
+           ETHERMTU + ETHER_HDR_LEN + ETHERNET_FCS_SIZE;
+
+       /* Allocate multicast array memory. */
+       adapter->mta = malloc(sizeof(u8) * ETHER_ADDR_LEN *
+           MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT);
+       if (adapter->mta == NULL) {
+               device_printf(dev, "Can not allocate multicast setup array\n");
+               error = ENOMEM;
+               goto err_late;
+       }
+
+       /* Check SOL/IDER usage */
+       if (igc_check_reset_block(hw))
+               device_printf(dev, "PHY reset is blocked"
+                             " due to SOL/IDER session.\n");
+
+       /* Sysctl for setting Energy Efficient Ethernet */
+       adapter->hw.dev_spec._i225.eee_disable = igc_eee_setting;
+       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+           OID_AUTO, "eee_control",
+           CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
+           adapter, 0, igc_sysctl_eee, "I",
+           "Disable Energy Efficient Ethernet");
+
+       /*
+       ** 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) {
+                       device_printf(dev,
+                           "The EEPROM Checksum Is Not Valid\n");
+                       error = EIO;
+                       goto err_late;
+               }
+       }
+
+       /* Copy the permanent MAC address out of the EEPROM */
+       if (igc_read_mac_addr(hw) < 0) {
+               device_printf(dev, "EEPROM read error while reading MAC"
+                             " address\n");
+               error = EIO;
+               goto err_late;
+       }
+
+       if (!igc_is_valid_ether_addr(hw->mac.addr)) {
+               device_printf(dev, "Invalid MAC address\n");
+               error = EIO;
+               goto err_late;
+       }
+
+       /*
+        * Get Wake-on-Lan and Management info for later use
+        */
+       igc_get_wakeup(ctx);
+
+       /* Enable only WOL MAGIC by default */
+       scctx->isc_capenable &= ~IFCAP_WOL;
+       if (adapter->wol != 0)
+               scctx->isc_capenable |= IFCAP_WOL_MAGIC;
+
+       iflib_set_mac(ctx, hw->mac.addr);
+
+       return (0);
+
+err_late:
+       igc_release_hw_control(adapter);
+err_pci:
+       igc_free_pci_resources(ctx);
+       free(adapter->mta, M_DEVBUF);
+
+       return (error);
+}
+
+static int
+igc_if_attach_post(if_ctx_t ctx)
+{
+       struct igc_adapter *adapter = iflib_get_softc(ctx);
+       struct igc_hw *hw = &adapter->hw;
+       int error = 0;
*** 11492 LINES SKIPPED ***
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to