Merge branch 'devel-1.6' into ethercat-backport_setip
This commit is contained in:
commit
762bb01ff9
|
|
@ -12,7 +12,7 @@ build:
|
|||
|
||||
script:
|
||||
- ./bootstrap
|
||||
- ./configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --disable-8139too --enable-tty --with-devices=2 --enable-ccat
|
||||
- ./configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --enable-tty --with-devices=2 --enable-ccat
|
||||
- make -j8 all modules
|
||||
- make DISTCHECK_CONFIGURE_FLAGS="--with-linux-dir=/usr/src/linux-obj/$(uname -i)/default" distcheck
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ doxygen:
|
|||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
script:
|
||||
- ./bootstrap
|
||||
- ./configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --disable-8139too --enable-tty --with-devices=2 --enable-ccat
|
||||
- ./configure --with-linux-dir=/usr/src/linux-obj/$(uname -i)/default --enable-tty --with-devices=2 --enable-ccat
|
||||
- make doc
|
||||
- mv doxygen-output/html/ html/
|
||||
artifacts:
|
||||
|
|
@ -83,7 +83,7 @@ pdf:
|
|||
update docs server:
|
||||
stage: deploy
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PROJECT_NAMESPACE == "etherlab.org"
|
||||
- if: $CI_COMMIT_BRANCH == "stable-1.5" && $CI_PROJECT_NAMESPACE == "etherlab.org"
|
||||
trigger: etherlab.org/docs
|
||||
|
||||
# from 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml', but on all branches
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ include $(top_srcdir)/Makefile.kbuild
|
|||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
AM_DISTCHECK_CONFIGURE_FLAGS = \
|
||||
--disable-8139too \
|
||||
--with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
|
||||
|
||||
SUBDIRS = \
|
||||
|
|
|
|||
111
configure.ac
111
configure.ac
|
|
@ -209,7 +209,7 @@ AC_ARG_ENABLE([8139too],
|
|||
;;
|
||||
esac
|
||||
],
|
||||
[enable8139too=$enablekernel]
|
||||
[enable8139too=0] # disabled by default
|
||||
)
|
||||
|
||||
AM_CONDITIONAL(ENABLE_8139TOO, test "x$enable8139too" = "x1")
|
||||
|
|
@ -432,6 +432,54 @@ fi
|
|||
AC_SUBST(KERNEL_E1000E,[$kernele1000e])
|
||||
AC_SUBST(E1000E_LAYOUT, [$e1000elayout])
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# genet driver
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
AC_ARG_ENABLE([genet],
|
||||
AS_HELP_STRING([--enable-genet],
|
||||
[Enable genet driver (for Raspi 4)]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) enablegenet=1
|
||||
;;
|
||||
no) enablegenet=0
|
||||
;;
|
||||
*) AC_MSG_ERROR([Invalid value for --enable-genet])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[enablegenet=0] # disabled by default
|
||||
)
|
||||
|
||||
AM_CONDITIONAL(ENABLE_GENET, test "x$enablegenet" = "x1")
|
||||
AC_SUBST(ENABLE_GENET,[$enablegenet])
|
||||
|
||||
AC_ARG_WITH([genet-kernel],
|
||||
AC_HELP_STRING(
|
||||
[--with-genet-kernel=<X.Y.Z>],
|
||||
[genet kernel (only if differing)]
|
||||
),
|
||||
[
|
||||
kernelgenet=[$withval]
|
||||
],
|
||||
[
|
||||
kernelgenet=$linuxversion
|
||||
]
|
||||
)
|
||||
|
||||
if test "x${enablegenet}" = "x1"; then
|
||||
AC_MSG_CHECKING([for kernel for genet driver])
|
||||
|
||||
if test ! -f "${srcdir}/devices/genet/bcmgenet-${kernelgenet}-orig.c"; then
|
||||
AC_MSG_ERROR([kernel $kernelgenet not available for genet driver!])
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([$kernelgenet])
|
||||
fi
|
||||
|
||||
AC_SUBST(KERNEL_GENET,[$kernelgenet])
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# igb driver
|
||||
#------------------------------------------------------------------------------
|
||||
|
|
@ -479,6 +527,52 @@ if test "x${enableigb}" = "x1"; then
|
|||
fi
|
||||
|
||||
AC_SUBST(KERNEL_IGB,[$kerneligb])
|
||||
#------------------------------------------------------------------------------
|
||||
# igc driver
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
AC_ARG_ENABLE([igc],
|
||||
AS_HELP_STRING([--enable-igc],
|
||||
[Enable igc driver]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) enableigc=1
|
||||
;;
|
||||
no) enableigc=0
|
||||
;;
|
||||
*) AC_MSG_ERROR([Invalid value for --enable-igc])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[enableigc=0] # disabled by default
|
||||
)
|
||||
|
||||
AM_CONDITIONAL(ENABLE_IGC, test "x$enableigc" = "x1")
|
||||
AC_SUBST(ENABLE_IGC,[$enableigc])
|
||||
|
||||
AC_ARG_WITH([igc-kernel],
|
||||
AS_HELP_STRING([--with-igc-kernel=<X.Y.Z>],
|
||||
[igc kernel (only if differing)]
|
||||
),
|
||||
[
|
||||
kerneligc=[$withval]
|
||||
],
|
||||
[
|
||||
kerneligc=$linuxversion
|
||||
]
|
||||
)
|
||||
|
||||
if test "x${enableigc}" = "x1"; then
|
||||
AC_MSG_CHECKING([for kernel for igc driver])
|
||||
|
||||
if test ! -f "${srcdir}/devices/igc/igc_main-${kerneligc}-orig.c"; then
|
||||
AC_MSG_ERROR([kernel $kerneligc not available for igc driver!])
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([$kerneligc])
|
||||
fi
|
||||
|
||||
AC_SUBST(KERNEL_IGC,[$kerneligc])
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# r8169 driver
|
||||
|
|
@ -520,16 +614,25 @@ if test "x${enable_r8169}" = "x1"; then
|
|||
AC_MSG_CHECKING([for kernel for r8169 driver])
|
||||
|
||||
kernels=`ls -1 ${srcdir}/devices/ | grep -oE "^r8169-.*-" | cut -d "-" -f 2 | uniq`
|
||||
kernels_subdir=`ls -1 ${srcdir}/devices/r8169/ | grep -oE "^r8169_main-.*-" | cut -d "-" -f 2 | uniq`
|
||||
found=0
|
||||
found_subdir=0
|
||||
for k in $kernels; do
|
||||
if test "$kernel_r8169" = "$k"; then
|
||||
found=1
|
||||
fi
|
||||
done
|
||||
for k in $kernels_subdir; do
|
||||
if test "$kernel_r8169" = "$k"; then
|
||||
found=1
|
||||
found_subdir=1
|
||||
fi
|
||||
done
|
||||
if test $found -ne 1; then
|
||||
AC_MSG_ERROR([kernel $kernel_r8169 not available for r8169 driver!])
|
||||
fi
|
||||
|
||||
AC_SUBST(R8169_IN_SUBDIR, [$found_subdir])
|
||||
AC_MSG_RESULT([$kernel_r8169])
|
||||
fi
|
||||
|
||||
|
|
@ -1122,8 +1225,14 @@ AC_CONFIG_FILES([
|
|||
devices/e1000/Makefile
|
||||
devices/e1000e/Kbuild
|
||||
devices/e1000e/Makefile
|
||||
devices/genet/Kbuild
|
||||
devices/genet/Makefile
|
||||
devices/igb/Kbuild
|
||||
devices/igb/Makefile
|
||||
devices/igc/Kbuild
|
||||
devices/igc/Makefile
|
||||
devices/r8169/Kbuild
|
||||
devices/r8169/Makefile
|
||||
ethercat.spec
|
||||
examples/Kbuild
|
||||
examples/Makefile
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -70,16 +70,28 @@ ifeq (@ENABLE_E1000E@,1)
|
|||
obj-m += e1000e/
|
||||
endif
|
||||
|
||||
ifeq (@ENABLE_GENET@,1)
|
||||
obj-m += genet/
|
||||
endif
|
||||
|
||||
ifeq (@ENABLE_IGB@,1)
|
||||
obj-m += igb/
|
||||
endif
|
||||
|
||||
ifeq (@ENABLE_IGC@,1)
|
||||
obj-m += igc/
|
||||
endif
|
||||
|
||||
ifeq (@ENABLE_R8169@,1)
|
||||
ifeq (@R8169_IN_SUBDIR@,1)
|
||||
obj-m += r8169/
|
||||
else
|
||||
EC_R8169_OBJ := r8169-@KERNEL_R8169@-ethercat.o
|
||||
obj-m += ec_r8169.o
|
||||
ec_r8169-objs := $(EC_R8169_OBJ)
|
||||
CFLAGS_$(EC_R8169_OBJ) = -DREV=$(REV)
|
||||
endif
|
||||
endif
|
||||
|
||||
KBUILD_EXTRA_SYMBOLS := \
|
||||
@abs_top_builddir@/$(LINUX_SYMVERS) \
|
||||
|
|
|
|||
|
|
@ -31,7 +31,10 @@ SUBDIRS = \
|
|||
ccat \
|
||||
e1000 \
|
||||
e1000e \
|
||||
igb
|
||||
genet \
|
||||
igb \
|
||||
igc \
|
||||
r8169
|
||||
|
||||
# using HEADERS to enable tags target
|
||||
noinst_HEADERS = \
|
||||
|
|
@ -95,6 +98,8 @@ noinst_HEADERS = \
|
|||
8139too-4.4-orig.c \
|
||||
8139too-5.10-ethercat.c \
|
||||
8139too-5.10-orig.c \
|
||||
8139too-6.1-ethercat.c \
|
||||
8139too-6.1-orig.c \
|
||||
create_driver_table.py \
|
||||
device_drivers_template.md \
|
||||
e100-2.6.20-ethercat.c \
|
||||
|
|
@ -137,6 +142,18 @@ noinst_HEADERS = \
|
|||
e100-3.8-orig.c \
|
||||
e100-4.4-ethercat.c \
|
||||
e100-4.4-orig.c \
|
||||
e100-5.4-ethercat.c \
|
||||
e100-5.4-orig.c \
|
||||
e100-5.10-ethercat.c \
|
||||
e100-5.10-orig.c \
|
||||
e100-5.14-ethercat.c \
|
||||
e100-5.14-orig.c \
|
||||
e100-5.15-ethercat.c \
|
||||
e100-5.15-orig.c \
|
||||
e100-6.1-ethercat.c \
|
||||
e100-6.1-orig.c \
|
||||
e100-6.4-ethercat.c \
|
||||
e100-6.4-orig.c \
|
||||
ecdev.h \
|
||||
generic.c \
|
||||
r8169-2.6.24-ethercat.c \
|
||||
|
|
|
|||
|
|
@ -249,9 +249,11 @@ struct ccat_mac_register {
|
|||
u8 mii_connected;
|
||||
};
|
||||
|
||||
static void ccat_eth_fifo_reset(struct ccat_eth_fifo *const fifo);
|
||||
static void fifo_set_end(struct ccat_eth_fifo *const fifo, size_t size)
|
||||
{
|
||||
fifo->end = fifo->mem.start + size - sizeof(struct ccat_eth_frame);
|
||||
ccat_eth_fifo_reset(fifo);
|
||||
}
|
||||
|
||||
static void ccat_dma_free(struct ccat_eth_priv *const priv)
|
||||
|
|
|
|||
|
|
@ -37,11 +37,16 @@ DRIVER_MAP=(
|
|||
(".", "e100", "e100"),
|
||||
("e1000", "e1000", "e1000_main"),
|
||||
("e1000e", "e1000e", "netdev"),
|
||||
("genet", "bcmgenet", "bcmgenet"),
|
||||
("igb", "igb", "igb_main"),
|
||||
("igc", "igc", "igc_main"),
|
||||
(".", "r8169", "r8169"),
|
||||
("r8169", "r8169", "r8169_main"),
|
||||
)
|
||||
|
||||
DRIVERS = tuple([x[1] for x in DRIVER_MAP])
|
||||
|
||||
DRIVERS = sorted(set([x[1] for x in DRIVER_MAP]))
|
||||
|
||||
|
||||
def compile_regex(prefix, file_extension):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -5,3 +5,17 @@ This table contains a list of all available native drivers,
|
|||
depending on the kernel version.
|
||||
|
||||
The `generic` and the `ccat` driver are independent of the kernel version.
|
||||
|
||||
To find out which native driver is required for your network card,
|
||||
you can use `lspci -vv` or look in `/sys`:
|
||||
```sh
|
||||
admin@ipc:~> ls -l /sys/class/net/eth5/device/driver
|
||||
lrwxrwxrwx 1 root root 0 6. Nov 15:35 /sys/class/net/eth5/device/driver -> ../../../../bus/pci/drivers/e1000
|
||||
```
|
||||
or
|
||||
```sh
|
||||
admin@ipc:~> basename $(readlink /sys/class/net/eth5/device/driver)
|
||||
e1000
|
||||
```
|
||||
|
||||
In this example, `eth5` uses the `e1000` driver.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -76,6 +76,14 @@ EXTRA_DIST = \
|
|||
e1000-3.8-orig.h \
|
||||
e1000-4.4-ethercat.h \
|
||||
e1000-4.4-orig.h \
|
||||
e1000-5.10-ethercat.h \
|
||||
e1000-5.10-orig.h \
|
||||
e1000-5.14-ethercat.h \
|
||||
e1000-5.14-orig.h \
|
||||
e1000-5.15-ethercat.h \
|
||||
e1000-5.15-orig.h \
|
||||
e1000-6.1-ethercat.h \
|
||||
e1000-6.1-orig.h \
|
||||
e1000_ethtool-2.6.13-ethercat.c \
|
||||
e1000_ethtool-2.6.13-orig.c \
|
||||
e1000_ethtool-2.6.18-ethercat.c \
|
||||
|
|
@ -122,6 +130,14 @@ EXTRA_DIST = \
|
|||
e1000_ethtool-3.8-orig.c \
|
||||
e1000_ethtool-4.4-ethercat.c \
|
||||
e1000_ethtool-4.4-orig.c \
|
||||
e1000_ethtool-5.10-ethercat.c \
|
||||
e1000_ethtool-5.10-orig.c \
|
||||
e1000_ethtool-5.14-ethercat.c \
|
||||
e1000_ethtool-5.14-orig.c \
|
||||
e1000_ethtool-5.15-ethercat.c \
|
||||
e1000_ethtool-5.15-orig.c \
|
||||
e1000_ethtool-6.1-ethercat.c \
|
||||
e1000_ethtool-6.1-orig.c \
|
||||
e1000_hw-2.6.13-ethercat.c \
|
||||
e1000_hw-2.6.13-ethercat.h \
|
||||
e1000_hw-2.6.13-orig.c \
|
||||
|
|
@ -214,6 +230,22 @@ EXTRA_DIST = \
|
|||
e1000_hw-4.4-ethercat.h \
|
||||
e1000_hw-4.4-orig.c \
|
||||
e1000_hw-4.4-orig.h \
|
||||
e1000_hw-5.10-ethercat.c \
|
||||
e1000_hw-5.10-ethercat.h \
|
||||
e1000_hw-5.10-orig.c \
|
||||
e1000_hw-5.10-orig.h \
|
||||
e1000_hw-5.14-ethercat.c \
|
||||
e1000_hw-5.14-ethercat.h \
|
||||
e1000_hw-5.14-orig.c \
|
||||
e1000_hw-5.14-orig.h \
|
||||
e1000_hw-5.15-ethercat.c \
|
||||
e1000_hw-5.15-ethercat.h \
|
||||
e1000_hw-5.15-orig.c \
|
||||
e1000_hw-5.15-orig.h \
|
||||
e1000_hw-6.1-ethercat.c \
|
||||
e1000_hw-6.1-ethercat.h \
|
||||
e1000_hw-6.1-orig.c \
|
||||
e1000_hw-6.1-orig.h \
|
||||
e1000_main-2.6.13-ethercat.c \
|
||||
e1000_main-2.6.13-orig.c \
|
||||
e1000_main-2.6.18-ethercat.c \
|
||||
|
|
@ -260,6 +292,14 @@ EXTRA_DIST = \
|
|||
e1000_main-3.8-orig.c \
|
||||
e1000_main-4.4-ethercat.c \
|
||||
e1000_main-4.4-orig.c \
|
||||
e1000_main-5.10-ethercat.c \
|
||||
e1000_main-5.10-orig.c \
|
||||
e1000_main-5.14-ethercat.c \
|
||||
e1000_main-5.14-orig.c \
|
||||
e1000_main-5.15-ethercat.c \
|
||||
e1000_main-5.15-orig.c \
|
||||
e1000_main-6.1-ethercat.c \
|
||||
e1000_main-6.1-orig.c \
|
||||
e1000_osdep-2.6.13-ethercat.h \
|
||||
e1000_osdep-2.6.13-orig.h \
|
||||
e1000_osdep-2.6.18-ethercat.h \
|
||||
|
|
@ -306,6 +346,14 @@ EXTRA_DIST = \
|
|||
e1000_osdep-3.8-orig.h \
|
||||
e1000_osdep-4.4-ethercat.h \
|
||||
e1000_osdep-4.4-orig.h \
|
||||
e1000_osdep-5.10-ethercat.h \
|
||||
e1000_osdep-5.10-orig.h \
|
||||
e1000_osdep-5.14-ethercat.h \
|
||||
e1000_osdep-5.14-orig.h \
|
||||
e1000_osdep-5.15-ethercat.h \
|
||||
e1000_osdep-5.15-orig.h \
|
||||
e1000_osdep-6.1-ethercat.h \
|
||||
e1000_osdep-6.1-orig.h \
|
||||
e1000_param-2.6.13-ethercat.c \
|
||||
e1000_param-2.6.13-orig.c \
|
||||
e1000_param-2.6.18-ethercat.c \
|
||||
|
|
@ -351,6 +399,14 @@ EXTRA_DIST = \
|
|||
e1000_param-3.8-ethercat.c \
|
||||
e1000_param-3.8-orig.c \
|
||||
e1000_param-4.4-ethercat.c \
|
||||
e1000_param-4.4-orig.c
|
||||
e1000_param-4.4-orig.c \
|
||||
e1000_param-5.10-ethercat.c \
|
||||
e1000_param-5.10-orig.c \
|
||||
e1000_param-5.14-ethercat.c \
|
||||
e1000_param-5.14-orig.c \
|
||||
e1000_param-5.15-ethercat.c \
|
||||
e1000_param-5.15-orig.c \
|
||||
e1000_param-6.1-ethercat.c \
|
||||
e1000_param-6.1-orig.c
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -0,0 +1,357 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _E1000_H_
|
||||
#define _E1000_H_
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include "../ecdev.h"
|
||||
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
|
||||
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||
|
||||
struct e1000_adapter;
|
||||
|
||||
#include "e1000_hw-5.10-ethercat.h"
|
||||
|
||||
#define E1000_MAX_INTR 10
|
||||
|
||||
/*
|
||||
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||
*/
|
||||
#define E1000_CHECK_RESET_COUNT 50
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define E1000_DEFAULT_TXD 256
|
||||
#define E1000_MAX_TXD 256
|
||||
#define E1000_MIN_TXD 48
|
||||
#define E1000_MAX_82544_TXD 4096
|
||||
|
||||
#define E1000_DEFAULT_RXD 256
|
||||
#define E1000_MAX_RXD 256
|
||||
#define E1000_MIN_RXD 48
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_512 512
|
||||
#define E1000_RXBUFFER_1024 1024
|
||||
#define E1000_RXBUFFER_2048 2048
|
||||
#define E1000_RXBUFFER_4096 4096
|
||||
#define E1000_RXBUFFER_8192 8192
|
||||
#define E1000_RXBUFFER_16384 16384
|
||||
|
||||
/* SmartSpeed delimiters */
|
||||
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||
#define E1000_SMARTSPEED_MAX 15
|
||||
|
||||
/* Packet Buffer allocations */
|
||||
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||
|
||||
/* Flow Control Watermarks */
|
||||
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||
|
||||
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define E1000_TX_QUEUE_WAKE 16
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define E1000_EEPROM_82544_APM 0x0004
|
||||
#define E1000_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef E1000_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define E1000_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct e1000_tx_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
bool mapped_as_page;
|
||||
unsigned short segs;
|
||||
unsigned int bytecount;
|
||||
};
|
||||
|
||||
struct e1000_rx_buffer {
|
||||
union {
|
||||
struct page *page; /* jumbo: alloc_page */
|
||||
u8 *data; /* else, netdev_alloc_frag */
|
||||
} rxbuf;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_tx_buffer *buffer_info;
|
||||
|
||||
u16 tdh;
|
||||
u16 tdt;
|
||||
bool last_tx_tso;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_rx_buffer *buffer_info;
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
/* cpu for rx queue */
|
||||
int cpu;
|
||||
|
||||
u16 rdh;
|
||||
u16 rdt;
|
||||
};
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
({ \
|
||||
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||
})
|
||||
|
||||
#define E1000_RX_DESC_EXT(R, i) \
|
||||
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||
|
||||
/* board specific private data structure */
|
||||
|
||||
struct e1000_adapter {
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u32 smartspeed;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t stats_lock;
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
u8 fc_autoneg;
|
||||
|
||||
/* TX */
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
unsigned int restart_queue;
|
||||
u32 txd_cmd;
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
u32 gotcl;
|
||||
u64 gotcl_old;
|
||||
u64 tpt_old;
|
||||
u64 colc_old;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u8 tx_timeout_factor;
|
||||
atomic_t tx_fifo_stall;
|
||||
bool pcix_82544;
|
||||
bool detect_tx_hung;
|
||||
bool dump_buffers;
|
||||
|
||||
/* RX */
|
||||
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int *work_done, int work_to_do);
|
||||
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int cleaned_count);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
struct napi_struct napi;
|
||||
|
||||
int num_tx_queues;
|
||||
int num_rx_queues;
|
||||
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
bool rx_csum;
|
||||
u32 gorcl;
|
||||
u64 gorcl_old;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
u32 test_icr;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
bool tso_force;
|
||||
bool smart_power_down; /* phy smart power down */
|
||||
bool quad_port_a;
|
||||
unsigned long flags;
|
||||
u32 eeprom_wol;
|
||||
|
||||
/* for ioport free */
|
||||
int bars;
|
||||
int need_ioport;
|
||||
|
||||
bool discarding;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct delayed_work watchdog_task;
|
||||
struct delayed_work fifo_stall_task;
|
||||
struct delayed_work phy_info_task;
|
||||
|
||||
ec_device_t *ecdev;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
__E1000_DOWN,
|
||||
__E1000_DISABLED
|
||||
};
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||
#define e_dbg(format, arg...) \
|
||||
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||
#define e_err(msglvl, format, arg...) \
|
||||
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_info(msglvl, format, arg...) \
|
||||
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_warn(msglvl, format, arg...) \
|
||||
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_notice(msglvl, format, arg...) \
|
||||
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_dev_info(format, arg...) \
|
||||
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_warn(format, arg...) \
|
||||
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_err(format, arg...) \
|
||||
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||
|
||||
extern char e1000_driver_name[];
|
||||
|
||||
int e1000_open(struct net_device *netdev);
|
||||
int e1000_close(struct net_device *netdev);
|
||||
int e1000_up(struct e1000_adapter *adapter);
|
||||
void e1000_down(struct e1000_adapter *adapter);
|
||||
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||
void e1000_reset(struct e1000_adapter *adapter);
|
||||
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||
void e1000_power_up_phy(struct e1000_adapter *);
|
||||
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||
void e1000_check_options(struct e1000_adapter *adapter);
|
||||
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
|
|
@ -0,0 +1,352 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _E1000_H_
|
||||
#define _E1000_H_
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
|
||||
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||
|
||||
struct e1000_adapter;
|
||||
|
||||
#include "e1000_hw.h"
|
||||
|
||||
#define E1000_MAX_INTR 10
|
||||
|
||||
/*
|
||||
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||
*/
|
||||
#define E1000_CHECK_RESET_COUNT 50
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define E1000_DEFAULT_TXD 256
|
||||
#define E1000_MAX_TXD 256
|
||||
#define E1000_MIN_TXD 48
|
||||
#define E1000_MAX_82544_TXD 4096
|
||||
|
||||
#define E1000_DEFAULT_RXD 256
|
||||
#define E1000_MAX_RXD 256
|
||||
#define E1000_MIN_RXD 48
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_512 512
|
||||
#define E1000_RXBUFFER_1024 1024
|
||||
#define E1000_RXBUFFER_2048 2048
|
||||
#define E1000_RXBUFFER_4096 4096
|
||||
#define E1000_RXBUFFER_8192 8192
|
||||
#define E1000_RXBUFFER_16384 16384
|
||||
|
||||
/* SmartSpeed delimiters */
|
||||
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||
#define E1000_SMARTSPEED_MAX 15
|
||||
|
||||
/* Packet Buffer allocations */
|
||||
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||
|
||||
/* Flow Control Watermarks */
|
||||
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||
|
||||
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define E1000_TX_QUEUE_WAKE 16
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define E1000_EEPROM_82544_APM 0x0004
|
||||
#define E1000_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef E1000_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define E1000_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct e1000_tx_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
bool mapped_as_page;
|
||||
unsigned short segs;
|
||||
unsigned int bytecount;
|
||||
};
|
||||
|
||||
struct e1000_rx_buffer {
|
||||
union {
|
||||
struct page *page; /* jumbo: alloc_page */
|
||||
u8 *data; /* else, netdev_alloc_frag */
|
||||
} rxbuf;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_tx_buffer *buffer_info;
|
||||
|
||||
u16 tdh;
|
||||
u16 tdt;
|
||||
bool last_tx_tso;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_rx_buffer *buffer_info;
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
/* cpu for rx queue */
|
||||
int cpu;
|
||||
|
||||
u16 rdh;
|
||||
u16 rdt;
|
||||
};
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
({ \
|
||||
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||
})
|
||||
|
||||
#define E1000_RX_DESC_EXT(R, i) \
|
||||
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||
|
||||
/* board specific private data structure */
|
||||
|
||||
struct e1000_adapter {
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u32 smartspeed;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t stats_lock;
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
u8 fc_autoneg;
|
||||
|
||||
/* TX */
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
unsigned int restart_queue;
|
||||
u32 txd_cmd;
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
u32 gotcl;
|
||||
u64 gotcl_old;
|
||||
u64 tpt_old;
|
||||
u64 colc_old;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u8 tx_timeout_factor;
|
||||
atomic_t tx_fifo_stall;
|
||||
bool pcix_82544;
|
||||
bool detect_tx_hung;
|
||||
bool dump_buffers;
|
||||
|
||||
/* RX */
|
||||
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int *work_done, int work_to_do);
|
||||
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int cleaned_count);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
struct napi_struct napi;
|
||||
|
||||
int num_tx_queues;
|
||||
int num_rx_queues;
|
||||
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
bool rx_csum;
|
||||
u32 gorcl;
|
||||
u64 gorcl_old;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
u32 test_icr;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
bool tso_force;
|
||||
bool smart_power_down; /* phy smart power down */
|
||||
bool quad_port_a;
|
||||
unsigned long flags;
|
||||
u32 eeprom_wol;
|
||||
|
||||
/* for ioport free */
|
||||
int bars;
|
||||
int need_ioport;
|
||||
|
||||
bool discarding;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct delayed_work watchdog_task;
|
||||
struct delayed_work fifo_stall_task;
|
||||
struct delayed_work phy_info_task;
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
__E1000_DOWN,
|
||||
__E1000_DISABLED
|
||||
};
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||
#define e_dbg(format, arg...) \
|
||||
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||
#define e_err(msglvl, format, arg...) \
|
||||
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_info(msglvl, format, arg...) \
|
||||
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_warn(msglvl, format, arg...) \
|
||||
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_notice(msglvl, format, arg...) \
|
||||
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_dev_info(format, arg...) \
|
||||
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_warn(format, arg...) \
|
||||
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_err(format, arg...) \
|
||||
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||
|
||||
extern char e1000_driver_name[];
|
||||
|
||||
int e1000_open(struct net_device *netdev);
|
||||
int e1000_close(struct net_device *netdev);
|
||||
int e1000_up(struct e1000_adapter *adapter);
|
||||
void e1000_down(struct e1000_adapter *adapter);
|
||||
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||
void e1000_reset(struct e1000_adapter *adapter);
|
||||
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||
void e1000_power_up_phy(struct e1000_adapter *);
|
||||
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||
void e1000_check_options(struct e1000_adapter *adapter);
|
||||
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
|
|
@ -0,0 +1,357 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _E1000_H_
|
||||
#define _E1000_H_
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include "../ecdev.h"
|
||||
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
|
||||
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||
|
||||
struct e1000_adapter;
|
||||
|
||||
#include "e1000_hw-5.14-ethercat.h"
|
||||
|
||||
#define E1000_MAX_INTR 10
|
||||
|
||||
/*
|
||||
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||
*/
|
||||
#define E1000_CHECK_RESET_COUNT 50
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define E1000_DEFAULT_TXD 256
|
||||
#define E1000_MAX_TXD 256
|
||||
#define E1000_MIN_TXD 48
|
||||
#define E1000_MAX_82544_TXD 4096
|
||||
|
||||
#define E1000_DEFAULT_RXD 256
|
||||
#define E1000_MAX_RXD 256
|
||||
#define E1000_MIN_RXD 48
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_512 512
|
||||
#define E1000_RXBUFFER_1024 1024
|
||||
#define E1000_RXBUFFER_2048 2048
|
||||
#define E1000_RXBUFFER_4096 4096
|
||||
#define E1000_RXBUFFER_8192 8192
|
||||
#define E1000_RXBUFFER_16384 16384
|
||||
|
||||
/* SmartSpeed delimiters */
|
||||
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||
#define E1000_SMARTSPEED_MAX 15
|
||||
|
||||
/* Packet Buffer allocations */
|
||||
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||
|
||||
/* Flow Control Watermarks */
|
||||
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||
|
||||
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define E1000_TX_QUEUE_WAKE 16
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define E1000_EEPROM_82544_APM 0x0004
|
||||
#define E1000_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef E1000_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define E1000_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct e1000_tx_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
bool mapped_as_page;
|
||||
unsigned short segs;
|
||||
unsigned int bytecount;
|
||||
};
|
||||
|
||||
struct e1000_rx_buffer {
|
||||
union {
|
||||
struct page *page; /* jumbo: alloc_page */
|
||||
u8 *data; /* else, netdev_alloc_frag */
|
||||
} rxbuf;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_tx_buffer *buffer_info;
|
||||
|
||||
u16 tdh;
|
||||
u16 tdt;
|
||||
bool last_tx_tso;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_rx_buffer *buffer_info;
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
/* cpu for rx queue */
|
||||
int cpu;
|
||||
|
||||
u16 rdh;
|
||||
u16 rdt;
|
||||
};
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
({ \
|
||||
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||
})
|
||||
|
||||
#define E1000_RX_DESC_EXT(R, i) \
|
||||
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||
|
||||
/* board specific private data structure */
|
||||
|
||||
struct e1000_adapter {
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u32 smartspeed;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t stats_lock;
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
u8 fc_autoneg;
|
||||
|
||||
/* TX */
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
unsigned int restart_queue;
|
||||
u32 txd_cmd;
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
u32 gotcl;
|
||||
u64 gotcl_old;
|
||||
u64 tpt_old;
|
||||
u64 colc_old;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u8 tx_timeout_factor;
|
||||
atomic_t tx_fifo_stall;
|
||||
bool pcix_82544;
|
||||
bool detect_tx_hung;
|
||||
bool dump_buffers;
|
||||
|
||||
/* RX */
|
||||
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int *work_done, int work_to_do);
|
||||
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int cleaned_count);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
struct napi_struct napi;
|
||||
|
||||
int num_tx_queues;
|
||||
int num_rx_queues;
|
||||
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
bool rx_csum;
|
||||
u32 gorcl;
|
||||
u64 gorcl_old;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
u32 test_icr;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
bool tso_force;
|
||||
bool smart_power_down; /* phy smart power down */
|
||||
bool quad_port_a;
|
||||
unsigned long flags;
|
||||
u32 eeprom_wol;
|
||||
|
||||
/* for ioport free */
|
||||
int bars;
|
||||
int need_ioport;
|
||||
|
||||
bool discarding;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct delayed_work watchdog_task;
|
||||
struct delayed_work fifo_stall_task;
|
||||
struct delayed_work phy_info_task;
|
||||
|
||||
ec_device_t *ecdev;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
__E1000_DOWN,
|
||||
__E1000_DISABLED
|
||||
};
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||
#define e_dbg(format, arg...) \
|
||||
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||
#define e_err(msglvl, format, arg...) \
|
||||
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_info(msglvl, format, arg...) \
|
||||
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_warn(msglvl, format, arg...) \
|
||||
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_notice(msglvl, format, arg...) \
|
||||
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_dev_info(format, arg...) \
|
||||
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_warn(format, arg...) \
|
||||
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_err(format, arg...) \
|
||||
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||
|
||||
extern char e1000_driver_name[];
|
||||
|
||||
int e1000_open(struct net_device *netdev);
|
||||
int e1000_close(struct net_device *netdev);
|
||||
int e1000_up(struct e1000_adapter *adapter);
|
||||
void e1000_down(struct e1000_adapter *adapter);
|
||||
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||
void e1000_reset(struct e1000_adapter *adapter);
|
||||
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||
void e1000_power_up_phy(struct e1000_adapter *);
|
||||
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||
void e1000_check_options(struct e1000_adapter *adapter);
|
||||
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
|
|
@ -0,0 +1,352 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _E1000_H_
|
||||
#define _E1000_H_
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
|
||||
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||
|
||||
struct e1000_adapter;
|
||||
|
||||
#include "e1000_hw.h"
|
||||
|
||||
#define E1000_MAX_INTR 10
|
||||
|
||||
/*
|
||||
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||
*/
|
||||
#define E1000_CHECK_RESET_COUNT 50
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define E1000_DEFAULT_TXD 256
|
||||
#define E1000_MAX_TXD 256
|
||||
#define E1000_MIN_TXD 48
|
||||
#define E1000_MAX_82544_TXD 4096
|
||||
|
||||
#define E1000_DEFAULT_RXD 256
|
||||
#define E1000_MAX_RXD 256
|
||||
#define E1000_MIN_RXD 48
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_512 512
|
||||
#define E1000_RXBUFFER_1024 1024
|
||||
#define E1000_RXBUFFER_2048 2048
|
||||
#define E1000_RXBUFFER_4096 4096
|
||||
#define E1000_RXBUFFER_8192 8192
|
||||
#define E1000_RXBUFFER_16384 16384
|
||||
|
||||
/* SmartSpeed delimiters */
|
||||
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||
#define E1000_SMARTSPEED_MAX 15
|
||||
|
||||
/* Packet Buffer allocations */
|
||||
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||
|
||||
/* Flow Control Watermarks */
|
||||
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||
|
||||
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define E1000_TX_QUEUE_WAKE 16
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define E1000_EEPROM_82544_APM 0x0004
|
||||
#define E1000_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef E1000_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define E1000_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct e1000_tx_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
bool mapped_as_page;
|
||||
unsigned short segs;
|
||||
unsigned int bytecount;
|
||||
};
|
||||
|
||||
struct e1000_rx_buffer {
|
||||
union {
|
||||
struct page *page; /* jumbo: alloc_page */
|
||||
u8 *data; /* else, netdev_alloc_frag */
|
||||
} rxbuf;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_tx_buffer *buffer_info;
|
||||
|
||||
u16 tdh;
|
||||
u16 tdt;
|
||||
bool last_tx_tso;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_rx_buffer *buffer_info;
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
/* cpu for rx queue */
|
||||
int cpu;
|
||||
|
||||
u16 rdh;
|
||||
u16 rdt;
|
||||
};
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
({ \
|
||||
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||
})
|
||||
|
||||
#define E1000_RX_DESC_EXT(R, i) \
|
||||
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||
|
||||
/* board specific private data structure */
|
||||
|
||||
struct e1000_adapter {
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u32 smartspeed;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t stats_lock;
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
u8 fc_autoneg;
|
||||
|
||||
/* TX */
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
unsigned int restart_queue;
|
||||
u32 txd_cmd;
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
u32 gotcl;
|
||||
u64 gotcl_old;
|
||||
u64 tpt_old;
|
||||
u64 colc_old;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u8 tx_timeout_factor;
|
||||
atomic_t tx_fifo_stall;
|
||||
bool pcix_82544;
|
||||
bool detect_tx_hung;
|
||||
bool dump_buffers;
|
||||
|
||||
/* RX */
|
||||
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int *work_done, int work_to_do);
|
||||
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int cleaned_count);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
struct napi_struct napi;
|
||||
|
||||
int num_tx_queues;
|
||||
int num_rx_queues;
|
||||
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
bool rx_csum;
|
||||
u32 gorcl;
|
||||
u64 gorcl_old;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
u32 test_icr;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
bool tso_force;
|
||||
bool smart_power_down; /* phy smart power down */
|
||||
bool quad_port_a;
|
||||
unsigned long flags;
|
||||
u32 eeprom_wol;
|
||||
|
||||
/* for ioport free */
|
||||
int bars;
|
||||
int need_ioport;
|
||||
|
||||
bool discarding;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct delayed_work watchdog_task;
|
||||
struct delayed_work fifo_stall_task;
|
||||
struct delayed_work phy_info_task;
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
__E1000_DOWN,
|
||||
__E1000_DISABLED
|
||||
};
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||
#define e_dbg(format, arg...) \
|
||||
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||
#define e_err(msglvl, format, arg...) \
|
||||
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_info(msglvl, format, arg...) \
|
||||
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_warn(msglvl, format, arg...) \
|
||||
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_notice(msglvl, format, arg...) \
|
||||
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_dev_info(format, arg...) \
|
||||
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_warn(format, arg...) \
|
||||
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_err(format, arg...) \
|
||||
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||
|
||||
extern char e1000_driver_name[];
|
||||
|
||||
int e1000_open(struct net_device *netdev);
|
||||
int e1000_close(struct net_device *netdev);
|
||||
int e1000_up(struct e1000_adapter *adapter);
|
||||
void e1000_down(struct e1000_adapter *adapter);
|
||||
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||
void e1000_reset(struct e1000_adapter *adapter);
|
||||
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||
void e1000_power_up_phy(struct e1000_adapter *);
|
||||
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||
void e1000_check_options(struct e1000_adapter *adapter);
|
||||
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
|
|
@ -0,0 +1,357 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _E1000_H_
|
||||
#define _E1000_H_
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include "../ecdev.h"
|
||||
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
|
||||
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||
|
||||
struct e1000_adapter;
|
||||
|
||||
#include "e1000_hw-5.15-ethercat.h"
|
||||
|
||||
#define E1000_MAX_INTR 10
|
||||
|
||||
/*
|
||||
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||
*/
|
||||
#define E1000_CHECK_RESET_COUNT 50
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define E1000_DEFAULT_TXD 256
|
||||
#define E1000_MAX_TXD 256
|
||||
#define E1000_MIN_TXD 48
|
||||
#define E1000_MAX_82544_TXD 4096
|
||||
|
||||
#define E1000_DEFAULT_RXD 256
|
||||
#define E1000_MAX_RXD 256
|
||||
#define E1000_MIN_RXD 48
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_512 512
|
||||
#define E1000_RXBUFFER_1024 1024
|
||||
#define E1000_RXBUFFER_2048 2048
|
||||
#define E1000_RXBUFFER_4096 4096
|
||||
#define E1000_RXBUFFER_8192 8192
|
||||
#define E1000_RXBUFFER_16384 16384
|
||||
|
||||
/* SmartSpeed delimiters */
|
||||
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||
#define E1000_SMARTSPEED_MAX 15
|
||||
|
||||
/* Packet Buffer allocations */
|
||||
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||
|
||||
/* Flow Control Watermarks */
|
||||
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||
|
||||
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define E1000_TX_QUEUE_WAKE 16
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define E1000_EEPROM_82544_APM 0x0004
|
||||
#define E1000_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef E1000_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define E1000_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct e1000_tx_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
bool mapped_as_page;
|
||||
unsigned short segs;
|
||||
unsigned int bytecount;
|
||||
};
|
||||
|
||||
struct e1000_rx_buffer {
|
||||
union {
|
||||
struct page *page; /* jumbo: alloc_page */
|
||||
u8 *data; /* else, netdev_alloc_frag */
|
||||
} rxbuf;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_tx_buffer *buffer_info;
|
||||
|
||||
u16 tdh;
|
||||
u16 tdt;
|
||||
bool last_tx_tso;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_rx_buffer *buffer_info;
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
/* cpu for rx queue */
|
||||
int cpu;
|
||||
|
||||
u16 rdh;
|
||||
u16 rdt;
|
||||
};
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
({ \
|
||||
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||
})
|
||||
|
||||
#define E1000_RX_DESC_EXT(R, i) \
|
||||
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||
|
||||
/* board specific private data structure */
|
||||
|
||||
struct e1000_adapter {
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u32 smartspeed;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t stats_lock;
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
u8 fc_autoneg;
|
||||
|
||||
/* TX */
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
unsigned int restart_queue;
|
||||
u32 txd_cmd;
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
u32 gotcl;
|
||||
u64 gotcl_old;
|
||||
u64 tpt_old;
|
||||
u64 colc_old;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u8 tx_timeout_factor;
|
||||
atomic_t tx_fifo_stall;
|
||||
bool pcix_82544;
|
||||
bool detect_tx_hung;
|
||||
bool dump_buffers;
|
||||
|
||||
/* RX */
|
||||
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int *work_done, int work_to_do);
|
||||
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int cleaned_count);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
struct napi_struct napi;
|
||||
|
||||
int num_tx_queues;
|
||||
int num_rx_queues;
|
||||
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
bool rx_csum;
|
||||
u32 gorcl;
|
||||
u64 gorcl_old;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
u32 test_icr;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
bool tso_force;
|
||||
bool smart_power_down; /* phy smart power down */
|
||||
bool quad_port_a;
|
||||
unsigned long flags;
|
||||
u32 eeprom_wol;
|
||||
|
||||
/* for ioport free */
|
||||
int bars;
|
||||
int need_ioport;
|
||||
|
||||
bool discarding;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct delayed_work watchdog_task;
|
||||
struct delayed_work fifo_stall_task;
|
||||
struct delayed_work phy_info_task;
|
||||
|
||||
ec_device_t *ecdev;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
__E1000_DOWN,
|
||||
__E1000_DISABLED
|
||||
};
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||
#define e_dbg(format, arg...) \
|
||||
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||
#define e_err(msglvl, format, arg...) \
|
||||
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_info(msglvl, format, arg...) \
|
||||
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_warn(msglvl, format, arg...) \
|
||||
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_notice(msglvl, format, arg...) \
|
||||
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_dev_info(format, arg...) \
|
||||
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_warn(format, arg...) \
|
||||
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_err(format, arg...) \
|
||||
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||
|
||||
extern char e1000_driver_name[];
|
||||
|
||||
int e1000_open(struct net_device *netdev);
|
||||
int e1000_close(struct net_device *netdev);
|
||||
int e1000_up(struct e1000_adapter *adapter);
|
||||
void e1000_down(struct e1000_adapter *adapter);
|
||||
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||
void e1000_reset(struct e1000_adapter *adapter);
|
||||
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||
void e1000_power_up_phy(struct e1000_adapter *);
|
||||
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||
void e1000_check_options(struct e1000_adapter *adapter);
|
||||
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
|
|
@ -0,0 +1,352 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _E1000_H_
|
||||
#define _E1000_H_
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
|
||||
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||
|
||||
struct e1000_adapter;
|
||||
|
||||
#include "e1000_hw.h"
|
||||
|
||||
#define E1000_MAX_INTR 10
|
||||
|
||||
/*
|
||||
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||
*/
|
||||
#define E1000_CHECK_RESET_COUNT 50
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define E1000_DEFAULT_TXD 256
|
||||
#define E1000_MAX_TXD 256
|
||||
#define E1000_MIN_TXD 48
|
||||
#define E1000_MAX_82544_TXD 4096
|
||||
|
||||
#define E1000_DEFAULT_RXD 256
|
||||
#define E1000_MAX_RXD 256
|
||||
#define E1000_MIN_RXD 48
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_512 512
|
||||
#define E1000_RXBUFFER_1024 1024
|
||||
#define E1000_RXBUFFER_2048 2048
|
||||
#define E1000_RXBUFFER_4096 4096
|
||||
#define E1000_RXBUFFER_8192 8192
|
||||
#define E1000_RXBUFFER_16384 16384
|
||||
|
||||
/* SmartSpeed delimiters */
|
||||
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||
#define E1000_SMARTSPEED_MAX 15
|
||||
|
||||
/* Packet Buffer allocations */
|
||||
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||
|
||||
/* Flow Control Watermarks */
|
||||
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||
|
||||
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define E1000_TX_QUEUE_WAKE 16
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define E1000_EEPROM_82544_APM 0x0004
|
||||
#define E1000_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef E1000_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define E1000_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct e1000_tx_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
bool mapped_as_page;
|
||||
unsigned short segs;
|
||||
unsigned int bytecount;
|
||||
};
|
||||
|
||||
struct e1000_rx_buffer {
|
||||
union {
|
||||
struct page *page; /* jumbo: alloc_page */
|
||||
u8 *data; /* else, netdev_alloc_frag */
|
||||
} rxbuf;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_tx_buffer *buffer_info;
|
||||
|
||||
u16 tdh;
|
||||
u16 tdt;
|
||||
bool last_tx_tso;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_rx_buffer *buffer_info;
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
/* cpu for rx queue */
|
||||
int cpu;
|
||||
|
||||
u16 rdh;
|
||||
u16 rdt;
|
||||
};
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
({ \
|
||||
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||
})
|
||||
|
||||
#define E1000_RX_DESC_EXT(R, i) \
|
||||
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||
|
||||
/* board specific private data structure */
|
||||
|
||||
struct e1000_adapter {
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u32 smartspeed;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t stats_lock;
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
u8 fc_autoneg;
|
||||
|
||||
/* TX */
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
unsigned int restart_queue;
|
||||
u32 txd_cmd;
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
u32 gotcl;
|
||||
u64 gotcl_old;
|
||||
u64 tpt_old;
|
||||
u64 colc_old;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u8 tx_timeout_factor;
|
||||
atomic_t tx_fifo_stall;
|
||||
bool pcix_82544;
|
||||
bool detect_tx_hung;
|
||||
bool dump_buffers;
|
||||
|
||||
/* RX */
|
||||
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int *work_done, int work_to_do);
|
||||
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int cleaned_count);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
struct napi_struct napi;
|
||||
|
||||
int num_tx_queues;
|
||||
int num_rx_queues;
|
||||
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
bool rx_csum;
|
||||
u32 gorcl;
|
||||
u64 gorcl_old;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
u32 test_icr;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
bool tso_force;
|
||||
bool smart_power_down; /* phy smart power down */
|
||||
bool quad_port_a;
|
||||
unsigned long flags;
|
||||
u32 eeprom_wol;
|
||||
|
||||
/* for ioport free */
|
||||
int bars;
|
||||
int need_ioport;
|
||||
|
||||
bool discarding;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct delayed_work watchdog_task;
|
||||
struct delayed_work fifo_stall_task;
|
||||
struct delayed_work phy_info_task;
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
__E1000_DOWN,
|
||||
__E1000_DISABLED
|
||||
};
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||
#define e_dbg(format, arg...) \
|
||||
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||
#define e_err(msglvl, format, arg...) \
|
||||
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_info(msglvl, format, arg...) \
|
||||
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_warn(msglvl, format, arg...) \
|
||||
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_notice(msglvl, format, arg...) \
|
||||
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_dev_info(format, arg...) \
|
||||
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_warn(format, arg...) \
|
||||
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_err(format, arg...) \
|
||||
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||
|
||||
extern char e1000_driver_name[];
|
||||
|
||||
int e1000_open(struct net_device *netdev);
|
||||
int e1000_close(struct net_device *netdev);
|
||||
int e1000_up(struct e1000_adapter *adapter);
|
||||
void e1000_down(struct e1000_adapter *adapter);
|
||||
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||
void e1000_reset(struct e1000_adapter *adapter);
|
||||
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||
void e1000_power_up_phy(struct e1000_adapter *);
|
||||
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||
void e1000_check_options(struct e1000_adapter *adapter);
|
||||
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
|
|
@ -0,0 +1,357 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _E1000_H_
|
||||
#define _E1000_H_
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include "../ecdev.h"
|
||||
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
|
||||
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||
|
||||
struct e1000_adapter;
|
||||
|
||||
#include "e1000_hw-6.1-ethercat.h"
|
||||
|
||||
#define E1000_MAX_INTR 10
|
||||
|
||||
/*
|
||||
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||
*/
|
||||
#define E1000_CHECK_RESET_COUNT 50
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define E1000_DEFAULT_TXD 256
|
||||
#define E1000_MAX_TXD 256
|
||||
#define E1000_MIN_TXD 48
|
||||
#define E1000_MAX_82544_TXD 4096
|
||||
|
||||
#define E1000_DEFAULT_RXD 256
|
||||
#define E1000_MAX_RXD 256
|
||||
#define E1000_MIN_RXD 48
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_512 512
|
||||
#define E1000_RXBUFFER_1024 1024
|
||||
#define E1000_RXBUFFER_2048 2048
|
||||
#define E1000_RXBUFFER_4096 4096
|
||||
#define E1000_RXBUFFER_8192 8192
|
||||
#define E1000_RXBUFFER_16384 16384
|
||||
|
||||
/* SmartSpeed delimiters */
|
||||
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||
#define E1000_SMARTSPEED_MAX 15
|
||||
|
||||
/* Packet Buffer allocations */
|
||||
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||
|
||||
/* Flow Control Watermarks */
|
||||
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||
|
||||
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define E1000_TX_QUEUE_WAKE 16
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define E1000_EEPROM_82544_APM 0x0004
|
||||
#define E1000_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef E1000_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define E1000_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct e1000_tx_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
bool mapped_as_page;
|
||||
unsigned short segs;
|
||||
unsigned int bytecount;
|
||||
};
|
||||
|
||||
struct e1000_rx_buffer {
|
||||
union {
|
||||
struct page *page; /* jumbo: alloc_page */
|
||||
u8 *data; /* else, netdev_alloc_frag */
|
||||
} rxbuf;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_tx_buffer *buffer_info;
|
||||
|
||||
u16 tdh;
|
||||
u16 tdt;
|
||||
bool last_tx_tso;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_rx_buffer *buffer_info;
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
/* cpu for rx queue */
|
||||
int cpu;
|
||||
|
||||
u16 rdh;
|
||||
u16 rdt;
|
||||
};
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
({ \
|
||||
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||
})
|
||||
|
||||
#define E1000_RX_DESC_EXT(R, i) \
|
||||
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||
|
||||
/* board specific private data structure */
|
||||
|
||||
struct e1000_adapter {
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u32 smartspeed;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t stats_lock;
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
u8 fc_autoneg;
|
||||
|
||||
/* TX */
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
unsigned int restart_queue;
|
||||
u32 txd_cmd;
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
u32 gotcl;
|
||||
u64 gotcl_old;
|
||||
u64 tpt_old;
|
||||
u64 colc_old;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u8 tx_timeout_factor;
|
||||
atomic_t tx_fifo_stall;
|
||||
bool pcix_82544;
|
||||
bool detect_tx_hung;
|
||||
bool dump_buffers;
|
||||
|
||||
/* RX */
|
||||
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int *work_done, int work_to_do);
|
||||
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int cleaned_count);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
struct napi_struct napi;
|
||||
|
||||
int num_tx_queues;
|
||||
int num_rx_queues;
|
||||
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
bool rx_csum;
|
||||
u32 gorcl;
|
||||
u64 gorcl_old;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
u32 test_icr;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
bool tso_force;
|
||||
bool smart_power_down; /* phy smart power down */
|
||||
bool quad_port_a;
|
||||
unsigned long flags;
|
||||
u32 eeprom_wol;
|
||||
|
||||
/* for ioport free */
|
||||
int bars;
|
||||
int need_ioport;
|
||||
|
||||
bool discarding;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct delayed_work watchdog_task;
|
||||
struct delayed_work fifo_stall_task;
|
||||
struct delayed_work phy_info_task;
|
||||
|
||||
ec_device_t *ecdev;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
__E1000_DOWN,
|
||||
__E1000_DISABLED
|
||||
};
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||
#define e_dbg(format, arg...) \
|
||||
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||
#define e_err(msglvl, format, arg...) \
|
||||
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_info(msglvl, format, arg...) \
|
||||
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_warn(msglvl, format, arg...) \
|
||||
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_notice(msglvl, format, arg...) \
|
||||
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_dev_info(format, arg...) \
|
||||
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_warn(format, arg...) \
|
||||
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_err(format, arg...) \
|
||||
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||
|
||||
extern char e1000_driver_name[];
|
||||
|
||||
int e1000_open(struct net_device *netdev);
|
||||
int e1000_close(struct net_device *netdev);
|
||||
int e1000_up(struct e1000_adapter *adapter);
|
||||
void e1000_down(struct e1000_adapter *adapter);
|
||||
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||
void e1000_reset(struct e1000_adapter *adapter);
|
||||
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||
void e1000_power_up_phy(struct e1000_adapter *);
|
||||
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||
void e1000_check_options(struct e1000_adapter *adapter);
|
||||
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
|
|
@ -0,0 +1,352 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* Linux PRO/1000 Ethernet Driver main header file */
|
||||
|
||||
#ifndef _E1000_H_
|
||||
#define _E1000_H_
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
#define BAR_0 0
|
||||
#define BAR_1 1
|
||||
|
||||
#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)}
|
||||
|
||||
struct e1000_adapter;
|
||||
|
||||
#include "e1000_hw.h"
|
||||
|
||||
#define E1000_MAX_INTR 10
|
||||
|
||||
/*
|
||||
* Count for polling __E1000_RESET condition every 10-20msec.
|
||||
*/
|
||||
#define E1000_CHECK_RESET_COUNT 50
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define E1000_DEFAULT_TXD 256
|
||||
#define E1000_MAX_TXD 256
|
||||
#define E1000_MIN_TXD 48
|
||||
#define E1000_MAX_82544_TXD 4096
|
||||
|
||||
#define E1000_DEFAULT_RXD 256
|
||||
#define E1000_MAX_RXD 256
|
||||
#define E1000_MIN_RXD 48
|
||||
#define E1000_MAX_82544_RXD 4096
|
||||
|
||||
#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */
|
||||
#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */
|
||||
|
||||
/* this is the size past which hardware will drop packets when setting LPE=0 */
|
||||
#define MAXIMUM_ETHERNET_VLAN_SIZE 1522
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define E1000_RXBUFFER_128 128 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_256 256 /* Used for packet split */
|
||||
#define E1000_RXBUFFER_512 512
|
||||
#define E1000_RXBUFFER_1024 1024
|
||||
#define E1000_RXBUFFER_2048 2048
|
||||
#define E1000_RXBUFFER_4096 4096
|
||||
#define E1000_RXBUFFER_8192 8192
|
||||
#define E1000_RXBUFFER_16384 16384
|
||||
|
||||
/* SmartSpeed delimiters */
|
||||
#define E1000_SMARTSPEED_DOWNSHIFT 3
|
||||
#define E1000_SMARTSPEED_MAX 15
|
||||
|
||||
/* Packet Buffer allocations */
|
||||
#define E1000_PBA_BYTES_SHIFT 0xA
|
||||
#define E1000_TX_HEAD_ADDR_SHIFT 7
|
||||
#define E1000_PBA_TX_MASK 0xFFFF0000
|
||||
|
||||
/* Flow Control Watermarks */
|
||||
#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */
|
||||
#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */
|
||||
|
||||
#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */
|
||||
|
||||
/* How many Tx Descriptors do we need to call netif_wake_queue ? */
|
||||
#define E1000_TX_QUEUE_WAKE 16
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define E1000_EEPROM_82544_APM 0x0004
|
||||
#define E1000_EEPROM_APME 0x0400
|
||||
|
||||
#ifndef E1000_MASTER_SLAVE
|
||||
/* Switch to override PHY master/slave setting */
|
||||
#define E1000_MASTER_SLAVE e1000_ms_hw_default
|
||||
#endif
|
||||
|
||||
#define E1000_MNG_VLAN_NONE (-1)
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct e1000_tx_buffer {
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t dma;
|
||||
unsigned long time_stamp;
|
||||
u16 length;
|
||||
u16 next_to_watch;
|
||||
bool mapped_as_page;
|
||||
unsigned short segs;
|
||||
unsigned int bytecount;
|
||||
};
|
||||
|
||||
struct e1000_rx_buffer {
|
||||
union {
|
||||
struct page *page; /* jumbo: alloc_page */
|
||||
u8 *data; /* else, netdev_alloc_frag */
|
||||
} rxbuf;
|
||||
dma_addr_t dma;
|
||||
};
|
||||
|
||||
struct e1000_tx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_tx_buffer *buffer_info;
|
||||
|
||||
u16 tdh;
|
||||
u16 tdt;
|
||||
bool last_tx_tso;
|
||||
};
|
||||
|
||||
struct e1000_rx_ring {
|
||||
/* pointer to the descriptor ring memory */
|
||||
void *desc;
|
||||
/* physical address of the descriptor ring */
|
||||
dma_addr_t dma;
|
||||
/* length of descriptor ring in bytes */
|
||||
unsigned int size;
|
||||
/* number of descriptors in the ring */
|
||||
unsigned int count;
|
||||
/* next descriptor to associate a buffer with */
|
||||
unsigned int next_to_use;
|
||||
/* next descriptor to check for DD status bit */
|
||||
unsigned int next_to_clean;
|
||||
/* array of buffer information structs */
|
||||
struct e1000_rx_buffer *buffer_info;
|
||||
struct sk_buff *rx_skb_top;
|
||||
|
||||
/* cpu for rx queue */
|
||||
int cpu;
|
||||
|
||||
u16 rdh;
|
||||
u16 rdt;
|
||||
};
|
||||
|
||||
#define E1000_DESC_UNUSED(R) \
|
||||
({ \
|
||||
unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \
|
||||
unsigned int use = READ_ONCE((R)->next_to_use); \
|
||||
(clean > use ? 0 : (R)->count) + clean - use - 1; \
|
||||
})
|
||||
|
||||
#define E1000_RX_DESC_EXT(R, i) \
|
||||
(&(((union e1000_rx_desc_extended *)((R).desc))[i]))
|
||||
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
|
||||
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
|
||||
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
|
||||
#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc)
|
||||
|
||||
/* board specific private data structure */
|
||||
|
||||
struct e1000_adapter {
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
u16 mng_vlan_id;
|
||||
u32 bd_number;
|
||||
u32 rx_buffer_len;
|
||||
u32 wol;
|
||||
u32 smartspeed;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
spinlock_t stats_lock;
|
||||
unsigned int total_tx_bytes;
|
||||
unsigned int total_tx_packets;
|
||||
unsigned int total_rx_bytes;
|
||||
unsigned int total_rx_packets;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 itr;
|
||||
u32 itr_setting;
|
||||
u16 tx_itr;
|
||||
u16 rx_itr;
|
||||
|
||||
u8 fc_autoneg;
|
||||
|
||||
/* TX */
|
||||
struct e1000_tx_ring *tx_ring; /* One per active queue */
|
||||
unsigned int restart_queue;
|
||||
u32 txd_cmd;
|
||||
u32 tx_int_delay;
|
||||
u32 tx_abs_int_delay;
|
||||
u32 gotcl;
|
||||
u64 gotcl_old;
|
||||
u64 tpt_old;
|
||||
u64 colc_old;
|
||||
u32 tx_timeout_count;
|
||||
u32 tx_fifo_head;
|
||||
u32 tx_head_addr;
|
||||
u32 tx_fifo_size;
|
||||
u8 tx_timeout_factor;
|
||||
atomic_t tx_fifo_stall;
|
||||
bool pcix_82544;
|
||||
bool detect_tx_hung;
|
||||
bool dump_buffers;
|
||||
|
||||
/* RX */
|
||||
bool (*clean_rx)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int *work_done, int work_to_do);
|
||||
void (*alloc_rx_buf)(struct e1000_adapter *adapter,
|
||||
struct e1000_rx_ring *rx_ring,
|
||||
int cleaned_count);
|
||||
struct e1000_rx_ring *rx_ring; /* One per active queue */
|
||||
struct napi_struct napi;
|
||||
|
||||
int num_tx_queues;
|
||||
int num_rx_queues;
|
||||
|
||||
u64 hw_csum_err;
|
||||
u64 hw_csum_good;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_int_delay;
|
||||
u32 rx_abs_int_delay;
|
||||
bool rx_csum;
|
||||
u32 gorcl;
|
||||
u64 gorcl_old;
|
||||
|
||||
/* OS defined structs */
|
||||
struct net_device *netdev;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
/* structs defined in e1000_hw.h */
|
||||
struct e1000_hw hw;
|
||||
struct e1000_hw_stats stats;
|
||||
struct e1000_phy_info phy_info;
|
||||
struct e1000_phy_stats phy_stats;
|
||||
|
||||
u32 test_icr;
|
||||
struct e1000_tx_ring test_tx_ring;
|
||||
struct e1000_rx_ring test_rx_ring;
|
||||
|
||||
int msg_enable;
|
||||
|
||||
/* to not mess up cache alignment, always add to the bottom */
|
||||
bool tso_force;
|
||||
bool smart_power_down; /* phy smart power down */
|
||||
bool quad_port_a;
|
||||
unsigned long flags;
|
||||
u32 eeprom_wol;
|
||||
|
||||
/* for ioport free */
|
||||
int bars;
|
||||
int need_ioport;
|
||||
|
||||
bool discarding;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct delayed_work watchdog_task;
|
||||
struct delayed_work fifo_stall_task;
|
||||
struct delayed_work phy_info_task;
|
||||
};
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
__E1000_DOWN,
|
||||
__E1000_DISABLED
|
||||
};
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
struct net_device *e1000_get_hw_dev(struct e1000_hw *hw);
|
||||
#define e_dbg(format, arg...) \
|
||||
netdev_dbg(e1000_get_hw_dev(hw), format, ## arg)
|
||||
#define e_err(msglvl, format, arg...) \
|
||||
netif_err(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_info(msglvl, format, arg...) \
|
||||
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_warn(msglvl, format, arg...) \
|
||||
netif_warn(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_notice(msglvl, format, arg...) \
|
||||
netif_notice(adapter, msglvl, adapter->netdev, format, ## arg)
|
||||
#define e_dev_info(format, arg...) \
|
||||
dev_info(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_warn(format, arg...) \
|
||||
dev_warn(&adapter->pdev->dev, format, ## arg)
|
||||
#define e_dev_err(format, arg...) \
|
||||
dev_err(&adapter->pdev->dev, format, ## arg)
|
||||
|
||||
extern char e1000_driver_name[];
|
||||
|
||||
int e1000_open(struct net_device *netdev);
|
||||
int e1000_close(struct net_device *netdev);
|
||||
int e1000_up(struct e1000_adapter *adapter);
|
||||
void e1000_down(struct e1000_adapter *adapter);
|
||||
void e1000_reinit_locked(struct e1000_adapter *adapter);
|
||||
void e1000_reset(struct e1000_adapter *adapter);
|
||||
int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx);
|
||||
int e1000_setup_all_rx_resources(struct e1000_adapter *adapter);
|
||||
int e1000_setup_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_rx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_free_all_tx_resources(struct e1000_adapter *adapter);
|
||||
void e1000_update_stats(struct e1000_adapter *adapter);
|
||||
bool e1000_has_link(struct e1000_adapter *adapter);
|
||||
void e1000_power_up_phy(struct e1000_adapter *);
|
||||
void e1000_set_ethtool_ops(struct net_device *netdev);
|
||||
void e1000_check_options(struct e1000_adapter *adapter);
|
||||
char *e1000_get_hw_dev_name(struct e1000_hw *hw);
|
||||
|
||||
#endif /* _E1000_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,83 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* glue for the OS independent part of e1000
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _E1000_OSDEP_H_
|
||||
#define _E1000_OSDEP_H_
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#define CONFIG_RAM_BASE 0x60000
|
||||
#define GBE_CONFIG_OFFSET 0x0
|
||||
|
||||
#define GBE_CONFIG_RAM_BASE \
|
||||
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||
|
||||
#define GBE_CONFIG_BASE_VIRT \
|
||||
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||
|
||||
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||
(iowrite16_rep(base + offset, data, count))
|
||||
|
||||
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||
(ioread16_rep(base + (offset << 1), data, count))
|
||||
|
||||
#define er32(reg) \
|
||||
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg)))
|
||||
|
||||
#define ew32(reg, value) \
|
||||
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg))))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset)))
|
||||
|
||||
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||
readl((a)->flash_address + reg))
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||
readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _E1000_OSDEP_H_ */
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* glue for the OS independent part of e1000
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _E1000_OSDEP_H_
|
||||
#define _E1000_OSDEP_H_
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#define CONFIG_RAM_BASE 0x60000
|
||||
#define GBE_CONFIG_OFFSET 0x0
|
||||
|
||||
#define GBE_CONFIG_RAM_BASE \
|
||||
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||
|
||||
#define GBE_CONFIG_BASE_VIRT \
|
||||
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||
|
||||
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||
(iowrite16_rep(base + offset, data, count))
|
||||
|
||||
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||
(ioread16_rep(base + (offset << 1), data, count))
|
||||
|
||||
#define er32(reg) \
|
||||
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg)))
|
||||
|
||||
#define ew32(reg, value) \
|
||||
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg))))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset)))
|
||||
|
||||
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||
readl((a)->flash_address + reg))
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||
readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _E1000_OSDEP_H_ */
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* glue for the OS independent part of e1000
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _E1000_OSDEP_H_
|
||||
#define _E1000_OSDEP_H_
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#define CONFIG_RAM_BASE 0x60000
|
||||
#define GBE_CONFIG_OFFSET 0x0
|
||||
|
||||
#define GBE_CONFIG_RAM_BASE \
|
||||
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||
|
||||
#define GBE_CONFIG_BASE_VIRT \
|
||||
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||
|
||||
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||
(iowrite16_rep(base + offset, data, count))
|
||||
|
||||
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||
(ioread16_rep(base + (offset << 1), data, count))
|
||||
|
||||
#define er32(reg) \
|
||||
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg)))
|
||||
|
||||
#define ew32(reg, value) \
|
||||
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg))))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset)))
|
||||
|
||||
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||
readl((a)->flash_address + reg))
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||
readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _E1000_OSDEP_H_ */
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* glue for the OS independent part of e1000
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _E1000_OSDEP_H_
|
||||
#define _E1000_OSDEP_H_
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#define CONFIG_RAM_BASE 0x60000
|
||||
#define GBE_CONFIG_OFFSET 0x0
|
||||
|
||||
#define GBE_CONFIG_RAM_BASE \
|
||||
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||
|
||||
#define GBE_CONFIG_BASE_VIRT \
|
||||
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||
|
||||
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||
(iowrite16_rep(base + offset, data, count))
|
||||
|
||||
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||
(ioread16_rep(base + (offset << 1), data, count))
|
||||
|
||||
#define er32(reg) \
|
||||
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg)))
|
||||
|
||||
#define ew32(reg, value) \
|
||||
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg))))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset)))
|
||||
|
||||
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||
readl((a)->flash_address + reg))
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||
readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _E1000_OSDEP_H_ */
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* glue for the OS independent part of e1000
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _E1000_OSDEP_H_
|
||||
#define _E1000_OSDEP_H_
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#define CONFIG_RAM_BASE 0x60000
|
||||
#define GBE_CONFIG_OFFSET 0x0
|
||||
|
||||
#define GBE_CONFIG_RAM_BASE \
|
||||
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||
|
||||
#define GBE_CONFIG_BASE_VIRT \
|
||||
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||
|
||||
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||
(iowrite16_rep(base + offset, data, count))
|
||||
|
||||
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||
(ioread16_rep(base + (offset << 1), data, count))
|
||||
|
||||
#define er32(reg) \
|
||||
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg)))
|
||||
|
||||
#define ew32(reg, value) \
|
||||
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg))))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset)))
|
||||
|
||||
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||
readl((a)->flash_address + reg))
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||
readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _E1000_OSDEP_H_ */
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* glue for the OS independent part of e1000
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _E1000_OSDEP_H_
|
||||
#define _E1000_OSDEP_H_
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#define CONFIG_RAM_BASE 0x60000
|
||||
#define GBE_CONFIG_OFFSET 0x0
|
||||
|
||||
#define GBE_CONFIG_RAM_BASE \
|
||||
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||
|
||||
#define GBE_CONFIG_BASE_VIRT \
|
||||
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||
|
||||
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||
(iowrite16_rep(base + offset, data, count))
|
||||
|
||||
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||
(ioread16_rep(base + (offset << 1), data, count))
|
||||
|
||||
#define er32(reg) \
|
||||
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg)))
|
||||
|
||||
#define ew32(reg, value) \
|
||||
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg))))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset)))
|
||||
|
||||
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||
readl((a)->flash_address + reg))
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||
readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _E1000_OSDEP_H_ */
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* glue for the OS independent part of e1000
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _E1000_OSDEP_H_
|
||||
#define _E1000_OSDEP_H_
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#define CONFIG_RAM_BASE 0x60000
|
||||
#define GBE_CONFIG_OFFSET 0x0
|
||||
|
||||
#define GBE_CONFIG_RAM_BASE \
|
||||
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||
|
||||
#define GBE_CONFIG_BASE_VIRT \
|
||||
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||
|
||||
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||
(iowrite16_rep(base + offset, data, count))
|
||||
|
||||
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||
(ioread16_rep(base + (offset << 1), data, count))
|
||||
|
||||
#define er32(reg) \
|
||||
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg)))
|
||||
|
||||
#define ew32(reg, value) \
|
||||
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg))))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset)))
|
||||
|
||||
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||
readl((a)->flash_address + reg))
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||
readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _E1000_OSDEP_H_ */
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
/* glue for the OS independent part of e1000
|
||||
* includes register access macros
|
||||
*/
|
||||
|
||||
#ifndef _E1000_OSDEP_H_
|
||||
#define _E1000_OSDEP_H_
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
#define CONFIG_RAM_BASE 0x60000
|
||||
#define GBE_CONFIG_OFFSET 0x0
|
||||
|
||||
#define GBE_CONFIG_RAM_BASE \
|
||||
((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET))
|
||||
|
||||
#define GBE_CONFIG_BASE_VIRT \
|
||||
((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE))
|
||||
|
||||
#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \
|
||||
(iowrite16_rep(base + offset, data, count))
|
||||
|
||||
#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \
|
||||
(ioread16_rep(base + (offset << 1), data, count))
|
||||
|
||||
#define er32(reg) \
|
||||
(readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg)))
|
||||
|
||||
#define ew32(reg, value) \
|
||||
(writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \
|
||||
? E1000_##reg : E1000_82542_##reg))))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \
|
||||
writel((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY(a, reg, offset) ( \
|
||||
readl((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 2)))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
|
||||
#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
|
||||
writew((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
|
||||
readw((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
((offset) << 1)))
|
||||
|
||||
#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
|
||||
writeb((value), ((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset))))
|
||||
|
||||
#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
|
||||
readb((a)->hw_addr + \
|
||||
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
|
||||
(offset)))
|
||||
|
||||
#define E1000_WRITE_FLUSH() er32(STATUS)
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \
|
||||
writel((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG(a, reg) ( \
|
||||
readl((a)->flash_address + reg))
|
||||
|
||||
#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \
|
||||
writew((value), ((a)->flash_address + reg)))
|
||||
|
||||
#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \
|
||||
readw((a)->flash_address + reg))
|
||||
|
||||
#endif /* _E1000_OSDEP_H_ */
|
||||
|
|
@ -0,0 +1,729 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
#include "e1000-5.10-ethercat.h"
|
||||
|
||||
/* This is the only thing that needs to be changed to adjust the
|
||||
* maximum number of ports that the driver can manage.
|
||||
*/
|
||||
|
||||
#define E1000_MAX_NIC 32
|
||||
|
||||
#define OPTION_UNSET -1
|
||||
#define OPTION_DISABLED 0
|
||||
#define OPTION_ENABLED 1
|
||||
|
||||
/* All parameters are treated the same, as an integer array of values.
|
||||
* This macro just reduces the need to repeat the same declaration code
|
||||
* over and over (plus this helps to avoid typo bugs).
|
||||
*/
|
||||
|
||||
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||
#define E1000_PARAM(X, desc) \
|
||||
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||
static unsigned int num_##X; \
|
||||
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||
MODULE_PARM_DESC(X, desc);
|
||||
|
||||
/* Transmit Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||
|
||||
/* Receive Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||
|
||||
/* User Specified Speed Override
|
||||
*
|
||||
* Valid Range: 0, 10, 100, 1000
|
||||
* - 0 - auto-negotiate at all supported speeds
|
||||
* - 10 - only link at 10 Mbps
|
||||
* - 100 - only link at 100 Mbps
|
||||
* - 1000 - only link at 1000 Mbps
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Speed, "Speed setting");
|
||||
|
||||
/* User Specified Duplex Override
|
||||
*
|
||||
* Valid Range: 0-2
|
||||
* - 0 - auto-negotiate for duplex
|
||||
* - 1 - only link at half duplex
|
||||
* - 2 - only link at full duplex
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Duplex, "Duplex setting");
|
||||
|
||||
/* Auto-negotiation Advertisement Override
|
||||
*
|
||||
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||
*
|
||||
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||
* combinations should be advertised during auto-negotiation.
|
||||
* The supported speed and duplex modes are listed below
|
||||
*
|
||||
* Bit 7 6 5 4 3 2 1 0
|
||||
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||
* Duplex Full Full Half Full Half
|
||||
*
|
||||
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||
*/
|
||||
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||
#define AUTONEG_ADV_MASK 0x2F
|
||||
|
||||
/* User Specified Flow Control Override
|
||||
*
|
||||
* Valid Range: 0-3
|
||||
* - 0 - No Flow Control
|
||||
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||
* - 3 - Full Flow Control Support
|
||||
*
|
||||
* Default Value: Read flow control settings from the EEPROM
|
||||
*/
|
||||
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||
|
||||
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
* - 0 - disables all checksum offload
|
||||
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||
* on 82543 and newer -based NICs
|
||||
*
|
||||
* Default Value: 1
|
||||
*/
|
||||
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||
|
||||
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||
* Tx interrupt delay needs to typically be set to something non zero
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||
#define DEFAULT_TIDV 8
|
||||
#define MAX_TXDELAY 0xFFFF
|
||||
#define MIN_TXDELAY 0
|
||||
|
||||
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||
#define DEFAULT_TADV 32
|
||||
#define MAX_TXABSDELAY 0xFFFF
|
||||
#define MIN_TXABSDELAY 0
|
||||
|
||||
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||
* hardware will likely hang if you set this to anything but zero.
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||
#define DEFAULT_RDTR 0
|
||||
#define MAX_RXDELAY 0xFFFF
|
||||
#define MIN_RXDELAY 0
|
||||
|
||||
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||
#define DEFAULT_RADV 8
|
||||
#define MAX_RXABSDELAY 0xFFFF
|
||||
#define MIN_RXABSDELAY 0
|
||||
|
||||
/* Interrupt Throttle Rate (interrupts/sec)
|
||||
*
|
||||
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||
*/
|
||||
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||
#define DEFAULT_ITR 3
|
||||
#define MAX_ITR 100000
|
||||
#define MIN_ITR 100
|
||||
|
||||
/* Enable Smart Power Down of the PHY
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
*
|
||||
* Default Value: 0 (disabled)
|
||||
*/
|
||||
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||
|
||||
struct e1000_option {
|
||||
enum { enable_option, range_option, list_option } type;
|
||||
const char *name;
|
||||
const char *err;
|
||||
int def;
|
||||
union {
|
||||
struct { /* range_option info */
|
||||
int min;
|
||||
int max;
|
||||
} r;
|
||||
struct { /* list_option info */
|
||||
int nr;
|
||||
const struct e1000_opt_list { int i; char *str; } *p;
|
||||
} l;
|
||||
} arg;
|
||||
};
|
||||
|
||||
static int e1000_validate_option(unsigned int *value,
|
||||
const struct e1000_option *opt,
|
||||
struct e1000_adapter *adapter)
|
||||
{
|
||||
if (*value == OPTION_UNSET) {
|
||||
*value = opt->def;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (opt->type) {
|
||||
case enable_option:
|
||||
switch (*value) {
|
||||
case OPTION_ENABLED:
|
||||
e_dev_info("%s Enabled\n", opt->name);
|
||||
return 0;
|
||||
case OPTION_DISABLED:
|
||||
e_dev_info("%s Disabled\n", opt->name);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case range_option:
|
||||
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case list_option: {
|
||||
int i;
|
||||
const struct e1000_opt_list *ent;
|
||||
|
||||
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||
ent = &opt->arg.l.p[i];
|
||||
if (*value == ent->i) {
|
||||
if (ent->str[0] != '\0')
|
||||
e_dev_info("%s\n", ent->str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||
opt->name, *value, opt->err);
|
||||
*value = opt->def;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||
|
||||
/**
|
||||
* e1000_check_options - Range Checking for Command Line Parameters
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* This routine checks all command line parameters for valid user
|
||||
* input. If an invalid value is given, or if no user specified
|
||||
* value exists, a default value is used. The final value is stored
|
||||
* in a variable in the adapter structure.
|
||||
**/
|
||||
void e1000_check_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
if (bd >= E1000_MAX_NIC) {
|
||||
e_dev_warn("Warning: no configuration for board #%i "
|
||||
"using defaults for all values\n", bd);
|
||||
}
|
||||
|
||||
{ /* Transmit Descriptor Count */
|
||||
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||
.def = E1000_DEFAULT_TXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_TXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_TxDescriptors > bd) {
|
||||
tx_ring->count = TxDescriptors[bd];
|
||||
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||
tx_ring->count = ALIGN(tx_ring->count,
|
||||
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
tx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||
tx_ring[i].count = tx_ring->count;
|
||||
}
|
||||
{ /* Receive Descriptor Count */
|
||||
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||
.def = E1000_DEFAULT_RXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_RXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||
E1000_MAX_82544_RXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_RxDescriptors > bd) {
|
||||
rx_ring->count = RxDescriptors[bd];
|
||||
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||
rx_ring->count = ALIGN(rx_ring->count,
|
||||
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
rx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||
rx_ring[i].count = rx_ring->count;
|
||||
}
|
||||
{ /* Checksum Offload Enable/Disable */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "Checksum Offload",
|
||||
.err = "defaulting to Enabled",
|
||||
.def = OPTION_ENABLED
|
||||
};
|
||||
|
||||
if (num_XsumRX > bd) {
|
||||
unsigned int rx_csum = XsumRX[bd];
|
||||
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||
adapter->rx_csum = rx_csum;
|
||||
} else {
|
||||
adapter->rx_csum = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Flow Control */
|
||||
|
||||
static const struct e1000_opt_list fc_list[] = {
|
||||
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||
};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Flow Control",
|
||||
.err = "reading default settings from EEPROM",
|
||||
.def = E1000_FC_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||
.p = fc_list }}
|
||||
};
|
||||
|
||||
if (num_FlowControl > bd) {
|
||||
unsigned int fc = FlowControl[bd];
|
||||
e1000_validate_option(&fc, &opt, adapter);
|
||||
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||
} else {
|
||||
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||
.def = DEFAULT_TIDV,
|
||||
.arg = { .r = { .min = MIN_TXDELAY,
|
||||
.max = MAX_TXDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxIntDelay > bd) {
|
||||
adapter->tx_int_delay = TxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||
.def = DEFAULT_TADV,
|
||||
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||
.max = MAX_TXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxAbsIntDelay > bd) {
|
||||
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||
.def = DEFAULT_RDTR,
|
||||
.arg = { .r = { .min = MIN_RXDELAY,
|
||||
.max = MAX_RXDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxIntDelay > bd) {
|
||||
adapter->rx_int_delay = RxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||
.def = DEFAULT_RADV,
|
||||
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||
.max = MAX_RXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxAbsIntDelay > bd) {
|
||||
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Interrupt Throttling Rate */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||
.def = DEFAULT_ITR,
|
||||
.arg = { .r = { .min = MIN_ITR,
|
||||
.max = MAX_ITR }}
|
||||
};
|
||||
|
||||
if (num_InterruptThrottleRate > bd) {
|
||||
adapter->itr = InterruptThrottleRate[bd];
|
||||
switch (adapter->itr) {
|
||||
case 0:
|
||||
e_dev_info("%s turned off\n", opt.name);
|
||||
break;
|
||||
case 1:
|
||||
e_dev_info("%s set to dynamic mode\n",
|
||||
opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 3:
|
||||
e_dev_info("%s set to dynamic conservative "
|
||||
"mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 4:
|
||||
e_dev_info("%s set to simplified "
|
||||
"(2000-8000) ints mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
break;
|
||||
default:
|
||||
e1000_validate_option(&adapter->itr, &opt,
|
||||
adapter);
|
||||
/* save the setting, because the dynamic bits
|
||||
* change itr.
|
||||
* clear the lower two bits because they are
|
||||
* used as control
|
||||
*/
|
||||
adapter->itr_setting = adapter->itr & ~3;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
adapter->itr_setting = opt.def;
|
||||
adapter->itr = 20000;
|
||||
}
|
||||
}
|
||||
{ /* Smart Power Down */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "PHY Smart Power Down",
|
||||
.err = "defaulting to Disabled",
|
||||
.def = OPTION_DISABLED
|
||||
};
|
||||
|
||||
if (num_SmartPowerDownEnable > bd) {
|
||||
unsigned int spd = SmartPowerDownEnable[bd];
|
||||
e1000_validate_option(&spd, &opt, adapter);
|
||||
adapter->smart_power_down = spd;
|
||||
} else {
|
||||
adapter->smart_power_down = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
switch (adapter->hw.media_type) {
|
||||
case e1000_media_type_fiber:
|
||||
case e1000_media_type_internal_serdes:
|
||||
e1000_check_fiber_options(adapter);
|
||||
break;
|
||||
case e1000_media_type_copper:
|
||||
e1000_check_copper_options(adapter);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on fiber adapters
|
||||
**/
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
int bd = adapter->bd_number;
|
||||
if (num_Speed > bd) {
|
||||
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||
"adapters, parameter ignored\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on copper adapters
|
||||
**/
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
unsigned int speed, dplx, an;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
{ /* Speed */
|
||||
static const struct e1000_opt_list speed_list[] = {
|
||||
{ 0, "" },
|
||||
{ SPEED_10, "" },
|
||||
{ SPEED_100, "" },
|
||||
{ SPEED_1000, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Speed",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||
.p = speed_list }}
|
||||
};
|
||||
|
||||
if (num_Speed > bd) {
|
||||
speed = Speed[bd];
|
||||
e1000_validate_option(&speed, &opt, adapter);
|
||||
} else {
|
||||
speed = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Duplex */
|
||||
static const struct e1000_opt_list dplx_list[] = {
|
||||
{ 0, "" },
|
||||
{ HALF_DUPLEX, "" },
|
||||
{ FULL_DUPLEX, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Duplex",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||
.p = dplx_list }}
|
||||
};
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
dplx = Duplex[bd];
|
||||
e1000_validate_option(&dplx, &opt, adapter);
|
||||
} else {
|
||||
dplx = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||
"parameter ignored\n");
|
||||
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||
} else { /* Autoneg */
|
||||
static const struct e1000_opt_list an_list[] =
|
||||
#define AA "AutoNeg advertising "
|
||||
{{ 0x01, AA "10/HD" },
|
||||
{ 0x02, AA "10/FD" },
|
||||
{ 0x03, AA "10/FD, 10/HD" },
|
||||
{ 0x04, AA "100/HD" },
|
||||
{ 0x05, AA "100/HD, 10/HD" },
|
||||
{ 0x06, AA "100/HD, 10/FD" },
|
||||
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||
{ 0x08, AA "100/FD" },
|
||||
{ 0x09, AA "100/FD, 10/HD" },
|
||||
{ 0x0a, AA "100/FD, 10/FD" },
|
||||
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||
{ 0x0c, AA "100/FD, 100/HD" },
|
||||
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x20, AA "1000/FD" },
|
||||
{ 0x21, AA "1000/FD, 10/HD" },
|
||||
{ 0x22, AA "1000/FD, 10/FD" },
|
||||
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||
{ 0x24, AA "1000/FD, 100/HD" },
|
||||
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x28, AA "1000/FD, 100/FD" },
|
||||
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "AutoNeg",
|
||||
.err = "parameter ignored",
|
||||
.def = AUTONEG_ADV_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||
.p = an_list }}
|
||||
};
|
||||
|
||||
if (num_AutoNeg > bd) {
|
||||
an = AutoNeg[bd];
|
||||
e1000_validate_option(&an, &opt, adapter);
|
||||
} else {
|
||||
an = opt.def;
|
||||
}
|
||||
adapter->hw.autoneg_advertised = an;
|
||||
}
|
||||
|
||||
switch (speed + dplx) {
|
||||
case 0:
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||
e_dev_info("Speed and duplex autonegotiation "
|
||||
"enabled\n");
|
||||
break;
|
||||
case HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_100_HALF;
|
||||
break;
|
||||
case FULL_DUPLEX:
|
||||
e_dev_info("Full Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||
ADVERTISE_100_FULL |
|
||||
ADVERTISE_1000_FULL;
|
||||
break;
|
||||
case SPEED_10:
|
||||
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_10_FULL;
|
||||
break;
|
||||
case SPEED_10 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_10 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100:
|
||||
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||
ADVERTISE_100_FULL;
|
||||
break;
|
||||
case SPEED_100 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||
goto full_duplex_only;
|
||||
case SPEED_1000 + HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||
fallthrough;
|
||||
case SPEED_1000 + FULL_DUPLEX:
|
||||
full_duplex_only:
|
||||
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||
"only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||
"Setting MDI-X to a compatible value.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,729 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
#include "e1000.h"
|
||||
|
||||
/* This is the only thing that needs to be changed to adjust the
|
||||
* maximum number of ports that the driver can manage.
|
||||
*/
|
||||
|
||||
#define E1000_MAX_NIC 32
|
||||
|
||||
#define OPTION_UNSET -1
|
||||
#define OPTION_DISABLED 0
|
||||
#define OPTION_ENABLED 1
|
||||
|
||||
/* All parameters are treated the same, as an integer array of values.
|
||||
* This macro just reduces the need to repeat the same declaration code
|
||||
* over and over (plus this helps to avoid typo bugs).
|
||||
*/
|
||||
|
||||
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||
#define E1000_PARAM(X, desc) \
|
||||
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||
static unsigned int num_##X; \
|
||||
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||
MODULE_PARM_DESC(X, desc);
|
||||
|
||||
/* Transmit Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||
|
||||
/* Receive Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||
|
||||
/* User Specified Speed Override
|
||||
*
|
||||
* Valid Range: 0, 10, 100, 1000
|
||||
* - 0 - auto-negotiate at all supported speeds
|
||||
* - 10 - only link at 10 Mbps
|
||||
* - 100 - only link at 100 Mbps
|
||||
* - 1000 - only link at 1000 Mbps
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Speed, "Speed setting");
|
||||
|
||||
/* User Specified Duplex Override
|
||||
*
|
||||
* Valid Range: 0-2
|
||||
* - 0 - auto-negotiate for duplex
|
||||
* - 1 - only link at half duplex
|
||||
* - 2 - only link at full duplex
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Duplex, "Duplex setting");
|
||||
|
||||
/* Auto-negotiation Advertisement Override
|
||||
*
|
||||
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||
*
|
||||
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||
* combinations should be advertised during auto-negotiation.
|
||||
* The supported speed and duplex modes are listed below
|
||||
*
|
||||
* Bit 7 6 5 4 3 2 1 0
|
||||
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||
* Duplex Full Full Half Full Half
|
||||
*
|
||||
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||
*/
|
||||
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||
#define AUTONEG_ADV_MASK 0x2F
|
||||
|
||||
/* User Specified Flow Control Override
|
||||
*
|
||||
* Valid Range: 0-3
|
||||
* - 0 - No Flow Control
|
||||
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||
* - 3 - Full Flow Control Support
|
||||
*
|
||||
* Default Value: Read flow control settings from the EEPROM
|
||||
*/
|
||||
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||
|
||||
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
* - 0 - disables all checksum offload
|
||||
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||
* on 82543 and newer -based NICs
|
||||
*
|
||||
* Default Value: 1
|
||||
*/
|
||||
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||
|
||||
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||
* Tx interrupt delay needs to typically be set to something non zero
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||
#define DEFAULT_TIDV 8
|
||||
#define MAX_TXDELAY 0xFFFF
|
||||
#define MIN_TXDELAY 0
|
||||
|
||||
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||
#define DEFAULT_TADV 32
|
||||
#define MAX_TXABSDELAY 0xFFFF
|
||||
#define MIN_TXABSDELAY 0
|
||||
|
||||
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||
* hardware will likely hang if you set this to anything but zero.
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||
#define DEFAULT_RDTR 0
|
||||
#define MAX_RXDELAY 0xFFFF
|
||||
#define MIN_RXDELAY 0
|
||||
|
||||
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||
#define DEFAULT_RADV 8
|
||||
#define MAX_RXABSDELAY 0xFFFF
|
||||
#define MIN_RXABSDELAY 0
|
||||
|
||||
/* Interrupt Throttle Rate (interrupts/sec)
|
||||
*
|
||||
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||
*/
|
||||
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||
#define DEFAULT_ITR 3
|
||||
#define MAX_ITR 100000
|
||||
#define MIN_ITR 100
|
||||
|
||||
/* Enable Smart Power Down of the PHY
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
*
|
||||
* Default Value: 0 (disabled)
|
||||
*/
|
||||
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||
|
||||
struct e1000_option {
|
||||
enum { enable_option, range_option, list_option } type;
|
||||
const char *name;
|
||||
const char *err;
|
||||
int def;
|
||||
union {
|
||||
struct { /* range_option info */
|
||||
int min;
|
||||
int max;
|
||||
} r;
|
||||
struct { /* list_option info */
|
||||
int nr;
|
||||
const struct e1000_opt_list { int i; char *str; } *p;
|
||||
} l;
|
||||
} arg;
|
||||
};
|
||||
|
||||
static int e1000_validate_option(unsigned int *value,
|
||||
const struct e1000_option *opt,
|
||||
struct e1000_adapter *adapter)
|
||||
{
|
||||
if (*value == OPTION_UNSET) {
|
||||
*value = opt->def;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (opt->type) {
|
||||
case enable_option:
|
||||
switch (*value) {
|
||||
case OPTION_ENABLED:
|
||||
e_dev_info("%s Enabled\n", opt->name);
|
||||
return 0;
|
||||
case OPTION_DISABLED:
|
||||
e_dev_info("%s Disabled\n", opt->name);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case range_option:
|
||||
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case list_option: {
|
||||
int i;
|
||||
const struct e1000_opt_list *ent;
|
||||
|
||||
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||
ent = &opt->arg.l.p[i];
|
||||
if (*value == ent->i) {
|
||||
if (ent->str[0] != '\0')
|
||||
e_dev_info("%s\n", ent->str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||
opt->name, *value, opt->err);
|
||||
*value = opt->def;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||
|
||||
/**
|
||||
* e1000_check_options - Range Checking for Command Line Parameters
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* This routine checks all command line parameters for valid user
|
||||
* input. If an invalid value is given, or if no user specified
|
||||
* value exists, a default value is used. The final value is stored
|
||||
* in a variable in the adapter structure.
|
||||
**/
|
||||
void e1000_check_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
if (bd >= E1000_MAX_NIC) {
|
||||
e_dev_warn("Warning: no configuration for board #%i "
|
||||
"using defaults for all values\n", bd);
|
||||
}
|
||||
|
||||
{ /* Transmit Descriptor Count */
|
||||
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||
.def = E1000_DEFAULT_TXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_TXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_TxDescriptors > bd) {
|
||||
tx_ring->count = TxDescriptors[bd];
|
||||
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||
tx_ring->count = ALIGN(tx_ring->count,
|
||||
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
tx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||
tx_ring[i].count = tx_ring->count;
|
||||
}
|
||||
{ /* Receive Descriptor Count */
|
||||
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||
.def = E1000_DEFAULT_RXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_RXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||
E1000_MAX_82544_RXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_RxDescriptors > bd) {
|
||||
rx_ring->count = RxDescriptors[bd];
|
||||
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||
rx_ring->count = ALIGN(rx_ring->count,
|
||||
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
rx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||
rx_ring[i].count = rx_ring->count;
|
||||
}
|
||||
{ /* Checksum Offload Enable/Disable */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "Checksum Offload",
|
||||
.err = "defaulting to Enabled",
|
||||
.def = OPTION_ENABLED
|
||||
};
|
||||
|
||||
if (num_XsumRX > bd) {
|
||||
unsigned int rx_csum = XsumRX[bd];
|
||||
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||
adapter->rx_csum = rx_csum;
|
||||
} else {
|
||||
adapter->rx_csum = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Flow Control */
|
||||
|
||||
static const struct e1000_opt_list fc_list[] = {
|
||||
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||
};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Flow Control",
|
||||
.err = "reading default settings from EEPROM",
|
||||
.def = E1000_FC_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||
.p = fc_list }}
|
||||
};
|
||||
|
||||
if (num_FlowControl > bd) {
|
||||
unsigned int fc = FlowControl[bd];
|
||||
e1000_validate_option(&fc, &opt, adapter);
|
||||
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||
} else {
|
||||
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||
.def = DEFAULT_TIDV,
|
||||
.arg = { .r = { .min = MIN_TXDELAY,
|
||||
.max = MAX_TXDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxIntDelay > bd) {
|
||||
adapter->tx_int_delay = TxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||
.def = DEFAULT_TADV,
|
||||
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||
.max = MAX_TXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxAbsIntDelay > bd) {
|
||||
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||
.def = DEFAULT_RDTR,
|
||||
.arg = { .r = { .min = MIN_RXDELAY,
|
||||
.max = MAX_RXDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxIntDelay > bd) {
|
||||
adapter->rx_int_delay = RxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||
.def = DEFAULT_RADV,
|
||||
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||
.max = MAX_RXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxAbsIntDelay > bd) {
|
||||
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Interrupt Throttling Rate */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||
.def = DEFAULT_ITR,
|
||||
.arg = { .r = { .min = MIN_ITR,
|
||||
.max = MAX_ITR }}
|
||||
};
|
||||
|
||||
if (num_InterruptThrottleRate > bd) {
|
||||
adapter->itr = InterruptThrottleRate[bd];
|
||||
switch (adapter->itr) {
|
||||
case 0:
|
||||
e_dev_info("%s turned off\n", opt.name);
|
||||
break;
|
||||
case 1:
|
||||
e_dev_info("%s set to dynamic mode\n",
|
||||
opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 3:
|
||||
e_dev_info("%s set to dynamic conservative "
|
||||
"mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 4:
|
||||
e_dev_info("%s set to simplified "
|
||||
"(2000-8000) ints mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
break;
|
||||
default:
|
||||
e1000_validate_option(&adapter->itr, &opt,
|
||||
adapter);
|
||||
/* save the setting, because the dynamic bits
|
||||
* change itr.
|
||||
* clear the lower two bits because they are
|
||||
* used as control
|
||||
*/
|
||||
adapter->itr_setting = adapter->itr & ~3;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
adapter->itr_setting = opt.def;
|
||||
adapter->itr = 20000;
|
||||
}
|
||||
}
|
||||
{ /* Smart Power Down */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "PHY Smart Power Down",
|
||||
.err = "defaulting to Disabled",
|
||||
.def = OPTION_DISABLED
|
||||
};
|
||||
|
||||
if (num_SmartPowerDownEnable > bd) {
|
||||
unsigned int spd = SmartPowerDownEnable[bd];
|
||||
e1000_validate_option(&spd, &opt, adapter);
|
||||
adapter->smart_power_down = spd;
|
||||
} else {
|
||||
adapter->smart_power_down = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
switch (adapter->hw.media_type) {
|
||||
case e1000_media_type_fiber:
|
||||
case e1000_media_type_internal_serdes:
|
||||
e1000_check_fiber_options(adapter);
|
||||
break;
|
||||
case e1000_media_type_copper:
|
||||
e1000_check_copper_options(adapter);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on fiber adapters
|
||||
**/
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
int bd = adapter->bd_number;
|
||||
if (num_Speed > bd) {
|
||||
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||
"adapters, parameter ignored\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on copper adapters
|
||||
**/
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
unsigned int speed, dplx, an;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
{ /* Speed */
|
||||
static const struct e1000_opt_list speed_list[] = {
|
||||
{ 0, "" },
|
||||
{ SPEED_10, "" },
|
||||
{ SPEED_100, "" },
|
||||
{ SPEED_1000, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Speed",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||
.p = speed_list }}
|
||||
};
|
||||
|
||||
if (num_Speed > bd) {
|
||||
speed = Speed[bd];
|
||||
e1000_validate_option(&speed, &opt, adapter);
|
||||
} else {
|
||||
speed = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Duplex */
|
||||
static const struct e1000_opt_list dplx_list[] = {
|
||||
{ 0, "" },
|
||||
{ HALF_DUPLEX, "" },
|
||||
{ FULL_DUPLEX, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Duplex",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||
.p = dplx_list }}
|
||||
};
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
dplx = Duplex[bd];
|
||||
e1000_validate_option(&dplx, &opt, adapter);
|
||||
} else {
|
||||
dplx = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||
"parameter ignored\n");
|
||||
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||
} else { /* Autoneg */
|
||||
static const struct e1000_opt_list an_list[] =
|
||||
#define AA "AutoNeg advertising "
|
||||
{{ 0x01, AA "10/HD" },
|
||||
{ 0x02, AA "10/FD" },
|
||||
{ 0x03, AA "10/FD, 10/HD" },
|
||||
{ 0x04, AA "100/HD" },
|
||||
{ 0x05, AA "100/HD, 10/HD" },
|
||||
{ 0x06, AA "100/HD, 10/FD" },
|
||||
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||
{ 0x08, AA "100/FD" },
|
||||
{ 0x09, AA "100/FD, 10/HD" },
|
||||
{ 0x0a, AA "100/FD, 10/FD" },
|
||||
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||
{ 0x0c, AA "100/FD, 100/HD" },
|
||||
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x20, AA "1000/FD" },
|
||||
{ 0x21, AA "1000/FD, 10/HD" },
|
||||
{ 0x22, AA "1000/FD, 10/FD" },
|
||||
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||
{ 0x24, AA "1000/FD, 100/HD" },
|
||||
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x28, AA "1000/FD, 100/FD" },
|
||||
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "AutoNeg",
|
||||
.err = "parameter ignored",
|
||||
.def = AUTONEG_ADV_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||
.p = an_list }}
|
||||
};
|
||||
|
||||
if (num_AutoNeg > bd) {
|
||||
an = AutoNeg[bd];
|
||||
e1000_validate_option(&an, &opt, adapter);
|
||||
} else {
|
||||
an = opt.def;
|
||||
}
|
||||
adapter->hw.autoneg_advertised = an;
|
||||
}
|
||||
|
||||
switch (speed + dplx) {
|
||||
case 0:
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||
e_dev_info("Speed and duplex autonegotiation "
|
||||
"enabled\n");
|
||||
break;
|
||||
case HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_100_HALF;
|
||||
break;
|
||||
case FULL_DUPLEX:
|
||||
e_dev_info("Full Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||
ADVERTISE_100_FULL |
|
||||
ADVERTISE_1000_FULL;
|
||||
break;
|
||||
case SPEED_10:
|
||||
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_10_FULL;
|
||||
break;
|
||||
case SPEED_10 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_10 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100:
|
||||
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||
ADVERTISE_100_FULL;
|
||||
break;
|
||||
case SPEED_100 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||
goto full_duplex_only;
|
||||
case SPEED_1000 + HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||
fallthrough;
|
||||
case SPEED_1000 + FULL_DUPLEX:
|
||||
full_duplex_only:
|
||||
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||
"only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||
"Setting MDI-X to a compatible value.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,729 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
#include "e1000-5.14-ethercat.h"
|
||||
|
||||
/* This is the only thing that needs to be changed to adjust the
|
||||
* maximum number of ports that the driver can manage.
|
||||
*/
|
||||
|
||||
#define E1000_MAX_NIC 32
|
||||
|
||||
#define OPTION_UNSET -1
|
||||
#define OPTION_DISABLED 0
|
||||
#define OPTION_ENABLED 1
|
||||
|
||||
/* All parameters are treated the same, as an integer array of values.
|
||||
* This macro just reduces the need to repeat the same declaration code
|
||||
* over and over (plus this helps to avoid typo bugs).
|
||||
*/
|
||||
|
||||
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||
#define E1000_PARAM(X, desc) \
|
||||
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||
static unsigned int num_##X; \
|
||||
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||
MODULE_PARM_DESC(X, desc);
|
||||
|
||||
/* Transmit Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||
|
||||
/* Receive Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||
|
||||
/* User Specified Speed Override
|
||||
*
|
||||
* Valid Range: 0, 10, 100, 1000
|
||||
* - 0 - auto-negotiate at all supported speeds
|
||||
* - 10 - only link at 10 Mbps
|
||||
* - 100 - only link at 100 Mbps
|
||||
* - 1000 - only link at 1000 Mbps
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Speed, "Speed setting");
|
||||
|
||||
/* User Specified Duplex Override
|
||||
*
|
||||
* Valid Range: 0-2
|
||||
* - 0 - auto-negotiate for duplex
|
||||
* - 1 - only link at half duplex
|
||||
* - 2 - only link at full duplex
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Duplex, "Duplex setting");
|
||||
|
||||
/* Auto-negotiation Advertisement Override
|
||||
*
|
||||
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||
*
|
||||
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||
* combinations should be advertised during auto-negotiation.
|
||||
* The supported speed and duplex modes are listed below
|
||||
*
|
||||
* Bit 7 6 5 4 3 2 1 0
|
||||
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||
* Duplex Full Full Half Full Half
|
||||
*
|
||||
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||
*/
|
||||
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||
#define AUTONEG_ADV_MASK 0x2F
|
||||
|
||||
/* User Specified Flow Control Override
|
||||
*
|
||||
* Valid Range: 0-3
|
||||
* - 0 - No Flow Control
|
||||
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||
* - 3 - Full Flow Control Support
|
||||
*
|
||||
* Default Value: Read flow control settings from the EEPROM
|
||||
*/
|
||||
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||
|
||||
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
* - 0 - disables all checksum offload
|
||||
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||
* on 82543 and newer -based NICs
|
||||
*
|
||||
* Default Value: 1
|
||||
*/
|
||||
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||
|
||||
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||
* Tx interrupt delay needs to typically be set to something non zero
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||
#define DEFAULT_TIDV 8
|
||||
#define MAX_TXDELAY 0xFFFF
|
||||
#define MIN_TXDELAY 0
|
||||
|
||||
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||
#define DEFAULT_TADV 32
|
||||
#define MAX_TXABSDELAY 0xFFFF
|
||||
#define MIN_TXABSDELAY 0
|
||||
|
||||
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||
* hardware will likely hang if you set this to anything but zero.
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||
#define DEFAULT_RDTR 0
|
||||
#define MAX_RXDELAY 0xFFFF
|
||||
#define MIN_RXDELAY 0
|
||||
|
||||
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||
#define DEFAULT_RADV 8
|
||||
#define MAX_RXABSDELAY 0xFFFF
|
||||
#define MIN_RXABSDELAY 0
|
||||
|
||||
/* Interrupt Throttle Rate (interrupts/sec)
|
||||
*
|
||||
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||
*/
|
||||
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||
#define DEFAULT_ITR 3
|
||||
#define MAX_ITR 100000
|
||||
#define MIN_ITR 100
|
||||
|
||||
/* Enable Smart Power Down of the PHY
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
*
|
||||
* Default Value: 0 (disabled)
|
||||
*/
|
||||
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||
|
||||
struct e1000_option {
|
||||
enum { enable_option, range_option, list_option } type;
|
||||
const char *name;
|
||||
const char *err;
|
||||
int def;
|
||||
union {
|
||||
struct { /* range_option info */
|
||||
int min;
|
||||
int max;
|
||||
} r;
|
||||
struct { /* list_option info */
|
||||
int nr;
|
||||
const struct e1000_opt_list { int i; char *str; } *p;
|
||||
} l;
|
||||
} arg;
|
||||
};
|
||||
|
||||
static int e1000_validate_option(unsigned int *value,
|
||||
const struct e1000_option *opt,
|
||||
struct e1000_adapter *adapter)
|
||||
{
|
||||
if (*value == OPTION_UNSET) {
|
||||
*value = opt->def;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (opt->type) {
|
||||
case enable_option:
|
||||
switch (*value) {
|
||||
case OPTION_ENABLED:
|
||||
e_dev_info("%s Enabled\n", opt->name);
|
||||
return 0;
|
||||
case OPTION_DISABLED:
|
||||
e_dev_info("%s Disabled\n", opt->name);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case range_option:
|
||||
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case list_option: {
|
||||
int i;
|
||||
const struct e1000_opt_list *ent;
|
||||
|
||||
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||
ent = &opt->arg.l.p[i];
|
||||
if (*value == ent->i) {
|
||||
if (ent->str[0] != '\0')
|
||||
e_dev_info("%s\n", ent->str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||
opt->name, *value, opt->err);
|
||||
*value = opt->def;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||
|
||||
/**
|
||||
* e1000_check_options - Range Checking for Command Line Parameters
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* This routine checks all command line parameters for valid user
|
||||
* input. If an invalid value is given, or if no user specified
|
||||
* value exists, a default value is used. The final value is stored
|
||||
* in a variable in the adapter structure.
|
||||
**/
|
||||
void e1000_check_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
if (bd >= E1000_MAX_NIC) {
|
||||
e_dev_warn("Warning: no configuration for board #%i "
|
||||
"using defaults for all values\n", bd);
|
||||
}
|
||||
|
||||
{ /* Transmit Descriptor Count */
|
||||
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||
.def = E1000_DEFAULT_TXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_TXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_TxDescriptors > bd) {
|
||||
tx_ring->count = TxDescriptors[bd];
|
||||
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||
tx_ring->count = ALIGN(tx_ring->count,
|
||||
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
tx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||
tx_ring[i].count = tx_ring->count;
|
||||
}
|
||||
{ /* Receive Descriptor Count */
|
||||
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||
.def = E1000_DEFAULT_RXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_RXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||
E1000_MAX_82544_RXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_RxDescriptors > bd) {
|
||||
rx_ring->count = RxDescriptors[bd];
|
||||
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||
rx_ring->count = ALIGN(rx_ring->count,
|
||||
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
rx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||
rx_ring[i].count = rx_ring->count;
|
||||
}
|
||||
{ /* Checksum Offload Enable/Disable */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "Checksum Offload",
|
||||
.err = "defaulting to Enabled",
|
||||
.def = OPTION_ENABLED
|
||||
};
|
||||
|
||||
if (num_XsumRX > bd) {
|
||||
unsigned int rx_csum = XsumRX[bd];
|
||||
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||
adapter->rx_csum = rx_csum;
|
||||
} else {
|
||||
adapter->rx_csum = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Flow Control */
|
||||
|
||||
static const struct e1000_opt_list fc_list[] = {
|
||||
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||
};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Flow Control",
|
||||
.err = "reading default settings from EEPROM",
|
||||
.def = E1000_FC_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||
.p = fc_list }}
|
||||
};
|
||||
|
||||
if (num_FlowControl > bd) {
|
||||
unsigned int fc = FlowControl[bd];
|
||||
e1000_validate_option(&fc, &opt, adapter);
|
||||
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||
} else {
|
||||
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||
.def = DEFAULT_TIDV,
|
||||
.arg = { .r = { .min = MIN_TXDELAY,
|
||||
.max = MAX_TXDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxIntDelay > bd) {
|
||||
adapter->tx_int_delay = TxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||
.def = DEFAULT_TADV,
|
||||
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||
.max = MAX_TXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxAbsIntDelay > bd) {
|
||||
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||
.def = DEFAULT_RDTR,
|
||||
.arg = { .r = { .min = MIN_RXDELAY,
|
||||
.max = MAX_RXDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxIntDelay > bd) {
|
||||
adapter->rx_int_delay = RxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||
.def = DEFAULT_RADV,
|
||||
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||
.max = MAX_RXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxAbsIntDelay > bd) {
|
||||
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Interrupt Throttling Rate */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||
.def = DEFAULT_ITR,
|
||||
.arg = { .r = { .min = MIN_ITR,
|
||||
.max = MAX_ITR }}
|
||||
};
|
||||
|
||||
if (num_InterruptThrottleRate > bd) {
|
||||
adapter->itr = InterruptThrottleRate[bd];
|
||||
switch (adapter->itr) {
|
||||
case 0:
|
||||
e_dev_info("%s turned off\n", opt.name);
|
||||
break;
|
||||
case 1:
|
||||
e_dev_info("%s set to dynamic mode\n",
|
||||
opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 3:
|
||||
e_dev_info("%s set to dynamic conservative "
|
||||
"mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 4:
|
||||
e_dev_info("%s set to simplified "
|
||||
"(2000-8000) ints mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
break;
|
||||
default:
|
||||
e1000_validate_option(&adapter->itr, &opt,
|
||||
adapter);
|
||||
/* save the setting, because the dynamic bits
|
||||
* change itr.
|
||||
* clear the lower two bits because they are
|
||||
* used as control
|
||||
*/
|
||||
adapter->itr_setting = adapter->itr & ~3;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
adapter->itr_setting = opt.def;
|
||||
adapter->itr = 20000;
|
||||
}
|
||||
}
|
||||
{ /* Smart Power Down */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "PHY Smart Power Down",
|
||||
.err = "defaulting to Disabled",
|
||||
.def = OPTION_DISABLED
|
||||
};
|
||||
|
||||
if (num_SmartPowerDownEnable > bd) {
|
||||
unsigned int spd = SmartPowerDownEnable[bd];
|
||||
e1000_validate_option(&spd, &opt, adapter);
|
||||
adapter->smart_power_down = spd;
|
||||
} else {
|
||||
adapter->smart_power_down = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
switch (adapter->hw.media_type) {
|
||||
case e1000_media_type_fiber:
|
||||
case e1000_media_type_internal_serdes:
|
||||
e1000_check_fiber_options(adapter);
|
||||
break;
|
||||
case e1000_media_type_copper:
|
||||
e1000_check_copper_options(adapter);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on fiber adapters
|
||||
**/
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
int bd = adapter->bd_number;
|
||||
if (num_Speed > bd) {
|
||||
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||
"adapters, parameter ignored\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on copper adapters
|
||||
**/
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
unsigned int speed, dplx, an;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
{ /* Speed */
|
||||
static const struct e1000_opt_list speed_list[] = {
|
||||
{ 0, "" },
|
||||
{ SPEED_10, "" },
|
||||
{ SPEED_100, "" },
|
||||
{ SPEED_1000, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Speed",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||
.p = speed_list }}
|
||||
};
|
||||
|
||||
if (num_Speed > bd) {
|
||||
speed = Speed[bd];
|
||||
e1000_validate_option(&speed, &opt, adapter);
|
||||
} else {
|
||||
speed = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Duplex */
|
||||
static const struct e1000_opt_list dplx_list[] = {
|
||||
{ 0, "" },
|
||||
{ HALF_DUPLEX, "" },
|
||||
{ FULL_DUPLEX, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Duplex",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||
.p = dplx_list }}
|
||||
};
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
dplx = Duplex[bd];
|
||||
e1000_validate_option(&dplx, &opt, adapter);
|
||||
} else {
|
||||
dplx = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||
"parameter ignored\n");
|
||||
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||
} else { /* Autoneg */
|
||||
static const struct e1000_opt_list an_list[] =
|
||||
#define AA "AutoNeg advertising "
|
||||
{{ 0x01, AA "10/HD" },
|
||||
{ 0x02, AA "10/FD" },
|
||||
{ 0x03, AA "10/FD, 10/HD" },
|
||||
{ 0x04, AA "100/HD" },
|
||||
{ 0x05, AA "100/HD, 10/HD" },
|
||||
{ 0x06, AA "100/HD, 10/FD" },
|
||||
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||
{ 0x08, AA "100/FD" },
|
||||
{ 0x09, AA "100/FD, 10/HD" },
|
||||
{ 0x0a, AA "100/FD, 10/FD" },
|
||||
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||
{ 0x0c, AA "100/FD, 100/HD" },
|
||||
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x20, AA "1000/FD" },
|
||||
{ 0x21, AA "1000/FD, 10/HD" },
|
||||
{ 0x22, AA "1000/FD, 10/FD" },
|
||||
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||
{ 0x24, AA "1000/FD, 100/HD" },
|
||||
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x28, AA "1000/FD, 100/FD" },
|
||||
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "AutoNeg",
|
||||
.err = "parameter ignored",
|
||||
.def = AUTONEG_ADV_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||
.p = an_list }}
|
||||
};
|
||||
|
||||
if (num_AutoNeg > bd) {
|
||||
an = AutoNeg[bd];
|
||||
e1000_validate_option(&an, &opt, adapter);
|
||||
} else {
|
||||
an = opt.def;
|
||||
}
|
||||
adapter->hw.autoneg_advertised = an;
|
||||
}
|
||||
|
||||
switch (speed + dplx) {
|
||||
case 0:
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||
e_dev_info("Speed and duplex autonegotiation "
|
||||
"enabled\n");
|
||||
break;
|
||||
case HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_100_HALF;
|
||||
break;
|
||||
case FULL_DUPLEX:
|
||||
e_dev_info("Full Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||
ADVERTISE_100_FULL |
|
||||
ADVERTISE_1000_FULL;
|
||||
break;
|
||||
case SPEED_10:
|
||||
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_10_FULL;
|
||||
break;
|
||||
case SPEED_10 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_10 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100:
|
||||
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||
ADVERTISE_100_FULL;
|
||||
break;
|
||||
case SPEED_100 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||
goto full_duplex_only;
|
||||
case SPEED_1000 + HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||
fallthrough;
|
||||
case SPEED_1000 + FULL_DUPLEX:
|
||||
full_duplex_only:
|
||||
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||
"only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||
"Setting MDI-X to a compatible value.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,729 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
#include "e1000.h"
|
||||
|
||||
/* This is the only thing that needs to be changed to adjust the
|
||||
* maximum number of ports that the driver can manage.
|
||||
*/
|
||||
|
||||
#define E1000_MAX_NIC 32
|
||||
|
||||
#define OPTION_UNSET -1
|
||||
#define OPTION_DISABLED 0
|
||||
#define OPTION_ENABLED 1
|
||||
|
||||
/* All parameters are treated the same, as an integer array of values.
|
||||
* This macro just reduces the need to repeat the same declaration code
|
||||
* over and over (plus this helps to avoid typo bugs).
|
||||
*/
|
||||
|
||||
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||
#define E1000_PARAM(X, desc) \
|
||||
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||
static unsigned int num_##X; \
|
||||
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||
MODULE_PARM_DESC(X, desc);
|
||||
|
||||
/* Transmit Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||
|
||||
/* Receive Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||
|
||||
/* User Specified Speed Override
|
||||
*
|
||||
* Valid Range: 0, 10, 100, 1000
|
||||
* - 0 - auto-negotiate at all supported speeds
|
||||
* - 10 - only link at 10 Mbps
|
||||
* - 100 - only link at 100 Mbps
|
||||
* - 1000 - only link at 1000 Mbps
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Speed, "Speed setting");
|
||||
|
||||
/* User Specified Duplex Override
|
||||
*
|
||||
* Valid Range: 0-2
|
||||
* - 0 - auto-negotiate for duplex
|
||||
* - 1 - only link at half duplex
|
||||
* - 2 - only link at full duplex
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Duplex, "Duplex setting");
|
||||
|
||||
/* Auto-negotiation Advertisement Override
|
||||
*
|
||||
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||
*
|
||||
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||
* combinations should be advertised during auto-negotiation.
|
||||
* The supported speed and duplex modes are listed below
|
||||
*
|
||||
* Bit 7 6 5 4 3 2 1 0
|
||||
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||
* Duplex Full Full Half Full Half
|
||||
*
|
||||
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||
*/
|
||||
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||
#define AUTONEG_ADV_MASK 0x2F
|
||||
|
||||
/* User Specified Flow Control Override
|
||||
*
|
||||
* Valid Range: 0-3
|
||||
* - 0 - No Flow Control
|
||||
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||
* - 3 - Full Flow Control Support
|
||||
*
|
||||
* Default Value: Read flow control settings from the EEPROM
|
||||
*/
|
||||
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||
|
||||
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
* - 0 - disables all checksum offload
|
||||
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||
* on 82543 and newer -based NICs
|
||||
*
|
||||
* Default Value: 1
|
||||
*/
|
||||
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||
|
||||
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||
* Tx interrupt delay needs to typically be set to something non zero
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||
#define DEFAULT_TIDV 8
|
||||
#define MAX_TXDELAY 0xFFFF
|
||||
#define MIN_TXDELAY 0
|
||||
|
||||
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||
#define DEFAULT_TADV 32
|
||||
#define MAX_TXABSDELAY 0xFFFF
|
||||
#define MIN_TXABSDELAY 0
|
||||
|
||||
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||
* hardware will likely hang if you set this to anything but zero.
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||
#define DEFAULT_RDTR 0
|
||||
#define MAX_RXDELAY 0xFFFF
|
||||
#define MIN_RXDELAY 0
|
||||
|
||||
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||
#define DEFAULT_RADV 8
|
||||
#define MAX_RXABSDELAY 0xFFFF
|
||||
#define MIN_RXABSDELAY 0
|
||||
|
||||
/* Interrupt Throttle Rate (interrupts/sec)
|
||||
*
|
||||
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||
*/
|
||||
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||
#define DEFAULT_ITR 3
|
||||
#define MAX_ITR 100000
|
||||
#define MIN_ITR 100
|
||||
|
||||
/* Enable Smart Power Down of the PHY
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
*
|
||||
* Default Value: 0 (disabled)
|
||||
*/
|
||||
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||
|
||||
struct e1000_option {
|
||||
enum { enable_option, range_option, list_option } type;
|
||||
const char *name;
|
||||
const char *err;
|
||||
int def;
|
||||
union {
|
||||
struct { /* range_option info */
|
||||
int min;
|
||||
int max;
|
||||
} r;
|
||||
struct { /* list_option info */
|
||||
int nr;
|
||||
const struct e1000_opt_list { int i; char *str; } *p;
|
||||
} l;
|
||||
} arg;
|
||||
};
|
||||
|
||||
static int e1000_validate_option(unsigned int *value,
|
||||
const struct e1000_option *opt,
|
||||
struct e1000_adapter *adapter)
|
||||
{
|
||||
if (*value == OPTION_UNSET) {
|
||||
*value = opt->def;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (opt->type) {
|
||||
case enable_option:
|
||||
switch (*value) {
|
||||
case OPTION_ENABLED:
|
||||
e_dev_info("%s Enabled\n", opt->name);
|
||||
return 0;
|
||||
case OPTION_DISABLED:
|
||||
e_dev_info("%s Disabled\n", opt->name);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case range_option:
|
||||
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case list_option: {
|
||||
int i;
|
||||
const struct e1000_opt_list *ent;
|
||||
|
||||
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||
ent = &opt->arg.l.p[i];
|
||||
if (*value == ent->i) {
|
||||
if (ent->str[0] != '\0')
|
||||
e_dev_info("%s\n", ent->str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||
opt->name, *value, opt->err);
|
||||
*value = opt->def;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||
|
||||
/**
|
||||
* e1000_check_options - Range Checking for Command Line Parameters
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* This routine checks all command line parameters for valid user
|
||||
* input. If an invalid value is given, or if no user specified
|
||||
* value exists, a default value is used. The final value is stored
|
||||
* in a variable in the adapter structure.
|
||||
**/
|
||||
void e1000_check_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
if (bd >= E1000_MAX_NIC) {
|
||||
e_dev_warn("Warning: no configuration for board #%i "
|
||||
"using defaults for all values\n", bd);
|
||||
}
|
||||
|
||||
{ /* Transmit Descriptor Count */
|
||||
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||
.def = E1000_DEFAULT_TXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_TXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_TxDescriptors > bd) {
|
||||
tx_ring->count = TxDescriptors[bd];
|
||||
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||
tx_ring->count = ALIGN(tx_ring->count,
|
||||
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
tx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||
tx_ring[i].count = tx_ring->count;
|
||||
}
|
||||
{ /* Receive Descriptor Count */
|
||||
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||
.def = E1000_DEFAULT_RXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_RXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||
E1000_MAX_82544_RXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_RxDescriptors > bd) {
|
||||
rx_ring->count = RxDescriptors[bd];
|
||||
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||
rx_ring->count = ALIGN(rx_ring->count,
|
||||
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
rx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||
rx_ring[i].count = rx_ring->count;
|
||||
}
|
||||
{ /* Checksum Offload Enable/Disable */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "Checksum Offload",
|
||||
.err = "defaulting to Enabled",
|
||||
.def = OPTION_ENABLED
|
||||
};
|
||||
|
||||
if (num_XsumRX > bd) {
|
||||
unsigned int rx_csum = XsumRX[bd];
|
||||
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||
adapter->rx_csum = rx_csum;
|
||||
} else {
|
||||
adapter->rx_csum = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Flow Control */
|
||||
|
||||
static const struct e1000_opt_list fc_list[] = {
|
||||
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||
};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Flow Control",
|
||||
.err = "reading default settings from EEPROM",
|
||||
.def = E1000_FC_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||
.p = fc_list }}
|
||||
};
|
||||
|
||||
if (num_FlowControl > bd) {
|
||||
unsigned int fc = FlowControl[bd];
|
||||
e1000_validate_option(&fc, &opt, adapter);
|
||||
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||
} else {
|
||||
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||
.def = DEFAULT_TIDV,
|
||||
.arg = { .r = { .min = MIN_TXDELAY,
|
||||
.max = MAX_TXDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxIntDelay > bd) {
|
||||
adapter->tx_int_delay = TxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||
.def = DEFAULT_TADV,
|
||||
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||
.max = MAX_TXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxAbsIntDelay > bd) {
|
||||
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||
.def = DEFAULT_RDTR,
|
||||
.arg = { .r = { .min = MIN_RXDELAY,
|
||||
.max = MAX_RXDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxIntDelay > bd) {
|
||||
adapter->rx_int_delay = RxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||
.def = DEFAULT_RADV,
|
||||
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||
.max = MAX_RXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxAbsIntDelay > bd) {
|
||||
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Interrupt Throttling Rate */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||
.def = DEFAULT_ITR,
|
||||
.arg = { .r = { .min = MIN_ITR,
|
||||
.max = MAX_ITR }}
|
||||
};
|
||||
|
||||
if (num_InterruptThrottleRate > bd) {
|
||||
adapter->itr = InterruptThrottleRate[bd];
|
||||
switch (adapter->itr) {
|
||||
case 0:
|
||||
e_dev_info("%s turned off\n", opt.name);
|
||||
break;
|
||||
case 1:
|
||||
e_dev_info("%s set to dynamic mode\n",
|
||||
opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 3:
|
||||
e_dev_info("%s set to dynamic conservative "
|
||||
"mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 4:
|
||||
e_dev_info("%s set to simplified "
|
||||
"(2000-8000) ints mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
break;
|
||||
default:
|
||||
e1000_validate_option(&adapter->itr, &opt,
|
||||
adapter);
|
||||
/* save the setting, because the dynamic bits
|
||||
* change itr.
|
||||
* clear the lower two bits because they are
|
||||
* used as control
|
||||
*/
|
||||
adapter->itr_setting = adapter->itr & ~3;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
adapter->itr_setting = opt.def;
|
||||
adapter->itr = 20000;
|
||||
}
|
||||
}
|
||||
{ /* Smart Power Down */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "PHY Smart Power Down",
|
||||
.err = "defaulting to Disabled",
|
||||
.def = OPTION_DISABLED
|
||||
};
|
||||
|
||||
if (num_SmartPowerDownEnable > bd) {
|
||||
unsigned int spd = SmartPowerDownEnable[bd];
|
||||
e1000_validate_option(&spd, &opt, adapter);
|
||||
adapter->smart_power_down = spd;
|
||||
} else {
|
||||
adapter->smart_power_down = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
switch (adapter->hw.media_type) {
|
||||
case e1000_media_type_fiber:
|
||||
case e1000_media_type_internal_serdes:
|
||||
e1000_check_fiber_options(adapter);
|
||||
break;
|
||||
case e1000_media_type_copper:
|
||||
e1000_check_copper_options(adapter);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on fiber adapters
|
||||
**/
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
int bd = adapter->bd_number;
|
||||
if (num_Speed > bd) {
|
||||
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||
"adapters, parameter ignored\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on copper adapters
|
||||
**/
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
unsigned int speed, dplx, an;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
{ /* Speed */
|
||||
static const struct e1000_opt_list speed_list[] = {
|
||||
{ 0, "" },
|
||||
{ SPEED_10, "" },
|
||||
{ SPEED_100, "" },
|
||||
{ SPEED_1000, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Speed",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||
.p = speed_list }}
|
||||
};
|
||||
|
||||
if (num_Speed > bd) {
|
||||
speed = Speed[bd];
|
||||
e1000_validate_option(&speed, &opt, adapter);
|
||||
} else {
|
||||
speed = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Duplex */
|
||||
static const struct e1000_opt_list dplx_list[] = {
|
||||
{ 0, "" },
|
||||
{ HALF_DUPLEX, "" },
|
||||
{ FULL_DUPLEX, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Duplex",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||
.p = dplx_list }}
|
||||
};
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
dplx = Duplex[bd];
|
||||
e1000_validate_option(&dplx, &opt, adapter);
|
||||
} else {
|
||||
dplx = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||
"parameter ignored\n");
|
||||
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||
} else { /* Autoneg */
|
||||
static const struct e1000_opt_list an_list[] =
|
||||
#define AA "AutoNeg advertising "
|
||||
{{ 0x01, AA "10/HD" },
|
||||
{ 0x02, AA "10/FD" },
|
||||
{ 0x03, AA "10/FD, 10/HD" },
|
||||
{ 0x04, AA "100/HD" },
|
||||
{ 0x05, AA "100/HD, 10/HD" },
|
||||
{ 0x06, AA "100/HD, 10/FD" },
|
||||
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||
{ 0x08, AA "100/FD" },
|
||||
{ 0x09, AA "100/FD, 10/HD" },
|
||||
{ 0x0a, AA "100/FD, 10/FD" },
|
||||
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||
{ 0x0c, AA "100/FD, 100/HD" },
|
||||
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x20, AA "1000/FD" },
|
||||
{ 0x21, AA "1000/FD, 10/HD" },
|
||||
{ 0x22, AA "1000/FD, 10/FD" },
|
||||
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||
{ 0x24, AA "1000/FD, 100/HD" },
|
||||
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x28, AA "1000/FD, 100/FD" },
|
||||
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "AutoNeg",
|
||||
.err = "parameter ignored",
|
||||
.def = AUTONEG_ADV_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||
.p = an_list }}
|
||||
};
|
||||
|
||||
if (num_AutoNeg > bd) {
|
||||
an = AutoNeg[bd];
|
||||
e1000_validate_option(&an, &opt, adapter);
|
||||
} else {
|
||||
an = opt.def;
|
||||
}
|
||||
adapter->hw.autoneg_advertised = an;
|
||||
}
|
||||
|
||||
switch (speed + dplx) {
|
||||
case 0:
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||
e_dev_info("Speed and duplex autonegotiation "
|
||||
"enabled\n");
|
||||
break;
|
||||
case HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_100_HALF;
|
||||
break;
|
||||
case FULL_DUPLEX:
|
||||
e_dev_info("Full Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||
ADVERTISE_100_FULL |
|
||||
ADVERTISE_1000_FULL;
|
||||
break;
|
||||
case SPEED_10:
|
||||
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_10_FULL;
|
||||
break;
|
||||
case SPEED_10 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_10 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100:
|
||||
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||
ADVERTISE_100_FULL;
|
||||
break;
|
||||
case SPEED_100 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||
goto full_duplex_only;
|
||||
case SPEED_1000 + HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||
fallthrough;
|
||||
case SPEED_1000 + FULL_DUPLEX:
|
||||
full_duplex_only:
|
||||
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||
"only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||
"Setting MDI-X to a compatible value.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,729 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
#include "e1000-5.15-ethercat.h"
|
||||
|
||||
/* This is the only thing that needs to be changed to adjust the
|
||||
* maximum number of ports that the driver can manage.
|
||||
*/
|
||||
|
||||
#define E1000_MAX_NIC 32
|
||||
|
||||
#define OPTION_UNSET -1
|
||||
#define OPTION_DISABLED 0
|
||||
#define OPTION_ENABLED 1
|
||||
|
||||
/* All parameters are treated the same, as an integer array of values.
|
||||
* This macro just reduces the need to repeat the same declaration code
|
||||
* over and over (plus this helps to avoid typo bugs).
|
||||
*/
|
||||
|
||||
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||
#define E1000_PARAM(X, desc) \
|
||||
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||
static unsigned int num_##X; \
|
||||
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||
MODULE_PARM_DESC(X, desc);
|
||||
|
||||
/* Transmit Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||
|
||||
/* Receive Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||
|
||||
/* User Specified Speed Override
|
||||
*
|
||||
* Valid Range: 0, 10, 100, 1000
|
||||
* - 0 - auto-negotiate at all supported speeds
|
||||
* - 10 - only link at 10 Mbps
|
||||
* - 100 - only link at 100 Mbps
|
||||
* - 1000 - only link at 1000 Mbps
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Speed, "Speed setting");
|
||||
|
||||
/* User Specified Duplex Override
|
||||
*
|
||||
* Valid Range: 0-2
|
||||
* - 0 - auto-negotiate for duplex
|
||||
* - 1 - only link at half duplex
|
||||
* - 2 - only link at full duplex
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Duplex, "Duplex setting");
|
||||
|
||||
/* Auto-negotiation Advertisement Override
|
||||
*
|
||||
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||
*
|
||||
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||
* combinations should be advertised during auto-negotiation.
|
||||
* The supported speed and duplex modes are listed below
|
||||
*
|
||||
* Bit 7 6 5 4 3 2 1 0
|
||||
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||
* Duplex Full Full Half Full Half
|
||||
*
|
||||
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||
*/
|
||||
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||
#define AUTONEG_ADV_MASK 0x2F
|
||||
|
||||
/* User Specified Flow Control Override
|
||||
*
|
||||
* Valid Range: 0-3
|
||||
* - 0 - No Flow Control
|
||||
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||
* - 3 - Full Flow Control Support
|
||||
*
|
||||
* Default Value: Read flow control settings from the EEPROM
|
||||
*/
|
||||
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||
|
||||
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
* - 0 - disables all checksum offload
|
||||
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||
* on 82543 and newer -based NICs
|
||||
*
|
||||
* Default Value: 1
|
||||
*/
|
||||
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||
|
||||
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||
* Tx interrupt delay needs to typically be set to something non zero
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||
#define DEFAULT_TIDV 8
|
||||
#define MAX_TXDELAY 0xFFFF
|
||||
#define MIN_TXDELAY 0
|
||||
|
||||
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||
#define DEFAULT_TADV 32
|
||||
#define MAX_TXABSDELAY 0xFFFF
|
||||
#define MIN_TXABSDELAY 0
|
||||
|
||||
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||
* hardware will likely hang if you set this to anything but zero.
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||
#define DEFAULT_RDTR 0
|
||||
#define MAX_RXDELAY 0xFFFF
|
||||
#define MIN_RXDELAY 0
|
||||
|
||||
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||
#define DEFAULT_RADV 8
|
||||
#define MAX_RXABSDELAY 0xFFFF
|
||||
#define MIN_RXABSDELAY 0
|
||||
|
||||
/* Interrupt Throttle Rate (interrupts/sec)
|
||||
*
|
||||
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||
*/
|
||||
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||
#define DEFAULT_ITR 3
|
||||
#define MAX_ITR 100000
|
||||
#define MIN_ITR 100
|
||||
|
||||
/* Enable Smart Power Down of the PHY
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
*
|
||||
* Default Value: 0 (disabled)
|
||||
*/
|
||||
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||
|
||||
struct e1000_option {
|
||||
enum { enable_option, range_option, list_option } type;
|
||||
const char *name;
|
||||
const char *err;
|
||||
int def;
|
||||
union {
|
||||
struct { /* range_option info */
|
||||
int min;
|
||||
int max;
|
||||
} r;
|
||||
struct { /* list_option info */
|
||||
int nr;
|
||||
const struct e1000_opt_list { int i; char *str; } *p;
|
||||
} l;
|
||||
} arg;
|
||||
};
|
||||
|
||||
static int e1000_validate_option(unsigned int *value,
|
||||
const struct e1000_option *opt,
|
||||
struct e1000_adapter *adapter)
|
||||
{
|
||||
if (*value == OPTION_UNSET) {
|
||||
*value = opt->def;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (opt->type) {
|
||||
case enable_option:
|
||||
switch (*value) {
|
||||
case OPTION_ENABLED:
|
||||
e_dev_info("%s Enabled\n", opt->name);
|
||||
return 0;
|
||||
case OPTION_DISABLED:
|
||||
e_dev_info("%s Disabled\n", opt->name);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case range_option:
|
||||
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case list_option: {
|
||||
int i;
|
||||
const struct e1000_opt_list *ent;
|
||||
|
||||
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||
ent = &opt->arg.l.p[i];
|
||||
if (*value == ent->i) {
|
||||
if (ent->str[0] != '\0')
|
||||
e_dev_info("%s\n", ent->str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||
opt->name, *value, opt->err);
|
||||
*value = opt->def;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||
|
||||
/**
|
||||
* e1000_check_options - Range Checking for Command Line Parameters
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* This routine checks all command line parameters for valid user
|
||||
* input. If an invalid value is given, or if no user specified
|
||||
* value exists, a default value is used. The final value is stored
|
||||
* in a variable in the adapter structure.
|
||||
**/
|
||||
void e1000_check_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
if (bd >= E1000_MAX_NIC) {
|
||||
e_dev_warn("Warning: no configuration for board #%i "
|
||||
"using defaults for all values\n", bd);
|
||||
}
|
||||
|
||||
{ /* Transmit Descriptor Count */
|
||||
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||
.def = E1000_DEFAULT_TXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_TXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_TxDescriptors > bd) {
|
||||
tx_ring->count = TxDescriptors[bd];
|
||||
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||
tx_ring->count = ALIGN(tx_ring->count,
|
||||
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
tx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||
tx_ring[i].count = tx_ring->count;
|
||||
}
|
||||
{ /* Receive Descriptor Count */
|
||||
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||
.def = E1000_DEFAULT_RXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_RXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||
E1000_MAX_82544_RXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_RxDescriptors > bd) {
|
||||
rx_ring->count = RxDescriptors[bd];
|
||||
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||
rx_ring->count = ALIGN(rx_ring->count,
|
||||
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
rx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||
rx_ring[i].count = rx_ring->count;
|
||||
}
|
||||
{ /* Checksum Offload Enable/Disable */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "Checksum Offload",
|
||||
.err = "defaulting to Enabled",
|
||||
.def = OPTION_ENABLED
|
||||
};
|
||||
|
||||
if (num_XsumRX > bd) {
|
||||
unsigned int rx_csum = XsumRX[bd];
|
||||
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||
adapter->rx_csum = rx_csum;
|
||||
} else {
|
||||
adapter->rx_csum = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Flow Control */
|
||||
|
||||
static const struct e1000_opt_list fc_list[] = {
|
||||
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||
};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Flow Control",
|
||||
.err = "reading default settings from EEPROM",
|
||||
.def = E1000_FC_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||
.p = fc_list }}
|
||||
};
|
||||
|
||||
if (num_FlowControl > bd) {
|
||||
unsigned int fc = FlowControl[bd];
|
||||
e1000_validate_option(&fc, &opt, adapter);
|
||||
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||
} else {
|
||||
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||
.def = DEFAULT_TIDV,
|
||||
.arg = { .r = { .min = MIN_TXDELAY,
|
||||
.max = MAX_TXDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxIntDelay > bd) {
|
||||
adapter->tx_int_delay = TxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||
.def = DEFAULT_TADV,
|
||||
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||
.max = MAX_TXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxAbsIntDelay > bd) {
|
||||
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||
.def = DEFAULT_RDTR,
|
||||
.arg = { .r = { .min = MIN_RXDELAY,
|
||||
.max = MAX_RXDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxIntDelay > bd) {
|
||||
adapter->rx_int_delay = RxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||
.def = DEFAULT_RADV,
|
||||
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||
.max = MAX_RXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxAbsIntDelay > bd) {
|
||||
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Interrupt Throttling Rate */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||
.def = DEFAULT_ITR,
|
||||
.arg = { .r = { .min = MIN_ITR,
|
||||
.max = MAX_ITR }}
|
||||
};
|
||||
|
||||
if (num_InterruptThrottleRate > bd) {
|
||||
adapter->itr = InterruptThrottleRate[bd];
|
||||
switch (adapter->itr) {
|
||||
case 0:
|
||||
e_dev_info("%s turned off\n", opt.name);
|
||||
break;
|
||||
case 1:
|
||||
e_dev_info("%s set to dynamic mode\n",
|
||||
opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 3:
|
||||
e_dev_info("%s set to dynamic conservative "
|
||||
"mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 4:
|
||||
e_dev_info("%s set to simplified "
|
||||
"(2000-8000) ints mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
break;
|
||||
default:
|
||||
e1000_validate_option(&adapter->itr, &opt,
|
||||
adapter);
|
||||
/* save the setting, because the dynamic bits
|
||||
* change itr.
|
||||
* clear the lower two bits because they are
|
||||
* used as control
|
||||
*/
|
||||
adapter->itr_setting = adapter->itr & ~3;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
adapter->itr_setting = opt.def;
|
||||
adapter->itr = 20000;
|
||||
}
|
||||
}
|
||||
{ /* Smart Power Down */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "PHY Smart Power Down",
|
||||
.err = "defaulting to Disabled",
|
||||
.def = OPTION_DISABLED
|
||||
};
|
||||
|
||||
if (num_SmartPowerDownEnable > bd) {
|
||||
unsigned int spd = SmartPowerDownEnable[bd];
|
||||
e1000_validate_option(&spd, &opt, adapter);
|
||||
adapter->smart_power_down = spd;
|
||||
} else {
|
||||
adapter->smart_power_down = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
switch (adapter->hw.media_type) {
|
||||
case e1000_media_type_fiber:
|
||||
case e1000_media_type_internal_serdes:
|
||||
e1000_check_fiber_options(adapter);
|
||||
break;
|
||||
case e1000_media_type_copper:
|
||||
e1000_check_copper_options(adapter);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on fiber adapters
|
||||
**/
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
int bd = adapter->bd_number;
|
||||
if (num_Speed > bd) {
|
||||
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||
"adapters, parameter ignored\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on copper adapters
|
||||
**/
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
unsigned int speed, dplx, an;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
{ /* Speed */
|
||||
static const struct e1000_opt_list speed_list[] = {
|
||||
{ 0, "" },
|
||||
{ SPEED_10, "" },
|
||||
{ SPEED_100, "" },
|
||||
{ SPEED_1000, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Speed",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||
.p = speed_list }}
|
||||
};
|
||||
|
||||
if (num_Speed > bd) {
|
||||
speed = Speed[bd];
|
||||
e1000_validate_option(&speed, &opt, adapter);
|
||||
} else {
|
||||
speed = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Duplex */
|
||||
static const struct e1000_opt_list dplx_list[] = {
|
||||
{ 0, "" },
|
||||
{ HALF_DUPLEX, "" },
|
||||
{ FULL_DUPLEX, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Duplex",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||
.p = dplx_list }}
|
||||
};
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
dplx = Duplex[bd];
|
||||
e1000_validate_option(&dplx, &opt, adapter);
|
||||
} else {
|
||||
dplx = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||
"parameter ignored\n");
|
||||
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||
} else { /* Autoneg */
|
||||
static const struct e1000_opt_list an_list[] =
|
||||
#define AA "AutoNeg advertising "
|
||||
{{ 0x01, AA "10/HD" },
|
||||
{ 0x02, AA "10/FD" },
|
||||
{ 0x03, AA "10/FD, 10/HD" },
|
||||
{ 0x04, AA "100/HD" },
|
||||
{ 0x05, AA "100/HD, 10/HD" },
|
||||
{ 0x06, AA "100/HD, 10/FD" },
|
||||
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||
{ 0x08, AA "100/FD" },
|
||||
{ 0x09, AA "100/FD, 10/HD" },
|
||||
{ 0x0a, AA "100/FD, 10/FD" },
|
||||
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||
{ 0x0c, AA "100/FD, 100/HD" },
|
||||
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x20, AA "1000/FD" },
|
||||
{ 0x21, AA "1000/FD, 10/HD" },
|
||||
{ 0x22, AA "1000/FD, 10/FD" },
|
||||
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||
{ 0x24, AA "1000/FD, 100/HD" },
|
||||
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x28, AA "1000/FD, 100/FD" },
|
||||
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "AutoNeg",
|
||||
.err = "parameter ignored",
|
||||
.def = AUTONEG_ADV_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||
.p = an_list }}
|
||||
};
|
||||
|
||||
if (num_AutoNeg > bd) {
|
||||
an = AutoNeg[bd];
|
||||
e1000_validate_option(&an, &opt, adapter);
|
||||
} else {
|
||||
an = opt.def;
|
||||
}
|
||||
adapter->hw.autoneg_advertised = an;
|
||||
}
|
||||
|
||||
switch (speed + dplx) {
|
||||
case 0:
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||
e_dev_info("Speed and duplex autonegotiation "
|
||||
"enabled\n");
|
||||
break;
|
||||
case HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_100_HALF;
|
||||
break;
|
||||
case FULL_DUPLEX:
|
||||
e_dev_info("Full Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||
ADVERTISE_100_FULL |
|
||||
ADVERTISE_1000_FULL;
|
||||
break;
|
||||
case SPEED_10:
|
||||
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_10_FULL;
|
||||
break;
|
||||
case SPEED_10 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_10 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100:
|
||||
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||
ADVERTISE_100_FULL;
|
||||
break;
|
||||
case SPEED_100 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||
goto full_duplex_only;
|
||||
case SPEED_1000 + HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||
fallthrough;
|
||||
case SPEED_1000 + FULL_DUPLEX:
|
||||
full_duplex_only:
|
||||
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||
"only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||
"Setting MDI-X to a compatible value.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,729 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
#include "e1000.h"
|
||||
|
||||
/* This is the only thing that needs to be changed to adjust the
|
||||
* maximum number of ports that the driver can manage.
|
||||
*/
|
||||
|
||||
#define E1000_MAX_NIC 32
|
||||
|
||||
#define OPTION_UNSET -1
|
||||
#define OPTION_DISABLED 0
|
||||
#define OPTION_ENABLED 1
|
||||
|
||||
/* All parameters are treated the same, as an integer array of values.
|
||||
* This macro just reduces the need to repeat the same declaration code
|
||||
* over and over (plus this helps to avoid typo bugs).
|
||||
*/
|
||||
|
||||
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||
#define E1000_PARAM(X, desc) \
|
||||
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||
static unsigned int num_##X; \
|
||||
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||
MODULE_PARM_DESC(X, desc);
|
||||
|
||||
/* Transmit Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||
|
||||
/* Receive Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||
|
||||
/* User Specified Speed Override
|
||||
*
|
||||
* Valid Range: 0, 10, 100, 1000
|
||||
* - 0 - auto-negotiate at all supported speeds
|
||||
* - 10 - only link at 10 Mbps
|
||||
* - 100 - only link at 100 Mbps
|
||||
* - 1000 - only link at 1000 Mbps
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Speed, "Speed setting");
|
||||
|
||||
/* User Specified Duplex Override
|
||||
*
|
||||
* Valid Range: 0-2
|
||||
* - 0 - auto-negotiate for duplex
|
||||
* - 1 - only link at half duplex
|
||||
* - 2 - only link at full duplex
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Duplex, "Duplex setting");
|
||||
|
||||
/* Auto-negotiation Advertisement Override
|
||||
*
|
||||
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||
*
|
||||
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||
* combinations should be advertised during auto-negotiation.
|
||||
* The supported speed and duplex modes are listed below
|
||||
*
|
||||
* Bit 7 6 5 4 3 2 1 0
|
||||
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||
* Duplex Full Full Half Full Half
|
||||
*
|
||||
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||
*/
|
||||
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||
#define AUTONEG_ADV_MASK 0x2F
|
||||
|
||||
/* User Specified Flow Control Override
|
||||
*
|
||||
* Valid Range: 0-3
|
||||
* - 0 - No Flow Control
|
||||
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||
* - 3 - Full Flow Control Support
|
||||
*
|
||||
* Default Value: Read flow control settings from the EEPROM
|
||||
*/
|
||||
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||
#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL
|
||||
|
||||
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
* - 0 - disables all checksum offload
|
||||
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||
* on 82543 and newer -based NICs
|
||||
*
|
||||
* Default Value: 1
|
||||
*/
|
||||
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||
|
||||
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||
* Tx interrupt delay needs to typically be set to something non zero
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||
#define DEFAULT_TIDV 8
|
||||
#define MAX_TXDELAY 0xFFFF
|
||||
#define MIN_TXDELAY 0
|
||||
|
||||
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||
#define DEFAULT_TADV 32
|
||||
#define MAX_TXABSDELAY 0xFFFF
|
||||
#define MIN_TXABSDELAY 0
|
||||
|
||||
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||
* hardware will likely hang if you set this to anything but zero.
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||
#define DEFAULT_RDTR 0
|
||||
#define MAX_RXDELAY 0xFFFF
|
||||
#define MIN_RXDELAY 0
|
||||
|
||||
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||
#define DEFAULT_RADV 8
|
||||
#define MAX_RXABSDELAY 0xFFFF
|
||||
#define MIN_RXABSDELAY 0
|
||||
|
||||
/* Interrupt Throttle Rate (interrupts/sec)
|
||||
*
|
||||
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||
*/
|
||||
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||
#define DEFAULT_ITR 3
|
||||
#define MAX_ITR 100000
|
||||
#define MIN_ITR 100
|
||||
|
||||
/* Enable Smart Power Down of the PHY
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
*
|
||||
* Default Value: 0 (disabled)
|
||||
*/
|
||||
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||
|
||||
struct e1000_option {
|
||||
enum { enable_option, range_option, list_option } type;
|
||||
const char *name;
|
||||
const char *err;
|
||||
int def;
|
||||
union {
|
||||
struct { /* range_option info */
|
||||
int min;
|
||||
int max;
|
||||
} r;
|
||||
struct { /* list_option info */
|
||||
int nr;
|
||||
const struct e1000_opt_list { int i; char *str; } *p;
|
||||
} l;
|
||||
} arg;
|
||||
};
|
||||
|
||||
static int e1000_validate_option(unsigned int *value,
|
||||
const struct e1000_option *opt,
|
||||
struct e1000_adapter *adapter)
|
||||
{
|
||||
if (*value == OPTION_UNSET) {
|
||||
*value = opt->def;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (opt->type) {
|
||||
case enable_option:
|
||||
switch (*value) {
|
||||
case OPTION_ENABLED:
|
||||
e_dev_info("%s Enabled\n", opt->name);
|
||||
return 0;
|
||||
case OPTION_DISABLED:
|
||||
e_dev_info("%s Disabled\n", opt->name);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case range_option:
|
||||
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case list_option: {
|
||||
int i;
|
||||
const struct e1000_opt_list *ent;
|
||||
|
||||
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||
ent = &opt->arg.l.p[i];
|
||||
if (*value == ent->i) {
|
||||
if (ent->str[0] != '\0')
|
||||
e_dev_info("%s\n", ent->str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||
opt->name, *value, opt->err);
|
||||
*value = opt->def;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||
|
||||
/**
|
||||
* e1000_check_options - Range Checking for Command Line Parameters
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* This routine checks all command line parameters for valid user
|
||||
* input. If an invalid value is given, or if no user specified
|
||||
* value exists, a default value is used. The final value is stored
|
||||
* in a variable in the adapter structure.
|
||||
**/
|
||||
void e1000_check_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
if (bd >= E1000_MAX_NIC) {
|
||||
e_dev_warn("Warning: no configuration for board #%i "
|
||||
"using defaults for all values\n", bd);
|
||||
}
|
||||
|
||||
{ /* Transmit Descriptor Count */
|
||||
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||
.def = E1000_DEFAULT_TXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_TXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_TxDescriptors > bd) {
|
||||
tx_ring->count = TxDescriptors[bd];
|
||||
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||
tx_ring->count = ALIGN(tx_ring->count,
|
||||
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
tx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||
tx_ring[i].count = tx_ring->count;
|
||||
}
|
||||
{ /* Receive Descriptor Count */
|
||||
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||
.def = E1000_DEFAULT_RXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_RXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||
E1000_MAX_82544_RXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_RxDescriptors > bd) {
|
||||
rx_ring->count = RxDescriptors[bd];
|
||||
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||
rx_ring->count = ALIGN(rx_ring->count,
|
||||
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
rx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||
rx_ring[i].count = rx_ring->count;
|
||||
}
|
||||
{ /* Checksum Offload Enable/Disable */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "Checksum Offload",
|
||||
.err = "defaulting to Enabled",
|
||||
.def = OPTION_ENABLED
|
||||
};
|
||||
|
||||
if (num_XsumRX > bd) {
|
||||
unsigned int rx_csum = XsumRX[bd];
|
||||
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||
adapter->rx_csum = rx_csum;
|
||||
} else {
|
||||
adapter->rx_csum = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Flow Control */
|
||||
|
||||
static const struct e1000_opt_list fc_list[] = {
|
||||
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||
};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Flow Control",
|
||||
.err = "reading default settings from EEPROM",
|
||||
.def = E1000_FC_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||
.p = fc_list }}
|
||||
};
|
||||
|
||||
if (num_FlowControl > bd) {
|
||||
unsigned int fc = FlowControl[bd];
|
||||
e1000_validate_option(&fc, &opt, adapter);
|
||||
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||
} else {
|
||||
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||
.def = DEFAULT_TIDV,
|
||||
.arg = { .r = { .min = MIN_TXDELAY,
|
||||
.max = MAX_TXDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxIntDelay > bd) {
|
||||
adapter->tx_int_delay = TxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||
.def = DEFAULT_TADV,
|
||||
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||
.max = MAX_TXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxAbsIntDelay > bd) {
|
||||
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||
.def = DEFAULT_RDTR,
|
||||
.arg = { .r = { .min = MIN_RXDELAY,
|
||||
.max = MAX_RXDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxIntDelay > bd) {
|
||||
adapter->rx_int_delay = RxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||
.def = DEFAULT_RADV,
|
||||
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||
.max = MAX_RXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxAbsIntDelay > bd) {
|
||||
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Interrupt Throttling Rate */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||
.def = DEFAULT_ITR,
|
||||
.arg = { .r = { .min = MIN_ITR,
|
||||
.max = MAX_ITR }}
|
||||
};
|
||||
|
||||
if (num_InterruptThrottleRate > bd) {
|
||||
adapter->itr = InterruptThrottleRate[bd];
|
||||
switch (adapter->itr) {
|
||||
case 0:
|
||||
e_dev_info("%s turned off\n", opt.name);
|
||||
break;
|
||||
case 1:
|
||||
e_dev_info("%s set to dynamic mode\n",
|
||||
opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 3:
|
||||
e_dev_info("%s set to dynamic conservative "
|
||||
"mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 4:
|
||||
e_dev_info("%s set to simplified "
|
||||
"(2000-8000) ints mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
break;
|
||||
default:
|
||||
e1000_validate_option(&adapter->itr, &opt,
|
||||
adapter);
|
||||
/* save the setting, because the dynamic bits
|
||||
* change itr.
|
||||
* clear the lower two bits because they are
|
||||
* used as control
|
||||
*/
|
||||
adapter->itr_setting = adapter->itr & ~3;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
adapter->itr_setting = opt.def;
|
||||
adapter->itr = 20000;
|
||||
}
|
||||
}
|
||||
{ /* Smart Power Down */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "PHY Smart Power Down",
|
||||
.err = "defaulting to Disabled",
|
||||
.def = OPTION_DISABLED
|
||||
};
|
||||
|
||||
if (num_SmartPowerDownEnable > bd) {
|
||||
unsigned int spd = SmartPowerDownEnable[bd];
|
||||
e1000_validate_option(&spd, &opt, adapter);
|
||||
adapter->smart_power_down = spd;
|
||||
} else {
|
||||
adapter->smart_power_down = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
switch (adapter->hw.media_type) {
|
||||
case e1000_media_type_fiber:
|
||||
case e1000_media_type_internal_serdes:
|
||||
e1000_check_fiber_options(adapter);
|
||||
break;
|
||||
case e1000_media_type_copper:
|
||||
e1000_check_copper_options(adapter);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on fiber adapters
|
||||
**/
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
int bd = adapter->bd_number;
|
||||
if (num_Speed > bd) {
|
||||
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||
"adapters, parameter ignored\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on copper adapters
|
||||
**/
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
unsigned int speed, dplx, an;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
{ /* Speed */
|
||||
static const struct e1000_opt_list speed_list[] = {
|
||||
{ 0, "" },
|
||||
{ SPEED_10, "" },
|
||||
{ SPEED_100, "" },
|
||||
{ SPEED_1000, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Speed",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||
.p = speed_list }}
|
||||
};
|
||||
|
||||
if (num_Speed > bd) {
|
||||
speed = Speed[bd];
|
||||
e1000_validate_option(&speed, &opt, adapter);
|
||||
} else {
|
||||
speed = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Duplex */
|
||||
static const struct e1000_opt_list dplx_list[] = {
|
||||
{ 0, "" },
|
||||
{ HALF_DUPLEX, "" },
|
||||
{ FULL_DUPLEX, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Duplex",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||
.p = dplx_list }}
|
||||
};
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
dplx = Duplex[bd];
|
||||
e1000_validate_option(&dplx, &opt, adapter);
|
||||
} else {
|
||||
dplx = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||
"parameter ignored\n");
|
||||
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||
} else { /* Autoneg */
|
||||
static const struct e1000_opt_list an_list[] =
|
||||
#define AA "AutoNeg advertising "
|
||||
{{ 0x01, AA "10/HD" },
|
||||
{ 0x02, AA "10/FD" },
|
||||
{ 0x03, AA "10/FD, 10/HD" },
|
||||
{ 0x04, AA "100/HD" },
|
||||
{ 0x05, AA "100/HD, 10/HD" },
|
||||
{ 0x06, AA "100/HD, 10/FD" },
|
||||
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||
{ 0x08, AA "100/FD" },
|
||||
{ 0x09, AA "100/FD, 10/HD" },
|
||||
{ 0x0a, AA "100/FD, 10/FD" },
|
||||
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||
{ 0x0c, AA "100/FD, 100/HD" },
|
||||
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x20, AA "1000/FD" },
|
||||
{ 0x21, AA "1000/FD, 10/HD" },
|
||||
{ 0x22, AA "1000/FD, 10/FD" },
|
||||
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||
{ 0x24, AA "1000/FD, 100/HD" },
|
||||
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x28, AA "1000/FD, 100/FD" },
|
||||
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "AutoNeg",
|
||||
.err = "parameter ignored",
|
||||
.def = AUTONEG_ADV_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||
.p = an_list }}
|
||||
};
|
||||
|
||||
if (num_AutoNeg > bd) {
|
||||
an = AutoNeg[bd];
|
||||
e1000_validate_option(&an, &opt, adapter);
|
||||
} else {
|
||||
an = opt.def;
|
||||
}
|
||||
adapter->hw.autoneg_advertised = an;
|
||||
}
|
||||
|
||||
switch (speed + dplx) {
|
||||
case 0:
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||
e_dev_info("Speed and duplex autonegotiation "
|
||||
"enabled\n");
|
||||
break;
|
||||
case HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_100_HALF;
|
||||
break;
|
||||
case FULL_DUPLEX:
|
||||
e_dev_info("Full Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||
ADVERTISE_100_FULL |
|
||||
ADVERTISE_1000_FULL;
|
||||
break;
|
||||
case SPEED_10:
|
||||
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_10_FULL;
|
||||
break;
|
||||
case SPEED_10 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_10 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100:
|
||||
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||
ADVERTISE_100_FULL;
|
||||
break;
|
||||
case SPEED_100 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||
goto full_duplex_only;
|
||||
case SPEED_1000 + HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||
fallthrough;
|
||||
case SPEED_1000 + FULL_DUPLEX:
|
||||
full_duplex_only:
|
||||
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||
"only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||
"Setting MDI-X to a compatible value.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,727 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
#include "e1000-6.1-ethercat.h"
|
||||
|
||||
/* This is the only thing that needs to be changed to adjust the
|
||||
* maximum number of ports that the driver can manage.
|
||||
*/
|
||||
|
||||
#define E1000_MAX_NIC 32
|
||||
|
||||
#define OPTION_UNSET -1
|
||||
#define OPTION_DISABLED 0
|
||||
#define OPTION_ENABLED 1
|
||||
|
||||
/* All parameters are treated the same, as an integer array of values.
|
||||
* This macro just reduces the need to repeat the same declaration code
|
||||
* over and over (plus this helps to avoid typo bugs).
|
||||
*/
|
||||
|
||||
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||
#define E1000_PARAM(X, desc) \
|
||||
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||
static unsigned int num_##X; \
|
||||
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||
MODULE_PARM_DESC(X, desc);
|
||||
|
||||
/* Transmit Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||
|
||||
/* Receive Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||
|
||||
/* User Specified Speed Override
|
||||
*
|
||||
* Valid Range: 0, 10, 100, 1000
|
||||
* - 0 - auto-negotiate at all supported speeds
|
||||
* - 10 - only link at 10 Mbps
|
||||
* - 100 - only link at 100 Mbps
|
||||
* - 1000 - only link at 1000 Mbps
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Speed, "Speed setting");
|
||||
|
||||
/* User Specified Duplex Override
|
||||
*
|
||||
* Valid Range: 0-2
|
||||
* - 0 - auto-negotiate for duplex
|
||||
* - 1 - only link at half duplex
|
||||
* - 2 - only link at full duplex
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Duplex, "Duplex setting");
|
||||
|
||||
/* Auto-negotiation Advertisement Override
|
||||
*
|
||||
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||
*
|
||||
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||
* combinations should be advertised during auto-negotiation.
|
||||
* The supported speed and duplex modes are listed below
|
||||
*
|
||||
* Bit 7 6 5 4 3 2 1 0
|
||||
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||
* Duplex Full Full Half Full Half
|
||||
*
|
||||
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||
*/
|
||||
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||
|
||||
/* User Specified Flow Control Override
|
||||
*
|
||||
* Valid Range: 0-3
|
||||
* - 0 - No Flow Control
|
||||
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||
* - 3 - Full Flow Control Support
|
||||
*
|
||||
* Default Value: Read flow control settings from the EEPROM
|
||||
*/
|
||||
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||
|
||||
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
* - 0 - disables all checksum offload
|
||||
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||
* on 82543 and newer -based NICs
|
||||
*
|
||||
* Default Value: 1
|
||||
*/
|
||||
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||
|
||||
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||
* Tx interrupt delay needs to typically be set to something non zero
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||
#define DEFAULT_TIDV 8
|
||||
#define MAX_TXDELAY 0xFFFF
|
||||
#define MIN_TXDELAY 0
|
||||
|
||||
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||
#define DEFAULT_TADV 32
|
||||
#define MAX_TXABSDELAY 0xFFFF
|
||||
#define MIN_TXABSDELAY 0
|
||||
|
||||
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||
* hardware will likely hang if you set this to anything but zero.
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||
#define DEFAULT_RDTR 0
|
||||
#define MAX_RXDELAY 0xFFFF
|
||||
#define MIN_RXDELAY 0
|
||||
|
||||
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||
#define DEFAULT_RADV 8
|
||||
#define MAX_RXABSDELAY 0xFFFF
|
||||
#define MIN_RXABSDELAY 0
|
||||
|
||||
/* Interrupt Throttle Rate (interrupts/sec)
|
||||
*
|
||||
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||
*/
|
||||
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||
#define DEFAULT_ITR 3
|
||||
#define MAX_ITR 100000
|
||||
#define MIN_ITR 100
|
||||
|
||||
/* Enable Smart Power Down of the PHY
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
*
|
||||
* Default Value: 0 (disabled)
|
||||
*/
|
||||
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||
|
||||
struct e1000_option {
|
||||
enum { enable_option, range_option, list_option } type;
|
||||
const char *name;
|
||||
const char *err;
|
||||
int def;
|
||||
union {
|
||||
struct { /* range_option info */
|
||||
int min;
|
||||
int max;
|
||||
} r;
|
||||
struct { /* list_option info */
|
||||
int nr;
|
||||
const struct e1000_opt_list { int i; char *str; } *p;
|
||||
} l;
|
||||
} arg;
|
||||
};
|
||||
|
||||
static int e1000_validate_option(unsigned int *value,
|
||||
const struct e1000_option *opt,
|
||||
struct e1000_adapter *adapter)
|
||||
{
|
||||
if (*value == OPTION_UNSET) {
|
||||
*value = opt->def;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (opt->type) {
|
||||
case enable_option:
|
||||
switch (*value) {
|
||||
case OPTION_ENABLED:
|
||||
e_dev_info("%s Enabled\n", opt->name);
|
||||
return 0;
|
||||
case OPTION_DISABLED:
|
||||
e_dev_info("%s Disabled\n", opt->name);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case range_option:
|
||||
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case list_option: {
|
||||
int i;
|
||||
const struct e1000_opt_list *ent;
|
||||
|
||||
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||
ent = &opt->arg.l.p[i];
|
||||
if (*value == ent->i) {
|
||||
if (ent->str[0] != '\0')
|
||||
e_dev_info("%s\n", ent->str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||
opt->name, *value, opt->err);
|
||||
*value = opt->def;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||
|
||||
/**
|
||||
* e1000_check_options - Range Checking for Command Line Parameters
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* This routine checks all command line parameters for valid user
|
||||
* input. If an invalid value is given, or if no user specified
|
||||
* value exists, a default value is used. The final value is stored
|
||||
* in a variable in the adapter structure.
|
||||
**/
|
||||
void e1000_check_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
if (bd >= E1000_MAX_NIC) {
|
||||
e_dev_warn("Warning: no configuration for board #%i "
|
||||
"using defaults for all values\n", bd);
|
||||
}
|
||||
|
||||
{ /* Transmit Descriptor Count */
|
||||
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||
.def = E1000_DEFAULT_TXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_TXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_TxDescriptors > bd) {
|
||||
tx_ring->count = TxDescriptors[bd];
|
||||
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||
tx_ring->count = ALIGN(tx_ring->count,
|
||||
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
tx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||
tx_ring[i].count = tx_ring->count;
|
||||
}
|
||||
{ /* Receive Descriptor Count */
|
||||
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||
.def = E1000_DEFAULT_RXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_RXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||
E1000_MAX_82544_RXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_RxDescriptors > bd) {
|
||||
rx_ring->count = RxDescriptors[bd];
|
||||
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||
rx_ring->count = ALIGN(rx_ring->count,
|
||||
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
rx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||
rx_ring[i].count = rx_ring->count;
|
||||
}
|
||||
{ /* Checksum Offload Enable/Disable */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "Checksum Offload",
|
||||
.err = "defaulting to Enabled",
|
||||
.def = OPTION_ENABLED
|
||||
};
|
||||
|
||||
if (num_XsumRX > bd) {
|
||||
unsigned int rx_csum = XsumRX[bd];
|
||||
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||
adapter->rx_csum = rx_csum;
|
||||
} else {
|
||||
adapter->rx_csum = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Flow Control */
|
||||
|
||||
static const struct e1000_opt_list fc_list[] = {
|
||||
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||
};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Flow Control",
|
||||
.err = "reading default settings from EEPROM",
|
||||
.def = E1000_FC_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||
.p = fc_list }}
|
||||
};
|
||||
|
||||
if (num_FlowControl > bd) {
|
||||
unsigned int fc = FlowControl[bd];
|
||||
e1000_validate_option(&fc, &opt, adapter);
|
||||
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||
} else {
|
||||
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||
.def = DEFAULT_TIDV,
|
||||
.arg = { .r = { .min = MIN_TXDELAY,
|
||||
.max = MAX_TXDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxIntDelay > bd) {
|
||||
adapter->tx_int_delay = TxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||
.def = DEFAULT_TADV,
|
||||
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||
.max = MAX_TXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxAbsIntDelay > bd) {
|
||||
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||
.def = DEFAULT_RDTR,
|
||||
.arg = { .r = { .min = MIN_RXDELAY,
|
||||
.max = MAX_RXDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxIntDelay > bd) {
|
||||
adapter->rx_int_delay = RxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||
.def = DEFAULT_RADV,
|
||||
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||
.max = MAX_RXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxAbsIntDelay > bd) {
|
||||
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Interrupt Throttling Rate */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||
.def = DEFAULT_ITR,
|
||||
.arg = { .r = { .min = MIN_ITR,
|
||||
.max = MAX_ITR }}
|
||||
};
|
||||
|
||||
if (num_InterruptThrottleRate > bd) {
|
||||
adapter->itr = InterruptThrottleRate[bd];
|
||||
switch (adapter->itr) {
|
||||
case 0:
|
||||
e_dev_info("%s turned off\n", opt.name);
|
||||
break;
|
||||
case 1:
|
||||
e_dev_info("%s set to dynamic mode\n",
|
||||
opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 3:
|
||||
e_dev_info("%s set to dynamic conservative "
|
||||
"mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 4:
|
||||
e_dev_info("%s set to simplified "
|
||||
"(2000-8000) ints mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
break;
|
||||
default:
|
||||
e1000_validate_option(&adapter->itr, &opt,
|
||||
adapter);
|
||||
/* save the setting, because the dynamic bits
|
||||
* change itr.
|
||||
* clear the lower two bits because they are
|
||||
* used as control
|
||||
*/
|
||||
adapter->itr_setting = adapter->itr & ~3;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
adapter->itr_setting = opt.def;
|
||||
adapter->itr = 20000;
|
||||
}
|
||||
}
|
||||
{ /* Smart Power Down */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "PHY Smart Power Down",
|
||||
.err = "defaulting to Disabled",
|
||||
.def = OPTION_DISABLED
|
||||
};
|
||||
|
||||
if (num_SmartPowerDownEnable > bd) {
|
||||
unsigned int spd = SmartPowerDownEnable[bd];
|
||||
e1000_validate_option(&spd, &opt, adapter);
|
||||
adapter->smart_power_down = spd;
|
||||
} else {
|
||||
adapter->smart_power_down = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
switch (adapter->hw.media_type) {
|
||||
case e1000_media_type_fiber:
|
||||
case e1000_media_type_internal_serdes:
|
||||
e1000_check_fiber_options(adapter);
|
||||
break;
|
||||
case e1000_media_type_copper:
|
||||
e1000_check_copper_options(adapter);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on fiber adapters
|
||||
**/
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
int bd = adapter->bd_number;
|
||||
if (num_Speed > bd) {
|
||||
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||
"adapters, parameter ignored\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on copper adapters
|
||||
**/
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
unsigned int speed, dplx, an;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
{ /* Speed */
|
||||
static const struct e1000_opt_list speed_list[] = {
|
||||
{ 0, "" },
|
||||
{ SPEED_10, "" },
|
||||
{ SPEED_100, "" },
|
||||
{ SPEED_1000, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Speed",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||
.p = speed_list }}
|
||||
};
|
||||
|
||||
if (num_Speed > bd) {
|
||||
speed = Speed[bd];
|
||||
e1000_validate_option(&speed, &opt, adapter);
|
||||
} else {
|
||||
speed = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Duplex */
|
||||
static const struct e1000_opt_list dplx_list[] = {
|
||||
{ 0, "" },
|
||||
{ HALF_DUPLEX, "" },
|
||||
{ FULL_DUPLEX, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Duplex",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||
.p = dplx_list }}
|
||||
};
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
dplx = Duplex[bd];
|
||||
e1000_validate_option(&dplx, &opt, adapter);
|
||||
} else {
|
||||
dplx = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||
"parameter ignored\n");
|
||||
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||
} else { /* Autoneg */
|
||||
static const struct e1000_opt_list an_list[] =
|
||||
#define AA "AutoNeg advertising "
|
||||
{{ 0x01, AA "10/HD" },
|
||||
{ 0x02, AA "10/FD" },
|
||||
{ 0x03, AA "10/FD, 10/HD" },
|
||||
{ 0x04, AA "100/HD" },
|
||||
{ 0x05, AA "100/HD, 10/HD" },
|
||||
{ 0x06, AA "100/HD, 10/FD" },
|
||||
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||
{ 0x08, AA "100/FD" },
|
||||
{ 0x09, AA "100/FD, 10/HD" },
|
||||
{ 0x0a, AA "100/FD, 10/FD" },
|
||||
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||
{ 0x0c, AA "100/FD, 100/HD" },
|
||||
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x20, AA "1000/FD" },
|
||||
{ 0x21, AA "1000/FD, 10/HD" },
|
||||
{ 0x22, AA "1000/FD, 10/FD" },
|
||||
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||
{ 0x24, AA "1000/FD, 100/HD" },
|
||||
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x28, AA "1000/FD, 100/FD" },
|
||||
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "AutoNeg",
|
||||
.err = "parameter ignored",
|
||||
.def = AUTONEG_ADV_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||
.p = an_list }}
|
||||
};
|
||||
|
||||
if (num_AutoNeg > bd) {
|
||||
an = AutoNeg[bd];
|
||||
e1000_validate_option(&an, &opt, adapter);
|
||||
} else {
|
||||
an = opt.def;
|
||||
}
|
||||
adapter->hw.autoneg_advertised = an;
|
||||
}
|
||||
|
||||
switch (speed + dplx) {
|
||||
case 0:
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||
e_dev_info("Speed and duplex autonegotiation "
|
||||
"enabled\n");
|
||||
break;
|
||||
case HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_100_HALF;
|
||||
break;
|
||||
case FULL_DUPLEX:
|
||||
e_dev_info("Full Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||
ADVERTISE_100_FULL |
|
||||
ADVERTISE_1000_FULL;
|
||||
break;
|
||||
case SPEED_10:
|
||||
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_10_FULL;
|
||||
break;
|
||||
case SPEED_10 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_10 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100:
|
||||
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||
ADVERTISE_100_FULL;
|
||||
break;
|
||||
case SPEED_100 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||
goto full_duplex_only;
|
||||
case SPEED_1000 + HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||
fallthrough;
|
||||
case SPEED_1000 + FULL_DUPLEX:
|
||||
full_duplex_only:
|
||||
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||
"only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||
"Setting MDI-X to a compatible value.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,727 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright(c) 1999 - 2006 Intel Corporation. */
|
||||
|
||||
#include "e1000.h"
|
||||
|
||||
/* This is the only thing that needs to be changed to adjust the
|
||||
* maximum number of ports that the driver can manage.
|
||||
*/
|
||||
|
||||
#define E1000_MAX_NIC 32
|
||||
|
||||
#define OPTION_UNSET -1
|
||||
#define OPTION_DISABLED 0
|
||||
#define OPTION_ENABLED 1
|
||||
|
||||
/* All parameters are treated the same, as an integer array of values.
|
||||
* This macro just reduces the need to repeat the same declaration code
|
||||
* over and over (plus this helps to avoid typo bugs).
|
||||
*/
|
||||
|
||||
#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
|
||||
#define E1000_PARAM(X, desc) \
|
||||
static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
|
||||
static unsigned int num_##X; \
|
||||
module_param_array_named(X, X, int, &num_##X, 0); \
|
||||
MODULE_PARM_DESC(X, desc);
|
||||
|
||||
/* Transmit Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(TxDescriptors, "Number of transmit descriptors");
|
||||
|
||||
/* Receive Descriptor Count
|
||||
*
|
||||
* Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers
|
||||
* Valid Range: 80-4096 for 82544 and newer
|
||||
*
|
||||
* Default Value: 256
|
||||
*/
|
||||
E1000_PARAM(RxDescriptors, "Number of receive descriptors");
|
||||
|
||||
/* User Specified Speed Override
|
||||
*
|
||||
* Valid Range: 0, 10, 100, 1000
|
||||
* - 0 - auto-negotiate at all supported speeds
|
||||
* - 10 - only link at 10 Mbps
|
||||
* - 100 - only link at 100 Mbps
|
||||
* - 1000 - only link at 1000 Mbps
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Speed, "Speed setting");
|
||||
|
||||
/* User Specified Duplex Override
|
||||
*
|
||||
* Valid Range: 0-2
|
||||
* - 0 - auto-negotiate for duplex
|
||||
* - 1 - only link at half duplex
|
||||
* - 2 - only link at full duplex
|
||||
*
|
||||
* Default Value: 0
|
||||
*/
|
||||
E1000_PARAM(Duplex, "Duplex setting");
|
||||
|
||||
/* Auto-negotiation Advertisement Override
|
||||
*
|
||||
* Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber)
|
||||
*
|
||||
* The AutoNeg value is a bit mask describing which speed and duplex
|
||||
* combinations should be advertised during auto-negotiation.
|
||||
* The supported speed and duplex modes are listed below
|
||||
*
|
||||
* Bit 7 6 5 4 3 2 1 0
|
||||
* Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
|
||||
* Duplex Full Full Half Full Half
|
||||
*
|
||||
* Default Value: 0x2F (copper); 0x20 (fiber)
|
||||
*/
|
||||
E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting");
|
||||
#define AUTONEG_ADV_DEFAULT 0x2F
|
||||
|
||||
/* User Specified Flow Control Override
|
||||
*
|
||||
* Valid Range: 0-3
|
||||
* - 0 - No Flow Control
|
||||
* - 1 - Rx only, respond to PAUSE frames but do not generate them
|
||||
* - 2 - Tx only, generate PAUSE frames but ignore them on receive
|
||||
* - 3 - Full Flow Control Support
|
||||
*
|
||||
* Default Value: Read flow control settings from the EEPROM
|
||||
*/
|
||||
E1000_PARAM(FlowControl, "Flow Control setting");
|
||||
|
||||
/* XsumRX - Receive Checksum Offload Enable/Disable
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
* - 0 - disables all checksum offload
|
||||
* - 1 - enables receive IP/TCP/UDP checksum offload
|
||||
* on 82543 and newer -based NICs
|
||||
*
|
||||
* Default Value: 1
|
||||
*/
|
||||
E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
|
||||
|
||||
/* Transmit Interrupt Delay in units of 1.024 microseconds
|
||||
* Tx interrupt delay needs to typically be set to something non zero
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
|
||||
#define DEFAULT_TIDV 8
|
||||
#define MAX_TXDELAY 0xFFFF
|
||||
#define MIN_TXDELAY 0
|
||||
|
||||
/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
|
||||
#define DEFAULT_TADV 32
|
||||
#define MAX_TXABSDELAY 0xFFFF
|
||||
#define MIN_TXABSDELAY 0
|
||||
|
||||
/* Receive Interrupt Delay in units of 1.024 microseconds
|
||||
* hardware will likely hang if you set this to anything but zero.
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
|
||||
#define DEFAULT_RDTR 0
|
||||
#define MAX_RXDELAY 0xFFFF
|
||||
#define MIN_RXDELAY 0
|
||||
|
||||
/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
|
||||
*
|
||||
* Valid Range: 0-65535
|
||||
*/
|
||||
E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
|
||||
#define DEFAULT_RADV 8
|
||||
#define MAX_RXABSDELAY 0xFFFF
|
||||
#define MIN_RXABSDELAY 0
|
||||
|
||||
/* Interrupt Throttle Rate (interrupts/sec)
|
||||
*
|
||||
* Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative)
|
||||
*/
|
||||
E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
|
||||
#define DEFAULT_ITR 3
|
||||
#define MAX_ITR 100000
|
||||
#define MIN_ITR 100
|
||||
|
||||
/* Enable Smart Power Down of the PHY
|
||||
*
|
||||
* Valid Range: 0, 1
|
||||
*
|
||||
* Default Value: 0 (disabled)
|
||||
*/
|
||||
E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
|
||||
|
||||
struct e1000_option {
|
||||
enum { enable_option, range_option, list_option } type;
|
||||
const char *name;
|
||||
const char *err;
|
||||
int def;
|
||||
union {
|
||||
struct { /* range_option info */
|
||||
int min;
|
||||
int max;
|
||||
} r;
|
||||
struct { /* list_option info */
|
||||
int nr;
|
||||
const struct e1000_opt_list { int i; char *str; } *p;
|
||||
} l;
|
||||
} arg;
|
||||
};
|
||||
|
||||
static int e1000_validate_option(unsigned int *value,
|
||||
const struct e1000_option *opt,
|
||||
struct e1000_adapter *adapter)
|
||||
{
|
||||
if (*value == OPTION_UNSET) {
|
||||
*value = opt->def;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (opt->type) {
|
||||
case enable_option:
|
||||
switch (*value) {
|
||||
case OPTION_ENABLED:
|
||||
e_dev_info("%s Enabled\n", opt->name);
|
||||
return 0;
|
||||
case OPTION_DISABLED:
|
||||
e_dev_info("%s Disabled\n", opt->name);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case range_option:
|
||||
if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
|
||||
e_dev_info("%s set to %i\n", opt->name, *value);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case list_option: {
|
||||
int i;
|
||||
const struct e1000_opt_list *ent;
|
||||
|
||||
for (i = 0; i < opt->arg.l.nr; i++) {
|
||||
ent = &opt->arg.l.p[i];
|
||||
if (*value == ent->i) {
|
||||
if (ent->str[0] != '\0')
|
||||
e_dev_info("%s\n", ent->str);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
e_dev_info("Invalid %s value specified (%i) %s\n",
|
||||
opt->name, *value, opt->err);
|
||||
*value = opt->def;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter);
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter);
|
||||
|
||||
/**
|
||||
* e1000_check_options - Range Checking for Command Line Parameters
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* This routine checks all command line parameters for valid user
|
||||
* input. If an invalid value is given, or if no user specified
|
||||
* value exists, a default value is used. The final value is stored
|
||||
* in a variable in the adapter structure.
|
||||
**/
|
||||
void e1000_check_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
if (bd >= E1000_MAX_NIC) {
|
||||
e_dev_warn("Warning: no configuration for board #%i "
|
||||
"using defaults for all values\n", bd);
|
||||
}
|
||||
|
||||
{ /* Transmit Descriptor Count */
|
||||
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_TXD),
|
||||
.def = E1000_DEFAULT_TXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_TXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_TxDescriptors > bd) {
|
||||
tx_ring->count = TxDescriptors[bd];
|
||||
e1000_validate_option(&tx_ring->count, &opt, adapter);
|
||||
tx_ring->count = ALIGN(tx_ring->count,
|
||||
REQ_TX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
tx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_tx_queues; i++)
|
||||
tx_ring[i].count = tx_ring->count;
|
||||
}
|
||||
{ /* Receive Descriptor Count */
|
||||
struct e1000_rx_ring *rx_ring = adapter->rx_ring;
|
||||
int i;
|
||||
e1000_mac_type mac_type = adapter->hw.mac_type;
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Descriptors",
|
||||
.err = "using default of "
|
||||
__MODULE_STRING(E1000_DEFAULT_RXD),
|
||||
.def = E1000_DEFAULT_RXD,
|
||||
.arg = { .r = {
|
||||
.min = E1000_MIN_RXD,
|
||||
.max = mac_type < e1000_82544 ? E1000_MAX_RXD :
|
||||
E1000_MAX_82544_RXD
|
||||
}}
|
||||
};
|
||||
|
||||
if (num_RxDescriptors > bd) {
|
||||
rx_ring->count = RxDescriptors[bd];
|
||||
e1000_validate_option(&rx_ring->count, &opt, adapter);
|
||||
rx_ring->count = ALIGN(rx_ring->count,
|
||||
REQ_RX_DESCRIPTOR_MULTIPLE);
|
||||
} else {
|
||||
rx_ring->count = opt.def;
|
||||
}
|
||||
for (i = 0; i < adapter->num_rx_queues; i++)
|
||||
rx_ring[i].count = rx_ring->count;
|
||||
}
|
||||
{ /* Checksum Offload Enable/Disable */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "Checksum Offload",
|
||||
.err = "defaulting to Enabled",
|
||||
.def = OPTION_ENABLED
|
||||
};
|
||||
|
||||
if (num_XsumRX > bd) {
|
||||
unsigned int rx_csum = XsumRX[bd];
|
||||
e1000_validate_option(&rx_csum, &opt, adapter);
|
||||
adapter->rx_csum = rx_csum;
|
||||
} else {
|
||||
adapter->rx_csum = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Flow Control */
|
||||
|
||||
static const struct e1000_opt_list fc_list[] = {
|
||||
{ E1000_FC_NONE, "Flow Control Disabled" },
|
||||
{ E1000_FC_RX_PAUSE, "Flow Control Receive Only" },
|
||||
{ E1000_FC_TX_PAUSE, "Flow Control Transmit Only" },
|
||||
{ E1000_FC_FULL, "Flow Control Enabled" },
|
||||
{ E1000_FC_DEFAULT, "Flow Control Hardware Default" }
|
||||
};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Flow Control",
|
||||
.err = "reading default settings from EEPROM",
|
||||
.def = E1000_FC_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(fc_list),
|
||||
.p = fc_list }}
|
||||
};
|
||||
|
||||
if (num_FlowControl > bd) {
|
||||
unsigned int fc = FlowControl[bd];
|
||||
e1000_validate_option(&fc, &opt, adapter);
|
||||
adapter->hw.fc = adapter->hw.original_fc = fc;
|
||||
} else {
|
||||
adapter->hw.fc = adapter->hw.original_fc = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TIDV),
|
||||
.def = DEFAULT_TIDV,
|
||||
.arg = { .r = { .min = MIN_TXDELAY,
|
||||
.max = MAX_TXDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxIntDelay > bd) {
|
||||
adapter->tx_int_delay = TxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Transmit Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Transmit Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_TADV),
|
||||
.def = DEFAULT_TADV,
|
||||
.arg = { .r = { .min = MIN_TXABSDELAY,
|
||||
.max = MAX_TXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_TxAbsIntDelay > bd) {
|
||||
adapter->tx_abs_int_delay = TxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->tx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->tx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RDTR),
|
||||
.def = DEFAULT_RDTR,
|
||||
.arg = { .r = { .min = MIN_RXDELAY,
|
||||
.max = MAX_RXDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxIntDelay > bd) {
|
||||
adapter->rx_int_delay = RxIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Receive Absolute Interrupt Delay */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Receive Absolute Interrupt Delay",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_RADV),
|
||||
.def = DEFAULT_RADV,
|
||||
.arg = { .r = { .min = MIN_RXABSDELAY,
|
||||
.max = MAX_RXABSDELAY }}
|
||||
};
|
||||
|
||||
if (num_RxAbsIntDelay > bd) {
|
||||
adapter->rx_abs_int_delay = RxAbsIntDelay[bd];
|
||||
e1000_validate_option(&adapter->rx_abs_int_delay, &opt,
|
||||
adapter);
|
||||
} else {
|
||||
adapter->rx_abs_int_delay = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Interrupt Throttling Rate */
|
||||
opt = (struct e1000_option) {
|
||||
.type = range_option,
|
||||
.name = "Interrupt Throttling Rate (ints/sec)",
|
||||
.err = "using default of " __MODULE_STRING(DEFAULT_ITR),
|
||||
.def = DEFAULT_ITR,
|
||||
.arg = { .r = { .min = MIN_ITR,
|
||||
.max = MAX_ITR }}
|
||||
};
|
||||
|
||||
if (num_InterruptThrottleRate > bd) {
|
||||
adapter->itr = InterruptThrottleRate[bd];
|
||||
switch (adapter->itr) {
|
||||
case 0:
|
||||
e_dev_info("%s turned off\n", opt.name);
|
||||
break;
|
||||
case 1:
|
||||
e_dev_info("%s set to dynamic mode\n",
|
||||
opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 3:
|
||||
e_dev_info("%s set to dynamic conservative "
|
||||
"mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
adapter->itr = 20000;
|
||||
break;
|
||||
case 4:
|
||||
e_dev_info("%s set to simplified "
|
||||
"(2000-8000) ints mode\n", opt.name);
|
||||
adapter->itr_setting = adapter->itr;
|
||||
break;
|
||||
default:
|
||||
e1000_validate_option(&adapter->itr, &opt,
|
||||
adapter);
|
||||
/* save the setting, because the dynamic bits
|
||||
* change itr.
|
||||
* clear the lower two bits because they are
|
||||
* used as control
|
||||
*/
|
||||
adapter->itr_setting = adapter->itr & ~3;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
adapter->itr_setting = opt.def;
|
||||
adapter->itr = 20000;
|
||||
}
|
||||
}
|
||||
{ /* Smart Power Down */
|
||||
opt = (struct e1000_option) {
|
||||
.type = enable_option,
|
||||
.name = "PHY Smart Power Down",
|
||||
.err = "defaulting to Disabled",
|
||||
.def = OPTION_DISABLED
|
||||
};
|
||||
|
||||
if (num_SmartPowerDownEnable > bd) {
|
||||
unsigned int spd = SmartPowerDownEnable[bd];
|
||||
e1000_validate_option(&spd, &opt, adapter);
|
||||
adapter->smart_power_down = spd;
|
||||
} else {
|
||||
adapter->smart_power_down = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
switch (adapter->hw.media_type) {
|
||||
case e1000_media_type_fiber:
|
||||
case e1000_media_type_internal_serdes:
|
||||
e1000_check_fiber_options(adapter);
|
||||
break;
|
||||
case e1000_media_type_copper:
|
||||
e1000_check_copper_options(adapter);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_fiber_options - Range Checking for Link Options, Fiber Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on fiber adapters
|
||||
**/
|
||||
static void e1000_check_fiber_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
int bd = adapter->bd_number;
|
||||
if (num_Speed > bd) {
|
||||
e_dev_info("Speed not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
e_dev_info("Duplex not valid for fiber adapters, parameter "
|
||||
"ignored\n");
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) {
|
||||
e_dev_info("AutoNeg other than 1000/Full is not valid for fiber"
|
||||
"adapters, parameter ignored\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* e1000_check_copper_options - Range Checking for Link Options, Copper Version
|
||||
* @adapter: board private structure
|
||||
*
|
||||
* Handles speed and duplex options on copper adapters
|
||||
**/
|
||||
static void e1000_check_copper_options(struct e1000_adapter *adapter)
|
||||
{
|
||||
struct e1000_option opt;
|
||||
unsigned int speed, dplx, an;
|
||||
int bd = adapter->bd_number;
|
||||
|
||||
{ /* Speed */
|
||||
static const struct e1000_opt_list speed_list[] = {
|
||||
{ 0, "" },
|
||||
{ SPEED_10, "" },
|
||||
{ SPEED_100, "" },
|
||||
{ SPEED_1000, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Speed",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(speed_list),
|
||||
.p = speed_list }}
|
||||
};
|
||||
|
||||
if (num_Speed > bd) {
|
||||
speed = Speed[bd];
|
||||
e1000_validate_option(&speed, &opt, adapter);
|
||||
} else {
|
||||
speed = opt.def;
|
||||
}
|
||||
}
|
||||
{ /* Duplex */
|
||||
static const struct e1000_opt_list dplx_list[] = {
|
||||
{ 0, "" },
|
||||
{ HALF_DUPLEX, "" },
|
||||
{ FULL_DUPLEX, "" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "Duplex",
|
||||
.err = "parameter ignored",
|
||||
.def = 0,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(dplx_list),
|
||||
.p = dplx_list }}
|
||||
};
|
||||
|
||||
if (num_Duplex > bd) {
|
||||
dplx = Duplex[bd];
|
||||
e1000_validate_option(&dplx, &opt, adapter);
|
||||
} else {
|
||||
dplx = opt.def;
|
||||
}
|
||||
}
|
||||
|
||||
if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) {
|
||||
e_dev_info("AutoNeg specified along with Speed or Duplex, "
|
||||
"parameter ignored\n");
|
||||
adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT;
|
||||
} else { /* Autoneg */
|
||||
static const struct e1000_opt_list an_list[] =
|
||||
#define AA "AutoNeg advertising "
|
||||
{{ 0x01, AA "10/HD" },
|
||||
{ 0x02, AA "10/FD" },
|
||||
{ 0x03, AA "10/FD, 10/HD" },
|
||||
{ 0x04, AA "100/HD" },
|
||||
{ 0x05, AA "100/HD, 10/HD" },
|
||||
{ 0x06, AA "100/HD, 10/FD" },
|
||||
{ 0x07, AA "100/HD, 10/FD, 10/HD" },
|
||||
{ 0x08, AA "100/FD" },
|
||||
{ 0x09, AA "100/FD, 10/HD" },
|
||||
{ 0x0a, AA "100/FD, 10/FD" },
|
||||
{ 0x0b, AA "100/FD, 10/FD, 10/HD" },
|
||||
{ 0x0c, AA "100/FD, 100/HD" },
|
||||
{ 0x0d, AA "100/FD, 100/HD, 10/HD" },
|
||||
{ 0x0e, AA "100/FD, 100/HD, 10/FD" },
|
||||
{ 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x20, AA "1000/FD" },
|
||||
{ 0x21, AA "1000/FD, 10/HD" },
|
||||
{ 0x22, AA "1000/FD, 10/FD" },
|
||||
{ 0x23, AA "1000/FD, 10/FD, 10/HD" },
|
||||
{ 0x24, AA "1000/FD, 100/HD" },
|
||||
{ 0x25, AA "1000/FD, 100/HD, 10/HD" },
|
||||
{ 0x26, AA "1000/FD, 100/HD, 10/FD" },
|
||||
{ 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
|
||||
{ 0x28, AA "1000/FD, 100/FD" },
|
||||
{ 0x29, AA "1000/FD, 100/FD, 10/HD" },
|
||||
{ 0x2a, AA "1000/FD, 100/FD, 10/FD" },
|
||||
{ 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
|
||||
{ 0x2c, AA "1000/FD, 100/FD, 100/HD" },
|
||||
{ 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
|
||||
{ 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
|
||||
{ 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }};
|
||||
|
||||
opt = (struct e1000_option) {
|
||||
.type = list_option,
|
||||
.name = "AutoNeg",
|
||||
.err = "parameter ignored",
|
||||
.def = AUTONEG_ADV_DEFAULT,
|
||||
.arg = { .l = { .nr = ARRAY_SIZE(an_list),
|
||||
.p = an_list }}
|
||||
};
|
||||
|
||||
if (num_AutoNeg > bd) {
|
||||
an = AutoNeg[bd];
|
||||
e1000_validate_option(&an, &opt, adapter);
|
||||
} else {
|
||||
an = opt.def;
|
||||
}
|
||||
adapter->hw.autoneg_advertised = an;
|
||||
}
|
||||
|
||||
switch (speed + dplx) {
|
||||
case 0:
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
if ((num_Speed > bd) && (speed != 0 || dplx != 0))
|
||||
e_dev_info("Speed and duplex autonegotiation "
|
||||
"enabled\n");
|
||||
break;
|
||||
case HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Half Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_100_HALF;
|
||||
break;
|
||||
case FULL_DUPLEX:
|
||||
e_dev_info("Full Duplex specified without Speed\n");
|
||||
e_dev_info("Using Autonegotiation at Full Duplex only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_FULL |
|
||||
ADVERTISE_100_FULL |
|
||||
ADVERTISE_1000_FULL;
|
||||
break;
|
||||
case SPEED_10:
|
||||
e_dev_info("10 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 10 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_10_HALF |
|
||||
ADVERTISE_10_FULL;
|
||||
break;
|
||||
case SPEED_10 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_10 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 10 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_10_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100:
|
||||
e_dev_info("100 Mbps Speed specified without Duplex\n");
|
||||
e_dev_info("Using Autonegotiation at 100 Mbps only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_100_HALF |
|
||||
ADVERTISE_100_FULL;
|
||||
break;
|
||||
case SPEED_100 + HALF_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Half Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_half;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_100 + FULL_DUPLEX:
|
||||
e_dev_info("Forcing to 100 Mbps Full Duplex\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 0;
|
||||
adapter->hw.forced_speed_duplex = e1000_100_full;
|
||||
adapter->hw.autoneg_advertised = 0;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
e_dev_info("1000 Mbps Speed specified without Duplex\n");
|
||||
goto full_duplex_only;
|
||||
case SPEED_1000 + HALF_DUPLEX:
|
||||
e_dev_info("Half Duplex is not supported at 1000 Mbps\n");
|
||||
fallthrough;
|
||||
case SPEED_1000 + FULL_DUPLEX:
|
||||
full_duplex_only:
|
||||
e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex "
|
||||
"only\n");
|
||||
adapter->hw.autoneg = adapter->fc_autoneg = 1;
|
||||
adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
/* Speed, AutoNeg and MDI/MDI-X must all play nice */
|
||||
if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) {
|
||||
e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. "
|
||||
"Setting MDI-X to a compatible value.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -21,7 +21,9 @@ for f in $KERNELDIR/drivers/net/ethernet/intel/e1000/*.[ch]; do
|
|||
cp -v $o $e
|
||||
op=${b/\./-$PREVER-orig.}
|
||||
ep=${b/\./-$PREVER-ethercat.}
|
||||
diff -u $op $ep | patch -p1 $e
|
||||
diff -p -u $op $ep | patch -p1 $e
|
||||
sed -i s/$PREVER-ethercat.h/$KERNELVER-ethercat.h/ $e
|
||||
git add $o $e
|
||||
echo -e "\t$e \\\\\n\t$o \\\\" >> Makefile.am
|
||||
done
|
||||
echo "Remember to update Makefile.am!"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Copyright (C) 2006-2017 Florian Pose, Ingenieurgemeinschaft IgH
|
||||
#
|
||||
# This file is part of the IgH EtherCAT Master.
|
||||
#
|
||||
# The IgH EtherCAT Master is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 2, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# The IgH EtherCAT Master is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with the IgH EtherCAT Master; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ---
|
||||
#
|
||||
# The license mentioned above concerns the source code only. Using the
|
||||
# EtherCAT technology and brand is only permitted in compliance with the
|
||||
# industrial property and similar rights of Beckhoff Automation GmbH.
|
||||
#
|
||||
# ---
|
||||
#
|
||||
# vim: syntax=make
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
TOPDIR := $(src)/../..
|
||||
|
||||
REV := $(shell if test -s $(TOPDIR)/revision; then \
|
||||
cat $(TOPDIR)/revision; \
|
||||
else \
|
||||
git -C $(TOPDIR) describe 2>/dev/null || echo "unknown"; \
|
||||
fi)
|
||||
|
||||
ifeq (@ENABLE_GENET@,1)
|
||||
obj-m += ec_genet.o
|
||||
ec_genet-objs := \
|
||||
bcmgenet-@KERNEL_GENET@-ethercat.o \
|
||||
bcmmii-@KERNEL_GENET@-ethercat.o \
|
||||
bcmgenet_wol-@KERNEL_GENET@-ethercat.o
|
||||
|
||||
CFLAGS_bcmgenet-@KERNEL_GENET@-ethercat.o = -DREV="\"$(REV)\""
|
||||
endif
|
||||
|
||||
KBUILD_EXTRA_SYMBOLS := \
|
||||
@abs_top_builddir@/$(LINUX_SYMVERS) \
|
||||
@abs_top_builddir@/master/$(LINUX_SYMVERS)
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2006-2021 Florian Pose, Ingenieurgemeinschaft IgH
|
||||
#
|
||||
# This file is part of the IgH EtherCAT Master.
|
||||
#
|
||||
# The IgH EtherCAT Master is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 2, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# The IgH EtherCAT Master is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with the IgH EtherCAT Master; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ---
|
||||
#
|
||||
# The license mentioned above concerns the source code only. Using the
|
||||
# EtherCAT technology and brand is only permitted in compliance with the
|
||||
# industrial property and similar rights of Beckhoff Automation GmbH.
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
include $(top_srcdir)/Makefile.kbuild
|
||||
|
||||
EXTRA_DIST = \
|
||||
bcmgenet-6.1-ethercat.c \
|
||||
bcmgenet-6.1-ethercat.h \
|
||||
bcmgenet-6.1-orig.c \
|
||||
bcmgenet-6.1-orig.h \
|
||||
bcmgenet_wol-6.1-ethercat.c \
|
||||
bcmgenet_wol-6.1-orig.c \
|
||||
bcmmii-6.1-ethercat.c \
|
||||
bcmmii-6.1-orig.c
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,714 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2014-2020 Broadcom
|
||||
*/
|
||||
|
||||
#ifndef __BCMGENET_H__
|
||||
#define __BCMGENET_H__
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/dim.h>
|
||||
#include <linux/ethtool.h>
|
||||
|
||||
#include "unimac-6.1-ethercat.h"
|
||||
|
||||
/* EtherCAT header file */
|
||||
#include "../ecdev.h"
|
||||
|
||||
/* total number of Buffer Descriptors, same for Rx/Tx */
|
||||
#define TOTAL_DESC 256
|
||||
|
||||
/* which ring is descriptor based */
|
||||
#define DESC_INDEX 16
|
||||
|
||||
/* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528.
|
||||
* 1536 is multiple of 256 bytes
|
||||
*/
|
||||
#define ENET_BRCM_TAG_LEN 6
|
||||
#define ENET_PAD 8
|
||||
#define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \
|
||||
ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)
|
||||
#define DMA_MAX_BURST_LENGTH 0x10
|
||||
|
||||
/* misc. configuration */
|
||||
#define MAX_NUM_OF_FS_RULES 16
|
||||
#define CLEAR_ALL_HFB 0xFF
|
||||
#define DMA_FC_THRESH_HI (TOTAL_DESC >> 4)
|
||||
#define DMA_FC_THRESH_LO 5
|
||||
|
||||
/* 64B receive/transmit status block */
|
||||
struct status_64 {
|
||||
u32 length_status; /* length and peripheral status */
|
||||
u32 ext_status; /* Extended status*/
|
||||
u32 rx_csum; /* partial rx checksum */
|
||||
u32 unused1[9]; /* unused */
|
||||
u32 tx_csum_info; /* Tx checksum info. */
|
||||
u32 unused2[3]; /* unused */
|
||||
};
|
||||
|
||||
/* Rx status bits */
|
||||
#define STATUS_RX_EXT_MASK 0x1FFFFF
|
||||
#define STATUS_RX_CSUM_MASK 0xFFFF
|
||||
#define STATUS_RX_CSUM_OK 0x10000
|
||||
#define STATUS_RX_CSUM_FR 0x20000
|
||||
#define STATUS_RX_PROTO_TCP 0
|
||||
#define STATUS_RX_PROTO_UDP 1
|
||||
#define STATUS_RX_PROTO_ICMP 2
|
||||
#define STATUS_RX_PROTO_OTHER 3
|
||||
#define STATUS_RX_PROTO_MASK 3
|
||||
#define STATUS_RX_PROTO_SHIFT 18
|
||||
#define STATUS_FILTER_INDEX_MASK 0xFFFF
|
||||
/* Tx status bits */
|
||||
#define STATUS_TX_CSUM_START_MASK 0X7FFF
|
||||
#define STATUS_TX_CSUM_START_SHIFT 16
|
||||
#define STATUS_TX_CSUM_PROTO_UDP 0x8000
|
||||
#define STATUS_TX_CSUM_OFFSET_MASK 0x7FFF
|
||||
#define STATUS_TX_CSUM_LV 0x80000000
|
||||
|
||||
/* DMA Descriptor */
|
||||
#define DMA_DESC_LENGTH_STATUS 0x00 /* in bytes of data in buffer */
|
||||
#define DMA_DESC_ADDRESS_LO 0x04 /* lower bits of PA */
|
||||
#define DMA_DESC_ADDRESS_HI 0x08 /* upper 32 bits of PA, GENETv4+ */
|
||||
|
||||
/* Rx/Tx common counter group */
|
||||
struct bcmgenet_pkt_counters {
|
||||
u32 cnt_64; /* RO Received/Transmited 64 bytes packet */
|
||||
u32 cnt_127; /* RO Rx/Tx 127 bytes packet */
|
||||
u32 cnt_255; /* RO Rx/Tx 65-255 bytes packet */
|
||||
u32 cnt_511; /* RO Rx/Tx 256-511 bytes packet */
|
||||
u32 cnt_1023; /* RO Rx/Tx 512-1023 bytes packet */
|
||||
u32 cnt_1518; /* RO Rx/Tx 1024-1518 bytes packet */
|
||||
u32 cnt_mgv; /* RO Rx/Tx 1519-1522 good VLAN packet */
|
||||
u32 cnt_2047; /* RO Rx/Tx 1522-2047 bytes packet*/
|
||||
u32 cnt_4095; /* RO Rx/Tx 2048-4095 bytes packet*/
|
||||
u32 cnt_9216; /* RO Rx/Tx 4096-9216 bytes packet*/
|
||||
};
|
||||
|
||||
/* RSV, Receive Status Vector */
|
||||
struct bcmgenet_rx_counters {
|
||||
struct bcmgenet_pkt_counters pkt_cnt;
|
||||
u32 pkt; /* RO (0x428) Received pkt count*/
|
||||
u32 bytes; /* RO Received byte count */
|
||||
u32 mca; /* RO # of Received multicast pkt */
|
||||
u32 bca; /* RO # of Receive broadcast pkt */
|
||||
u32 fcs; /* RO # of Received FCS error */
|
||||
u32 cf; /* RO # of Received control frame pkt*/
|
||||
u32 pf; /* RO # of Received pause frame pkt */
|
||||
u32 uo; /* RO # of unknown op code pkt */
|
||||
u32 aln; /* RO # of alignment error count */
|
||||
u32 flr; /* RO # of frame length out of range count */
|
||||
u32 cde; /* RO # of code error pkt */
|
||||
u32 fcr; /* RO # of carrier sense error pkt */
|
||||
u32 ovr; /* RO # of oversize pkt*/
|
||||
u32 jbr; /* RO # of jabber count */
|
||||
u32 mtue; /* RO # of MTU error pkt*/
|
||||
u32 pok; /* RO # of Received good pkt */
|
||||
u32 uc; /* RO # of unicast pkt */
|
||||
u32 ppp; /* RO # of PPP pkt */
|
||||
u32 rcrc; /* RO (0x470),# of CRC match pkt */
|
||||
};
|
||||
|
||||
/* TSV, Transmit Status Vector */
|
||||
struct bcmgenet_tx_counters {
|
||||
struct bcmgenet_pkt_counters pkt_cnt;
|
||||
u32 pkts; /* RO (0x4a8) Transmited pkt */
|
||||
u32 mca; /* RO # of xmited multicast pkt */
|
||||
u32 bca; /* RO # of xmited broadcast pkt */
|
||||
u32 pf; /* RO # of xmited pause frame count */
|
||||
u32 cf; /* RO # of xmited control frame count */
|
||||
u32 fcs; /* RO # of xmited FCS error count */
|
||||
u32 ovr; /* RO # of xmited oversize pkt */
|
||||
u32 drf; /* RO # of xmited deferral pkt */
|
||||
u32 edf; /* RO # of xmited Excessive deferral pkt*/
|
||||
u32 scl; /* RO # of xmited single collision pkt */
|
||||
u32 mcl; /* RO # of xmited multiple collision pkt*/
|
||||
u32 lcl; /* RO # of xmited late collision pkt */
|
||||
u32 ecl; /* RO # of xmited excessive collision pkt*/
|
||||
u32 frg; /* RO # of xmited fragments pkt*/
|
||||
u32 ncl; /* RO # of xmited total collision count */
|
||||
u32 jbr; /* RO # of xmited jabber count*/
|
||||
u32 bytes; /* RO # of xmited byte count */
|
||||
u32 pok; /* RO # of xmited good pkt */
|
||||
u32 uc; /* RO (0x0x4f0)# of xmited unitcast pkt */
|
||||
};
|
||||
|
||||
struct bcmgenet_mib_counters {
|
||||
struct bcmgenet_rx_counters rx;
|
||||
struct bcmgenet_tx_counters tx;
|
||||
u32 rx_runt_cnt;
|
||||
u32 rx_runt_fcs;
|
||||
u32 rx_runt_fcs_align;
|
||||
u32 rx_runt_bytes;
|
||||
u32 rbuf_ovflow_cnt;
|
||||
u32 rbuf_err_cnt;
|
||||
u32 mdf_err_cnt;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_dma_failed;
|
||||
u32 tx_dma_failed;
|
||||
u32 tx_realloc_tsb;
|
||||
u32 tx_realloc_tsb_failed;
|
||||
};
|
||||
|
||||
#define UMAC_MIB_START 0x400
|
||||
|
||||
#define UMAC_MDIO_CMD 0x614
|
||||
#define MDIO_START_BUSY (1 << 29)
|
||||
#define MDIO_READ_FAIL (1 << 28)
|
||||
#define MDIO_RD (2 << 26)
|
||||
#define MDIO_WR (1 << 26)
|
||||
#define MDIO_PMD_SHIFT 21
|
||||
#define MDIO_PMD_MASK 0x1F
|
||||
#define MDIO_REG_SHIFT 16
|
||||
#define MDIO_REG_MASK 0x1F
|
||||
|
||||
#define UMAC_RBUF_OVFL_CNT_V1 0x61C
|
||||
#define RBUF_OVFL_CNT_V2 0x80
|
||||
#define RBUF_OVFL_CNT_V3PLUS 0x94
|
||||
|
||||
#define UMAC_MPD_CTRL 0x620
|
||||
#define MPD_EN (1 << 0)
|
||||
#define MPD_PW_EN (1 << 27)
|
||||
#define MPD_MSEQ_LEN_SHIFT 16
|
||||
#define MPD_MSEQ_LEN_MASK 0xFF
|
||||
|
||||
#define UMAC_MPD_PW_MS 0x624
|
||||
#define UMAC_MPD_PW_LS 0x628
|
||||
#define UMAC_RBUF_ERR_CNT_V1 0x634
|
||||
#define RBUF_ERR_CNT_V2 0x84
|
||||
#define RBUF_ERR_CNT_V3PLUS 0x98
|
||||
#define UMAC_MDF_ERR_CNT 0x638
|
||||
#define UMAC_MDF_CTRL 0x650
|
||||
#define UMAC_MDF_ADDR 0x654
|
||||
#define UMAC_MIB_CTRL 0x580
|
||||
#define MIB_RESET_RX (1 << 0)
|
||||
#define MIB_RESET_RUNT (1 << 1)
|
||||
#define MIB_RESET_TX (1 << 2)
|
||||
|
||||
#define RBUF_CTRL 0x00
|
||||
#define RBUF_64B_EN (1 << 0)
|
||||
#define RBUF_ALIGN_2B (1 << 1)
|
||||
#define RBUF_BAD_DIS (1 << 2)
|
||||
|
||||
#define RBUF_STATUS 0x0C
|
||||
#define RBUF_STATUS_WOL (1 << 0)
|
||||
#define RBUF_STATUS_MPD_INTR_ACTIVE (1 << 1)
|
||||
#define RBUF_STATUS_ACPI_INTR_ACTIVE (1 << 2)
|
||||
|
||||
#define RBUF_CHK_CTRL 0x14
|
||||
#define RBUF_RXCHK_EN (1 << 0)
|
||||
#define RBUF_SKIP_FCS (1 << 4)
|
||||
#define RBUF_L3_PARSE_DIS (1 << 5)
|
||||
|
||||
#define RBUF_ENERGY_CTRL 0x9c
|
||||
#define RBUF_EEE_EN (1 << 0)
|
||||
#define RBUF_PM_EN (1 << 1)
|
||||
|
||||
#define RBUF_TBUF_SIZE_CTRL 0xb4
|
||||
|
||||
#define RBUF_HFB_CTRL_V1 0x38
|
||||
#define RBUF_HFB_FILTER_EN_SHIFT 16
|
||||
#define RBUF_HFB_FILTER_EN_MASK 0xffff0000
|
||||
#define RBUF_HFB_EN (1 << 0)
|
||||
#define RBUF_HFB_256B (1 << 1)
|
||||
#define RBUF_ACPI_EN (1 << 2)
|
||||
|
||||
#define RBUF_HFB_LEN_V1 0x3C
|
||||
#define RBUF_FLTR_LEN_MASK 0xFF
|
||||
#define RBUF_FLTR_LEN_SHIFT 8
|
||||
|
||||
#define TBUF_CTRL 0x00
|
||||
#define TBUF_64B_EN (1 << 0)
|
||||
#define TBUF_BP_MC 0x0C
|
||||
#define TBUF_ENERGY_CTRL 0x14
|
||||
#define TBUF_EEE_EN (1 << 0)
|
||||
#define TBUF_PM_EN (1 << 1)
|
||||
|
||||
#define TBUF_CTRL_V1 0x80
|
||||
#define TBUF_BP_MC_V1 0xA0
|
||||
|
||||
#define HFB_CTRL 0x00
|
||||
#define HFB_FLT_ENABLE_V3PLUS 0x04
|
||||
#define HFB_FLT_LEN_V2 0x04
|
||||
#define HFB_FLT_LEN_V3PLUS 0x1C
|
||||
|
||||
/* uniMac intrl2 registers */
|
||||
#define INTRL2_CPU_STAT 0x00
|
||||
#define INTRL2_CPU_SET 0x04
|
||||
#define INTRL2_CPU_CLEAR 0x08
|
||||
#define INTRL2_CPU_MASK_STATUS 0x0C
|
||||
#define INTRL2_CPU_MASK_SET 0x10
|
||||
#define INTRL2_CPU_MASK_CLEAR 0x14
|
||||
|
||||
/* INTRL2 instance 0 definitions */
|
||||
#define UMAC_IRQ_SCB (1 << 0)
|
||||
#define UMAC_IRQ_EPHY (1 << 1)
|
||||
#define UMAC_IRQ_PHY_DET_R (1 << 2)
|
||||
#define UMAC_IRQ_PHY_DET_F (1 << 3)
|
||||
#define UMAC_IRQ_LINK_UP (1 << 4)
|
||||
#define UMAC_IRQ_LINK_DOWN (1 << 5)
|
||||
#define UMAC_IRQ_LINK_EVENT (UMAC_IRQ_LINK_UP | UMAC_IRQ_LINK_DOWN)
|
||||
#define UMAC_IRQ_UMAC (1 << 6)
|
||||
#define UMAC_IRQ_UMAC_TSV (1 << 7)
|
||||
#define UMAC_IRQ_TBUF_UNDERRUN (1 << 8)
|
||||
#define UMAC_IRQ_RBUF_OVERFLOW (1 << 9)
|
||||
#define UMAC_IRQ_HFB_SM (1 << 10)
|
||||
#define UMAC_IRQ_HFB_MM (1 << 11)
|
||||
#define UMAC_IRQ_MPD_R (1 << 12)
|
||||
#define UMAC_IRQ_WAKE_EVENT (UMAC_IRQ_HFB_SM | UMAC_IRQ_HFB_MM | \
|
||||
UMAC_IRQ_MPD_R)
|
||||
#define UMAC_IRQ_RXDMA_MBDONE (1 << 13)
|
||||
#define UMAC_IRQ_RXDMA_PDONE (1 << 14)
|
||||
#define UMAC_IRQ_RXDMA_BDONE (1 << 15)
|
||||
#define UMAC_IRQ_RXDMA_DONE UMAC_IRQ_RXDMA_MBDONE
|
||||
#define UMAC_IRQ_TXDMA_MBDONE (1 << 16)
|
||||
#define UMAC_IRQ_TXDMA_PDONE (1 << 17)
|
||||
#define UMAC_IRQ_TXDMA_BDONE (1 << 18)
|
||||
#define UMAC_IRQ_TXDMA_DONE UMAC_IRQ_TXDMA_MBDONE
|
||||
|
||||
/* Only valid for GENETv3+ */
|
||||
#define UMAC_IRQ_MDIO_DONE (1 << 23)
|
||||
#define UMAC_IRQ_MDIO_ERROR (1 << 24)
|
||||
|
||||
/* INTRL2 instance 1 definitions */
|
||||
#define UMAC_IRQ1_TX_INTR_MASK 0xFFFF
|
||||
#define UMAC_IRQ1_RX_INTR_MASK 0xFFFF
|
||||
#define UMAC_IRQ1_RX_INTR_SHIFT 16
|
||||
|
||||
/* Register block offsets */
|
||||
#define GENET_SYS_OFF 0x0000
|
||||
#define GENET_GR_BRIDGE_OFF 0x0040
|
||||
#define GENET_EXT_OFF 0x0080
|
||||
#define GENET_INTRL2_0_OFF 0x0200
|
||||
#define GENET_INTRL2_1_OFF 0x0240
|
||||
#define GENET_RBUF_OFF 0x0300
|
||||
#define GENET_UMAC_OFF 0x0800
|
||||
|
||||
/* SYS block offsets and register definitions */
|
||||
#define SYS_REV_CTRL 0x00
|
||||
#define SYS_PORT_CTRL 0x04
|
||||
#define PORT_MODE_INT_EPHY 0
|
||||
#define PORT_MODE_INT_GPHY 1
|
||||
#define PORT_MODE_EXT_EPHY 2
|
||||
#define PORT_MODE_EXT_GPHY 3
|
||||
#define PORT_MODE_EXT_RVMII_25 (4 | BIT(4))
|
||||
#define PORT_MODE_EXT_RVMII_50 4
|
||||
#define LED_ACT_SOURCE_MAC (1 << 9)
|
||||
|
||||
#define SYS_RBUF_FLUSH_CTRL 0x08
|
||||
#define SYS_TBUF_FLUSH_CTRL 0x0C
|
||||
#define RBUF_FLUSH_CTRL_V1 0x04
|
||||
|
||||
/* Ext block register offsets and definitions */
|
||||
#define EXT_EXT_PWR_MGMT 0x00
|
||||
#define EXT_PWR_DOWN_BIAS (1 << 0)
|
||||
#define EXT_PWR_DOWN_DLL (1 << 1)
|
||||
#define EXT_PWR_DOWN_PHY (1 << 2)
|
||||
#define EXT_PWR_DN_EN_LD (1 << 3)
|
||||
#define EXT_ENERGY_DET (1 << 4)
|
||||
#define EXT_IDDQ_FROM_PHY (1 << 5)
|
||||
#define EXT_IDDQ_GLBL_PWR (1 << 7)
|
||||
#define EXT_PHY_RESET (1 << 8)
|
||||
#define EXT_ENERGY_DET_MASK (1 << 12)
|
||||
#define EXT_PWR_DOWN_PHY_TX (1 << 16)
|
||||
#define EXT_PWR_DOWN_PHY_RX (1 << 17)
|
||||
#define EXT_PWR_DOWN_PHY_SD (1 << 18)
|
||||
#define EXT_PWR_DOWN_PHY_RD (1 << 19)
|
||||
#define EXT_PWR_DOWN_PHY_EN (1 << 20)
|
||||
|
||||
#define EXT_RGMII_OOB_CTRL 0x0C
|
||||
#define RGMII_MODE_EN_V123 (1 << 0)
|
||||
#define RGMII_LINK (1 << 4)
|
||||
#define OOB_DISABLE (1 << 5)
|
||||
#define RGMII_MODE_EN (1 << 6)
|
||||
#define ID_MODE_DIS (1 << 16)
|
||||
|
||||
#define EXT_GPHY_CTRL 0x1C
|
||||
#define EXT_CFG_IDDQ_BIAS (1 << 0)
|
||||
#define EXT_CFG_PWR_DOWN (1 << 1)
|
||||
#define EXT_CK25_DIS (1 << 4)
|
||||
#define EXT_CFG_IDDQ_GLOBAL_PWR (1 << 3)
|
||||
#define EXT_GPHY_RESET (1 << 5)
|
||||
|
||||
/* DMA rings size */
|
||||
#define DMA_RING_SIZE (0x40)
|
||||
#define DMA_RINGS_SIZE (DMA_RING_SIZE * (DESC_INDEX + 1))
|
||||
|
||||
/* DMA registers common definitions */
|
||||
#define DMA_RW_POINTER_MASK 0x1FF
|
||||
#define DMA_P_INDEX_DISCARD_CNT_MASK 0xFFFF
|
||||
#define DMA_P_INDEX_DISCARD_CNT_SHIFT 16
|
||||
#define DMA_BUFFER_DONE_CNT_MASK 0xFFFF
|
||||
#define DMA_BUFFER_DONE_CNT_SHIFT 16
|
||||
#define DMA_P_INDEX_MASK 0xFFFF
|
||||
#define DMA_C_INDEX_MASK 0xFFFF
|
||||
|
||||
/* DMA ring size register */
|
||||
#define DMA_RING_SIZE_MASK 0xFFFF
|
||||
#define DMA_RING_SIZE_SHIFT 16
|
||||
#define DMA_RING_BUFFER_SIZE_MASK 0xFFFF
|
||||
|
||||
/* DMA interrupt threshold register */
|
||||
#define DMA_INTR_THRESHOLD_MASK 0x01FF
|
||||
|
||||
/* DMA XON/XOFF register */
|
||||
#define DMA_XON_THREHOLD_MASK 0xFFFF
|
||||
#define DMA_XOFF_THRESHOLD_MASK 0xFFFF
|
||||
#define DMA_XOFF_THRESHOLD_SHIFT 16
|
||||
|
||||
/* DMA flow period register */
|
||||
#define DMA_FLOW_PERIOD_MASK 0xFFFF
|
||||
#define DMA_MAX_PKT_SIZE_MASK 0xFFFF
|
||||
#define DMA_MAX_PKT_SIZE_SHIFT 16
|
||||
|
||||
|
||||
/* DMA control register */
|
||||
#define DMA_EN (1 << 0)
|
||||
#define DMA_RING_BUF_EN_SHIFT 0x01
|
||||
#define DMA_RING_BUF_EN_MASK 0xFFFF
|
||||
#define DMA_TSB_SWAP_EN (1 << 20)
|
||||
|
||||
/* DMA status register */
|
||||
#define DMA_DISABLED (1 << 0)
|
||||
#define DMA_DESC_RAM_INIT_BUSY (1 << 1)
|
||||
|
||||
/* DMA SCB burst size register */
|
||||
#define DMA_SCB_BURST_SIZE_MASK 0x1F
|
||||
|
||||
/* DMA activity vector register */
|
||||
#define DMA_ACTIVITY_VECTOR_MASK 0x1FFFF
|
||||
|
||||
/* DMA backpressure mask register */
|
||||
#define DMA_BACKPRESSURE_MASK 0x1FFFF
|
||||
#define DMA_PFC_ENABLE (1 << 31)
|
||||
|
||||
/* DMA backpressure status register */
|
||||
#define DMA_BACKPRESSURE_STATUS_MASK 0x1FFFF
|
||||
|
||||
/* DMA override register */
|
||||
#define DMA_LITTLE_ENDIAN_MODE (1 << 0)
|
||||
#define DMA_REGISTER_MODE (1 << 1)
|
||||
|
||||
/* DMA timeout register */
|
||||
#define DMA_TIMEOUT_MASK 0xFFFF
|
||||
#define DMA_TIMEOUT_VAL 5000 /* micro seconds */
|
||||
|
||||
/* TDMA rate limiting control register */
|
||||
#define DMA_RATE_LIMIT_EN_MASK 0xFFFF
|
||||
|
||||
/* TDMA arbitration control register */
|
||||
#define DMA_ARBITER_MODE_MASK 0x03
|
||||
#define DMA_RING_BUF_PRIORITY_MASK 0x1F
|
||||
#define DMA_RING_BUF_PRIORITY_SHIFT 5
|
||||
#define DMA_PRIO_REG_INDEX(q) ((q) / 6)
|
||||
#define DMA_PRIO_REG_SHIFT(q) (((q) % 6) * DMA_RING_BUF_PRIORITY_SHIFT)
|
||||
#define DMA_RATE_ADJ_MASK 0xFF
|
||||
|
||||
/* Tx/Rx Dma Descriptor common bits*/
|
||||
#define DMA_BUFLENGTH_MASK 0x0fff
|
||||
#define DMA_BUFLENGTH_SHIFT 16
|
||||
#define DMA_OWN 0x8000
|
||||
#define DMA_EOP 0x4000
|
||||
#define DMA_SOP 0x2000
|
||||
#define DMA_WRAP 0x1000
|
||||
/* Tx specific Dma descriptor bits */
|
||||
#define DMA_TX_UNDERRUN 0x0200
|
||||
#define DMA_TX_APPEND_CRC 0x0040
|
||||
#define DMA_TX_OW_CRC 0x0020
|
||||
#define DMA_TX_DO_CSUM 0x0010
|
||||
#define DMA_TX_QTAG_SHIFT 7
|
||||
|
||||
/* Rx Specific Dma descriptor bits */
|
||||
#define DMA_RX_CHK_V3PLUS 0x8000
|
||||
#define DMA_RX_CHK_V12 0x1000
|
||||
#define DMA_RX_BRDCAST 0x0040
|
||||
#define DMA_RX_MULT 0x0020
|
||||
#define DMA_RX_LG 0x0010
|
||||
#define DMA_RX_NO 0x0008
|
||||
#define DMA_RX_RXER 0x0004
|
||||
#define DMA_RX_CRC_ERROR 0x0002
|
||||
#define DMA_RX_OV 0x0001
|
||||
#define DMA_RX_FI_MASK 0x001F
|
||||
#define DMA_RX_FI_SHIFT 0x0007
|
||||
#define DMA_DESC_ALLOC_MASK 0x00FF
|
||||
|
||||
#define DMA_ARBITER_RR 0x00
|
||||
#define DMA_ARBITER_WRR 0x01
|
||||
#define DMA_ARBITER_SP 0x02
|
||||
|
||||
struct enet_cb {
|
||||
struct sk_buff *skb;
|
||||
void __iomem *bd_addr;
|
||||
DEFINE_DMA_UNMAP_ADDR(dma_addr);
|
||||
DEFINE_DMA_UNMAP_LEN(dma_len);
|
||||
};
|
||||
|
||||
/* power management mode */
|
||||
enum bcmgenet_power_mode {
|
||||
GENET_POWER_CABLE_SENSE = 0,
|
||||
GENET_POWER_PASSIVE,
|
||||
GENET_POWER_WOL_MAGIC,
|
||||
};
|
||||
|
||||
struct bcmgenet_priv;
|
||||
|
||||
/* We support both runtime GENET detection and compile-time
|
||||
* to optimize code-paths for a given hardware
|
||||
*/
|
||||
enum bcmgenet_version {
|
||||
GENET_V1 = 1,
|
||||
GENET_V2,
|
||||
GENET_V3,
|
||||
GENET_V4,
|
||||
GENET_V5
|
||||
};
|
||||
|
||||
#define GENET_IS_V1(p) ((p)->version == GENET_V1)
|
||||
#define GENET_IS_V2(p) ((p)->version == GENET_V2)
|
||||
#define GENET_IS_V3(p) ((p)->version == GENET_V3)
|
||||
#define GENET_IS_V4(p) ((p)->version == GENET_V4)
|
||||
#define GENET_IS_V5(p) ((p)->version == GENET_V5)
|
||||
|
||||
/* Hardware flags */
|
||||
#define GENET_HAS_40BITS (1 << 0)
|
||||
#define GENET_HAS_EXT (1 << 1)
|
||||
#define GENET_HAS_MDIO_INTR (1 << 2)
|
||||
#define GENET_HAS_MOCA_LINK_DET (1 << 3)
|
||||
|
||||
/* BCMGENET hardware parameters, keep this structure nicely aligned
|
||||
* since it is going to be used in hot paths
|
||||
*/
|
||||
struct bcmgenet_hw_params {
|
||||
u8 tx_queues;
|
||||
u8 tx_bds_per_q;
|
||||
u8 rx_queues;
|
||||
u8 rx_bds_per_q;
|
||||
u8 bp_in_en_shift;
|
||||
u32 bp_in_mask;
|
||||
u8 hfb_filter_cnt;
|
||||
u8 hfb_filter_size;
|
||||
u8 qtag_mask;
|
||||
u16 tbuf_offset;
|
||||
u32 hfb_offset;
|
||||
u32 hfb_reg_offset;
|
||||
u32 rdma_offset;
|
||||
u32 tdma_offset;
|
||||
u32 words_per_bd;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct bcmgenet_skb_cb {
|
||||
struct enet_cb *first_cb; /* First control block of SKB */
|
||||
struct enet_cb *last_cb; /* Last control block of SKB */
|
||||
unsigned int bytes_sent; /* bytes on the wire (no TSB) */
|
||||
};
|
||||
|
||||
#define GENET_CB(skb) ((struct bcmgenet_skb_cb *)((skb)->cb))
|
||||
|
||||
struct bcmgenet_tx_ring {
|
||||
spinlock_t lock; /* ring lock */
|
||||
struct napi_struct napi; /* NAPI per tx queue */
|
||||
unsigned long packets;
|
||||
unsigned long bytes;
|
||||
unsigned int index; /* ring index */
|
||||
unsigned int queue; /* queue index */
|
||||
struct enet_cb *cbs; /* tx ring buffer control block*/
|
||||
unsigned int size; /* size of each tx ring */
|
||||
unsigned int clean_ptr; /* Tx ring clean pointer */
|
||||
unsigned int c_index; /* last consumer index of each ring*/
|
||||
unsigned int free_bds; /* # of free bds for each ring */
|
||||
unsigned int write_ptr; /* Tx ring write pointer SW copy */
|
||||
unsigned int prod_index; /* Tx ring producer index SW copy */
|
||||
unsigned int cb_ptr; /* Tx ring initial CB ptr */
|
||||
unsigned int end_ptr; /* Tx ring end CB ptr */
|
||||
void (*int_enable)(struct bcmgenet_tx_ring *);
|
||||
void (*int_disable)(struct bcmgenet_tx_ring *);
|
||||
struct bcmgenet_priv *priv;
|
||||
};
|
||||
|
||||
struct bcmgenet_net_dim {
|
||||
u16 use_dim;
|
||||
u16 event_ctr;
|
||||
unsigned long packets;
|
||||
unsigned long bytes;
|
||||
struct dim dim;
|
||||
};
|
||||
|
||||
struct bcmgenet_rx_ring {
|
||||
struct napi_struct napi; /* Rx NAPI struct */
|
||||
unsigned long bytes;
|
||||
unsigned long packets;
|
||||
unsigned long errors;
|
||||
unsigned long dropped;
|
||||
unsigned int index; /* Rx ring index */
|
||||
struct enet_cb *cbs; /* Rx ring buffer control block */
|
||||
unsigned int size; /* Rx ring size */
|
||||
unsigned int c_index; /* Rx last consumer index */
|
||||
unsigned int read_ptr; /* Rx ring read pointer */
|
||||
unsigned int cb_ptr; /* Rx ring initial CB ptr */
|
||||
unsigned int end_ptr; /* Rx ring end CB ptr */
|
||||
unsigned int old_discards;
|
||||
struct bcmgenet_net_dim dim;
|
||||
u32 rx_max_coalesced_frames;
|
||||
u32 rx_coalesce_usecs;
|
||||
void (*int_enable)(struct bcmgenet_rx_ring *);
|
||||
void (*int_disable)(struct bcmgenet_rx_ring *);
|
||||
struct bcmgenet_priv *priv;
|
||||
};
|
||||
|
||||
enum bcmgenet_rxnfc_state {
|
||||
BCMGENET_RXNFC_STATE_UNUSED = 0,
|
||||
BCMGENET_RXNFC_STATE_DISABLED,
|
||||
BCMGENET_RXNFC_STATE_ENABLED
|
||||
};
|
||||
|
||||
struct bcmgenet_rxnfc_rule {
|
||||
struct list_head list;
|
||||
struct ethtool_rx_flow_spec fs;
|
||||
enum bcmgenet_rxnfc_state state;
|
||||
};
|
||||
|
||||
/* device context */
|
||||
struct bcmgenet_priv {
|
||||
void __iomem *base;
|
||||
enum bcmgenet_version version;
|
||||
struct net_device *dev;
|
||||
|
||||
/* transmit variables */
|
||||
void __iomem *tx_bds;
|
||||
struct enet_cb *tx_cbs;
|
||||
unsigned int num_tx_bds;
|
||||
|
||||
struct bcmgenet_tx_ring tx_rings[DESC_INDEX + 1];
|
||||
|
||||
/* receive variables */
|
||||
void __iomem *rx_bds;
|
||||
struct enet_cb *rx_cbs;
|
||||
unsigned int num_rx_bds;
|
||||
unsigned int rx_buf_len;
|
||||
struct bcmgenet_rxnfc_rule rxnfc_rules[MAX_NUM_OF_FS_RULES];
|
||||
struct list_head rxnfc_list;
|
||||
|
||||
struct bcmgenet_rx_ring rx_rings[DESC_INDEX + 1];
|
||||
|
||||
/* other misc variables */
|
||||
struct bcmgenet_hw_params *hw_params;
|
||||
unsigned autoneg_pause:1;
|
||||
unsigned tx_pause:1;
|
||||
unsigned rx_pause:1;
|
||||
|
||||
/* MDIO bus variables */
|
||||
wait_queue_head_t wq;
|
||||
bool internal_phy;
|
||||
struct device_node *phy_dn;
|
||||
struct device_node *mdio_dn;
|
||||
struct mii_bus *mii_bus;
|
||||
u16 gphy_rev;
|
||||
struct clk *clk_eee;
|
||||
bool clk_eee_enabled;
|
||||
|
||||
/* PHY device variables */
|
||||
phy_interface_t phy_interface;
|
||||
int phy_addr;
|
||||
int ext_phy;
|
||||
bool ephy_16nm;
|
||||
|
||||
/* Interrupt variables */
|
||||
struct work_struct bcmgenet_irq_work;
|
||||
int irq0;
|
||||
int irq1;
|
||||
int wol_irq;
|
||||
bool wol_irq_disabled;
|
||||
|
||||
/* shared status */
|
||||
spinlock_t lock;
|
||||
unsigned int irq0_stat;
|
||||
|
||||
/* HW descriptors/checksum variables */
|
||||
bool crc_fwd_en;
|
||||
|
||||
u32 dma_max_burst_length;
|
||||
|
||||
u32 msg_enable;
|
||||
|
||||
struct clk *clk;
|
||||
struct platform_device *pdev;
|
||||
struct platform_device *mii_pdev;
|
||||
|
||||
/* WOL */
|
||||
struct clk *clk_wol;
|
||||
u32 wolopts;
|
||||
u8 sopass[SOPASS_MAX];
|
||||
bool wol_active;
|
||||
|
||||
struct bcmgenet_mib_counters mib;
|
||||
|
||||
struct ethtool_eee eee;
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev;
|
||||
};
|
||||
|
||||
#define GENET_IO_MACRO(name, offset) \
|
||||
static inline u32 bcmgenet_##name##_readl(struct bcmgenet_priv *priv, \
|
||||
u32 off) \
|
||||
{ \
|
||||
/* MIPS chips strapped for BE will automagically configure the \
|
||||
* peripheral registers for CPU-native byte order. \
|
||||
*/ \
|
||||
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
|
||||
return __raw_readl(priv->base + offset + off); \
|
||||
else \
|
||||
return readl_relaxed(priv->base + offset + off); \
|
||||
} \
|
||||
static inline void bcmgenet_##name##_writel(struct bcmgenet_priv *priv, \
|
||||
u32 val, u32 off) \
|
||||
{ \
|
||||
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
|
||||
__raw_writel(val, priv->base + offset + off); \
|
||||
else \
|
||||
writel_relaxed(val, priv->base + offset + off); \
|
||||
}
|
||||
|
||||
GENET_IO_MACRO(ext, GENET_EXT_OFF);
|
||||
GENET_IO_MACRO(umac, GENET_UMAC_OFF);
|
||||
GENET_IO_MACRO(sys, GENET_SYS_OFF);
|
||||
|
||||
/* interrupt l2 registers accessors */
|
||||
GENET_IO_MACRO(intrl2_0, GENET_INTRL2_0_OFF);
|
||||
GENET_IO_MACRO(intrl2_1, GENET_INTRL2_1_OFF);
|
||||
|
||||
/* HFB register accessors */
|
||||
GENET_IO_MACRO(hfb, priv->hw_params->hfb_offset);
|
||||
|
||||
/* GENET v2+ HFB control and filter len helpers */
|
||||
GENET_IO_MACRO(hfb_reg, priv->hw_params->hfb_reg_offset);
|
||||
|
||||
/* RBUF register accessors */
|
||||
GENET_IO_MACRO(rbuf, GENET_RBUF_OFF);
|
||||
|
||||
/* MDIO routines */
|
||||
int bcmgenet_mii_init(struct net_device *dev);
|
||||
int bcmgenet_mii_config(struct net_device *dev, bool init);
|
||||
int bcmgenet_mii_probe(struct net_device *dev);
|
||||
void bcmgenet_mii_exit(struct net_device *dev);
|
||||
void bcmgenet_phy_pause_set(struct net_device *dev, bool rx, bool tx);
|
||||
void bcmgenet_phy_power_set(struct net_device *dev, bool enable);
|
||||
void bcmgenet_mii_setup(struct net_device *dev);
|
||||
|
||||
/* Wake-on-LAN routines */
|
||||
void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
|
||||
int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
|
||||
int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode);
|
||||
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode);
|
||||
|
||||
void bcmgenet_eee_enable_set(struct net_device *dev, bool enable,
|
||||
bool tx_lpi_enabled);
|
||||
|
||||
#endif /* __BCMGENET_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,709 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2014-2020 Broadcom
|
||||
*/
|
||||
|
||||
#ifndef __BCMGENET_H__
|
||||
#define __BCMGENET_H__
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/dim.h>
|
||||
#include <linux/ethtool.h>
|
||||
|
||||
#include "../unimac.h"
|
||||
|
||||
/* total number of Buffer Descriptors, same for Rx/Tx */
|
||||
#define TOTAL_DESC 256
|
||||
|
||||
/* which ring is descriptor based */
|
||||
#define DESC_INDEX 16
|
||||
|
||||
/* Body(1500) + EH_SIZE(14) + VLANTAG(4) + BRCMTAG(6) + FCS(4) = 1528.
|
||||
* 1536 is multiple of 256 bytes
|
||||
*/
|
||||
#define ENET_BRCM_TAG_LEN 6
|
||||
#define ENET_PAD 8
|
||||
#define ENET_MAX_MTU_SIZE (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \
|
||||
ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD)
|
||||
#define DMA_MAX_BURST_LENGTH 0x10
|
||||
|
||||
/* misc. configuration */
|
||||
#define MAX_NUM_OF_FS_RULES 16
|
||||
#define CLEAR_ALL_HFB 0xFF
|
||||
#define DMA_FC_THRESH_HI (TOTAL_DESC >> 4)
|
||||
#define DMA_FC_THRESH_LO 5
|
||||
|
||||
/* 64B receive/transmit status block */
|
||||
struct status_64 {
|
||||
u32 length_status; /* length and peripheral status */
|
||||
u32 ext_status; /* Extended status*/
|
||||
u32 rx_csum; /* partial rx checksum */
|
||||
u32 unused1[9]; /* unused */
|
||||
u32 tx_csum_info; /* Tx checksum info. */
|
||||
u32 unused2[3]; /* unused */
|
||||
};
|
||||
|
||||
/* Rx status bits */
|
||||
#define STATUS_RX_EXT_MASK 0x1FFFFF
|
||||
#define STATUS_RX_CSUM_MASK 0xFFFF
|
||||
#define STATUS_RX_CSUM_OK 0x10000
|
||||
#define STATUS_RX_CSUM_FR 0x20000
|
||||
#define STATUS_RX_PROTO_TCP 0
|
||||
#define STATUS_RX_PROTO_UDP 1
|
||||
#define STATUS_RX_PROTO_ICMP 2
|
||||
#define STATUS_RX_PROTO_OTHER 3
|
||||
#define STATUS_RX_PROTO_MASK 3
|
||||
#define STATUS_RX_PROTO_SHIFT 18
|
||||
#define STATUS_FILTER_INDEX_MASK 0xFFFF
|
||||
/* Tx status bits */
|
||||
#define STATUS_TX_CSUM_START_MASK 0X7FFF
|
||||
#define STATUS_TX_CSUM_START_SHIFT 16
|
||||
#define STATUS_TX_CSUM_PROTO_UDP 0x8000
|
||||
#define STATUS_TX_CSUM_OFFSET_MASK 0x7FFF
|
||||
#define STATUS_TX_CSUM_LV 0x80000000
|
||||
|
||||
/* DMA Descriptor */
|
||||
#define DMA_DESC_LENGTH_STATUS 0x00 /* in bytes of data in buffer */
|
||||
#define DMA_DESC_ADDRESS_LO 0x04 /* lower bits of PA */
|
||||
#define DMA_DESC_ADDRESS_HI 0x08 /* upper 32 bits of PA, GENETv4+ */
|
||||
|
||||
/* Rx/Tx common counter group */
|
||||
struct bcmgenet_pkt_counters {
|
||||
u32 cnt_64; /* RO Received/Transmited 64 bytes packet */
|
||||
u32 cnt_127; /* RO Rx/Tx 127 bytes packet */
|
||||
u32 cnt_255; /* RO Rx/Tx 65-255 bytes packet */
|
||||
u32 cnt_511; /* RO Rx/Tx 256-511 bytes packet */
|
||||
u32 cnt_1023; /* RO Rx/Tx 512-1023 bytes packet */
|
||||
u32 cnt_1518; /* RO Rx/Tx 1024-1518 bytes packet */
|
||||
u32 cnt_mgv; /* RO Rx/Tx 1519-1522 good VLAN packet */
|
||||
u32 cnt_2047; /* RO Rx/Tx 1522-2047 bytes packet*/
|
||||
u32 cnt_4095; /* RO Rx/Tx 2048-4095 bytes packet*/
|
||||
u32 cnt_9216; /* RO Rx/Tx 4096-9216 bytes packet*/
|
||||
};
|
||||
|
||||
/* RSV, Receive Status Vector */
|
||||
struct bcmgenet_rx_counters {
|
||||
struct bcmgenet_pkt_counters pkt_cnt;
|
||||
u32 pkt; /* RO (0x428) Received pkt count*/
|
||||
u32 bytes; /* RO Received byte count */
|
||||
u32 mca; /* RO # of Received multicast pkt */
|
||||
u32 bca; /* RO # of Receive broadcast pkt */
|
||||
u32 fcs; /* RO # of Received FCS error */
|
||||
u32 cf; /* RO # of Received control frame pkt*/
|
||||
u32 pf; /* RO # of Received pause frame pkt */
|
||||
u32 uo; /* RO # of unknown op code pkt */
|
||||
u32 aln; /* RO # of alignment error count */
|
||||
u32 flr; /* RO # of frame length out of range count */
|
||||
u32 cde; /* RO # of code error pkt */
|
||||
u32 fcr; /* RO # of carrier sense error pkt */
|
||||
u32 ovr; /* RO # of oversize pkt*/
|
||||
u32 jbr; /* RO # of jabber count */
|
||||
u32 mtue; /* RO # of MTU error pkt*/
|
||||
u32 pok; /* RO # of Received good pkt */
|
||||
u32 uc; /* RO # of unicast pkt */
|
||||
u32 ppp; /* RO # of PPP pkt */
|
||||
u32 rcrc; /* RO (0x470),# of CRC match pkt */
|
||||
};
|
||||
|
||||
/* TSV, Transmit Status Vector */
|
||||
struct bcmgenet_tx_counters {
|
||||
struct bcmgenet_pkt_counters pkt_cnt;
|
||||
u32 pkts; /* RO (0x4a8) Transmited pkt */
|
||||
u32 mca; /* RO # of xmited multicast pkt */
|
||||
u32 bca; /* RO # of xmited broadcast pkt */
|
||||
u32 pf; /* RO # of xmited pause frame count */
|
||||
u32 cf; /* RO # of xmited control frame count */
|
||||
u32 fcs; /* RO # of xmited FCS error count */
|
||||
u32 ovr; /* RO # of xmited oversize pkt */
|
||||
u32 drf; /* RO # of xmited deferral pkt */
|
||||
u32 edf; /* RO # of xmited Excessive deferral pkt*/
|
||||
u32 scl; /* RO # of xmited single collision pkt */
|
||||
u32 mcl; /* RO # of xmited multiple collision pkt*/
|
||||
u32 lcl; /* RO # of xmited late collision pkt */
|
||||
u32 ecl; /* RO # of xmited excessive collision pkt*/
|
||||
u32 frg; /* RO # of xmited fragments pkt*/
|
||||
u32 ncl; /* RO # of xmited total collision count */
|
||||
u32 jbr; /* RO # of xmited jabber count*/
|
||||
u32 bytes; /* RO # of xmited byte count */
|
||||
u32 pok; /* RO # of xmited good pkt */
|
||||
u32 uc; /* RO (0x0x4f0)# of xmited unitcast pkt */
|
||||
};
|
||||
|
||||
struct bcmgenet_mib_counters {
|
||||
struct bcmgenet_rx_counters rx;
|
||||
struct bcmgenet_tx_counters tx;
|
||||
u32 rx_runt_cnt;
|
||||
u32 rx_runt_fcs;
|
||||
u32 rx_runt_fcs_align;
|
||||
u32 rx_runt_bytes;
|
||||
u32 rbuf_ovflow_cnt;
|
||||
u32 rbuf_err_cnt;
|
||||
u32 mdf_err_cnt;
|
||||
u32 alloc_rx_buff_failed;
|
||||
u32 rx_dma_failed;
|
||||
u32 tx_dma_failed;
|
||||
u32 tx_realloc_tsb;
|
||||
u32 tx_realloc_tsb_failed;
|
||||
};
|
||||
|
||||
#define UMAC_MIB_START 0x400
|
||||
|
||||
#define UMAC_MDIO_CMD 0x614
|
||||
#define MDIO_START_BUSY (1 << 29)
|
||||
#define MDIO_READ_FAIL (1 << 28)
|
||||
#define MDIO_RD (2 << 26)
|
||||
#define MDIO_WR (1 << 26)
|
||||
#define MDIO_PMD_SHIFT 21
|
||||
#define MDIO_PMD_MASK 0x1F
|
||||
#define MDIO_REG_SHIFT 16
|
||||
#define MDIO_REG_MASK 0x1F
|
||||
|
||||
#define UMAC_RBUF_OVFL_CNT_V1 0x61C
|
||||
#define RBUF_OVFL_CNT_V2 0x80
|
||||
#define RBUF_OVFL_CNT_V3PLUS 0x94
|
||||
|
||||
#define UMAC_MPD_CTRL 0x620
|
||||
#define MPD_EN (1 << 0)
|
||||
#define MPD_PW_EN (1 << 27)
|
||||
#define MPD_MSEQ_LEN_SHIFT 16
|
||||
#define MPD_MSEQ_LEN_MASK 0xFF
|
||||
|
||||
#define UMAC_MPD_PW_MS 0x624
|
||||
#define UMAC_MPD_PW_LS 0x628
|
||||
#define UMAC_RBUF_ERR_CNT_V1 0x634
|
||||
#define RBUF_ERR_CNT_V2 0x84
|
||||
#define RBUF_ERR_CNT_V3PLUS 0x98
|
||||
#define UMAC_MDF_ERR_CNT 0x638
|
||||
#define UMAC_MDF_CTRL 0x650
|
||||
#define UMAC_MDF_ADDR 0x654
|
||||
#define UMAC_MIB_CTRL 0x580
|
||||
#define MIB_RESET_RX (1 << 0)
|
||||
#define MIB_RESET_RUNT (1 << 1)
|
||||
#define MIB_RESET_TX (1 << 2)
|
||||
|
||||
#define RBUF_CTRL 0x00
|
||||
#define RBUF_64B_EN (1 << 0)
|
||||
#define RBUF_ALIGN_2B (1 << 1)
|
||||
#define RBUF_BAD_DIS (1 << 2)
|
||||
|
||||
#define RBUF_STATUS 0x0C
|
||||
#define RBUF_STATUS_WOL (1 << 0)
|
||||
#define RBUF_STATUS_MPD_INTR_ACTIVE (1 << 1)
|
||||
#define RBUF_STATUS_ACPI_INTR_ACTIVE (1 << 2)
|
||||
|
||||
#define RBUF_CHK_CTRL 0x14
|
||||
#define RBUF_RXCHK_EN (1 << 0)
|
||||
#define RBUF_SKIP_FCS (1 << 4)
|
||||
#define RBUF_L3_PARSE_DIS (1 << 5)
|
||||
|
||||
#define RBUF_ENERGY_CTRL 0x9c
|
||||
#define RBUF_EEE_EN (1 << 0)
|
||||
#define RBUF_PM_EN (1 << 1)
|
||||
|
||||
#define RBUF_TBUF_SIZE_CTRL 0xb4
|
||||
|
||||
#define RBUF_HFB_CTRL_V1 0x38
|
||||
#define RBUF_HFB_FILTER_EN_SHIFT 16
|
||||
#define RBUF_HFB_FILTER_EN_MASK 0xffff0000
|
||||
#define RBUF_HFB_EN (1 << 0)
|
||||
#define RBUF_HFB_256B (1 << 1)
|
||||
#define RBUF_ACPI_EN (1 << 2)
|
||||
|
||||
#define RBUF_HFB_LEN_V1 0x3C
|
||||
#define RBUF_FLTR_LEN_MASK 0xFF
|
||||
#define RBUF_FLTR_LEN_SHIFT 8
|
||||
|
||||
#define TBUF_CTRL 0x00
|
||||
#define TBUF_64B_EN (1 << 0)
|
||||
#define TBUF_BP_MC 0x0C
|
||||
#define TBUF_ENERGY_CTRL 0x14
|
||||
#define TBUF_EEE_EN (1 << 0)
|
||||
#define TBUF_PM_EN (1 << 1)
|
||||
|
||||
#define TBUF_CTRL_V1 0x80
|
||||
#define TBUF_BP_MC_V1 0xA0
|
||||
|
||||
#define HFB_CTRL 0x00
|
||||
#define HFB_FLT_ENABLE_V3PLUS 0x04
|
||||
#define HFB_FLT_LEN_V2 0x04
|
||||
#define HFB_FLT_LEN_V3PLUS 0x1C
|
||||
|
||||
/* uniMac intrl2 registers */
|
||||
#define INTRL2_CPU_STAT 0x00
|
||||
#define INTRL2_CPU_SET 0x04
|
||||
#define INTRL2_CPU_CLEAR 0x08
|
||||
#define INTRL2_CPU_MASK_STATUS 0x0C
|
||||
#define INTRL2_CPU_MASK_SET 0x10
|
||||
#define INTRL2_CPU_MASK_CLEAR 0x14
|
||||
|
||||
/* INTRL2 instance 0 definitions */
|
||||
#define UMAC_IRQ_SCB (1 << 0)
|
||||
#define UMAC_IRQ_EPHY (1 << 1)
|
||||
#define UMAC_IRQ_PHY_DET_R (1 << 2)
|
||||
#define UMAC_IRQ_PHY_DET_F (1 << 3)
|
||||
#define UMAC_IRQ_LINK_UP (1 << 4)
|
||||
#define UMAC_IRQ_LINK_DOWN (1 << 5)
|
||||
#define UMAC_IRQ_LINK_EVENT (UMAC_IRQ_LINK_UP | UMAC_IRQ_LINK_DOWN)
|
||||
#define UMAC_IRQ_UMAC (1 << 6)
|
||||
#define UMAC_IRQ_UMAC_TSV (1 << 7)
|
||||
#define UMAC_IRQ_TBUF_UNDERRUN (1 << 8)
|
||||
#define UMAC_IRQ_RBUF_OVERFLOW (1 << 9)
|
||||
#define UMAC_IRQ_HFB_SM (1 << 10)
|
||||
#define UMAC_IRQ_HFB_MM (1 << 11)
|
||||
#define UMAC_IRQ_MPD_R (1 << 12)
|
||||
#define UMAC_IRQ_WAKE_EVENT (UMAC_IRQ_HFB_SM | UMAC_IRQ_HFB_MM | \
|
||||
UMAC_IRQ_MPD_R)
|
||||
#define UMAC_IRQ_RXDMA_MBDONE (1 << 13)
|
||||
#define UMAC_IRQ_RXDMA_PDONE (1 << 14)
|
||||
#define UMAC_IRQ_RXDMA_BDONE (1 << 15)
|
||||
#define UMAC_IRQ_RXDMA_DONE UMAC_IRQ_RXDMA_MBDONE
|
||||
#define UMAC_IRQ_TXDMA_MBDONE (1 << 16)
|
||||
#define UMAC_IRQ_TXDMA_PDONE (1 << 17)
|
||||
#define UMAC_IRQ_TXDMA_BDONE (1 << 18)
|
||||
#define UMAC_IRQ_TXDMA_DONE UMAC_IRQ_TXDMA_MBDONE
|
||||
|
||||
/* Only valid for GENETv3+ */
|
||||
#define UMAC_IRQ_MDIO_DONE (1 << 23)
|
||||
#define UMAC_IRQ_MDIO_ERROR (1 << 24)
|
||||
|
||||
/* INTRL2 instance 1 definitions */
|
||||
#define UMAC_IRQ1_TX_INTR_MASK 0xFFFF
|
||||
#define UMAC_IRQ1_RX_INTR_MASK 0xFFFF
|
||||
#define UMAC_IRQ1_RX_INTR_SHIFT 16
|
||||
|
||||
/* Register block offsets */
|
||||
#define GENET_SYS_OFF 0x0000
|
||||
#define GENET_GR_BRIDGE_OFF 0x0040
|
||||
#define GENET_EXT_OFF 0x0080
|
||||
#define GENET_INTRL2_0_OFF 0x0200
|
||||
#define GENET_INTRL2_1_OFF 0x0240
|
||||
#define GENET_RBUF_OFF 0x0300
|
||||
#define GENET_UMAC_OFF 0x0800
|
||||
|
||||
/* SYS block offsets and register definitions */
|
||||
#define SYS_REV_CTRL 0x00
|
||||
#define SYS_PORT_CTRL 0x04
|
||||
#define PORT_MODE_INT_EPHY 0
|
||||
#define PORT_MODE_INT_GPHY 1
|
||||
#define PORT_MODE_EXT_EPHY 2
|
||||
#define PORT_MODE_EXT_GPHY 3
|
||||
#define PORT_MODE_EXT_RVMII_25 (4 | BIT(4))
|
||||
#define PORT_MODE_EXT_RVMII_50 4
|
||||
#define LED_ACT_SOURCE_MAC (1 << 9)
|
||||
|
||||
#define SYS_RBUF_FLUSH_CTRL 0x08
|
||||
#define SYS_TBUF_FLUSH_CTRL 0x0C
|
||||
#define RBUF_FLUSH_CTRL_V1 0x04
|
||||
|
||||
/* Ext block register offsets and definitions */
|
||||
#define EXT_EXT_PWR_MGMT 0x00
|
||||
#define EXT_PWR_DOWN_BIAS (1 << 0)
|
||||
#define EXT_PWR_DOWN_DLL (1 << 1)
|
||||
#define EXT_PWR_DOWN_PHY (1 << 2)
|
||||
#define EXT_PWR_DN_EN_LD (1 << 3)
|
||||
#define EXT_ENERGY_DET (1 << 4)
|
||||
#define EXT_IDDQ_FROM_PHY (1 << 5)
|
||||
#define EXT_IDDQ_GLBL_PWR (1 << 7)
|
||||
#define EXT_PHY_RESET (1 << 8)
|
||||
#define EXT_ENERGY_DET_MASK (1 << 12)
|
||||
#define EXT_PWR_DOWN_PHY_TX (1 << 16)
|
||||
#define EXT_PWR_DOWN_PHY_RX (1 << 17)
|
||||
#define EXT_PWR_DOWN_PHY_SD (1 << 18)
|
||||
#define EXT_PWR_DOWN_PHY_RD (1 << 19)
|
||||
#define EXT_PWR_DOWN_PHY_EN (1 << 20)
|
||||
|
||||
#define EXT_RGMII_OOB_CTRL 0x0C
|
||||
#define RGMII_MODE_EN_V123 (1 << 0)
|
||||
#define RGMII_LINK (1 << 4)
|
||||
#define OOB_DISABLE (1 << 5)
|
||||
#define RGMII_MODE_EN (1 << 6)
|
||||
#define ID_MODE_DIS (1 << 16)
|
||||
|
||||
#define EXT_GPHY_CTRL 0x1C
|
||||
#define EXT_CFG_IDDQ_BIAS (1 << 0)
|
||||
#define EXT_CFG_PWR_DOWN (1 << 1)
|
||||
#define EXT_CK25_DIS (1 << 4)
|
||||
#define EXT_CFG_IDDQ_GLOBAL_PWR (1 << 3)
|
||||
#define EXT_GPHY_RESET (1 << 5)
|
||||
|
||||
/* DMA rings size */
|
||||
#define DMA_RING_SIZE (0x40)
|
||||
#define DMA_RINGS_SIZE (DMA_RING_SIZE * (DESC_INDEX + 1))
|
||||
|
||||
/* DMA registers common definitions */
|
||||
#define DMA_RW_POINTER_MASK 0x1FF
|
||||
#define DMA_P_INDEX_DISCARD_CNT_MASK 0xFFFF
|
||||
#define DMA_P_INDEX_DISCARD_CNT_SHIFT 16
|
||||
#define DMA_BUFFER_DONE_CNT_MASK 0xFFFF
|
||||
#define DMA_BUFFER_DONE_CNT_SHIFT 16
|
||||
#define DMA_P_INDEX_MASK 0xFFFF
|
||||
#define DMA_C_INDEX_MASK 0xFFFF
|
||||
|
||||
/* DMA ring size register */
|
||||
#define DMA_RING_SIZE_MASK 0xFFFF
|
||||
#define DMA_RING_SIZE_SHIFT 16
|
||||
#define DMA_RING_BUFFER_SIZE_MASK 0xFFFF
|
||||
|
||||
/* DMA interrupt threshold register */
|
||||
#define DMA_INTR_THRESHOLD_MASK 0x01FF
|
||||
|
||||
/* DMA XON/XOFF register */
|
||||
#define DMA_XON_THREHOLD_MASK 0xFFFF
|
||||
#define DMA_XOFF_THRESHOLD_MASK 0xFFFF
|
||||
#define DMA_XOFF_THRESHOLD_SHIFT 16
|
||||
|
||||
/* DMA flow period register */
|
||||
#define DMA_FLOW_PERIOD_MASK 0xFFFF
|
||||
#define DMA_MAX_PKT_SIZE_MASK 0xFFFF
|
||||
#define DMA_MAX_PKT_SIZE_SHIFT 16
|
||||
|
||||
|
||||
/* DMA control register */
|
||||
#define DMA_EN (1 << 0)
|
||||
#define DMA_RING_BUF_EN_SHIFT 0x01
|
||||
#define DMA_RING_BUF_EN_MASK 0xFFFF
|
||||
#define DMA_TSB_SWAP_EN (1 << 20)
|
||||
|
||||
/* DMA status register */
|
||||
#define DMA_DISABLED (1 << 0)
|
||||
#define DMA_DESC_RAM_INIT_BUSY (1 << 1)
|
||||
|
||||
/* DMA SCB burst size register */
|
||||
#define DMA_SCB_BURST_SIZE_MASK 0x1F
|
||||
|
||||
/* DMA activity vector register */
|
||||
#define DMA_ACTIVITY_VECTOR_MASK 0x1FFFF
|
||||
|
||||
/* DMA backpressure mask register */
|
||||
#define DMA_BACKPRESSURE_MASK 0x1FFFF
|
||||
#define DMA_PFC_ENABLE (1 << 31)
|
||||
|
||||
/* DMA backpressure status register */
|
||||
#define DMA_BACKPRESSURE_STATUS_MASK 0x1FFFF
|
||||
|
||||
/* DMA override register */
|
||||
#define DMA_LITTLE_ENDIAN_MODE (1 << 0)
|
||||
#define DMA_REGISTER_MODE (1 << 1)
|
||||
|
||||
/* DMA timeout register */
|
||||
#define DMA_TIMEOUT_MASK 0xFFFF
|
||||
#define DMA_TIMEOUT_VAL 5000 /* micro seconds */
|
||||
|
||||
/* TDMA rate limiting control register */
|
||||
#define DMA_RATE_LIMIT_EN_MASK 0xFFFF
|
||||
|
||||
/* TDMA arbitration control register */
|
||||
#define DMA_ARBITER_MODE_MASK 0x03
|
||||
#define DMA_RING_BUF_PRIORITY_MASK 0x1F
|
||||
#define DMA_RING_BUF_PRIORITY_SHIFT 5
|
||||
#define DMA_PRIO_REG_INDEX(q) ((q) / 6)
|
||||
#define DMA_PRIO_REG_SHIFT(q) (((q) % 6) * DMA_RING_BUF_PRIORITY_SHIFT)
|
||||
#define DMA_RATE_ADJ_MASK 0xFF
|
||||
|
||||
/* Tx/Rx Dma Descriptor common bits*/
|
||||
#define DMA_BUFLENGTH_MASK 0x0fff
|
||||
#define DMA_BUFLENGTH_SHIFT 16
|
||||
#define DMA_OWN 0x8000
|
||||
#define DMA_EOP 0x4000
|
||||
#define DMA_SOP 0x2000
|
||||
#define DMA_WRAP 0x1000
|
||||
/* Tx specific Dma descriptor bits */
|
||||
#define DMA_TX_UNDERRUN 0x0200
|
||||
#define DMA_TX_APPEND_CRC 0x0040
|
||||
#define DMA_TX_OW_CRC 0x0020
|
||||
#define DMA_TX_DO_CSUM 0x0010
|
||||
#define DMA_TX_QTAG_SHIFT 7
|
||||
|
||||
/* Rx Specific Dma descriptor bits */
|
||||
#define DMA_RX_CHK_V3PLUS 0x8000
|
||||
#define DMA_RX_CHK_V12 0x1000
|
||||
#define DMA_RX_BRDCAST 0x0040
|
||||
#define DMA_RX_MULT 0x0020
|
||||
#define DMA_RX_LG 0x0010
|
||||
#define DMA_RX_NO 0x0008
|
||||
#define DMA_RX_RXER 0x0004
|
||||
#define DMA_RX_CRC_ERROR 0x0002
|
||||
#define DMA_RX_OV 0x0001
|
||||
#define DMA_RX_FI_MASK 0x001F
|
||||
#define DMA_RX_FI_SHIFT 0x0007
|
||||
#define DMA_DESC_ALLOC_MASK 0x00FF
|
||||
|
||||
#define DMA_ARBITER_RR 0x00
|
||||
#define DMA_ARBITER_WRR 0x01
|
||||
#define DMA_ARBITER_SP 0x02
|
||||
|
||||
struct enet_cb {
|
||||
struct sk_buff *skb;
|
||||
void __iomem *bd_addr;
|
||||
DEFINE_DMA_UNMAP_ADDR(dma_addr);
|
||||
DEFINE_DMA_UNMAP_LEN(dma_len);
|
||||
};
|
||||
|
||||
/* power management mode */
|
||||
enum bcmgenet_power_mode {
|
||||
GENET_POWER_CABLE_SENSE = 0,
|
||||
GENET_POWER_PASSIVE,
|
||||
GENET_POWER_WOL_MAGIC,
|
||||
};
|
||||
|
||||
struct bcmgenet_priv;
|
||||
|
||||
/* We support both runtime GENET detection and compile-time
|
||||
* to optimize code-paths for a given hardware
|
||||
*/
|
||||
enum bcmgenet_version {
|
||||
GENET_V1 = 1,
|
||||
GENET_V2,
|
||||
GENET_V3,
|
||||
GENET_V4,
|
||||
GENET_V5
|
||||
};
|
||||
|
||||
#define GENET_IS_V1(p) ((p)->version == GENET_V1)
|
||||
#define GENET_IS_V2(p) ((p)->version == GENET_V2)
|
||||
#define GENET_IS_V3(p) ((p)->version == GENET_V3)
|
||||
#define GENET_IS_V4(p) ((p)->version == GENET_V4)
|
||||
#define GENET_IS_V5(p) ((p)->version == GENET_V5)
|
||||
|
||||
/* Hardware flags */
|
||||
#define GENET_HAS_40BITS (1 << 0)
|
||||
#define GENET_HAS_EXT (1 << 1)
|
||||
#define GENET_HAS_MDIO_INTR (1 << 2)
|
||||
#define GENET_HAS_MOCA_LINK_DET (1 << 3)
|
||||
|
||||
/* BCMGENET hardware parameters, keep this structure nicely aligned
|
||||
* since it is going to be used in hot paths
|
||||
*/
|
||||
struct bcmgenet_hw_params {
|
||||
u8 tx_queues;
|
||||
u8 tx_bds_per_q;
|
||||
u8 rx_queues;
|
||||
u8 rx_bds_per_q;
|
||||
u8 bp_in_en_shift;
|
||||
u32 bp_in_mask;
|
||||
u8 hfb_filter_cnt;
|
||||
u8 hfb_filter_size;
|
||||
u8 qtag_mask;
|
||||
u16 tbuf_offset;
|
||||
u32 hfb_offset;
|
||||
u32 hfb_reg_offset;
|
||||
u32 rdma_offset;
|
||||
u32 tdma_offset;
|
||||
u32 words_per_bd;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
struct bcmgenet_skb_cb {
|
||||
struct enet_cb *first_cb; /* First control block of SKB */
|
||||
struct enet_cb *last_cb; /* Last control block of SKB */
|
||||
unsigned int bytes_sent; /* bytes on the wire (no TSB) */
|
||||
};
|
||||
|
||||
#define GENET_CB(skb) ((struct bcmgenet_skb_cb *)((skb)->cb))
|
||||
|
||||
struct bcmgenet_tx_ring {
|
||||
spinlock_t lock; /* ring lock */
|
||||
struct napi_struct napi; /* NAPI per tx queue */
|
||||
unsigned long packets;
|
||||
unsigned long bytes;
|
||||
unsigned int index; /* ring index */
|
||||
unsigned int queue; /* queue index */
|
||||
struct enet_cb *cbs; /* tx ring buffer control block*/
|
||||
unsigned int size; /* size of each tx ring */
|
||||
unsigned int clean_ptr; /* Tx ring clean pointer */
|
||||
unsigned int c_index; /* last consumer index of each ring*/
|
||||
unsigned int free_bds; /* # of free bds for each ring */
|
||||
unsigned int write_ptr; /* Tx ring write pointer SW copy */
|
||||
unsigned int prod_index; /* Tx ring producer index SW copy */
|
||||
unsigned int cb_ptr; /* Tx ring initial CB ptr */
|
||||
unsigned int end_ptr; /* Tx ring end CB ptr */
|
||||
void (*int_enable)(struct bcmgenet_tx_ring *);
|
||||
void (*int_disable)(struct bcmgenet_tx_ring *);
|
||||
struct bcmgenet_priv *priv;
|
||||
};
|
||||
|
||||
struct bcmgenet_net_dim {
|
||||
u16 use_dim;
|
||||
u16 event_ctr;
|
||||
unsigned long packets;
|
||||
unsigned long bytes;
|
||||
struct dim dim;
|
||||
};
|
||||
|
||||
struct bcmgenet_rx_ring {
|
||||
struct napi_struct napi; /* Rx NAPI struct */
|
||||
unsigned long bytes;
|
||||
unsigned long packets;
|
||||
unsigned long errors;
|
||||
unsigned long dropped;
|
||||
unsigned int index; /* Rx ring index */
|
||||
struct enet_cb *cbs; /* Rx ring buffer control block */
|
||||
unsigned int size; /* Rx ring size */
|
||||
unsigned int c_index; /* Rx last consumer index */
|
||||
unsigned int read_ptr; /* Rx ring read pointer */
|
||||
unsigned int cb_ptr; /* Rx ring initial CB ptr */
|
||||
unsigned int end_ptr; /* Rx ring end CB ptr */
|
||||
unsigned int old_discards;
|
||||
struct bcmgenet_net_dim dim;
|
||||
u32 rx_max_coalesced_frames;
|
||||
u32 rx_coalesce_usecs;
|
||||
void (*int_enable)(struct bcmgenet_rx_ring *);
|
||||
void (*int_disable)(struct bcmgenet_rx_ring *);
|
||||
struct bcmgenet_priv *priv;
|
||||
};
|
||||
|
||||
enum bcmgenet_rxnfc_state {
|
||||
BCMGENET_RXNFC_STATE_UNUSED = 0,
|
||||
BCMGENET_RXNFC_STATE_DISABLED,
|
||||
BCMGENET_RXNFC_STATE_ENABLED
|
||||
};
|
||||
|
||||
struct bcmgenet_rxnfc_rule {
|
||||
struct list_head list;
|
||||
struct ethtool_rx_flow_spec fs;
|
||||
enum bcmgenet_rxnfc_state state;
|
||||
};
|
||||
|
||||
/* device context */
|
||||
struct bcmgenet_priv {
|
||||
void __iomem *base;
|
||||
enum bcmgenet_version version;
|
||||
struct net_device *dev;
|
||||
|
||||
/* transmit variables */
|
||||
void __iomem *tx_bds;
|
||||
struct enet_cb *tx_cbs;
|
||||
unsigned int num_tx_bds;
|
||||
|
||||
struct bcmgenet_tx_ring tx_rings[DESC_INDEX + 1];
|
||||
|
||||
/* receive variables */
|
||||
void __iomem *rx_bds;
|
||||
struct enet_cb *rx_cbs;
|
||||
unsigned int num_rx_bds;
|
||||
unsigned int rx_buf_len;
|
||||
struct bcmgenet_rxnfc_rule rxnfc_rules[MAX_NUM_OF_FS_RULES];
|
||||
struct list_head rxnfc_list;
|
||||
|
||||
struct bcmgenet_rx_ring rx_rings[DESC_INDEX + 1];
|
||||
|
||||
/* other misc variables */
|
||||
struct bcmgenet_hw_params *hw_params;
|
||||
unsigned autoneg_pause:1;
|
||||
unsigned tx_pause:1;
|
||||
unsigned rx_pause:1;
|
||||
|
||||
/* MDIO bus variables */
|
||||
wait_queue_head_t wq;
|
||||
bool internal_phy;
|
||||
struct device_node *phy_dn;
|
||||
struct device_node *mdio_dn;
|
||||
struct mii_bus *mii_bus;
|
||||
u16 gphy_rev;
|
||||
struct clk *clk_eee;
|
||||
bool clk_eee_enabled;
|
||||
|
||||
/* PHY device variables */
|
||||
phy_interface_t phy_interface;
|
||||
int phy_addr;
|
||||
int ext_phy;
|
||||
bool ephy_16nm;
|
||||
|
||||
/* Interrupt variables */
|
||||
struct work_struct bcmgenet_irq_work;
|
||||
int irq0;
|
||||
int irq1;
|
||||
int wol_irq;
|
||||
bool wol_irq_disabled;
|
||||
|
||||
/* shared status */
|
||||
spinlock_t lock;
|
||||
unsigned int irq0_stat;
|
||||
|
||||
/* HW descriptors/checksum variables */
|
||||
bool crc_fwd_en;
|
||||
|
||||
u32 dma_max_burst_length;
|
||||
|
||||
u32 msg_enable;
|
||||
|
||||
struct clk *clk;
|
||||
struct platform_device *pdev;
|
||||
struct platform_device *mii_pdev;
|
||||
|
||||
/* WOL */
|
||||
struct clk *clk_wol;
|
||||
u32 wolopts;
|
||||
u8 sopass[SOPASS_MAX];
|
||||
bool wol_active;
|
||||
|
||||
struct bcmgenet_mib_counters mib;
|
||||
|
||||
struct ethtool_eee eee;
|
||||
};
|
||||
|
||||
#define GENET_IO_MACRO(name, offset) \
|
||||
static inline u32 bcmgenet_##name##_readl(struct bcmgenet_priv *priv, \
|
||||
u32 off) \
|
||||
{ \
|
||||
/* MIPS chips strapped for BE will automagically configure the \
|
||||
* peripheral registers for CPU-native byte order. \
|
||||
*/ \
|
||||
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
|
||||
return __raw_readl(priv->base + offset + off); \
|
||||
else \
|
||||
return readl_relaxed(priv->base + offset + off); \
|
||||
} \
|
||||
static inline void bcmgenet_##name##_writel(struct bcmgenet_priv *priv, \
|
||||
u32 val, u32 off) \
|
||||
{ \
|
||||
if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \
|
||||
__raw_writel(val, priv->base + offset + off); \
|
||||
else \
|
||||
writel_relaxed(val, priv->base + offset + off); \
|
||||
}
|
||||
|
||||
GENET_IO_MACRO(ext, GENET_EXT_OFF);
|
||||
GENET_IO_MACRO(umac, GENET_UMAC_OFF);
|
||||
GENET_IO_MACRO(sys, GENET_SYS_OFF);
|
||||
|
||||
/* interrupt l2 registers accessors */
|
||||
GENET_IO_MACRO(intrl2_0, GENET_INTRL2_0_OFF);
|
||||
GENET_IO_MACRO(intrl2_1, GENET_INTRL2_1_OFF);
|
||||
|
||||
/* HFB register accessors */
|
||||
GENET_IO_MACRO(hfb, priv->hw_params->hfb_offset);
|
||||
|
||||
/* GENET v2+ HFB control and filter len helpers */
|
||||
GENET_IO_MACRO(hfb_reg, priv->hw_params->hfb_reg_offset);
|
||||
|
||||
/* RBUF register accessors */
|
||||
GENET_IO_MACRO(rbuf, GENET_RBUF_OFF);
|
||||
|
||||
/* MDIO routines */
|
||||
int bcmgenet_mii_init(struct net_device *dev);
|
||||
int bcmgenet_mii_config(struct net_device *dev, bool init);
|
||||
int bcmgenet_mii_probe(struct net_device *dev);
|
||||
void bcmgenet_mii_exit(struct net_device *dev);
|
||||
void bcmgenet_phy_pause_set(struct net_device *dev, bool rx, bool tx);
|
||||
void bcmgenet_phy_power_set(struct net_device *dev, bool enable);
|
||||
void bcmgenet_mii_setup(struct net_device *dev);
|
||||
|
||||
/* Wake-on-LAN routines */
|
||||
void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
|
||||
int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol);
|
||||
int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode);
|
||||
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode);
|
||||
|
||||
void bcmgenet_eee_enable_set(struct net_device *dev, bool enable,
|
||||
bool tx_lpi_enabled);
|
||||
|
||||
#endif /* __BCMGENET_H__ */
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
|
||||
*
|
||||
* Copyright (c) 2014-2020 Broadcom
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "bcmgenet_wol: " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <net/arp.h>
|
||||
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
#include "bcmgenet-6.1-ethercat.h"
|
||||
|
||||
/* ethtool function - get WOL (Wake on LAN) settings, Only Magic Packet
|
||||
* Detection is supported through ethtool
|
||||
*/
|
||||
void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
|
||||
if (!device_can_wakeup(kdev)) {
|
||||
wol->supported = 0;
|
||||
wol->wolopts = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
|
||||
wol->wolopts = priv->wolopts;
|
||||
memset(wol->sopass, 0, sizeof(wol->sopass));
|
||||
|
||||
if (wol->wolopts & WAKE_MAGICSECURE)
|
||||
memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
|
||||
}
|
||||
|
||||
/* ethtool function - set WOL (Wake on LAN) settings.
|
||||
* Only for magic packet detection mode.
|
||||
*/
|
||||
int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
|
||||
if (!device_can_wakeup(kdev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (wol->wolopts & ~(WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER))
|
||||
return -EINVAL;
|
||||
|
||||
if (wol->wolopts & WAKE_MAGICSECURE)
|
||||
memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
|
||||
|
||||
/* Flag the device and relevant IRQ as wakeup capable */
|
||||
if (wol->wolopts) {
|
||||
device_set_wakeup_enable(kdev, 1);
|
||||
/* Avoid unbalanced enable_irq_wake calls */
|
||||
if (priv->wol_irq_disabled)
|
||||
enable_irq_wake(priv->wol_irq);
|
||||
priv->wol_irq_disabled = false;
|
||||
} else {
|
||||
device_set_wakeup_enable(kdev, 0);
|
||||
/* Avoid unbalanced disable_irq_wake calls */
|
||||
if (!priv->wol_irq_disabled)
|
||||
disable_irq_wake(priv->wol_irq);
|
||||
priv->wol_irq_disabled = true;
|
||||
}
|
||||
|
||||
priv->wolopts = wol->wolopts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcmgenet_poll_wol_status(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct net_device *dev = priv->dev;
|
||||
int retries = 0;
|
||||
|
||||
while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS)
|
||||
& RBUF_STATUS_WOL)) {
|
||||
retries++;
|
||||
if (retries > 5) {
|
||||
netdev_crit(dev, "polling wol mode timeout\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
return retries;
|
||||
}
|
||||
|
||||
static void bcmgenet_set_mpd_password(struct bcmgenet_priv *priv)
|
||||
{
|
||||
bcmgenet_umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
|
||||
UMAC_MPD_PW_MS);
|
||||
bcmgenet_umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
|
||||
UMAC_MPD_PW_LS);
|
||||
}
|
||||
|
||||
int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode)
|
||||
{
|
||||
struct net_device *dev = priv->dev;
|
||||
struct bcmgenet_rxnfc_rule *rule;
|
||||
u32 reg, hfb_ctrl_reg, hfb_enable = 0;
|
||||
int retries = 0;
|
||||
|
||||
if (mode != GENET_POWER_WOL_MAGIC) {
|
||||
netif_err(priv, wol, dev, "unsupported mode: %d\n", mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Can't suspend with WoL if MAC is still in reset */
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||
if (reg & CMD_SW_RESET)
|
||||
reg &= ~CMD_SW_RESET;
|
||||
|
||||
/* disable RX */
|
||||
reg &= ~CMD_RX_EN;
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
mdelay(10);
|
||||
|
||||
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||
reg |= MPD_EN;
|
||||
if (priv->wolopts & WAKE_MAGICSECURE) {
|
||||
bcmgenet_set_mpd_password(priv);
|
||||
reg |= MPD_PW_EN;
|
||||
}
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||
}
|
||||
|
||||
hfb_ctrl_reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
|
||||
if (priv->wolopts & WAKE_FILTER) {
|
||||
list_for_each_entry(rule, &priv->rxnfc_list, list)
|
||||
if (rule->fs.ring_cookie == RX_CLS_FLOW_WAKE)
|
||||
hfb_enable |= (1 << rule->fs.location);
|
||||
reg = (hfb_ctrl_reg & ~RBUF_HFB_EN) | RBUF_ACPI_EN;
|
||||
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||
}
|
||||
|
||||
/* Do not leave UniMAC in MPD mode only */
|
||||
retries = bcmgenet_poll_wol_status(priv);
|
||||
if (retries < 0) {
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||
reg &= ~(MPD_EN | MPD_PW_EN);
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||
bcmgenet_hfb_reg_writel(priv, hfb_ctrl_reg, HFB_CTRL);
|
||||
return retries;
|
||||
}
|
||||
|
||||
netif_dbg(priv, wol, dev, "MPD WOL-ready status set after %d msec\n",
|
||||
retries);
|
||||
|
||||
clk_prepare_enable(priv->clk_wol);
|
||||
priv->wol_active = 1;
|
||||
|
||||
if (hfb_enable) {
|
||||
bcmgenet_hfb_reg_writel(priv, hfb_enable,
|
||||
HFB_FLT_ENABLE_V3PLUS + 4);
|
||||
hfb_ctrl_reg = RBUF_HFB_EN | RBUF_ACPI_EN;
|
||||
bcmgenet_hfb_reg_writel(priv, hfb_ctrl_reg, HFB_CTRL);
|
||||
}
|
||||
|
||||
/* Enable CRC forward */
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||
priv->crc_fwd_en = 1;
|
||||
reg |= CMD_CRC_FWD;
|
||||
|
||||
/* Receiver must be enabled for WOL MP detection */
|
||||
reg |= CMD_RX_EN;
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
|
||||
reg = UMAC_IRQ_MPD_R;
|
||||
if (hfb_enable)
|
||||
reg |= UMAC_IRQ_HFB_SM | UMAC_IRQ_HFB_MM;
|
||||
|
||||
bcmgenet_intrl2_0_writel(priv, reg, INTRL2_CPU_MASK_CLEAR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (mode != GENET_POWER_WOL_MAGIC) {
|
||||
netif_err(priv, wol, priv->dev, "invalid mode: %d\n", mode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!priv->wol_active)
|
||||
return; /* failed to suspend so skip the rest */
|
||||
|
||||
priv->wol_active = 0;
|
||||
clk_disable_unprepare(priv->clk_wol);
|
||||
priv->crc_fwd_en = 0;
|
||||
|
||||
/* Disable Magic Packet Detection */
|
||||
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||
if (!(reg & MPD_EN))
|
||||
return; /* already reset so skip the rest */
|
||||
reg &= ~(MPD_EN | MPD_PW_EN);
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||
}
|
||||
|
||||
/* Disable WAKE_FILTER Detection */
|
||||
if (priv->wolopts & WAKE_FILTER) {
|
||||
reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
|
||||
if (!(reg & RBUF_ACPI_EN))
|
||||
return; /* already reset so skip the rest */
|
||||
reg &= ~(RBUF_HFB_EN | RBUF_ACPI_EN);
|
||||
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||
}
|
||||
|
||||
/* Disable CRC Forward */
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||
reg &= ~CMD_CRC_FWD;
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
}
|
||||
|
|
@ -0,0 +1,244 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
|
||||
*
|
||||
* Copyright (c) 2014-2020 Broadcom
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "bcmgenet_wol: " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <net/arp.h>
|
||||
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/inetdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/phy.h>
|
||||
|
||||
#include "bcmgenet.h"
|
||||
|
||||
/* ethtool function - get WOL (Wake on LAN) settings, Only Magic Packet
|
||||
* Detection is supported through ethtool
|
||||
*/
|
||||
void bcmgenet_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
|
||||
if (!device_can_wakeup(kdev)) {
|
||||
wol->supported = 0;
|
||||
wol->wolopts = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
|
||||
wol->wolopts = priv->wolopts;
|
||||
memset(wol->sopass, 0, sizeof(wol->sopass));
|
||||
|
||||
if (wol->wolopts & WAKE_MAGICSECURE)
|
||||
memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
|
||||
}
|
||||
|
||||
/* ethtool function - set WOL (Wake on LAN) settings.
|
||||
* Only for magic packet detection mode.
|
||||
*/
|
||||
int bcmgenet_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
|
||||
if (!device_can_wakeup(kdev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (wol->wolopts & ~(WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER))
|
||||
return -EINVAL;
|
||||
|
||||
if (wol->wolopts & WAKE_MAGICSECURE)
|
||||
memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
|
||||
|
||||
/* Flag the device and relevant IRQ as wakeup capable */
|
||||
if (wol->wolopts) {
|
||||
device_set_wakeup_enable(kdev, 1);
|
||||
/* Avoid unbalanced enable_irq_wake calls */
|
||||
if (priv->wol_irq_disabled)
|
||||
enable_irq_wake(priv->wol_irq);
|
||||
priv->wol_irq_disabled = false;
|
||||
} else {
|
||||
device_set_wakeup_enable(kdev, 0);
|
||||
/* Avoid unbalanced disable_irq_wake calls */
|
||||
if (!priv->wol_irq_disabled)
|
||||
disable_irq_wake(priv->wol_irq);
|
||||
priv->wol_irq_disabled = true;
|
||||
}
|
||||
|
||||
priv->wolopts = wol->wolopts;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcmgenet_poll_wol_status(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct net_device *dev = priv->dev;
|
||||
int retries = 0;
|
||||
|
||||
while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS)
|
||||
& RBUF_STATUS_WOL)) {
|
||||
retries++;
|
||||
if (retries > 5) {
|
||||
netdev_crit(dev, "polling wol mode timeout\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
return retries;
|
||||
}
|
||||
|
||||
static void bcmgenet_set_mpd_password(struct bcmgenet_priv *priv)
|
||||
{
|
||||
bcmgenet_umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
|
||||
UMAC_MPD_PW_MS);
|
||||
bcmgenet_umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
|
||||
UMAC_MPD_PW_LS);
|
||||
}
|
||||
|
||||
int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode)
|
||||
{
|
||||
struct net_device *dev = priv->dev;
|
||||
struct bcmgenet_rxnfc_rule *rule;
|
||||
u32 reg, hfb_ctrl_reg, hfb_enable = 0;
|
||||
int retries = 0;
|
||||
|
||||
if (mode != GENET_POWER_WOL_MAGIC) {
|
||||
netif_err(priv, wol, dev, "unsupported mode: %d\n", mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Can't suspend with WoL if MAC is still in reset */
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||
if (reg & CMD_SW_RESET)
|
||||
reg &= ~CMD_SW_RESET;
|
||||
|
||||
/* disable RX */
|
||||
reg &= ~CMD_RX_EN;
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
mdelay(10);
|
||||
|
||||
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||
reg |= MPD_EN;
|
||||
if (priv->wolopts & WAKE_MAGICSECURE) {
|
||||
bcmgenet_set_mpd_password(priv);
|
||||
reg |= MPD_PW_EN;
|
||||
}
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||
}
|
||||
|
||||
hfb_ctrl_reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
|
||||
if (priv->wolopts & WAKE_FILTER) {
|
||||
list_for_each_entry(rule, &priv->rxnfc_list, list)
|
||||
if (rule->fs.ring_cookie == RX_CLS_FLOW_WAKE)
|
||||
hfb_enable |= (1 << rule->fs.location);
|
||||
reg = (hfb_ctrl_reg & ~RBUF_HFB_EN) | RBUF_ACPI_EN;
|
||||
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||
}
|
||||
|
||||
/* Do not leave UniMAC in MPD mode only */
|
||||
retries = bcmgenet_poll_wol_status(priv);
|
||||
if (retries < 0) {
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||
reg &= ~(MPD_EN | MPD_PW_EN);
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||
bcmgenet_hfb_reg_writel(priv, hfb_ctrl_reg, HFB_CTRL);
|
||||
return retries;
|
||||
}
|
||||
|
||||
netif_dbg(priv, wol, dev, "MPD WOL-ready status set after %d msec\n",
|
||||
retries);
|
||||
|
||||
clk_prepare_enable(priv->clk_wol);
|
||||
priv->wol_active = 1;
|
||||
|
||||
if (hfb_enable) {
|
||||
bcmgenet_hfb_reg_writel(priv, hfb_enable,
|
||||
HFB_FLT_ENABLE_V3PLUS + 4);
|
||||
hfb_ctrl_reg = RBUF_HFB_EN | RBUF_ACPI_EN;
|
||||
bcmgenet_hfb_reg_writel(priv, hfb_ctrl_reg, HFB_CTRL);
|
||||
}
|
||||
|
||||
/* Enable CRC forward */
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||
priv->crc_fwd_en = 1;
|
||||
reg |= CMD_CRC_FWD;
|
||||
|
||||
/* Receiver must be enabled for WOL MP detection */
|
||||
reg |= CMD_RX_EN;
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
|
||||
reg = UMAC_IRQ_MPD_R;
|
||||
if (hfb_enable)
|
||||
reg |= UMAC_IRQ_HFB_SM | UMAC_IRQ_HFB_MM;
|
||||
|
||||
bcmgenet_intrl2_0_writel(priv, reg, INTRL2_CPU_MASK_CLEAR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
|
||||
enum bcmgenet_power_mode mode)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (mode != GENET_POWER_WOL_MAGIC) {
|
||||
netif_err(priv, wol, priv->dev, "invalid mode: %d\n", mode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!priv->wol_active)
|
||||
return; /* failed to suspend so skip the rest */
|
||||
|
||||
priv->wol_active = 0;
|
||||
clk_disable_unprepare(priv->clk_wol);
|
||||
priv->crc_fwd_en = 0;
|
||||
|
||||
/* Disable Magic Packet Detection */
|
||||
if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL);
|
||||
if (!(reg & MPD_EN))
|
||||
return; /* already reset so skip the rest */
|
||||
reg &= ~(MPD_EN | MPD_PW_EN);
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL);
|
||||
}
|
||||
|
||||
/* Disable WAKE_FILTER Detection */
|
||||
if (priv->wolopts & WAKE_FILTER) {
|
||||
reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL);
|
||||
if (!(reg & RBUF_ACPI_EN))
|
||||
return; /* already reset so skip the rest */
|
||||
reg &= ~(RBUF_HFB_EN | RBUF_ACPI_EN);
|
||||
bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL);
|
||||
}
|
||||
|
||||
/* Disable CRC Forward */
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||
reg &= ~CMD_CRC_FWD;
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
}
|
||||
|
|
@ -0,0 +1,671 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Broadcom GENET MDIO routines
|
||||
*
|
||||
* Copyright (c) 2014-2017 Broadcom
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/phy_fixed.h>
|
||||
#include <linux/brcmphy.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/platform_data/bcmgenet.h>
|
||||
#include <linux/platform_data/mdio-bcm-unimac.h>
|
||||
|
||||
#include "bcmgenet-6.1-ethercat.h"
|
||||
|
||||
static void bcmgenet_mac_config(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
u32 reg, cmd_bits = 0;
|
||||
|
||||
/* speed */
|
||||
if (phydev->speed == SPEED_1000)
|
||||
cmd_bits = CMD_SPEED_1000;
|
||||
else if (phydev->speed == SPEED_100)
|
||||
cmd_bits = CMD_SPEED_100;
|
||||
else
|
||||
cmd_bits = CMD_SPEED_10;
|
||||
cmd_bits <<= CMD_SPEED_SHIFT;
|
||||
|
||||
/* duplex */
|
||||
if (phydev->duplex != DUPLEX_FULL) {
|
||||
cmd_bits |= CMD_HD_EN |
|
||||
CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
|
||||
} else {
|
||||
/* pause capability defaults to Symmetric */
|
||||
if (priv->autoneg_pause) {
|
||||
bool tx_pause = 0, rx_pause = 0;
|
||||
|
||||
if (phydev->autoneg)
|
||||
phy_get_pause(phydev, &tx_pause, &rx_pause);
|
||||
|
||||
if (!tx_pause)
|
||||
cmd_bits |= CMD_TX_PAUSE_IGNORE;
|
||||
if (!rx_pause)
|
||||
cmd_bits |= CMD_RX_PAUSE_IGNORE;
|
||||
}
|
||||
|
||||
/* Manual override */
|
||||
if (!priv->rx_pause)
|
||||
cmd_bits |= CMD_RX_PAUSE_IGNORE;
|
||||
if (!priv->tx_pause)
|
||||
cmd_bits |= CMD_TX_PAUSE_IGNORE;
|
||||
}
|
||||
|
||||
/* Program UMAC and RGMII block based on established
|
||||
* link speed, duplex, and pause. The speed set in
|
||||
* umac->cmd tell RGMII block which clock to use for
|
||||
* transmit -- 25MHz(100Mbps) or 125MHz(1Gbps).
|
||||
* Receive clock is provided by the PHY.
|
||||
*/
|
||||
reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
|
||||
reg &= ~OOB_DISABLE;
|
||||
reg |= RGMII_LINK;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
|
||||
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||
reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
|
||||
CMD_HD_EN |
|
||||
CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
|
||||
reg |= cmd_bits;
|
||||
if (reg & CMD_SW_RESET) {
|
||||
reg &= ~CMD_SW_RESET;
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
udelay(2);
|
||||
reg |= CMD_TX_EN | CMD_RX_EN;
|
||||
}
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
|
||||
priv->eee.eee_active = phy_init_eee(phydev, 0) >= 0;
|
||||
bcmgenet_eee_enable_set(dev,
|
||||
priv->eee.eee_enabled && priv->eee.eee_active,
|
||||
priv->eee.tx_lpi_enabled);
|
||||
}
|
||||
|
||||
/* setup netdev link state when PHY link status change and
|
||||
* update UMAC and RGMII block when link up
|
||||
*/
|
||||
void bcmgenet_mii_setup(struct net_device *dev)
|
||||
{
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
|
||||
if (phydev->link)
|
||||
bcmgenet_mac_config(dev);
|
||||
if (priv->ecdev)
|
||||
ecdev_set_link(priv->ecdev, phydev->link);
|
||||
phy_print_status(phydev);
|
||||
}
|
||||
|
||||
|
||||
static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
|
||||
struct fixed_phy_status *status)
|
||||
{
|
||||
struct bcmgenet_priv *priv;
|
||||
u32 reg;
|
||||
|
||||
if (dev && dev->phydev && status) {
|
||||
priv = netdev_priv(dev);
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_MODE);
|
||||
status->link = !!(reg & MODE_LINK_STATUS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bcmgenet_phy_pause_set(struct net_device *dev, bool rx, bool tx)
|
||||
{
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising, rx);
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising,
|
||||
rx | tx);
|
||||
phy_start_aneg(phydev);
|
||||
|
||||
mutex_lock(&phydev->lock);
|
||||
if (phydev->link)
|
||||
bcmgenet_mac_config(dev);
|
||||
mutex_unlock(&phydev->lock);
|
||||
}
|
||||
|
||||
void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
u32 reg = 0;
|
||||
|
||||
/* EXT_GPHY_CTRL is only valid for GENETv4 and onward */
|
||||
if (GENET_IS_V4(priv) || priv->ephy_16nm) {
|
||||
reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
|
||||
if (enable) {
|
||||
reg &= ~EXT_CK25_DIS;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||
mdelay(1);
|
||||
|
||||
reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN |
|
||||
EXT_CFG_IDDQ_GLOBAL_PWR);
|
||||
reg |= EXT_GPHY_RESET;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||
mdelay(1);
|
||||
|
||||
reg &= ~EXT_GPHY_RESET;
|
||||
} else {
|
||||
reg |= EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN |
|
||||
EXT_GPHY_RESET | EXT_CFG_IDDQ_GLOBAL_PWR;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||
mdelay(1);
|
||||
reg |= EXT_CK25_DIS;
|
||||
}
|
||||
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||
udelay(60);
|
||||
} else {
|
||||
mdelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
|
||||
{
|
||||
if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
|
||||
fixed_phy_set_link_update(priv->dev->phydev,
|
||||
bcmgenet_fixed_phy_link_update);
|
||||
}
|
||||
|
||||
int bcmgenet_mii_config(struct net_device *dev, bool init)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
const char *phy_name = NULL;
|
||||
u32 id_mode_dis = 0;
|
||||
u32 port_ctrl;
|
||||
u32 reg;
|
||||
|
||||
switch (priv->phy_interface) {
|
||||
case PHY_INTERFACE_MODE_INTERNAL:
|
||||
phy_name = "internal PHY";
|
||||
fallthrough;
|
||||
case PHY_INTERFACE_MODE_MOCA:
|
||||
/* Irrespective of the actually configured PHY speed (100 or
|
||||
* 1000) GENETv4 only has an internal GPHY so we will just end
|
||||
* up masking the Gigabit features from what we support, not
|
||||
* switching to the EPHY
|
||||
*/
|
||||
if (GENET_IS_V4(priv))
|
||||
port_ctrl = PORT_MODE_INT_GPHY;
|
||||
else
|
||||
port_ctrl = PORT_MODE_INT_EPHY;
|
||||
|
||||
if (!phy_name) {
|
||||
phy_name = "MoCA";
|
||||
if (!GENET_IS_V5(priv))
|
||||
port_ctrl |= LED_ACT_SOURCE_MAC;
|
||||
bcmgenet_moca_phy_setup(priv);
|
||||
}
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_MII:
|
||||
phy_name = "external MII";
|
||||
phy_set_max_speed(phydev, SPEED_100);
|
||||
port_ctrl = PORT_MODE_EXT_EPHY;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_REVMII:
|
||||
phy_name = "external RvMII";
|
||||
/* of_mdiobus_register took care of reading the 'max-speed'
|
||||
* PHY property for us, effectively limiting the PHY supported
|
||||
* capabilities, use that knowledge to also configure the
|
||||
* Reverse MII interface correctly.
|
||||
*/
|
||||
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||
dev->phydev->supported))
|
||||
port_ctrl = PORT_MODE_EXT_RVMII_50;
|
||||
else
|
||||
port_ctrl = PORT_MODE_EXT_RVMII_25;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
/* RGMII_NO_ID: TXC transitions at the same time as TXD
|
||||
* (requires PCB or receiver-side delay)
|
||||
*
|
||||
* ID is implicitly disabled for 100Mbps (RG)MII operation.
|
||||
*/
|
||||
phy_name = "external RGMII (no delay)";
|
||||
id_mode_dis = BIT(16);
|
||||
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
/* RGMII_TXID: Add 2ns delay on TXC (90 degree shift) */
|
||||
phy_name = "external RGMII (TX delay)";
|
||||
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
phy_name = "external RGMII (RX delay)";
|
||||
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||
break;
|
||||
default:
|
||||
dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
|
||||
|
||||
priv->ext_phy = !priv->internal_phy &&
|
||||
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
|
||||
|
||||
/* This is an external PHY (xMII), so we need to enable the RGMII
|
||||
* block for the interface to work
|
||||
*/
|
||||
if (priv->ext_phy) {
|
||||
reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
|
||||
reg &= ~ID_MODE_DIS;
|
||||
reg |= id_mode_dis;
|
||||
if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv))
|
||||
reg |= RGMII_MODE_EN_V123;
|
||||
else
|
||||
reg |= RGMII_MODE_EN;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
|
||||
}
|
||||
|
||||
if (init)
|
||||
dev_info(kdev, "configuring instance for %s\n", phy_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bcmgenet_mii_probe(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
struct device_node *dn = kdev->of_node;
|
||||
phy_interface_t phy_iface = priv->phy_interface;
|
||||
struct phy_device *phydev;
|
||||
u32 phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE |
|
||||
PHY_BRCM_DIS_TXCRXC_NOENRGY |
|
||||
PHY_BRCM_IDDQ_SUSPEND;
|
||||
int ret;
|
||||
|
||||
/* Communicate the integrated PHY revision */
|
||||
if (priv->internal_phy)
|
||||
phy_flags = priv->gphy_rev;
|
||||
|
||||
/* This is an ugly quirk but we have not been correctly interpreting
|
||||
* the phy_interface values and we have done that across different
|
||||
* drivers, so at least we are consistent in our mistakes.
|
||||
*
|
||||
* When the Generic PHY driver is in use either the PHY has been
|
||||
* strapped or programmed correctly by the boot loader so we should
|
||||
* stick to our incorrect interpretation since we have validated it.
|
||||
*
|
||||
* Now when a dedicated PHY driver is in use, we need to reverse the
|
||||
* meaning of the phy_interface_mode values to something that the PHY
|
||||
* driver will interpret and act on such that we have two mistakes
|
||||
* canceling themselves so to speak. We only do this for the two
|
||||
* modes that GENET driver officially supports on Broadcom STB chips:
|
||||
* PHY_INTERFACE_MODE_RGMII and PHY_INTERFACE_MODE_RGMII_TXID. Other
|
||||
* modes are not *officially* supported with the boot loader and the
|
||||
* scripted environment generating Device Tree blobs for those
|
||||
* platforms.
|
||||
*
|
||||
* Note that internal PHY, MoCA and fixed-link configurations are not
|
||||
* affected because they use different phy_interface_t values or the
|
||||
* Generic PHY driver.
|
||||
*/
|
||||
switch (priv->phy_interface) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
phy_iface = PHY_INTERFACE_MODE_RGMII_ID;
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
phy_iface = PHY_INTERFACE_MODE_RGMII_RXID;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (dn) {
|
||||
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
|
||||
phy_flags, phy_iface);
|
||||
if (!phydev) {
|
||||
pr_err("could not attach to PHY\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
if (has_acpi_companion(kdev)) {
|
||||
char mdio_bus_id[MII_BUS_ID_SIZE];
|
||||
struct mii_bus *unimacbus;
|
||||
|
||||
snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d",
|
||||
UNIMAC_MDIO_DRV_NAME, priv->pdev->id);
|
||||
|
||||
unimacbus = mdio_find_bus(mdio_bus_id);
|
||||
if (!unimacbus) {
|
||||
pr_err("Unable to find mii\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
phydev = phy_find_first(unimacbus);
|
||||
put_device(&unimacbus->dev);
|
||||
if (!phydev) {
|
||||
pr_err("Unable to find PHY\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
phydev = dev->phydev;
|
||||
}
|
||||
phydev->dev_flags = phy_flags;
|
||||
|
||||
ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
|
||||
phy_iface);
|
||||
if (ret) {
|
||||
pr_err("could not attach to PHY\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure port multiplexer based on what the probed PHY device since
|
||||
* reading the 'max-speed' property determines the maximum supported
|
||||
* PHY speed which is needed for bcmgenet_mii_config() to configure
|
||||
* things appropriately.
|
||||
*/
|
||||
ret = bcmgenet_mii_config(dev, true);
|
||||
if (ret) {
|
||||
phy_disconnect(dev->phydev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The internal PHY has its link interrupts routed to the
|
||||
* Ethernet MAC ISRs. On GENETv5 there is a hardware issue
|
||||
* that prevents the signaling of link UP interrupts when
|
||||
* the link operates at 10Mbps, so fallback to polling for
|
||||
* those versions of GENET.
|
||||
*/
|
||||
if (priv->internal_phy && !GENET_IS_V5(priv))
|
||||
dev->phydev->irq = PHY_MAC_INTERRUPT;
|
||||
|
||||
/* Indicate that the MAC is responsible for PHY PM */
|
||||
dev->phydev->mac_managed_pm = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_node *bcmgenet_mii_of_find_mdio(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct device_node *dn = priv->pdev->dev.of_node;
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
char *compat;
|
||||
|
||||
compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version);
|
||||
if (!compat)
|
||||
return NULL;
|
||||
|
||||
priv->mdio_dn = of_get_compatible_child(dn, compat);
|
||||
kfree(compat);
|
||||
if (!priv->mdio_dn) {
|
||||
dev_err(kdev, "unable to find MDIO bus node\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return priv->mdio_dn;
|
||||
}
|
||||
|
||||
static void bcmgenet_mii_pdata_init(struct bcmgenet_priv *priv,
|
||||
struct unimac_mdio_pdata *ppd)
|
||||
{
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
struct bcmgenet_platform_data *pd = kdev->platform_data;
|
||||
|
||||
if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) {
|
||||
/*
|
||||
* Internal or external PHY with MDIO access
|
||||
*/
|
||||
if (pd->phy_address >= 0 && pd->phy_address < PHY_MAX_ADDR)
|
||||
ppd->phy_mask = 1 << pd->phy_address;
|
||||
else
|
||||
ppd->phy_mask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int bcmgenet_mii_wait(void *wait_func_data)
|
||||
{
|
||||
struct bcmgenet_priv *priv = wait_func_data;
|
||||
|
||||
wait_event_timeout(priv->wq,
|
||||
!(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD)
|
||||
& MDIO_START_BUSY),
|
||||
HZ / 100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcmgenet_mii_register(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct platform_device *pdev = priv->pdev;
|
||||
struct bcmgenet_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct device_node *dn = pdev->dev.of_node;
|
||||
struct unimac_mdio_pdata ppd;
|
||||
struct platform_device *ppdev;
|
||||
struct resource *pres, res;
|
||||
int id, ret;
|
||||
|
||||
pres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!pres) {
|
||||
dev_err(&pdev->dev, "Invalid resource\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
memset(&res, 0, sizeof(res));
|
||||
memset(&ppd, 0, sizeof(ppd));
|
||||
|
||||
ppd.wait_func = bcmgenet_mii_wait;
|
||||
ppd.wait_func_data = priv;
|
||||
ppd.bus_name = "bcmgenet MII bus";
|
||||
|
||||
/* Unimac MDIO bus controller starts at UniMAC offset + MDIO_CMD
|
||||
* and is 2 * 32-bits word long, 8 bytes total.
|
||||
*/
|
||||
res.start = pres->start + GENET_UMAC_OFF + UMAC_MDIO_CMD;
|
||||
res.end = res.start + 8;
|
||||
res.flags = IORESOURCE_MEM;
|
||||
|
||||
if (dn)
|
||||
id = of_alias_get_id(dn, "eth");
|
||||
else
|
||||
id = pdev->id;
|
||||
|
||||
ppdev = platform_device_alloc(UNIMAC_MDIO_DRV_NAME, id);
|
||||
if (!ppdev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Retain this platform_device pointer for later cleanup */
|
||||
priv->mii_pdev = ppdev;
|
||||
ppdev->dev.parent = &pdev->dev;
|
||||
if (dn)
|
||||
ppdev->dev.of_node = bcmgenet_mii_of_find_mdio(priv);
|
||||
else if (pdata)
|
||||
bcmgenet_mii_pdata_init(priv, &ppd);
|
||||
else
|
||||
ppd.phy_mask = ~0;
|
||||
|
||||
ret = platform_device_add_resources(ppdev, &res, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = platform_device_add_data(ppdev, &ppd, sizeof(ppd));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = platform_device_add(ppdev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
platform_device_put(ppdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bcmgenet_phy_interface_init(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
int phy_mode = device_get_phy_mode(kdev);
|
||||
|
||||
if (phy_mode < 0) {
|
||||
dev_err(kdev, "invalid PHY mode property\n");
|
||||
return phy_mode;
|
||||
}
|
||||
|
||||
priv->phy_interface = phy_mode;
|
||||
|
||||
/* We need to specifically look up whether this PHY interface is
|
||||
* internal or not *before* we even try to probe the PHY driver
|
||||
* over MDIO as we may have shut down the internal PHY for power
|
||||
* saving purposes.
|
||||
*/
|
||||
if (priv->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
|
||||
priv->internal_phy = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct device_node *dn = priv->pdev->dev.of_node;
|
||||
struct phy_device *phydev;
|
||||
int ret;
|
||||
|
||||
/* Fetch the PHY phandle */
|
||||
priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0);
|
||||
|
||||
/* In the case of a fixed PHY, the DT node associated
|
||||
* to the PHY is the Ethernet MAC DT node.
|
||||
*/
|
||||
if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
|
||||
ret = of_phy_register_fixed_link(dn);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->phy_dn = of_node_get(dn);
|
||||
}
|
||||
|
||||
/* Get the link mode */
|
||||
ret = bcmgenet_phy_interface_init(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Make sure we initialize MoCA PHYs with a link down */
|
||||
if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
|
||||
phydev = of_phy_find_device(dn);
|
||||
if (phydev) {
|
||||
phydev->link = 0;
|
||||
put_device(&phydev->mdio.dev);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
struct bcmgenet_platform_data *pd = kdev->platform_data;
|
||||
char phy_name[MII_BUS_ID_SIZE + 3];
|
||||
char mdio_bus_id[MII_BUS_ID_SIZE];
|
||||
struct phy_device *phydev;
|
||||
|
||||
snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d",
|
||||
UNIMAC_MDIO_DRV_NAME, priv->pdev->id);
|
||||
|
||||
if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) {
|
||||
snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT,
|
||||
mdio_bus_id, pd->phy_address);
|
||||
|
||||
/*
|
||||
* Internal or external PHY with MDIO access
|
||||
*/
|
||||
phydev = phy_attach(priv->dev, phy_name, pd->phy_interface);
|
||||
if (IS_ERR(phydev)) {
|
||||
dev_err(kdev, "failed to register PHY device\n");
|
||||
return PTR_ERR(phydev);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* MoCA port or no MDIO access.
|
||||
* Use fixed PHY to represent the link layer.
|
||||
*/
|
||||
struct fixed_phy_status fphy_status = {
|
||||
.link = 1,
|
||||
.speed = pd->phy_speed,
|
||||
.duplex = pd->phy_duplex,
|
||||
.pause = 0,
|
||||
.asym_pause = 0,
|
||||
};
|
||||
|
||||
phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
|
||||
if (!phydev || IS_ERR(phydev)) {
|
||||
dev_err(kdev, "failed to register fixed PHY device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Make sure we initialize MoCA PHYs with a link down */
|
||||
phydev->link = 0;
|
||||
|
||||
}
|
||||
|
||||
priv->phy_interface = pd->phy_interface;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
struct device_node *dn = kdev->of_node;
|
||||
|
||||
if (dn)
|
||||
return bcmgenet_mii_of_init(priv);
|
||||
else if (has_acpi_companion(kdev))
|
||||
return bcmgenet_phy_interface_init(priv);
|
||||
else
|
||||
return bcmgenet_mii_pd_init(priv);
|
||||
}
|
||||
|
||||
int bcmgenet_mii_init(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = bcmgenet_mii_register(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bcmgenet_mii_bus_init(priv);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
bcmgenet_mii_exit(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bcmgenet_mii_exit(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device_node *dn = priv->pdev->dev.of_node;
|
||||
|
||||
if (of_phy_is_fixed_link(dn))
|
||||
of_phy_deregister_fixed_link(dn);
|
||||
of_node_put(priv->phy_dn);
|
||||
platform_device_unregister(priv->mii_pdev);
|
||||
}
|
||||
|
|
@ -0,0 +1,668 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Broadcom GENET MDIO routines
|
||||
*
|
||||
* Copyright (c) 2014-2017 Broadcom
|
||||
*/
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mii.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/phy.h>
|
||||
#include <linux/phy_fixed.h>
|
||||
#include <linux/brcmphy.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/platform_data/bcmgenet.h>
|
||||
#include <linux/platform_data/mdio-bcm-unimac.h>
|
||||
|
||||
#include "bcmgenet.h"
|
||||
|
||||
static void bcmgenet_mac_config(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
u32 reg, cmd_bits = 0;
|
||||
|
||||
/* speed */
|
||||
if (phydev->speed == SPEED_1000)
|
||||
cmd_bits = CMD_SPEED_1000;
|
||||
else if (phydev->speed == SPEED_100)
|
||||
cmd_bits = CMD_SPEED_100;
|
||||
else
|
||||
cmd_bits = CMD_SPEED_10;
|
||||
cmd_bits <<= CMD_SPEED_SHIFT;
|
||||
|
||||
/* duplex */
|
||||
if (phydev->duplex != DUPLEX_FULL) {
|
||||
cmd_bits |= CMD_HD_EN |
|
||||
CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
|
||||
} else {
|
||||
/* pause capability defaults to Symmetric */
|
||||
if (priv->autoneg_pause) {
|
||||
bool tx_pause = 0, rx_pause = 0;
|
||||
|
||||
if (phydev->autoneg)
|
||||
phy_get_pause(phydev, &tx_pause, &rx_pause);
|
||||
|
||||
if (!tx_pause)
|
||||
cmd_bits |= CMD_TX_PAUSE_IGNORE;
|
||||
if (!rx_pause)
|
||||
cmd_bits |= CMD_RX_PAUSE_IGNORE;
|
||||
}
|
||||
|
||||
/* Manual override */
|
||||
if (!priv->rx_pause)
|
||||
cmd_bits |= CMD_RX_PAUSE_IGNORE;
|
||||
if (!priv->tx_pause)
|
||||
cmd_bits |= CMD_TX_PAUSE_IGNORE;
|
||||
}
|
||||
|
||||
/* Program UMAC and RGMII block based on established
|
||||
* link speed, duplex, and pause. The speed set in
|
||||
* umac->cmd tell RGMII block which clock to use for
|
||||
* transmit -- 25MHz(100Mbps) or 125MHz(1Gbps).
|
||||
* Receive clock is provided by the PHY.
|
||||
*/
|
||||
reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
|
||||
reg &= ~OOB_DISABLE;
|
||||
reg |= RGMII_LINK;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
|
||||
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_CMD);
|
||||
reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
|
||||
CMD_HD_EN |
|
||||
CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
|
||||
reg |= cmd_bits;
|
||||
if (reg & CMD_SW_RESET) {
|
||||
reg &= ~CMD_SW_RESET;
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
udelay(2);
|
||||
reg |= CMD_TX_EN | CMD_RX_EN;
|
||||
}
|
||||
bcmgenet_umac_writel(priv, reg, UMAC_CMD);
|
||||
|
||||
priv->eee.eee_active = phy_init_eee(phydev, 0) >= 0;
|
||||
bcmgenet_eee_enable_set(dev,
|
||||
priv->eee.eee_enabled && priv->eee.eee_active,
|
||||
priv->eee.tx_lpi_enabled);
|
||||
}
|
||||
|
||||
/* setup netdev link state when PHY link status change and
|
||||
* update UMAC and RGMII block when link up
|
||||
*/
|
||||
void bcmgenet_mii_setup(struct net_device *dev)
|
||||
{
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
|
||||
if (phydev->link)
|
||||
bcmgenet_mac_config(dev);
|
||||
phy_print_status(phydev);
|
||||
}
|
||||
|
||||
|
||||
static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
|
||||
struct fixed_phy_status *status)
|
||||
{
|
||||
struct bcmgenet_priv *priv;
|
||||
u32 reg;
|
||||
|
||||
if (dev && dev->phydev && status) {
|
||||
priv = netdev_priv(dev);
|
||||
reg = bcmgenet_umac_readl(priv, UMAC_MODE);
|
||||
status->link = !!(reg & MODE_LINK_STATUS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bcmgenet_phy_pause_set(struct net_device *dev, bool rx, bool tx)
|
||||
{
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising, rx);
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising,
|
||||
rx | tx);
|
||||
phy_start_aneg(phydev);
|
||||
|
||||
mutex_lock(&phydev->lock);
|
||||
if (phydev->link)
|
||||
bcmgenet_mac_config(dev);
|
||||
mutex_unlock(&phydev->lock);
|
||||
}
|
||||
|
||||
void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
u32 reg = 0;
|
||||
|
||||
/* EXT_GPHY_CTRL is only valid for GENETv4 and onward */
|
||||
if (GENET_IS_V4(priv) || priv->ephy_16nm) {
|
||||
reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
|
||||
if (enable) {
|
||||
reg &= ~EXT_CK25_DIS;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||
mdelay(1);
|
||||
|
||||
reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN |
|
||||
EXT_CFG_IDDQ_GLOBAL_PWR);
|
||||
reg |= EXT_GPHY_RESET;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||
mdelay(1);
|
||||
|
||||
reg &= ~EXT_GPHY_RESET;
|
||||
} else {
|
||||
reg |= EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN |
|
||||
EXT_GPHY_RESET | EXT_CFG_IDDQ_GLOBAL_PWR;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||
mdelay(1);
|
||||
reg |= EXT_CK25_DIS;
|
||||
}
|
||||
bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
|
||||
udelay(60);
|
||||
} else {
|
||||
mdelay(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
|
||||
{
|
||||
if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
|
||||
fixed_phy_set_link_update(priv->dev->phydev,
|
||||
bcmgenet_fixed_phy_link_update);
|
||||
}
|
||||
|
||||
int bcmgenet_mii_config(struct net_device *dev, bool init)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
const char *phy_name = NULL;
|
||||
u32 id_mode_dis = 0;
|
||||
u32 port_ctrl;
|
||||
u32 reg;
|
||||
|
||||
switch (priv->phy_interface) {
|
||||
case PHY_INTERFACE_MODE_INTERNAL:
|
||||
phy_name = "internal PHY";
|
||||
fallthrough;
|
||||
case PHY_INTERFACE_MODE_MOCA:
|
||||
/* Irrespective of the actually configured PHY speed (100 or
|
||||
* 1000) GENETv4 only has an internal GPHY so we will just end
|
||||
* up masking the Gigabit features from what we support, not
|
||||
* switching to the EPHY
|
||||
*/
|
||||
if (GENET_IS_V4(priv))
|
||||
port_ctrl = PORT_MODE_INT_GPHY;
|
||||
else
|
||||
port_ctrl = PORT_MODE_INT_EPHY;
|
||||
|
||||
if (!phy_name) {
|
||||
phy_name = "MoCA";
|
||||
if (!GENET_IS_V5(priv))
|
||||
port_ctrl |= LED_ACT_SOURCE_MAC;
|
||||
bcmgenet_moca_phy_setup(priv);
|
||||
}
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_MII:
|
||||
phy_name = "external MII";
|
||||
phy_set_max_speed(phydev, SPEED_100);
|
||||
port_ctrl = PORT_MODE_EXT_EPHY;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_REVMII:
|
||||
phy_name = "external RvMII";
|
||||
/* of_mdiobus_register took care of reading the 'max-speed'
|
||||
* PHY property for us, effectively limiting the PHY supported
|
||||
* capabilities, use that knowledge to also configure the
|
||||
* Reverse MII interface correctly.
|
||||
*/
|
||||
if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
||||
dev->phydev->supported))
|
||||
port_ctrl = PORT_MODE_EXT_RVMII_50;
|
||||
else
|
||||
port_ctrl = PORT_MODE_EXT_RVMII_25;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
/* RGMII_NO_ID: TXC transitions at the same time as TXD
|
||||
* (requires PCB or receiver-side delay)
|
||||
*
|
||||
* ID is implicitly disabled for 100Mbps (RG)MII operation.
|
||||
*/
|
||||
phy_name = "external RGMII (no delay)";
|
||||
id_mode_dis = BIT(16);
|
||||
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
/* RGMII_TXID: Add 2ns delay on TXC (90 degree shift) */
|
||||
phy_name = "external RGMII (TX delay)";
|
||||
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
phy_name = "external RGMII (RX delay)";
|
||||
port_ctrl = PORT_MODE_EXT_GPHY;
|
||||
break;
|
||||
default:
|
||||
dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
|
||||
|
||||
priv->ext_phy = !priv->internal_phy &&
|
||||
(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
|
||||
|
||||
/* This is an external PHY (xMII), so we need to enable the RGMII
|
||||
* block for the interface to work
|
||||
*/
|
||||
if (priv->ext_phy) {
|
||||
reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
|
||||
reg &= ~ID_MODE_DIS;
|
||||
reg |= id_mode_dis;
|
||||
if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv))
|
||||
reg |= RGMII_MODE_EN_V123;
|
||||
else
|
||||
reg |= RGMII_MODE_EN;
|
||||
bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
|
||||
}
|
||||
|
||||
if (init)
|
||||
dev_info(kdev, "configuring instance for %s\n", phy_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bcmgenet_mii_probe(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
struct device_node *dn = kdev->of_node;
|
||||
phy_interface_t phy_iface = priv->phy_interface;
|
||||
struct phy_device *phydev;
|
||||
u32 phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE |
|
||||
PHY_BRCM_DIS_TXCRXC_NOENRGY |
|
||||
PHY_BRCM_IDDQ_SUSPEND;
|
||||
int ret;
|
||||
|
||||
/* Communicate the integrated PHY revision */
|
||||
if (priv->internal_phy)
|
||||
phy_flags = priv->gphy_rev;
|
||||
|
||||
/* This is an ugly quirk but we have not been correctly interpreting
|
||||
* the phy_interface values and we have done that across different
|
||||
* drivers, so at least we are consistent in our mistakes.
|
||||
*
|
||||
* When the Generic PHY driver is in use either the PHY has been
|
||||
* strapped or programmed correctly by the boot loader so we should
|
||||
* stick to our incorrect interpretation since we have validated it.
|
||||
*
|
||||
* Now when a dedicated PHY driver is in use, we need to reverse the
|
||||
* meaning of the phy_interface_mode values to something that the PHY
|
||||
* driver will interpret and act on such that we have two mistakes
|
||||
* canceling themselves so to speak. We only do this for the two
|
||||
* modes that GENET driver officially supports on Broadcom STB chips:
|
||||
* PHY_INTERFACE_MODE_RGMII and PHY_INTERFACE_MODE_RGMII_TXID. Other
|
||||
* modes are not *officially* supported with the boot loader and the
|
||||
* scripted environment generating Device Tree blobs for those
|
||||
* platforms.
|
||||
*
|
||||
* Note that internal PHY, MoCA and fixed-link configurations are not
|
||||
* affected because they use different phy_interface_t values or the
|
||||
* Generic PHY driver.
|
||||
*/
|
||||
switch (priv->phy_interface) {
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
phy_iface = PHY_INTERFACE_MODE_RGMII_ID;
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_RGMII_TXID:
|
||||
phy_iface = PHY_INTERFACE_MODE_RGMII_RXID;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (dn) {
|
||||
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
|
||||
phy_flags, phy_iface);
|
||||
if (!phydev) {
|
||||
pr_err("could not attach to PHY\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
if (has_acpi_companion(kdev)) {
|
||||
char mdio_bus_id[MII_BUS_ID_SIZE];
|
||||
struct mii_bus *unimacbus;
|
||||
|
||||
snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d",
|
||||
UNIMAC_MDIO_DRV_NAME, priv->pdev->id);
|
||||
|
||||
unimacbus = mdio_find_bus(mdio_bus_id);
|
||||
if (!unimacbus) {
|
||||
pr_err("Unable to find mii\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
phydev = phy_find_first(unimacbus);
|
||||
put_device(&unimacbus->dev);
|
||||
if (!phydev) {
|
||||
pr_err("Unable to find PHY\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
phydev = dev->phydev;
|
||||
}
|
||||
phydev->dev_flags = phy_flags;
|
||||
|
||||
ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
|
||||
phy_iface);
|
||||
if (ret) {
|
||||
pr_err("could not attach to PHY\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure port multiplexer based on what the probed PHY device since
|
||||
* reading the 'max-speed' property determines the maximum supported
|
||||
* PHY speed which is needed for bcmgenet_mii_config() to configure
|
||||
* things appropriately.
|
||||
*/
|
||||
ret = bcmgenet_mii_config(dev, true);
|
||||
if (ret) {
|
||||
phy_disconnect(dev->phydev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The internal PHY has its link interrupts routed to the
|
||||
* Ethernet MAC ISRs. On GENETv5 there is a hardware issue
|
||||
* that prevents the signaling of link UP interrupts when
|
||||
* the link operates at 10Mbps, so fallback to polling for
|
||||
* those versions of GENET.
|
||||
*/
|
||||
if (priv->internal_phy && !GENET_IS_V5(priv))
|
||||
dev->phydev->irq = PHY_MAC_INTERRUPT;
|
||||
|
||||
/* Indicate that the MAC is responsible for PHY PM */
|
||||
dev->phydev->mac_managed_pm = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_node *bcmgenet_mii_of_find_mdio(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct device_node *dn = priv->pdev->dev.of_node;
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
char *compat;
|
||||
|
||||
compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version);
|
||||
if (!compat)
|
||||
return NULL;
|
||||
|
||||
priv->mdio_dn = of_get_compatible_child(dn, compat);
|
||||
kfree(compat);
|
||||
if (!priv->mdio_dn) {
|
||||
dev_err(kdev, "unable to find MDIO bus node\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return priv->mdio_dn;
|
||||
}
|
||||
|
||||
static void bcmgenet_mii_pdata_init(struct bcmgenet_priv *priv,
|
||||
struct unimac_mdio_pdata *ppd)
|
||||
{
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
struct bcmgenet_platform_data *pd = kdev->platform_data;
|
||||
|
||||
if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) {
|
||||
/*
|
||||
* Internal or external PHY with MDIO access
|
||||
*/
|
||||
if (pd->phy_address >= 0 && pd->phy_address < PHY_MAX_ADDR)
|
||||
ppd->phy_mask = 1 << pd->phy_address;
|
||||
else
|
||||
ppd->phy_mask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int bcmgenet_mii_wait(void *wait_func_data)
|
||||
{
|
||||
struct bcmgenet_priv *priv = wait_func_data;
|
||||
|
||||
wait_event_timeout(priv->wq,
|
||||
!(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD)
|
||||
& MDIO_START_BUSY),
|
||||
HZ / 100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcmgenet_mii_register(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct platform_device *pdev = priv->pdev;
|
||||
struct bcmgenet_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct device_node *dn = pdev->dev.of_node;
|
||||
struct unimac_mdio_pdata ppd;
|
||||
struct platform_device *ppdev;
|
||||
struct resource *pres, res;
|
||||
int id, ret;
|
||||
|
||||
pres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!pres) {
|
||||
dev_err(&pdev->dev, "Invalid resource\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
memset(&res, 0, sizeof(res));
|
||||
memset(&ppd, 0, sizeof(ppd));
|
||||
|
||||
ppd.wait_func = bcmgenet_mii_wait;
|
||||
ppd.wait_func_data = priv;
|
||||
ppd.bus_name = "bcmgenet MII bus";
|
||||
|
||||
/* Unimac MDIO bus controller starts at UniMAC offset + MDIO_CMD
|
||||
* and is 2 * 32-bits word long, 8 bytes total.
|
||||
*/
|
||||
res.start = pres->start + GENET_UMAC_OFF + UMAC_MDIO_CMD;
|
||||
res.end = res.start + 8;
|
||||
res.flags = IORESOURCE_MEM;
|
||||
|
||||
if (dn)
|
||||
id = of_alias_get_id(dn, "eth");
|
||||
else
|
||||
id = pdev->id;
|
||||
|
||||
ppdev = platform_device_alloc(UNIMAC_MDIO_DRV_NAME, id);
|
||||
if (!ppdev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Retain this platform_device pointer for later cleanup */
|
||||
priv->mii_pdev = ppdev;
|
||||
ppdev->dev.parent = &pdev->dev;
|
||||
if (dn)
|
||||
ppdev->dev.of_node = bcmgenet_mii_of_find_mdio(priv);
|
||||
else if (pdata)
|
||||
bcmgenet_mii_pdata_init(priv, &ppd);
|
||||
else
|
||||
ppd.phy_mask = ~0;
|
||||
|
||||
ret = platform_device_add_resources(ppdev, &res, 1);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = platform_device_add_data(ppdev, &ppd, sizeof(ppd));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = platform_device_add(ppdev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
out:
|
||||
platform_device_put(ppdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bcmgenet_phy_interface_init(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
int phy_mode = device_get_phy_mode(kdev);
|
||||
|
||||
if (phy_mode < 0) {
|
||||
dev_err(kdev, "invalid PHY mode property\n");
|
||||
return phy_mode;
|
||||
}
|
||||
|
||||
priv->phy_interface = phy_mode;
|
||||
|
||||
/* We need to specifically look up whether this PHY interface is
|
||||
* internal or not *before* we even try to probe the PHY driver
|
||||
* over MDIO as we may have shut down the internal PHY for power
|
||||
* saving purposes.
|
||||
*/
|
||||
if (priv->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
|
||||
priv->internal_phy = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct device_node *dn = priv->pdev->dev.of_node;
|
||||
struct phy_device *phydev;
|
||||
int ret;
|
||||
|
||||
/* Fetch the PHY phandle */
|
||||
priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0);
|
||||
|
||||
/* In the case of a fixed PHY, the DT node associated
|
||||
* to the PHY is the Ethernet MAC DT node.
|
||||
*/
|
||||
if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
|
||||
ret = of_phy_register_fixed_link(dn);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->phy_dn = of_node_get(dn);
|
||||
}
|
||||
|
||||
/* Get the link mode */
|
||||
ret = bcmgenet_phy_interface_init(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Make sure we initialize MoCA PHYs with a link down */
|
||||
if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
|
||||
phydev = of_phy_find_device(dn);
|
||||
if (phydev) {
|
||||
phydev->link = 0;
|
||||
put_device(&phydev->mdio.dev);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
struct bcmgenet_platform_data *pd = kdev->platform_data;
|
||||
char phy_name[MII_BUS_ID_SIZE + 3];
|
||||
char mdio_bus_id[MII_BUS_ID_SIZE];
|
||||
struct phy_device *phydev;
|
||||
|
||||
snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d",
|
||||
UNIMAC_MDIO_DRV_NAME, priv->pdev->id);
|
||||
|
||||
if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) {
|
||||
snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT,
|
||||
mdio_bus_id, pd->phy_address);
|
||||
|
||||
/*
|
||||
* Internal or external PHY with MDIO access
|
||||
*/
|
||||
phydev = phy_attach(priv->dev, phy_name, pd->phy_interface);
|
||||
if (IS_ERR(phydev)) {
|
||||
dev_err(kdev, "failed to register PHY device\n");
|
||||
return PTR_ERR(phydev);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* MoCA port or no MDIO access.
|
||||
* Use fixed PHY to represent the link layer.
|
||||
*/
|
||||
struct fixed_phy_status fphy_status = {
|
||||
.link = 1,
|
||||
.speed = pd->phy_speed,
|
||||
.duplex = pd->phy_duplex,
|
||||
.pause = 0,
|
||||
.asym_pause = 0,
|
||||
};
|
||||
|
||||
phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
|
||||
if (!phydev || IS_ERR(phydev)) {
|
||||
dev_err(kdev, "failed to register fixed PHY device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Make sure we initialize MoCA PHYs with a link down */
|
||||
phydev->link = 0;
|
||||
|
||||
}
|
||||
|
||||
priv->phy_interface = pd->phy_interface;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv)
|
||||
{
|
||||
struct device *kdev = &priv->pdev->dev;
|
||||
struct device_node *dn = kdev->of_node;
|
||||
|
||||
if (dn)
|
||||
return bcmgenet_mii_of_init(priv);
|
||||
else if (has_acpi_companion(kdev))
|
||||
return bcmgenet_phy_interface_init(priv);
|
||||
else
|
||||
return bcmgenet_mii_pd_init(priv);
|
||||
}
|
||||
|
||||
int bcmgenet_mii_init(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = bcmgenet_mii_register(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = bcmgenet_mii_bus_init(priv);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
bcmgenet_mii_exit(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bcmgenet_mii_exit(struct net_device *dev)
|
||||
{
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct device_node *dn = priv->pdev->dev.of_node;
|
||||
|
||||
if (of_phy_is_fixed_link(dn))
|
||||
of_phy_deregister_fixed_link(dn);
|
||||
of_node_put(priv->phy_dn);
|
||||
platform_device_unregister(priv->mii_pdev);
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef __UNIMAC_H
|
||||
#define __UNIMAC_H
|
||||
|
||||
#define UMAC_HD_BKP_CTRL 0x004
|
||||
#define HD_FC_EN (1 << 0)
|
||||
#define HD_FC_BKOFF_OK (1 << 1)
|
||||
#define IPG_CONFIG_RX_SHIFT 2
|
||||
#define IPG_CONFIG_RX_MASK 0x1F
|
||||
#define UMAC_CMD 0x008
|
||||
#define CMD_TX_EN (1 << 0)
|
||||
#define CMD_RX_EN (1 << 1)
|
||||
#define CMD_SPEED_10 0
|
||||
#define CMD_SPEED_100 1
|
||||
#define CMD_SPEED_1000 2
|
||||
#define CMD_SPEED_2500 3
|
||||
#define CMD_SPEED_SHIFT 2
|
||||
#define CMD_SPEED_MASK 3
|
||||
#define CMD_PROMISC (1 << 4)
|
||||
#define CMD_PAD_EN (1 << 5)
|
||||
#define CMD_CRC_FWD (1 << 6)
|
||||
#define CMD_PAUSE_FWD (1 << 7)
|
||||
#define CMD_RX_PAUSE_IGNORE (1 << 8)
|
||||
#define CMD_TX_ADDR_INS (1 << 9)
|
||||
#define CMD_HD_EN (1 << 10)
|
||||
#define CMD_SW_RESET_OLD (1 << 11)
|
||||
#define CMD_SW_RESET (1 << 13)
|
||||
#define CMD_LCL_LOOP_EN (1 << 15)
|
||||
#define CMD_AUTO_CONFIG (1 << 22)
|
||||
#define CMD_CNTL_FRM_EN (1 << 23)
|
||||
#define CMD_NO_LEN_CHK (1 << 24)
|
||||
#define CMD_RMT_LOOP_EN (1 << 25)
|
||||
#define CMD_RX_ERR_DISC (1 << 26)
|
||||
#define CMD_PRBL_EN (1 << 27)
|
||||
#define CMD_TX_PAUSE_IGNORE (1 << 28)
|
||||
#define CMD_TX_RX_EN (1 << 29)
|
||||
#define CMD_RUNT_FILTER_DIS (1 << 30)
|
||||
#define UMAC_MAC0 0x00c
|
||||
#define UMAC_MAC1 0x010
|
||||
#define UMAC_MAX_FRAME_LEN 0x014
|
||||
#define UMAC_PAUSE_QUANTA 0x018
|
||||
#define UMAC_MODE 0x044
|
||||
#define MODE_LINK_STATUS (1 << 5)
|
||||
#define UMAC_FRM_TAG0 0x048 /* outer tag */
|
||||
#define UMAC_FRM_TAG1 0x04c /* inner tag */
|
||||
#define UMAC_TX_IPG_LEN 0x05c
|
||||
#define UMAC_EEE_CTRL 0x064
|
||||
#define EN_LPI_RX_PAUSE (1 << 0)
|
||||
#define EN_LPI_TX_PFC (1 << 1)
|
||||
#define EN_LPI_TX_PAUSE (1 << 2)
|
||||
#define EEE_EN (1 << 3)
|
||||
#define RX_FIFO_CHECK (1 << 4)
|
||||
#define EEE_TX_CLK_DIS (1 << 5)
|
||||
#define DIS_EEE_10M (1 << 6)
|
||||
#define LP_IDLE_PREDICTION_MODE (1 << 7)
|
||||
#define UMAC_EEE_LPI_TIMER 0x068
|
||||
#define UMAC_EEE_WAKE_TIMER 0x06C
|
||||
#define UMAC_EEE_REF_COUNT 0x070
|
||||
#define EEE_REFERENCE_COUNT_MASK 0xffff
|
||||
#define UMAC_RX_IPG_INV 0x078
|
||||
#define UMAC_MACSEC_PROG_TX_CRC 0x310
|
||||
#define UMAC_MACSEC_CTRL 0x314
|
||||
#define UMAC_PAUSE_CTRL 0x330
|
||||
#define UMAC_TX_FLUSH 0x334
|
||||
#define UMAC_RX_FIFO_STATUS 0x338
|
||||
#define UMAC_TX_FIFO_STATUS 0x33c
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
#ifndef __UNIMAC_H
|
||||
#define __UNIMAC_H
|
||||
|
||||
#define UMAC_HD_BKP_CTRL 0x004
|
||||
#define HD_FC_EN (1 << 0)
|
||||
#define HD_FC_BKOFF_OK (1 << 1)
|
||||
#define IPG_CONFIG_RX_SHIFT 2
|
||||
#define IPG_CONFIG_RX_MASK 0x1F
|
||||
#define UMAC_CMD 0x008
|
||||
#define CMD_TX_EN (1 << 0)
|
||||
#define CMD_RX_EN (1 << 1)
|
||||
#define CMD_SPEED_10 0
|
||||
#define CMD_SPEED_100 1
|
||||
#define CMD_SPEED_1000 2
|
||||
#define CMD_SPEED_2500 3
|
||||
#define CMD_SPEED_SHIFT 2
|
||||
#define CMD_SPEED_MASK 3
|
||||
#define CMD_PROMISC (1 << 4)
|
||||
#define CMD_PAD_EN (1 << 5)
|
||||
#define CMD_CRC_FWD (1 << 6)
|
||||
#define CMD_PAUSE_FWD (1 << 7)
|
||||
#define CMD_RX_PAUSE_IGNORE (1 << 8)
|
||||
#define CMD_TX_ADDR_INS (1 << 9)
|
||||
#define CMD_HD_EN (1 << 10)
|
||||
#define CMD_SW_RESET_OLD (1 << 11)
|
||||
#define CMD_SW_RESET (1 << 13)
|
||||
#define CMD_LCL_LOOP_EN (1 << 15)
|
||||
#define CMD_AUTO_CONFIG (1 << 22)
|
||||
#define CMD_CNTL_FRM_EN (1 << 23)
|
||||
#define CMD_NO_LEN_CHK (1 << 24)
|
||||
#define CMD_RMT_LOOP_EN (1 << 25)
|
||||
#define CMD_RX_ERR_DISC (1 << 26)
|
||||
#define CMD_PRBL_EN (1 << 27)
|
||||
#define CMD_TX_PAUSE_IGNORE (1 << 28)
|
||||
#define CMD_TX_RX_EN (1 << 29)
|
||||
#define CMD_RUNT_FILTER_DIS (1 << 30)
|
||||
#define UMAC_MAC0 0x00c
|
||||
#define UMAC_MAC1 0x010
|
||||
#define UMAC_MAX_FRAME_LEN 0x014
|
||||
#define UMAC_PAUSE_QUANTA 0x018
|
||||
#define UMAC_MODE 0x044
|
||||
#define MODE_LINK_STATUS (1 << 5)
|
||||
#define UMAC_FRM_TAG0 0x048 /* outer tag */
|
||||
#define UMAC_FRM_TAG1 0x04c /* inner tag */
|
||||
#define UMAC_TX_IPG_LEN 0x05c
|
||||
#define UMAC_EEE_CTRL 0x064
|
||||
#define EN_LPI_RX_PAUSE (1 << 0)
|
||||
#define EN_LPI_TX_PFC (1 << 1)
|
||||
#define EN_LPI_TX_PAUSE (1 << 2)
|
||||
#define EEE_EN (1 << 3)
|
||||
#define RX_FIFO_CHECK (1 << 4)
|
||||
#define EEE_TX_CLK_DIS (1 << 5)
|
||||
#define DIS_EEE_10M (1 << 6)
|
||||
#define LP_IDLE_PREDICTION_MODE (1 << 7)
|
||||
#define UMAC_EEE_LPI_TIMER 0x068
|
||||
#define UMAC_EEE_WAKE_TIMER 0x06C
|
||||
#define UMAC_EEE_REF_COUNT 0x070
|
||||
#define EEE_REFERENCE_COUNT_MASK 0xffff
|
||||
#define UMAC_RX_IPG_INV 0x078
|
||||
#define UMAC_MACSEC_PROG_TX_CRC 0x310
|
||||
#define UMAC_MACSEC_CTRL 0x314
|
||||
#define UMAC_PAUSE_CTRL 0x330
|
||||
#define UMAC_TX_FLUSH 0x334
|
||||
#define UMAC_RX_FIFO_STATUS 0x338
|
||||
#define UMAC_TX_FIFO_STATUS 0x33c
|
||||
|
||||
#endif
|
||||
|
|
@ -44,10 +44,18 @@ EXTRA_DIST = \
|
|||
e1000_82575-5.10-ethercat.h \
|
||||
e1000_82575-5.10-orig.c \
|
||||
e1000_82575-5.10-orig.h \
|
||||
e1000_82575-5.14-ethercat.c \
|
||||
e1000_82575-5.14-ethercat.h \
|
||||
e1000_82575-5.14-orig.c \
|
||||
e1000_82575-5.14-orig.h \
|
||||
e1000_82575-5.15-ethercat.c \
|
||||
e1000_82575-5.15-ethercat.h \
|
||||
e1000_82575-5.15-orig.c \
|
||||
e1000_82575-5.15-orig.h \
|
||||
e1000_82575-6.1-ethercat.c \
|
||||
e1000_82575-6.1-ethercat.h \
|
||||
e1000_82575-6.1-orig.c \
|
||||
e1000_82575-6.1-orig.h \
|
||||
e1000_defines-3.18-ethercat.h \
|
||||
e1000_defines-3.18-orig.h \
|
||||
e1000_defines-4.19-ethercat.h \
|
||||
|
|
@ -56,8 +64,12 @@ EXTRA_DIST = \
|
|||
e1000_defines-4.4-orig.h \
|
||||
e1000_defines-5.10-ethercat.h \
|
||||
e1000_defines-5.10-orig.h \
|
||||
e1000_defines-5.14-ethercat.h \
|
||||
e1000_defines-5.14-orig.h \
|
||||
e1000_defines-5.15-ethercat.h \
|
||||
e1000_defines-5.15-orig.h \
|
||||
e1000_defines-6.1-ethercat.h \
|
||||
e1000_defines-6.1-orig.h \
|
||||
e1000_hw-3.18-ethercat.h \
|
||||
e1000_hw-3.18-orig.h \
|
||||
e1000_hw-4.19-ethercat.h \
|
||||
|
|
@ -66,8 +78,12 @@ EXTRA_DIST = \
|
|||
e1000_hw-4.4-orig.h \
|
||||
e1000_hw-5.10-ethercat.h \
|
||||
e1000_hw-5.10-orig.h \
|
||||
e1000_hw-5.14-ethercat.h \
|
||||
e1000_hw-5.14-orig.h \
|
||||
e1000_hw-5.15-ethercat.h \
|
||||
e1000_hw-5.15-orig.h \
|
||||
e1000_hw-6.1-ethercat.h \
|
||||
e1000_hw-6.1-orig.h \
|
||||
e1000_i210-3.18-ethercat.c \
|
||||
e1000_i210-3.18-ethercat.h \
|
||||
e1000_i210-3.18-orig.c \
|
||||
|
|
@ -84,10 +100,18 @@ EXTRA_DIST = \
|
|||
e1000_i210-5.10-ethercat.h \
|
||||
e1000_i210-5.10-orig.c \
|
||||
e1000_i210-5.10-orig.h \
|
||||
e1000_i210-5.14-ethercat.c \
|
||||
e1000_i210-5.14-ethercat.h \
|
||||
e1000_i210-5.14-orig.c \
|
||||
e1000_i210-5.14-orig.h \
|
||||
e1000_i210-5.15-ethercat.c \
|
||||
e1000_i210-5.15-ethercat.h \
|
||||
e1000_i210-5.15-orig.c \
|
||||
e1000_i210-5.15-orig.h \
|
||||
e1000_i210-6.1-ethercat.c \
|
||||
e1000_i210-6.1-ethercat.h \
|
||||
e1000_i210-6.1-orig.c \
|
||||
e1000_i210-6.1-orig.h \
|
||||
e1000_mac-3.18-ethercat.c \
|
||||
e1000_mac-3.18-ethercat.h \
|
||||
e1000_mac-3.18-orig.c \
|
||||
|
|
@ -104,10 +128,18 @@ EXTRA_DIST = \
|
|||
e1000_mac-5.10-ethercat.h \
|
||||
e1000_mac-5.10-orig.c \
|
||||
e1000_mac-5.10-orig.h \
|
||||
e1000_mac-5.14-ethercat.c \
|
||||
e1000_mac-5.14-ethercat.h \
|
||||
e1000_mac-5.14-orig.c \
|
||||
e1000_mac-5.14-orig.h \
|
||||
e1000_mac-5.15-ethercat.c \
|
||||
e1000_mac-5.15-ethercat.h \
|
||||
e1000_mac-5.15-orig.c \
|
||||
e1000_mac-5.15-orig.h \
|
||||
e1000_mac-6.1-ethercat.c \
|
||||
e1000_mac-6.1-ethercat.h \
|
||||
e1000_mac-6.1-orig.c \
|
||||
e1000_mac-6.1-orig.h \
|
||||
e1000_mbx-3.18-ethercat.c \
|
||||
e1000_mbx-3.18-ethercat.h \
|
||||
e1000_mbx-3.18-orig.c \
|
||||
|
|
@ -124,10 +156,18 @@ EXTRA_DIST = \
|
|||
e1000_mbx-5.10-ethercat.h \
|
||||
e1000_mbx-5.10-orig.c \
|
||||
e1000_mbx-5.10-orig.h \
|
||||
e1000_mbx-5.14-ethercat.c \
|
||||
e1000_mbx-5.14-ethercat.h \
|
||||
e1000_mbx-5.14-orig.c \
|
||||
e1000_mbx-5.14-orig.h \
|
||||
e1000_mbx-5.15-ethercat.c \
|
||||
e1000_mbx-5.15-ethercat.h \
|
||||
e1000_mbx-5.15-orig.c \
|
||||
e1000_mbx-5.15-orig.h \
|
||||
e1000_mbx-6.1-ethercat.c \
|
||||
e1000_mbx-6.1-ethercat.h \
|
||||
e1000_mbx-6.1-orig.c \
|
||||
e1000_mbx-6.1-orig.h \
|
||||
e1000_nvm-3.18-ethercat.c \
|
||||
e1000_nvm-3.18-ethercat.h \
|
||||
e1000_nvm-3.18-orig.c \
|
||||
|
|
@ -144,10 +184,18 @@ EXTRA_DIST = \
|
|||
e1000_nvm-5.10-ethercat.h \
|
||||
e1000_nvm-5.10-orig.c \
|
||||
e1000_nvm-5.10-orig.h \
|
||||
e1000_nvm-5.14-ethercat.c \
|
||||
e1000_nvm-5.14-ethercat.h \
|
||||
e1000_nvm-5.14-orig.c \
|
||||
e1000_nvm-5.14-orig.h \
|
||||
e1000_nvm-5.15-ethercat.c \
|
||||
e1000_nvm-5.15-ethercat.h \
|
||||
e1000_nvm-5.15-orig.c \
|
||||
e1000_nvm-5.15-orig.h \
|
||||
e1000_nvm-6.1-ethercat.c \
|
||||
e1000_nvm-6.1-ethercat.h \
|
||||
e1000_nvm-6.1-orig.c \
|
||||
e1000_nvm-6.1-orig.h \
|
||||
e1000_phy-3.18-ethercat.c \
|
||||
e1000_phy-3.18-ethercat.h \
|
||||
e1000_phy-3.18-orig.c \
|
||||
|
|
@ -164,10 +212,18 @@ EXTRA_DIST = \
|
|||
e1000_phy-5.10-ethercat.h \
|
||||
e1000_phy-5.10-orig.c \
|
||||
e1000_phy-5.10-orig.h \
|
||||
e1000_phy-5.14-ethercat.c \
|
||||
e1000_phy-5.14-ethercat.h \
|
||||
e1000_phy-5.14-orig.c \
|
||||
e1000_phy-5.14-orig.h \
|
||||
e1000_phy-5.15-ethercat.c \
|
||||
e1000_phy-5.15-ethercat.h \
|
||||
e1000_phy-5.15-orig.c \
|
||||
e1000_phy-5.15-orig.h \
|
||||
e1000_phy-6.1-ethercat.c \
|
||||
e1000_phy-6.1-ethercat.h \
|
||||
e1000_phy-6.1-orig.c \
|
||||
e1000_phy-6.1-orig.h \
|
||||
e1000_regs-3.18-ethercat.h \
|
||||
e1000_regs-3.18-orig.h \
|
||||
e1000_regs-4.19-ethercat.h \
|
||||
|
|
@ -176,8 +232,12 @@ EXTRA_DIST = \
|
|||
e1000_regs-4.4-orig.h \
|
||||
e1000_regs-5.10-ethercat.h \
|
||||
e1000_regs-5.10-orig.h \
|
||||
e1000_regs-5.14-ethercat.h \
|
||||
e1000_regs-5.14-orig.h \
|
||||
e1000_regs-5.15-ethercat.h \
|
||||
e1000_regs-5.15-orig.h \
|
||||
e1000_regs-6.1-ethercat.h \
|
||||
e1000_regs-6.1-orig.h \
|
||||
igb-3.18-ethercat.h \
|
||||
igb-3.18-orig.h \
|
||||
igb-4.19-ethercat.h \
|
||||
|
|
@ -186,8 +246,12 @@ EXTRA_DIST = \
|
|||
igb-4.4-orig.h \
|
||||
igb-5.10-ethercat.h \
|
||||
igb-5.10-orig.h \
|
||||
igb-5.14-ethercat.h \
|
||||
igb-5.14-orig.h \
|
||||
igb-5.15-ethercat.h \
|
||||
igb-5.15-orig.h \
|
||||
igb-6.1-ethercat.h \
|
||||
igb-6.1-orig.h \
|
||||
igb_ethtool-3.18-ethercat.c \
|
||||
igb_ethtool-3.18-orig.c \
|
||||
igb_ethtool-4.19-ethercat.c \
|
||||
|
|
@ -196,8 +260,12 @@ EXTRA_DIST = \
|
|||
igb_ethtool-4.4-orig.c \
|
||||
igb_ethtool-5.10-ethercat.c \
|
||||
igb_ethtool-5.10-orig.c \
|
||||
igb_ethtool-5.14-ethercat.c \
|
||||
igb_ethtool-5.14-orig.c \
|
||||
igb_ethtool-5.15-ethercat.c \
|
||||
igb_ethtool-5.15-orig.c \
|
||||
igb_ethtool-6.1-ethercat.c \
|
||||
igb_ethtool-6.1-orig.c \
|
||||
igb_hwmon-3.18-ethercat.c \
|
||||
igb_hwmon-3.18-orig.c \
|
||||
igb_hwmon-4.19-ethercat.c \
|
||||
|
|
@ -206,8 +274,12 @@ EXTRA_DIST = \
|
|||
igb_hwmon-4.4-orig.c \
|
||||
igb_hwmon-5.10-ethercat.c \
|
||||
igb_hwmon-5.10-orig.c \
|
||||
igb_hwmon-5.14-ethercat.c \
|
||||
igb_hwmon-5.14-orig.c \
|
||||
igb_hwmon-5.15-ethercat.c \
|
||||
igb_hwmon-5.15-orig.c \
|
||||
igb_hwmon-6.1-ethercat.c \
|
||||
igb_hwmon-6.1-orig.c \
|
||||
igb_main-3.18-ethercat.c \
|
||||
igb_main-3.18-orig.c \
|
||||
igb_main-4.19-ethercat.c \
|
||||
|
|
@ -216,8 +288,12 @@ EXTRA_DIST = \
|
|||
igb_main-4.4-orig.c \
|
||||
igb_main-5.10-ethercat.c \
|
||||
igb_main-5.10-orig.c \
|
||||
igb_main-5.14-ethercat.c \
|
||||
igb_main-5.14-orig.c \
|
||||
igb_main-5.15-ethercat.c \
|
||||
igb_main-5.15-orig.c \
|
||||
igb_main-6.1-ethercat.c \
|
||||
igb_main-6.1-orig.c \
|
||||
igb_ptp-3.18-ethercat.c \
|
||||
igb_ptp-3.18-orig.c \
|
||||
igb_ptp-4.19-ethercat.c \
|
||||
|
|
@ -226,8 +302,12 @@ EXTRA_DIST = \
|
|||
igb_ptp-4.4-orig.c \
|
||||
igb_ptp-5.10-ethercat.c \
|
||||
igb_ptp-5.10-orig.c \
|
||||
igb_ptp-5.14-ethercat.c \
|
||||
igb_ptp-5.14-orig.c \
|
||||
igb_ptp-5.15-ethercat.c \
|
||||
igb_ptp-5.15-orig.c \
|
||||
igb_ptp-6.1-ethercat.c \
|
||||
igb_ptp-6.1-orig.c \
|
||||
update.sh
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -0,0 +1,554 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_IGB_HW_H_
|
||||
#define _E1000_IGB_HW_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "e1000_regs.h"
|
||||
#include "e1000_defines.h"
|
||||
|
||||
struct e1000_hw;
|
||||
|
||||
#define E1000_DEV_ID_82576 0x10C9
|
||||
#define E1000_DEV_ID_82576_FIBER 0x10E6
|
||||
#define E1000_DEV_ID_82576_SERDES 0x10E7
|
||||
#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8
|
||||
#define E1000_DEV_ID_82576_QUAD_COPPER_ET2 0x1526
|
||||
#define E1000_DEV_ID_82576_NS 0x150A
|
||||
#define E1000_DEV_ID_82576_NS_SERDES 0x1518
|
||||
#define E1000_DEV_ID_82576_SERDES_QUAD 0x150D
|
||||
#define E1000_DEV_ID_82575EB_COPPER 0x10A7
|
||||
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
|
||||
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
|
||||
#define E1000_DEV_ID_82580_COPPER 0x150E
|
||||
#define E1000_DEV_ID_82580_FIBER 0x150F
|
||||
#define E1000_DEV_ID_82580_SERDES 0x1510
|
||||
#define E1000_DEV_ID_82580_SGMII 0x1511
|
||||
#define E1000_DEV_ID_82580_COPPER_DUAL 0x1516
|
||||
#define E1000_DEV_ID_82580_QUAD_FIBER 0x1527
|
||||
#define E1000_DEV_ID_DH89XXCC_SGMII 0x0438
|
||||
#define E1000_DEV_ID_DH89XXCC_SERDES 0x043A
|
||||
#define E1000_DEV_ID_DH89XXCC_BACKPLANE 0x043C
|
||||
#define E1000_DEV_ID_DH89XXCC_SFP 0x0440
|
||||
#define E1000_DEV_ID_I350_COPPER 0x1521
|
||||
#define E1000_DEV_ID_I350_FIBER 0x1522
|
||||
#define E1000_DEV_ID_I350_SERDES 0x1523
|
||||
#define E1000_DEV_ID_I350_SGMII 0x1524
|
||||
#define E1000_DEV_ID_I210_COPPER 0x1533
|
||||
#define E1000_DEV_ID_I210_FIBER 0x1536
|
||||
#define E1000_DEV_ID_I210_SERDES 0x1537
|
||||
#define E1000_DEV_ID_I210_SGMII 0x1538
|
||||
#define E1000_DEV_ID_I210_COPPER_FLASHLESS 0x157B
|
||||
#define E1000_DEV_ID_I210_SERDES_FLASHLESS 0x157C
|
||||
#define E1000_DEV_ID_I211_COPPER 0x1539
|
||||
#define E1000_DEV_ID_I354_BACKPLANE_1GBPS 0x1F40
|
||||
#define E1000_DEV_ID_I354_SGMII 0x1F41
|
||||
#define E1000_DEV_ID_I354_BACKPLANE_2_5GBPS 0x1F45
|
||||
|
||||
#define E1000_REVISION_2 2
|
||||
#define E1000_REVISION_4 4
|
||||
|
||||
#define E1000_FUNC_0 0
|
||||
#define E1000_FUNC_1 1
|
||||
#define E1000_FUNC_2 2
|
||||
#define E1000_FUNC_3 3
|
||||
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN2 6
|
||||
#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN3 9
|
||||
|
||||
enum e1000_mac_type {
|
||||
e1000_undefined = 0,
|
||||
e1000_82575,
|
||||
e1000_82576,
|
||||
e1000_82580,
|
||||
e1000_i350,
|
||||
e1000_i354,
|
||||
e1000_i210,
|
||||
e1000_i211,
|
||||
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
|
||||
};
|
||||
|
||||
enum e1000_media_type {
|
||||
e1000_media_type_unknown = 0,
|
||||
e1000_media_type_copper = 1,
|
||||
e1000_media_type_fiber = 2,
|
||||
e1000_media_type_internal_serdes = 3,
|
||||
e1000_num_media_types
|
||||
};
|
||||
|
||||
enum e1000_nvm_type {
|
||||
e1000_nvm_unknown = 0,
|
||||
e1000_nvm_none,
|
||||
e1000_nvm_eeprom_spi,
|
||||
e1000_nvm_flash_hw,
|
||||
e1000_nvm_invm,
|
||||
e1000_nvm_flash_sw
|
||||
};
|
||||
|
||||
enum e1000_nvm_override {
|
||||
e1000_nvm_override_none = 0,
|
||||
e1000_nvm_override_spi_small,
|
||||
e1000_nvm_override_spi_large,
|
||||
};
|
||||
|
||||
enum e1000_phy_type {
|
||||
e1000_phy_unknown = 0,
|
||||
e1000_phy_none,
|
||||
e1000_phy_m88,
|
||||
e1000_phy_igp,
|
||||
e1000_phy_igp_2,
|
||||
e1000_phy_gg82563,
|
||||
e1000_phy_igp_3,
|
||||
e1000_phy_ife,
|
||||
e1000_phy_82580,
|
||||
e1000_phy_i210,
|
||||
e1000_phy_bcm54616,
|
||||
};
|
||||
|
||||
enum e1000_bus_type {
|
||||
e1000_bus_type_unknown = 0,
|
||||
e1000_bus_type_pci,
|
||||
e1000_bus_type_pcix,
|
||||
e1000_bus_type_pci_express,
|
||||
e1000_bus_type_reserved
|
||||
};
|
||||
|
||||
enum e1000_bus_speed {
|
||||
e1000_bus_speed_unknown = 0,
|
||||
e1000_bus_speed_33,
|
||||
e1000_bus_speed_66,
|
||||
e1000_bus_speed_100,
|
||||
e1000_bus_speed_120,
|
||||
e1000_bus_speed_133,
|
||||
e1000_bus_speed_2500,
|
||||
e1000_bus_speed_5000,
|
||||
e1000_bus_speed_reserved
|
||||
};
|
||||
|
||||
enum e1000_bus_width {
|
||||
e1000_bus_width_unknown = 0,
|
||||
e1000_bus_width_pcie_x1,
|
||||
e1000_bus_width_pcie_x2,
|
||||
e1000_bus_width_pcie_x4 = 4,
|
||||
e1000_bus_width_pcie_x8 = 8,
|
||||
e1000_bus_width_32,
|
||||
e1000_bus_width_64,
|
||||
e1000_bus_width_reserved
|
||||
};
|
||||
|
||||
enum e1000_1000t_rx_status {
|
||||
e1000_1000t_rx_status_not_ok = 0,
|
||||
e1000_1000t_rx_status_ok,
|
||||
e1000_1000t_rx_status_undefined = 0xFF
|
||||
};
|
||||
|
||||
enum e1000_rev_polarity {
|
||||
e1000_rev_polarity_normal = 0,
|
||||
e1000_rev_polarity_reversed,
|
||||
e1000_rev_polarity_undefined = 0xFF
|
||||
};
|
||||
|
||||
enum e1000_fc_mode {
|
||||
e1000_fc_none = 0,
|
||||
e1000_fc_rx_pause,
|
||||
e1000_fc_tx_pause,
|
||||
e1000_fc_full,
|
||||
e1000_fc_default = 0xFF
|
||||
};
|
||||
|
||||
/* Statistics counters collected by the MAC */
|
||||
struct e1000_hw_stats {
|
||||
u64 crcerrs;
|
||||
u64 algnerrc;
|
||||
u64 symerrs;
|
||||
u64 rxerrc;
|
||||
u64 mpc;
|
||||
u64 scc;
|
||||
u64 ecol;
|
||||
u64 mcc;
|
||||
u64 latecol;
|
||||
u64 colc;
|
||||
u64 dc;
|
||||
u64 tncrs;
|
||||
u64 sec;
|
||||
u64 cexterr;
|
||||
u64 rlec;
|
||||
u64 xonrxc;
|
||||
u64 xontxc;
|
||||
u64 xoffrxc;
|
||||
u64 xofftxc;
|
||||
u64 fcruc;
|
||||
u64 prc64;
|
||||
u64 prc127;
|
||||
u64 prc255;
|
||||
u64 prc511;
|
||||
u64 prc1023;
|
||||
u64 prc1522;
|
||||
u64 gprc;
|
||||
u64 bprc;
|
||||
u64 mprc;
|
||||
u64 gptc;
|
||||
u64 gorc;
|
||||
u64 gotc;
|
||||
u64 rnbc;
|
||||
u64 ruc;
|
||||
u64 rfc;
|
||||
u64 roc;
|
||||
u64 rjc;
|
||||
u64 mgprc;
|
||||
u64 mgpdc;
|
||||
u64 mgptc;
|
||||
u64 tor;
|
||||
u64 tot;
|
||||
u64 tpr;
|
||||
u64 tpt;
|
||||
u64 ptc64;
|
||||
u64 ptc127;
|
||||
u64 ptc255;
|
||||
u64 ptc511;
|
||||
u64 ptc1023;
|
||||
u64 ptc1522;
|
||||
u64 mptc;
|
||||
u64 bptc;
|
||||
u64 tsctc;
|
||||
u64 tsctfc;
|
||||
u64 iac;
|
||||
u64 icrxptc;
|
||||
u64 icrxatc;
|
||||
u64 ictxptc;
|
||||
u64 ictxatc;
|
||||
u64 ictxqec;
|
||||
u64 ictxqmtc;
|
||||
u64 icrxdmtc;
|
||||
u64 icrxoc;
|
||||
u64 cbtmpc;
|
||||
u64 htdpmc;
|
||||
u64 cbrdpc;
|
||||
u64 cbrmpc;
|
||||
u64 rpthc;
|
||||
u64 hgptc;
|
||||
u64 htcbdpc;
|
||||
u64 hgorc;
|
||||
u64 hgotc;
|
||||
u64 lenerrs;
|
||||
u64 scvpc;
|
||||
u64 hrmpc;
|
||||
u64 doosync;
|
||||
u64 o2bgptc;
|
||||
u64 o2bspc;
|
||||
u64 b2ospc;
|
||||
u64 b2ogprc;
|
||||
};
|
||||
|
||||
struct e1000_host_mng_dhcp_cookie {
|
||||
u32 signature;
|
||||
u8 status;
|
||||
u8 reserved0;
|
||||
u16 vlan_id;
|
||||
u32 reserved1;
|
||||
u16 reserved2;
|
||||
u8 reserved3;
|
||||
u8 checksum;
|
||||
};
|
||||
|
||||
/* Host Interface "Rev 1" */
|
||||
struct e1000_host_command_header {
|
||||
u8 command_id;
|
||||
u8 command_length;
|
||||
u8 command_options;
|
||||
u8 checksum;
|
||||
};
|
||||
|
||||
#define E1000_HI_MAX_DATA_LENGTH 252
|
||||
struct e1000_host_command_info {
|
||||
struct e1000_host_command_header command_header;
|
||||
u8 command_data[E1000_HI_MAX_DATA_LENGTH];
|
||||
};
|
||||
|
||||
/* Host Interface "Rev 2" */
|
||||
struct e1000_host_mng_command_header {
|
||||
u8 command_id;
|
||||
u8 checksum;
|
||||
u16 reserved1;
|
||||
u16 reserved2;
|
||||
u16 command_length;
|
||||
};
|
||||
|
||||
#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8
|
||||
struct e1000_host_mng_command_info {
|
||||
struct e1000_host_mng_command_header command_header;
|
||||
u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH];
|
||||
};
|
||||
|
||||
#include "e1000_mac.h"
|
||||
#include "e1000_phy.h"
|
||||
#include "e1000_nvm.h"
|
||||
#include "e1000_mbx.h"
|
||||
|
||||
struct e1000_mac_operations {
|
||||
s32 (*check_for_link)(struct e1000_hw *);
|
||||
s32 (*reset_hw)(struct e1000_hw *);
|
||||
s32 (*init_hw)(struct e1000_hw *);
|
||||
bool (*check_mng_mode)(struct e1000_hw *);
|
||||
s32 (*setup_physical_interface)(struct e1000_hw *);
|
||||
void (*rar_set)(struct e1000_hw *, u8 *, u32);
|
||||
s32 (*read_mac_addr)(struct e1000_hw *);
|
||||
s32 (*get_speed_and_duplex)(struct e1000_hw *, u16 *, u16 *);
|
||||
s32 (*acquire_swfw_sync)(struct e1000_hw *, u16);
|
||||
void (*release_swfw_sync)(struct e1000_hw *, u16);
|
||||
#ifdef CONFIG_IGB_HWMON
|
||||
s32 (*get_thermal_sensor_data)(struct e1000_hw *);
|
||||
s32 (*init_thermal_sensor_thresh)(struct e1000_hw *);
|
||||
#endif
|
||||
void (*write_vfta)(struct e1000_hw *, u32, u32);
|
||||
};
|
||||
|
||||
struct e1000_phy_operations {
|
||||
s32 (*acquire)(struct e1000_hw *);
|
||||
s32 (*check_polarity)(struct e1000_hw *);
|
||||
s32 (*check_reset_block)(struct e1000_hw *);
|
||||
s32 (*force_speed_duplex)(struct e1000_hw *);
|
||||
s32 (*get_cfg_done)(struct e1000_hw *hw);
|
||||
s32 (*get_cable_length)(struct e1000_hw *);
|
||||
s32 (*get_phy_info)(struct e1000_hw *);
|
||||
s32 (*read_reg)(struct e1000_hw *, u32, u16 *);
|
||||
void (*release)(struct e1000_hw *);
|
||||
s32 (*reset)(struct e1000_hw *);
|
||||
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
|
||||
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
|
||||
s32 (*write_reg)(struct e1000_hw *, u32, u16);
|
||||
s32 (*read_i2c_byte)(struct e1000_hw *, u8, u8, u8 *);
|
||||
s32 (*write_i2c_byte)(struct e1000_hw *, u8, u8, u8);
|
||||
};
|
||||
|
||||
struct e1000_nvm_operations {
|
||||
s32 (*acquire)(struct e1000_hw *);
|
||||
s32 (*read)(struct e1000_hw *, u16, u16, u16 *);
|
||||
void (*release)(struct e1000_hw *);
|
||||
s32 (*write)(struct e1000_hw *, u16, u16, u16 *);
|
||||
s32 (*update)(struct e1000_hw *);
|
||||
s32 (*validate)(struct e1000_hw *);
|
||||
s32 (*valid_led_default)(struct e1000_hw *, u16 *);
|
||||
};
|
||||
|
||||
#define E1000_MAX_SENSORS 3
|
||||
|
||||
struct e1000_thermal_diode_data {
|
||||
u8 location;
|
||||
u8 temp;
|
||||
u8 caution_thresh;
|
||||
u8 max_op_thresh;
|
||||
};
|
||||
|
||||
struct e1000_thermal_sensor_data {
|
||||
struct e1000_thermal_diode_data sensor[E1000_MAX_SENSORS];
|
||||
};
|
||||
|
||||
struct e1000_info {
|
||||
s32 (*get_invariants)(struct e1000_hw *);
|
||||
struct e1000_mac_operations *mac_ops;
|
||||
const struct e1000_phy_operations *phy_ops;
|
||||
struct e1000_nvm_operations *nvm_ops;
|
||||
};
|
||||
|
||||
extern const struct e1000_info e1000_82575_info;
|
||||
|
||||
struct e1000_mac_info {
|
||||
struct e1000_mac_operations ops;
|
||||
|
||||
u8 addr[6];
|
||||
u8 perm_addr[6];
|
||||
|
||||
enum e1000_mac_type type;
|
||||
|
||||
u32 ledctl_default;
|
||||
u32 ledctl_mode1;
|
||||
u32 ledctl_mode2;
|
||||
u32 mc_filter_type;
|
||||
u32 txcw;
|
||||
|
||||
u16 mta_reg_count;
|
||||
u16 uta_reg_count;
|
||||
|
||||
/* Maximum size of the MTA register table in all supported adapters */
|
||||
#define MAX_MTA_REG 128
|
||||
u32 mta_shadow[MAX_MTA_REG];
|
||||
u16 rar_entry_count;
|
||||
|
||||
u8 forced_speed_duplex;
|
||||
|
||||
bool adaptive_ifs;
|
||||
bool arc_subsystem_valid;
|
||||
bool asf_firmware_present;
|
||||
bool autoneg;
|
||||
bool autoneg_failed;
|
||||
bool disable_hw_init_bits;
|
||||
bool get_link_status;
|
||||
bool ifs_params_forced;
|
||||
bool in_ifs_mode;
|
||||
bool report_tx_early;
|
||||
bool serdes_has_link;
|
||||
bool tx_pkt_filtering;
|
||||
struct e1000_thermal_sensor_data thermal_sensor_data;
|
||||
};
|
||||
|
||||
struct e1000_phy_info {
|
||||
struct e1000_phy_operations ops;
|
||||
|
||||
enum e1000_phy_type type;
|
||||
|
||||
enum e1000_1000t_rx_status local_rx;
|
||||
enum e1000_1000t_rx_status remote_rx;
|
||||
enum e1000_ms_type ms_type;
|
||||
enum e1000_ms_type original_ms_type;
|
||||
enum e1000_rev_polarity cable_polarity;
|
||||
enum e1000_smart_speed smart_speed;
|
||||
|
||||
u32 addr;
|
||||
u32 id;
|
||||
u32 reset_delay_us; /* in usec */
|
||||
u32 revision;
|
||||
|
||||
enum e1000_media_type media_type;
|
||||
|
||||
u16 autoneg_advertised;
|
||||
u16 autoneg_mask;
|
||||
u16 cable_length;
|
||||
u16 max_cable_length;
|
||||
u16 min_cable_length;
|
||||
u16 pair_length[4];
|
||||
|
||||
u8 mdix;
|
||||
|
||||
bool disable_polarity_correction;
|
||||
bool is_mdix;
|
||||
bool polarity_correction;
|
||||
bool reset_disable;
|
||||
bool speed_downgraded;
|
||||
bool autoneg_wait_to_complete;
|
||||
};
|
||||
|
||||
struct e1000_nvm_info {
|
||||
struct e1000_nvm_operations ops;
|
||||
enum e1000_nvm_type type;
|
||||
enum e1000_nvm_override override;
|
||||
|
||||
u32 flash_bank_size;
|
||||
u32 flash_base_addr;
|
||||
|
||||
u16 word_size;
|
||||
u16 delay_usec;
|
||||
u16 address_bits;
|
||||
u16 opcode_bits;
|
||||
u16 page_size;
|
||||
};
|
||||
|
||||
struct e1000_bus_info {
|
||||
enum e1000_bus_type type;
|
||||
enum e1000_bus_speed speed;
|
||||
enum e1000_bus_width width;
|
||||
|
||||
u32 snoop;
|
||||
|
||||
u16 func;
|
||||
u16 pci_cmd_word;
|
||||
};
|
||||
|
||||
struct e1000_fc_info {
|
||||
u32 high_water; /* Flow control high-water mark */
|
||||
u32 low_water; /* Flow control low-water mark */
|
||||
u16 pause_time; /* Flow control pause timer */
|
||||
bool send_xon; /* Flow control send XON */
|
||||
bool strict_ieee; /* Strict IEEE mode */
|
||||
enum e1000_fc_mode current_mode; /* Type of flow control */
|
||||
enum e1000_fc_mode requested_mode;
|
||||
};
|
||||
|
||||
struct e1000_mbx_operations {
|
||||
s32 (*init_params)(struct e1000_hw *hw);
|
||||
s32 (*read)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id,
|
||||
bool unlock);
|
||||
s32 (*write)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
|
||||
s32 (*read_posted)(struct e1000_hw *hw, u32 *msg, u16 size, u16 mbx_id);
|
||||
s32 (*write_posted)(struct e1000_hw *hw, u32 *msg, u16 size,
|
||||
u16 mbx_id);
|
||||
s32 (*check_for_msg)(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 (*check_for_ack)(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 (*check_for_rst)(struct e1000_hw *hw, u16 mbx_id);
|
||||
s32 (*unlock)(struct e1000_hw *hw, u16 mbx_id);
|
||||
};
|
||||
|
||||
struct e1000_mbx_stats {
|
||||
u32 msgs_tx;
|
||||
u32 msgs_rx;
|
||||
|
||||
u32 acks;
|
||||
u32 reqs;
|
||||
u32 rsts;
|
||||
};
|
||||
|
||||
struct e1000_mbx_info {
|
||||
struct e1000_mbx_operations ops;
|
||||
struct e1000_mbx_stats stats;
|
||||
u32 timeout;
|
||||
u32 usec_delay;
|
||||
u16 size;
|
||||
};
|
||||
|
||||
struct e1000_dev_spec_82575 {
|
||||
bool sgmii_active;
|
||||
bool global_device_reset;
|
||||
bool eee_disable;
|
||||
bool clear_semaphore_once;
|
||||
struct e1000_sfp_flags eth_flags;
|
||||
bool module_plugged;
|
||||
u8 media_port;
|
||||
bool media_changed;
|
||||
bool mas_capable;
|
||||
};
|
||||
|
||||
struct e1000_hw {
|
||||
void *back;
|
||||
|
||||
u8 __iomem *hw_addr;
|
||||
u8 __iomem *flash_address;
|
||||
unsigned long io_base;
|
||||
|
||||
struct e1000_mac_info mac;
|
||||
struct e1000_fc_info fc;
|
||||
struct e1000_phy_info phy;
|
||||
struct e1000_nvm_info nvm;
|
||||
struct e1000_bus_info bus;
|
||||
struct e1000_mbx_info mbx;
|
||||
struct e1000_host_mng_dhcp_cookie mng_cookie;
|
||||
|
||||
union {
|
||||
struct e1000_dev_spec_82575 _82575;
|
||||
} dev_spec;
|
||||
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_device_id;
|
||||
u16 vendor_id;
|
||||
|
||||
u8 revision_id;
|
||||
};
|
||||
|
||||
struct net_device *igb_get_hw_dev(struct e1000_hw *hw);
|
||||
#define hw_dbg(format, arg...) \
|
||||
netdev_dbg(igb_get_hw_dev(hw), format, ##arg)
|
||||
|
||||
/* These functions must be implemented by drivers */
|
||||
s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
s32 igb_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
|
||||
void igb_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
void igb_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
|
||||
#endif /* _E1000_IGB_HW_H_ */
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_PHY_H_
|
||||
#define _E1000_PHY_H_
|
||||
|
||||
enum e1000_ms_type {
|
||||
e1000_ms_hw_default = 0,
|
||||
e1000_ms_force_master,
|
||||
e1000_ms_force_slave,
|
||||
e1000_ms_auto
|
||||
};
|
||||
|
||||
enum e1000_smart_speed {
|
||||
e1000_smart_speed_default = 0,
|
||||
e1000_smart_speed_on,
|
||||
e1000_smart_speed_off
|
||||
};
|
||||
|
||||
s32 igb_check_downshift(struct e1000_hw *hw);
|
||||
s32 igb_check_reset_block(struct e1000_hw *hw);
|
||||
s32 igb_copper_link_setup_igp(struct e1000_hw *hw);
|
||||
s32 igb_copper_link_setup_m88(struct e1000_hw *hw);
|
||||
s32 igb_copper_link_setup_m88_gen2(struct e1000_hw *hw);
|
||||
s32 igb_phy_force_speed_duplex_igp(struct e1000_hw *hw);
|
||||
s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_m88(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_igp_2(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_id(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_info_igp(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_info_m88(struct e1000_hw *hw);
|
||||
s32 igb_phy_sw_reset(struct e1000_hw *hw);
|
||||
s32 igb_phy_hw_reset(struct e1000_hw *hw);
|
||||
s32 igb_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_set_d3_lplu_state(struct e1000_hw *hw, bool active);
|
||||
s32 igb_setup_copper_link(struct e1000_hw *hw);
|
||||
s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations,
|
||||
u32 usec_interval, bool *success);
|
||||
void igb_power_up_phy_copper(struct e1000_hw *hw);
|
||||
void igb_power_down_phy_copper(struct e1000_hw *hw);
|
||||
s32 igb_phy_init_script_igp3(struct e1000_hw *hw);
|
||||
s32 igb_initialize_M88E1512_phy(struct e1000_hw *hw);
|
||||
s32 igb_initialize_M88E1543_phy(struct e1000_hw *hw);
|
||||
s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data);
|
||||
s32 igb_copper_link_setup_82580(struct e1000_hw *hw);
|
||||
s32 igb_get_phy_info_82580(struct e1000_hw *hw);
|
||||
s32 igb_phy_force_speed_duplex_82580(struct e1000_hw *hw);
|
||||
s32 igb_get_cable_length_82580(struct e1000_hw *hw);
|
||||
s32 igb_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data);
|
||||
s32 igb_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data);
|
||||
s32 igb_check_polarity_m88(struct e1000_hw *hw);
|
||||
|
||||
/* IGP01E1000 Specific Registers */
|
||||
#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */
|
||||
#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */
|
||||
#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */
|
||||
#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */
|
||||
#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */
|
||||
#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */
|
||||
#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4
|
||||
#define IGP01E1000_PHY_POLARITY_MASK 0x0078
|
||||
#define IGP01E1000_PSCR_AUTO_MDIX 0x1000
|
||||
#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */
|
||||
#define IGP01E1000_PSCFR_SMART_SPEED 0x0080
|
||||
|
||||
#define I82580_ADDR_REG 16
|
||||
#define I82580_CFG_REG 22
|
||||
#define I82580_CFG_ASSERT_CRS_ON_TX BIT(15)
|
||||
#define I82580_CFG_ENABLE_DOWNSHIFT (3u << 10) /* auto downshift 100/10 */
|
||||
#define I82580_CTRL_REG 23
|
||||
#define I82580_CTRL_DOWNSHIFT_MASK (7u << 10)
|
||||
|
||||
/* 82580 specific PHY registers */
|
||||
#define I82580_PHY_CTRL_2 18
|
||||
#define I82580_PHY_LBK_CTRL 19
|
||||
#define I82580_PHY_STATUS_2 26
|
||||
#define I82580_PHY_DIAG_STATUS 31
|
||||
|
||||
/* I82580 PHY Status 2 */
|
||||
#define I82580_PHY_STATUS2_REV_POLARITY 0x0400
|
||||
#define I82580_PHY_STATUS2_MDIX 0x0800
|
||||
#define I82580_PHY_STATUS2_SPEED_MASK 0x0300
|
||||
#define I82580_PHY_STATUS2_SPEED_1000MBPS 0x0200
|
||||
#define I82580_PHY_STATUS2_SPEED_100MBPS 0x0100
|
||||
|
||||
/* I82580 PHY Control 2 */
|
||||
#define I82580_PHY_CTRL2_MANUAL_MDIX 0x0200
|
||||
#define I82580_PHY_CTRL2_AUTO_MDI_MDIX 0x0400
|
||||
#define I82580_PHY_CTRL2_MDIX_CFG_MASK 0x0600
|
||||
|
||||
/* I82580 PHY Diagnostics Status */
|
||||
#define I82580_DSTATUS_CABLE_LENGTH 0x03FC
|
||||
#define I82580_DSTATUS_CABLE_LENGTH_SHIFT 2
|
||||
|
||||
/* 82580 PHY Power Management */
|
||||
#define E1000_82580_PHY_POWER_MGMT 0xE14
|
||||
#define E1000_82580_PM_SPD 0x0001 /* Smart Power Down */
|
||||
#define E1000_82580_PM_D0_LPLU 0x0002 /* For D0a states */
|
||||
#define E1000_82580_PM_D3_LPLU 0x0004 /* For all other states */
|
||||
#define E1000_82580_PM_GO_LINKD 0x0020 /* Go Link Disconnect */
|
||||
|
||||
/* Enable flexible speed on link-up */
|
||||
#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */
|
||||
#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */
|
||||
#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000
|
||||
#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002
|
||||
#define IGP01E1000_PSSR_MDIX 0x0800
|
||||
#define IGP01E1000_PSSR_SPEED_MASK 0xC000
|
||||
#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000
|
||||
#define IGP02E1000_PHY_CHANNEL_NUM 4
|
||||
#define IGP02E1000_PHY_AGC_A 0x11B1
|
||||
#define IGP02E1000_PHY_AGC_B 0x12B1
|
||||
#define IGP02E1000_PHY_AGC_C 0x14B1
|
||||
#define IGP02E1000_PHY_AGC_D 0x18B1
|
||||
#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course - 15:13, Fine - 12:9 */
|
||||
#define IGP02E1000_AGC_LENGTH_MASK 0x7F
|
||||
#define IGP02E1000_AGC_RANGE 15
|
||||
|
||||
#define E1000_CABLE_LENGTH_UNDEFINED 0xFF
|
||||
|
||||
/* SFP modules ID memory locations */
|
||||
#define E1000_SFF_IDENTIFIER_OFFSET 0x00
|
||||
#define E1000_SFF_IDENTIFIER_SFF 0x02
|
||||
#define E1000_SFF_IDENTIFIER_SFP 0x03
|
||||
|
||||
#define E1000_SFF_ETH_FLAGS_OFFSET 0x06
|
||||
/* Flags for SFP modules compatible with ETH up to 1Gb */
|
||||
struct e1000_sfp_flags {
|
||||
u8 e1000_base_sx:1;
|
||||
u8 e1000_base_lx:1;
|
||||
u8 e1000_base_cx:1;
|
||||
u8 e1000_base_t:1;
|
||||
u8 e100_base_lx:1;
|
||||
u8 e100_base_fx:1;
|
||||
u8 e10_base_bx10:1;
|
||||
u8 e10_base_px:1;
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,265 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_82575_H_
|
||||
#define _E1000_82575_H_
|
||||
|
||||
void igb_shutdown_serdes_link_82575(struct e1000_hw *hw);
|
||||
void igb_power_up_serdes_link_82575(struct e1000_hw *hw);
|
||||
void igb_power_down_phy_copper_82575(struct e1000_hw *hw);
|
||||
void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
|
||||
s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr,
|
||||
u8 *data);
|
||||
s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr,
|
||||
u8 data);
|
||||
|
||||
#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
|
||||
(ID_LED_DEF1_DEF2 << 8) | \
|
||||
(ID_LED_DEF1_DEF2 << 4) | \
|
||||
(ID_LED_OFF1_ON2))
|
||||
|
||||
#define E1000_RAR_ENTRIES_82575 16
|
||||
#define E1000_RAR_ENTRIES_82576 24
|
||||
#define E1000_RAR_ENTRIES_82580 24
|
||||
#define E1000_RAR_ENTRIES_I350 32
|
||||
|
||||
#define E1000_SW_SYNCH_MB 0x00000100
|
||||
#define E1000_STAT_DEV_RST_SET 0x00100000
|
||||
#define E1000_CTRL_DEV_RST 0x20000000
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
|
||||
#define E1000_SRRCTL_DROP_EN 0x80000000
|
||||
#define E1000_SRRCTL_TIMESTAMP 0x40000000
|
||||
|
||||
|
||||
#define E1000_MRQC_ENABLE_RSS_MQ 0x00000002
|
||||
#define E1000_MRQC_ENABLE_VMDQ 0x00000003
|
||||
#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
|
||||
#define E1000_MRQC_ENABLE_VMDQ_RSS_MQ 0x00000005
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
|
||||
|
||||
#define E1000_EICR_TX_QUEUE ( \
|
||||
E1000_EICR_TX_QUEUE0 | \
|
||||
E1000_EICR_TX_QUEUE1 | \
|
||||
E1000_EICR_TX_QUEUE2 | \
|
||||
E1000_EICR_TX_QUEUE3)
|
||||
|
||||
#define E1000_EICR_RX_QUEUE ( \
|
||||
E1000_EICR_RX_QUEUE0 | \
|
||||
E1000_EICR_RX_QUEUE1 | \
|
||||
E1000_EICR_RX_QUEUE2 | \
|
||||
E1000_EICR_RX_QUEUE3)
|
||||
|
||||
/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
|
||||
#define E1000_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
|
||||
#define E1000_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union e1000_adv_rx_desc {
|
||||
struct {
|
||||
__le64 pkt_addr; /* Packet buffer address */
|
||||
__le64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
struct {
|
||||
__le16 pkt_info; /* RSS type, Packet type */
|
||||
__le16 hdr_info; /* Split Head, buf len */
|
||||
} lo_dword;
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length; /* Packet length */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
|
||||
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
|
||||
#define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */
|
||||
#define E1000_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union e1000_adv_tx_desc {
|
||||
struct {
|
||||
__le64 buffer_addr; /* Address of descriptor's data buf */
|
||||
__le32 cmd_type_len;
|
||||
__le32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
__le64 rsvd; /* Reserved */
|
||||
__le32 nxtseq_seed;
|
||||
__le32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
|
||||
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
/* Context descriptors */
|
||||
struct e1000_adv_tx_context_desc {
|
||||
__le32 vlan_macip_lens;
|
||||
__le32 seqnum_seed;
|
||||
__le32 type_tucmd_mlhl;
|
||||
__le32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
|
||||
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
|
||||
/* IPSec Encrypt Enable for ESP */
|
||||
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
/* Adv ctxt IPSec SA IDX mask */
|
||||
/* Adv ctxt IPSec ESP len mask */
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
|
||||
/* Tx Queue Arbitration Priority 0=low, 1=high */
|
||||
|
||||
/* Additional Receive Descriptor Control definitions */
|
||||
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
|
||||
|
||||
/* Direct Cache Access (DCA) definitions */
|
||||
#define E1000_DCA_CTRL_DCA_MODE_DISABLE 0x01 /* DCA Disable */
|
||||
#define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */
|
||||
|
||||
#define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */
|
||||
#define E1000_DCA_RXCTRL_DESC_DCA_EN BIT(5) /* DCA Rx Desc enable */
|
||||
#define E1000_DCA_RXCTRL_HEAD_DCA_EN BIT(6) /* DCA Rx Desc header enable */
|
||||
#define E1000_DCA_RXCTRL_DATA_DCA_EN BIT(7) /* DCA Rx Desc payload enable */
|
||||
#define E1000_DCA_RXCTRL_DESC_RRO_EN BIT(9) /* DCA Rx rd Desc Relax Order */
|
||||
|
||||
#define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
|
||||
#define E1000_DCA_TXCTRL_DESC_DCA_EN BIT(5) /* DCA Tx Desc enable */
|
||||
#define E1000_DCA_TXCTRL_DESC_RRO_EN BIT(9) /* Tx rd Desc Relax Order */
|
||||
#define E1000_DCA_TXCTRL_TX_WB_RO_EN BIT(11) /* Tx Desc writeback RO bit */
|
||||
#define E1000_DCA_TXCTRL_DATA_RRO_EN BIT(13) /* Tx rd data Relax Order */
|
||||
|
||||
/* Additional DCA related definitions, note change in position of CPUID */
|
||||
#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
|
||||
#define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */
|
||||
#define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */
|
||||
#define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */
|
||||
|
||||
/* ETQF register bit definitions */
|
||||
#define E1000_ETQF_FILTER_ENABLE BIT(26)
|
||||
#define E1000_ETQF_1588 BIT(30)
|
||||
#define E1000_ETQF_IMM_INT BIT(29)
|
||||
#define E1000_ETQF_QUEUE_ENABLE BIT(31)
|
||||
#define E1000_ETQF_QUEUE_SHIFT 16
|
||||
#define E1000_ETQF_QUEUE_MASK 0x00070000
|
||||
#define E1000_ETQF_ETYPE_MASK 0x0000FFFF
|
||||
|
||||
/* FTQF register bit definitions */
|
||||
#define E1000_FTQF_VF_BP 0x00008000
|
||||
#define E1000_FTQF_1588_TIME_STAMP 0x08000000
|
||||
#define E1000_FTQF_MASK 0xF0000000
|
||||
#define E1000_FTQF_MASK_PROTO_BP 0x10000000
|
||||
#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000
|
||||
|
||||
#define E1000_NVM_APME_82575 0x0400
|
||||
#define MAX_NUM_VFS 8
|
||||
|
||||
#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */
|
||||
#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */
|
||||
#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */
|
||||
#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
|
||||
#define E1000_DTXSWC_VMDQ_LOOPBACK_EN BIT(31) /* global VF LB enable */
|
||||
|
||||
/* Easy defines for setting default pool, would normally be left a zero */
|
||||
#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7
|
||||
#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT)
|
||||
|
||||
/* Other useful VMD_CTL register defines */
|
||||
#define E1000_VT_CTL_IGNORE_MAC BIT(28)
|
||||
#define E1000_VT_CTL_DISABLE_DEF_POOL BIT(29)
|
||||
#define E1000_VT_CTL_VM_REPL_EN BIT(30)
|
||||
|
||||
/* Per VM Offload register setup */
|
||||
#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */
|
||||
#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */
|
||||
#define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */
|
||||
#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */
|
||||
#define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */
|
||||
#define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */
|
||||
#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */
|
||||
#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */
|
||||
#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
|
||||
#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */
|
||||
|
||||
#define E1000_DVMOLR_HIDEVLAN 0x20000000 /* Hide vlan enable */
|
||||
#define E1000_DVMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
|
||||
#define E1000_DVMOLR_STRCRC 0x80000000 /* CRC stripping enable */
|
||||
|
||||
#define E1000_VLVF_ARRAY_SIZE 32
|
||||
#define E1000_VLVF_VLANID_MASK 0x00000FFF
|
||||
#define E1000_VLVF_POOLSEL_SHIFT 12
|
||||
#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT)
|
||||
#define E1000_VLVF_LVLAN 0x00100000
|
||||
#define E1000_VLVF_VLANID_ENABLE 0x80000000
|
||||
|
||||
#define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
|
||||
#define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */
|
||||
|
||||
#define E1000_IOVCTL 0x05BBC
|
||||
#define E1000_IOVCTL_REUSE_VFQ 0x00000001
|
||||
|
||||
#define E1000_RPLOLR_STRVLAN 0x40000000
|
||||
#define E1000_RPLOLR_STRCRC 0x80000000
|
||||
|
||||
#define E1000_DTXCTL_8023LL 0x0004
|
||||
#define E1000_DTXCTL_VLAN_ADDED 0x0008
|
||||
#define E1000_DTXCTL_OOS_ENABLE 0x0010
|
||||
#define E1000_DTXCTL_MDP_EN 0x0020
|
||||
#define E1000_DTXCTL_SPOOF_INT 0x0040
|
||||
|
||||
#define E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT BIT(14)
|
||||
|
||||
#define ALL_QUEUES 0xFFFF
|
||||
|
||||
/* RX packet buffer size defines */
|
||||
#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F
|
||||
void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *, bool, int);
|
||||
void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
|
||||
void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
|
||||
u16 igb_rxpbs_adjust_82580(u32 data);
|
||||
s32 igb_read_emi_reg(struct e1000_hw *, u16 addr, u16 *data);
|
||||
s32 igb_set_eee_i350(struct e1000_hw *, bool adv1G, bool adv100M);
|
||||
s32 igb_set_eee_i354(struct e1000_hw *, bool adv1G, bool adv100M);
|
||||
s32 igb_get_eee_status_i354(struct e1000_hw *hw, bool *status);
|
||||
|
||||
#define E1000_I2C_THERMAL_SENSOR_ADDR 0xF8
|
||||
#define E1000_EMC_INTERNAL_DATA 0x00
|
||||
#define E1000_EMC_INTERNAL_THERM_LIMIT 0x20
|
||||
#define E1000_EMC_DIODE1_DATA 0x01
|
||||
#define E1000_EMC_DIODE1_THERM_LIMIT 0x19
|
||||
#define E1000_EMC_DIODE2_DATA 0x23
|
||||
#define E1000_EMC_DIODE2_THERM_LIMIT 0x1A
|
||||
#define E1000_EMC_DIODE3_DATA 0x2A
|
||||
#define E1000_EMC_DIODE3_THERM_LIMIT 0x30
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,265 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright(c) 2007 - 2018 Intel Corporation. */
|
||||
|
||||
#ifndef _E1000_82575_H_
|
||||
#define _E1000_82575_H_
|
||||
|
||||
void igb_shutdown_serdes_link_82575(struct e1000_hw *hw);
|
||||
void igb_power_up_serdes_link_82575(struct e1000_hw *hw);
|
||||
void igb_power_down_phy_copper_82575(struct e1000_hw *hw);
|
||||
void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
|
||||
s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr,
|
||||
u8 *data);
|
||||
s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, u8 dev_addr,
|
||||
u8 data);
|
||||
|
||||
#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
|
||||
(ID_LED_DEF1_DEF2 << 8) | \
|
||||
(ID_LED_DEF1_DEF2 << 4) | \
|
||||
(ID_LED_OFF1_ON2))
|
||||
|
||||
#define E1000_RAR_ENTRIES_82575 16
|
||||
#define E1000_RAR_ENTRIES_82576 24
|
||||
#define E1000_RAR_ENTRIES_82580 24
|
||||
#define E1000_RAR_ENTRIES_I350 32
|
||||
|
||||
#define E1000_SW_SYNCH_MB 0x00000100
|
||||
#define E1000_STAT_DEV_RST_SET 0x00100000
|
||||
#define E1000_CTRL_DEV_RST 0x20000000
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define E1000_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define E1000_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
#define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS 0x0A000000
|
||||
#define E1000_SRRCTL_DROP_EN 0x80000000
|
||||
#define E1000_SRRCTL_TIMESTAMP 0x40000000
|
||||
|
||||
|
||||
#define E1000_MRQC_ENABLE_RSS_MQ 0x00000002
|
||||
#define E1000_MRQC_ENABLE_VMDQ 0x00000003
|
||||
#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
|
||||
#define E1000_MRQC_ENABLE_VMDQ_RSS_MQ 0x00000005
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
|
||||
#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
|
||||
|
||||
#define E1000_EICR_TX_QUEUE ( \
|
||||
E1000_EICR_TX_QUEUE0 | \
|
||||
E1000_EICR_TX_QUEUE1 | \
|
||||
E1000_EICR_TX_QUEUE2 | \
|
||||
E1000_EICR_TX_QUEUE3)
|
||||
|
||||
#define E1000_EICR_RX_QUEUE ( \
|
||||
E1000_EICR_RX_QUEUE0 | \
|
||||
E1000_EICR_RX_QUEUE1 | \
|
||||
E1000_EICR_RX_QUEUE2 | \
|
||||
E1000_EICR_RX_QUEUE3)
|
||||
|
||||
/* Immediate Interrupt Rx (A.K.A. Low Latency Interrupt) */
|
||||
#define E1000_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
|
||||
#define E1000_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union e1000_adv_rx_desc {
|
||||
struct {
|
||||
__le64 pkt_addr; /* Packet buffer address */
|
||||
__le64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
struct {
|
||||
__le16 pkt_info; /* RSS type, Packet type */
|
||||
__le16 hdr_info; /* Split Head, buf len */
|
||||
} lo_dword;
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length; /* Packet length */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
#define E1000_RXDADV_HDRBUFLEN_MASK 0x7FE0
|
||||
#define E1000_RXDADV_HDRBUFLEN_SHIFT 5
|
||||
#define E1000_RXDADV_STAT_TS 0x10000 /* Pkt was time stamped */
|
||||
#define E1000_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union e1000_adv_tx_desc {
|
||||
struct {
|
||||
__le64 buffer_addr; /* Address of descriptor's data buf */
|
||||
__le32 cmd_type_len;
|
||||
__le32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
__le64 rsvd; /* Reserved */
|
||||
__le32 nxtseq_seed;
|
||||
__le32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define E1000_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
|
||||
#define E1000_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define E1000_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define E1000_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define E1000_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define E1000_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define E1000_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define E1000_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define E1000_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define E1000_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
/* Context descriptors */
|
||||
struct e1000_adv_tx_context_desc {
|
||||
__le32 vlan_macip_lens;
|
||||
__le32 seqnum_seed;
|
||||
__le32 type_tucmd_mlhl;
|
||||
__le32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
|
||||
#define E1000_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type: 1=IPv4 */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
|
||||
#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
|
||||
/* IPSec Encrypt Enable for ESP */
|
||||
#define E1000_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define E1000_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
/* Adv ctxt IPSec SA IDX mask */
|
||||
/* Adv ctxt IPSec ESP len mask */
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define E1000_TXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Tx Queue */
|
||||
/* Tx Queue Arbitration Priority 0=low, 1=high */
|
||||
|
||||
/* Additional Receive Descriptor Control definitions */
|
||||
#define E1000_RXDCTL_QUEUE_ENABLE 0x02000000 /* Enable specific Rx Queue */
|
||||
|
||||
/* Direct Cache Access (DCA) definitions */
|
||||
#define E1000_DCA_CTRL_DCA_MODE_DISABLE 0x01 /* DCA Disable */
|
||||
#define E1000_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */
|
||||
|
||||
#define E1000_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */
|
||||
#define E1000_DCA_RXCTRL_DESC_DCA_EN BIT(5) /* DCA Rx Desc enable */
|
||||
#define E1000_DCA_RXCTRL_HEAD_DCA_EN BIT(6) /* DCA Rx Desc header enable */
|
||||
#define E1000_DCA_RXCTRL_DATA_DCA_EN BIT(7) /* DCA Rx Desc payload enable */
|
||||
#define E1000_DCA_RXCTRL_DESC_RRO_EN BIT(9) /* DCA Rx rd Desc Relax Order */
|
||||
|
||||
#define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
|
||||
#define E1000_DCA_TXCTRL_DESC_DCA_EN BIT(5) /* DCA Tx Desc enable */
|
||||
#define E1000_DCA_TXCTRL_DESC_RRO_EN BIT(9) /* Tx rd Desc Relax Order */
|
||||
#define E1000_DCA_TXCTRL_TX_WB_RO_EN BIT(11) /* Tx Desc writeback RO bit */
|
||||
#define E1000_DCA_TXCTRL_DATA_RRO_EN BIT(13) /* Tx rd data Relax Order */
|
||||
|
||||
/* Additional DCA related definitions, note change in position of CPUID */
|
||||
#define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
|
||||
#define E1000_DCA_RXCTRL_CPUID_MASK_82576 0xFF000000 /* Rx CPUID Mask */
|
||||
#define E1000_DCA_TXCTRL_CPUID_SHIFT 24 /* Tx CPUID now in the last byte */
|
||||
#define E1000_DCA_RXCTRL_CPUID_SHIFT 24 /* Rx CPUID now in the last byte */
|
||||
|
||||
/* ETQF register bit definitions */
|
||||
#define E1000_ETQF_FILTER_ENABLE BIT(26)
|
||||
#define E1000_ETQF_1588 BIT(30)
|
||||
#define E1000_ETQF_IMM_INT BIT(29)
|
||||
#define E1000_ETQF_QUEUE_ENABLE BIT(31)
|
||||
#define E1000_ETQF_QUEUE_SHIFT 16
|
||||
#define E1000_ETQF_QUEUE_MASK 0x00070000
|
||||
#define E1000_ETQF_ETYPE_MASK 0x0000FFFF
|
||||
|
||||
/* FTQF register bit definitions */
|
||||
#define E1000_FTQF_VF_BP 0x00008000
|
||||
#define E1000_FTQF_1588_TIME_STAMP 0x08000000
|
||||
#define E1000_FTQF_MASK 0xF0000000
|
||||
#define E1000_FTQF_MASK_PROTO_BP 0x10000000
|
||||
#define E1000_FTQF_MASK_SOURCE_PORT_BP 0x80000000
|
||||
|
||||
#define E1000_NVM_APME_82575 0x0400
|
||||
#define MAX_NUM_VFS 8
|
||||
|
||||
#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */
|
||||
#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */
|
||||
#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */
|
||||
#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
|
||||
#define E1000_DTXSWC_VMDQ_LOOPBACK_EN BIT(31) /* global VF LB enable */
|
||||
|
||||
/* Easy defines for setting default pool, would normally be left a zero */
|
||||
#define E1000_VT_CTL_DEFAULT_POOL_SHIFT 7
|
||||
#define E1000_VT_CTL_DEFAULT_POOL_MASK (0x7 << E1000_VT_CTL_DEFAULT_POOL_SHIFT)
|
||||
|
||||
/* Other useful VMD_CTL register defines */
|
||||
#define E1000_VT_CTL_IGNORE_MAC BIT(28)
|
||||
#define E1000_VT_CTL_DISABLE_DEF_POOL BIT(29)
|
||||
#define E1000_VT_CTL_VM_REPL_EN BIT(30)
|
||||
|
||||
/* Per VM Offload register setup */
|
||||
#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */
|
||||
#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */
|
||||
#define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */
|
||||
#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */
|
||||
#define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */
|
||||
#define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */
|
||||
#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */
|
||||
#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */
|
||||
#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
|
||||
#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */
|
||||
|
||||
#define E1000_DVMOLR_HIDEVLAN 0x20000000 /* Hide vlan enable */
|
||||
#define E1000_DVMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
|
||||
#define E1000_DVMOLR_STRCRC 0x80000000 /* CRC stripping enable */
|
||||
|
||||
#define E1000_VLVF_ARRAY_SIZE 32
|
||||
#define E1000_VLVF_VLANID_MASK 0x00000FFF
|
||||
#define E1000_VLVF_POOLSEL_SHIFT 12
|
||||
#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT)
|
||||
#define E1000_VLVF_LVLAN 0x00100000
|
||||
#define E1000_VLVF_VLANID_ENABLE 0x80000000
|
||||
|
||||
#define E1000_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
|
||||
#define E1000_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */
|
||||
|
||||
#define E1000_IOVCTL 0x05BBC
|
||||
#define E1000_IOVCTL_REUSE_VFQ 0x00000001
|
||||
|
||||
#define E1000_RPLOLR_STRVLAN 0x40000000
|
||||
#define E1000_RPLOLR_STRCRC 0x80000000
|
||||
|
||||
#define E1000_DTXCTL_8023LL 0x0004
|
||||
#define E1000_DTXCTL_VLAN_ADDED 0x0008
|
||||
#define E1000_DTXCTL_OOS_ENABLE 0x0010
|
||||
#define E1000_DTXCTL_MDP_EN 0x0020
|
||||
#define E1000_DTXCTL_SPOOF_INT 0x0040
|
||||
|
||||
#define E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT BIT(14)
|
||||
|
||||
#define ALL_QUEUES 0xFFFF
|
||||
|
||||
/* RX packet buffer size defines */
|
||||
#define E1000_RXPBS_SIZE_MASK_82576 0x0000007F
|
||||
void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *, bool, int);
|
||||
void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
|
||||
void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
|
||||
u16 igb_rxpbs_adjust_82580(u32 data);
|
||||
s32 igb_read_emi_reg(struct e1000_hw *, u16 addr, u16 *data);
|
||||
s32 igb_set_eee_i350(struct e1000_hw *, bool adv1G, bool adv100M);
|
||||
s32 igb_set_eee_i354(struct e1000_hw *, bool adv1G, bool adv100M);
|
||||
s32 igb_get_eee_status_i354(struct e1000_hw *hw, bool *status);
|
||||
|
||||
#define E1000_I2C_THERMAL_SENSOR_ADDR 0xF8
|
||||
#define E1000_EMC_INTERNAL_DATA 0x00
|
||||
#define E1000_EMC_INTERNAL_THERM_LIMIT 0x20
|
||||
#define E1000_EMC_DIODE1_DATA 0x01
|
||||
#define E1000_EMC_DIODE1_THERM_LIMIT 0x19
|
||||
#define E1000_EMC_DIODE2_DATA 0x23
|
||||
#define E1000_EMC_DIODE2_THERM_LIMIT 0x1A
|
||||
#define E1000_EMC_DIODE3_DATA 0x2A
|
||||
#define E1000_EMC_DIODE3_THERM_LIMIT 0x30
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue