{"id":2221936,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2221936/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-pci/patch/20260410-sdxi-base-v1-21-1d184cb5c60a@amd.com/","project":{"id":28,"url":"http://patchwork.ozlabs.org/api/1.1/projects/28/?format=json","name":"Linux PCI development","link_name":"linux-pci","list_id":"linux-pci.vger.kernel.org","list_email":"linux-pci@vger.kernel.org","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<20260410-sdxi-base-v1-21-1d184cb5c60a@amd.com>","date":"2026-04-10T13:07:31","name":"[21/23] dmaengine: sdxi: Add unit tests for descriptor encoding","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"ccc5950d2c890bdbe037c1eb3905eebe78b43e1b","submitter":{"id":91626,"url":"http://patchwork.ozlabs.org/api/1.1/people/91626/?format=json","name":"Nathan Lynch via B4 Relay","email":"devnull+nathan.lynch.amd.com@kernel.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-pci/patch/20260410-sdxi-base-v1-21-1d184cb5c60a@amd.com/mbox/","series":[{"id":499458,"url":"http://patchwork.ozlabs.org/api/1.1/series/499458/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-pci/list/?series=499458","date":"2026-04-10T13:07:10","name":"dmaengine: Smart Data Accelerator Interface (SDXI) basic support","version":1,"mbox":"http://patchwork.ozlabs.org/series/499458/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2221936/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2221936/checks/","tags":{},"headers":{"Return-Path":"\n <linux-pci+bounces-52332-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-pci@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256\n header.s=k20201202 header.b=M4JTqawH;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=linux-pci+bounces-52332-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=\"M4JTqawH\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=10.30.226.201"],"Received":["from tor.lore.kernel.org (tor.lore.kernel.org\n [IPv6:2600:3c04:e001:36c::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fscYz1xd6z1yGb\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 10 Apr 2026 23:08:39 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id CA7D5303DF52\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 10 Apr 2026 13:08:05 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 446E83C1987;\n\tFri, 10 Apr 2026 13:07:51 +0000 (UTC)","from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org\n [10.30.226.201])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 0300F3BED3D;\n\tFri, 10 Apr 2026 13:07:51 +0000 (UTC)","by smtp.kernel.org (Postfix) with ESMTPS id DE293C19421;\n\tFri, 10 Apr 2026 13:07:50 +0000 (UTC)","from aws-us-west-2-korg-lkml-1.web.codeaurora.org\n (localhost.localdomain [127.0.0.1])\n\tby smtp.lore.kernel.org (Postfix) with ESMTP id D929DF44862;\n\tFri, 10 Apr 2026 13:07:50 +0000 (UTC)"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775826471; cv=none;\n b=Om5i5zXvAtLL0QiWdVf5StaMqh2W35yJE0KiE0HSTd9jURdomnylW5nb1edsmuRWyUewN6tCARV9l7UNiJinqGTsQNGBlgiNQoKpQBQu/fuJk3z10YQDOKNG/vJrhlPUYh5p9IboVlsSCgidV5LFem05jvneTVMN8XExT2xO24E=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775826471; c=relaxed/simple;\n\tbh=YM8VU8aWLOhSa2zgTuPFVBkAqcL75HYPrjMg05rhMX8=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=nY3jgy0omOG+RAZBH0kH+dJ64DSH2ENm97ovx39T3RUVflieS9uibxuAsFZDrQGaFk6BNCcIRZj4LJfymB02omWyBNOHoOiDozA4ermD4ZonPKSYLbyYtArl6vBSkCeBMUBNWqC4o/JIKx/WnvgfUnw1U7Ranh1OAL16qAob5j4=","ARC-Authentication-Results":"i=1; smtp.subspace.kernel.org;\n dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org\n header.b=M4JTqawH; arc=none smtp.client-ip=10.30.226.201","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;\n\ts=k20201202; t=1775826470;\n\tbh=YM8VU8aWLOhSa2zgTuPFVBkAqcL75HYPrjMg05rhMX8=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From;\n\tb=M4JTqawH7vwjXA3qBtOkwKGLP6WKiCxj3tIN73BKkyRsDukNHCKv8lbXsjBX1q3cz\n\t 3Exr7Gs4MzUmgM0FSdLujAubQmVS8RnHwQvtYDz4TgU91b/91umVEETWIDIURWCNIJ\n\t uGAPMuMucvLiyQB+In4nOeNNooq3rpujiyC97bRygqoZP7uNn/DR7h/uCQsWQxv0g3\n\t nXOKyY28kDVJrsi5MgMjwqaLXKoThJpGR2eBUEEDJdRWLSV3EBvCQJ7hV97/YteQgS\n\t WlrcJwC1vnxPsD5UARCG+opVJoKNekq02RmNoMfh4NIBxS6Nn9HmeKU4te2/cvBFo1\n\t VdL4h3L4vNULw==","From":"Nathan Lynch via B4 Relay <devnull+nathan.lynch.amd.com@kernel.org>","Date":"Fri, 10 Apr 2026 08:07:31 -0500","Subject":"[PATCH 21/23] dmaengine: sdxi: Add unit tests for descriptor\n encoding","Precedence":"bulk","X-Mailing-List":"linux-pci@vger.kernel.org","List-Id":"<linux-pci.vger.kernel.org>","List-Subscribe":"<mailto:linux-pci+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-pci+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"7bit","Message-Id":"<20260410-sdxi-base-v1-21-1d184cb5c60a@amd.com>","References":"<20260410-sdxi-base-v1-0-1d184cb5c60a@amd.com>","In-Reply-To":"<20260410-sdxi-base-v1-0-1d184cb5c60a@amd.com>","To":"Vinod Koul <vkoul@kernel.org>","Cc":"Wei Huang <wei.huang2@amd.com>,\n Mario Limonciello <mario.limonciello@amd.com>,\n Bjorn Helgaas <bhelgaas@google.com>,\n Jonathan Cameron <jonathan.cameron@huawei.com>,\n Stephen Bates <Stephen.Bates@amd.com>, PradeepVineshReddy.Kodamati@amd.com,\n John.Kariuki@amd.com, linux-pci@vger.kernel.org,\n linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org,\n Nathan Lynch <nathan.lynch@amd.com>","X-Mailer":"b4 0.15.2","X-Developer-Signature":"v=1; a=ed25519-sha256; t=1775826467; l=16274;\n i=nathan.lynch@amd.com; s=20260410; h=from:subject:message-id;\n bh=2tw9BTJzJ0IPaXU3BSVre9DbnH5JMgDOs9LvzLhbO50=;\n b=hcm6Mi/KaHzj/iZCFf2FUpRBtrq8Sdp6aXAIlBfBSz4G5RTfsEZhGuJ5jKC0gRQaGAMs/2jYz\n C69tOLQOEPpAdLfvGOe2OBnFmezcLwunvwbNo5ttXKpjFdJqYp8PqS8","X-Developer-Key":"i=nathan.lynch@amd.com; a=ed25519;\n pk=PK4ozhq+/z9/2Jl5rgDmvHa9raVomv79qM8p1RAFpEw=","X-Endpoint-Received":"by B4 Relay for nathan.lynch@amd.com/20260410 with\n auth_id=728","X-Original-From":"Nathan Lynch <nathan.lynch@amd.com>","Reply-To":"nathan.lynch@amd.com"},"content":"From: Nathan Lynch <nathan.lynch@amd.com>\n\nTest the encoder function for each descriptor type currently used by\nthe driver.\n\nThe production code uses the GENMASK()/BIT() family of macros to\nsupport encoding descriptors. The tests for that code use the packing\nAPI to decode descriptors produced by that code without relying on\nthose bitmask definitions.\n\nBy limiting what's shared between the real code and the tests we gain\nconfidence in both. If both the driver code and the tests rely on the\nbitfield macros, and then upon adding a new descriptor field the\nauthor mistranslates the bit numbering from the spec, that error is\nmore likely to propagate to the tests undetected than if the test code\nrelies on a separate mechanism for decoding descriptors.\n\nCo-developed-by: Wei Huang <wei.huang2@amd.com>\nSigned-off-by: Wei Huang <wei.huang2@amd.com>\nSigned-off-by: Nathan Lynch <nathan.lynch@amd.com>\n---\n drivers/dma/sdxi/Kconfig            |   1 +\n drivers/dma/sdxi/Makefile           |   1 +\n drivers/dma/sdxi/descriptor_kunit.c | 484 ++++++++++++++++++++++++++++++++++++\n 3 files changed, 486 insertions(+)","diff":"diff --git a/drivers/dma/sdxi/Kconfig b/drivers/dma/sdxi/Kconfig\nindex e616d3e323bc..39343eb85614 100644\n--- a/drivers/dma/sdxi/Kconfig\n+++ b/drivers/dma/sdxi/Kconfig\n@@ -11,6 +11,7 @@ config SDXI_KUNIT_TEST\n \ttristate \"SDXI unit tests\" if !KUNIT_ALL_TESTS\n \tdepends on SDXI && KUNIT\n \tdefault KUNIT_ALL_TESTS\n+\tselect PACKING\n \thelp\n \t  KUnit tests for parts of the SDXI driver. Does not require\n \t  SDXI hardware.\ndiff --git a/drivers/dma/sdxi/Makefile b/drivers/dma/sdxi/Makefile\nindex 08dd73a45dc7..419c71c2ef6a 100644\n--- a/drivers/dma/sdxi/Makefile\n+++ b/drivers/dma/sdxi/Makefile\n@@ -11,4 +11,5 @@ sdxi-objs += \\\n sdxi-$(CONFIG_PCI_MSI) += pci.o\n \n obj-$(CONFIG_SDXI_KUNIT_TEST) += \\\n+\tdescriptor_kunit.o    \\\n \tring_kunit.o\ndiff --git a/drivers/dma/sdxi/descriptor_kunit.c b/drivers/dma/sdxi/descriptor_kunit.c\nnew file mode 100644\nindex 000000000000..1f3c2e7ab2dd\n--- /dev/null\n+++ b/drivers/dma/sdxi/descriptor_kunit.c\n@@ -0,0 +1,484 @@\n+// SPDX-License-Identifier: GPL-2.0-only\n+/*\n+ * SDXI descriptor encoding tests.\n+ *\n+ * Copyright Advanced Micro Devices, Inc.\n+ *\n+ * While the driver code uses bitfield macros (BIT, GENMASK) to encode\n+ * descriptors, these tests use the packing API to decode them.\n+ * Capturing the descriptor layout using PACKED_FIELD() is basically a\n+ * copy-paste exercise since SDXI defines control structure fields in\n+ * terms of bit offsets. Eschewing the bitfield constants such as\n+ * SDXI_DSC_VL in the test code makes it possible for the tests to\n+ * detect any mistakes in defining them.\n+ *\n+ * Note that the checks in unpack_fields() can be quite time-consuming\n+ * at build time. Uncomment '#define SKIP_PACKING_CHECKS' below if\n+ * that's too annoying when working on this code.\n+ */\n+#include <kunit/device.h>\n+#include <kunit/test-bug.h>\n+#include <kunit/test.h>\n+#include <linux/container_of.h>\n+#include <linux/dma-mapping.h>\n+#include <linux/module.h>\n+#include <linux/packing.h>\n+#include <linux/stddef.h>\n+#include <linux/string.h>\n+\n+#include \"descriptor.h\"\n+\n+/* #define SKIP_PACKING_CHECKS */\n+\n+MODULE_IMPORT_NS(\"EXPORTED_FOR_KUNIT_TESTING\");\n+\n+enum {\n+\tSDXI_PACKING_QUIRKS = QUIRK_LITTLE_ENDIAN | QUIRK_LSW32_IS_FIRST,\n+};\n+\n+\n+#define desc_field(_high, _low, _target_struct, _member) \\\n+\tPACKED_FIELD(_high, _low, _target_struct, _member)\n+#define desc_flag(_bit, _target_struct, _member) \\\n+\tdesc_field(_bit, _bit, _target_struct, _member)\n+\n+/* DMAB_COPY */\n+struct unpacked__copy {\n+\tu32 size;\n+\tu8 attr_src;\n+\tu8 attr_dst;\n+\tu16 akey0;\n+\tu16 akey1;\n+\tu64 addr0;\n+\tu64 addr1;\n+};\n+\n+#define copy_field(_high, _low, _member) \\\n+\tdesc_field(_high, _low, struct unpacked__copy, _member)\n+\n+static const struct packed_field_u16 copy_subfields[] = {\n+\tcopy_field(63, 32, size),\n+\tcopy_field(67, 64, attr_src),\n+\tcopy_field(71, 68, attr_dst),\n+\tcopy_field(111, 96, akey0),\n+\tcopy_field(127, 112, akey1),\n+\tcopy_field(191, 128, addr0),\n+\tcopy_field(255, 192, addr1),\n+};\n+\n+/* DSC_INTR */\n+struct unpacked__intr {\n+\tu16 akey;\n+};\n+\n+#define intr_field(_high, _low, _member) \\\n+\tdesc_field(_high, _low, struct unpacked__intr, _member)\n+\n+static const struct packed_field_u16 intr_subfields[] = {\n+\tintr_field(111, 96, akey),\n+};\n+\n+/* DSC_SYNC */\n+struct unpacked__sync {\n+\tu8 flt;\n+\tbool vf;\n+\tu16 vf_num;\n+\tu16 cxt_start;\n+\tu16 cxt_end;\n+\tu16 key_start;\n+\tu16 key_end;\n+};\n+\n+#define sync_field(_high, _low, _member) \\\n+\tdesc_field(_high, _low, struct unpacked__sync, _member)\n+#define sync_flag(_bit, _member) sync_field(_bit, _bit, _member)\n+\n+static const struct packed_field_u16 sync_subfields[] = {\n+\tsync_field(34, 32, flt),\n+\tsync_flag(47, vf),\n+\tsync_field(63, 48, vf_num),\n+\tsync_field(79, 64, cxt_start),\n+\tsync_field(95, 80, cxt_end),\n+\tsync_field(111, 96, key_start),\n+\tsync_field(127, 112, key_end),\n+};\n+\n+/* DSC_CXT_START */\n+struct unpacked__cxt_start {\n+\tbool dv;\n+\tbool vf;\n+\tu16 vf_num;\n+\tu16 cxt_start;\n+\tu16 cxt_end;\n+\tu64 db_value;\n+};\n+\n+#define cxt_start_field(_high, _low, _member) \\\n+\tdesc_field(_high, _low, struct unpacked__cxt_start, _member)\n+#define cxt_start_flag(_bit, _member) cxt_start_field(_bit, _bit, _member)\n+\n+static const struct packed_field_u16 cxt_start_subfields[] = {\n+\tcxt_start_flag(46, dv),\n+\tcxt_start_flag(47, vf),\n+\tcxt_start_field(63, 48, vf_num),\n+\tcxt_start_field(79, 64, cxt_start),\n+\tcxt_start_field(95, 80, cxt_end),\n+\tcxt_start_field(191, 128, db_value),\n+};\n+\n+/* DSC_CXT_STOP */\n+struct unpacked__cxt_stop {\n+\tbool hs;\n+\tbool vf;\n+\tu16 vf_num;\n+\tu16 cxt_start;\n+\tu16 cxt_end;\n+};\n+\n+#define cxt_stop_field(_high, _low, _member) \\\n+\tdesc_field(_high, _low, struct unpacked__cxt_stop, _member)\n+#define cxt_stop_flag(_bit, _member) cxt_stop_field(_bit, _bit, _member)\n+\n+static const struct packed_field_u16 cxt_stop_subfields[] = {\n+\tcxt_stop_flag(45, hs),\n+\tcxt_stop_flag(47, vf),\n+\tcxt_stop_field(63, 48, vf_num),\n+\tcxt_stop_field(79, 64, cxt_start),\n+\tcxt_stop_field(95, 80, cxt_end),\n+};\n+\n+/* DSC_GENERIC */\n+struct unpacked_desc {\n+\tu64 csb_ptr;\n+\tu16 type;\n+\tu8 subtype;\n+\tbool vl;\n+\tbool se;\n+\tbool fe;\n+\tbool ch;\n+\tbool csr;\n+\tbool rb;\n+\tbool np;\n+\tunion {\n+\t\tstruct unpacked__copy copy;\n+\t\tstruct unpacked__intr intr;\n+\t\tstruct unpacked__sync sync;\n+\t\tstruct unpacked__cxt_start cxt_start;\n+\t\tstruct unpacked__cxt_stop cxt_stop;\n+\t};\n+};\n+\n+#define generic_field(_high, _low, _member)\t\t\t\\\n+\tdesc_field(_high, _low, struct unpacked_desc, _member)\n+#define generic_flag(_bit, _member) generic_field(_bit, _bit, _member)\n+\n+static const struct packed_field_u16 generic_subfields[] = {\n+\tgeneric_flag(0, vl),\n+\tgeneric_flag(1, se),\n+\tgeneric_flag(2, fe),\n+\tgeneric_flag(3, ch),\n+\tgeneric_flag(4, csr),\n+\tgeneric_flag(5, rb),\n+\tgeneric_field(15, 8, subtype),\n+\tgeneric_field(26, 16, type),\n+\tgeneric_flag(448, np),\n+\tgeneric_field(511, 453, csb_ptr),\n+};\n+\n+#ifndef SKIP_PACKING_CHECKS\n+#define define_unpack_fn(_T)\t\t\t\t\t\t\\\n+\tstatic void unpack_ ## _T(struct unpacked_desc *to,\t\t\\\n+\t\t\t\t  const struct sdxi_desc *from)\t\t\\\n+\t{\t\t\t\t\t\t\t\t\\\n+\t\tunpack_fields(from, sizeof(*from), to,\t\\\n+\t\t\t      generic_subfields, SDXI_PACKING_QUIRKS);\t\\\n+\t\tunpack_fields(from, sizeof(*from), &to->_T,\t\t\\\n+\t\t\t      _T ## _subfields, SDXI_PACKING_QUIRKS);\t\\\n+\t}\n+#else\n+#define define_unpack_fn(_T)\t\t\t\t\t\t\\\n+\tstatic void unpack_ ## _T(struct unpacked_desc *to,\t\t\\\n+\t\t\t\t  const struct sdxi_desc *from)\t\t\\\n+\t{\t\t\t\t\t\t\t\t\\\n+\t\tunpack_fields_u16(from, sizeof(*from), to,\t\t\\\n+\t\t\t\t  generic_subfields,\t\t\t\\\n+\t\t\t\t  ARRAY_SIZE(generic_subfields),\t\\\n+\t\t\t\t  SDXI_PACKING_QUIRKS);\t\t\t\\\n+\t\tunpack_fields_u16(from, sizeof(*from), &to->_T,\t\t\\\n+\t\t\t\t  _T ## _subfields,\t\t\t\\\n+\t\t\t\t  ARRAY_SIZE(_T ## _subfields),\t\t\\\n+\t\t\t\t  SDXI_PACKING_QUIRKS);\t\t\t\\\n+\t}\n+#endif\t/* SKIP_PACKING_CHECKS */\n+\n+define_unpack_fn(intr)\n+define_unpack_fn(copy)\n+define_unpack_fn(sync)\n+define_unpack_fn(cxt_start)\n+define_unpack_fn(cxt_stop)\n+\n+static void desc_poison(struct sdxi_desc *d)\n+{\n+\tmemset(d, 0xff, sizeof(*d));\n+}\n+\n+static void encode_size32(struct kunit *t)\n+{\n+\t__le32 res = cpu_to_le32(U32_MAX);\n+\n+\t/* Valid sizes. */\n+\tKUNIT_EXPECT_EQ(t, 0, sdxi_encode_size32(1, &res));\n+\tKUNIT_EXPECT_EQ(t, 0, le32_to_cpu(res));\n+\n+\tKUNIT_EXPECT_EQ(t, 0, sdxi_encode_size32(SZ_4K, &res));\n+\tKUNIT_EXPECT_EQ(t, SZ_4K - 1, le32_to_cpu(res));\n+\n+\tKUNIT_EXPECT_EQ(t, 0, sdxi_encode_size32(SZ_4M, &res));\n+\tKUNIT_EXPECT_EQ(t, SZ_4M - 1, le32_to_cpu(res));\n+\n+\tKUNIT_EXPECT_EQ(t, 0, sdxi_encode_size32(SZ_4G - 1, &res));\n+\tKUNIT_EXPECT_EQ(t, SZ_4G - 2, le32_to_cpu(res));\n+\n+\tKUNIT_EXPECT_EQ(t, 0, sdxi_encode_size32(SZ_4G, &res));\n+\tKUNIT_EXPECT_EQ(t, SZ_4G - 1, le32_to_cpu(res));\n+\n+\t/* Invalid sizes. Ensure the out parameter is unmodified. */\n+#define RES_VAL 0x843829\n+\tres = cpu_to_le32(RES_VAL);\n+\n+\tKUNIT_EXPECT_EQ(t, -EINVAL, sdxi_encode_size32(0, &res));\n+\tKUNIT_EXPECT_EQ(t, RES_VAL, le32_to_cpu(res));\n+\n+\tKUNIT_EXPECT_EQ(t, -EINVAL, sdxi_encode_size32(SZ_4G + 1, &res));\n+\tKUNIT_EXPECT_EQ(t, RES_VAL, le32_to_cpu(res));\n+\n+\tKUNIT_EXPECT_EQ(t, -EINVAL, sdxi_encode_size32(SZ_8G, &res));\n+\tKUNIT_EXPECT_EQ(t, RES_VAL, le32_to_cpu(res));\n+\n+\tKUNIT_EXPECT_EQ(t, -EINVAL, sdxi_encode_size32(U64_MAX, &res));\n+\tKUNIT_EXPECT_EQ(t, RES_VAL, le32_to_cpu(res));\n+\n+#undef RES_VAL\n+}\n+\n+static void copy(struct kunit *t)\n+{\n+\tstruct unpacked_desc unpacked;\n+\tstruct sdxi_desc desc = {};\n+\tstruct sdxi_copy copy = {\n+\t\t.src = 0x1000,\n+\t\t.dst = 0x2000,\n+\t\t.len = 4096,\n+\t\t.src_akey = 0,\n+\t\t.dst_akey = 0,\n+\t};\n+\n+\tKUNIT_EXPECT_EQ(t, 0, sdxi_encode_copy(&desc, &copy));\n+\n+\tunpack_copy(&unpacked, &desc);\n+\tKUNIT_EXPECT_EQ(t, unpacked.vl, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.ch, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.subtype, SDXI_DSC_OP_SUBTYPE_COPY);\n+\tKUNIT_EXPECT_EQ(t, unpacked.type, SDXI_DSC_OP_TYPE_DMAB);\n+\tKUNIT_EXPECT_EQ(t, unpacked.csb_ptr, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.np, 1);\n+\n+\tKUNIT_EXPECT_EQ(t, unpacked.copy.size, copy.len - 1);\n+\n+\t/* Zero isn't a valid size. */\n+\tdesc_poison(&desc);\n+\tcopy.len = 0;\n+\tKUNIT_EXPECT_EQ(t, -EINVAL, sdxi_encode_copy(&desc, &copy));\n+\n+\t/* But 1 is. */\n+\tdesc_poison(&desc);\n+\tcopy.len = 1;\n+\tKUNIT_EXPECT_EQ(t, 0, sdxi_encode_copy(&desc, &copy));\n+\tunpack_copy(&unpacked, &desc);\n+\tKUNIT_EXPECT_EQ(t, unpacked.copy.size, copy.len - 1);\n+\n+\t/* SDXI forbids overlapping source and destination. */\n+\tdesc_poison(&desc);\n+\tcopy.len = 4097;\n+\tKUNIT_EXPECT_EQ(t, -EINVAL, sdxi_encode_copy(&desc, &copy));\n+\tcopy = (typeof(copy)) {\n+\t\t.src = 0x4000,\n+\t\t.dst = 0x4000,\n+\t\t.len = 1,\n+\t\t.src_akey = 0,\n+\t\t.dst_akey = 0,\n+\t};\n+\tKUNIT_EXPECT_EQ(t, -EINVAL, sdxi_encode_copy(&desc, &copy));\n+\n+\tdesc_poison(&desc);\n+\tKUNIT_EXPECT_EQ(t, 0,\n+\t\t\tsdxi_encode_copy(&desc,\n+\t\t\t\t\t &(struct sdxi_copy) {\n+\t\t\t\t\t\t .src = 0x1000,\n+\t\t\t\t\t\t .dst = 0x2000,\n+\t\t\t\t\t\t .len = 0x100,\n+\t\t\t\t\t\t .src_akey = 1,\n+\t\t\t\t\t\t .dst_akey = 2,\n+\t\t\t\t\t }));\n+\tKUNIT_EXPECT_EQ(t, 0x1000, le64_to_cpu(desc.copy.addr0));\n+\tKUNIT_EXPECT_EQ(t, 0x2000, le64_to_cpu(desc.copy.addr1));\n+\tKUNIT_EXPECT_EQ(t, 0x100, 1 + le32_to_cpu(desc.copy.size));\n+\tKUNIT_EXPECT_EQ(t, 1, le16_to_cpu(desc.copy.akey0));\n+\tKUNIT_EXPECT_EQ(t, 2, le16_to_cpu(desc.copy.akey1));\n+\n+\tunpack_copy(&unpacked, &desc);\n+\tKUNIT_EXPECT_EQ(t, unpacked.vl, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.ch, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.subtype, SDXI_DSC_OP_SUBTYPE_COPY);\n+\tKUNIT_EXPECT_EQ(t, unpacked.type, SDXI_DSC_OP_TYPE_DMAB);\n+\tKUNIT_EXPECT_EQ(t, unpacked.csb_ptr, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.np, 1);\n+\n+\tKUNIT_EXPECT_EQ(t, unpacked.copy.size, 0x100 - 1);\n+}\n+\n+static void intr(struct kunit *t)\n+{\n+\tstruct unpacked_desc unpacked;\n+\tstruct sdxi_intr intr = {\n+\t\t.akey = 1234,\n+\t};\n+\tstruct sdxi_desc desc;\n+\n+\tdesc_poison(&desc);\n+\tKUNIT_EXPECT_EQ(t, 0, sdxi_encode_intr(&desc, &intr));\n+\n+\tunpack_intr(&unpacked, &desc);\n+\tKUNIT_EXPECT_EQ(t, unpacked.vl, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.ch, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.subtype, SDXI_DSC_OP_SUBTYPE_INTR);\n+\tKUNIT_EXPECT_EQ(t, unpacked.type, SDXI_DSC_OP_TYPE_INTR);\n+\tKUNIT_EXPECT_EQ(t, unpacked.csb_ptr, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.np, 1);\n+\n+\tKUNIT_EXPECT_EQ(t, unpacked.intr.akey, 1234);\n+}\n+\n+static void cxt_start(struct kunit *t)\n+{\n+\tstruct unpacked_desc unpacked;\n+\tstruct sdxi_cxt_start start = {\n+\t\t.range = sdxi_cxt_range_single(2),\n+\t};\n+\tstruct sdxi_desc desc;\n+\n+\tdesc_poison(&desc);\n+\tKUNIT_ASSERT_EQ(t, 0, sdxi_encode_cxt_start(&desc, &start));\n+\n+\tunpack_cxt_start(&unpacked, &desc);\n+\n+\t/* Check op-specific fields. */\n+\tKUNIT_EXPECT_EQ(t, 0, desc.cxt_start.vflags);\n+\n+\t/*\n+\t * Check generic fields. Some flags have mandatory values\n+\t * according to the operation type.\n+\t */\n+\tKUNIT_EXPECT_EQ(t, unpacked.vl, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.se, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.fe, 1);\n+\tKUNIT_EXPECT_EQ(t, unpacked.ch, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.subtype, SDXI_DSC_OP_SUBTYPE_CXT_START_NM);\n+\tKUNIT_EXPECT_EQ(t, unpacked.type, SDXI_DSC_OP_TYPE_ADMIN);\n+\tKUNIT_EXPECT_EQ(t, unpacked.csb_ptr, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.np, 1);\n+\n+\tKUNIT_EXPECT_FALSE(t, unpacked.cxt_start.dv);\n+\tKUNIT_EXPECT_FALSE(t, unpacked.cxt_start.vf);\n+\tKUNIT_EXPECT_EQ(t, unpacked.cxt_start.cxt_start, 2);\n+\tKUNIT_EXPECT_EQ(t, unpacked.cxt_start.cxt_end, 2);\n+\tKUNIT_EXPECT_EQ(t, unpacked.cxt_start.vf_num, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.cxt_start.db_value, 0);\n+}\n+\n+static void cxt_stop(struct kunit *t)\n+{\n+\tstruct unpacked_desc unpacked;\n+\tstruct sdxi_cxt_stop stop = {\n+\t\t.range = sdxi_cxt_range_single(2),\n+\t};\n+\tstruct sdxi_desc desc;\n+\n+\tdesc_poison(&desc);\n+\tKUNIT_ASSERT_EQ(t, 0, sdxi_encode_cxt_stop(&desc, &stop));\n+\n+\tunpack_cxt_stop(&unpacked, &desc);\n+\n+\t/* Check op-specific fields. */\n+\tKUNIT_EXPECT_EQ(t, 0, desc.cxt_start.vflags);\n+\n+\t/*\n+\t * Check generic fields. Some flags have mandatory values\n+\t * according to the operation type.\n+\t */\n+\tKUNIT_EXPECT_EQ(t, unpacked.vl, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.se, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.fe, 1);\n+\tKUNIT_EXPECT_EQ(t, unpacked.ch, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.subtype, SDXI_DSC_OP_SUBTYPE_CXT_STOP);\n+\tKUNIT_EXPECT_EQ(t, unpacked.type, SDXI_DSC_OP_TYPE_ADMIN);\n+\tKUNIT_EXPECT_EQ(t, unpacked.csb_ptr, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.np, 1);\n+\n+\tKUNIT_EXPECT_FALSE(t, unpacked.cxt_stop.hs);\n+\tKUNIT_EXPECT_FALSE(t, unpacked.cxt_stop.vf);\n+\tKUNIT_EXPECT_EQ(t, unpacked.cxt_stop.cxt_start, 2);\n+\tKUNIT_EXPECT_EQ(t, unpacked.cxt_stop.cxt_end, 2);\n+\tKUNIT_EXPECT_EQ(t, unpacked.cxt_stop.vf_num, 0);\n+}\n+\n+static void sync(struct kunit *t)\n+{\n+\tstruct sdxi_sync sync = {\n+\t\t.filter = SDXI_SYNC_FLT_STOP,\n+\t\t.range = sdxi_cxt_range(1, U16_MAX),\n+\t};\n+\tstruct sdxi_desc desc;\n+\tstruct unpacked_desc unpacked;\n+\n+\tdesc_poison(&desc);\n+\tKUNIT_ASSERT_EQ(t, 0, sdxi_encode_sync(&desc, &sync));\n+\tunpack_sync(&unpacked, &desc);\n+\n+\tKUNIT_EXPECT_EQ(t, unpacked.type, SDXI_DSC_OP_TYPE_ADMIN);\n+\tKUNIT_EXPECT_EQ(t, unpacked.subtype, SDXI_DSC_OP_SUBTYPE_SYNC);\n+\tKUNIT_EXPECT_EQ(t, unpacked.ch, 0);\n+\tKUNIT_EXPECT_EQ(t, unpacked.sync.flt, SDXI_SYNC_FLT_STOP);\n+\tKUNIT_EXPECT_EQ(t, unpacked.sync.cxt_start, 1);\n+\tKUNIT_EXPECT_EQ(t, unpacked.sync.cxt_end, U16_MAX);\n+}\n+\n+static struct kunit_case generic_desc_tcs[] = {\n+\tKUNIT_CASE(encode_size32),\n+\tKUNIT_CASE(copy),\n+\tKUNIT_CASE(intr),\n+\tKUNIT_CASE(cxt_start),\n+\tKUNIT_CASE(cxt_stop),\n+\tKUNIT_CASE(sync),\n+\t{}\n+};\n+\n+static int generic_desc_setup_device(struct kunit *t)\n+{\n+\tstruct device *dev = kunit_device_register(t, \"sdxi-mock-device\");\n+\n+\tKUNIT_ASSERT_NOT_ERR_OR_NULL(t, dev);\n+\tt->priv = dev;\n+\treturn 0;\n+}\n+\n+static struct kunit_suite generic_desc_ts = {\n+\t.name = \"Generic SDXI descriptor encoding\",\n+\t.test_cases = generic_desc_tcs,\n+\t.init = generic_desc_setup_device,\n+};\n+kunit_test_suite(generic_desc_ts);\n+\n+MODULE_DESCRIPTION(\"SDXI descriptor encoding tests\");\n+MODULE_AUTHOR(\"Nathan Lynch\");\n+MODULE_LICENSE(\"GPL\");\n","prefixes":["21/23"]}