[SRU][F][PULL][PATCH v2 20/23] Revert "UBUNTU: SAUCE: Remove built-in tests from mlxbf_gige driver"
Asmaa Mnebhi
asmaa at nvidia.com
Fri Jul 9 19:08:27 UTC 2021
BugLink: https://bugs.launchpad.net/bugs/1934923
This reverts commit 4dd38f4ed12f5ec4f612a73623b4ac39b710b62d.
Signed-off-by: Asmaa Mnebhi <asmaa at nvidia.com>
---
.../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 41 +
.../mellanox/mlxbf_gige/mlxbf_gige_main.c | 1207 +++++++++++++++++
.../mellanox/mlxbf_gige/mlxbf_gige_regs.h | 18 +
3 files changed, 1266 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h
index 31213c47919c..86a8f0d6993c 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h
@@ -13,6 +13,9 @@
#include <linux/irqreturn.h>
#include <linux/netdevice.h>
+/* Always define this for internal Mellanox use */
+#define MLXBF_GIGE_INTERNAL
+
#define MLXBF_GIGE_MIN_RXQ_SZ 32
#define MLXBF_GIGE_MAX_RXQ_SZ 32768
#define MLXBF_GIGE_DEFAULT_RXQ_SZ 128
@@ -26,6 +29,26 @@
/* Known pattern for initial state of RX buffers */
#define MLXBF_GIGE_INIT_BYTE_RX_BUF 0x10
+#ifdef MLXBF_GIGE_INTERNAL
+/* Number of bytes in packet to be displayed by debug routines */
+#define MLXBF_GIGE_NUM_BYTES_IN_PKT_DUMP 64
+
+/* Known pattern for fake destination MAC. This
+ * value should be different from the value of
+ * MLXBF_GIGE_INIT_BYTE_RX_BUF in order to track RX.
+ */
+#define MLXBF_GIGE_FAKE_DMAC_BYTE 0x20
+
+/* Known pattern for fake source MAC. */
+#define MLXBF_GIGE_FAKE_SMAC_BYTE 0xFF
+
+/* Number of packets to transmit with verbose debugging on */
+#define MLXBF_GIGE_MAX_TX_PKTS_VERBOSE 5
+
+/* Default TX packet size used in 'start_tx_store' */
+#define MLXBF_GIGE_DEFAULT_TX_PKT_SIZE 60
+#endif /* MLXBF_GIGE_INTERNAL */
+
/* There are four individual MAC RX filters. Currently
* two of them are being used: one for the broadcast MAC
* (index 0) and one for local MAC (index 1)
@@ -98,6 +121,11 @@ struct mlxbf_gige {
bool promisc_enabled;
struct napi_struct napi;
struct mlxbf_gige_stats stats;
+
+#ifdef MLXBF_GIGE_INTERNAL
+ /* Starting seed for data in loopback packets */
+ u8 tx_data_seed;
+#endif /* MLXBF_GIGE_INTERNAL */
};
/* Rx Work Queue Element definitions */
@@ -111,6 +139,12 @@ struct mlxbf_gige {
#define MLXBF_GIGE_RX_CQE_PKT_STATUS_MAC_ERR GENMASK(12, 12)
#define MLXBF_GIGE_RX_CQE_PKT_STATUS_TRUNCATED GENMASK(13, 13)
#define MLXBF_GIGE_RX_CQE_CHKSUM_MASK GENMASK(31, 16)
+#ifdef MLXBF_GIGE_INTERNAL
+#define MLXBF_GIGE_RX_CQE_PKT_LEN_SHIFT 0
+#define MLXBF_GIGE_RX_CQE_VALID_SHIFT 11
+#define MLXBF_GIGE_RX_CQE_PKT_STATUS_SHIFT 12
+#define MLXBF_GIGE_RX_CQE_CHKSUM_SHIFT 16
+#endif
/* Tx Work Queue Element definitions */
#define MLXBF_GIGE_TX_WQE_SZ_QWORDS 2
@@ -120,6 +154,13 @@ struct mlxbf_gige {
#define MLXBF_GIGE_TX_WQE_CHKSUM_LEN_MASK GENMASK(42, 32)
#define MLXBF_GIGE_TX_WQE_CHKSUM_START_MASK GENMASK(55, 48)
#define MLXBF_GIGE_TX_WQE_CHKSUM_OFFSET_MASK GENMASK(63, 56)
+#ifdef MLXBF_GIGE_INTERNAL
+#define MLXBF_GIGE_TX_WQE_PKT_LEN_SHIFT 0
+#define MLXBF_GIGE_TX_WQE_UPDATE_SHIFT 31
+#define MLXBF_GIGE_TX_WQE_CHKSUM_LEN_SHIFT 32
+#define MLXBF_GIGE_TX_WQE_CHKSUM_START_SHIFT 48
+#define MLXBF_GIGE_TX_WQE_CHKSUM_OFFSET_SHIFT 56
+#endif
/* Macro to return packet length of specified TX WQE */
#define MLXBF_GIGE_TX_WQE_PKT_LEN(tx_wqe_addr) \
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
index 88b0406c2d9e..0432d836add7 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
@@ -5,6 +5,9 @@
* Copyright (c) 2020, Mellanox Technologies
*/
+/* Standard method to enable kernel debug (e.g. dev_dbg) */
+#define DEBUG
+
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/etherdevice.h>
@@ -14,18 +17,240 @@
#include <linux/phy.h>
#include <linux/platform_device.h>
+/* The MLXBF_GIGE_INTERNAL setting is defined in the
+ * "mlxbf_gige.h" header file, so this header file must
+ * be included before any processing of that setting.
+ */
#include "mlxbf_gige.h"
#include "mlxbf_gige_regs.h"
+#ifdef MLXBF_GIGE_INTERNAL
+#include <linux/version.h>
+/*
+ * Upstreaming guidelines:
+ * =======================
+ * 1) Do not upstream any code that is encapsulated by
+ * the "MLXBF_GIGE_INTERNAL" tag; that tag is for code
+ * that is for internal use only.
+ * 2) Remove all code that defines or checks for the
+ * definition of "FAST_MODELS". The code encapsulated
+ * by "#ifdef FAST_MODELS" should always be enabled
+ * in the upstream source since it is PHY related.
+ * 3) Remove all code that defines or checks for the
+ * definition of "MLXBF_GIGE_LOOPBACK". The code encapsulated
+ * by "#ifndef MLXBF_GIGE_LOOPBACK" should always be enabled,
+ * i.e. upstream code should run in non-loopback mode.
+ * 4) Remove any code that checks for current Linux version
+ * via "LINUX_VERSION_CODE". The upstream code should
+ * always be tailored to a specific Linux kernel.
+ * 5) Remove "#define DEBUG" at top of this file.
+ */
+
+/* Define to create mmio read/write sysfs entries */
+#define MLXBF_GIGE_MMIO_SYSFS
+
+/* Define this to perform read/write tests to MMIO regs */
+#define MLXBF_GIGE_MMIO_TESTS
+
+/* Define this to perform read/write tests to LLU MMIO regs
+ * NOTE: there is no LLU on FastModels, so don't try it.
+ */
+/* #define LLU_MMIO_TESTS */
+
+/* Define this to perform read/write tests to PLU MMIO regs
+ * NOTE: there is no PLU on FastModels, so don't try it.
+ */
+/* #define PLU_MMIO_TESTS */
+
+/* Define this to put IP networking stack into loopback mode,
+ * where IP stack will not transmit packets out the GigE interface.
+ * Instead use the GigE sysfs entry (e.g. 'echo <n> > start_tx')
+ * to send packets. It is assumed that interface is being put into
+ * loopback mode by one of these methods:
+ * a) Fast Models loopback
+ * b) PLU loopback mode
+ * c) PHY loopback mode
+ */
+/* #define MLXBF_GIGE_LOOPBACK */
+#endif /* MLXBF_GIGE_INTERNAL */
+
+#define FAST_MODELS
+
#define DRV_NAME "mlxbf_gige"
#define DRV_VERSION "1.0"
+#ifdef MLXBF_GIGE_INTERNAL
+#define MLXBF_GIGE_MSG_FORMAT \
+ " %02x %02x %02x %02x %02x %02x %02x %02x" \
+ " %02x %02x %02x %02x %02x %02x %02x %02x\n"
+
+#define MLXBF_GIGE_MSG_ARGS(p) \
+ *p, *(p + 1), *(p + 2), *(p + 3), \
+ *(p + 4), *(p + 5), *(p + 6), *(p + 7), \
+ *(p + 8), *(p + 9), *(p + 10), *(p + 11), \
+ *(p + 12), *(p + 13), *(p + 14), *(p + 15)
+
+static void mlxbf_gige_plu_selftests(struct platform_device *pdev,
+ struct mlxbf_gige *priv)
+{
+#ifdef PLU_MMIO_TESTS
+ u32 rd_data, exp_data;
+
+ dev_dbg(&pdev->dev, "Running PLU MMIO tests\n");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->plu_base + 0x8);
+ exp_data = 0x1ff;
+ dev_dbg(&pdev->dev, "PLU 0x8 equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->plu_base + 0x140);
+ exp_data = 0xe8001870;
+ dev_dbg(&pdev->dev, "PLU 0x140 equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->plu_base + 0x610);
+ exp_data = 0x31001;
+ dev_dbg(&pdev->dev, "PLU 0x610 equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->plu_base + 0x618);
+ exp_data = 0xb0000;
+ dev_dbg(&pdev->dev, "PLU 0x618 equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->plu_base + 0x890);
+ exp_data = 0x9;
+ dev_dbg(&pdev->dev, "PLU 0x890 equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->plu_base + 0x894);
+ exp_data = 0x1;
+ dev_dbg(&pdev->dev, "PLU 0x894 equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+#endif
+}
+
+static void mlxbf_gige_llu_selftests(struct platform_device *pdev,
+ struct mlxbf_gige *priv)
+{
+#ifdef LLU_MMIO_TESTS
+ u32 rd_data, exp_data;
+
+ dev_dbg(&pdev->dev, "Running LLU MMIO tests\n");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->llu_base + 0x2200);
+ exp_data = 0x91008808;
+ dev_dbg(&pdev->dev, "LLU 0x2200 equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->llu_base + 0x2204);
+ exp_data = 0x810088a8;
+ dev_dbg(&pdev->dev, "LLU 0x2204 equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->llu_base + 0x2208);
+ exp_data = 0x22e90000;
+ dev_dbg(&pdev->dev, "LLU 0x2208 equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->llu_base + 0x220c);
+ exp_data = 0x893f0000;
+ dev_dbg(&pdev->dev, "LLU 0x220c equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->llu_base + 0x2260);
+ exp_data = 0x8060806;
+ dev_dbg(&pdev->dev, "LLU 0x2260 equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readl(priv->llu_base + 0x2264);
+ exp_data = 0x891422e7;
+ dev_dbg(&pdev->dev, "LLU 0x2264 equals %x - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+#endif
+}
+
+static void mlxbf_gige_selftests(struct platform_device *pdev,
+ struct mlxbf_gige *priv)
+{
+#ifdef MLXBF_GIGE_MMIO_TESTS
+ u64 rd_data, wr_data, exp_data;
+
+ dev_dbg(&pdev->dev, "Running MLXBF_GIGE MMIO tests\n");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readq(priv->base + MLXBF_GIGE_CONFIG);
+ exp_data = (MLXBF_GIGE_CONFIG_MAX_PKT_SZ_RESET_VAL
+ << MLXBF_GIGE_CONFIG_MAX_PKT_SZ_SHIFT);
+ dev_dbg(&pdev->dev, "MLXBF_GIGE_CONFIG equals %llx - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readq(priv->base + MLXBF_GIGE_RX_WQE_SIZE_LOG2);
+ exp_data = MLXBF_GIGE_RX_WQE_SIZE_LOG2_RESET_VAL;
+ dev_dbg(&pdev->dev, "MLXBF_GIGE_RX_WQE_SIZE_LOG2 equals %llx - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Read data should match reset value in register header file */
+ rd_data = readq(priv->base + MLXBF_GIGE_TX_WQ_SIZE_LOG2);
+ exp_data = MLXBF_GIGE_TX_WQ_SIZE_LOG2_RESET_VAL;
+ dev_dbg(&pdev->dev, "MLXBF_GIGE_TX_WQ_SIZE_LOG2 equals %llx - %s\n",
+ rd_data, (rd_data == exp_data) ? "OK" : "FAIL");
+
+ /* Do some SCRATCHPAD testing */
+ rd_data = readq(priv->base + MLXBF_GIGE_SCRATCHPAD);
+ dev_dbg(&pdev->dev, "MLXBF_GIGE_SCRATCHPAD equals %llx\n", rd_data);
+
+ wr_data = 0x1122334455667788;
+ writeq(wr_data, priv->base + MLXBF_GIGE_SCRATCHPAD);
+ dev_dbg(&pdev->dev, "Will write %llx to MLXBF_GIGE_SCRATCHPAD\n",
+ wr_data);
+
+ rd_data = readq(priv->base + MLXBF_GIGE_SCRATCHPAD);
+ dev_dbg(&pdev->dev, "MLXBF_GIGE_SCRATCHPAD equals %llx - %s\n",
+ rd_data, (rd_data == wr_data) ? "OK" : "FAIL");
+
+ wr_data = 0xaabbccddeeff4321;
+ writeq(wr_data, priv->base + MLXBF_GIGE_SCRATCHPAD);
+ dev_dbg(&pdev->dev, "Will write %llx to MLXBF_GIGE_SCRATCHPAD\n",
+ wr_data);
+
+ rd_data = readq(priv->base + MLXBF_GIGE_SCRATCHPAD);
+ dev_dbg(&pdev->dev, "MLXBF_GIGE_SCRATCHPAD equals %llx - %s\n",
+ rd_data, (rd_data == wr_data) ? "OK" : "FAIL");
+#endif /* MLXBF_GIGE_MMIO_TESTS */
+}
+#endif /* MLXBF_GIGE_INTERNAL */
+
static void mlxbf_gige_set_mac_rx_filter(struct mlxbf_gige *priv,
unsigned int index, u64 dmac)
{
void __iomem *base = priv->base;
u64 control;
+#ifdef MLXBF_GIGE_INTERNAL
+ if (index > 3) {
+ dev_err(priv->dev, "%s: invalid index %d\n",
+ __func__, index);
+ return;
+ }
+
+ dev_dbg(priv->dev, "set_mac_rx_filter: index=%d dmac=%llx\n",
+ index, dmac);
+#endif
+
/* Write destination MAC to specified MAC RX filter */
writeq(dmac, base + MLXBF_GIGE_RX_MAC_FILTER +
(index * MLXBF_GIGE_RX_MAC_FILTER_STRIDE));
@@ -41,10 +266,29 @@ static int mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv,
{
void __iomem *base = priv->base;
+#ifdef MLXBF_GIGE_INTERNAL
+ if (index > 3) {
+ dev_err(priv->dev, "%s: invalid index %d\n",
+ __func__, index);
+ return -EINVAL;
+ }
+
+ if (!dmac) {
+ dev_err(priv->dev, "%s: invalid dmac pointer NULL\n",
+ __func__);
+ return -EINVAL;
+ }
+#endif
+
/* Read destination MAC from specified MAC RX filter */
*dmac = readq(base + MLXBF_GIGE_RX_MAC_FILTER +
(index * MLXBF_GIGE_RX_MAC_FILTER_STRIDE));
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(priv->dev, "get_mac_rx_filter: index=%d dmac=%llx\n",
+ index, *dmac);
+#endif
+
return 0;
}
@@ -53,6 +297,10 @@ static void mlxbf_gige_enable_promisc(struct mlxbf_gige *priv)
void __iomem *base = priv->base;
u64 control;
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(priv->dev, "%s\n", __func__);
+#endif
+
/* Enable MAC_ID_RANGE match functionality */
control = readq(base + MLXBF_GIGE_CONTROL);
control |= MLXBF_GIGE_CONTROL_MAC_ID_RANGE_EN;
@@ -70,6 +318,10 @@ static void mlxbf_gige_disable_promisc(struct mlxbf_gige *priv)
void __iomem *base = priv->base;
u64 control;
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(priv->dev, "%s\n", __func__);
+#endif
+
/* Disable MAC_ID_RANGE match functionality */
control = readq(base + MLXBF_GIGE_CONTROL);
control &= ~MLXBF_GIGE_CONTROL_MAC_ID_RANGE_EN;
@@ -107,6 +359,11 @@ static int mlxbf_gige_rx_init(struct mlxbf_gige *priv)
if (!priv->rx_wqe_base)
return -ENOMEM;
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(priv->dev, "rx_init: RX WQE base 0x%llx 0x%llx\n",
+ (u64)priv->rx_wqe_base, (u64)priv->rx_wqe_base_dma);
+#endif
+
/* Initialize 'rx_wqe_ptr' to point to first RX WQE in array
* Each RX WQE is simply a receive buffer pointer, so walk
* the entire array, allocating a 2KB buffer for each element
@@ -114,6 +371,9 @@ static int mlxbf_gige_rx_init(struct mlxbf_gige *priv)
rx_wqe_ptr = priv->rx_wqe_base;
for (i = 0; i < priv->rx_q_entries; i++) {
+#ifdef MLXBF_GIGE_INTERNAL
+ u8 *p;
+#endif
/* Allocate a receive buffer for this RX WQE. The DMA
* form (dma_addr_t) of the receive buffer address is
* stored in the RX WQE array (via 'rx_wqe_ptr') where
@@ -128,6 +388,14 @@ static int mlxbf_gige_rx_init(struct mlxbf_gige *priv)
if (!priv->rx_buf[i])
goto free_wqe_and_buf;
+#ifdef MLXBF_GIGE_INTERNAL
+ /* Initialize the first 16 bytes of each RX buffer
+ * to a known pattern. This will make it easy to
+ * identify when each receive buffer is populated
+ */
+ p = priv->rx_buf[i];
+ memset(p, MLXBF_GIGE_INIT_BYTE_RX_BUF, 16);
+#endif
*rx_wqe_ptr++ = rx_buf_dma;
}
@@ -141,6 +409,11 @@ static int mlxbf_gige_rx_init(struct mlxbf_gige *priv)
if (!priv->rx_cqe_base)
goto free_wqe_and_buf;
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(priv->dev, "rx_init: RX CQE base 0x%llx 0x%llx\n",
+ (u64)priv->rx_cqe_base, (u64)priv->rx_cqe_base_dma);
+#endif
+
/* Write RX CQE base address into MMIO reg */
writeq(priv->rx_cqe_base_dma, priv->base + MLXBF_GIGE_RX_CQ_BASE);
@@ -200,6 +473,11 @@ static int mlxbf_gige_tx_init(struct mlxbf_gige *priv)
if (!priv->tx_wqe_base)
return -ENOMEM;
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(priv->dev, "tx_init: TX WQE base 0x%llx 0x%llx\n",
+ (u64)priv->tx_wqe_base, (u64)priv->tx_wqe_base_dma);
+#endif
+
priv->tx_wqe_next = priv->tx_wqe_base;
/* Write TX WQE base address into MMIO reg */
@@ -215,6 +493,11 @@ static int mlxbf_gige_tx_init(struct mlxbf_gige *priv)
return -ENOMEM;
}
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(priv->dev, "tx_init: TX CC 0x%llx 0x%llx\n",
+ (u64)priv->tx_cc, (u64)priv->tx_cc_dma);
+#endif
+
/* Write TX CC base address into MMIO reg */
writeq(priv->tx_cc_dma, priv->base + MLXBF_GIGE_TX_CI_UPDATE_ADDRESS);
@@ -369,6 +652,12 @@ static int mlxbf_gige_set_ringparam(struct net_device *netdev,
new_tx_q_entries == priv->tx_q_entries)
return 0;
+#ifdef MLXBF_GIGE_INTERNAL
+ netdev_printk(KERN_DEBUG, netdev,
+ "set_ringparam(): new_tx=%x new_rx=%x\n",
+ new_tx_q_entries, new_rx_q_entries);
+#endif
+
if (netif_running(netdev))
ops->ndo_stop(netdev);
@@ -480,6 +769,7 @@ static const struct ethtool_ops mlxbf_gige_ethtool_ops = {
.get_ethtool_stats = mlxbf_gige_get_ethtool_stats,
};
+#ifdef FAST_MODELS
static void mlxbf_gige_handle_link_change(struct net_device *netdev)
{
struct mlxbf_gige *priv = netdev_priv(netdev);
@@ -493,6 +783,7 @@ static void mlxbf_gige_handle_link_change(struct net_device *netdev)
/* print new link status only if the interrupt came from the PHY */
phy_print_status(phydev);
}
+#endif /* FAST_MODELS */
/* Start of struct net_device_ops functions */
static irqreturn_t mlxbf_gige_error_intr(int irq, void *dev_id)
@@ -506,12 +797,33 @@ static irqreturn_t mlxbf_gige_error_intr(int irq, void *dev_id)
int_status = readq(priv->base + MLXBF_GIGE_INT_STATUS);
+#ifdef MLXBF_GIGE_INTERNAL
+ /* Trigger kernel log message on first interrupt of each
+ * type and then service the asserted error condition(s).
+ */
+#endif
+
if (int_status & MLXBF_GIGE_INT_STATUS_HW_ACCESS_ERROR) {
priv->stats.hw_access_errors++;
+#ifdef MLXBF_GIGE_INTERNAL
+ if (priv->stats.hw_access_errors == 1) {
+ dev_info(priv->dev,
+ "%s: hw_access_error triggered\n",
+ __func__);
+ }
+ /* TODO - add logic to service hw_access_error */
+#endif
}
if (int_status & MLXBF_GIGE_INT_STATUS_TX_CHECKSUM_INPUTS) {
priv->stats.tx_invalid_checksums++;
+#ifdef MLXBF_GIGE_INTERNAL
+ if (priv->stats.tx_invalid_checksums == 1) {
+ dev_info(priv->dev,
+ "%s: tx_invalid_checksum triggered\n",
+ __func__);
+ }
+#endif
/* This error condition is latched into MLXBF_GIGE_INT_STATUS
* when the GigE silicon operates on the offending
* TX WQE. The write to MLXBF_GIGE_INT_STATUS at the bottom
@@ -535,14 +847,38 @@ static irqreturn_t mlxbf_gige_error_intr(int irq, void *dev_id)
if (int_status & MLXBF_GIGE_INT_STATUS_TX_PI_CI_EXCEED_WQ_SIZE) {
priv->stats.tx_index_errors++;
+#ifdef MLXBF_GIGE_INTERNAL
+ if (priv->stats.tx_index_errors == 1) {
+ dev_info(priv->dev,
+ "%s: tx_index_error triggered\n",
+ __func__);
+ }
+ /* TODO - add logic to service tx_index_error */
+#endif
}
if (int_status & MLXBF_GIGE_INT_STATUS_SW_CONFIG_ERROR) {
priv->stats.sw_config_errors++;
+#ifdef MLXBF_GIGE_INTERNAL
+ if (priv->stats.sw_config_errors == 1) {
+ dev_info(priv->dev,
+ "%s: sw_config_error triggered\n",
+ __func__);
+ }
+ /* TODO - add logic to service sw_config_error */
+#endif
}
if (int_status & MLXBF_GIGE_INT_STATUS_SW_ACCESS_ERROR) {
priv->stats.sw_access_errors++;
+#ifdef MLXBF_GIGE_INTERNAL
+ if (priv->stats.sw_access_errors == 1) {
+ dev_info(priv->dev,
+ "%s: sw_access_error triggered\n",
+ __func__);
+ }
+ /* TODO - add logic to service sw_access_error */
+#endif
}
/* Clear all error interrupts by writing '1' back to
@@ -590,6 +926,14 @@ static irqreturn_t mlxbf_gige_llu_plu_intr(int irq, void *dev_id)
priv = dev_id;
priv->llu_plu_intr_count++;
+#ifdef MLXBF_GIGE_INTERNAL
+ /* Trigger kernel log message on first interrupt */
+ if (priv->llu_plu_intr_count == 1)
+ dev_info(priv->dev, "%s: triggered\n", __func__);
+
+ /* TODO - add logic to service LLU and PLU interrupts */
+#endif
+
return IRQ_HANDLED;
}
@@ -652,9 +996,11 @@ static bool mlxbf_gige_handle_tx_complete(struct mlxbf_gige *priv)
stats->tx_packets++;
stats->tx_bytes += MLXBF_GIGE_TX_WQE_PKT_LEN(tx_wqe_addr);
+#ifndef MLXBF_GIGE_LOOPBACK
dma_free_coherent(priv->dev, MLXBF_GIGE_DEFAULT_BUF_SZ,
priv->tx_buf[tx_wqe_index], *tx_wqe_addr);
priv->tx_buf[tx_wqe_index] = NULL;
+#endif
}
/* Since the TX ring was likely just drained, check if TX queue
@@ -663,6 +1009,9 @@ static bool mlxbf_gige_handle_tx_complete(struct mlxbf_gige *priv)
*/
if (netif_queue_stopped(priv->netdev) &&
mlxbf_gige_tx_buffs_avail(priv)) {
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(priv->dev, "%s: waking TX queue", __func__);
+#endif
netif_wake_queue(priv->netdev);
}
@@ -695,8 +1044,14 @@ static bool mlxbf_gige_rx_packet(struct mlxbf_gige *priv, int *rx_pkts)
netdev->stats.rx_bytes += datalen;
} else if (rx_cqe & MLXBF_GIGE_RX_CQE_PKT_STATUS_MAC_ERR) {
priv->stats.rx_mac_errors++;
+#ifdef MLXBF_GIGE_INTERNAL
+ /* TODO - handle error case */
+#endif
} else if (rx_cqe & MLXBF_GIGE_RX_CQE_PKT_STATUS_TRUNCATED) {
priv->stats.rx_truncate_errors++;
+#ifdef MLXBF_GIGE_INTERNAL
+ /* TODO - handle error case */
+#endif
}
skb = dev_alloc_skb(datalen);
@@ -797,10 +1152,17 @@ static void mlxbf_gige_free_irqs(struct mlxbf_gige *priv)
static int mlxbf_gige_open(struct net_device *netdev)
{
struct mlxbf_gige *priv = netdev_priv(netdev);
+#ifdef FAST_MODELS
struct phy_device *phydev;
+#endif
u64 int_en;
int err;
+#ifdef MLXBF_GIGE_INTERNAL
+ netdev_printk(KERN_DEBUG, netdev, "open: priv=%llx\n",
+ (u64)priv);
+#endif
+
memset(&priv->stats, 0, sizeof(priv->stats));
mlxbf_gige_rx_init(priv);
@@ -813,6 +1175,7 @@ static int mlxbf_gige_open(struct net_device *netdev)
if (err)
return err;
+#ifdef FAST_MODELS
phydev = phy_find_first(priv->mdiobus);
if (!phydev)
return -EIO;
@@ -828,6 +1191,7 @@ static int mlxbf_gige_open(struct net_device *netdev)
return err;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
/* MAC only supports 1000T full duplex mode */
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Full_BIT);
@@ -837,6 +1201,18 @@ static int mlxbf_gige_open(struct net_device *netdev)
/* MAC supports symmetric flow control */
phy_support_sym_pause(phydev);
+#else
+ /* MAC only supports 1000T full duplex mode */
+ phydev->supported &= ~SUPPORTED_1000baseT_Half;
+ phydev->supported &= ~SUPPORTED_100baseT_Full;
+ phydev->supported &= ~SUPPORTED_100baseT_Half;
+ phydev->supported &= ~SUPPORTED_10baseT_Full;
+ phydev->supported &= ~SUPPORTED_10baseT_Half;
+
+ /* MAC supports symmetric flow control */
+ phydev->supported |= SUPPORTED_Pause;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) */
+
phy_start(phydev);
err = phy_start_aneg(phydev);
if (err < 0) {
@@ -844,9 +1220,29 @@ static int mlxbf_gige_open(struct net_device *netdev)
return err;
}
+#ifdef MLXBF_GIGE_INTERNAL
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+ netdev_printk(KERN_DEBUG, netdev, "supported: %*pb, advertising: %*pb,"
+ " speed: 0x%x, duplex: 0x%x, autoneg: 0x%x, pause: 0x%x,"
+ " asym_pause: 0x%x\n",
+ __ETHTOOL_LINK_MODE_MASK_NBITS, phydev->supported,
+ __ETHTOOL_LINK_MODE_MASK_NBITS, phydev->advertising,
+ phydev->speed, phydev->duplex, phydev->autoneg,
+ phydev->pause, phydev->asym_pause);
+#else
+ netdev_printk(KERN_DEBUG, netdev, "supported: 0x%x, advertising: 0x%x,"
+ " speed: 0x%x, duplex: 0x%x, autoneg: 0x%x, pause: 0x%x,"
+ " asym_pause: 0x%x\n",
+ phydev->supported, phydev->advertising, phydev->speed,
+ phydev->duplex, phydev->autoneg, phydev->pause,
+ phydev->asym_pause);
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) */
+#endif /* MLXBF_GIGE_INTERNAL */
+
/* Display information about attached PHY device */
phy_attached_info(phydev);
+#endif /* FAST_MODELS */
/* Set bits in INT_EN that we care about */
int_en = MLXBF_GIGE_INT_EN_HW_ACCESS_ERROR |
@@ -900,14 +1296,21 @@ static int mlxbf_gige_stop(struct net_device *netdev)
{
struct mlxbf_gige *priv = netdev_priv(netdev);
+#ifdef MLXBF_GIGE_INTERNAL
+ netdev_printk(KERN_DEBUG, netdev, "stop: priv=%llx\n",
+ (u64)priv);
+#endif
+
writeq(0, priv->base + MLXBF_GIGE_INT_EN);
netif_stop_queue(netdev);
napi_disable(&priv->napi);
netif_napi_del(&priv->napi);
mlxbf_gige_free_irqs(priv);
+#ifdef FAST_MODELS
phy_stop(netdev->phydev);
phy_disconnect(netdev->phydev);
+#endif /* FAST_MODELS */
mlxbf_gige_rx_deinit(priv);
mlxbf_gige_tx_deinit(priv);
@@ -932,6 +1335,7 @@ static void mlxbf_gige_update_tx_wqe_next(struct mlxbf_gige *priv)
static netdev_tx_t mlxbf_gige_start_xmit(struct sk_buff *skb,
struct net_device *netdev)
{
+#ifndef MLXBF_GIGE_LOOPBACK
struct mlxbf_gige *priv = netdev_priv(netdev);
dma_addr_t tx_buf_dma;
u8 *tx_buf = NULL;
@@ -941,6 +1345,10 @@ static netdev_tx_t mlxbf_gige_start_xmit(struct sk_buff *skb,
/* Check that there is room left in TX ring */
if (!mlxbf_gige_tx_buffs_avail(priv)) {
/* TX ring is full, inform stack but do not free SKB */
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(priv->dev, "%s: TX ring is full, stopping TX queue\n",
+ __func__);
+#endif
netif_stop_queue(netdev);
netdev->stats.tx_dropped++;
return NETDEV_TX_BUSY;
@@ -987,6 +1395,7 @@ static netdev_tx_t mlxbf_gige_start_xmit(struct sk_buff *skb,
wmb();
writeq(priv->tx_pi, priv->base + MLXBF_GIGE_TX_PRODUCER_INDEX);
+#endif
/* Free incoming skb, contents already copied to HW */
dev_kfree_skb(skb);
@@ -997,17 +1406,34 @@ static netdev_tx_t mlxbf_gige_start_xmit(struct sk_buff *skb,
static int mlxbf_gige_do_ioctl(struct net_device *netdev,
struct ifreq *ifr, int cmd)
{
+#ifdef FAST_MODELS
if (!(netif_running(netdev)))
return -EINVAL;
return phy_mii_ioctl(netdev->phydev, ifr, cmd);
+#else
+ return 0;
+
+#endif /* FAST_MODELS*/
}
+#ifdef MLXBF_GIGE_INTERNAL
+static void mlxbf_gige_tx_timeout(struct net_device *netdev)
+{
+ /* TODO - add TX timeout logic */
+}
+#endif
+
static void mlxbf_gige_set_rx_mode(struct net_device *netdev)
{
struct mlxbf_gige *priv = netdev_priv(netdev);
bool new_promisc_enabled;
+#ifdef MLXBF_GIGE_INTERNAL
+ netdev_printk(KERN_DEBUG, netdev, "set_rx_mode: priv=%llx flags=%x\n",
+ (u64)priv, netdev->flags);
+#endif
+
new_promisc_enabled = netdev->flags & IFF_PROMISC;
/* Only write to the hardware registers if the new setting
@@ -1017,8 +1443,16 @@ static void mlxbf_gige_set_rx_mode(struct net_device *netdev)
priv->promisc_enabled = new_promisc_enabled;
if (new_promisc_enabled) {
+#ifdef MLXBF_GIGE_INTERNAL
+ netdev_printk(KERN_DEBUG, netdev,
+ "set_rx_mode: enable promisc\n");
+#endif
mlxbf_gige_enable_promisc(priv);
} else {
+#ifdef MLXBF_GIGE_INTERNAL
+ netdev_printk(KERN_DEBUG, netdev,
+ "set_rx_mode: disable promisc\n");
+#endif
mlxbf_gige_disable_promisc(priv);
}
}
@@ -1032,8 +1466,686 @@ static const struct net_device_ops mlxbf_gige_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_do_ioctl = mlxbf_gige_do_ioctl,
.ndo_set_rx_mode = mlxbf_gige_set_rx_mode,
+#ifdef MLXBF_GIGE_INTERNAL
+ .ndo_tx_timeout = mlxbf_gige_tx_timeout,
+#endif
};
+#ifdef MLXBF_GIGE_INTERNAL
+#ifdef MLXBF_GIGE_MMIO_SYSFS
+static ssize_t mmio_read_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct mlxbf_gige *priv;
+ u64 offset;
+ int cnt;
+
+ priv = dev_get_drvdata(dev);
+
+ cnt = sscanf(buf, "%llx\n", &offset);
+
+ if (cnt != 1) {
+ dev_err(dev, "MMIO read: invalid arguments\n");
+ return len;
+ }
+
+ /* Make sure offset is within MAC block and 8-byte aligned */
+ if (offset <= MLXBF_GIGE_MAC_CFG &&
+ ((offset & 0x7) == 0)) {
+ dev_err(dev,
+ "MMIO read: offset=0x%llx data=0x%llx\n",
+ offset, readq(priv->base + offset));
+ } else {
+ dev_err(dev,
+ "MMIO read: invalid offset 0x%llx\n",
+ offset);
+ }
+
+ return len;
+}
+
+static ssize_t mmio_write_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct mlxbf_gige *priv;
+ u64 offset, data;
+ int cnt;
+
+ priv = dev_get_drvdata(dev);
+
+ cnt = sscanf(buf, "%llx %llx\n", &offset, &data);
+
+ if (cnt != 2) {
+ dev_err(dev, "MMIO write: invalid arguments\n");
+ return len;
+ }
+
+ /* Make sure offset is within MAC block and 8-byte aligned */
+ if (offset <= MLXBF_GIGE_MAC_CFG &&
+ ((offset & 0x7) == 0)) {
+ dev_err(dev,
+ "MMIO write: offset=0x%llx data=0x%llx\n",
+ offset, data);
+ writeq(data, priv->base + offset);
+ } else {
+ dev_err(dev,
+ "MMIO write: invalid offset 0x%llx\n",
+ offset);
+ }
+
+ return len;
+}
+
+static ssize_t llu_mmio_read_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct mlxbf_gige *priv;
+ u64 offset;
+ int cnt;
+
+ priv = dev_get_drvdata(dev);
+
+ cnt = sscanf(buf, "%llx\n", &offset);
+
+ if (cnt != 1) {
+ dev_err(dev, "LLU MMIO read: invalid arguments\n");
+ return len;
+ }
+
+ /* Make sure offset is within LLU and 4-byte aligned */
+ if (offset <= MLXBF_GIGE_LLU_MAX_OFFSET &&
+ ((offset & 0x3) == 0)) {
+ dev_err(dev,
+ "LLU MMIO read: offset=0x%llx data=0x%x\n",
+ offset, readl(priv->llu_base + offset));
+ } else {
+ dev_err(dev,
+ "LLU MMIO read: invalid offset 0x%llx\n",
+ offset);
+ }
+
+ return len;
+}
+
+static ssize_t llu_mmio_write_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct mlxbf_gige *priv;
+ u64 offset;
+ u32 data;
+ int cnt;
+
+ priv = dev_get_drvdata(dev);
+
+ cnt = sscanf(buf, "%llx %x\n", &offset, &data);
+
+ if (cnt != 2) {
+ dev_err(dev, "LLU MMIO write: invalid arguments\n");
+ return len;
+ }
+
+ /* Make sure offset is within LLU and 4-byte aligned */
+ if (offset <= MLXBF_GIGE_LLU_MAX_OFFSET &&
+ ((offset & 0x3) == 0)) {
+ dev_err(dev,
+ "LLU MMIO write: offset=0x%llx data=0x%x\n",
+ offset, data);
+ writel(data, priv->llu_base + offset);
+ } else {
+ dev_err(dev,
+ "LLU MMIO write: invalid offset 0x%llx\n",
+ offset);
+ }
+
+ return len;
+}
+
+static ssize_t plu_mmio_read_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct mlxbf_gige *priv;
+ u64 offset;
+ int cnt;
+
+ priv = dev_get_drvdata(dev);
+
+ cnt = sscanf(buf, "%llx\n", &offset);
+
+ if (cnt != 1) {
+ dev_err(dev, "PLU MMIO read: invalid arguments\n");
+ return len;
+ }
+
+ /* Make sure offset is within PLU and 4-byte aligned */
+ if (offset <= MLXBF_GIGE_PLU_MAX_OFFSET &&
+ ((offset & 0x3) == 0)) {
+ dev_err(dev,
+ "PLU MMIO read: offset=0x%llx data=0x%x\n",
+ offset, readl(priv->plu_base + offset));
+ } else {
+ dev_err(dev,
+ "PLU MMIO read: invalid offset 0x%llx\n",
+ offset);
+ }
+
+ return len;
+}
+
+static ssize_t plu_mmio_write_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct mlxbf_gige *priv;
+ u64 offset;
+ u32 data;
+ int cnt;
+
+ priv = dev_get_drvdata(dev);
+
+ cnt = sscanf(buf, "%llx %x\n", &offset, &data);
+
+ if (cnt != 2) {
+ dev_err(dev, "PLU MMIO write: invalid arguments\n");
+ return len;
+ }
+
+ /* Make sure offset is within PLU and 4-byte aligned */
+ if (offset <= MLXBF_GIGE_PLU_MAX_OFFSET &&
+ ((offset & 0x3) == 0)) {
+ dev_err(dev,
+ "PLU MMIO write: offset=0x%llx data=0x%x\n",
+ offset, data);
+ writel(data, priv->plu_base + offset);
+ } else {
+ dev_err(dev,
+ "PLU MMIO write: invalid offset 0x%llx\n",
+ offset);
+ }
+
+ return len;
+}
+
+DEVICE_ATTR_WO(mmio_read);
+DEVICE_ATTR_WO(mmio_write);
+DEVICE_ATTR_WO(llu_mmio_read);
+DEVICE_ATTR_WO(llu_mmio_write);
+DEVICE_ATTR_WO(plu_mmio_read);
+DEVICE_ATTR_WO(plu_mmio_write);
+#endif /* MLXBF_GIGE_MMIO_SYSFS */
+
+static void oob_dump_tx_wqe(struct device *dev, u64 *tx_wqe_addr)
+{
+ u64 word1, word2;
+
+ /* Sanity check the TX WQE address */
+ if (!tx_wqe_addr)
+ return;
+
+ word1 = *tx_wqe_addr;
+ word2 = *(tx_wqe_addr + 1);
+
+ /* If TX WQE is empty (i.e. both words are 0)
+ * then don't bother displaying WQE details
+ */
+ if (word1 == (u64)0 && word2 == (u64)0) {
+ dev_dbg(dev, "%s(%llx)=%llx %llx", __func__,
+ (u64)tx_wqe_addr, word1, word2);
+ } else {
+ dev_dbg(dev, "%s(%llx)", __func__,
+ (u64)tx_wqe_addr);
+
+ dev_dbg(dev, " buffer addr: %llx\n", word1);
+
+ dev_dbg(dev, " pkt_len: %llx\n",
+ ((word2 & MLXBF_GIGE_TX_WQE_PKT_LEN_MASK)
+ >> MLXBF_GIGE_TX_WQE_PKT_LEN_SHIFT));
+
+ dev_dbg(dev, " update: %llx\n",
+ ((word2 & MLXBF_GIGE_TX_WQE_UPDATE_MASK)
+ >> MLXBF_GIGE_TX_WQE_UPDATE_SHIFT));
+
+ dev_dbg(dev, " cksum_len: %llx\n",
+ ((word2 & MLXBF_GIGE_TX_WQE_CHKSUM_LEN_MASK)
+ >> MLXBF_GIGE_TX_WQE_CHKSUM_LEN_SHIFT));
+
+ dev_dbg(dev, " cksum_start: %llx\n",
+ ((word2 & MLXBF_GIGE_TX_WQE_CHKSUM_START_MASK)
+ >> MLXBF_GIGE_TX_WQE_CHKSUM_START_SHIFT));
+
+ dev_dbg(dev, " cksum_offset: %llx\n",
+ ((word2 & MLXBF_GIGE_TX_WQE_CHKSUM_OFFSET_MASK)
+ >> MLXBF_GIGE_TX_WQE_CHKSUM_OFFSET_SHIFT));
+ }
+}
+
+/* Handler for sysfs entry 'dump_tx' found at
+ * /sys/devices/platform/MLNXBF17:00/
+ * Issue 'cat dump_tx' to invoke this routine
+ */
+static ssize_t dump_tx_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mlxbf_gige *priv;
+ u64 data;
+ int i;
+
+ priv = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "============================================\n");
+
+ dev_dbg(dev, "%s: dev_get_drvdata=%llx\n",
+ __func__, (u64)priv);
+
+ /* Loop through 'n' TX WQE entries */
+ for (i = 0;
+ (priv->netdev->flags & IFF_UP) && (i < priv->tx_q_entries);
+ i++) {
+ u8 *p;
+
+ oob_dump_tx_wqe(dev,
+ (u64 *)((u64)priv->tx_wqe_base +
+ (i * MLXBF_GIGE_TX_WQE_SZ)));
+
+ p = priv->tx_buf[i];
+ dev_dbg(dev, " tx_buf[%d] = %llx\n", i, (u64)priv->tx_buf[i]);
+
+ if (p) {
+ int j;
+
+ for (j = 0;
+ j < (MLXBF_GIGE_NUM_BYTES_IN_PKT_DUMP / 16);
+ j++, p += 16) {
+ dev_dbg(dev, MLXBF_GIGE_MSG_FORMAT,
+ MLXBF_GIGE_MSG_ARGS(p));
+ }
+ }
+ }
+
+ if (priv->netdev->flags & IFF_UP) {
+ dev_dbg(dev, "tx_cc=%llx *tx_cc=%llx\n",
+ (u64)priv->tx_cc, *(u64 *)priv->tx_cc);
+ }
+
+ /* Display TX producer index */
+ data = readq(priv->base + MLXBF_GIGE_TX_PRODUCER_INDEX);
+ dev_dbg(dev, "tx_producer_index=%llx\n", (u64)data);
+
+ /* Display TX consumer index */
+ data = readq(priv->base + MLXBF_GIGE_TX_CONSUMER_INDEX);
+ dev_dbg(dev, "tx_consumer_index=%llx\n", (u64)data);
+
+ /* Display TX status */
+ data = readq(priv->base + MLXBF_GIGE_TX_STATUS);
+ dev_dbg(dev, "tx_status=%llx\n", (u64)data);
+
+ /* Display TX FIFO status */
+ data = readq(priv->base + MLXBF_GIGE_TX_FIFOS_STATUS);
+ dev_dbg(dev, "tx_fifos_status=%llx\n", (u64)data);
+
+ return strlen(buf);
+}
+
+DEVICE_ATTR_RO(dump_tx);
+
+static void oob_dump_rx_wqe(struct device *dev, u64 *rx_wqe_addr)
+{
+ /* Sanity check the RX WQE address */
+ if (!rx_wqe_addr)
+ return;
+
+ dev_dbg(dev, "%s(%llx)=%llx\n", __func__,
+ (u64)rx_wqe_addr, *rx_wqe_addr);
+}
+
+static void oob_dump_rx_cqe(struct device *dev, u64 *rx_cqe_addr)
+{
+ u64 rx_cqe;
+
+ /* Sanity check the RX CQE address */
+ if (!rx_cqe_addr)
+ return;
+
+ rx_cqe = *rx_cqe_addr;
+
+ /* If RX CQE is empty (i.e. value is 0) then
+ * don't bother displaying CQE details
+ */
+ if (rx_cqe == (u64)0) {
+ dev_dbg(dev, "%s(%llx)=%llx", __func__,
+ (u64)rx_cqe_addr, rx_cqe);
+ } else {
+ dev_dbg(dev, "%s(%llx)", __func__,
+ (u64)rx_cqe_addr);
+
+ dev_dbg(dev, " pkt_len: %llx\n",
+ (rx_cqe & MLXBF_GIGE_RX_CQE_PKT_LEN_MASK));
+
+ dev_dbg(dev, " valid: %llx\n",
+ ((rx_cqe & MLXBF_GIGE_RX_CQE_VALID_MASK)
+ >> MLXBF_GIGE_RX_CQE_VALID_SHIFT));
+
+ dev_dbg(dev, " pkt_status: %llx\n",
+ ((rx_cqe & MLXBF_GIGE_RX_CQE_PKT_STATUS_MASK)
+ >> MLXBF_GIGE_RX_CQE_PKT_STATUS_SHIFT));
+
+ dev_dbg(dev, " chksum: %llx\n",
+ ((rx_cqe & MLXBF_GIGE_RX_CQE_CHKSUM_MASK)
+ >> MLXBF_GIGE_RX_CQE_CHKSUM_SHIFT));
+ }
+}
+
+/* Handler for sysfs entry 'dump_rx' found at
+ * /sys/devices/platform/MLNXBF17:00/
+ * Issue 'cat dump_rx' to invoke this routine
+ */
+static ssize_t dump_rx_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct mlxbf_gige *priv;
+ u64 data;
+ int i;
+
+ priv = dev_get_drvdata(dev);
+
+ dev_dbg(dev, "============================================\n");
+ dev_dbg(dev, "%s: dev_get_drvdata=%llx\n", __func__, (u64)priv);
+
+ /* Loop through 'n' RX WQE entries */
+ for (i = 0;
+ (priv->netdev->flags & IFF_UP) && (i < priv->rx_q_entries);
+ i++) {
+ u8 *p;
+
+ oob_dump_rx_wqe(dev, priv->rx_wqe_base + i);
+
+ p = priv->rx_buf[i];
+ dev_dbg(dev, " rx_buf[%d] = %llx\n", i, (u64)priv->rx_buf[i]);
+
+ /* Only display RX buffer contents if not in initial state */
+ if (p && (*p != MLXBF_GIGE_INIT_BYTE_RX_BUF)) {
+ int j;
+
+ for (j = 0;
+ j < (MLXBF_GIGE_NUM_BYTES_IN_PKT_DUMP / 16);
+ j++, p += 16) {
+ dev_dbg(dev, MLXBF_GIGE_MSG_FORMAT,
+ MLXBF_GIGE_MSG_ARGS(p));
+ }
+ }
+ }
+
+ /* Loop through 'n' RX CQE entries */
+ for (i = 0;
+ (priv->netdev->flags & IFF_UP) && (i < priv->rx_q_entries);
+ i++) {
+ oob_dump_rx_cqe(dev, priv->rx_cqe_base + i);
+ }
+
+ /* Display RX WQE producer index */
+ data = readq(priv->base + MLXBF_GIGE_RX_WQE_PI);
+ dev_dbg(dev, "rx_wqe_pi=%llx\n", (u64)data);
+
+ /* Display INT_STATUS */
+ data = readq(priv->base + MLXBF_GIGE_INT_STATUS);
+ dev_dbg(dev, "int_status=%llx\n", (u64)data);
+
+ /* Then, clear INT_STATUS */
+ data = 0x1FF;
+ writeq(data, priv->base + MLXBF_GIGE_INT_STATUS);
+
+ /* Display RX_DIN_DROP_COUNTER */
+ data = readq(priv->base + MLXBF_GIGE_RX_DIN_DROP_COUNTER);
+ dev_dbg(dev, "rx_din_drop_counter=%llx\n", (u64)data);
+
+ /* Display INT_STATUS_EXP */
+ data = readq(priv->base + MLXBF_GIGE_INT_STATUS_EXP);
+ dev_dbg(dev, "int_status_exp=%llx\n", (u64)data);
+
+ /* Then, clear INT_STATUS_EXP */
+ data = 0;
+ writeq(data, priv->base + MLXBF_GIGE_INT_STATUS_EXP);
+
+ /* Display RX_MAC_FILTER_PASS_COUNTER_ALL */
+ data = readq(priv->base + MLXBF_GIGE_RX_PASS_COUNTER_ALL);
+ dev_dbg(dev, "rx_mac_filter_pass_counter_all=%llx\n", (u64)data);
+
+ /* Display RX_MAC_FILTER_DISC_COUNTER_ALL */
+ data = readq(priv->base + MLXBF_GIGE_RX_DISC_COUNTER_ALL);
+ dev_dbg(dev, "rx_mac_filter_disc_counter_all=%llx\n", (u64)data);
+
+ /* Display first word of RX_MAC_FILTER */
+ data = readq(priv->base + MLXBF_GIGE_RX_MAC_FILTER);
+ dev_dbg(dev, "rx_mac_filter0=%llx\n", (u64)data);
+
+ /* Display second word of RX_MAC_FILTER */
+ data = readq(priv->base + MLXBF_GIGE_RX_MAC_FILTER + 0x8);
+ dev_dbg(dev, "rx_mac_filter1=%llx\n", (u64)data);
+
+ /* Display third word of RX_MAC_FILTER */
+ data = readq(priv->base + MLXBF_GIGE_RX_MAC_FILTER + 0x10);
+ dev_dbg(dev, "rx_mac_filter2=%llx\n", (u64)data);
+
+ /* Display fourth word of RX_MAC_FILTER */
+ data = readq(priv->base + MLXBF_GIGE_RX_MAC_FILTER + 0x18);
+ dev_dbg(dev, "rx_mac_filter3=%llx\n", (u64)data);
+
+ /* Display MLXBF_GIGE_RX_CQE_PACKET_CI */
+ data = readq(priv->base + MLXBF_GIGE_RX_CQE_PACKET_CI);
+ dev_dbg(dev, "MLXBF_GIGE_RX_CQE_PACKET_CI=%llx\n", (u64)data);
+
+ dev_dbg(dev, "error_intr_count=%llx\n", priv->error_intr_count);
+ dev_dbg(dev, "rx_intr_count=%llx\n", priv->rx_intr_count);
+ dev_dbg(dev, "llu_plu_intr_count=%llx\n", priv->llu_plu_intr_count);
+
+ /* Display INT_EN */
+ data = readq(priv->base + MLXBF_GIGE_INT_EN);
+ dev_dbg(dev, "int_en=%llx\n", (u64)data);
+
+ /* Display INT_MASK */
+ data = readq(priv->base + MLXBF_GIGE_INT_MASK);
+ dev_dbg(dev, "int_mask=%llx\n", (u64)data);
+
+ return strlen(buf);
+}
+
+DEVICE_ATTR_RO(dump_rx);
+
+/* Handler for sysfs entry 'start_tx' found at
+ * /sys/devices/platform/MLNXBF17:00/
+ * Issue 'echo <N> > start_tx' to invoke this routine
+ * which will send <N> dummy IP packets to GigE port
+ */
+static ssize_t start_tx_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct mlxbf_gige *priv;
+ dma_addr_t tx_buf_dma;
+ u8 oob_tx_data_seed;
+ int oob_tx_pkt_size;
+ long num_pkts = 1;
+ u64 *tx_wqe_addr;
+ u8 *tx_buf;
+ u16 data16;
+ u64 word2;
+ int i, j;
+ int ret;
+
+ priv = dev_get_drvdata(dev);
+
+ oob_tx_pkt_size = MLXBF_GIGE_DEFAULT_TX_PKT_SIZE;
+
+ if (buf) {
+ ret = kstrtol(buf, 10, &num_pkts);
+
+ if (ret == 0) {
+ dev_dbg(dev, "%s: num_pkts %d\n",
+ __func__, (int)num_pkts);
+ }
+ }
+
+ for (i = 0; i < num_pkts; i++) {
+ /* The data seed is used to populate the packet with
+ * fake, but predictable, data. The value of seed
+ * is stored in the first byte after the L2 header,
+ * then (seed+1) is stored in the second byte, etc.
+ */
+ oob_tx_data_seed = priv->tx_data_seed;
+ priv->tx_data_seed += 4;
+
+ /* To limit output only perform debug logging if number
+ * of packets to send is less than some maximum value.
+ */
+ if (num_pkts < MLXBF_GIGE_MAX_TX_PKTS_VERBOSE) {
+ dev_dbg(dev, "%s: size=%x seed=%x\n",
+ __func__, oob_tx_pkt_size,
+ oob_tx_data_seed);
+ }
+
+ /* Allocate ptr for buffer */
+ tx_buf = dma_alloc_coherent(dev, MLXBF_GIGE_DEFAULT_BUF_SZ,
+ &tx_buf_dma, GFP_KERNEL);
+
+ if (!tx_buf)
+ return -ENOMEM;
+
+ if (num_pkts < MLXBF_GIGE_MAX_TX_PKTS_VERBOSE) {
+ dev_dbg(dev, "%s: tx_buf %llx %llx\n",
+ __func__, (u64)tx_buf, (u64)tx_buf_dma);
+ }
+
+ if (num_pkts < MLXBF_GIGE_MAX_TX_PKTS_VERBOSE) {
+ dev_dbg(dev, "%s: pkt num %llx buffer index %x\n",
+ __func__, (u64)priv->tx_pi,
+ (priv->tx_pi % priv->tx_q_entries));
+ }
+
+ priv->tx_buf[priv->tx_pi % priv->tx_q_entries] = tx_buf;
+
+ /* Put in four bytes of fake destination MAC, but use real
+ * value of 'tx_pi' in order to track TX producer index
+ * in the actual packet contents.
+ */
+ *tx_buf++ = MLXBF_GIGE_FAKE_DMAC_BYTE;
+ *tx_buf++ = MLXBF_GIGE_FAKE_DMAC_BYTE;
+ *tx_buf++ = MLXBF_GIGE_FAKE_DMAC_BYTE;
+ *tx_buf++ = MLXBF_GIGE_FAKE_DMAC_BYTE;
+ *tx_buf++ = (priv->tx_pi & 0xFF00) >> 8;
+ *tx_buf++ = (priv->tx_pi & 0xFF);
+
+ /* Put in fake source MAC */
+ *tx_buf++ = MLXBF_GIGE_FAKE_SMAC_BYTE;
+ *tx_buf++ = MLXBF_GIGE_FAKE_SMAC_BYTE;
+ *tx_buf++ = MLXBF_GIGE_FAKE_SMAC_BYTE;
+ *tx_buf++ = MLXBF_GIGE_FAKE_SMAC_BYTE;
+ *tx_buf++ = MLXBF_GIGE_FAKE_SMAC_BYTE;
+ *tx_buf++ = MLXBF_GIGE_FAKE_SMAC_BYTE;
+
+ /* Set ethertype for IP (0x0800) */
+ *tx_buf++ = 0x08;
+ *tx_buf++ = 0x00;
+
+ /* Put in fake packet payload */
+ for (j = 0; j < (oob_tx_pkt_size - ETH_HLEN); j++)
+ *tx_buf++ = (u8)(j + oob_tx_data_seed);
+
+ /* TODO - should really reorganize all low-level TX */
+ /* logic and call it here and in 'xmit' function also */
+
+ /* Get address of TX WQE */
+ tx_wqe_addr = priv->tx_wqe_next;
+
+ if (num_pkts < MLXBF_GIGE_MAX_TX_PKTS_VERBOSE) {
+ dev_dbg(dev, "%s: tx_wqe_addr=%llx\n",
+ __func__, (u64)tx_wqe_addr);
+ }
+
+ mlxbf_gige_update_tx_wqe_next(priv);
+
+ if (num_pkts < MLXBF_GIGE_MAX_TX_PKTS_VERBOSE) {
+ dev_dbg(dev, "%s: tx_wqe_next=%llx\n",
+ __func__, (u64)priv->tx_wqe_next);
+ }
+
+ /* Put PA of buffer address into first 64-bit word of TX WQE */
+ *tx_wqe_addr = tx_buf_dma;
+
+ /* Set TX WQE pkt_len appropriately */
+ word2 = oob_tx_pkt_size & MLXBF_GIGE_TX_WQE_PKT_LEN_MASK;
+
+ if (num_pkts < MLXBF_GIGE_MAX_TX_PKTS_VERBOSE) {
+ dev_dbg(dev, "%s: word2=%llx\n",
+ __func__, (u64)word2);
+ }
+
+ /* Write entire 2nd word of TX WQE */
+ *(tx_wqe_addr + 1) = word2;
+
+ /* Create memory barrier before write to TX PI */
+ wmb();
+
+ priv->tx_pi++;
+
+ writeq(priv->tx_pi, priv->base + MLXBF_GIGE_TX_PRODUCER_INDEX);
+
+ if (priv->tx_pi >= 0x20) {
+ data16 = readq(priv->base + MLXBF_GIGE_RX_WQE_PI) + 1;
+ writeq(data16, priv->base + MLXBF_GIGE_RX_WQE_PI);
+ }
+ } /* end - i loop */
+
+ return len;
+}
+
+DEVICE_ATTR_WO(start_tx);
+
+void mlxbf_gige_create_sysfs(struct device *dev)
+{
+#ifdef MLXBF_GIGE_MMIO_SYSFS
+ if (device_create_file(dev, &dev_attr_mmio_read))
+ dev_info(dev, "failed to create mmio_read sysfs entry\n");
+ if (device_create_file(dev, &dev_attr_mmio_write))
+ dev_info(dev, "failed to create mmio_write sysfs entry\n");
+ if (device_create_file(dev, &dev_attr_llu_mmio_read))
+ dev_info(dev, "failed to create llu_mmio_read sysfs entry\n");
+ if (device_create_file(dev, &dev_attr_llu_mmio_write))
+ dev_info(dev, "failed to create llu_mmio_write sysfs entry\n");
+ if (device_create_file(dev, &dev_attr_plu_mmio_read))
+ dev_info(dev, "failed to create plu_mmio_read sysfs entry\n");
+ if (device_create_file(dev, &dev_attr_plu_mmio_write))
+ dev_info(dev, "failed to create plu_mmio_write sysfs entry\n");
+#endif
+
+ if (device_create_file(dev, &dev_attr_dump_rx))
+ dev_info(dev, "failed to create dump_rx sysfs entry\n");
+ if (device_create_file(dev, &dev_attr_dump_tx))
+ dev_info(dev, "failed to create dump_tx sysfs entry\n");
+ if (device_create_file(dev, &dev_attr_start_tx))
+ dev_info(dev, "failed to create start_tx sysfs entry\n");
+}
+
+void mlxbf_gige_remove_sysfs(struct device *dev)
+{
+#ifdef MLXBF_GIGE_MMIO_SYSFS
+ device_remove_file(dev, &dev_attr_mmio_read);
+ device_remove_file(dev, &dev_attr_mmio_write);
+ device_remove_file(dev, &dev_attr_llu_mmio_read);
+ device_remove_file(dev, &dev_attr_llu_mmio_write);
+ device_remove_file(dev, &dev_attr_plu_mmio_read);
+ device_remove_file(dev, &dev_attr_plu_mmio_write);
+#endif
+
+ device_remove_file(dev, &dev_attr_dump_rx);
+ device_remove_file(dev, &dev_attr_dump_tx);
+ device_remove_file(dev, &dev_attr_start_tx);
+}
+#endif /* MLXBF_GIGE_INTERNAL */
+
static u64 mlxbf_gige_mac_to_u64(u8 *addr)
{
u64 mac = 0;
@@ -1068,11 +2180,18 @@ static void mlxbf_gige_initial_mac(struct mlxbf_gige *priv)
if (is_valid_ether_addr(mac)) {
ether_addr_copy(priv->netdev->dev_addr, mac);
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_info(priv->dev, "Read MAC address %pM from chip\n", mac);
+#endif
} else {
/* Provide a random MAC if for some reason the device has
* not been configured with a valid MAC address already.
*/
eth_hw_addr_random(priv->netdev);
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_info(priv->dev, "Generated random MAC address %pM\n",
+ priv->netdev->dev_addr);
+#endif
}
local_mac = mlxbf_gige_mac_to_u64(priv->netdev->dev_addr);
@@ -1093,10 +2212,22 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
u64 control;
int err = 0;
+#ifdef MLXBF_GIGE_INTERNAL
+ u64 exp_data;
+
+ dev_dbg(&pdev->dev, "probe: pdev=0x%llx pdev->dev=0x%llx\n",
+ (u64)pdev, (u64)&pdev->dev);
+#endif
+
mac_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_MAC);
if (!mac_res)
return -ENXIO;
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(&pdev->dev, "probe: resource %d (MAC) start=0x%llx end=0x%llx\n",
+ MLXBF_GIGE_RES_MAC, mac_res->start, mac_res->end);
+#endif
+
base = devm_ioremap_resource(&pdev->dev, mac_res);
if (IS_ERR(base))
return PTR_ERR(base);
@@ -1105,6 +2236,11 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
if (!llu_res)
return -ENXIO;
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(&pdev->dev, "probe: resource %d (LLU) start=0x%llx end=0x%llx\n",
+ MLXBF_GIGE_RES_LLU, llu_res->start, llu_res->end);
+#endif
+
llu_base = devm_ioremap_resource(&pdev->dev, llu_res);
if (IS_ERR(llu_base))
return PTR_ERR(llu_base);
@@ -1113,10 +2249,26 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
if (!plu_res)
return -ENXIO;
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(&pdev->dev, "probe: resource %d (PLU) start=0x%llx end=0x%llx\n",
+ MLXBF_GIGE_RES_PLU, plu_res->start, plu_res->end);
+#endif
+
plu_base = devm_ioremap_resource(&pdev->dev, plu_res);
if (IS_ERR(plu_base))
return PTR_ERR(plu_base);
+#ifdef MLXBF_GIGE_INTERNAL
+ /* Read single MMIO register and compare to expected value */
+ exp_data = (MLXBF_GIGE_CONFIG_MAX_PKT_SZ_RESET_VAL
+ << MLXBF_GIGE_CONFIG_MAX_PKT_SZ_SHIFT);
+ if (readq(base + MLXBF_GIGE_CONFIG) != exp_data) {
+ dev_err(&pdev->dev,
+ "probe failed, unexpected value in MLXBF_GIGE_CONFIG\n");
+ return -ENODEV;
+ }
+#endif
+
/* Perform general init of GigE block */
control = readq(base + MLXBF_GIGE_CONTROL);
control |= MLXBF_GIGE_CONTROL_PORT_EN;
@@ -1124,9 +2276,16 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
netdev = devm_alloc_etherdev(&pdev->dev, sizeof(*priv));
if (!netdev) {
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_err(&pdev->dev, "Failed to allocate etherdev\n");
+#endif
return -ENOMEM;
}
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(&pdev->dev, "probe: netdev=%llx\n", (u64)netdev);
+#endif
+
SET_NETDEV_DEV(netdev, &pdev->dev);
netdev->netdev_ops = &mlxbf_gige_netdev_ops;
netdev->ethtool_ops = &mlxbf_gige_ethtool_ops;
@@ -1140,21 +2299,47 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
priv->dev = &pdev->dev;
priv->pdev = pdev;
+#ifdef FAST_MODELS
+ /*
+ * TODO: Palladium has no connection to the PHY hardware, so
+ * the MDIO probe will fail.
+ * This needs to be removed once palladium provides a connection
+ * to the PHY device.
+ */
+
/* Attach MDIO device */
err = mlxbf_gige_mdio_probe(pdev, priv);
if (err)
return err;
+#endif /* FAST_MODELS */
priv->base = base;
priv->llu_base = llu_base;
priv->plu_base = plu_base;
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(&pdev->dev, "probe: priv=0x%llx priv->base=0x%llx\n",
+ (u64)priv, (u64)priv->base);
+ dev_dbg(&pdev->dev, "probe: llu_base=0x%llx plu_base=0x%llx\n",
+ (u64)priv->llu_base, (u64)priv->plu_base);
+
+ /* Perform some self tests on MAC, PLU, LLU */
+ mlxbf_gige_selftests(pdev, priv);
+ mlxbf_gige_plu_selftests(pdev, priv);
+ mlxbf_gige_llu_selftests(pdev, priv);
+#endif
+
priv->rx_q_entries = MLXBF_GIGE_DEFAULT_RXQ_SZ;
priv->tx_q_entries = MLXBF_GIGE_DEFAULT_TXQ_SZ;
/* Write initial MAC address to hardware */
mlxbf_gige_initial_mac(priv);
+#ifdef MLXBF_GIGE_INTERNAL
+ /* Create sysfs entries for driver */
+ mlxbf_gige_create_sysfs(&pdev->dev);
+#endif
+
err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
if (err) {
dev_err(&pdev->dev, "DMA configuration failed: 0x%x\n", err);
@@ -1165,12 +2350,23 @@ static int mlxbf_gige_probe(struct platform_device *pdev)
priv->rx_irq = platform_get_irq(pdev, MLXBF_GIGE_RECEIVE_PKT_INTR_IDX);
priv->llu_plu_irq = platform_get_irq(pdev, MLXBF_GIGE_LLU_PLU_INTR_IDX);
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(&pdev->dev, "probe: irq[] = %d %d %d\n",
+ priv->error_irq, priv->rx_irq, priv->llu_plu_irq);
+#endif
+
err = register_netdev(netdev);
if (err) {
dev_err(&pdev->dev, "Failed to register netdev\n");
return err;
}
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_info(&pdev->dev, "probed\n");
+
+ priv->tx_data_seed = 0xB0;
+#endif
+
return 0;
}
@@ -1179,12 +2375,23 @@ static int mlxbf_gige_remove(struct platform_device *pdev)
{
struct mlxbf_gige *priv;
+#ifdef MLXBF_GIGE_INTERNAL
+ dev_dbg(&pdev->dev, "remove: pdev=%llx\n", (u64)pdev);
+#endif
+
priv = platform_get_drvdata(pdev);
unregister_netdev(priv->netdev);
+#ifdef MLXBF_GIGE_INTERNAL
+ /* Remove driver sysfs entries */
+ mlxbf_gige_remove_sysfs(&pdev->dev);
+#endif
+
+#ifdef FAST_MODELS
/* Remove mdio */
mlxbf_gige_mdio_remove(priv);
+#endif /* FAST_MODELS */
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h
index ff490c70fff1..4aeb6e45579e 100644
--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h
+++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h
@@ -8,8 +8,16 @@
#ifndef __MLXBF_GIGE_REGS_H__
#define __MLXBF_GIGE_REGS_H__
+#ifdef MLXBF_GIGE_INTERNAL
+#define MLXBF_GIGE_CONFIG 0x0008
+#define MLXBF_GIGE_CONFIG_MAX_PKT_SZ_SHIFT 16
+#define MLXBF_GIGE_CONFIG_MAX_PKT_SZ_RESET_VAL 1522
+#endif /* MLXBF_GIGE_INTERNAL */
#define MLXBF_GIGE_STATUS 0x0010
#define MLXBF_GIGE_STATUS_READY BIT(0)
+#ifdef MLXBF_GIGE_INTERNAL
+#define MLXBF_GIGE_SCRATCHPAD 0x0020
+#endif /* MLXBF_GIGE_INTERNAL */
#define MLXBF_GIGE_INT_STATUS 0x0028
#define MLXBF_GIGE_INT_STATUS_RX_RECEIVE_PACKET BIT(0)
#define MLXBF_GIGE_INT_STATUS_RX_MAC_ERROR BIT(1)
@@ -50,11 +58,17 @@
#define MLXBF_GIGE_RX_MAC_FILTER 0x0240
#define MLXBF_GIGE_RX_MAC_FILTER_STRIDE 0x0008
#define MLXBF_GIGE_RX_DIN_DROP_COUNTER 0x0260
+#ifdef MLXBF_GIGE_INTERNAL
+#define MLXBF_GIGE_INT_STATUS_EXP 0x0308
+#endif /* MLXBF_GIGE_INTERNAL */
#define MLXBF_GIGE_TX_CONSUMER_INDEX 0x0310
#define MLXBF_GIGE_TX_CONTROL 0x0318
#define MLXBF_GIGE_TX_CONTROL_GRACEFUL_STOP BIT(0)
#define MLXBF_GIGE_TX_STATUS 0x0388
#define MLXBF_GIGE_TX_STATUS_DATA_FIFO_FULL BIT(1)
+#ifdef MLXBF_GIGE_INTERNAL
+#define MLXBF_GIGE_TX_FIFOS_STATUS 0x0390
+#endif /* MLXBF_GIGE_INTERNAL */
#define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_START 0x0520
#define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_END 0x0528
#define MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC 0x0540
@@ -69,5 +83,9 @@
#define MLXBF_GIGE_RX_DMA_EN BIT(0)
#define MLXBF_GIGE_RX_CQE_PACKET_CI 0x05b0
#define MLXBF_GIGE_MAC_CFG 0x05e8
+#ifdef MLXBF_GIGE_INTERNAL
+#define MLXBF_GIGE_LLU_MAX_OFFSET 0xa0fc
+#define MLXBF_GIGE_PLU_MAX_OFFSET 0x10fc
+#endif /* MLXBF_GIGE_INTERNAL */
#endif /* !defined(__MLXBF_GIGE_REGS_H__) */
--
2.30.1
More information about the kernel-team
mailing list