From patchwork Fri Jul 9 19:08:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Asmaa Mnebhi X-Patchwork-Id: 1503340 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GM2mQ1vlqz9sX2; Sat, 10 Jul 2021 05:10:14 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1m1vt3-00042v-Ok; Fri, 09 Jul 2021 19:10:09 +0000 Received: from mail-il-dmz.mellanox.com ([193.47.165.129] helo=mellanox.co.il) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1m1vrx-0003G6-6G for kernel-team@lists.ubuntu.com; Fri, 09 Jul 2021 19:09:01 +0000 Received: from Internal Mail-Server by MTLPINE1 (envelope-from asmaa@mellanox.com) with SMTP; 9 Jul 2021 22:08:58 +0300 Received: from farm-0002.mtbu.labs.mlnx (farm-0002.mtbu.labs.mlnx [10.15.2.32]) by mtbu-labmailer.labs.mlnx (8.14.4/8.14.4) with ESMTP id 169J8wce030253; Fri, 9 Jul 2021 15:08:58 -0400 Received: (from asmaa@localhost) by farm-0002.mtbu.labs.mlnx (8.14.7/8.13.8/Submit) id 169J8wvO005473; Fri, 9 Jul 2021 15:08:58 -0400 From: Asmaa Mnebhi To: kernel-team@lists.ubuntu.com Subject: [SRU][F][PULL][PATCH v2 20/23] Revert "UBUNTU: SAUCE: Remove built-in tests from mlxbf_gige driver" Date: Fri, 9 Jul 2021 15:08:27 -0400 Message-Id: <20210709190830.5405-21-asmaa@nvidia.com> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210709190830.5405-1-asmaa@nvidia.com> References: <20210709190830.5405-1-asmaa@nvidia.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: asmaa@nvidia.com, davthompson@nvidia.com Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/1934923 This reverts commit 4dd38f4ed12f5ec4f612a73623b4ac39b710b62d. Signed-off-by: Asmaa Mnebhi --- .../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 #include +/* 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 #include #include @@ -14,18 +17,240 @@ #include #include +/* 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 +/* + * 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 > 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 > start_tx' to invoke this routine + * which will send 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__) */