From nobody Thu Apr 9 16:33:38 2026 Received: from mail-qk1-f176.google.com (mail-qk1-f176.google.com [209.85.222.176]) (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 A5DE133AD82 for ; Sat, 7 Mar 2026 10:58:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772881134; cv=none; b=XCNESgJgMBc+eJ8uQgiN4hJlh1UFgWJarXIRg2EJOnI1lMjrBrLSx5u6RxneASpHku2s742ZMA0npkGVp1IzFUWVQ2U8dpPHUoajqcammkU0+CiMLkEn8HvAK9LqksyAgUkTnkTX0gFy5rENS+76Vt8vv+JEZOoqX7pHj381MpA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772881134; c=relaxed/simple; bh=93TQgJ8fwIHqNzuPGnTauQWb0Q4gUaZfsNNvvAc162s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=t4KgtBr9emafWsbNlSioQKXJ7mK5YSTvTssuzVcp0nCMusvR407QtO0qOC7cjnxTWn++TP3F5Zf9TFVP+SGubwKNc31Xm0KBFN0yu7IDmPL3DCHmgK+vpz2vNVzMMEv71oD0J5T9lFruUL1M3ySpOMy61xlzwmH9bEzDsYsBnM8= 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=fzwcV/An; arc=none smtp.client-ip=209.85.222.176 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="fzwcV/An" Received: by mail-qk1-f176.google.com with SMTP id af79cd13be357-8cd767d2d70so62197785a.3 for ; Sat, 07 Mar 2026 02:58:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772881132; x=1773485932; 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=+bJqlJHeOUmKAaYm1Xbyn5/BnRtTCsqfQBFGOZH+2Y8=; b=fzwcV/An2OmjpEAYf3cQlM81ZylnZ8Hqp+md6TOroRbXs/covEr3edpNtnc+r3iRsB rDUEgoIo5UdDHVX2tg3x/tKd2OKNq970KkDqyFiI6g0GR1ew02UGEVpe76tGXUWxAXcQ Ry4uKKZT+3SaZ5go3oW7WJQvpdz9Jsp8PTRaY8bqjfUCMDLwLa0Bv29LlhboZnVUYWjh qXr2VGjUBSHz6KXlWm/kpe1GtZxP9nUMbEbOMZLUZiCzQb4gUSM+bFRXmFfau54uzAQO eCTtCukCljGqNRI9WQBznP1sC4wwr7FMIZnlwOOhUCu0SfleqOtXIr+pJ9Wxv5x96wZW LGBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772881132; x=1773485932; 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=+bJqlJHeOUmKAaYm1Xbyn5/BnRtTCsqfQBFGOZH+2Y8=; b=R5YIQpc/xY5B6YUqc8m57WAoU+LxMU6lE72t98g4aDgc+AIiaF2GWrkBojXSIXyqN8 UA6KsgtRLxT3mNyFj3piKKOR8sMVOduxWDJad5Bwkt0mYsEtY56ho8o/bYwbZaDH9XAU MRHIHKWjcvRr8ecnQgM0BKTaqnMT0qYaH2B8hTU+jpssch7GNnWIUvNMO/fQJ7hQiytF t4V1l53sk+seLe2Foj4Q3/1UK0IHh/3nyGJLqdu8GMEJjHzpyme2y7yjd2EClxlrkulX ekQr+N6jDp2jeD/R4OIzO/nazOHFlAsRR6Dq1gd77BpUUmHN9UVsw3HUNZpfbYxd/ZKM JCDA== X-Forwarded-Encrypted: i=1; AJvYcCXnNIMADhA4fyPk8tWs1lZbnn0brtk8iO3cb2ardA7fvwJlx9r7V6DO+TCQKJmT9r+Uz2CSz3ztx2+G0lM=@vger.kernel.org X-Gm-Message-State: AOJu0Yx6OeMnuuWQUa0IzptaKU+HwY96MShNxe+n1cl5NxTjC4xYkFJU Lq9GCap/8ffKTs4w1voimzcwXm9UkaOuOAvYCdwqwjXqBii4rlSULgms X-Gm-Gg: ATEYQzxNq0zCBzUAfUVDlJ3AZ49AVkVicdf1ztXQmXoTI1fpalU+bpVXTkumM9uYPAj cwJ2Y7L1OjF5rkJnrHl+lUZ1Q9HVVniqQVDa0jsl9rTbE/ssVog361TU+J+S7H9mUDI0Yb8rLb/ 1PbqIn9BlnGsVDmWuv3xomiO9rNz4yHUCFBlUd5g42yG8dnAUI9x7KQA/EhBuUF9Pd5s3KeT7tD 9MOKaN/HrB079yARiRjWDqoyP2LXZl3lMDQK3w9s+K5e2XKEnDRgmvkuNGeKq0FHlHxGkI2KHWg DY61n+IoYmmEsZZxaIw+mn1aeNjL5zL8EsWFxng0PsEXvH0zoteuMMRfLOhfI+ZS3ohf9BqgiQB qver2eLFWy5zBSEwSJoA8MKF7hjt1de3VLvIR2LqxFvgr86Tpe+k5iRXgsbZXvHvtLGjsWaApeJ 7Xdts5V/p6m5Gq/xTvRqY70sUJNh9VgbRrWCyheu0MxYOWwbogCcNowfQF X-Received: by 2002:a05:620a:371b:b0:8c9:f8e5:9f0d with SMTP id af79cd13be357-8cd6d37fabdmr710288885a.32.1772881131520; Sat, 07 Mar 2026 02:58:51 -0800 (PST) Received: from PF5YBGDS.localdomain ([163.114.130.7]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8cd6f4a2fdasm293278485a.17.2026.03.07.02.58.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 02:58:51 -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 , Mohsin Bashir , Lee Trager , 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 v4 1/5] net: export netif_open for self_test usage Date: Sat, 7 Mar 2026 05:58:43 -0500 Message-ID: <20260307105847.1438-2-mike.marciniszyn@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260307105847.1438-1-mike.marciniszyn@gmail.com> References: <20260307105847.1438-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: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Mike Marciniszyn (Meta)" dev_open() already is exported, but drivers which use the netdev instance lock need to use netif_open() instead. netif_close() is also already exported [1] so this completes the pairing. This export is required for the following fbnic self tests to avoid calling ndo_stop() and ndo_open() in favor of the more appropriate netif_open() and netif_close() that notifies any listeners that the interface went down to test and is now coming back up. Link: https://patch.msgid.link/20250309215851.2003708-1-sdf@fomichev.me [1] Signed-off-by: Mike Marciniszyn (Meta) --- net/core/dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/dev.c b/net/core/dev.c index 203dc36aaed5..964503d403f1 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1731,6 +1731,7 @@ int netif_open(struct net_device *dev, struct netlink= _ext_ack *extack) =20 return ret; } +EXPORT_SYMBOL(netif_open); =20 static void __dev_close_many(struct list_head *head) { --=20 2.43.0 From nobody Thu Apr 9 16:33:38 2026 Received: from mail-qk1-f172.google.com (mail-qk1-f172.google.com [209.85.222.172]) (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 ADFC834CFC6 for ; Sat, 7 Mar 2026 10:58:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772881138; cv=none; b=PIaLVWaYEBIIIcPT8wt12viWauc+blNgjQU9jUuUULhzvD0ByVMZSu8otf3piBYJOXyLYn5YilLha6wxtQTKQrEeohoaGuIckxsulCcLuC8gKZDt62hrqunCZFQ7FnFEDOjAr8JVTmNFgJncALktJ/6ghRj9RsicvkR7neH2Q+8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772881138; c=relaxed/simple; bh=e2tXAtnj+aGqCFZpPDbMh5edKehkObPrv2UPmz9ZmqI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=imox3samwspoqPwzVix3a+5nrfXXGGe2F5rgzyQtumgkP2MLeIruCXxForfajrTp0W6co9Ij5s96hiLP0DxI8CnF4PZJ9DEFDuilEwdGEJ4c17/Th9k8Pejq+xby8Vv8cGML5PKMMfTBy8l7u4C5DUbjkL6W02RjnzKh7fWVyVw= 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=YScqjL+z; arc=none smtp.client-ip=209.85.222.172 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="YScqjL+z" Received: by mail-qk1-f172.google.com with SMTP id af79cd13be357-8cb3fb47559so1154708385a.1 for ; Sat, 07 Mar 2026 02:58:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772881134; x=1773485934; 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=Ujux5jQ7wtrQAjBE81FNR+E906/W7mZameBVGWZg9hk=; b=YScqjL+zIptLtcghSTHRcBLvsAo+CX/p+OtkG0GZSsJWlgJAGokNWCwce2fZg9kN+V KX7E9va8HCXTvcWLnrsH2TYOt/CX/UpXKduycG+5LfDVBOuX8pKwUpvXtLE61lvZwcMj R1jYTvZabs/1HzOtnvVL8W5QQenWoYUP8Xe4B9XRKFkQyaIkcz/TNqFBEhZYjmhW3DSl J1WmrGKoOK1wu3kM3LIIf7RuzeVPGEeo7qLFvOba2IBbPVcvsgoc3aDq8ybEITv2z8rl DeCRikcQxfvHnKtmcrbT0S57gEXljtkB+QU3iaHfiIhYy8EJ35yRc3N0YkQCYxcaHC6B ZVUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772881134; x=1773485934; 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=Ujux5jQ7wtrQAjBE81FNR+E906/W7mZameBVGWZg9hk=; b=D/a1euGCG9zZcAtQtwM2N3TdKPsHG02DRLJXb32spN+nhDVYFWI4EgLTNq3EqwUOEr giaCT52Xj0HYK4rKBQt0n1LQrZlmoTpDFdtDTHNUGioOZJPb/6WlBsRq3IhW0C0reWI/ PKU8cWB2uJ9vpHzd0fsVKLwLYgLDrk04TSFkNIyB20AN4+sN3OLzR3/0bc6zbcoG7VRL pAMhp8PnCMICOAvJVnljmS+81AgofLfAEiQAyAodDtsFOmjD7mpMZujCcZ3fRugDHAg3 HqmDlD2iwULgU+YLRXRjCsJBrkpDpizOriYk9rA9VP9Uw06YEA/71m7Bzw0GUpWnU7Ed 3hDw== X-Forwarded-Encrypted: i=1; AJvYcCXbm4J+/6pRxH/2PCnzfQrd7h8zFuArooYU1vZ5LImOrts2n88KguIYXCoavLHRE2/lUS8BgGJafNyqvx8=@vger.kernel.org X-Gm-Message-State: AOJu0YyIXeGxj4XlrU/K5PqHbPTFhzKRNuxUhf4NIlqEU8ThuhZbxSdq 44osPEmOUuE93JZN86740/A6h8Dzo8GrEYSZtHfxjF04U7krcXMk7Faf X-Gm-Gg: ATEYQzzxSepP795p5trJZ2H8KMIlvLAX6/diHullDXBvea+djA3T2uxWjtYGo4gUaqt FKmugI6moiXMS3oK7AIbG4SlXywpxhxSTtbWQ2E2EoJ5Z0MIIg0viIAEV4jyh2SgBLfns4ejOia 1Z9zzSIJ4imLid6GFBs2cutlx3wIq4VKPtD8SoM1TTwFiAqAUtRYlAjoJwEiteeOKB//68WolHf msUubrCfqO2EXxEkdPtxy7FVXPVpYyKBxhddUrUnTtfYQm/fz9ImNrdNPHDfRUMpntWJqMdAtGv NjX9VliPJd+vRxyjd23iO+rOqRtVGbBS/KOEclQvMKJBri7/nC0JDSZuvbjTKNSO1tjrMbEISIs 3bNOARb64/MzkyMf4kqGCOGguOxSinAC2954RGIbLuvbr4lVS6iVTtSKW+VKJhPaOKP2JzNsfc1 ly8vHzfmalZY1fF7gCwBpv9mqylzFx+kGbVRl7rEUpwWWZNrvr75VWNRm1 X-Received: by 2002:a05:620a:4890:b0:8c9:eb6a:1659 with SMTP id af79cd13be357-8cd6d40d272mr629082585a.9.1772881133508; Sat, 07 Mar 2026 02:58:53 -0800 (PST) Received: from PF5YBGDS.localdomain ([163.114.130.7]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8cd6f4a2fdasm293278485a.17.2026.03.07.02.58.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 02:58:52 -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 , Mohsin Bashir , Lee Trager , 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 v4 2/5] eth fbnic: Add register self test Date: Sat, 7 Mar 2026 05:58:44 -0500 Message-ID: <20260307105847.1438-3-mike.marciniszyn@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260307105847.1438-1-mike.marciniszyn@gmail.com> References: <20260307105847.1438-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: quoted-printable Content-Type: text/plain; charset="utf-8" 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 v3 - no changes v4 - no changes 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/ethe= rnet/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) =20 return len; } + +/* CSR register test data + * + * The register test will be used to verify hardware is behaving as expect= ed. + * + * 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 =3D FBNIC_QUEUE(0) + FBNIC_QUEUE_##_name, \ + .reg_offset =3D FBNIC_QUEUE_STRIDE, \ + .array_len =3D 64, \ + .read =3D _read, \ + .write =3D _write \ +} + +static const struct fbnic_csr_reg_test_data pattern_test[] =3D { + 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[] =3D { ~0, 0x5A5A5A5A, 0xA5A5A5A5, 0}; + enum fbnic_reg_self_test_codes reg; + int i; + + reg =3D test_data->reg + test_data->reg_offset * index; + for (i =3D 0; i < ARRAY_SIZE(pattern); i++) { + u32 val =3D pattern[i] & test_data->write; + u32 result; + + wr32(fbd, reg, val); + result =3D rd32(fbd, reg); + val &=3D test_data->read; + + if (result =3D=3D 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 =3D pattern_test; + test_data < pattern_test + ARRAY_SIZE(pattern_test); test_data++) { + u32 i; + + for (i =3D 0; i < test_data->array_len; i++) { + enum fbnic_reg_self_test_codes reg =3D + 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/ethe= rnet/meta/fbnic/fbnic_csr.h index 72eb22a52572..43de522af172 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_csr.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.h @@ -6,6 +6,8 @@ =20 #include =20 +struct fbnic_dev; + #define CSR_BIT(nr) (1u << (nr)) #define CSR_GENMASK(h, l) GENMASK(h, l) =20 @@ -1221,4 +1223,21 @@ enum{ FBNIC_CSR_VERSION_V1_0_ASIC =3D 1, }; =20 +/** + * 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 =3D 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 70c995b8d1bd..cad963a3d825 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_stat= s[] =3D { #define FBNIC_STATS_LEN \ (FBNIC_HW_STATS_LEN + FBNIC_XDP_STATS_LEN * FBNIC_MAX_XDPQS) =20 +enum fbnic_self_test_results { + TEST_REG =3D 0, +}; + +static const char fbnic_gstrings_self_test[][ETH_GSTRING_LEN] =3D { + [TEST_REG] =3D "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 *drvin= fo) { @@ -475,6 +485,10 @@ static void fbnic_get_strings(struct net_device *dev, = u32 sset, u8 *data) for (i =3D 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; } } =20 @@ -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; } @@ -1478,6 +1494,39 @@ fbnic_remove_rxfh_context(struct net_device *netdev, return 0; } =20 +static int fbnic_ethtool_regs_test(struct net_device *netdev, u64 *data) +{ + struct fbnic_net *fbn =3D netdev_priv(netdev); + struct fbnic_dev *fbd =3D fbn->fbd; + + *data =3D 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 =3D netif_running(netdev); + + if (!(eth_test->flags & ETH_TEST_FL_OFFLINE)) { + data[TEST_REG] =3D 0; + return; + } + + if (if_running) + netif_close(netdev); + + if (fbnic_ethtool_regs_test(netdev, &data[TEST_REG])) + eth_test->flags |=3D 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 |=3D ETH_TEST_FL_FAILED; + } +} + static void fbnic_get_channels(struct net_device *netdev, struct ethtool_channels *ch) { @@ -1940,6 +1989,7 @@ static const struct ethtool_ops fbnic_ethtool_ops =3D= { .get_pause_stats =3D fbnic_get_pause_stats, .get_pauseparam =3D fbnic_phylink_get_pauseparam, .set_pauseparam =3D fbnic_phylink_set_pauseparam, + .self_test =3D fbnic_self_test, .get_strings =3D fbnic_get_strings, .get_ethtool_stats =3D fbnic_get_ethtool_stats, .get_sset_count =3D fbnic_get_sset_count, --=20 2.43.0 From nobody Thu Apr 9 16:33:38 2026 Received: from mail-qk1-f171.google.com (mail-qk1-f171.google.com [209.85.222.171]) (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 DD41434EEF9 for ; Sat, 7 Mar 2026 10:58:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772881140; cv=none; b=WPtXYoknGObkNvSNh67tqIeANfraRwMHWD16e6XD5UpHmRQoQF6GQE178IbWXmOK/KvND8GrYHm7APZfI8s5JYYzhMCQt+2dtp6gzSXZu2NWSK6gkPP9JpZKuy5GNNY9T005MqP8ztXS50VA7+sUw7hbDAyqCmApwb40K/13tyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772881140; c=relaxed/simple; bh=l4n/YqP3KyhSn3VlED1Yu/syKa2SVWzzb0PFHGXJ+D8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=WVuPTAdkQXGC93u4KD5MRZm++kRLHgFzHC6eQ0ym1cbDG7uHQBeSwi2jqiD4tI5tdDtt+g21LqEPGDfltju0RiKR5a5CefDuDucynqv6Z8KjGm/of44LaPMWrYRJ+kdbgFpCNcwqF/zReqeK2K3hj0ZaCmDbBzKKE+45/EVZFl8= 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=REmYbhE6; arc=none smtp.client-ip=209.85.222.171 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="REmYbhE6" Received: by mail-qk1-f171.google.com with SMTP id af79cd13be357-8ca01dc7d40so1029369685a.1 for ; Sat, 07 Mar 2026 02:58:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772881135; x=1773485935; 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=nthtvmm8w9C5mAQ8p8js3NflR5wHb3y3LhcZm7H7OQI=; b=REmYbhE65xu0Oxt2hFattYZ6xVquye8nWJgfx3tnl0oJiQqoqE14hdiRxx/vuW+wRn zIg3FiB849Tx+lDGsU/DamfoYO4H19Rg5hTgUHe9HMyMHC0Ywn7Co9W4yYm9P5Ucj8ju clAZ5wFEEQ7YTnoXTX1MLfuTcioYggeSw4x2M7oPycpMwo8mPCvMqG9aLZsdgMCKgVtk FSoiUJQmUGaJhrGInQqU5oMBNG3JjG4TmUjAZ+r3B0c/+/ZAgV4tY9tRJTQhuWAQSBRf YWBMQZKUxd6Am8E9EXTH4XchYnBdA2KxouGocSwQPF6yycL7j+VzkkGZ+RCwfdyx2rol BROg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772881135; x=1773485935; 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=nthtvmm8w9C5mAQ8p8js3NflR5wHb3y3LhcZm7H7OQI=; b=ruhaW9iHVXRfLUjsVxt5FH/JGRCC7t+VaNBT6zcwQSqYcSt8XOtTjx5NMIRybvWngz TQrY81yL/+euFXeZ6yIuVhNwYXePAozRdlrUPq8noSPy5kYWr6xs0nurFqfWYtSnVsUr G2daRhRPEImos2I0ukHdSuxs0HVST6NSa9WKUqoausvm6HVaNSjjd4loZ4QCGI4Z8I14 C/UDChal9Ilax0WxCAQoZFxRFdvfUayKQ+9k1l/Q2ga3Us0Z00/JfV8OKPJywuS0AUWN 4ftvfi+X8a/CV6d0Vjr590uGz+cnThmAi15OAIpEBwEJ7QzknjsXCcyDWKDkWEscsO8c FMHA== X-Forwarded-Encrypted: i=1; AJvYcCVeln6DDbNokTYH8Y2pAny7wt8TAVsjXfIRInV8pjV1LIVor0L9M9SF/VvqFAuq58zDu3Z3yaz8tPu2PS0=@vger.kernel.org X-Gm-Message-State: AOJu0YyuexW4k6qOdvg+/g2lIFib2/xmmAmh0O6Df6RKzZRj1mZ0C3RY Cu2iyuerjh652ivMLnkXLJIFRMAWim88H9hhWoEJ5Isb8Da9Pm49UmQt X-Gm-Gg: ATEYQzy1vWZFsUGzfD1z9gwbadpXlr/Fn/vyZSIrK/HDMfHiNv4RvjO0XBpd0osXOPC CPXU7/KO7AU4v3h5R4OisBdjtQN1BmxMeT/38DbxHB7CGVln6/wR/5Ui1Nd39/smGXSixXTnK0+ y3ptniQCZZ3sAk/qgEsiTuIKkmNN4wBCX1aNbudRy2UuxLblGEMTzD+vKn5Auxwg+7uoTaJz1Z1 JXJSgxQzptTQG1m93oD1nzB/OrjwnhIXOvjjs8P8kRrGsmWGeU4IO9+PiBNaMbNKJWSfB34uPly APOdlfnJaBHFeTH7Yi+DkBNBLQlvmLOg6ooxOspY2Hel2VM6qXqC1PGbk8ol4zu4namvbCMY8q/ ovaQptakPV0lpLX9Lu+UyMbYWyhRy3ANxGsl7pdaCE9Bd+agVquDs0z6wQMnsM2gggjkDmq0TsH lFF1UrmK3Xr2/v0aK/fVaVBdHrvkx7IMmvo1z3ewinAU77ZjuanbbKW9Gw X-Received: by 2002:a05:620a:454d:b0:8c9:f996:81f2 with SMTP id af79cd13be357-8cd6d3d9388mr655004785a.17.1772881134776; Sat, 07 Mar 2026 02:58:54 -0800 (PST) Received: from PF5YBGDS.localdomain ([163.114.130.7]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8cd6f4a2fdasm293278485a.17.2026.03.07.02.58.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 02:58:54 -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 , Mohsin Bashir , Lee Trager , 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 v4 3/5] eth fbnic: Add msix self test Date: Sat, 7 Mar 2026 05:58:45 -0500 Message-ID: <20260307105847.1438-4-mike.marciniszyn@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260307105847.1438-1-mike.marciniszyn@gmail.com> References: <20260307105847.1438-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: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Mike Marciniszyn (Meta)" This function is meant to test the global interrupt registers and the PCIe IP MSI-X functionality. It essentially goes through and tests various combinations of the set, clear, and mask bits in order to verify the behavior is as we expect it to be from the driver. Signed-off-by: Mike Marciniszyn (Meta) --- v2 - add enum for test return codes v3 - add missing enum v4 - use kzalloc_obj() vs. kzalloc with sizeof drivers/net/ethernet/meta/fbnic/fbnic.h | 18 ++ .../net/ethernet/meta/fbnic/fbnic_ethtool.c | 28 ++++ drivers/net/ethernet/meta/fbnic/fbnic_irq.c | 154 ++++++++++++++++++ 3 files changed, 214 insertions(+) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic.h b/drivers/net/ethernet= /meta/fbnic/fbnic.h index a760a27b1516..f7df5302e91a 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic.h @@ -197,6 +197,38 @@ void fbnic_synchronize_irq(struct fbnic_dev *fbd, int = nr); int fbnic_request_irq(struct fbnic_dev *dev, int nr, irq_handler_t handler, unsigned long flags, const char *name, void *data); void fbnic_free_irq(struct fbnic_dev *dev, int nr, void *data); + +/** + * enum fbnic_msix_self_test_codes - return codes from self test routines + * + * These are the codes returned from the self test routines and + * stored in the test result array indexed by the specific + * test name. + * + * @FBNIC_TEST_MSIX_SUCCESS: no errors + * @FBNIC_TEST_MSIX_NOMEM: allocation failure + * @FBNIC_TEST_MSIX_IRQ_REQ_FAIL: IRQ request failure + * @FBNIC_TEST_MSIX_MASK: masking failed to prevent IRQ + * @FBNIC_TEST_MSIX_UNMASK: unmasking failure w/ sw status set + * @FBNIC_TEST_MSIX_IRQ_CLEAR: interrupt when clearing mask + * @FBNIC_TEST_MSIX_NO_INTERRUPT: no interrupt when not masked + * @FBNIC_TEST_MSIX_NO_CLEAR_OR_MASK: status not cleared, or mask not set + * @FBNIC_TEST_MSIX_BITS_SET_AFTER_TEST: Bits are set after test + */ +enum fbnic_msix_self_test_codes { + FBNIC_TEST_MSIX_SUCCESS =3D 0, + FBNIC_TEST_MSIX_NOMEM =3D 5, + FBNIC_TEST_MSIX_IRQ_REQ_FAIL =3D 10, + FBNIC_TEST_MSIX_MASK =3D 20, + FBNIC_TEST_MSIX_UNMASK =3D 30, + FBNIC_TEST_MSIX_IRQ_CLEAR =3D 40, + FBNIC_TEST_MSIX_NO_INTERRUPT =3D 50, + FBNIC_TEST_MSIX_NO_CLEAR_OR_MASK =3D 60, + FBNIC_TEST_MSIX_BITS_SET_AFTER_TEST =3D 70, +}; + +enum fbnic_msix_self_test_codes fbnic_msix_test(struct fbnic_dev *fbd); + void fbnic_free_irqs(struct fbnic_dev *fbd); int fbnic_alloc_irqs(struct fbnic_dev *fbd); =20 diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/= ethernet/meta/fbnic/fbnic_ethtool.c index cad963a3d825..b5012601b102 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c @@ -128,10 +128,12 @@ static const struct fbnic_stat fbnic_gstrings_xdp_sta= ts[] =3D { =20 enum fbnic_self_test_results { TEST_REG =3D 0, + TEST_MSIX, }; =20 static const char fbnic_gstrings_self_test[][ETH_GSTRING_LEN] =3D { [TEST_REG] =3D "Register test (offline)", + [TEST_MSIX] =3D "MSI-X Interrupt test (offline)", }; =20 #define FBNIC_TEST_LEN ARRAY_SIZE(fbnic_gstrings_self_test) @@ -1504,6 +1506,28 @@ static int fbnic_ethtool_regs_test(struct net_device= *netdev, u64 *data) return !!*data; } =20 +/** + * fbnic_ethtool_msix_test - Verify behavior of NIC interrupts + * @netdev: netdev device to test + * @data: Pointer to results storage + * + * This function is meant to test the global interrupt registers and the + * PCIe IP MSI-X functionality. It essentially goes through and tests + * test various combinations of the set, clear, and mask bits in order to + * verify the behavior is as we expect it to be from the driver. + * + * Return: non-zero on failure. + **/ +static int fbnic_ethtool_msix_test(struct net_device *netdev, u64 *data) +{ + struct fbnic_net *fbn =3D netdev_priv(netdev); + struct fbnic_dev *fbd =3D fbn->fbd; + + *data =3D fbnic_msix_test(fbd); + + return !!*data; +} + static void fbnic_self_test(struct net_device *netdev, struct ethtool_test *eth_test, u64 *data) { @@ -1511,6 +1535,7 @@ static void fbnic_self_test(struct net_device *netdev, =20 if (!(eth_test->flags & ETH_TEST_FL_OFFLINE)) { data[TEST_REG] =3D 0; + data[TEST_MSIX] =3D 0; return; } =20 @@ -1520,6 +1545,9 @@ static void fbnic_self_test(struct net_device *netdev, if (fbnic_ethtool_regs_test(netdev, &data[TEST_REG])) eth_test->flags |=3D ETH_TEST_FL_FAILED; =20 + if (fbnic_ethtool_msix_test(netdev, &data[TEST_MSIX])) + eth_test->flags |=3D ETH_TEST_FL_FAILED; + if (if_running && netif_open(netdev, NULL)) { netdev_err(netdev, "Failed to re-initialize hardware following test\n"); diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_irq.c b/drivers/net/ethe= rnet/meta/fbnic/fbnic_irq.c index 1e6a8fd6f702..5e383d40abc7 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_irq.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_irq.c @@ -240,6 +240,160 @@ void fbnic_free_irq(struct fbnic_dev *fbd, int nr, vo= id *data) free_irq(irq, data); } =20 +struct fbnic_msix_test_data { + struct fbnic_dev *fbd; + unsigned long test_msix_status[BITS_TO_LONGS(FBNIC_MAX_MSIX_VECS)]; + int irq_vector[FBNIC_MAX_MSIX_VECS]; +}; + +static irqreturn_t fbnic_irq_test(int irq, void *data) +{ + struct fbnic_msix_test_data *test_data =3D data; + struct fbnic_dev *fbd =3D test_data->fbd; + int i; + + for (i =3D fbd->num_irqs; i--;) { + if (test_data->irq_vector[i] =3D=3D irq) { + set_bit(i, test_data->test_msix_status); + break; + } + } + + return IRQ_HANDLED; +} + +/** + * fbnic_msix_test - Verify behavior of NIC interrupts + * @fbd: device to test + * + * This function is meant to test the global interrupt registers and the + * PCIe IP MSI-X functionality. It essentially goes through and tests + * various combinations of the set, clear, and mask bits in order to + * verify the behavior is as we expect it to be from the driver. + * + * Return: See enum fbnic_msix_self_test_codes + **/ +enum fbnic_msix_self_test_codes fbnic_msix_test(struct fbnic_dev *fbd) +{ + enum fbnic_msix_self_test_codes result =3D FBNIC_TEST_MSIX_SUCCESS; + struct pci_dev *pdev =3D to_pci_dev(fbd->dev); + struct fbnic_msix_test_data *test_data; + u32 mask =3D 0; + int i; + + /* Allocate bitmap and IRQ vector table */ + test_data =3D kzalloc_obj(*test_data, GFP_KERNEL); + + /* memory allocation failure */ + if (!test_data) + return FBNIC_TEST_MSIX_NOMEM; + + /* Initialize test data */ + test_data->fbd =3D fbd; + + for (i =3D FBNIC_NON_NAPI_VECTORS; i < fbd->num_irqs; i++) { + /* Add IRQ to vector table so it can be found */ + test_data->irq_vector[i] =3D pci_irq_vector(pdev, i); + + /* Enable the interrupt */ + if (!fbnic_request_irq(fbd, i, fbnic_irq_test, 0, + fbd->netdev->name, test_data)) + continue; + + while (i-- > FBNIC_NON_NAPI_VECTORS) + fbnic_free_irq(fbd, i, test_data); + kfree(test_data); + + /* IRQ request failure */ + return FBNIC_TEST_MSIX_IRQ_REQ_FAIL; + } + + /* Test each bit individually */ + for (i =3D FBNIC_NON_NAPI_VECTORS; i < fbd->num_irqs; i++) { + mask =3D 1U << (i % 32); + + /* Start with mask set and interrupt cleared */ + fbnic_wr32(fbd, FBNIC_INTR_MASK_SET(i / 32), mask); + fbnic_wrfl(fbd); + fbnic_wr32(fbd, FBNIC_INTR_CLEAR(i / 32), mask); + fbnic_wrfl(fbd); + + /* masking failure to prevent interrupt */ + result =3D FBNIC_TEST_MSIX_MASK; + + fbnic_wr32(fbd, FBNIC_INTR_SET(i / 32), mask); + fbnic_wrfl(fbd); + usleep_range(10000, 11000); + + if (test_bit(i, test_data->test_msix_status)) + break; + + /* unmasking failure w/ sw status set */ + result =3D FBNIC_TEST_MSIX_UNMASK; + + fbnic_wr32(fbd, FBNIC_INTR_MASK_CLEAR(i / 32), mask); + fbnic_wrfl(fbd); + usleep_range(10000, 11000); + + if (!test_bit(i, test_data->test_msix_status)) + break; + + /* interrupt when clearing mask */ + result =3D FBNIC_TEST_MSIX_IRQ_CLEAR; + + clear_bit(i, test_data->test_msix_status); + fbnic_wr32(fbd, FBNIC_INTR_MASK_CLEAR(i / 32), mask); + fbnic_wrfl(fbd); + usleep_range(10000, 11000); + + if (test_bit(i, test_data->test_msix_status)) + break; + + /* interrupt not triggering when not masked */ + result =3D FBNIC_TEST_MSIX_NO_INTERRUPT; + + fbnic_wr32(fbd, FBNIC_INTR_SET(i / 32), mask); + fbnic_wrfl(fbd); + usleep_range(10000, 11000); + + if (!test_bit(i, test_data->test_msix_status)) + break; + + /* status not cleared, or mask not set */ + result =3D FBNIC_TEST_MSIX_NO_CLEAR_OR_MASK; + if (mask & fbnic_rd32(fbd, FBNIC_INTR_STATUS(i / 32))) + break; + if (!(mask & fbnic_rd32(fbd, FBNIC_INTR_MASK(i / 32)))) + break; + + /* Result =3D 0 - Success */ + result =3D FBNIC_TEST_MSIX_SUCCESS; + + clear_bit(i, test_data->test_msix_status); + } + + if (i < fbd->num_irqs) { + fbnic_wr32(fbd, FBNIC_INTR_MASK_SET(i / 32), mask); + fbnic_wrfl(fbd); + fbnic_wr32(fbd, FBNIC_INTR_CLEAR(i / 32), mask); + fbnic_wrfl(fbd); + clear_bit(i, test_data->test_msix_status); + } + + for (i =3D FBNIC_NON_NAPI_VECTORS; i < fbd->num_irqs; i++) { + /* Test for bits set after testing */ + if (test_bit(i, test_data->test_msix_status)) + result =3D FBNIC_TEST_MSIX_BITS_SET_AFTER_TEST; + + /* Free IRQ */ + fbnic_free_irq(fbd, i, test_data); + } + + kfree(test_data); + + return result; +} + void fbnic_napi_name_irqs(struct fbnic_dev *fbd) { unsigned int i; --=20 2.43.0 From nobody Thu Apr 9 16:33:38 2026 Received: from mail-qk1-f170.google.com (mail-qk1-f170.google.com [209.85.222.170]) (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 6448A33C18B for ; Sat, 7 Mar 2026 10:58:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772881141; cv=none; b=Bn2ikf4okn3mRtSB/wt1DMH4RGRTk+Bo+E0vHyBPw5KF4NNwE2rQKgI8I6l4CIn2fx4en0rCwNVH47C8afsrgnwnll1igtbkK78E2TefsZWJ+uDEcnC27JdNSMeVeJIOSl0Z1Jrvh7ugkBUUQZ9Bbm3IYlzafsJwvkN3fK5HY9M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772881141; c=relaxed/simple; bh=T1S92E+ewejtyDlhaA7GchagGaUIywz++uX2x+Xpq5E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YrHEQfsgx7g2Ne9QvDgVxOXO4Mo39ihwPgRfQb+A5Ga6GRfjAhX2BVweM7KIsI3Cmzp2lN3UUA/Nl/Ea+iM6veWpPrvqoxNDkLo51PCilmRA5JKXLRe6cSGjo5dvfMmt+L4v+aQskXWkm4WKLZZF9PBLHI3Fs5WDP6re6SBe/zs= 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=YZenIOYk; arc=none smtp.client-ip=209.85.222.170 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="YZenIOYk" Received: by mail-qk1-f170.google.com with SMTP id af79cd13be357-8c6f21c2d81so958958285a.2 for ; Sat, 07 Mar 2026 02:58:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772881136; x=1773485936; 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=w/FjiCtmQ3xbbF6fN1F+SpM7nSYH0WutfVCmNIFZmtM=; b=YZenIOYkfixxxK9/VlxwGYBhWQdE+DyxoAT8popbDJM6GkfYvgmu79G6T8raQln/E5 qh3yZs2JwGmzr2qDgmV8p/uWrWT+BzCwdsIe3O8DQjizWm73PQ/OVY8GyqN3ziQXctlr q0EenbPNiAv573XDHg8p/m77X1k5lgDVEBweCuQreRkWhl1lQQfpimbpvDWeqm1vPIU9 YZtqb9A+g14S5DK/z2AoYwlt/qoTZ4yI+3CDOrEds1SoV/+UaHuVP75SXQMSmPrxtnRY h+Vd74FrRzadidRwV4wpHd66L0P48w4/Nl1Nn8IDMKuJZaaSdHMC60tLy8K2oi7Z6cjZ LsfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772881136; x=1773485936; 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=w/FjiCtmQ3xbbF6fN1F+SpM7nSYH0WutfVCmNIFZmtM=; b=XwyiDKFLyocElZ6AyeJLgXmcVgtOYkBjvCLZrq45t4UvR3DTq+LTxgxkZiCC10vve6 Q36tVoUyEAwmlzLWw/zfg8xSuXumYPyXE1xIA7RqsTkkMJk5udNGQVDDJ2CGkT1/fwsm DGUGjrVTxbsb4MHgHgRmWqZ5md0lwF8Z22c+weFIKAHBf89qE9K7r7xd+vku/L2Xe2sG n7eujRLmze1458k2DxpShLT/3LSa3sVFxtMVZ6NJ6fBlAj4te9rX7g9kWjujwymUqRdZ NNhPR6C0N5Y2mRNs1fL+L6lIlg3WsMfnNN083u6fSnunQvwzqyrAKr4gWNMlgtiBEsWT yA6A== X-Forwarded-Encrypted: i=1; AJvYcCW1m9zp14WUrdyawEJQq+x4663E2bIKzNXk+sXMFSqdYZ7FPOuVXYzDDwNkFbG4B9qkFzhlqpBhdQXJWjc=@vger.kernel.org X-Gm-Message-State: AOJu0YwM0fFNL5NvF5ROHe6C43vGO/9GtfakNBTxcGPG7t6eMq8hqRMt ci0Ax4Gn6KXVbzh65qpLYyoT1ot57E+bRG+OnZZ2IYCAuLnX+rKt5KD6 X-Gm-Gg: ATEYQzyBG6y1LRcpdgjZQgbbMX7UDVYeYK8YEqixF2rmm1hSiwGDAGIB0tcly6f98dy fvynMmQhiUnZBlAiMz6elLP/dtIVKcYm+Meomcj9LxyRkuLePRNG0lun/Nxvq3IR3TOhPGlMyeb jR4HC58FDtmTQoC51/DOnG5l5HcbX3UxDUqM5SZOma4OKRJqkF2W1+VLEXXDGkYjp3/s9uZ8Ko/ yac69LUgUdXZatbirhhNkyIVwnS7QztLldOWAuO8ccKUUQWysW1+sIAaLbLvlSNnup4eot9hZev ea5Bt1gCy+73xTr0UtswJ6Tvg8RUy9QG/xFa4TE+k2nCQFQ2WXd+YG6YB5gl/NWz44h9Js0lnHP YxUd6kQuFXV0ZZbQhe9UdbrxMaFm/FFOVJH468Y8CkYIhmIQjBqQPL800uwrsKiRR/wVJo4lYaB RKdxMAXjxD3wxNSAYVsH+hi0rXfNf5m3rjl4GHkwrvlFQau0dScpGjjmO5 X-Received: by 2002:a05:620a:1913:b0:8be:88f2:5b15 with SMTP id af79cd13be357-8cd6d4a16ecmr624673785a.38.1772881135997; Sat, 07 Mar 2026 02:58:55 -0800 (PST) Received: from PF5YBGDS.localdomain ([163.114.130.7]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8cd6f4a2fdasm293278485a.17.2026.03.07.02.58.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 02:58:55 -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 , Mohsin Bashir , Lee Trager , 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 v4 4/5] eth fbnic: TLV support for use by MBX self test Date: Sat, 7 Mar 2026 05:58:46 -0500 Message-ID: <20260307105847.1438-5-mike.marciniszyn@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260307105847.1438-1-mike.marciniszyn@gmail.com> References: <20260307105847.1438-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: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Mike Marciniszyn (Meta)" The TLV (Type-Value-Length) self uses a known set of data to create a TLV message. These routines support the MBX self test by creating the test messages and parsing the response message coming back from the firmware. Signed-off-by: Mike Marciniszyn (Meta) --- v2 - place forward of struct fbnic_dev after include with a blank line v3 - no changes v4 - no changes drivers/net/ethernet/meta/fbnic/fbnic_tlv.c | 276 ++++++++++++++++++++ drivers/net/ethernet/meta/fbnic/fbnic_tlv.h | 27 ++ 2 files changed, 303 insertions(+) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c b/drivers/net/ethe= rnet/meta/fbnic/fbnic_tlv.c index 517ed8b2f1cb..c55d4f76a5fc 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c @@ -551,6 +551,172 @@ int fbnic_tlv_parser_error(void *opaque, struct fbnic= _tlv_msg **results) return -EBADMSG; } =20 +#define FBNIC_TLV_TEST_STRING_LEN 32 + +struct fbnic_tlv_test { + u64 test_u64; + s64 test_s64; + u32 test_u32; + s32 test_s32; + u16 test_u16; + s16 test_s16; + u8 test_mac[ETH_ALEN]; + u8 test_mac_array[4][ETH_ALEN]; + u8 test_true; + u8 test_false; + char test_string[FBNIC_TLV_TEST_STRING_LEN]; +}; + +static struct fbnic_tlv_test test_struct; + +const struct fbnic_tlv_index fbnic_tlv_test_index[] =3D { + FBNIC_TLV_ATTR_U64(FBNIC_TLV_TEST_MSG_U64), + FBNIC_TLV_ATTR_S64(FBNIC_TLV_TEST_MSG_S64), + FBNIC_TLV_ATTR_U32(FBNIC_TLV_TEST_MSG_U32), + FBNIC_TLV_ATTR_S32(FBNIC_TLV_TEST_MSG_S32), + FBNIC_TLV_ATTR_U32(FBNIC_TLV_TEST_MSG_U16), + FBNIC_TLV_ATTR_S32(FBNIC_TLV_TEST_MSG_S16), + FBNIC_TLV_ATTR_MAC_ADDR(FBNIC_TLV_TEST_MSG_MAC_ADDR), + FBNIC_TLV_ATTR_FLAG(FBNIC_TLV_TEST_MSG_FLAG_TRUE), + FBNIC_TLV_ATTR_FLAG(FBNIC_TLV_TEST_MSG_FLAG_FALSE), + FBNIC_TLV_ATTR_STRING(FBNIC_TLV_TEST_MSG_STRING, + FBNIC_TLV_TEST_STRING_LEN), + FBNIC_TLV_ATTR_ARRAY(FBNIC_TLV_TEST_MSG_ARRAY), + FBNIC_TLV_ATTR_NESTED(FBNIC_TLV_TEST_MSG_NESTED), + FBNIC_TLV_ATTR_LAST +}; + +static void fbnic_tlv_test_struct_init(void) +{ + int i =3D FBNIC_TLV_TEST_STRING_LEN - 1; + + /* Populate the struct with random data */ + get_random_once(&test_struct, + offsetof(struct fbnic_tlv_test, test_string) + i); + + /* Force true/false to their expected values */ + test_struct.test_false =3D false; + test_struct.test_true =3D true; + + /* Convert test_string to a true ASCII string */ + test_struct.test_string[i] =3D '\0'; + while (i--) { + /* Force characters into displayable range */ + if (test_struct.test_string[i] < 64 || + test_struct.test_string[i] >=3D 96) { + test_struct.test_string[i] %=3D 32; + test_struct.test_string[i] +=3D 64; + } + } +} + +static int fbnic_tlv_test_attr_data(struct fbnic_tlv_msg *msg) +{ + struct fbnic_tlv_msg *array; + int err, i; + + err =3D fbnic_tlv_attr_put_int(msg, FBNIC_TLV_TEST_MSG_U64, + test_struct.test_u64); + if (err) + return err; + + err =3D fbnic_tlv_attr_put_int(msg, FBNIC_TLV_TEST_MSG_S64, + test_struct.test_s64); + if (err) + return err; + + err =3D fbnic_tlv_attr_put_int(msg, FBNIC_TLV_TEST_MSG_U32, + test_struct.test_u32); + if (err) + return err; + + err =3D fbnic_tlv_attr_put_int(msg, FBNIC_TLV_TEST_MSG_S32, + test_struct.test_s32); + if (err) + return err; + + err =3D fbnic_tlv_attr_put_int(msg, FBNIC_TLV_TEST_MSG_U16, + test_struct.test_u16); + if (err) + return err; + + err =3D fbnic_tlv_attr_put_int(msg, FBNIC_TLV_TEST_MSG_S16, + test_struct.test_s16); + if (err) + return err; + + err =3D fbnic_tlv_attr_put_value(msg, FBNIC_TLV_TEST_MSG_MAC_ADDR, + test_struct.test_mac, ETH_ALEN); + if (err) + return err; + + /* Start MAC address array */ + array =3D fbnic_tlv_attr_nest_start(msg, FBNIC_TLV_TEST_MSG_ARRAY); + if (!array) + return -ENOSPC; + + for (i =3D 0; i < 4; i++) { + err =3D fbnic_tlv_attr_put_value(array, + FBNIC_TLV_TEST_MSG_MAC_ADDR, + test_struct.test_mac_array[i], + ETH_ALEN); + if (err) + return err; + } + + /* Close array */ + fbnic_tlv_attr_nest_stop(msg); + + err =3D fbnic_tlv_attr_put_flag(msg, FBNIC_TLV_TEST_MSG_FLAG_TRUE); + if (err) + return err; + + return fbnic_tlv_attr_put_string(msg, FBNIC_TLV_TEST_MSG_STRING, + test_struct.test_string); +} + +/** + * fbnic_tlv_test_create - Allocate a test message and fill it w/ data + * @fbd: FBNIC device structure + * + * Return: NULL on failure to allocate or pointer to new TLV test message. + **/ +struct fbnic_tlv_msg *fbnic_tlv_test_create(struct fbnic_dev *fbd) +{ + struct fbnic_tlv_msg *msg, *nest; + int err; + + msg =3D fbnic_tlv_msg_alloc(FBNIC_TLV_MSG_ID_TEST); + if (!msg) + return NULL; + + /* Randomize struct data */ + fbnic_tlv_test_struct_init(); + + /* Add first level of data to message */ + err =3D fbnic_tlv_test_attr_data(msg); + if (err) + goto free_message; + + /* Start second level nested */ + nest =3D fbnic_tlv_attr_nest_start(msg, FBNIC_TLV_TEST_MSG_NESTED); + if (!nest) + goto free_message; + + /* Add nested data */ + err =3D fbnic_tlv_test_attr_data(nest); + if (err) + goto free_message; + + /* Close nest and report full message */ + fbnic_tlv_attr_nest_stop(msg); + + return msg; +free_message: + free_page((unsigned long)msg); + return NULL; +} + void fbnic_tlv_attr_addr_copy(u8 *dest, struct fbnic_tlv_msg *src) { u8 *mac_addr; @@ -558,3 +724,113 @@ void fbnic_tlv_attr_addr_copy(u8 *dest, struct fbnic_= tlv_msg *src) mac_addr =3D fbnic_tlv_attr_get_value_ptr(src); memcpy(dest, mac_addr, ETH_ALEN); } + +/** + * fbnic_tlv_parser_test_attr - Function loading test attributes into stru= cture + * @str: Test structure to load + * @results: Pointer to results array + * + * Copies attributes into structure. Any attribute that doesn't exist in t= he + * results array is not populated. + **/ +static void fbnic_tlv_parser_test_attr(struct fbnic_tlv_test *str, + struct fbnic_tlv_msg **results) +{ + struct fbnic_tlv_msg *array_results[4]; + struct fbnic_tlv_msg *attr; + char *string =3D NULL; + int i, err; + + str->test_u64 =3D fta_get_uint(results, FBNIC_TLV_TEST_MSG_U64); + str->test_u32 =3D fta_get_uint(results, FBNIC_TLV_TEST_MSG_U32); + str->test_u16 =3D fta_get_uint(results, FBNIC_TLV_TEST_MSG_U16); + + str->test_s64 =3D fta_get_sint(results, FBNIC_TLV_TEST_MSG_S64); + str->test_s32 =3D fta_get_sint(results, FBNIC_TLV_TEST_MSG_S32); + str->test_s16 =3D fta_get_sint(results, FBNIC_TLV_TEST_MSG_S16); + + attr =3D results[FBNIC_TLV_TEST_MSG_MAC_ADDR]; + if (attr) + fbnic_tlv_attr_addr_copy(str->test_mac, attr); + + attr =3D results[FBNIC_TLV_TEST_MSG_ARRAY]; + if (attr) { + int len =3D le16_to_cpu(attr->hdr.len) / sizeof(u32) - 1; + + err =3D fbnic_tlv_attr_parse_array(&attr[1], len, + array_results, + fbnic_tlv_test_index, + FBNIC_TLV_TEST_MSG_MAC_ADDR, + 4); + if (!err) { + for (i =3D 0; i < 4 && array_results[i]; i++) + fbnic_tlv_attr_addr_copy(str->test_mac_array[i], + array_results[i]); + } + } + + str->test_true =3D !!results[FBNIC_TLV_TEST_MSG_FLAG_TRUE]; + str->test_false =3D !!results[FBNIC_TLV_TEST_MSG_FLAG_FALSE]; + + attr =3D results[FBNIC_TLV_TEST_MSG_STRING]; + if (attr) { + string =3D fbnic_tlv_attr_get_value_ptr(attr); + strscpy(str->test_string, string, FBNIC_TLV_TEST_STRING_LEN); + } +} + +static void fbnic_tlv_test_dump(struct fbnic_tlv_test *value, char *prefix) +{ + print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 16, 1, + value, sizeof(*value), true); +} + +/** + * fbnic_tlv_parser_test - Function for parsing and testing test message + * @opaque: Unused value + * @results: Results of parser output + * + * Return: negative value on error, or 0 on success. + * + * Parses attributes to structures and compares the structure to the + * expected test value that should have been used to populate the message. + * + * Used to verify message generation and parser are working correctly. + **/ +int fbnic_tlv_parser_test(void *opaque, struct fbnic_tlv_msg **results) +{ + struct fbnic_tlv_msg *nest_results[FBNIC_TLV_RESULTS_MAX] =3D { 0 }; + struct fbnic_tlv_test result_struct; + struct fbnic_tlv_msg *attr; + int err; + + memset(&result_struct, 0, sizeof(result_struct)); + fbnic_tlv_parser_test_attr(&result_struct, results); + + if (memcmp(&test_struct, &result_struct, sizeof(test_struct))) { + fbnic_tlv_test_dump(&result_struct, "fbnic: found - "); + fbnic_tlv_test_dump(&test_struct, "fbnic: expected - "); + return -EINVAL; + } + + attr =3D results[FBNIC_TLV_TEST_MSG_NESTED]; + if (!attr) + return -EINVAL; + + err =3D fbnic_tlv_attr_parse(&attr[1], + le16_to_cpu(attr->hdr.len) / sizeof(u32) - 1, + nest_results, fbnic_tlv_test_index); + if (err) + return err; + + memset(&result_struct, 0, sizeof(result_struct)); + fbnic_tlv_parser_test_attr(&result_struct, nest_results); + + if (memcmp(&test_struct, &result_struct, sizeof(test_struct))) { + fbnic_tlv_test_dump(&result_struct, "fbnic: found - "); + fbnic_tlv_test_dump(&test_struct, "fbnic: expected - "); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_tlv.h b/drivers/net/ethe= rnet/meta/fbnic/fbnic_tlv.h index 3508b46ebdd0..9c4e4759394a 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_tlv.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_tlv.h @@ -9,6 +9,8 @@ #include #include =20 +struct fbnic_dev; + #define FBNIC_TLV_MSG_ALIGN(len) ALIGN(len, sizeof(u32)) #define FBNIC_TLV_MSG_SIZE(len) \ (FBNIC_TLV_MSG_ALIGN(len) / sizeof(u32)) @@ -153,6 +155,31 @@ int fbnic_tlv_parser_error(void *opaque, struct fbnic_= tlv_msg **results); #define fta_get_str(_results, _id, _dst, _dstsize) \ fbnic_tlv_attr_get_string(_results[_id], _dst, _dstsize) =20 +#define FBNIC_TLV_MSG_ID_TEST 0 + +enum fbnic_tlv_test_attr_id { + FBNIC_TLV_TEST_MSG_U64, + FBNIC_TLV_TEST_MSG_S64, + FBNIC_TLV_TEST_MSG_U32, + FBNIC_TLV_TEST_MSG_S32, + FBNIC_TLV_TEST_MSG_U16, + FBNIC_TLV_TEST_MSG_S16, + FBNIC_TLV_TEST_MSG_MAC_ADDR, + FBNIC_TLV_TEST_MSG_FLAG_TRUE, + FBNIC_TLV_TEST_MSG_FLAG_FALSE, + FBNIC_TLV_TEST_MSG_STRING, + FBNIC_TLV_TEST_MSG_NESTED, + FBNIC_TLV_TEST_MSG_ARRAY, + FBNIC_TLV_TEST_MSG_MAX +}; + +extern const struct fbnic_tlv_index fbnic_tlv_test_index[]; +struct fbnic_tlv_msg *fbnic_tlv_test_create(struct fbnic_dev *fbd); +int fbnic_tlv_parser_test(void *opaque, struct fbnic_tlv_msg **results); + +#define FBNIC_TLV_MSG_TEST \ + FBNIC_TLV_PARSER(TEST, fbnic_tlv_test_index, \ + fbnic_tlv_parser_test) #define FBNIC_TLV_MSG_ERROR \ FBNIC_TLV_PARSER(UNKNOWN, NULL, fbnic_tlv_parser_error) #endif /* _FBNIC_TLV_H_ */ --=20 2.43.0 From nobody Thu Apr 9 16:33:38 2026 Received: from mail-qk1-f176.google.com (mail-qk1-f176.google.com [209.85.222.176]) (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 82EBE34A76F for ; Sat, 7 Mar 2026 10:58:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772881141; cv=none; b=OiZrtB7r/USB8OvmOkBGkOqznpbBZq16txg6S2qC0e+FukQtI1tYx6c6BzHOJVydgfHwUDbzlM3Xnw5Gp9Jm80MdKsnWpGPie+NJpXpaxiT2gRT+y7UN7VQLI0HZj8c8Wwxr7zIbgFobHA0NRdVIZtgHaelTcaMy01mzSYHNeJQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772881141; c=relaxed/simple; bh=FDd2xI8Jd7D9gB0fKiSlbyHiTNXBNZ0++jcrlUyV+Ts=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=T44NF0X8dCJn2BAq8GhTbs+60HYnPD5fj2eTILxaspEZ+8k4bVAjQ4+z9LHmFncK5YLUwm0aSYhxLvSTFgfCGnaI9md8ycAUhaWWq/yWOqSjgvQ/9rT24Q/IpBNG0kbejGJGqTE1OiwG5pgpqsRgYuPrQtedmZOiOCzLsBcW5aM= 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=UveXsbBq; arc=none smtp.client-ip=209.85.222.176 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="UveXsbBq" Received: by mail-qk1-f176.google.com with SMTP id af79cd13be357-8cd722c2923so138530485a.1 for ; Sat, 07 Mar 2026 02:58:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1772881137; x=1773485937; 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=YWqt7jbBjf5NmoQedgg0t/HNcW4ltoXPePYOrcGOf0c=; b=UveXsbBq9n1AIxvHpcbSZcWpFZMk6sJRt8LK9yjHXD75E84Xjq3GksYdQi/KF1fG/j yx00sIhZRJP3XI0QRdYq4FfziQuGYc7IhQpCP1UvD4vsqPkDgwaKkO/SAK6Illwbl9GD f34by7Qrap9P6RY8zy8t7O1zHj009hp3ghTitE559Ecrizplq5GVIWJRVRl9opOnRNA+ P5+U6QEz3tpuqaFlocG2Yzn8NEUZGPSCFT3fNy3BlejUpWoKYlfEZcwas+NPS0LlDJ/a Yc5fP/K7TEZOTsnGSM7DsFdVKcP1RiCb49gtnyEYFcUiPBBTNBIkmn2JMF64EMrLE25R Zemw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1772881137; x=1773485937; 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=YWqt7jbBjf5NmoQedgg0t/HNcW4ltoXPePYOrcGOf0c=; b=P6Qjzc7jHavZB8MFVns9QyHgp8BvLms04h5ISs0Oy8L3EnybwzK2/cOOTlM9kb9pns kIPKqL5sqDMUsSL/selEmLNbxbfnlRtvR0wh5QZi42/jMqVu4Z+4I573kkuuZBo2NQdH q1E5M833vg+NHf2spBiGfsdiAkCrL8L0896WW93kQFONIHaQykK4Pbmdx7np4SxkSE66 ljFwLvZaGSPTuhF7KWZWasCOQhLMQ7EQBRos8yKBIATke5ul1wRfGG9z8brLddP5AQB/ nfxHQZhNNbDmxsOM1s4rkl4Ia0WqcyN6ArPjndzdLuFyTXv94Lpy5F30lLXnYEjXrWv5 KugQ== X-Forwarded-Encrypted: i=1; AJvYcCUncIKMD/Ik/okhXpsJ7yWCh1DtEtKBLlFfo35GbfXcvpYag1hmWwlP3UXMVHrJwT67qKi/vbiARvyNej0=@vger.kernel.org X-Gm-Message-State: AOJu0YyS4mAoltiTXmKjFfRocbjZgBoh45xlTk9w3Rbo3DXJY01xKUH9 XEqLMdN6bnE8atHwmXp4XCXwPwVjtIU0uoZ4phn6Y5RkH2rGhm2tc1xq X-Gm-Gg: ATEYQzx3TuIpSZLYLGGaaILs3yjXjA70PYd/l+FYaEcotBkibojcNG+zq4TIRbcl+o0 Yl23UDNVwzo7JunC0LepvH9fE7dNaeOMgSQ7wWOldlr9I4vlIO+QZ191KQD+vIXvjKxdgHwQMae OrsojXYNt1z/HPETpMuiOY6YbhBK0nHmL18tV2GgK34J6kvJ04SYSXVi02hdz6tMQ1qm5ES2b/F a2TwSKH//zCoY+zUWnwx2OeOtpuOUrZGlObpx5ZYvNa07nCl0jct4TZaNbkgTmvsE7JW1rVsHV3 2m0GP6CA3XOWq419mNVqt/TAU3Vyz6SdSTwlAuQZY102IPNLROHEJNkjZHxw2ZwfWWqFFXacv4L fFj7UXcsj1v3vuFUpkOZea1znYGr6YGup0Eez8uPhEqwZLCiHI5EpGR1jBr+7hb+xlaeSQrgCiM udF26wlFje2CvKwBhhPsDeDB8nmJpYUYPbIJR8ya2w4NprbFlcXzO8U7rc3TT0gFTz8pU= X-Received: by 2002:a05:620a:2549:b0:89f:8bb8:c103 with SMTP id af79cd13be357-8cd6d4b4f11mr640784885a.49.1772881137186; Sat, 07 Mar 2026 02:58:57 -0800 (PST) Received: from PF5YBGDS.localdomain ([163.114.130.7]) by smtp.gmail.com with ESMTPSA id af79cd13be357-8cd6f4a2fdasm293278485a.17.2026.03.07.02.58.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 07 Mar 2026 02:58:56 -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 , Mohsin Bashir , Lee Trager , 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 v4 5/5] eth fbnic: Add mailbox self test Date: Sat, 7 Mar 2026 05:58:47 -0500 Message-ID: <20260307105847.1438-6-mike.marciniszyn@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260307105847.1438-1-mike.marciniszyn@gmail.com> References: <20260307105847.1438-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: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Mike Marciniszyn (Meta)" The mailbox self test ensures the interface to and from the firmware is healthy by sending a test message and fielding the response from the firmware. This patch uses the new completion API [1][2] that allocates a completion structure, binds the completion to the TEST message, and uses a new FW parsing routine that wraps the completion processing around the TLV parser. Link: https://patch.msgid.link/20250516164804.741348-1-lee@trager.us [1] Link: https://patch.msgid.link/20260115003353.4150771-6-mohsin.bashr@gmail.= com [2] Signed-off-by: Mike Marciniszyn (Meta) --- v2 - add enum for test return codes v3 - no changes v4 - no changes drivers/net/ethernet/meta/fbnic/fbnic.h | 14 ++- .../net/ethernet/meta/fbnic/fbnic_ethtool.c | 15 +++ drivers/net/ethernet/meta/fbnic/fbnic_fw.c | 100 ++++++++++++++++++ drivers/net/ethernet/meta/fbnic/fbnic_fw.h | 27 +++++ 3 files changed, 142 insertions(+) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/= ethernet/meta/fbnic/fbnic_ethtool.c index b5012601b102..f14de2366854 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c @@ -129,11 +129,13 @@ static const struct fbnic_stat fbnic_gstrings_xdp_sta= ts[] =3D { enum fbnic_self_test_results { TEST_REG =3D 0, TEST_MSIX, + TEST_MBX, }; =20 static const char fbnic_gstrings_self_test[][ETH_GSTRING_LEN] =3D { [TEST_REG] =3D "Register test (offline)", [TEST_MSIX] =3D "MSI-X Interrupt test (offline)", + [TEST_MBX] =3D "FW mailbox test (on/offline)", }; =20 #define FBNIC_TEST_LEN ARRAY_SIZE(fbnic_gstrings_self_test) @@ -1528,11 +1530,24 @@ static int fbnic_ethtool_msix_test(struct net_devic= e *netdev, u64 *data) return !!*data; } =20 +static int fbnic_ethtool_mbx_self_test(struct net_device *netdev, u64 *dat= a) +{ + struct fbnic_net *fbn =3D netdev_priv(netdev); + struct fbnic_dev *fbd =3D fbn->fbd; + + *data =3D fbnic_fw_mbx_self_test(fbd); + + return !!*data; +} + static void fbnic_self_test(struct net_device *netdev, struct ethtool_test *eth_test, u64 *data) { bool if_running =3D netif_running(netdev); =20 + if (fbnic_ethtool_mbx_self_test(netdev, &data[TEST_MBX])) + eth_test->flags |=3D ETH_TEST_FL_FAILED; + if (!(eth_test->flags & ETH_TEST_FL_OFFLINE)) { data[TEST_REG] =3D 0; data[TEST_MSIX] =3D 0; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ether= net/meta/fbnic/fbnic_fw.c index 1f0b6350bef4..c2bad51bdde6 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c @@ -378,6 +378,37 @@ fbnic_fw_get_cmpl_by_type(struct fbnic_dev *fbd, u32 m= sg_type) return cmpl_data; } =20 +/** + * fbnic_fw_xmit_test_msg - Create and transmit a test message to FW mailb= ox + * @fbd: FBNIC device structure + * @cmpl: fw completion struct + * + * Return: zero on success, negative value on failure + * + * Generates a single page mailbox test message and places it in the Tx + * mailbox queue. Expectation is that the FW will validate that the nested + * value matches the external values, and then will echo them back to us. + * + * Also sets a completion slot for use in the completion wait calls when + * the cmpl arg is non-NULL. + */ +int fbnic_fw_xmit_test_msg(struct fbnic_dev *fbd, + struct fbnic_fw_completion *cmpl) +{ + struct fbnic_tlv_msg *test_msg; + int err; + + test_msg =3D fbnic_tlv_test_create(fbd); + if (!test_msg) + return -ENOMEM; + + err =3D fbnic_mbx_map_req_w_cmpl(fbd, test_msg, cmpl); + if (err) + free_page((unsigned long)test_msg); + + return err; +} + /** * fbnic_fw_xmit_simple_msg - Transmit a simple single TLV message w/o data * @fbd: FBNIC device structure @@ -1556,7 +1587,29 @@ int fbnic_fw_xmit_send_logs(struct fbnic_dev *fbd, b= ool enable, return err; } =20 +static int +fbnic_fw_parser_test(void *opaque, struct fbnic_tlv_msg **results) +{ + struct fbnic_fw_completion *cmpl; + struct fbnic_dev *fbd =3D opaque; + int err; + + /* find cmpl */ + cmpl =3D fbnic_fw_get_cmpl_by_type(fbd, FBNIC_TLV_MSG_ID_TEST); + if (!cmpl) + return -ENOSPC; + + err =3D fbnic_tlv_parser_test(opaque, results); + + cmpl->result =3D err; + complete(&cmpl->done); + fbnic_fw_put_cmpl(cmpl); + + return err; +} + static const struct fbnic_tlv_parser fbnic_fw_tlv_parser[] =3D { + FBNIC_TLV_PARSER(TEST, fbnic_tlv_test_index, fbnic_fw_parser_test), FBNIC_TLV_PARSER(FW_CAP_RESP, fbnic_fw_cap_resp_index, fbnic_fw_parse_cap_resp), FBNIC_TLV_PARSER(OWNERSHIP_RESP, fbnic_ownership_resp_index, @@ -1787,6 +1840,53 @@ void fbnic_mbx_flush_tx(struct fbnic_dev *fbd) } while (time_is_after_jiffies(timeout)); } =20 +/** + * fbnic_fw_mbx_self_test() - verify firmware interface + * @fbd: device to test + * + * This function tests the interfaces to/from the firmware. + * + * Return: See enum fbnic_fw_self_test_codes + **/ +enum fbnic_fw_self_test_codes fbnic_fw_mbx_self_test(struct fbnic_dev *fbd) +{ + enum fbnic_fw_self_test_codes err; + struct fbnic_fw_completion *cmpl; + + /* Skip test if FW interface is not present */ + if (!fbnic_fw_present(fbd)) + return FBNIC_TEST_FW_NO_FIRMWARE; + + cmpl =3D fbnic_fw_alloc_cmpl(FBNIC_TLV_MSG_ID_TEST); + if (!cmpl) + return FBNIC_TEST_FW_NO_CMPL; + + /* Load a test message onto the FW mailbox interface + * and arm the completion. + */ + err =3D fbnic_fw_xmit_test_msg(fbd, cmpl); + if (err) { + err =3D FBNIC_TEST_FW_NO_XMIT; + goto exit_free; + } + + /* Verify we received a message back */ + if (!fbnic_mbx_wait_for_cmpl(cmpl)) { + err =3D FBNIC_TEST_FW_NO_MSG; + goto exit_cleanup; + } + + /* Verify there were no parsing errors */ + if (cmpl->result) + err =3D FBNIC_TEST_FW_PARSE; +exit_cleanup: + fbnic_mbx_clear_cmpl(fbd, cmpl); +exit_free: + fbnic_fw_put_cmpl(cmpl); + + return err; +} + int fbnic_fw_xmit_rpc_macda_sync(struct fbnic_dev *fbd) { struct fbnic_tlv_msg *mac_array; diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h b/drivers/net/ether= net/meta/fbnic/fbnic_fw.h index 8f7218900562..d84723e4cfa3 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h @@ -104,6 +104,33 @@ void fbnic_mbx_clear_cmpl(struct fbnic_dev *fbd, void fbnic_mbx_poll(struct fbnic_dev *fbd); int fbnic_mbx_poll_tx_ready(struct fbnic_dev *fbd); void fbnic_mbx_flush_tx(struct fbnic_dev *fbd); + +/** + * enum fbnic_fw_self_test_codes - return codes from self test routines + * + * These are the codes returned from the self test routines and + * stored in the test result array indexed by the specific + * test name. + * + * @FBNIC_TEST_FW_SUCCESS: test success + * @FBNIC_TEST_FW_NO_FIRMWARE: FW interface not present + * @FBNIC_TEST_FW_NO_CMPL: No completion available + * @FBNIC_TEST_FW_NO_XMIT: Could not xmit message + * @FBNIC_TEST_FW_NO_MSG: no message returned + * @FBNIC_TEST_FW_PARSE: returned message had parsing error + */ +enum fbnic_fw_self_test_codes { + FBNIC_TEST_FW_SUCCESS =3D 0, + FBNIC_TEST_FW_NO_FIRMWARE =3D 10, + FBNIC_TEST_FW_NO_CMPL =3D 20, + FBNIC_TEST_FW_NO_XMIT =3D 30, + FBNIC_TEST_FW_NO_MSG =3D 40, + FBNIC_TEST_FW_PARSE =3D 50, +}; + +enum fbnic_fw_self_test_codes fbnic_fw_mbx_self_test(struct fbnic_dev *fbd= ); +int fbnic_fw_xmit_test_msg(struct fbnic_dev *fbd, + struct fbnic_fw_completion *c); int fbnic_fw_xmit_ownership_msg(struct fbnic_dev *fbd, bool take_ownership= ); int fbnic_fw_init_heartbeat(struct fbnic_dev *fbd, bool poll); void fbnic_fw_check_heartbeat(struct fbnic_dev *fbd); --=20 2.43.0