diff options
author | David Thompson <davthompson@nvidia.com> | 2021-06-24 21:11:46 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-06-25 11:20:23 -0700 |
commit | f92e1869d74e1acc6551256eb084a1c14a054e19 (patch) | |
tree | e978b9338c55ccc16f8389c00958d7e35bebcb7f /drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c | |
parent | 19938bafa7ae8fc0a4a2c1c1430abb1a04668da1 (diff) | |
download | linux-f92e1869d74e1acc6551256eb084a1c14a054e19.tar.bz2 |
Add Mellanox BlueField Gigabit Ethernet driver
This patch adds build and driver logic for the "mlxbf_gige"
Ethernet driver from Mellanox Technologies. The second
generation BlueField SoC from Mellanox supports an
out-of-band GigaBit Ethernet management port to the Arm
subsystem. This driver supports TCP/IP network connectivity
for that port, and provides back-end routines to handle
basic ethtool requests.
The driver interfaces to the Gigabit Ethernet block of
BlueField SoC via MMIO accesses to registers, which contain
control information or pointers describing transmit and
receive resources. There is a single transmit queue, and
the port supports transmit ring sizes of 4 to 256 entries.
There is a single receive queue, and the port supports
receive ring sizes of 32 to 32K entries. The transmit and
receive rings are allocated from DMA coherent memory. There
is a 16-bit producer and consumer index per ring to denote
software ownership and hardware ownership, respectively.
The main driver logic such as probe(), remove(), and netdev
ops are in "mlxbf_gige_main.c". Logic in "mlxbf_gige_rx.c"
and "mlxbf_gige_tx.c" handles the packet processing for
receive and transmit respectively.
The logic in "mlxbf_gige_ethtool.c" supports the handling
of some basic ethtool requests: get driver info, get ring
parameters, get registers, and get statistics.
The logic in "mlxbf_gige_mdio.c" is the driver controlling
the Mellanox BlueField hardware that interacts with a PHY
device via MDIO/MDC pins. This driver does the following:
- At driver probe time, it configures several BlueField MDIO
parameters such as sample rate, full drive, voltage and MDC
- It defines functions to read and write MDIO registers and
registers the MDIO bus.
- It defines the phy interrupt handler reporting a
link up/down status change
- This driver's probe is invoked from the main driver logic
while the phy interrupt handler is registered in ndo_open.
Driver limitations
- Only supports 1Gbps speed
- Only supports GMII protocol
- Supports maximum packet size of 2KB
- Does not support scatter-gather buffering
Testing
- Successful build of kernel for ARM64, ARM32, X86_64
- Tested ARM64 build on FastModels & Palladium
- Tested ARM64 build on several Mellanox boards that are built with
the BlueField-2 SoC. The testing includes coverage in the areas
of networking (e.g. ping, iperf, ifconfig, route), file transfers
(e.g. SCP), and various ethtool options relevant to this driver.
Signed-off-by: David Thompson <davthompson@nvidia.com>
Signed-off-by: Asmaa Mnebhi <asmaa@nvidia.com>
Reviewed-by: Liming Sun <limings@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c new file mode 100644 index 000000000000..92b798f8e73a --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause + +/* Ethtool support for Mellanox Gigabit Ethernet driver + * + * Copyright (C) 2020-2021 NVIDIA CORPORATION & AFFILIATES + */ + +#include <linux/phy.h> + +#include "mlxbf_gige.h" +#include "mlxbf_gige_regs.h" + +/* Start of struct ethtool_ops functions */ +static int mlxbf_gige_get_regs_len(struct net_device *netdev) +{ + return MLXBF_GIGE_MMIO_REG_SZ; +} + +static void mlxbf_gige_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *p) +{ + struct mlxbf_gige *priv = netdev_priv(netdev); + + regs->version = MLXBF_GIGE_REGS_VERSION; + + /* Read entire MMIO register space and store results + * into the provided buffer. Each 64-bit word is converted + * to big-endian to make the output more readable. + * + * NOTE: by design, a read to an offset without an existing + * register will be acknowledged and return zero. + */ + memcpy_fromio(p, priv->base, MLXBF_GIGE_MMIO_REG_SZ); +} + +static void mlxbf_gige_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ering) +{ + struct mlxbf_gige *priv = netdev_priv(netdev); + + ering->rx_max_pending = MLXBF_GIGE_MAX_RXQ_SZ; + ering->tx_max_pending = MLXBF_GIGE_MAX_TXQ_SZ; + ering->rx_pending = priv->rx_q_entries; + ering->tx_pending = priv->tx_q_entries; +} + +static const struct { + const char string[ETH_GSTRING_LEN]; +} mlxbf_gige_ethtool_stats_keys[] = { + { "hw_access_errors" }, + { "tx_invalid_checksums" }, + { "tx_small_frames" }, + { "tx_index_errors" }, + { "sw_config_errors" }, + { "sw_access_errors" }, + { "rx_truncate_errors" }, + { "rx_mac_errors" }, + { "rx_din_dropped_pkts" }, + { "tx_fifo_full" }, + { "rx_filter_passed_pkts" }, + { "rx_filter_discard_pkts" }, +}; + +static int mlxbf_gige_get_sset_count(struct net_device *netdev, int stringset) +{ + if (stringset != ETH_SS_STATS) + return -EOPNOTSUPP; + return ARRAY_SIZE(mlxbf_gige_ethtool_stats_keys); +} + +static void mlxbf_gige_get_strings(struct net_device *netdev, u32 stringset, + u8 *buf) +{ + if (stringset != ETH_SS_STATS) + return; + memcpy(buf, &mlxbf_gige_ethtool_stats_keys, + sizeof(mlxbf_gige_ethtool_stats_keys)); +} + +static void mlxbf_gige_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *estats, + u64 *data) +{ + struct mlxbf_gige *priv = netdev_priv(netdev); + + /* Fill data array with interface statistics + * + * NOTE: the data writes must be in + * sync with the strings shown in + * the mlxbf_gige_ethtool_stats_keys[] array + * + * NOTE2: certain statistics below are zeroed upon + * port disable, so the calculation below + * must include the "cached" value of the stat + * plus the value read directly from hardware. + * Cached statistics are currently: + * rx_din_dropped_pkts + * rx_filter_passed_pkts + * rx_filter_discard_pkts + */ + *data++ = priv->stats.hw_access_errors; + *data++ = priv->stats.tx_invalid_checksums; + *data++ = priv->stats.tx_small_frames; + *data++ = priv->stats.tx_index_errors; + *data++ = priv->stats.sw_config_errors; + *data++ = priv->stats.sw_access_errors; + *data++ = priv->stats.rx_truncate_errors; + *data++ = priv->stats.rx_mac_errors; + *data++ = (priv->stats.rx_din_dropped_pkts + + readq(priv->base + MLXBF_GIGE_RX_DIN_DROP_COUNTER)); + *data++ = priv->stats.tx_fifo_full; + *data++ = (priv->stats.rx_filter_passed_pkts + + readq(priv->base + MLXBF_GIGE_RX_PASS_COUNTER_ALL)); + *data++ = (priv->stats.rx_filter_discard_pkts + + readq(priv->base + MLXBF_GIGE_RX_DISC_COUNTER_ALL)); +} + +static void mlxbf_gige_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) +{ + pause->autoneg = AUTONEG_DISABLE; + pause->rx_pause = 1; + pause->tx_pause = 1; +} + +const struct ethtool_ops mlxbf_gige_ethtool_ops = { + .get_link = ethtool_op_get_link, + .get_ringparam = mlxbf_gige_get_ringparam, + .get_regs_len = mlxbf_gige_get_regs_len, + .get_regs = mlxbf_gige_get_regs, + .get_strings = mlxbf_gige_get_strings, + .get_sset_count = mlxbf_gige_get_sset_count, + .get_ethtool_stats = mlxbf_gige_get_ethtool_stats, + .nway_reset = phy_ethtool_nway_reset, + .get_pauseparam = mlxbf_gige_get_pauseparam, + .get_link_ksettings = phy_ethtool_get_link_ksettings, +}; |