Commit 14da890a authored by Adam Wujek's avatar Adam Wujek

[FEATURE: #285] kernel/wr_nic: Support new functionality in ethtool

Add:
--Enabling Jumbo Frames
--Enabling transmit regardless of whether a valid link has been established
--Disabling Autonegotiation
Signed-off-by: 's avatarAdam Wujek <dev_public@wujek.eu>
parent 2d0d246b
......@@ -2499,7 +2499,7 @@ decompression and the @t{-C} (change directory) option.
Tools
Most of the tools
are build from source files in @file{userspace/tools} while the
scripts are copied directly from @file{userspace/rootfs_override/wr/bin}.
......@@ -2661,6 +2661,21 @@ The following tools and scripts are provided:
information, please refer to the
@ref{Configuration Items that Apply at Run Time}.
@item ethtool
The standad Linux tool used to query or control network driver and hardware
settings. In WRS the number of parameters that this tool can change is
limited. However, this tool can be used to:
``@t{ethtool -s wriX autoneg off}'' disables (or enable if @t{on} is used)
autonegotiation
``@t{ethtool --set-priv-flags wriX "Unidirectional Enable" on}'' enables
(or disables if @t{off} is used) transmit regardless of whether a valid link
has been established
``@t{ethtool --set-priv-flags wriX "Accept RX Jumbo Frames" on}'' accepts
(or drops if @t{off} is used) RX Jumbo Frames
@c FIXME: document rtu_stat spll_dbg_proxy
@end table
......
/*
* Ethtool operations for White-Rabbit switch network interface
*
* Copyright (C) 2010 CERN (www.cern.ch)
* Copyright (C) 2010-2023 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
* Author: Adam Wujek
* Partly from previous work by Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* Partly from previous work by Emilio G. Cota <cota@braap.org>
*
......@@ -20,6 +21,12 @@
#include "wr-nic.h"
/* Define flag in generic MII register.
* In linux/mii.h this bit is defined under reserved/unused (BMCR_RESV) */
#define BMCR_UNI_EN 0x0020
#define FRAME_SIZE_JUMBO 9216
#define FRAME_SIZE_STANDARD 0x800
static int wrn_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct wrn_ep *ep = netdev_priv(dev);
......@@ -39,20 +46,37 @@ static int wrn_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
cmd->port = PORT_FIBRE;
cmd->speed = SPEED_1000;
cmd->duplex = DUPLEX_FULL;
cmd->autoneg = AUTONEG_ENABLE;
return ret;
}
static int wrn_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct wrn_ep *ep = netdev_priv(dev);
int ret;
u32 bmcr;
u32 tmp;
spin_lock_irq(&ep->lock);
ret = mii_ethtool_sset(&ep->mii, cmd);
bmcr = wrn_phy_read(dev, 0, MII_BMCR);
if (cmd->autoneg == AUTONEG_ENABLE) {
bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
ep->mii.force_media = 0;
} else {
bmcr &= ~BMCR_ANENABLE;
ep->mii.force_media = 1;
}
wrn_phy_write(dev, 0, MII_BMCR, bmcr);
tmp = wrn_phy_read(dev, 0, MII_BMCR);
spin_unlock_irq(&ep->lock);
return ret;
/* Ignore BMCR_ANRESTART when checking write */
if (tmp != (bmcr & ~BMCR_ANRESTART)) {
printk(KERN_ERR KBUILD_MODNAME ": %s: Unable to set BMCR "
"register for port wri%d. Wrote 0x%08x, read 0x%08x\n",
__func__, ep->ep_number + 1, bmcr, tmp);
return -EIO;
}
return 0;
}
static int wrn_nwayreset(struct net_device *dev)
......@@ -76,6 +100,104 @@ static void wrn_get_drvinfo(struct net_device *dev,
sizeof(info->bus_info));
}
enum {
WRN_PRI_FLAG_UNI_EN,
WRN_PRI_FLAG_ACCEPT_RX_JUMBO,
WRN_PRI_FLAG_LEN,
};
static const char wrn_private_arr[WRN_PRI_FLAG_LEN][ETH_GSTRING_LEN] = {
/* "Enable transmit regardless of whether a valid link has been
* established" */
"Unidirectional Enable",
"Accept RX Jumbo Frames",
};
static int wrn_get_sset_count(struct net_device *dev, int stringset)
{
switch (stringset) {
case ETH_SS_PRIV_FLAGS:
return WRN_PRI_FLAG_LEN;
default:
return -EINVAL;
}
}
static u32 wrn_get_private_flags(struct net_device *dev)
{
struct wrn_ep *ep = netdev_priv(dev);
u32 flags = 0;
u32 bmcr;
u32 rfcr;
spin_lock_irq(&ep->lock);
bmcr = wrn_phy_read(dev, 0, MII_BMCR);
rfcr = wrn_ep_read(ep, RFCR);
spin_unlock_irq(&ep->lock);
flags |= (!!(bmcr & BMCR_UNI_EN)) << WRN_PRI_FLAG_UNI_EN;
flags |= (!!(rfcr & EP_RFCR_A_GIANT)) << WRN_PRI_FLAG_ACCEPT_RX_JUMBO;
return flags;
}
static int wrn_set_private_flags(struct net_device *dev, u32 flags)
{
struct wrn_ep *ep = netdev_priv(dev);
u32 bmcr;
u32 rfcr;
u32 tmp;
spin_lock_irq(&ep->lock);
bmcr = wrn_phy_read(dev, 0, MII_BMCR);
bmcr &= ~BMCR_UNI_EN;
bmcr |= (flags & (1 << WRN_PRI_FLAG_UNI_EN)) ? BMCR_UNI_EN : 0;
wrn_phy_write(dev, 0, MII_BMCR, bmcr);
tmp = wrn_phy_read(dev, 0, MII_BMCR);
spin_unlock_irq(&ep->lock);
if (tmp != bmcr) {
printk(KERN_ERR KBUILD_MODNAME ": %s: Unable to set BMCR "
"register for port wri%d. Wrote 0x%08x, read 0x%08x\n",
__func__, ep->ep_number + 1, bmcr, tmp);
return -EIO;
}
spin_lock_irq(&ep->lock);
rfcr = wrn_ep_read(ep, RFCR);
rfcr &= ~(EP_RFCR_A_GIANT | EP_RFCR_MRU_MASK);
if (flags & (1 << WRN_PRI_FLAG_ACCEPT_RX_JUMBO)) {
rfcr |= EP_RFCR_A_GIANT;
rfcr |= FRAME_SIZE_JUMBO << EP_RFCR_MRU_SHIFT;
} else {
rfcr |= FRAME_SIZE_STANDARD << EP_RFCR_MRU_SHIFT;
}
wrn_ep_write(ep, RFCR, rfcr);
tmp = wrn_ep_read(ep, RFCR);
spin_unlock_irq(&ep->lock);
if (tmp != rfcr) {
printk(KERN_ERR KBUILD_MODNAME ": %s: Unable to set RFCR "
"register for port wri%d. Wrote 0x%08x, read 0x%08x\n",
__func__, ep->ep_number + 1, rfcr, tmp);
return -EIO;
}
return 0;
}
static void wrn_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
{
switch (stringset) {
case ETH_SS_PRIV_FLAGS:
memcpy(buf, wrn_private_arr,
ETH_GSTRING_LEN * WRN_PRI_FLAG_LEN);
break;
}
}
/*
* These are the operations we support. No coalescing is there since
* most of the traffic will just happen within the FPGA switching core.
......@@ -87,6 +209,10 @@ static const struct ethtool_ops wrn_ethtool_ops = {
.set_settings = wrn_set_settings,
.get_drvinfo = wrn_get_drvinfo,
.nway_reset = wrn_nwayreset,
.get_sset_count = wrn_get_sset_count,
.get_priv_flags = wrn_get_private_flags,
.set_priv_flags = wrn_set_private_flags,
.get_strings = wrn_get_strings,
/* Some of the default methods apply for us */
.get_link = ethtool_op_get_link,
/* FIXME: get_regs_len and get_regs may be useful for debugging */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment