From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CC8332701B1; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098130; cv=none; b=etLPSqsxOuMZrPqcTB4IZfyp9MOqzPPPiN+QkpRLog1hkIJCCQkB/LHZ6psTmU1a3IKFtFsTuqV869SwVqFO4yWetHuMc+ZT96IJVxCNoYRQTCsiqdAW1GJp30mXNc3mPoeWxH4ycxufv4qJ9qpwb+s13eRHJbdjLeXx0chASfg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098130; c=relaxed/simple; bh=cNmbCY+t6TV7EQ7mnMPyCQFcbNB1z1uoW0jwR/JCPok=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LiVcJU8funfeU8V3ZvjWb8gcW6BT7rmoSkCXQm42esivN2qIDY2EM0brxPYChUYLwdTKYSSXkxNdxhRyNrRoZu3UKf9mrgA8iu3gfoUhpJxcbzGXRzKP3BoK8kE4w37j/Kggx+hDArqnZsswlKPorDRRgLgGq5smu7qrKPAkUaM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FgYAYDcw; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FgYAYDcw" Received: by smtp.kernel.org (Postfix) with ESMTPS id 74AD3C4CEF8; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098130; bh=cNmbCY+t6TV7EQ7mnMPyCQFcbNB1z1uoW0jwR/JCPok=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=FgYAYDcwg+Tfk8Ex5OAOY+CUlAtyv3a2MItV3sKoUEWVofm0n6JKc7yxtM8RI+sFa gfZrVGVviNm3V+7zrxvQh6WiLcCns+h72bYtchiwXAAOufk5fX/3e+YRhD57Si6AQR LQWBKS1AdfWCiYETP/oN2qZLif6ZMrkt9v1qBEhE+9acEcq0eYVDn1Hba2brz5E7EZ rLgo2H6VMIMrQpfqDmYqR0djAtQKr6Go8daBKTm88fH7wtB96EEyErTeqvGM/SCrZy rJxY2J8QCM6y38KgMt74g3qSSNC0jAulBQKFFVfgk73vmN30B76+g3CU4/Oha0fziK vbr0ceY7x7hrg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5D325CA0FED; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:24 -0500 Subject: [PATCH RFC 01/13] PCI: Add SNIA SDXI accelerator sub-class Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-1-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098128; l=1221; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=cLbH23/lVKsKayqAoeaUUitg+lat6CFljkhFBcYIeRM=; b=z9iadhwq4aD126u/pxl2+eSCYi+5s2XIYfBIZ0WB/TKWi1ktB0fifgdSB9s7gYkn25U3fmNN1 QlPrDkwGK6PBcfvYKWduOxi3i5WNamHtWmlNveGYblcipp4gDeqSIL3 X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch This was added to the PCI Code and ID Assignment Specification in revision 1.14 (2021). Refer to 1.19. "Base Class 12h" of that document as well as the "SDXI PCI-Express Device Architecture" chapter of the SDXI specification: """ SDXI functions are expected to be identified through the SDXI class code. * SNIA Smart Data Accelerator Interface (SDXI) controller: * Base Class =3D 0x12 * Sub Class =3D 0x01 * Programming Interface =3D 0x0 """ Information about SDXI may be found at the SNIA website: https://www.snia.org/sdxi Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- include/linux/pci_ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 92ffc4373f6de3dcf82226a50d0e36af366e888e..ac9bb3d64949919019d40d1f86c= d3658bfb1c661 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -154,6 +154,7 @@ =20 #define PCI_BASE_CLASS_ACCELERATOR 0x12 #define PCI_CLASS_ACCELERATOR_PROCESSING 0x1200 +#define PCI_CLASS_ACCELERATOR_SDXI 0x120100 =20 #define PCI_CLASS_OTHERS 0xff =20 --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CA123266EF1; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098130; cv=none; b=uYh293t1ev7x7EB94GK65tPfTNnM4nskBb8TW+T2uzn6C9+Bawdh9t61joC3OBx3XcYJJtNWaA4RY+JNJf2Zse6lPLsDKJGjdpToOjOLY7WahBtE7GD48Y7nD9gzodGvADgE1hlRqdsdWpxsfkyIm2mojO+AoFpVM706HPM4Qjk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098130; c=relaxed/simple; bh=Rw+cTPsK8UY84BYmUMrDlUQJRiodAoy6jQpwhK25JPM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VmMPxG3D6OvMSViM9DeT5JUf+WM25uDUxiO6AomEKJ4id2o9HdQNkWM5SCKhkZVPdt3R7HCh8RtX5bQbguum1BQYcZBbxjeTQ2jARt7K7CZtzNEO3Sonrgca25RyGe/SFm7EEvTwK3aWIVovt3ZRkvKFmgSV9vEwAdQpC0mlYZQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lqvOitLp; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="lqvOitLp" Received: by smtp.kernel.org (Postfix) with ESMTPS id 7FD83C4CEF7; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098130; bh=Rw+cTPsK8UY84BYmUMrDlUQJRiodAoy6jQpwhK25JPM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=lqvOitLphJb7KVP3y7zZwHqQFf7hfcak6X3LeqPyva1h3dbcyITyMFXPu3OIeXGTa HWApatfHGkr51P8n4Nyleqd52cQ4WyTl+ydL/hJnA4/reknegOnekVtx7bKnuXpZZz 3nrV9tUOOWBGrzBKxVal1vp+AF4YTy7wgE7JS2sXnRV+3y7Fh1EHHQJhFAUa4aW4ti kBIfrjJbU222ClZdCrpkVlT1JmWFne5Ek/+HS/0muMf8cfN7mN2X07gXD89hgWGdgo PlomLc2PA9HUWECZVTEOAscMGth4r76VE0ItKnYn/6nwHOdyqSlnLO0JuaeE4Ob7vq g/b0pQu/MGmCg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6A7B9CA1016; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:25 -0500 Subject: [PATCH RFC 02/13] dmaengine: sdxi: Add control structure definitions Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-2-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098128; l=8206; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=LtALJDsZZcNVuQomuX0ryG8qKKEmQgfZsMY945HU3DI=; b=VmhOE7l2pTRn9K5Irjx4OXk1BllKBLscXAZDVayTXJ71gxJU1AwvUwRf2VshAqUaKDoy/g1sG 8vZtgtr3NQHAquGGB+oQ27rqTvDFsiUkPvWm633XR4m+91DhTf5ay4d X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch SDXI defines a multitude of control structures that reside in system memory and are shared between software and the implementation. Add: * C struct definitions for the SDXI control structures to be used by the driver; * Bitmask constants for accessing fields and subfields of the control structures; * Symbolic constants corresponding to significant values such as context states and commands. Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- drivers/dma/sdxi/hw.h | 249 ++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 249 insertions(+) diff --git a/drivers/dma/sdxi/hw.h b/drivers/dma/sdxi/hw.h new file mode 100644 index 0000000000000000000000000000000000000000..4ac0e200773b0646e84a65794e0= 2cdf9e583db6d --- /dev/null +++ b/drivers/dma/sdxi/hw.h @@ -0,0 +1,249 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (C) 2025 Advanced Micro Devices, Inc. */ + +/* + * Control structures and constants defined in the SDXI specification, + * with low-level accessors. The ordering of the structures here + * follows the order of their definitions in the SDXI spec. + * + * Names of structures, members, and subfields (bit ranges within + * members) are written to match the spec, generally. E.g. struct + * sdxi_cxt_l2_ent corresponds to CXT_L2_ENT in the spec. + * + * Note: a member can have a subfield whose name is identical to the + * member's name. E.g. CXT_L2_ENT's lv01_ptr. + * + * All reserved fields and bits (usually named "rsvd" or some + * variation) must be set to zero by the driver unless otherwise + * specified. + */ + +#ifndef LINUX_SDXI_HW_H +#define LINUX_SDXI_HW_H + +#include +#include +#include +#include +#include +#include +#include + +/* Context Level 2 Table Entry (CXT_L2_ENT) */ +struct sdxi_cxt_l2_ent { + __le64 lv01_ptr; +#define SDXI_CXT_L2_ENT_LV01_PTR GENMASK_ULL(63, 12) +#define SDXI_CXT_L2_ENT_VL BIT_ULL(0) +} __packed; +static_assert(sizeof(struct sdxi_cxt_l2_ent) =3D=3D 8); + +/* + * The level 2 table is 4KB and has 512 level 1 pointer entries. + */ +#define SDXI_L2_TABLE_ENTRIES 512 +struct sdxi_cxt_l2_table { + struct sdxi_cxt_l2_ent entry[SDXI_L2_TABLE_ENTRIES]; +}; +static_assert(sizeof(struct sdxi_cxt_l2_table) =3D=3D 4096); + +/* Context level 1 table entry (CXT_L1_ENT) */ +struct sdxi_cxt_l1_ent { + __le64 cxt_ctl_ptr; +#define SDXI_CXT_L1_ENT_VL BIT_ULL(0) +#define SDXI_CXT_L1_ENT_KA BIT_ULL(1) +#define SDXI_CXT_L1_ENT_PV BIT_ULL(2) +#define SDXI_CXT_L1_ENT_CXT_CTL_PTR GENMASK_ULL(63, 6) + __le64 akey_ptr; +#define SDXI_CXT_L1_ENT_AKEY_SZ GENMASK_ULL(3, 0) +#define SDXI_CXT_L1_ENT_AKEY_PTR GENMASK_ULL(63, 12) + __le32 misc0; +#define SDXI_CXT_L1_ENT_PASID GENMASK(19, 0) +#define SDXI_CXT_L1_ENT_MAX_BUFFER GENMASK(23, 20) + __le32 opb_000_enb; + __u8 rsvd_0[8]; +} __packed; +static_assert(sizeof(struct sdxi_cxt_l1_ent) =3D=3D 32); + +#define SDXI_L1_TABLE_ENTRIES 128 +struct sdxi_cxt_l1_table { + struct sdxi_cxt_l1_ent entry[SDXI_L1_TABLE_ENTRIES]; +}; +static_assert(sizeof(struct sdxi_cxt_l1_table) =3D=3D 4096); + +/* Context control block (CXT_CTL) */ +struct sdxi_cxt_ctl { + __le64 ds_ring_ptr; +#define SDXI_CXT_CTL_VL BIT_ULL(0) +#define SDXI_CXT_CTL_QOS GENMASK_ULL(3, 2) +#define SDXI_CXT_CTL_SE BIT_ULL(4) +#define SDXI_CXT_CTL_CSA BIT_ULL(5) +#define SDXI_CXT_CTL_DS_RING_PTR GENMASK_ULL(63, 6) + __le32 ds_ring_sz; + __u8 rsvd_0[4]; + __le64 cxt_sts_ptr; +#define SDXI_CXT_CTL_CXT_STS_PTR GENMASK_ULL(63, 4) + __le64 write_index_ptr; +#define SDXI_CXT_CTL_WRITE_INDEX_PTR GENMASK_ULL(63, 3) + __u8 rsvd_1[32]; +} __packed; +static_assert(sizeof(struct sdxi_cxt_ctl) =3D=3D 64); + +/* Context Status (CXT_STS) */ +struct sdxi_cxt_sts { + __u8 state; +#define SDXI_CXT_STS_STATE GENMASK(3, 0) + __u8 misc0; + __u8 rsvd_0[6]; + __le64 read_index; +} __packed; +static_assert(sizeof(struct sdxi_cxt_sts) =3D=3D 16); + +/* Valid values for FIELD_GET(SDXI_CXT_STS_STATE, sdxi_cxt_sts.state) */ +enum cxt_sts_state { + CXTV_STOP_SW =3D 0x0, + CXTV_RUN =3D 0x1, + CXTV_STOPG_SW =3D 0x2, + CXTV_STOP_FN =3D 0x4, + CXTV_STOPG_FN =3D 0x6, + CXTV_ERR_FN =3D 0xf, +}; + +static inline enum cxt_sts_state sdxi_cxt_sts_state(const struct sdxi_cxt_= sts *sts) +{ + return FIELD_GET(SDXI_CXT_STS_STATE, READ_ONCE(sts->state)); +} + +/* Access key entry (AKEY_ENT) */ +struct sdxi_akey_ent { + __le16 intr_num; +#define SDXI_AKEY_ENT_VL BIT(0) +#define SDXI_AKEY_ENT_PV BIT(2) + __le16 tgt_sfunc; + __le32 pasid; +#define SDXI_AKEY_ENT_PASID GENMASK(19, 0) + __le16 stag; + __u8 rsvd_0[2]; + __le16 rkey; + __u8 rsvd_1[2]; +} __packed; +static_assert(sizeof(struct sdxi_akey_ent) =3D=3D 16); + +/* Error Log Header Entry (ERRLOG_HD_ENT) */ +struct sdxi_errlog_hd_ent { + __le32 opcode; + __le16 misc0; + __le16 cxt_num; + __le64 dsc_index; + __u8 rsvd_0[28]; + __le16 err_class; + __u8 rsvd_1[2]; + __le32 vendor[4]; +} __packed; +static_assert(sizeof(struct sdxi_errlog_hd_ent) =3D=3D 64); + +/* Completion status block (CST_BLK) */ +struct sdxi_cst_blk { + __le64 signal; + __le32 flags; +#define SDXI_CST_BLK_ER_BIT BIT(31) + __u8 rsvd_0[20]; +} __packed; +static_assert(sizeof(struct sdxi_cst_blk) =3D=3D 32); + +/* + * Size of the "body" of each descriptor between the common opcode and + * csb_ptr fields. + */ +#define DSC_OPERATION_BYTES 52 + +#define define_sdxi_dsc(tag_, name_, op_body_) \ + struct tag_ { \ + __le32 opcode; \ + op_body_ \ + __le64 csb_ptr; \ + } name_; \ + static_assert(sizeof(struct tag_) =3D=3D \ + sizeof(struct sdxi_dsc_generic)); \ + static_assert(offsetof(struct tag_, csb_ptr) =3D=3D \ + offsetof(struct sdxi_dsc_generic, csb_ptr)) + +struct sdxi_desc { + union { + __le64 qw[8]; + + /* DSC_GENERIC - common header and footer */ + struct_group_tagged(sdxi_dsc_generic, generic, + __le32 opcode; +#define SDXI_DSC_VL BIT(0) +#define SDXI_DSC_SE BIT(1) +#define SDXI_DSC_FE BIT(2) +#define SDXI_DSC_CH BIT(3) +#define SDXI_DSC_CSR BIT(4) +#define SDXI_DSC_RB BIT(5) +#define SDXI_DSC_FLAGS GENMASK(5, 0) +#define SDXI_DSC_SUBTYPE GENMASK(15, 8) +#define SDXI_DSC_TYPE GENMASK(26, 16) + __u8 operation[DSC_OPERATION_BYTES]; + __le64 csb_ptr; +#define SDXI_DSC_NP BIT_ULL(0) +#define SDXI_DSC_CSB_PTR GENMASK_ULL(63, 5) + ); + + /* DmaBaseGrp: DSC_DMAB_NOP */ + define_sdxi_dsc(sdxi_dsc_dmab_nop, nop, + __u8 rsvd_0[DSC_OPERATION_BYTES]; + ); + +#define SDXI_DSC_OP_TYPE_DMAB 0x001 +#define SDXI_DSC_OP_SUBTYPE_COPY 0x03 + /* DmaBaseGrp: DSC_DMAB_COPY */ + define_sdxi_dsc(sdxi_dsc_dmab_copy, copy, + __le32 size; + __u8 attr; + __u8 rsvd_0[3]; + __le16 akey0; + __le16 akey1; + __le64 addr0; + __le64 addr1; + __u8 rsvd_1[24]; + ); + +#define SDXI_DSC_OP_TYPE_INTR 0x004 +#define SDXI_DSC_OP_SUBTYPE_INTR 0x00 + /* IntrGrp: DSC_INTR */ + define_sdxi_dsc(sdxi_dsc_intr, intr, + __u8 rsvd_0[8]; + __le16 akey; + __u8 rsvd_1[42]; + ); + +#define SDXI_DSC_OP_TYPE_ADMIN 0x002 +#define SDXI_DSC_OP_SUBTYPE_CXT_START_NM 0x03 +#define SDXI_DSC_OP_SUBTYPE_CXT_START_RS 0x08 + /* AdminGrp: DSC_CXT_START */ + define_sdxi_dsc(sdxi_dsc_cxt_start, cxt_start, + __u8 rsvd_0; + __u8 vflags; + __le16 vf_num; + __le16 cxt_start; + __le16 cxt_end; + __u8 rsvd_1[4]; + __le64 db_value; + __u8 rsvd_2[32]; + ); + +#define SDXI_DSC_OP_SUBTYPE_CXT_STOP 0x04 + /* AdminGrp: DSC_CXT_STOP */ + define_sdxi_dsc(sdxi_dsc_cxt_stop, cxt_stop, + __u8 rsvd_0; + __u8 vflags; + __le16 vf_num; + __le16 cxt_start; + __le16 cxt_end; + __u8 rsvd_1[44]; + ); + }; +}; +static_assert(sizeof(struct sdxi_desc) =3D=3D 64); + +#endif /* LINUX_SDXI_HW_H */ --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CA18326C39E; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098130; cv=none; b=VHTmTJvj1yGQoXmyheEpzHnDmnJz5z66ri4mMazM7cOkeDoZKrDkjn5KWh6XS6y92CGKdOdCaxrDSNfYG+O2yyESB5JnLL/nLhQW53GK55gnmzRahWsl+0hBZ5OfBmaUvMHWV/Wn0wWW8K1wrPA8uvD4/TnslryIdUug+jv9v40= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098130; c=relaxed/simple; bh=0RsfSk7Z7giYDTRx/TlwUf+aWs1ysuZSuIiQt3xAsKc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TBxdFd/Wn+vlu48RoBOggI3jSchQUF6b6IVABftU3QHPZEhRPsd8QUjij95Ud/KAO6cpWKNFDNWr9ugyeQ1aR/M/Ze0I4UkffprelSZhoBcB5ghRtT5K2+OQQyD/WPVTwowDAJXuIzLK9mWetWBeaH1S/zp9uWO5CUMgQu3q93s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cuQkjbHn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cuQkjbHn" Received: by smtp.kernel.org (Postfix) with ESMTPS id 876ABC4CEFB; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098130; bh=0RsfSk7Z7giYDTRx/TlwUf+aWs1ysuZSuIiQt3xAsKc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=cuQkjbHnGKhjJKAJMFhWZNE33XdOiRrWYzQvVujoMJ9S81Ppm71J0qrT/zBNu6FKE Q4/dVGwvzJtGHyGGWfuYWSKh0+fdDfHBIRlB32zxqTNANFxo3uxz4VnGQ7iG+An5E6 I0hLh6YdG6e5V3Koa2/vccY4sj6QxPpS2nyuYBmfur3ikRjb5TodkUJuSeFG5vZR+B E0xUo04JJjoyO5UsI6ELmSIibZ3sNkPMT6SIwqyGRo7Wyeab/IEfxk4TaJDVSlgkPH wFQeUOk13LSIJub+3yXoFGLCK3HT8CVRnsf4MTR48E4Qk3xCWFNrNfrFn7ty/eEo2i qDtIF3yHVzzDw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 78A65CA101F; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:26 -0500 Subject: [PATCH RFC 03/13] dmaengine: sdxi: Add descriptor encoding and unit tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-3-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098128; l=15232; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=UezToU+VmZcS1jraaaN8wx3PC2DeVePS8pHMHmsC5dQ=; b=VDFU1hO+cBEzdN0KG639/c4S4BO9U0MkDWKjhXjihFFSVQglPW0F3m7VV75nYmL1zErwvWonP L+NkJLEUsZLDsMkM6HgMR6Ns5CP21Vz9Pg73HDL3cZlErBmWf5TOikq X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch Add support for encoding several types of SDXI descriptors: * Copy * Interrupt * Context start * Context stop Each type of descriptor has a corresponding parameter struct which is an input to its encoder function. E.g. to encode a copy descriptor, the client initializes a struct sdxi_copy object with the source, destination, size, etc and passes that to sdxi_encode_copy(). Include unit tests that verify that encoded descriptors have the expected values and that fallible encode functions fail on invalid inputs. Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- drivers/dma/sdxi/.kunitconfig | 4 + drivers/dma/sdxi/descriptor.c | 197 ++++++++++++++++++++++++++++++++= ++++ drivers/dma/sdxi/descriptor.h | 107 ++++++++++++++++++++ drivers/dma/sdxi/descriptor_kunit.c | 181 +++++++++++++++++++++++++++++++++ 4 files changed, 489 insertions(+) diff --git a/drivers/dma/sdxi/.kunitconfig b/drivers/dma/sdxi/.kunitconfig new file mode 100644 index 0000000000000000000000000000000000000000..a98cf19770f03bce82ef86d378d= 2a2e34da5154a --- /dev/null +++ b/drivers/dma/sdxi/.kunitconfig @@ -0,0 +1,4 @@ +CONFIG_KUNIT=3Dy +CONFIG_DMADEVICES=3Dy +CONFIG_SDXI=3Dy +CONFIG_SDXI_KUNIT_TEST=3Dy diff --git a/drivers/dma/sdxi/descriptor.c b/drivers/dma/sdxi/descriptor.c new file mode 100644 index 0000000000000000000000000000000000000000..6ea5247bf8cdaac19131ca5326b= a1640c0b557f8 --- /dev/null +++ b/drivers/dma/sdxi/descriptor.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * SDXI descriptor encoding. + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hw.h" +#include "descriptor.h" + +enum { + SDXI_PACKING_QUIRKS =3D QUIRK_LITTLE_ENDIAN | QUIRK_LSW32_IS_FIRST, +}; + +#define sdxi_desc_field(_high, _low, _member) \ + PACKED_FIELD(_high, _low, struct sdxi_desc_unpacked, _member) +#define sdxi_desc_flag(_bit, _member) \ + sdxi_desc_field(_bit, _bit, _member) + +static const struct packed_field_u16 common_descriptor_fields[] =3D { + sdxi_desc_flag(0, vl), + sdxi_desc_flag(1, se), + sdxi_desc_flag(2, fe), + sdxi_desc_flag(3, ch), + sdxi_desc_flag(4, csr), + sdxi_desc_flag(5, rb), + sdxi_desc_field(15, 8, subtype), + sdxi_desc_field(26, 16, type), + sdxi_desc_flag(448, np), + sdxi_desc_field(511, 453, csb_ptr), +}; + +void sdxi_desc_unpack(struct sdxi_desc_unpacked *to, + const struct sdxi_desc *from) +{ + *to =3D (struct sdxi_desc_unpacked){}; + unpack_fields(from, sizeof(*from), to, common_descriptor_fields, + SDXI_PACKING_QUIRKS); +} +EXPORT_SYMBOL_IF_KUNIT(sdxi_desc_unpack); + +static void desc_clear(struct sdxi_desc *desc) +{ + memset(desc, 0, sizeof(*desc)); +} + +static __must_check int sdxi_encode_size32(u64 size, __le32 *dest) +{ + /* + * sizes are encoded as value - 1: + * value encoding + * 1 0 + * 2 1 + * ... + * 4G 0xffffffff + */ + if (WARN_ON_ONCE(size > SZ_4G) || + WARN_ON_ONCE(size =3D=3D 0)) + return -EINVAL; + size =3D clamp_val(size, 1, SZ_4G); + *dest =3D cpu_to_le32((u32)(size - 1)); + return 0; +} + +int sdxi_encode_copy(struct sdxi_desc *desc, const struct sdxi_copy *param= s) +{ + u64 csb_ptr; + u32 opcode; + __le32 size; + int err; + + err =3D sdxi_encode_size32(params->len, &size); + if (err) + return err; + /* + * TODO: reject overlapping src and dst. Quoting "Memory + * Consistency Model": "Software shall not ... overlap the + * source buffer, destination buffer, Atomic Return Data, or + * completion status block." + */ + + opcode =3D (FIELD_PREP(SDXI_DSC_VL, 1) | + FIELD_PREP(SDXI_DSC_SUBTYPE, SDXI_DSC_OP_SUBTYPE_COPY) | + FIELD_PREP(SDXI_DSC_TYPE, SDXI_DSC_OP_TYPE_DMAB)); + + csb_ptr =3D FIELD_PREP(SDXI_DSC_NP, 1); + + desc_clear(desc); + desc->copy =3D (struct sdxi_dsc_dmab_copy) { + .opcode =3D cpu_to_le32(opcode), + .size =3D size, + .akey0 =3D cpu_to_le16(params->src_akey), + .akey1 =3D cpu_to_le16(params->dst_akey), + .addr0 =3D cpu_to_le64(params->src), + .addr1 =3D cpu_to_le64(params->dst), + .csb_ptr =3D cpu_to_le64(csb_ptr), + }; + + return 0; +} +EXPORT_SYMBOL_IF_KUNIT(sdxi_encode_copy); + +int sdxi_encode_intr(struct sdxi_desc *desc, + const struct sdxi_intr *params) +{ + u64 csb_ptr; + u32 opcode; + + opcode =3D (FIELD_PREP(SDXI_DSC_VL, 1) | + FIELD_PREP(SDXI_DSC_SUBTYPE, SDXI_DSC_OP_SUBTYPE_INTR) | + FIELD_PREP(SDXI_DSC_TYPE, SDXI_DSC_OP_TYPE_INTR)); + + csb_ptr =3D FIELD_PREP(SDXI_DSC_NP, 1); + + desc_clear(desc); + desc->intr =3D (struct sdxi_dsc_intr) { + .opcode =3D cpu_to_le32(opcode), + .akey =3D cpu_to_le16(params->akey), + .csb_ptr =3D cpu_to_le64(csb_ptr), + }; + + return 0; +} +EXPORT_SYMBOL_IF_KUNIT(sdxi_encode_intr); + +int sdxi_encode_cxt_start(struct sdxi_desc *desc, + const struct sdxi_cxt_start *params) +{ + u16 cxt_start; + u16 cxt_end; + u64 csb_ptr; + u32 opcode; + + opcode =3D (FIELD_PREP(SDXI_DSC_VL, 1) | + FIELD_PREP(SDXI_DSC_FE, 1) | + FIELD_PREP(SDXI_DSC_SUBTYPE, SDXI_DSC_OP_SUBTYPE_CXT_START_NM) | + FIELD_PREP(SDXI_DSC_TYPE, SDXI_DSC_OP_TYPE_ADMIN)); + + cxt_start =3D params->range.cxt_start; + cxt_end =3D params->range.cxt_end; + + csb_ptr =3D FIELD_PREP(SDXI_DSC_NP, 1); + + desc_clear(desc); + desc->cxt_start =3D (struct sdxi_dsc_cxt_start) { + .opcode =3D cpu_to_le32(opcode), + .cxt_start =3D cpu_to_le16(cxt_start), + .cxt_end =3D cpu_to_le16(cxt_end), + .csb_ptr =3D cpu_to_le64(csb_ptr), + }; + + return 0; +} +EXPORT_SYMBOL_IF_KUNIT(sdxi_encode_cxt_start); + +int sdxi_encode_cxt_stop(struct sdxi_desc *desc, + const struct sdxi_cxt_stop *params) +{ + u16 cxt_start; + u16 cxt_end; + u64 csb_ptr; + u32 opcode; + + opcode =3D (FIELD_PREP(SDXI_DSC_VL, 1) | + FIELD_PREP(SDXI_DSC_FE, 1) | + FIELD_PREP(SDXI_DSC_SUBTYPE, SDXI_DSC_OP_SUBTYPE_CXT_STOP) | + FIELD_PREP(SDXI_DSC_TYPE, SDXI_DSC_OP_TYPE_ADMIN)); + + cxt_start =3D params->range.cxt_start; + cxt_end =3D params->range.cxt_end; + + csb_ptr =3D FIELD_PREP(SDXI_DSC_NP, 1); + + desc_clear(desc); + desc->cxt_stop =3D (struct sdxi_dsc_cxt_stop) { + .opcode =3D cpu_to_le32(opcode), + .cxt_start =3D cpu_to_le16(cxt_start), + .cxt_end =3D cpu_to_le16(cxt_end), + .csb_ptr =3D cpu_to_le64(csb_ptr), + }; + + return 0; +} +EXPORT_SYMBOL_IF_KUNIT(sdxi_encode_cxt_stop); diff --git a/drivers/dma/sdxi/descriptor.h b/drivers/dma/sdxi/descriptor.h new file mode 100644 index 0000000000000000000000000000000000000000..141463dfd56bd4a88b4b3c9d45b= 13cc8101e1961 --- /dev/null +++ b/drivers/dma/sdxi/descriptor.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef DMA_SDXI_DESCRIPTOR_H +#define DMA_SDXI_DESCRIPTOR_H + +/* + * Facilities for encoding SDXI descriptors. + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hw.h" + +static inline void sdxi_desc_set_csb(struct sdxi_desc *desc, + dma_addr_t addr) +{ + desc->csb_ptr =3D cpu_to_le64(FIELD_PREP(SDXI_DSC_CSB_PTR, addr >> 5)); +} + +struct sdxi_cxt_range { + u16 cxt_start; + u16 cxt_end; +}; + +static inline struct sdxi_cxt_range __sdxi_cxt_range(u16 a, u16 b) +{ + return (struct sdxi_cxt_range) { + .cxt_start =3D min(a, b), + .cxt_end =3D max(a, b), + }; +} + +#define sdxi_cxt_range_1(_id) \ + ({ \ + u16 id =3D (_id); \ + __sdxi_cxt_range(id, id); \ + }) + +#define sdxi_cxt_range_2(_id1, _id2) __sdxi_cxt_range(_id1, _id2) + +#define _sdxi_cxt_range(_1, _2, _fn, ...) _fn + +#define sdxi_cxt_range(...) \ + _sdxi_cxt_range(__VA_ARGS__, \ + sdxi_cxt_range_2, sdxi_cxt_range_1)(__VA_ARGS__) + +struct sdxi_copy { + dma_addr_t src; + dma_addr_t dst; + size_t len; + u16 src_akey; + u16 dst_akey; +}; + +int sdxi_encode_copy(struct sdxi_desc *desc, + const struct sdxi_copy *params); + +struct sdxi_intr { + u16 akey; +}; + +int sdxi_encode_intr(struct sdxi_desc *desc, + const struct sdxi_intr *params); + +struct sdxi_cxt_start { + struct sdxi_cxt_range range; +}; + +int sdxi_encode_cxt_start(struct sdxi_desc *desc, + const struct sdxi_cxt_start *params); + +struct sdxi_cxt_stop { + struct sdxi_cxt_range range; +}; + +int sdxi_encode_cxt_stop(struct sdxi_desc *desc, + const struct sdxi_cxt_stop *params); + +/* + * Fields common to all SDXI descriptors in "unpacked" form, for use + * with pack_fields() and unpack_fields(). + */ +struct sdxi_desc_unpacked { + u64 csb_ptr; + u16 type; + u8 subtype; + bool vl; + bool se; + bool fe; + bool ch; + bool csr; + bool rb; + bool np; +}; + +void sdxi_desc_unpack(struct sdxi_desc_unpacked *to, + const struct sdxi_desc *from); + +#endif /* DMA_SDXI_DESCRIPTOR_H */ diff --git a/drivers/dma/sdxi/descriptor_kunit.c b/drivers/dma/sdxi/descrip= tor_kunit.c new file mode 100644 index 0000000000000000000000000000000000000000..eb89d5a152cd789fb8cfa66b78b= f30e583a1680d --- /dev/null +++ b/drivers/dma/sdxi/descriptor_kunit.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * SDXI descriptor encoding tests. + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "descriptor.h" + +MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); + +static void desc_poison(struct sdxi_desc *d) +{ + memset(d, 0xff, sizeof(*d)); +} + +static void copy(struct kunit *t) +{ + struct sdxi_desc_unpacked unpacked; + struct sdxi_copy copy =3D {}; + struct sdxi_desc desc =3D {}; + + desc_poison(&desc); + KUNIT_EXPECT_EQ(t, -EINVAL, sdxi_encode_copy(&desc, ©)); + + desc_poison(&desc); + copy.len =3D SZ_4G + 1; + KUNIT_EXPECT_EQ(t, -EINVAL, sdxi_encode_copy(&desc, ©)); + + desc_poison(&desc); + copy.len =3D 1; + KUNIT_EXPECT_EQ(t, 0, sdxi_encode_copy(&desc, ©)); + + desc_poison(&desc); + copy.len =3D SZ_4G; + KUNIT_EXPECT_EQ(t, 0, sdxi_encode_copy(&desc, ©)); + KUNIT_EXPECT_EQ(t, SZ_4G - 1, le32_to_cpu(desc.copy.size)); + + desc_poison(&desc); + KUNIT_EXPECT_EQ(t, 0, + sdxi_encode_copy(&desc, + &(struct sdxi_copy) { + .src =3D 0x1000, + .dst =3D 0x2000, + .len =3D 0x100, + .src_akey =3D 1, + .dst_akey =3D 2, + })); + KUNIT_EXPECT_EQ(t, 0x1000, le64_to_cpu(desc.copy.addr0)); + KUNIT_EXPECT_EQ(t, 0x2000, le64_to_cpu(desc.copy.addr1)); + KUNIT_EXPECT_EQ(t, 0x100, 1 + le32_to_cpu(desc.copy.size)); + KUNIT_EXPECT_EQ(t, 1, le16_to_cpu(desc.copy.akey0)); + KUNIT_EXPECT_EQ(t, 2, le16_to_cpu(desc.copy.akey1)); + + sdxi_desc_unpack(&unpacked, &desc); + KUNIT_EXPECT_EQ(t, unpacked.vl, 1); + KUNIT_EXPECT_EQ(t, unpacked.ch, 0); + KUNIT_EXPECT_EQ(t, unpacked.subtype, SDXI_DSC_OP_SUBTYPE_COPY); + KUNIT_EXPECT_EQ(t, unpacked.type, SDXI_DSC_OP_TYPE_DMAB); + KUNIT_EXPECT_EQ(t, unpacked.csb_ptr, 0); + KUNIT_EXPECT_EQ(t, unpacked.np, 1); +} + +static void intr(struct kunit *t) +{ + struct sdxi_desc_unpacked unpacked; + struct sdxi_intr intr =3D { + .akey =3D 1234, + }; + struct sdxi_desc desc; + + desc_poison(&desc); + KUNIT_EXPECT_EQ(t, 0, sdxi_encode_intr(&desc, &intr)); + KUNIT_EXPECT_EQ(t, 1234, le16_to_cpu(desc.intr.akey)); + + sdxi_desc_unpack(&unpacked, &desc); + KUNIT_EXPECT_EQ(t, unpacked.vl, 1); + KUNIT_EXPECT_EQ(t, unpacked.ch, 0); + KUNIT_EXPECT_EQ(t, unpacked.subtype, SDXI_DSC_OP_SUBTYPE_INTR); + KUNIT_EXPECT_EQ(t, unpacked.type, SDXI_DSC_OP_TYPE_INTR); + KUNIT_EXPECT_EQ(t, unpacked.csb_ptr, 0); + KUNIT_EXPECT_EQ(t, unpacked.np, 1); +} + +static void cxt_start(struct kunit *t) +{ + struct sdxi_cxt_start start =3D { + .range =3D sdxi_cxt_range(1, U16_MAX) + }; + struct sdxi_desc desc =3D {}; + struct sdxi_desc_unpacked unpacked; + + KUNIT_EXPECT_EQ(t, 0, sdxi_encode_cxt_start(&desc, &start)); + + /* Check op-specific fields. */ + KUNIT_EXPECT_EQ(t, 0, desc.cxt_start.vflags); + KUNIT_EXPECT_EQ(t, 0, desc.cxt_start.vf_num); + KUNIT_EXPECT_EQ(t, 1, desc.cxt_start.cxt_start); + KUNIT_EXPECT_EQ(t, U16_MAX, desc.cxt_start.cxt_end); + KUNIT_EXPECT_EQ(t, 0, desc.cxt_start.db_value); + + /* + * Check generic fields. Some flags have mandatory values + * according to the operation type. + */ + sdxi_desc_unpack(&unpacked, &desc); + KUNIT_EXPECT_EQ(t, unpacked.vl, 1); + KUNIT_EXPECT_EQ(t, unpacked.se, 0); + KUNIT_EXPECT_EQ(t, unpacked.fe, 1); + KUNIT_EXPECT_EQ(t, unpacked.ch, 0); + KUNIT_EXPECT_EQ(t, unpacked.subtype, SDXI_DSC_OP_SUBTYPE_CXT_START_NM); + KUNIT_EXPECT_EQ(t, unpacked.type, SDXI_DSC_OP_TYPE_ADMIN); + KUNIT_EXPECT_EQ(t, unpacked.csb_ptr, 0); + KUNIT_EXPECT_EQ(t, unpacked.np, 1); +} + +static void cxt_stop(struct kunit *t) +{ + struct sdxi_cxt_stop stop =3D { + .range =3D sdxi_cxt_range(1, U16_MAX) + }; + struct sdxi_desc desc =3D {}; + struct sdxi_desc_unpacked unpacked; + + KUNIT_EXPECT_EQ(t, 0, sdxi_encode_cxt_stop(&desc, &stop)); + + /* Check op-specific fields */ + KUNIT_EXPECT_EQ(t, 0, desc.cxt_stop.vflags); + KUNIT_EXPECT_EQ(t, 0, desc.cxt_stop.vf_num); + KUNIT_EXPECT_EQ(t, 1, desc.cxt_stop.cxt_start); + KUNIT_EXPECT_EQ(t, U16_MAX, desc.cxt_stop.cxt_end); + + /* + * Check generic fields. Some flags have mandatory values + * according to the operation type. + */ + sdxi_desc_unpack(&unpacked, &desc); + KUNIT_EXPECT_EQ(t, unpacked.vl, 1); + KUNIT_EXPECT_EQ(t, unpacked.se, 0); + KUNIT_EXPECT_EQ(t, unpacked.fe, 1); + KUNIT_EXPECT_EQ(t, unpacked.ch, 0); + KUNIT_EXPECT_EQ(t, unpacked.subtype, SDXI_DSC_OP_SUBTYPE_CXT_STOP); + KUNIT_EXPECT_EQ(t, unpacked.type, SDXI_DSC_OP_TYPE_ADMIN); + KUNIT_EXPECT_EQ(t, unpacked.csb_ptr, 0); + KUNIT_EXPECT_EQ(t, unpacked.np, 1); +} + +static struct kunit_case generic_desc_tcs[] =3D { + KUNIT_CASE(copy), + KUNIT_CASE(intr), + KUNIT_CASE(cxt_start), + KUNIT_CASE(cxt_stop), + {}, +}; + +static int generic_desc_setup_device(struct kunit *t) +{ + struct device *dev =3D kunit_device_register(t, "sdxi-mock-device"); + + KUNIT_ASSERT_NOT_ERR_OR_NULL(t, dev); + t->priv =3D dev; + return 0; +} + +static struct kunit_suite generic_desc_ts =3D { + .name =3D "Generic SDXI descriptor encoding", + .test_cases =3D generic_desc_tcs, + .init =3D generic_desc_setup_device, +}; +kunit_test_suite(generic_desc_ts); + +MODULE_DESCRIPTION("SDXI descriptor encoding tests"); +MODULE_AUTHOR("Nathan Lynch"); +MODULE_LICENSE("GPL"); --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EEF632701B8; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; cv=none; b=ZDErWw5ISxHq2II9Ozik++JxBx1MqH5usEjgt9GmIjoVhEbGgh4P0wz8agNOMBja/VbMsYrQlqndVhT/o1HMAtkATM2yiGgE/lZZ9Jt4t59eBmyfYsO8v1okc1ULPNmtKjvhYC8wpVKh0ge4eLgy5yAT5frc0dCMXmFRupriqcQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; c=relaxed/simple; bh=qnf1b2zKcFkUTQHKXISqjdW6MILR4BxPUkttA+Smuto=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uXOSA2RCdV8Gl62FKF9kXVn0onjXjvD0vyjf8ulGpF3bXSMgsEQHdspnvkPO/KdxBS1bIHXvTYrafeaTT0smxNHwwS5SrneWKJa/+23f5I+yEHAgUmWo+wy88ZrvjfjYqDa6M2T6qBLP5LO5eDzjxfvq1vvd57J7zKqvQ5XJ4hU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YPCL8cjh; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="YPCL8cjh" Received: by smtp.kernel.org (Postfix) with ESMTPS id 8F428C4CEFA; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098130; bh=qnf1b2zKcFkUTQHKXISqjdW6MILR4BxPUkttA+Smuto=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=YPCL8cjhV2u0KXG1MfOuW+Vd1s1HqK1GdZh6sC+Z+dlmb/+CK9a0bl7uyrvDLWXqm mBOj0+9FyCyN27Nd1tPtgcyauGim5yNhv0VzbqxVdILkxNV2cEfYrds4bDORVcysRG vN8/gKOU1yUknk1gSQJJEAl6yZ2AmrRnhgHzjx+oUYIY+5R0TjCgcuM8Vcr1tptYpD 4xUG5sar0GfUXgb7gSrOjuU+XdF7RsAlzmoMUOWOGd36Ip7rOw7cRNkDTcbVG0QcSA 1xzKvo0+BbT/265pShS1UWcVL7U0gGX2WxyvmdjxdwWrew8FNFksSMdSNr1/ls2SU4 jn2Y/F9hl1xLQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 86A13CA1017; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:27 -0500 Subject: [PATCH RFC 04/13] dmaengine: sdxi: Add MMIO register definitions Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-4-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098128; l=4036; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=AGyFf5vWBLGgXMTQeKDi2itH4wGLo9U+txLID+JDYc8=; b=ckXC4832wmhdl4X+GtoJDyWK0pWs8vPBZBZHOHorNo+MFrwg6bZ22a0Ak7sqn1klOyKsStt2B li2rBwFyrwtCp8P9srcd/tkiA9PC/r4rA82+S0RqE0uln/bfHYYtEKj X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch Add offsets and bitmasks for: * General control and status registers (MMIO_CTL0, MMIO_CTL2, MMIO_STS0) * Capability registers (MMIO_CAP0, MMIO_CAP1) * Context table pointer register (MMIO_CXT_L2) * Error logging control and status registers (MMIO_ERR_CTL, MMIO_ERR_STS, MMIO_ERR_CFG, MMIO_ERR_WRT, MMIO_ERR_RD) This is a useful subset of the MMIO registers and fields defined in the spec. The driver currently does not use MMIO_VERSION, MMIO_GRP_ENUM, or the mailbox registers. Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- drivers/dma/sdxi/mmio.h | 92 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 92 insertions(+) diff --git a/drivers/dma/sdxi/mmio.h b/drivers/dma/sdxi/mmio.h new file mode 100644 index 0000000000000000000000000000000000000000..36d174a1f8859055f7808d520de= 1ff193c49ae26 --- /dev/null +++ b/drivers/dma/sdxi/mmio.h @@ -0,0 +1,92 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * SDXI MMIO register offsets and layouts. + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ + +#ifndef DMA_SDXI_MMIO_H +#define DMA_SDXI_MMIO_H + +#include +#include +#include +#include + +/* Refer to "MMIO Control Registers". */ +enum sdxi_reg { + SDXI_MMIO_CTL0 =3D 0x00000, + SDXI_MMIO_CTL2 =3D 0x00010, + SDXI_MMIO_STS0 =3D 0x00100, + SDXI_MMIO_CAP0 =3D 0x00200, + SDXI_MMIO_CAP1 =3D 0x00208, + SDXI_MMIO_VERSION =3D 0x00210, + SDXI_MMIO_CXT_L2 =3D 0x10000, + SDXI_MMIO_RKEY =3D 0x10100, + SDXI_MMIO_ERR_CTL =3D 0x20000, + SDXI_MMIO_ERR_STS =3D 0x20008, + SDXI_MMIO_ERR_CFG =3D 0x20010, + SDXI_MMIO_ERR_WRT =3D 0x20020, + SDXI_MMIO_ERR_RD =3D 0x20028, +}; + +enum { + /* SDXI_MMIO_CTL0 fields */ + SDXI_MMIO_CTL0_FN_GSR =3D GENMASK_ULL(1, 0), + SDXI_MMIO_CTL0_FN_PASID_VL =3D BIT_ULL(2), + SDXI_MMIO_CTL0_FN_ERR_INTR_EN =3D BIT_ULL(4), + SDXI_MMIO_CTL0_FN_PASID =3D GENMASK_ULL(27, 8), + SDXI_MMIO_CTL0_FN_GRP_ID =3D GENMASK_ULL(63, 32), + + /* SDXI_MMIO_CTL2 fields */ + SDXI_MMIO_CTL2_MAX_BUFFER =3D GENMASK_ULL(3, 0), + SDXI_MMIO_CTL2_MAX_AKEY_SZ =3D GENMASK_ULL(15, 12), + SDXI_MMIO_CTL2_MAX_CXT =3D GENMASK_ULL(31, 16), + SDXI_MMIO_CTL2_OPB_000_AVL =3D GENMASK_ULL(63, 32), + + /* SDXI_MMIO_STS0 bit definitions */ + SDXI_MMIO_STS0_FN_GSV =3D GENMASK_ULL(2, 0), + + /* SDXI_MMIO_CAP0 bit definitions */ + SDXI_MMIO_CAP0_SFUNC =3D GENMASK_ULL(15, 0), + SDXI_MMIO_CAP0_DB_STRIDE =3D GENMASK_ULL(22, 20), + SDXI_MMIO_CAP0_MAX_DS_RING_SZ =3D GENMASK_ULL(28, 24), + + /* SDXI_MMIO_CAP1 fields */ + SDXI_MMIO_CAP1_MAX_BUFFER =3D GENMASK_ULL(3, 0), + SDXI_MMIO_CAP1_RKEY_CAP =3D BIT_ULL(4), + SDXI_MMIO_CAP1_RM =3D BIT_ULL(5), + SDXI_MMIO_CAP1_MMIO64 =3D BIT_ULL(6), + SDXI_MMIO_CAP1_MAX_ERRLOG_SZ =3D GENMASK_ULL(11, 8), + SDXI_MMIO_CAP1_MAX_AKEY_SZ =3D GENMASK_ULL(15, 12), + SDXI_MMIO_CAP1_MAX_CXT =3D GENMASK_ULL(31, 16), + SDXI_MMIO_CAP1_OPB_000_CAP =3D GENMASK_ULL(63, 32), + + /* SDXI_MMIO_VERSION fields */ + SDXI_MMIO_VERSION_MINOR =3D GENMASK_ULL(7, 0), + SDXI_MMIO_VERSION_MAJOR =3D GENMASK_ULL(23, 16), + + /* SDXI_MMIO_CXT_L2 fields */ + SDXI_MMIO_CXT_L2_PTR =3D GENMASK_ULL(63, 12), + + /* SDXI_MMIO_ERR_CFG bit definitions */ + SDXI_MMIO_ERR_CFG_PTR =3D GENMASK_ULL(63, 12), + SDXI_MMIO_ERR_CFG_SZ =3D GENMASK_ULL(5, 1), + SDXI_MMIO_ERR_CFG_EN =3D BIT_ULL(0), + + /* SDXI_MMIO_RKEY bit definitions */ + SDXI_MMIO_RKEY_PTR =3D GENMASK_ULL(63, 12), + SDXI_MMIO_RKEY_SZ =3D GENMASK_ULL(4, 1), + SDXI_MMIO_RKEY_EN =3D BIT_ULL(0), + + /* SDXI_MMIO_ERR_CTL bit definitions */ + SDXI_MMIO_ERR_CTL_EN =3D BIT_ULL(0), + + /* SDXI_MMIO_ERR_STS bit definitions. */ + SDXI_MMIO_ERR_STS_STS_BIT =3D BIT_ULL(0), + SDXI_MMIO_ERR_STS_OVF_BIT =3D BIT_ULL(1), + SDXI_MMIO_ERR_STS_ERR_BIT =3D BIT_ULL(3), +}; + +#endif /* DMA_SDXI_MMIO_H */ --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0CF6527A92D; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; cv=none; b=dl8TcMgFJ3dyy1567bxOJsfOgGrDW5Vu0sq5W9jlPmYX1LIpEOis9YsjtJYcqMS7xzTLyfmGPRK93PzKDB6MrV59ltkpwiftBWJmtpdzgk9Fm5ehgwMEeN96HFtNC4ZSWHAgcwxoDxPItxYsH73HzUsjmyU5+wbJDNbDFxNkOMY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; c=relaxed/simple; bh=oY7DZ4hu+GU2kn9kp52VDZlC4m4nEfN7jMAWydDl790=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aFW6qMviFB0CvUQyHzs2RXJ7GaqMMLroCFMCv3sHzYNpz39uZ2920OWZ+NBOHGM3i8MJvhebjHBWYugiwe5vqi/oWiYD9qSVQVPBB3qonag08aXS1vKeXbxxp0MisOb0GZlzx6TEBm4MmECtNjOK6BkVgUACiigX1qr5uoyFkiI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FglUFUls; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FglUFUls" Received: by smtp.kernel.org (Postfix) with ESMTPS id 9AEC5C4CEF9; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098130; bh=oY7DZ4hu+GU2kn9kp52VDZlC4m4nEfN7jMAWydDl790=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=FglUFUlseaITtECkehYpxpd9i2FQiH1tvTo0q74DfX3/H2ChAScDInehOwTsWKQuu JkvN9icN9jYxsalV9iVnHFxPMzOIMcRL9EoBI0N5zOKyoIrVX77nGX183V9nGvdNIm +E6rZFp/TRIlYRQ2Gk4rRuaWFYOWZIgDXLwUSd5xKorZO8EG+NAUFKKhsAs3PrS6rK 9G0RptGZ59F1T9Ad5JaojN1/L4squk8MDgTgDJCuCaZS1IATSegnJBHYrvQAwcs6o7 I9rbMI68QYSxZEJs2TiC3+bpgoIB8eyPAuxSwYbBRqQFd+P1YIDVOcKVvZcqJncY5C x5PZF6HYnWoyQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 94130CAC581; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:28 -0500 Subject: [PATCH RFC 05/13] dmaengine: sdxi: Add software data structures Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-5-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098128; l=6245; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=6veT8qjJZW/zhzeosOQPDAoX6bJfuMluVBRqdMpn4R0=; b=2xrS4Vw5j64mX6zutDqCi9KaHmiUMwtNrlbgWk/6ag/G5hWq881JNMASZ1qj0YOsCmh2inFvJ OirL2NdFFWCA/VrewmfKGIgPTO2wwHG/oPShdgR3wL+5Hd22Xae3v8m X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch Add the driver's central header sdxi.h, which brings in the major software abstractions used throughout the driver -- mainly the SDXI device or function (sdxi_dev) and context (sdxi_cxt). Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- drivers/dma/sdxi/sdxi.h | 206 ++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 206 insertions(+) diff --git a/drivers/dma/sdxi/sdxi.h b/drivers/dma/sdxi/sdxi.h new file mode 100644 index 0000000000000000000000000000000000000000..13e02f0541e0d60412c99b0b75b= d37155a531e1d --- /dev/null +++ b/drivers/dma/sdxi/sdxi.h @@ -0,0 +1,206 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * SDXI device driver header + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ + +#ifndef __SDXI_H +#define __SDXI_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../virt-dma.h" +#include "hw.h" +#include "mmio.h" + +#define SDXI_DRV_NAME "sdxi" + +#define ID_TO_L2_INDEX(id) (((id) >> 9) & 0x1FF) +#define ID_TO_L1_INDEX(id) ((id) & 0x7F) +#define IS_VF_DEVICE(sdxi) ((sdxi)->is_vf) + +#define L2_TABLE_ENTRIES (1 << 9) +#define L1_TABLE_ENTRIES (1 << 7) +#define L2_TABLE_SIZE 4096 +#define L1_TABLE_SIZE 4096 + +#define OP_TYPE_ERRLOG 0x7f7 + +#define DESC_RING_BASE_PTR_SHIFT 6 +#define CXT_STATUS_PTR_SHIFT 4 +#define WRT_INDEX_PTR_SHIFT 3 + +#define L1_CXT_CTRL_PTR_SHIFT 6 +#define L1_CXT_AKEY_PTR_SHIFT 12 + +#define MAX_DMA_COPY_BYTES (1ULL << 32) + +/* Submission Queue */ +struct sdxi_sq { + struct sdxi_cxt *cxt; /* owner */ + + u32 ring_entries; + u32 ring_size; + struct sdxi_desc *desc_ring; + dma_addr_t ring_dma; + + __le64 *write_index; + dma_addr_t write_index_dma; + + struct sdxi_cxt_sts *cxt_sts; + dma_addr_t cxt_sts_dma; + + /* NB: define doorbell here */ +}; + +struct sdxi_tasklet_data { + struct sdxi_cmd *cmd; +}; + +struct sdxi_cmd { + struct work_struct work; + struct sdxi_cxt *cxt; + struct sdxi_cst_blk *cst_blk; + dma_addr_t cst_blk_dma; + int ret; + size_t len; + u64 src_addr; + u64 dst_addr; + /* completion callback support */ + void (*sdxi_cmd_callback)(void *data, int err); + void *data; +}; + +struct sdxi_dma_chan { + struct virt_dma_chan vc; + struct sdxi_cxt *cxt; +}; + +/* + * The size of the AKey table is flexible, from 4KB to 1MB. Always use + * the minimum size for now. + */ +struct sdxi_akey_table { + struct sdxi_akey_ent entry[SZ_4K / sizeof(struct sdxi_akey_ent)]; +}; + +/* For encoding the akey table size in CXT_L1_ENT's akey_sz. */ +static inline u8 akey_table_order(const struct sdxi_akey_table *tbl) +{ + static_assert(sizeof(struct sdxi_akey_table) =3D=3D SZ_4K); + return 0; +} + +/* Context */ +struct sdxi_cxt { + struct sdxi_dev *sdxi; /* owner */ + unsigned int id; + + resource_size_t db_base; /* doorbell MMIO base addr */ + __le64 __iomem *db; /* doorbell virt addr */ + + struct sdxi_cxt_ctl *cxt_ctl; + dma_addr_t cxt_ctl_dma; + + struct sdxi_akey_table *akey_table; + dma_addr_t akey_table_dma; + + struct sdxi_sq *sq; + + /* NB: might need to move to sdxi_device? */ + struct sdxi_dma_chan sdxi_dma_chan; + + struct sdxi_process *process; /* process reprsentation */ +}; + +/** + * struct sdxi_dev_ops - Bus-specific methods for SDXI devices. + * + * @irq_init: Allocate MSIs. + * @irq_exit: Release MSIs. + */ +struct sdxi_dev_ops { + int (*irq_init)(struct sdxi_dev *sdxi); + void (*irq_exit)(struct sdxi_dev *sdxi); +}; + +struct sdxi_dev { + struct device *dev; + resource_size_t ctrl_regs_bar; /* ctrl registers base (BAR0) */ + resource_size_t dbs_bar; /* doorbells base (BAR2) */ + void __iomem *ctrl_regs; /* virt addr of ctrl registers */ + void __iomem *dbs; /* virt addr of doorbells */ + + /* hardware capabilities (from cap0 & cap1) */ + u16 sfunc; /* function's requester id */ + u32 db_stride; /* doorbell stride in bytes */ + u64 max_ring_entries; /* max # of ring entries supported */ + + u32 max_akeys; /* max akey # supported */ + u32 max_cxts; /* max contexts # supported */ + u32 op_grp_cap; /* supported operatation group cap */ + + /* context management */ + struct mutex cxt_lock; /* context protection */ + int cxt_count; + struct sdxi_cxt_l2_table *l2_table; + dma_addr_t l2_dma; + /* list of context l1 tables, on-demand, access with [l2_idx] */ + struct sdxi_cxt_l1_table *l1_table_array[L2_TABLE_ENTRIES]; + /* all contexts, on-demand, access with [l2_idx][l1_idx] */ + struct sdxi_cxt **cxt_array[L2_TABLE_ENTRIES]; + + struct dma_pool *write_index_pool; + struct dma_pool *cxt_sts_pool; + struct dma_pool *cxt_ctl_pool; + + /* error log */ + int error_irq; + struct sdxi_errlog_hd_ent *err_log; + dma_addr_t err_log_dma; + + /* DMA engine */ + struct dma_device dma_dev; + struct sdxi_dma_chan *sdxi_dma_chan; + struct sdxi_tasklet_data tdata; + + /* special contexts */ + struct sdxi_cxt *admin_cxt; /* admin context */ + struct sdxi_cxt *dma_cxt; /* DMA engine context */ + + const struct sdxi_dev_ops *dev_ops; +}; + +static inline struct device *sdxi_to_dev(const struct sdxi_dev *sdxi) +{ + return sdxi->dev; +} + +#define sdxi_dbg(s, fmt, ...) dev_dbg(sdxi_to_dev(s), fmt, ## __VA_ARGS__) +#define sdxi_info(s, fmt, ...) dev_info(sdxi_to_dev(s), fmt, ## __VA_ARGS_= _) +#define sdxi_err(s, fmt, ...) dev_err(sdxi_to_dev(s), fmt, ## __VA_ARGS__) + +/* Device Control */ +int sdxi_device_init(struct sdxi_dev *sdxi, const struct sdxi_dev_ops *ops= ); +void sdxi_device_exit(struct sdxi_dev *sdxi); + +static inline u64 sdxi_read64(const struct sdxi_dev *sdxi, enum sdxi_reg r= eg) +{ + return ioread64(sdxi->ctrl_regs + reg); +} + +static inline void sdxi_write64(struct sdxi_dev *sdxi, enum sdxi_reg reg, = u64 val) +{ + iowrite64(val, sdxi->ctrl_regs + reg); +} + +#endif /* __SDXI_H */ --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0B0E927A909; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; cv=none; b=cvvOq2pJXSwf389D8eXGQ8WGAn3F7cCkSQd4c5Vdu3bpFq7lCLAjljBlx3B8ZMM/KJLT76NO1QKy383ilHnyDynihJ+R1o1p7QGo2f1N6/mqstA16w2Y9x0aAaQvkNnUHYIUz5QM5+YQQ96ogrHeH6PGvl7pVHqRtpRDyvnQCt4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; c=relaxed/simple; bh=gxLms/n20WfLhcKgyfWTqx+j2vFsLPMIcU0uK5jEDN8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=I8jb6+bOX8yF79b0MJFaWgWzcpXEwxM2+dk84Ia+9smRI3iq2YTBbotklucF+YURVXfY4v/UmaNOEOFPRh5YZVj5wb3ZUTTxytGqJY9iHVEOHOvayUoApSWqI37CTnwwK1fMtKnBTikqvthLvgn1j2wAKEE9rJZiJEJQyAn0yHg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=N4YmxzDp; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="N4YmxzDp" Received: by smtp.kernel.org (Postfix) with ESMTPS id AD1EBC113D0; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098130; bh=gxLms/n20WfLhcKgyfWTqx+j2vFsLPMIcU0uK5jEDN8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=N4YmxzDpoD2C4slpYEGXeI5semrRJBCZrHX/mQE4k9GRM8sqLdGMswHu+7fwEFSGZ frlMFCrc3iHRN/rJigjZQNJmC9QjOnSpA+DZ3LQj9gVvn6ZZhOzTJwMenJrqaXFPUy e68NqBNe4Bfi8Y8hvDO+3ej0QLVvHuqCQXfugpTWO2p1Vlpey2rp1981RUlVgM/sUt aZL3goSXV1pZulMji30L8re9VNZalip5mkgprBup2P+1N4EytqRj7LG4TRMVWcxjAD rz/Oz1Je9eF1OPilAAUTqGIQn+G0oDLVWi0tx2ixRcaJWL0Gt+Ua4S4UElJB5Y2Zw2 kUhdpykzE7cWw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A14C8CA101F; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:29 -0500 Subject: [PATCH RFC 06/13] dmaengine: sdxi: Add error reporting support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-6-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098128; l=11588; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=6rZREI4qtaKsK3PLJAoeE8SshEtSkRN4UhMeM+BErEk=; b=tRj2S/vHwCyhHxb/jjucfFIPOohG6RXZjlIfumuDTioFhUimAkyvOhpE8vQ7jk+W5UsR5/enF JvP7BBAknarAyI/W7dLR61u1HsJh+o/kGQf3AVjj0FRY0BI9B2RChkO X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch SDXI implementations provide software with detailed information about error conditions using a per-device ring buffer in system memory. When an error condition is signaled via interrupt, the driver retrieves any pending error log entries and reports them to the kernel log. Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- drivers/dma/sdxi/error.c | 340 +++++++++++++++++++++++++++++++++++++++++++= ++++ drivers/dma/sdxi/error.h | 16 +++ 2 files changed, 356 insertions(+) diff --git a/drivers/dma/sdxi/error.c b/drivers/dma/sdxi/error.c new file mode 100644 index 0000000000000000000000000000000000000000..c5e33f5989250352f6b081a3049= b3b1f972c85a6 --- /dev/null +++ b/drivers/dma/sdxi/error.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * SDXI error reporting. + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include + +#include "error.h" +#include "mmio.h" +#include "sdxi.h" + +/* + * The error log ring buffer size is configurable, but for now we fix + * it to 64 entries (which is the spec minimum). + */ +#define ERROR_LOG_ENTRIES 64 +#define ERROR_LOG_SZ (ERROR_LOG_ENTRIES * sizeof(struct sdxi_errlog_hd_ent= )) + +/* The "unpacked" counterpart to ERRLOG_HD_ENT. */ +struct errlog_entry { + u64 dsc_index; + u16 cxt_num; + u16 err_class; + u16 type; + u8 step; + u8 buf; + u8 sub_step; + u8 re; + bool vl; + bool cv; + bool div; + bool bv; +}; + +#define ERRLOG_ENTRY_FIELD(hi_, lo_, name_) \ + PACKED_FIELD(hi_, lo_, struct errlog_entry, name_) +#define ERRLOG_ENTRY_FLAG(nr_, name_) \ + ERRLOG_ENTRY_FIELD(nr_, nr_, name_) + +/* Refer to "Error Log Header Entry (ERRLOG_HD_ENT)" */ +static const struct packed_field_u16 errlog_hd_ent_fields[] =3D { + ERRLOG_ENTRY_FLAG(0, vl), + ERRLOG_ENTRY_FIELD(13, 8, step), + ERRLOG_ENTRY_FIELD(26, 16, type), + ERRLOG_ENTRY_FLAG(32, cv), + ERRLOG_ENTRY_FLAG(33, div), + ERRLOG_ENTRY_FLAG(34, bv), + ERRLOG_ENTRY_FIELD(38, 36, buf), + ERRLOG_ENTRY_FIELD(43, 40, sub_step), + ERRLOG_ENTRY_FIELD(46, 44, re), + ERRLOG_ENTRY_FIELD(63, 48, cxt_num), + ERRLOG_ENTRY_FIELD(127, 64, dsc_index), + ERRLOG_ENTRY_FIELD(367, 352, err_class), +}; + +enum { + SDXI_PACKING_QUIRKS =3D QUIRK_LITTLE_ENDIAN | QUIRK_LSW32_IS_FIRST, +}; + +/* + * Refer to "(Flagged) Processing Step" and + * "Error Log Header Entry (ERRLOG_HD_ENT)", subfield "step" + */ +enum errv_step { + ERRV_INT =3D 1, + ERRV_CXT_L2 =3D 2, + ERRV_CXT_L1 =3D 3, + ERRV_CXT_CTL =3D 4, + ERRV_CXT_STS =3D 5, + ERRV_WRT_IDX =3D 6, + ERRV_DSC_GEN =3D 7, + ERRV_DSC_CSB =3D 8, + ERRV_ATOMIC =3D 9, + ERRV_DSC_BUF =3D 10, + ERRV_DSC_AKEY =3D 11, + ERRV_FN_RKEY =3D 12, +}; + +static const char *const processing_steps[] =3D { + [ERRV_INT] =3D "Internal Error", + [ERRV_CXT_L2] =3D "Context Level 2 Table Entry - Translate, Read, Val= idate", + [ERRV_CXT_L1] =3D "Context Level 1 Table Entry - Translate, Read, Val= idate", + [ERRV_CXT_CTL] =3D "Context Control - Translate, Read, Validate", + [ERRV_CXT_STS] =3D "Context Status - Translate, Access, Validate", + [ERRV_WRT_IDX] =3D "Write_Index - Translate, Read, Validate", + [ERRV_DSC_GEN] =3D "Descriptor Entry - Translate, Access, Validate", + [ERRV_DSC_CSB] =3D "Descriptor CST_BLK - Translate, Access, Validate", + [ERRV_ATOMIC] =3D "Atomic Return Data - Translate, Access", + [ERRV_DSC_BUF] =3D "Descriptor: Data Buffer - Translate, Access", + [ERRV_DSC_AKEY] =3D "Descriptor AKey Lookup - Translate, Access, Valida= te", + [ERRV_FN_RKEY] =3D "Function RKey Lookup - Translate, Read, Validate", +}; + +static const char *step_str(enum errv_step step) +{ + const char *str =3D "reserved"; + + switch (step) { + case ERRV_INT ... ERRV_FN_RKEY: + str =3D processing_steps[step]; + break; + } + + return str; +} + +/* Refer to "Error Log Header Entry (ERRLOG_HD_ENT)", subfield "sub_step" = */ +enum errv_sub_step { + SUB_STEP_OTHER =3D 0, + SUB_STEP_ATF =3D 1, + SUB_STEP_DAF =3D 2, + SUB_STEP_DVF =3D 3, +}; + +static const char * const processing_sub_steps[] =3D { + [SUB_STEP_OTHER] =3D "Other/unknown", + [SUB_STEP_ATF] =3D "Address Translation Failure", + [SUB_STEP_DAF] =3D "Data Access Failure", + [SUB_STEP_DVF] =3D "Data Validation Failure", +}; + +static const char *sub_step_str(enum errv_sub_step sub_step) +{ + const char *str =3D "reserved"; + + switch (sub_step) { + case SUB_STEP_OTHER ... SUB_STEP_DVF: + str =3D processing_sub_steps[sub_step]; + break; + } + + return str; +} + +/* Refer to "Error Log Header Entry (ERRLOG_HD_ENT)", subfield "re" */ +enum fn_reaction { + FN_REACT_INFORM =3D 0, + FN_REACT_CXT_STOP =3D 1, + FN_REACT_FN_STOP =3D 2, +}; + +static const char * const fn_reactions[] =3D { + [FN_REACT_INFORM] =3D "Informative, nothing stopped", + [FN_REACT_CXT_STOP] =3D "Context stopped", + [FN_REACT_FN_STOP] =3D "Function stopped", +}; + +static const char *reaction_str(enum fn_reaction reaction) +{ + const char *str =3D "reserved"; + + switch (reaction) { + case FN_REACT_INFORM ... FN_REACT_FN_STOP: + str =3D fn_reactions[reaction]; + break; + } + + return str; +} + +static void sdxi_print_err(struct sdxi_dev *sdxi, u64 err_rd) +{ + struct errlog_entry ent; + size_t index; + + index =3D err_rd % ERROR_LOG_ENTRIES; + + unpack_fields(&sdxi->err_log[index], sizeof(sdxi->err_log[0]), + &ent, errlog_hd_ent_fields, SDXI_PACKING_QUIRKS); + + if (!ent.vl) { + dev_err_ratelimited(sdxi_to_dev(sdxi), + "Ignoring error log entry with vl=3D0\n"); + return; + } + + if (ent.type !=3D OP_TYPE_ERRLOG) { + dev_err_ratelimited(sdxi_to_dev(sdxi), + "Ignoring error log entry with type=3D%#x\n", + ent.type); + return; + } + + sdxi_err(sdxi, "error log entry[%zu], MMIO_ERR_RD=3D%#llx:\n", + index, err_rd); + sdxi_err(sdxi, " re: %#x (%s)\n", ent.re, reaction_str(ent.re)); + sdxi_err(sdxi, " step: %#x (%s)\n", ent.step, step_str(ent.step)); + sdxi_err(sdxi, " sub_step: %#x (%s)\n", + ent.sub_step, sub_step_str(ent.sub_step)); + sdxi_err(sdxi, " cv: %u div: %u bv: %u\n", ent.cv, ent.div, ent.bv); + if (ent.bv) + sdxi_err(sdxi, " buf: %u\n", ent.buf); + if (ent.cv) + sdxi_err(sdxi, " cxt_num: %#x\n", ent.cxt_num); + if (ent.div) + sdxi_err(sdxi, " dsc_index: %#llx\n", ent.dsc_index); + sdxi_err(sdxi, " err_class: %#x\n", ent.err_class); +} + +/* Refer to "Error Log Processing by Software" */ +static irqreturn_t sdxi_irq_thread(int irq, void *data) +{ + struct sdxi_dev *sdxi =3D data; + u64 write_index; + u64 read_index; + u64 err_sts; + + /* 1. Check MMIO_ERR_STS and perform any required remediation. */ + err_sts =3D sdxi_read64(sdxi, SDXI_MMIO_ERR_STS); + if (!(err_sts & SDXI_MMIO_ERR_STS_STS_BIT)) + return IRQ_HANDLED; + + if (err_sts & SDXI_MMIO_ERR_STS_ERR_BIT) { + /* + * Assume this isn't recoverable; e.g. the error log + * isn't configured correctly. Don't clear + * SDXI_MMIO_ERR_STS before returning. + */ + sdxi_err(sdxi, "attempted but failed to log errors\n"); + sdxi_err(sdxi, "error log not functional\n"); + return IRQ_HANDLED; + } + + if (err_sts & SDXI_MMIO_ERR_STS_OVF_BIT) + sdxi_err(sdxi, "error log overflow, some entries lost\n"); + + /* 2. If MMIO_ERR_STS.sts is 1, then compute read_index. */ + read_index =3D sdxi_read64(sdxi, SDXI_MMIO_ERR_RD); + + /* 3. Clear MMIO_ERR_STS. The flags in this register are RW1C. */ + sdxi_write64(sdxi, SDXI_MMIO_ERR_STS, + SDXI_MMIO_ERR_STS_STS_BIT | + SDXI_MMIO_ERR_STS_OVF_BIT | + SDXI_MMIO_ERR_STS_ERR_BIT); + + /* 4. Compute write_index. */ + write_index =3D sdxi_read64(sdxi, SDXI_MMIO_ERR_WRT); + + /* 5. If the indexes are equal then exit. */ + if (read_index =3D=3D write_index) + return IRQ_HANDLED; + + /* 6. While read_index < write_index... */ + while (read_index < write_index) { + + /* + * 7. and 8. Compute the real ring buffer index from + * read_index and process the entry. + */ + sdxi_print_err(sdxi, read_index); + + /* 9. Advance read_index. */ + ++read_index; + + /* 10. Return to step 6. */ + } + + /* 11. Write read_index to MMIO_ERR_RD. */ + sdxi_write64(sdxi, SDXI_MMIO_ERR_RD, read_index); + + return IRQ_HANDLED; +} + +/* Refer to "Error Log Initialization" */ +int sdxi_error_init(struct sdxi_dev *sdxi) +{ + u64 reg; + int err; + + /* 1. Clear MMIO_ERR_CFG. Error interrupts are inhibited until step 6. */ + sdxi_write64(sdxi, SDXI_MMIO_ERR_CFG, 0); + + /* 2. Clear MMIO_ERR_STS. The flags in this register are RW1C. */ + reg =3D FIELD_PREP(SDXI_MMIO_ERR_STS_STS_BIT, 1) | + FIELD_PREP(SDXI_MMIO_ERR_STS_OVF_BIT, 1) | + FIELD_PREP(SDXI_MMIO_ERR_STS_ERR_BIT, 1); + sdxi_write64(sdxi, SDXI_MMIO_ERR_STS, reg); + + /* 3. Allocate memory for the error log ring buffer, initialize to zero. = */ + sdxi->err_log =3D dma_alloc_coherent(sdxi_to_dev(sdxi), ERROR_LOG_SZ, + &sdxi->err_log_dma, GFP_KERNEL); + if (!sdxi->err_log) + return -ENOMEM; + + /* + * 4. Set MMIO_ERR_CTL.intr_en to 1 if interrupts on + * context-level errors are desired. + */ + reg =3D sdxi_read64(sdxi, SDXI_MMIO_ERR_CTL); + FIELD_MODIFY(SDXI_MMIO_ERR_CTL_EN, ®, 1); + sdxi_write64(sdxi, SDXI_MMIO_ERR_CTL, reg); + + /* + * The spec is not explicit about when to do this, but this + * seems like the right time: enable interrupt on + * function-level transition to error state. + */ + reg =3D sdxi_read64(sdxi, SDXI_MMIO_CTL0); + FIELD_MODIFY(SDXI_MMIO_CTL0_FN_ERR_INTR_EN, ®, 1); + sdxi_write64(sdxi, SDXI_MMIO_CTL0, reg); + + /* 5. Clear MMIO_ERR_WRT and MMIO_ERR_RD. */ + sdxi_write64(sdxi, SDXI_MMIO_ERR_WRT, 0); + sdxi_write64(sdxi, SDXI_MMIO_ERR_RD, 0); + + /* + * Error interrupts can be generated once MMIO_ERR_CFG.en is + * set in step 6, so set up the handler now. + */ + err =3D request_threaded_irq(sdxi->error_irq, NULL, sdxi_irq_thread, + IRQF_TRIGGER_NONE, "SDXI error", sdxi); + if (err) + goto free_errlog; + + /* 6. Program MMIO_ERR_CFG. */ + reg =3D FIELD_PREP(SDXI_MMIO_ERR_CFG_PTR, sdxi->err_log_dma >> 12) | + FIELD_PREP(SDXI_MMIO_ERR_CFG_SZ, ERROR_LOG_ENTRIES >> 6) | + FIELD_PREP(SDXI_MMIO_ERR_CFG_EN, 1); + sdxi_write64(sdxi, SDXI_MMIO_ERR_CFG, reg); + + return 0; + +free_errlog: + dma_free_coherent(sdxi_to_dev(sdxi), ERROR_LOG_SZ, + sdxi->err_log, sdxi->err_log_dma); + return err; +} + +void sdxi_error_exit(struct sdxi_dev *sdxi) +{ + sdxi_write64(sdxi, SDXI_MMIO_ERR_CFG, 0); + free_irq(sdxi->error_irq, sdxi); + dma_free_coherent(sdxi_to_dev(sdxi), ERROR_LOG_SZ, + sdxi->err_log, sdxi->err_log_dma); +} diff --git a/drivers/dma/sdxi/error.h b/drivers/dma/sdxi/error.h new file mode 100644 index 0000000000000000000000000000000000000000..50019d9811184464227ae13baa5= 09101a2a3aacc --- /dev/null +++ b/drivers/dma/sdxi/error.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * SDXI error handling entry points. + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ + +#ifndef DMA_SDXI_ERROR_H +#define DMA_SDXI_ERROR_H + +struct sdxi_dev; + +int sdxi_error_init(struct sdxi_dev *sdxi); +void sdxi_error_exit(struct sdxi_dev *sdxi); + +#endif /* DMA_SDXI_ERROR_H */ --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0980127A46F; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; cv=none; b=an+JLMFz/R79cwcz3n3RXS0DjSZf0UyYFeP7/uf/KWVwkl28Iklao7lqdOg0VKh2j92j/N44/HAEWGlJiuMAJip2HJvgz1PJTDq4hc1gEvwfCWAR/vYmdb98RrM1Jaa/2Z97h97+tJFputD+ajZOsSLGW/ybzG8XzYD2WztZFrk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; c=relaxed/simple; bh=wiKtrMUTBnbglWQdf3kSumEayhCZBoUGyUsbB4zNui0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ckGkdUg48tWjtLPZvbeUYY1jeat55KYrRf1LXBBnM5VYnBVPG7+etsl8rgC5H22PnwwPUQU9kRMKfeL+bkJ4sldAFfiUYcnxmlDk9sOYczg/fB9Uft3BcsRafLFQRkGRH5uciRazWcZvy7ph0Z3ro5wL8HogY9RbDictezt0otk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jejWE39U; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jejWE39U" Received: by smtp.kernel.org (Postfix) with ESMTPS id B9927C116B1; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098130; bh=wiKtrMUTBnbglWQdf3kSumEayhCZBoUGyUsbB4zNui0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=jejWE39UFeayJLgnCIT97DVFruUITO5IRxYVJWdCwrX6AWJsC9MEaocKO0kn1RxBz 9gHr5IjTSzOjrK9WL1TwUzsXDSTs8lF6U4aQz3ucO0pzmXZhsCcqRR0aw77nR2LQYf nHbvCN1+G+ueYKe2fYnsasFZ/vduP08owZOs6AmQrciThCRuMHzbuHo8tdu1xt+gDE wwptPt0BlDwUMI0D7UoXOlQqbo5gLWhA4x4k70QcfgYqR2RjkmU6oh8wVd2pNTpAtD 5NXYOzDGZ8ORwecqB7J2DxaW/z/N1vDkjN2DV6GVcP4G+z6CNl1n1BqzcgVcBjUzTE qUjwji3P897xg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE75DCA1016; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:30 -0500 Subject: [PATCH RFC 07/13] dmaengine: sdxi: Import descriptor enqueue code from spec Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-7-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098128; l=7380; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=V/0nM3VPtzsbRtFsPQeZdWfXoMPAZ0o1AE15Y38dm0o=; b=1pvAl0avFaxDykwFGf9Ax+fGUUnqKK5QmQiIabsFmkUCiMOieAGEKZrrlTAtQhwDGj6gJOF/m VRgUqSw0VKPD6Vi/5/uCIEluW3p6j2ogo8khUvU8QLWP2RXRroaEazw X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch Import the example code from the "SDXI Descriptor Ring Operation" chapter of the SDXI 1.0 spec[1], which demonstrates lockless descriptor submission to the ring. Lightly alter the code to (somewhat) comply with Linux coding style, and use byte order-aware types as well as kernel atomic and barrier APIs. Ultimately we may not really need a lockless submission path, and it would be better for it to more closely integrate with the rest of the driver. [1] https://www.snia.org/sites/default/files/technical-work/sdxi/release/SN= IA-SDXI-Specification-v1.0a.pdf Signed-off-by: Nathan Lynch --- drivers/dma/sdxi/enqueue.c | 136 +++++++++++++++++++++++++++++++++++++++++= ++++ drivers/dma/sdxi/enqueue.h | 16 ++++++ 2 files changed, 152 insertions(+) diff --git a/drivers/dma/sdxi/enqueue.c b/drivers/dma/sdxi/enqueue.c new file mode 100644 index 0000000000000000000000000000000000000000..822d9b890fa3538dcc09e99ef56= 2a6d8419290f0 --- /dev/null +++ b/drivers/dma/sdxi/enqueue.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * + * Copyright (c) 2024, The Storage Networking Industry Association. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of The Storage Networking Industry Association + * (SNIA) nor the names of its contributors may be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "enqueue.h" + +/* + * Code adapted from the "SDXI Descriptor Ring Operation" chapter of + * the SDXI spec, specifically the example code in "Enqueuing one or + * more Descriptors." + */ + +#define SDXI_DESCR_SIZE 64 +#define SDXI_DS_NUM_QW (SDXI_DESCR_SIZE / sizeof(__le64)) +#define SDXI_MULTI_PRODUCER 1 /* Define to 0 if single-producer. */ + +static int update_ring(const __le64 *enq_entries, /* Ptr to entries to e= nqueue */ + u64 enq_num, /* Number of entries to enqueue */ + __le64 *ring_base, /* Ptr to ring location */ + u64 ring_size, /* (Ring Size in bytes)/64 */ + u64 index) /* Starting ring index to update */ +{ + for (u64 i =3D 0; i < enq_num; i++) { + __le64 *ringp =3D ring_base + ((index + i) % ring_size) * SDXI_DS_NUM_QW; + const __le64 *entryp =3D enq_entries + (i * SDXI_DS_NUM_QW); + + for (u64 j =3D 1; j < SDXI_DS_NUM_QW; j++) + *(ringp + j) =3D *(entryp + j); + } + + /* Now write the first QW of the new entries to the ring. */ + dma_wmb(); + for (u64 i =3D 0; i < enq_num; i++) { + __le64 *ringp =3D ring_base + ((index + i) % ring_size) * SDXI_DS_NUM_QW; + const __le64 *entryp =3D enq_entries + (i * SDXI_DS_NUM_QW); + + *ringp =3D *entryp; + } + + return 0; +} + +int sdxi_enqueue(const __le64 *enq_entries, /* Ptr to entr= ies to enqueue */ + u64 enq_num, /* Number of entries to enqu= eue */ + __le64 *ring_base, /* Ptr to ring location */ + u64 ring_size, /* (Ring Size in bytes)/64 */ + __le64 const volatile * const Read_Index, /* Ptr to Read_Index locatio= n */ + __le64 volatile * const Write_Index, /* Ptr to Write_Index locati= on */ + __le64 __iomem *Door_Bell) /* Ptr to Ring Doorbell loca= tion */ +{ + u64 old_write_idx; + u64 new_idx; + + while (true) { + u64 read_idx; + + read_idx =3D le64_to_cpu(READ_ONCE(*Read_Index)); + dma_rmb(); /* Get Read_Index before Write_Index to always get consisten= t values */ + old_write_idx =3D le64_to_cpu(READ_ONCE(*Write_Index)); + + if (read_idx > old_write_idx) { + /* Only happens if Write_Index wraps or ring has bad setup */ + return -EIO; + } + + new_idx =3D old_write_idx + enq_num; + if (new_idx - read_idx > ring_size) { + cpu_relax(); + continue; /* Not enough free entries, try again */ + } + + if (SDXI_MULTI_PRODUCER) { + /* Try to atomically update Write_Index. */ + bool success =3D cmpxchg(Write_Index, + cpu_to_le64(old_write_idx), + cpu_to_le64(new_idx)) =3D=3D cpu_to_le64(old_write_idx); + if (success) + break; /* Updated Write_Index, no need to try again. */ + } else { + /* Single-Producer case */ + WRITE_ONCE(*Write_Index, cpu_to_le64(new_idx)); + dma_wmb(); /* Make the Write_Index update visible before the Door_Bell= update. */ + break; /* Always successful for single-producer */ + } + /* Couldn"t update Write_Index, try again. */ + } + + /* Write_Index is now advanced. Let's write out entries to the ring. */ + update_ring(enq_entries, enq_num, ring_base, ring_size, old_write_idx); + + /* Door_Bell write required; only needs ordering wrt update of Write_Inde= x. */ + iowrite64(new_idx, Door_Bell); + + return 0; +} diff --git a/drivers/dma/sdxi/enqueue.h b/drivers/dma/sdxi/enqueue.h new file mode 100644 index 0000000000000000000000000000000000000000..28c1493779db1119ff0d682fa66= 23b016998042a --- /dev/null +++ b/drivers/dma/sdxi/enqueue.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright (c) 2024, The Storage Networking Industry Association. */ +#ifndef DMA_SDXI_ENQUEUE_H +#define DMA_SDXI_ENQUEUE_H + +#include + +int sdxi_enqueue(const __le64 *enq_entries, /* Ptr to entries to enqueue = */ + u64 enq_num, /* Number of entries to enqueue */ + __le64 *ring_base, /* Ptr to ring location */ + u64 ring_size, /* (Ring Size in bytes)/64 */ + __le64 const volatile * const Read_Index, /* Ptr to Read_Index locatio= n */ + __le64 volatile * const Write_Index, /* Ptr to Write_Index location */ + __le64 __iomem *Door_Bell); /* Ptr to Ring Doorbell location */ + +#endif /* DMA_SDXI_ENQUEUE_H */ --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49E5627F4CA; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; cv=none; b=jpVR+xSeAboyBETj6Z+pJRg2Oxn8GxGTEo3+j0kl1vg7bija5ICh17NpBWAWeSewtPrXPt7AeQlim/TU2WSq1LEmI4lGxEkOyk0q9WOYKAoyi/RnlGEI4gHmKP6A+uYgK5XU0DW6VHTFT6PS0GpwsXSMgg2bRiZXEiEnmBrsZK4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; c=relaxed/simple; bh=lNpp44K3BnOuDeghBvmyBNwrIJSkqRSym+tsHtCvq4g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LDLb+x5crzNppFZWDP6VnUqSwF1ZPRDqHzLedCmwFYd9TuYg//c/yI+2qcLtej+8JmC1IQcApFF/+dDyfVPKl38AFwdtsZapj5i82ffzMMOpjJL9cqRK0Xa5yeStG0xsURKSyrpYy18n0+WOIbq9UVVorKol3hCagtYTbMjAb88= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=mTcY9GeY; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="mTcY9GeY" Received: by smtp.kernel.org (Postfix) with ESMTPS id C8D0BC4CEFD; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098130; bh=lNpp44K3BnOuDeghBvmyBNwrIJSkqRSym+tsHtCvq4g=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=mTcY9GeYCIGVAXkEg+UPmPW3DaUQmFFqDOsAGGNQyLzA7Svg6m5erHGqP9V1qoHAw Xtd2fQQNKEqlhS7K2O39D22RT3Bx2FENwJwDSBQaaldbqptI3W8PvUyL53mdvhYcq2 tWwz/ISWtXKBWm+MmijUXeNyg8xE/5NmV2EzCxZe0kYGwMR/kKkYIZpQlQ6+BNtjuD Roer7Y048nZdfFqwWCyhBYitBLPTID6lugNsiTWblMgkiIyDUEfWA+IIYFrhpO0Uyx lWAPE9Z2eN8OVP44WVDy9I7Vd2LxDFUX2lIOBSW+EVtYBayFLRO2++bNkKXwJsBc/L i8TDWR6oBDPHQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id BDA13CA0FED; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:31 -0500 Subject: [PATCH RFC 08/13] dmaengine: sdxi: Context creation/removal, descriptor submission Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-8-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098128; l=16593; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=6vnlgFihNDCCXUt5FVQCXcCV30Q9eCrvX8Y1CxnbF2M=; b=8QHr3XJ6xjZkL9PA8vDDjIp4VwpfOSbnZ/dCQjuUyBQCe3HDSsYzvWKYN3TAkkKA0E+t8ByHO tXb7vRmiudeCNfA5kNnm2qihGN9q6or9XLw3RUP1DfxLE229RdsTXns X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch Add functions for creating and removing SDXI contexts and submitting descriptors against them. An SDXI function supports one or more contexts, each of which has its own descriptor ring and associated state. Each context has a 16-bit index. A special context is installed at index 0 and is used for configuring other contexts and performing administrative actions. The creation of each context entails the allocation of the following control structure hierarchy: * Context L1 Table slot * Access key (AKey) table * Context control block * Descriptor ring * Write index * Context status block Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- drivers/dma/sdxi/context.c | 547 +++++++++++++++++++++++++++++++++++++++++= ++++ drivers/dma/sdxi/context.h | 28 +++ 2 files changed, 575 insertions(+) diff --git a/drivers/dma/sdxi/context.c b/drivers/dma/sdxi/context.c new file mode 100644 index 0000000000000000000000000000000000000000..50eae5b3b303d67891113377e2d= f209d199aa533 --- /dev/null +++ b/drivers/dma/sdxi/context.c @@ -0,0 +1,547 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * SDXI submission queue (sq) and descriptor management + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ + +#define pr_fmt(fmt) "SDXI: " fmt + +#include +#include +#include +#include +#include +#include + +#include "context.h" +#include "descriptor.h" +#include "enqueue.h" +#include "hw.h" +#include "sdxi.h" + +/* Alloc sdxi_sq in kernel space */ +static struct sdxi_sq *sdxi_sq_alloc(struct sdxi_cxt *cxt, int ring_entrie= s) +{ + struct sdxi_dev *sdxi =3D cxt->sdxi; + struct device *dev =3D sdxi_to_dev(sdxi); + u64 write_index_ptr; + struct sdxi_sq *sq; + u64 ds_ring_ptr; + u64 cxt_sts_ptr; + u32 ds_ring_sz; + + /* alloc desc_ring */ + if (ring_entries > sdxi->max_ring_entries) { + sdxi_err(sdxi, "%d ring entries requested, max is %llu\n", + ring_entries, sdxi->max_ring_entries); + return NULL; + } + + sq =3D kzalloc(sizeof(*sq), GFP_KERNEL); + if (!sq) + return NULL; + + sq->ring_entries =3D ring_entries; + sq->ring_size =3D sizeof(sq->desc_ring[0]) * sq->ring_entries; + sq->desc_ring =3D dma_alloc_coherent(dev, sq->ring_size, &sq->ring_dma, + GFP_KERNEL); + if (!sq->desc_ring) + goto free_sq; + + sq->cxt_sts =3D dma_pool_zalloc(sdxi->cxt_sts_pool, GFP_KERNEL, &sq->cxt_= sts_dma); + if (!sq->cxt_sts) + goto free_desc_ring; + + sq->write_index =3D dma_pool_zalloc(sdxi->write_index_pool, GFP_KERNEL, + &sq->write_index_dma); + if (!sq->write_index) + goto free_cxt_sts; + + /* final setup */ + if (cxt->id =3D=3D SDXI_ADMIN_CXT_ID || cxt->id =3D=3D SDXI_DMA_CXT_ID) + sq->cxt_sts->state =3D FIELD_PREP(SDXI_CXT_STS_STATE, CXTV_RUN); + + write_index_ptr =3D FIELD_PREP(SDXI_CXT_CTL_WRITE_INDEX_PTR, + sq->write_index_dma >> 3); + cxt_sts_ptr =3D FIELD_PREP(SDXI_CXT_CTL_CXT_STS_PTR, + sq->cxt_sts_dma >> 4); + ds_ring_sz =3D sq->ring_size >> 6; + + cxt->cxt_ctl->write_index_ptr =3D cpu_to_le64(write_index_ptr); + cxt->cxt_ctl->cxt_sts_ptr =3D cpu_to_le64(cxt_sts_ptr); + cxt->cxt_ctl->ds_ring_sz =3D cpu_to_le32(ds_ring_sz); + + /* turn it on now */ + sq->cxt =3D cxt; + cxt->sq =3D sq; + ds_ring_ptr =3D (FIELD_PREP(SDXI_CXT_CTL_DS_RING_PTR, sq->ring_dma >> 6) | + FIELD_PREP(SDXI_CXT_CTL_VL, 1)); + dma_wmb(); + WRITE_ONCE(cxt->cxt_ctl->ds_ring_ptr, cpu_to_le64(ds_ring_ptr)); + + sdxi_dbg(sdxi, "sq created, id=3D%d, cxt_ctl=3D%p\n" + " desc ring addr: v=3D0x%p:d=3D%pad\n" + " write index addr: v=3D0x%p:d=3D%pad\n" + " cxt status addr: v=3D0x%p:d=3D%pad\n", + cxt->id, cxt->cxt_ctl, + sq->desc_ring, &sq->ring_dma, + sq->write_index, &sq->write_index_dma, + sq->cxt_sts, &sq->cxt_sts_dma); + + return sq; + +free_cxt_sts: + dma_pool_free(sdxi->cxt_sts_pool, sq->cxt_sts, sq->cxt_sts_dma); +free_desc_ring: + dma_free_coherent(dev, sq->ring_size, sq->desc_ring, sq->ring_dma); +free_sq: + kfree(sq); + return NULL; +} + +static void sdxi_sq_free(struct sdxi_sq *sq) +{ + struct sdxi_cxt *cxt =3D sq->cxt; + struct sdxi_dev *sdxi =3D cxt->sdxi; + struct device *dev =3D sdxi_to_dev(sdxi); + + if (!cxt) + return; + + dma_pool_free(sdxi->write_index_pool, sq->write_index, sq->write_index_dm= a); + dma_pool_free(sdxi->cxt_sts_pool, sq->cxt_sts, sq->cxt_sts_dma); + dma_free_coherent(dev, sq->ring_size, sq->desc_ring, sq->ring_dma); + + cxt->sq =3D NULL; + kfree(sq); +} + +/* Default size 1024 =3D=3D> 64KB descriptor ring, guaranteed */ +#define DEFAULT_DESC_RING_ENTRIES 1024 +static struct sdxi_sq *sdxi_sq_alloc_default(struct sdxi_cxt *cxt) +{ + return sdxi_sq_alloc(cxt, DEFAULT_DESC_RING_ENTRIES); +} + +static bool sdxi_cxt_l2_ent_vl(const struct sdxi_cxt_l2_ent *ent) +{ + return FIELD_GET(SDXI_CXT_L2_ENT_VL, le64_to_cpu(ent->lv01_ptr)); +} + +static dma_addr_t sdxi_cxt_l2_ent_lv01_ptr(const struct sdxi_cxt_l2_ent *e= nt) +{ + return FIELD_GET(SDXI_CXT_L2_ENT_LV01_PTR, le64_to_cpu(ent->lv01_ptr)) <<= ilog2(SZ_4K); +} + +static void set_cxt_l2_entry(struct sdxi_cxt_l2_ent *l2_entry, + dma_addr_t l1_table_dma) +{ + u64 lv01_ptr; + + /* We shouldn't be updating a live entry. */ + if (WARN_ON_ONCE(sdxi_cxt_l2_ent_vl(l2_entry))) + return; + /* L1 tables must be 4K-aligned. */ + if (WARN_ON_ONCE(!IS_ALIGNED(l1_table_dma, SZ_4K))) + return; + + lv01_ptr =3D (FIELD_PREP(SDXI_CXT_L2_ENT_LV01_PTR, + l1_table_dma >> ilog2(SZ_4K)) | + FIELD_PREP(SDXI_CXT_L2_ENT_VL, 1)); + + /* + * Ensure the valid bit update follows prior updates to other + * control structures. + */ + dma_wmb(); + WRITE_ONCE(l2_entry->lv01_ptr, cpu_to_le64(lv01_ptr)); +} + +static void set_cxt_l1_entry(struct sdxi_dev *sdxi, + struct sdxi_cxt_l1_ent *l1_entry, + struct sdxi_cxt *cxt) +{ + u64 cxt_ctl_ptr; + u64 akey_ptr; + u16 intr_num; + u32 misc0; + + if (!cxt) { + memset(l1_entry, 0, sizeof(*l1_entry)); + return; + } + + cxt_ctl_ptr =3D (FIELD_PREP(SDXI_CXT_L1_ENT_VL, 1) | + FIELD_PREP(SDXI_CXT_L1_ENT_KA, 1) | + FIELD_PREP(SDXI_CXT_L1_ENT_CXT_CTL_PTR, + cxt->cxt_ctl_dma >> L1_CXT_CTRL_PTR_SHIFT)); + akey_ptr =3D (FIELD_PREP(SDXI_CXT_L1_ENT_AKEY_SZ, + akey_table_order(cxt->akey_table)) | + FIELD_PREP(SDXI_CXT_L1_ENT_AKEY_PTR, + cxt->akey_table_dma >> L1_CXT_AKEY_PTR_SHIFT)); + misc0 =3D FIELD_PREP(SDXI_CXT_L1_ENT_MAX_BUFFER, 11); + + *l1_entry =3D (struct sdxi_cxt_l1_ent) { + .cxt_ctl_ptr =3D cpu_to_le64(cxt_ctl_ptr), + .akey_ptr =3D cpu_to_le64(akey_ptr), + .misc0 =3D cpu_to_le32(misc0), + .opb_000_enb =3D cpu_to_le32(sdxi->op_grp_cap), + }; + + intr_num =3D le16_to_cpu(cxt->akey_table->entry[0].intr_num); + FIELD_MODIFY(SDXI_AKEY_ENT_VL, &intr_num, 1); + cxt->akey_table->entry[0].intr_num =3D cpu_to_le16(intr_num); +} + +static int config_cxt_tables(struct sdxi_dev *sdxi, + struct sdxi_cxt *cxt) +{ + struct sdxi_cxt_l1_table *l1_table; + struct sdxi_cxt_l1_ent *l1_entry; + u16 l2_idx; + u8 l1_idx; + + l2_idx =3D ID_TO_L2_INDEX(cxt->id); + l1_idx =3D ID_TO_L1_INDEX(cxt->id); + + /* Allocate L1 table if not present. */ + l1_table =3D sdxi->l1_table_array[l2_idx]; + if (!l1_table) { + struct sdxi_cxt_l2_ent *l2_entry; + dma_addr_t l1_table_dma; + + l1_table =3D dma_alloc_coherent(sdxi_to_dev(sdxi), + sizeof(*l1_table), + &l1_table_dma, GFP_KERNEL); + if (!l1_table) + return -ENOMEM; + + /* Track the L1 table vaddr. */ + sdxi->l1_table_array[l2_idx] =3D l1_table; + + /* Install the new entry in the L2 table. */ + l2_entry =3D &sdxi->l2_table->entry[l2_idx]; + set_cxt_l2_entry(l2_entry, l1_table_dma); + } + + /* Populate the L1 entry. */ + l1_entry =3D &l1_table->entry[l1_idx]; + set_cxt_l1_entry(cxt->sdxi, l1_entry, cxt); + + return 0; +} + +static void clear_cxt_table_entries(struct sdxi_cxt_l2_table *l2_table, + struct sdxi_cxt_l1_table *l1_table, + struct sdxi_cxt *cxt) +{ + struct sdxi_cxt_l2_ent *l2_entry; + struct sdxi_cxt_l1_ent *l1_entry; + struct sdxi_dev *sdxi =3D cxt->sdxi; + dma_addr_t l1_dma; + + l2_entry =3D &l2_table->entry[ID_TO_L2_INDEX(cxt->id)]; + l1_entry =3D &l1_table->entry[ID_TO_L1_INDEX(cxt->id)]; + + memset(l1_entry, 0, sizeof(*l1_entry)); + + /* If this L1 table has been completely zeroed then free it. */ + if (memchr_inv(l1_table, 0, L1_TABLE_SIZE)) + return; + + l1_dma =3D sdxi_cxt_l2_ent_lv01_ptr(l2_entry); + + memset(l2_entry, 0, sizeof(*l2_entry)); + + dma_free_coherent(sdxi_to_dev(sdxi), sizeof(*l1_table), + l1_table, l1_dma); +} + +static void cleanup_cxt_tables(struct sdxi_dev *sdxi, + struct sdxi_cxt *cxt) +{ + u16 l2_idx; + struct sdxi_cxt_l1_table *l1_table; + + if (!cxt) + return; + + l2_idx =3D ID_TO_L2_INDEX(cxt->id); + + l1_table =3D sdxi->l1_table_array[l2_idx]; + /* clear l1 entry */ + /* FIXME combine clear_cxt_table_entries and this function */ + clear_cxt_table_entries(sdxi->l2_table, l1_table, cxt); +} + +static struct sdxi_cxt *alloc_cxt(struct sdxi_dev *sdxi) +{ + struct sdxi_cxt *cxt; + u16 id, l2_idx, l1_idx; + + if (sdxi->cxt_count >=3D sdxi->max_cxts) + return NULL; + + /* search for an empty context slot */ + for (id =3D 0; id < sdxi->max_cxts; id++) { + l2_idx =3D ID_TO_L2_INDEX(id); + l1_idx =3D ID_TO_L1_INDEX(id); + + if (sdxi->cxt_array[l2_idx] =3D=3D NULL) { + int sz =3D sizeof(struct sdxi_cxt *) * L1_TABLE_ENTRIES; + struct sdxi_cxt **ptr =3D kzalloc(sz, GFP_KERNEL); + + sdxi->cxt_array[l2_idx] =3D ptr; + if (!(sdxi->cxt_array[l2_idx])) + return NULL; + } + + cxt =3D (sdxi->cxt_array)[l2_idx][l1_idx]; + /* found one empty slot */ + if (!cxt) + break; + } + + /* nothing found, bail... */ + if (id =3D=3D sdxi->max_cxts) + return NULL; + + /* alloc context and initialize it */ + cxt =3D kzalloc(sizeof(struct sdxi_cxt), GFP_KERNEL); + if (!cxt) + return NULL; + + cxt->akey_table =3D dma_alloc_coherent(sdxi_to_dev(sdxi), + sizeof(*cxt->akey_table), + &cxt->akey_table_dma, GFP_KERNEL); + if (!cxt->akey_table) { + kfree(cxt); + return NULL; + } + + cxt->sdxi =3D sdxi; + cxt->id =3D id; + cxt->db_base =3D sdxi->dbs_bar + id * sdxi->db_stride; + cxt->db =3D sdxi->dbs + id * sdxi->db_stride; + + sdxi->cxt_array[l2_idx][l1_idx] =3D cxt; + sdxi->cxt_count++; + + return cxt; +} + +static void free_cxt(struct sdxi_cxt *cxt) +{ + struct sdxi_dev *sdxi =3D cxt->sdxi; + u16 l2_idx, l1_idx; + + l2_idx =3D ID_TO_L2_INDEX(cxt->id); + l1_idx =3D ID_TO_L1_INDEX(cxt->id); + + sdxi->cxt_count--; + dma_free_coherent(sdxi_to_dev(sdxi), sizeof(*cxt->akey_table), + cxt->akey_table, cxt->akey_table_dma); + kfree(cxt); + + (sdxi->cxt_array)[l2_idx][l1_idx] =3D NULL; +} + +/* alloc context resources and populate context table */ +static struct sdxi_cxt *sdxi_cxt_alloc(struct sdxi_dev *sdxi) +{ + struct sdxi_cxt *cxt; + + mutex_lock(&sdxi->cxt_lock); + + cxt =3D alloc_cxt(sdxi); + if (!cxt) + goto drop_cxt_lock; + + cxt->cxt_ctl =3D dma_pool_zalloc(sdxi->cxt_ctl_pool, GFP_KERNEL, + &cxt->cxt_ctl_dma); + if (!cxt->cxt_ctl) + goto release_cxt; + + if (config_cxt_tables(sdxi, cxt)) + goto release_cxt_ctl; + + mutex_unlock(&sdxi->cxt_lock); + return cxt; + +release_cxt_ctl: + dma_pool_free(sdxi->cxt_ctl_pool, cxt->cxt_ctl, cxt->cxt_ctl_dma); +release_cxt: + free_cxt(cxt); +drop_cxt_lock: + mutex_unlock(&sdxi->cxt_lock); + return NULL; +} + +/* clear context table and free context resources */ +static void sdxi_cxt_free(struct sdxi_cxt *cxt) +{ + struct sdxi_dev *sdxi =3D cxt->sdxi; + + mutex_lock(&sdxi->cxt_lock); + + cleanup_cxt_tables(sdxi, cxt); + dma_pool_free(sdxi->cxt_ctl_pool, cxt->cxt_ctl, cxt->cxt_ctl_dma); + free_cxt(cxt); + + mutex_unlock(&sdxi->cxt_lock); +} + +struct sdxi_cxt *sdxi_working_cxt_init(struct sdxi_dev *sdxi, + enum sdxi_cxt_id id) +{ + struct sdxi_cxt *cxt; + struct sdxi_sq *sq; + + cxt =3D sdxi_cxt_alloc(sdxi); + if (!cxt) { + sdxi_err(sdxi, "failed to alloc a new context\n"); + return NULL; + } + + /* check if context ID matches */ + if (id < SDXI_ANY_CXT_ID && cxt->id !=3D id) { + sdxi_err(sdxi, "failed to alloc a context with id=3D%d\n", id); + goto err_cxt_id; + } + + sq =3D sdxi_sq_alloc_default(cxt); + if (!sq) { + sdxi_err(sdxi, "failed to alloc a submission queue (sq)\n"); + goto err_sq_alloc; + } + + return cxt; + +err_sq_alloc: +err_cxt_id: + sdxi_cxt_free(cxt); + + return NULL; +} + +static const char *cxt_sts_state_str(enum cxt_sts_state state) +{ + static const char *const context_states[] =3D { + [CXTV_STOP_SW] =3D "stopped (software)", + [CXTV_RUN] =3D "running", + [CXTV_STOPG_SW] =3D "stopping (software)", + [CXTV_STOP_FN] =3D "stopped (function)", + [CXTV_STOPG_FN] =3D "stopping (function)", + [CXTV_ERR_FN] =3D "error", + }; + const char *str =3D "unknown"; + + switch (state) { + case CXTV_STOP_SW: + case CXTV_RUN: + case CXTV_STOPG_SW: + case CXTV_STOP_FN: + case CXTV_STOPG_FN: + case CXTV_ERR_FN: + str =3D context_states[state]; + } + + return str; +} + +int sdxi_submit_desc(struct sdxi_cxt *cxt, const struct sdxi_desc *desc) +{ + struct sdxi_sq *sq; + __le64 __iomem *db; + __le64 *ring_base; + u64 ring_entries; + __le64 *rd_idx; + __le64 *wr_idx; + + sq =3D cxt->sq; + ring_entries =3D sq->ring_entries; + ring_base =3D sq->desc_ring[0].qw; + rd_idx =3D &sq->cxt_sts->read_index; + wr_idx =3D sq->write_index; + db =3D cxt->db; + + return sdxi_enqueue(desc->qw, 1, ring_base, ring_entries, + rd_idx, wr_idx, db); +} + +static void sdxi_cxt_shutdown(struct sdxi_cxt *target_cxt) +{ + unsigned long deadline =3D jiffies + msecs_to_jiffies(1000); + struct sdxi_cxt *admin_cxt =3D target_cxt->sdxi->admin_cxt; + struct sdxi_dev *sdxi =3D target_cxt->sdxi; + struct sdxi_cxt_sts *sts =3D target_cxt->sq->cxt_sts; + struct sdxi_desc desc; + u16 cxtid =3D target_cxt->id; + struct sdxi_cxt_stop params =3D { + .range =3D sdxi_cxt_range(cxtid), + }; + enum cxt_sts_state state =3D sdxi_cxt_sts_state(sts); + int err; + + sdxi_dbg(sdxi, "%s entry: context state: %s", + __func__, cxt_sts_state_str(state)); + + err =3D sdxi_encode_cxt_stop(&desc, ¶ms); + if (err) + return; + + err =3D sdxi_submit_desc(admin_cxt, &desc); + if (err) + return; + + sdxi_dbg(sdxi, "shutting down context %u\n", cxtid); + + do { + enum cxt_sts_state state =3D sdxi_cxt_sts_state(sts); + + sdxi_dbg(sdxi, "context %u state: %s", cxtid, + cxt_sts_state_str(state)); + + switch (state) { + case CXTV_ERR_FN: + sdxi_err(sdxi, "context %u went into error state while stopping\n", + cxtid); + fallthrough; + case CXTV_STOP_SW: + case CXTV_STOP_FN: + return; + case CXTV_RUN: + case CXTV_STOPG_SW: + case CXTV_STOPG_FN: + /* transitional states */ + fsleep(1000); + break; + default: + sdxi_err(sdxi, "context %u in unknown state %u\n", + cxtid, state); + return; + } + } while (time_before(jiffies, deadline)); + + sdxi_err(sdxi, "stopping context %u timed out (state =3D %u)\n", + cxtid, sdxi_cxt_sts_state(sts)); +} + +void sdxi_working_cxt_exit(struct sdxi_cxt *cxt) +{ + struct sdxi_sq *sq; + + if (!cxt) + return; + + sq =3D cxt->sq; + if (!sq) + return; + + sdxi_cxt_shutdown(cxt); + + sdxi_sq_free(sq); + + sdxi_cxt_free(cxt); +} diff --git a/drivers/dma/sdxi/context.h b/drivers/dma/sdxi/context.h new file mode 100644 index 0000000000000000000000000000000000000000..0c4ab90ff3bd41d585c8b05ac95= d51d7e1c82aa3 --- /dev/null +++ b/drivers/dma/sdxi/context.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Header for sq and descriptor management + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ + +#ifndef __SDXI_SQ_H +#define __SDXI_SQ_H + +struct sdxi_cxt; +struct sdxi_dev; +struct sdxi_desc; + +enum sdxi_cxt_id { + SDXI_ADMIN_CXT_ID =3D 0, + SDXI_DMA_CXT_ID =3D 1, + SDXI_ANY_CXT_ID, +}; + +/* Context Control */ +struct sdxi_cxt *sdxi_working_cxt_init(struct sdxi_dev *sdxi, + enum sdxi_cxt_id); +void sdxi_working_cxt_exit(struct sdxi_cxt *cxt); + +int sdxi_submit_desc(struct sdxi_cxt *cxt, const struct sdxi_desc *desc); + +#endif /* __SDXI_SQ_H */ --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 08000277017; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; cv=none; b=DYzwMmZlrRwznXgAbipTEaldYG18dvaytN275Zg1VPNZpTy8CMNjJ6a+HmktFU9R77ZzWlhTX31jDbiJ66D/M4/T43LGByWusd2oGRriup16+MgvWQjsi/FuXf1wYNXCstughSGbt5qhlJTwSOa5Zf1F+Fsy5Qtusr8W8byUZ88= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; c=relaxed/simple; bh=B9kAQoXWWXJAF0httlFrFKkdVM5OkPjDH2UJkh+cJ8Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FxU/Zhw7O4eSunOM3aHfqLpy0q4gRO3RxJLoPmKoFF7JoCQiwXPBO6PUkZ6yZyr3UGXrXGSuvgdlUxYLaqtu9kX70sC8pDUKNCbbmvufl4+2xHbsK3zrZpv6N6f9PsQGmISoE6Or4MP3auh3WVqR0lcztqF2//v5cVB3BZ6fL/c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EwMF/Dwd; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EwMF/Dwd" Received: by smtp.kernel.org (Postfix) with ESMTPS id D1411C116D0; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098130; bh=B9kAQoXWWXJAF0httlFrFKkdVM5OkPjDH2UJkh+cJ8Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=EwMF/DwdCPbLZgm7Yh9SYMkAQ/nhj+iwfhCUNykgAlXE4c5nhVD84w+sExcHr0kbZ +NUEXsxlGKJC3QB6nlHEZd9orIiDLIQSy5i7h7Z2GYl68LkqoRTwiX6AoaDte6J1Hy k6TNhY5zbH6xGJS87YEM+guF6xvR/x+pDFmE/VsNzRjT4ZrYhkSHwU2MgrdI3G5BlD EbTothHvlg1wzhLRttJSdr1QYEKoD1efvNGxA0jRNk+e3oHFv/nCeKnfBWp4feqIh2 StjHifsbxEPLnI91xnB6tE7sEsYLNSnN5TM+UZ00zuDN3ZNRBOJW1cXoV7ULrQ48mZ Rf58Mwm/XV4FQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CADBECA1017; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:32 -0500 Subject: [PATCH RFC 09/13] dmaengine: sdxi: Add core device management code Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-9-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098128; l=11769; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=9diIsq+I052wh0xw/r7UWxXJ4kXLffKLLVhFVkqEMsg=; b=2Qa7f9ttJwQevg9mRIGXo42mE5vgS17JbEW+6LS8IJKYzBd7Brkd/kuqkEp6mZwX4eWiby4Zc 8HrjMtAGjBNBkZSJbxdh5vujGeIRtD3SEaXjj8XM8EYn4KLpwDdFFn2 X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch Add code that manages device initialization and exit and provides entry points for the PCI driver code to come. Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- drivers/dma/sdxi/device.c | 397 ++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 397 insertions(+) diff --git a/drivers/dma/sdxi/device.c b/drivers/dma/sdxi/device.c new file mode 100644 index 0000000000000000000000000000000000000000..61123bc1d47b6547538b6e783ad= 96a9c2851494e --- /dev/null +++ b/drivers/dma/sdxi/device.c @@ -0,0 +1,397 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * SDXI hardware device driver + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "context.h" +#include "descriptor.h" +#include "hw.h" +#include "error.h" +#include "sdxi.h" + +enum sdxi_fn_gsv { + SDXI_GSV_STOP, + SDXI_GSV_INIT, + SDXI_GSV_ACTIVE, + SDXI_GSV_STOPG_SF, + SDXI_GSV_STOPG_HD, + SDXI_GSV_ERROR, +}; + +static const char *const gsv_strings[] =3D { + [SDXI_GSV_STOP] =3D "stopped", + [SDXI_GSV_INIT] =3D "initializing", + [SDXI_GSV_ACTIVE] =3D "active", + [SDXI_GSV_STOPG_SF] =3D "soft stopping", + [SDXI_GSV_STOPG_HD] =3D "hard stopping", + [SDXI_GSV_ERROR] =3D "error", +}; + +static const char *gsv_str(enum sdxi_fn_gsv gsv) +{ + if ((size_t)gsv < ARRAY_SIZE(gsv_strings)) + return gsv_strings[(size_t)gsv]; + + WARN_ONCE(1, "unexpected gsv %u\n", gsv); + + return "unknown"; +} + +enum sdxi_fn_gsr { + SDXI_GSRV_RESET, + SDXI_GSRV_STOP_SF, + SDXI_GSRV_STOP_HD, + SDXI_GSRV_ACTIVE, +}; + +static enum sdxi_fn_gsv sdxi_dev_gsv(const struct sdxi_dev *sdxi) +{ + return (enum sdxi_fn_gsv)FIELD_GET(SDXI_MMIO_STS0_FN_GSV, + sdxi_read64(sdxi, SDXI_MMIO_STS0)); +} + +static void sdxi_write_fn_gsr(struct sdxi_dev *sdxi, enum sdxi_fn_gsr cmd) +{ + u64 ctl0 =3D sdxi_read64(sdxi, SDXI_MMIO_CTL0); + + FIELD_MODIFY(SDXI_MMIO_CTL0_FN_GSR, &ctl0, cmd); + sdxi_write64(sdxi, SDXI_MMIO_CTL0, ctl0); +} + +static int sdxi_dev_start(struct sdxi_dev *sdxi) +{ + unsigned long deadline; + enum sdxi_fn_gsv status; + + status =3D sdxi_dev_gsv(sdxi); + if (status !=3D SDXI_GSV_STOP) { + sdxi_err(sdxi, + "can't activate busy device (unexpected gsv: %s)\n", + gsv_str(status)); + return -EIO; + } + + sdxi_write_fn_gsr(sdxi, SDXI_GSRV_ACTIVE); + + deadline =3D jiffies + msecs_to_jiffies(1000); + do { + status =3D sdxi_dev_gsv(sdxi); + sdxi_dbg(sdxi, "%s: function state: %s\n", __func__, gsv_str(status)); + + switch (status) { + case SDXI_GSV_ACTIVE: + sdxi_dbg(sdxi, "activated\n"); + return 0; + case SDXI_GSV_ERROR: + sdxi_err(sdxi, "went to error state\n"); + return -EIO; + case SDXI_GSV_INIT: + case SDXI_GSV_STOP: + /* transitional states, wait */ + fsleep(1000); + break; + default: + sdxi_err(sdxi, "unexpected gsv %u, giving up\n", status); + return -EIO; + } + } while (time_before(jiffies, deadline)); + + sdxi_err(sdxi, "activation timed out, current status %u\n", + sdxi_dev_gsv(sdxi)); + return -ETIMEDOUT; + +} + +/* Get the device to the GSV_STOP state. */ +static int sdxi_dev_stop(struct sdxi_dev *sdxi) +{ + unsigned long deadline =3D jiffies + msecs_to_jiffies(1000); + bool reset_issued =3D false; + + do { + enum sdxi_fn_gsv status =3D sdxi_dev_gsv(sdxi); + + sdxi_dbg(sdxi, "%s: function state: %s\n", __func__, gsv_str(status)); + + switch (status) { + case SDXI_GSV_ACTIVE: + sdxi_write_fn_gsr(sdxi, SDXI_GSRV_STOP_SF); + break; + case SDXI_GSV_ERROR: + if (!reset_issued) { + sdxi_info(sdxi, + "function in error state, issuing reset\n"); + sdxi_write_fn_gsr(sdxi, SDXI_GSRV_RESET); + reset_issued =3D true; + } else { + fsleep(1000); + } + break; + case SDXI_GSV_STOP: + return 0; + case SDXI_GSV_INIT: + case SDXI_GSV_STOPG_SF: + case SDXI_GSV_STOPG_HD: + /* transitional states, wait */ + sdxi_dbg(sdxi, "waiting for stop (gsv =3D %u)\n", + status); + fsleep(1000); + break; + default: + sdxi_err(sdxi, "unknown gsv %u, giving up\n", status); + return -EIO; + } + } while (time_before(jiffies, deadline)); + + sdxi_err(sdxi, "stop attempt timed out, current status %u\n", + sdxi_dev_gsv(sdxi)); + return -ETIMEDOUT; +} + +static void sdxi_stop(struct sdxi_dev *sdxi) +{ + sdxi_dev_stop(sdxi); +} + +/* Refer to "Activation of the SDXI Function by Software". */ +static int sdxi_fn_activate(struct sdxi_dev *sdxi) +{ + const struct sdxi_dev_ops *ops =3D sdxi->dev_ops; + u64 cxt_l2; + u64 cap0; + u64 cap1; + u64 ctl2; + int err; + + /* + * Clear any existing configuration from MMIO_CTL0 and ensure + * the function is in GSV_STOP state. + */ + sdxi_write64(sdxi, SDXI_MMIO_CTL0, 0); + err =3D sdxi_dev_stop(sdxi); + if (err) + return err; + + /* + * 1.a. Discover limits and implemented features via MMIO_CAP0 + * and MMIO_CAP1. + */ + cap0 =3D sdxi_read64(sdxi, SDXI_MMIO_CAP0); + sdxi->sfunc =3D FIELD_GET(SDXI_MMIO_CAP0_SFUNC, cap0); + sdxi->max_ring_entries =3D SZ_1K; + sdxi->max_ring_entries *=3D 1U << FIELD_GET(SDXI_MMIO_CAP0_MAX_DS_RING_SZ= , cap0); + sdxi->db_stride =3D SZ_4K; + sdxi->db_stride *=3D 1U << FIELD_GET(SDXI_MMIO_CAP0_DB_STRIDE, cap0); + + cap1 =3D sdxi_read64(sdxi, SDXI_MMIO_CAP1); + sdxi->max_akeys =3D SZ_256; + sdxi->max_akeys *=3D 1U << FIELD_GET(SDXI_MMIO_CAP1_MAX_AKEY_SZ, cap1); + sdxi->max_cxts =3D 1 + FIELD_GET(SDXI_MMIO_CAP1_MAX_CXT, cap1); + sdxi->op_grp_cap =3D FIELD_GET(SDXI_MMIO_CAP1_OPB_000_CAP, cap1); + + /* + * 1.b. Configure SDXI parameters via MMIO_CTL2. We don't have + * any reason to impose more conservative limits than those + * reported in the capability registers, so use those for now. + */ + ctl2 =3D 0; + ctl2 |=3D FIELD_PREP(SDXI_MMIO_CTL2_MAX_BUFFER, + FIELD_GET(SDXI_MMIO_CAP1_MAX_BUFFER, cap1)); + ctl2 |=3D FIELD_PREP(SDXI_MMIO_CTL2_MAX_AKEY_SZ, + FIELD_GET(SDXI_MMIO_CAP1_MAX_AKEY_SZ, cap1)); + ctl2 |=3D FIELD_PREP(SDXI_MMIO_CTL2_MAX_CXT, + FIELD_GET(SDXI_MMIO_CAP1_MAX_CXT, cap1)); + ctl2 |=3D FIELD_PREP(SDXI_MMIO_CTL2_OPB_000_AVL, + FIELD_GET(SDXI_MMIO_CAP1_OPB_000_CAP, cap1)); + sdxi_write64(sdxi, SDXI_MMIO_CTL2, ctl2); + + sdxi_dbg(sdxi, + "sfunc:%#x descmax:%llu dbstride:%#x akeymax:%u cxtmax:%u opgrps:%#x\n", + sdxi->sfunc, sdxi->max_ring_entries, sdxi->db_stride, + sdxi->max_akeys, sdxi->max_cxts, sdxi->op_grp_cap); + + /* 2.a-2.b. Allocate and zero the 4KB Context Level 2 Table */ + sdxi->l2_table =3D dmam_alloc_coherent(sdxi_to_dev(sdxi), L2_TABLE_SIZE, + &sdxi->l2_dma, GFP_KERNEL); + if (!sdxi->l2_table) + return -ENOMEM; + + /* 2.c. Program MMIO_CXT_L2 */ + cxt_l2 =3D FIELD_PREP(SDXI_MMIO_CXT_L2_PTR, sdxi->l2_dma >> ilog2(SZ_4K)); + sdxi_write64(sdxi, SDXI_MMIO_CXT_L2, cxt_l2); + + /* + * 2.c.i. TODO: Program MMIO_CTL0.fn_pasid and + * MMIO_CTL0.fn_pasid if guest virtual addressing required. + */ + + /* + * This covers the following steps: + * + * 3. Context Level 1 Table Setup for contexts 0..127. + * 4.a. Create the administrative context and associated control + * structures. + * 4.b. Set its CXT_STS.state to CXTV_RUN; see 10.b. + * + * The admin context will not consume descriptors until we + * write its doorbell later. + */ + sdxi->admin_cxt =3D sdxi_working_cxt_init(sdxi, SDXI_ADMIN_CXT_ID); + if (!sdxi->admin_cxt) + return -ENOMEM; + /* + * 5. Mailbox: we don't use this facility and we assume the + * reset values are sane. + * + * 6. If restoring saved state, adjust as appropriate. (We're not.) + */ + + /* + * MSI allocation is informed by the function's maximum + * supported contexts, which was discovered in 1.a. Need to do + * this before step 7, which claims an IRQ. + */ + err =3D (ops && ops->irq_init) ? ops->irq_init(sdxi) : 0; + if (err) + goto admin_cxt_exit; + + /* 7. Initialize error log according to "Error Log Initialization". */ + err =3D sdxi_error_init(sdxi); + if (err) + goto irq_exit; + + /* + * 8. "Software may also need to configure and enable + * additional [features]". We've already performed MSI setup, + * nothing else for us to do here for now. + */ + + /* + * 9. Set MMIO_CTL0.fn_gsr to GSRV_ACTIVE and wait for + * MMIO_STS0.fn_gsv to reach GSV_ACTIVE or GSV_ERROR. + */ + err =3D sdxi_dev_start(sdxi); + if (err) + goto error_exit; + + /* + * 10. Jump start the admin context. This step refers to + * "Starting A context and Context Signaling," where method #3 + * recommends writing an "appropriate" value to the doorbell + * register. We haven't queued any descriptors to the admin + * context at this point, so the appropriate value would be 0. + */ + iowrite64(0, sdxi->admin_cxt->db); + + return 0; + +error_exit: + sdxi_error_exit(sdxi); +irq_exit: + if (ops && ops->irq_exit) + ops->irq_exit(sdxi); +admin_cxt_exit: + sdxi_working_cxt_exit(sdxi->admin_cxt); + return err; +} + +int sdxi_device_init(struct sdxi_dev *sdxi, const struct sdxi_dev_ops *ops) +{ + struct sdxi_cxt_start params; + struct sdxi_cxt *admin_cxt; + struct sdxi_desc desc; + struct sdxi_cxt *dma_cxt; + int err; + + sdxi->dev_ops =3D ops; + + sdxi->write_index_pool =3D dmam_pool_create("Write_Index", sdxi_to_dev(sd= xi), + sizeof(__le64), sizeof(__le64), 0); + sdxi->cxt_sts_pool =3D dmam_pool_create("CXT_STS", sdxi_to_dev(sdxi), + sizeof(struct sdxi_cxt_sts), + sizeof(struct sdxi_cxt_sts), 0); + sdxi->cxt_ctl_pool =3D dmam_pool_create("CXT_CTL", sdxi_to_dev(sdxi), + sizeof(struct sdxi_cxt_ctl), + sizeof(struct sdxi_cxt_ctl), 0); + if (!sdxi->write_index_pool || !sdxi->cxt_sts_pool || !sdxi->cxt_ctl_pool) + return -ENOMEM; + + err =3D sdxi_fn_activate(sdxi); + if (err) + return err; + + admin_cxt =3D sdxi->admin_cxt; + + dma_cxt =3D sdxi_working_cxt_init(sdxi, SDXI_DMA_CXT_ID); + if (!dma_cxt) { + err =3D -EINVAL; + goto fn_stop; + } + + sdxi->dma_cxt =3D dma_cxt; + + params =3D (typeof(params)) { + .range =3D sdxi_cxt_range(dma_cxt->id), + }; + err =3D sdxi_encode_cxt_start(&desc, ¶ms); + if (err) + goto fn_stop; + + err =3D sdxi_submit_desc(admin_cxt, &desc); + if (err) + goto fn_stop; + + return 0; +fn_stop: + sdxi_stop(sdxi); + return err; +} + +void sdxi_device_exit(struct sdxi_dev *sdxi) +{ + sdxi_working_cxt_exit(sdxi->dma_cxt); + + /* Walk sdxi->cxt_array freeing any allocated rows. */ + for (size_t i =3D 0; i < L2_TABLE_ENTRIES; ++i) { + if (!sdxi->cxt_array[i]) + continue; + /* When a context is released its entry in the table should be NULL. */ + for (size_t j =3D 0; j < L1_TABLE_ENTRIES; ++j) { + struct sdxi_cxt *cxt =3D sdxi->cxt_array[i][j]; + + if (!cxt) + continue; + if (cxt->id !=3D 0) /* admin context shutdown is last */ + sdxi_working_cxt_exit(cxt); + sdxi->cxt_array[i][j] =3D NULL; + } + if (i !=3D 0) /* another special case for admin cxt */ + kfree(sdxi->cxt_array[i]); + } + + sdxi_working_cxt_exit(sdxi->admin_cxt); + kfree(sdxi->cxt_array[0]); /* ugh */ + + sdxi_stop(sdxi); + sdxi_error_exit(sdxi); + if (sdxi->dev_ops && sdxi->dev_ops->irq_exit) + sdxi->dev_ops->irq_exit(sdxi); +} + +MODULE_DESCRIPTION("SDXI driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Wei Huang"); +MODULE_AUTHOR("Nathan Lynch"); --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49DDE27F182; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; cv=none; b=EAbN62+1L79o858KKlb2Tzbve1P5llzZ6lNPLZIwR9jExddHWmlBIOlmJFKuh538jNmup9GwXsbpz/qEbh9LLmNh5RB1C1jm8nn3Ra15C0CIzYmLV034pxfXG99VpM25kZxMuGXhV91JTMHh7nQPmdik0J8iMFnzDmwOsjwYLws= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; c=relaxed/simple; bh=VuqyHd/j7amx7qZTFAuuOIay+gRe3rBdR2mbbyet7+M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HRIQR9KgTG/DhE4G1zQpdTZVxyCWv59NMhkc04Ti2hwqEDKTJUjMq2YjE7yOPD7AqKajUma4KQMp46AZk8dOZ+sZk+gnKVi9vCc1lTbcUFDq/uVY7XvCAk/xOErFZp0RYUNoQ6nm/E5G3fV575jH+zDxZXo5yMC0c2S9impSZZw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=vQk52Nn0; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="vQk52Nn0" Received: by smtp.kernel.org (Postfix) with ESMTPS id DD72AC4CEFF; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098130; bh=VuqyHd/j7amx7qZTFAuuOIay+gRe3rBdR2mbbyet7+M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=vQk52Nn0DaUm3t4oc5jh0zcN9gJIjgHVkIHx6SqJriA2fVIkD0ClOrj1EP2W25uIB 9bMrMfkVhJTJeriHCkD/ptuYY7WWUhwPcvifwLJVxpe3XYg2qvOxL+e0Ugp7hrRYxN jsyNxnhQg+w3ef91Y5jZDjX4h8YKys70+v5Gktm5m+OxhgsbVfmhz26AH9G+d3wol3 944DfqBdz61DRIRiaYF+XFawBK1Yq11qu3DI3xWEo7aCgarycBB/PbxPcvcHLVjwb+ 9ZxAEoTcQjznO7dsozi6KWppwHvnY3iZ9EZ27I4aMpIUvFC2rSDmjifd2+dm8hJzC5 WbYwpP6wf9zJw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id D6DA9CAC580; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:33 -0500 Subject: [PATCH RFC 10/13] dmaengine: sdxi: Add PCI driver support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-10-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098128; l=5608; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=m3XoOo9ffzkPrZw4+4jLMw0l82s7JUrIjtnNqA36HbE=; b=b+YDt/h2Pw7KLvvDg6sXddSGdT5SqziimKeIAWWCz82Uv+SYamNChMpSav8KAeB4FK8f2DKQK XU+8ajrDePhDt5ubwyQbiOmkDvA6NDKTflP4KbsWHewEgo3gvX2eM5L X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch Add support for binding to PCIe-hosted SDXI devices. SDXI requires MSI(-X) for PCI implementations, so this code will be gated by CONFIG_PCI_MSI in the Makefile. Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- drivers/dma/sdxi/pci.c | 216 +++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 216 insertions(+) diff --git a/drivers/dma/sdxi/pci.c b/drivers/dma/sdxi/pci.c new file mode 100644 index 0000000000000000000000000000000000000000..b7f74555395c605c4affffb198e= e359accac8521 --- /dev/null +++ b/drivers/dma/sdxi/pci.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * SDXI PCI device code + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mmio.h" +#include "sdxi.h" + +/* + * SDXI devices signal message 0 on error conditions, see "Error + * Logging Control and Status Registers". + */ +#define ERROR_IRQ_MSG 0 + +/* MMIO BARs */ +#define MMIO_CTL_REGS_BAR 0x0 +#define MMIO_DOORBELL_BAR 0x2 + +static struct pci_dev *sdxi_to_pci_dev(const struct sdxi_dev *sdxi) +{ + return to_pci_dev(sdxi_to_dev(sdxi)); +} + +static int sdxi_pci_irq_init(struct sdxi_dev *sdxi) +{ + struct pci_dev *pdev =3D sdxi_to_pci_dev(sdxi); + int msi_count; + int ret; + + /* 1st irq for error + 1 for each context */ + msi_count =3D sdxi->max_cxts + 1; + + ret =3D pci_alloc_irq_vectors(pdev, 1, msi_count, + PCI_IRQ_MSI | PCI_IRQ_MSIX); + if (ret < 0) { + sdxi_err(sdxi, "alloc MSI/MSI-X vectors failed\n"); + return ret; + } + + sdxi->error_irq =3D pci_irq_vector(pdev, ERROR_IRQ_MSG); + + sdxi_dbg(sdxi, "allocated %d irq vectors", ret); + + return 0; +} + +static void sdxi_pci_irq_exit(struct sdxi_dev *sdxi) +{ + pci_free_irq_vectors(sdxi_to_pci_dev(sdxi)); +} + +static int sdxi_pci_map(struct sdxi_dev *sdxi) +{ + struct pci_dev *pdev =3D sdxi_to_pci_dev(sdxi); + int bars, ret; + + bars =3D 1 << MMIO_CTL_REGS_BAR | 1 << MMIO_DOORBELL_BAR; + ret =3D pcim_iomap_regions(pdev, bars, SDXI_DRV_NAME); + if (ret) { + sdxi_err(sdxi, "pcim_iomap_regions failed (%d)\n", ret); + return ret; + } + + sdxi->dbs_bar =3D pci_resource_start(pdev, MMIO_DOORBELL_BAR); + + /* FIXME: pcim_iomap_table may return NULL, and it's deprecated. */ + sdxi->ctrl_regs =3D pcim_iomap_table(pdev)[MMIO_CTL_REGS_BAR]; + sdxi->dbs =3D pcim_iomap_table(pdev)[MMIO_DOORBELL_BAR]; + if (!sdxi->ctrl_regs || !sdxi->dbs) { + sdxi_err(sdxi, "pcim_iomap_table failed\n"); + return -EINVAL; + } + + return 0; +} + +static void sdxi_pci_unmap(struct sdxi_dev *sdxi) +{ + struct pci_dev *pdev =3D sdxi_to_pci_dev(sdxi); + + pcim_iounmap(pdev, sdxi->ctrl_regs); + pcim_iounmap(pdev, sdxi->dbs); +} + +static int sdxi_pci_init(struct sdxi_dev *sdxi) +{ + struct pci_dev *pdev =3D sdxi_to_pci_dev(sdxi); + struct device *dev =3D &pdev->dev; + int dma_bits =3D 64; + int ret; + + ret =3D pcim_enable_device(pdev); + if (ret) { + sdxi_err(sdxi, "pcim_enbale_device failed\n"); + return ret; + } + + pci_set_master(pdev); + ret =3D dma_set_mask_and_coherent(dev, DMA_BIT_MASK(dma_bits)); + if (ret) { + sdxi_err(sdxi, "failed to set DMA mask & coherent bits\n"); + return ret; + } + + ret =3D sdxi_pci_map(sdxi); + if (ret) { + sdxi_err(sdxi, "failed to map device IO resources\n"); + return ret; + } + + return 0; +} + +static void sdxi_pci_exit(struct sdxi_dev *sdxi) +{ + sdxi_pci_unmap(sdxi); +} + +static struct sdxi_dev *sdxi_device_alloc(struct device *dev) +{ + struct sdxi_dev *sdxi; + + sdxi =3D kzalloc(sizeof(*sdxi), GFP_KERNEL); + if (!sdxi) + return NULL; + + sdxi->dev =3D dev; + + mutex_init(&sdxi->cxt_lock); + + return sdxi; +} + +static void sdxi_device_free(struct sdxi_dev *sdxi) +{ + kfree(sdxi); +} + +static const struct sdxi_dev_ops sdxi_pci_dev_ops =3D { + .irq_init =3D sdxi_pci_irq_init, + .irq_exit =3D sdxi_pci_irq_exit, +}; + +static int sdxi_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct device *dev =3D &pdev->dev; + struct sdxi_dev *sdxi; + int err; + + sdxi =3D sdxi_device_alloc(dev); + if (!sdxi) + return -ENOMEM; + + pci_set_drvdata(pdev, sdxi); + + err =3D sdxi_pci_init(sdxi); + if (err) + goto free_sdxi; + + err =3D sdxi_device_init(sdxi, &sdxi_pci_dev_ops); + if (err) + goto pci_exit; + + return 0; + +pci_exit: + sdxi_pci_exit(sdxi); +free_sdxi: + sdxi_device_free(sdxi); + + return err; +} + +static void sdxi_pci_remove(struct pci_dev *pdev) +{ + struct sdxi_dev *sdxi =3D pci_get_drvdata(pdev); + + sdxi_device_exit(sdxi); + sdxi_pci_exit(sdxi); + sdxi_device_free(sdxi); +} + +static const struct pci_device_id sdxi_id_table[] =3D { + { PCI_DEVICE_CLASS(PCI_CLASS_ACCELERATOR_SDXI, 0xffffff) }, + {0, } +}; +MODULE_DEVICE_TABLE(pci, sdxi_id_table); + +static struct pci_driver sdxi_driver =3D { + .name =3D "sdxi", + .id_table =3D sdxi_id_table, + .probe =3D sdxi_pci_probe, + .remove =3D sdxi_pci_remove, + .sriov_configure =3D pci_sriov_configure_simple, +}; + +module_pci_driver(sdxi_driver); --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 52EA727FD59; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; cv=none; b=eDnbLwNYq2SQ84Vg6VFokSH/P9MFoAiWYNJe9ZhmnJj/Ww+urRp5Oecd3GTfVlc+vxkTlLvXz/iRN/C9rLsu1AWAzx/8tUQrAsiChlTeimtf/mp4gLI3bS/MY0//vbNrnkcDtM2qpSmLdtaGj76xA8Ud9FTyfQ8HvQ6BTcNaOaY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; c=relaxed/simple; bh=lxQ0PBEDBMqbgoT/wr1UNF+vxzeTB+WN2igvu5+vg6g=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XzcFcJQPqbWVgX68bRAuhnviRHgmGUT2R71LT4nK2QsXxdnArg+ZfroraBUxo1W8xJK6n9XSRNOTVue7T8ytCiO8pyXmr88sNO1FjhB8y5XcwGMmT3Oli3hwl6M+YOgdGBvnUELpo0Q5ANgM0R14ufCTlK6YmqlmNVjCfyO6TFo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hE1WC3xm; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="hE1WC3xm" Received: by smtp.kernel.org (Postfix) with ESMTPS id EBC21C116C6; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098131; bh=lxQ0PBEDBMqbgoT/wr1UNF+vxzeTB+WN2igvu5+vg6g=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=hE1WC3xmZOriWPx1nFi9okT2uGF1/1Q+RqVPaui5po+4SGVDcHAEwZAqStQ9GwVdq /pxGhj4812kVjnoZA6v2COMq5EDi1AcoxuN03j+etgEo8DA32i0c35o9u2drz3IOLX luK3nR23OcraTEWwZRCJcNy8hyx3TmbXm+wfh4Y9RTf6ZoljYiPt3NGxjpB+QsZQg8 bQ2gsPa2Cq3EEGcSMf8n3px5q8bFSg2OVLxYx6DQWLBIctOuW5QsolmSDBPM1z3250 iELolA5fIqtCs2Hp1g7KyLBuIAZj8ATAv/KouLP1QjCoSW4H3oLw6BKiLywRfksnDe PFch8us+j/WNw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E5A72CA101F; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:34 -0500 Subject: [PATCH RFC 11/13] dmaengine: sdxi: Add DMA engine provider Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-11-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098129; l=12485; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=oicl0mAaS0xJnaRPITeh2PX2Yd+o4ZUX9+VqlDQ+2I4=; b=f4JgqMzOx0UfzHT/2tsJX1m9aMQnsbM3C/SEsrWL3bisPI70rFtEUkflIwWzjP81qRMg3/eng c3EzrtwAx24A2JEqJZ9kUp98FqdzqzzDg3ssgmcxTEy18QSEczJgu7x X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch Add support for memcpy and interrupt capabilities. Register one channel per SDXI function discovered for now. Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- drivers/dma/sdxi/device.c | 4 + drivers/dma/sdxi/dma.c | 409 ++++++++++++++++++++++++++++++++++++++++++= ++++ drivers/dma/sdxi/dma.h | 12 ++ 3 files changed, 425 insertions(+) diff --git a/drivers/dma/sdxi/device.c b/drivers/dma/sdxi/device.c index 61123bc1d47b6547538b6e783ad96a9c2851494e..e5e1593189993717cae31190688= 5ae268385b28d 100644 --- a/drivers/dma/sdxi/device.c +++ b/drivers/dma/sdxi/device.c @@ -18,6 +18,7 @@ =20 #include "context.h" #include "descriptor.h" +#include "dma.h" #include "hw.h" #include "error.h" #include "sdxi.h" @@ -354,6 +355,8 @@ int sdxi_device_init(struct sdxi_dev *sdxi, const struc= t sdxi_dev_ops *ops) if (err) goto fn_stop; =20 + sdxi_dma_register(sdxi->dma_cxt); + return 0; fn_stop: sdxi_stop(sdxi); @@ -362,6 +365,7 @@ int sdxi_device_init(struct sdxi_dev *sdxi, const struc= t sdxi_dev_ops *ops) =20 void sdxi_device_exit(struct sdxi_dev *sdxi) { + sdxi_dma_unregister(sdxi->dma_cxt); sdxi_working_cxt_exit(sdxi->dma_cxt); =20 /* Walk sdxi->cxt_array freeing any allocated rows. */ diff --git a/drivers/dma/sdxi/dma.c b/drivers/dma/sdxi/dma.c new file mode 100644 index 0000000000000000000000000000000000000000..ad8515deba53898b2b4ea0d38c4= 0042b566abe1f --- /dev/null +++ b/drivers/dma/sdxi/dma.c @@ -0,0 +1,409 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * SDXI DMA engine implementation + * Derived from ptdma code + * + * Copyright (C) 2025 Advanced Micro Devices, Inc. + */ + +#include +#include + +#include "../dmaengine.h" +#include "context.h" +#include "descriptor.h" +#include "dma.h" +#include "sdxi.h" + +struct sdxi_dma_desc { + struct virt_dma_desc vd; + struct sdxi_cxt *cxt; + enum dma_status status; + bool issued_to_hw; + struct sdxi_cmd sdxi_cmd; +}; + +static inline struct sdxi_dma_chan *to_sdxi_dma_chan(struct dma_chan *dma_= chan) +{ + return container_of(dma_chan, struct sdxi_dma_chan, vc.chan); +} + +static inline struct sdxi_dma_desc *to_sdxi_dma_desc(struct virt_dma_desc = *vd) +{ + return container_of(vd, struct sdxi_dma_desc, vd); +} + +static void sdxi_dma_free_chan_resources(struct dma_chan *dma_chan) +{ + struct sdxi_dma_chan *chan =3D to_sdxi_dma_chan(dma_chan); + + vchan_free_chan_resources(&chan->vc); + /* NB: more configure with sdxi_cxt? */ +} + +static void sdxi_dma_synchronize(struct dma_chan *c) +{ + struct sdxi_dma_chan *chan =3D to_sdxi_dma_chan(c); + + vchan_synchronize(&chan->vc); +} + +static void sdxi_do_cleanup(struct virt_dma_desc *vd) +{ + struct sdxi_dma_desc *dma_desc =3D to_sdxi_dma_desc(vd); + struct sdxi_cmd *cmd =3D &dma_desc->sdxi_cmd; + struct device *dev =3D sdxi_to_dev(dma_desc->cxt->sdxi); + + dma_free_coherent(dev, sizeof(*cmd->cst_blk), + cmd->cst_blk, cmd->cst_blk_dma); + kfree(dma_desc); +} + +static int sdxi_dma_start_desc(struct sdxi_dma_desc *dma_desc) +{ + struct sdxi_dev *sdxi; + struct sdxi_cmd *sdxi_cmd; + struct sdxi_cxt *cxt; + struct sdxi_desc desc; + struct sdxi_copy copy; + struct sdxi_cst_blk *cst_blk; + dma_addr_t cst_blk_dma; + int err; + + sdxi_cmd =3D &dma_desc->sdxi_cmd; + sdxi =3D sdxi_cmd->cxt->sdxi; + + cxt =3D dma_desc->cxt; + + if (sdxi_cmd->len > MAX_DMA_COPY_BYTES) + return -EINVAL; + + copy =3D (typeof(copy)) { + .src =3D sdxi_cmd->src_addr, + .dst =3D sdxi_cmd->dst_addr, + .src_akey =3D 0, + .dst_akey =3D 0, + .len =3D sdxi_cmd->len, + }; + + err =3D sdxi_encode_copy(&desc, ©); + if (err) + return err; + + err =3D sdxi_encode_copy(&desc, ©); + if (err) + return err; + + /* FIXME convert to pool */ + cst_blk =3D dma_alloc_coherent(sdxi_to_dev(sdxi), sizeof(*cst_blk), + &cst_blk_dma, GFP_NOWAIT); + if (!cst_blk) + return -ENOMEM; + + cst_blk->signal =3D cpu_to_le64(0xff); + + sdxi_cmd->cst_blk =3D cst_blk; + sdxi_cmd->cst_blk_dma =3D cst_blk_dma; + sdxi_cmd->ret =3D 0; /* TODO: get desc submit status & update ret value */ + + sdxi_desc_set_csb(&desc, cst_blk_dma); + err =3D sdxi_submit_desc(cxt, &desc); + if (err) + goto free_cst_blk; + + sdxi->tdata.cmd =3D sdxi_cmd; /* FIXME: this is not compatible w/multiple= clients */ + dma_desc->issued_to_hw =3D 1; + return 0; +free_cst_blk: + dma_free_coherent(sdxi_to_dev(sdxi), sizeof(*cst_blk), + cst_blk, cst_blk_dma); + return err; +} + +static struct sdxi_dma_desc *sdxi_next_dma_desc(struct sdxi_dma_chan *chan) +{ + /* Get the next DMA descriptor on the active list */ + struct virt_dma_desc *vd =3D vchan_next_desc(&chan->vc); + + return vd ? to_sdxi_dma_desc(vd) : NULL; +} + +static struct sdxi_dma_desc *sdxi_handle_active_desc(struct sdxi_dma_chan = *chan, + struct sdxi_dma_desc *desc) +{ + struct dma_async_tx_descriptor *tx_desc; + struct virt_dma_desc *vd; + unsigned long flags; + + /* Loop over descriptors until one is found with commands */ + do { + if (desc) { + if (!desc->issued_to_hw) { + /* No errors, keep going */ + if (desc->status !=3D DMA_ERROR) + return desc; + } + + tx_desc =3D &desc->vd.tx; + vd =3D &desc->vd; + } else { + tx_desc =3D NULL; + } + + spin_lock_irqsave(&chan->vc.lock, flags); + + if (desc) { + + if (desc->status !=3D DMA_COMPLETE) { + if (desc->status !=3D DMA_ERROR) + desc->status =3D DMA_COMPLETE; + + dma_cookie_complete(tx_desc); + dma_descriptor_unmap(tx_desc); + list_del(&desc->vd.node); + } else { + /* Don't handle it twice */ + tx_desc =3D NULL; + } + } + + desc =3D sdxi_next_dma_desc(chan); + + spin_unlock_irqrestore(&chan->vc.lock, flags); + + if (tx_desc) { + dmaengine_desc_get_callback_invoke(tx_desc, NULL); + dma_run_dependencies(tx_desc); + vchan_vdesc_fini(vd); + } + } while (desc); + + return NULL; +} + +static void sdxi_cmd_callback(void *data, int err) +{ + struct sdxi_dma_desc *desc =3D data; + struct dma_chan *dma_chan; + struct sdxi_dma_chan *chan; + int ret; + + if (err =3D=3D -EINPROGRESS) + return; + + dma_chan =3D desc->vd.tx.chan; + chan =3D to_sdxi_dma_chan(dma_chan); + + if (err) + desc->status =3D DMA_ERROR; + + while (true) { + /* Check for DMA descriptor completion */ + desc =3D sdxi_handle_active_desc(chan, desc); + + /* Don't submit cmd if no descriptor or DMA is paused */ + if (!desc) + break; + + ret =3D sdxi_dma_start_desc(desc); + if (!ret) + break; + + desc->status =3D DMA_ERROR; + } +} + +static struct sdxi_dma_desc *sdxi_dma_alloc_dma_desc(struct sdxi_dma_chan = *chan, + unsigned long flags) +{ + struct sdxi_dma_desc *desc; + + desc =3D kzalloc(sizeof(*desc), GFP_NOWAIT); + if (!desc) + return NULL; + + desc->cxt =3D chan->cxt; + + vchan_tx_prep(&chan->vc, &desc->vd, flags); + + desc->cxt->sdxi =3D chan->cxt->sdxi; + desc->issued_to_hw =3D 0; + desc->status =3D DMA_IN_PROGRESS; + + return desc; +} + +static struct sdxi_dma_desc *sdxi_dma_create_desc(struct dma_chan *dma_cha= n, + dma_addr_t dst, + dma_addr_t src, + unsigned int len, + unsigned long flags) +{ + struct sdxi_dma_chan *chan =3D to_sdxi_dma_chan(dma_chan); + struct sdxi_dma_desc *desc; + struct sdxi_cmd *sdxi_cmd; + + desc =3D sdxi_dma_alloc_dma_desc(chan, flags); + if (!desc) + return NULL; + + sdxi_cmd =3D &desc->sdxi_cmd; + sdxi_cmd->cxt =3D chan->cxt; + sdxi_cmd->cxt->sdxi =3D chan->cxt->sdxi; + sdxi_cmd->src_addr =3D src; + sdxi_cmd->dst_addr =3D dst; + sdxi_cmd->len =3D len; + sdxi_cmd->sdxi_cmd_callback =3D sdxi_cmd_callback; + sdxi_cmd->data =3D desc; + + return desc; +} + +static struct dma_async_tx_descriptor * +sdxi_dma_prep_memcpy(struct dma_chan *dma_chan, dma_addr_t dst, + dma_addr_t src, size_t len, unsigned long flags) +{ + struct sdxi_dma_desc *desc; + + desc =3D sdxi_dma_create_desc(dma_chan, dst, src, len, flags); + if (!desc) + return NULL; + + return &desc->vd.tx; +} + +static struct dma_async_tx_descriptor * +sdxi_prep_dma_interrupt(struct dma_chan *dma_chan, unsigned long flags) +{ + struct sdxi_dma_chan *chan =3D to_sdxi_dma_chan(dma_chan); + struct sdxi_dma_desc *desc; + + desc =3D sdxi_dma_alloc_dma_desc(chan, flags); + if (!desc) + return NULL; + + return &desc->vd.tx; +} + +static void sdxi_dma_issue_pending(struct dma_chan *dma_chan) +{ + struct sdxi_dma_chan *chan =3D to_sdxi_dma_chan(dma_chan); + struct sdxi_dma_desc *desc; + unsigned long flags; + bool engine_is_idle =3D true; + + spin_lock_irqsave(&chan->vc.lock, flags); + + desc =3D sdxi_next_dma_desc(chan); + if (desc) + engine_is_idle =3D false; + + vchan_issue_pending(&chan->vc); + + desc =3D sdxi_next_dma_desc(chan); + + spin_unlock_irqrestore(&chan->vc.lock, flags); + + /* If there was nothing active, start processing */ + if (engine_is_idle) + sdxi_cmd_callback(desc, 0); +} + +static void sdxi_check_trans_status(struct sdxi_dma_chan *chan) +{ + struct sdxi_cxt *cxt =3D chan->cxt; + struct sdxi_cmd *cmd; + + if (!cxt) + return; + + cmd =3D cxt->sdxi->tdata.cmd; + + if (le64_to_cpu(cmd->cst_blk->signal) =3D=3D 0xfe) + sdxi_cmd_callback(cmd->data, cmd->ret); +} + +static enum dma_status sdxi_tx_status(struct dma_chan *dma_chan, dma_cooki= e_t cookie, + struct dma_tx_state *tx_state) +{ + struct sdxi_dma_chan *chan =3D to_sdxi_dma_chan(dma_chan); + + sdxi_check_trans_status(chan); + + return dma_cookie_status(dma_chan, cookie, tx_state); +} + +static int sdxi_dma_terminate_all(struct dma_chan *dma_chan) +{ + struct sdxi_dma_chan *chan =3D to_sdxi_dma_chan(dma_chan); + unsigned long flags; + LIST_HEAD(head); + + spin_lock_irqsave(&chan->vc.lock, flags); + vchan_get_all_descriptors(&chan->vc, &head); + spin_unlock_irqrestore(&chan->vc.lock, flags); + + vchan_dma_desc_free_list(&chan->vc, &head); + vchan_free_chan_resources(&chan->vc); + + return 0; +} + +int sdxi_dma_register(struct sdxi_cxt *dma_cxt) +{ + struct sdxi_dma_chan *chan; + struct sdxi_dev *sdxi =3D dma_cxt->sdxi; + struct device *dev =3D sdxi_to_dev(sdxi); + struct dma_device *dma_dev =3D &sdxi->dma_dev; + int ret =3D 0; + + sdxi->sdxi_dma_chan =3D devm_kzalloc(dev, sizeof(*sdxi->sdxi_dma_chan), + GFP_KERNEL); + if (!sdxi->sdxi_dma_chan) + return -ENOMEM; + + sdxi->sdxi_dma_chan->cxt =3D dma_cxt; + + dma_dev->dev =3D dev; + dma_dev->src_addr_widths =3D DMA_SLAVE_BUSWIDTH_64_BYTES; + dma_dev->dst_addr_widths =3D DMA_SLAVE_BUSWIDTH_64_BYTES; + dma_dev->directions =3D BIT(DMA_MEM_TO_MEM); + dma_dev->residue_granularity =3D DMA_RESIDUE_GRANULARITY_DESCRIPTOR; + dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask); + dma_cap_set(DMA_INTERRUPT, dma_dev->cap_mask); + + dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask); + + INIT_LIST_HEAD(&dma_dev->channels); + + chan =3D sdxi->sdxi_dma_chan; + chan->cxt->sdxi =3D sdxi; + + /* Set base and prep routines */ + dma_dev->device_free_chan_resources =3D sdxi_dma_free_chan_resources; + dma_dev->device_prep_dma_memcpy =3D sdxi_dma_prep_memcpy; + dma_dev->device_prep_dma_interrupt =3D sdxi_prep_dma_interrupt; + dma_dev->device_issue_pending =3D sdxi_dma_issue_pending; + dma_dev->device_tx_status =3D sdxi_tx_status; + dma_dev->device_terminate_all =3D sdxi_dma_terminate_all; + dma_dev->device_synchronize =3D sdxi_dma_synchronize; + + chan->vc.desc_free =3D sdxi_do_cleanup; + vchan_init(&chan->vc, dma_dev); + + dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + + ret =3D dma_async_device_register(dma_dev); + if (ret) + goto err_reg; + + return 0; + +err_reg: + return ret; +} + +void sdxi_dma_unregister(struct sdxi_cxt *dma_cxt) +{ + dma_async_device_unregister(&dma_cxt->sdxi->dma_dev); +} diff --git a/drivers/dma/sdxi/dma.h b/drivers/dma/sdxi/dma.h new file mode 100644 index 0000000000000000000000000000000000000000..cdea77cd274043a76b658fa9371= 6f6cea2867216 --- /dev/null +++ b/drivers/dma/sdxi/dma.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (C) 2025 Advanced Micro Devices, Inc. */ + +#ifndef DMA_SDXI_DMA_H +#define DMA_SDXI_DMA_H + +struct sdxi_cxt; + +int sdxi_dma_register(struct sdxi_cxt *dma_cxt); +void sdxi_dma_unregister(struct sdxi_cxt *dma_cxt); + +#endif /* DMA_SDXI_DMA_H */ --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 53582280017; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; cv=none; b=f4k/Mb32+r+vqcMOE+ZA6AEw/UEH2HL5LujXkruaty9R//erFd7ADLKtXqTHQKzsj6AGWK7jJi4Fe2cHP5RTzNX50/lIVINqmcvoOgu7TQTT5mORM2sgRfZha+ZTUtOhrpLqHnlpx2r1jpNav2FK8Qi2blQl3uiTY/h8XN4qyJk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; c=relaxed/simple; bh=q/cnJYwiQrYCXLKiAQYrAuGmRzLn79YGRxuj3an5Vmw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WDZmSFw7zqZTvIbPP75X38znvDQbtGQO0b0/dn++AAojzqqx0uad6ZsR7XStS5N/qxaNkGKBXmZ7ya3T8ZVtZZqraQhEXv+iI42XPq//HBz2PYQSjerqLEknY/AvTFjEK4J2G3wRVahSMWte7kSAN0a7LG9lvEeMnBTNHrS6dw0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uns1K3EQ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uns1K3EQ" Received: by smtp.kernel.org (Postfix) with ESMTPS id 06067C4CEFB; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098131; bh=q/cnJYwiQrYCXLKiAQYrAuGmRzLn79YGRxuj3an5Vmw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=uns1K3EQQuQU1283oQwUuOGEFpHFwTkZFZ5mLzp2+VjFCNEATIeenO8yLWbXi5DH/ 0CdDQaxHILYc9D+J/cIAzjflTnkSI8z0aMhVar4o1Qr+hLC4OqnbWHqufXn4rOe8+a XSeOFk6E+9pL0CsZr4BQruljJ2UomxoV7yh8xutR8nNZKJ440Bqw3h+M9Vf4D6vi2u IbGm1HeHh33Tak8oOoRU+oxAWwZSDJWp5sm7Rm+UaF2L52pkkEbQL0eO9pZQn6Pxti kohaeYpJCy4dqW9P3J7VngFoM9+4RpkgXddqY/9EQvibEkzSF97zv1NANLnswAoy8c FC0kxNdr5BgoA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id F33BCCA1017; Fri, 5 Sep 2025 18:48:50 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:35 -0500 Subject: [PATCH RFC 12/13] dmaengine: sdxi: Add Kconfig and Makefile Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-12-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098129; l=3113; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=ouNlAF3ey9kkPHIHkTAL8nkSqeI8aY290db9HnPAHSw=; b=9QEgbeZtoY02av3vXIAReneK8LIym6iDIavrtDdkJoaGAe+hK8loAznGg4DdNdfkul4tka+N0 gEXJrStJhE2APqhhM6Crk3tgkYiLF4lmaIzYy1L6gpxa4Mx6/56hMGo X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch Add SDXI Kconfig that includes debug and unit test options in addition to the usual tristate. SDXI_DEBUG seems necessary because DMADEVICES_DEBUG makes dmatest too verbose. One goal is to keep the bus-agnostic portions of the driver buildable without PCI(_MSI), in case non-PCI SDXI implementations come along later. Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- drivers/dma/Kconfig | 2 ++ drivers/dma/Makefile | 1 + drivers/dma/sdxi/Kconfig | 23 +++++++++++++++++++++++ drivers/dma/sdxi/Makefile | 17 +++++++++++++++++ 4 files changed, 43 insertions(+) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 05c7c7d9e5a4e52a8ad7ada8c8b9b1a6f9d875f6..cccf00b73e025944681b03cffe4= 41c372526d3f3 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -774,6 +774,8 @@ source "drivers/dma/fsl-dpaa2-qdma/Kconfig" =20 source "drivers/dma/lgm/Kconfig" =20 +source "drivers/dma/sdxi/Kconfig" + source "drivers/dma/stm32/Kconfig" =20 # clients diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index a54d7688392b1a0e956fa5d23633507f52f017d9..ae4154595e1a6250b441a90078e= 9df3607d3d1dd 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -85,6 +85,7 @@ obj-$(CONFIG_XGENE_DMA) +=3D xgene-dma.o obj-$(CONFIG_ST_FDMA) +=3D st_fdma.o obj-$(CONFIG_FSL_DPAA2_QDMA) +=3D fsl-dpaa2-qdma/ obj-$(CONFIG_INTEL_LDMA) +=3D lgm/ +obj-$(CONFIG_SDXI) +=3D sdxi/ =20 obj-y +=3D amd/ obj-y +=3D mediatek/ diff --git a/drivers/dma/sdxi/Kconfig b/drivers/dma/sdxi/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..c9757cffb5f64fbc175ded8d0c9= d751f0a22b6df --- /dev/null +++ b/drivers/dma/sdxi/Kconfig @@ -0,0 +1,23 @@ +config SDXI + tristate "SDXI support" + select DMA_ENGINE + select DMA_VIRTUAL_CHANNELS + select PACKING + help + Enable support for Smart Data Accelerator Interface (SDXI) + Platform Data Mover devices. SDXI is a vendor-neutral + standard for a memory-to-memory data mover and acceleration + interface. + +config SDXI_DEBUG + bool "SDXI driver debug" + default DMADEVICES_DEBUG + depends on SDXI !=3D n + help + Enable debug output from the SDXI driver. This is an option + for use by developers and most users should say N here. + +config SDXI_KUNIT_TEST + tristate "SDXI unit tests" if !KUNIT_ALL_TESTS + depends on SDXI && KUNIT + default KUNIT_ALL_TESTS diff --git a/drivers/dma/sdxi/Makefile b/drivers/dma/sdxi/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c67e475689b45d6260fe970fb4a= fcc25f8f9ebc1 --- /dev/null +++ b/drivers/dma/sdxi/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 + +ccflags-$(CONFIG_SDXI_DEBUG) +=3D -DDEBUG + +obj-$(CONFIG_SDXI) +=3D sdxi.o + +sdxi-objs +=3D \ + context.o \ + descriptor.o \ + device.o \ + dma.o \ + enqueue.o \ + error.o + +sdxi-$(CONFIG_PCI_MSI) +=3D pci.o + +obj-$(CONFIG_SDXI_KUNIT_TEST) +=3D descriptor_kunit.o --=20 2.39.5 From nobody Wed Sep 10 05:43:46 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 52E0727FD52; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; cv=none; b=Dm+lvrHI/wCsGhO+87xpRKkVlSyFpigWQuw4ryJY4Y808INlOKqFPhr3bQ0w99pO7CPolsx0e8uNcFjdahP8zklYlfr3CXosMcnMQhWEuQznWOJ4nihYAMPNzAqJZW/oXBcLJRy7CmJIeKjm+aeDn8ksnu1oCQZCOyKBEllSn78= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757098131; c=relaxed/simple; bh=tqV2mVMBTfLNMFvpkSBPSeNnVNAfe/oi/nk13MKepyo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rreRbCP5FtPZUYQ7j8GgeLrLWoXO5AJ9ZOLsLOgSAfC9zhyZTMrJ2FMt6zVYtRahmHUdS7jbTtHJs6QfwARtnig72EmeKWlQIUD2sJM35iCHGXscx0PXcSaW2VwdHdamp3pz6dCuHSpgaJf6ESk4dJziZzinv8hSGmiJ77QZUS4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=d8OBGPdV; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="d8OBGPdV" Received: by smtp.kernel.org (Postfix) with ESMTPS id 145C7C4CEF7; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1757098131; bh=tqV2mVMBTfLNMFvpkSBPSeNnVNAfe/oi/nk13MKepyo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=d8OBGPdVAiAG+m0Sxb0rkR8Yl/L4Xn7TaLOS5Ke/pUdxOfHTV2O57JSthSDxFkoi8 C0Uc421bf68efQXuhiTTv3qZr3T3VF0oORVszt+Lm/6Zo+SEHVHDWNos14Xb5mqDR9 n7uexv0i3Aikzllqg767vCfMVHyJOZLOD/P9hy0Fsw/YjaPI/8Ppup7VqAEsUaQ8Kt H/FYrXIdNmqtH+LVIUTYv0dleMJgcC6sojErdKz4v2HaS8tUEfxpXCRt1UhT+9ehyM yCEFRDf74IYAN0bo7x4NvCNZko6CPGAqXTebthH38cO7NqJvkTEBE3E6KTRaWwtKxE 7ZG32K9cist+w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0D0A9CA0FED; Fri, 5 Sep 2025 18:48:51 +0000 (UTC) From: Nathan Lynch via B4 Relay Date: Fri, 05 Sep 2025 13:48:36 -0500 Subject: [PATCH RFC 13/13] MAINTAINERS: Add entry for SDXI driver Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20250905-sdxi-base-v1-13-d0341a1292ba@amd.com> References: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> In-Reply-To: <20250905-sdxi-base-v1-0-d0341a1292ba@amd.com> To: Vinod Koul Cc: Wei Huang , Mario Limonciello , Bjorn Helgaas , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1757098129; l=1013; i=nathan.lynch@amd.com; s=20241010; h=from:subject:message-id; bh=diiwvZ2HCcciUzDvmvbMM69P2dAF5ySeGY7sk+v6Rfw=; b=g9pjE89RBK+G+94dsfImJO3xLonKWVpKq/ow7JavJ4WfGw+Z+81XFuOanuP8PQeYHoz+RzLuN PDECOO8Y88YDR2o8fDQjDpiQ/OQtnuSyg/MUMU4+QC+s9ppZpxdUGoU X-Developer-Key: i=nathan.lynch@amd.com; a=ed25519; pk=ZR637UTGg5YLDj56cxFeHdYoUjPMMFbcijfOkAmAnbc= X-Endpoint-Received: by B4 Relay for nathan.lynch@amd.com/20241010 with auth_id=241 X-Original-From: Nathan Lynch Reply-To: nathan.lynch@amd.com From: Nathan Lynch Add an entry for the SDXI driver to MAINTAINERS. Wei and I will maintain the driver. The SDXI specification and other materials may be found at: https://www.snia.org/sdxi Co-developed-by: Wei Huang Signed-off-by: Wei Huang Signed-off-by: Nathan Lynch --- MAINTAINERS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index daf520a13bdf6a991c0160a96620f40308c29ee0..eb636ed1aa77aff30a871057efe= f81de8ff56cd7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22676,6 +22676,13 @@ L: sdricohcs-devel@lists.sourceforge.net (subscrib= ers-only) S: Maintained F: drivers/mmc/host/sdricoh_cs.c =20 +SDXI (Smart Data Accelerator Interface) DRIVER +M: Nathan Lynch +M: Wei Huang +L: dmaengine@vger.kernel.org +S: Supported +F: drivers/dma/sdxi/ + SECO BOARDS CEC DRIVER M: Ettore Chimenti S: Maintained --=20 2.39.5