Merge remote-tracking branch 'origin/devel-1.6' into 84-api-call-for-eoe-set-ip-command
This commit is contained in:
commit
40212a30a6
|
|
@ -29,6 +29,14 @@ xenomai2:
|
|||
- ./configure --disable-8139too --with-linux-dir=/usr/src/linux-obj/x86_64/0318xenomai2 --enable-rtdm --with-xenomai-dir=/usr
|
||||
- make -j8 all modules
|
||||
|
||||
kernel 3.4:
|
||||
stage: build
|
||||
image: registry.gitlab.com/etherlab.org/build-container-factory/ethercat-kernels:k3.4-rt145
|
||||
script:
|
||||
- ./bootstrap
|
||||
- ./configure --enable-8139too --enable-e100 --enable-e1000 --enable-e1000e --enable-r8169 --with-linux-dir=/usr/src/linux-obj/x86_64/0304rt
|
||||
- make -j8 all modules
|
||||
|
||||
xenomai3:
|
||||
stage: build
|
||||
image: registry.gitlab.com/etherlab.org/build-container-factory/ethercat-kernels:xenomai3
|
||||
|
|
|
|||
1
NEWS
1
NEWS
|
|
@ -10,6 +10,7 @@ Changes in 1.6.0:
|
|||
* Dropped support for kernels < 3.0.
|
||||
* Allow to query the scanning progress via API.
|
||||
* Added EoE set IP command via command-line-tool.
|
||||
* Changed the default AL state change timeout from 5 to 10 s.
|
||||
|
||||
Changes since 1.5.2:
|
||||
|
||||
|
|
|
|||
113
configure.ac
113
configure.ac
|
|
@ -66,7 +66,7 @@ AC_ARG_ENABLE([kernel],
|
|||
;;
|
||||
no) enablekernel=0
|
||||
;;
|
||||
*) AC_MSG_ERROR([Invalid value for --enable-generic])
|
||||
*) AC_MSG_ERROR([Invalid value for --enable-kernel])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
|
|
@ -163,6 +163,37 @@ AC_SUBST(INSTALL_MOD_DIR,[$moddir])
|
|||
AC_MSG_CHECKING([for Linux modules installation directory])
|
||||
AC_MSG_RESULT([$INSTALL_MOD_DIR])
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Native driver resource (de)allocation verifying
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
AC_MSG_CHECKING([whether to verify native driver resources])
|
||||
|
||||
AC_ARG_ENABLE([driver-resource-verifying],
|
||||
AS_HELP_STRING([--enable-driver-resource-verifying],
|
||||
[Verify resource (de-)allocation in native drivers]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) enableverifying=1
|
||||
;;
|
||||
no) enableverifying=0
|
||||
;;
|
||||
*) AC_MSG_ERROR([Invalid value for --enable-driver-resource-verifying])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[enableverifying=0]
|
||||
)
|
||||
|
||||
if test "x$enableverifying" = "x1"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(ENABLE_DRIVER_RESOURCE_VERIFYING, test "x$enableverifying" = "x1")
|
||||
AC_SUBST(ENABLE_DRIVER_RESOURCE_VERIFYING,[$enableverifying])
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Generic Ethernet driver
|
||||
#-----------------------------------------------------------------------------
|
||||
|
|
@ -633,6 +664,80 @@ fi
|
|||
|
||||
AC_SUBST(KERNEL_R8169,[$kernel_r8169])
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# stmmac-pci and dwmac-intel driver
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
enablestmmac=0
|
||||
|
||||
AC_ARG_ENABLE([stmmac-pci],
|
||||
AS_HELP_STRING([--enable-stmmac-pci],
|
||||
[Enable stmmac driver]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) enablestmmacpci=1
|
||||
enablestmmac=1
|
||||
;;
|
||||
no) enablestmmacpci=0
|
||||
;;
|
||||
*) AC_MSG_ERROR([Invalid value for --enable-stmmac])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[enablestmmacpci=0] # disabled by default
|
||||
)
|
||||
|
||||
AM_CONDITIONAL(ENABLE_STMMACPCI, test "x$enablestmmacpci" = "x1")
|
||||
AC_SUBST(ENABLE_STMMACPCI,[$enablestmmacpci])
|
||||
|
||||
AC_ARG_ENABLE([dwmac-intel],
|
||||
AS_HELP_STRING([--enable-dwmac-intel],
|
||||
[Enable stmmac driver]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) enabledwmacintel=1
|
||||
enablestmmac=1
|
||||
;;
|
||||
no) enabledwmacintel=0
|
||||
;;
|
||||
*) AC_MSG_ERROR([Invalid value for --enable-stmmac])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[enabledwmacintel=0] # disabled by default
|
||||
)
|
||||
|
||||
AM_CONDITIONAL(ENABLE_DWMACINTEL, test "x$enabledwmacintel" = "x1")
|
||||
AC_SUBST(ENABLE_DWMACINTEL,[$enabledwmacintel])
|
||||
|
||||
AM_CONDITIONAL(ENABLE_STMMAC, test "x$enablestmmac" = "x1")
|
||||
AC_SUBST(ENABLE_STMMAC, [$enablestmmac])
|
||||
|
||||
AC_ARG_WITH([stmmac-kernel],
|
||||
AC_HELP_STRING(
|
||||
[--with-stmmac-kernel=<X.Y.Z>],
|
||||
[stmmac kernel (only if differing)]
|
||||
),
|
||||
[
|
||||
kernelstmmac=[$withval]
|
||||
],
|
||||
[
|
||||
kernelstmmac=$linuxversion
|
||||
]
|
||||
)
|
||||
|
||||
if test "x${enablestmmac}" = "x1"; then
|
||||
AC_MSG_CHECKING([for kernel for stmmac driver])
|
||||
|
||||
if test ! -f "${srcdir}/devices/stmmac/stmmac-${kernelstmmac}-orig.h"; then
|
||||
AC_MSG_ERROR([kernel $kernelstmmac not available for stmmac driver!])
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([$kernelstmmac])
|
||||
fi
|
||||
|
||||
AC_SUBST(KERNEL_STMMAC,[$kernelstmmac])
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# CCAT driver
|
||||
#-----------------------------------------------------------------------------
|
||||
|
|
@ -688,7 +793,7 @@ AC_MSG_CHECKING([for RTAI path])
|
|||
if test -z "${rtaidir}"; then
|
||||
AC_MSG_RESULT([not specified.])
|
||||
else
|
||||
if test \! -r ${rtaidir}/include/rtai.h; then
|
||||
if test \! -x ${rtaidir}/bin/rtai-config; then
|
||||
AC_MSG_ERROR([no RTAI installation found in ${rtaidir}!])
|
||||
fi
|
||||
AC_MSG_RESULT([$rtaidir])
|
||||
|
|
@ -696,6 +801,7 @@ else
|
|||
rtai_lxrt_cflags=`$rtaidir/bin/rtai-config --lxrt-cflags`
|
||||
rtai_lxrt_ldflags=`$rtaidir/bin/rtai-config --lxrt-ldflags`
|
||||
rtai_module_dir=`$rtaidir/bin/rtai-config --module-dir`
|
||||
rtai_kernel_cflags=`$rtaidir/bin/rtai-config --kernel-cflags`
|
||||
fi
|
||||
|
||||
AC_SUBST(RTAI_DIR,[$rtaidir])
|
||||
|
|
@ -705,6 +811,7 @@ AC_SUBST(ENABLE_RTAI,[$rtai])
|
|||
AC_SUBST(RTAI_LXRT_CFLAGS,[$rtai_lxrt_cflags])
|
||||
AC_SUBST(RTAI_LXRT_LDFLAGS,[$rtai_lxrt_ldflags])
|
||||
AC_SUBST(RTAI_MODULE_DIR,[$rtai_module_dir])
|
||||
AC_SUBST(RTAI_KERNEL_CFLAGS,[$rtai_kernel_cflags])
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Xenomai path (optional)
|
||||
|
|
@ -1263,6 +1370,8 @@ AC_CONFIG_FILES([
|
|||
devices/igc/Makefile
|
||||
devices/r8169/Kbuild
|
||||
devices/r8169/Makefile
|
||||
devices/stmmac/Kbuild
|
||||
devices/stmmac/Makefile
|
||||
ethercat.spec
|
||||
examples/Kbuild
|
||||
examples/Makefile
|
||||
|
|
|
|||
|
|
@ -149,6 +149,17 @@
|
|||
#include "../globals.h"
|
||||
#include "ecdev.h"
|
||||
|
||||
#ifdef CONFIG_SUSE_KERNEL
|
||||
#include <linux/suse_version.h>
|
||||
#else
|
||||
# ifndef SUSE_VERSION
|
||||
# define SUSE_VERSION 0
|
||||
# endif
|
||||
# ifndef SUSE_PATCHLEVEL
|
||||
# define SUSE_PATCHLEVEL 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define RTL8139_DRIVER_NAME DRV_NAME \
|
||||
" EtherCAT-capable Fast Ethernet driver " \
|
||||
DRV_VERSION ", master " EC_MASTER_VERSION
|
||||
|
|
@ -662,7 +673,7 @@ struct rtl8139_private {
|
|||
ec_device_t *ecdev;
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
|
||||
MODULE_AUTHOR("Florian Pose <fp@igh.de>");
|
||||
MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(EC_MASTER_VERSION);
|
||||
|
|
@ -2383,8 +2394,11 @@ static int rtl8139_set_mac_address(struct net_device *dev, void *p)
|
|||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5
|
||||
eth_hw_addr_set(dev, addr->sa_data);
|
||||
#else
|
||||
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
|
||||
|
||||
#endif
|
||||
spin_lock_irq(&tp->lock);
|
||||
|
||||
RTL_W8_F(Cfg9346, Cfg9346_Unlock);
|
||||
|
|
|
|||
|
|
@ -662,7 +662,7 @@ struct rtl8139_private {
|
|||
ec_device_t *ecdev;
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Florian Pose <fp@igh-essen.com>");
|
||||
MODULE_AUTHOR("Florian Pose <fp@igh.de>");
|
||||
MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(EC_MASTER_VERSION);
|
||||
|
|
|
|||
|
|
@ -660,9 +660,18 @@ struct rtl8139_private {
|
|||
unsigned int regs_len;
|
||||
unsigned long fifo_copy_timeout;
|
||||
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct rtl8139_private *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Florian Pose <fp@igh.de>");
|
||||
MODULE_DESCRIPTION("RealTek RTL-8139 EtherCAT driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -1083,9 +1092,10 @@ static int rtl8139_init_one(struct pci_dev *pdev,
|
|||
/* dev is fully set up and ready to use now */
|
||||
|
||||
// offer device to EtherCAT master module
|
||||
tp->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
|
||||
tp->ecdev_ = ecdev_offer(dev, ec_poll, THIS_MODULE);
|
||||
tp->ecdev_initialized = true;
|
||||
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
pr_debug("about to register device named %s (%p)...\n",
|
||||
dev->name, dev);
|
||||
i = register_netdev (dev);
|
||||
|
|
@ -1158,10 +1168,10 @@ static int rtl8139_init_one(struct pci_dev *pdev,
|
|||
if (rtl_chip_info[tp->chipset].flags & HasHltClk)
|
||||
RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */
|
||||
|
||||
if (tp->ecdev) {
|
||||
i = ecdev_open(tp->ecdev);
|
||||
if (get_ecdev(tp)) {
|
||||
i = ecdev_open(get_ecdev(tp));
|
||||
if (i) {
|
||||
ecdev_withdraw(tp->ecdev);
|
||||
ecdev_withdraw(get_ecdev(tp));
|
||||
goto err_out;
|
||||
}
|
||||
}
|
||||
|
|
@ -1182,9 +1192,9 @@ static void rtl8139_remove_one(struct pci_dev *pdev)
|
|||
|
||||
assert (dev != NULL);
|
||||
|
||||
if (tp->ecdev) {
|
||||
ecdev_close(tp->ecdev);
|
||||
ecdev_withdraw(tp->ecdev);
|
||||
if (get_ecdev(tp)) {
|
||||
ecdev_close(get_ecdev(tp));
|
||||
ecdev_withdraw(get_ecdev(tp));
|
||||
}
|
||||
else {
|
||||
cancel_delayed_work_sync(&tp->thread);
|
||||
|
|
@ -1393,7 +1403,7 @@ static int rtl8139_open (struct net_device *dev)
|
|||
const int irq = tp->pci_dev->irq;
|
||||
int retval;
|
||||
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
retval = request_irq(irq, rtl8139_interrupt, IRQF_SHARED, dev->name, dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
|
@ -1404,7 +1414,7 @@ static int rtl8139_open (struct net_device *dev)
|
|||
tp->rx_ring = dma_alloc_coherent(&tp->pci_dev->dev, RX_BUF_TOT_LEN,
|
||||
&tp->rx_ring_dma, GFP_KERNEL);
|
||||
if (tp->tx_bufs == NULL || tp->rx_ring == NULL) {
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
free_irq(irq, dev);
|
||||
}
|
||||
|
||||
|
|
@ -1426,7 +1436,7 @@ static int rtl8139_open (struct net_device *dev)
|
|||
|
||||
rtl8139_init_ring (dev);
|
||||
rtl8139_hw_start (dev);
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
netif_start_queue (dev);
|
||||
}
|
||||
|
||||
|
|
@ -1437,7 +1447,7 @@ static int rtl8139_open (struct net_device *dev)
|
|||
irq, RTL_R8 (MediaStatus),
|
||||
tp->mii.full_duplex ? "full" : "half");
|
||||
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
rtl8139_start_thread(tp);
|
||||
}
|
||||
|
||||
|
|
@ -1449,10 +1459,10 @@ static void rtl_check_media (struct net_device *dev, unsigned int init_media)
|
|||
{
|
||||
struct rtl8139_private *tp = netdev_priv(dev);
|
||||
|
||||
if (tp->ecdev) {
|
||||
if (get_ecdev(tp)) {
|
||||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
u16 state = RTL_R16(BasicModeStatus) & BMSR_LSTATUS;
|
||||
ecdev_set_link(tp->ecdev, state ? 1 : 0);
|
||||
ecdev_set_link(get_ecdev(tp), state ? 1 : 0);
|
||||
}
|
||||
else {
|
||||
if (tp->phys[0] >= 0) {
|
||||
|
|
@ -1523,7 +1533,7 @@ static void rtl8139_hw_start (struct net_device *dev)
|
|||
if ((!(tmp & CmdRxEnb)) || (!(tmp & CmdTxEnb)))
|
||||
RTL_W8 (ChipCmd, CmdRxEnb | CmdTxEnb);
|
||||
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
/* Enable all known interrupts by setting the interrupt mask. */
|
||||
RTL_W16 (IntrMask, rtl8139_intr_mask);
|
||||
}
|
||||
|
|
@ -1770,7 +1780,7 @@ static void rtl8139_tx_timeout_task (struct work_struct *work)
|
|||
if (tmp8 & CmdTxEnb)
|
||||
RTL_W8 (ChipCmd, CmdRxEnb);
|
||||
|
||||
if (tp->ecdev) {
|
||||
if (get_ecdev(tp)) {
|
||||
rtl8139_tx_clear (tp);
|
||||
rtl8139_hw_start (dev);
|
||||
}
|
||||
|
|
@ -1798,7 +1808,7 @@ static void rtl8139_tx_timeout(struct net_device *dev, unsigned int txqueue)
|
|||
struct rtl8139_private *tp = netdev_priv(dev);
|
||||
|
||||
tp->watchdog_fired = 1;
|
||||
if (!tp->ecdev && !tp->have_thread) {
|
||||
if (!get_ecdev(tp) && !tp->have_thread) {
|
||||
INIT_DELAYED_WORK(&tp->thread, rtl8139_thread);
|
||||
schedule_delayed_work(&tp->thread, next_tick);
|
||||
}
|
||||
|
|
@ -1821,18 +1831,18 @@ static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb,
|
|||
if (len < ETH_ZLEN)
|
||||
memset(tp->tx_buf[entry], 0, ETH_ZLEN);
|
||||
skb_copy_and_csum_dev(skb, tp->tx_buf[entry]);
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
} else {
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
dev->stats.tx_dropped++;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
spin_lock_irqsave(&tp->lock, flags);
|
||||
}
|
||||
/*
|
||||
|
|
@ -1846,7 +1856,7 @@ static netdev_tx_t rtl8139_start_xmit (struct sk_buff *skb,
|
|||
|
||||
tp->cur_tx++;
|
||||
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
|
||||
netif_stop_queue (dev);
|
||||
spin_unlock_irqrestore(&tp->lock, flags);
|
||||
|
|
@ -1925,7 +1935,7 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
|
|||
if (tp->dirty_tx != dirty_tx) {
|
||||
tp->dirty_tx = dirty_tx;
|
||||
mb();
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
netif_wake_queue (dev);
|
||||
}
|
||||
}
|
||||
|
|
@ -2061,7 +2071,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
|
|||
RTL_R16 (RxBufAddr),
|
||||
RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd));
|
||||
|
||||
while ((tp->ecdev || netif_running(dev))
|
||||
while ((get_ecdev(tp) || netif_running(dev))
|
||||
&& received < budget
|
||||
&& (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
|
||||
u32 ring_offset = cur_rx % RX_BUF_LEN;
|
||||
|
|
@ -2079,7 +2089,7 @@ static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
|
|||
else
|
||||
pkt_size = rx_size;
|
||||
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
if (netif_msg_rx_status(tp))
|
||||
pr_debug("%s: rtl8139_rx() status %4.4x, size %4.4x,"
|
||||
" cur %4.4x.\n", dev->name, rx_status,
|
||||
|
|
@ -2151,8 +2161,8 @@ no_early_rx:
|
|||
}
|
||||
|
||||
keep_pkt:
|
||||
if (tp->ecdev) {
|
||||
ecdev_receive(tp->ecdev, &rx_ring[ring_offset + 4], pkt_size);
|
||||
if (get_ecdev(tp)) {
|
||||
ecdev_receive(get_ecdev(tp), &rx_ring[ring_offset + 4], pkt_size);
|
||||
}
|
||||
else {
|
||||
/* Malloc up new buffer, compatible with net-2e. */
|
||||
|
|
@ -2290,7 +2300,7 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
|
|||
int link_changed = 0; /* avoid bogus "uninit" warning */
|
||||
int handled = 0;
|
||||
|
||||
if (tp->ecdev) {
|
||||
if (get_ecdev(tp)) {
|
||||
status = RTL_R16 (IntrStatus);
|
||||
}
|
||||
else {
|
||||
|
|
@ -2308,7 +2318,7 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
|
|||
if (unlikely(status == 0xFFFF))
|
||||
goto out;
|
||||
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
/* close possible race's with dev_close */
|
||||
if (unlikely(!netif_running(dev))) {
|
||||
RTL_W16 (IntrMask, 0);
|
||||
|
|
@ -2328,7 +2338,7 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
|
|||
/* Receive packets are processed by poll routine.
|
||||
If not running start it now. */
|
||||
if (status & RxAckBits){
|
||||
if (tp->ecdev) {
|
||||
if (get_ecdev(tp)) {
|
||||
/* EtherCAT device: Just receive all frames */
|
||||
rtl8139_rx(dev, tp, 100); // FIXME
|
||||
} else {
|
||||
|
|
@ -2351,7 +2361,7 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
|
|||
RTL_W16 (IntrStatus, TxErr);
|
||||
}
|
||||
out:
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
spin_unlock (&tp->lock);
|
||||
}
|
||||
|
||||
|
|
@ -2405,7 +2415,7 @@ static int rtl8139_close (struct net_device *dev)
|
|||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
netif_stop_queue(dev);
|
||||
napi_disable(&tp->napi);
|
||||
|
||||
|
|
@ -2426,7 +2436,7 @@ static int rtl8139_close (struct net_device *dev)
|
|||
dev->stats.rx_missed_errors += RTL_R32 (RxMissed);
|
||||
RTL_W32 (RxMissed, 0);
|
||||
|
||||
if (!tp->ecdev) {
|
||||
if (!get_ecdev(tp)) {
|
||||
spin_unlock_irqrestore (&tp->lock, flags);
|
||||
|
||||
free_irq(tp->pci_dev->irq, dev);
|
||||
|
|
@ -2654,7 +2664,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
|||
struct rtl8139_private *tp = netdev_priv(dev);
|
||||
int rc;
|
||||
|
||||
if (tp->ecdev || !netif_running(dev))
|
||||
if (get_ecdev(tp) || !netif_running(dev))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irq(&tp->lock);
|
||||
|
|
@ -2673,7 +2683,7 @@ rtl8139_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
|
|||
unsigned long flags;
|
||||
unsigned int start;
|
||||
|
||||
if (tp->ecdev || netif_running(dev)) {
|
||||
if (get_ecdev(tp) || netif_running(dev)) {
|
||||
spin_lock_irqsave (&tp->lock, flags);
|
||||
dev->stats.rx_missed_errors += RTL_R32 (RxMissed);
|
||||
RTL_W32 (RxMissed, 0);
|
||||
|
|
@ -2762,7 +2772,7 @@ static int __maybe_unused rtl8139_suspend(struct device *device)
|
|||
void __iomem *ioaddr = tp->mmio_addr;
|
||||
unsigned long flags;
|
||||
|
||||
if (tp->ecdev || !netif_running (dev))
|
||||
if (get_ecdev(tp) || !netif_running (dev))
|
||||
return 0;
|
||||
|
||||
netif_device_detach (dev);
|
||||
|
|
@ -2787,7 +2797,7 @@ static int __maybe_unused rtl8139_resume(struct device *device)
|
|||
struct net_device *dev = dev_get_drvdata(device);
|
||||
struct rtl8139_private *tp = netdev_priv(dev);
|
||||
|
||||
if (tp->ecdev || !netif_running (dev))
|
||||
if (get_ecdev(tp) || !netif_running (dev))
|
||||
return 0;
|
||||
|
||||
rtl8139_init_ring (dev);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@
|
|||
src := @abs_srcdir@
|
||||
ccflags-y := -I@abs_top_builddir@
|
||||
|
||||
ifeq (@ENABLE_DRIVER_RESOURCE_VERIFYING@,1)
|
||||
ccflags-y += -DEC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
endif
|
||||
|
||||
|
||||
REV := $(shell if test -s $(src)/../revision; then \
|
||||
cat $(src)/../revision; \
|
||||
else \
|
||||
|
|
@ -88,6 +93,10 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq (@ENABLE_STMMAC@,1)
|
||||
obj-m += stmmac/
|
||||
endif
|
||||
|
||||
KBUILD_EXTRA_SYMBOLS := \
|
||||
@abs_top_builddir@/$(LINUX_SYMVERS) \
|
||||
@abs_top_builddir@/master/$(LINUX_SYMVERS)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ SUBDIRS = \
|
|||
genet \
|
||||
igb \
|
||||
igc \
|
||||
r8169
|
||||
r8169 \
|
||||
stmmac
|
||||
|
||||
# using HEADERS to enable tags target
|
||||
noinst_HEADERS = \
|
||||
|
|
|
|||
|
|
@ -31,6 +31,17 @@
|
|||
#define request_dma(X, Y) ((int)(-EINVAL))
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SUSE_KERNEL
|
||||
#include <linux/suse_version.h>
|
||||
#else
|
||||
# ifndef SUSE_VERSION
|
||||
# define SUSE_VERSION 0
|
||||
# endif
|
||||
# ifndef SUSE_PATCHLEVEL
|
||||
# define SUSE_PATCHLEVEL 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "module.h"
|
||||
|
||||
/**
|
||||
|
|
@ -897,7 +908,7 @@ static int ccat_eth_init_netdev(struct ccat_eth_priv *priv)
|
|||
|
||||
/* init netdev with MAC and stack callbacks */
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) || (SUSE_VERSION == 15 && SUSE_PATCHLEVEL == 5)
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
||||
if (priv->netdev->addr_len != ETH_ALEN)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ from re import compile
|
|||
DRIVER_MAP=(
|
||||
# (subdir, driver name, file prefix)
|
||||
(".", "8139too", "8139too"),
|
||||
("stmmac", "dwmac-intel", "dwmac-intel"),
|
||||
(".", "e100", "e100"),
|
||||
("e1000", "e1000", "e1000_main"),
|
||||
("e1000e", "e1000e", "netdev"),
|
||||
|
|
@ -36,6 +37,7 @@ DRIVER_MAP=(
|
|||
("igc", "igc", "igc_main"),
|
||||
(".", "r8169", "r8169"),
|
||||
("r8169", "r8169", "r8169_main"),
|
||||
("stmmac", "stmmac-pci", "stmmac_pci"),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2408,7 +2408,11 @@ static int e100_set_mac_address(struct net_device *netdev, void *p)
|
|||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5
|
||||
eth_hw_addr_set(netdev, addr->sa_data);
|
||||
#else
|
||||
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
|
||||
#endif
|
||||
e100_exec_cb(nic, NULL, e100_setup_iaaddr);
|
||||
|
||||
return 0;
|
||||
|
|
@ -3092,7 +3096,11 @@ static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
|
||||
e100_phy_init(nic);
|
||||
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5
|
||||
eth_hw_addr_set(netdev, (const u8*)nic->eeprom);
|
||||
#else
|
||||
memcpy(netdev->dev_addr, nic->eeprom, ETH_ALEN);
|
||||
#endif
|
||||
if (!is_valid_ether_addr(netdev->dev_addr)) {
|
||||
if (!eeprom_bad_csum_allow) {
|
||||
netif_err(nic, probe, nic->netdev, "Invalid MAC address from EEPROM, aborting\n");
|
||||
|
|
|
|||
|
|
@ -646,10 +646,19 @@ struct nic {
|
|||
__le16 eeprom[256];
|
||||
spinlock_t mdio_lock;
|
||||
const struct firmware *fw;
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct nic *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
static inline void e100_write_flush(struct nic *nic)
|
||||
{
|
||||
/* Flush previous PCI writes through intermediate bridges
|
||||
|
|
@ -661,7 +670,7 @@ static void e100_enable_irq(struct nic *nic)
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (nic->ecdev)
|
||||
if (get_ecdev(nic))
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&nic->cmd_lock, flags);
|
||||
|
|
@ -674,11 +683,11 @@ static void e100_disable_irq(struct nic *nic)
|
|||
{
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (!nic->ecdev)
|
||||
if (!nic->ecdev_)
|
||||
spin_lock_irqsave(&nic->cmd_lock, flags);
|
||||
iowrite8(irq_mask_all, &nic->csr->scb.cmd_hi);
|
||||
e100_write_flush(nic);
|
||||
if (!nic->ecdev)
|
||||
if (!nic->ecdev_)
|
||||
spin_unlock_irqrestore(&nic->cmd_lock, flags);
|
||||
}
|
||||
|
||||
|
|
@ -868,7 +877,7 @@ static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
|
|||
unsigned int i;
|
||||
int err = 0;
|
||||
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
spin_lock_irqsave(&nic->cmd_lock, flags);
|
||||
|
||||
/* Previous command is accepted when SCB clears */
|
||||
|
|
@ -889,7 +898,7 @@ static int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
|
|||
iowrite8(cmd, &nic->csr->scb.cmd_lo);
|
||||
|
||||
err_unlock:
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
spin_unlock_irqrestore(&nic->cmd_lock, flags);
|
||||
|
||||
return err;
|
||||
|
|
@ -902,7 +911,7 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
|
|||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
spin_lock_irqsave(&nic->cb_lock, flags);
|
||||
}
|
||||
|
||||
|
|
@ -950,7 +959,7 @@ static int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
|
|||
}
|
||||
|
||||
err_unlock:
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
spin_unlock_irqrestore(&nic->cb_lock, flags);
|
||||
}
|
||||
|
||||
|
|
@ -984,7 +993,7 @@ static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
|
|||
* manipulation of the MDI control registers is a multi-step
|
||||
* procedure it should be done under lock.
|
||||
*/
|
||||
if (!nic->ecdev)
|
||||
if (!nic->ecdev_) /* exemption of initialization check */
|
||||
spin_lock_irqsave(&nic->mdio_lock, flags);
|
||||
for (i = 100; i; --i) {
|
||||
if (ioread32(&nic->csr->mdi_ctrl) & mdi_ready)
|
||||
|
|
@ -993,7 +1002,7 @@ static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
|
|||
}
|
||||
if (unlikely(!i)) {
|
||||
netdev_err(nic->netdev, "e100.mdio_ctrl won't go Ready\n");
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
spin_unlock_irqrestore(&nic->mdio_lock, flags);
|
||||
return 0; /* No way to indicate timeout error */
|
||||
}
|
||||
|
|
@ -1004,7 +1013,7 @@ static u16 mdio_ctrl_hw(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data)
|
|||
if ((data_out = ioread32(&nic->csr->mdi_ctrl)) & mdi_ready)
|
||||
break;
|
||||
}
|
||||
if (!nic->ecdev)
|
||||
if (!nic->ecdev_)
|
||||
spin_unlock_irqrestore(&nic->mdio_lock, flags);
|
||||
netif_printk(nic, hw, KERN_DEBUG, nic->netdev,
|
||||
"%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n",
|
||||
|
|
@ -1182,7 +1191,7 @@ static int e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
|
|||
config->multicast_all = 0x1; /* 1=accept, 0=no */
|
||||
|
||||
/* disable WoL when up */
|
||||
if (nic->ecdev ||
|
||||
if (get_ecdev(nic) ||
|
||||
(netif_running(nic->netdev) || !(nic->flags & wol_magic)))
|
||||
config->magic_packet_disable = 0x1; /* 1=off, 0=on */
|
||||
|
||||
|
|
@ -1748,8 +1757,8 @@ static void e100_watchdog_impl(struct nic *nic)
|
|||
struct ethtool_cmd cmd = { .cmd = ETHTOOL_GSET };
|
||||
u32 speed;
|
||||
|
||||
if (nic->ecdev) {
|
||||
ecdev_set_link(nic->ecdev, mii_link_ok(&nic->mii) ? 1 : 0);
|
||||
if (get_ecdev(nic)) {
|
||||
ecdev_set_link(get_ecdev(nic), mii_link_ok(&nic->mii) ? 1 : 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1862,14 +1871,14 @@ static netdev_tx_t e100_xmit_frame(struct sk_buff *skb,
|
|||
/* We queued the skb, but now we're out of space. */
|
||||
netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
|
||||
"No space for CB\n");
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
netif_stop_queue(netdev);
|
||||
break;
|
||||
case -ENOMEM:
|
||||
/* This is a hard error - log it. */
|
||||
netif_printk(nic, tx_err, KERN_DEBUG, nic->netdev,
|
||||
"Out of Tx resources, returning skb\n");
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
netif_stop_queue(netdev);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
|
@ -1883,7 +1892,7 @@ static int e100_tx_clean(struct nic *nic)
|
|||
struct cb *cb;
|
||||
int tx_cleaned = 0;
|
||||
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
spin_lock(&nic->cb_lock);
|
||||
|
||||
/* Clean CBs marked complete */
|
||||
|
|
@ -1904,7 +1913,7 @@ static int e100_tx_clean(struct nic *nic)
|
|||
le32_to_cpu(cb->u.tcb.tbd.buf_addr),
|
||||
le16_to_cpu(cb->u.tcb.tbd.size),
|
||||
DMA_TO_DEVICE);
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
dev_kfree_skb_any(cb->skb);
|
||||
cb->skb = NULL;
|
||||
tx_cleaned = 1;
|
||||
|
|
@ -1913,7 +1922,7 @@ static int e100_tx_clean(struct nic *nic)
|
|||
nic->cbs_avail++;
|
||||
}
|
||||
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
spin_unlock(&nic->cb_lock);
|
||||
|
||||
/* Recover from running out of Tx resources in xmit_frame */
|
||||
|
|
@ -1934,7 +1943,7 @@ static void e100_clean_cbs(struct nic *nic)
|
|||
le32_to_cpu(cb->u.tcb.tbd.buf_addr),
|
||||
le16_to_cpu(cb->u.tcb.tbd.size),
|
||||
DMA_TO_DEVICE);
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
dev_kfree_skb(cb->skb);
|
||||
}
|
||||
nic->cb_to_clean = nic->cb_to_clean->next;
|
||||
|
|
@ -2089,7 +2098,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
|
|||
nic->ru_running = RU_SUSPENDED;
|
||||
}
|
||||
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
/* Pull off the RFD and put the actual data (minus eth hdr) */
|
||||
skb_reserve(skb, sizeof(struct rfd));
|
||||
skb_put(skb, actual_size);
|
||||
|
|
@ -2107,27 +2116,27 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
|
|||
}
|
||||
|
||||
if (unlikely(!(rfd_status & cb_ok))) {
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
/* Don't indicate if hardware indicates errors */
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
} else if (actual_size > ETH_DATA_LEN + VLAN_ETH_HLEN + fcs_pad) {
|
||||
/* Don't indicate oversized frames */
|
||||
nic->rx_over_length_errors++;
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
} else {
|
||||
process_skb:
|
||||
dev->stats.rx_packets++;
|
||||
dev->stats.rx_bytes += (actual_size - fcs_pad);
|
||||
if (nic->ecdev) {
|
||||
ecdev_receive(nic->ecdev,
|
||||
if (get_ecdev(nic)) {
|
||||
ecdev_receive(get_ecdev(nic),
|
||||
skb->data + sizeof(struct rfd), actual_size - fcs_pad);
|
||||
|
||||
// No need to detect link status as
|
||||
// long as frames are received: Reset watchdog.
|
||||
if (ecdev_get_link(nic->ecdev)) {
|
||||
if (ecdev_get_link(get_ecdev(nic))) {
|
||||
nic->ec_watchdog_jiffies = jiffies;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -2137,7 +2146,7 @@ process_skb:
|
|||
(*work_done)++;
|
||||
}
|
||||
|
||||
if (nic->ecdev) {
|
||||
if (get_ecdev(nic)) {
|
||||
// make receive frame descriptior usable again
|
||||
memcpy(skb->data, &nic->blank_rfd, sizeof(struct rfd));
|
||||
rx->dma_addr = dma_map_single(&nic->pdev->dev, skb->data,
|
||||
|
|
@ -2191,7 +2200,7 @@ static void e100_rx_clean(struct nic *nic, unsigned int *work_done,
|
|||
old_before_last_rx = nic->rx_to_use->prev->prev;
|
||||
old_before_last_rfd = (struct rfd *)old_before_last_rx->skb->data;
|
||||
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
/* Alloc new skbs to refill list */
|
||||
for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
|
||||
if(unlikely(e100_rx_alloc_skb(nic, rx)))
|
||||
|
|
@ -2288,7 +2297,7 @@ static int e100_rx_alloc_list(struct nic *nic)
|
|||
}
|
||||
}
|
||||
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
/* Set the el-bit on the buffer that is before the last buffer.
|
||||
* This lets us update the next pointer on the last buffer without
|
||||
* worrying about hardware touching it.
|
||||
|
|
@ -2330,7 +2339,7 @@ static irqreturn_t e100_intr(int irq, void *dev_id)
|
|||
if (stat_ack & stat_ack_rnr)
|
||||
nic->ru_running = RU_SUSPENDED;
|
||||
|
||||
if (!nic->ecdev && likely(napi_schedule_prep(&nic->napi))) {
|
||||
if (!get_ecdev(nic) && likely(napi_schedule_prep(&nic->napi))) {
|
||||
e100_disable_irq(nic);
|
||||
__napi_schedule(&nic->napi);
|
||||
}
|
||||
|
|
@ -2418,13 +2427,13 @@ static int e100_up(struct nic *nic)
|
|||
goto err_clean_cbs;
|
||||
e100_set_multicast_list(nic->netdev);
|
||||
e100_start_receiver(nic, NULL);
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
mod_timer(&nic->watchdog, jiffies);
|
||||
}
|
||||
if ((err = request_irq(nic->pdev->irq, e100_intr, IRQF_SHARED,
|
||||
nic->netdev->name, nic->netdev)))
|
||||
goto err_no_irq;
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
netif_wake_queue(nic->netdev);
|
||||
napi_enable(&nic->napi);
|
||||
/* enable ints _after_ enabling poll, preventing a race between
|
||||
|
|
@ -2434,7 +2443,7 @@ static int e100_up(struct nic *nic)
|
|||
return 0;
|
||||
|
||||
err_no_irq:
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
del_timer_sync(&nic->watchdog);
|
||||
err_clean_cbs:
|
||||
e100_clean_cbs(nic);
|
||||
|
|
@ -2445,14 +2454,14 @@ err_rx_clean_list:
|
|||
|
||||
static void e100_down(struct nic *nic)
|
||||
{
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
/* wait here for poll to complete */
|
||||
napi_disable(&nic->napi);
|
||||
netif_stop_queue(nic->netdev);
|
||||
}
|
||||
e100_hw_reset(nic);
|
||||
free_irq(nic->pdev->irq, nic->netdev);
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
del_timer_sync(&nic->watchdog);
|
||||
netif_carrier_off(nic->netdev);
|
||||
}
|
||||
|
|
@ -2929,7 +2938,7 @@ static int e100_open(struct net_device *netdev)
|
|||
struct nic *nic = netdev_priv(netdev);
|
||||
int err = 0;
|
||||
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
netif_carrier_off(netdev);
|
||||
if ((err = e100_up(nic)))
|
||||
netif_err(nic, ifup, nic->netdev, "Cannot open interface, aborting\n");
|
||||
|
|
@ -3089,9 +3098,10 @@ static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
pci_pme_active(pdev, false);
|
||||
|
||||
// offer device to EtherCAT master module
|
||||
nic->ecdev = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE);
|
||||
nic->ecdev_ = ecdev_offer(netdev, e100_ec_poll, THIS_MODULE);
|
||||
nic->ecdev_initialized = true;
|
||||
|
||||
if (!nic->ecdev) {
|
||||
if (!get_ecdev(nic)) {
|
||||
strcpy(netdev->name, "eth%d");
|
||||
if ((err = register_netdev(netdev))) {
|
||||
netif_err(nic, probe, nic->netdev,
|
||||
|
|
@ -3115,10 +3125,10 @@ static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
(unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0),
|
||||
pdev->irq, netdev->dev_addr);
|
||||
|
||||
if (nic->ecdev) {
|
||||
err = ecdev_open(nic->ecdev);
|
||||
if (get_ecdev(nic)) {
|
||||
err = ecdev_open(get_ecdev(nic));
|
||||
if (err) {
|
||||
ecdev_withdraw(nic->ecdev);
|
||||
ecdev_withdraw(get_ecdev(nic));
|
||||
goto err_out_free;
|
||||
}
|
||||
}
|
||||
|
|
@ -3146,9 +3156,9 @@ static void e100_remove(struct pci_dev *pdev)
|
|||
|
||||
if (netdev) {
|
||||
struct nic *nic = netdev_priv(netdev);
|
||||
if (nic->ecdev) {
|
||||
ecdev_close(nic->ecdev);
|
||||
ecdev_withdraw(nic->ecdev);
|
||||
if (get_ecdev(nic)) {
|
||||
ecdev_close(get_ecdev(nic));
|
||||
ecdev_withdraw(get_ecdev(nic));
|
||||
} else {
|
||||
unregister_netdev(netdev);
|
||||
}
|
||||
|
|
@ -3263,7 +3273,7 @@ static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel
|
|||
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||
struct nic *nic = netdev_priv(netdev);
|
||||
|
||||
if (nic->ecdev)
|
||||
if (get_ecdev(nic))
|
||||
return -EBUSY;
|
||||
|
||||
netif_device_detach(netdev);
|
||||
|
|
@ -3290,7 +3300,7 @@ static pci_ers_result_t e100_io_slot_reset(struct pci_dev *pdev)
|
|||
struct net_device *netdev = pci_get_drvdata(pdev);
|
||||
struct nic *nic = netdev_priv(netdev);
|
||||
|
||||
if (nic->ecdev)
|
||||
if (get_ecdev(nic))
|
||||
return -EBUSY;
|
||||
|
||||
if (pci_enable_device(pdev)) {
|
||||
|
|
@ -3323,11 +3333,11 @@ static void e100_io_resume(struct pci_dev *pdev)
|
|||
/* ack any pending wake events, disable PME */
|
||||
pci_enable_wake(pdev, PCI_D0, 0);
|
||||
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
netif_device_attach(netdev);
|
||||
if (nic->ecdev || netif_running(netdev)) {
|
||||
if (get_ecdev(nic) || netif_running(netdev)) {
|
||||
e100_open(netdev);
|
||||
if (!nic->ecdev)
|
||||
if (!get_ecdev(nic))
|
||||
mod_timer(&nic->watchdog, jiffies);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ ifeq (@ENABLE_E1000@,1)
|
|||
obj-m += ec_e1000.o
|
||||
ec_e1000-objs := $(EC_E1000_OBJ)
|
||||
CFLAGS_e1000_main-@KERNEL_E1000@-ethercat.o = -DREV=$(REV)
|
||||
|
||||
ifeq (@ENABLE_DRIVER_RESOURCE_VERIFYING@,1)
|
||||
ccflags-y := -DEC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
endif
|
||||
endif
|
||||
|
||||
KBUILD_EXTRA_SYMBOLS := \
|
||||
|
|
|
|||
|
|
@ -303,11 +303,20 @@ struct e1000_adapter {
|
|||
struct delayed_work fifo_stall_task;
|
||||
struct delayed_work phy_info_task;
|
||||
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
struct irq_work ec_watchdog_kicker;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct e1000_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
|
|
|
|||
|
|
@ -303,11 +303,20 @@ struct e1000_adapter {
|
|||
struct delayed_work fifo_stall_task;
|
||||
struct delayed_work phy_info_task;
|
||||
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
struct irq_work ec_watchdog_kicker;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct e1000_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
enum e1000_state_t {
|
||||
__E1000_TESTING,
|
||||
__E1000_RESETTING,
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ static struct net_device_stats * e1000_get_stats(struct net_device *netdev);
|
|||
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
|
||||
static int e1000_set_mac(struct net_device *netdev, void *p);
|
||||
void ec_poll(struct net_device *);
|
||||
static void ec_kick_watchdog(struct irq_work *work);
|
||||
static irqreturn_t e1000_intr(int irq, void *data);
|
||||
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
||||
struct e1000_tx_ring *tx_ring);
|
||||
|
|
@ -527,9 +528,7 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)
|
|||
{
|
||||
set_bit(__E1000_DOWN, &adapter->flags);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
cancel_delayed_work_sync(&adapter->watchdog_task);
|
||||
}
|
||||
cancel_delayed_work_sync(&adapter->watchdog_task);
|
||||
|
||||
/*
|
||||
* Since the watchdog task can reschedule other tasks, we should cancel
|
||||
|
|
@ -1328,12 +1327,14 @@ static void e1000_remove(struct pci_dev *pdev)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
bool disable_dev;
|
||||
|
||||
if (adapter->ecdev)
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
|
||||
e1000_down_and_stop(adapter);
|
||||
e1000_release_manageability(adapter);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_close(adapter->ecdev);
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
} else {
|
||||
unregister_netdev(netdev);
|
||||
|
|
@ -3864,7 +3865,7 @@ static void ec_kick_watchdog(struct irq_work *work)
|
|||
struct e1000_adapter *adapter =
|
||||
container_of(work, struct e1000_adapter, ec_watchdog_kicker);
|
||||
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
schedule_delayed_work(&adapter->watchdog_task, 1);
|
||||
}
|
||||
|
||||
void ec_poll(struct net_device *netdev)
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
|
||||
static int e1000_set_mac(struct net_device *netdev, void *p);
|
||||
void ec_poll(struct net_device *);
|
||||
static void ec_kick_watchdog(struct irq_work *work);
|
||||
static irqreturn_t e1000_intr(int irq, void *data);
|
||||
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
||||
struct e1000_tx_ring *tx_ring);
|
||||
|
|
@ -496,9 +497,7 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)
|
|||
{
|
||||
set_bit(__E1000_DOWN, &adapter->flags);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
cancel_delayed_work_sync(&adapter->watchdog_task);
|
||||
}
|
||||
cancel_delayed_work_sync(&adapter->watchdog_task);
|
||||
|
||||
/*
|
||||
* Since the watchdog task can reschedule other tasks, we should cancel
|
||||
|
|
@ -1309,12 +1308,14 @@ static void e1000_remove(struct pci_dev *pdev)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
bool disable_dev;
|
||||
|
||||
if (adapter->ecdev)
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
|
||||
e1000_down_and_stop(adapter);
|
||||
e1000_release_manageability(adapter);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_close(adapter->ecdev);
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
} else {
|
||||
unregister_netdev(netdev);
|
||||
|
|
@ -3842,7 +3843,7 @@ static void ec_kick_watchdog(struct irq_work *work)
|
|||
struct e1000_adapter *adapter =
|
||||
container_of(work, struct e1000_adapter, ec_watchdog_kicker);
|
||||
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
schedule_delayed_work(&adapter->watchdog_task, 1);
|
||||
}
|
||||
|
||||
void ec_poll(struct net_device *netdev)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,17 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/if_vlan.h>
|
||||
|
||||
#ifdef CONFIG_SUSE_KERNEL
|
||||
#include <linux/suse_version.h>
|
||||
#else
|
||||
# ifndef SUSE_VERSION
|
||||
# define SUSE_VERSION 0
|
||||
# endif
|
||||
# ifndef SUSE_PATCHLEVEL
|
||||
# define SUSE_PATCHLEVEL 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
char e1000_driver_name[] = "ec_e1000";
|
||||
static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
|
||||
static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation.";
|
||||
|
|
@ -108,6 +119,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
|
||||
static int e1000_set_mac(struct net_device *netdev, void *p);
|
||||
void ec_poll(struct net_device *);
|
||||
static void ec_kick_watchdog(struct irq_work *work);
|
||||
static irqreturn_t e1000_intr(int irq, void *data);
|
||||
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
||||
struct e1000_tx_ring *tx_ring);
|
||||
|
|
@ -259,7 +271,7 @@ static int e1000_request_irq(struct e1000_adapter *adapter)
|
|||
int irq_flags = IRQF_SHARED;
|
||||
int err;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -276,7 +288,7 @@ static void e1000_free_irq(struct e1000_adapter *adapter)
|
|||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +303,7 @@ static void e1000_irq_disable(struct e1000_adapter *adapter)
|
|||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (!adapter->ecdev_) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -308,7 +320,7 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
|
|||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -395,7 +407,7 @@ static void e1000_configure(struct e1000_adapter *adapter)
|
|||
*/
|
||||
for (i = 0; i < adapter->num_rx_queues; i++) {
|
||||
struct e1000_rx_ring *ring = &adapter->rx_ring[i];
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
/* fill rx ring completely! */
|
||||
adapter->alloc_rx_buf(adapter, ring, ring->count);
|
||||
} else {
|
||||
|
|
@ -415,7 +427,7 @@ int e1000_up(struct e1000_adapter *adapter)
|
|||
|
||||
clear_bit(__E1000_DOWN, &adapter->flags);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
napi_enable(&adapter->napi);
|
||||
|
||||
e1000_irq_enable(adapter);
|
||||
|
|
@ -496,9 +508,7 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)
|
|||
{
|
||||
set_bit(__E1000_DOWN, &adapter->flags);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
cancel_delayed_work_sync(&adapter->watchdog_task);
|
||||
}
|
||||
cancel_delayed_work_sync(&adapter->watchdog_task);
|
||||
|
||||
/*
|
||||
* Since the watchdog task can reschedule other tasks, we should cancel
|
||||
|
|
@ -506,13 +516,13 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)
|
|||
* still running after the adapter has been turned down.
|
||||
*/
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
cancel_delayed_work_sync(&adapter->phy_info_task);
|
||||
cancel_delayed_work_sync(&adapter->fifo_stall_task);
|
||||
}
|
||||
|
||||
/* Only kill reset task if adapter is not resetting */
|
||||
if (!adapter->ecdev && !test_bit(__E1000_RESETTING, &adapter->flags))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_RESETTING, &adapter->flags))
|
||||
cancel_work_sync(&adapter->reset_task);
|
||||
}
|
||||
|
||||
|
|
@ -527,7 +537,7 @@ void e1000_down(struct e1000_adapter *adapter)
|
|||
ew32(RCTL, rctl & ~E1000_RCTL_EN);
|
||||
/* flush and sleep below */
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_tx_disable(netdev);
|
||||
}
|
||||
|
||||
|
|
@ -547,7 +557,7 @@ void e1000_down(struct e1000_adapter *adapter)
|
|||
* in the hardware until the next IFF_DOWN+IFF_UP cycle.
|
||||
*/
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_carrier_off(netdev);
|
||||
napi_disable(&adapter->napi);
|
||||
|
||||
|
|
@ -1002,6 +1012,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
|
||||
adapter->bars = bars;
|
||||
adapter->need_ioport = need_ioport;
|
||||
adapter->ecdev_initialized = 0;
|
||||
|
||||
hw = &adapter->hw;
|
||||
hw->back = adapter;
|
||||
|
|
@ -1137,7 +1148,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
e_err(probe, "EEPROM Read Error\n");
|
||||
}
|
||||
/* don't block initialization here due to bad MAC address */
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5
|
||||
eth_hw_addr_set(netdev, hw->mac_addr);
|
||||
#else
|
||||
memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len);
|
||||
#endif
|
||||
|
||||
if (!is_valid_ether_addr(netdev->dev_addr))
|
||||
e_err(probe, "Invalid MAC Address\n");
|
||||
|
|
@ -1232,12 +1247,13 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
e1000_reset(adapter);
|
||||
|
||||
// offer device to EtherCAT master module
|
||||
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
if (adapter->ecdev) {
|
||||
adapter->ecdev_ = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
adapter->ecdev_initialized = 1;
|
||||
if (get_ecdev(adapter)) {
|
||||
init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog);
|
||||
err = ecdev_open(adapter->ecdev);
|
||||
err = ecdev_open(get_ecdev(adapter));
|
||||
if (err) {
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
goto err_register;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1259,7 +1275,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
|
||||
netdev->dev_addr);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
}
|
||||
|
|
@ -1309,13 +1325,15 @@ static void e1000_remove(struct pci_dev *pdev)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
bool disable_dev;
|
||||
|
||||
if (get_ecdev(adapter))
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
|
||||
e1000_down_and_stop(adapter);
|
||||
e1000_release_manageability(adapter);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_close(adapter->ecdev);
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_close(get_ecdev(adapter));
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
} else {
|
||||
unregister_netdev(netdev);
|
||||
}
|
||||
|
|
@ -1448,7 +1466,7 @@ int e1000_open(struct net_device *netdev)
|
|||
/* From here on the code is the same as e1000_up() */
|
||||
clear_bit(__E1000_DOWN, &adapter->flags);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
napi_enable(&adapter->napi);
|
||||
|
||||
e1000_irq_enable(adapter);
|
||||
|
|
@ -1910,7 +1928,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 rdlen, rctl, rxcsum;
|
||||
|
||||
if (!adapter->ecdev && adapter->netdev->mtu > ETH_DATA_LEN) {
|
||||
if (!get_ecdev(adapter) && adapter->netdev->mtu > ETH_DATA_LEN) {
|
||||
rdlen = adapter->rx_ring[0].count *
|
||||
sizeof(struct e1000_rx_desc);
|
||||
adapter->clean_rx = e1000_clean_jumbo_rx_irq;
|
||||
|
|
@ -2010,7 +2028,7 @@ static void
|
|||
e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
|
||||
struct e1000_tx_buffer *buffer_info)
|
||||
{
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2220,7 +2238,7 @@ static void e1000_enter_82542_rst(struct e1000_adapter *adapter)
|
|||
E1000_WRITE_FLUSH();
|
||||
mdelay(5);
|
||||
|
||||
if (!adapter->ecdev && netif_running(netdev))
|
||||
if (!get_ecdev(adapter) && netif_running(netdev))
|
||||
e1000_clean_all_rx_rings(adapter);
|
||||
}
|
||||
|
||||
|
|
@ -2243,7 +2261,7 @@ static void e1000_leave_82542_rst(struct e1000_adapter *adapter)
|
|||
/* No need to loop, because 82542 supports only 1 queue */
|
||||
struct e1000_rx_ring *ring = &adapter->rx_ring[0];
|
||||
e1000_configure_rx(adapter);
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
/* fill rx ring completely! */
|
||||
adapter->alloc_rx_buf(adapter, ring, ring->count);
|
||||
} else {
|
||||
|
|
@ -2275,7 +2293,11 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
|
|||
if (hw->mac_type == e1000_82542_rev2_0)
|
||||
e1000_enter_82542_rst(adapter);
|
||||
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5
|
||||
eth_hw_addr_set(netdev, addr->sa_data);
|
||||
#else
|
||||
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
|
||||
#endif
|
||||
memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len);
|
||||
|
||||
e1000_rar_set(hw, hw->mac_addr, 0);
|
||||
|
|
@ -2499,12 +2521,12 @@ static void e1000_watchdog(struct work_struct *work)
|
|||
u32 link, tctl;
|
||||
|
||||
link = e1000_has_link(adapter);
|
||||
if (!adapter->ecdev && (netif_carrier_ok(netdev)) && link)
|
||||
if (!get_ecdev(adapter) && (netif_carrier_ok(netdev)) && link)
|
||||
goto link_up;
|
||||
|
||||
if (link) {
|
||||
if ((adapter->ecdev && !ecdev_get_link(adapter->ecdev)) ||
|
||||
(!adapter->ecdev && !netif_carrier_ok(netdev))) {
|
||||
if ((get_ecdev(adapter) && !ecdev_get_link(get_ecdev(adapter))) ||
|
||||
(!get_ecdev(adapter) && !netif_carrier_ok(netdev))) {
|
||||
u32 ctrl;
|
||||
/* update snapshot of PHY registers on LSC */
|
||||
e1000_get_speed_and_duplex(hw,
|
||||
|
|
@ -2539,8 +2561,8 @@ static void e1000_watchdog(struct work_struct *work)
|
|||
tctl |= E1000_TCTL_EN;
|
||||
ew32(TCTL, tctl);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 1);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 1);
|
||||
}
|
||||
else {
|
||||
netif_carrier_on(netdev);
|
||||
|
|
@ -2551,15 +2573,15 @@ static void e1000_watchdog(struct work_struct *work)
|
|||
adapter->smartspeed = 0;
|
||||
}
|
||||
} else {
|
||||
if ((adapter->ecdev && ecdev_get_link(adapter->ecdev))
|
||||
|| (!adapter->ecdev && netif_carrier_ok(netdev))) {
|
||||
if ((get_ecdev(adapter) && ecdev_get_link(get_ecdev(adapter)))
|
||||
|| (!get_ecdev(adapter) && netif_carrier_ok(netdev))) {
|
||||
adapter->link_speed = 0;
|
||||
adapter->link_duplex = 0;
|
||||
pr_info("%s NIC Link is Down\n",
|
||||
netdev->name);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
} else {
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
|
|
@ -2587,7 +2609,7 @@ link_up:
|
|||
|
||||
e1000_update_adaptive(hw);
|
||||
|
||||
if (!adapter->ecdev && !netif_carrier_ok(netdev)) {
|
||||
if (!get_ecdev(adapter) && !netif_carrier_ok(netdev)) {
|
||||
if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
|
||||
/* We've lost link, so the controller stops DMA,
|
||||
* but we've got queued Tx work that's never going
|
||||
|
|
@ -2623,7 +2645,7 @@ link_up:
|
|||
adapter->detect_tx_hung = true;
|
||||
|
||||
/* Reschedule the task */
|
||||
if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->flags))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_DOWN, &adapter->flags))
|
||||
schedule_delayed_work(&adapter->watchdog_task, 2 * HZ);
|
||||
}
|
||||
|
||||
|
|
@ -3144,7 +3166,7 @@ static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
|
|||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
@ -3240,7 +3262,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
if (!__pskb_pull_tail(skb, pull_size)) {
|
||||
e_err(drv, "__pskb_pull_tail "
|
||||
"failed.\n");
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
return NETDEV_TX_OK;
|
||||
|
|
@ -3291,7 +3313,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
|
||||
if (unlikely((hw->mac_type == e1000_82547) &&
|
||||
(e1000_82547_fifo_workaround(adapter, skb)))) {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_stop_queue(netdev);
|
||||
if (!test_bit(__E1000_DOWN, &adapter->flags))
|
||||
schedule_delayed_work(&adapter->fifo_stall_task, 1);
|
||||
|
|
@ -3309,7 +3331,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
|
||||
tso = e1000_tso(adapter, tx_ring, skb, protocol);
|
||||
if (tso < 0) {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
return NETDEV_TX_OK;
|
||||
|
|
@ -3341,7 +3363,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
*/
|
||||
int desc_needed = MAX_SKB_FRAGS + 7;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netdev_sent_queue(netdev, skb->len);
|
||||
skb_tx_timestamp(skb);
|
||||
}
|
||||
|
|
@ -3358,12 +3380,12 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
/* Make sure there is space in the ring for the next send. */
|
||||
e1000_maybe_stop_tx(netdev, tx_ring, desc_needed);
|
||||
|
||||
if (adapter->ecdev || !netdev_xmit_more() ||
|
||||
if (get_ecdev(adapter) || !netdev_xmit_more() ||
|
||||
netif_xmit_stopped(netdev_get_tx_queue(netdev, 0))) {
|
||||
writel(tx_ring->next_to_use, hw->hw_addr + tx_ring->tdt);
|
||||
}
|
||||
} else {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
tx_ring->buffer_info[first].time_stamp = 0;
|
||||
|
|
@ -3614,7 +3636,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
@ -3700,7 +3722,7 @@ void e1000_update_stats(struct e1000_adapter *adapter)
|
|||
if (pci_channel_offline(pdev))
|
||||
return;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
spin_lock_irqsave(&adapter->stats_lock, flags);
|
||||
}
|
||||
|
||||
|
|
@ -3831,7 +3853,7 @@ void e1000_update_stats(struct e1000_adapter *adapter)
|
|||
adapter->stats.mgpdc += er32(MGTPDC);
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
spin_unlock_irqrestore(&adapter->stats_lock, flags);
|
||||
}
|
||||
}
|
||||
|
|
@ -3841,7 +3863,7 @@ static void ec_kick_watchdog(struct irq_work *work)
|
|||
struct e1000_adapter *adapter =
|
||||
container_of(work, struct e1000_adapter, ec_watchdog_kicker);
|
||||
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
schedule_delayed_work(&adapter->watchdog_task, 1);
|
||||
}
|
||||
|
||||
void ec_poll(struct net_device *netdev)
|
||||
|
|
@ -3880,11 +3902,11 @@ static irqreturn_t e1000_intr(int irq, void *data)
|
|||
if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
|
||||
hw->get_link_status = 1;
|
||||
/* guard against interrupt when we're going down */
|
||||
if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->flags))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_DOWN, &adapter->flags))
|
||||
schedule_delayed_work(&adapter->watchdog_task, 1);
|
||||
}
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
int i, ec_work_done = 0;
|
||||
for (i = 0; i < E1000_MAX_INTR; i++) {
|
||||
if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring,
|
||||
|
|
@ -4002,12 +4024,12 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
|||
*/
|
||||
smp_store_release(&tx_ring->next_to_clean, i);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netdev_completed_queue(netdev, pkts_compl, bytes_compl);
|
||||
}
|
||||
|
||||
#define TX_WAKE_THRESHOLD 32
|
||||
if (!adapter->ecdev && unlikely(count && netif_carrier_ok(netdev) &&
|
||||
if (!get_ecdev(adapter) && unlikely(count && netif_carrier_ok(netdev) &&
|
||||
E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {
|
||||
/* Make sure that anybody stopping the queue after this
|
||||
* sees the new next_to_clean.
|
||||
|
|
@ -4021,7 +4043,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
|||
}
|
||||
}
|
||||
|
||||
if (!adapter->ecdev && adapter->detect_tx_hung) {
|
||||
if (!get_ecdev(adapter) && adapter->detect_tx_hung) {
|
||||
/* Detect a transmit hang in hardware, this serializes the
|
||||
* check with the clearing of time_stamp and movement of i
|
||||
*/
|
||||
|
|
@ -4509,7 +4531,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
|||
length = le16_to_cpu(rx_desc->length);
|
||||
|
||||
data = buffer_info->rxbuf.data;
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
prefetch(data);
|
||||
skb = e1000_copybreak(adapter, buffer_info, length, data);
|
||||
if (!skb) {
|
||||
|
|
@ -4553,7 +4575,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
|||
if (adapter->discarding) {
|
||||
/* All receives must fit into a single buffer */
|
||||
netdev_dbg(netdev, "Receive packet consumed multiple buffers\n");
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
if (status & E1000_RXD_STAT_EOP)
|
||||
|
|
@ -4569,7 +4591,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
|||
} else if (netdev->features & NETIF_F_RXALL) {
|
||||
goto process_skb;
|
||||
} else {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
goto next_desc;
|
||||
|
|
@ -4586,7 +4608,7 @@ process_skb:
|
|||
*/
|
||||
length -= 4;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
if (buffer_info->rxbuf.data == NULL)
|
||||
skb_put(skb, length);
|
||||
else /* copybreak skb */
|
||||
|
|
@ -4599,10 +4621,10 @@ process_skb:
|
|||
le16_to_cpu(rx_desc->csum), skb);
|
||||
}
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
dma_sync_single_for_cpu(&adapter->pdev->dev, buffer_info->dma,
|
||||
adapter->rx_buffer_len, DMA_FROM_DEVICE);
|
||||
ecdev_receive(adapter->ecdev, data, length);
|
||||
ecdev_receive(get_ecdev(adapter), data, length);
|
||||
|
||||
// No need to detect link status as
|
||||
// long as frames are received: Reset watchdog.
|
||||
|
|
@ -4921,7 +4943,7 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
|
|||
data->phy_id = hw->phy_addr;
|
||||
break;
|
||||
case SIOCGMIIREG:
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EPERM;
|
||||
}
|
||||
spin_lock_irqsave(&adapter->stats_lock, flags);
|
||||
|
|
@ -4933,7 +4955,7 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
|
|||
spin_unlock_irqrestore(&adapter->stats_lock, flags);
|
||||
break;
|
||||
case SIOCSMIIREG:
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EPERM;
|
||||
}
|
||||
if (data->reg_num & ~(0x1F))
|
||||
|
|
@ -5223,7 +5245,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
|
|||
u32 ctrl, ctrl_ext, rctl, status;
|
||||
u32 wufc = adapter->wol;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
@ -5319,7 +5341,7 @@ static int __maybe_unused e1000_resume(struct device *dev)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 err;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
@ -5355,7 +5377,7 @@ static int __maybe_unused e1000_resume(struct device *dev)
|
|||
if (netif_running(netdev))
|
||||
e1000_up(adapter);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_device_attach(netdev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
|
||||
static int e1000_set_mac(struct net_device *netdev, void *p);
|
||||
void ec_poll(struct net_device *);
|
||||
static void ec_kick_watchdog(struct irq_work *work);
|
||||
static irqreturn_t e1000_intr(int irq, void *data);
|
||||
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
||||
struct e1000_tx_ring *tx_ring);
|
||||
|
|
@ -496,9 +497,7 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)
|
|||
{
|
||||
set_bit(__E1000_DOWN, &adapter->flags);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
cancel_delayed_work_sync(&adapter->watchdog_task);
|
||||
}
|
||||
cancel_delayed_work_sync(&adapter->watchdog_task);
|
||||
|
||||
/*
|
||||
* Since the watchdog task can reschedule other tasks, we should cancel
|
||||
|
|
@ -1309,12 +1308,14 @@ static void e1000_remove(struct pci_dev *pdev)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
bool disable_dev;
|
||||
|
||||
if (adapter->ecdev)
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
|
||||
e1000_down_and_stop(adapter);
|
||||
e1000_release_manageability(adapter);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_close(adapter->ecdev);
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
} else {
|
||||
unregister_netdev(netdev);
|
||||
|
|
@ -3841,7 +3842,7 @@ static void ec_kick_watchdog(struct irq_work *work)
|
|||
struct e1000_adapter *adapter =
|
||||
container_of(work, struct e1000_adapter, ec_watchdog_kicker);
|
||||
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
schedule_delayed_work(&adapter->watchdog_task, 1);
|
||||
}
|
||||
|
||||
void ec_poll(struct net_device *netdev)
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
static int e1000_change_mtu(struct net_device *netdev, int new_mtu);
|
||||
static int e1000_set_mac(struct net_device *netdev, void *p);
|
||||
void ec_poll(struct net_device *);
|
||||
static void ec_kick_watchdog(struct irq_work *work);
|
||||
static irqreturn_t e1000_intr(int irq, void *data);
|
||||
static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
||||
struct e1000_tx_ring *tx_ring);
|
||||
|
|
@ -259,7 +260,7 @@ static int e1000_request_irq(struct e1000_adapter *adapter)
|
|||
int irq_flags = IRQF_SHARED;
|
||||
int err;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -276,7 +277,7 @@ static void e1000_free_irq(struct e1000_adapter *adapter)
|
|||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +292,7 @@ static void e1000_irq_disable(struct e1000_adapter *adapter)
|
|||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (adapter->ecdev_) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -308,7 +309,7 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
|
|||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -395,7 +396,7 @@ static void e1000_configure(struct e1000_adapter *adapter)
|
|||
*/
|
||||
for (i = 0; i < adapter->num_rx_queues; i++) {
|
||||
struct e1000_rx_ring *ring = &adapter->rx_ring[i];
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
/* fill rx ring completely! */
|
||||
adapter->alloc_rx_buf(adapter, ring, ring->count);
|
||||
} else {
|
||||
|
|
@ -415,7 +416,7 @@ int e1000_up(struct e1000_adapter *adapter)
|
|||
|
||||
clear_bit(__E1000_DOWN, &adapter->flags);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
napi_enable(&adapter->napi);
|
||||
|
||||
e1000_irq_enable(adapter);
|
||||
|
|
@ -496,9 +497,7 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)
|
|||
{
|
||||
set_bit(__E1000_DOWN, &adapter->flags);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
cancel_delayed_work_sync(&adapter->watchdog_task);
|
||||
}
|
||||
cancel_delayed_work_sync(&adapter->watchdog_task);
|
||||
|
||||
/*
|
||||
* Since the watchdog task can reschedule other tasks, we should cancel
|
||||
|
|
@ -506,13 +505,13 @@ static void e1000_down_and_stop(struct e1000_adapter *adapter)
|
|||
* still running after the adapter has been turned down.
|
||||
*/
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
cancel_delayed_work_sync(&adapter->phy_info_task);
|
||||
cancel_delayed_work_sync(&adapter->fifo_stall_task);
|
||||
}
|
||||
|
||||
/* Only kill reset task if adapter is not resetting */
|
||||
if (!adapter->ecdev && !test_bit(__E1000_RESETTING, &adapter->flags))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_RESETTING, &adapter->flags))
|
||||
cancel_work_sync(&adapter->reset_task);
|
||||
}
|
||||
|
||||
|
|
@ -527,7 +526,7 @@ void e1000_down(struct e1000_adapter *adapter)
|
|||
ew32(RCTL, rctl & ~E1000_RCTL_EN);
|
||||
/* flush and sleep below */
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_tx_disable(netdev);
|
||||
}
|
||||
|
||||
|
|
@ -547,7 +546,7 @@ void e1000_down(struct e1000_adapter *adapter)
|
|||
* in the hardware until the next IFF_DOWN+IFF_UP cycle.
|
||||
*/
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_carrier_off(netdev);
|
||||
napi_disable(&adapter->napi);
|
||||
|
||||
|
|
@ -1002,6 +1001,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
|
||||
adapter->bars = bars;
|
||||
adapter->need_ioport = need_ioport;
|
||||
adapter->ecdev_initialized = 0;
|
||||
|
||||
hw = &adapter->hw;
|
||||
hw->back = adapter;
|
||||
|
|
@ -1232,12 +1232,13 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
e1000_reset(adapter);
|
||||
|
||||
// offer device to EtherCAT master module
|
||||
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
if (adapter->ecdev) {
|
||||
adapter->ecdev_ = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
adapter->ecdev_initialized = 1;
|
||||
if (get_ecdev(adapter)) {
|
||||
init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog);
|
||||
err = ecdev_open(adapter->ecdev);
|
||||
err = ecdev_open(get_ecdev(adapter));
|
||||
if (err) {
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
goto err_register;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1259,7 +1260,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
((hw->bus_width == e1000_bus_width_64) ? 64 : 32),
|
||||
netdev->dev_addr);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* carrier off reporting is important to ethtool even BEFORE open */
|
||||
netif_carrier_off(netdev);
|
||||
}
|
||||
|
|
@ -1309,13 +1310,15 @@ static void e1000_remove(struct pci_dev *pdev)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
bool disable_dev;
|
||||
|
||||
if (get_ecdev(adapter))
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
|
||||
e1000_down_and_stop(adapter);
|
||||
e1000_release_manageability(adapter);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_close(adapter->ecdev);
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_close(get_ecdev(adapter));
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
} else {
|
||||
unregister_netdev(netdev);
|
||||
}
|
||||
|
|
@ -1448,7 +1451,7 @@ int e1000_open(struct net_device *netdev)
|
|||
/* From here on the code is the same as e1000_up() */
|
||||
clear_bit(__E1000_DOWN, &adapter->flags);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
napi_enable(&adapter->napi);
|
||||
|
||||
e1000_irq_enable(adapter);
|
||||
|
|
@ -1910,7 +1913,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 rdlen, rctl, rxcsum;
|
||||
|
||||
if (!adapter->ecdev && adapter->netdev->mtu > ETH_DATA_LEN) {
|
||||
if (!get_ecdev(adapter) && adapter->netdev->mtu > ETH_DATA_LEN) {
|
||||
rdlen = adapter->rx_ring[0].count *
|
||||
sizeof(struct e1000_rx_desc);
|
||||
adapter->clean_rx = e1000_clean_jumbo_rx_irq;
|
||||
|
|
@ -2011,7 +2014,7 @@ e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
|
|||
struct e1000_tx_buffer *buffer_info,
|
||||
int budget)
|
||||
{
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2221,7 +2224,7 @@ static void e1000_enter_82542_rst(struct e1000_adapter *adapter)
|
|||
E1000_WRITE_FLUSH();
|
||||
mdelay(5);
|
||||
|
||||
if (!adapter->ecdev && netif_running(netdev))
|
||||
if (!get_ecdev(adapter) && netif_running(netdev))
|
||||
e1000_clean_all_rx_rings(adapter);
|
||||
}
|
||||
|
||||
|
|
@ -2244,7 +2247,7 @@ static void e1000_leave_82542_rst(struct e1000_adapter *adapter)
|
|||
/* No need to loop, because 82542 supports only 1 queue */
|
||||
struct e1000_rx_ring *ring = &adapter->rx_ring[0];
|
||||
e1000_configure_rx(adapter);
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
/* fill rx ring completely! */
|
||||
adapter->alloc_rx_buf(adapter, ring, ring->count);
|
||||
} else {
|
||||
|
|
@ -2500,12 +2503,12 @@ static void e1000_watchdog(struct work_struct *work)
|
|||
u32 link, tctl;
|
||||
|
||||
link = e1000_has_link(adapter);
|
||||
if (!adapter->ecdev && (netif_carrier_ok(netdev)) && link)
|
||||
if (!get_ecdev(adapter) && (netif_carrier_ok(netdev)) && link)
|
||||
goto link_up;
|
||||
|
||||
if (link) {
|
||||
if ((adapter->ecdev && !ecdev_get_link(adapter->ecdev)) ||
|
||||
(!adapter->ecdev && !netif_carrier_ok(netdev))) {
|
||||
if ((get_ecdev(adapter) && !ecdev_get_link(get_ecdev(adapter))) ||
|
||||
(!get_ecdev(adapter) && !netif_carrier_ok(netdev))) {
|
||||
u32 ctrl;
|
||||
/* update snapshot of PHY registers on LSC */
|
||||
e1000_get_speed_and_duplex(hw,
|
||||
|
|
@ -2540,8 +2543,8 @@ static void e1000_watchdog(struct work_struct *work)
|
|||
tctl |= E1000_TCTL_EN;
|
||||
ew32(TCTL, tctl);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 1);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 1);
|
||||
}
|
||||
else {
|
||||
netif_carrier_on(netdev);
|
||||
|
|
@ -2552,15 +2555,15 @@ static void e1000_watchdog(struct work_struct *work)
|
|||
adapter->smartspeed = 0;
|
||||
}
|
||||
} else {
|
||||
if ((adapter->ecdev && ecdev_get_link(adapter->ecdev))
|
||||
|| (!adapter->ecdev && netif_carrier_ok(netdev))) {
|
||||
if ((get_ecdev(adapter) && ecdev_get_link(get_ecdev(adapter)))
|
||||
|| (!get_ecdev(adapter) && netif_carrier_ok(netdev))) {
|
||||
adapter->link_speed = 0;
|
||||
adapter->link_duplex = 0;
|
||||
pr_info("%s NIC Link is Down\n",
|
||||
netdev->name);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
} else {
|
||||
netif_carrier_off(netdev);
|
||||
|
||||
|
|
@ -2588,7 +2591,7 @@ link_up:
|
|||
|
||||
e1000_update_adaptive(hw);
|
||||
|
||||
if (!adapter->ecdev && !netif_carrier_ok(netdev)) {
|
||||
if (!get_ecdev(adapter) && !netif_carrier_ok(netdev)) {
|
||||
if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) {
|
||||
/* We've lost link, so the controller stops DMA,
|
||||
* but we've got queued Tx work that's never going
|
||||
|
|
@ -2624,7 +2627,7 @@ link_up:
|
|||
adapter->detect_tx_hung = true;
|
||||
|
||||
/* Reschedule the task */
|
||||
if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->flags))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_DOWN, &adapter->flags))
|
||||
schedule_delayed_work(&adapter->watchdog_task, 2 * HZ);
|
||||
}
|
||||
|
||||
|
|
@ -3145,7 +3148,7 @@ static int __e1000_maybe_stop_tx(struct net_device *netdev, int size)
|
|||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_tx_ring *tx_ring = adapter->tx_ring;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
@ -3241,7 +3244,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
if (!__pskb_pull_tail(skb, pull_size)) {
|
||||
e_err(drv, "__pskb_pull_tail "
|
||||
"failed.\n");
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
return NETDEV_TX_OK;
|
||||
|
|
@ -3292,7 +3295,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
|
||||
if (unlikely((hw->mac_type == e1000_82547) &&
|
||||
(e1000_82547_fifo_workaround(adapter, skb)))) {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_stop_queue(netdev);
|
||||
if (!test_bit(__E1000_DOWN, &adapter->flags))
|
||||
schedule_delayed_work(&adapter->fifo_stall_task, 1);
|
||||
|
|
@ -3310,7 +3313,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
|
||||
tso = e1000_tso(adapter, tx_ring, skb, protocol);
|
||||
if (tso < 0) {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
return NETDEV_TX_OK;
|
||||
|
|
@ -3342,7 +3345,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
*/
|
||||
int desc_needed = MAX_SKB_FRAGS + 7;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netdev_sent_queue(netdev, skb->len);
|
||||
skb_tx_timestamp(skb);
|
||||
}
|
||||
|
|
@ -3359,12 +3362,12 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
/* Make sure there is space in the ring for the next send. */
|
||||
e1000_maybe_stop_tx(netdev, tx_ring, desc_needed);
|
||||
|
||||
if (adapter->ecdev || !netdev_xmit_more() ||
|
||||
if (get_ecdev(adapter) || !netdev_xmit_more() ||
|
||||
netif_xmit_stopped(netdev_get_tx_queue(netdev, 0))) {
|
||||
writel(tx_ring->next_to_use, hw->hw_addr + tx_ring->tdt);
|
||||
}
|
||||
} else {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
tx_ring->buffer_info[first].time_stamp = 0;
|
||||
|
|
@ -3615,7 +3618,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
@ -3701,7 +3704,7 @@ void e1000_update_stats(struct e1000_adapter *adapter)
|
|||
if (pci_channel_offline(pdev))
|
||||
return;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
spin_lock_irqsave(&adapter->stats_lock, flags);
|
||||
}
|
||||
|
||||
|
|
@ -3832,7 +3835,7 @@ void e1000_update_stats(struct e1000_adapter *adapter)
|
|||
adapter->stats.mgpdc += er32(MGTPDC);
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
spin_unlock_irqrestore(&adapter->stats_lock, flags);
|
||||
}
|
||||
}
|
||||
|
|
@ -3842,7 +3845,7 @@ static void ec_kick_watchdog(struct irq_work *work)
|
|||
struct e1000_adapter *adapter =
|
||||
container_of(work, struct e1000_adapter, ec_watchdog_kicker);
|
||||
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
schedule_delayed_work(&adapter->watchdog_task, 1);
|
||||
}
|
||||
|
||||
void ec_poll(struct net_device *netdev)
|
||||
|
|
@ -3881,11 +3884,11 @@ static irqreturn_t e1000_intr(int irq, void *data)
|
|||
if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) {
|
||||
hw->get_link_status = 1;
|
||||
/* guard against interrupt when we're going down */
|
||||
if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->flags))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_DOWN, &adapter->flags))
|
||||
schedule_delayed_work(&adapter->watchdog_task, 1);
|
||||
}
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
int i, ec_work_done = 0;
|
||||
for (i = 0; i < E1000_MAX_INTR; i++) {
|
||||
if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring,
|
||||
|
|
@ -4004,12 +4007,12 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
|||
*/
|
||||
smp_store_release(&tx_ring->next_to_clean, i);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netdev_completed_queue(netdev, pkts_compl, bytes_compl);
|
||||
}
|
||||
|
||||
#define TX_WAKE_THRESHOLD 32
|
||||
if (!adapter->ecdev && unlikely(count && netif_carrier_ok(netdev) &&
|
||||
if (!get_ecdev(adapter) && unlikely(count && netif_carrier_ok(netdev) &&
|
||||
E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) {
|
||||
/* Make sure that anybody stopping the queue after this
|
||||
* sees the new next_to_clean.
|
||||
|
|
@ -4023,7 +4026,7 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
|
|||
}
|
||||
}
|
||||
|
||||
if (!adapter->ecdev && adapter->detect_tx_hung) {
|
||||
if (!get_ecdev(adapter) && adapter->detect_tx_hung) {
|
||||
/* Detect a transmit hang in hardware, this serializes the
|
||||
* check with the clearing of time_stamp and movement of i
|
||||
*/
|
||||
|
|
@ -4511,7 +4514,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
|||
length = le16_to_cpu(rx_desc->length);
|
||||
|
||||
data = buffer_info->rxbuf.data;
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
prefetch(data);
|
||||
skb = e1000_copybreak(adapter, buffer_info, length, data);
|
||||
if (!skb) {
|
||||
|
|
@ -4555,7 +4558,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
|||
if (adapter->discarding) {
|
||||
/* All receives must fit into a single buffer */
|
||||
netdev_dbg(netdev, "Receive packet consumed multiple buffers\n");
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
if (status & E1000_RXD_STAT_EOP)
|
||||
|
|
@ -4571,7 +4574,7 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
|
|||
} else if (netdev->features & NETIF_F_RXALL) {
|
||||
goto process_skb;
|
||||
} else {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb(skb);
|
||||
}
|
||||
goto next_desc;
|
||||
|
|
@ -4588,7 +4591,7 @@ process_skb:
|
|||
*/
|
||||
length -= 4;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
if (buffer_info->rxbuf.data == NULL)
|
||||
skb_put(skb, length);
|
||||
else /* copybreak skb */
|
||||
|
|
@ -4601,10 +4604,10 @@ process_skb:
|
|||
le16_to_cpu(rx_desc->csum), skb);
|
||||
}
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
dma_sync_single_for_cpu(&adapter->pdev->dev, buffer_info->dma,
|
||||
adapter->rx_buffer_len, DMA_FROM_DEVICE);
|
||||
ecdev_receive(adapter->ecdev, data, length);
|
||||
ecdev_receive(get_ecdev(adapter), data, length);
|
||||
|
||||
// No need to detect link status as
|
||||
// long as frames are received: Reset watchdog.
|
||||
|
|
@ -4923,7 +4926,7 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
|
|||
data->phy_id = hw->phy_addr;
|
||||
break;
|
||||
case SIOCGMIIREG:
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EPERM;
|
||||
}
|
||||
spin_lock_irqsave(&adapter->stats_lock, flags);
|
||||
|
|
@ -4935,7 +4938,7 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
|
|||
spin_unlock_irqrestore(&adapter->stats_lock, flags);
|
||||
break;
|
||||
case SIOCSMIIREG:
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EPERM;
|
||||
}
|
||||
if (data->reg_num & ~(0x1F))
|
||||
|
|
@ -5225,7 +5228,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
|
|||
u32 ctrl, ctrl_ext, rctl, status;
|
||||
u32 wufc = adapter->wol;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
@ -5321,7 +5324,7 @@ static int __maybe_unused e1000_resume(struct device *dev)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 err;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
|
|
@ -5357,7 +5360,7 @@ static int __maybe_unused e1000_resume(struct device *dev)
|
|||
if (netif_running(netdev))
|
||||
e1000_up(adapter);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_device_attach(netdev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,10 @@ ifeq (@ENABLE_E1000E@,1)
|
|||
ec_e1000e-objs := $(EC_E1000E_OBJ)
|
||||
|
||||
CFLAGS_netdev-@KERNEL_E1000E@-ethercat.o = -DREV=$(REV)
|
||||
|
||||
ifeq (@ENABLE_DRIVER_RESOURCE_VERIFYING@,1)
|
||||
ccflags-y := -DEC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
endif
|
||||
endif
|
||||
|
||||
KBUILD_EXTRA_SYMBOLS := \
|
||||
|
|
|
|||
|
|
@ -336,11 +336,20 @@ struct e1000_adapter {
|
|||
u16 eee_advert;
|
||||
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
struct irq_work watchdog_kicker;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct e1000_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
struct e1000_info {
|
||||
enum e1000_mac_type mac;
|
||||
unsigned int flags;
|
||||
|
|
|
|||
|
|
@ -338,11 +338,20 @@ struct e1000_adapter {
|
|||
u16 eee_advert;
|
||||
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
struct irq_work watchdog_kicker;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct e1000_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
struct e1000_info {
|
||||
enum e1000_mac_type mac;
|
||||
unsigned int flags;
|
||||
|
|
|
|||
|
|
@ -29,12 +29,23 @@
|
|||
|
||||
#include "e1000-5.14-ethercat.h"
|
||||
|
||||
#ifdef CONFIG_SUSE_KERNEL
|
||||
#include <linux/suse_version.h>
|
||||
#else
|
||||
# ifndef SUSE_VERSION
|
||||
# define SUSE_VERSION 0
|
||||
# endif
|
||||
# ifndef SUSE_PATCHLEVEL
|
||||
# define SUSE_PATCHLEVEL 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
char e1000e_driver_name[] = "ec_e1000e";
|
||||
|
||||
static inline int check_arbiter_wa_flag(const struct e1000_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_DISABLE_E1000E_WORKAROUND
|
||||
return !adapter->ecdev && (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA);
|
||||
return !get_ecdev(adapter) && (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA);
|
||||
#else
|
||||
return adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA;
|
||||
#endif
|
||||
|
|
@ -948,7 +959,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
skb = buffer_info->skb;
|
||||
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
buffer_info->skb = NULL;
|
||||
|
||||
prefetch(skb->data - NET_IP_ALIGN);
|
||||
|
|
@ -988,7 +999,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
goto next_desc;
|
||||
}
|
||||
|
||||
if (unlikely(!adapter->ecdev &&
|
||||
if (unlikely(!get_ecdev(adapter) &&
|
||||
(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) &&
|
||||
!(netdev->features & NETIF_F_RXALL))) {
|
||||
/* recycle */
|
||||
|
|
@ -1015,7 +1026,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
* performance for small packets with large amounts
|
||||
* of reassembly being done in the stack
|
||||
*/
|
||||
if (!adapter->ecdev && length < copybreak) {
|
||||
if (!get_ecdev(adapter) && length < copybreak) {
|
||||
struct sk_buff *new_skb =
|
||||
napi_alloc_skb(&adapter->napi, length);
|
||||
if (new_skb) {
|
||||
|
|
@ -1039,8 +1050,8 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_receive(adapter->ecdev, skb->data, length);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_receive(get_ecdev(adapter), skb->data, length);
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
} else {
|
||||
e1000_receive_skb(adapter, netdev, skb, staterr,
|
||||
|
|
@ -1090,7 +1101,7 @@ static void e1000_put_txbuf(struct e1000_ring *tx_ring,
|
|||
buffer_info->dma = 0;
|
||||
}
|
||||
if (buffer_info->skb) {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
if (drop)
|
||||
dev_kfree_skb_any(buffer_info->skb);
|
||||
else
|
||||
|
|
@ -1142,8 +1153,8 @@ static void e1000_print_hw_hang(struct work_struct *work)
|
|||
}
|
||||
|
||||
/* Real hang detected */
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
}
|
||||
else {
|
||||
netif_stop_queue(netdev);
|
||||
|
|
@ -1285,12 +1296,12 @@ static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring)
|
|||
|
||||
tx_ring->next_to_clean = i;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netdev_completed_queue(netdev, pkts_compl, bytes_compl);
|
||||
}
|
||||
|
||||
#define TX_WAKE_THRESHOLD 32
|
||||
if (!adapter->ecdev && count && netif_carrier_ok(netdev) &&
|
||||
if (!get_ecdev(adapter) && count && netif_carrier_ok(netdev) &&
|
||||
e1000_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD) {
|
||||
/* Make sure that anybody stopping the queue after this
|
||||
* sees the new next_to_clean.
|
||||
|
|
@ -1304,7 +1315,7 @@ static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring)
|
|||
}
|
||||
}
|
||||
|
||||
if (!adapter->ecdev && adapter->detect_tx_hung) {
|
||||
if (!get_ecdev(adapter) && adapter->detect_tx_hung) {
|
||||
/* Detect a transmit hang in hardware, this serializes the
|
||||
* check with the clearing of time_stamp and movement of i
|
||||
*/
|
||||
|
|
@ -1383,7 +1394,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
if (adapter->flags2 & FLAG2_IS_DISCARDING) {
|
||||
e_dbg("Packet Split buffers didn't pick up the full packet\n");
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_irq(skb);
|
||||
}
|
||||
if (staterr & E1000_RXD_STAT_EOP)
|
||||
|
|
@ -1393,7 +1404,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
if (unlikely((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) &&
|
||||
!(netdev->features & NETIF_F_RXALL))) {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_irq(skb);
|
||||
}
|
||||
goto next_desc;
|
||||
|
|
@ -1403,7 +1414,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
if (!length) {
|
||||
e_dbg("Last part of the packet spanning multiple descriptors\n");
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_irq(skb);
|
||||
}
|
||||
goto next_desc;
|
||||
|
|
@ -1492,8 +1503,8 @@ copydone:
|
|||
cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))
|
||||
adapter->rx_hdr_split++;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_receive(adapter->ecdev, skb->data, length);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_receive(get_ecdev(adapter), skb->data, length);
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
} else {
|
||||
e1000_receive_skb(adapter, netdev, skb, staterr,
|
||||
|
|
@ -1502,7 +1513,7 @@ copydone:
|
|||
|
||||
next_desc:
|
||||
rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF);
|
||||
if (!adapter->ecdev) buffer_info->skb = NULL;
|
||||
if (!get_ecdev(adapter)) buffer_info->skb = NULL;
|
||||
|
||||
/* return some buffers to hardware, one at a time is too slow */
|
||||
if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
|
||||
|
|
@ -1576,7 +1587,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
skb = buffer_info->skb;
|
||||
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
buffer_info->skb = NULL;
|
||||
|
||||
++i;
|
||||
|
|
@ -1602,7 +1613,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
/* recycle both page and skb */
|
||||
buffer_info->skb = skb;
|
||||
/* an error means any chain goes out the window too */
|
||||
if (!adapter->ecdev && rx_ring->rx_skb_top)
|
||||
if (!get_ecdev(adapter) && rx_ring->rx_skb_top)
|
||||
dev_kfree_skb_irq(rx_ring->rx_skb_top);
|
||||
rx_ring->rx_skb_top = NULL;
|
||||
goto next_desc;
|
||||
|
|
@ -1675,14 +1686,14 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
total_rx_packets++;
|
||||
|
||||
/* eth type trans needs skb->data to point to something */
|
||||
if (!adapter->ecdev && !pskb_may_pull(skb, ETH_HLEN)) {
|
||||
if (!get_ecdev(adapter) && !pskb_may_pull(skb, ETH_HLEN)) {
|
||||
e_err("pskb_may_pull failed.\n");
|
||||
dev_kfree_skb_irq(skb);
|
||||
goto next_desc;
|
||||
}
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_receive(adapter->ecdev, skb->data, length);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_receive(get_ecdev(adapter), skb->data, length);
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
} else {
|
||||
e1000_receive_skb(adapter, netdev, skb, staterr,
|
||||
|
|
@ -1807,7 +1818,7 @@ static irqreturn_t e1000_intr_msi(int __always_unused irq, void *data)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 icr = er32(ICR);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
int ec_work_done = 0;
|
||||
adapter->clean_rx(adapter->rx_ring, &ec_work_done, 100);
|
||||
e1000_clean_tx_irq(adapter->tx_ring);
|
||||
|
|
@ -1881,7 +1892,7 @@ static irqreturn_t e1000_intr(int __always_unused irq, void *data)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 rctl, icr = er32(ICR);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
int ec_work_done = 0;
|
||||
adapter->clean_rx(adapter->rx_ring, &ec_work_done, 100);
|
||||
e1000_clean_tx_irq(adapter->tx_ring);
|
||||
|
|
@ -1969,7 +1980,7 @@ static irqreturn_t e1000_msix_other(int __always_unused irq, void *data)
|
|||
if (icr & E1000_ICR_LSC) {
|
||||
hw->mac.get_link_status = true;
|
||||
/* guard against interrupt when we're going down */
|
||||
if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
mod_timer(&adapter->watchdog_timer, jiffies + 1);
|
||||
}
|
||||
|
||||
|
|
@ -2016,7 +2027,7 @@ static irqreturn_t e1000_intr_msix_rx(int __always_unused irq, void *data)
|
|||
rx_ring->set_itr = 0;
|
||||
}
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
int ec_work_done = 0;
|
||||
adapter->clean_rx(adapter->rx_ring, &ec_work_done, 100);
|
||||
} else {
|
||||
|
|
@ -2230,7 +2241,7 @@ static int e1000_request_irq(struct e1000_adapter *adapter)
|
|||
struct net_device *netdev = adapter->netdev;
|
||||
int err;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return 0;
|
||||
|
||||
if (adapter->msix_entries) {
|
||||
|
|
@ -2265,7 +2276,7 @@ static void e1000_free_irq(struct e1000_adapter *adapter)
|
|||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2299,7 +2310,7 @@ static void e1000_irq_disable(struct e1000_adapter *adapter)
|
|||
ew32(EIAC_82574, 0);
|
||||
e1e_flush();
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2321,7 +2332,7 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
|
|||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return;
|
||||
|
||||
if (adapter->msix_entries) {
|
||||
|
|
@ -3848,7 +3859,7 @@ static void e1000_configure(struct e1000_adapter *adapter)
|
|||
e1000e_setup_rss_hash(adapter);
|
||||
e1000_setup_rctl(adapter);
|
||||
e1000_configure_rx(adapter);
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
adapter->alloc_rx_buf(rx_ring, adapter->rx_ring->count, GFP_KERNEL);
|
||||
} else {
|
||||
adapter->alloc_rx_buf(rx_ring, e1000_desc_unused(rx_ring),
|
||||
|
|
@ -4290,7 +4301,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
|
|||
|
||||
/**
|
||||
* e1000e_trigger_lsc - trigger an LSC interrupt
|
||||
* @adapter:
|
||||
* @adapter:
|
||||
*
|
||||
* Fire a link status change interrupt to start the watchdog.
|
||||
**/
|
||||
|
|
@ -4311,7 +4322,7 @@ void e1000e_up(struct e1000_adapter *adapter)
|
|||
|
||||
clear_bit(__E1000_DOWN, &adapter->state);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
if (adapter->msix_entries)
|
||||
e1000_configure_msix(adapter);
|
||||
e1000_irq_enable(adapter);
|
||||
|
|
@ -4364,8 +4375,8 @@ void e1000e_down(struct e1000_adapter *adapter, bool reset)
|
|||
*/
|
||||
set_bit(__E1000_DOWN, &adapter->state);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
}
|
||||
else {
|
||||
netif_carrier_off(netdev);
|
||||
|
|
@ -4377,7 +4388,7 @@ void e1000e_down(struct e1000_adapter *adapter, bool reset)
|
|||
ew32(RCTL, rctl & ~E1000_RCTL_EN);
|
||||
/* flush and sleep below */
|
||||
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
netif_stop_queue(netdev);
|
||||
|
||||
/* disable transmits in the hardware */
|
||||
|
|
@ -4389,7 +4400,7 @@ void e1000e_down(struct e1000_adapter *adapter, bool reset)
|
|||
e1e_flush();
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
e1000_irq_disable(adapter);
|
||||
|
||||
napi_synchronize(&adapter->napi);
|
||||
|
|
@ -4722,8 +4733,8 @@ int e1000e_open(struct net_device *netdev)
|
|||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
} else {
|
||||
netif_carrier_off(netdev);
|
||||
netif_stop_queue(netdev);
|
||||
|
|
@ -4771,7 +4782,7 @@ int e1000e_open(struct net_device *netdev)
|
|||
* ignore e1000e MSI messages, which means we need to test our MSI
|
||||
* interrupt now
|
||||
*/
|
||||
if (!adapter->ecdev && adapter->int_mode != E1000E_INT_MODE_LEGACY) {
|
||||
if (!get_ecdev(adapter) && adapter->int_mode != E1000E_INT_MODE_LEGACY) {
|
||||
err = e1000_test_msi(adapter);
|
||||
if (err) {
|
||||
e_err("Interrupt allocation failed\n");
|
||||
|
|
@ -4782,7 +4793,7 @@ int e1000e_open(struct net_device *netdev)
|
|||
/* From here on the code is the same as e1000e_up() */
|
||||
clear_bit(__E1000_DOWN, &adapter->state);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
napi_enable(&adapter->napi);
|
||||
|
||||
e1000_irq_enable(adapter);
|
||||
|
|
@ -4843,7 +4854,7 @@ int e1000e_close(struct net_device *netdev)
|
|||
netdev_info(netdev, "NIC Link is Down\n");
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
napi_disable(&adapter->napi);
|
||||
}
|
||||
|
||||
|
|
@ -4887,7 +4898,11 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
|
|||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5
|
||||
eth_hw_addr_set(netdev, addr->sa_data);
|
||||
#else
|
||||
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
|
||||
#endif
|
||||
memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len);
|
||||
|
||||
hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, 0);
|
||||
|
|
@ -5314,9 +5329,9 @@ static void e1000_watchdog_task(struct work_struct *work)
|
|||
return;
|
||||
|
||||
link = e1000e_has_link(adapter);
|
||||
if ((adapter->ecdev && (ecdev_get_link(adapter->ecdev)) && link)
|
||||
|| (!adapter->ecdev && (netif_carrier_ok(netdev)) && link)) {
|
||||
if (!adapter->ecdev) {
|
||||
if ((get_ecdev(adapter) && (ecdev_get_link(get_ecdev(adapter))) && link)
|
||||
|| (!get_ecdev(adapter) && (netif_carrier_ok(netdev)) && link)) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* Cancel scheduled suspend requests. */
|
||||
pm_runtime_resume(netdev->dev.parent);
|
||||
}
|
||||
|
|
@ -5330,8 +5345,8 @@ static void e1000_watchdog_task(struct work_struct *work)
|
|||
e1000_update_mng_vlan(adapter);
|
||||
|
||||
if (link) {
|
||||
if ((adapter->ecdev && !ecdev_get_link(adapter->ecdev))
|
||||
|| (!adapter->ecdev && !netif_carrier_ok(netdev))) {
|
||||
if ((get_ecdev(adapter) && !ecdev_get_link(get_ecdev(adapter)))
|
||||
|| (!get_ecdev(adapter) && !netif_carrier_ok(netdev))) {
|
||||
bool txb2b = true;
|
||||
|
||||
/* Cancel scheduled suspend requests. */
|
||||
|
|
@ -5447,27 +5462,27 @@ static void e1000_watchdog_task(struct work_struct *work)
|
|||
if (phy->ops.cfg_on_link_up)
|
||||
phy->ops.cfg_on_link_up(hw);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 1);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 1);
|
||||
}
|
||||
else {
|
||||
netif_wake_queue(netdev);
|
||||
netif_carrier_on(netdev);
|
||||
}
|
||||
|
||||
if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
mod_timer(&adapter->phy_info_timer,
|
||||
round_jiffies(jiffies + 2 * HZ));
|
||||
}
|
||||
} else {
|
||||
if ((adapter->ecdev && ecdev_get_link(adapter->ecdev))
|
||||
|| (!adapter->ecdev && netif_carrier_ok(netdev))) {
|
||||
if ((get_ecdev(adapter) && ecdev_get_link(get_ecdev(adapter)))
|
||||
|| (!get_ecdev(adapter) && netif_carrier_ok(netdev))) {
|
||||
adapter->link_speed = 0;
|
||||
adapter->link_duplex = 0;
|
||||
/* Link status message must follow this format */
|
||||
netdev_info(netdev, "NIC Link is Down\n");
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
}
|
||||
else {
|
||||
netif_carrier_off(netdev);
|
||||
|
|
@ -5569,7 +5584,7 @@ link_up:
|
|||
}
|
||||
|
||||
/* Reset the timer */
|
||||
if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
mod_timer(&adapter->watchdog_timer,
|
||||
round_jiffies(jiffies + 2 * HZ));
|
||||
}
|
||||
|
|
@ -5950,13 +5965,13 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
__be16 protocol = vlan_get_protocol(skb);
|
||||
|
||||
if (test_bit(__E1000_DOWN, &adapter->state)) {
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
if (skb->len <= 0) {
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
|
@ -5985,7 +6000,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
pull_size = min_t(unsigned int, 4, skb->data_len);
|
||||
if (!__pskb_pull_tail(skb, pull_size)) {
|
||||
e_err("__pskb_pull_tail failed.\n");
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
|
@ -6011,7 +6026,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
/* need: count + 2 desc gap to keep tail from touching
|
||||
* head, otherwise try next time
|
||||
*/
|
||||
if (!adapter->ecdev && e1000_maybe_stop_tx(tx_ring, count + 2))
|
||||
if (!get_ecdev(adapter) && e1000_maybe_stop_tx(tx_ring, count + 2))
|
||||
return NETDEV_TX_BUSY;
|
||||
|
||||
if (skb_vlan_tag_present(skb)) {
|
||||
|
|
@ -6024,7 +6039,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
|
||||
tso = e1000_tso(tx_ring, skb, protocol);
|
||||
if (tso < 0) {
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
|
@ -6066,14 +6081,14 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
netdev_sent_queue(netdev, skb->len);
|
||||
e1000_tx_queue(tx_ring, tx_flags, count);
|
||||
/* Make sure there is space in the ring for the next send. */
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
e1000_maybe_stop_tx(tx_ring,
|
||||
(MAX_SKB_FRAGS *
|
||||
DIV_ROUND_UP(PAGE_SIZE,
|
||||
adapter->tx_fifo_limit) + 2));
|
||||
}
|
||||
|
||||
if (adapter->ecdev || !netdev_xmit_more() ||
|
||||
if (get_ecdev(adapter) || !netdev_xmit_more() ||
|
||||
netif_xmit_stopped(netdev_get_tx_queue(netdev, 0))) {
|
||||
if (check_arbiter_wa_flag(adapter))
|
||||
e1000e_update_tdt_wa(tx_ring,
|
||||
|
|
@ -6082,7 +6097,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
writel(tx_ring->next_to_use, tx_ring->tail);
|
||||
}
|
||||
} else {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
tx_ring->buffer_info[first].time_stamp = 0;
|
||||
|
|
@ -6184,7 +6199,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
|
|||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
int max_frame = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
/* Jumbo frame support */
|
||||
|
|
@ -7004,7 +7019,7 @@ static int __e1000_resume(struct pci_dev *pdev)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
u16 aspm_disable_flag = 0;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
if (adapter->flags2 & FLAG2_DISABLE_ASPM_L0S)
|
||||
|
|
@ -7078,7 +7093,7 @@ static __maybe_unused int e1000e_pm_suspend(struct device *dev)
|
|||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
int rc;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
e1000e_flush_lpic(pdev);
|
||||
|
|
@ -7571,6 +7586,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
adapter->hw.mac.type = ei->mac;
|
||||
adapter->max_hw_frame_size = ei->max_hw_frame_size;
|
||||
adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
|
||||
adapter->ecdev_initialized = 0;
|
||||
|
||||
mmio_start = pci_resource_start(pdev, 0);
|
||||
mmio_len = pci_resource_len(pdev, 0);
|
||||
|
|
@ -7705,7 +7721,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
dev_err(&pdev->dev,
|
||||
"NVM Read Error while reading MAC address\n");
|
||||
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5
|
||||
eth_hw_addr_set(netdev, adapter->hw.mac.addr);
|
||||
#else
|
||||
memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
|
||||
#endif
|
||||
|
||||
if (!is_valid_ether_addr(netdev->dev_addr)) {
|
||||
dev_err(&pdev->dev, "Invalid MAC Address: %pM\n",
|
||||
|
|
@ -7797,12 +7817,13 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (hw->mac.type >= e1000_pch_cnp)
|
||||
adapter->flags2 |= FLAG2_ENABLE_S0IX_FLOWS;
|
||||
|
||||
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
if (adapter->ecdev) {
|
||||
adapter->ecdev_ = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
adapter->ecdev_initialized = 1;
|
||||
if (get_ecdev(adapter)) {
|
||||
init_irq_work(&adapter->watchdog_kicker, ec_watchdog_kicker);
|
||||
err = ecdev_open(adapter->ecdev);
|
||||
err = ecdev_open(get_ecdev(adapter));
|
||||
if (err) {
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
goto err_register;
|
||||
}
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
|
|
@ -7874,10 +7895,10 @@ static void e1000_remove(struct pci_dev *pdev)
|
|||
|
||||
e1000e_ptp_remove(adapter);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_close(adapter->ecdev);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_close(get_ecdev(adapter));
|
||||
irq_work_sync(&adapter->watchdog_kicker);
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
}
|
||||
|
||||
/* The timers may be rescheduled, so explicitly disable them
|
||||
|
|
@ -7901,7 +7922,7 @@ static void e1000_remove(struct pci_dev *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
unregister_netdev(netdev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ char e1000e_driver_name[] = "ec_e1000e";
|
|||
static inline int check_arbiter_wa_flag(const struct e1000_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_DISABLE_E1000E_WORKAROUND
|
||||
return !adapter->ecdev && (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA);
|
||||
return !get_ecdev(adapter) && (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA);
|
||||
#else
|
||||
return adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA;
|
||||
#endif
|
||||
|
|
@ -949,7 +949,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
skb = buffer_info->skb;
|
||||
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
buffer_info->skb = NULL;
|
||||
|
||||
prefetch(skb->data - NET_IP_ALIGN);
|
||||
|
|
@ -989,7 +989,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
goto next_desc;
|
||||
}
|
||||
|
||||
if (unlikely(!adapter->ecdev &&
|
||||
if (unlikely(!get_ecdev(adapter) &&
|
||||
(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) &&
|
||||
!(netdev->features & NETIF_F_RXALL))) {
|
||||
/* recycle */
|
||||
|
|
@ -1016,7 +1016,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
* performance for small packets with large amounts
|
||||
* of reassembly being done in the stack
|
||||
*/
|
||||
if (!adapter->ecdev && length < copybreak) {
|
||||
if (!get_ecdev(adapter) && length < copybreak) {
|
||||
struct sk_buff *new_skb =
|
||||
napi_alloc_skb(&adapter->napi, length);
|
||||
if (new_skb) {
|
||||
|
|
@ -1040,8 +1040,8 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_receive(adapter->ecdev, skb->data, length);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_receive(get_ecdev(adapter), skb->data, length);
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
} else {
|
||||
e1000_receive_skb(adapter, netdev, skb, staterr,
|
||||
|
|
@ -1091,7 +1091,7 @@ static void e1000_put_txbuf(struct e1000_ring *tx_ring,
|
|||
buffer_info->dma = 0;
|
||||
}
|
||||
if (buffer_info->skb) {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
if (drop)
|
||||
dev_kfree_skb_any(buffer_info->skb);
|
||||
else
|
||||
|
|
@ -1143,8 +1143,8 @@ static void e1000_print_hw_hang(struct work_struct *work)
|
|||
}
|
||||
|
||||
/* Real hang detected */
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
}
|
||||
else {
|
||||
netif_stop_queue(netdev);
|
||||
|
|
@ -1286,12 +1286,12 @@ static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring)
|
|||
|
||||
tx_ring->next_to_clean = i;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netdev_completed_queue(netdev, pkts_compl, bytes_compl);
|
||||
}
|
||||
|
||||
#define TX_WAKE_THRESHOLD 32
|
||||
if (!adapter->ecdev && count && netif_carrier_ok(netdev) &&
|
||||
if (!get_ecdev(adapter) && count && netif_carrier_ok(netdev) &&
|
||||
e1000_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD) {
|
||||
/* Make sure that anybody stopping the queue after this
|
||||
* sees the new next_to_clean.
|
||||
|
|
@ -1305,7 +1305,7 @@ static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring)
|
|||
}
|
||||
}
|
||||
|
||||
if (!adapter->ecdev && adapter->detect_tx_hung) {
|
||||
if (!get_ecdev(adapter) && adapter->detect_tx_hung) {
|
||||
/* Detect a transmit hang in hardware, this serializes the
|
||||
* check with the clearing of time_stamp and movement of i
|
||||
*/
|
||||
|
|
@ -1384,7 +1384,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
if (adapter->flags2 & FLAG2_IS_DISCARDING) {
|
||||
e_dbg("Packet Split buffers didn't pick up the full packet\n");
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_irq(skb);
|
||||
}
|
||||
if (staterr & E1000_RXD_STAT_EOP)
|
||||
|
|
@ -1394,7 +1394,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
if (unlikely((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) &&
|
||||
!(netdev->features & NETIF_F_RXALL))) {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_irq(skb);
|
||||
}
|
||||
goto next_desc;
|
||||
|
|
@ -1404,7 +1404,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
if (!length) {
|
||||
e_dbg("Last part of the packet spanning multiple descriptors\n");
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_irq(skb);
|
||||
}
|
||||
goto next_desc;
|
||||
|
|
@ -1493,8 +1493,8 @@ copydone:
|
|||
cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP))
|
||||
adapter->rx_hdr_split++;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_receive(adapter->ecdev, skb->data, length);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_receive(get_ecdev(adapter), skb->data, length);
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
} else {
|
||||
e1000_receive_skb(adapter, netdev, skb, staterr,
|
||||
|
|
@ -1503,7 +1503,7 @@ copydone:
|
|||
|
||||
next_desc:
|
||||
rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF);
|
||||
if (!adapter->ecdev) buffer_info->skb = NULL;
|
||||
if (!get_ecdev(adapter)) buffer_info->skb = NULL;
|
||||
|
||||
/* return some buffers to hardware, one at a time is too slow */
|
||||
if (cleaned_count >= E1000_RX_BUFFER_WRITE) {
|
||||
|
|
@ -1577,7 +1577,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
|
||||
skb = buffer_info->skb;
|
||||
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
buffer_info->skb = NULL;
|
||||
|
||||
++i;
|
||||
|
|
@ -1603,7 +1603,7 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
/* recycle both page and skb */
|
||||
buffer_info->skb = skb;
|
||||
/* an error means any chain goes out the window too */
|
||||
if (!adapter->ecdev && rx_ring->rx_skb_top)
|
||||
if (!get_ecdev(adapter) && rx_ring->rx_skb_top)
|
||||
dev_kfree_skb_irq(rx_ring->rx_skb_top);
|
||||
rx_ring->rx_skb_top = NULL;
|
||||
goto next_desc;
|
||||
|
|
@ -1676,14 +1676,14 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
|
|||
total_rx_packets++;
|
||||
|
||||
/* eth type trans needs skb->data to point to something */
|
||||
if (!adapter->ecdev && !pskb_may_pull(skb, ETH_HLEN)) {
|
||||
if (!get_ecdev(adapter) && !pskb_may_pull(skb, ETH_HLEN)) {
|
||||
e_err("pskb_may_pull failed.\n");
|
||||
dev_kfree_skb_irq(skb);
|
||||
goto next_desc;
|
||||
}
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_receive(adapter->ecdev, skb->data, length);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_receive(get_ecdev(adapter), skb->data, length);
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
} else {
|
||||
e1000_receive_skb(adapter, netdev, skb, staterr,
|
||||
|
|
@ -1808,7 +1808,7 @@ static irqreturn_t e1000_intr_msi(int __always_unused irq, void *data)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 icr = er32(ICR);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
int ec_work_done = 0;
|
||||
adapter->clean_rx(adapter->rx_ring, &ec_work_done, 100);
|
||||
e1000_clean_tx_irq(adapter->tx_ring);
|
||||
|
|
@ -1882,7 +1882,7 @@ static irqreturn_t e1000_intr(int __always_unused irq, void *data)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
u32 rctl, icr = er32(ICR);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
int ec_work_done = 0;
|
||||
adapter->clean_rx(adapter->rx_ring, &ec_work_done, 100);
|
||||
e1000_clean_tx_irq(adapter->tx_ring);
|
||||
|
|
@ -1970,7 +1970,7 @@ static irqreturn_t e1000_msix_other(int __always_unused irq, void *data)
|
|||
if (icr & E1000_ICR_LSC) {
|
||||
hw->mac.get_link_status = true;
|
||||
/* guard against interrupt when we're going down */
|
||||
if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
mod_timer(&adapter->watchdog_timer, jiffies + 1);
|
||||
}
|
||||
|
||||
|
|
@ -2017,7 +2017,7 @@ static irqreturn_t e1000_intr_msix_rx(int __always_unused irq, void *data)
|
|||
rx_ring->set_itr = 0;
|
||||
}
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
int ec_work_done = 0;
|
||||
adapter->clean_rx(adapter->rx_ring, &ec_work_done, 100);
|
||||
} else {
|
||||
|
|
@ -2231,7 +2231,7 @@ static int e1000_request_irq(struct e1000_adapter *adapter)
|
|||
struct net_device *netdev = adapter->netdev;
|
||||
int err;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return 0;
|
||||
|
||||
if (adapter->msix_entries) {
|
||||
|
|
@ -2266,7 +2266,7 @@ static void e1000_free_irq(struct e1000_adapter *adapter)
|
|||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2300,7 +2300,7 @@ static void e1000_irq_disable(struct e1000_adapter *adapter)
|
|||
ew32(EIAC_82574, 0);
|
||||
e1e_flush();
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2322,7 +2322,7 @@ static void e1000_irq_enable(struct e1000_adapter *adapter)
|
|||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return;
|
||||
|
||||
if (adapter->msix_entries) {
|
||||
|
|
@ -3845,7 +3845,7 @@ static void e1000_configure(struct e1000_adapter *adapter)
|
|||
e1000e_setup_rss_hash(adapter);
|
||||
e1000_setup_rctl(adapter);
|
||||
e1000_configure_rx(adapter);
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
adapter->alloc_rx_buf(rx_ring, adapter->rx_ring->count, GFP_KERNEL);
|
||||
} else {
|
||||
adapter->alloc_rx_buf(rx_ring, e1000_desc_unused(rx_ring),
|
||||
|
|
@ -4309,7 +4309,7 @@ void e1000e_up(struct e1000_adapter *adapter)
|
|||
|
||||
clear_bit(__E1000_DOWN, &adapter->state);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
if (adapter->msix_entries)
|
||||
e1000_configure_msix(adapter);
|
||||
e1000_irq_enable(adapter);
|
||||
|
|
@ -4362,8 +4362,8 @@ void e1000e_down(struct e1000_adapter *adapter, bool reset)
|
|||
*/
|
||||
set_bit(__E1000_DOWN, &adapter->state);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
}
|
||||
else {
|
||||
netif_carrier_off(netdev);
|
||||
|
|
@ -4375,7 +4375,7 @@ void e1000e_down(struct e1000_adapter *adapter, bool reset)
|
|||
ew32(RCTL, rctl & ~E1000_RCTL_EN);
|
||||
/* flush and sleep below */
|
||||
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
netif_stop_queue(netdev);
|
||||
|
||||
/* disable transmits in the hardware */
|
||||
|
|
@ -4387,7 +4387,7 @@ void e1000e_down(struct e1000_adapter *adapter, bool reset)
|
|||
e1e_flush();
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
e1000_irq_disable(adapter);
|
||||
|
||||
napi_synchronize(&adapter->napi);
|
||||
|
|
@ -4720,8 +4720,8 @@ int e1000e_open(struct net_device *netdev)
|
|||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
} else {
|
||||
netif_carrier_off(netdev);
|
||||
netif_stop_queue(netdev);
|
||||
|
|
@ -4769,7 +4769,7 @@ int e1000e_open(struct net_device *netdev)
|
|||
* ignore e1000e MSI messages, which means we need to test our MSI
|
||||
* interrupt now
|
||||
*/
|
||||
if (!adapter->ecdev && adapter->int_mode != E1000E_INT_MODE_LEGACY) {
|
||||
if (!get_ecdev(adapter) && adapter->int_mode != E1000E_INT_MODE_LEGACY) {
|
||||
err = e1000_test_msi(adapter);
|
||||
if (err) {
|
||||
e_err("Interrupt allocation failed\n");
|
||||
|
|
@ -4780,7 +4780,7 @@ int e1000e_open(struct net_device *netdev)
|
|||
/* From here on the code is the same as e1000e_up() */
|
||||
clear_bit(__E1000_DOWN, &adapter->state);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
napi_enable(&adapter->napi);
|
||||
|
||||
e1000_irq_enable(adapter);
|
||||
|
|
@ -4841,7 +4841,7 @@ int e1000e_close(struct net_device *netdev)
|
|||
netdev_info(netdev, "NIC Link is Down\n");
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
napi_disable(&adapter->napi);
|
||||
}
|
||||
|
||||
|
|
@ -5312,9 +5312,9 @@ static void e1000_watchdog_task(struct work_struct *work)
|
|||
return;
|
||||
|
||||
link = e1000e_has_link(adapter);
|
||||
if ((adapter->ecdev && (ecdev_get_link(adapter->ecdev)) && link)
|
||||
|| (!adapter->ecdev && (netif_carrier_ok(netdev)) && link)) {
|
||||
if (!adapter->ecdev) {
|
||||
if ((get_ecdev(adapter) && (ecdev_get_link(get_ecdev(adapter))) && link)
|
||||
|| (!get_ecdev(adapter) && (netif_carrier_ok(netdev)) && link)) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* Cancel scheduled suspend requests. */
|
||||
pm_runtime_resume(netdev->dev.parent);
|
||||
}
|
||||
|
|
@ -5328,8 +5328,8 @@ static void e1000_watchdog_task(struct work_struct *work)
|
|||
e1000_update_mng_vlan(adapter);
|
||||
|
||||
if (link) {
|
||||
if ((adapter->ecdev && !ecdev_get_link(adapter->ecdev))
|
||||
|| (!adapter->ecdev && !netif_carrier_ok(netdev))) {
|
||||
if ((get_ecdev(adapter) && !ecdev_get_link(get_ecdev(adapter)))
|
||||
|| (!get_ecdev(adapter) && !netif_carrier_ok(netdev))) {
|
||||
bool txb2b = true;
|
||||
|
||||
/* Cancel scheduled suspend requests. */
|
||||
|
|
@ -5420,27 +5420,27 @@ static void e1000_watchdog_task(struct work_struct *work)
|
|||
if (phy->ops.cfg_on_link_up)
|
||||
phy->ops.cfg_on_link_up(hw);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 1);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 1);
|
||||
}
|
||||
else {
|
||||
netif_wake_queue(netdev);
|
||||
netif_carrier_on(netdev);
|
||||
}
|
||||
|
||||
if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
mod_timer(&adapter->phy_info_timer,
|
||||
round_jiffies(jiffies + 2 * HZ));
|
||||
}
|
||||
} else {
|
||||
if ((adapter->ecdev && ecdev_get_link(adapter->ecdev))
|
||||
|| (!adapter->ecdev && netif_carrier_ok(netdev))) {
|
||||
if ((get_ecdev(adapter) && ecdev_get_link(get_ecdev(adapter)))
|
||||
|| (!get_ecdev(adapter) && netif_carrier_ok(netdev))) {
|
||||
adapter->link_speed = 0;
|
||||
adapter->link_duplex = 0;
|
||||
/* Link status message must follow this format */
|
||||
netdev_info(netdev, "NIC Link is Down\n");
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
}
|
||||
else {
|
||||
netif_carrier_off(netdev);
|
||||
|
|
@ -5542,7 +5542,7 @@ link_up:
|
|||
}
|
||||
|
||||
/* Reset the timer */
|
||||
if (!adapter->ecdev && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
if (!get_ecdev(adapter) && !test_bit(__E1000_DOWN, &adapter->state))
|
||||
mod_timer(&adapter->watchdog_timer,
|
||||
round_jiffies(jiffies + 2 * HZ));
|
||||
}
|
||||
|
|
@ -5923,13 +5923,13 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
__be16 protocol = vlan_get_protocol(skb);
|
||||
|
||||
if (test_bit(__E1000_DOWN, &adapter->state)) {
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
if (skb->len <= 0) {
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
|
@ -5958,7 +5958,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
pull_size = min_t(unsigned int, 4, skb->data_len);
|
||||
if (!__pskb_pull_tail(skb, pull_size)) {
|
||||
e_err("__pskb_pull_tail failed.\n");
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
|
@ -5984,7 +5984,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
/* need: count + 2 desc gap to keep tail from touching
|
||||
* head, otherwise try next time
|
||||
*/
|
||||
if (!adapter->ecdev && e1000_maybe_stop_tx(tx_ring, count + 2))
|
||||
if (!get_ecdev(adapter) && e1000_maybe_stop_tx(tx_ring, count + 2))
|
||||
return NETDEV_TX_BUSY;
|
||||
|
||||
if (skb_vlan_tag_present(skb)) {
|
||||
|
|
@ -5997,7 +5997,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
|
||||
tso = e1000_tso(tx_ring, skb, protocol);
|
||||
if (tso < 0) {
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
dev_kfree_skb_any(skb);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
|
@ -6039,14 +6039,14 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
netdev_sent_queue(netdev, skb->len);
|
||||
e1000_tx_queue(tx_ring, tx_flags, count);
|
||||
/* Make sure there is space in the ring for the next send. */
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
e1000_maybe_stop_tx(tx_ring,
|
||||
((MAX_SKB_FRAGS + 1) *
|
||||
DIV_ROUND_UP(PAGE_SIZE,
|
||||
adapter->tx_fifo_limit) + 4));
|
||||
}
|
||||
|
||||
if (adapter->ecdev || !netdev_xmit_more() ||
|
||||
if (get_ecdev(adapter) || !netdev_xmit_more() ||
|
||||
netif_xmit_stopped(netdev_get_tx_queue(netdev, 0))) {
|
||||
if (check_arbiter_wa_flag(adapter))
|
||||
e1000e_update_tdt_wa(tx_ring,
|
||||
|
|
@ -6055,7 +6055,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
|
|||
writel(tx_ring->next_to_use, tx_ring->tail);
|
||||
}
|
||||
} else {
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
tx_ring->buffer_info[first].time_stamp = 0;
|
||||
|
|
@ -6157,7 +6157,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
|
|||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
int max_frame = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
/* Jumbo frame support */
|
||||
|
|
@ -7033,7 +7033,7 @@ static int __e1000_resume(struct pci_dev *pdev)
|
|||
struct e1000_hw *hw = &adapter->hw;
|
||||
u16 aspm_disable_flag = 0;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
if (adapter->flags2 & FLAG2_DISABLE_ASPM_L0S)
|
||||
|
|
@ -7107,7 +7107,7 @@ static __maybe_unused int e1000e_pm_suspend(struct device *dev)
|
|||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
int rc;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
e1000e_flush_lpic(pdev);
|
||||
|
|
@ -7594,6 +7594,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
adapter->hw.mac.type = ei->mac;
|
||||
adapter->max_hw_frame_size = ei->max_hw_frame_size;
|
||||
adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
|
||||
adapter->ecdev_initialized = 0;
|
||||
|
||||
mmio_start = pci_resource_start(pdev, 0);
|
||||
mmio_len = pci_resource_len(pdev, 0);
|
||||
|
|
@ -7844,12 +7845,13 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
if (hw->mac.type >= e1000_pch_cnp)
|
||||
adapter->flags2 |= FLAG2_ENABLE_S0IX_FLOWS;
|
||||
|
||||
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
if (adapter->ecdev) {
|
||||
adapter->ecdev_ = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
adapter->ecdev_initialized = 1;
|
||||
if (get_ecdev(adapter)) {
|
||||
init_irq_work(&adapter->watchdog_kicker, ec_watchdog_kicker);
|
||||
err = ecdev_open(adapter->ecdev);
|
||||
err = ecdev_open(get_ecdev(adapter));
|
||||
if (err) {
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
goto err_register;
|
||||
}
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
|
|
@ -7921,10 +7923,10 @@ static void e1000_remove(struct pci_dev *pdev)
|
|||
|
||||
e1000e_ptp_remove(adapter);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_close(adapter->ecdev);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_close(get_ecdev(adapter));
|
||||
irq_work_sync(&adapter->watchdog_kicker);
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
}
|
||||
|
||||
/* The timers may be rescheduled, so explicitly disable them
|
||||
|
|
@ -7948,7 +7950,7 @@ static void e1000_remove(struct pci_dev *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
unregister_netdev(netdev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,17 @@
|
|||
|
||||
#define EC_GEN_RX_BUF_SIZE 1600
|
||||
|
||||
#ifdef CONFIG_SUSE_KERNEL
|
||||
#include <linux/suse_version.h>
|
||||
#else
|
||||
# ifndef SUSE_VERSION
|
||||
# define SUSE_VERSION 0
|
||||
# endif
|
||||
# ifndef SUSE_PATCHLEVEL
|
||||
# define SUSE_PATCHLEVEL 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
int __init ec_gen_init_module(void);
|
||||
|
|
@ -239,7 +250,7 @@ int ec_gen_device_offer(
|
|||
int ret = 0;
|
||||
|
||||
dev->used_netdev = desc->netdev;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) || (SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5)
|
||||
eth_hw_addr_set(dev->netdev, desc->dev_addr);
|
||||
#else
|
||||
memcpy(dev->netdev->dev_addr, desc->dev_addr, ETH_ALEN);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ ifeq (@ENABLE_GENET@,1)
|
|||
bcmmii-@KERNEL_GENET@-ethercat.o \
|
||||
bcmgenet_wol-@KERNEL_GENET@-ethercat.o
|
||||
|
||||
ifeq (@ENABLE_DRIVER_RESOURCE_VERIFYING@,1)
|
||||
ccflags-y := -DEC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
endif
|
||||
|
||||
CFLAGS_bcmgenet-@KERNEL_GENET@-ethercat.o = -DREV="\"$(REV)\""
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -22,13 +22,33 @@
|
|||
include $(top_srcdir)/Makefile.kbuild
|
||||
|
||||
EXTRA_DIST = \
|
||||
bcmgenet-5.10-ethercat.c \
|
||||
bcmgenet-5.10-ethercat.h \
|
||||
bcmgenet-5.10-orig.c \
|
||||
bcmgenet-5.10-orig.h \
|
||||
bcmgenet-5.14-ethercat.c \
|
||||
bcmgenet-5.14-ethercat.h \
|
||||
bcmgenet-5.14-orig.c \
|
||||
bcmgenet-5.14-orig.h \
|
||||
bcmgenet-6.1-ethercat.c \
|
||||
bcmgenet-6.1-ethercat.h \
|
||||
bcmgenet-6.1-orig.c \
|
||||
bcmgenet-6.1-orig.h \
|
||||
bcmgenet_wol-5.10-ethercat.c \
|
||||
bcmgenet_wol-5.10-orig.c \
|
||||
bcmgenet_wol-5.14-ethercat.c \
|
||||
bcmgenet_wol-5.14-orig.c \
|
||||
bcmgenet_wol-6.1-ethercat.c \
|
||||
bcmgenet_wol-6.1-orig.c \
|
||||
bcmmii-5.14-ethercat.c \
|
||||
bcmmii-5.14-orig.c \
|
||||
bcmmii-5.10-ethercat.c \
|
||||
bcmmii-5.10-orig.c \
|
||||
bcmmii-6.1-ethercat.c \
|
||||
bcmmii-6.1-orig.c
|
||||
bcmmii-6.1-orig.c \
|
||||
unimac-5.14-ethercat.h \
|
||||
unimac-5.14-orig.h \
|
||||
unimac-6.1-ethercat.h \
|
||||
unimac-6.1-orig.h
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,764 @@
|
|||
/* 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>
|
||||
|
||||
/* 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_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 UMAC_SPEED_10 0
|
||||
#define UMAC_SPEED_100 1
|
||||
#define UMAC_SPEED_1000 2
|
||||
#define UMAC_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 (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_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_MODE 0x44
|
||||
#define MODE_LINK_STATUS (1 << 5)
|
||||
|
||||
#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_TX_FLUSH 0x334
|
||||
|
||||
#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_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;
|
||||
|
||||
/* 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 */
|
||||
int old_link;
|
||||
int old_speed;
|
||||
int old_duplex;
|
||||
int old_pause;
|
||||
phy_interface_t phy_interface;
|
||||
int phy_addr;
|
||||
int ext_phy;
|
||||
|
||||
/* 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_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);
|
||||
|
||||
#endif /* __BCMGENET_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,759 @@
|
|||
/* 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>
|
||||
|
||||
/* 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_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 UMAC_SPEED_10 0
|
||||
#define UMAC_SPEED_100 1
|
||||
#define UMAC_SPEED_1000 2
|
||||
#define UMAC_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 (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_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_MODE 0x44
|
||||
#define MODE_LINK_STATUS (1 << 5)
|
||||
|
||||
#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_TX_FLUSH 0x334
|
||||
|
||||
#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_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;
|
||||
|
||||
/* 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 */
|
||||
int old_link;
|
||||
int old_speed;
|
||||
int old_duplex;
|
||||
int old_pause;
|
||||
phy_interface_t phy_interface;
|
||||
int phy_addr;
|
||||
int ext_phy;
|
||||
|
||||
/* 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_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);
|
||||
|
||||
#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-5.14-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_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;
|
||||
|
||||
/* 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 */
|
||||
int old_link;
|
||||
int old_speed;
|
||||
int old_duplex;
|
||||
int old_pause;
|
||||
phy_interface_t phy_interface;
|
||||
int phy_addr;
|
||||
int ext_phy;
|
||||
|
||||
/* 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_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);
|
||||
|
||||
#endif /* __BCMGENET_H__ */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,704 @@
|
|||
/* 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_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;
|
||||
|
||||
/* 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 */
|
||||
int old_link;
|
||||
int old_speed;
|
||||
int old_duplex;
|
||||
int old_pause;
|
||||
phy_interface_t phy_interface;
|
||||
int phy_addr;
|
||||
int ext_phy;
|
||||
|
||||
/* 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_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);
|
||||
|
||||
#endif /* __BCMGENET_H__ */
|
||||
|
|
@ -1897,7 +1897,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
|
|||
if (skb) {
|
||||
pkts_compl++;
|
||||
bytes_compl += GENET_CB(skb)->bytes_sent;
|
||||
if (!priv->ecdev)
|
||||
if (!get_ecdev(priv))
|
||||
dev_consume_skb_any(skb);
|
||||
}
|
||||
|
||||
|
|
@ -1914,7 +1914,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
|
|||
ring->packets += pkts_compl;
|
||||
ring->bytes += bytes_compl;
|
||||
|
||||
if (!priv->ecdev)
|
||||
if (!get_ecdev(priv))
|
||||
netdev_tx_completed_queue(netdev_get_tx_queue(dev, ring->queue),
|
||||
pkts_compl, bytes_compl);
|
||||
|
||||
|
|
@ -1940,7 +1940,7 @@ static int bcmgenet_tx_poll(struct napi_struct *napi, int budget)
|
|||
unsigned int work_done = 0;
|
||||
struct netdev_queue *txq;
|
||||
|
||||
if (ring->priv->ecdev)
|
||||
if (get_ecdev(ring->priv))
|
||||
return 0;
|
||||
|
||||
spin_lock(&ring->lock);
|
||||
|
|
@ -1992,6 +1992,7 @@ static struct sk_buff *bcmgenet_add_tsb(struct net_device *dev,
|
|||
/* If 64 byte status block enabled, must make sure skb has
|
||||
* enough headroom for us to insert 64B status block.
|
||||
*/
|
||||
BUG_ON(get_ecdev(priv));
|
||||
new_skb = skb_realloc_headroom(skb, sizeof(*status));
|
||||
if (!new_skb) {
|
||||
dev_kfree_skb_any(skb);
|
||||
|
|
@ -2077,7 +2078,7 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
|
||||
spin_lock(&ring->lock);
|
||||
if (ring->free_bds <= (nr_frags + 1)) {
|
||||
if (!priv->ecdev && !netif_tx_queue_stopped(txq)) {
|
||||
if (!get_ecdev(priv) && !netif_tx_queue_stopped(txq)) {
|
||||
netif_tx_stop_queue(txq);
|
||||
netdev_err(dev,
|
||||
"%s: tx ring %d full when queue %d awake\n",
|
||||
|
|
@ -2157,14 +2158,14 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
ring->prod_index += nr_frags + 1;
|
||||
ring->prod_index &= DMA_P_INDEX_MASK;
|
||||
|
||||
if (!priv->ecdev) {
|
||||
if (!get_ecdev(priv)) {
|
||||
netdev_tx_sent_queue(txq, GENET_CB(skb)->bytes_sent);
|
||||
|
||||
if (ring->free_bds <= (MAX_SKB_FRAGS + 1))
|
||||
netif_tx_stop_queue(txq);
|
||||
}
|
||||
|
||||
if (priv->ecdev || !netdev_xmit_more() || netif_xmit_stopped(txq))
|
||||
if (get_ecdev(priv) || !netdev_xmit_more() || netif_xmit_stopped(txq))
|
||||
/* Packets are ready, update producer index */
|
||||
bcmgenet_tdma_ring_writel(priv, ring->index,
|
||||
ring->prod_index, TDMA_PROD_INDEX);
|
||||
|
|
@ -2183,7 +2184,7 @@ out_unmap_frags:
|
|||
bcmgenet_free_tx_cb(kdev, tx_cb_ptr);
|
||||
}
|
||||
|
||||
if (!priv->ecdev)
|
||||
if (!get_ecdev(priv))
|
||||
dev_kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -2249,7 +2250,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
|
|||
unsigned int p_index, mask;
|
||||
unsigned int discards;
|
||||
|
||||
if (!priv->ecdev) {
|
||||
if (!get_ecdev(priv)) {
|
||||
/* Clear status before servicing to reduce spurious interrupts */
|
||||
if (ring->index == DESC_INDEX) {
|
||||
bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_RXDMA_DONE,
|
||||
|
|
@ -2291,7 +2292,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
|
|||
__be16 rx_csum;
|
||||
|
||||
cb = &priv->rx_cbs[ring->read_ptr];
|
||||
if (priv->ecdev)
|
||||
if (get_ecdev(priv))
|
||||
/* DMA unmap current skb */
|
||||
skb = bcmgenet_free_rx_cb(kdev, cb);
|
||||
else
|
||||
|
|
@ -2327,7 +2328,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
|
|||
netif_err(priv, rx_status, dev, "oversized packet\n");
|
||||
dev->stats.rx_length_errors++;
|
||||
dev->stats.rx_errors++;
|
||||
if (!priv->ecdev)
|
||||
if (!get_ecdev(priv))
|
||||
dev_kfree_skb_any(skb);
|
||||
goto next;
|
||||
}
|
||||
|
|
@ -2336,7 +2337,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
|
|||
netif_err(priv, rx_status, dev,
|
||||
"dropping fragmented packet!\n");
|
||||
ring->errors++;
|
||||
if (!priv->ecdev)
|
||||
if (!get_ecdev(priv))
|
||||
dev_kfree_skb_any(skb);
|
||||
goto next;
|
||||
}
|
||||
|
|
@ -2358,12 +2359,12 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
|
|||
if (dma_flag & DMA_RX_LG)
|
||||
dev->stats.rx_length_errors++;
|
||||
dev->stats.rx_errors++;
|
||||
if (!priv->ecdev)
|
||||
if (!get_ecdev(priv))
|
||||
dev_kfree_skb_any(skb);
|
||||
goto next;
|
||||
} /* error packet */
|
||||
|
||||
if (!priv->ecdev) {
|
||||
if (!get_ecdev(priv)) {
|
||||
skb_put(skb, len);
|
||||
|
||||
/* remove RSB and hardware 2bytes added for IP alignment */
|
||||
|
|
@ -2372,7 +2373,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
|
|||
len -= 66;
|
||||
|
||||
if (priv->crc_fwd_en) {
|
||||
if (!priv->ecdev)
|
||||
if (!get_ecdev(priv))
|
||||
skb_trim(skb, len - ETH_FCS_LEN);
|
||||
len -= ETH_FCS_LEN;
|
||||
}
|
||||
|
|
@ -2386,12 +2387,12 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,
|
|||
if (dma_flag & DMA_RX_MULT)
|
||||
dev->stats.multicast++;
|
||||
|
||||
if (priv->ecdev) {
|
||||
if (get_ecdev(priv)) {
|
||||
dma_addr_t mapping;
|
||||
/* skip status block and padding in skb */
|
||||
const unsigned char *data = skb->data + 66;
|
||||
|
||||
ecdev_receive(priv->ecdev, data, len);
|
||||
ecdev_receive(get_ecdev(priv), data, len);
|
||||
|
||||
/* remap skb */
|
||||
mapping = dma_map_single(kdev, skb->data, priv->rx_buf_len,
|
||||
|
|
@ -2438,7 +2439,7 @@ static int bcmgenet_rx_poll(struct napi_struct *napi, int budget)
|
|||
struct dim_sample dim_sample = {};
|
||||
unsigned int work_done;
|
||||
|
||||
if (ring->priv->ecdev)
|
||||
if (get_ecdev(ring->priv))
|
||||
return 0;
|
||||
|
||||
work_done = bcmgenet_desc_rx(ring, budget);
|
||||
|
|
@ -2652,7 +2653,7 @@ static void init_umac(struct bcmgenet_priv *priv)
|
|||
/* Enable MDIO interrupts on GENET v3+ */
|
||||
if (priv->hw_params->flags & GENET_HAS_MDIO_INTR) {
|
||||
int0_enable |= UMAC_IRQ_MDIO_ERROR;
|
||||
if (!priv->ecdev)
|
||||
if (!get_ecdev(priv))
|
||||
int0_enable |= UMAC_IRQ_MDIO_DONE;
|
||||
}
|
||||
|
||||
|
|
@ -2682,7 +2683,7 @@ static void bcmgenet_init_rx_coalesce(struct bcmgenet_rx_ring *ring)
|
|||
usecs = ring->rx_coalesce_usecs;
|
||||
pkts = ring->rx_max_coalesced_frames;
|
||||
|
||||
if (ring->priv->ecdev)
|
||||
if (get_ecdev(ring->priv))
|
||||
return;
|
||||
|
||||
/* If DIM was enabled, re-apply default parameters */
|
||||
|
|
@ -2751,7 +2752,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,
|
|||
DMA_END_ADDR);
|
||||
|
||||
/* Initialize Tx NAPI */
|
||||
if (!priv->ecdev)
|
||||
if (!get_ecdev(priv))
|
||||
netif_napi_add_tx(priv->dev, &ring->napi, bcmgenet_tx_poll);
|
||||
}
|
||||
|
||||
|
|
@ -2788,7 +2789,7 @@ static int bcmgenet_init_rx_ring(struct bcmgenet_priv *priv,
|
|||
bcmgenet_init_rx_coalesce(ring);
|
||||
|
||||
/* Initialize Rx NAPI */
|
||||
if (!priv->ecdev)
|
||||
if (!get_ecdev(priv))
|
||||
netif_napi_add(priv->dev, &ring->napi, bcmgenet_rx_poll);
|
||||
|
||||
bcmgenet_rdma_ring_writel(priv, index, 0, RDMA_PROD_INDEX);
|
||||
|
|
@ -2819,7 +2820,7 @@ static void bcmgenet_enable_tx_napi(struct bcmgenet_priv *priv)
|
|||
unsigned int i;
|
||||
struct bcmgenet_tx_ring *ring;
|
||||
|
||||
if (priv->ecdev)
|
||||
if (get_ecdev(priv))
|
||||
return;
|
||||
|
||||
for (i = 0; i < priv->hw_params->tx_queues; ++i) {
|
||||
|
|
@ -2838,7 +2839,7 @@ static void bcmgenet_disable_tx_napi(struct bcmgenet_priv *priv)
|
|||
unsigned int i;
|
||||
struct bcmgenet_tx_ring *ring;
|
||||
|
||||
if (priv->ecdev)
|
||||
if (get_ecdev(priv))
|
||||
return;
|
||||
|
||||
for (i = 0; i < priv->hw_params->tx_queues; ++i) {
|
||||
|
|
@ -2855,7 +2856,7 @@ static void bcmgenet_fini_tx_napi(struct bcmgenet_priv *priv)
|
|||
unsigned int i;
|
||||
struct bcmgenet_tx_ring *ring;
|
||||
|
||||
if (priv->ecdev)
|
||||
if (get_ecdev(priv))
|
||||
return;
|
||||
|
||||
for (i = 0; i < priv->hw_params->tx_queues; ++i) {
|
||||
|
|
@ -2941,7 +2942,7 @@ static void bcmgenet_enable_rx_napi(struct bcmgenet_priv *priv)
|
|||
unsigned int i;
|
||||
struct bcmgenet_rx_ring *ring;
|
||||
|
||||
if (priv->ecdev)
|
||||
if (get_ecdev(priv))
|
||||
return;
|
||||
|
||||
for (i = 0; i < priv->hw_params->rx_queues; ++i) {
|
||||
|
|
@ -2960,7 +2961,7 @@ static void bcmgenet_disable_rx_napi(struct bcmgenet_priv *priv)
|
|||
unsigned int i;
|
||||
struct bcmgenet_rx_ring *ring;
|
||||
|
||||
if (priv->ecdev)
|
||||
if (get_ecdev(priv))
|
||||
return;
|
||||
|
||||
for (i = 0; i < priv->hw_params->rx_queues; ++i) {
|
||||
|
|
@ -2979,7 +2980,7 @@ static void bcmgenet_fini_rx_napi(struct bcmgenet_priv *priv)
|
|||
unsigned int i;
|
||||
struct bcmgenet_rx_ring *ring;
|
||||
|
||||
if (priv->ecdev)
|
||||
if (get_ecdev(priv))
|
||||
return;
|
||||
|
||||
for (i = 0; i < priv->hw_params->rx_queues; ++i) {
|
||||
|
|
@ -3519,7 +3520,7 @@ static int bcmgenet_open(struct net_device *dev)
|
|||
|
||||
bcmgenet_netif_start(dev);
|
||||
|
||||
if (!priv->ecdev)
|
||||
if (!get_ecdev(priv))
|
||||
netif_tx_start_all_queues(dev);
|
||||
|
||||
return 0;
|
||||
|
|
@ -4088,6 +4089,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
priv = netdev_priv(dev);
|
||||
priv->ecdev_initialized = false;
|
||||
priv->irq0 = platform_get_irq(pdev, 0);
|
||||
if (priv->irq0 < 0) {
|
||||
err = priv->irq0;
|
||||
|
|
@ -4244,12 +4246,13 @@ static int bcmgenet_probe(struct platform_device *pdev)
|
|||
/* Turn off the main clock, WOL clock is handled separately */
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
priv->ecdev = ecdev_offer(dev, ec_poll, THIS_MODULE);
|
||||
if (priv->ecdev) {
|
||||
err = ecdev_open(priv->ecdev);
|
||||
priv->ecdev_ = ecdev_offer(dev, ec_poll, THIS_MODULE);
|
||||
priv->ecdev_initialized = true;
|
||||
if (get_ecdev(priv)) {
|
||||
err = ecdev_open(get_ecdev(priv));
|
||||
if (err) {
|
||||
ecdev_withdraw(priv->ecdev);
|
||||
priv->ecdev = NULL;
|
||||
ecdev_withdraw(get_ecdev(priv));
|
||||
priv->ecdev_ = NULL;
|
||||
bcmgenet_mii_exit(dev);
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -4275,10 +4278,10 @@ static int bcmgenet_remove(struct platform_device *pdev)
|
|||
struct bcmgenet_priv *priv = dev_to_priv(&pdev->dev);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
if (priv->ecdev) {
|
||||
ecdev_close(priv->ecdev);
|
||||
ecdev_withdraw(priv->ecdev);
|
||||
priv->ecdev = NULL;
|
||||
if (get_ecdev(priv)) {
|
||||
ecdev_close(get_ecdev(priv));
|
||||
ecdev_withdraw(get_ecdev(priv));
|
||||
priv->ecdev_ = NULL;
|
||||
} else
|
||||
unregister_netdev(priv->dev);
|
||||
bcmgenet_mii_exit(priv->dev);
|
||||
|
|
@ -4300,8 +4303,8 @@ static int bcmgenet_resume_noirq(struct device *d)
|
|||
int ret;
|
||||
u32 reg;
|
||||
|
||||
if (priv->ecdev)
|
||||
ecdev_open(priv->ecdev);
|
||||
if (get_ecdev(priv))
|
||||
ecdev_open(get_ecdev(priv));
|
||||
else if (!netif_running(dev))
|
||||
return 0;
|
||||
|
||||
|
|
@ -4387,8 +4390,8 @@ static int bcmgenet_resume(struct device *d)
|
|||
|
||||
bcmgenet_netif_start(dev);
|
||||
|
||||
if (priv->ecdev)
|
||||
ecdev_open(priv->ecdev);
|
||||
if (get_ecdev(priv))
|
||||
ecdev_open(get_ecdev(priv));
|
||||
else
|
||||
netif_device_attach(dev);
|
||||
|
||||
|
|
@ -4406,8 +4409,8 @@ static int bcmgenet_suspend(struct device *d)
|
|||
struct net_device *dev = dev_get_drvdata(d);
|
||||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
|
||||
if (priv->ecdev) {
|
||||
ecdev_close(priv->ecdev);
|
||||
if (get_ecdev(priv)) {
|
||||
ecdev_close(get_ecdev(priv));
|
||||
} else {
|
||||
if (!netif_running(dev))
|
||||
return 0;
|
||||
|
|
@ -4432,8 +4435,8 @@ static int bcmgenet_suspend_noirq(struct device *d)
|
|||
struct bcmgenet_priv *priv = netdev_priv(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (priv->ecdev) {
|
||||
ecdev_close(priv->ecdev);
|
||||
if (get_ecdev(priv)) {
|
||||
ecdev_close(get_ecdev(priv));
|
||||
} else if (!netif_running(dev))
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -650,9 +650,19 @@ struct bcmgenet_priv {
|
|||
|
||||
struct ethtool_eee eee;
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct bcmgenet_priv *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
|
||||
#define GENET_IO_MACRO(name, offset) \
|
||||
static inline u32 bcmgenet_##name##_readl(struct bcmgenet_priv *priv, \
|
||||
u32 off) \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,245 @@
|
|||
// 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/version.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-5.10-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,245 @@
|
|||
// 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/version.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,237 @@
|
|||
// 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-5.14-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);
|
||||
|
||||
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,237 @@
|
|||
// 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);
|
||||
|
||||
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,637 @@
|
|||
// 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-5.10-ethercat.h"
|
||||
|
||||
/* 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 bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
u32 reg, cmd_bits = 0;
|
||||
bool status_changed = false;
|
||||
|
||||
if (priv->old_link != phydev->link) {
|
||||
status_changed = true;
|
||||
priv->old_link = phydev->link;
|
||||
}
|
||||
|
||||
if (phydev->link) {
|
||||
/* check speed/duplex/pause changes */
|
||||
if (priv->old_speed != phydev->speed) {
|
||||
status_changed = true;
|
||||
priv->old_speed = phydev->speed;
|
||||
}
|
||||
|
||||
if (priv->old_duplex != phydev->duplex) {
|
||||
status_changed = true;
|
||||
priv->old_duplex = phydev->duplex;
|
||||
}
|
||||
|
||||
if (priv->old_pause != phydev->pause) {
|
||||
status_changed = true;
|
||||
priv->old_pause = phydev->pause;
|
||||
}
|
||||
|
||||
/* done if nothing has changed */
|
||||
if (!status_changed)
|
||||
return;
|
||||
|
||||
/* speed */
|
||||
if (phydev->speed == SPEED_1000)
|
||||
cmd_bits = UMAC_SPEED_1000;
|
||||
else if (phydev->speed == SPEED_100)
|
||||
cmd_bits = UMAC_SPEED_100;
|
||||
else
|
||||
cmd_bits = UMAC_SPEED_10;
|
||||
cmd_bits <<= CMD_SPEED_SHIFT;
|
||||
|
||||
/* duplex */
|
||||
if (phydev->duplex != DUPLEX_FULL)
|
||||
cmd_bits |= CMD_HD_EN;
|
||||
|
||||
/* pause capability */
|
||||
if (!phydev->pause)
|
||||
cmd_bits |= CMD_RX_PAUSE_IGNORE | 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);
|
||||
} else {
|
||||
/* done if nothing has changed */
|
||||
if (!status_changed)
|
||||
return;
|
||||
|
||||
/* needed for MoCA fixed PHY to reflect correct link status */
|
||||
netif_carrier_off(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_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)) {
|
||||
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);
|
||||
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;
|
||||
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)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (!GENET_IS_V5(priv)) {
|
||||
/* Speed settings are set in bcmgenet_mii_setup() */
|
||||
reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL);
|
||||
reg |= LED_ACT_SOURCE_MAC;
|
||||
bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
|
||||
}
|
||||
|
||||
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";
|
||||
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;
|
||||
struct phy_device *phydev;
|
||||
u32 phy_flags = 0;
|
||||
int ret;
|
||||
|
||||
/* Communicate the integrated PHY revision */
|
||||
if (priv->internal_phy)
|
||||
phy_flags = priv->gphy_rev;
|
||||
|
||||
/* Initialize link state variables that bcmgenet_mii_setup() uses */
|
||||
priv->old_link = -1;
|
||||
priv->old_speed = -1;
|
||||
priv->old_duplex = -1;
|
||||
priv->old_pause = -1;
|
||||
|
||||
if (dn) {
|
||||
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
|
||||
phy_flags, priv->phy_interface);
|
||||
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,
|
||||
priv->phy_interface);
|
||||
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;
|
||||
}
|
||||
|
||||
linkmode_copy(phydev->advertising, phydev->supported);
|
||||
|
||||
/* 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_IGNORE_INTERRUPT;
|
||||
|
||||
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 (!phydev) {
|
||||
dev_err(kdev, "failed to register PHY device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} 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,635 @@
|
|||
// 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"
|
||||
|
||||
/* 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 bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
u32 reg, cmd_bits = 0;
|
||||
bool status_changed = false;
|
||||
|
||||
if (priv->old_link != phydev->link) {
|
||||
status_changed = true;
|
||||
priv->old_link = phydev->link;
|
||||
}
|
||||
|
||||
if (phydev->link) {
|
||||
/* check speed/duplex/pause changes */
|
||||
if (priv->old_speed != phydev->speed) {
|
||||
status_changed = true;
|
||||
priv->old_speed = phydev->speed;
|
||||
}
|
||||
|
||||
if (priv->old_duplex != phydev->duplex) {
|
||||
status_changed = true;
|
||||
priv->old_duplex = phydev->duplex;
|
||||
}
|
||||
|
||||
if (priv->old_pause != phydev->pause) {
|
||||
status_changed = true;
|
||||
priv->old_pause = phydev->pause;
|
||||
}
|
||||
|
||||
/* done if nothing has changed */
|
||||
if (!status_changed)
|
||||
return;
|
||||
|
||||
/* speed */
|
||||
if (phydev->speed == SPEED_1000)
|
||||
cmd_bits = UMAC_SPEED_1000;
|
||||
else if (phydev->speed == SPEED_100)
|
||||
cmd_bits = UMAC_SPEED_100;
|
||||
else
|
||||
cmd_bits = UMAC_SPEED_10;
|
||||
cmd_bits <<= CMD_SPEED_SHIFT;
|
||||
|
||||
/* duplex */
|
||||
if (phydev->duplex != DUPLEX_FULL)
|
||||
cmd_bits |= CMD_HD_EN;
|
||||
|
||||
/* pause capability */
|
||||
if (!phydev->pause)
|
||||
cmd_bits |= CMD_RX_PAUSE_IGNORE | 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);
|
||||
} else {
|
||||
/* done if nothing has changed */
|
||||
if (!status_changed)
|
||||
return;
|
||||
|
||||
/* needed for MoCA fixed PHY to reflect correct link status */
|
||||
netif_carrier_off(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_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)) {
|
||||
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);
|
||||
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;
|
||||
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)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (!GENET_IS_V5(priv)) {
|
||||
/* Speed settings are set in bcmgenet_mii_setup() */
|
||||
reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL);
|
||||
reg |= LED_ACT_SOURCE_MAC;
|
||||
bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
|
||||
}
|
||||
|
||||
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";
|
||||
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;
|
||||
struct phy_device *phydev;
|
||||
u32 phy_flags = 0;
|
||||
int ret;
|
||||
|
||||
/* Communicate the integrated PHY revision */
|
||||
if (priv->internal_phy)
|
||||
phy_flags = priv->gphy_rev;
|
||||
|
||||
/* Initialize link state variables that bcmgenet_mii_setup() uses */
|
||||
priv->old_link = -1;
|
||||
priv->old_speed = -1;
|
||||
priv->old_duplex = -1;
|
||||
priv->old_pause = -1;
|
||||
|
||||
if (dn) {
|
||||
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
|
||||
phy_flags, priv->phy_interface);
|
||||
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,
|
||||
priv->phy_interface);
|
||||
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;
|
||||
}
|
||||
|
||||
linkmode_copy(phydev->advertising, phydev->supported);
|
||||
|
||||
/* 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_IGNORE_INTERRUPT;
|
||||
|
||||
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 (!phydev) {
|
||||
dev_err(kdev, "failed to register PHY device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} 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,637 @@
|
|||
// 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-5.14-ethercat.h"
|
||||
|
||||
/* 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 bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
u32 reg, cmd_bits = 0;
|
||||
bool status_changed = false;
|
||||
|
||||
if (priv->old_link != phydev->link) {
|
||||
status_changed = true;
|
||||
priv->old_link = phydev->link;
|
||||
}
|
||||
|
||||
if (phydev->link) {
|
||||
/* check speed/duplex/pause changes */
|
||||
if (priv->old_speed != phydev->speed) {
|
||||
status_changed = true;
|
||||
priv->old_speed = phydev->speed;
|
||||
}
|
||||
|
||||
if (priv->old_duplex != phydev->duplex) {
|
||||
status_changed = true;
|
||||
priv->old_duplex = phydev->duplex;
|
||||
}
|
||||
|
||||
if (priv->old_pause != phydev->pause) {
|
||||
status_changed = true;
|
||||
priv->old_pause = phydev->pause;
|
||||
}
|
||||
|
||||
/* done if nothing has changed */
|
||||
if (!status_changed)
|
||||
return;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* pause capability */
|
||||
if (!phydev->pause)
|
||||
cmd_bits |= CMD_RX_PAUSE_IGNORE | 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);
|
||||
} else {
|
||||
/* done if nothing has changed */
|
||||
if (!status_changed)
|
||||
return;
|
||||
|
||||
/* needed for MoCA fixed PHY to reflect correct link status */
|
||||
netif_carrier_off(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_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)) {
|
||||
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);
|
||||
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;
|
||||
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)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (!GENET_IS_V5(priv)) {
|
||||
/* Speed settings are set in bcmgenet_mii_setup() */
|
||||
reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL);
|
||||
reg |= LED_ACT_SOURCE_MAC;
|
||||
bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
|
||||
}
|
||||
|
||||
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";
|
||||
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;
|
||||
struct phy_device *phydev;
|
||||
u32 phy_flags = 0;
|
||||
int ret;
|
||||
|
||||
/* Communicate the integrated PHY revision */
|
||||
if (priv->internal_phy)
|
||||
phy_flags = priv->gphy_rev;
|
||||
|
||||
/* Initialize link state variables that bcmgenet_mii_setup() uses */
|
||||
priv->old_link = -1;
|
||||
priv->old_speed = -1;
|
||||
priv->old_duplex = -1;
|
||||
priv->old_pause = -1;
|
||||
|
||||
if (dn) {
|
||||
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
|
||||
phy_flags, priv->phy_interface);
|
||||
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,
|
||||
priv->phy_interface);
|
||||
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;
|
||||
}
|
||||
|
||||
linkmode_copy(phydev->advertising, phydev->supported);
|
||||
|
||||
/* 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;
|
||||
|
||||
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 (!phydev) {
|
||||
dev_err(kdev, "failed to register PHY device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} 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,635 @@
|
|||
// 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"
|
||||
|
||||
/* 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 bcmgenet_priv *priv = netdev_priv(dev);
|
||||
struct phy_device *phydev = dev->phydev;
|
||||
u32 reg, cmd_bits = 0;
|
||||
bool status_changed = false;
|
||||
|
||||
if (priv->old_link != phydev->link) {
|
||||
status_changed = true;
|
||||
priv->old_link = phydev->link;
|
||||
}
|
||||
|
||||
if (phydev->link) {
|
||||
/* check speed/duplex/pause changes */
|
||||
if (priv->old_speed != phydev->speed) {
|
||||
status_changed = true;
|
||||
priv->old_speed = phydev->speed;
|
||||
}
|
||||
|
||||
if (priv->old_duplex != phydev->duplex) {
|
||||
status_changed = true;
|
||||
priv->old_duplex = phydev->duplex;
|
||||
}
|
||||
|
||||
if (priv->old_pause != phydev->pause) {
|
||||
status_changed = true;
|
||||
priv->old_pause = phydev->pause;
|
||||
}
|
||||
|
||||
/* done if nothing has changed */
|
||||
if (!status_changed)
|
||||
return;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* pause capability */
|
||||
if (!phydev->pause)
|
||||
cmd_bits |= CMD_RX_PAUSE_IGNORE | 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);
|
||||
} else {
|
||||
/* done if nothing has changed */
|
||||
if (!status_changed)
|
||||
return;
|
||||
|
||||
/* needed for MoCA fixed PHY to reflect correct link status */
|
||||
netif_carrier_off(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_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)) {
|
||||
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);
|
||||
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;
|
||||
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)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (!GENET_IS_V5(priv)) {
|
||||
/* Speed settings are set in bcmgenet_mii_setup() */
|
||||
reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL);
|
||||
reg |= LED_ACT_SOURCE_MAC;
|
||||
bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
|
||||
}
|
||||
|
||||
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";
|
||||
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;
|
||||
struct phy_device *phydev;
|
||||
u32 phy_flags = 0;
|
||||
int ret;
|
||||
|
||||
/* Communicate the integrated PHY revision */
|
||||
if (priv->internal_phy)
|
||||
phy_flags = priv->gphy_rev;
|
||||
|
||||
/* Initialize link state variables that bcmgenet_mii_setup() uses */
|
||||
priv->old_link = -1;
|
||||
priv->old_speed = -1;
|
||||
priv->old_duplex = -1;
|
||||
priv->old_pause = -1;
|
||||
|
||||
if (dn) {
|
||||
phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
|
||||
phy_flags, priv->phy_interface);
|
||||
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,
|
||||
priv->phy_interface);
|
||||
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;
|
||||
}
|
||||
|
||||
linkmode_copy(phydev->advertising, phydev->supported);
|
||||
|
||||
/* 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;
|
||||
|
||||
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 (!phydev) {
|
||||
dev_err(kdev, "failed to register PHY device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
|
|
@ -105,8 +105,8 @@ void bcmgenet_mii_setup(struct net_device *dev)
|
|||
|
||||
if (phydev->link)
|
||||
bcmgenet_mac_config(dev);
|
||||
if (priv->ecdev)
|
||||
ecdev_set_link(priv->ecdev, phydev->link);
|
||||
if (get_ecdev(priv))
|
||||
ecdev_set_link(get_ecdev(priv), phydev->link);
|
||||
phy_print_status(phydev);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ $# -ne 3 ]; then
|
||||
echo "Need 3 arguments: 1) kernel source dir, 2) previous version, 3) version to add"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
KERNELDIR=$1
|
||||
PREVER=$2
|
||||
KERNELVER=$3
|
||||
|
||||
GENETDIR=drivers/net/ethernet/broadcom/genet
|
||||
|
||||
FILES="bcmgenet.c bcmgenet.h bcmgenet_wol.c bcmmii.c"
|
||||
|
||||
for f in $FILES; do
|
||||
echo $f
|
||||
o=${f/\./-$KERNELVER-orig.}
|
||||
e=${f/\./-$KERNELVER-ethercat.}
|
||||
cp -v $KERNELDIR/$GENETDIR/$f $o
|
||||
chmod 644 $o
|
||||
cp -v $o $e
|
||||
op=${f/\./-$PREVER-orig.}
|
||||
ep=${f/\./-$PREVER-ethercat.}
|
||||
diff -up $op $ep | patch -p1 --no-backup-if-mismatch $e
|
||||
sed -i s/$PREVER-ethercat.h/$KERNELVER-ethercat.h/ $e
|
||||
git add $o $e
|
||||
echo -e "\t$e \\" >> Makefile.am
|
||||
echo -e "\t$o \\" >> Makefile.am
|
||||
done
|
||||
|
||||
cp $KERNELDIR/$GENETDIR/../unimac.h unimac-$KERNELVER-orig.h
|
||||
cp $KERNELDIR/$GENETDIR/../unimac.h unimac-$KERNELVER-ethercat.h
|
||||
git add unimac-$KERNELVER-orig.h unimac-$KERNELVER-ethercat.h
|
||||
echo -e "\tunimac-$KERNELVER-ethercat.h \\" >> Makefile.am
|
||||
echo -e "\tunimac-$KERNELVER-orig.h \\" >> Makefile.am
|
||||
|
||||
echo "Don't forget to update Makefile.am!"
|
||||
|
|
@ -37,6 +37,10 @@ REV := $(shell if test -s $(TOPDIR)/revision; then \
|
|||
ifeq (@ENABLE_IGB@,1)
|
||||
obj-m += ec_igb.o
|
||||
|
||||
ifeq (@ENABLE_DRIVER_RESOURCE_VERIFYING@,1)
|
||||
ccflags-y := -DEC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
endif
|
||||
|
||||
ec_igb-objs := \
|
||||
e1000_82575-@KERNEL_IGB@-ethercat.o \
|
||||
e1000_i210-@KERNEL_IGB@-ethercat.o \
|
||||
|
|
|
|||
|
|
@ -670,11 +670,20 @@ struct igb_adapter {
|
|||
struct vf_mac_filter *vf_mac_list;
|
||||
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
struct irq_work ec_watchdog_kicker;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct igb_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
/* flags controlling PTP/1588 function */
|
||||
#define IGB_PTP_ENABLED BIT(0)
|
||||
#define IGB_PTP_OVERFLOW_CHECK BIT(1)
|
||||
|
|
|
|||
|
|
@ -670,11 +670,20 @@ struct igb_adapter {
|
|||
struct vf_mac_filter *vf_mac_list;
|
||||
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
struct irq_work ec_watchdog_kicker;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct igb_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
/* flags controlling PTP/1588 function */
|
||||
#define IGB_PTP_ENABLED BIT(0)
|
||||
#define IGB_PTP_OVERFLOW_CHECK BIT(1)
|
||||
|
|
|
|||
|
|
@ -672,11 +672,20 @@ struct igb_adapter {
|
|||
spinlock_t vfs_lock;
|
||||
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
struct irq_work ec_watchdog_kicker;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct igb_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
/* flags controlling PTP/1588 function */
|
||||
#define IGB_PTP_ENABLED BIT(0)
|
||||
#define IGB_PTP_OVERFLOW_CHECK BIT(1)
|
||||
|
|
|
|||
|
|
@ -1047,10 +1047,7 @@ static void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx)
|
|||
if (q_vector->rx.ring)
|
||||
adapter->tx_ring[q_vector->rx.ring->queue_index] = NULL;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
netif_napi_del(&q_vector->napi);
|
||||
}
|
||||
|
||||
netif_napi_del(&q_vector->napi);
|
||||
}
|
||||
|
||||
static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
|
||||
|
|
@ -1221,11 +1218,9 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
|
|||
if (!q_vector)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
/* initialize NAPI */
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
}
|
||||
/* initialize NAPI */
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
|
||||
/* tie q_vector and adapter together */
|
||||
adapter->q_vector[v_idx] = q_vector;
|
||||
|
|
@ -6430,6 +6425,9 @@ static int igb_poll(struct napi_struct *napi, int budget)
|
|||
napi);
|
||||
bool clean_complete = true;
|
||||
|
||||
if (q_vector->adapter->ecdev)
|
||||
return -EBUSY;
|
||||
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED)
|
||||
igb_update_dca(q_vector);
|
||||
|
|
|
|||
|
|
@ -1037,10 +1037,7 @@ static void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx)
|
|||
if (q_vector->rx.ring)
|
||||
adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
netif_napi_del(&q_vector->napi);
|
||||
}
|
||||
|
||||
netif_napi_del(&q_vector->napi);
|
||||
}
|
||||
|
||||
static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
|
||||
|
|
@ -1219,11 +1216,9 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
|
|||
if (!q_vector)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
/* initialize NAPI */
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
}
|
||||
/* initialize NAPI */
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
|
||||
/* tie q_vector and adapter together */
|
||||
adapter->q_vector[v_idx] = q_vector;
|
||||
|
|
@ -7858,6 +7853,9 @@ static int igb_poll(struct napi_struct *napi, int budget)
|
|||
bool clean_complete = true;
|
||||
int work_done = 0;
|
||||
|
||||
if (q_vector->adapter->ecdev)
|
||||
return -EBUSY;
|
||||
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED)
|
||||
igb_update_dca(q_vector);
|
||||
|
|
|
|||
|
|
@ -1047,10 +1047,7 @@ static void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx)
|
|||
if (q_vector->rx.ring)
|
||||
adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
netif_napi_del(&q_vector->napi);
|
||||
}
|
||||
|
||||
netif_napi_del(&q_vector->napi);
|
||||
}
|
||||
|
||||
static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
|
||||
|
|
@ -1227,11 +1224,9 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
|
|||
if (!q_vector)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
/* initialize NAPI */
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
}
|
||||
/* initialize NAPI */
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
|
||||
/* tie q_vector and adapter together */
|
||||
adapter->q_vector[v_idx] = q_vector;
|
||||
|
|
@ -6506,6 +6501,9 @@ static int igb_poll(struct napi_struct *napi, int budget)
|
|||
bool clean_complete = true;
|
||||
int work_done = 0;
|
||||
|
||||
if (q_vector->adapter->ecdev)
|
||||
return -EBUSY;
|
||||
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED)
|
||||
igb_update_dca(q_vector);
|
||||
|
|
|
|||
|
|
@ -1036,9 +1036,7 @@ static void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx)
|
|||
if (q_vector->rx.ring)
|
||||
adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL;
|
||||
|
||||
if (!adapter->ecdev)
|
||||
netif_napi_del(&q_vector->napi);
|
||||
|
||||
netif_napi_del(&q_vector->napi);
|
||||
}
|
||||
|
||||
static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
|
||||
|
|
@ -1218,10 +1216,8 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
|
|||
return -ENOMEM;
|
||||
|
||||
/* initialize NAPI */
|
||||
if (!adapter->ecdev) {
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
}
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
|
||||
/* tie q_vector and adapter together */
|
||||
adapter->q_vector[v_idx] = q_vector;
|
||||
|
|
@ -6491,7 +6487,7 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
|
|||
first->bytecount = skb->len;
|
||||
first->gso_segs = 1;
|
||||
|
||||
if (unlikely(!adapter->ecdev &&
|
||||
if (unlikely(!adapter->ecdev &&
|
||||
skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
|
||||
|
||||
if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON &&
|
||||
|
|
@ -8133,6 +8129,10 @@ static int igb_poll(struct napi_struct *napi, int budget)
|
|||
bool clean_complete = true;
|
||||
int work_done = 0;
|
||||
|
||||
if (q_vector->adapter->ecdev) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED)
|
||||
igb_update_dca(q_vector);
|
||||
|
|
@ -8274,7 +8274,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
q_vector->tx.total_bytes += total_bytes;
|
||||
q_vector->tx.total_packets += total_packets;
|
||||
|
||||
if (!adapter->ecdev &&
|
||||
if (!adapter->ecdev &&
|
||||
test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) {
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
|
|
@ -8926,7 +8926,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
|||
total_packets++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* verify the packet layout is correct */
|
||||
if (igb_cleanup_headers(rx_ring, rx_desc, skb)) {
|
||||
skb = NULL;
|
||||
|
|
|
|||
|
|
@ -946,7 +946,7 @@ static int igb_request_msix(struct igb_adapter *adapter)
|
|||
struct net_device *netdev = adapter->netdev;
|
||||
int i, err = 0, vector = 0, free_vector = 0;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1047,8 +1047,7 @@ static void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx)
|
|||
if (q_vector->rx.ring)
|
||||
adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL;
|
||||
|
||||
if (!adapter->ecdev)
|
||||
netif_napi_del(&q_vector->napi);
|
||||
netif_napi_del(&q_vector->napi);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1229,10 +1228,8 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
|
|||
return -ENOMEM;
|
||||
|
||||
/* initialize NAPI */
|
||||
if (!adapter->ecdev) {
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
}
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
|
||||
/* tie q_vector and adapter together */
|
||||
adapter->q_vector[v_idx] = q_vector;
|
||||
|
|
@ -1450,7 +1447,7 @@ static int igb_request_irq(struct igb_adapter *adapter)
|
|||
|
||||
igb_assign_vector(adapter->q_vector[0], 0);
|
||||
|
||||
if (!adapter->ecdev && adapter->flags & IGB_FLAG_HAS_MSI) {
|
||||
if (!get_ecdev(adapter) && adapter->flags & IGB_FLAG_HAS_MSI) {
|
||||
err = request_irq(pdev->irq, igb_intr_msi, 0,
|
||||
netdev->name, adapter);
|
||||
if (!err)
|
||||
|
|
@ -1461,7 +1458,7 @@ static int igb_request_irq(struct igb_adapter *adapter)
|
|||
adapter->flags &= ~IGB_FLAG_HAS_MSI;
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
err = request_irq(pdev->irq, igb_intr, IRQF_SHARED,
|
||||
netdev->name, adapter);
|
||||
|
||||
|
|
@ -1476,7 +1473,7 @@ request_done:
|
|||
|
||||
static void igb_free_irq(struct igb_adapter *adapter)
|
||||
{
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return;
|
||||
if (adapter->flags & IGB_FLAG_HAS_MSIX) {
|
||||
int vector = 0, i;
|
||||
|
|
@ -1516,7 +1513,7 @@ static void igb_irq_disable(struct igb_adapter *adapter)
|
|||
wr32(E1000_IMC, ~0);
|
||||
wrfl();
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
/* skip synchronizing IRQs */
|
||||
return;
|
||||
}
|
||||
|
|
@ -1538,7 +1535,7 @@ static void igb_irq_enable(struct igb_adapter *adapter)
|
|||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return;
|
||||
|
||||
if (adapter->flags & IGB_FLAG_HAS_MSIX) {
|
||||
|
|
@ -2156,7 +2153,7 @@ int igb_up(struct igb_adapter *adapter)
|
|||
|
||||
clear_bit(__IGB_DOWN, &adapter->state);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
for (i = 0; i < adapter->num_q_vectors; i++)
|
||||
napi_enable(&(adapter->q_vector[i]->napi));
|
||||
}
|
||||
|
|
@ -2179,7 +2176,7 @@ int igb_up(struct igb_adapter *adapter)
|
|||
wr32(E1000_CTRL_EXT, reg_data);
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
/* start the watchdog. */
|
||||
|
|
@ -2213,7 +2210,7 @@ void igb_down(struct igb_adapter *adapter)
|
|||
|
||||
igb_nfc_filter_exit(adapter);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_carrier_off(netdev);
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
}
|
||||
|
|
@ -2231,7 +2228,7 @@ void igb_down(struct igb_adapter *adapter)
|
|||
adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE;
|
||||
|
||||
for (i = 0; i < adapter->num_q_vectors; i++) {
|
||||
if (!adapter->ecdev && adapter->q_vector[i]) {
|
||||
if (!get_ecdev(adapter) && adapter->q_vector[i]) {
|
||||
napi_synchronize(&adapter->q_vector[i]->napi);
|
||||
napi_disable(&adapter->q_vector[i]->napi);
|
||||
}
|
||||
|
|
@ -2454,7 +2451,7 @@ void igb_reset(struct igb_adapter *adapter)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!adapter->ecdev && !netif_running(adapter->netdev))
|
||||
if (!get_ecdev(adapter) && !netif_running(adapter->netdev))
|
||||
igb_power_down_link(adapter);
|
||||
|
||||
igb_update_mng_vlan(adapter);
|
||||
|
|
@ -2918,7 +2915,7 @@ static int igb_xdp_setup(struct net_device *dev, struct netdev_bpf *bpf)
|
|||
static int igb_xdp(struct net_device *dev, struct netdev_bpf *xdp)
|
||||
{
|
||||
struct igb_adapter *adapter = netdev_priv(dev);
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
|
||||
|
|
@ -2987,7 +2984,7 @@ static int igb_xdp_xmit(struct net_device *dev, int n,
|
|||
int nxmit = 0;
|
||||
int i;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
if (unlikely(test_bit(__IGB_DOWN, &adapter->state)))
|
||||
|
|
@ -3289,6 +3286,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
adapter = netdev_priv(netdev);
|
||||
adapter->netdev = netdev;
|
||||
adapter->pdev = pdev;
|
||||
adapter->ecdev_initialized = 0;
|
||||
hw = &adapter->hw;
|
||||
hw->back = adapter;
|
||||
adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
|
||||
|
|
@ -3438,7 +3436,11 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
dev_err(&pdev->dev, "NVM Read Error\n");
|
||||
}
|
||||
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5
|
||||
eth_hw_addr_set(netdev, hw->mac.addr);
|
||||
#else
|
||||
memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len);
|
||||
#endif
|
||||
|
||||
if (!is_valid_ether_addr(netdev->dev_addr)) {
|
||||
dev_err(&pdev->dev, "Invalid MAC Address\n");
|
||||
|
|
@ -3572,12 +3574,13 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
igb_get_hw_control(adapter);
|
||||
|
||||
|
||||
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
if (adapter->ecdev) {
|
||||
adapter->ecdev_ = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
adapter->ecdev_initialized = 1;
|
||||
if (get_ecdev(adapter)) {
|
||||
init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog);
|
||||
err = ecdev_open(adapter->ecdev);
|
||||
err = ecdev_open(get_ecdev(adapter));
|
||||
if (err) {
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
goto err_register;
|
||||
}
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
|
|
@ -3877,10 +3880,10 @@ static void igb_remove(struct pci_dev *pdev)
|
|||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_close(adapter->ecdev);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_close(get_ecdev(adapter));
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
}
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
|
|
@ -3917,7 +3920,7 @@ static void igb_remove(struct pci_dev *pdev)
|
|||
igb_disable_sriov(pdev);
|
||||
#endif
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
unregister_netdev(netdev);
|
||||
}
|
||||
|
||||
|
|
@ -4160,8 +4163,8 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
if (!resuming)
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
} else {
|
||||
netif_carrier_off(netdev);
|
||||
}
|
||||
|
|
@ -4189,7 +4192,7 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
if (err)
|
||||
goto err_req_irq;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* Notify the stack of the actual queue counts. */
|
||||
err = netif_set_real_num_tx_queues(adapter->netdev,
|
||||
adapter->num_tx_queues);
|
||||
|
|
@ -4205,7 +4208,7 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
/* From here on the code is the same as igb_up() */
|
||||
clear_bit(__IGB_DOWN, &adapter->state);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
for (i = 0; i < adapter->num_q_vectors; i++)
|
||||
napi_enable(&(adapter->q_vector[i]->napi));
|
||||
}
|
||||
|
|
@ -4224,14 +4227,14 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
wr32(E1000_CTRL_EXT, reg_data);
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_tx_start_all_queues(netdev);
|
||||
}
|
||||
|
||||
if (!resuming)
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
|
|
@ -4480,7 +4483,7 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
|
|||
rx_ring->next_to_clean = 0;
|
||||
rx_ring->next_to_use = 0;
|
||||
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
rx_ring->xdp_prog = adapter->xdp_prog;
|
||||
|
||||
/* XDP RX-queue info */
|
||||
|
|
@ -4791,7 +4794,7 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
|
|||
int reg_idx = ring->reg_idx;
|
||||
u32 rxdctl = 0;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq);
|
||||
WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
|
||||
MEM_TYPE_PAGE_SHARED, NULL));
|
||||
|
|
@ -4931,7 +4934,7 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring)
|
|||
|
||||
/* Free all the Tx ring sk_buffs */
|
||||
struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(tx_buffer->skb);
|
||||
}
|
||||
|
||||
|
|
@ -5108,7 +5111,11 @@ static int igb_set_mac(struct net_device *netdev, void *p)
|
|||
if (!is_valid_ether_addr(addr->sa_data))
|
||||
return -EADDRNOTAVAIL;
|
||||
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5
|
||||
eth_hw_addr_set(netdev, addr->sa_data);
|
||||
#else
|
||||
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
|
||||
#endif
|
||||
memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
|
||||
|
||||
/* set the correct pool for the new PF MAC address in entry 0 */
|
||||
|
|
@ -5541,13 +5548,13 @@ static void igb_watchdog_task(struct work_struct *work)
|
|||
u32 connsw;
|
||||
u16 phy_data, retry_count = 20;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
hw->mac.get_link_status = true;
|
||||
|
||||
link = igb_has_link(adapter);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, link);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), link);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -6198,7 +6205,7 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
|
|||
struct net_device *netdev = tx_ring->netdev;
|
||||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_stop_subqueue(netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
|
|
@ -6215,7 +6222,7 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
|
|||
return -EBUSY;
|
||||
|
||||
/* A reprieve! */
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_wake_subqueue(netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
|
|
@ -6371,7 +6378,7 @@ dma_error:
|
|||
DMA_TO_DEVICE);
|
||||
dma_unmap_len_set(tx_buffer, len, 0);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(tx_buffer->skb);
|
||||
tx_buffer->skb = NULL;
|
||||
}
|
||||
|
|
@ -6489,7 +6496,7 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
|
|||
first->bytecount = skb->len;
|
||||
first->gso_segs = 1;
|
||||
|
||||
if (unlikely(!adapter->ecdev &&
|
||||
if (unlikely(!get_ecdev(adapter) &&
|
||||
skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
|
||||
|
||||
if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON &&
|
||||
|
|
@ -6528,12 +6535,12 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
|
|||
return NETDEV_TX_OK;
|
||||
|
||||
out_drop:
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(first->skb);
|
||||
first->skb = NULL;
|
||||
}
|
||||
cleanup_tx_tstamp:
|
||||
if (unlikely(!adapter->ecdev && tx_flags & IGB_TX_FLAGS_TSTAMP)) {
|
||||
if (unlikely(!get_ecdev(adapter) && tx_flags & IGB_TX_FLAGS_TSTAMP)) {
|
||||
dev_kfree_skb_any(adapter->ptp_tx_skb);
|
||||
adapter->ptp_tx_skb = NULL;
|
||||
if (adapter->hw.mac.type == e1000_82576)
|
||||
|
|
@ -8131,6 +8138,10 @@ static int igb_poll(struct napi_struct *napi, int budget)
|
|||
bool clean_complete = true;
|
||||
int work_done = 0;
|
||||
|
||||
if (get_ecdev(q_vector->adapter)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED)
|
||||
igb_update_dca(q_vector);
|
||||
|
|
@ -8205,7 +8216,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
total_packets += tx_buffer->gso_segs;
|
||||
|
||||
/* free the skb */
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
if (tx_buffer->type == IGB_TYPE_SKB)
|
||||
napi_consume_skb(tx_buffer->skb, napi_budget);
|
||||
else
|
||||
|
|
@ -8259,7 +8270,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
budget--;
|
||||
} while (likely(budget));
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netdev_tx_completed_queue(txring_txq(tx_ring),
|
||||
total_packets, total_bytes);
|
||||
}
|
||||
|
|
@ -8272,7 +8283,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
q_vector->tx.total_bytes += total_bytes;
|
||||
q_vector->tx.total_packets += total_packets;
|
||||
|
||||
if (!adapter->ecdev &&
|
||||
if (!get_ecdev(adapter) &&
|
||||
test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) {
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
|
|
@ -8316,7 +8327,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
}
|
||||
|
||||
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
|
||||
if (unlikely(!adapter->ecdev && total_packets &&
|
||||
if (unlikely(!get_ecdev(adapter) && total_packets &&
|
||||
netif_carrier_ok(tx_ring->netdev) &&
|
||||
igb_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) {
|
||||
/* Make sure that anybody stopping the queue after this
|
||||
|
|
@ -8858,9 +8869,9 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
|||
rx_buffer = igb_get_rx_buffer(rx_ring, size, &rx_buf_pgcnt);
|
||||
pktbuf = page_address(rx_buffer->page) + rx_buffer->page_offset;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
|
||||
ecdev_receive(adapter->ecdev, pktbuf, size);
|
||||
ecdev_receive(get_ecdev(adapter), pktbuf, size);
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
igb_reuse_rx_page(rx_ring, rx_buffer);
|
||||
} else {
|
||||
|
|
@ -8923,7 +8934,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
|||
if (igb_is_non_eop(rx_ring, rx_desc))
|
||||
continue;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
total_packets++;
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -935,7 +935,7 @@ static int igb_request_msix(struct igb_adapter *adapter)
|
|||
struct net_device *netdev = adapter->netdev;
|
||||
int i, err = 0, vector = 0, free_vector = 0;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1036,8 +1036,7 @@ static void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx)
|
|||
if (q_vector->rx.ring)
|
||||
adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL;
|
||||
|
||||
if (!adapter->ecdev)
|
||||
netif_napi_del(&q_vector->napi);
|
||||
netif_napi_del(&q_vector->napi);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1218,10 +1217,8 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
|
|||
return -ENOMEM;
|
||||
|
||||
/* initialize NAPI */
|
||||
if (!adapter->ecdev) {
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
}
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi,
|
||||
igb_poll, 64);
|
||||
|
||||
/* tie q_vector and adapter together */
|
||||
adapter->q_vector[v_idx] = q_vector;
|
||||
|
|
@ -1439,7 +1436,7 @@ static int igb_request_irq(struct igb_adapter *adapter)
|
|||
|
||||
igb_assign_vector(adapter->q_vector[0], 0);
|
||||
|
||||
if (!adapter->ecdev && adapter->flags & IGB_FLAG_HAS_MSI) {
|
||||
if (!get_ecdev(adapter) && adapter->flags & IGB_FLAG_HAS_MSI) {
|
||||
err = request_irq(pdev->irq, igb_intr_msi, 0,
|
||||
netdev->name, adapter);
|
||||
if (!err)
|
||||
|
|
@ -1450,7 +1447,7 @@ static int igb_request_irq(struct igb_adapter *adapter)
|
|||
adapter->flags &= ~IGB_FLAG_HAS_MSI;
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
err = request_irq(pdev->irq, igb_intr, IRQF_SHARED,
|
||||
netdev->name, adapter);
|
||||
|
||||
|
|
@ -1465,7 +1462,7 @@ request_done:
|
|||
|
||||
static void igb_free_irq(struct igb_adapter *adapter)
|
||||
{
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return;
|
||||
if (adapter->flags & IGB_FLAG_HAS_MSIX) {
|
||||
int vector = 0, i;
|
||||
|
|
@ -1505,7 +1502,7 @@ static void igb_irq_disable(struct igb_adapter *adapter)
|
|||
wr32(E1000_IMC, ~0);
|
||||
wrfl();
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
/* skip synchronizing IRQs */
|
||||
return;
|
||||
}
|
||||
|
|
@ -1527,7 +1524,7 @@ static void igb_irq_enable(struct igb_adapter *adapter)
|
|||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return;
|
||||
|
||||
if (adapter->flags & IGB_FLAG_HAS_MSIX) {
|
||||
|
|
@ -2145,7 +2142,7 @@ int igb_up(struct igb_adapter *adapter)
|
|||
|
||||
clear_bit(__IGB_DOWN, &adapter->state);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
for (i = 0; i < adapter->num_q_vectors; i++)
|
||||
napi_enable(&(adapter->q_vector[i]->napi));
|
||||
}
|
||||
|
|
@ -2168,7 +2165,7 @@ int igb_up(struct igb_adapter *adapter)
|
|||
wr32(E1000_CTRL_EXT, reg_data);
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
/* start the watchdog. */
|
||||
|
|
@ -2202,7 +2199,7 @@ void igb_down(struct igb_adapter *adapter)
|
|||
|
||||
igb_nfc_filter_exit(adapter);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_carrier_off(netdev);
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
}
|
||||
|
|
@ -2220,7 +2217,7 @@ void igb_down(struct igb_adapter *adapter)
|
|||
adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE;
|
||||
|
||||
for (i = 0; i < adapter->num_q_vectors; i++) {
|
||||
if (!adapter->ecdev && adapter->q_vector[i]) {
|
||||
if (!get_ecdev(adapter) && adapter->q_vector[i]) {
|
||||
napi_synchronize(&adapter->q_vector[i]->napi);
|
||||
napi_disable(&adapter->q_vector[i]->napi);
|
||||
}
|
||||
|
|
@ -2443,7 +2440,7 @@ void igb_reset(struct igb_adapter *adapter)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!adapter->ecdev && !netif_running(adapter->netdev))
|
||||
if (!get_ecdev(adapter) && !netif_running(adapter->netdev))
|
||||
igb_power_down_link(adapter);
|
||||
|
||||
igb_update_mng_vlan(adapter);
|
||||
|
|
@ -2907,7 +2904,7 @@ static int igb_xdp_setup(struct net_device *dev, struct netdev_bpf *bpf)
|
|||
static int igb_xdp(struct net_device *dev, struct netdev_bpf *xdp)
|
||||
{
|
||||
struct igb_adapter *adapter = netdev_priv(dev);
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
|
||||
|
|
@ -2976,7 +2973,7 @@ static int igb_xdp_xmit(struct net_device *dev, int n,
|
|||
int nxmit = 0;
|
||||
int i;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
if (unlikely(test_bit(__IGB_DOWN, &adapter->state)))
|
||||
|
|
@ -3278,6 +3275,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
adapter = netdev_priv(netdev);
|
||||
adapter->netdev = netdev;
|
||||
adapter->pdev = pdev;
|
||||
adapter->ecdev_initialized = 0;
|
||||
hw = &adapter->hw;
|
||||
hw->back = adapter;
|
||||
adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
|
||||
|
|
@ -3561,12 +3559,13 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
igb_get_hw_control(adapter);
|
||||
|
||||
|
||||
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
if (adapter->ecdev) {
|
||||
adapter->ecdev_ = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
adapter->ecdev_initialized = 1;
|
||||
if (get_ecdev(adapter)) {
|
||||
init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog);
|
||||
err = ecdev_open(adapter->ecdev);
|
||||
err = ecdev_open(get_ecdev(adapter));
|
||||
if (err) {
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
goto err_register;
|
||||
}
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
|
|
@ -3866,10 +3865,10 @@ static void igb_remove(struct pci_dev *pdev)
|
|||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_close(adapter->ecdev);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_close(get_ecdev(adapter));
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
}
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
|
|
@ -3906,7 +3905,7 @@ static void igb_remove(struct pci_dev *pdev)
|
|||
igb_disable_sriov(pdev);
|
||||
#endif
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
unregister_netdev(netdev);
|
||||
}
|
||||
|
||||
|
|
@ -4149,8 +4148,8 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
if (!resuming)
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
} else {
|
||||
netif_carrier_off(netdev);
|
||||
}
|
||||
|
|
@ -4178,7 +4177,7 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
if (err)
|
||||
goto err_req_irq;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* Notify the stack of the actual queue counts. */
|
||||
err = netif_set_real_num_tx_queues(adapter->netdev,
|
||||
adapter->num_tx_queues);
|
||||
|
|
@ -4194,7 +4193,7 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
/* From here on the code is the same as igb_up() */
|
||||
clear_bit(__IGB_DOWN, &adapter->state);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
for (i = 0; i < adapter->num_q_vectors; i++)
|
||||
napi_enable(&(adapter->q_vector[i]->napi));
|
||||
}
|
||||
|
|
@ -4213,14 +4212,14 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
wr32(E1000_CTRL_EXT, reg_data);
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_tx_start_all_queues(netdev);
|
||||
}
|
||||
|
||||
if (!resuming)
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
|
|
@ -4450,7 +4449,7 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
|
|||
struct device *dev = rx_ring->dev;
|
||||
int size, res;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* XDP RX-queue info */
|
||||
if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq))
|
||||
xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
|
||||
|
|
@ -4482,7 +4481,7 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
|
|||
rx_ring->next_to_clean = 0;
|
||||
rx_ring->next_to_use = 0;
|
||||
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
rx_ring->xdp_prog = adapter->xdp_prog;
|
||||
|
||||
return 0;
|
||||
|
|
@ -4789,7 +4788,7 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
|
|||
int reg_idx = ring->reg_idx;
|
||||
u32 rxdctl = 0;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq);
|
||||
WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
|
||||
MEM_TYPE_PAGE_SHARED, NULL));
|
||||
|
|
@ -4929,7 +4928,7 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring)
|
|||
|
||||
/* Free all the Tx ring sk_buffs */
|
||||
struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(tx_buffer->skb);
|
||||
}
|
||||
|
||||
|
|
@ -5539,13 +5538,13 @@ static void igb_watchdog_task(struct work_struct *work)
|
|||
u32 connsw;
|
||||
u16 phy_data, retry_count = 20;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
hw->mac.get_link_status = true;
|
||||
|
||||
link = igb_has_link(adapter);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, link);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), link);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -6196,7 +6195,7 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
|
|||
struct net_device *netdev = tx_ring->netdev;
|
||||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_stop_subqueue(netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
|
|
@ -6213,7 +6212,7 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
|
|||
return -EBUSY;
|
||||
|
||||
/* A reprieve! */
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_wake_subqueue(netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
|
|
@ -6369,7 +6368,7 @@ dma_error:
|
|||
DMA_TO_DEVICE);
|
||||
dma_unmap_len_set(tx_buffer, len, 0);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(tx_buffer->skb);
|
||||
tx_buffer->skb = NULL;
|
||||
}
|
||||
|
|
@ -6487,7 +6486,7 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
|
|||
first->bytecount = skb->len;
|
||||
first->gso_segs = 1;
|
||||
|
||||
if (unlikely(!adapter->ecdev &&
|
||||
if (unlikely(!get_ecdev(adapter) &&
|
||||
skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
|
||||
|
||||
if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON &&
|
||||
|
|
@ -6526,12 +6525,12 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
|
|||
return NETDEV_TX_OK;
|
||||
|
||||
out_drop:
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(first->skb);
|
||||
first->skb = NULL;
|
||||
}
|
||||
cleanup_tx_tstamp:
|
||||
if (unlikely(!adapter->ecdev && tx_flags & IGB_TX_FLAGS_TSTAMP)) {
|
||||
if (unlikely(!get_ecdev(adapter) && tx_flags & IGB_TX_FLAGS_TSTAMP)) {
|
||||
dev_kfree_skb_any(adapter->ptp_tx_skb);
|
||||
adapter->ptp_tx_skb = NULL;
|
||||
if (adapter->hw.mac.type == e1000_82576)
|
||||
|
|
@ -8129,6 +8128,10 @@ static int igb_poll(struct napi_struct *napi, int budget)
|
|||
bool clean_complete = true;
|
||||
int work_done = 0;
|
||||
|
||||
if (get_ecdev(q_vector->adapter)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED)
|
||||
igb_update_dca(q_vector);
|
||||
|
|
@ -8203,7 +8206,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
total_packets += tx_buffer->gso_segs;
|
||||
|
||||
/* free the skb */
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
if (tx_buffer->type == IGB_TYPE_SKB)
|
||||
napi_consume_skb(tx_buffer->skb, napi_budget);
|
||||
else
|
||||
|
|
@ -8257,7 +8260,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
budget--;
|
||||
} while (likely(budget));
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netdev_tx_completed_queue(txring_txq(tx_ring),
|
||||
total_packets, total_bytes);
|
||||
}
|
||||
|
|
@ -8270,7 +8273,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
q_vector->tx.total_bytes += total_bytes;
|
||||
q_vector->tx.total_packets += total_packets;
|
||||
|
||||
if (!adapter->ecdev &&
|
||||
if (!get_ecdev(adapter) &&
|
||||
test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) {
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
|
|
@ -8314,7 +8317,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
}
|
||||
|
||||
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
|
||||
if (unlikely(!adapter->ecdev && total_packets &&
|
||||
if (unlikely(!get_ecdev(adapter) && total_packets &&
|
||||
netif_carrier_ok(tx_ring->netdev) &&
|
||||
igb_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) {
|
||||
/* Make sure that anybody stopping the queue after this
|
||||
|
|
@ -8852,9 +8855,9 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
|||
rx_buffer = igb_get_rx_buffer(rx_ring, size, &rx_buf_pgcnt);
|
||||
pktbuf = page_address(rx_buffer->page) + rx_buffer->page_offset;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
|
||||
ecdev_receive(adapter->ecdev, pktbuf, size);
|
||||
ecdev_receive(get_ecdev(adapter), pktbuf, size);
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
igb_reuse_rx_page(rx_ring, rx_buffer);
|
||||
} else {
|
||||
|
|
@ -8917,11 +8920,11 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
|||
if (igb_is_non_eop(rx_ring, rx_desc))
|
||||
continue;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
total_packets++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* verify the packet layout is correct */
|
||||
if (igb_cleanup_headers(rx_ring, rx_desc, skb)) {
|
||||
skb = NULL;
|
||||
|
|
|
|||
|
|
@ -933,7 +933,7 @@ static int igb_request_msix(struct igb_adapter *adapter)
|
|||
struct net_device *netdev = adapter->netdev;
|
||||
int i, err = 0, vector = 0, free_vector = 0;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1034,8 +1034,7 @@ static void igb_reset_q_vector(struct igb_adapter *adapter, int v_idx)
|
|||
if (q_vector->rx.ring)
|
||||
adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL;
|
||||
|
||||
if (!adapter->ecdev)
|
||||
netif_napi_del(&q_vector->napi);
|
||||
netif_napi_del(&q_vector->napi);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1220,9 +1219,7 @@ static int igb_alloc_q_vector(struct igb_adapter *adapter,
|
|||
return -ENOMEM;
|
||||
|
||||
/* initialize NAPI */
|
||||
if (!adapter->ecdev) {
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll);
|
||||
}
|
||||
netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll);
|
||||
|
||||
/* tie q_vector and adapter together */
|
||||
adapter->q_vector[v_idx] = q_vector;
|
||||
|
|
@ -1440,7 +1437,7 @@ static int igb_request_irq(struct igb_adapter *adapter)
|
|||
|
||||
igb_assign_vector(adapter->q_vector[0], 0);
|
||||
|
||||
if (!adapter->ecdev && adapter->flags & IGB_FLAG_HAS_MSI) {
|
||||
if (!get_ecdev(adapter) && adapter->flags & IGB_FLAG_HAS_MSI) {
|
||||
err = request_irq(pdev->irq, igb_intr_msi, 0,
|
||||
netdev->name, adapter);
|
||||
if (!err)
|
||||
|
|
@ -1451,7 +1448,7 @@ static int igb_request_irq(struct igb_adapter *adapter)
|
|||
adapter->flags &= ~IGB_FLAG_HAS_MSI;
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
err = request_irq(pdev->irq, igb_intr, IRQF_SHARED,
|
||||
netdev->name, adapter);
|
||||
|
||||
|
|
@ -1466,7 +1463,7 @@ request_done:
|
|||
|
||||
static void igb_free_irq(struct igb_adapter *adapter)
|
||||
{
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return;
|
||||
if (adapter->flags & IGB_FLAG_HAS_MSIX) {
|
||||
int vector = 0, i;
|
||||
|
|
@ -1506,7 +1503,7 @@ static void igb_irq_disable(struct igb_adapter *adapter)
|
|||
wr32(E1000_IMC, ~0);
|
||||
wrfl();
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
/* skip synchronizing IRQs */
|
||||
return;
|
||||
}
|
||||
|
|
@ -1528,7 +1525,7 @@ static void igb_irq_enable(struct igb_adapter *adapter)
|
|||
{
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return;
|
||||
|
||||
if (adapter->flags & IGB_FLAG_HAS_MSIX) {
|
||||
|
|
@ -2146,7 +2143,7 @@ int igb_up(struct igb_adapter *adapter)
|
|||
|
||||
clear_bit(__IGB_DOWN, &adapter->state);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
for (i = 0; i < adapter->num_q_vectors; i++)
|
||||
napi_enable(&(adapter->q_vector[i]->napi));
|
||||
}
|
||||
|
|
@ -2169,7 +2166,7 @@ int igb_up(struct igb_adapter *adapter)
|
|||
wr32(E1000_CTRL_EXT, reg_data);
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_tx_start_all_queues(adapter->netdev);
|
||||
|
||||
/* start the watchdog. */
|
||||
|
|
@ -2203,7 +2200,7 @@ void igb_down(struct igb_adapter *adapter)
|
|||
|
||||
igb_nfc_filter_exit(adapter);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_carrier_off(netdev);
|
||||
netif_tx_stop_all_queues(netdev);
|
||||
}
|
||||
|
|
@ -2221,7 +2218,7 @@ void igb_down(struct igb_adapter *adapter)
|
|||
adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE;
|
||||
|
||||
for (i = 0; i < adapter->num_q_vectors; i++) {
|
||||
if (!adapter->ecdev && adapter->q_vector[i]) {
|
||||
if (!get_ecdev(adapter) && adapter->q_vector[i]) {
|
||||
napi_synchronize(&adapter->q_vector[i]->napi);
|
||||
napi_disable(&adapter->q_vector[i]->napi);
|
||||
}
|
||||
|
|
@ -2469,7 +2466,7 @@ void igb_reset(struct igb_adapter *adapter)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!adapter->ecdev && !netif_running(adapter->netdev))
|
||||
if (!get_ecdev(adapter) && !netif_running(adapter->netdev))
|
||||
igb_power_down_link(adapter);
|
||||
|
||||
igb_update_mng_vlan(adapter);
|
||||
|
|
@ -2933,7 +2930,7 @@ static int igb_xdp_setup(struct net_device *dev, struct netdev_bpf *bpf)
|
|||
static int igb_xdp(struct net_device *dev, struct netdev_bpf *xdp)
|
||||
{
|
||||
struct igb_adapter *adapter = netdev_priv(dev);
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
|
||||
|
|
@ -3002,7 +2999,7 @@ static int igb_xdp_xmit(struct net_device *dev, int n,
|
|||
int nxmit = 0;
|
||||
int i;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
return -EBUSY;
|
||||
|
||||
if (unlikely(test_bit(__IGB_DOWN, &adapter->state)))
|
||||
|
|
@ -3298,6 +3295,7 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
adapter = netdev_priv(netdev);
|
||||
adapter->netdev = netdev;
|
||||
adapter->pdev = pdev;
|
||||
adapter->ecdev_initialized = 0;
|
||||
hw = &adapter->hw;
|
||||
hw->back = adapter;
|
||||
adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
|
||||
|
|
@ -3580,12 +3578,13 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
igb_get_hw_control(adapter);
|
||||
|
||||
|
||||
adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
if (adapter->ecdev) {
|
||||
adapter->ecdev_ = ecdev_offer(netdev, ec_poll, THIS_MODULE);
|
||||
adapter->ecdev_initialized = 1;
|
||||
if (get_ecdev(adapter)) {
|
||||
init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog);
|
||||
err = ecdev_open(adapter->ecdev);
|
||||
err = ecdev_open(get_ecdev(adapter));
|
||||
if (err) {
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
goto err_register;
|
||||
}
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
|
|
@ -3893,10 +3892,10 @@ static void igb_remove(struct pci_dev *pdev)
|
|||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_close(adapter->ecdev);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_close(get_ecdev(adapter));
|
||||
irq_work_sync(&adapter->ec_watchdog_kicker);
|
||||
ecdev_withdraw(adapter->ecdev);
|
||||
ecdev_withdraw(get_ecdev(adapter));
|
||||
}
|
||||
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
|
|
@ -3933,7 +3932,7 @@ static void igb_remove(struct pci_dev *pdev)
|
|||
igb_disable_sriov(pdev);
|
||||
#endif
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
unregister_netdev(netdev);
|
||||
}
|
||||
|
||||
|
|
@ -4179,8 +4178,8 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
if (!resuming)
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, 0);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), 0);
|
||||
} else {
|
||||
netif_carrier_off(netdev);
|
||||
}
|
||||
|
|
@ -4208,7 +4207,7 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
if (err)
|
||||
goto err_req_irq;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* Notify the stack of the actual queue counts. */
|
||||
err = netif_set_real_num_tx_queues(adapter->netdev,
|
||||
adapter->num_tx_queues);
|
||||
|
|
@ -4224,7 +4223,7 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
/* From here on the code is the same as igb_up() */
|
||||
clear_bit(__IGB_DOWN, &adapter->state);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
for (i = 0; i < adapter->num_q_vectors; i++)
|
||||
napi_enable(&(adapter->q_vector[i]->napi));
|
||||
}
|
||||
|
|
@ -4243,14 +4242,14 @@ static int __igb_open(struct net_device *netdev, bool resuming)
|
|||
wr32(E1000_CTRL_EXT, reg_data);
|
||||
}
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_tx_start_all_queues(netdev);
|
||||
}
|
||||
|
||||
if (!resuming)
|
||||
pm_runtime_put(&pdev->dev);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* start the watchdog. */
|
||||
hw->mac.get_link_status = 1;
|
||||
schedule_work(&adapter->watchdog_task);
|
||||
|
|
@ -4480,7 +4479,7 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
|
|||
struct device *dev = rx_ring->dev;
|
||||
int size, res;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
/* XDP RX-queue info */
|
||||
if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq))
|
||||
xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
|
||||
|
|
@ -4512,7 +4511,7 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
|
|||
rx_ring->next_to_clean = 0;
|
||||
rx_ring->next_to_use = 0;
|
||||
|
||||
if (!adapter->ecdev)
|
||||
if (!get_ecdev(adapter))
|
||||
rx_ring->xdp_prog = adapter->xdp_prog;
|
||||
|
||||
return 0;
|
||||
|
|
@ -4819,7 +4818,7 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
|
|||
int reg_idx = ring->reg_idx;
|
||||
u32 rxdctl = 0;
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq);
|
||||
WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
|
||||
MEM_TYPE_PAGE_SHARED, NULL));
|
||||
|
|
@ -4959,7 +4958,7 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring)
|
|||
|
||||
/* Free all the Tx ring sk_buffs or xdp frames */
|
||||
struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
if (tx_buffer->type == IGB_TYPE_SKB)
|
||||
dev_kfree_skb_any(tx_buffer->skb);
|
||||
else
|
||||
|
|
@ -5572,13 +5571,13 @@ static void igb_watchdog_task(struct work_struct *work)
|
|||
u32 connsw;
|
||||
u16 phy_data, retry_count = 20;
|
||||
|
||||
if (adapter->ecdev)
|
||||
if (get_ecdev(adapter))
|
||||
hw->mac.get_link_status = true;
|
||||
|
||||
link = igb_has_link(adapter);
|
||||
|
||||
if (adapter->ecdev) {
|
||||
ecdev_set_link(adapter->ecdev, link);
|
||||
if (get_ecdev(adapter)) {
|
||||
ecdev_set_link(get_ecdev(adapter), link);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -6230,7 +6229,7 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
|
|||
struct net_device *netdev = tx_ring->netdev;
|
||||
struct igb_adapter *adapter = netdev_priv(netdev);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_stop_subqueue(netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
|
|
@ -6247,7 +6246,7 @@ static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
|
|||
return -EBUSY;
|
||||
|
||||
/* A reprieve! */
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netif_wake_subqueue(netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
|
|
@ -6403,7 +6402,7 @@ dma_error:
|
|||
DMA_TO_DEVICE);
|
||||
dma_unmap_len_set(tx_buffer, len, 0);
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(tx_buffer->skb);
|
||||
tx_buffer->skb = NULL;
|
||||
}
|
||||
|
|
@ -6555,7 +6554,7 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
|
|||
first->bytecount = skb->len;
|
||||
first->gso_segs = 1;
|
||||
|
||||
if (unlikely(!adapter->ecdev &&
|
||||
if (unlikely(!get_ecdev(adapter) &&
|
||||
skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
|
||||
|
||||
if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON &&
|
||||
|
|
@ -6594,12 +6593,12 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
|
|||
return NETDEV_TX_OK;
|
||||
|
||||
out_drop:
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
dev_kfree_skb_any(first->skb);
|
||||
first->skb = NULL;
|
||||
}
|
||||
cleanup_tx_tstamp:
|
||||
if (unlikely(!adapter->ecdev && tx_flags & IGB_TX_FLAGS_TSTAMP)) {
|
||||
if (unlikely(!get_ecdev(adapter) && tx_flags & IGB_TX_FLAGS_TSTAMP)) {
|
||||
dev_kfree_skb_any(adapter->ptp_tx_skb);
|
||||
adapter->ptp_tx_skb = NULL;
|
||||
if (adapter->hw.mac.type == e1000_82576)
|
||||
|
|
@ -8282,6 +8281,10 @@ static int igb_poll(struct napi_struct *napi, int budget)
|
|||
bool clean_complete = true;
|
||||
int work_done = 0;
|
||||
|
||||
if (get_ecdev(q_vector->adapter)) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IGB_DCA
|
||||
if (q_vector->adapter->flags & IGB_FLAG_DCA_ENABLED)
|
||||
igb_update_dca(q_vector);
|
||||
|
|
@ -8356,7 +8359,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
total_packets += tx_buffer->gso_segs;
|
||||
|
||||
/* free the skb */
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
if (tx_buffer->type == IGB_TYPE_SKB)
|
||||
napi_consume_skb(tx_buffer->skb, napi_budget);
|
||||
else
|
||||
|
|
@ -8410,7 +8413,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
budget--;
|
||||
} while (likely(budget));
|
||||
|
||||
if (!adapter->ecdev) {
|
||||
if (!get_ecdev(adapter)) {
|
||||
netdev_tx_completed_queue(txring_txq(tx_ring),
|
||||
total_packets, total_bytes);
|
||||
}
|
||||
|
|
@ -8423,7 +8426,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
q_vector->tx.total_bytes += total_bytes;
|
||||
q_vector->tx.total_packets += total_packets;
|
||||
|
||||
if (!adapter->ecdev &&
|
||||
if (!get_ecdev(adapter) &&
|
||||
test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) {
|
||||
struct e1000_hw *hw = &adapter->hw;
|
||||
|
||||
|
|
@ -8467,7 +8470,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
|
|||
}
|
||||
|
||||
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
|
||||
if (unlikely(!adapter->ecdev && total_packets &&
|
||||
if (unlikely(!get_ecdev(adapter) && total_packets &&
|
||||
netif_carrier_ok(tx_ring->netdev) &&
|
||||
igb_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) {
|
||||
/* Make sure that anybody stopping the queue after this
|
||||
|
|
@ -9005,9 +9008,9 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
|||
rx_buffer = igb_get_rx_buffer(rx_ring, size, &rx_buf_pgcnt);
|
||||
pktbuf = page_address(rx_buffer->page) + rx_buffer->page_offset;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
|
||||
ecdev_receive(adapter->ecdev, pktbuf, size);
|
||||
ecdev_receive(get_ecdev(adapter), pktbuf, size);
|
||||
adapter->ec_watchdog_jiffies = jiffies;
|
||||
igb_reuse_rx_page(rx_ring, rx_buffer);
|
||||
} else {
|
||||
|
|
@ -9071,7 +9074,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
|
|||
if (igb_is_non_eop(rx_ring, rx_desc))
|
||||
continue;
|
||||
|
||||
if (adapter->ecdev) {
|
||||
if (get_ecdev(adapter)) {
|
||||
total_packets++;
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,10 @@ ifeq (@ENABLE_IGC@,1)
|
|||
igc_ethtool-@KERNEL_IGC@-ethercat.o \
|
||||
igc_nvm-@KERNEL_IGC@-ethercat.o
|
||||
|
||||
ifeq (@ENABLE_DRIVER_RESOURCE_VERIFYING@,1)
|
||||
ccflags-y := -DEC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
endif
|
||||
|
||||
CFLAGS_igc_main-@KERNEL_IGC@-ethercat.o = -DREV=$(REV)
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -21,99 +21,196 @@
|
|||
|
||||
include $(top_srcdir)/Makefile.kbuild
|
||||
|
||||
EXTRiA_DIST = igc-6.6-ethercat.h \
|
||||
igc_base-6.6-orig.h \
|
||||
igc_diag-6.6-orig.c \
|
||||
igc_ethtool-6.6-orig.c \
|
||||
igc_i225-6.6-orig.c \
|
||||
igc_mac-6.6-orig.c \
|
||||
igc_nvm-6.6-ethercat.h \
|
||||
igc_phy-6.6-orig.c \
|
||||
igc_regs-6.6-orig.h \
|
||||
igc_xdp-6.6-ethercat.c \
|
||||
igc-6.6-orig.h \
|
||||
igc_defines-6.6-ethercat.h \
|
||||
igc_diag-6.6-orig.h \
|
||||
igc_hw-6.6-ethercat.h \
|
||||
igc_i225-6.6-orig.h \
|
||||
igc_mac-6.6-orig.h \
|
||||
igc_nvm-6.6-orig.c \
|
||||
igc_phy-6.6-orig.h \
|
||||
igc_tsn-6.6-ethercat.c \
|
||||
igc_xdp-6.6-ethercat.h \
|
||||
igc_base-6.6-ethercat.c \
|
||||
igc_defines-6.6-orig.h \
|
||||
igc_dump-6.6-ethercat.c \
|
||||
igc_hw-6.6-orig.h \
|
||||
igc_main-6.6-ethercat.c \
|
||||
igc_nvm-6.6-orig.h \
|
||||
igc_ptp-6.6-ethercat.c \
|
||||
igc_tsn-6.6-ethercat.h \
|
||||
igc_xdp-6.6-orig.c\
|
||||
igc_base-6.6-ethercat.h \
|
||||
igc_diag-6.6-ethercat.c \
|
||||
igc_dump-6.6-orig.c \
|
||||
igc_i225-6.6-ethercat.c \
|
||||
igc_mac-6.6-ethercat.c \
|
||||
igc_main-6.6-orig.c \
|
||||
igc_phy-6.6-ethercat.c \
|
||||
igc_ptp-6.6-orig.c \
|
||||
igc_tsn-6.6-orig.c \
|
||||
igc_xdp-6.6-orig.h\
|
||||
igc_base-6.6-orig.c \
|
||||
igc_diag-6.6-ethercat.h \
|
||||
igc_ethtool-6.6-ethercat.c \
|
||||
igc_i225-6.6-ethercat.h \
|
||||
igc_mac-6.6-ethercat.h \
|
||||
igc_nvm-6.6-ethercat.c \
|
||||
igc_phy-6.6-ethercat.h \
|
||||
igc_regs-6.6-ethercat.h \
|
||||
igc_tsn-6.6-orig.h \
|
||||
EXTRA_DIST = \
|
||||
igc-5.14-ethercat.h \
|
||||
igc-5.14-orig.h \
|
||||
igc-6.1-ethercat.h \
|
||||
igc-6.1-orig.h \
|
||||
igc-6.4-ethercat.h \
|
||||
igc_base-6.4-orig.h \
|
||||
igc_diag-6.4-orig.c \
|
||||
igc_ethtool-6.4-orig.c \
|
||||
igc_i225-6.4-orig.c \
|
||||
igc_mac-6.4-orig.c \
|
||||
igc_nvm-6.4-ethercat.h \
|
||||
igc_phy-6.4-orig.c \
|
||||
igc_regs-6.4-orig.h \
|
||||
igc_xdp-6.4-ethercat.c \
|
||||
igc-6.4-orig.h \
|
||||
igc_defines-6.4-ethercat.h \
|
||||
igc_diag-6.4-orig.h \
|
||||
igc_hw-6.4-ethercat.h \
|
||||
igc_i225-6.4-orig.h \
|
||||
igc_mac-6.4-orig.h \
|
||||
igc_nvm-6.4-orig.c \
|
||||
igc_phy-6.4-orig.h \
|
||||
igc_tsn-6.4-ethercat.c \
|
||||
igc_xdp-6.4-ethercat.h \
|
||||
igc-6.6-ethercat.h \
|
||||
igc-6.6-orig.h \
|
||||
igc_base-5.14-ethercat.c \
|
||||
igc_base-5.14-ethercat.h \
|
||||
igc_base-5.14-orig.c \
|
||||
igc_base-5.14-orig.h \
|
||||
igc_base-6.1-ethercat.c \
|
||||
igc_base-6.1-ethercat.h \
|
||||
igc_base-6.1-orig.c \
|
||||
igc_base-6.1-orig.h \
|
||||
igc_base-6.4-ethercat.c \
|
||||
igc_defines-6.4-orig.h \
|
||||
igc_dump-6.4-ethercat.c \
|
||||
igc_hw-6.4-orig.h \
|
||||
igc_main-6.4-ethercat.c \
|
||||
igc_nvm-6.4-orig.h \
|
||||
igc_ptp-6.4-ethercat.c \
|
||||
igc_tsn-6.4-ethercat.h \
|
||||
igc_xdp-6.4-orig.c\
|
||||
igc_base-6.4-ethercat.h \
|
||||
igc_diag-6.4-ethercat.c \
|
||||
igc_dump-6.4-orig.c \
|
||||
igc_i225-6.4-ethercat.c \
|
||||
igc_mac-6.4-ethercat.c \
|
||||
igc_main-6.4-orig.c \
|
||||
igc_phy-6.4-ethercat.c \
|
||||
igc_ptp-6.4-orig.c \
|
||||
igc_tsn-6.4-orig.c \
|
||||
igc_xdp-6.4-orig.h\
|
||||
igc_base-6.4-orig.c \
|
||||
igc_base-6.4-orig.h \
|
||||
igc_base-6.6-ethercat.c \
|
||||
igc_base-6.6-ethercat.h \
|
||||
igc_base-6.6-orig.c \
|
||||
igc_base-6.6-orig.h \
|
||||
igc_defines-5.14-ethercat.h \
|
||||
igc_defines-5.14-orig.h \
|
||||
igc_defines-6.1-ethercat.h \
|
||||
igc_defines-6.1-orig.h \
|
||||
igc_defines-6.4-ethercat.h \
|
||||
igc_defines-6.4-orig.h \
|
||||
igc_defines-6.6-ethercat.h \
|
||||
igc_defines-6.6-orig.h \
|
||||
igc_diag-5.14-ethercat.c \
|
||||
igc_diag-5.14-ethercat.h \
|
||||
igc_diag-5.14-orig.c \
|
||||
igc_diag-5.14-orig.h \
|
||||
igc_diag-6.1-ethercat.c \
|
||||
igc_diag-6.1-ethercat.h \
|
||||
igc_diag-6.1-orig.c \
|
||||
igc_diag-6.1-orig.h \
|
||||
igc_diag-6.4-ethercat.c \
|
||||
igc_diag-6.4-ethercat.h \
|
||||
igc_diag-6.4-orig.c \
|
||||
igc_diag-6.4-orig.h \
|
||||
igc_diag-6.6-ethercat.c \
|
||||
igc_diag-6.6-ethercat.h \
|
||||
igc_diag-6.6-orig.c \
|
||||
igc_diag-6.6-orig.h \
|
||||
igc_dump-5.14-ethercat.c \
|
||||
igc_dump-5.14-orig.c \
|
||||
igc_dump-6.1-ethercat.c \
|
||||
igc_dump-6.1-orig.c \
|
||||
igc_dump-6.4-ethercat.c \
|
||||
igc_dump-6.4-orig.c \
|
||||
igc_dump-6.6-ethercat.c \
|
||||
igc_dump-6.6-orig.c \
|
||||
igc_ethtool-5.14-ethercat.c \
|
||||
igc_ethtool-5.14-orig.c \
|
||||
igc_ethtool-6.1-ethercat.c \
|
||||
igc_ethtool-6.1-orig.c \
|
||||
igc_ethtool-6.4-ethercat.c \
|
||||
igc_ethtool-6.4-orig.c \
|
||||
igc_ethtool-6.6-ethercat.c \
|
||||
igc_ethtool-6.6-orig.c \
|
||||
igc_hw-5.14-ethercat.h \
|
||||
igc_hw-5.14-orig.h \
|
||||
igc_hw-6.1-ethercat.h \
|
||||
igc_hw-6.1-orig.h \
|
||||
igc_hw-6.4-ethercat.h \
|
||||
igc_hw-6.4-orig.h \
|
||||
igc_hw-6.6-ethercat.h \
|
||||
igc_hw-6.6-orig.h \
|
||||
igc_i225-5.14-ethercat.c \
|
||||
igc_i225-5.14-ethercat.h \
|
||||
igc_i225-5.14-orig.c \
|
||||
igc_i225-5.14-orig.h \
|
||||
igc_i225-6.1-ethercat.c \
|
||||
igc_i225-6.1-ethercat.h \
|
||||
igc_i225-6.1-orig.c \
|
||||
igc_i225-6.1-orig.h \
|
||||
igc_i225-6.4-ethercat.c \
|
||||
igc_i225-6.4-ethercat.h \
|
||||
igc_i225-6.4-orig.c \
|
||||
igc_i225-6.4-orig.h \
|
||||
igc_i225-6.6-ethercat.c \
|
||||
igc_i225-6.6-ethercat.h \
|
||||
igc_i225-6.6-orig.c \
|
||||
igc_i225-6.6-orig.h \
|
||||
igc_mac-5.14-ethercat.c \
|
||||
igc_mac-5.14-ethercat.h \
|
||||
igc_mac-5.14-orig.c \
|
||||
igc_mac-5.14-orig.h \
|
||||
igc_mac-6.1-ethercat.c \
|
||||
igc_mac-6.1-ethercat.h \
|
||||
igc_mac-6.1-orig.c \
|
||||
igc_mac-6.1-orig.h \
|
||||
igc_mac-6.4-ethercat.c \
|
||||
igc_mac-6.4-ethercat.h \
|
||||
igc_mac-6.4-orig.c \
|
||||
igc_mac-6.4-orig.h \
|
||||
igc_mac-6.6-ethercat.c \
|
||||
igc_mac-6.6-ethercat.h \
|
||||
igc_mac-6.6-orig.c \
|
||||
igc_mac-6.6-orig.h \
|
||||
igc_main-5.14-ethercat.c \
|
||||
igc_main-5.14-orig.c \
|
||||
igc_main-6.1-ethercat.c \
|
||||
igc_main-6.1-orig.c \
|
||||
igc_main-6.4-ethercat.c \
|
||||
igc_main-6.4-orig.c \
|
||||
igc_main-6.6-ethercat.c \
|
||||
igc_main-6.6-orig.c \
|
||||
igc_nvm-5.14-ethercat.c \
|
||||
igc_nvm-5.14-ethercat.h \
|
||||
igc_nvm-5.14-orig.c \
|
||||
igc_nvm-5.14-orig.h \
|
||||
igc_nvm-6.1-ethercat.c \
|
||||
igc_nvm-6.1-ethercat.h \
|
||||
igc_nvm-6.1-orig.c \
|
||||
igc_nvm-6.1-orig.h \
|
||||
igc_nvm-6.4-ethercat.c \
|
||||
igc_nvm-6.4-ethercat.h \
|
||||
igc_nvm-6.4-orig.c \
|
||||
igc_nvm-6.4-orig.h \
|
||||
igc_nvm-6.6-ethercat.c \
|
||||
igc_nvm-6.6-ethercat.h \
|
||||
igc_nvm-6.6-orig.c \
|
||||
igc_nvm-6.6-orig.h \
|
||||
igc_phy-5.14-ethercat.c \
|
||||
igc_phy-5.14-ethercat.h \
|
||||
igc_phy-5.14-orig.c \
|
||||
igc_phy-5.14-orig.h \
|
||||
igc_phy-6.1-ethercat.c \
|
||||
igc_phy-6.1-ethercat.h \
|
||||
igc_phy-6.1-orig.c \
|
||||
igc_phy-6.1-orig.h \
|
||||
igc_phy-6.4-ethercat.c \
|
||||
igc_phy-6.4-ethercat.h \
|
||||
igc_phy-6.4-orig.c \
|
||||
igc_phy-6.4-orig.h \
|
||||
igc_phy-6.6-ethercat.c \
|
||||
igc_phy-6.6-ethercat.h \
|
||||
igc_phy-6.6-orig.c \
|
||||
igc_phy-6.6-orig.h \
|
||||
igc_ptp-5.14-ethercat.c \
|
||||
igc_ptp-5.14-orig.c \
|
||||
igc_ptp-6.1-ethercat.c \
|
||||
igc_ptp-6.1-orig.c \
|
||||
igc_ptp-6.4-ethercat.c \
|
||||
igc_ptp-6.4-orig.c \
|
||||
igc_ptp-6.6-ethercat.c \
|
||||
igc_ptp-6.6-orig.c \
|
||||
igc_regs-5.14-ethercat.h \
|
||||
igc_regs-5.14-orig.h \
|
||||
igc_regs-6.1-ethercat.h \
|
||||
igc_regs-6.1-orig.h \
|
||||
igc_regs-6.4-ethercat.h \
|
||||
igc_tsn-6.4-orig.h
|
||||
igc_regs-6.4-orig.h \
|
||||
igc_regs-6.6-ethercat.h \
|
||||
igc_regs-6.6-orig.h \
|
||||
igc_tsn-5.14-ethercat.c \
|
||||
igc_tsn-5.14-ethercat.h \
|
||||
igc_tsn-5.14-orig.c \
|
||||
igc_tsn-5.14-orig.h \
|
||||
igc_tsn-6.1-ethercat.c \
|
||||
igc_tsn-6.1-ethercat.h \
|
||||
igc_tsn-6.1-orig.c \
|
||||
igc_tsn-6.1-orig.h \
|
||||
igc_tsn-6.4-ethercat.c \
|
||||
igc_tsn-6.4-ethercat.h \
|
||||
igc_tsn-6.4-orig.c \
|
||||
igc_tsn-6.4-orig.h \
|
||||
igc_tsn-6.6-ethercat.c \
|
||||
igc_tsn-6.6-ethercat.h \
|
||||
igc_tsn-6.6-orig.c \
|
||||
igc_tsn-6.6-orig.h \
|
||||
igc_xdp-5.14-ethercat.c \
|
||||
igc_xdp-5.14-ethercat.h \
|
||||
igc_xdp-5.14-orig.c \
|
||||
igc_xdp-5.14-orig.h \
|
||||
igc_xdp-6.1-ethercat.c \
|
||||
igc_xdp-6.1-ethercat.h \
|
||||
igc_xdp-6.1-orig.c \
|
||||
igc_xdp-6.1-orig.h \
|
||||
igc_xdp-6.4-ethercat.c \
|
||||
igc_xdp-6.4-ethercat.h \
|
||||
igc_xdp-6.4-orig.c \
|
||||
igc_xdp-6.4-orig.h \
|
||||
igc_xdp-6.6-ethercat.c \
|
||||
igc_xdp-6.6-ethercat.h \
|
||||
igc_xdp-6.6-orig.c \
|
||||
igc_xdp-6.6-orig.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,627 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_H_
|
||||
#define _IGC_H_
|
||||
#include "../ecdev.h"
|
||||
|
||||
#include <linux/irq_work.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/sctp.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/timecounter.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
|
||||
#include "igc_hw-5.14-ethercat.h"
|
||||
|
||||
void igc_ethtool_set_ops(struct net_device *);
|
||||
|
||||
/* Transmit and receive queues */
|
||||
#define IGC_MAX_RX_QUEUES 4
|
||||
#define IGC_MAX_TX_QUEUES 4
|
||||
|
||||
#define MAX_Q_VECTORS 8
|
||||
#define MAX_STD_JUMBO_FRAME_SIZE 9216
|
||||
|
||||
#define MAX_ETYPE_FILTER 8
|
||||
#define IGC_RETA_SIZE 128
|
||||
|
||||
/* SDP support */
|
||||
#define IGC_N_EXTTS 2
|
||||
#define IGC_N_PEROUT 2
|
||||
#define IGC_N_SDP 4
|
||||
|
||||
enum igc_mac_filter_type {
|
||||
IGC_MAC_FILTER_TYPE_DST = 0,
|
||||
IGC_MAC_FILTER_TYPE_SRC
|
||||
};
|
||||
|
||||
struct igc_tx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 restart_queue;
|
||||
u64 restart_queue2;
|
||||
};
|
||||
|
||||
struct igc_rx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 drops;
|
||||
u64 csum_err;
|
||||
u64 alloc_failed;
|
||||
};
|
||||
|
||||
struct igc_rx_packet_stats {
|
||||
u64 ipv4_packets; /* IPv4 headers processed */
|
||||
u64 ipv4e_packets; /* IPv4E headers with extensions processed */
|
||||
u64 ipv6_packets; /* IPv6 headers processed */
|
||||
u64 ipv6e_packets; /* IPv6E headers with extensions processed */
|
||||
u64 tcp_packets; /* TCP headers processed */
|
||||
u64 udp_packets; /* UDP headers processed */
|
||||
u64 sctp_packets; /* SCTP headers processed */
|
||||
u64 nfs_packets; /* NFS headers processe */
|
||||
u64 other_packets;
|
||||
};
|
||||
|
||||
struct igc_ring_container {
|
||||
struct igc_ring *ring; /* pointer to linked list of rings */
|
||||
unsigned int total_bytes; /* total bytes processed this int */
|
||||
unsigned int total_packets; /* total packets processed this int */
|
||||
u16 work_limit; /* total work allowed per interrupt */
|
||||
u8 count; /* total number of rings in vector */
|
||||
u8 itr; /* current ITR setting for ring */
|
||||
};
|
||||
|
||||
struct igc_ring {
|
||||
struct igc_q_vector *q_vector; /* backlink to q_vector */
|
||||
struct net_device *netdev; /* back pointer to net_device */
|
||||
struct device *dev; /* device for dma mapping */
|
||||
union { /* array of buffer info structs */
|
||||
struct igc_tx_buffer *tx_buffer_info;
|
||||
struct igc_rx_buffer *rx_buffer_info;
|
||||
};
|
||||
void *desc; /* descriptor ring memory */
|
||||
unsigned long flags; /* ring specific flags */
|
||||
void __iomem *tail; /* pointer to ring tail register */
|
||||
dma_addr_t dma; /* phys address of the ring */
|
||||
unsigned int size; /* length of desc. ring in bytes */
|
||||
|
||||
u16 count; /* number of desc. in the ring */
|
||||
u8 queue_index; /* logical index of the ring*/
|
||||
u8 reg_idx; /* physical index of the ring */
|
||||
bool launchtime_enable; /* true if LaunchTime is enabled */
|
||||
|
||||
u32 start_time;
|
||||
u32 end_time;
|
||||
|
||||
/* everything past this point are written often */
|
||||
u16 next_to_clean;
|
||||
u16 next_to_use;
|
||||
u16 next_to_alloc;
|
||||
|
||||
union {
|
||||
/* TX */
|
||||
struct {
|
||||
struct igc_tx_queue_stats tx_stats;
|
||||
struct u64_stats_sync tx_syncp;
|
||||
struct u64_stats_sync tx_syncp2;
|
||||
};
|
||||
/* RX */
|
||||
struct {
|
||||
struct igc_rx_queue_stats rx_stats;
|
||||
struct igc_rx_packet_stats pkt_stats;
|
||||
struct u64_stats_sync rx_syncp;
|
||||
struct sk_buff *skb;
|
||||
};
|
||||
};
|
||||
|
||||
struct xdp_rxq_info xdp_rxq;
|
||||
struct xsk_buff_pool *xsk_pool;
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
/* Board specific private data structure */
|
||||
struct igc_adapter {
|
||||
struct net_device *netdev;
|
||||
|
||||
struct ethtool_eee eee;
|
||||
u16 eee_advert;
|
||||
|
||||
unsigned long state;
|
||||
unsigned int flags;
|
||||
unsigned int num_q_vectors;
|
||||
|
||||
struct msix_entry *msix_entries;
|
||||
|
||||
/* TX */
|
||||
u16 tx_work_limit;
|
||||
u32 tx_timeout_count;
|
||||
int num_tx_queues;
|
||||
struct igc_ring *tx_ring[IGC_MAX_TX_QUEUES];
|
||||
|
||||
/* RX */
|
||||
int num_rx_queues;
|
||||
struct igc_ring *rx_ring[IGC_MAX_RX_QUEUES];
|
||||
|
||||
struct timer_list watchdog_timer;
|
||||
struct timer_list dma_err_timer;
|
||||
struct timer_list phy_info_timer;
|
||||
|
||||
u32 wol;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
|
||||
u8 port_num;
|
||||
|
||||
u8 __iomem *io_addr;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 rx_itr_setting;
|
||||
u32 tx_itr_setting;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct work_struct watchdog_task;
|
||||
struct work_struct dma_err_task;
|
||||
bool fc_autoneg;
|
||||
|
||||
u8 tx_timeout_factor;
|
||||
|
||||
int msg_enable;
|
||||
u32 max_frame_size;
|
||||
u32 min_frame_size;
|
||||
|
||||
ktime_t base_time;
|
||||
ktime_t cycle_time;
|
||||
|
||||
/* OS defined structs */
|
||||
struct pci_dev *pdev;
|
||||
/* lock for statistics */
|
||||
spinlock_t stats64_lock;
|
||||
struct rtnl_link_stats64 stats64;
|
||||
|
||||
/* structs defined in igc_hw.h */
|
||||
struct igc_hw hw;
|
||||
struct igc_hw_stats stats;
|
||||
|
||||
struct igc_q_vector *q_vector[MAX_Q_VECTORS];
|
||||
u32 eims_enable_mask;
|
||||
u32 eims_other;
|
||||
|
||||
u16 tx_ring_count;
|
||||
u16 rx_ring_count;
|
||||
|
||||
u32 tx_hwtstamp_timeouts;
|
||||
u32 tx_hwtstamp_skipped;
|
||||
u32 rx_hwtstamp_cleared;
|
||||
|
||||
u32 rss_queues;
|
||||
u32 rss_indir_tbl_init;
|
||||
|
||||
/* Any access to elements in nfc_rule_list is protected by the
|
||||
* nfc_rule_lock.
|
||||
*/
|
||||
struct mutex nfc_rule_lock;
|
||||
struct list_head nfc_rule_list;
|
||||
unsigned int nfc_rule_count;
|
||||
|
||||
u8 rss_indir_tbl[IGC_RETA_SIZE];
|
||||
|
||||
unsigned long link_check_timeout;
|
||||
struct igc_info ei;
|
||||
|
||||
u32 test_icr;
|
||||
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct ptp_clock_info ptp_caps;
|
||||
struct work_struct ptp_tx_work;
|
||||
struct sk_buff *ptp_tx_skb;
|
||||
struct hwtstamp_config tstamp_config;
|
||||
unsigned long ptp_tx_start;
|
||||
unsigned int ptp_flags;
|
||||
/* System time value lock */
|
||||
spinlock_t tmreg_lock;
|
||||
struct cyclecounter cc;
|
||||
struct timecounter tc;
|
||||
struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */
|
||||
ktime_t ptp_reset_start; /* Reset time in clock mono */
|
||||
|
||||
char fw_version[32];
|
||||
|
||||
struct bpf_prog *xdp_prog;
|
||||
|
||||
bool pps_sys_wrap_on;
|
||||
|
||||
struct ptp_pin_desc sdp_config[IGC_N_SDP];
|
||||
struct {
|
||||
struct timespec64 start;
|
||||
struct timespec64 period;
|
||||
} perout[IGC_N_PEROUT];
|
||||
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
struct irq_work ec_watchdog_kicker;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct igc_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
void igc_up(struct igc_adapter *adapter);
|
||||
void igc_down(struct igc_adapter *adapter);
|
||||
int igc_open(struct net_device *netdev);
|
||||
int igc_close(struct net_device *netdev);
|
||||
int igc_setup_tx_resources(struct igc_ring *ring);
|
||||
int igc_setup_rx_resources(struct igc_ring *ring);
|
||||
void igc_free_tx_resources(struct igc_ring *ring);
|
||||
void igc_free_rx_resources(struct igc_ring *ring);
|
||||
unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter);
|
||||
void igc_set_flag_queue_pairs(struct igc_adapter *adapter,
|
||||
const u32 max_rss_queues);
|
||||
int igc_reinit_queues(struct igc_adapter *adapter);
|
||||
void igc_write_rss_indir_tbl(struct igc_adapter *adapter);
|
||||
bool igc_has_link(struct igc_adapter *adapter);
|
||||
void igc_reset(struct igc_adapter *adapter);
|
||||
int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx);
|
||||
void igc_update_stats(struct igc_adapter *adapter);
|
||||
void igc_disable_rx_ring(struct igc_ring *ring);
|
||||
void igc_enable_rx_ring(struct igc_ring *ring);
|
||||
void igc_disable_tx_ring(struct igc_ring *ring);
|
||||
void igc_enable_tx_ring(struct igc_ring *ring);
|
||||
int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags);
|
||||
|
||||
/* igc_dump declarations */
|
||||
void igc_rings_dump(struct igc_adapter *adapter);
|
||||
void igc_regs_dump(struct igc_adapter *adapter);
|
||||
|
||||
extern char igc_driver_name[];
|
||||
|
||||
#define IGC_REGS_LEN 740
|
||||
|
||||
/* flags controlling PTP/1588 function */
|
||||
#define IGC_PTP_ENABLED BIT(0)
|
||||
|
||||
/* Flags definitions */
|
||||
#define IGC_FLAG_HAS_MSI BIT(0)
|
||||
#define IGC_FLAG_QUEUE_PAIRS BIT(3)
|
||||
#define IGC_FLAG_DMAC BIT(4)
|
||||
#define IGC_FLAG_PTP BIT(8)
|
||||
#define IGC_FLAG_WOL_SUPPORTED BIT(8)
|
||||
#define IGC_FLAG_NEED_LINK_UPDATE BIT(9)
|
||||
#define IGC_FLAG_MEDIA_RESET BIT(10)
|
||||
#define IGC_FLAG_MAS_ENABLE BIT(12)
|
||||
#define IGC_FLAG_HAS_MSIX BIT(13)
|
||||
#define IGC_FLAG_EEE BIT(14)
|
||||
#define IGC_FLAG_VLAN_PROMISC BIT(15)
|
||||
#define IGC_FLAG_RX_LEGACY BIT(16)
|
||||
#define IGC_FLAG_TSN_QBV_ENABLED BIT(17)
|
||||
|
||||
#define IGC_FLAG_RSS_FIELD_IPV4_UDP BIT(6)
|
||||
#define IGC_FLAG_RSS_FIELD_IPV6_UDP BIT(7)
|
||||
|
||||
#define IGC_MRQC_ENABLE_RSS_MQ 0x00000002
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
|
||||
|
||||
/* Interrupt defines */
|
||||
#define IGC_START_ITR 648 /* ~6000 ints/sec */
|
||||
#define IGC_4K_ITR 980
|
||||
#define IGC_20K_ITR 196
|
||||
#define IGC_70K_ITR 56
|
||||
|
||||
#define IGC_DEFAULT_ITR 3 /* dynamic */
|
||||
#define IGC_MAX_ITR_USECS 10000
|
||||
#define IGC_MIN_ITR_USECS 10
|
||||
#define NON_Q_VECTORS 1
|
||||
#define MAX_MSIX_ENTRIES 10
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define IGC_DEFAULT_TXD 256
|
||||
#define IGC_DEFAULT_TX_WORK 128
|
||||
#define IGC_MIN_TXD 80
|
||||
#define IGC_MAX_TXD 4096
|
||||
|
||||
#define IGC_DEFAULT_RXD 256
|
||||
#define IGC_MIN_RXD 80
|
||||
#define IGC_MAX_RXD 4096
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define IGC_RXBUFFER_256 256
|
||||
#define IGC_RXBUFFER_2048 2048
|
||||
#define IGC_RXBUFFER_3072 3072
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define IGC_RX_HDR_LEN IGC_RXBUFFER_256
|
||||
|
||||
/* Transmit and receive latency (for PTP timestamps) */
|
||||
#define IGC_I225_TX_LATENCY_10 240
|
||||
#define IGC_I225_TX_LATENCY_100 58
|
||||
#define IGC_I225_TX_LATENCY_1000 80
|
||||
#define IGC_I225_TX_LATENCY_2500 1325
|
||||
#define IGC_I225_RX_LATENCY_10 6450
|
||||
#define IGC_I225_RX_LATENCY_100 185
|
||||
#define IGC_I225_RX_LATENCY_1000 300
|
||||
#define IGC_I225_RX_LATENCY_2500 1485
|
||||
|
||||
/* RX and TX descriptor control thresholds.
|
||||
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
|
||||
* descriptors available in its onboard memory.
|
||||
* Setting this to 0 disables RX descriptor prefetch.
|
||||
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
|
||||
* available in host memory.
|
||||
* If PTHRESH is 0, this should also be 0.
|
||||
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
|
||||
* descriptors until either it has this many to write back, or the
|
||||
* ITR timer expires.
|
||||
*/
|
||||
#define IGC_RX_PTHRESH 8
|
||||
#define IGC_RX_HTHRESH 8
|
||||
#define IGC_TX_PTHRESH 8
|
||||
#define IGC_TX_HTHRESH 1
|
||||
#define IGC_RX_WTHRESH 4
|
||||
#define IGC_TX_WTHRESH 16
|
||||
|
||||
#define IGC_RX_DMA_ATTR \
|
||||
(DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
|
||||
|
||||
#define IGC_TS_HDR_LEN 16
|
||||
|
||||
#define IGC_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
|
||||
|
||||
#if (PAGE_SIZE < 8192)
|
||||
#define IGC_MAX_FRAME_BUILD_SKB \
|
||||
(SKB_WITH_OVERHEAD(IGC_RXBUFFER_2048) - IGC_SKB_PAD - IGC_TS_HDR_LEN)
|
||||
#else
|
||||
#define IGC_MAX_FRAME_BUILD_SKB (IGC_RXBUFFER_2048 - IGC_TS_HDR_LEN)
|
||||
#endif
|
||||
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define IGC_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
/* VLAN info */
|
||||
#define IGC_TX_FLAGS_VLAN_MASK 0xffff0000
|
||||
#define IGC_TX_FLAGS_VLAN_SHIFT 16
|
||||
|
||||
/* igc_test_staterr - tests bits within Rx descriptor status and error fields */
|
||||
static inline __le32 igc_test_staterr(union igc_adv_rx_desc *rx_desc,
|
||||
const u32 stat_err_bits)
|
||||
{
|
||||
return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits);
|
||||
}
|
||||
|
||||
enum igc_state_t {
|
||||
__IGC_TESTING,
|
||||
__IGC_RESETTING,
|
||||
__IGC_DOWN,
|
||||
__IGC_PTP_TX_IN_PROGRESS,
|
||||
};
|
||||
|
||||
enum igc_tx_flags {
|
||||
/* cmd_type flags */
|
||||
IGC_TX_FLAGS_VLAN = 0x01,
|
||||
IGC_TX_FLAGS_TSO = 0x02,
|
||||
IGC_TX_FLAGS_TSTAMP = 0x04,
|
||||
|
||||
/* olinfo flags */
|
||||
IGC_TX_FLAGS_IPV4 = 0x10,
|
||||
IGC_TX_FLAGS_CSUM = 0x20,
|
||||
};
|
||||
|
||||
enum igc_boards {
|
||||
board_base,
|
||||
};
|
||||
|
||||
/* The largest size we can write to the descriptor is 65535. In order to
|
||||
* maintain a power of two alignment we have to limit ourselves to 32K.
|
||||
*/
|
||||
#define IGC_MAX_TXD_PWR 15
|
||||
#define IGC_MAX_DATA_PER_TXD BIT(IGC_MAX_TXD_PWR)
|
||||
|
||||
/* Tx Descriptors needed, worst case */
|
||||
#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGC_MAX_DATA_PER_TXD)
|
||||
#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
|
||||
|
||||
enum igc_tx_buffer_type {
|
||||
IGC_TX_BUFFER_TYPE_SKB,
|
||||
IGC_TX_BUFFER_TYPE_XDP,
|
||||
IGC_TX_BUFFER_TYPE_XSK,
|
||||
};
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct igc_tx_buffer {
|
||||
union igc_adv_tx_desc *next_to_watch;
|
||||
unsigned long time_stamp;
|
||||
enum igc_tx_buffer_type type;
|
||||
union {
|
||||
struct sk_buff *skb;
|
||||
struct xdp_frame *xdpf;
|
||||
};
|
||||
unsigned int bytecount;
|
||||
u16 gso_segs;
|
||||
__be16 protocol;
|
||||
|
||||
DEFINE_DMA_UNMAP_ADDR(dma);
|
||||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
u32 tx_flags;
|
||||
};
|
||||
|
||||
struct igc_rx_buffer {
|
||||
union {
|
||||
struct {
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
|
||||
__u32 page_offset;
|
||||
#else
|
||||
__u16 page_offset;
|
||||
#endif
|
||||
__u16 pagecnt_bias;
|
||||
};
|
||||
struct xdp_buff *xdp;
|
||||
};
|
||||
};
|
||||
|
||||
struct igc_q_vector {
|
||||
struct igc_adapter *adapter; /* backlink */
|
||||
void __iomem *itr_register;
|
||||
u32 eims_value; /* EIMS mask value */
|
||||
|
||||
u16 itr_val;
|
||||
u8 set_itr;
|
||||
|
||||
struct igc_ring_container rx, tx;
|
||||
|
||||
struct napi_struct napi;
|
||||
|
||||
struct rcu_head rcu; /* to avoid race with update stats on free */
|
||||
char name[IFNAMSIZ + 9];
|
||||
struct net_device poll_dev;
|
||||
|
||||
/* for dynamic allocation of rings associated with this q_vector */
|
||||
struct igc_ring ring[] ____cacheline_internodealigned_in_smp;
|
||||
};
|
||||
|
||||
enum igc_filter_match_flags {
|
||||
IGC_FILTER_FLAG_ETHER_TYPE = 0x1,
|
||||
IGC_FILTER_FLAG_VLAN_TCI = 0x2,
|
||||
IGC_FILTER_FLAG_SRC_MAC_ADDR = 0x4,
|
||||
IGC_FILTER_FLAG_DST_MAC_ADDR = 0x8,
|
||||
};
|
||||
|
||||
struct igc_nfc_filter {
|
||||
u8 match_flags;
|
||||
u16 etype;
|
||||
u16 vlan_tci;
|
||||
u8 src_addr[ETH_ALEN];
|
||||
u8 dst_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct igc_nfc_rule {
|
||||
struct list_head list;
|
||||
struct igc_nfc_filter filter;
|
||||
u32 location;
|
||||
u16 action;
|
||||
};
|
||||
|
||||
/* IGC supports a total of 32 NFC rules: 16 MAC address based,, 8 VLAN priority
|
||||
* based, and 8 ethertype based.
|
||||
*/
|
||||
#define IGC_MAX_RXNFC_RULES 32
|
||||
|
||||
/* igc_desc_unused - calculate if we have unused descriptors */
|
||||
static inline u16 igc_desc_unused(const struct igc_ring *ring)
|
||||
{
|
||||
u16 ntc = ring->next_to_clean;
|
||||
u16 ntu = ring->next_to_use;
|
||||
|
||||
return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
|
||||
}
|
||||
|
||||
static inline s32 igc_get_phy_info(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.get_phy_info)
|
||||
return hw->phy.ops.get_phy_info(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igc_reset_phy(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.reset)
|
||||
return hw->phy.ops.reset(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct netdev_queue *txring_txq(const struct igc_ring *tx_ring)
|
||||
{
|
||||
return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
enum igc_ring_flags_t {
|
||||
IGC_RING_FLAG_RX_3K_BUFFER,
|
||||
IGC_RING_FLAG_RX_BUILD_SKB_ENABLED,
|
||||
IGC_RING_FLAG_RX_SCTP_CSUM,
|
||||
IGC_RING_FLAG_RX_LB_VLAN_BSWAP,
|
||||
IGC_RING_FLAG_TX_CTX_IDX,
|
||||
IGC_RING_FLAG_TX_DETECT_HANG,
|
||||
IGC_RING_FLAG_AF_XDP_ZC,
|
||||
};
|
||||
|
||||
#define ring_uses_large_buffer(ring) \
|
||||
test_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define set_ring_uses_large_buffer(ring) \
|
||||
set_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define clear_ring_uses_large_buffer(ring) \
|
||||
clear_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
|
||||
#define ring_uses_build_skb(ring) \
|
||||
test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
|
||||
|
||||
static inline unsigned int igc_rx_bufsz(struct igc_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return IGC_RXBUFFER_3072;
|
||||
|
||||
if (ring_uses_build_skb(ring))
|
||||
return IGC_MAX_FRAME_BUILD_SKB + IGC_TS_HDR_LEN;
|
||||
#endif
|
||||
return IGC_RXBUFFER_2048;
|
||||
}
|
||||
|
||||
static inline unsigned int igc_rx_pg_order(struct igc_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data)
|
||||
{
|
||||
if (hw->phy.ops.read_reg)
|
||||
return hw->phy.ops.read_reg(hw, offset, data);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
void igc_reinit_locked(struct igc_adapter *);
|
||||
struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
|
||||
u32 location);
|
||||
int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
|
||||
void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
|
||||
|
||||
void igc_ptp_init(struct igc_adapter *adapter);
|
||||
void igc_ptp_reset(struct igc_adapter *adapter);
|
||||
void igc_ptp_suspend(struct igc_adapter *adapter);
|
||||
void igc_ptp_stop(struct igc_adapter *adapter);
|
||||
ktime_t igc_ptp_rx_pktstamp(struct igc_adapter *adapter, __le32 *buf);
|
||||
int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
void igc_ptp_tx_hang(struct igc_adapter *adapter);
|
||||
void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts);
|
||||
|
||||
#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
|
||||
|
||||
#define IGC_TXD_DCMD (IGC_ADVTXD_DCMD_EOP | IGC_ADVTXD_DCMD_RS)
|
||||
|
||||
#define IGC_RX_DESC(R, i) \
|
||||
(&(((union igc_adv_rx_desc *)((R)->desc))[i]))
|
||||
#define IGC_TX_DESC(R, i) \
|
||||
(&(((union igc_adv_tx_desc *)((R)->desc))[i]))
|
||||
#define IGC_TX_CTXTDESC(R, i) \
|
||||
(&(((struct igc_adv_tx_context_desc *)((R)->desc))[i]))
|
||||
|
||||
#endif /* _IGC_H_ */
|
||||
|
|
@ -0,0 +1,611 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_H_
|
||||
#define _IGC_H_
|
||||
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/sctp.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/timecounter.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
|
||||
#include "igc_hw.h"
|
||||
|
||||
void igc_ethtool_set_ops(struct net_device *);
|
||||
|
||||
/* Transmit and receive queues */
|
||||
#define IGC_MAX_RX_QUEUES 4
|
||||
#define IGC_MAX_TX_QUEUES 4
|
||||
|
||||
#define MAX_Q_VECTORS 8
|
||||
#define MAX_STD_JUMBO_FRAME_SIZE 9216
|
||||
|
||||
#define MAX_ETYPE_FILTER 8
|
||||
#define IGC_RETA_SIZE 128
|
||||
|
||||
/* SDP support */
|
||||
#define IGC_N_EXTTS 2
|
||||
#define IGC_N_PEROUT 2
|
||||
#define IGC_N_SDP 4
|
||||
|
||||
enum igc_mac_filter_type {
|
||||
IGC_MAC_FILTER_TYPE_DST = 0,
|
||||
IGC_MAC_FILTER_TYPE_SRC
|
||||
};
|
||||
|
||||
struct igc_tx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 restart_queue;
|
||||
u64 restart_queue2;
|
||||
};
|
||||
|
||||
struct igc_rx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 drops;
|
||||
u64 csum_err;
|
||||
u64 alloc_failed;
|
||||
};
|
||||
|
||||
struct igc_rx_packet_stats {
|
||||
u64 ipv4_packets; /* IPv4 headers processed */
|
||||
u64 ipv4e_packets; /* IPv4E headers with extensions processed */
|
||||
u64 ipv6_packets; /* IPv6 headers processed */
|
||||
u64 ipv6e_packets; /* IPv6E headers with extensions processed */
|
||||
u64 tcp_packets; /* TCP headers processed */
|
||||
u64 udp_packets; /* UDP headers processed */
|
||||
u64 sctp_packets; /* SCTP headers processed */
|
||||
u64 nfs_packets; /* NFS headers processe */
|
||||
u64 other_packets;
|
||||
};
|
||||
|
||||
struct igc_ring_container {
|
||||
struct igc_ring *ring; /* pointer to linked list of rings */
|
||||
unsigned int total_bytes; /* total bytes processed this int */
|
||||
unsigned int total_packets; /* total packets processed this int */
|
||||
u16 work_limit; /* total work allowed per interrupt */
|
||||
u8 count; /* total number of rings in vector */
|
||||
u8 itr; /* current ITR setting for ring */
|
||||
};
|
||||
|
||||
struct igc_ring {
|
||||
struct igc_q_vector *q_vector; /* backlink to q_vector */
|
||||
struct net_device *netdev; /* back pointer to net_device */
|
||||
struct device *dev; /* device for dma mapping */
|
||||
union { /* array of buffer info structs */
|
||||
struct igc_tx_buffer *tx_buffer_info;
|
||||
struct igc_rx_buffer *rx_buffer_info;
|
||||
};
|
||||
void *desc; /* descriptor ring memory */
|
||||
unsigned long flags; /* ring specific flags */
|
||||
void __iomem *tail; /* pointer to ring tail register */
|
||||
dma_addr_t dma; /* phys address of the ring */
|
||||
unsigned int size; /* length of desc. ring in bytes */
|
||||
|
||||
u16 count; /* number of desc. in the ring */
|
||||
u8 queue_index; /* logical index of the ring*/
|
||||
u8 reg_idx; /* physical index of the ring */
|
||||
bool launchtime_enable; /* true if LaunchTime is enabled */
|
||||
|
||||
u32 start_time;
|
||||
u32 end_time;
|
||||
|
||||
/* everything past this point are written often */
|
||||
u16 next_to_clean;
|
||||
u16 next_to_use;
|
||||
u16 next_to_alloc;
|
||||
|
||||
union {
|
||||
/* TX */
|
||||
struct {
|
||||
struct igc_tx_queue_stats tx_stats;
|
||||
struct u64_stats_sync tx_syncp;
|
||||
struct u64_stats_sync tx_syncp2;
|
||||
};
|
||||
/* RX */
|
||||
struct {
|
||||
struct igc_rx_queue_stats rx_stats;
|
||||
struct igc_rx_packet_stats pkt_stats;
|
||||
struct u64_stats_sync rx_syncp;
|
||||
struct sk_buff *skb;
|
||||
};
|
||||
};
|
||||
|
||||
struct xdp_rxq_info xdp_rxq;
|
||||
struct xsk_buff_pool *xsk_pool;
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
/* Board specific private data structure */
|
||||
struct igc_adapter {
|
||||
struct net_device *netdev;
|
||||
|
||||
struct ethtool_eee eee;
|
||||
u16 eee_advert;
|
||||
|
||||
unsigned long state;
|
||||
unsigned int flags;
|
||||
unsigned int num_q_vectors;
|
||||
|
||||
struct msix_entry *msix_entries;
|
||||
|
||||
/* TX */
|
||||
u16 tx_work_limit;
|
||||
u32 tx_timeout_count;
|
||||
int num_tx_queues;
|
||||
struct igc_ring *tx_ring[IGC_MAX_TX_QUEUES];
|
||||
|
||||
/* RX */
|
||||
int num_rx_queues;
|
||||
struct igc_ring *rx_ring[IGC_MAX_RX_QUEUES];
|
||||
|
||||
struct timer_list watchdog_timer;
|
||||
struct timer_list dma_err_timer;
|
||||
struct timer_list phy_info_timer;
|
||||
|
||||
u32 wol;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
|
||||
u8 port_num;
|
||||
|
||||
u8 __iomem *io_addr;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 rx_itr_setting;
|
||||
u32 tx_itr_setting;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct work_struct watchdog_task;
|
||||
struct work_struct dma_err_task;
|
||||
bool fc_autoneg;
|
||||
|
||||
u8 tx_timeout_factor;
|
||||
|
||||
int msg_enable;
|
||||
u32 max_frame_size;
|
||||
u32 min_frame_size;
|
||||
|
||||
ktime_t base_time;
|
||||
ktime_t cycle_time;
|
||||
|
||||
/* OS defined structs */
|
||||
struct pci_dev *pdev;
|
||||
/* lock for statistics */
|
||||
spinlock_t stats64_lock;
|
||||
struct rtnl_link_stats64 stats64;
|
||||
|
||||
/* structs defined in igc_hw.h */
|
||||
struct igc_hw hw;
|
||||
struct igc_hw_stats stats;
|
||||
|
||||
struct igc_q_vector *q_vector[MAX_Q_VECTORS];
|
||||
u32 eims_enable_mask;
|
||||
u32 eims_other;
|
||||
|
||||
u16 tx_ring_count;
|
||||
u16 rx_ring_count;
|
||||
|
||||
u32 tx_hwtstamp_timeouts;
|
||||
u32 tx_hwtstamp_skipped;
|
||||
u32 rx_hwtstamp_cleared;
|
||||
|
||||
u32 rss_queues;
|
||||
u32 rss_indir_tbl_init;
|
||||
|
||||
/* Any access to elements in nfc_rule_list is protected by the
|
||||
* nfc_rule_lock.
|
||||
*/
|
||||
struct mutex nfc_rule_lock;
|
||||
struct list_head nfc_rule_list;
|
||||
unsigned int nfc_rule_count;
|
||||
|
||||
u8 rss_indir_tbl[IGC_RETA_SIZE];
|
||||
|
||||
unsigned long link_check_timeout;
|
||||
struct igc_info ei;
|
||||
|
||||
u32 test_icr;
|
||||
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct ptp_clock_info ptp_caps;
|
||||
struct work_struct ptp_tx_work;
|
||||
struct sk_buff *ptp_tx_skb;
|
||||
struct hwtstamp_config tstamp_config;
|
||||
unsigned long ptp_tx_start;
|
||||
unsigned int ptp_flags;
|
||||
/* System time value lock */
|
||||
spinlock_t tmreg_lock;
|
||||
struct cyclecounter cc;
|
||||
struct timecounter tc;
|
||||
struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */
|
||||
ktime_t ptp_reset_start; /* Reset time in clock mono */
|
||||
|
||||
char fw_version[32];
|
||||
|
||||
struct bpf_prog *xdp_prog;
|
||||
|
||||
bool pps_sys_wrap_on;
|
||||
|
||||
struct ptp_pin_desc sdp_config[IGC_N_SDP];
|
||||
struct {
|
||||
struct timespec64 start;
|
||||
struct timespec64 period;
|
||||
} perout[IGC_N_PEROUT];
|
||||
};
|
||||
|
||||
void igc_up(struct igc_adapter *adapter);
|
||||
void igc_down(struct igc_adapter *adapter);
|
||||
int igc_open(struct net_device *netdev);
|
||||
int igc_close(struct net_device *netdev);
|
||||
int igc_setup_tx_resources(struct igc_ring *ring);
|
||||
int igc_setup_rx_resources(struct igc_ring *ring);
|
||||
void igc_free_tx_resources(struct igc_ring *ring);
|
||||
void igc_free_rx_resources(struct igc_ring *ring);
|
||||
unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter);
|
||||
void igc_set_flag_queue_pairs(struct igc_adapter *adapter,
|
||||
const u32 max_rss_queues);
|
||||
int igc_reinit_queues(struct igc_adapter *adapter);
|
||||
void igc_write_rss_indir_tbl(struct igc_adapter *adapter);
|
||||
bool igc_has_link(struct igc_adapter *adapter);
|
||||
void igc_reset(struct igc_adapter *adapter);
|
||||
int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx);
|
||||
void igc_update_stats(struct igc_adapter *adapter);
|
||||
void igc_disable_rx_ring(struct igc_ring *ring);
|
||||
void igc_enable_rx_ring(struct igc_ring *ring);
|
||||
void igc_disable_tx_ring(struct igc_ring *ring);
|
||||
void igc_enable_tx_ring(struct igc_ring *ring);
|
||||
int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags);
|
||||
|
||||
/* igc_dump declarations */
|
||||
void igc_rings_dump(struct igc_adapter *adapter);
|
||||
void igc_regs_dump(struct igc_adapter *adapter);
|
||||
|
||||
extern char igc_driver_name[];
|
||||
|
||||
#define IGC_REGS_LEN 740
|
||||
|
||||
/* flags controlling PTP/1588 function */
|
||||
#define IGC_PTP_ENABLED BIT(0)
|
||||
|
||||
/* Flags definitions */
|
||||
#define IGC_FLAG_HAS_MSI BIT(0)
|
||||
#define IGC_FLAG_QUEUE_PAIRS BIT(3)
|
||||
#define IGC_FLAG_DMAC BIT(4)
|
||||
#define IGC_FLAG_PTP BIT(8)
|
||||
#define IGC_FLAG_WOL_SUPPORTED BIT(8)
|
||||
#define IGC_FLAG_NEED_LINK_UPDATE BIT(9)
|
||||
#define IGC_FLAG_MEDIA_RESET BIT(10)
|
||||
#define IGC_FLAG_MAS_ENABLE BIT(12)
|
||||
#define IGC_FLAG_HAS_MSIX BIT(13)
|
||||
#define IGC_FLAG_EEE BIT(14)
|
||||
#define IGC_FLAG_VLAN_PROMISC BIT(15)
|
||||
#define IGC_FLAG_RX_LEGACY BIT(16)
|
||||
#define IGC_FLAG_TSN_QBV_ENABLED BIT(17)
|
||||
|
||||
#define IGC_FLAG_RSS_FIELD_IPV4_UDP BIT(6)
|
||||
#define IGC_FLAG_RSS_FIELD_IPV6_UDP BIT(7)
|
||||
|
||||
#define IGC_MRQC_ENABLE_RSS_MQ 0x00000002
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
|
||||
|
||||
/* Interrupt defines */
|
||||
#define IGC_START_ITR 648 /* ~6000 ints/sec */
|
||||
#define IGC_4K_ITR 980
|
||||
#define IGC_20K_ITR 196
|
||||
#define IGC_70K_ITR 56
|
||||
|
||||
#define IGC_DEFAULT_ITR 3 /* dynamic */
|
||||
#define IGC_MAX_ITR_USECS 10000
|
||||
#define IGC_MIN_ITR_USECS 10
|
||||
#define NON_Q_VECTORS 1
|
||||
#define MAX_MSIX_ENTRIES 10
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define IGC_DEFAULT_TXD 256
|
||||
#define IGC_DEFAULT_TX_WORK 128
|
||||
#define IGC_MIN_TXD 80
|
||||
#define IGC_MAX_TXD 4096
|
||||
|
||||
#define IGC_DEFAULT_RXD 256
|
||||
#define IGC_MIN_RXD 80
|
||||
#define IGC_MAX_RXD 4096
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define IGC_RXBUFFER_256 256
|
||||
#define IGC_RXBUFFER_2048 2048
|
||||
#define IGC_RXBUFFER_3072 3072
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define IGC_RX_HDR_LEN IGC_RXBUFFER_256
|
||||
|
||||
/* Transmit and receive latency (for PTP timestamps) */
|
||||
#define IGC_I225_TX_LATENCY_10 240
|
||||
#define IGC_I225_TX_LATENCY_100 58
|
||||
#define IGC_I225_TX_LATENCY_1000 80
|
||||
#define IGC_I225_TX_LATENCY_2500 1325
|
||||
#define IGC_I225_RX_LATENCY_10 6450
|
||||
#define IGC_I225_RX_LATENCY_100 185
|
||||
#define IGC_I225_RX_LATENCY_1000 300
|
||||
#define IGC_I225_RX_LATENCY_2500 1485
|
||||
|
||||
/* RX and TX descriptor control thresholds.
|
||||
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
|
||||
* descriptors available in its onboard memory.
|
||||
* Setting this to 0 disables RX descriptor prefetch.
|
||||
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
|
||||
* available in host memory.
|
||||
* If PTHRESH is 0, this should also be 0.
|
||||
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
|
||||
* descriptors until either it has this many to write back, or the
|
||||
* ITR timer expires.
|
||||
*/
|
||||
#define IGC_RX_PTHRESH 8
|
||||
#define IGC_RX_HTHRESH 8
|
||||
#define IGC_TX_PTHRESH 8
|
||||
#define IGC_TX_HTHRESH 1
|
||||
#define IGC_RX_WTHRESH 4
|
||||
#define IGC_TX_WTHRESH 16
|
||||
|
||||
#define IGC_RX_DMA_ATTR \
|
||||
(DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
|
||||
|
||||
#define IGC_TS_HDR_LEN 16
|
||||
|
||||
#define IGC_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
|
||||
|
||||
#if (PAGE_SIZE < 8192)
|
||||
#define IGC_MAX_FRAME_BUILD_SKB \
|
||||
(SKB_WITH_OVERHEAD(IGC_RXBUFFER_2048) - IGC_SKB_PAD - IGC_TS_HDR_LEN)
|
||||
#else
|
||||
#define IGC_MAX_FRAME_BUILD_SKB (IGC_RXBUFFER_2048 - IGC_TS_HDR_LEN)
|
||||
#endif
|
||||
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define IGC_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
/* VLAN info */
|
||||
#define IGC_TX_FLAGS_VLAN_MASK 0xffff0000
|
||||
#define IGC_TX_FLAGS_VLAN_SHIFT 16
|
||||
|
||||
/* igc_test_staterr - tests bits within Rx descriptor status and error fields */
|
||||
static inline __le32 igc_test_staterr(union igc_adv_rx_desc *rx_desc,
|
||||
const u32 stat_err_bits)
|
||||
{
|
||||
return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits);
|
||||
}
|
||||
|
||||
enum igc_state_t {
|
||||
__IGC_TESTING,
|
||||
__IGC_RESETTING,
|
||||
__IGC_DOWN,
|
||||
__IGC_PTP_TX_IN_PROGRESS,
|
||||
};
|
||||
|
||||
enum igc_tx_flags {
|
||||
/* cmd_type flags */
|
||||
IGC_TX_FLAGS_VLAN = 0x01,
|
||||
IGC_TX_FLAGS_TSO = 0x02,
|
||||
IGC_TX_FLAGS_TSTAMP = 0x04,
|
||||
|
||||
/* olinfo flags */
|
||||
IGC_TX_FLAGS_IPV4 = 0x10,
|
||||
IGC_TX_FLAGS_CSUM = 0x20,
|
||||
};
|
||||
|
||||
enum igc_boards {
|
||||
board_base,
|
||||
};
|
||||
|
||||
/* The largest size we can write to the descriptor is 65535. In order to
|
||||
* maintain a power of two alignment we have to limit ourselves to 32K.
|
||||
*/
|
||||
#define IGC_MAX_TXD_PWR 15
|
||||
#define IGC_MAX_DATA_PER_TXD BIT(IGC_MAX_TXD_PWR)
|
||||
|
||||
/* Tx Descriptors needed, worst case */
|
||||
#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGC_MAX_DATA_PER_TXD)
|
||||
#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
|
||||
|
||||
enum igc_tx_buffer_type {
|
||||
IGC_TX_BUFFER_TYPE_SKB,
|
||||
IGC_TX_BUFFER_TYPE_XDP,
|
||||
IGC_TX_BUFFER_TYPE_XSK,
|
||||
};
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct igc_tx_buffer {
|
||||
union igc_adv_tx_desc *next_to_watch;
|
||||
unsigned long time_stamp;
|
||||
enum igc_tx_buffer_type type;
|
||||
union {
|
||||
struct sk_buff *skb;
|
||||
struct xdp_frame *xdpf;
|
||||
};
|
||||
unsigned int bytecount;
|
||||
u16 gso_segs;
|
||||
__be16 protocol;
|
||||
|
||||
DEFINE_DMA_UNMAP_ADDR(dma);
|
||||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
u32 tx_flags;
|
||||
};
|
||||
|
||||
struct igc_rx_buffer {
|
||||
union {
|
||||
struct {
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
|
||||
__u32 page_offset;
|
||||
#else
|
||||
__u16 page_offset;
|
||||
#endif
|
||||
__u16 pagecnt_bias;
|
||||
};
|
||||
struct xdp_buff *xdp;
|
||||
};
|
||||
};
|
||||
|
||||
struct igc_q_vector {
|
||||
struct igc_adapter *adapter; /* backlink */
|
||||
void __iomem *itr_register;
|
||||
u32 eims_value; /* EIMS mask value */
|
||||
|
||||
u16 itr_val;
|
||||
u8 set_itr;
|
||||
|
||||
struct igc_ring_container rx, tx;
|
||||
|
||||
struct napi_struct napi;
|
||||
|
||||
struct rcu_head rcu; /* to avoid race with update stats on free */
|
||||
char name[IFNAMSIZ + 9];
|
||||
struct net_device poll_dev;
|
||||
|
||||
/* for dynamic allocation of rings associated with this q_vector */
|
||||
struct igc_ring ring[] ____cacheline_internodealigned_in_smp;
|
||||
};
|
||||
|
||||
enum igc_filter_match_flags {
|
||||
IGC_FILTER_FLAG_ETHER_TYPE = 0x1,
|
||||
IGC_FILTER_FLAG_VLAN_TCI = 0x2,
|
||||
IGC_FILTER_FLAG_SRC_MAC_ADDR = 0x4,
|
||||
IGC_FILTER_FLAG_DST_MAC_ADDR = 0x8,
|
||||
};
|
||||
|
||||
struct igc_nfc_filter {
|
||||
u8 match_flags;
|
||||
u16 etype;
|
||||
u16 vlan_tci;
|
||||
u8 src_addr[ETH_ALEN];
|
||||
u8 dst_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
struct igc_nfc_rule {
|
||||
struct list_head list;
|
||||
struct igc_nfc_filter filter;
|
||||
u32 location;
|
||||
u16 action;
|
||||
};
|
||||
|
||||
/* IGC supports a total of 32 NFC rules: 16 MAC address based,, 8 VLAN priority
|
||||
* based, and 8 ethertype based.
|
||||
*/
|
||||
#define IGC_MAX_RXNFC_RULES 32
|
||||
|
||||
/* igc_desc_unused - calculate if we have unused descriptors */
|
||||
static inline u16 igc_desc_unused(const struct igc_ring *ring)
|
||||
{
|
||||
u16 ntc = ring->next_to_clean;
|
||||
u16 ntu = ring->next_to_use;
|
||||
|
||||
return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
|
||||
}
|
||||
|
||||
static inline s32 igc_get_phy_info(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.get_phy_info)
|
||||
return hw->phy.ops.get_phy_info(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igc_reset_phy(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.reset)
|
||||
return hw->phy.ops.reset(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct netdev_queue *txring_txq(const struct igc_ring *tx_ring)
|
||||
{
|
||||
return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
enum igc_ring_flags_t {
|
||||
IGC_RING_FLAG_RX_3K_BUFFER,
|
||||
IGC_RING_FLAG_RX_BUILD_SKB_ENABLED,
|
||||
IGC_RING_FLAG_RX_SCTP_CSUM,
|
||||
IGC_RING_FLAG_RX_LB_VLAN_BSWAP,
|
||||
IGC_RING_FLAG_TX_CTX_IDX,
|
||||
IGC_RING_FLAG_TX_DETECT_HANG,
|
||||
IGC_RING_FLAG_AF_XDP_ZC,
|
||||
};
|
||||
|
||||
#define ring_uses_large_buffer(ring) \
|
||||
test_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define set_ring_uses_large_buffer(ring) \
|
||||
set_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define clear_ring_uses_large_buffer(ring) \
|
||||
clear_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
|
||||
#define ring_uses_build_skb(ring) \
|
||||
test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
|
||||
|
||||
static inline unsigned int igc_rx_bufsz(struct igc_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return IGC_RXBUFFER_3072;
|
||||
|
||||
if (ring_uses_build_skb(ring))
|
||||
return IGC_MAX_FRAME_BUILD_SKB + IGC_TS_HDR_LEN;
|
||||
#endif
|
||||
return IGC_RXBUFFER_2048;
|
||||
}
|
||||
|
||||
static inline unsigned int igc_rx_pg_order(struct igc_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data)
|
||||
{
|
||||
if (hw->phy.ops.read_reg)
|
||||
return hw->phy.ops.read_reg(hw, offset, data);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
void igc_reinit_locked(struct igc_adapter *);
|
||||
struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
|
||||
u32 location);
|
||||
int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
|
||||
void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
|
||||
|
||||
void igc_ptp_init(struct igc_adapter *adapter);
|
||||
void igc_ptp_reset(struct igc_adapter *adapter);
|
||||
void igc_ptp_suspend(struct igc_adapter *adapter);
|
||||
void igc_ptp_stop(struct igc_adapter *adapter);
|
||||
ktime_t igc_ptp_rx_pktstamp(struct igc_adapter *adapter, __le32 *buf);
|
||||
int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
void igc_ptp_tx_hang(struct igc_adapter *adapter);
|
||||
void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts);
|
||||
|
||||
#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
|
||||
|
||||
#define IGC_TXD_DCMD (IGC_ADVTXD_DCMD_EOP | IGC_ADVTXD_DCMD_RS)
|
||||
|
||||
#define IGC_RX_DESC(R, i) \
|
||||
(&(((union igc_adv_rx_desc *)((R)->desc))[i]))
|
||||
#define IGC_TX_DESC(R, i) \
|
||||
(&(((union igc_adv_tx_desc *)((R)->desc))[i]))
|
||||
#define IGC_TX_CTXTDESC(R, i) \
|
||||
(&(((struct igc_adv_tx_context_desc *)((R)->desc))[i]))
|
||||
|
||||
#endif /* _IGC_H_ */
|
||||
|
|
@ -0,0 +1,665 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_H_
|
||||
#define _IGC_H_
|
||||
#include "../ecdev.h"
|
||||
|
||||
#include <linux/irq_work.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/sctp.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/timecounter.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
|
||||
#include "igc_hw-6.1-ethercat.h"
|
||||
|
||||
void igc_ethtool_set_ops(struct net_device *);
|
||||
|
||||
/* Transmit and receive queues */
|
||||
#define IGC_MAX_RX_QUEUES 4
|
||||
#define IGC_MAX_TX_QUEUES 4
|
||||
|
||||
#define MAX_Q_VECTORS 8
|
||||
#define MAX_STD_JUMBO_FRAME_SIZE 9216
|
||||
|
||||
#define MAX_ETYPE_FILTER 8
|
||||
#define IGC_RETA_SIZE 128
|
||||
|
||||
/* SDP support */
|
||||
#define IGC_N_EXTTS 2
|
||||
#define IGC_N_PEROUT 2
|
||||
#define IGC_N_SDP 4
|
||||
|
||||
#define MAX_FLEX_FILTER 32
|
||||
|
||||
enum igc_mac_filter_type {
|
||||
IGC_MAC_FILTER_TYPE_DST = 0,
|
||||
IGC_MAC_FILTER_TYPE_SRC
|
||||
};
|
||||
|
||||
struct igc_tx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 restart_queue;
|
||||
u64 restart_queue2;
|
||||
};
|
||||
|
||||
struct igc_rx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 drops;
|
||||
u64 csum_err;
|
||||
u64 alloc_failed;
|
||||
};
|
||||
|
||||
struct igc_rx_packet_stats {
|
||||
u64 ipv4_packets; /* IPv4 headers processed */
|
||||
u64 ipv4e_packets; /* IPv4E headers with extensions processed */
|
||||
u64 ipv6_packets; /* IPv6 headers processed */
|
||||
u64 ipv6e_packets; /* IPv6E headers with extensions processed */
|
||||
u64 tcp_packets; /* TCP headers processed */
|
||||
u64 udp_packets; /* UDP headers processed */
|
||||
u64 sctp_packets; /* SCTP headers processed */
|
||||
u64 nfs_packets; /* NFS headers processe */
|
||||
u64 other_packets;
|
||||
};
|
||||
|
||||
struct igc_ring_container {
|
||||
struct igc_ring *ring; /* pointer to linked list of rings */
|
||||
unsigned int total_bytes; /* total bytes processed this int */
|
||||
unsigned int total_packets; /* total packets processed this int */
|
||||
u16 work_limit; /* total work allowed per interrupt */
|
||||
u8 count; /* total number of rings in vector */
|
||||
u8 itr; /* current ITR setting for ring */
|
||||
};
|
||||
|
||||
struct igc_ring {
|
||||
struct igc_q_vector *q_vector; /* backlink to q_vector */
|
||||
struct net_device *netdev; /* back pointer to net_device */
|
||||
struct device *dev; /* device for dma mapping */
|
||||
union { /* array of buffer info structs */
|
||||
struct igc_tx_buffer *tx_buffer_info;
|
||||
struct igc_rx_buffer *rx_buffer_info;
|
||||
};
|
||||
void *desc; /* descriptor ring memory */
|
||||
unsigned long flags; /* ring specific flags */
|
||||
void __iomem *tail; /* pointer to ring tail register */
|
||||
dma_addr_t dma; /* phys address of the ring */
|
||||
unsigned int size; /* length of desc. ring in bytes */
|
||||
|
||||
u16 count; /* number of desc. in the ring */
|
||||
u8 queue_index; /* logical index of the ring*/
|
||||
u8 reg_idx; /* physical index of the ring */
|
||||
bool launchtime_enable; /* true if LaunchTime is enabled */
|
||||
ktime_t last_tx_cycle; /* end of the cycle with a launchtime transmission */
|
||||
ktime_t last_ff_cycle; /* Last cycle with an active first flag */
|
||||
|
||||
u32 start_time;
|
||||
u32 end_time;
|
||||
|
||||
/* CBS parameters */
|
||||
bool cbs_enable; /* indicates if CBS is enabled */
|
||||
s32 idleslope; /* idleSlope in kbps */
|
||||
s32 sendslope; /* sendSlope in kbps */
|
||||
s32 hicredit; /* hiCredit in bytes */
|
||||
s32 locredit; /* loCredit in bytes */
|
||||
|
||||
/* everything past this point are written often */
|
||||
u16 next_to_clean;
|
||||
u16 next_to_use;
|
||||
u16 next_to_alloc;
|
||||
|
||||
union {
|
||||
/* TX */
|
||||
struct {
|
||||
struct igc_tx_queue_stats tx_stats;
|
||||
struct u64_stats_sync tx_syncp;
|
||||
struct u64_stats_sync tx_syncp2;
|
||||
};
|
||||
/* RX */
|
||||
struct {
|
||||
struct igc_rx_queue_stats rx_stats;
|
||||
struct igc_rx_packet_stats pkt_stats;
|
||||
struct u64_stats_sync rx_syncp;
|
||||
struct sk_buff *skb;
|
||||
};
|
||||
};
|
||||
|
||||
struct xdp_rxq_info xdp_rxq;
|
||||
struct xsk_buff_pool *xsk_pool;
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
/* Board specific private data structure */
|
||||
struct igc_adapter {
|
||||
struct net_device *netdev;
|
||||
|
||||
struct ethtool_eee eee;
|
||||
u16 eee_advert;
|
||||
|
||||
unsigned long state;
|
||||
unsigned int flags;
|
||||
unsigned int num_q_vectors;
|
||||
|
||||
struct msix_entry *msix_entries;
|
||||
|
||||
/* TX */
|
||||
u16 tx_work_limit;
|
||||
u32 tx_timeout_count;
|
||||
int num_tx_queues;
|
||||
struct igc_ring *tx_ring[IGC_MAX_TX_QUEUES];
|
||||
|
||||
/* RX */
|
||||
int num_rx_queues;
|
||||
struct igc_ring *rx_ring[IGC_MAX_RX_QUEUES];
|
||||
|
||||
struct timer_list watchdog_timer;
|
||||
struct timer_list dma_err_timer;
|
||||
struct timer_list phy_info_timer;
|
||||
|
||||
u32 wol;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
|
||||
u8 port_num;
|
||||
|
||||
u8 __iomem *io_addr;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 rx_itr_setting;
|
||||
u32 tx_itr_setting;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct work_struct watchdog_task;
|
||||
struct work_struct dma_err_task;
|
||||
bool fc_autoneg;
|
||||
|
||||
u8 tx_timeout_factor;
|
||||
|
||||
int msg_enable;
|
||||
u32 max_frame_size;
|
||||
u32 min_frame_size;
|
||||
|
||||
ktime_t base_time;
|
||||
ktime_t cycle_time;
|
||||
bool qbv_enable;
|
||||
|
||||
/* OS defined structs */
|
||||
struct pci_dev *pdev;
|
||||
/* lock for statistics */
|
||||
spinlock_t stats64_lock;
|
||||
struct rtnl_link_stats64 stats64;
|
||||
|
||||
/* structs defined in igc_hw.h */
|
||||
struct igc_hw hw;
|
||||
struct igc_hw_stats stats;
|
||||
|
||||
struct igc_q_vector *q_vector[MAX_Q_VECTORS];
|
||||
u32 eims_enable_mask;
|
||||
u32 eims_other;
|
||||
|
||||
u16 tx_ring_count;
|
||||
u16 rx_ring_count;
|
||||
|
||||
u32 tx_hwtstamp_timeouts;
|
||||
u32 tx_hwtstamp_skipped;
|
||||
u32 rx_hwtstamp_cleared;
|
||||
|
||||
u32 rss_queues;
|
||||
u32 rss_indir_tbl_init;
|
||||
|
||||
/* Any access to elements in nfc_rule_list is protected by the
|
||||
* nfc_rule_lock.
|
||||
*/
|
||||
struct mutex nfc_rule_lock;
|
||||
struct list_head nfc_rule_list;
|
||||
unsigned int nfc_rule_count;
|
||||
|
||||
u8 rss_indir_tbl[IGC_RETA_SIZE];
|
||||
|
||||
unsigned long link_check_timeout;
|
||||
struct igc_info ei;
|
||||
|
||||
u32 test_icr;
|
||||
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct ptp_clock_info ptp_caps;
|
||||
struct work_struct ptp_tx_work;
|
||||
struct sk_buff *ptp_tx_skb;
|
||||
struct hwtstamp_config tstamp_config;
|
||||
unsigned long ptp_tx_start;
|
||||
unsigned int ptp_flags;
|
||||
/* System time value lock */
|
||||
spinlock_t tmreg_lock;
|
||||
struct cyclecounter cc;
|
||||
struct timecounter tc;
|
||||
struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */
|
||||
ktime_t ptp_reset_start; /* Reset time in clock mono */
|
||||
struct system_time_snapshot snapshot;
|
||||
|
||||
char fw_version[32];
|
||||
|
||||
struct bpf_prog *xdp_prog;
|
||||
|
||||
bool pps_sys_wrap_on;
|
||||
|
||||
struct ptp_pin_desc sdp_config[IGC_N_SDP];
|
||||
struct {
|
||||
struct timespec64 start;
|
||||
struct timespec64 period;
|
||||
} perout[IGC_N_PEROUT];
|
||||
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
struct irq_work ec_watchdog_kicker;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct igc_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
void igc_up(struct igc_adapter *adapter);
|
||||
void igc_down(struct igc_adapter *adapter);
|
||||
int igc_open(struct net_device *netdev);
|
||||
int igc_close(struct net_device *netdev);
|
||||
int igc_setup_tx_resources(struct igc_ring *ring);
|
||||
int igc_setup_rx_resources(struct igc_ring *ring);
|
||||
void igc_free_tx_resources(struct igc_ring *ring);
|
||||
void igc_free_rx_resources(struct igc_ring *ring);
|
||||
unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter);
|
||||
void igc_set_flag_queue_pairs(struct igc_adapter *adapter,
|
||||
const u32 max_rss_queues);
|
||||
int igc_reinit_queues(struct igc_adapter *adapter);
|
||||
void igc_write_rss_indir_tbl(struct igc_adapter *adapter);
|
||||
bool igc_has_link(struct igc_adapter *adapter);
|
||||
void igc_reset(struct igc_adapter *adapter);
|
||||
void igc_update_stats(struct igc_adapter *adapter);
|
||||
void igc_disable_rx_ring(struct igc_ring *ring);
|
||||
void igc_enable_rx_ring(struct igc_ring *ring);
|
||||
void igc_disable_tx_ring(struct igc_ring *ring);
|
||||
void igc_enable_tx_ring(struct igc_ring *ring);
|
||||
int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags);
|
||||
|
||||
/* igc_dump declarations */
|
||||
void igc_rings_dump(struct igc_adapter *adapter);
|
||||
void igc_regs_dump(struct igc_adapter *adapter);
|
||||
|
||||
extern char igc_driver_name[];
|
||||
|
||||
#define IGC_REGS_LEN 740
|
||||
|
||||
/* flags controlling PTP/1588 function */
|
||||
#define IGC_PTP_ENABLED BIT(0)
|
||||
|
||||
/* Flags definitions */
|
||||
#define IGC_FLAG_HAS_MSI BIT(0)
|
||||
#define IGC_FLAG_QUEUE_PAIRS BIT(3)
|
||||
#define IGC_FLAG_DMAC BIT(4)
|
||||
#define IGC_FLAG_PTP BIT(8)
|
||||
#define IGC_FLAG_WOL_SUPPORTED BIT(8)
|
||||
#define IGC_FLAG_NEED_LINK_UPDATE BIT(9)
|
||||
#define IGC_FLAG_MEDIA_RESET BIT(10)
|
||||
#define IGC_FLAG_MAS_ENABLE BIT(12)
|
||||
#define IGC_FLAG_HAS_MSIX BIT(13)
|
||||
#define IGC_FLAG_EEE BIT(14)
|
||||
#define IGC_FLAG_VLAN_PROMISC BIT(15)
|
||||
#define IGC_FLAG_RX_LEGACY BIT(16)
|
||||
#define IGC_FLAG_TSN_QBV_ENABLED BIT(17)
|
||||
#define IGC_FLAG_TSN_QAV_ENABLED BIT(18)
|
||||
|
||||
#define IGC_FLAG_TSN_ANY_ENABLED \
|
||||
(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED)
|
||||
|
||||
#define IGC_FLAG_RSS_FIELD_IPV4_UDP BIT(6)
|
||||
#define IGC_FLAG_RSS_FIELD_IPV6_UDP BIT(7)
|
||||
|
||||
#define IGC_MRQC_ENABLE_RSS_MQ 0x00000002
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
|
||||
|
||||
/* Interrupt defines */
|
||||
#define IGC_START_ITR 648 /* ~6000 ints/sec */
|
||||
#define IGC_4K_ITR 980
|
||||
#define IGC_20K_ITR 196
|
||||
#define IGC_70K_ITR 56
|
||||
|
||||
#define IGC_DEFAULT_ITR 3 /* dynamic */
|
||||
#define IGC_MAX_ITR_USECS 10000
|
||||
#define IGC_MIN_ITR_USECS 10
|
||||
#define NON_Q_VECTORS 1
|
||||
#define MAX_MSIX_ENTRIES 10
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define IGC_DEFAULT_TXD 256
|
||||
#define IGC_DEFAULT_TX_WORK 128
|
||||
#define IGC_MIN_TXD 80
|
||||
#define IGC_MAX_TXD 4096
|
||||
|
||||
#define IGC_DEFAULT_RXD 256
|
||||
#define IGC_MIN_RXD 80
|
||||
#define IGC_MAX_RXD 4096
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define IGC_RXBUFFER_256 256
|
||||
#define IGC_RXBUFFER_2048 2048
|
||||
#define IGC_RXBUFFER_3072 3072
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define IGC_RX_HDR_LEN IGC_RXBUFFER_256
|
||||
|
||||
/* Transmit and receive latency (for PTP timestamps) */
|
||||
#define IGC_I225_TX_LATENCY_10 240
|
||||
#define IGC_I225_TX_LATENCY_100 58
|
||||
#define IGC_I225_TX_LATENCY_1000 80
|
||||
#define IGC_I225_TX_LATENCY_2500 1325
|
||||
#define IGC_I225_RX_LATENCY_10 6450
|
||||
#define IGC_I225_RX_LATENCY_100 185
|
||||
#define IGC_I225_RX_LATENCY_1000 300
|
||||
#define IGC_I225_RX_LATENCY_2500 1485
|
||||
|
||||
/* RX and TX descriptor control thresholds.
|
||||
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
|
||||
* descriptors available in its onboard memory.
|
||||
* Setting this to 0 disables RX descriptor prefetch.
|
||||
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
|
||||
* available in host memory.
|
||||
* If PTHRESH is 0, this should also be 0.
|
||||
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
|
||||
* descriptors until either it has this many to write back, or the
|
||||
* ITR timer expires.
|
||||
*/
|
||||
#define IGC_RX_PTHRESH 8
|
||||
#define IGC_RX_HTHRESH 8
|
||||
#define IGC_TX_PTHRESH 8
|
||||
#define IGC_TX_HTHRESH 1
|
||||
#define IGC_RX_WTHRESH 4
|
||||
#define IGC_TX_WTHRESH 16
|
||||
|
||||
#define IGC_RX_DMA_ATTR \
|
||||
(DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
|
||||
|
||||
#define IGC_TS_HDR_LEN 16
|
||||
|
||||
#define IGC_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
|
||||
|
||||
#if (PAGE_SIZE < 8192)
|
||||
#define IGC_MAX_FRAME_BUILD_SKB \
|
||||
(SKB_WITH_OVERHEAD(IGC_RXBUFFER_2048) - IGC_SKB_PAD - IGC_TS_HDR_LEN)
|
||||
#else
|
||||
#define IGC_MAX_FRAME_BUILD_SKB (IGC_RXBUFFER_2048 - IGC_TS_HDR_LEN)
|
||||
#endif
|
||||
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define IGC_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
/* VLAN info */
|
||||
#define IGC_TX_FLAGS_VLAN_MASK 0xffff0000
|
||||
#define IGC_TX_FLAGS_VLAN_SHIFT 16
|
||||
|
||||
/* igc_test_staterr - tests bits within Rx descriptor status and error fields */
|
||||
static inline __le32 igc_test_staterr(union igc_adv_rx_desc *rx_desc,
|
||||
const u32 stat_err_bits)
|
||||
{
|
||||
return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits);
|
||||
}
|
||||
|
||||
enum igc_state_t {
|
||||
__IGC_TESTING,
|
||||
__IGC_RESETTING,
|
||||
__IGC_DOWN,
|
||||
__IGC_PTP_TX_IN_PROGRESS,
|
||||
};
|
||||
|
||||
enum igc_tx_flags {
|
||||
/* cmd_type flags */
|
||||
IGC_TX_FLAGS_VLAN = 0x01,
|
||||
IGC_TX_FLAGS_TSO = 0x02,
|
||||
IGC_TX_FLAGS_TSTAMP = 0x04,
|
||||
|
||||
/* olinfo flags */
|
||||
IGC_TX_FLAGS_IPV4 = 0x10,
|
||||
IGC_TX_FLAGS_CSUM = 0x20,
|
||||
};
|
||||
|
||||
enum igc_boards {
|
||||
board_base,
|
||||
};
|
||||
|
||||
/* The largest size we can write to the descriptor is 65535. In order to
|
||||
* maintain a power of two alignment we have to limit ourselves to 32K.
|
||||
*/
|
||||
#define IGC_MAX_TXD_PWR 15
|
||||
#define IGC_MAX_DATA_PER_TXD BIT(IGC_MAX_TXD_PWR)
|
||||
|
||||
/* Tx Descriptors needed, worst case */
|
||||
#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGC_MAX_DATA_PER_TXD)
|
||||
#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
|
||||
|
||||
enum igc_tx_buffer_type {
|
||||
IGC_TX_BUFFER_TYPE_SKB,
|
||||
IGC_TX_BUFFER_TYPE_XDP,
|
||||
IGC_TX_BUFFER_TYPE_XSK,
|
||||
};
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct igc_tx_buffer {
|
||||
union igc_adv_tx_desc *next_to_watch;
|
||||
unsigned long time_stamp;
|
||||
enum igc_tx_buffer_type type;
|
||||
union {
|
||||
struct sk_buff *skb;
|
||||
struct xdp_frame *xdpf;
|
||||
};
|
||||
unsigned int bytecount;
|
||||
u16 gso_segs;
|
||||
__be16 protocol;
|
||||
|
||||
DEFINE_DMA_UNMAP_ADDR(dma);
|
||||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
u32 tx_flags;
|
||||
};
|
||||
|
||||
struct igc_rx_buffer {
|
||||
union {
|
||||
struct {
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
|
||||
__u32 page_offset;
|
||||
#else
|
||||
__u16 page_offset;
|
||||
#endif
|
||||
__u16 pagecnt_bias;
|
||||
};
|
||||
struct xdp_buff *xdp;
|
||||
};
|
||||
};
|
||||
|
||||
struct igc_q_vector {
|
||||
struct igc_adapter *adapter; /* backlink */
|
||||
void __iomem *itr_register;
|
||||
u32 eims_value; /* EIMS mask value */
|
||||
|
||||
u16 itr_val;
|
||||
u8 set_itr;
|
||||
|
||||
struct igc_ring_container rx, tx;
|
||||
|
||||
struct napi_struct napi;
|
||||
|
||||
struct rcu_head rcu; /* to avoid race with update stats on free */
|
||||
char name[IFNAMSIZ + 9];
|
||||
struct net_device poll_dev;
|
||||
|
||||
/* for dynamic allocation of rings associated with this q_vector */
|
||||
struct igc_ring ring[] ____cacheline_internodealigned_in_smp;
|
||||
};
|
||||
|
||||
enum igc_filter_match_flags {
|
||||
IGC_FILTER_FLAG_ETHER_TYPE = BIT(0),
|
||||
IGC_FILTER_FLAG_VLAN_TCI = BIT(1),
|
||||
IGC_FILTER_FLAG_SRC_MAC_ADDR = BIT(2),
|
||||
IGC_FILTER_FLAG_DST_MAC_ADDR = BIT(3),
|
||||
IGC_FILTER_FLAG_USER_DATA = BIT(4),
|
||||
IGC_FILTER_FLAG_VLAN_ETYPE = BIT(5),
|
||||
};
|
||||
|
||||
struct igc_nfc_filter {
|
||||
u8 match_flags;
|
||||
u16 etype;
|
||||
__be16 vlan_etype;
|
||||
u16 vlan_tci;
|
||||
u8 src_addr[ETH_ALEN];
|
||||
u8 dst_addr[ETH_ALEN];
|
||||
u8 user_data[8];
|
||||
u8 user_mask[8];
|
||||
u8 flex_index;
|
||||
u8 rx_queue;
|
||||
u8 prio;
|
||||
u8 immediate_irq;
|
||||
u8 drop;
|
||||
};
|
||||
|
||||
struct igc_nfc_rule {
|
||||
struct list_head list;
|
||||
struct igc_nfc_filter filter;
|
||||
u32 location;
|
||||
u16 action;
|
||||
bool flex;
|
||||
};
|
||||
|
||||
/* IGC supports a total of 32 NFC rules: 16 MAC address based, 8 VLAN priority
|
||||
* based, 8 ethertype based and 32 Flex filter based rules.
|
||||
*/
|
||||
#define IGC_MAX_RXNFC_RULES 64
|
||||
|
||||
struct igc_flex_filter {
|
||||
u8 index;
|
||||
u8 data[128];
|
||||
u8 mask[16];
|
||||
u8 length;
|
||||
u8 rx_queue;
|
||||
u8 prio;
|
||||
u8 immediate_irq;
|
||||
u8 drop;
|
||||
};
|
||||
|
||||
/* igc_desc_unused - calculate if we have unused descriptors */
|
||||
static inline u16 igc_desc_unused(const struct igc_ring *ring)
|
||||
{
|
||||
u16 ntc = ring->next_to_clean;
|
||||
u16 ntu = ring->next_to_use;
|
||||
|
||||
return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
|
||||
}
|
||||
|
||||
static inline s32 igc_get_phy_info(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.get_phy_info)
|
||||
return hw->phy.ops.get_phy_info(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igc_reset_phy(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.reset)
|
||||
return hw->phy.ops.reset(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct netdev_queue *txring_txq(const struct igc_ring *tx_ring)
|
||||
{
|
||||
return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
enum igc_ring_flags_t {
|
||||
IGC_RING_FLAG_RX_3K_BUFFER,
|
||||
IGC_RING_FLAG_RX_BUILD_SKB_ENABLED,
|
||||
IGC_RING_FLAG_RX_SCTP_CSUM,
|
||||
IGC_RING_FLAG_RX_LB_VLAN_BSWAP,
|
||||
IGC_RING_FLAG_TX_CTX_IDX,
|
||||
IGC_RING_FLAG_TX_DETECT_HANG,
|
||||
IGC_RING_FLAG_AF_XDP_ZC,
|
||||
};
|
||||
|
||||
#define ring_uses_large_buffer(ring) \
|
||||
test_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define set_ring_uses_large_buffer(ring) \
|
||||
set_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define clear_ring_uses_large_buffer(ring) \
|
||||
clear_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
|
||||
#define ring_uses_build_skb(ring) \
|
||||
test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
|
||||
|
||||
static inline unsigned int igc_rx_bufsz(struct igc_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return IGC_RXBUFFER_3072;
|
||||
|
||||
if (ring_uses_build_skb(ring))
|
||||
return IGC_MAX_FRAME_BUILD_SKB + IGC_TS_HDR_LEN;
|
||||
#endif
|
||||
return IGC_RXBUFFER_2048;
|
||||
}
|
||||
|
||||
static inline unsigned int igc_rx_pg_order(struct igc_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data)
|
||||
{
|
||||
if (hw->phy.ops.read_reg)
|
||||
return hw->phy.ops.read_reg(hw, offset, data);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
void igc_reinit_locked(struct igc_adapter *);
|
||||
struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
|
||||
u32 location);
|
||||
int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
|
||||
void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
|
||||
|
||||
void igc_ptp_init(struct igc_adapter *adapter);
|
||||
void igc_ptp_reset(struct igc_adapter *adapter);
|
||||
void igc_ptp_suspend(struct igc_adapter *adapter);
|
||||
void igc_ptp_stop(struct igc_adapter *adapter);
|
||||
ktime_t igc_ptp_rx_pktstamp(struct igc_adapter *adapter, __le32 *buf);
|
||||
int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
void igc_ptp_tx_hang(struct igc_adapter *adapter);
|
||||
void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts);
|
||||
|
||||
#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
|
||||
|
||||
#define IGC_TXD_DCMD (IGC_ADVTXD_DCMD_EOP | IGC_ADVTXD_DCMD_RS)
|
||||
|
||||
#define IGC_RX_DESC(R, i) \
|
||||
(&(((union igc_adv_rx_desc *)((R)->desc))[i]))
|
||||
#define IGC_TX_DESC(R, i) \
|
||||
(&(((union igc_adv_tx_desc *)((R)->desc))[i]))
|
||||
#define IGC_TX_CTXTDESC(R, i) \
|
||||
(&(((struct igc_adv_tx_context_desc *)((R)->desc))[i]))
|
||||
|
||||
#endif /* _IGC_H_ */
|
||||
|
|
@ -0,0 +1,649 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_H_
|
||||
#define _IGC_H_
|
||||
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/sctp.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/timecounter.h>
|
||||
#include <linux/net_tstamp.h>
|
||||
|
||||
#include "igc_hw.h"
|
||||
|
||||
void igc_ethtool_set_ops(struct net_device *);
|
||||
|
||||
/* Transmit and receive queues */
|
||||
#define IGC_MAX_RX_QUEUES 4
|
||||
#define IGC_MAX_TX_QUEUES 4
|
||||
|
||||
#define MAX_Q_VECTORS 8
|
||||
#define MAX_STD_JUMBO_FRAME_SIZE 9216
|
||||
|
||||
#define MAX_ETYPE_FILTER 8
|
||||
#define IGC_RETA_SIZE 128
|
||||
|
||||
/* SDP support */
|
||||
#define IGC_N_EXTTS 2
|
||||
#define IGC_N_PEROUT 2
|
||||
#define IGC_N_SDP 4
|
||||
|
||||
#define MAX_FLEX_FILTER 32
|
||||
|
||||
enum igc_mac_filter_type {
|
||||
IGC_MAC_FILTER_TYPE_DST = 0,
|
||||
IGC_MAC_FILTER_TYPE_SRC
|
||||
};
|
||||
|
||||
struct igc_tx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 restart_queue;
|
||||
u64 restart_queue2;
|
||||
};
|
||||
|
||||
struct igc_rx_queue_stats {
|
||||
u64 packets;
|
||||
u64 bytes;
|
||||
u64 drops;
|
||||
u64 csum_err;
|
||||
u64 alloc_failed;
|
||||
};
|
||||
|
||||
struct igc_rx_packet_stats {
|
||||
u64 ipv4_packets; /* IPv4 headers processed */
|
||||
u64 ipv4e_packets; /* IPv4E headers with extensions processed */
|
||||
u64 ipv6_packets; /* IPv6 headers processed */
|
||||
u64 ipv6e_packets; /* IPv6E headers with extensions processed */
|
||||
u64 tcp_packets; /* TCP headers processed */
|
||||
u64 udp_packets; /* UDP headers processed */
|
||||
u64 sctp_packets; /* SCTP headers processed */
|
||||
u64 nfs_packets; /* NFS headers processe */
|
||||
u64 other_packets;
|
||||
};
|
||||
|
||||
struct igc_ring_container {
|
||||
struct igc_ring *ring; /* pointer to linked list of rings */
|
||||
unsigned int total_bytes; /* total bytes processed this int */
|
||||
unsigned int total_packets; /* total packets processed this int */
|
||||
u16 work_limit; /* total work allowed per interrupt */
|
||||
u8 count; /* total number of rings in vector */
|
||||
u8 itr; /* current ITR setting for ring */
|
||||
};
|
||||
|
||||
struct igc_ring {
|
||||
struct igc_q_vector *q_vector; /* backlink to q_vector */
|
||||
struct net_device *netdev; /* back pointer to net_device */
|
||||
struct device *dev; /* device for dma mapping */
|
||||
union { /* array of buffer info structs */
|
||||
struct igc_tx_buffer *tx_buffer_info;
|
||||
struct igc_rx_buffer *rx_buffer_info;
|
||||
};
|
||||
void *desc; /* descriptor ring memory */
|
||||
unsigned long flags; /* ring specific flags */
|
||||
void __iomem *tail; /* pointer to ring tail register */
|
||||
dma_addr_t dma; /* phys address of the ring */
|
||||
unsigned int size; /* length of desc. ring in bytes */
|
||||
|
||||
u16 count; /* number of desc. in the ring */
|
||||
u8 queue_index; /* logical index of the ring*/
|
||||
u8 reg_idx; /* physical index of the ring */
|
||||
bool launchtime_enable; /* true if LaunchTime is enabled */
|
||||
ktime_t last_tx_cycle; /* end of the cycle with a launchtime transmission */
|
||||
ktime_t last_ff_cycle; /* Last cycle with an active first flag */
|
||||
|
||||
u32 start_time;
|
||||
u32 end_time;
|
||||
|
||||
/* CBS parameters */
|
||||
bool cbs_enable; /* indicates if CBS is enabled */
|
||||
s32 idleslope; /* idleSlope in kbps */
|
||||
s32 sendslope; /* sendSlope in kbps */
|
||||
s32 hicredit; /* hiCredit in bytes */
|
||||
s32 locredit; /* loCredit in bytes */
|
||||
|
||||
/* everything past this point are written often */
|
||||
u16 next_to_clean;
|
||||
u16 next_to_use;
|
||||
u16 next_to_alloc;
|
||||
|
||||
union {
|
||||
/* TX */
|
||||
struct {
|
||||
struct igc_tx_queue_stats tx_stats;
|
||||
struct u64_stats_sync tx_syncp;
|
||||
struct u64_stats_sync tx_syncp2;
|
||||
};
|
||||
/* RX */
|
||||
struct {
|
||||
struct igc_rx_queue_stats rx_stats;
|
||||
struct igc_rx_packet_stats pkt_stats;
|
||||
struct u64_stats_sync rx_syncp;
|
||||
struct sk_buff *skb;
|
||||
};
|
||||
};
|
||||
|
||||
struct xdp_rxq_info xdp_rxq;
|
||||
struct xsk_buff_pool *xsk_pool;
|
||||
} ____cacheline_internodealigned_in_smp;
|
||||
|
||||
/* Board specific private data structure */
|
||||
struct igc_adapter {
|
||||
struct net_device *netdev;
|
||||
|
||||
struct ethtool_eee eee;
|
||||
u16 eee_advert;
|
||||
|
||||
unsigned long state;
|
||||
unsigned int flags;
|
||||
unsigned int num_q_vectors;
|
||||
|
||||
struct msix_entry *msix_entries;
|
||||
|
||||
/* TX */
|
||||
u16 tx_work_limit;
|
||||
u32 tx_timeout_count;
|
||||
int num_tx_queues;
|
||||
struct igc_ring *tx_ring[IGC_MAX_TX_QUEUES];
|
||||
|
||||
/* RX */
|
||||
int num_rx_queues;
|
||||
struct igc_ring *rx_ring[IGC_MAX_RX_QUEUES];
|
||||
|
||||
struct timer_list watchdog_timer;
|
||||
struct timer_list dma_err_timer;
|
||||
struct timer_list phy_info_timer;
|
||||
|
||||
u32 wol;
|
||||
u32 en_mng_pt;
|
||||
u16 link_speed;
|
||||
u16 link_duplex;
|
||||
|
||||
u8 port_num;
|
||||
|
||||
u8 __iomem *io_addr;
|
||||
/* Interrupt Throttle Rate */
|
||||
u32 rx_itr_setting;
|
||||
u32 tx_itr_setting;
|
||||
|
||||
struct work_struct reset_task;
|
||||
struct work_struct watchdog_task;
|
||||
struct work_struct dma_err_task;
|
||||
bool fc_autoneg;
|
||||
|
||||
u8 tx_timeout_factor;
|
||||
|
||||
int msg_enable;
|
||||
u32 max_frame_size;
|
||||
u32 min_frame_size;
|
||||
|
||||
ktime_t base_time;
|
||||
ktime_t cycle_time;
|
||||
bool qbv_enable;
|
||||
|
||||
/* OS defined structs */
|
||||
struct pci_dev *pdev;
|
||||
/* lock for statistics */
|
||||
spinlock_t stats64_lock;
|
||||
struct rtnl_link_stats64 stats64;
|
||||
|
||||
/* structs defined in igc_hw.h */
|
||||
struct igc_hw hw;
|
||||
struct igc_hw_stats stats;
|
||||
|
||||
struct igc_q_vector *q_vector[MAX_Q_VECTORS];
|
||||
u32 eims_enable_mask;
|
||||
u32 eims_other;
|
||||
|
||||
u16 tx_ring_count;
|
||||
u16 rx_ring_count;
|
||||
|
||||
u32 tx_hwtstamp_timeouts;
|
||||
u32 tx_hwtstamp_skipped;
|
||||
u32 rx_hwtstamp_cleared;
|
||||
|
||||
u32 rss_queues;
|
||||
u32 rss_indir_tbl_init;
|
||||
|
||||
/* Any access to elements in nfc_rule_list is protected by the
|
||||
* nfc_rule_lock.
|
||||
*/
|
||||
struct mutex nfc_rule_lock;
|
||||
struct list_head nfc_rule_list;
|
||||
unsigned int nfc_rule_count;
|
||||
|
||||
u8 rss_indir_tbl[IGC_RETA_SIZE];
|
||||
|
||||
unsigned long link_check_timeout;
|
||||
struct igc_info ei;
|
||||
|
||||
u32 test_icr;
|
||||
|
||||
struct ptp_clock *ptp_clock;
|
||||
struct ptp_clock_info ptp_caps;
|
||||
struct work_struct ptp_tx_work;
|
||||
struct sk_buff *ptp_tx_skb;
|
||||
struct hwtstamp_config tstamp_config;
|
||||
unsigned long ptp_tx_start;
|
||||
unsigned int ptp_flags;
|
||||
/* System time value lock */
|
||||
spinlock_t tmreg_lock;
|
||||
struct cyclecounter cc;
|
||||
struct timecounter tc;
|
||||
struct timespec64 prev_ptp_time; /* Pre-reset PTP clock */
|
||||
ktime_t ptp_reset_start; /* Reset time in clock mono */
|
||||
struct system_time_snapshot snapshot;
|
||||
|
||||
char fw_version[32];
|
||||
|
||||
struct bpf_prog *xdp_prog;
|
||||
|
||||
bool pps_sys_wrap_on;
|
||||
|
||||
struct ptp_pin_desc sdp_config[IGC_N_SDP];
|
||||
struct {
|
||||
struct timespec64 start;
|
||||
struct timespec64 period;
|
||||
} perout[IGC_N_PEROUT];
|
||||
};
|
||||
|
||||
void igc_up(struct igc_adapter *adapter);
|
||||
void igc_down(struct igc_adapter *adapter);
|
||||
int igc_open(struct net_device *netdev);
|
||||
int igc_close(struct net_device *netdev);
|
||||
int igc_setup_tx_resources(struct igc_ring *ring);
|
||||
int igc_setup_rx_resources(struct igc_ring *ring);
|
||||
void igc_free_tx_resources(struct igc_ring *ring);
|
||||
void igc_free_rx_resources(struct igc_ring *ring);
|
||||
unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter);
|
||||
void igc_set_flag_queue_pairs(struct igc_adapter *adapter,
|
||||
const u32 max_rss_queues);
|
||||
int igc_reinit_queues(struct igc_adapter *adapter);
|
||||
void igc_write_rss_indir_tbl(struct igc_adapter *adapter);
|
||||
bool igc_has_link(struct igc_adapter *adapter);
|
||||
void igc_reset(struct igc_adapter *adapter);
|
||||
void igc_update_stats(struct igc_adapter *adapter);
|
||||
void igc_disable_rx_ring(struct igc_ring *ring);
|
||||
void igc_enable_rx_ring(struct igc_ring *ring);
|
||||
void igc_disable_tx_ring(struct igc_ring *ring);
|
||||
void igc_enable_tx_ring(struct igc_ring *ring);
|
||||
int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags);
|
||||
|
||||
/* igc_dump declarations */
|
||||
void igc_rings_dump(struct igc_adapter *adapter);
|
||||
void igc_regs_dump(struct igc_adapter *adapter);
|
||||
|
||||
extern char igc_driver_name[];
|
||||
|
||||
#define IGC_REGS_LEN 740
|
||||
|
||||
/* flags controlling PTP/1588 function */
|
||||
#define IGC_PTP_ENABLED BIT(0)
|
||||
|
||||
/* Flags definitions */
|
||||
#define IGC_FLAG_HAS_MSI BIT(0)
|
||||
#define IGC_FLAG_QUEUE_PAIRS BIT(3)
|
||||
#define IGC_FLAG_DMAC BIT(4)
|
||||
#define IGC_FLAG_PTP BIT(8)
|
||||
#define IGC_FLAG_WOL_SUPPORTED BIT(8)
|
||||
#define IGC_FLAG_NEED_LINK_UPDATE BIT(9)
|
||||
#define IGC_FLAG_MEDIA_RESET BIT(10)
|
||||
#define IGC_FLAG_MAS_ENABLE BIT(12)
|
||||
#define IGC_FLAG_HAS_MSIX BIT(13)
|
||||
#define IGC_FLAG_EEE BIT(14)
|
||||
#define IGC_FLAG_VLAN_PROMISC BIT(15)
|
||||
#define IGC_FLAG_RX_LEGACY BIT(16)
|
||||
#define IGC_FLAG_TSN_QBV_ENABLED BIT(17)
|
||||
#define IGC_FLAG_TSN_QAV_ENABLED BIT(18)
|
||||
|
||||
#define IGC_FLAG_TSN_ANY_ENABLED \
|
||||
(IGC_FLAG_TSN_QBV_ENABLED | IGC_FLAG_TSN_QAV_ENABLED)
|
||||
|
||||
#define IGC_FLAG_RSS_FIELD_IPV4_UDP BIT(6)
|
||||
#define IGC_FLAG_RSS_FIELD_IPV6_UDP BIT(7)
|
||||
|
||||
#define IGC_MRQC_ENABLE_RSS_MQ 0x00000002
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
|
||||
|
||||
/* Interrupt defines */
|
||||
#define IGC_START_ITR 648 /* ~6000 ints/sec */
|
||||
#define IGC_4K_ITR 980
|
||||
#define IGC_20K_ITR 196
|
||||
#define IGC_70K_ITR 56
|
||||
|
||||
#define IGC_DEFAULT_ITR 3 /* dynamic */
|
||||
#define IGC_MAX_ITR_USECS 10000
|
||||
#define IGC_MIN_ITR_USECS 10
|
||||
#define NON_Q_VECTORS 1
|
||||
#define MAX_MSIX_ENTRIES 10
|
||||
|
||||
/* TX/RX descriptor defines */
|
||||
#define IGC_DEFAULT_TXD 256
|
||||
#define IGC_DEFAULT_TX_WORK 128
|
||||
#define IGC_MIN_TXD 80
|
||||
#define IGC_MAX_TXD 4096
|
||||
|
||||
#define IGC_DEFAULT_RXD 256
|
||||
#define IGC_MIN_RXD 80
|
||||
#define IGC_MAX_RXD 4096
|
||||
|
||||
/* Supported Rx Buffer Sizes */
|
||||
#define IGC_RXBUFFER_256 256
|
||||
#define IGC_RXBUFFER_2048 2048
|
||||
#define IGC_RXBUFFER_3072 3072
|
||||
|
||||
#define AUTO_ALL_MODES 0
|
||||
#define IGC_RX_HDR_LEN IGC_RXBUFFER_256
|
||||
|
||||
/* Transmit and receive latency (for PTP timestamps) */
|
||||
#define IGC_I225_TX_LATENCY_10 240
|
||||
#define IGC_I225_TX_LATENCY_100 58
|
||||
#define IGC_I225_TX_LATENCY_1000 80
|
||||
#define IGC_I225_TX_LATENCY_2500 1325
|
||||
#define IGC_I225_RX_LATENCY_10 6450
|
||||
#define IGC_I225_RX_LATENCY_100 185
|
||||
#define IGC_I225_RX_LATENCY_1000 300
|
||||
#define IGC_I225_RX_LATENCY_2500 1485
|
||||
|
||||
/* RX and TX descriptor control thresholds.
|
||||
* PTHRESH - MAC will consider prefetch if it has fewer than this number of
|
||||
* descriptors available in its onboard memory.
|
||||
* Setting this to 0 disables RX descriptor prefetch.
|
||||
* HTHRESH - MAC will only prefetch if there are at least this many descriptors
|
||||
* available in host memory.
|
||||
* If PTHRESH is 0, this should also be 0.
|
||||
* WTHRESH - RX descriptor writeback threshold - MAC will delay writing back
|
||||
* descriptors until either it has this many to write back, or the
|
||||
* ITR timer expires.
|
||||
*/
|
||||
#define IGC_RX_PTHRESH 8
|
||||
#define IGC_RX_HTHRESH 8
|
||||
#define IGC_TX_PTHRESH 8
|
||||
#define IGC_TX_HTHRESH 1
|
||||
#define IGC_RX_WTHRESH 4
|
||||
#define IGC_TX_WTHRESH 16
|
||||
|
||||
#define IGC_RX_DMA_ATTR \
|
||||
(DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING)
|
||||
|
||||
#define IGC_TS_HDR_LEN 16
|
||||
|
||||
#define IGC_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN)
|
||||
|
||||
#if (PAGE_SIZE < 8192)
|
||||
#define IGC_MAX_FRAME_BUILD_SKB \
|
||||
(SKB_WITH_OVERHEAD(IGC_RXBUFFER_2048) - IGC_SKB_PAD - IGC_TS_HDR_LEN)
|
||||
#else
|
||||
#define IGC_MAX_FRAME_BUILD_SKB (IGC_RXBUFFER_2048 - IGC_TS_HDR_LEN)
|
||||
#endif
|
||||
|
||||
/* How many Rx Buffers do we bundle into one write to the hardware ? */
|
||||
#define IGC_RX_BUFFER_WRITE 16 /* Must be power of 2 */
|
||||
|
||||
/* VLAN info */
|
||||
#define IGC_TX_FLAGS_VLAN_MASK 0xffff0000
|
||||
#define IGC_TX_FLAGS_VLAN_SHIFT 16
|
||||
|
||||
/* igc_test_staterr - tests bits within Rx descriptor status and error fields */
|
||||
static inline __le32 igc_test_staterr(union igc_adv_rx_desc *rx_desc,
|
||||
const u32 stat_err_bits)
|
||||
{
|
||||
return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits);
|
||||
}
|
||||
|
||||
enum igc_state_t {
|
||||
__IGC_TESTING,
|
||||
__IGC_RESETTING,
|
||||
__IGC_DOWN,
|
||||
__IGC_PTP_TX_IN_PROGRESS,
|
||||
};
|
||||
|
||||
enum igc_tx_flags {
|
||||
/* cmd_type flags */
|
||||
IGC_TX_FLAGS_VLAN = 0x01,
|
||||
IGC_TX_FLAGS_TSO = 0x02,
|
||||
IGC_TX_FLAGS_TSTAMP = 0x04,
|
||||
|
||||
/* olinfo flags */
|
||||
IGC_TX_FLAGS_IPV4 = 0x10,
|
||||
IGC_TX_FLAGS_CSUM = 0x20,
|
||||
};
|
||||
|
||||
enum igc_boards {
|
||||
board_base,
|
||||
};
|
||||
|
||||
/* The largest size we can write to the descriptor is 65535. In order to
|
||||
* maintain a power of two alignment we have to limit ourselves to 32K.
|
||||
*/
|
||||
#define IGC_MAX_TXD_PWR 15
|
||||
#define IGC_MAX_DATA_PER_TXD BIT(IGC_MAX_TXD_PWR)
|
||||
|
||||
/* Tx Descriptors needed, worst case */
|
||||
#define TXD_USE_COUNT(S) DIV_ROUND_UP((S), IGC_MAX_DATA_PER_TXD)
|
||||
#define DESC_NEEDED (MAX_SKB_FRAGS + 4)
|
||||
|
||||
enum igc_tx_buffer_type {
|
||||
IGC_TX_BUFFER_TYPE_SKB,
|
||||
IGC_TX_BUFFER_TYPE_XDP,
|
||||
IGC_TX_BUFFER_TYPE_XSK,
|
||||
};
|
||||
|
||||
/* wrapper around a pointer to a socket buffer,
|
||||
* so a DMA handle can be stored along with the buffer
|
||||
*/
|
||||
struct igc_tx_buffer {
|
||||
union igc_adv_tx_desc *next_to_watch;
|
||||
unsigned long time_stamp;
|
||||
enum igc_tx_buffer_type type;
|
||||
union {
|
||||
struct sk_buff *skb;
|
||||
struct xdp_frame *xdpf;
|
||||
};
|
||||
unsigned int bytecount;
|
||||
u16 gso_segs;
|
||||
__be16 protocol;
|
||||
|
||||
DEFINE_DMA_UNMAP_ADDR(dma);
|
||||
DEFINE_DMA_UNMAP_LEN(len);
|
||||
u32 tx_flags;
|
||||
};
|
||||
|
||||
struct igc_rx_buffer {
|
||||
union {
|
||||
struct {
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
|
||||
__u32 page_offset;
|
||||
#else
|
||||
__u16 page_offset;
|
||||
#endif
|
||||
__u16 pagecnt_bias;
|
||||
};
|
||||
struct xdp_buff *xdp;
|
||||
};
|
||||
};
|
||||
|
||||
struct igc_q_vector {
|
||||
struct igc_adapter *adapter; /* backlink */
|
||||
void __iomem *itr_register;
|
||||
u32 eims_value; /* EIMS mask value */
|
||||
|
||||
u16 itr_val;
|
||||
u8 set_itr;
|
||||
|
||||
struct igc_ring_container rx, tx;
|
||||
|
||||
struct napi_struct napi;
|
||||
|
||||
struct rcu_head rcu; /* to avoid race with update stats on free */
|
||||
char name[IFNAMSIZ + 9];
|
||||
struct net_device poll_dev;
|
||||
|
||||
/* for dynamic allocation of rings associated with this q_vector */
|
||||
struct igc_ring ring[] ____cacheline_internodealigned_in_smp;
|
||||
};
|
||||
|
||||
enum igc_filter_match_flags {
|
||||
IGC_FILTER_FLAG_ETHER_TYPE = BIT(0),
|
||||
IGC_FILTER_FLAG_VLAN_TCI = BIT(1),
|
||||
IGC_FILTER_FLAG_SRC_MAC_ADDR = BIT(2),
|
||||
IGC_FILTER_FLAG_DST_MAC_ADDR = BIT(3),
|
||||
IGC_FILTER_FLAG_USER_DATA = BIT(4),
|
||||
IGC_FILTER_FLAG_VLAN_ETYPE = BIT(5),
|
||||
};
|
||||
|
||||
struct igc_nfc_filter {
|
||||
u8 match_flags;
|
||||
u16 etype;
|
||||
__be16 vlan_etype;
|
||||
u16 vlan_tci;
|
||||
u8 src_addr[ETH_ALEN];
|
||||
u8 dst_addr[ETH_ALEN];
|
||||
u8 user_data[8];
|
||||
u8 user_mask[8];
|
||||
u8 flex_index;
|
||||
u8 rx_queue;
|
||||
u8 prio;
|
||||
u8 immediate_irq;
|
||||
u8 drop;
|
||||
};
|
||||
|
||||
struct igc_nfc_rule {
|
||||
struct list_head list;
|
||||
struct igc_nfc_filter filter;
|
||||
u32 location;
|
||||
u16 action;
|
||||
bool flex;
|
||||
};
|
||||
|
||||
/* IGC supports a total of 32 NFC rules: 16 MAC address based, 8 VLAN priority
|
||||
* based, 8 ethertype based and 32 Flex filter based rules.
|
||||
*/
|
||||
#define IGC_MAX_RXNFC_RULES 64
|
||||
|
||||
struct igc_flex_filter {
|
||||
u8 index;
|
||||
u8 data[128];
|
||||
u8 mask[16];
|
||||
u8 length;
|
||||
u8 rx_queue;
|
||||
u8 prio;
|
||||
u8 immediate_irq;
|
||||
u8 drop;
|
||||
};
|
||||
|
||||
/* igc_desc_unused - calculate if we have unused descriptors */
|
||||
static inline u16 igc_desc_unused(const struct igc_ring *ring)
|
||||
{
|
||||
u16 ntc = ring->next_to_clean;
|
||||
u16 ntu = ring->next_to_use;
|
||||
|
||||
return ((ntc > ntu) ? 0 : ring->count) + ntc - ntu - 1;
|
||||
}
|
||||
|
||||
static inline s32 igc_get_phy_info(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.get_phy_info)
|
||||
return hw->phy.ops.get_phy_info(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igc_reset_phy(struct igc_hw *hw)
|
||||
{
|
||||
if (hw->phy.ops.reset)
|
||||
return hw->phy.ops.reset(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct netdev_queue *txring_txq(const struct igc_ring *tx_ring)
|
||||
{
|
||||
return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
|
||||
}
|
||||
|
||||
enum igc_ring_flags_t {
|
||||
IGC_RING_FLAG_RX_3K_BUFFER,
|
||||
IGC_RING_FLAG_RX_BUILD_SKB_ENABLED,
|
||||
IGC_RING_FLAG_RX_SCTP_CSUM,
|
||||
IGC_RING_FLAG_RX_LB_VLAN_BSWAP,
|
||||
IGC_RING_FLAG_TX_CTX_IDX,
|
||||
IGC_RING_FLAG_TX_DETECT_HANG,
|
||||
IGC_RING_FLAG_AF_XDP_ZC,
|
||||
};
|
||||
|
||||
#define ring_uses_large_buffer(ring) \
|
||||
test_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define set_ring_uses_large_buffer(ring) \
|
||||
set_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
#define clear_ring_uses_large_buffer(ring) \
|
||||
clear_bit(IGC_RING_FLAG_RX_3K_BUFFER, &(ring)->flags)
|
||||
|
||||
#define ring_uses_build_skb(ring) \
|
||||
test_bit(IGC_RING_FLAG_RX_BUILD_SKB_ENABLED, &(ring)->flags)
|
||||
|
||||
static inline unsigned int igc_rx_bufsz(struct igc_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return IGC_RXBUFFER_3072;
|
||||
|
||||
if (ring_uses_build_skb(ring))
|
||||
return IGC_MAX_FRAME_BUILD_SKB + IGC_TS_HDR_LEN;
|
||||
#endif
|
||||
return IGC_RXBUFFER_2048;
|
||||
}
|
||||
|
||||
static inline unsigned int igc_rx_pg_order(struct igc_ring *ring)
|
||||
{
|
||||
#if (PAGE_SIZE < 8192)
|
||||
if (ring_uses_large_buffer(ring))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data)
|
||||
{
|
||||
if (hw->phy.ops.read_reg)
|
||||
return hw->phy.ops.read_reg(hw, offset, data);
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
void igc_reinit_locked(struct igc_adapter *);
|
||||
struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
|
||||
u32 location);
|
||||
int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
|
||||
void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
|
||||
|
||||
void igc_ptp_init(struct igc_adapter *adapter);
|
||||
void igc_ptp_reset(struct igc_adapter *adapter);
|
||||
void igc_ptp_suspend(struct igc_adapter *adapter);
|
||||
void igc_ptp_stop(struct igc_adapter *adapter);
|
||||
ktime_t igc_ptp_rx_pktstamp(struct igc_adapter *adapter, __le32 *buf);
|
||||
int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);
|
||||
void igc_ptp_tx_hang(struct igc_adapter *adapter);
|
||||
void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts);
|
||||
|
||||
#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
|
||||
|
||||
#define IGC_TXD_DCMD (IGC_ADVTXD_DCMD_EOP | IGC_ADVTXD_DCMD_RS)
|
||||
|
||||
#define IGC_RX_DESC(R, i) \
|
||||
(&(((union igc_adv_rx_desc *)((R)->desc))[i]))
|
||||
#define IGC_TX_DESC(R, i) \
|
||||
(&(((union igc_adv_tx_desc *)((R)->desc))[i]))
|
||||
#define IGC_TX_CTXTDESC(R, i) \
|
||||
(&(((struct igc_adv_tx_context_desc *)((R)->desc))[i]))
|
||||
|
||||
#endif /* _IGC_H_ */
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/net_tstamp.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include <net/xdp.h>
|
||||
|
||||
#include "igc_hw-6.4-ethercat.h"
|
||||
|
||||
|
|
@ -267,11 +268,20 @@ struct igc_adapter {
|
|||
} perout[IGC_N_PEROUT];
|
||||
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
struct irq_work ec_watchdog_kicker;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct igc_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
void igc_up(struct igc_adapter *adapter);
|
||||
void igc_down(struct igc_adapter *adapter);
|
||||
int igc_open(struct net_device *netdev);
|
||||
|
|
|
|||
|
|
@ -282,11 +282,20 @@ struct igc_adapter {
|
|||
} perout[IGC_N_PEROUT];
|
||||
|
||||
/* EtherCAT device variables */
|
||||
ec_device_t *ecdev;
|
||||
ec_device_t *ecdev_;
|
||||
unsigned long ec_watchdog_jiffies;
|
||||
struct irq_work ec_watchdog_kicker;
|
||||
bool ecdev_initialized;
|
||||
};
|
||||
|
||||
static inline ec_device_t *get_ecdev(struct igc_adapter *adapter)
|
||||
{
|
||||
#ifdef EC_ENABLE_DRIVER_RESOURCE_VERIFYING
|
||||
WARN_ON(!adapter->ecdev_initialized);
|
||||
#endif
|
||||
return adapter->ecdev_;
|
||||
}
|
||||
|
||||
void igc_up(struct igc_adapter *adapter);
|
||||
void igc_down(struct igc_adapter *adapter);
|
||||
int igc_open(struct net_device *netdev);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,433 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "igc_hw-5.14-ethercat.h"
|
||||
#include "igc_i225-5.14-ethercat.h"
|
||||
#include "igc_mac-5.14-ethercat.h"
|
||||
#include "igc_base-5.14-ethercat.h"
|
||||
#include "igc-5.14-ethercat.h"
|
||||
|
||||
/**
|
||||
* igc_reset_hw_base - Reset hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This resets the hardware into a known state. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static s32 igc_reset_hw_base(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
u32 ctrl;
|
||||
|
||||
/* Prevent the PCI-E bus from sticking if there is no TLP connection
|
||||
* on the last TLP read/write transaction when MAC is reset.
|
||||
*/
|
||||
ret_val = igc_disable_pcie_master(hw);
|
||||
if (ret_val)
|
||||
hw_dbg("PCI-E Master disable polling has failed\n");
|
||||
|
||||
hw_dbg("Masking off all interrupts\n");
|
||||
wr32(IGC_IMC, 0xffffffff);
|
||||
|
||||
wr32(IGC_RCTL, 0);
|
||||
wr32(IGC_TCTL, IGC_TCTL_PSP);
|
||||
wrfl();
|
||||
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
ctrl = rd32(IGC_CTRL);
|
||||
|
||||
hw_dbg("Issuing a global reset to MAC\n");
|
||||
wr32(IGC_CTRL, ctrl | IGC_CTRL_DEV_RST);
|
||||
|
||||
ret_val = igc_get_auto_rd_done(hw);
|
||||
if (ret_val) {
|
||||
/* When auto config read does not complete, do not
|
||||
* return with an error. This can happen in situations
|
||||
* where there is no eeprom and prevents getting link.
|
||||
*/
|
||||
hw_dbg("Auto Read Done did not complete\n");
|
||||
}
|
||||
|
||||
/* Clear any pending interrupt events. */
|
||||
wr32(IGC_IMC, 0xffffffff);
|
||||
rd32(IGC_ICR);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_nvm_params_base - Init NVM func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_nvm_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = rd32(IGC_EECD);
|
||||
u16 size;
|
||||
|
||||
size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >>
|
||||
IGC_EECD_SIZE_EX_SHIFT);
|
||||
|
||||
/* Added to a constant, "size" becomes the left-shift value
|
||||
* for setting word_size.
|
||||
*/
|
||||
size += NVM_WORD_SIZE_BASE_SHIFT;
|
||||
|
||||
/* Just in case size is out of range, cap it to the largest
|
||||
* EEPROM size supported
|
||||
*/
|
||||
if (size > 15)
|
||||
size = 15;
|
||||
|
||||
nvm->type = igc_nvm_eeprom_spi;
|
||||
nvm->word_size = BIT(size);
|
||||
nvm->opcode_bits = 8;
|
||||
nvm->delay_usec = 1;
|
||||
|
||||
nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8;
|
||||
nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ?
|
||||
16 : 8;
|
||||
|
||||
if (nvm->word_size == BIT(15))
|
||||
nvm->page_size = 128;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_setup_copper_link_base - Configure copper link settings
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Configures the link for auto-neg or forced speed and duplex. Then we check
|
||||
* for link, once link is established calls to configure collision distance
|
||||
* and flow control are called.
|
||||
*/
|
||||
static s32 igc_setup_copper_link_base(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
u32 ctrl;
|
||||
|
||||
ctrl = rd32(IGC_CTRL);
|
||||
ctrl |= IGC_CTRL_SLU;
|
||||
ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
|
||||
wr32(IGC_CTRL, ctrl);
|
||||
|
||||
ret_val = igc_setup_copper_link(hw);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_mac_params_base - Init MAC func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_mac_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_dev_spec_base *dev_spec = &hw->dev_spec._base;
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
|
||||
/* Set mta register count */
|
||||
mac->mta_reg_count = 128;
|
||||
mac->rar_entry_count = IGC_RAR_ENTRIES;
|
||||
|
||||
/* reset */
|
||||
mac->ops.reset_hw = igc_reset_hw_base;
|
||||
|
||||
mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225;
|
||||
mac->ops.release_swfw_sync = igc_release_swfw_sync_i225;
|
||||
|
||||
/* Allow a single clear of the SW semaphore on I225 */
|
||||
if (mac->type == igc_i225)
|
||||
dev_spec->clear_semaphore_once = true;
|
||||
|
||||
/* physical interface link setup */
|
||||
mac->ops.setup_physical_interface = igc_setup_copper_link_base;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_phy_params_base - Init PHY func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_phy_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_phy_info *phy = &hw->phy;
|
||||
s32 ret_val = 0;
|
||||
|
||||
if (hw->phy.media_type != igc_media_type_copper) {
|
||||
phy->type = igc_phy_none;
|
||||
goto out;
|
||||
}
|
||||
|
||||
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500;
|
||||
phy->reset_delay_us = 100;
|
||||
|
||||
/* set lan id */
|
||||
hw->bus.func = (rd32(IGC_STATUS) & IGC_STATUS_FUNC_MASK) >>
|
||||
IGC_STATUS_FUNC_SHIFT;
|
||||
|
||||
/* Make sure the PHY is in a good state. Several people have reported
|
||||
* firmware leaving the PHY's page select register set to something
|
||||
* other than the default of zero, which causes the PHY ID read to
|
||||
* access something other than the intended register.
|
||||
*/
|
||||
ret_val = hw->phy.ops.reset(hw);
|
||||
if (ret_val) {
|
||||
hw_dbg("Error resetting the PHY\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = igc_get_phy_id(hw);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
igc_check_for_copper_link(hw);
|
||||
|
||||
/* Verify phy id and set remaining function pointers */
|
||||
switch (phy->id) {
|
||||
case I225_I_PHY_ID:
|
||||
phy->type = igc_phy_i225;
|
||||
break;
|
||||
default:
|
||||
ret_val = -IGC_ERR_PHY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static s32 igc_get_invariants_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
s32 ret_val = 0;
|
||||
|
||||
switch (hw->device_id) {
|
||||
case IGC_DEV_ID_I225_LM:
|
||||
case IGC_DEV_ID_I225_V:
|
||||
case IGC_DEV_ID_I225_I:
|
||||
case IGC_DEV_ID_I220_V:
|
||||
case IGC_DEV_ID_I225_K:
|
||||
case IGC_DEV_ID_I225_K2:
|
||||
case IGC_DEV_ID_I226_K:
|
||||
case IGC_DEV_ID_I225_LMVP:
|
||||
case IGC_DEV_ID_I225_IT:
|
||||
case IGC_DEV_ID_I226_LM:
|
||||
case IGC_DEV_ID_I226_V:
|
||||
case IGC_DEV_ID_I226_IT:
|
||||
case IGC_DEV_ID_I221_V:
|
||||
case IGC_DEV_ID_I226_BLANK_NVM:
|
||||
case IGC_DEV_ID_I225_BLANK_NVM:
|
||||
mac->type = igc_i225;
|
||||
break;
|
||||
default:
|
||||
return -IGC_ERR_MAC_INIT;
|
||||
}
|
||||
|
||||
hw->phy.media_type = igc_media_type_copper;
|
||||
|
||||
/* mac initialization and operations */
|
||||
ret_val = igc_init_mac_params_base(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
/* NVM initialization */
|
||||
ret_val = igc_init_nvm_params_base(hw);
|
||||
switch (hw->mac.type) {
|
||||
case igc_i225:
|
||||
ret_val = igc_init_nvm_params_i225(hw);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* setup PHY parameters */
|
||||
ret_val = igc_init_phy_params_base(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_acquire_phy_base - Acquire rights to access PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire access rights to the correct PHY. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static s32 igc_acquire_phy_base(struct igc_hw *hw)
|
||||
{
|
||||
u16 mask = IGC_SWFW_PHY0_SM;
|
||||
|
||||
return hw->mac.ops.acquire_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_release_phy_base - Release rights to access PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* A wrapper to release access rights to the correct PHY. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static void igc_release_phy_base(struct igc_hw *hw)
|
||||
{
|
||||
u16 mask = IGC_SWFW_PHY0_SM;
|
||||
|
||||
hw->mac.ops.release_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_hw_base - Initialize hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This inits the hardware readying it for operation.
|
||||
*/
|
||||
static s32 igc_init_hw_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
u16 i, rar_count = mac->rar_entry_count;
|
||||
s32 ret_val = 0;
|
||||
|
||||
/* Setup the receive address */
|
||||
igc_init_rx_addrs(hw, rar_count);
|
||||
|
||||
/* Zero out the Multicast HASH table */
|
||||
hw_dbg("Zeroing the MTA\n");
|
||||
for (i = 0; i < mac->mta_reg_count; i++)
|
||||
array_wr32(IGC_MTA, i, 0);
|
||||
|
||||
/* Zero out the Unicast HASH table */
|
||||
hw_dbg("Zeroing the UTA\n");
|
||||
for (i = 0; i < mac->uta_reg_count; i++)
|
||||
array_wr32(IGC_UTA, i, 0);
|
||||
|
||||
/* Setup link and flow control */
|
||||
ret_val = igc_setup_link(hw);
|
||||
|
||||
/* Clear all of the statistics registers (clear on read). It is
|
||||
* important that we do this after we have tried to establish link
|
||||
* because the symbol error count will increment wildly if there
|
||||
* is no link.
|
||||
*/
|
||||
igc_clear_hw_cntrs_base(hw);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_power_down_phy_copper_base - Remove link during PHY power down
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* In the case of a PHY power down to save power, or to turn off link during a
|
||||
* driver unload, or wake on lan is not enabled, remove the link.
|
||||
*/
|
||||
void igc_power_down_phy_copper_base(struct igc_hw *hw)
|
||||
{
|
||||
/* If the management interface is not enabled, then power down */
|
||||
if (!(igc_enable_mng_pass_thru(hw) || igc_check_reset_block(hw)))
|
||||
igc_power_down_phy_copper(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_rx_fifo_flush_base - Clean rx fifo after Rx enable
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* After Rx enable, if manageability is enabled then there is likely some
|
||||
* bad data at the start of the fifo and possibly in the DMA fifo. This
|
||||
* function clears the fifos and flushes any packets that came in as rx was
|
||||
* being enabled.
|
||||
*/
|
||||
void igc_rx_fifo_flush_base(struct igc_hw *hw)
|
||||
{
|
||||
u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
|
||||
int i, ms_wait;
|
||||
|
||||
/* disable IPv6 options as per hardware errata */
|
||||
rfctl = rd32(IGC_RFCTL);
|
||||
rfctl |= IGC_RFCTL_IPV6_EX_DIS;
|
||||
wr32(IGC_RFCTL, rfctl);
|
||||
|
||||
if (!(rd32(IGC_MANC) & IGC_MANC_RCV_TCO_EN))
|
||||
return;
|
||||
|
||||
/* Disable all Rx queues */
|
||||
for (i = 0; i < 4; i++) {
|
||||
rxdctl[i] = rd32(IGC_RXDCTL(i));
|
||||
wr32(IGC_RXDCTL(i),
|
||||
rxdctl[i] & ~IGC_RXDCTL_QUEUE_ENABLE);
|
||||
}
|
||||
/* Poll all queues to verify they have shut down */
|
||||
for (ms_wait = 0; ms_wait < 10; ms_wait++) {
|
||||
usleep_range(1000, 2000);
|
||||
rx_enabled = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
rx_enabled |= rd32(IGC_RXDCTL(i));
|
||||
if (!(rx_enabled & IGC_RXDCTL_QUEUE_ENABLE))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ms_wait == 10)
|
||||
hw_dbg("Queue disable timed out after 10ms\n");
|
||||
|
||||
/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
|
||||
* incoming packets are rejected. Set enable and wait 2ms so that
|
||||
* any packet that was coming in as RCTL.EN was set is flushed
|
||||
*/
|
||||
wr32(IGC_RFCTL, rfctl & ~IGC_RFCTL_LEF);
|
||||
|
||||
rlpml = rd32(IGC_RLPML);
|
||||
wr32(IGC_RLPML, 0);
|
||||
|
||||
rctl = rd32(IGC_RCTL);
|
||||
temp_rctl = rctl & ~(IGC_RCTL_EN | IGC_RCTL_SBP);
|
||||
temp_rctl |= IGC_RCTL_LPE;
|
||||
|
||||
wr32(IGC_RCTL, temp_rctl);
|
||||
wr32(IGC_RCTL, temp_rctl | IGC_RCTL_EN);
|
||||
wrfl();
|
||||
usleep_range(2000, 3000);
|
||||
|
||||
/* Enable Rx queues that were previously enabled and restore our
|
||||
* previous state
|
||||
*/
|
||||
for (i = 0; i < 4; i++)
|
||||
wr32(IGC_RXDCTL(i), rxdctl[i]);
|
||||
wr32(IGC_RCTL, rctl);
|
||||
wrfl();
|
||||
|
||||
wr32(IGC_RLPML, rlpml);
|
||||
wr32(IGC_RFCTL, rfctl);
|
||||
|
||||
/* Flush receive errors generated by workaround */
|
||||
rd32(IGC_ROC);
|
||||
rd32(IGC_RNBC);
|
||||
rd32(IGC_MPC);
|
||||
}
|
||||
|
||||
static struct igc_mac_operations igc_mac_ops_base = {
|
||||
.init_hw = igc_init_hw_base,
|
||||
.check_for_link = igc_check_for_copper_link,
|
||||
.rar_set = igc_rar_set,
|
||||
.read_mac_addr = igc_read_mac_addr,
|
||||
.get_speed_and_duplex = igc_get_speed_and_duplex_copper,
|
||||
};
|
||||
|
||||
static const struct igc_phy_operations igc_phy_ops_base = {
|
||||
.acquire = igc_acquire_phy_base,
|
||||
.release = igc_release_phy_base,
|
||||
.reset = igc_phy_hw_reset,
|
||||
.read_reg = igc_read_phy_reg_gpy,
|
||||
.write_reg = igc_write_phy_reg_gpy,
|
||||
};
|
||||
|
||||
const struct igc_info igc_base_info = {
|
||||
.get_invariants = igc_get_invariants_base,
|
||||
.mac_ops = &igc_mac_ops_base,
|
||||
.phy_ops = &igc_phy_ops_base,
|
||||
};
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_BASE_H_
|
||||
#define _IGC_BASE_H_
|
||||
|
||||
/* forward declaration */
|
||||
void igc_rx_fifo_flush_base(struct igc_hw *hw);
|
||||
void igc_power_down_phy_copper_base(struct igc_hw *hw);
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union igc_adv_tx_desc {
|
||||
struct {
|
||||
__le64 buffer_addr; /* Address of descriptor's data buf */
|
||||
__le32 cmd_type_len;
|
||||
__le32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
__le64 rsvd; /* Reserved */
|
||||
__le32 nxtseq_seed;
|
||||
__le32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Context descriptors */
|
||||
struct igc_adv_tx_context_desc {
|
||||
__le32 vlan_macip_lens;
|
||||
__le32 launch_time;
|
||||
__le32 type_tucmd_mlhl;
|
||||
__le32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define IGC_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
|
||||
#define IGC_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define IGC_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define IGC_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define IGC_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define IGC_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define IGC_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define IGC_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define IGC_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define IGC_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
#define IGC_RAR_ENTRIES 16
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union igc_adv_rx_desc {
|
||||
struct {
|
||||
__le64 pkt_addr; /* Packet buffer address */
|
||||
__le64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
union {
|
||||
__le32 data;
|
||||
struct {
|
||||
__le16 pkt_info; /*RSS type, Pkt type*/
|
||||
/* Split Header, header buffer len */
|
||||
__le16 hdr_info;
|
||||
} hs_rss;
|
||||
} lo_dword;
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length; /* Packet length */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
|
||||
#define IGC_TXDCTL_SWFLUSH 0x04000000 /* Transmit Software Flush */
|
||||
|
||||
/* Additional Receive Descriptor Control definitions */
|
||||
#define IGC_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */
|
||||
#define IGC_RXDCTL_SWFLUSH 0x04000000 /* Receive Software Flush */
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define IGC_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define IGC_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
|
||||
#endif /* _IGC_BASE_H */
|
||||
|
|
@ -0,0 +1,433 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "igc_hw.h"
|
||||
#include "igc_i225.h"
|
||||
#include "igc_mac.h"
|
||||
#include "igc_base.h"
|
||||
#include "igc.h"
|
||||
|
||||
/**
|
||||
* igc_reset_hw_base - Reset hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This resets the hardware into a known state. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static s32 igc_reset_hw_base(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
u32 ctrl;
|
||||
|
||||
/* Prevent the PCI-E bus from sticking if there is no TLP connection
|
||||
* on the last TLP read/write transaction when MAC is reset.
|
||||
*/
|
||||
ret_val = igc_disable_pcie_master(hw);
|
||||
if (ret_val)
|
||||
hw_dbg("PCI-E Master disable polling has failed\n");
|
||||
|
||||
hw_dbg("Masking off all interrupts\n");
|
||||
wr32(IGC_IMC, 0xffffffff);
|
||||
|
||||
wr32(IGC_RCTL, 0);
|
||||
wr32(IGC_TCTL, IGC_TCTL_PSP);
|
||||
wrfl();
|
||||
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
ctrl = rd32(IGC_CTRL);
|
||||
|
||||
hw_dbg("Issuing a global reset to MAC\n");
|
||||
wr32(IGC_CTRL, ctrl | IGC_CTRL_DEV_RST);
|
||||
|
||||
ret_val = igc_get_auto_rd_done(hw);
|
||||
if (ret_val) {
|
||||
/* When auto config read does not complete, do not
|
||||
* return with an error. This can happen in situations
|
||||
* where there is no eeprom and prevents getting link.
|
||||
*/
|
||||
hw_dbg("Auto Read Done did not complete\n");
|
||||
}
|
||||
|
||||
/* Clear any pending interrupt events. */
|
||||
wr32(IGC_IMC, 0xffffffff);
|
||||
rd32(IGC_ICR);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_nvm_params_base - Init NVM func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_nvm_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = rd32(IGC_EECD);
|
||||
u16 size;
|
||||
|
||||
size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >>
|
||||
IGC_EECD_SIZE_EX_SHIFT);
|
||||
|
||||
/* Added to a constant, "size" becomes the left-shift value
|
||||
* for setting word_size.
|
||||
*/
|
||||
size += NVM_WORD_SIZE_BASE_SHIFT;
|
||||
|
||||
/* Just in case size is out of range, cap it to the largest
|
||||
* EEPROM size supported
|
||||
*/
|
||||
if (size > 15)
|
||||
size = 15;
|
||||
|
||||
nvm->type = igc_nvm_eeprom_spi;
|
||||
nvm->word_size = BIT(size);
|
||||
nvm->opcode_bits = 8;
|
||||
nvm->delay_usec = 1;
|
||||
|
||||
nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8;
|
||||
nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ?
|
||||
16 : 8;
|
||||
|
||||
if (nvm->word_size == BIT(15))
|
||||
nvm->page_size = 128;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_setup_copper_link_base - Configure copper link settings
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Configures the link for auto-neg or forced speed and duplex. Then we check
|
||||
* for link, once link is established calls to configure collision distance
|
||||
* and flow control are called.
|
||||
*/
|
||||
static s32 igc_setup_copper_link_base(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
u32 ctrl;
|
||||
|
||||
ctrl = rd32(IGC_CTRL);
|
||||
ctrl |= IGC_CTRL_SLU;
|
||||
ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
|
||||
wr32(IGC_CTRL, ctrl);
|
||||
|
||||
ret_val = igc_setup_copper_link(hw);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_mac_params_base - Init MAC func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_mac_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_dev_spec_base *dev_spec = &hw->dev_spec._base;
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
|
||||
/* Set mta register count */
|
||||
mac->mta_reg_count = 128;
|
||||
mac->rar_entry_count = IGC_RAR_ENTRIES;
|
||||
|
||||
/* reset */
|
||||
mac->ops.reset_hw = igc_reset_hw_base;
|
||||
|
||||
mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225;
|
||||
mac->ops.release_swfw_sync = igc_release_swfw_sync_i225;
|
||||
|
||||
/* Allow a single clear of the SW semaphore on I225 */
|
||||
if (mac->type == igc_i225)
|
||||
dev_spec->clear_semaphore_once = true;
|
||||
|
||||
/* physical interface link setup */
|
||||
mac->ops.setup_physical_interface = igc_setup_copper_link_base;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_phy_params_base - Init PHY func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_phy_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_phy_info *phy = &hw->phy;
|
||||
s32 ret_val = 0;
|
||||
|
||||
if (hw->phy.media_type != igc_media_type_copper) {
|
||||
phy->type = igc_phy_none;
|
||||
goto out;
|
||||
}
|
||||
|
||||
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500;
|
||||
phy->reset_delay_us = 100;
|
||||
|
||||
/* set lan id */
|
||||
hw->bus.func = (rd32(IGC_STATUS) & IGC_STATUS_FUNC_MASK) >>
|
||||
IGC_STATUS_FUNC_SHIFT;
|
||||
|
||||
/* Make sure the PHY is in a good state. Several people have reported
|
||||
* firmware leaving the PHY's page select register set to something
|
||||
* other than the default of zero, which causes the PHY ID read to
|
||||
* access something other than the intended register.
|
||||
*/
|
||||
ret_val = hw->phy.ops.reset(hw);
|
||||
if (ret_val) {
|
||||
hw_dbg("Error resetting the PHY\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = igc_get_phy_id(hw);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
igc_check_for_copper_link(hw);
|
||||
|
||||
/* Verify phy id and set remaining function pointers */
|
||||
switch (phy->id) {
|
||||
case I225_I_PHY_ID:
|
||||
phy->type = igc_phy_i225;
|
||||
break;
|
||||
default:
|
||||
ret_val = -IGC_ERR_PHY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static s32 igc_get_invariants_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
s32 ret_val = 0;
|
||||
|
||||
switch (hw->device_id) {
|
||||
case IGC_DEV_ID_I225_LM:
|
||||
case IGC_DEV_ID_I225_V:
|
||||
case IGC_DEV_ID_I225_I:
|
||||
case IGC_DEV_ID_I220_V:
|
||||
case IGC_DEV_ID_I225_K:
|
||||
case IGC_DEV_ID_I225_K2:
|
||||
case IGC_DEV_ID_I226_K:
|
||||
case IGC_DEV_ID_I225_LMVP:
|
||||
case IGC_DEV_ID_I225_IT:
|
||||
case IGC_DEV_ID_I226_LM:
|
||||
case IGC_DEV_ID_I226_V:
|
||||
case IGC_DEV_ID_I226_IT:
|
||||
case IGC_DEV_ID_I221_V:
|
||||
case IGC_DEV_ID_I226_BLANK_NVM:
|
||||
case IGC_DEV_ID_I225_BLANK_NVM:
|
||||
mac->type = igc_i225;
|
||||
break;
|
||||
default:
|
||||
return -IGC_ERR_MAC_INIT;
|
||||
}
|
||||
|
||||
hw->phy.media_type = igc_media_type_copper;
|
||||
|
||||
/* mac initialization and operations */
|
||||
ret_val = igc_init_mac_params_base(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
/* NVM initialization */
|
||||
ret_val = igc_init_nvm_params_base(hw);
|
||||
switch (hw->mac.type) {
|
||||
case igc_i225:
|
||||
ret_val = igc_init_nvm_params_i225(hw);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* setup PHY parameters */
|
||||
ret_val = igc_init_phy_params_base(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_acquire_phy_base - Acquire rights to access PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire access rights to the correct PHY. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static s32 igc_acquire_phy_base(struct igc_hw *hw)
|
||||
{
|
||||
u16 mask = IGC_SWFW_PHY0_SM;
|
||||
|
||||
return hw->mac.ops.acquire_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_release_phy_base - Release rights to access PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* A wrapper to release access rights to the correct PHY. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static void igc_release_phy_base(struct igc_hw *hw)
|
||||
{
|
||||
u16 mask = IGC_SWFW_PHY0_SM;
|
||||
|
||||
hw->mac.ops.release_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_hw_base - Initialize hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This inits the hardware readying it for operation.
|
||||
*/
|
||||
static s32 igc_init_hw_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
u16 i, rar_count = mac->rar_entry_count;
|
||||
s32 ret_val = 0;
|
||||
|
||||
/* Setup the receive address */
|
||||
igc_init_rx_addrs(hw, rar_count);
|
||||
|
||||
/* Zero out the Multicast HASH table */
|
||||
hw_dbg("Zeroing the MTA\n");
|
||||
for (i = 0; i < mac->mta_reg_count; i++)
|
||||
array_wr32(IGC_MTA, i, 0);
|
||||
|
||||
/* Zero out the Unicast HASH table */
|
||||
hw_dbg("Zeroing the UTA\n");
|
||||
for (i = 0; i < mac->uta_reg_count; i++)
|
||||
array_wr32(IGC_UTA, i, 0);
|
||||
|
||||
/* Setup link and flow control */
|
||||
ret_val = igc_setup_link(hw);
|
||||
|
||||
/* Clear all of the statistics registers (clear on read). It is
|
||||
* important that we do this after we have tried to establish link
|
||||
* because the symbol error count will increment wildly if there
|
||||
* is no link.
|
||||
*/
|
||||
igc_clear_hw_cntrs_base(hw);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_power_down_phy_copper_base - Remove link during PHY power down
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* In the case of a PHY power down to save power, or to turn off link during a
|
||||
* driver unload, or wake on lan is not enabled, remove the link.
|
||||
*/
|
||||
void igc_power_down_phy_copper_base(struct igc_hw *hw)
|
||||
{
|
||||
/* If the management interface is not enabled, then power down */
|
||||
if (!(igc_enable_mng_pass_thru(hw) || igc_check_reset_block(hw)))
|
||||
igc_power_down_phy_copper(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_rx_fifo_flush_base - Clean rx fifo after Rx enable
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* After Rx enable, if manageability is enabled then there is likely some
|
||||
* bad data at the start of the fifo and possibly in the DMA fifo. This
|
||||
* function clears the fifos and flushes any packets that came in as rx was
|
||||
* being enabled.
|
||||
*/
|
||||
void igc_rx_fifo_flush_base(struct igc_hw *hw)
|
||||
{
|
||||
u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
|
||||
int i, ms_wait;
|
||||
|
||||
/* disable IPv6 options as per hardware errata */
|
||||
rfctl = rd32(IGC_RFCTL);
|
||||
rfctl |= IGC_RFCTL_IPV6_EX_DIS;
|
||||
wr32(IGC_RFCTL, rfctl);
|
||||
|
||||
if (!(rd32(IGC_MANC) & IGC_MANC_RCV_TCO_EN))
|
||||
return;
|
||||
|
||||
/* Disable all Rx queues */
|
||||
for (i = 0; i < 4; i++) {
|
||||
rxdctl[i] = rd32(IGC_RXDCTL(i));
|
||||
wr32(IGC_RXDCTL(i),
|
||||
rxdctl[i] & ~IGC_RXDCTL_QUEUE_ENABLE);
|
||||
}
|
||||
/* Poll all queues to verify they have shut down */
|
||||
for (ms_wait = 0; ms_wait < 10; ms_wait++) {
|
||||
usleep_range(1000, 2000);
|
||||
rx_enabled = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
rx_enabled |= rd32(IGC_RXDCTL(i));
|
||||
if (!(rx_enabled & IGC_RXDCTL_QUEUE_ENABLE))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ms_wait == 10)
|
||||
hw_dbg("Queue disable timed out after 10ms\n");
|
||||
|
||||
/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
|
||||
* incoming packets are rejected. Set enable and wait 2ms so that
|
||||
* any packet that was coming in as RCTL.EN was set is flushed
|
||||
*/
|
||||
wr32(IGC_RFCTL, rfctl & ~IGC_RFCTL_LEF);
|
||||
|
||||
rlpml = rd32(IGC_RLPML);
|
||||
wr32(IGC_RLPML, 0);
|
||||
|
||||
rctl = rd32(IGC_RCTL);
|
||||
temp_rctl = rctl & ~(IGC_RCTL_EN | IGC_RCTL_SBP);
|
||||
temp_rctl |= IGC_RCTL_LPE;
|
||||
|
||||
wr32(IGC_RCTL, temp_rctl);
|
||||
wr32(IGC_RCTL, temp_rctl | IGC_RCTL_EN);
|
||||
wrfl();
|
||||
usleep_range(2000, 3000);
|
||||
|
||||
/* Enable Rx queues that were previously enabled and restore our
|
||||
* previous state
|
||||
*/
|
||||
for (i = 0; i < 4; i++)
|
||||
wr32(IGC_RXDCTL(i), rxdctl[i]);
|
||||
wr32(IGC_RCTL, rctl);
|
||||
wrfl();
|
||||
|
||||
wr32(IGC_RLPML, rlpml);
|
||||
wr32(IGC_RFCTL, rfctl);
|
||||
|
||||
/* Flush receive errors generated by workaround */
|
||||
rd32(IGC_ROC);
|
||||
rd32(IGC_RNBC);
|
||||
rd32(IGC_MPC);
|
||||
}
|
||||
|
||||
static struct igc_mac_operations igc_mac_ops_base = {
|
||||
.init_hw = igc_init_hw_base,
|
||||
.check_for_link = igc_check_for_copper_link,
|
||||
.rar_set = igc_rar_set,
|
||||
.read_mac_addr = igc_read_mac_addr,
|
||||
.get_speed_and_duplex = igc_get_speed_and_duplex_copper,
|
||||
};
|
||||
|
||||
static const struct igc_phy_operations igc_phy_ops_base = {
|
||||
.acquire = igc_acquire_phy_base,
|
||||
.release = igc_release_phy_base,
|
||||
.reset = igc_phy_hw_reset,
|
||||
.read_reg = igc_read_phy_reg_gpy,
|
||||
.write_reg = igc_write_phy_reg_gpy,
|
||||
};
|
||||
|
||||
const struct igc_info igc_base_info = {
|
||||
.get_invariants = igc_get_invariants_base,
|
||||
.mac_ops = &igc_mac_ops_base,
|
||||
.phy_ops = &igc_phy_ops_base,
|
||||
};
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_BASE_H_
|
||||
#define _IGC_BASE_H_
|
||||
|
||||
/* forward declaration */
|
||||
void igc_rx_fifo_flush_base(struct igc_hw *hw);
|
||||
void igc_power_down_phy_copper_base(struct igc_hw *hw);
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union igc_adv_tx_desc {
|
||||
struct {
|
||||
__le64 buffer_addr; /* Address of descriptor's data buf */
|
||||
__le32 cmd_type_len;
|
||||
__le32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
__le64 rsvd; /* Reserved */
|
||||
__le32 nxtseq_seed;
|
||||
__le32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Context descriptors */
|
||||
struct igc_adv_tx_context_desc {
|
||||
__le32 vlan_macip_lens;
|
||||
__le32 launch_time;
|
||||
__le32 type_tucmd_mlhl;
|
||||
__le32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define IGC_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
|
||||
#define IGC_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define IGC_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define IGC_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define IGC_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define IGC_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define IGC_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define IGC_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define IGC_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define IGC_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
#define IGC_RAR_ENTRIES 16
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union igc_adv_rx_desc {
|
||||
struct {
|
||||
__le64 pkt_addr; /* Packet buffer address */
|
||||
__le64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
union {
|
||||
__le32 data;
|
||||
struct {
|
||||
__le16 pkt_info; /*RSS type, Pkt type*/
|
||||
/* Split Header, header buffer len */
|
||||
__le16 hdr_info;
|
||||
} hs_rss;
|
||||
} lo_dword;
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length; /* Packet length */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
|
||||
#define IGC_TXDCTL_SWFLUSH 0x04000000 /* Transmit Software Flush */
|
||||
|
||||
/* Additional Receive Descriptor Control definitions */
|
||||
#define IGC_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */
|
||||
#define IGC_RXDCTL_SWFLUSH 0x04000000 /* Receive Software Flush */
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define IGC_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define IGC_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
|
||||
#endif /* _IGC_BASE_H */
|
||||
|
|
@ -0,0 +1,419 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "igc_hw-6.1-ethercat.h"
|
||||
#include "igc_i225-6.1-ethercat.h"
|
||||
#include "igc_mac-6.1-ethercat.h"
|
||||
#include "igc_base-6.1-ethercat.h"
|
||||
#include "igc-6.1-ethercat.h"
|
||||
|
||||
/**
|
||||
* igc_reset_hw_base - Reset hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This resets the hardware into a known state. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static s32 igc_reset_hw_base(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
u32 ctrl;
|
||||
|
||||
/* Prevent the PCI-E bus from sticking if there is no TLP connection
|
||||
* on the last TLP read/write transaction when MAC is reset.
|
||||
*/
|
||||
ret_val = igc_disable_pcie_master(hw);
|
||||
if (ret_val)
|
||||
hw_dbg("PCI-E Master disable polling has failed\n");
|
||||
|
||||
hw_dbg("Masking off all interrupts\n");
|
||||
wr32(IGC_IMC, 0xffffffff);
|
||||
|
||||
wr32(IGC_RCTL, 0);
|
||||
wr32(IGC_TCTL, IGC_TCTL_PSP);
|
||||
wrfl();
|
||||
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
ctrl = rd32(IGC_CTRL);
|
||||
|
||||
hw_dbg("Issuing a global reset to MAC\n");
|
||||
wr32(IGC_CTRL, ctrl | IGC_CTRL_RST);
|
||||
|
||||
ret_val = igc_get_auto_rd_done(hw);
|
||||
if (ret_val) {
|
||||
/* When auto config read does not complete, do not
|
||||
* return with an error. This can happen in situations
|
||||
* where there is no eeprom and prevents getting link.
|
||||
*/
|
||||
hw_dbg("Auto Read Done did not complete\n");
|
||||
}
|
||||
|
||||
/* Clear any pending interrupt events. */
|
||||
wr32(IGC_IMC, 0xffffffff);
|
||||
rd32(IGC_ICR);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_nvm_params_base - Init NVM func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_nvm_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = rd32(IGC_EECD);
|
||||
u16 size;
|
||||
|
||||
size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >>
|
||||
IGC_EECD_SIZE_EX_SHIFT);
|
||||
|
||||
/* Added to a constant, "size" becomes the left-shift value
|
||||
* for setting word_size.
|
||||
*/
|
||||
size += NVM_WORD_SIZE_BASE_SHIFT;
|
||||
|
||||
/* Just in case size is out of range, cap it to the largest
|
||||
* EEPROM size supported
|
||||
*/
|
||||
if (size > 15)
|
||||
size = 15;
|
||||
|
||||
nvm->type = igc_nvm_eeprom_spi;
|
||||
nvm->word_size = BIT(size);
|
||||
nvm->opcode_bits = 8;
|
||||
nvm->delay_usec = 1;
|
||||
|
||||
nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8;
|
||||
nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ?
|
||||
16 : 8;
|
||||
|
||||
if (nvm->word_size == BIT(15))
|
||||
nvm->page_size = 128;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_setup_copper_link_base - Configure copper link settings
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Configures the link for auto-neg or forced speed and duplex. Then we check
|
||||
* for link, once link is established calls to configure collision distance
|
||||
* and flow control are called.
|
||||
*/
|
||||
static s32 igc_setup_copper_link_base(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
u32 ctrl;
|
||||
|
||||
ctrl = rd32(IGC_CTRL);
|
||||
ctrl |= IGC_CTRL_SLU;
|
||||
ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
|
||||
wr32(IGC_CTRL, ctrl);
|
||||
|
||||
ret_val = igc_setup_copper_link(hw);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_mac_params_base - Init MAC func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_mac_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_dev_spec_base *dev_spec = &hw->dev_spec._base;
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
|
||||
/* Set mta register count */
|
||||
mac->mta_reg_count = 128;
|
||||
mac->rar_entry_count = IGC_RAR_ENTRIES;
|
||||
|
||||
/* reset */
|
||||
mac->ops.reset_hw = igc_reset_hw_base;
|
||||
|
||||
mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225;
|
||||
mac->ops.release_swfw_sync = igc_release_swfw_sync_i225;
|
||||
|
||||
/* Allow a single clear of the SW semaphore on I225 */
|
||||
if (mac->type == igc_i225)
|
||||
dev_spec->clear_semaphore_once = true;
|
||||
|
||||
/* physical interface link setup */
|
||||
mac->ops.setup_physical_interface = igc_setup_copper_link_base;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_phy_params_base - Init PHY func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_phy_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_phy_info *phy = &hw->phy;
|
||||
s32 ret_val = 0;
|
||||
|
||||
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500;
|
||||
phy->reset_delay_us = 100;
|
||||
|
||||
/* set lan id */
|
||||
hw->bus.func = (rd32(IGC_STATUS) & IGC_STATUS_FUNC_MASK) >>
|
||||
IGC_STATUS_FUNC_SHIFT;
|
||||
|
||||
/* Make sure the PHY is in a good state. Several people have reported
|
||||
* firmware leaving the PHY's page select register set to something
|
||||
* other than the default of zero, which causes the PHY ID read to
|
||||
* access something other than the intended register.
|
||||
*/
|
||||
ret_val = hw->phy.ops.reset(hw);
|
||||
if (ret_val) {
|
||||
hw_dbg("Error resetting the PHY\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = igc_get_phy_id(hw);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
igc_check_for_copper_link(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static s32 igc_get_invariants_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
s32 ret_val = 0;
|
||||
|
||||
switch (hw->device_id) {
|
||||
case IGC_DEV_ID_I225_LM:
|
||||
case IGC_DEV_ID_I225_V:
|
||||
case IGC_DEV_ID_I225_I:
|
||||
case IGC_DEV_ID_I220_V:
|
||||
case IGC_DEV_ID_I225_K:
|
||||
case IGC_DEV_ID_I225_K2:
|
||||
case IGC_DEV_ID_I226_K:
|
||||
case IGC_DEV_ID_I225_LMVP:
|
||||
case IGC_DEV_ID_I226_LMVP:
|
||||
case IGC_DEV_ID_I225_IT:
|
||||
case IGC_DEV_ID_I226_LM:
|
||||
case IGC_DEV_ID_I226_V:
|
||||
case IGC_DEV_ID_I226_IT:
|
||||
case IGC_DEV_ID_I221_V:
|
||||
case IGC_DEV_ID_I226_BLANK_NVM:
|
||||
case IGC_DEV_ID_I225_BLANK_NVM:
|
||||
mac->type = igc_i225;
|
||||
break;
|
||||
default:
|
||||
return -IGC_ERR_MAC_INIT;
|
||||
}
|
||||
|
||||
hw->phy.media_type = igc_media_type_copper;
|
||||
|
||||
/* mac initialization and operations */
|
||||
ret_val = igc_init_mac_params_base(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
/* NVM initialization */
|
||||
ret_val = igc_init_nvm_params_base(hw);
|
||||
switch (hw->mac.type) {
|
||||
case igc_i225:
|
||||
ret_val = igc_init_nvm_params_i225(hw);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* setup PHY parameters */
|
||||
ret_val = igc_init_phy_params_base(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_acquire_phy_base - Acquire rights to access PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire access rights to the correct PHY. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static s32 igc_acquire_phy_base(struct igc_hw *hw)
|
||||
{
|
||||
u16 mask = IGC_SWFW_PHY0_SM;
|
||||
|
||||
return hw->mac.ops.acquire_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_release_phy_base - Release rights to access PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* A wrapper to release access rights to the correct PHY. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static void igc_release_phy_base(struct igc_hw *hw)
|
||||
{
|
||||
u16 mask = IGC_SWFW_PHY0_SM;
|
||||
|
||||
hw->mac.ops.release_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_hw_base - Initialize hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This inits the hardware readying it for operation.
|
||||
*/
|
||||
static s32 igc_init_hw_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
u16 i, rar_count = mac->rar_entry_count;
|
||||
s32 ret_val = 0;
|
||||
|
||||
/* Setup the receive address */
|
||||
igc_init_rx_addrs(hw, rar_count);
|
||||
|
||||
/* Zero out the Multicast HASH table */
|
||||
hw_dbg("Zeroing the MTA\n");
|
||||
for (i = 0; i < mac->mta_reg_count; i++)
|
||||
array_wr32(IGC_MTA, i, 0);
|
||||
|
||||
/* Zero out the Unicast HASH table */
|
||||
hw_dbg("Zeroing the UTA\n");
|
||||
for (i = 0; i < mac->uta_reg_count; i++)
|
||||
array_wr32(IGC_UTA, i, 0);
|
||||
|
||||
/* Setup link and flow control */
|
||||
ret_val = igc_setup_link(hw);
|
||||
|
||||
/* Clear all of the statistics registers (clear on read). It is
|
||||
* important that we do this after we have tried to establish link
|
||||
* because the symbol error count will increment wildly if there
|
||||
* is no link.
|
||||
*/
|
||||
igc_clear_hw_cntrs_base(hw);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_power_down_phy_copper_base - Remove link during PHY power down
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* In the case of a PHY power down to save power, or to turn off link during a
|
||||
* driver unload, or wake on lan is not enabled, remove the link.
|
||||
*/
|
||||
void igc_power_down_phy_copper_base(struct igc_hw *hw)
|
||||
{
|
||||
/* If the management interface is not enabled, then power down */
|
||||
if (!(igc_enable_mng_pass_thru(hw) || igc_check_reset_block(hw)))
|
||||
igc_power_down_phy_copper(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_rx_fifo_flush_base - Clean rx fifo after Rx enable
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* After Rx enable, if manageability is enabled then there is likely some
|
||||
* bad data at the start of the fifo and possibly in the DMA fifo. This
|
||||
* function clears the fifos and flushes any packets that came in as rx was
|
||||
* being enabled.
|
||||
*/
|
||||
void igc_rx_fifo_flush_base(struct igc_hw *hw)
|
||||
{
|
||||
u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
|
||||
int i, ms_wait;
|
||||
|
||||
/* disable IPv6 options as per hardware errata */
|
||||
rfctl = rd32(IGC_RFCTL);
|
||||
rfctl |= IGC_RFCTL_IPV6_EX_DIS;
|
||||
wr32(IGC_RFCTL, rfctl);
|
||||
|
||||
if (!(rd32(IGC_MANC) & IGC_MANC_RCV_TCO_EN))
|
||||
return;
|
||||
|
||||
/* Disable all Rx queues */
|
||||
for (i = 0; i < 4; i++) {
|
||||
rxdctl[i] = rd32(IGC_RXDCTL(i));
|
||||
wr32(IGC_RXDCTL(i),
|
||||
rxdctl[i] & ~IGC_RXDCTL_QUEUE_ENABLE);
|
||||
}
|
||||
/* Poll all queues to verify they have shut down */
|
||||
for (ms_wait = 0; ms_wait < 10; ms_wait++) {
|
||||
usleep_range(1000, 2000);
|
||||
rx_enabled = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
rx_enabled |= rd32(IGC_RXDCTL(i));
|
||||
if (!(rx_enabled & IGC_RXDCTL_QUEUE_ENABLE))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ms_wait == 10)
|
||||
hw_dbg("Queue disable timed out after 10ms\n");
|
||||
|
||||
/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
|
||||
* incoming packets are rejected. Set enable and wait 2ms so that
|
||||
* any packet that was coming in as RCTL.EN was set is flushed
|
||||
*/
|
||||
wr32(IGC_RFCTL, rfctl & ~IGC_RFCTL_LEF);
|
||||
|
||||
rlpml = rd32(IGC_RLPML);
|
||||
wr32(IGC_RLPML, 0);
|
||||
|
||||
rctl = rd32(IGC_RCTL);
|
||||
temp_rctl = rctl & ~(IGC_RCTL_EN | IGC_RCTL_SBP);
|
||||
temp_rctl |= IGC_RCTL_LPE;
|
||||
|
||||
wr32(IGC_RCTL, temp_rctl);
|
||||
wr32(IGC_RCTL, temp_rctl | IGC_RCTL_EN);
|
||||
wrfl();
|
||||
usleep_range(2000, 3000);
|
||||
|
||||
/* Enable Rx queues that were previously enabled and restore our
|
||||
* previous state
|
||||
*/
|
||||
for (i = 0; i < 4; i++)
|
||||
wr32(IGC_RXDCTL(i), rxdctl[i]);
|
||||
wr32(IGC_RCTL, rctl);
|
||||
wrfl();
|
||||
|
||||
wr32(IGC_RLPML, rlpml);
|
||||
wr32(IGC_RFCTL, rfctl);
|
||||
|
||||
/* Flush receive errors generated by workaround */
|
||||
rd32(IGC_ROC);
|
||||
rd32(IGC_RNBC);
|
||||
rd32(IGC_MPC);
|
||||
}
|
||||
|
||||
static struct igc_mac_operations igc_mac_ops_base = {
|
||||
.init_hw = igc_init_hw_base,
|
||||
.check_for_link = igc_check_for_copper_link,
|
||||
.rar_set = igc_rar_set,
|
||||
.read_mac_addr = igc_read_mac_addr,
|
||||
.get_speed_and_duplex = igc_get_speed_and_duplex_copper,
|
||||
};
|
||||
|
||||
static const struct igc_phy_operations igc_phy_ops_base = {
|
||||
.acquire = igc_acquire_phy_base,
|
||||
.release = igc_release_phy_base,
|
||||
.reset = igc_phy_hw_reset,
|
||||
.read_reg = igc_read_phy_reg_gpy,
|
||||
.write_reg = igc_write_phy_reg_gpy,
|
||||
};
|
||||
|
||||
const struct igc_info igc_base_info = {
|
||||
.get_invariants = igc_get_invariants_base,
|
||||
.mac_ops = &igc_mac_ops_base,
|
||||
.phy_ops = &igc_phy_ops_base,
|
||||
};
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_BASE_H_
|
||||
#define _IGC_BASE_H_
|
||||
|
||||
/* forward declaration */
|
||||
void igc_rx_fifo_flush_base(struct igc_hw *hw);
|
||||
void igc_power_down_phy_copper_base(struct igc_hw *hw);
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union igc_adv_tx_desc {
|
||||
struct {
|
||||
__le64 buffer_addr; /* Address of descriptor's data buf */
|
||||
__le32 cmd_type_len;
|
||||
__le32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
__le64 rsvd; /* Reserved */
|
||||
__le32 nxtseq_seed;
|
||||
__le32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Context descriptors */
|
||||
struct igc_adv_tx_context_desc {
|
||||
__le32 vlan_macip_lens;
|
||||
__le32 launch_time;
|
||||
__le32 type_tucmd_mlhl;
|
||||
__le32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define IGC_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
|
||||
#define IGC_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define IGC_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define IGC_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define IGC_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define IGC_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define IGC_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define IGC_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define IGC_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define IGC_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
#define IGC_RAR_ENTRIES 16
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union igc_adv_rx_desc {
|
||||
struct {
|
||||
__le64 pkt_addr; /* Packet buffer address */
|
||||
__le64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
union {
|
||||
__le32 data;
|
||||
struct {
|
||||
__le16 pkt_info; /*RSS type, Pkt type*/
|
||||
/* Split Header, header buffer len */
|
||||
__le16 hdr_info;
|
||||
} hs_rss;
|
||||
} lo_dword;
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length; /* Packet length */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
|
||||
#define IGC_TXDCTL_SWFLUSH 0x04000000 /* Transmit Software Flush */
|
||||
|
||||
/* Additional Receive Descriptor Control definitions */
|
||||
#define IGC_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */
|
||||
#define IGC_RXDCTL_SWFLUSH 0x04000000 /* Receive Software Flush */
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define IGC_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define IGC_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
|
||||
#endif /* _IGC_BASE_H */
|
||||
|
|
@ -0,0 +1,419 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "igc_hw.h"
|
||||
#include "igc_i225.h"
|
||||
#include "igc_mac.h"
|
||||
#include "igc_base.h"
|
||||
#include "igc.h"
|
||||
|
||||
/**
|
||||
* igc_reset_hw_base - Reset hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This resets the hardware into a known state. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static s32 igc_reset_hw_base(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val;
|
||||
u32 ctrl;
|
||||
|
||||
/* Prevent the PCI-E bus from sticking if there is no TLP connection
|
||||
* on the last TLP read/write transaction when MAC is reset.
|
||||
*/
|
||||
ret_val = igc_disable_pcie_master(hw);
|
||||
if (ret_val)
|
||||
hw_dbg("PCI-E Master disable polling has failed\n");
|
||||
|
||||
hw_dbg("Masking off all interrupts\n");
|
||||
wr32(IGC_IMC, 0xffffffff);
|
||||
|
||||
wr32(IGC_RCTL, 0);
|
||||
wr32(IGC_TCTL, IGC_TCTL_PSP);
|
||||
wrfl();
|
||||
|
||||
usleep_range(10000, 20000);
|
||||
|
||||
ctrl = rd32(IGC_CTRL);
|
||||
|
||||
hw_dbg("Issuing a global reset to MAC\n");
|
||||
wr32(IGC_CTRL, ctrl | IGC_CTRL_RST);
|
||||
|
||||
ret_val = igc_get_auto_rd_done(hw);
|
||||
if (ret_val) {
|
||||
/* When auto config read does not complete, do not
|
||||
* return with an error. This can happen in situations
|
||||
* where there is no eeprom and prevents getting link.
|
||||
*/
|
||||
hw_dbg("Auto Read Done did not complete\n");
|
||||
}
|
||||
|
||||
/* Clear any pending interrupt events. */
|
||||
wr32(IGC_IMC, 0xffffffff);
|
||||
rd32(IGC_ICR);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_nvm_params_base - Init NVM func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_nvm_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_nvm_info *nvm = &hw->nvm;
|
||||
u32 eecd = rd32(IGC_EECD);
|
||||
u16 size;
|
||||
|
||||
size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >>
|
||||
IGC_EECD_SIZE_EX_SHIFT);
|
||||
|
||||
/* Added to a constant, "size" becomes the left-shift value
|
||||
* for setting word_size.
|
||||
*/
|
||||
size += NVM_WORD_SIZE_BASE_SHIFT;
|
||||
|
||||
/* Just in case size is out of range, cap it to the largest
|
||||
* EEPROM size supported
|
||||
*/
|
||||
if (size > 15)
|
||||
size = 15;
|
||||
|
||||
nvm->type = igc_nvm_eeprom_spi;
|
||||
nvm->word_size = BIT(size);
|
||||
nvm->opcode_bits = 8;
|
||||
nvm->delay_usec = 1;
|
||||
|
||||
nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8;
|
||||
nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ?
|
||||
16 : 8;
|
||||
|
||||
if (nvm->word_size == BIT(15))
|
||||
nvm->page_size = 128;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_setup_copper_link_base - Configure copper link settings
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Configures the link for auto-neg or forced speed and duplex. Then we check
|
||||
* for link, once link is established calls to configure collision distance
|
||||
* and flow control are called.
|
||||
*/
|
||||
static s32 igc_setup_copper_link_base(struct igc_hw *hw)
|
||||
{
|
||||
s32 ret_val = 0;
|
||||
u32 ctrl;
|
||||
|
||||
ctrl = rd32(IGC_CTRL);
|
||||
ctrl |= IGC_CTRL_SLU;
|
||||
ctrl &= ~(IGC_CTRL_FRCSPD | IGC_CTRL_FRCDPX);
|
||||
wr32(IGC_CTRL, ctrl);
|
||||
|
||||
ret_val = igc_setup_copper_link(hw);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_mac_params_base - Init MAC func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_mac_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_dev_spec_base *dev_spec = &hw->dev_spec._base;
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
|
||||
/* Set mta register count */
|
||||
mac->mta_reg_count = 128;
|
||||
mac->rar_entry_count = IGC_RAR_ENTRIES;
|
||||
|
||||
/* reset */
|
||||
mac->ops.reset_hw = igc_reset_hw_base;
|
||||
|
||||
mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225;
|
||||
mac->ops.release_swfw_sync = igc_release_swfw_sync_i225;
|
||||
|
||||
/* Allow a single clear of the SW semaphore on I225 */
|
||||
if (mac->type == igc_i225)
|
||||
dev_spec->clear_semaphore_once = true;
|
||||
|
||||
/* physical interface link setup */
|
||||
mac->ops.setup_physical_interface = igc_setup_copper_link_base;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_phy_params_base - Init PHY func ptrs.
|
||||
* @hw: pointer to the HW structure
|
||||
*/
|
||||
static s32 igc_init_phy_params_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_phy_info *phy = &hw->phy;
|
||||
s32 ret_val = 0;
|
||||
|
||||
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT_2500;
|
||||
phy->reset_delay_us = 100;
|
||||
|
||||
/* set lan id */
|
||||
hw->bus.func = (rd32(IGC_STATUS) & IGC_STATUS_FUNC_MASK) >>
|
||||
IGC_STATUS_FUNC_SHIFT;
|
||||
|
||||
/* Make sure the PHY is in a good state. Several people have reported
|
||||
* firmware leaving the PHY's page select register set to something
|
||||
* other than the default of zero, which causes the PHY ID read to
|
||||
* access something other than the intended register.
|
||||
*/
|
||||
ret_val = hw->phy.ops.reset(hw);
|
||||
if (ret_val) {
|
||||
hw_dbg("Error resetting the PHY\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret_val = igc_get_phy_id(hw);
|
||||
if (ret_val)
|
||||
return ret_val;
|
||||
|
||||
igc_check_for_copper_link(hw);
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static s32 igc_get_invariants_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
s32 ret_val = 0;
|
||||
|
||||
switch (hw->device_id) {
|
||||
case IGC_DEV_ID_I225_LM:
|
||||
case IGC_DEV_ID_I225_V:
|
||||
case IGC_DEV_ID_I225_I:
|
||||
case IGC_DEV_ID_I220_V:
|
||||
case IGC_DEV_ID_I225_K:
|
||||
case IGC_DEV_ID_I225_K2:
|
||||
case IGC_DEV_ID_I226_K:
|
||||
case IGC_DEV_ID_I225_LMVP:
|
||||
case IGC_DEV_ID_I226_LMVP:
|
||||
case IGC_DEV_ID_I225_IT:
|
||||
case IGC_DEV_ID_I226_LM:
|
||||
case IGC_DEV_ID_I226_V:
|
||||
case IGC_DEV_ID_I226_IT:
|
||||
case IGC_DEV_ID_I221_V:
|
||||
case IGC_DEV_ID_I226_BLANK_NVM:
|
||||
case IGC_DEV_ID_I225_BLANK_NVM:
|
||||
mac->type = igc_i225;
|
||||
break;
|
||||
default:
|
||||
return -IGC_ERR_MAC_INIT;
|
||||
}
|
||||
|
||||
hw->phy.media_type = igc_media_type_copper;
|
||||
|
||||
/* mac initialization and operations */
|
||||
ret_val = igc_init_mac_params_base(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
/* NVM initialization */
|
||||
ret_val = igc_init_nvm_params_base(hw);
|
||||
switch (hw->mac.type) {
|
||||
case igc_i225:
|
||||
ret_val = igc_init_nvm_params_i225(hw);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* setup PHY parameters */
|
||||
ret_val = igc_init_phy_params_base(hw);
|
||||
if (ret_val)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_acquire_phy_base - Acquire rights to access PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* Acquire access rights to the correct PHY. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static s32 igc_acquire_phy_base(struct igc_hw *hw)
|
||||
{
|
||||
u16 mask = IGC_SWFW_PHY0_SM;
|
||||
|
||||
return hw->mac.ops.acquire_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_release_phy_base - Release rights to access PHY
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* A wrapper to release access rights to the correct PHY. This is a
|
||||
* function pointer entry point called by the api module.
|
||||
*/
|
||||
static void igc_release_phy_base(struct igc_hw *hw)
|
||||
{
|
||||
u16 mask = IGC_SWFW_PHY0_SM;
|
||||
|
||||
hw->mac.ops.release_swfw_sync(hw, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_init_hw_base - Initialize hardware
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* This inits the hardware readying it for operation.
|
||||
*/
|
||||
static s32 igc_init_hw_base(struct igc_hw *hw)
|
||||
{
|
||||
struct igc_mac_info *mac = &hw->mac;
|
||||
u16 i, rar_count = mac->rar_entry_count;
|
||||
s32 ret_val = 0;
|
||||
|
||||
/* Setup the receive address */
|
||||
igc_init_rx_addrs(hw, rar_count);
|
||||
|
||||
/* Zero out the Multicast HASH table */
|
||||
hw_dbg("Zeroing the MTA\n");
|
||||
for (i = 0; i < mac->mta_reg_count; i++)
|
||||
array_wr32(IGC_MTA, i, 0);
|
||||
|
||||
/* Zero out the Unicast HASH table */
|
||||
hw_dbg("Zeroing the UTA\n");
|
||||
for (i = 0; i < mac->uta_reg_count; i++)
|
||||
array_wr32(IGC_UTA, i, 0);
|
||||
|
||||
/* Setup link and flow control */
|
||||
ret_val = igc_setup_link(hw);
|
||||
|
||||
/* Clear all of the statistics registers (clear on read). It is
|
||||
* important that we do this after we have tried to establish link
|
||||
* because the symbol error count will increment wildly if there
|
||||
* is no link.
|
||||
*/
|
||||
igc_clear_hw_cntrs_base(hw);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_power_down_phy_copper_base - Remove link during PHY power down
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* In the case of a PHY power down to save power, or to turn off link during a
|
||||
* driver unload, or wake on lan is not enabled, remove the link.
|
||||
*/
|
||||
void igc_power_down_phy_copper_base(struct igc_hw *hw)
|
||||
{
|
||||
/* If the management interface is not enabled, then power down */
|
||||
if (!(igc_enable_mng_pass_thru(hw) || igc_check_reset_block(hw)))
|
||||
igc_power_down_phy_copper(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_rx_fifo_flush_base - Clean rx fifo after Rx enable
|
||||
* @hw: pointer to the HW structure
|
||||
*
|
||||
* After Rx enable, if manageability is enabled then there is likely some
|
||||
* bad data at the start of the fifo and possibly in the DMA fifo. This
|
||||
* function clears the fifos and flushes any packets that came in as rx was
|
||||
* being enabled.
|
||||
*/
|
||||
void igc_rx_fifo_flush_base(struct igc_hw *hw)
|
||||
{
|
||||
u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled;
|
||||
int i, ms_wait;
|
||||
|
||||
/* disable IPv6 options as per hardware errata */
|
||||
rfctl = rd32(IGC_RFCTL);
|
||||
rfctl |= IGC_RFCTL_IPV6_EX_DIS;
|
||||
wr32(IGC_RFCTL, rfctl);
|
||||
|
||||
if (!(rd32(IGC_MANC) & IGC_MANC_RCV_TCO_EN))
|
||||
return;
|
||||
|
||||
/* Disable all Rx queues */
|
||||
for (i = 0; i < 4; i++) {
|
||||
rxdctl[i] = rd32(IGC_RXDCTL(i));
|
||||
wr32(IGC_RXDCTL(i),
|
||||
rxdctl[i] & ~IGC_RXDCTL_QUEUE_ENABLE);
|
||||
}
|
||||
/* Poll all queues to verify they have shut down */
|
||||
for (ms_wait = 0; ms_wait < 10; ms_wait++) {
|
||||
usleep_range(1000, 2000);
|
||||
rx_enabled = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
rx_enabled |= rd32(IGC_RXDCTL(i));
|
||||
if (!(rx_enabled & IGC_RXDCTL_QUEUE_ENABLE))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ms_wait == 10)
|
||||
hw_dbg("Queue disable timed out after 10ms\n");
|
||||
|
||||
/* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all
|
||||
* incoming packets are rejected. Set enable and wait 2ms so that
|
||||
* any packet that was coming in as RCTL.EN was set is flushed
|
||||
*/
|
||||
wr32(IGC_RFCTL, rfctl & ~IGC_RFCTL_LEF);
|
||||
|
||||
rlpml = rd32(IGC_RLPML);
|
||||
wr32(IGC_RLPML, 0);
|
||||
|
||||
rctl = rd32(IGC_RCTL);
|
||||
temp_rctl = rctl & ~(IGC_RCTL_EN | IGC_RCTL_SBP);
|
||||
temp_rctl |= IGC_RCTL_LPE;
|
||||
|
||||
wr32(IGC_RCTL, temp_rctl);
|
||||
wr32(IGC_RCTL, temp_rctl | IGC_RCTL_EN);
|
||||
wrfl();
|
||||
usleep_range(2000, 3000);
|
||||
|
||||
/* Enable Rx queues that were previously enabled and restore our
|
||||
* previous state
|
||||
*/
|
||||
for (i = 0; i < 4; i++)
|
||||
wr32(IGC_RXDCTL(i), rxdctl[i]);
|
||||
wr32(IGC_RCTL, rctl);
|
||||
wrfl();
|
||||
|
||||
wr32(IGC_RLPML, rlpml);
|
||||
wr32(IGC_RFCTL, rfctl);
|
||||
|
||||
/* Flush receive errors generated by workaround */
|
||||
rd32(IGC_ROC);
|
||||
rd32(IGC_RNBC);
|
||||
rd32(IGC_MPC);
|
||||
}
|
||||
|
||||
static struct igc_mac_operations igc_mac_ops_base = {
|
||||
.init_hw = igc_init_hw_base,
|
||||
.check_for_link = igc_check_for_copper_link,
|
||||
.rar_set = igc_rar_set,
|
||||
.read_mac_addr = igc_read_mac_addr,
|
||||
.get_speed_and_duplex = igc_get_speed_and_duplex_copper,
|
||||
};
|
||||
|
||||
static const struct igc_phy_operations igc_phy_ops_base = {
|
||||
.acquire = igc_acquire_phy_base,
|
||||
.release = igc_release_phy_base,
|
||||
.reset = igc_phy_hw_reset,
|
||||
.read_reg = igc_read_phy_reg_gpy,
|
||||
.write_reg = igc_write_phy_reg_gpy,
|
||||
};
|
||||
|
||||
const struct igc_info igc_base_info = {
|
||||
.get_invariants = igc_get_invariants_base,
|
||||
.mac_ops = &igc_mac_ops_base,
|
||||
.phy_ops = &igc_phy_ops_base,
|
||||
};
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_BASE_H_
|
||||
#define _IGC_BASE_H_
|
||||
|
||||
/* forward declaration */
|
||||
void igc_rx_fifo_flush_base(struct igc_hw *hw);
|
||||
void igc_power_down_phy_copper_base(struct igc_hw *hw);
|
||||
|
||||
/* Transmit Descriptor - Advanced */
|
||||
union igc_adv_tx_desc {
|
||||
struct {
|
||||
__le64 buffer_addr; /* Address of descriptor's data buf */
|
||||
__le32 cmd_type_len;
|
||||
__le32 olinfo_status;
|
||||
} read;
|
||||
struct {
|
||||
__le64 rsvd; /* Reserved */
|
||||
__le32 nxtseq_seed;
|
||||
__le32 status;
|
||||
} wb;
|
||||
};
|
||||
|
||||
/* Context descriptors */
|
||||
struct igc_adv_tx_context_desc {
|
||||
__le32 vlan_macip_lens;
|
||||
__le32 launch_time;
|
||||
__le32 type_tucmd_mlhl;
|
||||
__le32 mss_l4len_idx;
|
||||
};
|
||||
|
||||
/* Adv Transmit Descriptor Config Masks */
|
||||
#define IGC_ADVTXD_MAC_TSTAMP 0x00080000 /* IEEE1588 Timestamp packet */
|
||||
#define IGC_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Descriptor */
|
||||
#define IGC_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
|
||||
#define IGC_ADVTXD_DCMD_EOP 0x01000000 /* End of Packet */
|
||||
#define IGC_ADVTXD_DCMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
|
||||
#define IGC_ADVTXD_DCMD_RS 0x08000000 /* Report Status */
|
||||
#define IGC_ADVTXD_DCMD_DEXT 0x20000000 /* Descriptor extension (1=Adv) */
|
||||
#define IGC_ADVTXD_DCMD_VLE 0x40000000 /* VLAN pkt enable */
|
||||
#define IGC_ADVTXD_DCMD_TSE 0x80000000 /* TCP Seg enable */
|
||||
#define IGC_ADVTXD_PAYLEN_SHIFT 14 /* Adv desc PAYLEN shift */
|
||||
|
||||
#define IGC_RAR_ENTRIES 16
|
||||
|
||||
/* Receive Descriptor - Advanced */
|
||||
union igc_adv_rx_desc {
|
||||
struct {
|
||||
__le64 pkt_addr; /* Packet buffer address */
|
||||
__le64 hdr_addr; /* Header buffer address */
|
||||
} read;
|
||||
struct {
|
||||
struct {
|
||||
union {
|
||||
__le32 data;
|
||||
struct {
|
||||
__le16 pkt_info; /*RSS type, Pkt type*/
|
||||
/* Split Header, header buffer len */
|
||||
__le16 hdr_info;
|
||||
} hs_rss;
|
||||
} lo_dword;
|
||||
union {
|
||||
__le32 rss; /* RSS Hash */
|
||||
struct {
|
||||
__le16 ip_id; /* IP id */
|
||||
__le16 csum; /* Packet Checksum */
|
||||
} csum_ip;
|
||||
} hi_dword;
|
||||
} lower;
|
||||
struct {
|
||||
__le32 status_error; /* ext status/error */
|
||||
__le16 length; /* Packet length */
|
||||
__le16 vlan; /* VLAN tag */
|
||||
} upper;
|
||||
} wb; /* writeback */
|
||||
};
|
||||
|
||||
/* Additional Transmit Descriptor Control definitions */
|
||||
#define IGC_TXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Tx Queue */
|
||||
#define IGC_TXDCTL_SWFLUSH 0x04000000 /* Transmit Software Flush */
|
||||
|
||||
/* Additional Receive Descriptor Control definitions */
|
||||
#define IGC_RXDCTL_QUEUE_ENABLE 0x02000000 /* Ena specific Rx Queue */
|
||||
#define IGC_RXDCTL_SWFLUSH 0x04000000 /* Receive Software Flush */
|
||||
|
||||
/* SRRCTL bit definitions */
|
||||
#define IGC_SRRCTL_BSIZEPKT_SHIFT 10 /* Shift _right_ */
|
||||
#define IGC_SRRCTL_BSIZEHDRSIZE_SHIFT 2 /* Shift _left_ */
|
||||
#define IGC_SRRCTL_DESCTYPE_ADV_ONEBUF 0x02000000
|
||||
|
||||
#endif /* _IGC_BASE_H */
|
||||
|
|
@ -0,0 +1,596 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_DEFINES_H_
|
||||
#define _IGC_DEFINES_H_
|
||||
|
||||
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
|
||||
#define REQ_TX_DESCRIPTOR_MULTIPLE 8
|
||||
#define REQ_RX_DESCRIPTOR_MULTIPLE 8
|
||||
|
||||
#define IGC_CTRL_EXT_SDP2_DIR 0x00000400 /* SDP2 Data direction */
|
||||
#define IGC_CTRL_EXT_SDP3_DIR 0x00000800 /* SDP3 Data direction */
|
||||
#define IGC_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */
|
||||
|
||||
/* Definitions for power management and wakeup registers */
|
||||
/* Wake Up Control */
|
||||
#define IGC_WUC_PME_EN 0x00000002 /* PME Enable */
|
||||
|
||||
/* Wake Up Filter Control */
|
||||
#define IGC_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
|
||||
#define IGC_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
|
||||
#define IGC_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
|
||||
#define IGC_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */
|
||||
#define IGC_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
|
||||
|
||||
#define IGC_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */
|
||||
|
||||
/* Wake Up Status */
|
||||
#define IGC_WUS_EX 0x00000004 /* Directed Exact */
|
||||
#define IGC_WUS_ARPD 0x00000020 /* Directed ARP Request */
|
||||
#define IGC_WUS_IPV4 0x00000040 /* Directed IPv4 */
|
||||
#define IGC_WUS_IPV6 0x00000080 /* Directed IPv6 */
|
||||
#define IGC_WUS_NSD 0x00000400 /* Directed IPv6 Neighbor Solicitation */
|
||||
|
||||
/* Packet types that are enabled for wake packet delivery */
|
||||
#define WAKE_PKT_WUS ( \
|
||||
IGC_WUS_EX | \
|
||||
IGC_WUS_ARPD | \
|
||||
IGC_WUS_IPV4 | \
|
||||
IGC_WUS_IPV6 | \
|
||||
IGC_WUS_NSD)
|
||||
|
||||
/* Wake Up Packet Length */
|
||||
#define IGC_WUPL_MASK 0x00000FFF
|
||||
|
||||
/* Wake Up Packet Memory stores the first 128 bytes of the wake up packet */
|
||||
#define IGC_WUPM_BYTES 128
|
||||
|
||||
/* Loop limit on how long we wait for auto-negotiation to complete */
|
||||
#define COPPER_LINK_UP_LIMIT 10
|
||||
#define PHY_AUTO_NEG_LIMIT 45
|
||||
|
||||
/* Number of 100 microseconds we wait for PCI Express master disable */
|
||||
#define MASTER_DISABLE_TIMEOUT 800
|
||||
/*Blocks new Master requests */
|
||||
#define IGC_CTRL_GIO_MASTER_DISABLE 0x00000004
|
||||
/* Status of Master requests. */
|
||||
#define IGC_STATUS_GIO_MASTER_ENABLE 0x00080000
|
||||
|
||||
/* Receive Address
|
||||
* Number of high/low register pairs in the RAR. The RAR (Receive Address
|
||||
* Registers) holds the directed and multicast addresses that we monitor.
|
||||
* Technically, we have 16 spots. However, we reserve one of these spots
|
||||
* (RAR[15]) for our directed address used by controllers with
|
||||
* manageability enabled, allowing us room for 15 multicast addresses.
|
||||
*/
|
||||
#define IGC_RAH_RAH_MASK 0x0000FFFF
|
||||
#define IGC_RAH_ASEL_MASK 0x00030000
|
||||
#define IGC_RAH_ASEL_SRC_ADDR BIT(16)
|
||||
#define IGC_RAH_QSEL_MASK 0x000C0000
|
||||
#define IGC_RAH_QSEL_SHIFT 18
|
||||
#define IGC_RAH_QSEL_ENABLE BIT(28)
|
||||
#define IGC_RAH_AV 0x80000000 /* Receive descriptor valid */
|
||||
|
||||
#define IGC_RAL_MAC_ADDR_LEN 4
|
||||
#define IGC_RAH_MAC_ADDR_LEN 2
|
||||
|
||||
/* Error Codes */
|
||||
#define IGC_SUCCESS 0
|
||||
#define IGC_ERR_NVM 1
|
||||
#define IGC_ERR_PHY 2
|
||||
#define IGC_ERR_CONFIG 3
|
||||
#define IGC_ERR_PARAM 4
|
||||
#define IGC_ERR_MAC_INIT 5
|
||||
#define IGC_ERR_RESET 9
|
||||
#define IGC_ERR_MASTER_REQUESTS_PENDING 10
|
||||
#define IGC_ERR_BLK_PHY_RESET 12
|
||||
#define IGC_ERR_SWFW_SYNC 13
|
||||
|
||||
/* Device Control */
|
||||
#define IGC_CTRL_DEV_RST 0x20000000 /* Device reset */
|
||||
|
||||
#define IGC_CTRL_PHY_RST 0x80000000 /* PHY Reset */
|
||||
#define IGC_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
|
||||
#define IGC_CTRL_FRCSPD 0x00000800 /* Force Speed */
|
||||
#define IGC_CTRL_FRCDPX 0x00001000 /* Force Duplex */
|
||||
#define IGC_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
|
||||
|
||||
#define IGC_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
|
||||
#define IGC_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
|
||||
|
||||
#define IGC_CTRL_SDP0_DIR 0x00400000 /* SDP0 Data direction */
|
||||
#define IGC_CTRL_SDP1_DIR 0x00800000 /* SDP1 Data direction */
|
||||
|
||||
/* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */
|
||||
#define MAX_JUMBO_FRAME_SIZE 0x2600
|
||||
|
||||
/* PBA constants */
|
||||
#define IGC_PBA_34K 0x0022
|
||||
|
||||
/* SW Semaphore Register */
|
||||
#define IGC_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
|
||||
#define IGC_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
|
||||
|
||||
/* SWFW_SYNC Definitions */
|
||||
#define IGC_SWFW_EEP_SM 0x1
|
||||
#define IGC_SWFW_PHY0_SM 0x2
|
||||
|
||||
/* Autoneg Advertisement Register */
|
||||
#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
|
||||
#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
|
||||
#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
|
||||
#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
|
||||
#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
|
||||
#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
|
||||
|
||||
/* Link Partner Ability Register (Base Page) */
|
||||
#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
|
||||
#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
|
||||
|
||||
/* 1000BASE-T Control Register */
|
||||
#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
|
||||
#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
|
||||
|
||||
/* 1000BASE-T Status Register */
|
||||
#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
|
||||
|
||||
/* PHY GPY 211 registers */
|
||||
#define STANDARD_AN_REG_MASK 0x0007 /* MMD */
|
||||
#define ANEG_MULTIGBT_AN_CTRL 0x0020 /* MULTI GBT AN Control Register */
|
||||
#define MMD_DEVADDR_SHIFT 16 /* Shift MMD to higher bits */
|
||||
#define CR_2500T_FD_CAPS 0x0080 /* Advertise 2500T FD capability */
|
||||
|
||||
/* NVM Control */
|
||||
/* Number of milliseconds for NVM auto read done after MAC reset. */
|
||||
#define AUTO_READ_DONE_TIMEOUT 10
|
||||
#define IGC_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
|
||||
#define IGC_EECD_REQ 0x00000040 /* NVM Access Request */
|
||||
#define IGC_EECD_GNT 0x00000080 /* NVM Access Grant */
|
||||
/* NVM Addressing bits based on type 0=small, 1=large */
|
||||
#define IGC_EECD_ADDR_BITS 0x00000400
|
||||
#define IGC_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */
|
||||
#define IGC_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
|
||||
#define IGC_EECD_SIZE_EX_SHIFT 11
|
||||
#define IGC_EECD_FLUPD_I225 0x00800000 /* Update FLASH */
|
||||
#define IGC_EECD_FLUDONE_I225 0x04000000 /* Update FLASH done*/
|
||||
#define IGC_EECD_FLASH_DETECTED_I225 0x00080000 /* FLASH detected */
|
||||
#define IGC_FLUDONE_ATTEMPTS 20000
|
||||
#define IGC_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */
|
||||
|
||||
/* Offset to data in NVM read/write registers */
|
||||
#define IGC_NVM_RW_REG_DATA 16
|
||||
#define IGC_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
|
||||
#define IGC_NVM_RW_REG_START 1 /* Start operation */
|
||||
#define IGC_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
|
||||
#define IGC_NVM_POLL_READ 0 /* Flag for polling for read complete */
|
||||
#define IGC_NVM_DEV_STARTER 5 /* Dev_starter Version */
|
||||
|
||||
/* NVM Word Offsets */
|
||||
#define NVM_CHECKSUM_REG 0x003F
|
||||
|
||||
/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
|
||||
#define NVM_SUM 0xBABA
|
||||
#define NVM_WORD_SIZE_BASE_SHIFT 6
|
||||
|
||||
/* Collision related configuration parameters */
|
||||
#define IGC_COLLISION_THRESHOLD 15
|
||||
#define IGC_CT_SHIFT 4
|
||||
#define IGC_COLLISION_DISTANCE 63
|
||||
#define IGC_COLD_SHIFT 12
|
||||
|
||||
/* Device Status */
|
||||
#define IGC_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
|
||||
#define IGC_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
|
||||
#define IGC_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
|
||||
#define IGC_STATUS_FUNC_SHIFT 2
|
||||
#define IGC_STATUS_TXOFF 0x00000010 /* transmission paused */
|
||||
#define IGC_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
|
||||
#define IGC_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
|
||||
#define IGC_STATUS_SPEED_2500 0x00400000 /* Speed 2.5Gb/s */
|
||||
|
||||
#define SPEED_10 10
|
||||
#define SPEED_100 100
|
||||
#define SPEED_1000 1000
|
||||
#define SPEED_2500 2500
|
||||
#define HALF_DUPLEX 1
|
||||
#define FULL_DUPLEX 2
|
||||
|
||||
/* 1Gbps and 2.5Gbps half duplex is not supported, nor spec-compliant. */
|
||||
#define ADVERTISE_10_HALF 0x0001
|
||||
#define ADVERTISE_10_FULL 0x0002
|
||||
#define ADVERTISE_100_HALF 0x0004
|
||||
#define ADVERTISE_100_FULL 0x0008
|
||||
#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */
|
||||
#define ADVERTISE_1000_FULL 0x0020
|
||||
#define ADVERTISE_2500_HALF 0x0040 /* Not used, just FYI */
|
||||
#define ADVERTISE_2500_FULL 0x0080
|
||||
|
||||
#define IGC_ALL_SPEED_DUPLEX_2500 ( \
|
||||
ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \
|
||||
ADVERTISE_100_FULL | ADVERTISE_1000_FULL | ADVERTISE_2500_FULL)
|
||||
|
||||
#define AUTONEG_ADVERTISE_SPEED_DEFAULT_2500 IGC_ALL_SPEED_DUPLEX_2500
|
||||
|
||||
/* Interrupt Cause Read */
|
||||
#define IGC_ICR_TXDW BIT(0) /* Transmit desc written back */
|
||||
#define IGC_ICR_TXQE BIT(1) /* Transmit Queue empty */
|
||||
#define IGC_ICR_LSC BIT(2) /* Link Status Change */
|
||||
#define IGC_ICR_RXSEQ BIT(3) /* Rx sequence error */
|
||||
#define IGC_ICR_RXDMT0 BIT(4) /* Rx desc min. threshold (0) */
|
||||
#define IGC_ICR_RXO BIT(6) /* Rx overrun */
|
||||
#define IGC_ICR_RXT0 BIT(7) /* Rx timer intr (ring 0) */
|
||||
#define IGC_ICR_TS BIT(19) /* Time Sync Interrupt */
|
||||
#define IGC_ICR_DRSTA BIT(30) /* Device Reset Asserted */
|
||||
|
||||
/* If this bit asserted, the driver should claim the interrupt */
|
||||
#define IGC_ICR_INT_ASSERTED BIT(31)
|
||||
|
||||
#define IGC_ICS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */
|
||||
|
||||
#define IMS_ENABLE_MASK ( \
|
||||
IGC_IMS_RXT0 | \
|
||||
IGC_IMS_TXDW | \
|
||||
IGC_IMS_RXDMT0 | \
|
||||
IGC_IMS_RXSEQ | \
|
||||
IGC_IMS_LSC)
|
||||
|
||||
/* Interrupt Mask Set */
|
||||
#define IGC_IMS_TXDW IGC_ICR_TXDW /* Tx desc written back */
|
||||
#define IGC_IMS_RXSEQ IGC_ICR_RXSEQ /* Rx sequence error */
|
||||
#define IGC_IMS_LSC IGC_ICR_LSC /* Link Status Change */
|
||||
#define IGC_IMS_DOUTSYNC IGC_ICR_DOUTSYNC /* NIC DMA out of sync */
|
||||
#define IGC_IMS_DRSTA IGC_ICR_DRSTA /* Device Reset Asserted */
|
||||
#define IGC_IMS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */
|
||||
#define IGC_IMS_RXDMT0 IGC_ICR_RXDMT0 /* Rx desc min. threshold */
|
||||
#define IGC_IMS_TS IGC_ICR_TS /* Time Sync Interrupt */
|
||||
|
||||
#define IGC_QVECTOR_MASK 0x7FFC /* Q-vector mask */
|
||||
#define IGC_ITR_VAL_MASK 0x04 /* ITR value mask */
|
||||
|
||||
/* Interrupt Cause Set */
|
||||
#define IGC_ICS_LSC IGC_ICR_LSC /* Link Status Change */
|
||||
#define IGC_ICS_RXDMT0 IGC_ICR_RXDMT0 /* rx desc min. threshold */
|
||||
|
||||
#define IGC_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */
|
||||
#define IGC_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */
|
||||
#define IGC_IVAR_VALID 0x80
|
||||
#define IGC_GPIE_NSICR 0x00000001
|
||||
#define IGC_GPIE_MSIX_MODE 0x00000010
|
||||
#define IGC_GPIE_EIAME 0x40000000
|
||||
#define IGC_GPIE_PBA 0x80000000
|
||||
|
||||
/* Receive Descriptor bit definitions */
|
||||
#define IGC_RXD_STAT_DD 0x01 /* Descriptor Done */
|
||||
|
||||
/* Transmit Descriptor bit definitions */
|
||||
#define IGC_TXD_DTYP_D 0x00100000 /* Data Descriptor */
|
||||
#define IGC_TXD_DTYP_C 0x00000000 /* Context Descriptor */
|
||||
#define IGC_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
|
||||
#define IGC_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
|
||||
#define IGC_TXD_CMD_EOP 0x01000000 /* End of Packet */
|
||||
#define IGC_TXD_CMD_IC 0x04000000 /* Insert Checksum */
|
||||
#define IGC_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */
|
||||
#define IGC_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */
|
||||
#define IGC_TXD_STAT_DD 0x00000001 /* Descriptor Done */
|
||||
#define IGC_TXD_CMD_TCP 0x01000000 /* TCP packet */
|
||||
#define IGC_TXD_CMD_IP 0x02000000 /* IP packet */
|
||||
#define IGC_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
|
||||
#define IGC_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */
|
||||
|
||||
/* IPSec Encrypt Enable */
|
||||
#define IGC_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define IGC_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
|
||||
/* Transmit Control */
|
||||
#define IGC_TCTL_EN 0x00000002 /* enable Tx */
|
||||
#define IGC_TCTL_PSP 0x00000008 /* pad short packets */
|
||||
#define IGC_TCTL_CT 0x00000ff0 /* collision threshold */
|
||||
#define IGC_TCTL_COLD 0x003ff000 /* collision distance */
|
||||
#define IGC_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
|
||||
|
||||
/* Flow Control Constants */
|
||||
#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001
|
||||
#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
|
||||
#define FLOW_CONTROL_TYPE 0x8808
|
||||
/* Enable XON frame transmission */
|
||||
#define IGC_FCRTL_XONE 0x80000000
|
||||
|
||||
/* Management Control */
|
||||
#define IGC_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
|
||||
#define IGC_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
|
||||
|
||||
/* Receive Control */
|
||||
#define IGC_RCTL_RST 0x00000001 /* Software reset */
|
||||
#define IGC_RCTL_EN 0x00000002 /* enable */
|
||||
#define IGC_RCTL_SBP 0x00000004 /* store bad packet */
|
||||
#define IGC_RCTL_UPE 0x00000008 /* unicast promisc enable */
|
||||
#define IGC_RCTL_MPE 0x00000010 /* multicast promisc enable */
|
||||
#define IGC_RCTL_LPE 0x00000020 /* long packet enable */
|
||||
#define IGC_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
|
||||
#define IGC_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
|
||||
|
||||
#define IGC_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */
|
||||
#define IGC_RCTL_BAM 0x00008000 /* broadcast enable */
|
||||
|
||||
/* Split Replication Receive Control */
|
||||
#define IGC_SRRCTL_TIMESTAMP 0x40000000
|
||||
#define IGC_SRRCTL_TIMER1SEL(timer) (((timer) & 0x3) << 14)
|
||||
#define IGC_SRRCTL_TIMER0SEL(timer) (((timer) & 0x3) << 17)
|
||||
|
||||
/* Receive Descriptor bit definitions */
|
||||
#define IGC_RXD_STAT_EOP 0x02 /* End of Packet */
|
||||
#define IGC_RXD_STAT_IXSM 0x04 /* Ignore checksum */
|
||||
#define IGC_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
|
||||
#define IGC_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
|
||||
#define IGC_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
|
||||
|
||||
#define IGC_RXDEXT_STATERR_LB 0x00040000
|
||||
|
||||
/* Advanced Receive Descriptor bit definitions */
|
||||
#define IGC_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */
|
||||
|
||||
#define IGC_RXDEXT_STATERR_L4E 0x20000000
|
||||
#define IGC_RXDEXT_STATERR_IPE 0x40000000
|
||||
#define IGC_RXDEXT_STATERR_RXE 0x80000000
|
||||
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4 0x00020000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6 0x00100000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
|
||||
|
||||
/* Header split receive */
|
||||
#define IGC_RFCTL_IPV6_EX_DIS 0x00010000
|
||||
#define IGC_RFCTL_LEF 0x00040000
|
||||
|
||||
#define IGC_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */
|
||||
|
||||
#define IGC_RCTL_MO_SHIFT 12 /* multicast offset shift */
|
||||
#define IGC_RCTL_CFIEN 0x00080000 /* canonical form enable */
|
||||
#define IGC_RCTL_DPF 0x00400000 /* discard pause frames */
|
||||
#define IGC_RCTL_PMCF 0x00800000 /* pass MAC control frames */
|
||||
#define IGC_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
|
||||
|
||||
#define I225_RXPBSIZE_DEFAULT 0x000000A2 /* RXPBSIZE default */
|
||||
#define I225_TXPBSIZE_DEFAULT 0x04000014 /* TXPBSIZE default */
|
||||
#define IGC_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */
|
||||
|
||||
#define IGC_TXPBSIZE_TSN 0x04145145 /* 5k bytes buffer for each queue */
|
||||
|
||||
#define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */
|
||||
#define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */
|
||||
|
||||
/* Time Sync Interrupt Causes */
|
||||
#define IGC_TSICR_SYS_WRAP BIT(0) /* SYSTIM Wrap around. */
|
||||
#define IGC_TSICR_TXTS BIT(1) /* Transmit Timestamp. */
|
||||
#define IGC_TSICR_TT0 BIT(3) /* Target Time 0 Trigger. */
|
||||
#define IGC_TSICR_TT1 BIT(4) /* Target Time 1 Trigger. */
|
||||
#define IGC_TSICR_AUTT0 BIT(5) /* Auxiliary Timestamp 0 Taken. */
|
||||
#define IGC_TSICR_AUTT1 BIT(6) /* Auxiliary Timestamp 1 Taken. */
|
||||
|
||||
#define IGC_TSICR_INTERRUPTS IGC_TSICR_TXTS
|
||||
|
||||
#define IGC_FTQF_VF_BP 0x00008000
|
||||
#define IGC_FTQF_1588_TIME_STAMP 0x08000000
|
||||
#define IGC_FTQF_MASK 0xF0000000
|
||||
#define IGC_FTQF_MASK_PROTO_BP 0x10000000
|
||||
|
||||
/* Time Sync Receive Control bit definitions */
|
||||
#define IGC_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */
|
||||
#define IGC_TSYNCRXCTL_TYPE_L2_V2 0x00
|
||||
#define IGC_TSYNCRXCTL_TYPE_L4_V1 0x02
|
||||
#define IGC_TSYNCRXCTL_TYPE_L2_L4_V2 0x04
|
||||
#define IGC_TSYNCRXCTL_TYPE_ALL 0x08
|
||||
#define IGC_TSYNCRXCTL_TYPE_EVENT_V2 0x0A
|
||||
#define IGC_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */
|
||||
#define IGC_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */
|
||||
#define IGC_TSYNCRXCTL_RXSYNSIG 0x00000400 /* Sample RX tstamp in PHY sop */
|
||||
|
||||
/* Time Sync Receive Configuration */
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01
|
||||
|
||||
/* Immediate Interrupt Receive */
|
||||
#define IGC_IMIR_CLEAR_MASK 0xF001FFFF /* IMIR Reg Clear Mask */
|
||||
#define IGC_IMIR_PORT_BYPASS 0x20000 /* IMIR Port Bypass Bit */
|
||||
#define IGC_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */
|
||||
#define IGC_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */
|
||||
|
||||
/* Immediate Interrupt Receive Extended */
|
||||
#define IGC_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */
|
||||
#define IGC_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
|
||||
|
||||
/* Time Sync Transmit Control bit definitions */
|
||||
#define IGC_TSYNCTXCTL_TXTT_0 0x00000001 /* Tx timestamp reg 0 valid */
|
||||
#define IGC_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */
|
||||
#define IGC_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */
|
||||
#define IGC_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */
|
||||
#define IGC_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete */
|
||||
#define IGC_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */
|
||||
#define IGC_TSYNCTXCTL_TXSYNSIG 0x00000020 /* Sample TX tstamp in PHY sop */
|
||||
|
||||
/* Timer selection bits */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM0 (0u << 30) /* Select SYSTIM0 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM1 (1u << 30) /* Select SYSTIM1 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM2 (2u << 30) /* Select SYSTIM2 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM3 (3u << 30) /* Select SYSTIM3 for auxiliary time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM0 (0u << 30) /* Select SYSTIM0 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM1 (1u << 30) /* Select SYSTIM1 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM2 (2u << 30) /* Select SYSTIM2 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM3 (3u << 30) /* Select SYSTIM3 for target time stamp */
|
||||
|
||||
/* TSAUXC Configuration Bits */
|
||||
#define IGC_TSAUXC_EN_TT0 BIT(0) /* Enable target time 0. */
|
||||
#define IGC_TSAUXC_EN_TT1 BIT(1) /* Enable target time 1. */
|
||||
#define IGC_TSAUXC_EN_CLK0 BIT(2) /* Enable Configurable Frequency Clock 0. */
|
||||
#define IGC_TSAUXC_EN_CLK1 BIT(5) /* Enable Configurable Frequency Clock 1. */
|
||||
#define IGC_TSAUXC_EN_TS0 BIT(8) /* Enable hardware timestamp 0. */
|
||||
#define IGC_TSAUXC_AUTT0 BIT(9) /* Auxiliary Timestamp Taken. */
|
||||
#define IGC_TSAUXC_EN_TS1 BIT(10) /* Enable hardware timestamp 0. */
|
||||
#define IGC_TSAUXC_AUTT1 BIT(11) /* Auxiliary Timestamp Taken. */
|
||||
#define IGC_TSAUXC_PLSG BIT(17) /* Generate a pulse. */
|
||||
#define IGC_TSAUXC_DISABLE1 BIT(27) /* Disable SYSTIM0 Count Operation. */
|
||||
#define IGC_TSAUXC_DISABLE2 BIT(28) /* Disable SYSTIM1 Count Operation. */
|
||||
#define IGC_TSAUXC_DISABLE3 BIT(29) /* Disable SYSTIM2 Count Operation. */
|
||||
#define IGC_TSAUXC_DIS_TS_CLEAR BIT(30) /* Disable EN_TT0/1 auto clear. */
|
||||
#define IGC_TSAUXC_DISABLE0 BIT(31) /* Disable SYSTIM0 Count Operation. */
|
||||
|
||||
/* SDP Configuration Bits */
|
||||
#define IGC_AUX0_SEL_SDP0 (0u << 0) /* Assign SDP0 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP1 (1u << 0) /* Assign SDP1 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP2 (2u << 0) /* Assign SDP2 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP3 (3u << 0) /* Assign SDP3 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_TS_SDP_EN (1u << 2) /* Enable auxiliary time stamp trigger 0. */
|
||||
#define IGC_AUX1_SEL_SDP0 (0u << 3) /* Assign SDP0 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP1 (1u << 3) /* Assign SDP1 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP2 (2u << 3) /* Assign SDP2 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP3 (3u << 3) /* Assign SDP3 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_TS_SDP_EN (1u << 5) /* Enable auxiliary time stamp trigger 1. */
|
||||
#define IGC_TS_SDP0_SEL_TT0 (0u << 6) /* Target time 0 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_TT1 (1u << 6) /* Target time 1 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_FC0 (2u << 6) /* Freq clock 0 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_FC1 (3u << 6) /* Freq clock 1 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_EN (1u << 8) /* SDP0 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP1_SEL_TT0 (0u << 9) /* Target time 0 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_TT1 (1u << 9) /* Target time 1 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_FC0 (2u << 9) /* Freq clock 0 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_FC1 (3u << 9) /* Freq clock 1 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_EN (1u << 11) /* SDP1 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP2_SEL_TT0 (0u << 12) /* Target time 0 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_TT1 (1u << 12) /* Target time 1 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_FC0 (2u << 12) /* Freq clock 0 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_FC1 (3u << 12) /* Freq clock 1 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_EN (1u << 14) /* SDP2 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP3_SEL_TT0 (0u << 15) /* Target time 0 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_TT1 (1u << 15) /* Target time 1 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_FC0 (2u << 15) /* Freq clock 0 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_FC1 (3u << 15) /* Freq clock 1 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_EN (1u << 17) /* SDP3 is assigned to Tsync. */
|
||||
|
||||
/* Transmit Scheduling */
|
||||
#define IGC_TQAVCTRL_TRANSMIT_MODE_TSN 0x00000001
|
||||
#define IGC_TQAVCTRL_ENHANCED_QAV 0x00000008
|
||||
|
||||
#define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001
|
||||
#define IGC_TXQCTL_STRICT_CYCLE 0x00000002
|
||||
#define IGC_TXQCTL_STRICT_END 0x00000004
|
||||
|
||||
/* Receive Checksum Control */
|
||||
#define IGC_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */
|
||||
#define IGC_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
|
||||
|
||||
/* GPY211 - I225 defines */
|
||||
#define GPY_MMD_MASK 0xFFFF0000
|
||||
#define GPY_MMD_SHIFT 16
|
||||
#define GPY_REG_MASK 0x0000FFFF
|
||||
|
||||
#define IGC_MMDAC_FUNC_DATA 0x4000 /* Data, no post increment */
|
||||
|
||||
/* MAC definitions */
|
||||
#define IGC_FACTPS_MNGCG 0x20000000
|
||||
#define IGC_FWSM_MODE_MASK 0xE
|
||||
#define IGC_FWSM_MODE_SHIFT 1
|
||||
|
||||
/* Management Control */
|
||||
#define IGC_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */
|
||||
#define IGC_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */
|
||||
|
||||
/* PHY */
|
||||
#define PHY_REVISION_MASK 0xFFFFFFF0
|
||||
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
|
||||
#define IGC_GEN_POLL_TIMEOUT 1920
|
||||
|
||||
/* PHY Control Register */
|
||||
#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
|
||||
#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
|
||||
#define MII_CR_POWER_DOWN 0x0800 /* Power down */
|
||||
#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
|
||||
|
||||
/* PHY Status Register */
|
||||
#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
|
||||
#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
|
||||
#define IGC_PHY_RST_COMP 0x0100 /* Internal PHY reset completion */
|
||||
|
||||
/* PHY 1000 MII Register/Bit Definitions */
|
||||
/* PHY Registers defined by IEEE */
|
||||
#define PHY_CONTROL 0x00 /* Control Register */
|
||||
#define PHY_STATUS 0x01 /* Status Register */
|
||||
#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
|
||||
#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
|
||||
#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
|
||||
#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
|
||||
#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
|
||||
#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
|
||||
|
||||
/* Bit definitions for valid PHY IDs. I = Integrated E = External */
|
||||
#define I225_I_PHY_ID 0x67C9DC00
|
||||
|
||||
/* MDI Control */
|
||||
#define IGC_MDIC_DATA_MASK 0x0000FFFF
|
||||
#define IGC_MDIC_REG_MASK 0x001F0000
|
||||
#define IGC_MDIC_REG_SHIFT 16
|
||||
#define IGC_MDIC_PHY_MASK 0x03E00000
|
||||
#define IGC_MDIC_PHY_SHIFT 21
|
||||
#define IGC_MDIC_OP_WRITE 0x04000000
|
||||
#define IGC_MDIC_OP_READ 0x08000000
|
||||
#define IGC_MDIC_READY 0x10000000
|
||||
#define IGC_MDIC_INT_EN 0x20000000
|
||||
#define IGC_MDIC_ERROR 0x40000000
|
||||
|
||||
#define IGC_N0_QUEUE -1
|
||||
|
||||
#define IGC_MAX_MAC_HDR_LEN 127
|
||||
#define IGC_MAX_NETWORK_HDR_LEN 511
|
||||
|
||||
#define IGC_VLANPQF_QSEL(_n, q_idx) ((q_idx) << ((_n) * 4))
|
||||
#define IGC_VLANPQF_VALID(_n) (0x1 << (3 + (_n) * 4))
|
||||
#define IGC_VLANPQF_QUEUE_MASK 0x03
|
||||
|
||||
#define IGC_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define IGC_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type:1=IPv4 */
|
||||
#define IGC_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet Type of TCP */
|
||||
#define IGC_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
|
||||
|
||||
/* Maximum size of the MTA register table in all supported adapters */
|
||||
#define MAX_MTA_REG 128
|
||||
|
||||
/* EEE defines */
|
||||
#define IGC_IPCNFG_EEE_2_5G_AN 0x00000010 /* IPCNFG EEE Ena 2.5G AN */
|
||||
#define IGC_IPCNFG_EEE_1G_AN 0x00000008 /* IPCNFG EEE Ena 1G AN */
|
||||
#define IGC_IPCNFG_EEE_100M_AN 0x00000004 /* IPCNFG EEE Ena 100M AN */
|
||||
#define IGC_EEER_EEE_NEG 0x20000000 /* EEE capability nego */
|
||||
#define IGC_EEER_TX_LPI_EN 0x00010000 /* EEER Tx LPI Enable */
|
||||
#define IGC_EEER_RX_LPI_EN 0x00020000 /* EEER Rx LPI Enable */
|
||||
#define IGC_EEER_LPI_FC 0x00040000 /* EEER Ena on Flow Cntrl */
|
||||
#define IGC_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */
|
||||
|
||||
/* LTR defines */
|
||||
#define IGC_LTRC_EEEMS_EN 0x00000020 /* Enable EEE LTR max send */
|
||||
#define IGC_RXPBS_SIZE_I225_MASK 0x0000003F /* Rx packet buffer size */
|
||||
#define IGC_TW_SYSTEM_1000_MASK 0x000000FF
|
||||
/* Minimum time for 100BASE-T where no data will be transmit following move out
|
||||
* of EEE LPI Tx state
|
||||
*/
|
||||
#define IGC_TW_SYSTEM_100_MASK 0x0000FF00
|
||||
#define IGC_TW_SYSTEM_100_SHIFT 8
|
||||
#define IGC_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */
|
||||
#define IGC_DMACR_DMACTHR_MASK 0x00FF0000
|
||||
#define IGC_DMACR_DMACTHR_SHIFT 16
|
||||
/* Reg val to set scale to 1024 nsec */
|
||||
#define IGC_LTRMINV_SCALE_1024 2
|
||||
/* Reg val to set scale to 32768 nsec */
|
||||
#define IGC_LTRMINV_SCALE_32768 3
|
||||
/* Reg val to set scale to 1024 nsec */
|
||||
#define IGC_LTRMAXV_SCALE_1024 2
|
||||
/* Reg val to set scale to 32768 nsec */
|
||||
#define IGC_LTRMAXV_SCALE_32768 3
|
||||
#define IGC_LTRMINV_LTRV_MASK 0x000003FF /* LTR minimum value */
|
||||
#define IGC_LTRMAXV_LTRV_MASK 0x000003FF /* LTR maximum value */
|
||||
#define IGC_LTRMINV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */
|
||||
#define IGC_LTRMINV_SCALE_SHIFT 10
|
||||
#define IGC_LTRMAXV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */
|
||||
#define IGC_LTRMAXV_SCALE_SHIFT 10
|
||||
|
||||
#endif /* _IGC_DEFINES_H_ */
|
||||
|
|
@ -0,0 +1,596 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_DEFINES_H_
|
||||
#define _IGC_DEFINES_H_
|
||||
|
||||
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
|
||||
#define REQ_TX_DESCRIPTOR_MULTIPLE 8
|
||||
#define REQ_RX_DESCRIPTOR_MULTIPLE 8
|
||||
|
||||
#define IGC_CTRL_EXT_SDP2_DIR 0x00000400 /* SDP2 Data direction */
|
||||
#define IGC_CTRL_EXT_SDP3_DIR 0x00000800 /* SDP3 Data direction */
|
||||
#define IGC_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */
|
||||
|
||||
/* Definitions for power management and wakeup registers */
|
||||
/* Wake Up Control */
|
||||
#define IGC_WUC_PME_EN 0x00000002 /* PME Enable */
|
||||
|
||||
/* Wake Up Filter Control */
|
||||
#define IGC_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
|
||||
#define IGC_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
|
||||
#define IGC_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
|
||||
#define IGC_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */
|
||||
#define IGC_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
|
||||
|
||||
#define IGC_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */
|
||||
|
||||
/* Wake Up Status */
|
||||
#define IGC_WUS_EX 0x00000004 /* Directed Exact */
|
||||
#define IGC_WUS_ARPD 0x00000020 /* Directed ARP Request */
|
||||
#define IGC_WUS_IPV4 0x00000040 /* Directed IPv4 */
|
||||
#define IGC_WUS_IPV6 0x00000080 /* Directed IPv6 */
|
||||
#define IGC_WUS_NSD 0x00000400 /* Directed IPv6 Neighbor Solicitation */
|
||||
|
||||
/* Packet types that are enabled for wake packet delivery */
|
||||
#define WAKE_PKT_WUS ( \
|
||||
IGC_WUS_EX | \
|
||||
IGC_WUS_ARPD | \
|
||||
IGC_WUS_IPV4 | \
|
||||
IGC_WUS_IPV6 | \
|
||||
IGC_WUS_NSD)
|
||||
|
||||
/* Wake Up Packet Length */
|
||||
#define IGC_WUPL_MASK 0x00000FFF
|
||||
|
||||
/* Wake Up Packet Memory stores the first 128 bytes of the wake up packet */
|
||||
#define IGC_WUPM_BYTES 128
|
||||
|
||||
/* Loop limit on how long we wait for auto-negotiation to complete */
|
||||
#define COPPER_LINK_UP_LIMIT 10
|
||||
#define PHY_AUTO_NEG_LIMIT 45
|
||||
|
||||
/* Number of 100 microseconds we wait for PCI Express master disable */
|
||||
#define MASTER_DISABLE_TIMEOUT 800
|
||||
/*Blocks new Master requests */
|
||||
#define IGC_CTRL_GIO_MASTER_DISABLE 0x00000004
|
||||
/* Status of Master requests. */
|
||||
#define IGC_STATUS_GIO_MASTER_ENABLE 0x00080000
|
||||
|
||||
/* Receive Address
|
||||
* Number of high/low register pairs in the RAR. The RAR (Receive Address
|
||||
* Registers) holds the directed and multicast addresses that we monitor.
|
||||
* Technically, we have 16 spots. However, we reserve one of these spots
|
||||
* (RAR[15]) for our directed address used by controllers with
|
||||
* manageability enabled, allowing us room for 15 multicast addresses.
|
||||
*/
|
||||
#define IGC_RAH_RAH_MASK 0x0000FFFF
|
||||
#define IGC_RAH_ASEL_MASK 0x00030000
|
||||
#define IGC_RAH_ASEL_SRC_ADDR BIT(16)
|
||||
#define IGC_RAH_QSEL_MASK 0x000C0000
|
||||
#define IGC_RAH_QSEL_SHIFT 18
|
||||
#define IGC_RAH_QSEL_ENABLE BIT(28)
|
||||
#define IGC_RAH_AV 0x80000000 /* Receive descriptor valid */
|
||||
|
||||
#define IGC_RAL_MAC_ADDR_LEN 4
|
||||
#define IGC_RAH_MAC_ADDR_LEN 2
|
||||
|
||||
/* Error Codes */
|
||||
#define IGC_SUCCESS 0
|
||||
#define IGC_ERR_NVM 1
|
||||
#define IGC_ERR_PHY 2
|
||||
#define IGC_ERR_CONFIG 3
|
||||
#define IGC_ERR_PARAM 4
|
||||
#define IGC_ERR_MAC_INIT 5
|
||||
#define IGC_ERR_RESET 9
|
||||
#define IGC_ERR_MASTER_REQUESTS_PENDING 10
|
||||
#define IGC_ERR_BLK_PHY_RESET 12
|
||||
#define IGC_ERR_SWFW_SYNC 13
|
||||
|
||||
/* Device Control */
|
||||
#define IGC_CTRL_DEV_RST 0x20000000 /* Device reset */
|
||||
|
||||
#define IGC_CTRL_PHY_RST 0x80000000 /* PHY Reset */
|
||||
#define IGC_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
|
||||
#define IGC_CTRL_FRCSPD 0x00000800 /* Force Speed */
|
||||
#define IGC_CTRL_FRCDPX 0x00001000 /* Force Duplex */
|
||||
#define IGC_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
|
||||
|
||||
#define IGC_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
|
||||
#define IGC_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
|
||||
|
||||
#define IGC_CTRL_SDP0_DIR 0x00400000 /* SDP0 Data direction */
|
||||
#define IGC_CTRL_SDP1_DIR 0x00800000 /* SDP1 Data direction */
|
||||
|
||||
/* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */
|
||||
#define MAX_JUMBO_FRAME_SIZE 0x2600
|
||||
|
||||
/* PBA constants */
|
||||
#define IGC_PBA_34K 0x0022
|
||||
|
||||
/* SW Semaphore Register */
|
||||
#define IGC_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
|
||||
#define IGC_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
|
||||
|
||||
/* SWFW_SYNC Definitions */
|
||||
#define IGC_SWFW_EEP_SM 0x1
|
||||
#define IGC_SWFW_PHY0_SM 0x2
|
||||
|
||||
/* Autoneg Advertisement Register */
|
||||
#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
|
||||
#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
|
||||
#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
|
||||
#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
|
||||
#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
|
||||
#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
|
||||
|
||||
/* Link Partner Ability Register (Base Page) */
|
||||
#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
|
||||
#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
|
||||
|
||||
/* 1000BASE-T Control Register */
|
||||
#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
|
||||
#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
|
||||
|
||||
/* 1000BASE-T Status Register */
|
||||
#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
|
||||
|
||||
/* PHY GPY 211 registers */
|
||||
#define STANDARD_AN_REG_MASK 0x0007 /* MMD */
|
||||
#define ANEG_MULTIGBT_AN_CTRL 0x0020 /* MULTI GBT AN Control Register */
|
||||
#define MMD_DEVADDR_SHIFT 16 /* Shift MMD to higher bits */
|
||||
#define CR_2500T_FD_CAPS 0x0080 /* Advertise 2500T FD capability */
|
||||
|
||||
/* NVM Control */
|
||||
/* Number of milliseconds for NVM auto read done after MAC reset. */
|
||||
#define AUTO_READ_DONE_TIMEOUT 10
|
||||
#define IGC_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
|
||||
#define IGC_EECD_REQ 0x00000040 /* NVM Access Request */
|
||||
#define IGC_EECD_GNT 0x00000080 /* NVM Access Grant */
|
||||
/* NVM Addressing bits based on type 0=small, 1=large */
|
||||
#define IGC_EECD_ADDR_BITS 0x00000400
|
||||
#define IGC_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */
|
||||
#define IGC_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
|
||||
#define IGC_EECD_SIZE_EX_SHIFT 11
|
||||
#define IGC_EECD_FLUPD_I225 0x00800000 /* Update FLASH */
|
||||
#define IGC_EECD_FLUDONE_I225 0x04000000 /* Update FLASH done*/
|
||||
#define IGC_EECD_FLASH_DETECTED_I225 0x00080000 /* FLASH detected */
|
||||
#define IGC_FLUDONE_ATTEMPTS 20000
|
||||
#define IGC_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */
|
||||
|
||||
/* Offset to data in NVM read/write registers */
|
||||
#define IGC_NVM_RW_REG_DATA 16
|
||||
#define IGC_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
|
||||
#define IGC_NVM_RW_REG_START 1 /* Start operation */
|
||||
#define IGC_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
|
||||
#define IGC_NVM_POLL_READ 0 /* Flag for polling for read complete */
|
||||
#define IGC_NVM_DEV_STARTER 5 /* Dev_starter Version */
|
||||
|
||||
/* NVM Word Offsets */
|
||||
#define NVM_CHECKSUM_REG 0x003F
|
||||
|
||||
/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
|
||||
#define NVM_SUM 0xBABA
|
||||
#define NVM_WORD_SIZE_BASE_SHIFT 6
|
||||
|
||||
/* Collision related configuration parameters */
|
||||
#define IGC_COLLISION_THRESHOLD 15
|
||||
#define IGC_CT_SHIFT 4
|
||||
#define IGC_COLLISION_DISTANCE 63
|
||||
#define IGC_COLD_SHIFT 12
|
||||
|
||||
/* Device Status */
|
||||
#define IGC_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
|
||||
#define IGC_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
|
||||
#define IGC_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
|
||||
#define IGC_STATUS_FUNC_SHIFT 2
|
||||
#define IGC_STATUS_TXOFF 0x00000010 /* transmission paused */
|
||||
#define IGC_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
|
||||
#define IGC_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
|
||||
#define IGC_STATUS_SPEED_2500 0x00400000 /* Speed 2.5Gb/s */
|
||||
|
||||
#define SPEED_10 10
|
||||
#define SPEED_100 100
|
||||
#define SPEED_1000 1000
|
||||
#define SPEED_2500 2500
|
||||
#define HALF_DUPLEX 1
|
||||
#define FULL_DUPLEX 2
|
||||
|
||||
/* 1Gbps and 2.5Gbps half duplex is not supported, nor spec-compliant. */
|
||||
#define ADVERTISE_10_HALF 0x0001
|
||||
#define ADVERTISE_10_FULL 0x0002
|
||||
#define ADVERTISE_100_HALF 0x0004
|
||||
#define ADVERTISE_100_FULL 0x0008
|
||||
#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */
|
||||
#define ADVERTISE_1000_FULL 0x0020
|
||||
#define ADVERTISE_2500_HALF 0x0040 /* Not used, just FYI */
|
||||
#define ADVERTISE_2500_FULL 0x0080
|
||||
|
||||
#define IGC_ALL_SPEED_DUPLEX_2500 ( \
|
||||
ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \
|
||||
ADVERTISE_100_FULL | ADVERTISE_1000_FULL | ADVERTISE_2500_FULL)
|
||||
|
||||
#define AUTONEG_ADVERTISE_SPEED_DEFAULT_2500 IGC_ALL_SPEED_DUPLEX_2500
|
||||
|
||||
/* Interrupt Cause Read */
|
||||
#define IGC_ICR_TXDW BIT(0) /* Transmit desc written back */
|
||||
#define IGC_ICR_TXQE BIT(1) /* Transmit Queue empty */
|
||||
#define IGC_ICR_LSC BIT(2) /* Link Status Change */
|
||||
#define IGC_ICR_RXSEQ BIT(3) /* Rx sequence error */
|
||||
#define IGC_ICR_RXDMT0 BIT(4) /* Rx desc min. threshold (0) */
|
||||
#define IGC_ICR_RXO BIT(6) /* Rx overrun */
|
||||
#define IGC_ICR_RXT0 BIT(7) /* Rx timer intr (ring 0) */
|
||||
#define IGC_ICR_TS BIT(19) /* Time Sync Interrupt */
|
||||
#define IGC_ICR_DRSTA BIT(30) /* Device Reset Asserted */
|
||||
|
||||
/* If this bit asserted, the driver should claim the interrupt */
|
||||
#define IGC_ICR_INT_ASSERTED BIT(31)
|
||||
|
||||
#define IGC_ICS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */
|
||||
|
||||
#define IMS_ENABLE_MASK ( \
|
||||
IGC_IMS_RXT0 | \
|
||||
IGC_IMS_TXDW | \
|
||||
IGC_IMS_RXDMT0 | \
|
||||
IGC_IMS_RXSEQ | \
|
||||
IGC_IMS_LSC)
|
||||
|
||||
/* Interrupt Mask Set */
|
||||
#define IGC_IMS_TXDW IGC_ICR_TXDW /* Tx desc written back */
|
||||
#define IGC_IMS_RXSEQ IGC_ICR_RXSEQ /* Rx sequence error */
|
||||
#define IGC_IMS_LSC IGC_ICR_LSC /* Link Status Change */
|
||||
#define IGC_IMS_DOUTSYNC IGC_ICR_DOUTSYNC /* NIC DMA out of sync */
|
||||
#define IGC_IMS_DRSTA IGC_ICR_DRSTA /* Device Reset Asserted */
|
||||
#define IGC_IMS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */
|
||||
#define IGC_IMS_RXDMT0 IGC_ICR_RXDMT0 /* Rx desc min. threshold */
|
||||
#define IGC_IMS_TS IGC_ICR_TS /* Time Sync Interrupt */
|
||||
|
||||
#define IGC_QVECTOR_MASK 0x7FFC /* Q-vector mask */
|
||||
#define IGC_ITR_VAL_MASK 0x04 /* ITR value mask */
|
||||
|
||||
/* Interrupt Cause Set */
|
||||
#define IGC_ICS_LSC IGC_ICR_LSC /* Link Status Change */
|
||||
#define IGC_ICS_RXDMT0 IGC_ICR_RXDMT0 /* rx desc min. threshold */
|
||||
|
||||
#define IGC_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */
|
||||
#define IGC_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */
|
||||
#define IGC_IVAR_VALID 0x80
|
||||
#define IGC_GPIE_NSICR 0x00000001
|
||||
#define IGC_GPIE_MSIX_MODE 0x00000010
|
||||
#define IGC_GPIE_EIAME 0x40000000
|
||||
#define IGC_GPIE_PBA 0x80000000
|
||||
|
||||
/* Receive Descriptor bit definitions */
|
||||
#define IGC_RXD_STAT_DD 0x01 /* Descriptor Done */
|
||||
|
||||
/* Transmit Descriptor bit definitions */
|
||||
#define IGC_TXD_DTYP_D 0x00100000 /* Data Descriptor */
|
||||
#define IGC_TXD_DTYP_C 0x00000000 /* Context Descriptor */
|
||||
#define IGC_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
|
||||
#define IGC_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
|
||||
#define IGC_TXD_CMD_EOP 0x01000000 /* End of Packet */
|
||||
#define IGC_TXD_CMD_IC 0x04000000 /* Insert Checksum */
|
||||
#define IGC_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */
|
||||
#define IGC_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */
|
||||
#define IGC_TXD_STAT_DD 0x00000001 /* Descriptor Done */
|
||||
#define IGC_TXD_CMD_TCP 0x01000000 /* TCP packet */
|
||||
#define IGC_TXD_CMD_IP 0x02000000 /* IP packet */
|
||||
#define IGC_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
|
||||
#define IGC_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */
|
||||
|
||||
/* IPSec Encrypt Enable */
|
||||
#define IGC_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define IGC_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
|
||||
/* Transmit Control */
|
||||
#define IGC_TCTL_EN 0x00000002 /* enable Tx */
|
||||
#define IGC_TCTL_PSP 0x00000008 /* pad short packets */
|
||||
#define IGC_TCTL_CT 0x00000ff0 /* collision threshold */
|
||||
#define IGC_TCTL_COLD 0x003ff000 /* collision distance */
|
||||
#define IGC_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
|
||||
|
||||
/* Flow Control Constants */
|
||||
#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001
|
||||
#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
|
||||
#define FLOW_CONTROL_TYPE 0x8808
|
||||
/* Enable XON frame transmission */
|
||||
#define IGC_FCRTL_XONE 0x80000000
|
||||
|
||||
/* Management Control */
|
||||
#define IGC_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
|
||||
#define IGC_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
|
||||
|
||||
/* Receive Control */
|
||||
#define IGC_RCTL_RST 0x00000001 /* Software reset */
|
||||
#define IGC_RCTL_EN 0x00000002 /* enable */
|
||||
#define IGC_RCTL_SBP 0x00000004 /* store bad packet */
|
||||
#define IGC_RCTL_UPE 0x00000008 /* unicast promisc enable */
|
||||
#define IGC_RCTL_MPE 0x00000010 /* multicast promisc enable */
|
||||
#define IGC_RCTL_LPE 0x00000020 /* long packet enable */
|
||||
#define IGC_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
|
||||
#define IGC_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
|
||||
|
||||
#define IGC_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */
|
||||
#define IGC_RCTL_BAM 0x00008000 /* broadcast enable */
|
||||
|
||||
/* Split Replication Receive Control */
|
||||
#define IGC_SRRCTL_TIMESTAMP 0x40000000
|
||||
#define IGC_SRRCTL_TIMER1SEL(timer) (((timer) & 0x3) << 14)
|
||||
#define IGC_SRRCTL_TIMER0SEL(timer) (((timer) & 0x3) << 17)
|
||||
|
||||
/* Receive Descriptor bit definitions */
|
||||
#define IGC_RXD_STAT_EOP 0x02 /* End of Packet */
|
||||
#define IGC_RXD_STAT_IXSM 0x04 /* Ignore checksum */
|
||||
#define IGC_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
|
||||
#define IGC_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
|
||||
#define IGC_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
|
||||
|
||||
#define IGC_RXDEXT_STATERR_LB 0x00040000
|
||||
|
||||
/* Advanced Receive Descriptor bit definitions */
|
||||
#define IGC_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */
|
||||
|
||||
#define IGC_RXDEXT_STATERR_L4E 0x20000000
|
||||
#define IGC_RXDEXT_STATERR_IPE 0x40000000
|
||||
#define IGC_RXDEXT_STATERR_RXE 0x80000000
|
||||
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4 0x00020000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6 0x00100000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
|
||||
|
||||
/* Header split receive */
|
||||
#define IGC_RFCTL_IPV6_EX_DIS 0x00010000
|
||||
#define IGC_RFCTL_LEF 0x00040000
|
||||
|
||||
#define IGC_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */
|
||||
|
||||
#define IGC_RCTL_MO_SHIFT 12 /* multicast offset shift */
|
||||
#define IGC_RCTL_CFIEN 0x00080000 /* canonical form enable */
|
||||
#define IGC_RCTL_DPF 0x00400000 /* discard pause frames */
|
||||
#define IGC_RCTL_PMCF 0x00800000 /* pass MAC control frames */
|
||||
#define IGC_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
|
||||
|
||||
#define I225_RXPBSIZE_DEFAULT 0x000000A2 /* RXPBSIZE default */
|
||||
#define I225_TXPBSIZE_DEFAULT 0x04000014 /* TXPBSIZE default */
|
||||
#define IGC_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */
|
||||
|
||||
#define IGC_TXPBSIZE_TSN 0x04145145 /* 5k bytes buffer for each queue */
|
||||
|
||||
#define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */
|
||||
#define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */
|
||||
|
||||
/* Time Sync Interrupt Causes */
|
||||
#define IGC_TSICR_SYS_WRAP BIT(0) /* SYSTIM Wrap around. */
|
||||
#define IGC_TSICR_TXTS BIT(1) /* Transmit Timestamp. */
|
||||
#define IGC_TSICR_TT0 BIT(3) /* Target Time 0 Trigger. */
|
||||
#define IGC_TSICR_TT1 BIT(4) /* Target Time 1 Trigger. */
|
||||
#define IGC_TSICR_AUTT0 BIT(5) /* Auxiliary Timestamp 0 Taken. */
|
||||
#define IGC_TSICR_AUTT1 BIT(6) /* Auxiliary Timestamp 1 Taken. */
|
||||
|
||||
#define IGC_TSICR_INTERRUPTS IGC_TSICR_TXTS
|
||||
|
||||
#define IGC_FTQF_VF_BP 0x00008000
|
||||
#define IGC_FTQF_1588_TIME_STAMP 0x08000000
|
||||
#define IGC_FTQF_MASK 0xF0000000
|
||||
#define IGC_FTQF_MASK_PROTO_BP 0x10000000
|
||||
|
||||
/* Time Sync Receive Control bit definitions */
|
||||
#define IGC_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */
|
||||
#define IGC_TSYNCRXCTL_TYPE_L2_V2 0x00
|
||||
#define IGC_TSYNCRXCTL_TYPE_L4_V1 0x02
|
||||
#define IGC_TSYNCRXCTL_TYPE_L2_L4_V2 0x04
|
||||
#define IGC_TSYNCRXCTL_TYPE_ALL 0x08
|
||||
#define IGC_TSYNCRXCTL_TYPE_EVENT_V2 0x0A
|
||||
#define IGC_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */
|
||||
#define IGC_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */
|
||||
#define IGC_TSYNCRXCTL_RXSYNSIG 0x00000400 /* Sample RX tstamp in PHY sop */
|
||||
|
||||
/* Time Sync Receive Configuration */
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01
|
||||
|
||||
/* Immediate Interrupt Receive */
|
||||
#define IGC_IMIR_CLEAR_MASK 0xF001FFFF /* IMIR Reg Clear Mask */
|
||||
#define IGC_IMIR_PORT_BYPASS 0x20000 /* IMIR Port Bypass Bit */
|
||||
#define IGC_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */
|
||||
#define IGC_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */
|
||||
|
||||
/* Immediate Interrupt Receive Extended */
|
||||
#define IGC_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */
|
||||
#define IGC_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
|
||||
|
||||
/* Time Sync Transmit Control bit definitions */
|
||||
#define IGC_TSYNCTXCTL_TXTT_0 0x00000001 /* Tx timestamp reg 0 valid */
|
||||
#define IGC_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */
|
||||
#define IGC_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */
|
||||
#define IGC_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */
|
||||
#define IGC_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete */
|
||||
#define IGC_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */
|
||||
#define IGC_TSYNCTXCTL_TXSYNSIG 0x00000020 /* Sample TX tstamp in PHY sop */
|
||||
|
||||
/* Timer selection bits */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM0 (0u << 30) /* Select SYSTIM0 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM1 (1u << 30) /* Select SYSTIM1 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM2 (2u << 30) /* Select SYSTIM2 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM3 (3u << 30) /* Select SYSTIM3 for auxiliary time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM0 (0u << 30) /* Select SYSTIM0 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM1 (1u << 30) /* Select SYSTIM1 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM2 (2u << 30) /* Select SYSTIM2 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM3 (3u << 30) /* Select SYSTIM3 for target time stamp */
|
||||
|
||||
/* TSAUXC Configuration Bits */
|
||||
#define IGC_TSAUXC_EN_TT0 BIT(0) /* Enable target time 0. */
|
||||
#define IGC_TSAUXC_EN_TT1 BIT(1) /* Enable target time 1. */
|
||||
#define IGC_TSAUXC_EN_CLK0 BIT(2) /* Enable Configurable Frequency Clock 0. */
|
||||
#define IGC_TSAUXC_EN_CLK1 BIT(5) /* Enable Configurable Frequency Clock 1. */
|
||||
#define IGC_TSAUXC_EN_TS0 BIT(8) /* Enable hardware timestamp 0. */
|
||||
#define IGC_TSAUXC_AUTT0 BIT(9) /* Auxiliary Timestamp Taken. */
|
||||
#define IGC_TSAUXC_EN_TS1 BIT(10) /* Enable hardware timestamp 0. */
|
||||
#define IGC_TSAUXC_AUTT1 BIT(11) /* Auxiliary Timestamp Taken. */
|
||||
#define IGC_TSAUXC_PLSG BIT(17) /* Generate a pulse. */
|
||||
#define IGC_TSAUXC_DISABLE1 BIT(27) /* Disable SYSTIM0 Count Operation. */
|
||||
#define IGC_TSAUXC_DISABLE2 BIT(28) /* Disable SYSTIM1 Count Operation. */
|
||||
#define IGC_TSAUXC_DISABLE3 BIT(29) /* Disable SYSTIM2 Count Operation. */
|
||||
#define IGC_TSAUXC_DIS_TS_CLEAR BIT(30) /* Disable EN_TT0/1 auto clear. */
|
||||
#define IGC_TSAUXC_DISABLE0 BIT(31) /* Disable SYSTIM0 Count Operation. */
|
||||
|
||||
/* SDP Configuration Bits */
|
||||
#define IGC_AUX0_SEL_SDP0 (0u << 0) /* Assign SDP0 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP1 (1u << 0) /* Assign SDP1 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP2 (2u << 0) /* Assign SDP2 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP3 (3u << 0) /* Assign SDP3 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_TS_SDP_EN (1u << 2) /* Enable auxiliary time stamp trigger 0. */
|
||||
#define IGC_AUX1_SEL_SDP0 (0u << 3) /* Assign SDP0 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP1 (1u << 3) /* Assign SDP1 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP2 (2u << 3) /* Assign SDP2 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP3 (3u << 3) /* Assign SDP3 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_TS_SDP_EN (1u << 5) /* Enable auxiliary time stamp trigger 1. */
|
||||
#define IGC_TS_SDP0_SEL_TT0 (0u << 6) /* Target time 0 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_TT1 (1u << 6) /* Target time 1 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_FC0 (2u << 6) /* Freq clock 0 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_FC1 (3u << 6) /* Freq clock 1 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_EN (1u << 8) /* SDP0 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP1_SEL_TT0 (0u << 9) /* Target time 0 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_TT1 (1u << 9) /* Target time 1 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_FC0 (2u << 9) /* Freq clock 0 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_FC1 (3u << 9) /* Freq clock 1 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_EN (1u << 11) /* SDP1 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP2_SEL_TT0 (0u << 12) /* Target time 0 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_TT1 (1u << 12) /* Target time 1 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_FC0 (2u << 12) /* Freq clock 0 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_FC1 (3u << 12) /* Freq clock 1 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_EN (1u << 14) /* SDP2 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP3_SEL_TT0 (0u << 15) /* Target time 0 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_TT1 (1u << 15) /* Target time 1 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_FC0 (2u << 15) /* Freq clock 0 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_FC1 (3u << 15) /* Freq clock 1 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_EN (1u << 17) /* SDP3 is assigned to Tsync. */
|
||||
|
||||
/* Transmit Scheduling */
|
||||
#define IGC_TQAVCTRL_TRANSMIT_MODE_TSN 0x00000001
|
||||
#define IGC_TQAVCTRL_ENHANCED_QAV 0x00000008
|
||||
|
||||
#define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001
|
||||
#define IGC_TXQCTL_STRICT_CYCLE 0x00000002
|
||||
#define IGC_TXQCTL_STRICT_END 0x00000004
|
||||
|
||||
/* Receive Checksum Control */
|
||||
#define IGC_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */
|
||||
#define IGC_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
|
||||
|
||||
/* GPY211 - I225 defines */
|
||||
#define GPY_MMD_MASK 0xFFFF0000
|
||||
#define GPY_MMD_SHIFT 16
|
||||
#define GPY_REG_MASK 0x0000FFFF
|
||||
|
||||
#define IGC_MMDAC_FUNC_DATA 0x4000 /* Data, no post increment */
|
||||
|
||||
/* MAC definitions */
|
||||
#define IGC_FACTPS_MNGCG 0x20000000
|
||||
#define IGC_FWSM_MODE_MASK 0xE
|
||||
#define IGC_FWSM_MODE_SHIFT 1
|
||||
|
||||
/* Management Control */
|
||||
#define IGC_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */
|
||||
#define IGC_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */
|
||||
|
||||
/* PHY */
|
||||
#define PHY_REVISION_MASK 0xFFFFFFF0
|
||||
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
|
||||
#define IGC_GEN_POLL_TIMEOUT 1920
|
||||
|
||||
/* PHY Control Register */
|
||||
#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
|
||||
#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
|
||||
#define MII_CR_POWER_DOWN 0x0800 /* Power down */
|
||||
#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
|
||||
|
||||
/* PHY Status Register */
|
||||
#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
|
||||
#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
|
||||
#define IGC_PHY_RST_COMP 0x0100 /* Internal PHY reset completion */
|
||||
|
||||
/* PHY 1000 MII Register/Bit Definitions */
|
||||
/* PHY Registers defined by IEEE */
|
||||
#define PHY_CONTROL 0x00 /* Control Register */
|
||||
#define PHY_STATUS 0x01 /* Status Register */
|
||||
#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
|
||||
#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
|
||||
#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
|
||||
#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
|
||||
#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
|
||||
#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
|
||||
|
||||
/* Bit definitions for valid PHY IDs. I = Integrated E = External */
|
||||
#define I225_I_PHY_ID 0x67C9DC00
|
||||
|
||||
/* MDI Control */
|
||||
#define IGC_MDIC_DATA_MASK 0x0000FFFF
|
||||
#define IGC_MDIC_REG_MASK 0x001F0000
|
||||
#define IGC_MDIC_REG_SHIFT 16
|
||||
#define IGC_MDIC_PHY_MASK 0x03E00000
|
||||
#define IGC_MDIC_PHY_SHIFT 21
|
||||
#define IGC_MDIC_OP_WRITE 0x04000000
|
||||
#define IGC_MDIC_OP_READ 0x08000000
|
||||
#define IGC_MDIC_READY 0x10000000
|
||||
#define IGC_MDIC_INT_EN 0x20000000
|
||||
#define IGC_MDIC_ERROR 0x40000000
|
||||
|
||||
#define IGC_N0_QUEUE -1
|
||||
|
||||
#define IGC_MAX_MAC_HDR_LEN 127
|
||||
#define IGC_MAX_NETWORK_HDR_LEN 511
|
||||
|
||||
#define IGC_VLANPQF_QSEL(_n, q_idx) ((q_idx) << ((_n) * 4))
|
||||
#define IGC_VLANPQF_VALID(_n) (0x1 << (3 + (_n) * 4))
|
||||
#define IGC_VLANPQF_QUEUE_MASK 0x03
|
||||
|
||||
#define IGC_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define IGC_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type:1=IPv4 */
|
||||
#define IGC_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet Type of TCP */
|
||||
#define IGC_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
|
||||
|
||||
/* Maximum size of the MTA register table in all supported adapters */
|
||||
#define MAX_MTA_REG 128
|
||||
|
||||
/* EEE defines */
|
||||
#define IGC_IPCNFG_EEE_2_5G_AN 0x00000010 /* IPCNFG EEE Ena 2.5G AN */
|
||||
#define IGC_IPCNFG_EEE_1G_AN 0x00000008 /* IPCNFG EEE Ena 1G AN */
|
||||
#define IGC_IPCNFG_EEE_100M_AN 0x00000004 /* IPCNFG EEE Ena 100M AN */
|
||||
#define IGC_EEER_EEE_NEG 0x20000000 /* EEE capability nego */
|
||||
#define IGC_EEER_TX_LPI_EN 0x00010000 /* EEER Tx LPI Enable */
|
||||
#define IGC_EEER_RX_LPI_EN 0x00020000 /* EEER Rx LPI Enable */
|
||||
#define IGC_EEER_LPI_FC 0x00040000 /* EEER Ena on Flow Cntrl */
|
||||
#define IGC_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */
|
||||
|
||||
/* LTR defines */
|
||||
#define IGC_LTRC_EEEMS_EN 0x00000020 /* Enable EEE LTR max send */
|
||||
#define IGC_RXPBS_SIZE_I225_MASK 0x0000003F /* Rx packet buffer size */
|
||||
#define IGC_TW_SYSTEM_1000_MASK 0x000000FF
|
||||
/* Minimum time for 100BASE-T where no data will be transmit following move out
|
||||
* of EEE LPI Tx state
|
||||
*/
|
||||
#define IGC_TW_SYSTEM_100_MASK 0x0000FF00
|
||||
#define IGC_TW_SYSTEM_100_SHIFT 8
|
||||
#define IGC_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */
|
||||
#define IGC_DMACR_DMACTHR_MASK 0x00FF0000
|
||||
#define IGC_DMACR_DMACTHR_SHIFT 16
|
||||
/* Reg val to set scale to 1024 nsec */
|
||||
#define IGC_LTRMINV_SCALE_1024 2
|
||||
/* Reg val to set scale to 32768 nsec */
|
||||
#define IGC_LTRMINV_SCALE_32768 3
|
||||
/* Reg val to set scale to 1024 nsec */
|
||||
#define IGC_LTRMAXV_SCALE_1024 2
|
||||
/* Reg val to set scale to 32768 nsec */
|
||||
#define IGC_LTRMAXV_SCALE_32768 3
|
||||
#define IGC_LTRMINV_LTRV_MASK 0x000003FF /* LTR minimum value */
|
||||
#define IGC_LTRMAXV_LTRV_MASK 0x000003FF /* LTR maximum value */
|
||||
#define IGC_LTRMINV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */
|
||||
#define IGC_LTRMINV_SCALE_SHIFT 10
|
||||
#define IGC_LTRMAXV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */
|
||||
#define IGC_LTRMAXV_SCALE_SHIFT 10
|
||||
|
||||
#endif /* _IGC_DEFINES_H_ */
|
||||
|
|
@ -0,0 +1,673 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_DEFINES_H_
|
||||
#define _IGC_DEFINES_H_
|
||||
|
||||
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
|
||||
#define REQ_TX_DESCRIPTOR_MULTIPLE 8
|
||||
#define REQ_RX_DESCRIPTOR_MULTIPLE 8
|
||||
|
||||
#define IGC_CTRL_EXT_SDP2_DIR 0x00000400 /* SDP2 Data direction */
|
||||
#define IGC_CTRL_EXT_SDP3_DIR 0x00000800 /* SDP3 Data direction */
|
||||
#define IGC_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */
|
||||
|
||||
/* Definitions for power management and wakeup registers */
|
||||
/* Wake Up Control */
|
||||
#define IGC_WUC_PME_EN 0x00000002 /* PME Enable */
|
||||
|
||||
/* Wake Up Filter Control */
|
||||
#define IGC_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
|
||||
#define IGC_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
|
||||
#define IGC_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
|
||||
#define IGC_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */
|
||||
#define IGC_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
|
||||
#define IGC_WUFC_FLEX_HQ BIT(14) /* Flex Filters Host Queuing */
|
||||
#define IGC_WUFC_FLX0 BIT(16) /* Flexible Filter 0 Enable */
|
||||
#define IGC_WUFC_FLX1 BIT(17) /* Flexible Filter 1 Enable */
|
||||
#define IGC_WUFC_FLX2 BIT(18) /* Flexible Filter 2 Enable */
|
||||
#define IGC_WUFC_FLX3 BIT(19) /* Flexible Filter 3 Enable */
|
||||
#define IGC_WUFC_FLX4 BIT(20) /* Flexible Filter 4 Enable */
|
||||
#define IGC_WUFC_FLX5 BIT(21) /* Flexible Filter 5 Enable */
|
||||
#define IGC_WUFC_FLX6 BIT(22) /* Flexible Filter 6 Enable */
|
||||
#define IGC_WUFC_FLX7 BIT(23) /* Flexible Filter 7 Enable */
|
||||
|
||||
#define IGC_WUFC_FILTER_MASK GENMASK(23, 14)
|
||||
|
||||
#define IGC_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */
|
||||
|
||||
/* Wake Up Status */
|
||||
#define IGC_WUS_EX 0x00000004 /* Directed Exact */
|
||||
#define IGC_WUS_ARPD 0x00000020 /* Directed ARP Request */
|
||||
#define IGC_WUS_IPV4 0x00000040 /* Directed IPv4 */
|
||||
#define IGC_WUS_IPV6 0x00000080 /* Directed IPv6 */
|
||||
#define IGC_WUS_NSD 0x00000400 /* Directed IPv6 Neighbor Solicitation */
|
||||
|
||||
/* Packet types that are enabled for wake packet delivery */
|
||||
#define WAKE_PKT_WUS ( \
|
||||
IGC_WUS_EX | \
|
||||
IGC_WUS_ARPD | \
|
||||
IGC_WUS_IPV4 | \
|
||||
IGC_WUS_IPV6 | \
|
||||
IGC_WUS_NSD)
|
||||
|
||||
/* Wake Up Packet Length */
|
||||
#define IGC_WUPL_MASK 0x00000FFF
|
||||
|
||||
/* Wake Up Packet Memory stores the first 128 bytes of the wake up packet */
|
||||
#define IGC_WUPM_BYTES 128
|
||||
|
||||
/* Wakeup Filter Control Extended */
|
||||
#define IGC_WUFC_EXT_FLX8 BIT(8) /* Flexible Filter 8 Enable */
|
||||
#define IGC_WUFC_EXT_FLX9 BIT(9) /* Flexible Filter 9 Enable */
|
||||
#define IGC_WUFC_EXT_FLX10 BIT(10) /* Flexible Filter 10 Enable */
|
||||
#define IGC_WUFC_EXT_FLX11 BIT(11) /* Flexible Filter 11 Enable */
|
||||
#define IGC_WUFC_EXT_FLX12 BIT(12) /* Flexible Filter 12 Enable */
|
||||
#define IGC_WUFC_EXT_FLX13 BIT(13) /* Flexible Filter 13 Enable */
|
||||
#define IGC_WUFC_EXT_FLX14 BIT(14) /* Flexible Filter 14 Enable */
|
||||
#define IGC_WUFC_EXT_FLX15 BIT(15) /* Flexible Filter 15 Enable */
|
||||
#define IGC_WUFC_EXT_FLX16 BIT(16) /* Flexible Filter 16 Enable */
|
||||
#define IGC_WUFC_EXT_FLX17 BIT(17) /* Flexible Filter 17 Enable */
|
||||
#define IGC_WUFC_EXT_FLX18 BIT(18) /* Flexible Filter 18 Enable */
|
||||
#define IGC_WUFC_EXT_FLX19 BIT(19) /* Flexible Filter 19 Enable */
|
||||
#define IGC_WUFC_EXT_FLX20 BIT(20) /* Flexible Filter 20 Enable */
|
||||
#define IGC_WUFC_EXT_FLX21 BIT(21) /* Flexible Filter 21 Enable */
|
||||
#define IGC_WUFC_EXT_FLX22 BIT(22) /* Flexible Filter 22 Enable */
|
||||
#define IGC_WUFC_EXT_FLX23 BIT(23) /* Flexible Filter 23 Enable */
|
||||
#define IGC_WUFC_EXT_FLX24 BIT(24) /* Flexible Filter 24 Enable */
|
||||
#define IGC_WUFC_EXT_FLX25 BIT(25) /* Flexible Filter 25 Enable */
|
||||
#define IGC_WUFC_EXT_FLX26 BIT(26) /* Flexible Filter 26 Enable */
|
||||
#define IGC_WUFC_EXT_FLX27 BIT(27) /* Flexible Filter 27 Enable */
|
||||
#define IGC_WUFC_EXT_FLX28 BIT(28) /* Flexible Filter 28 Enable */
|
||||
#define IGC_WUFC_EXT_FLX29 BIT(29) /* Flexible Filter 29 Enable */
|
||||
#define IGC_WUFC_EXT_FLX30 BIT(30) /* Flexible Filter 30 Enable */
|
||||
#define IGC_WUFC_EXT_FLX31 BIT(31) /* Flexible Filter 31 Enable */
|
||||
|
||||
#define IGC_WUFC_EXT_FILTER_MASK GENMASK(31, 8)
|
||||
|
||||
/* Loop limit on how long we wait for auto-negotiation to complete */
|
||||
#define COPPER_LINK_UP_LIMIT 10
|
||||
#define PHY_AUTO_NEG_LIMIT 45
|
||||
|
||||
/* Number of 100 microseconds we wait for PCI Express master disable */
|
||||
#define MASTER_DISABLE_TIMEOUT 800
|
||||
/*Blocks new Master requests */
|
||||
#define IGC_CTRL_GIO_MASTER_DISABLE 0x00000004
|
||||
/* Status of Master requests. */
|
||||
#define IGC_STATUS_GIO_MASTER_ENABLE 0x00080000
|
||||
|
||||
/* Receive Address
|
||||
* Number of high/low register pairs in the RAR. The RAR (Receive Address
|
||||
* Registers) holds the directed and multicast addresses that we monitor.
|
||||
* Technically, we have 16 spots. However, we reserve one of these spots
|
||||
* (RAR[15]) for our directed address used by controllers with
|
||||
* manageability enabled, allowing us room for 15 multicast addresses.
|
||||
*/
|
||||
#define IGC_RAH_RAH_MASK 0x0000FFFF
|
||||
#define IGC_RAH_ASEL_MASK 0x00030000
|
||||
#define IGC_RAH_ASEL_SRC_ADDR BIT(16)
|
||||
#define IGC_RAH_QSEL_MASK 0x000C0000
|
||||
#define IGC_RAH_QSEL_SHIFT 18
|
||||
#define IGC_RAH_QSEL_ENABLE BIT(28)
|
||||
#define IGC_RAH_AV 0x80000000 /* Receive descriptor valid */
|
||||
|
||||
#define IGC_RAL_MAC_ADDR_LEN 4
|
||||
#define IGC_RAH_MAC_ADDR_LEN 2
|
||||
|
||||
/* Error Codes */
|
||||
#define IGC_SUCCESS 0
|
||||
#define IGC_ERR_NVM 1
|
||||
#define IGC_ERR_PHY 2
|
||||
#define IGC_ERR_CONFIG 3
|
||||
#define IGC_ERR_PARAM 4
|
||||
#define IGC_ERR_MAC_INIT 5
|
||||
#define IGC_ERR_RESET 9
|
||||
#define IGC_ERR_MASTER_REQUESTS_PENDING 10
|
||||
#define IGC_ERR_BLK_PHY_RESET 12
|
||||
#define IGC_ERR_SWFW_SYNC 13
|
||||
|
||||
/* Device Control */
|
||||
#define IGC_CTRL_RST 0x04000000 /* Global reset */
|
||||
|
||||
#define IGC_CTRL_PHY_RST 0x80000000 /* PHY Reset */
|
||||
#define IGC_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
|
||||
#define IGC_CTRL_FRCSPD 0x00000800 /* Force Speed */
|
||||
#define IGC_CTRL_FRCDPX 0x00001000 /* Force Duplex */
|
||||
#define IGC_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
|
||||
|
||||
#define IGC_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
|
||||
#define IGC_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
|
||||
|
||||
#define IGC_CTRL_SDP0_DIR 0x00400000 /* SDP0 Data direction */
|
||||
#define IGC_CTRL_SDP1_DIR 0x00800000 /* SDP1 Data direction */
|
||||
|
||||
/* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */
|
||||
#define MAX_JUMBO_FRAME_SIZE 0x2600
|
||||
|
||||
/* PBA constants */
|
||||
#define IGC_PBA_34K 0x0022
|
||||
|
||||
/* SW Semaphore Register */
|
||||
#define IGC_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
|
||||
#define IGC_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
|
||||
|
||||
/* SWFW_SYNC Definitions */
|
||||
#define IGC_SWFW_EEP_SM 0x1
|
||||
#define IGC_SWFW_PHY0_SM 0x2
|
||||
|
||||
/* Autoneg Advertisement Register */
|
||||
#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
|
||||
#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
|
||||
#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
|
||||
#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
|
||||
#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
|
||||
#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
|
||||
|
||||
/* Link Partner Ability Register (Base Page) */
|
||||
#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
|
||||
#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
|
||||
|
||||
/* 1000BASE-T Control Register */
|
||||
#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
|
||||
#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
|
||||
|
||||
/* 1000BASE-T Status Register */
|
||||
#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
|
||||
|
||||
/* PHY GPY 211 registers */
|
||||
#define STANDARD_AN_REG_MASK 0x0007 /* MMD */
|
||||
#define ANEG_MULTIGBT_AN_CTRL 0x0020 /* MULTI GBT AN Control Register */
|
||||
#define MMD_DEVADDR_SHIFT 16 /* Shift MMD to higher bits */
|
||||
#define CR_2500T_FD_CAPS 0x0080 /* Advertise 2500T FD capability */
|
||||
|
||||
/* NVM Control */
|
||||
/* Number of milliseconds for NVM auto read done after MAC reset. */
|
||||
#define AUTO_READ_DONE_TIMEOUT 10
|
||||
#define IGC_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
|
||||
#define IGC_EECD_REQ 0x00000040 /* NVM Access Request */
|
||||
#define IGC_EECD_GNT 0x00000080 /* NVM Access Grant */
|
||||
/* NVM Addressing bits based on type 0=small, 1=large */
|
||||
#define IGC_EECD_ADDR_BITS 0x00000400
|
||||
#define IGC_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */
|
||||
#define IGC_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
|
||||
#define IGC_EECD_SIZE_EX_SHIFT 11
|
||||
#define IGC_EECD_FLUPD_I225 0x00800000 /* Update FLASH */
|
||||
#define IGC_EECD_FLUDONE_I225 0x04000000 /* Update FLASH done*/
|
||||
#define IGC_EECD_FLASH_DETECTED_I225 0x00080000 /* FLASH detected */
|
||||
#define IGC_FLUDONE_ATTEMPTS 20000
|
||||
#define IGC_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */
|
||||
|
||||
/* Offset to data in NVM read/write registers */
|
||||
#define IGC_NVM_RW_REG_DATA 16
|
||||
#define IGC_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
|
||||
#define IGC_NVM_RW_REG_START 1 /* Start operation */
|
||||
#define IGC_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
|
||||
#define IGC_NVM_POLL_READ 0 /* Flag for polling for read complete */
|
||||
#define IGC_NVM_DEV_STARTER 5 /* Dev_starter Version */
|
||||
|
||||
/* NVM Word Offsets */
|
||||
#define NVM_CHECKSUM_REG 0x003F
|
||||
|
||||
/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
|
||||
#define NVM_SUM 0xBABA
|
||||
#define NVM_WORD_SIZE_BASE_SHIFT 6
|
||||
|
||||
/* Collision related configuration parameters */
|
||||
#define IGC_COLLISION_THRESHOLD 15
|
||||
#define IGC_CT_SHIFT 4
|
||||
#define IGC_COLLISION_DISTANCE 63
|
||||
#define IGC_COLD_SHIFT 12
|
||||
|
||||
/* Device Status */
|
||||
#define IGC_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
|
||||
#define IGC_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
|
||||
#define IGC_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
|
||||
#define IGC_STATUS_FUNC_SHIFT 2
|
||||
#define IGC_STATUS_TXOFF 0x00000010 /* transmission paused */
|
||||
#define IGC_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
|
||||
#define IGC_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
|
||||
#define IGC_STATUS_SPEED_2500 0x00400000 /* Speed 2.5Gb/s */
|
||||
|
||||
#define SPEED_10 10
|
||||
#define SPEED_100 100
|
||||
#define SPEED_1000 1000
|
||||
#define SPEED_2500 2500
|
||||
#define HALF_DUPLEX 1
|
||||
#define FULL_DUPLEX 2
|
||||
|
||||
/* 1Gbps and 2.5Gbps half duplex is not supported, nor spec-compliant. */
|
||||
#define ADVERTISE_10_HALF 0x0001
|
||||
#define ADVERTISE_10_FULL 0x0002
|
||||
#define ADVERTISE_100_HALF 0x0004
|
||||
#define ADVERTISE_100_FULL 0x0008
|
||||
#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */
|
||||
#define ADVERTISE_1000_FULL 0x0020
|
||||
#define ADVERTISE_2500_HALF 0x0040 /* Not used, just FYI */
|
||||
#define ADVERTISE_2500_FULL 0x0080
|
||||
|
||||
#define IGC_ALL_SPEED_DUPLEX_2500 ( \
|
||||
ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \
|
||||
ADVERTISE_100_FULL | ADVERTISE_1000_FULL | ADVERTISE_2500_FULL)
|
||||
|
||||
#define AUTONEG_ADVERTISE_SPEED_DEFAULT_2500 IGC_ALL_SPEED_DUPLEX_2500
|
||||
|
||||
/* Interrupt Cause Read */
|
||||
#define IGC_ICR_TXDW BIT(0) /* Transmit desc written back */
|
||||
#define IGC_ICR_TXQE BIT(1) /* Transmit Queue empty */
|
||||
#define IGC_ICR_LSC BIT(2) /* Link Status Change */
|
||||
#define IGC_ICR_RXSEQ BIT(3) /* Rx sequence error */
|
||||
#define IGC_ICR_RXDMT0 BIT(4) /* Rx desc min. threshold (0) */
|
||||
#define IGC_ICR_RXO BIT(6) /* Rx overrun */
|
||||
#define IGC_ICR_RXT0 BIT(7) /* Rx timer intr (ring 0) */
|
||||
#define IGC_ICR_TS BIT(19) /* Time Sync Interrupt */
|
||||
#define IGC_ICR_DRSTA BIT(30) /* Device Reset Asserted */
|
||||
|
||||
/* If this bit asserted, the driver should claim the interrupt */
|
||||
#define IGC_ICR_INT_ASSERTED BIT(31)
|
||||
|
||||
#define IGC_ICS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */
|
||||
|
||||
#define IMS_ENABLE_MASK ( \
|
||||
IGC_IMS_RXT0 | \
|
||||
IGC_IMS_TXDW | \
|
||||
IGC_IMS_RXDMT0 | \
|
||||
IGC_IMS_RXSEQ | \
|
||||
IGC_IMS_LSC)
|
||||
|
||||
/* Interrupt Mask Set */
|
||||
#define IGC_IMS_TXDW IGC_ICR_TXDW /* Tx desc written back */
|
||||
#define IGC_IMS_RXSEQ IGC_ICR_RXSEQ /* Rx sequence error */
|
||||
#define IGC_IMS_LSC IGC_ICR_LSC /* Link Status Change */
|
||||
#define IGC_IMS_DOUTSYNC IGC_ICR_DOUTSYNC /* NIC DMA out of sync */
|
||||
#define IGC_IMS_DRSTA IGC_ICR_DRSTA /* Device Reset Asserted */
|
||||
#define IGC_IMS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */
|
||||
#define IGC_IMS_RXDMT0 IGC_ICR_RXDMT0 /* Rx desc min. threshold */
|
||||
#define IGC_IMS_TS IGC_ICR_TS /* Time Sync Interrupt */
|
||||
|
||||
#define IGC_QVECTOR_MASK 0x7FFC /* Q-vector mask */
|
||||
#define IGC_ITR_VAL_MASK 0x04 /* ITR value mask */
|
||||
|
||||
/* Interrupt Cause Set */
|
||||
#define IGC_ICS_LSC IGC_ICR_LSC /* Link Status Change */
|
||||
#define IGC_ICS_RXDMT0 IGC_ICR_RXDMT0 /* rx desc min. threshold */
|
||||
|
||||
#define IGC_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */
|
||||
#define IGC_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */
|
||||
#define IGC_IVAR_VALID 0x80
|
||||
#define IGC_GPIE_NSICR 0x00000001
|
||||
#define IGC_GPIE_MSIX_MODE 0x00000010
|
||||
#define IGC_GPIE_EIAME 0x40000000
|
||||
#define IGC_GPIE_PBA 0x80000000
|
||||
|
||||
/* Receive Descriptor bit definitions */
|
||||
#define IGC_RXD_STAT_DD 0x01 /* Descriptor Done */
|
||||
|
||||
/* Transmit Descriptor bit definitions */
|
||||
#define IGC_TXD_DTYP_D 0x00100000 /* Data Descriptor */
|
||||
#define IGC_TXD_DTYP_C 0x00000000 /* Context Descriptor */
|
||||
#define IGC_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
|
||||
#define IGC_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
|
||||
#define IGC_TXD_CMD_EOP 0x01000000 /* End of Packet */
|
||||
#define IGC_TXD_CMD_IC 0x04000000 /* Insert Checksum */
|
||||
#define IGC_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */
|
||||
#define IGC_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */
|
||||
#define IGC_TXD_STAT_DD 0x00000001 /* Descriptor Done */
|
||||
#define IGC_TXD_CMD_TCP 0x01000000 /* TCP packet */
|
||||
#define IGC_TXD_CMD_IP 0x02000000 /* IP packet */
|
||||
#define IGC_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
|
||||
#define IGC_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */
|
||||
|
||||
/* IPSec Encrypt Enable */
|
||||
#define IGC_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define IGC_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
|
||||
#define IGC_ADVTXD_TSN_CNTX_FIRST 0x00000080
|
||||
|
||||
/* Transmit Control */
|
||||
#define IGC_TCTL_EN 0x00000002 /* enable Tx */
|
||||
#define IGC_TCTL_PSP 0x00000008 /* pad short packets */
|
||||
#define IGC_TCTL_CT 0x00000ff0 /* collision threshold */
|
||||
#define IGC_TCTL_COLD 0x003ff000 /* collision distance */
|
||||
#define IGC_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
|
||||
|
||||
/* Flow Control Constants */
|
||||
#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001
|
||||
#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
|
||||
#define FLOW_CONTROL_TYPE 0x8808
|
||||
/* Enable XON frame transmission */
|
||||
#define IGC_FCRTL_XONE 0x80000000
|
||||
|
||||
/* Management Control */
|
||||
#define IGC_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
|
||||
#define IGC_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
|
||||
|
||||
/* Receive Control */
|
||||
#define IGC_RCTL_RST 0x00000001 /* Software reset */
|
||||
#define IGC_RCTL_EN 0x00000002 /* enable */
|
||||
#define IGC_RCTL_SBP 0x00000004 /* store bad packet */
|
||||
#define IGC_RCTL_UPE 0x00000008 /* unicast promisc enable */
|
||||
#define IGC_RCTL_MPE 0x00000010 /* multicast promisc enable */
|
||||
#define IGC_RCTL_LPE 0x00000020 /* long packet enable */
|
||||
#define IGC_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
|
||||
#define IGC_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
|
||||
|
||||
#define IGC_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */
|
||||
#define IGC_RCTL_BAM 0x00008000 /* broadcast enable */
|
||||
|
||||
/* Split Replication Receive Control */
|
||||
#define IGC_SRRCTL_TIMESTAMP 0x40000000
|
||||
#define IGC_SRRCTL_TIMER1SEL(timer) (((timer) & 0x3) << 14)
|
||||
#define IGC_SRRCTL_TIMER0SEL(timer) (((timer) & 0x3) << 17)
|
||||
|
||||
/* Receive Descriptor bit definitions */
|
||||
#define IGC_RXD_STAT_EOP 0x02 /* End of Packet */
|
||||
#define IGC_RXD_STAT_IXSM 0x04 /* Ignore checksum */
|
||||
#define IGC_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
|
||||
#define IGC_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
|
||||
#define IGC_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
|
||||
|
||||
#define IGC_RXDEXT_STATERR_LB 0x00040000
|
||||
|
||||
/* Advanced Receive Descriptor bit definitions */
|
||||
#define IGC_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */
|
||||
|
||||
#define IGC_RXDEXT_STATERR_L4E 0x20000000
|
||||
#define IGC_RXDEXT_STATERR_IPE 0x40000000
|
||||
#define IGC_RXDEXT_STATERR_RXE 0x80000000
|
||||
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4 0x00020000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6 0x00100000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
|
||||
|
||||
/* Header split receive */
|
||||
#define IGC_RFCTL_IPV6_EX_DIS 0x00010000
|
||||
#define IGC_RFCTL_LEF 0x00040000
|
||||
|
||||
#define IGC_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */
|
||||
|
||||
#define IGC_RCTL_MO_SHIFT 12 /* multicast offset shift */
|
||||
#define IGC_RCTL_CFIEN 0x00080000 /* canonical form enable */
|
||||
#define IGC_RCTL_DPF 0x00400000 /* discard pause frames */
|
||||
#define IGC_RCTL_PMCF 0x00800000 /* pass MAC control frames */
|
||||
#define IGC_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
|
||||
|
||||
#define I225_RXPBSIZE_DEFAULT 0x000000A2 /* RXPBSIZE default */
|
||||
#define I225_TXPBSIZE_DEFAULT 0x04000014 /* TXPBSIZE default */
|
||||
#define IGC_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */
|
||||
|
||||
#define IGC_TXPBSIZE_TSN 0x04145145 /* 5k bytes buffer for each queue */
|
||||
|
||||
#define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */
|
||||
#define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */
|
||||
|
||||
/* Time Sync Interrupt Causes */
|
||||
#define IGC_TSICR_SYS_WRAP BIT(0) /* SYSTIM Wrap around. */
|
||||
#define IGC_TSICR_TXTS BIT(1) /* Transmit Timestamp. */
|
||||
#define IGC_TSICR_TT0 BIT(3) /* Target Time 0 Trigger. */
|
||||
#define IGC_TSICR_TT1 BIT(4) /* Target Time 1 Trigger. */
|
||||
#define IGC_TSICR_AUTT0 BIT(5) /* Auxiliary Timestamp 0 Taken. */
|
||||
#define IGC_TSICR_AUTT1 BIT(6) /* Auxiliary Timestamp 1 Taken. */
|
||||
|
||||
#define IGC_TSICR_INTERRUPTS IGC_TSICR_TXTS
|
||||
|
||||
#define IGC_FTQF_VF_BP 0x00008000
|
||||
#define IGC_FTQF_1588_TIME_STAMP 0x08000000
|
||||
#define IGC_FTQF_MASK 0xF0000000
|
||||
#define IGC_FTQF_MASK_PROTO_BP 0x10000000
|
||||
|
||||
/* Time Sync Receive Control bit definitions */
|
||||
#define IGC_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */
|
||||
#define IGC_TSYNCRXCTL_TYPE_L2_V2 0x00
|
||||
#define IGC_TSYNCRXCTL_TYPE_L4_V1 0x02
|
||||
#define IGC_TSYNCRXCTL_TYPE_L2_L4_V2 0x04
|
||||
#define IGC_TSYNCRXCTL_TYPE_ALL 0x08
|
||||
#define IGC_TSYNCRXCTL_TYPE_EVENT_V2 0x0A
|
||||
#define IGC_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */
|
||||
#define IGC_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */
|
||||
#define IGC_TSYNCRXCTL_RXSYNSIG 0x00000400 /* Sample RX tstamp in PHY sop */
|
||||
|
||||
/* Time Sync Receive Configuration */
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01
|
||||
|
||||
/* Immediate Interrupt Receive */
|
||||
#define IGC_IMIR_CLEAR_MASK 0xF001FFFF /* IMIR Reg Clear Mask */
|
||||
#define IGC_IMIR_PORT_BYPASS 0x20000 /* IMIR Port Bypass Bit */
|
||||
#define IGC_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */
|
||||
#define IGC_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */
|
||||
|
||||
/* Immediate Interrupt Receive Extended */
|
||||
#define IGC_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */
|
||||
#define IGC_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
|
||||
|
||||
/* Time Sync Transmit Control bit definitions */
|
||||
#define IGC_TSYNCTXCTL_TXTT_0 0x00000001 /* Tx timestamp reg 0 valid */
|
||||
#define IGC_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */
|
||||
#define IGC_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */
|
||||
#define IGC_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */
|
||||
#define IGC_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete */
|
||||
#define IGC_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */
|
||||
#define IGC_TSYNCTXCTL_TXSYNSIG 0x00000020 /* Sample TX tstamp in PHY sop */
|
||||
|
||||
/* Timer selection bits */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM0 (0u << 30) /* Select SYSTIM0 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM1 (1u << 30) /* Select SYSTIM1 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM2 (2u << 30) /* Select SYSTIM2 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM3 (3u << 30) /* Select SYSTIM3 for auxiliary time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM0 (0u << 30) /* Select SYSTIM0 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM1 (1u << 30) /* Select SYSTIM1 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM2 (2u << 30) /* Select SYSTIM2 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM3 (3u << 30) /* Select SYSTIM3 for target time stamp */
|
||||
|
||||
/* TSAUXC Configuration Bits */
|
||||
#define IGC_TSAUXC_EN_TT0 BIT(0) /* Enable target time 0. */
|
||||
#define IGC_TSAUXC_EN_TT1 BIT(1) /* Enable target time 1. */
|
||||
#define IGC_TSAUXC_EN_CLK0 BIT(2) /* Enable Configurable Frequency Clock 0. */
|
||||
#define IGC_TSAUXC_ST0 BIT(4) /* Start Clock 0 Toggle on Target Time 0. */
|
||||
#define IGC_TSAUXC_EN_CLK1 BIT(5) /* Enable Configurable Frequency Clock 1. */
|
||||
#define IGC_TSAUXC_ST1 BIT(7) /* Start Clock 1 Toggle on Target Time 1. */
|
||||
#define IGC_TSAUXC_EN_TS0 BIT(8) /* Enable hardware timestamp 0. */
|
||||
#define IGC_TSAUXC_AUTT0 BIT(9) /* Auxiliary Timestamp Taken. */
|
||||
#define IGC_TSAUXC_EN_TS1 BIT(10) /* Enable hardware timestamp 0. */
|
||||
#define IGC_TSAUXC_AUTT1 BIT(11) /* Auxiliary Timestamp Taken. */
|
||||
#define IGC_TSAUXC_PLSG BIT(17) /* Generate a pulse. */
|
||||
#define IGC_TSAUXC_DISABLE1 BIT(27) /* Disable SYSTIM0 Count Operation. */
|
||||
#define IGC_TSAUXC_DISABLE2 BIT(28) /* Disable SYSTIM1 Count Operation. */
|
||||
#define IGC_TSAUXC_DISABLE3 BIT(29) /* Disable SYSTIM2 Count Operation. */
|
||||
#define IGC_TSAUXC_DIS_TS_CLEAR BIT(30) /* Disable EN_TT0/1 auto clear. */
|
||||
#define IGC_TSAUXC_DISABLE0 BIT(31) /* Disable SYSTIM0 Count Operation. */
|
||||
|
||||
/* SDP Configuration Bits */
|
||||
#define IGC_AUX0_SEL_SDP0 (0u << 0) /* Assign SDP0 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP1 (1u << 0) /* Assign SDP1 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP2 (2u << 0) /* Assign SDP2 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP3 (3u << 0) /* Assign SDP3 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_TS_SDP_EN (1u << 2) /* Enable auxiliary time stamp trigger 0. */
|
||||
#define IGC_AUX1_SEL_SDP0 (0u << 3) /* Assign SDP0 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP1 (1u << 3) /* Assign SDP1 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP2 (2u << 3) /* Assign SDP2 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP3 (3u << 3) /* Assign SDP3 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_TS_SDP_EN (1u << 5) /* Enable auxiliary time stamp trigger 1. */
|
||||
#define IGC_TS_SDP0_SEL_TT0 (0u << 6) /* Target time 0 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_TT1 (1u << 6) /* Target time 1 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_FC0 (2u << 6) /* Freq clock 0 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_FC1 (3u << 6) /* Freq clock 1 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_EN (1u << 8) /* SDP0 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP1_SEL_TT0 (0u << 9) /* Target time 0 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_TT1 (1u << 9) /* Target time 1 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_FC0 (2u << 9) /* Freq clock 0 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_FC1 (3u << 9) /* Freq clock 1 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_EN (1u << 11) /* SDP1 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP2_SEL_TT0 (0u << 12) /* Target time 0 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_TT1 (1u << 12) /* Target time 1 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_FC0 (2u << 12) /* Freq clock 0 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_FC1 (3u << 12) /* Freq clock 1 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_EN (1u << 14) /* SDP2 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP3_SEL_TT0 (0u << 15) /* Target time 0 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_TT1 (1u << 15) /* Target time 1 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_FC0 (2u << 15) /* Freq clock 0 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_FC1 (3u << 15) /* Freq clock 1 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_EN (1u << 17) /* SDP3 is assigned to Tsync. */
|
||||
|
||||
/* Transmit Scheduling */
|
||||
#define IGC_TQAVCTRL_TRANSMIT_MODE_TSN 0x00000001
|
||||
#define IGC_TQAVCTRL_ENHANCED_QAV 0x00000008
|
||||
|
||||
#define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001
|
||||
#define IGC_TXQCTL_STRICT_CYCLE 0x00000002
|
||||
#define IGC_TXQCTL_STRICT_END 0x00000004
|
||||
#define IGC_TXQCTL_QAV_SEL_MASK 0x000000C0
|
||||
#define IGC_TXQCTL_QAV_SEL_CBS0 0x00000080
|
||||
#define IGC_TXQCTL_QAV_SEL_CBS1 0x000000C0
|
||||
|
||||
#define IGC_TQAVCC_IDLESLOPE_MASK 0xFFFF
|
||||
#define IGC_TQAVCC_KEEP_CREDITS BIT(30)
|
||||
|
||||
#define IGC_MAX_SR_QUEUES 2
|
||||
|
||||
/* Receive Checksum Control */
|
||||
#define IGC_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */
|
||||
#define IGC_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
|
||||
|
||||
/* PCIe PTM Control */
|
||||
#define IGC_PTM_CTRL_START_NOW BIT(29) /* Start PTM Now */
|
||||
#define IGC_PTM_CTRL_EN BIT(30) /* Enable PTM */
|
||||
#define IGC_PTM_CTRL_TRIG BIT(31) /* PTM Cycle trigger */
|
||||
#define IGC_PTM_CTRL_SHRT_CYC(usec) (((usec) & 0x2f) << 2)
|
||||
#define IGC_PTM_CTRL_PTM_TO(usec) (((usec) & 0xff) << 8)
|
||||
|
||||
#define IGC_PTM_SHORT_CYC_DEFAULT 10 /* Default Short/interrupted cycle interval */
|
||||
#define IGC_PTM_CYC_TIME_DEFAULT 5 /* Default PTM cycle time */
|
||||
#define IGC_PTM_TIMEOUT_DEFAULT 255 /* Default timeout for PTM errors */
|
||||
|
||||
/* PCIe Digital Delay */
|
||||
#define IGC_PCIE_DIG_DELAY_DEFAULT 0x01440000
|
||||
|
||||
/* PCIe PHY Delay */
|
||||
#define IGC_PCIE_PHY_DELAY_DEFAULT 0x40900000
|
||||
|
||||
#define IGC_TIMADJ_ADJUST_METH 0x40000000
|
||||
|
||||
/* PCIe PTM Status */
|
||||
#define IGC_PTM_STAT_VALID BIT(0) /* PTM Status */
|
||||
#define IGC_PTM_STAT_RET_ERR BIT(1) /* Root port timeout */
|
||||
#define IGC_PTM_STAT_BAD_PTM_RES BIT(2) /* PTM Response msg instead of PTM Response Data */
|
||||
#define IGC_PTM_STAT_T4M1_OVFL BIT(3) /* T4 minus T1 overflow */
|
||||
#define IGC_PTM_STAT_ADJUST_1ST BIT(4) /* 1588 timer adjusted during 1st PTM cycle */
|
||||
#define IGC_PTM_STAT_ADJUST_CYC BIT(5) /* 1588 timer adjusted during non-1st PTM cycle */
|
||||
|
||||
/* PCIe PTM Cycle Control */
|
||||
#define IGC_PTM_CYCLE_CTRL_CYC_TIME(msec) ((msec) & 0x3ff) /* PTM Cycle Time (msec) */
|
||||
#define IGC_PTM_CYCLE_CTRL_AUTO_CYC_EN BIT(31) /* PTM Cycle Control */
|
||||
|
||||
/* GPY211 - I225 defines */
|
||||
#define GPY_MMD_MASK 0xFFFF0000
|
||||
#define GPY_MMD_SHIFT 16
|
||||
#define GPY_REG_MASK 0x0000FFFF
|
||||
|
||||
#define IGC_MMDAC_FUNC_DATA 0x4000 /* Data, no post increment */
|
||||
|
||||
/* MAC definitions */
|
||||
#define IGC_FACTPS_MNGCG 0x20000000
|
||||
#define IGC_FWSM_MODE_MASK 0xE
|
||||
#define IGC_FWSM_MODE_SHIFT 1
|
||||
|
||||
/* Management Control */
|
||||
#define IGC_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */
|
||||
#define IGC_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */
|
||||
|
||||
/* PHY */
|
||||
#define PHY_REVISION_MASK 0xFFFFFFF0
|
||||
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
|
||||
#define IGC_GEN_POLL_TIMEOUT 1920
|
||||
|
||||
/* PHY Control Register */
|
||||
#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
|
||||
#define MII_CR_POWER_DOWN 0x0800 /* Power down */
|
||||
#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
|
||||
|
||||
/* PHY Status Register */
|
||||
#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
|
||||
#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
|
||||
#define IGC_PHY_RST_COMP 0x0100 /* Internal PHY reset completion */
|
||||
|
||||
/* PHY 1000 MII Register/Bit Definitions */
|
||||
/* PHY Registers defined by IEEE */
|
||||
#define PHY_CONTROL 0x00 /* Control Register */
|
||||
#define PHY_STATUS 0x01 /* Status Register */
|
||||
#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
|
||||
#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
|
||||
#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
|
||||
#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
|
||||
#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
|
||||
#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
|
||||
|
||||
/* MDI Control */
|
||||
#define IGC_MDIC_DATA_MASK 0x0000FFFF
|
||||
#define IGC_MDIC_REG_MASK 0x001F0000
|
||||
#define IGC_MDIC_REG_SHIFT 16
|
||||
#define IGC_MDIC_PHY_MASK 0x03E00000
|
||||
#define IGC_MDIC_PHY_SHIFT 21
|
||||
#define IGC_MDIC_OP_WRITE 0x04000000
|
||||
#define IGC_MDIC_OP_READ 0x08000000
|
||||
#define IGC_MDIC_READY 0x10000000
|
||||
#define IGC_MDIC_ERROR 0x40000000
|
||||
|
||||
#define IGC_N0_QUEUE -1
|
||||
|
||||
#define IGC_MAX_MAC_HDR_LEN 127
|
||||
#define IGC_MAX_NETWORK_HDR_LEN 511
|
||||
|
||||
#define IGC_VLANPQF_QSEL(_n, q_idx) ((q_idx) << ((_n) * 4))
|
||||
#define IGC_VLANPQF_VALID(_n) (0x1 << (3 + (_n) * 4))
|
||||
#define IGC_VLANPQF_QUEUE_MASK 0x03
|
||||
|
||||
#define IGC_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define IGC_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type:1=IPv4 */
|
||||
#define IGC_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet Type of TCP */
|
||||
#define IGC_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
|
||||
|
||||
/* Maximum size of the MTA register table in all supported adapters */
|
||||
#define MAX_MTA_REG 128
|
||||
|
||||
/* EEE defines */
|
||||
#define IGC_IPCNFG_EEE_2_5G_AN 0x00000010 /* IPCNFG EEE Ena 2.5G AN */
|
||||
#define IGC_IPCNFG_EEE_1G_AN 0x00000008 /* IPCNFG EEE Ena 1G AN */
|
||||
#define IGC_IPCNFG_EEE_100M_AN 0x00000004 /* IPCNFG EEE Ena 100M AN */
|
||||
#define IGC_EEER_EEE_NEG 0x20000000 /* EEE capability nego */
|
||||
#define IGC_EEER_TX_LPI_EN 0x00010000 /* EEER Tx LPI Enable */
|
||||
#define IGC_EEER_RX_LPI_EN 0x00020000 /* EEER Rx LPI Enable */
|
||||
#define IGC_EEER_LPI_FC 0x00040000 /* EEER Ena on Flow Cntrl */
|
||||
#define IGC_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */
|
||||
|
||||
/* LTR defines */
|
||||
#define IGC_LTRC_EEEMS_EN 0x00000020 /* Enable EEE LTR max send */
|
||||
#define IGC_RXPBS_SIZE_I225_MASK 0x0000003F /* Rx packet buffer size */
|
||||
#define IGC_TW_SYSTEM_1000_MASK 0x000000FF
|
||||
/* Minimum time for 100BASE-T where no data will be transmit following move out
|
||||
* of EEE LPI Tx state
|
||||
*/
|
||||
#define IGC_TW_SYSTEM_100_MASK 0x0000FF00
|
||||
#define IGC_TW_SYSTEM_100_SHIFT 8
|
||||
#define IGC_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */
|
||||
#define IGC_DMACR_DMACTHR_MASK 0x00FF0000
|
||||
#define IGC_DMACR_DMACTHR_SHIFT 16
|
||||
/* Reg val to set scale to 1024 nsec */
|
||||
#define IGC_LTRMINV_SCALE_1024 2
|
||||
/* Reg val to set scale to 32768 nsec */
|
||||
#define IGC_LTRMINV_SCALE_32768 3
|
||||
/* Reg val to set scale to 1024 nsec */
|
||||
#define IGC_LTRMAXV_SCALE_1024 2
|
||||
/* Reg val to set scale to 32768 nsec */
|
||||
#define IGC_LTRMAXV_SCALE_32768 3
|
||||
#define IGC_LTRMINV_LTRV_MASK 0x000003FF /* LTR minimum value */
|
||||
#define IGC_LTRMAXV_LTRV_MASK 0x000003FF /* LTR maximum value */
|
||||
#define IGC_LTRMINV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */
|
||||
#define IGC_LTRMINV_SCALE_SHIFT 10
|
||||
#define IGC_LTRMAXV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */
|
||||
#define IGC_LTRMAXV_SCALE_SHIFT 10
|
||||
|
||||
#endif /* _IGC_DEFINES_H_ */
|
||||
|
|
@ -0,0 +1,673 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_DEFINES_H_
|
||||
#define _IGC_DEFINES_H_
|
||||
|
||||
/* Number of Transmit and Receive Descriptors must be a multiple of 8 */
|
||||
#define REQ_TX_DESCRIPTOR_MULTIPLE 8
|
||||
#define REQ_RX_DESCRIPTOR_MULTIPLE 8
|
||||
|
||||
#define IGC_CTRL_EXT_SDP2_DIR 0x00000400 /* SDP2 Data direction */
|
||||
#define IGC_CTRL_EXT_SDP3_DIR 0x00000800 /* SDP3 Data direction */
|
||||
#define IGC_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */
|
||||
|
||||
/* Definitions for power management and wakeup registers */
|
||||
/* Wake Up Control */
|
||||
#define IGC_WUC_PME_EN 0x00000002 /* PME Enable */
|
||||
|
||||
/* Wake Up Filter Control */
|
||||
#define IGC_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
|
||||
#define IGC_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */
|
||||
#define IGC_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */
|
||||
#define IGC_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */
|
||||
#define IGC_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */
|
||||
#define IGC_WUFC_FLEX_HQ BIT(14) /* Flex Filters Host Queuing */
|
||||
#define IGC_WUFC_FLX0 BIT(16) /* Flexible Filter 0 Enable */
|
||||
#define IGC_WUFC_FLX1 BIT(17) /* Flexible Filter 1 Enable */
|
||||
#define IGC_WUFC_FLX2 BIT(18) /* Flexible Filter 2 Enable */
|
||||
#define IGC_WUFC_FLX3 BIT(19) /* Flexible Filter 3 Enable */
|
||||
#define IGC_WUFC_FLX4 BIT(20) /* Flexible Filter 4 Enable */
|
||||
#define IGC_WUFC_FLX5 BIT(21) /* Flexible Filter 5 Enable */
|
||||
#define IGC_WUFC_FLX6 BIT(22) /* Flexible Filter 6 Enable */
|
||||
#define IGC_WUFC_FLX7 BIT(23) /* Flexible Filter 7 Enable */
|
||||
|
||||
#define IGC_WUFC_FILTER_MASK GENMASK(23, 14)
|
||||
|
||||
#define IGC_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */
|
||||
|
||||
/* Wake Up Status */
|
||||
#define IGC_WUS_EX 0x00000004 /* Directed Exact */
|
||||
#define IGC_WUS_ARPD 0x00000020 /* Directed ARP Request */
|
||||
#define IGC_WUS_IPV4 0x00000040 /* Directed IPv4 */
|
||||
#define IGC_WUS_IPV6 0x00000080 /* Directed IPv6 */
|
||||
#define IGC_WUS_NSD 0x00000400 /* Directed IPv6 Neighbor Solicitation */
|
||||
|
||||
/* Packet types that are enabled for wake packet delivery */
|
||||
#define WAKE_PKT_WUS ( \
|
||||
IGC_WUS_EX | \
|
||||
IGC_WUS_ARPD | \
|
||||
IGC_WUS_IPV4 | \
|
||||
IGC_WUS_IPV6 | \
|
||||
IGC_WUS_NSD)
|
||||
|
||||
/* Wake Up Packet Length */
|
||||
#define IGC_WUPL_MASK 0x00000FFF
|
||||
|
||||
/* Wake Up Packet Memory stores the first 128 bytes of the wake up packet */
|
||||
#define IGC_WUPM_BYTES 128
|
||||
|
||||
/* Wakeup Filter Control Extended */
|
||||
#define IGC_WUFC_EXT_FLX8 BIT(8) /* Flexible Filter 8 Enable */
|
||||
#define IGC_WUFC_EXT_FLX9 BIT(9) /* Flexible Filter 9 Enable */
|
||||
#define IGC_WUFC_EXT_FLX10 BIT(10) /* Flexible Filter 10 Enable */
|
||||
#define IGC_WUFC_EXT_FLX11 BIT(11) /* Flexible Filter 11 Enable */
|
||||
#define IGC_WUFC_EXT_FLX12 BIT(12) /* Flexible Filter 12 Enable */
|
||||
#define IGC_WUFC_EXT_FLX13 BIT(13) /* Flexible Filter 13 Enable */
|
||||
#define IGC_WUFC_EXT_FLX14 BIT(14) /* Flexible Filter 14 Enable */
|
||||
#define IGC_WUFC_EXT_FLX15 BIT(15) /* Flexible Filter 15 Enable */
|
||||
#define IGC_WUFC_EXT_FLX16 BIT(16) /* Flexible Filter 16 Enable */
|
||||
#define IGC_WUFC_EXT_FLX17 BIT(17) /* Flexible Filter 17 Enable */
|
||||
#define IGC_WUFC_EXT_FLX18 BIT(18) /* Flexible Filter 18 Enable */
|
||||
#define IGC_WUFC_EXT_FLX19 BIT(19) /* Flexible Filter 19 Enable */
|
||||
#define IGC_WUFC_EXT_FLX20 BIT(20) /* Flexible Filter 20 Enable */
|
||||
#define IGC_WUFC_EXT_FLX21 BIT(21) /* Flexible Filter 21 Enable */
|
||||
#define IGC_WUFC_EXT_FLX22 BIT(22) /* Flexible Filter 22 Enable */
|
||||
#define IGC_WUFC_EXT_FLX23 BIT(23) /* Flexible Filter 23 Enable */
|
||||
#define IGC_WUFC_EXT_FLX24 BIT(24) /* Flexible Filter 24 Enable */
|
||||
#define IGC_WUFC_EXT_FLX25 BIT(25) /* Flexible Filter 25 Enable */
|
||||
#define IGC_WUFC_EXT_FLX26 BIT(26) /* Flexible Filter 26 Enable */
|
||||
#define IGC_WUFC_EXT_FLX27 BIT(27) /* Flexible Filter 27 Enable */
|
||||
#define IGC_WUFC_EXT_FLX28 BIT(28) /* Flexible Filter 28 Enable */
|
||||
#define IGC_WUFC_EXT_FLX29 BIT(29) /* Flexible Filter 29 Enable */
|
||||
#define IGC_WUFC_EXT_FLX30 BIT(30) /* Flexible Filter 30 Enable */
|
||||
#define IGC_WUFC_EXT_FLX31 BIT(31) /* Flexible Filter 31 Enable */
|
||||
|
||||
#define IGC_WUFC_EXT_FILTER_MASK GENMASK(31, 8)
|
||||
|
||||
/* Loop limit on how long we wait for auto-negotiation to complete */
|
||||
#define COPPER_LINK_UP_LIMIT 10
|
||||
#define PHY_AUTO_NEG_LIMIT 45
|
||||
|
||||
/* Number of 100 microseconds we wait for PCI Express master disable */
|
||||
#define MASTER_DISABLE_TIMEOUT 800
|
||||
/*Blocks new Master requests */
|
||||
#define IGC_CTRL_GIO_MASTER_DISABLE 0x00000004
|
||||
/* Status of Master requests. */
|
||||
#define IGC_STATUS_GIO_MASTER_ENABLE 0x00080000
|
||||
|
||||
/* Receive Address
|
||||
* Number of high/low register pairs in the RAR. The RAR (Receive Address
|
||||
* Registers) holds the directed and multicast addresses that we monitor.
|
||||
* Technically, we have 16 spots. However, we reserve one of these spots
|
||||
* (RAR[15]) for our directed address used by controllers with
|
||||
* manageability enabled, allowing us room for 15 multicast addresses.
|
||||
*/
|
||||
#define IGC_RAH_RAH_MASK 0x0000FFFF
|
||||
#define IGC_RAH_ASEL_MASK 0x00030000
|
||||
#define IGC_RAH_ASEL_SRC_ADDR BIT(16)
|
||||
#define IGC_RAH_QSEL_MASK 0x000C0000
|
||||
#define IGC_RAH_QSEL_SHIFT 18
|
||||
#define IGC_RAH_QSEL_ENABLE BIT(28)
|
||||
#define IGC_RAH_AV 0x80000000 /* Receive descriptor valid */
|
||||
|
||||
#define IGC_RAL_MAC_ADDR_LEN 4
|
||||
#define IGC_RAH_MAC_ADDR_LEN 2
|
||||
|
||||
/* Error Codes */
|
||||
#define IGC_SUCCESS 0
|
||||
#define IGC_ERR_NVM 1
|
||||
#define IGC_ERR_PHY 2
|
||||
#define IGC_ERR_CONFIG 3
|
||||
#define IGC_ERR_PARAM 4
|
||||
#define IGC_ERR_MAC_INIT 5
|
||||
#define IGC_ERR_RESET 9
|
||||
#define IGC_ERR_MASTER_REQUESTS_PENDING 10
|
||||
#define IGC_ERR_BLK_PHY_RESET 12
|
||||
#define IGC_ERR_SWFW_SYNC 13
|
||||
|
||||
/* Device Control */
|
||||
#define IGC_CTRL_RST 0x04000000 /* Global reset */
|
||||
|
||||
#define IGC_CTRL_PHY_RST 0x80000000 /* PHY Reset */
|
||||
#define IGC_CTRL_SLU 0x00000040 /* Set link up (Force Link) */
|
||||
#define IGC_CTRL_FRCSPD 0x00000800 /* Force Speed */
|
||||
#define IGC_CTRL_FRCDPX 0x00001000 /* Force Duplex */
|
||||
#define IGC_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */
|
||||
|
||||
#define IGC_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */
|
||||
#define IGC_CTRL_TFCE 0x10000000 /* Transmit flow control enable */
|
||||
|
||||
#define IGC_CTRL_SDP0_DIR 0x00400000 /* SDP0 Data direction */
|
||||
#define IGC_CTRL_SDP1_DIR 0x00800000 /* SDP1 Data direction */
|
||||
|
||||
/* As per the EAS the maximum supported size is 9.5KB (9728 bytes) */
|
||||
#define MAX_JUMBO_FRAME_SIZE 0x2600
|
||||
|
||||
/* PBA constants */
|
||||
#define IGC_PBA_34K 0x0022
|
||||
|
||||
/* SW Semaphore Register */
|
||||
#define IGC_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
|
||||
#define IGC_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
|
||||
|
||||
/* SWFW_SYNC Definitions */
|
||||
#define IGC_SWFW_EEP_SM 0x1
|
||||
#define IGC_SWFW_PHY0_SM 0x2
|
||||
|
||||
/* Autoneg Advertisement Register */
|
||||
#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */
|
||||
#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */
|
||||
#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */
|
||||
#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */
|
||||
#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */
|
||||
#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */
|
||||
|
||||
/* Link Partner Ability Register (Base Page) */
|
||||
#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */
|
||||
#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */
|
||||
|
||||
/* 1000BASE-T Control Register */
|
||||
#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */
|
||||
#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */
|
||||
|
||||
/* 1000BASE-T Status Register */
|
||||
#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */
|
||||
|
||||
/* PHY GPY 211 registers */
|
||||
#define STANDARD_AN_REG_MASK 0x0007 /* MMD */
|
||||
#define ANEG_MULTIGBT_AN_CTRL 0x0020 /* MULTI GBT AN Control Register */
|
||||
#define MMD_DEVADDR_SHIFT 16 /* Shift MMD to higher bits */
|
||||
#define CR_2500T_FD_CAPS 0x0080 /* Advertise 2500T FD capability */
|
||||
|
||||
/* NVM Control */
|
||||
/* Number of milliseconds for NVM auto read done after MAC reset. */
|
||||
#define AUTO_READ_DONE_TIMEOUT 10
|
||||
#define IGC_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */
|
||||
#define IGC_EECD_REQ 0x00000040 /* NVM Access Request */
|
||||
#define IGC_EECD_GNT 0x00000080 /* NVM Access Grant */
|
||||
/* NVM Addressing bits based on type 0=small, 1=large */
|
||||
#define IGC_EECD_ADDR_BITS 0x00000400
|
||||
#define IGC_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */
|
||||
#define IGC_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */
|
||||
#define IGC_EECD_SIZE_EX_SHIFT 11
|
||||
#define IGC_EECD_FLUPD_I225 0x00800000 /* Update FLASH */
|
||||
#define IGC_EECD_FLUDONE_I225 0x04000000 /* Update FLASH done*/
|
||||
#define IGC_EECD_FLASH_DETECTED_I225 0x00080000 /* FLASH detected */
|
||||
#define IGC_FLUDONE_ATTEMPTS 20000
|
||||
#define IGC_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */
|
||||
|
||||
/* Offset to data in NVM read/write registers */
|
||||
#define IGC_NVM_RW_REG_DATA 16
|
||||
#define IGC_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
|
||||
#define IGC_NVM_RW_REG_START 1 /* Start operation */
|
||||
#define IGC_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
|
||||
#define IGC_NVM_POLL_READ 0 /* Flag for polling for read complete */
|
||||
#define IGC_NVM_DEV_STARTER 5 /* Dev_starter Version */
|
||||
|
||||
/* NVM Word Offsets */
|
||||
#define NVM_CHECKSUM_REG 0x003F
|
||||
|
||||
/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */
|
||||
#define NVM_SUM 0xBABA
|
||||
#define NVM_WORD_SIZE_BASE_SHIFT 6
|
||||
|
||||
/* Collision related configuration parameters */
|
||||
#define IGC_COLLISION_THRESHOLD 15
|
||||
#define IGC_CT_SHIFT 4
|
||||
#define IGC_COLLISION_DISTANCE 63
|
||||
#define IGC_COLD_SHIFT 12
|
||||
|
||||
/* Device Status */
|
||||
#define IGC_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
|
||||
#define IGC_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
|
||||
#define IGC_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
|
||||
#define IGC_STATUS_FUNC_SHIFT 2
|
||||
#define IGC_STATUS_TXOFF 0x00000010 /* transmission paused */
|
||||
#define IGC_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
|
||||
#define IGC_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
|
||||
#define IGC_STATUS_SPEED_2500 0x00400000 /* Speed 2.5Gb/s */
|
||||
|
||||
#define SPEED_10 10
|
||||
#define SPEED_100 100
|
||||
#define SPEED_1000 1000
|
||||
#define SPEED_2500 2500
|
||||
#define HALF_DUPLEX 1
|
||||
#define FULL_DUPLEX 2
|
||||
|
||||
/* 1Gbps and 2.5Gbps half duplex is not supported, nor spec-compliant. */
|
||||
#define ADVERTISE_10_HALF 0x0001
|
||||
#define ADVERTISE_10_FULL 0x0002
|
||||
#define ADVERTISE_100_HALF 0x0004
|
||||
#define ADVERTISE_100_FULL 0x0008
|
||||
#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */
|
||||
#define ADVERTISE_1000_FULL 0x0020
|
||||
#define ADVERTISE_2500_HALF 0x0040 /* Not used, just FYI */
|
||||
#define ADVERTISE_2500_FULL 0x0080
|
||||
|
||||
#define IGC_ALL_SPEED_DUPLEX_2500 ( \
|
||||
ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \
|
||||
ADVERTISE_100_FULL | ADVERTISE_1000_FULL | ADVERTISE_2500_FULL)
|
||||
|
||||
#define AUTONEG_ADVERTISE_SPEED_DEFAULT_2500 IGC_ALL_SPEED_DUPLEX_2500
|
||||
|
||||
/* Interrupt Cause Read */
|
||||
#define IGC_ICR_TXDW BIT(0) /* Transmit desc written back */
|
||||
#define IGC_ICR_TXQE BIT(1) /* Transmit Queue empty */
|
||||
#define IGC_ICR_LSC BIT(2) /* Link Status Change */
|
||||
#define IGC_ICR_RXSEQ BIT(3) /* Rx sequence error */
|
||||
#define IGC_ICR_RXDMT0 BIT(4) /* Rx desc min. threshold (0) */
|
||||
#define IGC_ICR_RXO BIT(6) /* Rx overrun */
|
||||
#define IGC_ICR_RXT0 BIT(7) /* Rx timer intr (ring 0) */
|
||||
#define IGC_ICR_TS BIT(19) /* Time Sync Interrupt */
|
||||
#define IGC_ICR_DRSTA BIT(30) /* Device Reset Asserted */
|
||||
|
||||
/* If this bit asserted, the driver should claim the interrupt */
|
||||
#define IGC_ICR_INT_ASSERTED BIT(31)
|
||||
|
||||
#define IGC_ICS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */
|
||||
|
||||
#define IMS_ENABLE_MASK ( \
|
||||
IGC_IMS_RXT0 | \
|
||||
IGC_IMS_TXDW | \
|
||||
IGC_IMS_RXDMT0 | \
|
||||
IGC_IMS_RXSEQ | \
|
||||
IGC_IMS_LSC)
|
||||
|
||||
/* Interrupt Mask Set */
|
||||
#define IGC_IMS_TXDW IGC_ICR_TXDW /* Tx desc written back */
|
||||
#define IGC_IMS_RXSEQ IGC_ICR_RXSEQ /* Rx sequence error */
|
||||
#define IGC_IMS_LSC IGC_ICR_LSC /* Link Status Change */
|
||||
#define IGC_IMS_DOUTSYNC IGC_ICR_DOUTSYNC /* NIC DMA out of sync */
|
||||
#define IGC_IMS_DRSTA IGC_ICR_DRSTA /* Device Reset Asserted */
|
||||
#define IGC_IMS_RXT0 IGC_ICR_RXT0 /* Rx timer intr */
|
||||
#define IGC_IMS_RXDMT0 IGC_ICR_RXDMT0 /* Rx desc min. threshold */
|
||||
#define IGC_IMS_TS IGC_ICR_TS /* Time Sync Interrupt */
|
||||
|
||||
#define IGC_QVECTOR_MASK 0x7FFC /* Q-vector mask */
|
||||
#define IGC_ITR_VAL_MASK 0x04 /* ITR value mask */
|
||||
|
||||
/* Interrupt Cause Set */
|
||||
#define IGC_ICS_LSC IGC_ICR_LSC /* Link Status Change */
|
||||
#define IGC_ICS_RXDMT0 IGC_ICR_RXDMT0 /* rx desc min. threshold */
|
||||
|
||||
#define IGC_ICR_DOUTSYNC 0x10000000 /* NIC DMA out of sync */
|
||||
#define IGC_EITR_CNT_IGNR 0x80000000 /* Don't reset counters on write */
|
||||
#define IGC_IVAR_VALID 0x80
|
||||
#define IGC_GPIE_NSICR 0x00000001
|
||||
#define IGC_GPIE_MSIX_MODE 0x00000010
|
||||
#define IGC_GPIE_EIAME 0x40000000
|
||||
#define IGC_GPIE_PBA 0x80000000
|
||||
|
||||
/* Receive Descriptor bit definitions */
|
||||
#define IGC_RXD_STAT_DD 0x01 /* Descriptor Done */
|
||||
|
||||
/* Transmit Descriptor bit definitions */
|
||||
#define IGC_TXD_DTYP_D 0x00100000 /* Data Descriptor */
|
||||
#define IGC_TXD_DTYP_C 0x00000000 /* Context Descriptor */
|
||||
#define IGC_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
|
||||
#define IGC_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
|
||||
#define IGC_TXD_CMD_EOP 0x01000000 /* End of Packet */
|
||||
#define IGC_TXD_CMD_IC 0x04000000 /* Insert Checksum */
|
||||
#define IGC_TXD_CMD_DEXT 0x20000000 /* Desc extension (0 = legacy) */
|
||||
#define IGC_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */
|
||||
#define IGC_TXD_STAT_DD 0x00000001 /* Descriptor Done */
|
||||
#define IGC_TXD_CMD_TCP 0x01000000 /* TCP packet */
|
||||
#define IGC_TXD_CMD_IP 0x02000000 /* IP packet */
|
||||
#define IGC_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */
|
||||
#define IGC_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */
|
||||
|
||||
/* IPSec Encrypt Enable */
|
||||
#define IGC_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
|
||||
#define IGC_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
|
||||
|
||||
#define IGC_ADVTXD_TSN_CNTX_FIRST 0x00000080
|
||||
|
||||
/* Transmit Control */
|
||||
#define IGC_TCTL_EN 0x00000002 /* enable Tx */
|
||||
#define IGC_TCTL_PSP 0x00000008 /* pad short packets */
|
||||
#define IGC_TCTL_CT 0x00000ff0 /* collision threshold */
|
||||
#define IGC_TCTL_COLD 0x003ff000 /* collision distance */
|
||||
#define IGC_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
|
||||
|
||||
/* Flow Control Constants */
|
||||
#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001
|
||||
#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
|
||||
#define FLOW_CONTROL_TYPE 0x8808
|
||||
/* Enable XON frame transmission */
|
||||
#define IGC_FCRTL_XONE 0x80000000
|
||||
|
||||
/* Management Control */
|
||||
#define IGC_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
|
||||
#define IGC_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
|
||||
|
||||
/* Receive Control */
|
||||
#define IGC_RCTL_RST 0x00000001 /* Software reset */
|
||||
#define IGC_RCTL_EN 0x00000002 /* enable */
|
||||
#define IGC_RCTL_SBP 0x00000004 /* store bad packet */
|
||||
#define IGC_RCTL_UPE 0x00000008 /* unicast promisc enable */
|
||||
#define IGC_RCTL_MPE 0x00000010 /* multicast promisc enable */
|
||||
#define IGC_RCTL_LPE 0x00000020 /* long packet enable */
|
||||
#define IGC_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
|
||||
#define IGC_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
|
||||
|
||||
#define IGC_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min thresh size */
|
||||
#define IGC_RCTL_BAM 0x00008000 /* broadcast enable */
|
||||
|
||||
/* Split Replication Receive Control */
|
||||
#define IGC_SRRCTL_TIMESTAMP 0x40000000
|
||||
#define IGC_SRRCTL_TIMER1SEL(timer) (((timer) & 0x3) << 14)
|
||||
#define IGC_SRRCTL_TIMER0SEL(timer) (((timer) & 0x3) << 17)
|
||||
|
||||
/* Receive Descriptor bit definitions */
|
||||
#define IGC_RXD_STAT_EOP 0x02 /* End of Packet */
|
||||
#define IGC_RXD_STAT_IXSM 0x04 /* Ignore checksum */
|
||||
#define IGC_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
|
||||
#define IGC_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
|
||||
#define IGC_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
|
||||
|
||||
#define IGC_RXDEXT_STATERR_LB 0x00040000
|
||||
|
||||
/* Advanced Receive Descriptor bit definitions */
|
||||
#define IGC_RXDADV_STAT_TSIP 0x08000 /* timestamp in packet */
|
||||
|
||||
#define IGC_RXDEXT_STATERR_L4E 0x20000000
|
||||
#define IGC_RXDEXT_STATERR_IPE 0x40000000
|
||||
#define IGC_RXDEXT_STATERR_RXE 0x80000000
|
||||
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV4 0x00020000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6 0x00100000
|
||||
#define IGC_MRQC_RSS_FIELD_IPV6_TCP 0x00200000
|
||||
|
||||
/* Header split receive */
|
||||
#define IGC_RFCTL_IPV6_EX_DIS 0x00010000
|
||||
#define IGC_RFCTL_LEF 0x00040000
|
||||
|
||||
#define IGC_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */
|
||||
|
||||
#define IGC_RCTL_MO_SHIFT 12 /* multicast offset shift */
|
||||
#define IGC_RCTL_CFIEN 0x00080000 /* canonical form enable */
|
||||
#define IGC_RCTL_DPF 0x00400000 /* discard pause frames */
|
||||
#define IGC_RCTL_PMCF 0x00800000 /* pass MAC control frames */
|
||||
#define IGC_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
|
||||
|
||||
#define I225_RXPBSIZE_DEFAULT 0x000000A2 /* RXPBSIZE default */
|
||||
#define I225_TXPBSIZE_DEFAULT 0x04000014 /* TXPBSIZE default */
|
||||
#define IGC_RXPBS_CFG_TS_EN 0x80000000 /* Timestamp in Rx buffer */
|
||||
|
||||
#define IGC_TXPBSIZE_TSN 0x04145145 /* 5k bytes buffer for each queue */
|
||||
|
||||
#define IGC_DTXMXPKTSZ_TSN 0x19 /* 1600 bytes of max TX DMA packet size */
|
||||
#define IGC_DTXMXPKTSZ_DEFAULT 0x98 /* 9728-byte Jumbo frames */
|
||||
|
||||
/* Time Sync Interrupt Causes */
|
||||
#define IGC_TSICR_SYS_WRAP BIT(0) /* SYSTIM Wrap around. */
|
||||
#define IGC_TSICR_TXTS BIT(1) /* Transmit Timestamp. */
|
||||
#define IGC_TSICR_TT0 BIT(3) /* Target Time 0 Trigger. */
|
||||
#define IGC_TSICR_TT1 BIT(4) /* Target Time 1 Trigger. */
|
||||
#define IGC_TSICR_AUTT0 BIT(5) /* Auxiliary Timestamp 0 Taken. */
|
||||
#define IGC_TSICR_AUTT1 BIT(6) /* Auxiliary Timestamp 1 Taken. */
|
||||
|
||||
#define IGC_TSICR_INTERRUPTS IGC_TSICR_TXTS
|
||||
|
||||
#define IGC_FTQF_VF_BP 0x00008000
|
||||
#define IGC_FTQF_1588_TIME_STAMP 0x08000000
|
||||
#define IGC_FTQF_MASK 0xF0000000
|
||||
#define IGC_FTQF_MASK_PROTO_BP 0x10000000
|
||||
|
||||
/* Time Sync Receive Control bit definitions */
|
||||
#define IGC_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */
|
||||
#define IGC_TSYNCRXCTL_TYPE_L2_V2 0x00
|
||||
#define IGC_TSYNCRXCTL_TYPE_L4_V1 0x02
|
||||
#define IGC_TSYNCRXCTL_TYPE_L2_L4_V2 0x04
|
||||
#define IGC_TSYNCRXCTL_TYPE_ALL 0x08
|
||||
#define IGC_TSYNCRXCTL_TYPE_EVENT_V2 0x0A
|
||||
#define IGC_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */
|
||||
#define IGC_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */
|
||||
#define IGC_TSYNCRXCTL_RXSYNSIG 0x00000400 /* Sample RX tstamp in PHY sop */
|
||||
|
||||
/* Time Sync Receive Configuration */
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_CTRLT_MASK 0x000000FF
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE 0x00
|
||||
#define IGC_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE 0x01
|
||||
|
||||
/* Immediate Interrupt Receive */
|
||||
#define IGC_IMIR_CLEAR_MASK 0xF001FFFF /* IMIR Reg Clear Mask */
|
||||
#define IGC_IMIR_PORT_BYPASS 0x20000 /* IMIR Port Bypass Bit */
|
||||
#define IGC_IMIR_PRIORITY_SHIFT 29 /* IMIR Priority Shift */
|
||||
#define IGC_IMIREXT_CLEAR_MASK 0x7FFFF /* IMIREXT Reg Clear Mask */
|
||||
|
||||
/* Immediate Interrupt Receive Extended */
|
||||
#define IGC_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of ctrl bits */
|
||||
#define IGC_IMIREXT_SIZE_BP 0x00001000 /* Packet size bypass */
|
||||
|
||||
/* Time Sync Transmit Control bit definitions */
|
||||
#define IGC_TSYNCTXCTL_TXTT_0 0x00000001 /* Tx timestamp reg 0 valid */
|
||||
#define IGC_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */
|
||||
#define IGC_TSYNCTXCTL_MAX_ALLOWED_DLY_MASK 0x0000F000 /* max delay */
|
||||
#define IGC_TSYNCTXCTL_SYNC_COMP_ERR 0x20000000 /* sync err */
|
||||
#define IGC_TSYNCTXCTL_SYNC_COMP 0x40000000 /* sync complete */
|
||||
#define IGC_TSYNCTXCTL_START_SYNC 0x80000000 /* initiate sync */
|
||||
#define IGC_TSYNCTXCTL_TXSYNSIG 0x00000020 /* Sample TX tstamp in PHY sop */
|
||||
|
||||
/* Timer selection bits */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM0 (0u << 30) /* Select SYSTIM0 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM1 (1u << 30) /* Select SYSTIM1 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM2 (2u << 30) /* Select SYSTIM2 for auxiliary time stamp */
|
||||
#define IGC_AUX_IO_TIMER_SEL_SYSTIM3 (3u << 30) /* Select SYSTIM3 for auxiliary time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM0 (0u << 30) /* Select SYSTIM0 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM1 (1u << 30) /* Select SYSTIM1 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM2 (2u << 30) /* Select SYSTIM2 for target time stamp */
|
||||
#define IGC_TT_IO_TIMER_SEL_SYSTIM3 (3u << 30) /* Select SYSTIM3 for target time stamp */
|
||||
|
||||
/* TSAUXC Configuration Bits */
|
||||
#define IGC_TSAUXC_EN_TT0 BIT(0) /* Enable target time 0. */
|
||||
#define IGC_TSAUXC_EN_TT1 BIT(1) /* Enable target time 1. */
|
||||
#define IGC_TSAUXC_EN_CLK0 BIT(2) /* Enable Configurable Frequency Clock 0. */
|
||||
#define IGC_TSAUXC_ST0 BIT(4) /* Start Clock 0 Toggle on Target Time 0. */
|
||||
#define IGC_TSAUXC_EN_CLK1 BIT(5) /* Enable Configurable Frequency Clock 1. */
|
||||
#define IGC_TSAUXC_ST1 BIT(7) /* Start Clock 1 Toggle on Target Time 1. */
|
||||
#define IGC_TSAUXC_EN_TS0 BIT(8) /* Enable hardware timestamp 0. */
|
||||
#define IGC_TSAUXC_AUTT0 BIT(9) /* Auxiliary Timestamp Taken. */
|
||||
#define IGC_TSAUXC_EN_TS1 BIT(10) /* Enable hardware timestamp 0. */
|
||||
#define IGC_TSAUXC_AUTT1 BIT(11) /* Auxiliary Timestamp Taken. */
|
||||
#define IGC_TSAUXC_PLSG BIT(17) /* Generate a pulse. */
|
||||
#define IGC_TSAUXC_DISABLE1 BIT(27) /* Disable SYSTIM0 Count Operation. */
|
||||
#define IGC_TSAUXC_DISABLE2 BIT(28) /* Disable SYSTIM1 Count Operation. */
|
||||
#define IGC_TSAUXC_DISABLE3 BIT(29) /* Disable SYSTIM2 Count Operation. */
|
||||
#define IGC_TSAUXC_DIS_TS_CLEAR BIT(30) /* Disable EN_TT0/1 auto clear. */
|
||||
#define IGC_TSAUXC_DISABLE0 BIT(31) /* Disable SYSTIM0 Count Operation. */
|
||||
|
||||
/* SDP Configuration Bits */
|
||||
#define IGC_AUX0_SEL_SDP0 (0u << 0) /* Assign SDP0 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP1 (1u << 0) /* Assign SDP1 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP2 (2u << 0) /* Assign SDP2 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_SEL_SDP3 (3u << 0) /* Assign SDP3 to auxiliary time stamp 0. */
|
||||
#define IGC_AUX0_TS_SDP_EN (1u << 2) /* Enable auxiliary time stamp trigger 0. */
|
||||
#define IGC_AUX1_SEL_SDP0 (0u << 3) /* Assign SDP0 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP1 (1u << 3) /* Assign SDP1 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP2 (2u << 3) /* Assign SDP2 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_SEL_SDP3 (3u << 3) /* Assign SDP3 to auxiliary time stamp 1. */
|
||||
#define IGC_AUX1_TS_SDP_EN (1u << 5) /* Enable auxiliary time stamp trigger 1. */
|
||||
#define IGC_TS_SDP0_SEL_TT0 (0u << 6) /* Target time 0 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_TT1 (1u << 6) /* Target time 1 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_FC0 (2u << 6) /* Freq clock 0 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_SEL_FC1 (3u << 6) /* Freq clock 1 is output on SDP0. */
|
||||
#define IGC_TS_SDP0_EN (1u << 8) /* SDP0 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP1_SEL_TT0 (0u << 9) /* Target time 0 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_TT1 (1u << 9) /* Target time 1 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_FC0 (2u << 9) /* Freq clock 0 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_SEL_FC1 (3u << 9) /* Freq clock 1 is output on SDP1. */
|
||||
#define IGC_TS_SDP1_EN (1u << 11) /* SDP1 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP2_SEL_TT0 (0u << 12) /* Target time 0 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_TT1 (1u << 12) /* Target time 1 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_FC0 (2u << 12) /* Freq clock 0 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_SEL_FC1 (3u << 12) /* Freq clock 1 is output on SDP2. */
|
||||
#define IGC_TS_SDP2_EN (1u << 14) /* SDP2 is assigned to Tsync. */
|
||||
#define IGC_TS_SDP3_SEL_TT0 (0u << 15) /* Target time 0 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_TT1 (1u << 15) /* Target time 1 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_FC0 (2u << 15) /* Freq clock 0 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_SEL_FC1 (3u << 15) /* Freq clock 1 is output on SDP3. */
|
||||
#define IGC_TS_SDP3_EN (1u << 17) /* SDP3 is assigned to Tsync. */
|
||||
|
||||
/* Transmit Scheduling */
|
||||
#define IGC_TQAVCTRL_TRANSMIT_MODE_TSN 0x00000001
|
||||
#define IGC_TQAVCTRL_ENHANCED_QAV 0x00000008
|
||||
|
||||
#define IGC_TXQCTL_QUEUE_MODE_LAUNCHT 0x00000001
|
||||
#define IGC_TXQCTL_STRICT_CYCLE 0x00000002
|
||||
#define IGC_TXQCTL_STRICT_END 0x00000004
|
||||
#define IGC_TXQCTL_QAV_SEL_MASK 0x000000C0
|
||||
#define IGC_TXQCTL_QAV_SEL_CBS0 0x00000080
|
||||
#define IGC_TXQCTL_QAV_SEL_CBS1 0x000000C0
|
||||
|
||||
#define IGC_TQAVCC_IDLESLOPE_MASK 0xFFFF
|
||||
#define IGC_TQAVCC_KEEP_CREDITS BIT(30)
|
||||
|
||||
#define IGC_MAX_SR_QUEUES 2
|
||||
|
||||
/* Receive Checksum Control */
|
||||
#define IGC_RXCSUM_CRCOFL 0x00000800 /* CRC32 offload enable */
|
||||
#define IGC_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
|
||||
|
||||
/* PCIe PTM Control */
|
||||
#define IGC_PTM_CTRL_START_NOW BIT(29) /* Start PTM Now */
|
||||
#define IGC_PTM_CTRL_EN BIT(30) /* Enable PTM */
|
||||
#define IGC_PTM_CTRL_TRIG BIT(31) /* PTM Cycle trigger */
|
||||
#define IGC_PTM_CTRL_SHRT_CYC(usec) (((usec) & 0x2f) << 2)
|
||||
#define IGC_PTM_CTRL_PTM_TO(usec) (((usec) & 0xff) << 8)
|
||||
|
||||
#define IGC_PTM_SHORT_CYC_DEFAULT 10 /* Default Short/interrupted cycle interval */
|
||||
#define IGC_PTM_CYC_TIME_DEFAULT 5 /* Default PTM cycle time */
|
||||
#define IGC_PTM_TIMEOUT_DEFAULT 255 /* Default timeout for PTM errors */
|
||||
|
||||
/* PCIe Digital Delay */
|
||||
#define IGC_PCIE_DIG_DELAY_DEFAULT 0x01440000
|
||||
|
||||
/* PCIe PHY Delay */
|
||||
#define IGC_PCIE_PHY_DELAY_DEFAULT 0x40900000
|
||||
|
||||
#define IGC_TIMADJ_ADJUST_METH 0x40000000
|
||||
|
||||
/* PCIe PTM Status */
|
||||
#define IGC_PTM_STAT_VALID BIT(0) /* PTM Status */
|
||||
#define IGC_PTM_STAT_RET_ERR BIT(1) /* Root port timeout */
|
||||
#define IGC_PTM_STAT_BAD_PTM_RES BIT(2) /* PTM Response msg instead of PTM Response Data */
|
||||
#define IGC_PTM_STAT_T4M1_OVFL BIT(3) /* T4 minus T1 overflow */
|
||||
#define IGC_PTM_STAT_ADJUST_1ST BIT(4) /* 1588 timer adjusted during 1st PTM cycle */
|
||||
#define IGC_PTM_STAT_ADJUST_CYC BIT(5) /* 1588 timer adjusted during non-1st PTM cycle */
|
||||
|
||||
/* PCIe PTM Cycle Control */
|
||||
#define IGC_PTM_CYCLE_CTRL_CYC_TIME(msec) ((msec) & 0x3ff) /* PTM Cycle Time (msec) */
|
||||
#define IGC_PTM_CYCLE_CTRL_AUTO_CYC_EN BIT(31) /* PTM Cycle Control */
|
||||
|
||||
/* GPY211 - I225 defines */
|
||||
#define GPY_MMD_MASK 0xFFFF0000
|
||||
#define GPY_MMD_SHIFT 16
|
||||
#define GPY_REG_MASK 0x0000FFFF
|
||||
|
||||
#define IGC_MMDAC_FUNC_DATA 0x4000 /* Data, no post increment */
|
||||
|
||||
/* MAC definitions */
|
||||
#define IGC_FACTPS_MNGCG 0x20000000
|
||||
#define IGC_FWSM_MODE_MASK 0xE
|
||||
#define IGC_FWSM_MODE_SHIFT 1
|
||||
|
||||
/* Management Control */
|
||||
#define IGC_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */
|
||||
#define IGC_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */
|
||||
|
||||
/* PHY */
|
||||
#define PHY_REVISION_MASK 0xFFFFFFF0
|
||||
#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */
|
||||
#define IGC_GEN_POLL_TIMEOUT 1920
|
||||
|
||||
/* PHY Control Register */
|
||||
#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
|
||||
#define MII_CR_POWER_DOWN 0x0800 /* Power down */
|
||||
#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
|
||||
|
||||
/* PHY Status Register */
|
||||
#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */
|
||||
#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */
|
||||
#define IGC_PHY_RST_COMP 0x0100 /* Internal PHY reset completion */
|
||||
|
||||
/* PHY 1000 MII Register/Bit Definitions */
|
||||
/* PHY Registers defined by IEEE */
|
||||
#define PHY_CONTROL 0x00 /* Control Register */
|
||||
#define PHY_STATUS 0x01 /* Status Register */
|
||||
#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */
|
||||
#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */
|
||||
#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */
|
||||
#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */
|
||||
#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */
|
||||
#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
|
||||
|
||||
/* MDI Control */
|
||||
#define IGC_MDIC_DATA_MASK 0x0000FFFF
|
||||
#define IGC_MDIC_REG_MASK 0x001F0000
|
||||
#define IGC_MDIC_REG_SHIFT 16
|
||||
#define IGC_MDIC_PHY_MASK 0x03E00000
|
||||
#define IGC_MDIC_PHY_SHIFT 21
|
||||
#define IGC_MDIC_OP_WRITE 0x04000000
|
||||
#define IGC_MDIC_OP_READ 0x08000000
|
||||
#define IGC_MDIC_READY 0x10000000
|
||||
#define IGC_MDIC_ERROR 0x40000000
|
||||
|
||||
#define IGC_N0_QUEUE -1
|
||||
|
||||
#define IGC_MAX_MAC_HDR_LEN 127
|
||||
#define IGC_MAX_NETWORK_HDR_LEN 511
|
||||
|
||||
#define IGC_VLANPQF_QSEL(_n, q_idx) ((q_idx) << ((_n) * 4))
|
||||
#define IGC_VLANPQF_VALID(_n) (0x1 << (3 + (_n) * 4))
|
||||
#define IGC_VLANPQF_QUEUE_MASK 0x03
|
||||
|
||||
#define IGC_ADVTXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */
|
||||
#define IGC_ADVTXD_TUCMD_IPV4 0x00000400 /* IP Packet Type:1=IPv4 */
|
||||
#define IGC_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet Type of TCP */
|
||||
#define IGC_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 packet TYPE of SCTP */
|
||||
|
||||
/* Maximum size of the MTA register table in all supported adapters */
|
||||
#define MAX_MTA_REG 128
|
||||
|
||||
/* EEE defines */
|
||||
#define IGC_IPCNFG_EEE_2_5G_AN 0x00000010 /* IPCNFG EEE Ena 2.5G AN */
|
||||
#define IGC_IPCNFG_EEE_1G_AN 0x00000008 /* IPCNFG EEE Ena 1G AN */
|
||||
#define IGC_IPCNFG_EEE_100M_AN 0x00000004 /* IPCNFG EEE Ena 100M AN */
|
||||
#define IGC_EEER_EEE_NEG 0x20000000 /* EEE capability nego */
|
||||
#define IGC_EEER_TX_LPI_EN 0x00010000 /* EEER Tx LPI Enable */
|
||||
#define IGC_EEER_RX_LPI_EN 0x00020000 /* EEER Rx LPI Enable */
|
||||
#define IGC_EEER_LPI_FC 0x00040000 /* EEER Ena on Flow Cntrl */
|
||||
#define IGC_EEE_SU_LPI_CLK_STP 0x00800000 /* EEE LPI Clock Stop */
|
||||
|
||||
/* LTR defines */
|
||||
#define IGC_LTRC_EEEMS_EN 0x00000020 /* Enable EEE LTR max send */
|
||||
#define IGC_RXPBS_SIZE_I225_MASK 0x0000003F /* Rx packet buffer size */
|
||||
#define IGC_TW_SYSTEM_1000_MASK 0x000000FF
|
||||
/* Minimum time for 100BASE-T where no data will be transmit following move out
|
||||
* of EEE LPI Tx state
|
||||
*/
|
||||
#define IGC_TW_SYSTEM_100_MASK 0x0000FF00
|
||||
#define IGC_TW_SYSTEM_100_SHIFT 8
|
||||
#define IGC_DMACR_DMAC_EN 0x80000000 /* Enable DMA Coalescing */
|
||||
#define IGC_DMACR_DMACTHR_MASK 0x00FF0000
|
||||
#define IGC_DMACR_DMACTHR_SHIFT 16
|
||||
/* Reg val to set scale to 1024 nsec */
|
||||
#define IGC_LTRMINV_SCALE_1024 2
|
||||
/* Reg val to set scale to 32768 nsec */
|
||||
#define IGC_LTRMINV_SCALE_32768 3
|
||||
/* Reg val to set scale to 1024 nsec */
|
||||
#define IGC_LTRMAXV_SCALE_1024 2
|
||||
/* Reg val to set scale to 32768 nsec */
|
||||
#define IGC_LTRMAXV_SCALE_32768 3
|
||||
#define IGC_LTRMINV_LTRV_MASK 0x000003FF /* LTR minimum value */
|
||||
#define IGC_LTRMAXV_LTRV_MASK 0x000003FF /* LTR maximum value */
|
||||
#define IGC_LTRMINV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */
|
||||
#define IGC_LTRMINV_SCALE_SHIFT 10
|
||||
#define IGC_LTRMAXV_LSNP_REQ 0x00008000 /* LTR Snoop Requirement */
|
||||
#define IGC_LTRMAXV_SCALE_SHIFT 10
|
||||
|
||||
#endif /* _IGC_DEFINES_H_ */
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2020 Intel Corporation */
|
||||
|
||||
#include "igc-5.14-ethercat.h"
|
||||
#include "igc_diag-5.14-ethercat.h"
|
||||
|
||||
static struct igc_reg_test reg_test[] = {
|
||||
{ IGC_FCAL, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_FCAH, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
|
||||
{ IGC_FCT, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
|
||||
{ IGC_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
|
||||
{ IGC_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
|
||||
{ IGC_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_FCRTH, 1, PATTERN_TEST, 0x0003FFF0, 0x0003FFF0 },
|
||||
{ IGC_FCTTV, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_TIPG, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
|
||||
{ IGC_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
|
||||
{ IGC_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
|
||||
{ IGC_TDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0x003FFFFB },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0xFFFFFFFF },
|
||||
{ IGC_TCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
|
||||
{ IGC_RA, 16, TABLE64_TEST_LO,
|
||||
0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_RA, 16, TABLE64_TEST_HI,
|
||||
0x900FFFFF, 0xFFFFFFFF },
|
||||
{ IGC_MTA, 128, TABLE32_TEST,
|
||||
0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static bool reg_pattern_test(struct igc_adapter *adapter, u64 *data, int reg,
|
||||
u32 mask, u32 write)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 pat, val, before;
|
||||
static const u32 test_pattern[] = {
|
||||
0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
|
||||
};
|
||||
|
||||
for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
|
||||
before = rd32(reg);
|
||||
wr32(reg, test_pattern[pat] & write);
|
||||
val = rd32(reg);
|
||||
if (val != (test_pattern[pat] & write & mask)) {
|
||||
netdev_err(adapter->netdev,
|
||||
"pattern test reg %04X failed: got 0x%08X expected 0x%08X",
|
||||
reg, val, test_pattern[pat] & write & mask);
|
||||
*data = reg;
|
||||
wr32(reg, before);
|
||||
return false;
|
||||
}
|
||||
wr32(reg, before);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool reg_set_and_check(struct igc_adapter *adapter, u64 *data, int reg,
|
||||
u32 mask, u32 write)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 val, before;
|
||||
|
||||
before = rd32(reg);
|
||||
wr32(reg, write & mask);
|
||||
val = rd32(reg);
|
||||
if ((write & mask) != (val & mask)) {
|
||||
netdev_err(adapter->netdev,
|
||||
"set/check reg %04X test failed: got 0x%08X expected 0x%08X",
|
||||
reg, (val & mask), (write & mask));
|
||||
*data = reg;
|
||||
wr32(reg, before);
|
||||
return false;
|
||||
}
|
||||
wr32(reg, before);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_reg_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
struct igc_reg_test *test = reg_test;
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 value, before, after;
|
||||
u32 i, toggle, b = false;
|
||||
|
||||
/* Because the status register is such a special case,
|
||||
* we handle it separately from the rest of the register
|
||||
* tests. Some bits are read-only, some toggle, and some
|
||||
* are writeable.
|
||||
*/
|
||||
toggle = 0x6800D3;
|
||||
before = rd32(IGC_STATUS);
|
||||
value = before & toggle;
|
||||
wr32(IGC_STATUS, toggle);
|
||||
after = rd32(IGC_STATUS) & toggle;
|
||||
if (value != after) {
|
||||
netdev_err(adapter->netdev,
|
||||
"failed STATUS register test got: 0x%08X expected: 0x%08X",
|
||||
after, value);
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
/* restore previous status */
|
||||
wr32(IGC_STATUS, before);
|
||||
|
||||
/* Perform the remainder of the register test, looping through
|
||||
* the test table until we either fail or reach the null entry.
|
||||
*/
|
||||
while (test->reg) {
|
||||
for (i = 0; i < test->array_len; i++) {
|
||||
switch (test->test_type) {
|
||||
case PATTERN_TEST:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 0x40),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case SET_READ_TEST:
|
||||
b = reg_set_and_check(adapter, data,
|
||||
test->reg + (i * 0x40),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE64_TEST_LO:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 8),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE64_TEST_HI:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + 4 + (i * 8),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE32_TEST:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 4),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
}
|
||||
if (!b)
|
||||
return false;
|
||||
}
|
||||
test++;
|
||||
}
|
||||
*data = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
|
||||
*data = 0;
|
||||
|
||||
if (hw->nvm.ops.validate(hw) != IGC_SUCCESS) {
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_link_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
bool link_up;
|
||||
|
||||
*data = 0;
|
||||
|
||||
/* add delay to give enough time for autonegotioation to finish */
|
||||
if (adapter->hw.mac.autoneg)
|
||||
ssleep(5);
|
||||
|
||||
link_up = igc_has_link(adapter);
|
||||
if (!link_up) {
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2020 Intel Corporation */
|
||||
|
||||
bool igc_reg_test(struct igc_adapter *adapter, u64 *data);
|
||||
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data);
|
||||
bool igc_link_test(struct igc_adapter *adapter, u64 *data);
|
||||
|
||||
struct igc_reg_test {
|
||||
u16 reg;
|
||||
u8 array_len;
|
||||
u8 test_type;
|
||||
u32 mask;
|
||||
u32 write;
|
||||
};
|
||||
|
||||
/* In the hardware, registers are laid out either singly, in arrays
|
||||
* spaced 0x40 bytes apart, or in contiguous tables. We assume
|
||||
* most tests take place on arrays or single registers (handled
|
||||
* as a single-element array) and special-case the tables.
|
||||
* Table tests are always pattern tests.
|
||||
*
|
||||
* We also make provision for some required setup steps by specifying
|
||||
* registers to be written without any read-back testing.
|
||||
*/
|
||||
|
||||
#define PATTERN_TEST 1
|
||||
#define SET_READ_TEST 2
|
||||
#define TABLE32_TEST 3
|
||||
#define TABLE64_TEST_LO 4
|
||||
#define TABLE64_TEST_HI 5
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2020 Intel Corporation */
|
||||
|
||||
#include "igc.h"
|
||||
#include "igc_diag.h"
|
||||
|
||||
static struct igc_reg_test reg_test[] = {
|
||||
{ IGC_FCAL, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_FCAH, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
|
||||
{ IGC_FCT, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
|
||||
{ IGC_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
|
||||
{ IGC_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
|
||||
{ IGC_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_FCRTH, 1, PATTERN_TEST, 0x0003FFF0, 0x0003FFF0 },
|
||||
{ IGC_FCTTV, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_TIPG, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
|
||||
{ IGC_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
|
||||
{ IGC_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
|
||||
{ IGC_TDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0x003FFFFB },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0xFFFFFFFF },
|
||||
{ IGC_TCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
|
||||
{ IGC_RA, 16, TABLE64_TEST_LO,
|
||||
0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_RA, 16, TABLE64_TEST_HI,
|
||||
0x900FFFFF, 0xFFFFFFFF },
|
||||
{ IGC_MTA, 128, TABLE32_TEST,
|
||||
0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static bool reg_pattern_test(struct igc_adapter *adapter, u64 *data, int reg,
|
||||
u32 mask, u32 write)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 pat, val, before;
|
||||
static const u32 test_pattern[] = {
|
||||
0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
|
||||
};
|
||||
|
||||
for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
|
||||
before = rd32(reg);
|
||||
wr32(reg, test_pattern[pat] & write);
|
||||
val = rd32(reg);
|
||||
if (val != (test_pattern[pat] & write & mask)) {
|
||||
netdev_err(adapter->netdev,
|
||||
"pattern test reg %04X failed: got 0x%08X expected 0x%08X",
|
||||
reg, val, test_pattern[pat] & write & mask);
|
||||
*data = reg;
|
||||
wr32(reg, before);
|
||||
return false;
|
||||
}
|
||||
wr32(reg, before);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool reg_set_and_check(struct igc_adapter *adapter, u64 *data, int reg,
|
||||
u32 mask, u32 write)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 val, before;
|
||||
|
||||
before = rd32(reg);
|
||||
wr32(reg, write & mask);
|
||||
val = rd32(reg);
|
||||
if ((write & mask) != (val & mask)) {
|
||||
netdev_err(adapter->netdev,
|
||||
"set/check reg %04X test failed: got 0x%08X expected 0x%08X",
|
||||
reg, (val & mask), (write & mask));
|
||||
*data = reg;
|
||||
wr32(reg, before);
|
||||
return false;
|
||||
}
|
||||
wr32(reg, before);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_reg_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
struct igc_reg_test *test = reg_test;
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 value, before, after;
|
||||
u32 i, toggle, b = false;
|
||||
|
||||
/* Because the status register is such a special case,
|
||||
* we handle it separately from the rest of the register
|
||||
* tests. Some bits are read-only, some toggle, and some
|
||||
* are writeable.
|
||||
*/
|
||||
toggle = 0x6800D3;
|
||||
before = rd32(IGC_STATUS);
|
||||
value = before & toggle;
|
||||
wr32(IGC_STATUS, toggle);
|
||||
after = rd32(IGC_STATUS) & toggle;
|
||||
if (value != after) {
|
||||
netdev_err(adapter->netdev,
|
||||
"failed STATUS register test got: 0x%08X expected: 0x%08X",
|
||||
after, value);
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
/* restore previous status */
|
||||
wr32(IGC_STATUS, before);
|
||||
|
||||
/* Perform the remainder of the register test, looping through
|
||||
* the test table until we either fail or reach the null entry.
|
||||
*/
|
||||
while (test->reg) {
|
||||
for (i = 0; i < test->array_len; i++) {
|
||||
switch (test->test_type) {
|
||||
case PATTERN_TEST:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 0x40),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case SET_READ_TEST:
|
||||
b = reg_set_and_check(adapter, data,
|
||||
test->reg + (i * 0x40),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE64_TEST_LO:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 8),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE64_TEST_HI:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + 4 + (i * 8),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE32_TEST:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 4),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
}
|
||||
if (!b)
|
||||
return false;
|
||||
}
|
||||
test++;
|
||||
}
|
||||
*data = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
|
||||
*data = 0;
|
||||
|
||||
if (hw->nvm.ops.validate(hw) != IGC_SUCCESS) {
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_link_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
bool link_up;
|
||||
|
||||
*data = 0;
|
||||
|
||||
/* add delay to give enough time for autonegotioation to finish */
|
||||
if (adapter->hw.mac.autoneg)
|
||||
ssleep(5);
|
||||
|
||||
link_up = igc_has_link(adapter);
|
||||
if (!link_up) {
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2020 Intel Corporation */
|
||||
|
||||
bool igc_reg_test(struct igc_adapter *adapter, u64 *data);
|
||||
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data);
|
||||
bool igc_link_test(struct igc_adapter *adapter, u64 *data);
|
||||
|
||||
struct igc_reg_test {
|
||||
u16 reg;
|
||||
u8 array_len;
|
||||
u8 test_type;
|
||||
u32 mask;
|
||||
u32 write;
|
||||
};
|
||||
|
||||
/* In the hardware, registers are laid out either singly, in arrays
|
||||
* spaced 0x40 bytes apart, or in contiguous tables. We assume
|
||||
* most tests take place on arrays or single registers (handled
|
||||
* as a single-element array) and special-case the tables.
|
||||
* Table tests are always pattern tests.
|
||||
*
|
||||
* We also make provision for some required setup steps by specifying
|
||||
* registers to be written without any read-back testing.
|
||||
*/
|
||||
|
||||
#define PATTERN_TEST 1
|
||||
#define SET_READ_TEST 2
|
||||
#define TABLE32_TEST 3
|
||||
#define TABLE64_TEST_LO 4
|
||||
#define TABLE64_TEST_HI 5
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2020 Intel Corporation */
|
||||
|
||||
#include "igc-6.1-ethercat.h"
|
||||
#include "igc_diag-6.1-ethercat.h"
|
||||
|
||||
static struct igc_reg_test reg_test[] = {
|
||||
{ IGC_FCAL, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_FCAH, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
|
||||
{ IGC_FCT, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
|
||||
{ IGC_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
|
||||
{ IGC_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
|
||||
{ IGC_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_FCRTH, 1, PATTERN_TEST, 0x0003FFF0, 0x0003FFF0 },
|
||||
{ IGC_FCTTV, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_TIPG, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
|
||||
{ IGC_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
|
||||
{ IGC_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
|
||||
{ IGC_TDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0x003FFFFB },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0xFFFFFFFF },
|
||||
{ IGC_TCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
|
||||
{ IGC_RA, 16, TABLE64_TEST_LO,
|
||||
0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_RA, 16, TABLE64_TEST_HI,
|
||||
0x900FFFFF, 0xFFFFFFFF },
|
||||
{ IGC_MTA, 128, TABLE32_TEST,
|
||||
0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static bool reg_pattern_test(struct igc_adapter *adapter, u64 *data, int reg,
|
||||
u32 mask, u32 write)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 pat, val, before;
|
||||
static const u32 test_pattern[] = {
|
||||
0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
|
||||
};
|
||||
|
||||
for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
|
||||
before = rd32(reg);
|
||||
wr32(reg, test_pattern[pat] & write);
|
||||
val = rd32(reg);
|
||||
if (val != (test_pattern[pat] & write & mask)) {
|
||||
netdev_err(adapter->netdev,
|
||||
"pattern test reg %04X failed: got 0x%08X expected 0x%08X",
|
||||
reg, val, test_pattern[pat] & write & mask);
|
||||
*data = reg;
|
||||
wr32(reg, before);
|
||||
return false;
|
||||
}
|
||||
wr32(reg, before);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool reg_set_and_check(struct igc_adapter *adapter, u64 *data, int reg,
|
||||
u32 mask, u32 write)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 val, before;
|
||||
|
||||
before = rd32(reg);
|
||||
wr32(reg, write & mask);
|
||||
val = rd32(reg);
|
||||
if ((write & mask) != (val & mask)) {
|
||||
netdev_err(adapter->netdev,
|
||||
"set/check reg %04X test failed: got 0x%08X expected 0x%08X",
|
||||
reg, (val & mask), (write & mask));
|
||||
*data = reg;
|
||||
wr32(reg, before);
|
||||
return false;
|
||||
}
|
||||
wr32(reg, before);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_reg_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
struct igc_reg_test *test = reg_test;
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 value, before, after;
|
||||
u32 i, toggle, b = false;
|
||||
|
||||
/* Because the status register is such a special case,
|
||||
* we handle it separately from the rest of the register
|
||||
* tests. Some bits are read-only, some toggle, and some
|
||||
* are writeable.
|
||||
*/
|
||||
toggle = 0x6800D3;
|
||||
before = rd32(IGC_STATUS);
|
||||
value = before & toggle;
|
||||
wr32(IGC_STATUS, toggle);
|
||||
after = rd32(IGC_STATUS) & toggle;
|
||||
if (value != after) {
|
||||
netdev_err(adapter->netdev,
|
||||
"failed STATUS register test got: 0x%08X expected: 0x%08X",
|
||||
after, value);
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
/* restore previous status */
|
||||
wr32(IGC_STATUS, before);
|
||||
|
||||
/* Perform the remainder of the register test, looping through
|
||||
* the test table until we either fail or reach the null entry.
|
||||
*/
|
||||
while (test->reg) {
|
||||
for (i = 0; i < test->array_len; i++) {
|
||||
switch (test->test_type) {
|
||||
case PATTERN_TEST:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 0x40),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case SET_READ_TEST:
|
||||
b = reg_set_and_check(adapter, data,
|
||||
test->reg + (i * 0x40),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE64_TEST_LO:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 8),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE64_TEST_HI:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + 4 + (i * 8),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE32_TEST:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 4),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
}
|
||||
if (!b)
|
||||
return false;
|
||||
}
|
||||
test++;
|
||||
}
|
||||
*data = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
|
||||
*data = 0;
|
||||
|
||||
if (hw->nvm.ops.validate(hw) != IGC_SUCCESS) {
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_link_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
bool link_up;
|
||||
|
||||
*data = 0;
|
||||
|
||||
/* add delay to give enough time for autonegotioation to finish */
|
||||
if (adapter->hw.mac.autoneg)
|
||||
ssleep(5);
|
||||
|
||||
link_up = igc_has_link(adapter);
|
||||
if (!link_up) {
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2020 Intel Corporation */
|
||||
|
||||
bool igc_reg_test(struct igc_adapter *adapter, u64 *data);
|
||||
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data);
|
||||
bool igc_link_test(struct igc_adapter *adapter, u64 *data);
|
||||
|
||||
struct igc_reg_test {
|
||||
u16 reg;
|
||||
u8 array_len;
|
||||
u8 test_type;
|
||||
u32 mask;
|
||||
u32 write;
|
||||
};
|
||||
|
||||
/* In the hardware, registers are laid out either singly, in arrays
|
||||
* spaced 0x40 bytes apart, or in contiguous tables. We assume
|
||||
* most tests take place on arrays or single registers (handled
|
||||
* as a single-element array) and special-case the tables.
|
||||
* Table tests are always pattern tests.
|
||||
*
|
||||
* We also make provision for some required setup steps by specifying
|
||||
* registers to be written without any read-back testing.
|
||||
*/
|
||||
|
||||
#define PATTERN_TEST 1
|
||||
#define SET_READ_TEST 2
|
||||
#define TABLE32_TEST 3
|
||||
#define TABLE64_TEST_LO 4
|
||||
#define TABLE64_TEST_HI 5
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2020 Intel Corporation */
|
||||
|
||||
#include "igc.h"
|
||||
#include "igc_diag.h"
|
||||
|
||||
static struct igc_reg_test reg_test[] = {
|
||||
{ IGC_FCAL, 1, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_FCAH, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
|
||||
{ IGC_FCT, 1, PATTERN_TEST, 0x0000FFFF, 0xFFFFFFFF },
|
||||
{ IGC_RDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_RDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
|
||||
{ IGC_RDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
|
||||
{ IGC_RDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_FCRTH, 1, PATTERN_TEST, 0x0003FFF0, 0x0003FFF0 },
|
||||
{ IGC_FCTTV, 1, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_TIPG, 1, PATTERN_TEST, 0x3FFFFFFF, 0x3FFFFFFF },
|
||||
{ IGC_TDBAH(0), 4, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_TDBAL(0), 4, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 },
|
||||
{ IGC_TDLEN(0), 4, PATTERN_TEST, 0x000FFF80, 0x000FFFFF },
|
||||
{ IGC_TDT(0), 4, PATTERN_TEST, 0x0000FFFF, 0x0000FFFF },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0x003FFFFB },
|
||||
{ IGC_RCTL, 1, SET_READ_TEST, 0x04CFB2FE, 0xFFFFFFFF },
|
||||
{ IGC_TCTL, 1, SET_READ_TEST, 0xFFFFFFFF, 0x00000000 },
|
||||
{ IGC_RA, 16, TABLE64_TEST_LO,
|
||||
0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ IGC_RA, 16, TABLE64_TEST_HI,
|
||||
0x900FFFFF, 0xFFFFFFFF },
|
||||
{ IGC_MTA, 128, TABLE32_TEST,
|
||||
0xFFFFFFFF, 0xFFFFFFFF },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static bool reg_pattern_test(struct igc_adapter *adapter, u64 *data, int reg,
|
||||
u32 mask, u32 write)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 pat, val, before;
|
||||
static const u32 test_pattern[] = {
|
||||
0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF
|
||||
};
|
||||
|
||||
for (pat = 0; pat < ARRAY_SIZE(test_pattern); pat++) {
|
||||
before = rd32(reg);
|
||||
wr32(reg, test_pattern[pat] & write);
|
||||
val = rd32(reg);
|
||||
if (val != (test_pattern[pat] & write & mask)) {
|
||||
netdev_err(adapter->netdev,
|
||||
"pattern test reg %04X failed: got 0x%08X expected 0x%08X",
|
||||
reg, val, test_pattern[pat] & write & mask);
|
||||
*data = reg;
|
||||
wr32(reg, before);
|
||||
return false;
|
||||
}
|
||||
wr32(reg, before);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool reg_set_and_check(struct igc_adapter *adapter, u64 *data, int reg,
|
||||
u32 mask, u32 write)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 val, before;
|
||||
|
||||
before = rd32(reg);
|
||||
wr32(reg, write & mask);
|
||||
val = rd32(reg);
|
||||
if ((write & mask) != (val & mask)) {
|
||||
netdev_err(adapter->netdev,
|
||||
"set/check reg %04X test failed: got 0x%08X expected 0x%08X",
|
||||
reg, (val & mask), (write & mask));
|
||||
*data = reg;
|
||||
wr32(reg, before);
|
||||
return false;
|
||||
}
|
||||
wr32(reg, before);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_reg_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
struct igc_reg_test *test = reg_test;
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 value, before, after;
|
||||
u32 i, toggle, b = false;
|
||||
|
||||
/* Because the status register is such a special case,
|
||||
* we handle it separately from the rest of the register
|
||||
* tests. Some bits are read-only, some toggle, and some
|
||||
* are writeable.
|
||||
*/
|
||||
toggle = 0x6800D3;
|
||||
before = rd32(IGC_STATUS);
|
||||
value = before & toggle;
|
||||
wr32(IGC_STATUS, toggle);
|
||||
after = rd32(IGC_STATUS) & toggle;
|
||||
if (value != after) {
|
||||
netdev_err(adapter->netdev,
|
||||
"failed STATUS register test got: 0x%08X expected: 0x%08X",
|
||||
after, value);
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
/* restore previous status */
|
||||
wr32(IGC_STATUS, before);
|
||||
|
||||
/* Perform the remainder of the register test, looping through
|
||||
* the test table until we either fail or reach the null entry.
|
||||
*/
|
||||
while (test->reg) {
|
||||
for (i = 0; i < test->array_len; i++) {
|
||||
switch (test->test_type) {
|
||||
case PATTERN_TEST:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 0x40),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case SET_READ_TEST:
|
||||
b = reg_set_and_check(adapter, data,
|
||||
test->reg + (i * 0x40),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE64_TEST_LO:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 8),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE64_TEST_HI:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + 4 + (i * 8),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
case TABLE32_TEST:
|
||||
b = reg_pattern_test(adapter, data,
|
||||
test->reg + (i * 4),
|
||||
test->mask,
|
||||
test->write);
|
||||
break;
|
||||
}
|
||||
if (!b)
|
||||
return false;
|
||||
}
|
||||
test++;
|
||||
}
|
||||
*data = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
|
||||
*data = 0;
|
||||
|
||||
if (hw->nvm.ops.validate(hw) != IGC_SUCCESS) {
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool igc_link_test(struct igc_adapter *adapter, u64 *data)
|
||||
{
|
||||
bool link_up;
|
||||
|
||||
*data = 0;
|
||||
|
||||
/* add delay to give enough time for autonegotioation to finish */
|
||||
if (adapter->hw.mac.autoneg)
|
||||
ssleep(5);
|
||||
|
||||
link_up = igc_has_link(adapter);
|
||||
if (!link_up) {
|
||||
*data = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2020 Intel Corporation */
|
||||
|
||||
bool igc_reg_test(struct igc_adapter *adapter, u64 *data);
|
||||
bool igc_eeprom_test(struct igc_adapter *adapter, u64 *data);
|
||||
bool igc_link_test(struct igc_adapter *adapter, u64 *data);
|
||||
|
||||
struct igc_reg_test {
|
||||
u16 reg;
|
||||
u8 array_len;
|
||||
u8 test_type;
|
||||
u32 mask;
|
||||
u32 write;
|
||||
};
|
||||
|
||||
/* In the hardware, registers are laid out either singly, in arrays
|
||||
* spaced 0x40 bytes apart, or in contiguous tables. We assume
|
||||
* most tests take place on arrays or single registers (handled
|
||||
* as a single-element array) and special-case the tables.
|
||||
* Table tests are always pattern tests.
|
||||
*
|
||||
* We also make provision for some required setup steps by specifying
|
||||
* registers to be written without any read-back testing.
|
||||
*/
|
||||
|
||||
#define PATTERN_TEST 1
|
||||
#define SET_READ_TEST 2
|
||||
#define TABLE32_TEST 3
|
||||
#define TABLE64_TEST_LO 4
|
||||
#define TABLE64_TEST_HI 5
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#include "igc-5.14-ethercat.h"
|
||||
|
||||
struct igc_reg_info {
|
||||
u32 ofs;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct igc_reg_info igc_reg_info_tbl[] = {
|
||||
/* General Registers */
|
||||
{IGC_CTRL, "CTRL"},
|
||||
{IGC_STATUS, "STATUS"},
|
||||
{IGC_CTRL_EXT, "CTRL_EXT"},
|
||||
{IGC_MDIC, "MDIC"},
|
||||
|
||||
/* Interrupt Registers */
|
||||
{IGC_ICR, "ICR"},
|
||||
|
||||
/* RX Registers */
|
||||
{IGC_RCTL, "RCTL"},
|
||||
{IGC_RDLEN(0), "RDLEN"},
|
||||
{IGC_RDH(0), "RDH"},
|
||||
{IGC_RDT(0), "RDT"},
|
||||
{IGC_RXDCTL(0), "RXDCTL"},
|
||||
{IGC_RDBAL(0), "RDBAL"},
|
||||
{IGC_RDBAH(0), "RDBAH"},
|
||||
|
||||
/* TX Registers */
|
||||
{IGC_TCTL, "TCTL"},
|
||||
{IGC_TDBAL(0), "TDBAL"},
|
||||
{IGC_TDBAH(0), "TDBAH"},
|
||||
{IGC_TDLEN(0), "TDLEN"},
|
||||
{IGC_TDH(0), "TDH"},
|
||||
{IGC_TDT(0), "TDT"},
|
||||
{IGC_TXDCTL(0), "TXDCTL"},
|
||||
|
||||
/* List Terminator */
|
||||
{}
|
||||
};
|
||||
|
||||
/* igc_regdump - register printout routine */
|
||||
static void igc_regdump(struct igc_hw *hw, struct igc_reg_info *reginfo)
|
||||
{
|
||||
struct net_device *dev = igc_get_hw_dev(hw);
|
||||
int n = 0;
|
||||
char rname[16];
|
||||
u32 regs[8];
|
||||
|
||||
switch (reginfo->ofs) {
|
||||
case IGC_RDLEN(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDLEN(n));
|
||||
break;
|
||||
case IGC_RDH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDH(n));
|
||||
break;
|
||||
case IGC_RDT(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDT(n));
|
||||
break;
|
||||
case IGC_RXDCTL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RXDCTL(n));
|
||||
break;
|
||||
case IGC_RDBAL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDBAL(n));
|
||||
break;
|
||||
case IGC_RDBAH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDBAH(n));
|
||||
break;
|
||||
case IGC_TDBAL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDBAL(n));
|
||||
break;
|
||||
case IGC_TDBAH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDBAH(n));
|
||||
break;
|
||||
case IGC_TDLEN(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDLEN(n));
|
||||
break;
|
||||
case IGC_TDH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDH(n));
|
||||
break;
|
||||
case IGC_TDT(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDT(n));
|
||||
break;
|
||||
case IGC_TXDCTL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TXDCTL(n));
|
||||
break;
|
||||
default:
|
||||
netdev_info(dev, "%-15s %08x\n", reginfo->name,
|
||||
rd32(reginfo->ofs));
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]");
|
||||
netdev_info(dev, "%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1],
|
||||
regs[2], regs[3]);
|
||||
}
|
||||
|
||||
/* igc_rings_dump - Tx-rings and Rx-rings */
|
||||
void igc_rings_dump(struct igc_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct my_u0 { __le64 a; __le64 b; } *u0;
|
||||
union igc_adv_tx_desc *tx_desc;
|
||||
union igc_adv_rx_desc *rx_desc;
|
||||
struct igc_ring *tx_ring;
|
||||
struct igc_ring *rx_ring;
|
||||
u32 staterr;
|
||||
u16 i, n;
|
||||
|
||||
if (!netif_msg_hw(adapter))
|
||||
return;
|
||||
|
||||
netdev_info(netdev, "Device info: state %016lX trans_start %016lX\n",
|
||||
netdev->state, dev_trans_start(netdev));
|
||||
|
||||
/* Print TX Ring Summary */
|
||||
if (!netif_running(netdev))
|
||||
goto exit;
|
||||
|
||||
netdev_info(netdev, "TX Rings Summary\n");
|
||||
netdev_info(netdev, "Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n");
|
||||
for (n = 0; n < adapter->num_tx_queues; n++) {
|
||||
struct igc_tx_buffer *buffer_info;
|
||||
|
||||
tx_ring = adapter->tx_ring[n];
|
||||
buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean];
|
||||
|
||||
netdev_info(netdev, "%5d %5X %5X %016llX %04X %p %016llX\n",
|
||||
n, tx_ring->next_to_use, tx_ring->next_to_clean,
|
||||
(u64)dma_unmap_addr(buffer_info, dma),
|
||||
dma_unmap_len(buffer_info, len),
|
||||
buffer_info->next_to_watch,
|
||||
(u64)buffer_info->time_stamp);
|
||||
}
|
||||
|
||||
/* Print TX Rings */
|
||||
if (!netif_msg_tx_done(adapter))
|
||||
goto rx_ring_summary;
|
||||
|
||||
netdev_info(netdev, "TX Rings Dump\n");
|
||||
|
||||
/* Transmit Descriptor Formats
|
||||
*
|
||||
* Advanced Transmit Descriptor
|
||||
* +--------------------------------------------------------------+
|
||||
* 0 | Buffer Address [63:0] |
|
||||
* +--------------------------------------------------------------+
|
||||
* 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN |
|
||||
* +--------------------------------------------------------------+
|
||||
* 63 46 45 40 39 38 36 35 32 31 24 15 0
|
||||
*/
|
||||
|
||||
for (n = 0; n < adapter->num_tx_queues; n++) {
|
||||
tx_ring = adapter->tx_ring[n];
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "TX QUEUE INDEX = %d\n",
|
||||
tx_ring->queue_index);
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "T [desc] [address 63:0 ] [PlPOCIStDDM Ln] [bi->dma ] leng ntw timestamp bi->skb\n");
|
||||
|
||||
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
|
||||
const char *next_desc;
|
||||
struct igc_tx_buffer *buffer_info;
|
||||
|
||||
tx_desc = IGC_TX_DESC(tx_ring, i);
|
||||
buffer_info = &tx_ring->tx_buffer_info[i];
|
||||
u0 = (struct my_u0 *)tx_desc;
|
||||
if (i == tx_ring->next_to_use &&
|
||||
i == tx_ring->next_to_clean)
|
||||
next_desc = " NTC/U";
|
||||
else if (i == tx_ring->next_to_use)
|
||||
next_desc = " NTU";
|
||||
else if (i == tx_ring->next_to_clean)
|
||||
next_desc = " NTC";
|
||||
else
|
||||
next_desc = "";
|
||||
|
||||
netdev_info(netdev, "T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n",
|
||||
i, le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
(u64)dma_unmap_addr(buffer_info, dma),
|
||||
dma_unmap_len(buffer_info, len),
|
||||
buffer_info->next_to_watch,
|
||||
(u64)buffer_info->time_stamp,
|
||||
buffer_info->skb, next_desc);
|
||||
|
||||
if (netif_msg_pktdata(adapter) && buffer_info->skb)
|
||||
print_hex_dump(KERN_INFO, "",
|
||||
DUMP_PREFIX_ADDRESS,
|
||||
16, 1, buffer_info->skb->data,
|
||||
dma_unmap_len(buffer_info, len),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print RX Rings Summary */
|
||||
rx_ring_summary:
|
||||
netdev_info(netdev, "RX Rings Summary\n");
|
||||
netdev_info(netdev, "Queue [NTU] [NTC]\n");
|
||||
for (n = 0; n < adapter->num_rx_queues; n++) {
|
||||
rx_ring = adapter->rx_ring[n];
|
||||
netdev_info(netdev, "%5d %5X %5X\n", n, rx_ring->next_to_use,
|
||||
rx_ring->next_to_clean);
|
||||
}
|
||||
|
||||
/* Print RX Rings */
|
||||
if (!netif_msg_rx_status(adapter))
|
||||
goto exit;
|
||||
|
||||
netdev_info(netdev, "RX Rings Dump\n");
|
||||
|
||||
/* Advanced Receive Descriptor (Read) Format
|
||||
* 63 1 0
|
||||
* +-----------------------------------------------------+
|
||||
* 0 | Packet Buffer Address [63:1] |A0/NSE|
|
||||
* +----------------------------------------------+------+
|
||||
* 8 | Header Buffer Address [63:1] | DD |
|
||||
* +-----------------------------------------------------+
|
||||
*
|
||||
*
|
||||
* Advanced Receive Descriptor (Write-Back) Format
|
||||
*
|
||||
* 63 48 47 32 31 30 21 20 17 16 4 3 0
|
||||
* +------------------------------------------------------+
|
||||
* 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS |
|
||||
* | Checksum Ident | | | | Type | Type |
|
||||
* +------------------------------------------------------+
|
||||
* 8 | VLAN Tag | Length | Extended Error | Extended Status |
|
||||
* +------------------------------------------------------+
|
||||
* 63 48 47 32 31 20 19 0
|
||||
*/
|
||||
|
||||
for (n = 0; n < adapter->num_rx_queues; n++) {
|
||||
rx_ring = adapter->rx_ring[n];
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "RX QUEUE INDEX = %d\n",
|
||||
rx_ring->queue_index);
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n");
|
||||
netdev_info(netdev, "RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] ---------------- [bi->skb] <-- Adv Rx Write-Back format\n");
|
||||
|
||||
for (i = 0; i < rx_ring->count; i++) {
|
||||
const char *next_desc;
|
||||
struct igc_rx_buffer *buffer_info;
|
||||
|
||||
buffer_info = &rx_ring->rx_buffer_info[i];
|
||||
rx_desc = IGC_RX_DESC(rx_ring, i);
|
||||
u0 = (struct my_u0 *)rx_desc;
|
||||
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
|
||||
if (i == rx_ring->next_to_use)
|
||||
next_desc = " NTU";
|
||||
else if (i == rx_ring->next_to_clean)
|
||||
next_desc = " NTC";
|
||||
else
|
||||
next_desc = "";
|
||||
|
||||
if (staterr & IGC_RXD_STAT_DD) {
|
||||
/* Descriptor Done */
|
||||
netdev_info(netdev, "%s[0x%03X] %016llX %016llX ---------------- %s\n",
|
||||
"RWB", i,
|
||||
le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
next_desc);
|
||||
} else {
|
||||
netdev_info(netdev, "%s[0x%03X] %016llX %016llX %016llX %s\n",
|
||||
"R ", i,
|
||||
le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
(u64)buffer_info->dma,
|
||||
next_desc);
|
||||
|
||||
if (netif_msg_pktdata(adapter) &&
|
||||
buffer_info->dma && buffer_info->page) {
|
||||
print_hex_dump(KERN_INFO, "",
|
||||
DUMP_PREFIX_ADDRESS,
|
||||
16, 1,
|
||||
page_address
|
||||
(buffer_info->page) +
|
||||
buffer_info->page_offset,
|
||||
igc_rx_bufsz(rx_ring),
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
/* igc_regs_dump - registers dump */
|
||||
void igc_regs_dump(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
struct igc_reg_info *reginfo;
|
||||
|
||||
/* Print Registers */
|
||||
netdev_info(adapter->netdev, "Register Dump\n");
|
||||
netdev_info(adapter->netdev, "Register Name Value\n");
|
||||
for (reginfo = (struct igc_reg_info *)igc_reg_info_tbl;
|
||||
reginfo->name; reginfo++) {
|
||||
igc_regdump(hw, reginfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#include "igc.h"
|
||||
|
||||
struct igc_reg_info {
|
||||
u32 ofs;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct igc_reg_info igc_reg_info_tbl[] = {
|
||||
/* General Registers */
|
||||
{IGC_CTRL, "CTRL"},
|
||||
{IGC_STATUS, "STATUS"},
|
||||
{IGC_CTRL_EXT, "CTRL_EXT"},
|
||||
{IGC_MDIC, "MDIC"},
|
||||
|
||||
/* Interrupt Registers */
|
||||
{IGC_ICR, "ICR"},
|
||||
|
||||
/* RX Registers */
|
||||
{IGC_RCTL, "RCTL"},
|
||||
{IGC_RDLEN(0), "RDLEN"},
|
||||
{IGC_RDH(0), "RDH"},
|
||||
{IGC_RDT(0), "RDT"},
|
||||
{IGC_RXDCTL(0), "RXDCTL"},
|
||||
{IGC_RDBAL(0), "RDBAL"},
|
||||
{IGC_RDBAH(0), "RDBAH"},
|
||||
|
||||
/* TX Registers */
|
||||
{IGC_TCTL, "TCTL"},
|
||||
{IGC_TDBAL(0), "TDBAL"},
|
||||
{IGC_TDBAH(0), "TDBAH"},
|
||||
{IGC_TDLEN(0), "TDLEN"},
|
||||
{IGC_TDH(0), "TDH"},
|
||||
{IGC_TDT(0), "TDT"},
|
||||
{IGC_TXDCTL(0), "TXDCTL"},
|
||||
|
||||
/* List Terminator */
|
||||
{}
|
||||
};
|
||||
|
||||
/* igc_regdump - register printout routine */
|
||||
static void igc_regdump(struct igc_hw *hw, struct igc_reg_info *reginfo)
|
||||
{
|
||||
struct net_device *dev = igc_get_hw_dev(hw);
|
||||
int n = 0;
|
||||
char rname[16];
|
||||
u32 regs[8];
|
||||
|
||||
switch (reginfo->ofs) {
|
||||
case IGC_RDLEN(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDLEN(n));
|
||||
break;
|
||||
case IGC_RDH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDH(n));
|
||||
break;
|
||||
case IGC_RDT(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDT(n));
|
||||
break;
|
||||
case IGC_RXDCTL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RXDCTL(n));
|
||||
break;
|
||||
case IGC_RDBAL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDBAL(n));
|
||||
break;
|
||||
case IGC_RDBAH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDBAH(n));
|
||||
break;
|
||||
case IGC_TDBAL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDBAL(n));
|
||||
break;
|
||||
case IGC_TDBAH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDBAH(n));
|
||||
break;
|
||||
case IGC_TDLEN(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDLEN(n));
|
||||
break;
|
||||
case IGC_TDH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDH(n));
|
||||
break;
|
||||
case IGC_TDT(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDT(n));
|
||||
break;
|
||||
case IGC_TXDCTL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TXDCTL(n));
|
||||
break;
|
||||
default:
|
||||
netdev_info(dev, "%-15s %08x\n", reginfo->name,
|
||||
rd32(reginfo->ofs));
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]");
|
||||
netdev_info(dev, "%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1],
|
||||
regs[2], regs[3]);
|
||||
}
|
||||
|
||||
/* igc_rings_dump - Tx-rings and Rx-rings */
|
||||
void igc_rings_dump(struct igc_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct my_u0 { __le64 a; __le64 b; } *u0;
|
||||
union igc_adv_tx_desc *tx_desc;
|
||||
union igc_adv_rx_desc *rx_desc;
|
||||
struct igc_ring *tx_ring;
|
||||
struct igc_ring *rx_ring;
|
||||
u32 staterr;
|
||||
u16 i, n;
|
||||
|
||||
if (!netif_msg_hw(adapter))
|
||||
return;
|
||||
|
||||
netdev_info(netdev, "Device info: state %016lX trans_start %016lX\n",
|
||||
netdev->state, dev_trans_start(netdev));
|
||||
|
||||
/* Print TX Ring Summary */
|
||||
if (!netif_running(netdev))
|
||||
goto exit;
|
||||
|
||||
netdev_info(netdev, "TX Rings Summary\n");
|
||||
netdev_info(netdev, "Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n");
|
||||
for (n = 0; n < adapter->num_tx_queues; n++) {
|
||||
struct igc_tx_buffer *buffer_info;
|
||||
|
||||
tx_ring = adapter->tx_ring[n];
|
||||
buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean];
|
||||
|
||||
netdev_info(netdev, "%5d %5X %5X %016llX %04X %p %016llX\n",
|
||||
n, tx_ring->next_to_use, tx_ring->next_to_clean,
|
||||
(u64)dma_unmap_addr(buffer_info, dma),
|
||||
dma_unmap_len(buffer_info, len),
|
||||
buffer_info->next_to_watch,
|
||||
(u64)buffer_info->time_stamp);
|
||||
}
|
||||
|
||||
/* Print TX Rings */
|
||||
if (!netif_msg_tx_done(adapter))
|
||||
goto rx_ring_summary;
|
||||
|
||||
netdev_info(netdev, "TX Rings Dump\n");
|
||||
|
||||
/* Transmit Descriptor Formats
|
||||
*
|
||||
* Advanced Transmit Descriptor
|
||||
* +--------------------------------------------------------------+
|
||||
* 0 | Buffer Address [63:0] |
|
||||
* +--------------------------------------------------------------+
|
||||
* 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN |
|
||||
* +--------------------------------------------------------------+
|
||||
* 63 46 45 40 39 38 36 35 32 31 24 15 0
|
||||
*/
|
||||
|
||||
for (n = 0; n < adapter->num_tx_queues; n++) {
|
||||
tx_ring = adapter->tx_ring[n];
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "TX QUEUE INDEX = %d\n",
|
||||
tx_ring->queue_index);
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "T [desc] [address 63:0 ] [PlPOCIStDDM Ln] [bi->dma ] leng ntw timestamp bi->skb\n");
|
||||
|
||||
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
|
||||
const char *next_desc;
|
||||
struct igc_tx_buffer *buffer_info;
|
||||
|
||||
tx_desc = IGC_TX_DESC(tx_ring, i);
|
||||
buffer_info = &tx_ring->tx_buffer_info[i];
|
||||
u0 = (struct my_u0 *)tx_desc;
|
||||
if (i == tx_ring->next_to_use &&
|
||||
i == tx_ring->next_to_clean)
|
||||
next_desc = " NTC/U";
|
||||
else if (i == tx_ring->next_to_use)
|
||||
next_desc = " NTU";
|
||||
else if (i == tx_ring->next_to_clean)
|
||||
next_desc = " NTC";
|
||||
else
|
||||
next_desc = "";
|
||||
|
||||
netdev_info(netdev, "T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n",
|
||||
i, le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
(u64)dma_unmap_addr(buffer_info, dma),
|
||||
dma_unmap_len(buffer_info, len),
|
||||
buffer_info->next_to_watch,
|
||||
(u64)buffer_info->time_stamp,
|
||||
buffer_info->skb, next_desc);
|
||||
|
||||
if (netif_msg_pktdata(adapter) && buffer_info->skb)
|
||||
print_hex_dump(KERN_INFO, "",
|
||||
DUMP_PREFIX_ADDRESS,
|
||||
16, 1, buffer_info->skb->data,
|
||||
dma_unmap_len(buffer_info, len),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print RX Rings Summary */
|
||||
rx_ring_summary:
|
||||
netdev_info(netdev, "RX Rings Summary\n");
|
||||
netdev_info(netdev, "Queue [NTU] [NTC]\n");
|
||||
for (n = 0; n < adapter->num_rx_queues; n++) {
|
||||
rx_ring = adapter->rx_ring[n];
|
||||
netdev_info(netdev, "%5d %5X %5X\n", n, rx_ring->next_to_use,
|
||||
rx_ring->next_to_clean);
|
||||
}
|
||||
|
||||
/* Print RX Rings */
|
||||
if (!netif_msg_rx_status(adapter))
|
||||
goto exit;
|
||||
|
||||
netdev_info(netdev, "RX Rings Dump\n");
|
||||
|
||||
/* Advanced Receive Descriptor (Read) Format
|
||||
* 63 1 0
|
||||
* +-----------------------------------------------------+
|
||||
* 0 | Packet Buffer Address [63:1] |A0/NSE|
|
||||
* +----------------------------------------------+------+
|
||||
* 8 | Header Buffer Address [63:1] | DD |
|
||||
* +-----------------------------------------------------+
|
||||
*
|
||||
*
|
||||
* Advanced Receive Descriptor (Write-Back) Format
|
||||
*
|
||||
* 63 48 47 32 31 30 21 20 17 16 4 3 0
|
||||
* +------------------------------------------------------+
|
||||
* 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS |
|
||||
* | Checksum Ident | | | | Type | Type |
|
||||
* +------------------------------------------------------+
|
||||
* 8 | VLAN Tag | Length | Extended Error | Extended Status |
|
||||
* +------------------------------------------------------+
|
||||
* 63 48 47 32 31 20 19 0
|
||||
*/
|
||||
|
||||
for (n = 0; n < adapter->num_rx_queues; n++) {
|
||||
rx_ring = adapter->rx_ring[n];
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "RX QUEUE INDEX = %d\n",
|
||||
rx_ring->queue_index);
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n");
|
||||
netdev_info(netdev, "RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] ---------------- [bi->skb] <-- Adv Rx Write-Back format\n");
|
||||
|
||||
for (i = 0; i < rx_ring->count; i++) {
|
||||
const char *next_desc;
|
||||
struct igc_rx_buffer *buffer_info;
|
||||
|
||||
buffer_info = &rx_ring->rx_buffer_info[i];
|
||||
rx_desc = IGC_RX_DESC(rx_ring, i);
|
||||
u0 = (struct my_u0 *)rx_desc;
|
||||
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
|
||||
if (i == rx_ring->next_to_use)
|
||||
next_desc = " NTU";
|
||||
else if (i == rx_ring->next_to_clean)
|
||||
next_desc = " NTC";
|
||||
else
|
||||
next_desc = "";
|
||||
|
||||
if (staterr & IGC_RXD_STAT_DD) {
|
||||
/* Descriptor Done */
|
||||
netdev_info(netdev, "%s[0x%03X] %016llX %016llX ---------------- %s\n",
|
||||
"RWB", i,
|
||||
le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
next_desc);
|
||||
} else {
|
||||
netdev_info(netdev, "%s[0x%03X] %016llX %016llX %016llX %s\n",
|
||||
"R ", i,
|
||||
le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
(u64)buffer_info->dma,
|
||||
next_desc);
|
||||
|
||||
if (netif_msg_pktdata(adapter) &&
|
||||
buffer_info->dma && buffer_info->page) {
|
||||
print_hex_dump(KERN_INFO, "",
|
||||
DUMP_PREFIX_ADDRESS,
|
||||
16, 1,
|
||||
page_address
|
||||
(buffer_info->page) +
|
||||
buffer_info->page_offset,
|
||||
igc_rx_bufsz(rx_ring),
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
/* igc_regs_dump - registers dump */
|
||||
void igc_regs_dump(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
struct igc_reg_info *reginfo;
|
||||
|
||||
/* Print Registers */
|
||||
netdev_info(adapter->netdev, "Register Dump\n");
|
||||
netdev_info(adapter->netdev, "Register Name Value\n");
|
||||
for (reginfo = (struct igc_reg_info *)igc_reg_info_tbl;
|
||||
reginfo->name; reginfo++) {
|
||||
igc_regdump(hw, reginfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#include "igc-6.1-ethercat.h"
|
||||
|
||||
struct igc_reg_info {
|
||||
u32 ofs;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct igc_reg_info igc_reg_info_tbl[] = {
|
||||
/* General Registers */
|
||||
{IGC_CTRL, "CTRL"},
|
||||
{IGC_STATUS, "STATUS"},
|
||||
{IGC_CTRL_EXT, "CTRL_EXT"},
|
||||
{IGC_MDIC, "MDIC"},
|
||||
|
||||
/* Interrupt Registers */
|
||||
{IGC_ICR, "ICR"},
|
||||
|
||||
/* RX Registers */
|
||||
{IGC_RCTL, "RCTL"},
|
||||
{IGC_RDLEN(0), "RDLEN"},
|
||||
{IGC_RDH(0), "RDH"},
|
||||
{IGC_RDT(0), "RDT"},
|
||||
{IGC_RXDCTL(0), "RXDCTL"},
|
||||
{IGC_RDBAL(0), "RDBAL"},
|
||||
{IGC_RDBAH(0), "RDBAH"},
|
||||
|
||||
/* TX Registers */
|
||||
{IGC_TCTL, "TCTL"},
|
||||
{IGC_TDBAL(0), "TDBAL"},
|
||||
{IGC_TDBAH(0), "TDBAH"},
|
||||
{IGC_TDLEN(0), "TDLEN"},
|
||||
{IGC_TDH(0), "TDH"},
|
||||
{IGC_TDT(0), "TDT"},
|
||||
{IGC_TXDCTL(0), "TXDCTL"},
|
||||
|
||||
/* List Terminator */
|
||||
{}
|
||||
};
|
||||
|
||||
/* igc_regdump - register printout routine */
|
||||
static void igc_regdump(struct igc_hw *hw, struct igc_reg_info *reginfo)
|
||||
{
|
||||
struct net_device *dev = igc_get_hw_dev(hw);
|
||||
int n = 0;
|
||||
char rname[16];
|
||||
u32 regs[8];
|
||||
|
||||
switch (reginfo->ofs) {
|
||||
case IGC_RDLEN(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDLEN(n));
|
||||
break;
|
||||
case IGC_RDH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDH(n));
|
||||
break;
|
||||
case IGC_RDT(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDT(n));
|
||||
break;
|
||||
case IGC_RXDCTL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RXDCTL(n));
|
||||
break;
|
||||
case IGC_RDBAL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDBAL(n));
|
||||
break;
|
||||
case IGC_RDBAH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDBAH(n));
|
||||
break;
|
||||
case IGC_TDBAL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDBAL(n));
|
||||
break;
|
||||
case IGC_TDBAH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDBAH(n));
|
||||
break;
|
||||
case IGC_TDLEN(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDLEN(n));
|
||||
break;
|
||||
case IGC_TDH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDH(n));
|
||||
break;
|
||||
case IGC_TDT(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDT(n));
|
||||
break;
|
||||
case IGC_TXDCTL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TXDCTL(n));
|
||||
break;
|
||||
default:
|
||||
netdev_info(dev, "%-15s %08x\n", reginfo->name,
|
||||
rd32(reginfo->ofs));
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]");
|
||||
netdev_info(dev, "%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1],
|
||||
regs[2], regs[3]);
|
||||
}
|
||||
|
||||
/* igc_rings_dump - Tx-rings and Rx-rings */
|
||||
void igc_rings_dump(struct igc_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct my_u0 { __le64 a; __le64 b; } *u0;
|
||||
union igc_adv_tx_desc *tx_desc;
|
||||
union igc_adv_rx_desc *rx_desc;
|
||||
struct igc_ring *tx_ring;
|
||||
struct igc_ring *rx_ring;
|
||||
u32 staterr;
|
||||
u16 i, n;
|
||||
|
||||
if (!netif_msg_hw(adapter))
|
||||
return;
|
||||
|
||||
netdev_info(netdev, "Device info: state %016lX trans_start %016lX\n",
|
||||
netdev->state, dev_trans_start(netdev));
|
||||
|
||||
/* Print TX Ring Summary */
|
||||
if (!netif_running(netdev))
|
||||
goto exit;
|
||||
|
||||
netdev_info(netdev, "TX Rings Summary\n");
|
||||
netdev_info(netdev, "Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n");
|
||||
for (n = 0; n < adapter->num_tx_queues; n++) {
|
||||
struct igc_tx_buffer *buffer_info;
|
||||
|
||||
tx_ring = adapter->tx_ring[n];
|
||||
buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean];
|
||||
|
||||
netdev_info(netdev, "%5d %5X %5X %016llX %04X %p %016llX\n",
|
||||
n, tx_ring->next_to_use, tx_ring->next_to_clean,
|
||||
(u64)dma_unmap_addr(buffer_info, dma),
|
||||
dma_unmap_len(buffer_info, len),
|
||||
buffer_info->next_to_watch,
|
||||
(u64)buffer_info->time_stamp);
|
||||
}
|
||||
|
||||
/* Print TX Rings */
|
||||
if (!netif_msg_tx_done(adapter))
|
||||
goto rx_ring_summary;
|
||||
|
||||
netdev_info(netdev, "TX Rings Dump\n");
|
||||
|
||||
/* Transmit Descriptor Formats
|
||||
*
|
||||
* Advanced Transmit Descriptor
|
||||
* +--------------------------------------------------------------+
|
||||
* 0 | Buffer Address [63:0] |
|
||||
* +--------------------------------------------------------------+
|
||||
* 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN |
|
||||
* +--------------------------------------------------------------+
|
||||
* 63 46 45 40 39 38 36 35 32 31 24 15 0
|
||||
*/
|
||||
|
||||
for (n = 0; n < adapter->num_tx_queues; n++) {
|
||||
tx_ring = adapter->tx_ring[n];
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "TX QUEUE INDEX = %d\n",
|
||||
tx_ring->queue_index);
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "T [desc] [address 63:0 ] [PlPOCIStDDM Ln] [bi->dma ] leng ntw timestamp bi->skb\n");
|
||||
|
||||
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
|
||||
const char *next_desc;
|
||||
struct igc_tx_buffer *buffer_info;
|
||||
|
||||
tx_desc = IGC_TX_DESC(tx_ring, i);
|
||||
buffer_info = &tx_ring->tx_buffer_info[i];
|
||||
u0 = (struct my_u0 *)tx_desc;
|
||||
if (i == tx_ring->next_to_use &&
|
||||
i == tx_ring->next_to_clean)
|
||||
next_desc = " NTC/U";
|
||||
else if (i == tx_ring->next_to_use)
|
||||
next_desc = " NTU";
|
||||
else if (i == tx_ring->next_to_clean)
|
||||
next_desc = " NTC";
|
||||
else
|
||||
next_desc = "";
|
||||
|
||||
netdev_info(netdev, "T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n",
|
||||
i, le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
(u64)dma_unmap_addr(buffer_info, dma),
|
||||
dma_unmap_len(buffer_info, len),
|
||||
buffer_info->next_to_watch,
|
||||
(u64)buffer_info->time_stamp,
|
||||
buffer_info->skb, next_desc);
|
||||
|
||||
if (netif_msg_pktdata(adapter) && buffer_info->skb)
|
||||
print_hex_dump(KERN_INFO, "",
|
||||
DUMP_PREFIX_ADDRESS,
|
||||
16, 1, buffer_info->skb->data,
|
||||
dma_unmap_len(buffer_info, len),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print RX Rings Summary */
|
||||
rx_ring_summary:
|
||||
netdev_info(netdev, "RX Rings Summary\n");
|
||||
netdev_info(netdev, "Queue [NTU] [NTC]\n");
|
||||
for (n = 0; n < adapter->num_rx_queues; n++) {
|
||||
rx_ring = adapter->rx_ring[n];
|
||||
netdev_info(netdev, "%5d %5X %5X\n", n, rx_ring->next_to_use,
|
||||
rx_ring->next_to_clean);
|
||||
}
|
||||
|
||||
/* Print RX Rings */
|
||||
if (!netif_msg_rx_status(adapter))
|
||||
goto exit;
|
||||
|
||||
netdev_info(netdev, "RX Rings Dump\n");
|
||||
|
||||
/* Advanced Receive Descriptor (Read) Format
|
||||
* 63 1 0
|
||||
* +-----------------------------------------------------+
|
||||
* 0 | Packet Buffer Address [63:1] |A0/NSE|
|
||||
* +----------------------------------------------+------+
|
||||
* 8 | Header Buffer Address [63:1] | DD |
|
||||
* +-----------------------------------------------------+
|
||||
*
|
||||
*
|
||||
* Advanced Receive Descriptor (Write-Back) Format
|
||||
*
|
||||
* 63 48 47 32 31 30 21 20 17 16 4 3 0
|
||||
* +------------------------------------------------------+
|
||||
* 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS |
|
||||
* | Checksum Ident | | | | Type | Type |
|
||||
* +------------------------------------------------------+
|
||||
* 8 | VLAN Tag | Length | Extended Error | Extended Status |
|
||||
* +------------------------------------------------------+
|
||||
* 63 48 47 32 31 20 19 0
|
||||
*/
|
||||
|
||||
for (n = 0; n < adapter->num_rx_queues; n++) {
|
||||
rx_ring = adapter->rx_ring[n];
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "RX QUEUE INDEX = %d\n",
|
||||
rx_ring->queue_index);
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n");
|
||||
netdev_info(netdev, "RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] ---------------- [bi->skb] <-- Adv Rx Write-Back format\n");
|
||||
|
||||
for (i = 0; i < rx_ring->count; i++) {
|
||||
const char *next_desc;
|
||||
struct igc_rx_buffer *buffer_info;
|
||||
|
||||
buffer_info = &rx_ring->rx_buffer_info[i];
|
||||
rx_desc = IGC_RX_DESC(rx_ring, i);
|
||||
u0 = (struct my_u0 *)rx_desc;
|
||||
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
|
||||
if (i == rx_ring->next_to_use)
|
||||
next_desc = " NTU";
|
||||
else if (i == rx_ring->next_to_clean)
|
||||
next_desc = " NTC";
|
||||
else
|
||||
next_desc = "";
|
||||
|
||||
if (staterr & IGC_RXD_STAT_DD) {
|
||||
/* Descriptor Done */
|
||||
netdev_info(netdev, "%s[0x%03X] %016llX %016llX ---------------- %s\n",
|
||||
"RWB", i,
|
||||
le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
next_desc);
|
||||
} else {
|
||||
netdev_info(netdev, "%s[0x%03X] %016llX %016llX %016llX %s\n",
|
||||
"R ", i,
|
||||
le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
(u64)buffer_info->dma,
|
||||
next_desc);
|
||||
|
||||
if (netif_msg_pktdata(adapter) &&
|
||||
buffer_info->dma && buffer_info->page) {
|
||||
print_hex_dump(KERN_INFO, "",
|
||||
DUMP_PREFIX_ADDRESS,
|
||||
16, 1,
|
||||
page_address
|
||||
(buffer_info->page) +
|
||||
buffer_info->page_offset,
|
||||
igc_rx_bufsz(rx_ring),
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
/* igc_regs_dump - registers dump */
|
||||
void igc_regs_dump(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
struct igc_reg_info *reginfo;
|
||||
|
||||
/* Print Registers */
|
||||
netdev_info(adapter->netdev, "Register Dump\n");
|
||||
netdev_info(adapter->netdev, "Register Name Value\n");
|
||||
for (reginfo = (struct igc_reg_info *)igc_reg_info_tbl;
|
||||
reginfo->name; reginfo++) {
|
||||
igc_regdump(hw, reginfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#include "igc.h"
|
||||
|
||||
struct igc_reg_info {
|
||||
u32 ofs;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static const struct igc_reg_info igc_reg_info_tbl[] = {
|
||||
/* General Registers */
|
||||
{IGC_CTRL, "CTRL"},
|
||||
{IGC_STATUS, "STATUS"},
|
||||
{IGC_CTRL_EXT, "CTRL_EXT"},
|
||||
{IGC_MDIC, "MDIC"},
|
||||
|
||||
/* Interrupt Registers */
|
||||
{IGC_ICR, "ICR"},
|
||||
|
||||
/* RX Registers */
|
||||
{IGC_RCTL, "RCTL"},
|
||||
{IGC_RDLEN(0), "RDLEN"},
|
||||
{IGC_RDH(0), "RDH"},
|
||||
{IGC_RDT(0), "RDT"},
|
||||
{IGC_RXDCTL(0), "RXDCTL"},
|
||||
{IGC_RDBAL(0), "RDBAL"},
|
||||
{IGC_RDBAH(0), "RDBAH"},
|
||||
|
||||
/* TX Registers */
|
||||
{IGC_TCTL, "TCTL"},
|
||||
{IGC_TDBAL(0), "TDBAL"},
|
||||
{IGC_TDBAH(0), "TDBAH"},
|
||||
{IGC_TDLEN(0), "TDLEN"},
|
||||
{IGC_TDH(0), "TDH"},
|
||||
{IGC_TDT(0), "TDT"},
|
||||
{IGC_TXDCTL(0), "TXDCTL"},
|
||||
|
||||
/* List Terminator */
|
||||
{}
|
||||
};
|
||||
|
||||
/* igc_regdump - register printout routine */
|
||||
static void igc_regdump(struct igc_hw *hw, struct igc_reg_info *reginfo)
|
||||
{
|
||||
struct net_device *dev = igc_get_hw_dev(hw);
|
||||
int n = 0;
|
||||
char rname[16];
|
||||
u32 regs[8];
|
||||
|
||||
switch (reginfo->ofs) {
|
||||
case IGC_RDLEN(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDLEN(n));
|
||||
break;
|
||||
case IGC_RDH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDH(n));
|
||||
break;
|
||||
case IGC_RDT(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDT(n));
|
||||
break;
|
||||
case IGC_RXDCTL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RXDCTL(n));
|
||||
break;
|
||||
case IGC_RDBAL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDBAL(n));
|
||||
break;
|
||||
case IGC_RDBAH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_RDBAH(n));
|
||||
break;
|
||||
case IGC_TDBAL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDBAL(n));
|
||||
break;
|
||||
case IGC_TDBAH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDBAH(n));
|
||||
break;
|
||||
case IGC_TDLEN(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDLEN(n));
|
||||
break;
|
||||
case IGC_TDH(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDH(n));
|
||||
break;
|
||||
case IGC_TDT(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TDT(n));
|
||||
break;
|
||||
case IGC_TXDCTL(0):
|
||||
for (n = 0; n < 4; n++)
|
||||
regs[n] = rd32(IGC_TXDCTL(n));
|
||||
break;
|
||||
default:
|
||||
netdev_info(dev, "%-15s %08x\n", reginfo->name,
|
||||
rd32(reginfo->ofs));
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(rname, 16, "%s%s", reginfo->name, "[0-3]");
|
||||
netdev_info(dev, "%-15s %08x %08x %08x %08x\n", rname, regs[0], regs[1],
|
||||
regs[2], regs[3]);
|
||||
}
|
||||
|
||||
/* igc_rings_dump - Tx-rings and Rx-rings */
|
||||
void igc_rings_dump(struct igc_adapter *adapter)
|
||||
{
|
||||
struct net_device *netdev = adapter->netdev;
|
||||
struct my_u0 { __le64 a; __le64 b; } *u0;
|
||||
union igc_adv_tx_desc *tx_desc;
|
||||
union igc_adv_rx_desc *rx_desc;
|
||||
struct igc_ring *tx_ring;
|
||||
struct igc_ring *rx_ring;
|
||||
u32 staterr;
|
||||
u16 i, n;
|
||||
|
||||
if (!netif_msg_hw(adapter))
|
||||
return;
|
||||
|
||||
netdev_info(netdev, "Device info: state %016lX trans_start %016lX\n",
|
||||
netdev->state, dev_trans_start(netdev));
|
||||
|
||||
/* Print TX Ring Summary */
|
||||
if (!netif_running(netdev))
|
||||
goto exit;
|
||||
|
||||
netdev_info(netdev, "TX Rings Summary\n");
|
||||
netdev_info(netdev, "Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n");
|
||||
for (n = 0; n < adapter->num_tx_queues; n++) {
|
||||
struct igc_tx_buffer *buffer_info;
|
||||
|
||||
tx_ring = adapter->tx_ring[n];
|
||||
buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_clean];
|
||||
|
||||
netdev_info(netdev, "%5d %5X %5X %016llX %04X %p %016llX\n",
|
||||
n, tx_ring->next_to_use, tx_ring->next_to_clean,
|
||||
(u64)dma_unmap_addr(buffer_info, dma),
|
||||
dma_unmap_len(buffer_info, len),
|
||||
buffer_info->next_to_watch,
|
||||
(u64)buffer_info->time_stamp);
|
||||
}
|
||||
|
||||
/* Print TX Rings */
|
||||
if (!netif_msg_tx_done(adapter))
|
||||
goto rx_ring_summary;
|
||||
|
||||
netdev_info(netdev, "TX Rings Dump\n");
|
||||
|
||||
/* Transmit Descriptor Formats
|
||||
*
|
||||
* Advanced Transmit Descriptor
|
||||
* +--------------------------------------------------------------+
|
||||
* 0 | Buffer Address [63:0] |
|
||||
* +--------------------------------------------------------------+
|
||||
* 8 | PAYLEN | PORTS |CC|IDX | STA | DCMD |DTYP|MAC|RSV| DTALEN |
|
||||
* +--------------------------------------------------------------+
|
||||
* 63 46 45 40 39 38 36 35 32 31 24 15 0
|
||||
*/
|
||||
|
||||
for (n = 0; n < adapter->num_tx_queues; n++) {
|
||||
tx_ring = adapter->tx_ring[n];
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "TX QUEUE INDEX = %d\n",
|
||||
tx_ring->queue_index);
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "T [desc] [address 63:0 ] [PlPOCIStDDM Ln] [bi->dma ] leng ntw timestamp bi->skb\n");
|
||||
|
||||
for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
|
||||
const char *next_desc;
|
||||
struct igc_tx_buffer *buffer_info;
|
||||
|
||||
tx_desc = IGC_TX_DESC(tx_ring, i);
|
||||
buffer_info = &tx_ring->tx_buffer_info[i];
|
||||
u0 = (struct my_u0 *)tx_desc;
|
||||
if (i == tx_ring->next_to_use &&
|
||||
i == tx_ring->next_to_clean)
|
||||
next_desc = " NTC/U";
|
||||
else if (i == tx_ring->next_to_use)
|
||||
next_desc = " NTU";
|
||||
else if (i == tx_ring->next_to_clean)
|
||||
next_desc = " NTC";
|
||||
else
|
||||
next_desc = "";
|
||||
|
||||
netdev_info(netdev, "T [0x%03X] %016llX %016llX %016llX %04X %p %016llX %p%s\n",
|
||||
i, le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
(u64)dma_unmap_addr(buffer_info, dma),
|
||||
dma_unmap_len(buffer_info, len),
|
||||
buffer_info->next_to_watch,
|
||||
(u64)buffer_info->time_stamp,
|
||||
buffer_info->skb, next_desc);
|
||||
|
||||
if (netif_msg_pktdata(adapter) && buffer_info->skb)
|
||||
print_hex_dump(KERN_INFO, "",
|
||||
DUMP_PREFIX_ADDRESS,
|
||||
16, 1, buffer_info->skb->data,
|
||||
dma_unmap_len(buffer_info, len),
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print RX Rings Summary */
|
||||
rx_ring_summary:
|
||||
netdev_info(netdev, "RX Rings Summary\n");
|
||||
netdev_info(netdev, "Queue [NTU] [NTC]\n");
|
||||
for (n = 0; n < adapter->num_rx_queues; n++) {
|
||||
rx_ring = adapter->rx_ring[n];
|
||||
netdev_info(netdev, "%5d %5X %5X\n", n, rx_ring->next_to_use,
|
||||
rx_ring->next_to_clean);
|
||||
}
|
||||
|
||||
/* Print RX Rings */
|
||||
if (!netif_msg_rx_status(adapter))
|
||||
goto exit;
|
||||
|
||||
netdev_info(netdev, "RX Rings Dump\n");
|
||||
|
||||
/* Advanced Receive Descriptor (Read) Format
|
||||
* 63 1 0
|
||||
* +-----------------------------------------------------+
|
||||
* 0 | Packet Buffer Address [63:1] |A0/NSE|
|
||||
* +----------------------------------------------+------+
|
||||
* 8 | Header Buffer Address [63:1] | DD |
|
||||
* +-----------------------------------------------------+
|
||||
*
|
||||
*
|
||||
* Advanced Receive Descriptor (Write-Back) Format
|
||||
*
|
||||
* 63 48 47 32 31 30 21 20 17 16 4 3 0
|
||||
* +------------------------------------------------------+
|
||||
* 0 | Packet IP |SPH| HDR_LEN | RSV|Packet| RSS |
|
||||
* | Checksum Ident | | | | Type | Type |
|
||||
* +------------------------------------------------------+
|
||||
* 8 | VLAN Tag | Length | Extended Error | Extended Status |
|
||||
* +------------------------------------------------------+
|
||||
* 63 48 47 32 31 20 19 0
|
||||
*/
|
||||
|
||||
for (n = 0; n < adapter->num_rx_queues; n++) {
|
||||
rx_ring = adapter->rx_ring[n];
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "RX QUEUE INDEX = %d\n",
|
||||
rx_ring->queue_index);
|
||||
netdev_info(netdev, "------------------------------------\n");
|
||||
netdev_info(netdev, "R [desc] [ PktBuf A0] [ HeadBuf DD] [bi->dma ] [bi->skb] <-- Adv Rx Read format\n");
|
||||
netdev_info(netdev, "RWB[desc] [PcsmIpSHl PtRs] [vl er S cks ln] ---------------- [bi->skb] <-- Adv Rx Write-Back format\n");
|
||||
|
||||
for (i = 0; i < rx_ring->count; i++) {
|
||||
const char *next_desc;
|
||||
struct igc_rx_buffer *buffer_info;
|
||||
|
||||
buffer_info = &rx_ring->rx_buffer_info[i];
|
||||
rx_desc = IGC_RX_DESC(rx_ring, i);
|
||||
u0 = (struct my_u0 *)rx_desc;
|
||||
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
|
||||
|
||||
if (i == rx_ring->next_to_use)
|
||||
next_desc = " NTU";
|
||||
else if (i == rx_ring->next_to_clean)
|
||||
next_desc = " NTC";
|
||||
else
|
||||
next_desc = "";
|
||||
|
||||
if (staterr & IGC_RXD_STAT_DD) {
|
||||
/* Descriptor Done */
|
||||
netdev_info(netdev, "%s[0x%03X] %016llX %016llX ---------------- %s\n",
|
||||
"RWB", i,
|
||||
le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
next_desc);
|
||||
} else {
|
||||
netdev_info(netdev, "%s[0x%03X] %016llX %016llX %016llX %s\n",
|
||||
"R ", i,
|
||||
le64_to_cpu(u0->a),
|
||||
le64_to_cpu(u0->b),
|
||||
(u64)buffer_info->dma,
|
||||
next_desc);
|
||||
|
||||
if (netif_msg_pktdata(adapter) &&
|
||||
buffer_info->dma && buffer_info->page) {
|
||||
print_hex_dump(KERN_INFO, "",
|
||||
DUMP_PREFIX_ADDRESS,
|
||||
16, 1,
|
||||
page_address
|
||||
(buffer_info->page) +
|
||||
buffer_info->page_offset,
|
||||
igc_rx_bufsz(rx_ring),
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
/* igc_regs_dump - registers dump */
|
||||
void igc_regs_dump(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
struct igc_reg_info *reginfo;
|
||||
|
||||
/* Print Registers */
|
||||
netdev_info(adapter->netdev, "Register Dump\n");
|
||||
netdev_info(adapter->netdev, "Register Name Value\n");
|
||||
for (reginfo = (struct igc_reg_info *)igc_reg_info_tbl;
|
||||
reginfo->name; reginfo++) {
|
||||
igc_regdump(hw, reginfo);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -9,6 +9,18 @@
|
|||
#include "igc-6.4-ethercat.h"
|
||||
#include "igc_diag-6.4-ethercat.h"
|
||||
|
||||
#ifdef CONFIG_SUSE_KERNEL
|
||||
#include <linux/suse_version.h>
|
||||
#else
|
||||
# ifndef SUSE_VERSION
|
||||
# define SUSE_VERSION 0
|
||||
# endif
|
||||
# ifndef SUSE_PATCHLEVEL
|
||||
# define SUSE_PATCHLEVEL 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* forward declaration */
|
||||
struct igc_stats {
|
||||
char stat_string[ETH_GSTRING_LEN];
|
||||
|
|
@ -1420,11 +1432,20 @@ static u32 igc_ethtool_get_rxfh_indir_size(struct net_device *netdev)
|
|||
return IGC_RETA_SIZE;
|
||||
}
|
||||
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL == 6
|
||||
static int igc_ethtool_get_rxfh(struct net_device *netdev,
|
||||
struct ethtool_rxfh_param *rxfh)
|
||||
#else
|
||||
static int igc_ethtool_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
|
||||
u8 *hfunc)
|
||||
#endif
|
||||
{
|
||||
struct igc_adapter *adapter = netdev_priv(netdev);
|
||||
int i;
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL == 6
|
||||
u32 *indir = rxfh->indir;
|
||||
u8 *hfunc = &rxfh->hfunc;
|
||||
#endif
|
||||
|
||||
if (hfunc)
|
||||
*hfunc = ETH_RSS_HASH_TOP;
|
||||
|
|
@ -1436,12 +1457,23 @@ static int igc_ethtool_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL == 6
|
||||
static int igc_ethtool_set_rxfh(struct net_device *netdev,
|
||||
struct ethtool_rxfh_param *rxfh,
|
||||
struct netlink_ext_ack *extack)
|
||||
#else
|
||||
static int igc_ethtool_set_rxfh(struct net_device *netdev, const u32 *indir,
|
||||
const u8 *key, const u8 hfunc)
|
||||
#endif
|
||||
{
|
||||
struct igc_adapter *adapter = netdev_priv(netdev);
|
||||
u32 num_queues;
|
||||
int i;
|
||||
#if SUSE_VERSION == 15 && SUSE_PATCHLEVEL == 6
|
||||
const u8 *key = rxfh->key;
|
||||
const u32 *indir = rxfh->indir;
|
||||
const u8 hfunc = rxfh->hfunc;
|
||||
#endif
|
||||
|
||||
/* We do not allow change in unsupported parameters */
|
||||
if (key ||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,298 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_HW_H_
|
||||
#define _IGC_HW_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "igc_regs-5.14-ethercat.h"
|
||||
#include "igc_defines-5.14-ethercat.h"
|
||||
#include "igc_mac-5.14-ethercat.h"
|
||||
#include "igc_phy-5.14-ethercat.h"
|
||||
#include "igc_nvm-5.14-ethercat.h"
|
||||
#include "igc_i225-5.14-ethercat.h"
|
||||
#include "igc_base-5.14-ethercat.h"
|
||||
|
||||
#define IGC_DEV_ID_I225_LM 0x15F2
|
||||
#define IGC_DEV_ID_I225_V 0x15F3
|
||||
#define IGC_DEV_ID_I225_I 0x15F8
|
||||
#define IGC_DEV_ID_I220_V 0x15F7
|
||||
#define IGC_DEV_ID_I225_K 0x3100
|
||||
#define IGC_DEV_ID_I225_K2 0x3101
|
||||
#define IGC_DEV_ID_I226_K 0x3102
|
||||
#define IGC_DEV_ID_I225_LMVP 0x5502
|
||||
#define IGC_DEV_ID_I225_IT 0x0D9F
|
||||
#define IGC_DEV_ID_I226_LM 0x125B
|
||||
#define IGC_DEV_ID_I226_V 0x125C
|
||||
#define IGC_DEV_ID_I226_IT 0x125D
|
||||
#define IGC_DEV_ID_I221_V 0x125E
|
||||
#define IGC_DEV_ID_I226_BLANK_NVM 0x125F
|
||||
#define IGC_DEV_ID_I225_BLANK_NVM 0x15FD
|
||||
|
||||
/* Function pointers for the MAC. */
|
||||
struct igc_mac_operations {
|
||||
s32 (*check_for_link)(struct igc_hw *hw);
|
||||
s32 (*reset_hw)(struct igc_hw *hw);
|
||||
s32 (*init_hw)(struct igc_hw *hw);
|
||||
s32 (*setup_physical_interface)(struct igc_hw *hw);
|
||||
void (*rar_set)(struct igc_hw *hw, u8 *address, u32 index);
|
||||
s32 (*read_mac_addr)(struct igc_hw *hw);
|
||||
s32 (*get_speed_and_duplex)(struct igc_hw *hw, u16 *speed,
|
||||
u16 *duplex);
|
||||
s32 (*acquire_swfw_sync)(struct igc_hw *hw, u16 mask);
|
||||
void (*release_swfw_sync)(struct igc_hw *hw, u16 mask);
|
||||
};
|
||||
|
||||
enum igc_mac_type {
|
||||
igc_undefined = 0,
|
||||
igc_i225,
|
||||
igc_num_macs /* List is 1-based, so subtract 1 for true count. */
|
||||
};
|
||||
|
||||
enum igc_phy_type {
|
||||
igc_phy_unknown = 0,
|
||||
igc_phy_none,
|
||||
igc_phy_i225,
|
||||
};
|
||||
|
||||
enum igc_media_type {
|
||||
igc_media_type_unknown = 0,
|
||||
igc_media_type_copper = 1,
|
||||
igc_num_media_types
|
||||
};
|
||||
|
||||
enum igc_nvm_type {
|
||||
igc_nvm_unknown = 0,
|
||||
igc_nvm_eeprom_spi,
|
||||
igc_nvm_flash_hw,
|
||||
igc_nvm_invm,
|
||||
};
|
||||
|
||||
struct igc_info {
|
||||
s32 (*get_invariants)(struct igc_hw *hw);
|
||||
struct igc_mac_operations *mac_ops;
|
||||
const struct igc_phy_operations *phy_ops;
|
||||
struct igc_nvm_operations *nvm_ops;
|
||||
};
|
||||
|
||||
extern const struct igc_info igc_base_info;
|
||||
|
||||
struct igc_mac_info {
|
||||
struct igc_mac_operations ops;
|
||||
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 perm_addr[ETH_ALEN];
|
||||
|
||||
enum igc_mac_type type;
|
||||
|
||||
u32 mc_filter_type;
|
||||
|
||||
u16 mta_reg_count;
|
||||
u16 uta_reg_count;
|
||||
|
||||
u32 mta_shadow[MAX_MTA_REG];
|
||||
u16 rar_entry_count;
|
||||
|
||||
u8 forced_speed_duplex;
|
||||
|
||||
bool asf_firmware_present;
|
||||
bool arc_subsystem_valid;
|
||||
|
||||
bool autoneg;
|
||||
bool autoneg_failed;
|
||||
bool get_link_status;
|
||||
};
|
||||
|
||||
struct igc_nvm_operations {
|
||||
s32 (*acquire)(struct igc_hw *hw);
|
||||
s32 (*read)(struct igc_hw *hw, u16 offset, u16 i, u16 *data);
|
||||
void (*release)(struct igc_hw *hw);
|
||||
s32 (*write)(struct igc_hw *hw, u16 offset, u16 i, u16 *data);
|
||||
s32 (*update)(struct igc_hw *hw);
|
||||
s32 (*validate)(struct igc_hw *hw);
|
||||
};
|
||||
|
||||
struct igc_phy_operations {
|
||||
s32 (*acquire)(struct igc_hw *hw);
|
||||
s32 (*check_reset_block)(struct igc_hw *hw);
|
||||
s32 (*force_speed_duplex)(struct igc_hw *hw);
|
||||
s32 (*get_phy_info)(struct igc_hw *hw);
|
||||
s32 (*read_reg)(struct igc_hw *hw, u32 address, u16 *data);
|
||||
void (*release)(struct igc_hw *hw);
|
||||
s32 (*reset)(struct igc_hw *hw);
|
||||
s32 (*write_reg)(struct igc_hw *hw, u32 address, u16 data);
|
||||
};
|
||||
|
||||
struct igc_nvm_info {
|
||||
struct igc_nvm_operations ops;
|
||||
enum igc_nvm_type type;
|
||||
|
||||
u16 word_size;
|
||||
u16 delay_usec;
|
||||
u16 address_bits;
|
||||
u16 opcode_bits;
|
||||
u16 page_size;
|
||||
};
|
||||
|
||||
struct igc_phy_info {
|
||||
struct igc_phy_operations ops;
|
||||
|
||||
enum igc_phy_type type;
|
||||
|
||||
u32 addr;
|
||||
u32 id;
|
||||
u32 reset_delay_us; /* in usec */
|
||||
u32 revision;
|
||||
|
||||
enum igc_media_type media_type;
|
||||
|
||||
u16 autoneg_advertised;
|
||||
u16 autoneg_mask;
|
||||
|
||||
u8 mdix;
|
||||
|
||||
bool is_mdix;
|
||||
bool speed_downgraded;
|
||||
bool autoneg_wait_to_complete;
|
||||
};
|
||||
|
||||
struct igc_bus_info {
|
||||
u16 func;
|
||||
u16 pci_cmd_word;
|
||||
};
|
||||
|
||||
enum igc_fc_mode {
|
||||
igc_fc_none = 0,
|
||||
igc_fc_rx_pause,
|
||||
igc_fc_tx_pause,
|
||||
igc_fc_full,
|
||||
igc_fc_default = 0xFF
|
||||
};
|
||||
|
||||
struct igc_fc_info {
|
||||
u32 high_water; /* Flow control high-water mark */
|
||||
u32 low_water; /* Flow control low-water mark */
|
||||
u16 pause_time; /* Flow control pause timer */
|
||||
bool send_xon; /* Flow control send XON */
|
||||
bool strict_ieee; /* Strict IEEE mode */
|
||||
enum igc_fc_mode current_mode; /* Type of flow control */
|
||||
enum igc_fc_mode requested_mode;
|
||||
};
|
||||
|
||||
struct igc_dev_spec_base {
|
||||
bool clear_semaphore_once;
|
||||
bool eee_enable;
|
||||
};
|
||||
|
||||
struct igc_hw {
|
||||
void *back;
|
||||
|
||||
u8 __iomem *hw_addr;
|
||||
unsigned long io_base;
|
||||
|
||||
struct igc_mac_info mac;
|
||||
struct igc_fc_info fc;
|
||||
struct igc_nvm_info nvm;
|
||||
struct igc_phy_info phy;
|
||||
|
||||
struct igc_bus_info bus;
|
||||
|
||||
union {
|
||||
struct igc_dev_spec_base _base;
|
||||
} dev_spec;
|
||||
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_device_id;
|
||||
u16 vendor_id;
|
||||
|
||||
u8 revision_id;
|
||||
};
|
||||
|
||||
/* Statistics counters collected by the MAC */
|
||||
struct igc_hw_stats {
|
||||
u64 crcerrs;
|
||||
u64 algnerrc;
|
||||
u64 symerrs;
|
||||
u64 rxerrc;
|
||||
u64 mpc;
|
||||
u64 scc;
|
||||
u64 ecol;
|
||||
u64 mcc;
|
||||
u64 latecol;
|
||||
u64 colc;
|
||||
u64 dc;
|
||||
u64 tncrs;
|
||||
u64 sec;
|
||||
u64 cexterr;
|
||||
u64 rlec;
|
||||
u64 xonrxc;
|
||||
u64 xontxc;
|
||||
u64 xoffrxc;
|
||||
u64 xofftxc;
|
||||
u64 fcruc;
|
||||
u64 prc64;
|
||||
u64 prc127;
|
||||
u64 prc255;
|
||||
u64 prc511;
|
||||
u64 prc1023;
|
||||
u64 prc1522;
|
||||
u64 tlpic;
|
||||
u64 rlpic;
|
||||
u64 gprc;
|
||||
u64 bprc;
|
||||
u64 mprc;
|
||||
u64 gptc;
|
||||
u64 gorc;
|
||||
u64 gotc;
|
||||
u64 rnbc;
|
||||
u64 ruc;
|
||||
u64 rfc;
|
||||
u64 roc;
|
||||
u64 rjc;
|
||||
u64 mgprc;
|
||||
u64 mgpdc;
|
||||
u64 mgptc;
|
||||
u64 tor;
|
||||
u64 tot;
|
||||
u64 tpr;
|
||||
u64 tpt;
|
||||
u64 ptc64;
|
||||
u64 ptc127;
|
||||
u64 ptc255;
|
||||
u64 ptc511;
|
||||
u64 ptc1023;
|
||||
u64 ptc1522;
|
||||
u64 mptc;
|
||||
u64 bptc;
|
||||
u64 tsctc;
|
||||
u64 tsctfc;
|
||||
u64 iac;
|
||||
u64 htdpmc;
|
||||
u64 rpthc;
|
||||
u64 hgptc;
|
||||
u64 hgorc;
|
||||
u64 hgotc;
|
||||
u64 lenerrs;
|
||||
u64 scvpc;
|
||||
u64 hrmpc;
|
||||
u64 doosync;
|
||||
u64 o2bgptc;
|
||||
u64 o2bspc;
|
||||
u64 b2ospc;
|
||||
u64 b2ogprc;
|
||||
};
|
||||
|
||||
struct net_device *igc_get_hw_dev(struct igc_hw *hw);
|
||||
#define hw_dbg(format, arg...) \
|
||||
netdev_dbg(igc_get_hw_dev(hw), format, ##arg)
|
||||
|
||||
s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
|
||||
#endif /* _IGC_HW_H_ */
|
||||
|
|
@ -0,0 +1,298 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2018 Intel Corporation */
|
||||
|
||||
#ifndef _IGC_HW_H_
|
||||
#define _IGC_HW_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "igc_regs.h"
|
||||
#include "igc_defines.h"
|
||||
#include "igc_mac.h"
|
||||
#include "igc_phy.h"
|
||||
#include "igc_nvm.h"
|
||||
#include "igc_i225.h"
|
||||
#include "igc_base.h"
|
||||
|
||||
#define IGC_DEV_ID_I225_LM 0x15F2
|
||||
#define IGC_DEV_ID_I225_V 0x15F3
|
||||
#define IGC_DEV_ID_I225_I 0x15F8
|
||||
#define IGC_DEV_ID_I220_V 0x15F7
|
||||
#define IGC_DEV_ID_I225_K 0x3100
|
||||
#define IGC_DEV_ID_I225_K2 0x3101
|
||||
#define IGC_DEV_ID_I226_K 0x3102
|
||||
#define IGC_DEV_ID_I225_LMVP 0x5502
|
||||
#define IGC_DEV_ID_I225_IT 0x0D9F
|
||||
#define IGC_DEV_ID_I226_LM 0x125B
|
||||
#define IGC_DEV_ID_I226_V 0x125C
|
||||
#define IGC_DEV_ID_I226_IT 0x125D
|
||||
#define IGC_DEV_ID_I221_V 0x125E
|
||||
#define IGC_DEV_ID_I226_BLANK_NVM 0x125F
|
||||
#define IGC_DEV_ID_I225_BLANK_NVM 0x15FD
|
||||
|
||||
/* Function pointers for the MAC. */
|
||||
struct igc_mac_operations {
|
||||
s32 (*check_for_link)(struct igc_hw *hw);
|
||||
s32 (*reset_hw)(struct igc_hw *hw);
|
||||
s32 (*init_hw)(struct igc_hw *hw);
|
||||
s32 (*setup_physical_interface)(struct igc_hw *hw);
|
||||
void (*rar_set)(struct igc_hw *hw, u8 *address, u32 index);
|
||||
s32 (*read_mac_addr)(struct igc_hw *hw);
|
||||
s32 (*get_speed_and_duplex)(struct igc_hw *hw, u16 *speed,
|
||||
u16 *duplex);
|
||||
s32 (*acquire_swfw_sync)(struct igc_hw *hw, u16 mask);
|
||||
void (*release_swfw_sync)(struct igc_hw *hw, u16 mask);
|
||||
};
|
||||
|
||||
enum igc_mac_type {
|
||||
igc_undefined = 0,
|
||||
igc_i225,
|
||||
igc_num_macs /* List is 1-based, so subtract 1 for true count. */
|
||||
};
|
||||
|
||||
enum igc_phy_type {
|
||||
igc_phy_unknown = 0,
|
||||
igc_phy_none,
|
||||
igc_phy_i225,
|
||||
};
|
||||
|
||||
enum igc_media_type {
|
||||
igc_media_type_unknown = 0,
|
||||
igc_media_type_copper = 1,
|
||||
igc_num_media_types
|
||||
};
|
||||
|
||||
enum igc_nvm_type {
|
||||
igc_nvm_unknown = 0,
|
||||
igc_nvm_eeprom_spi,
|
||||
igc_nvm_flash_hw,
|
||||
igc_nvm_invm,
|
||||
};
|
||||
|
||||
struct igc_info {
|
||||
s32 (*get_invariants)(struct igc_hw *hw);
|
||||
struct igc_mac_operations *mac_ops;
|
||||
const struct igc_phy_operations *phy_ops;
|
||||
struct igc_nvm_operations *nvm_ops;
|
||||
};
|
||||
|
||||
extern const struct igc_info igc_base_info;
|
||||
|
||||
struct igc_mac_info {
|
||||
struct igc_mac_operations ops;
|
||||
|
||||
u8 addr[ETH_ALEN];
|
||||
u8 perm_addr[ETH_ALEN];
|
||||
|
||||
enum igc_mac_type type;
|
||||
|
||||
u32 mc_filter_type;
|
||||
|
||||
u16 mta_reg_count;
|
||||
u16 uta_reg_count;
|
||||
|
||||
u32 mta_shadow[MAX_MTA_REG];
|
||||
u16 rar_entry_count;
|
||||
|
||||
u8 forced_speed_duplex;
|
||||
|
||||
bool asf_firmware_present;
|
||||
bool arc_subsystem_valid;
|
||||
|
||||
bool autoneg;
|
||||
bool autoneg_failed;
|
||||
bool get_link_status;
|
||||
};
|
||||
|
||||
struct igc_nvm_operations {
|
||||
s32 (*acquire)(struct igc_hw *hw);
|
||||
s32 (*read)(struct igc_hw *hw, u16 offset, u16 i, u16 *data);
|
||||
void (*release)(struct igc_hw *hw);
|
||||
s32 (*write)(struct igc_hw *hw, u16 offset, u16 i, u16 *data);
|
||||
s32 (*update)(struct igc_hw *hw);
|
||||
s32 (*validate)(struct igc_hw *hw);
|
||||
};
|
||||
|
||||
struct igc_phy_operations {
|
||||
s32 (*acquire)(struct igc_hw *hw);
|
||||
s32 (*check_reset_block)(struct igc_hw *hw);
|
||||
s32 (*force_speed_duplex)(struct igc_hw *hw);
|
||||
s32 (*get_phy_info)(struct igc_hw *hw);
|
||||
s32 (*read_reg)(struct igc_hw *hw, u32 address, u16 *data);
|
||||
void (*release)(struct igc_hw *hw);
|
||||
s32 (*reset)(struct igc_hw *hw);
|
||||
s32 (*write_reg)(struct igc_hw *hw, u32 address, u16 data);
|
||||
};
|
||||
|
||||
struct igc_nvm_info {
|
||||
struct igc_nvm_operations ops;
|
||||
enum igc_nvm_type type;
|
||||
|
||||
u16 word_size;
|
||||
u16 delay_usec;
|
||||
u16 address_bits;
|
||||
u16 opcode_bits;
|
||||
u16 page_size;
|
||||
};
|
||||
|
||||
struct igc_phy_info {
|
||||
struct igc_phy_operations ops;
|
||||
|
||||
enum igc_phy_type type;
|
||||
|
||||
u32 addr;
|
||||
u32 id;
|
||||
u32 reset_delay_us; /* in usec */
|
||||
u32 revision;
|
||||
|
||||
enum igc_media_type media_type;
|
||||
|
||||
u16 autoneg_advertised;
|
||||
u16 autoneg_mask;
|
||||
|
||||
u8 mdix;
|
||||
|
||||
bool is_mdix;
|
||||
bool speed_downgraded;
|
||||
bool autoneg_wait_to_complete;
|
||||
};
|
||||
|
||||
struct igc_bus_info {
|
||||
u16 func;
|
||||
u16 pci_cmd_word;
|
||||
};
|
||||
|
||||
enum igc_fc_mode {
|
||||
igc_fc_none = 0,
|
||||
igc_fc_rx_pause,
|
||||
igc_fc_tx_pause,
|
||||
igc_fc_full,
|
||||
igc_fc_default = 0xFF
|
||||
};
|
||||
|
||||
struct igc_fc_info {
|
||||
u32 high_water; /* Flow control high-water mark */
|
||||
u32 low_water; /* Flow control low-water mark */
|
||||
u16 pause_time; /* Flow control pause timer */
|
||||
bool send_xon; /* Flow control send XON */
|
||||
bool strict_ieee; /* Strict IEEE mode */
|
||||
enum igc_fc_mode current_mode; /* Type of flow control */
|
||||
enum igc_fc_mode requested_mode;
|
||||
};
|
||||
|
||||
struct igc_dev_spec_base {
|
||||
bool clear_semaphore_once;
|
||||
bool eee_enable;
|
||||
};
|
||||
|
||||
struct igc_hw {
|
||||
void *back;
|
||||
|
||||
u8 __iomem *hw_addr;
|
||||
unsigned long io_base;
|
||||
|
||||
struct igc_mac_info mac;
|
||||
struct igc_fc_info fc;
|
||||
struct igc_nvm_info nvm;
|
||||
struct igc_phy_info phy;
|
||||
|
||||
struct igc_bus_info bus;
|
||||
|
||||
union {
|
||||
struct igc_dev_spec_base _base;
|
||||
} dev_spec;
|
||||
|
||||
u16 device_id;
|
||||
u16 subsystem_vendor_id;
|
||||
u16 subsystem_device_id;
|
||||
u16 vendor_id;
|
||||
|
||||
u8 revision_id;
|
||||
};
|
||||
|
||||
/* Statistics counters collected by the MAC */
|
||||
struct igc_hw_stats {
|
||||
u64 crcerrs;
|
||||
u64 algnerrc;
|
||||
u64 symerrs;
|
||||
u64 rxerrc;
|
||||
u64 mpc;
|
||||
u64 scc;
|
||||
u64 ecol;
|
||||
u64 mcc;
|
||||
u64 latecol;
|
||||
u64 colc;
|
||||
u64 dc;
|
||||
u64 tncrs;
|
||||
u64 sec;
|
||||
u64 cexterr;
|
||||
u64 rlec;
|
||||
u64 xonrxc;
|
||||
u64 xontxc;
|
||||
u64 xoffrxc;
|
||||
u64 xofftxc;
|
||||
u64 fcruc;
|
||||
u64 prc64;
|
||||
u64 prc127;
|
||||
u64 prc255;
|
||||
u64 prc511;
|
||||
u64 prc1023;
|
||||
u64 prc1522;
|
||||
u64 tlpic;
|
||||
u64 rlpic;
|
||||
u64 gprc;
|
||||
u64 bprc;
|
||||
u64 mprc;
|
||||
u64 gptc;
|
||||
u64 gorc;
|
||||
u64 gotc;
|
||||
u64 rnbc;
|
||||
u64 ruc;
|
||||
u64 rfc;
|
||||
u64 roc;
|
||||
u64 rjc;
|
||||
u64 mgprc;
|
||||
u64 mgpdc;
|
||||
u64 mgptc;
|
||||
u64 tor;
|
||||
u64 tot;
|
||||
u64 tpr;
|
||||
u64 tpt;
|
||||
u64 ptc64;
|
||||
u64 ptc127;
|
||||
u64 ptc255;
|
||||
u64 ptc511;
|
||||
u64 ptc1023;
|
||||
u64 ptc1522;
|
||||
u64 mptc;
|
||||
u64 bptc;
|
||||
u64 tsctc;
|
||||
u64 tsctfc;
|
||||
u64 iac;
|
||||
u64 htdpmc;
|
||||
u64 rpthc;
|
||||
u64 hgptc;
|
||||
u64 hgorc;
|
||||
u64 hgotc;
|
||||
u64 lenerrs;
|
||||
u64 scvpc;
|
||||
u64 hrmpc;
|
||||
u64 doosync;
|
||||
u64 o2bgptc;
|
||||
u64 o2bspc;
|
||||
u64 b2ospc;
|
||||
u64 b2ogprc;
|
||||
};
|
||||
|
||||
struct net_device *igc_get_hw_dev(struct igc_hw *hw);
|
||||
#define hw_dbg(format, arg...) \
|
||||
netdev_dbg(igc_get_hw_dev(hw), format, ##arg)
|
||||
|
||||
s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
|
||||
|
||||
#endif /* _IGC_HW_H_ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue