From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qk1-f169.google.com (mail-qk1-f169.google.com [209.85.222.169]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0274E2FE05B for ; Sun, 1 Mar 2026 11:06:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.169 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772363178; cv=none; b=GlNOTlHZY02UZD0VnrFaan+hyRYS9AhT7mq7O2/8k7ypBoxF6F3MLvGqEyjvFxHPG8tiHp99ayOwcJM9I2ct5FOLPol2DBSKtX97xtFSg/CpBqUC3mh6L3b712IePV0twsYHpT/KR0EP3GwJXdrHkVv/DiTK84Zr6aJDNgh8TFo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772363178; c=relaxed/simple; bh=s0OEadwKsZ5uB72903eG5RUc45bWVph/h/bYOTTGRO0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=iPM+uv14i9QOT0IDGJN0upR2qYp91ab9d/uDcNvcnEf/cFLXZMbkP4w9OirmnERYascNlMeB7iSkV1xCCSeLYUmu1c8YwodRuVeHZ7iv2s7YjdRpkCOfMPLp8KVb1VVboJTcHszEiHeG90By9mtRW9xRfO8jNllLw0hDnQA5LU4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=SwktBchL; arc=none smtp.client-ip=209.85.222.169 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="SwktBchL" Received: by mail-qk1-f169.google.com with SMTP id af79cd13be357-8ca01dc7d40so378192485a.1 for ; Sun, 01 Mar 2026 03:06:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772363176; x=1772967976; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ZwG8pm1dGdxVJroX0vDelpeAdI8P+haKbzJ+FGu2QUU=; b=SwktBchLd0pJgIbEVxytKjgDvqS5byduilKNrFRS/pts2D5HCM6Nj7OdgJ+YeDyROL 5Gjg0ZkjTySUnVz+R8HIlY3CA6LUQLomV9JZyqPDj0dRM3JO/w8G3eKLesw4qtXTYjlf DHYjZETyU6F0dq+eFt3XqDQB3jHu8c1rShxOk99DgvunU66qx15dm7gi9EUY5se8d6Hg VbxzmcMC0PzmPEFEDIgiwS/4lAIolNgL1Q9QC9j3hb7ctq00PVyH02YUGJKrXjLfRsqT bEr0HorpKK+28TJooznQ6IKo+gAgPUCpvvik5IG4uoWMYjc/4qRBss8LNL8WZ8+uA75t Q2ng== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772363176; x=1772967976; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=ZwG8pm1dGdxVJroX0vDelpeAdI8P+haKbzJ+FGu2QUU=; b=usGjvghcbeI7xMN0S4gAK2+NRwG723TJlWlBNls3Rv6Lc45XZSs7ViZK6GxI39V3Be P14Veybfe1l/t0zUx+C4O+90QVIVXLIjr6u5X6d3vVsNKwspw/ZYaWBW3ZN0/5Ev3KXl d2lE2EOrCo3lft1ISzdUNo3HwZIIiPklxqSEfEpWHQCW8RAuqyWcJX5R4oj/lzzYMDz7 vEVzlNY+EbxjdAryEU0FV9JDyuHna+OCG3WYDXiigNym2sK8FyCondDCVpe3RpIaW4Sb Avta8vLSZyOX4Ge5SvQp4M2wu8+kV1Y5fjRvp+fvtEWXWtcOhrGsCJV/Um834wVI9PXg KdrQ== X-Forwarded-Encrypted: i=1; AJvYcCUokqmlKU4C+WcbIoP8N8nnwUJ1dWiD97P0+d/Q4x1T4E4J8LfR8HpAc2Ma1EWDpsU/PVS6NSRxSRR2/wY=@vger.kernel.org X-Gm-Message-State: AOJu0Yz9EKGocFt3oSNAgV47tXer6IGXs9qVsYheYndRHZozSORvc3SU OOWj/LJCXXoZdHcCiIBqQWom5zF0Qa0HnklD997Ifz2xTWRVkA88H5It X-Gm-Gg: ATEYQzwQSXKE0lFARF07yPMdGDJ0teNsrlSIn/VMhRhtiN9Mj3/5H39VgRnojdzIEnB N3CTJ8mBNcVR5pgptPqu0t8o1Js5J2BU4U6kh53ZHShkkSZ/A3zlQtt7o5bmJlqJhCUoBBWP5UZ lQWAYA88/a7pkrfIFqS6khXlds+AJD35UW+yVVg05JiugGUnNhbGOmuEQFZ0vB6ldVvrBbQoKG3 Ap19ObCivqmOezpvoZc2yfVkBlQZkC8MNynjitQ8ABbC8n3lmYXGNlmF3XxX8eavKJ3ut4WgI3z Acm44x+FnkYb0EkDoMcnKa1QnB3pCHEOmKfZ55BS5lmpcqRIrKH4ZsxNO/xb//cHMyivEqv3uZ0 O3nBfpfUoof7polXKmkYh1ZmTI8myVbcazjBJK84ddzIYL9fsNNgeYpNHSY7HSA8wap+VJNZMo1 KGRlek9klwavyhh9b3WadPgZsUJLBjUs9C8OXTSKFg6BXhRBGfGpvy/NzkHq8QH07v7ZKB3Pazy MzDpSY3y8u1nmNN X-Received: by 2002:a05:620a:298d:b0:8cb:4b07:c42f with SMTP id af79cd13be357-8cbc8f673c3mr958439085a.82.1772363175751; Sun, 01 Mar 2026 03:06:15 -0800 (PST) Received: from PF5YBGDS.localdomain (70.15.25.19.res-cmts.sm3.ptd.net. [70.15.25.19]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-899c716caebsm83888876d6.15.2026.03.01.03.06.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 01 Mar 2026 03:06:15 -0800 (PST) From: mike.marciniszyn@gmail.com To: Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Simon Horman , Russell King , Jacob Keller , Lee Trager , Mohsin Bashir , Dan Carpenter , Pei Xiao , Stanislav Fomichev , Kuniyuki Iwashima , Samiullah Khawaja , Hangbin Liu Cc: mike.marciniszyn@gmail.com, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2.2 2/5] eth fbnic: Add register self test Date: Sun, 1 Mar 2026 06:06:03 -0500 Message-ID: <20260301110606.3739-3-mike.marciniszyn@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260301110606.3739-1-mike.marciniszyn@gmail.com> References: <20260301110606.3739-1-mike.marciniszyn@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: "Mike Marciniszyn (Meta)" The register test will be used to verify hardware is behaving as expected. The test itself will have us writing to registers that should have no side effects due to us resetting after the test has been completed. While the test is being run the interface should be offline. This patch counts on the first patch of this series to export netif_open() and also ensures that the half close calls netif_close() to avoid deadlock. Signed-off-by: Mike Marciniszyn (Meta) --- v2 - add enum for test return codes - place forward of struct fbnic_dev after include with a blank line drivers/net/ethernet/meta/fbnic/fbnic.h | 18 +++ drivers/net/ethernet/meta/fbnic/fbnic_csr.c | 128 ++++++++++++++++++ drivers/net/ethernet/meta/fbnic/fbnic_csr.h | 19 +++ .../net/ethernet/meta/fbnic/fbnic_ethtool.c | 50 +++++++ 3 files changed, 197 insertions(+) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.c b/drivers/net/ethernet/meta/fbnic/fbnic_csr.c index d9c0dc1c2af9..dc62d623e37c 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_csr.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.c @@ -147,3 +147,131 @@ int fbnic_csr_regs_len(struct fbnic_dev *fbd) return len; } + +/* CSR register test data + * + * The register test will be used to verify hardware is behaving as expected. + * + * The test itself will have us writing to registers that should have no + * side effects due to us resetting after the test has been completed. + * While the test is being run the interface should be offline. + */ +struct fbnic_csr_reg_test_data { + int reg; + u16 reg_offset; + u8 array_len; + u32 read; + u32 write; +}; + +#define FBNIC_QUEUE_REG_TEST(_name, _read, _write) { \ + .reg = FBNIC_QUEUE(0) + FBNIC_QUEUE_##_name, \ + .reg_offset = FBNIC_QUEUE_STRIDE, \ + .array_len = 64, \ + .read = _read, \ + .write = _write \ +} + +static const struct fbnic_csr_reg_test_data pattern_test[] = { + FBNIC_QUEUE_REG_TEST(TWQ0_CTL, FBNIC_QUEUE_TWQ_CTL_RESET, + FBNIC_QUEUE_TWQ_CTL_RESET), + FBNIC_QUEUE_REG_TEST(TWQ0_PTRS, 0, ~0), + FBNIC_QUEUE_REG_TEST(TWQ0_SIZE, FBNIC_QUEUE_TWQ_SIZE_MASK, ~0), + FBNIC_QUEUE_REG_TEST(TWQ0_BAL, FBNIC_QUEUE_BAL_MASK, ~0), + FBNIC_QUEUE_REG_TEST(TWQ0_BAH, ~0, ~0), + FBNIC_QUEUE_REG_TEST(TWQ1_CTL, FBNIC_QUEUE_TWQ_CTL_RESET, + FBNIC_QUEUE_TWQ_CTL_RESET), + FBNIC_QUEUE_REG_TEST(TWQ1_PTRS, 0, ~0), + FBNIC_QUEUE_REG_TEST(TWQ1_SIZE, FBNIC_QUEUE_TWQ_SIZE_MASK, ~0), + FBNIC_QUEUE_REG_TEST(TWQ1_BAL, FBNIC_QUEUE_BAL_MASK, ~0), + FBNIC_QUEUE_REG_TEST(TWQ1_BAH, ~0, ~0), + FBNIC_QUEUE_REG_TEST(TCQ_CTL, FBNIC_QUEUE_TCQ_CTL_RESET, + FBNIC_QUEUE_TCQ_CTL_RESET), + FBNIC_QUEUE_REG_TEST(TCQ_PTRS, 0, ~0), + FBNIC_QUEUE_REG_TEST(TCQ_SIZE, FBNIC_QUEUE_TCQ_SIZE_MASK, ~0), + FBNIC_QUEUE_REG_TEST(TCQ_BAL, FBNIC_QUEUE_BAL_MASK, ~0), + FBNIC_QUEUE_REG_TEST(TCQ_BAH, ~0, ~0), + FBNIC_QUEUE_REG_TEST(RCQ_CTL, FBNIC_QUEUE_RCQ_CTL_RESET, + FBNIC_QUEUE_RCQ_CTL_RESET), + FBNIC_QUEUE_REG_TEST(RCQ_PTRS, 0, ~0), + FBNIC_QUEUE_REG_TEST(RCQ_SIZE, FBNIC_QUEUE_RCQ_SIZE_MASK, ~0), + FBNIC_QUEUE_REG_TEST(RCQ_BAL, FBNIC_QUEUE_BAL_MASK, ~0), + FBNIC_QUEUE_REG_TEST(RCQ_BAH, ~0, ~0), + FBNIC_QUEUE_REG_TEST(BDQ_CTL, FBNIC_QUEUE_BDQ_CTL_RESET, + FBNIC_QUEUE_BDQ_CTL_RESET), + FBNIC_QUEUE_REG_TEST(BDQ_HPQ_PTRS, 0, ~0), + FBNIC_QUEUE_REG_TEST(BDQ_HPQ_SIZE, FBNIC_QUEUE_BDQ_SIZE_MASK, ~0), + FBNIC_QUEUE_REG_TEST(BDQ_HPQ_BAL, FBNIC_QUEUE_BAL_MASK, ~0), + FBNIC_QUEUE_REG_TEST(BDQ_HPQ_BAH, ~0, ~0), + FBNIC_QUEUE_REG_TEST(BDQ_PPQ_PTRS, 0, ~0), + FBNIC_QUEUE_REG_TEST(BDQ_PPQ_SIZE, FBNIC_QUEUE_BDQ_SIZE_MASK, ~0), + FBNIC_QUEUE_REG_TEST(BDQ_PPQ_BAL, FBNIC_QUEUE_BAL_MASK, ~0), + FBNIC_QUEUE_REG_TEST(BDQ_PPQ_BAH, ~0, ~0), +}; + +static enum fbnic_reg_self_test_codes +fbnic_csr_reg_pattern_test(struct fbnic_dev *fbd, int index, + const struct fbnic_csr_reg_test_data *test_data) +{ + static const u32 pattern[] = { ~0, 0x5A5A5A5A, 0xA5A5A5A5, 0}; + enum fbnic_reg_self_test_codes reg; + int i; + + reg = test_data->reg + test_data->reg_offset * index; + for (i = 0; i < ARRAY_SIZE(pattern); i++) { + u32 val = pattern[i] & test_data->write; + u32 result; + + wr32(fbd, reg, val); + result = rd32(fbd, reg); + val &= test_data->read; + + if (result == val) + continue; + + dev_err(fbd->dev, + "%s: reg 0x%06X failed, expected 0x%08X received 0x%08X\n", + __func__, reg, val, result); + + /* Note that FBNIC_INTR_STATUS(0) could be tested and fail + * and the result would not be reported since the register + * offset is 0. However as that register isn't included in + * the register test that isn't an issue. + */ + return reg; + } + + return FBNIC_REG_TEST_SUCCESS; +} + +/** + * fbnic_csr_regs_test() - Verify behavior of NIC registers + * @fbd: device to test + * + * This function is meant to test the bit values of various registers in + * the NIC device. Specifically this test will verify which bits are + * writable and which ones are not. It will write varying patterns of bits + * to the registers testing for sticky bits, or bits that are writable but + * should not be. + * + * Return: FBNIC_REG_TEST_SUCCESS on success, register number on failure + **/ +enum fbnic_reg_self_test_codes fbnic_csr_regs_test(struct fbnic_dev *fbd) +{ + const struct fbnic_csr_reg_test_data *test_data; + + for (test_data = pattern_test; + test_data < pattern_test + ARRAY_SIZE(pattern_test); test_data++) { + u32 i; + + for (i = 0; i < test_data->array_len; i++) { + enum fbnic_reg_self_test_codes reg = + fbnic_csr_reg_pattern_test(fbd, i, test_data); + + if (reg) + return reg; + } + } + + return FBNIC_REG_TEST_SUCCESS; +} diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h index b717db879cd3..7cfb42067327 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h @@ -6,6 +6,8 @@ #include +struct fbnic_dev; + #define CSR_BIT(nr) (1u << (nr)) #define CSR_GENMASK(h, l) GENMASK(h, l) @@ -1210,4 +1212,21 @@ enum{ FBNIC_CSR_VERSION_V1_0_ASIC = 1, }; +/** + * enum fbnic_reg_self_test_codes - return codes from self test routines + * + * This is the code that is returned from the register self test + * routines. + * + * The test either returns success or the register number + * that failed during the test. + * + * @FBNIC_REG_TEST_SUCCESS: no errors + */ +enum fbnic_reg_self_test_codes { + FBNIC_REG_TEST_SUCCESS = 0, +}; + +enum fbnic_reg_self_test_codes fbnic_csr_regs_test(struct fbnic_dev *fbd); + #endif /* _FBNIC_CSR_H_ */ diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c index 11745a2d8a44..2e882dbd408d 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c @@ -126,6 +126,16 @@ static const struct fbnic_stat fbnic_gstrings_xdp_stats[] = { #define FBNIC_STATS_LEN \ (FBNIC_HW_STATS_LEN + FBNIC_XDP_STATS_LEN * FBNIC_MAX_XDPQS) +enum fbnic_self_test_results { + TEST_REG = 0, +}; + +static const char fbnic_gstrings_self_test[][ETH_GSTRING_LEN] = { + [TEST_REG] = "Register test (offline)", +}; + +#define FBNIC_TEST_LEN ARRAY_SIZE(fbnic_gstrings_self_test) + static void fbnic_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { @@ -475,6 +485,10 @@ static void fbnic_get_strings(struct net_device *dev, u32 sset, u8 *data) for (i = 0; i < FBNIC_MAX_XDPQS; i++) fbnic_get_xdp_queue_strings(&data, i); break; + case ETH_SS_TEST: + memcpy(data, fbnic_gstrings_self_test, + sizeof(fbnic_gstrings_self_test)); + break; } } @@ -566,6 +580,8 @@ static int fbnic_get_sset_count(struct net_device *dev, int sset) switch (sset) { case ETH_SS_STATS: return FBNIC_STATS_LEN; + case ETH_SS_TEST: + return FBNIC_TEST_LEN; default: return -EOPNOTSUPP; } @@ -1475,6 +1491,39 @@ fbnic_remove_rxfh_context(struct net_device *netdev, return 0; } +static int fbnic_ethtool_regs_test(struct net_device *netdev, u64 *data) +{ + struct fbnic_net *fbn = netdev_priv(netdev); + struct fbnic_dev *fbd = fbn->fbd; + + *data = fbnic_csr_regs_test(fbd); + + return !!*data; +} + +static void fbnic_self_test(struct net_device *netdev, + struct ethtool_test *eth_test, u64 *data) +{ + bool if_running = netif_running(netdev); + + if (!(eth_test->flags & ETH_TEST_FL_OFFLINE)) { + data[TEST_REG] = 0; + return; + } + + if (if_running) + netif_close(netdev); + + if (fbnic_ethtool_regs_test(netdev, &data[TEST_REG])) + eth_test->flags |= ETH_TEST_FL_FAILED; + + if (if_running && netif_open(netdev, NULL)) { + netdev_err(netdev, + "Failed to re-initialize hardware following test\n"); + eth_test->flags |= ETH_TEST_FL_FAILED; + } +} + static void fbnic_get_channels(struct net_device *netdev, struct ethtool_channels *ch) { @@ -1893,6 +1942,7 @@ static const struct ethtool_ops fbnic_ethtool_ops = { .get_pause_stats = fbnic_get_pause_stats, .get_pauseparam = fbnic_phylink_get_pauseparam, .set_pauseparam = fbnic_phylink_set_pauseparam, + .self_test = fbnic_self_test, .get_strings = fbnic_get_strings, .get_ethtool_stats = fbnic_get_ethtool_stats, .get_sset_count = fbnic_get_sset_count, -- 2.43.0