From nobody Sat Feb 7 08:13:38 2026 Received: from CH5PR02CU005.outbound.protection.outlook.com (mail-northcentralusazon11012034.outbound.protection.outlook.com [40.107.200.34]) (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 A56A72848BB for ; Mon, 26 Jan 2026 19:28:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.200.34 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769455691; cv=fail; b=Wj9k2TXuUFGQrau0p8vgGdrjZRMPNTkAb0W2v+2GXREH60LCx7uOwvLK/FgtXj8/3WW4+No8O6PEyXlQiL7WJ9FXjQJO6H01g28NQezPK3qq51anVgMliJlN1Sq6YB+3gJ9GoIxiIUFrNruXgsKP0tj5CxZU3navVWGYhYgGNHs= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769455691; c=relaxed/simple; bh=tz4NmCoDhum61ajSHGw1IZe50A+HOmpSbfKxuE58RDc=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=g4xBr4EOnwdpNZdZJxS3m2dm/0nMMbMiHhhUGad+HA6O5s4u4aGgugQ3QoxdXi2QbGBO+xWHM/P+Tn0BE/W8mis8a6WJ7t3L7X3Bq2RxcZXGOH9rWAXApzpxY7/bIMN0TVLkpeLqKZD0OmA1BOn8h5OOXT4e4sfB5/N/GgPoORQ= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=sNTt0mSt; arc=fail smtp.client-ip=40.107.200.34 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="sNTt0mSt" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Lh9uUMXaOV5bjNjlcL3/iOWxa2snLwkYPWZE3PBROekKB8q+Yi4wc5RTn0mgjz9G18MDfCdez003DQDcAIb7AAKSRdkSNJAECP//Gx2dM4lBtXz13s886JY16G6Rtb8pLyu1PnA5VH0vLQ8URnfGGSsCF52YlMeQ16LDsn37wItCpRXtdo+w9t3y5RG+f39W0FxB7RRgHChTi/U0aQ6DktFJmWKDpsmw8JQ2ZR/rp1lPWMeQTDCIze4CflgsLemESrdCZSMSIqAVIsW7IgwF5qUf0b8rrdT/NSx1xAHCPMGciHziYOl9RyFxZPhJJP600cRyGDNtPIhx+AIKA9PX8w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=UOdbvLQbAiqRqFGMqm7pr+Z38uLzt1pKc5PPb8cs294=; b=Y+RdZqdNjI6ovV7M8aVyPJgOxJJcYyd7ACoU4upLsxEe/mB8D8fOGQXjQ8zcDG1kQm5fGqRLVCAgEsDbvG7yfM00i0Aj5U19TiluldutBLWKIJhQaKZjwB+icl0RKLs1gj/TcnYYBOjsZWpbMBLzSGe3JUrTaBhbHJYFNb17kDlZ1aG5UNZ6+aH/d0xXbvW3B0PWwfdcEuz4xYp9UBat2r3QbzUv5+SCY4orUXLibsgENmKJyHdrKhPRzVEnDNuCnuu/2k0zFJgoNshWrMKsSVJJv7v4BftLbzM9sWGEMPZOAy8cSRx/rkjZxVJ9FSfH/KBdoY+NpHNFgjx7DhM8Xw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=UOdbvLQbAiqRqFGMqm7pr+Z38uLzt1pKc5PPb8cs294=; b=sNTt0mStpjnidqD01iqV4nnbPsUu9luensW1iped+7X7xNfdjgLjhhw5PmQfqeufV1ZHamb51goqQRj41W8n3YHqckQkdi6VbUwZLJiV4X5xldFM+NxZj3IX/XLn+nPvJHN+tIwQoQgOLMbqLyr90/6LckDlHLDAEmH4GfO0WiY= Received: from IA1P220CA0022.NAMP220.PROD.OUTLOOK.COM (2603:10b6:208:464::11) by CH2PR12MB4278.namprd12.prod.outlook.com (2603:10b6:610:ab::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.15; Mon, 26 Jan 2026 19:28:04 +0000 Received: from MN1PEPF0000F0DF.namprd04.prod.outlook.com (2603:10b6:208:464:cafe::d6) by IA1P220CA0022.outlook.office365.com (2603:10b6:208:464::11) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9542.16 via Frontend Transport; Mon, 26 Jan 2026 19:28:06 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=satlexmb08.amd.com; pr=C Received: from satlexmb08.amd.com (165.204.84.17) by MN1PEPF0000F0DF.mail.protection.outlook.com (10.167.242.37) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9564.3 via Frontend Transport; Mon, 26 Jan 2026 19:28:03 +0000 Received: from satlexmb08.amd.com (10.181.42.217) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 26 Jan 2026 13:28:00 -0600 Received: from xsjdavidzha51.xilinx.com (10.180.168.240) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Mon, 26 Jan 2026 13:27:59 -0600 From: David Zhang To: , , , , CC: , , , Subject: [PATCH V2 1/5] accel/amd_vpci: Add documentation for AMD Versal PCI accelerator management Date: Mon, 26 Jan 2026 11:27:28 -0800 Message-ID: <20260126192732.1507084-2-yidong.zhang@amd.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260126192732.1507084-1-yidong.zhang@amd.com> References: <20260126192732.1507084-1-yidong.zhang@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: MN1PEPF0000F0DF:EE_|CH2PR12MB4278:EE_ X-MS-Office365-Filtering-Correlation-Id: 593b6b33-721a-43a6-e9e5-08de5d110698 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|82310400026|36860700013|376014|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?pXf+KFqDDZ8Je0ESv2A3c0zWvVoZlDqumCn317ubWbF3OAL/V8wAlYTVEa3n?= =?us-ascii?Q?7F3gGE5n+3RCkZqit9HXI0BkBD7r0Tzw9fT2C58ZVvRAreXvyVovVDcKut0C?= =?us-ascii?Q?buy7sg0h9aYU55KlAYmXWtU1W8oj6hzE+yVY625F/2ZP0UV9YLnssO9A9gzM?= =?us-ascii?Q?E9UJio/5BvagFpif/lL+LxJ4+ZhspzuTL1ZoJQxDTlTb9pcsPBJv2e/3yLix?= =?us-ascii?Q?yzyaEhRSt27ptwxANEKDzlGJyAe4OWZQWNLjzv+SgZB6EUuUEZe5y/Dm/1Eb?= =?us-ascii?Q?08Xsuob5E1tg7aHbpkjqwmcaN61IInxs3wN+qNzJ8glxyff9lu1e6iKslZCd?= =?us-ascii?Q?Jj6HrGWab38EdkaCMTwkE/ArHTaYuDxumgOQt7Xs7OLtze9ZalSnHtWp2OYM?= =?us-ascii?Q?oysZtO6A+O4sevyOQRRLq1PzfdrbsyolK+kvVA6xjFaJJQRhhEcxo4pezySs?= =?us-ascii?Q?7iybo/15gnJHdndS6yIOyM6V69R51s5tq9DIhIJqKvVVew18L9TfLOp+vNAl?= =?us-ascii?Q?GfRySZ6q5IGW4AsWRaMKg146io+159DpabgF3BtR0jeEvXWy3SaG/n+nKoHK?= =?us-ascii?Q?gAJKNR/gh3Rov+G1Jii6uKQTa7caYl0Lrf8cFIkJ8N4/RCdPKtg6gVcapLi7?= =?us-ascii?Q?ghoZEyqf4ymV98B7a6hYl6GaY0GA85KlUaR125OsErdftH4vauJaLfqHCwt4?= =?us-ascii?Q?ij/1ari4Erl3sm8POZzNcsEN5Wd9rRPFaaclmmZF3/qP3GzVN5H1+Jd5vD5R?= =?us-ascii?Q?4Bxhg1YJbO930eFYl5EegrsayASaByOuiPIaU7Tps1eahYtYt/B0NtJYTpYK?= =?us-ascii?Q?JlNOB/QlSKwA9yUKsFjcTGuz0oPZyiT6zsf87dCSeagqNEamcFF/tSwMWS9i?= =?us-ascii?Q?7xMIQmcWWheNIRAe6b4HbC7c3r6P8oD5xYuSWHM6jfnHkPOu0S2Vthc5Jqer?= =?us-ascii?Q?0dKLmGUt3+nheGF07FGifeaI8H36KMX6oHq7kUSM7bX8v7MYjy5mrGM8zUvw?= =?us-ascii?Q?4m6xXvgrt2Vp6N4+T88iTBsw9fg9p5GWS0c3DiiSDEbIi4F3KXd/wGLSVYKb?= =?us-ascii?Q?RJanVhxEm8P3RXlsIwb+r4QNSG20qcawvIAWrXuEPKxacJJKvIWDnKhtPNfa?= =?us-ascii?Q?vGF41Q5fbypbK0Zx9l8fFLfo93inYlDGNSowDEqo9LqSiZhm5wuz/JSiqF57?= =?us-ascii?Q?sNTIPz6Ury+9luURoUpymk1QefZLwiktTzSUEVRfYmihgZsNYJ8rrbWRDapv?= =?us-ascii?Q?CMr11OZBfHF7tzSVvDsub9tp1XD+3iD7+74bBFAuXpIPmcashCjkHXsv+dIt?= =?us-ascii?Q?LAfgixfDMH6UwIyyKire+fqDJHTMwx72L1KzUFo9SMjMb8wfLM14sdeqmWU7?= =?us-ascii?Q?39DHvGImZYS5hogEBXJ42ZM10xPHomsZ65f90TnEEFm35+HvIyQHGPDBhQKo?= =?us-ascii?Q?L1WsGANyIPJ8XtLyzY+wCLW4/D5FqsJaAVNqdHGRBI3bAHAYdMfSQ0CqDAKa?= =?us-ascii?Q?PWQBw9kfxAWRCkVTrz4iYKejPdDFKhFJ+49YfVJozj4OxNTxu2m4g2HVljOI?= =?us-ascii?Q?pbeTEzNg7vrvvATr8uc+wOQ3q1QdU2enoP9WT4agNOs3QSQs2UTYlJESr5Mm?= =?us-ascii?Q?tefXflXduWGIMI6vZFSXW4H1hGbXfbYHlf1tNqBWUszKFpecacYnyetNCOXI?= =?us-ascii?Q?oq93XQ=3D=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:satlexmb08.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230040)(82310400026)(36860700013)(376014)(1800799024);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jan 2026 19:28:03.9263 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 593b6b33-721a-43a6-e9e5-08de5d110698 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[satlexmb08.amd.com] X-MS-Exchange-CrossTenant-AuthSource: MN1PEPF0000F0DF.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH2PR12MB4278 Content-Type: text/plain; charset="utf-8" This patch introduces documentation for the AMD Versal PCI accelerator management driver. The driver runs on the host and manages the AMD Versal AI Edge SoC on the AMD Embedded+ platform. It handles management-plane operations including firmware image loading, reset, and health monitoring. This documentation also describes the firmware interface (VMR) and overall platform architecture. Co-developed-by: Sonal Santan Signed-off-by: Sonal Santan Signed-off-by: David Zhang --- Documentation/accel/amd_vpci/amd_vpci.rst | 122 ++++++++++++++++++++++ Documentation/accel/amd_vpci/index.rst | 11 ++ Documentation/accel/index.rst | 1 + 3 files changed, 134 insertions(+) create mode 100644 Documentation/accel/amd_vpci/amd_vpci.rst create mode 100644 Documentation/accel/amd_vpci/index.rst diff --git a/Documentation/accel/amd_vpci/amd_vpci.rst b/Documentation/acce= l/amd_vpci/amd_vpci.rst new file mode 100644 index 000000000000..7638e9107ff6 --- /dev/null +++ b/Documentation/accel/amd_vpci/amd_vpci.rst @@ -0,0 +1,122 @@ +.. SPDX-License-Identifier: GPL-2.0-only + +.. include:: + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + AMD Versal PCI +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +:Copyright: |copy| 2026 Advanced Micro Devices, Inc. +:Authors: - Sonal Santan + - Yidong (David) Zhang + +Overview +=3D=3D=3D=3D=3D=3D=3D=3D + +The AMD Embedded+ platform integrates AMD Ryzen Embedded processors with +AMD Versal AI Edge adaptive System-on-Chip (SoC) on a single PCB. The AMD +Ryzen Embedded processor is connected to the Versal AI Edge adaptive SoC +via PCIe enabling a tightly coupled heterogeneous compute platform. AMD +Embedded+ platform is commonly used for sensor fusion, AI inferencing, +industrial networking, control, and visualization. + +AMD Versal PCI driver, versal-pci, is a host-side PCIe driver for AMD +Embedded+ platform running on AMD Ryzen Embedded processor. The versal-pci +driver is responsible for the **management-plane** operations for the AMD +Versal AI Edge adaptive SoC, including: + +* Loading accelerator firmware images +* Reset and recovery +* Health monitoring + +Please note that the versal-pci driver does *not* participate in workload +execution. + +Hardware Description +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +AMD Versal AI SoCs boot from a dedicated flash device and presents two +PCIe physical functions to the AMD Ryzen Embedded processor which acts as +PCIe host. + +* Physical function 0 (PF0) is used for the management-plane to interact + with versal-pci driver. +* Physical function 1 (PF1) is used for the execution-plane. In some cases + PF1 can be attached to a VM. + +Versal Management Runtime (VMR) Firmware +---------------------------------------- + +AMD Versal AI SoC runs Versal Management Runtime (VMR) firmware on a +microcontroller. VMR is responsible for: + +* Low-level management of the AMD Versal AI SoC. +* Loading accelerator images into a dedicated partition on the AMD Versal + AI SoC. + +The VMR communicates with the versal-pci driver via: + +* A command queue mapped to PCIe PF0 BAR. +* A shared memory region in the PCIe PF0 BAR. + +Accelerator Image +----------------- + +An AMD Embedded+ platform may store multiple *accelerator images*, each +identified by a UUID in a secure location on the AMD Ryzen host file +system. Each image enables a specific application like sensor fusion, AI +inferencing, etc. A chosen accelerator image is sent to the VMR by the +versal-pci driver. Once loaded, the accelerator image running in the +dedicated partition of AMD Versal AI SoC interfaces with the AMD Ryzen host +via PCIe PF1. + +Accelerator Image Loading Workflow +---------------------------------- + +1. A user application requests an image load by sending the UUID of the + desired image to the user driver attached to PF1. +2. The user driver forwards the UUID to the versal-pci driver via a mailbox + channel which connects PF1 to PF0. +3. The versal-pci driver on PF0 receives the UUID via the mailbox channel. +4. The versal-pci driver on PF0 then requests the accelerator image change + by sending a message to the VMR. +5. The versal-pci driver copies the accelerator image to the shared memory + region on the PF0 PCIe BAR. It then sends a message to the VMR via the + command queue. +6. Upon receiving the request from versal-pci, the VMR programs dedicated + hardware in the AMD Versal AI SoC to perform image loading. +7. The image is loaded over the dedicated partition which then starts + running. The VMR sends success response to the versal-pci driver. +8. The versal-pci driver then responds to the user PF driver over the + communication channel. +9. The versal-pci driver begins monitoring the health of the AMD Versal + SoC. + + +The Driver Architecture +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +.. code-block:: bash + + +------------+ + | | + | VM | + +------------+ | | + | versal-pci | | | + +---+----o-------+-----+-----o------+-----+ + | | Linux | | AMD Ryzen Host + +--------|-------------------|------------+ + PF0 PF1 + | | + +--------v--------+----------v------------+ + | . | + | VMR . Accelerator Image | AMD Versal AI SoC + | . | + +-----------------+-----------------------+ + + +References +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +* `AMD Embedded Plus `_ +* `AMD Embedded Platform Architecture `_ diff --git a/Documentation/accel/amd_vpci/index.rst b/Documentation/accel/a= md_vpci/index.rst new file mode 100644 index 000000000000..3ed4ab9e1332 --- /dev/null +++ b/Documentation/accel/amd_vpci/index.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0-only + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + accel/amd_vpci Versal Embedded Plus driver +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The accel/amd_vpci driver supports the AMD Versal Embedded Plus accelerator + +.. toctree:: + + amd_vpci diff --git a/Documentation/accel/index.rst b/Documentation/accel/index.rst index d8fa332d60a8..30fed42e1686 100644 --- a/Documentation/accel/index.rst +++ b/Documentation/accel/index.rst @@ -9,6 +9,7 @@ Compute Accelerators =20 introduction amdxdna/index + amd_vpci/index qaic/index rocket/index =20 --=20 2.34.1 From nobody Sat Feb 7 08:13:38 2026 Received: from CY7PR03CU001.outbound.protection.outlook.com (mail-westcentralusazon11010012.outbound.protection.outlook.com [40.93.198.12]) (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 3113F221DB1 for ; Mon, 26 Jan 2026 19:28:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.198.12 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769455712; cv=fail; b=TYr8Pv4KlusrEAP6+WGuoCrRGgfEEY16UrB9uua+KOdil0wa2ABK9N3UdgZqk+CcWm4LcauRosM6KDT2jO5vIBmcP2X+xb67khh5NCXToYq027S2EIBaN0CDxPhKA6KUGxEJtxUOE9nepOhNeIBeXiknbtm5kwvqiQg/KlIrBPE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769455712; c=relaxed/simple; bh=AGUG7HUTOTmXs5sWFlt2ncqKXXVbS4me+2tnAbrqK4g=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=vGHhFvNIPw8VdxmuVmaZ7hhblfQFHW/IPlwQTzEJinWEI70lEKEYrIjDTqEy2HIZa4DEC2UVAePuzNiqH+CbpUtkqelL2YlxdplRtK91pfIjtr+dOmdIfgHqMgFxXaewEOZpYwG4EIASGRGE+60lWL2gHc6YlgizWjWDB+v1O7E= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=QFJ8L9H4; arc=fail smtp.client-ip=40.93.198.12 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="QFJ8L9H4" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=KCF4RJW9GbL3uQStPrY+AG6Ajoxsk5jA+ELO1Td7F0f7FTykyZKJGrriOfUGqsHtIeVcK1YkJmm4F4BGigZWUxUIVmqxNn7ylVmHdIyQazhv2IA2mw35FwEedqkVJuasxHAMmg33s954kQdMSqnL1OO7jMdU4t9CSJyRILYvaBYv37nOvlK3+jRNWvtPVKs1Yu7A1fl2jb+JAms34H1qKw7We/MLZvxDOBFN04Z66/ilMVDYSWG15xurOh21XJ8shIQ6obkMnjQlCReDjFKAtz4w0lo8uBVMTZkN/GVNCjXqX0G9HfjYcUkkqxh65xkBN5ySxHkpayYMAwkrUOLJQg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=5fA967fUS+fO8kOgdryHp8lUKMghn/I58/Tu1w0/TA0=; b=om/WcLhdDvSrsL7lvn3DUS7DOMO5lPk4iVUwYhhELiRI/fOOSr47fpFvHrGzXHelHqfFpD56P9+dKvnk+2KxzYnJ1qAJ+TkK6biwXXFrn6q2hMIe0/4r7XlQy9JTamJxRUcidTomvrHhY0e7XlUHxLXjhZyFa1rq8yrHlnthv7ZEbimVRMohMK2Z7slLDCG5t5SZ08245z9sLbD5bSPrKId/BmucETNKzC2LsMiPetJ9YZMib0ZtgL+jy5m4xfwfY1IgGXFNpYABnzKBEsmSJbsacXmva0UjoCj1GQ6blhXo9RrhgrTvdSpmGV+Gx8kenmfmqilFiP7ahQFU0RccoQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=5fA967fUS+fO8kOgdryHp8lUKMghn/I58/Tu1w0/TA0=; b=QFJ8L9H4mbCOtX+KcULjeTBmv8eehptZLiglYCwKcEDkeFWcnTQQiVMPn+Q5imspcOsMX9GtH4opkxULPaMSf2t5xafDaLUrsAIupUTSkXt3Yx48UcaPQG+hNztahmPsRNxBHmCSJ/7CsQE/2mgstTGdprsa5sGqnJokqNTuIqI= Received: from MN0PR03CA0017.namprd03.prod.outlook.com (2603:10b6:208:52f::11) by CYXPR12MB9444.namprd12.prod.outlook.com (2603:10b6:930:d6::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.15; Mon, 26 Jan 2026 19:28:19 +0000 Received: from MN1PEPF0000F0E3.namprd04.prod.outlook.com (2603:10b6:208:52f:cafe::98) by MN0PR03CA0017.outlook.office365.com (2603:10b6:208:52f::11) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9542.16 via Frontend Transport; Mon, 26 Jan 2026 19:28:09 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=satlexmb08.amd.com; pr=C Received: from satlexmb08.amd.com (165.204.84.17) by MN1PEPF0000F0E3.mail.protection.outlook.com (10.167.242.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9564.3 via Frontend Transport; Mon, 26 Jan 2026 19:28:19 +0000 Received: from Satlexmb09.amd.com (10.181.42.218) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 26 Jan 2026 13:28:01 -0600 Received: from satlexmb08.amd.com (10.181.42.217) by satlexmb09.amd.com (10.181.42.218) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 26 Jan 2026 11:28:01 -0800 Received: from xsjdavidzha51.xilinx.com (10.180.168.240) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Mon, 26 Jan 2026 13:28:00 -0600 From: David Zhang To: , , , , CC: , , , , DMG Karthik , Nishad Saraf Subject: [PATCH V2 2/5] accel/amd_vpci: Add new driver for AMD Versal PCI accelerator Date: Mon, 26 Jan 2026 11:27:29 -0800 Message-ID: <20260126192732.1507084-3-yidong.zhang@amd.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260126192732.1507084-1-yidong.zhang@amd.com> References: <20260126192732.1507084-1-yidong.zhang@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: MN1PEPF0000F0E3:EE_|CYXPR12MB9444:EE_ X-MS-Office365-Filtering-Correlation-Id: 4fde5bee-988d-4d2b-b7e4-08de5d110fd7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|82310400026|376014|1800799024|36860700013; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?QB+ipiH5WwGQVQ+re+6Wm5hmZSjCbbWcCYxyTZVHYQHFpxVXkO2eQz95cSUx?= =?us-ascii?Q?FJ9y3Ln6VogoPjSeeJGd8oszfV5Zlc3Q3Cj6tuSJkoan1B/vLD9q2hI5nSs5?= =?us-ascii?Q?sdprJIr0A+qQg1WQP7m3mCkqL3yhoCBi63jhsz9SyYOuLNMdCo8VrLSh1ny/?= =?us-ascii?Q?1z1fuDAGjlHGEvffkQ1oEUzAxKg7S+ZyZH9TZkq1kamylqFeXBLyjJzNwgKm?= =?us-ascii?Q?UGwxkjSthrbjF5uUBNITDS2JOYNHBBwK8cfepjx1k6v58LrcmEIW+Qk8c6Ar?= =?us-ascii?Q?W4vctPSmthJrYD9/wBiUDdsyVo+koAFKTfETSc756rHuumpfXwTRxM1Ii61D?= =?us-ascii?Q?dAK2Bg/pYZ8BD0e9mauwSKdXUkZjF4MFlPpN5M0QhmLPVaKTBVLHDfUg+I7r?= =?us-ascii?Q?umYlIfRSbEiM7biq/Uo7EQvvGDZc6pE9Y2wQNJ7Xn3UHF4w5qZgQtVjfUKbp?= =?us-ascii?Q?UJBI8Moh8uOPKJxjNDcNZea0AeVH47b4RbIdA4e+l+kHRPWfYxkpOuVTwhR3?= =?us-ascii?Q?vhCgZupEJXd9WNUNA3m3RdevmYE8h3D3nx7b76ppErlYduJ2v3blP7bO5NM5?= =?us-ascii?Q?Rs4iA2tjHfw0JhPrWX+qjkbu1bGH33jEVXiRQKOpgDKrPEld3FDsZ2Yepzdg?= =?us-ascii?Q?OAm36uVX6SZ2njCzIB8138zt7gs8L+I4ed8nP1qrpx28BFOO+El0ezwAX3wH?= =?us-ascii?Q?6VCQy3kQGPIjbr4o2Qg3DoWwCWs2Hcm0W65KUb90dnAVRH+sBqvwOxozwMtm?= =?us-ascii?Q?srnmp9SGu/zZ5eDwUlBKyqM5J5PPJFRXDV7Fsj1PnwK9QV2B8f8CCvhaQ2Nt?= =?us-ascii?Q?CPySoWeFamTPbN4O0DLu9EpuAKmSkeXDGnHNRKmTnLiPZ6oy/zgzPclVybrG?= =?us-ascii?Q?5B+2vBKiWBzVjh6j3f88gVpe6054ffTZ0fJeYYJd01kNVLsInsOww96TxAGA?= =?us-ascii?Q?w91FhaIg9WddRWsaf/YvDOrGu+pQlpmBam4ngDcEnz41jYg7luAJ+R77VOSy?= =?us-ascii?Q?6k2alMWHCKd9pekvWsx77Kv4h74ObFV/OK0FXegl06Mf83SUPWHE7MVSWsvB?= =?us-ascii?Q?rH1YGraq1vf459sWk/Z4Yc5pWu0RYFsrPM2RjXnfhlf1iX0n6MUaWD5NbDAD?= =?us-ascii?Q?WMuDXlizr1FbNrpbChzpOF1vCcvShK9W61+zo6S7CzROU3JQvISInjIhvXmQ?= =?us-ascii?Q?YG+kvjsSobRfz5CpGMU/cZhduP2xKtKUT13l/IIfwJO6f6yJv3SK7kwRemMJ?= =?us-ascii?Q?VtbGm+EHSRH+RJ8nHfiaT0rbgYE0rAoiW2WQcbR+escKvGI5zqMhNoE386V6?= =?us-ascii?Q?nwv/NdQpb7Wga5ZsfFlgB6rw7jgWAolaok+cDZfPLBJGNnBEMAGV61OVHOJg?= =?us-ascii?Q?bawGn6kj1XPlVoAu0nJZa6Gm0zR9Dyx3MyzKlDcMnQt0KKR0akl8wtvDS5YZ?= =?us-ascii?Q?wmPBY2u2uh7W9u2HGXZKoFC2q+zmIhgU8GZD3qaUi6Mwae9Cj1Hp4Dl5HhO3?= =?us-ascii?Q?IhuDDISGFumZx+o8A7jdoZKvzSMkM8PriyV91WEaAO4GcSTYJz6MWCSUGFc9?= =?us-ascii?Q?iQr9EP3/jDZCjIV2eNY4z8STVPp8pyIp5/MX+sAzF4l94psCeRKKIdhk8xNG?= =?us-ascii?Q?Bhgi3v4WkXYvK1d66SBp7paUMDsygBCpSsEexoVlup5xYR/IFQtwiIVjhFhV?= =?us-ascii?Q?0TMZ1w=3D=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:satlexmb08.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230040)(82310400026)(376014)(1800799024)(36860700013);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jan 2026 19:28:19.4352 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 4fde5bee-988d-4d2b-b7e4-08de5d110fd7 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[satlexmb08.amd.com] X-MS-Exchange-CrossTenant-AuthSource: MN1PEPF0000F0E3.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CYXPR12MB9444 Content-Type: text/plain; charset="utf-8" This patch introduces a new PCI driver for AMD Versal-based accelerator cards. The driver provides basic module and PCI device initialization, based on BAR resources used to establish a hardware queue-based ring buffer between the PCIe host and the Versal Management Runtime (VMR) service running on the embedded SoC. This interface enables firmware management and board health monitoring. Key features: - PCI probe and BAR resource initialization. - Integration with configfs for firmware management - Compatibility check using firmware-reported UUIDs The base firmware image is expected under /lib/firmware/xilinx/ and can be programmed to the device through the configfs interface. Firmware transfer is handled via a remote queue service (added in a later patch). Co-developed-by: DMG Karthik Signed-off-by: DMG Karthik Co-developed-by: Nishad Saraf Signed-off-by: Nishad Saraf Signed-off-by: David Zhang --- MAINTAINERS | 5 + drivers/accel/Kconfig | 1 + drivers/accel/Makefile | 3 +- drivers/accel/amd_vpci/Kconfig | 15 ++ drivers/accel/amd_vpci/Makefile | 6 + drivers/accel/amd_vpci/versal-pci-main.c | 280 +++++++++++++++++++++++ drivers/accel/amd_vpci/versal-pci.h | 62 +++++ 7 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 drivers/accel/amd_vpci/Kconfig create mode 100644 drivers/accel/amd_vpci/Makefile create mode 100644 drivers/accel/amd_vpci/versal-pci-main.c create mode 100644 drivers/accel/amd_vpci/versal-pci.h diff --git a/MAINTAINERS b/MAINTAINERS index 6863d5fa07a1..8fb7276eb7c1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1271,6 +1271,11 @@ F: drivers/spi/spi-amd-pci.c F: drivers/spi/spi-amd.c F: drivers/spi/spi-amd.h =20 +AMD VERSAL PCI DRIVER +M: Yidong Zhang +S: Supported +F: drivers/accel/amd_vpci/ + AMD XDNA DRIVER M: Min Ma M: Lizhi Hou diff --git a/drivers/accel/Kconfig b/drivers/accel/Kconfig index bdf48ccafcf2..f80998fdb3fc 100644 --- a/drivers/accel/Kconfig +++ b/drivers/accel/Kconfig @@ -25,6 +25,7 @@ menuconfig DRM_ACCEL and debugfs). =20 source "drivers/accel/amdxdna/Kconfig" +source "drivers/accel/amd_vpci/Kconfig" source "drivers/accel/ethosu/Kconfig" source "drivers/accel/habanalabs/Kconfig" source "drivers/accel/ivpu/Kconfig" diff --git a/drivers/accel/Makefile b/drivers/accel/Makefile index 1d3a7251b950..be62e08bbef1 100644 --- a/drivers/accel/Makefile +++ b/drivers/accel/Makefile @@ -1,8 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-only =20 obj-$(CONFIG_DRM_ACCEL_AMDXDNA) +=3D amdxdna/ +obj-$(CONFIG_DRM_ACCEL_AMD_VPCI) +=3D amd_vpci/ obj-$(CONFIG_DRM_ACCEL_ARM_ETHOSU) +=3D ethosu/ obj-$(CONFIG_DRM_ACCEL_HABANALABS) +=3D habanalabs/ obj-$(CONFIG_DRM_ACCEL_IVPU) +=3D ivpu/ obj-$(CONFIG_DRM_ACCEL_QAIC) +=3D qaic/ -obj-$(CONFIG_DRM_ACCEL_ROCKET) +=3D rocket/ \ No newline at end of file +obj-$(CONFIG_DRM_ACCEL_ROCKET) +=3D rocket/ diff --git a/drivers/accel/amd_vpci/Kconfig b/drivers/accel/amd_vpci/Kconfig new file mode 100644 index 000000000000..dcf83bf3d8e6 --- /dev/null +++ b/drivers/accel/amd_vpci/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only + +config DRM_ACCEL_AMD_VPCI + tristate "AMD Versal PCIe Management Driver" + depends on DRM_ACCEL + depends on PCI && HAS_IOMEM + select FW_LOADER + select CONFIGFS_FS + default m + help + AMD Versal PCIe Management Driver provides management services, + including download firmware, program bitstream, and communicate with + the User function. + + If "M" is selected, the driver module will be versal-pci diff --git a/drivers/accel/amd_vpci/Makefile b/drivers/accel/amd_vpci/Makef= ile new file mode 100644 index 000000000000..03849875ad0b --- /dev/null +++ b/drivers/accel/amd_vpci/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-$(CONFIG_DRM_ACCEL_AMD_VPCI) :=3D versal-pci.o + +versal-pci-y :=3D \ + versal-pci-main.o diff --git a/drivers/accel/amd_vpci/versal-pci-main.c b/drivers/accel/amd_v= pci/versal-pci-main.c new file mode 100644 index 000000000000..36f88d5aee95 --- /dev/null +++ b/drivers/accel/amd_vpci/versal-pci-main.c @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Versal PCIe device + * + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. + */ + +#include + +#include "versal-pci.h" + +#define DRV_NAME "amd-versal-pci" + +#define PCI_DEVICE_ID_V70PQ2 0x50B0 +#define PCI_DEVICE_ID_RAVE 0x5700 +#define VERSAL_XCLBIN_MAGIC_ID "xclbin2" + +static inline u32 versal_pci_devid(struct versal_pci_device *vdev) +{ + return ((pci_domain_nr(vdev->pdev->bus) << 16) | + PCI_DEVID(vdev->pdev->bus->number, vdev->pdev->devfn)); +} + +static int versal_pci_load_shell(struct versal_pci_device *vdev, char *fw_= name) +{ + const struct firmware *fw; + struct axlf *xsabin; + int ret; + + strim(fw_name); + + ret =3D request_firmware(&fw, fw_name, &vdev->pdev->dev); + if (ret) { + vdev_warn(vdev, "request xsabin fw %s failed %d", fw_name, ret); + return ret; + } + + xsabin =3D (struct axlf *)fw->data; + if (memcmp(xsabin->magic, VERSAL_XCLBIN_MAGIC_ID, strlen(VERSAL_XCLBIN_MA= GIC_ID))) { + vdev_err(vdev, "Invalid device firmware"); + ret =3D -EINVAL; + goto release_firmware; + } + + if (!fw->size || + fw->size !=3D xsabin->header.length || + fw->size < sizeof(*xsabin) || + fw->size > SZ_1G) { + vdev_err(vdev, "Invalid device firmware size %zu", fw->size); + ret =3D -EINVAL; + goto release_firmware; + } + + if (!uuid_equal(&vdev->intf_uuid, &xsabin->header.rom_uuid)) { + vdev_err(vdev, "base shell doesn't match uuid %pUb", &xsabin->header.rom= _uuid); + ret =3D -EINVAL; + goto release_firmware; + } + + /* TODO upload fw to card */ + if (ret) { + vdev_err(vdev, "failed to load xsabin %s : %d", fw_name, ret); + goto release_firmware; + } + + vdev_info(vdev, "Downloaded xsabin %pUb of size %lld Bytes", + &xsabin->header.uuid, xsabin->header.length); + +release_firmware: + release_firmware(fw); + + return ret; +} + +static inline struct versal_pci_device *item_to_vdev(struct config_item *i= tem) +{ + return container_of(to_configfs_subsystem(to_config_group(item)), + struct versal_pci_device, cfs_subsys); +} + +static ssize_t versal_pci_cfs_config_store(struct config_item *item, + const char *page, size_t count) +{ + struct versal_pci_device *vdev =3D item_to_vdev(item); + u32 config; + int ret; + + ret =3D kstrtou32(page, 0, &config); + if (ret) + return -EINVAL; + + if (config) + ret =3D versal_pci_load_shell(vdev, vdev->fw.name); + + if (ret) + return -EFAULT; + + return count; +} +CONFIGFS_ATTR_WO(versal_pci_cfs_, config); + +static ssize_t versal_pci_cfs_image_show(struct config_item *item, char *p= age) +{ + struct versal_pci_device *vdev =3D item_to_vdev(item); + + vdev_info(vdev, "fw name: %s", vdev->fw.name); + + return 0; +} + +static ssize_t versal_pci_cfs_image_store(struct config_item *item, + const char *page, size_t count) +{ + struct versal_pci_device *vdev =3D item_to_vdev(item); + + count =3D snprintf(vdev->fw.name, sizeof(vdev->fw.name), "%s", page); + + vdev_info(vdev, "fw name: %s", vdev->fw.name); + return count; +} +CONFIGFS_ATTR(versal_pci_cfs_, image); + +static struct configfs_attribute *versal_pci_cfs_attrs[] =3D { + &versal_pci_cfs_attr_config, + &versal_pci_cfs_attr_image, + NULL, +}; + +static const struct config_item_type versal_pci_cfs_table =3D { + .ct_owner =3D THIS_MODULE, + .ct_attrs =3D versal_pci_cfs_attrs, +}; + +static int versal_pci_cfs_init(struct versal_pci_device *vdev) +{ + struct configfs_subsystem *subsys =3D &vdev->cfs_subsys; + + snprintf(subsys->su_group.cg_item.ci_namebuf, + sizeof(subsys->su_group.cg_item.ci_namebuf), + "%s%x", DRV_NAME, versal_pci_devid(vdev)); + + subsys->su_group.cg_item.ci_type =3D &versal_pci_cfs_table; + + config_group_init(&subsys->su_group); + return configfs_register_subsystem(subsys); +} + +static void versal_pci_fw_fini(struct versal_pci_device *vdev) +{ + uuid_copy(&vdev->intf_uuid, &uuid_null); +} + +static void versal_pci_cfs_fini(struct configfs_subsystem *subsys) +{ + configfs_unregister_subsystem(subsys); +} + +static void versal_pci_device_teardown(struct versal_pci_device *vdev) +{ + versal_pci_cfs_fini(&vdev->cfs_subsys); + versal_pci_fw_fini(vdev); +} + +static int versal_pci_uuid_parse(struct versal_pci_device *vdev, uuid_t *u= uid) +{ + char str[UUID_STRING_LEN]; + u8 i, j; + int len =3D strlen(vdev->fw_id); + + /* parse uuid into a valid uuid string format */ + for (i =3D 0, j =3D 0; i < len && i < sizeof(str); i++) { + str[j++] =3D vdev->fw_id[i]; + if (j =3D=3D 8 || j =3D=3D 13 || j =3D=3D 18 || j =3D=3D 23) + str[j++] =3D '-'; + } + + if (uuid_parse(str, uuid)) { + vdev_warn(vdev, "Invalid fw_id format"); + return -EINVAL; + } + + vdev_info(vdev, "Interface uuid %pU", uuid); + return 0; +} + +static int versal_pci_fw_init(struct versal_pci_device *vdev) +{ + int ret; + + /* TODO request compatible fw_id from card */ + + ret =3D versal_pci_uuid_parse(vdev, &vdev->intf_uuid); + + return ret; +} + +static int versal_pci_device_setup(struct versal_pci_device *vdev) +{ + int ret; + + ret =3D versal_pci_fw_init(vdev); + if (ret) { + vdev_err(vdev, "Failed to init fw, err %d", ret); + goto comm_chan_fini; + } + + ret =3D versal_pci_cfs_init(vdev); + if (ret) { + vdev_err(vdev, "Failed to init configfs subsys, err %d", ret); + goto comm_chan_fini; + } + + return 0; + +comm_chan_fini: + versal_pci_fw_fini(vdev); + + return ret; +} + +static void versal_pci_remove(struct pci_dev *pdev) +{ + struct versal_pci_device *vdev =3D pci_get_drvdata(pdev); + + versal_pci_device_teardown(vdev); +} + +static int versal_pci_probe(struct pci_dev *pdev, const struct pci_device_= id *pdev_id) +{ + struct versal_pci_device *vdev; + int ret; + + vdev =3D devm_kzalloc(&pdev->dev, sizeof(*vdev), GFP_KERNEL); + if (!vdev) + return -ENOMEM; + + pci_set_drvdata(pdev, vdev); + vdev->pdev =3D pdev; + + ret =3D pcim_enable_device(pdev); + if (ret) { + vdev_err(vdev, "Failed to enable device %d", ret); + return ret; + } + + vdev->io_regs =3D pcim_iomap_region(vdev->pdev, MGMT_BAR, DRV_NAME); + if (IS_ERR(vdev->io_regs)) { + vdev_err(vdev, "Failed to map RM shared memory BAR%d", MGMT_BAR); + return PTR_ERR(vdev->io_regs); + } + + ret =3D versal_pci_device_setup(vdev); + if (ret) { + vdev_err(vdev, "Failed to setup Versal device %d", ret); + return ret; + } + + return 0; +} + +static const struct pci_device_id versal_pci_ids[] =3D { + { PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_V70PQ2), }, + { PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_RAVE), }, + { 0 } +}; + +MODULE_DEVICE_TABLE(pci, versal_pci_ids); + +static struct pci_driver versal_pci_driver =3D { + .name =3D DRV_NAME, + .id_table =3D versal_pci_ids, + .probe =3D versal_pci_probe, + .remove =3D versal_pci_remove, +}; + +module_pci_driver(versal_pci_driver); + +MODULE_DESCRIPTION("AMD Versal PCIe Management Driver"); +MODULE_AUTHOR("XRT Team "); +MODULE_LICENSE("GPL"); diff --git a/drivers/accel/amd_vpci/versal-pci.h b/drivers/accel/amd_vpci/v= ersal-pci.h new file mode 100644 index 000000000000..890da1d6bcc9 --- /dev/null +++ b/drivers/accel/amd_vpci/versal-pci.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Driver for Versal PCIe device + * + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. + */ + +#ifndef __VERSAL_PCI_H +#define __VERSAL_PCI_H + +#include +#include + +#define MGMT_BAR 0 + +#define vdev_info(vdev, fmt, args...) \ + dev_info(&(vdev)->pdev->dev, "%s: "fmt, __func__, ##args) + +#define vdev_warn(vdev, fmt, args...) \ + dev_warn(&(vdev)->pdev->dev, "%s: "fmt, __func__, ##args) + +#define vdev_err(vdev, fmt, args...) \ + dev_err(&(vdev)->pdev->dev, "%s: "fmt, __func__, ##args) + +#define vdev_dbg(vdev, fmt, args...) \ + dev_dbg(&(vdev)->pdev->dev, fmt, ##args) + +struct versal_pci_device; + +struct axlf_header { + __u64 length; + __u8 reserved1[24]; + uuid_t rom_uuid; + __u8 reserved2[64]; + uuid_t uuid; + __u8 reserved3[24]; +} __packed; + +struct axlf { + __u8 magic[8]; + __u8 reserved[296]; + struct axlf_header header; +} __packed; + +struct fw_info { + __u32 opcode; + char name[128]; +}; + +struct versal_pci_device { + struct pci_dev *pdev; + + struct fw_info fw; + + void __iomem *io_regs; + uuid_t intf_uuid; + __u8 fw_id[UUID_STRING_LEN + 1]; + + struct configfs_subsystem cfs_subsys; +}; + +#endif /* __VERSAL_PCI_H */ --=20 2.34.1 From nobody Sat Feb 7 08:13:38 2026 Received: from BL2PR02CU003.outbound.protection.outlook.com (mail-eastusazon11011029.outbound.protection.outlook.com [52.101.52.29]) (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 58462284894 for ; Mon, 26 Jan 2026 19:28:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.52.29 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769455709; cv=fail; b=dt/Ip1EMNcV6zkqohnCIK/dI0YEt79I8T3xJjRWUGHv86DVZXGrooSnINLxlGKSJ3+SOgf9LnUHinblsWDNN+qkZ7PBPU/XBoRSZ6yKJCEKC1R55nUbiU7yuyMd2TgBmXs/XypyITF35whlQVGQ8EAHOa7z0bor6f/tKtNkMJwQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769455709; c=relaxed/simple; bh=S2XoAAtlsaBIVcg/j49R3cD/HuMextrr/sOenmmdgDA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=gsMrGGZIrWXkAbhZUwfiJvSAIf7O0S0kn00OeEqMRy2yDQhhz/qL2oAtQwf3FsFALEwj3nVsj5atA4l+DKXiDR5Atj3e34Me63OHFxMiNiZU7bK8iHGHHuw5pZPep2Xu958LdrMaWj8DaNCV48ynUA/2pPd53l5U6cm663PJ3qU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=PuMbPYRe; arc=fail smtp.client-ip=52.101.52.29 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="PuMbPYRe" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=SIrKKjm/TbAUhHL1eQusMK7tbiSHEZUwqKtHNQU4MHgW7TP1x0p46QCklVgH6WdSbr3qPljKptCva/uGbE+TH/AXgwW6noS2vx1+KBSfxn2p/m9kJ5/Gu7CWmW7Gwt9rd3045kS1Pl227QJfWzVGvdkolaFFEWKfMJqPP2vJwO4tc3fRsnXSHMhrffnJHZ00FyCtxIt2jE9ct0dfo2sK05Gh86fj/fFpuNfUmSAKjO6lp31N2bV5YQCrealuBqFrfPXN1qQqbP+9ZqOPCgcPe2psq9dyCZhBWm4OVYk1dB4UbisXRBUQfOu74Q/yNb/Nl9AUd38lsrCWfMzkFmmpmA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=wTbSn/EkbBKDF5WC+GqtU9wMbP7eMfLgwR/ZBugwlm8=; b=T0s2w9LKi7eo+dtmcJTnR/RYUdjpm1J6uzqCOWusFPzTmnfeHGn6aG/bATT1wCDfEUMPDRq0pWhYB2BZObERpuIWn8qobDYjYBUl9GvvDEEDZ7x58xUkRrywX+wljDFM9eSOvGPQJruWMo732Y1s4q29uS5uZQQp4rpaL6D2x18Fi/6tOf6c1PfyT3uHVowUk3hV/v54h3YGyPbTfK8KBbBpeTCQf2PDkkwBwWPlvjtoCi5siqlEERcpi6P//SZyidYZRbXbchlJyEIIjJ2AQhGCmnbSY1wpWDBFIljJnTF8yxCo4CjdSHxcorLl35bZGnJLiY4OXj0YjH3XD8QDNg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=wTbSn/EkbBKDF5WC+GqtU9wMbP7eMfLgwR/ZBugwlm8=; b=PuMbPYReuhBjr17VMW+7ItdADZK6r2zJAkGXRxfR7f5+ZKTqm4GFmi7F2qkfgH+fUf/YZ6qtFaa5F74eqd+8loDnOc7ZCGRX5iLPOvXLGc5YsVsCgJN0BNsg6L4Nb9SQhZETYY0rnqPgRuf2vt3zI/irhG5Un+5uonXF1t45x4k= Received: from BL1PR13CA0170.namprd13.prod.outlook.com (2603:10b6:208:2bd::25) by DS2PR12MB9589.namprd12.prod.outlook.com (2603:10b6:8:279::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.15; Mon, 26 Jan 2026 19:28:20 +0000 Received: from MN1PEPF0000F0E1.namprd04.prod.outlook.com (2603:10b6:208:2bd:cafe::37) by BL1PR13CA0170.outlook.office365.com (2603:10b6:208:2bd::25) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9564.7 via Frontend Transport; Mon, 26 Jan 2026 19:28:14 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=satlexmb08.amd.com; pr=C Received: from satlexmb08.amd.com (165.204.84.17) by MN1PEPF0000F0E1.mail.protection.outlook.com (10.167.242.39) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9564.3 via Frontend Transport; Mon, 26 Jan 2026 19:28:20 +0000 Received: from SATLEXMB03.amd.com (10.181.40.144) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.2.2562.17; Mon, 26 Jan 2026 13:28:02 -0600 Received: from satlexmb08.amd.com (10.181.42.217) by SATLEXMB03.amd.com (10.181.40.144) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Mon, 26 Jan 2026 13:28:02 -0600 Received: from xsjdavidzha51.xilinx.com (10.180.168.240) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Mon, 26 Jan 2026 13:28:01 -0600 From: David Zhang To: , , , , CC: , , , , Nishad Saraf Subject: [PATCH V2 3/5] accel/amd_vpci: Add Remote Management(RM) queue infrastructure Date: Mon, 26 Jan 2026 11:27:30 -0800 Message-ID: <20260126192732.1507084-4-yidong.zhang@amd.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260126192732.1507084-1-yidong.zhang@amd.com> References: <20260126192732.1507084-1-yidong.zhang@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: None (SATLEXMB03.amd.com: yidong.zhang@amd.com does not designate permitted sender hosts) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: MN1PEPF0000F0E1:EE_|DS2PR12MB9589:EE_ X-MS-Office365-Filtering-Correlation-Id: 02a4ed89-5115-49ba-89cf-08de5d11106a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|82310400026|376014|36860700013|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?YeDuPVQHtuJVLwGXP+8YDdaRMSJvlArbXibMd6/q7lOEPDGc8yRxhPQqmktA?= =?us-ascii?Q?v+XBfrdBC+5EkQ9Nex5dO7oqmt1YkpWhOymGw5Jys6s1VehJCyvfDjnund+n?= =?us-ascii?Q?ioLdjv2j11lDzEPtfoeF4tcS6YzZsiybOKA2B5leRMcidjGIPZwMDYyvSpbf?= =?us-ascii?Q?U6UzqI4eiJ3zu0qgzkatXQzF214/3q+pGQWCbZPoy99B0RP7TMJFIoggxvE1?= =?us-ascii?Q?bmIaTdYvFK7MOoc7iIlaZ3rQZLKY7PlMXUEckB81ikNMMZ3D0EOP4JYmm8os?= =?us-ascii?Q?eEgdv/HnONUV8bR6YuzH07pF0ZQ3yJxzFufSBLbQaxGnHNdtrxpnE3IYhAlP?= =?us-ascii?Q?JoxEHDdxtufoUyab7erRRdbjsaXQXWpcCc+bH9qZ4CkhULdWoRpXp07Mbx9U?= =?us-ascii?Q?yS8asxPlGfjKzkRSOAJy1G5HMDXSFgAGYZsxd6IvokSpaDlXduLG+CET5zOA?= =?us-ascii?Q?Sf1ptasu18vD1LCcVtO1MHadRf5mtt9IYrOzclu1RYs0YXrPBBMf2D5wT+J3?= =?us-ascii?Q?RAvKeLG1ZjQtKoXLbUBTAoxjSTJs/R09/NBDsFOXuaefIDQcmr2g6vLB8SYB?= =?us-ascii?Q?IbHELw37DcBNeC8R7vkSfba3XUxCHeQFbrWArhSLO9Vlo6D6Kt2+V6yOo1dv?= =?us-ascii?Q?Fvo9eHRcstv7XDTJMPjZ62LoatkCdgGpDbkr4DN7i7KT/iFRL5BQLSa+K1W3?= =?us-ascii?Q?/kLj26xqZIAJYB0IW7m1kp09du8Rqfn6X0BcC8r9dmA2Dc04ZupEh7QvUWxq?= =?us-ascii?Q?PfZe9ZFfq1hEQJRumLbUrYRdkA+mUBrNabKzCrvIxgI1fKKQsS2lfsQywmcz?= =?us-ascii?Q?5ZjIAC7UGOUPKzqC0WiHrBIqJ85nEYVHe3qKtCyLkX/8Al4WmtGGPgEAEYTe?= =?us-ascii?Q?1AxSbL8hrSejSALaQUS7NC74CYyLUXXPXrDB+o+slRL13ht0fe0I7aEaGgxI?= =?us-ascii?Q?j0Ai+kO71Va2uoIinzFlUkJFyo/HzvCF+hYQOw+FnAInrAgJbwGcxxrf1B+3?= =?us-ascii?Q?hDX1AXRehr0zimavf9HrZ+ywRkYMxPW94InjNgOSfe754Ihlanf2UqUefrcw?= =?us-ascii?Q?eN6MWdXFfSgZb9R7GMBCiEri0poP9l8n9H5vv8VmTxR6v6vVd9pZuUUAtvIZ?= =?us-ascii?Q?fEcDF6iVa8AJGfsF4C2aRgGqsakRTwQNJ29WiHEjWJ/k2g5ho3ddGA4Xl2Ad?= =?us-ascii?Q?aE4v0aet/2+Hz48laaU0V3SreThnwC0Qgx5PN/K/EmVz7eHwz8494c0LPfa2?= =?us-ascii?Q?I52TYBQT2cPpwZmUgukRt4xUC4Ug8aP4nsTVRZQ5fKrJNecitHgHngoZRLVX?= =?us-ascii?Q?CtVb/3nfCEykGEe0A/3zOC5c2dRNcbGlWm8DSjh+/YamhePW9OP7/ANx1hoM?= =?us-ascii?Q?Tp+hWu2KEmKFYO3OZznccsN+CmzDVhZcj7DqcIKXhkjklY9v7sQfINhCLo+1?= =?us-ascii?Q?wowqvagzS7uNtBEBIvr+OQb9lEVHH1MlPq1Eg+9n9508L5psfYHDoaMv3Btw?= =?us-ascii?Q?0+mgRH2w/1bZhPAC58SsAW6uVvzN+BYzYC5TdrhL1iznswKbTDvVBi5nxBYN?= =?us-ascii?Q?7aZj6oPPPrEMELUQ3K1JTNZ93gVRUdwNFovvN2kSz93138U0aUfGpOHPlf78?= =?us-ascii?Q?w7ZEmAAQfUMSTZKniI6cvAFt4uRvuiN7/bxquTTC70+jb/7E/F4Q+Aagnvta?= =?us-ascii?Q?x0MfEw=3D=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:satlexmb08.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230040)(82310400026)(376014)(36860700013)(1800799024);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jan 2026 19:28:20.4071 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 02a4ed89-5115-49ba-89cf-08de5d11106a X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[satlexmb08.amd.com] X-MS-Exchange-CrossTenant-AuthSource: MN1PEPF0000F0E1.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS2PR12MB9589 Content-Type: text/plain; charset="utf-8" This patch introduces a Remote Management (RM) queue service, which provides a way to communicate between the management PCIe function (PF0) and the embedded firmware running on AMD Versal SoCs. The RM service implements a hardware-based ring buffer for bidirectional command and response exchange between the host driver and the firmware. This patch adds the core infrastructure for: - Initializing and managing the RM queue - Submitting commands to the embedded firmware - Polling for command completion Subsequent patches will integrate the infrastructure with the firmware management logic to enable firmware download, status query, and other control operations. Co-developed-by: Nishad Saraf Signed-off-by: Nishad Saraf Signed-off-by: David Zhang --- drivers/accel/amd_vpci/Makefile | 3 +- drivers/accel/amd_vpci/versal-pci-rm-queue.c | 316 ++++++++++++++++++ drivers/accel/amd_vpci/versal-pci-rm-queue.h | 21 ++ .../accel/amd_vpci/versal-pci-rm-service.h | 209 ++++++++++++ drivers/accel/amd_vpci/versal-pci.h | 1 + 5 files changed, 549 insertions(+), 1 deletion(-) create mode 100644 drivers/accel/amd_vpci/versal-pci-rm-queue.c create mode 100644 drivers/accel/amd_vpci/versal-pci-rm-queue.h create mode 100644 drivers/accel/amd_vpci/versal-pci-rm-service.h diff --git a/drivers/accel/amd_vpci/Makefile b/drivers/accel/amd_vpci/Makef= ile index 03849875ad0b..9e4e56ac2dee 100644 --- a/drivers/accel/amd_vpci/Makefile +++ b/drivers/accel/amd_vpci/Makefile @@ -3,4 +3,5 @@ obj-$(CONFIG_DRM_ACCEL_AMD_VPCI) :=3D versal-pci.o =20 versal-pci-y :=3D \ - versal-pci-main.o + versal-pci-main.o \ + versal-pci-rm-queue.o diff --git a/drivers/accel/amd_vpci/versal-pci-rm-queue.c b/drivers/accel/a= md_vpci/versal-pci-rm-queue.c new file mode 100644 index 000000000000..eeda07065487 --- /dev/null +++ b/drivers/accel/amd_vpci/versal-pci-rm-queue.c @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Versal PCIe device + * + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. + */ + +#include + +#include "versal-pci.h" +#include "versal-pci-rm-queue.h" +#include "versal-pci-rm-service.h" + +static inline struct rm_device *to_rdev_msg_monitor(struct work_struct *w) +{ + return container_of(w, struct rm_device, msg_monitor); +} + +static inline struct rm_device *to_rdev_msg_timer(struct timer_list *t) +{ + return container_of(t, struct rm_device, msg_timer); +} + +static inline u32 rm_io_read(struct rm_device *rdev, u32 offset) +{ + /* TODO */ + return 0; +} + +static inline int rm_io_write(struct rm_device *rdev, u32 offset, u32 valu= e) +{ + /* TODO */ + return 0; +} + +static inline u32 rm_queue_read(struct rm_device *rdev, u32 offset) +{ + /* TODO */ + return 0; +} + +static inline void rm_queue_write(struct rm_device *rdev, u32 offset, u32 = value) +{ + /* TODO */ +} + +static inline void rm_queue_bulk_read(struct rm_device *rdev, u32 offset, + u32 *value, u32 size) +{ + /* TODO */ +} + +static inline void rm_queue_bulk_write(struct rm_device *rdev, u32 offset, + u32 *value, u32 size) +{ + /* TODO */ +} + +static inline u32 rm_queue_get_cidx(struct rm_device *rdev, enum rm_queue_= type type) +{ + u32 off; + + if (type =3D=3D RM_QUEUE_SQ) + off =3D offsetof(struct rm_queue_header, sq_cidx); + else + off =3D offsetof(struct rm_queue_header, cq_cidx); + + return rm_queue_read(rdev, off); +} + +static inline void rm_queue_set_cidx(struct rm_device *rdev, enum rm_queue= _type type, + u32 value) +{ + u32 off; + + if (type =3D=3D RM_QUEUE_SQ) + off =3D offsetof(struct rm_queue_header, sq_cidx); + else + off =3D offsetof(struct rm_queue_header, cq_cidx); + + rm_queue_write(rdev, off, value); +} + +static inline u32 rm_queue_get_pidx(struct rm_device *rdev, enum rm_queue_= type type) +{ + if (type =3D=3D RM_QUEUE_SQ) + return rm_io_read(rdev, RM_IO_SQ_PIDX_OFF); + else + return rm_io_read(rdev, RM_IO_CQ_PIDX_OFF); +} + +static inline int rm_queue_set_pidx(struct rm_device *rdev, + enum rm_queue_type type, u32 value) +{ + if (type =3D=3D RM_QUEUE_SQ) + return rm_io_write(rdev, RM_IO_SQ_PIDX_OFF, value); + else + return rm_io_write(rdev, RM_IO_CQ_PIDX_OFF, value); +} + +static inline u32 rm_queue_get_sq_slot_offset(struct rm_device *rdev) +{ + u32 index; + + if ((rdev->sq.pidx - rdev->sq.cidx) >=3D rdev->queue_size) + return RM_INVALID_SLOT; + + index =3D rdev->sq.pidx & (rdev->queue_size - 1); + return rdev->sq.offset + RM_CMD_SQ_SLOT_SIZE * index; +} + +static inline u32 rm_queue_get_cq_slot_offset(struct rm_device *rdev) +{ + u32 index; + + index =3D rdev->cq.cidx & (rdev->queue_size - 1); + return rdev->cq.offset + RM_CMD_CQ_SLOT_SIZE * index; +} + +static int rm_queue_submit_cmd(struct rm_cmd *cmd) +{ + struct versal_pci_device *vdev =3D cmd->rdev->vdev; + struct rm_device *rdev =3D cmd->rdev; + u32 offset; + int ret; + + guard(mutex)(&rdev->queue); + + offset =3D rm_queue_get_sq_slot_offset(rdev); + if (!offset) { + vdev_err(vdev, "No SQ slot available"); + return -ENOSPC; + } + + rm_queue_bulk_write(rdev, offset, (u32 *)&cmd->sq_msg, + sizeof(cmd->sq_msg)); + + ret =3D rm_queue_set_pidx(rdev, RM_QUEUE_SQ, ++rdev->sq.pidx); + if (ret) { + vdev_err(vdev, "Failed to update PIDX, ret %d", ret); + return ret; + } + + list_add_tail(&cmd->list, &rdev->submitted_cmds); + return ret; +} + +void rm_queue_withdraw_cmd(struct rm_cmd *cmd) +{ + guard(mutex)(&cmd->rdev->queue); + list_del(&cmd->list); +} + +static int rm_queue_wait_cmd_timeout(struct rm_cmd *cmd, unsigned long tim= eout) +{ + struct versal_pci_device *vdev =3D cmd->rdev->vdev; + int ret; + + if (wait_for_completion_timeout(&cmd->executed, timeout)) { + ret =3D cmd->cq_msg.data.rcode; + if (!ret) + return 0; + + vdev_err(vdev, "CMD returned with a failure: %d", ret); + return ret; + } + + /* + * each cmds will be cleaned up by complete before it times out. + * if we reach here, the cmd should be cleared and hot reset should + * be issued. + */ + vdev_err(vdev, "cmd timed out, please reset the card"); + rm_queue_withdraw_cmd(cmd); + return -ETIME; +} + +int rm_queue_send_cmd(struct rm_cmd *cmd, unsigned long timeout) +{ + int ret; + + ret =3D rm_queue_submit_cmd(cmd); + if (ret) + return ret; + + return rm_queue_wait_cmd_timeout(cmd, timeout); +} + +static int rm_process_msg(struct rm_device *rdev) +{ + struct versal_pci_device *vdev =3D rdev->vdev; + struct rm_cmd *cmd, *next; + struct rm_cmd_cq_hdr header; + u32 offset; + + offset =3D rm_queue_get_cq_slot_offset(rdev); + if (!offset) { + vdev_err(vdev, "Invalid CQ offset"); + return -EINVAL; + } + + rm_queue_bulk_read(rdev, offset, (u32 *)&header, sizeof(header)); + + list_for_each_entry_safe(cmd, next, &rdev->submitted_cmds, list) { + u32 value =3D 0; + + if (cmd->sq_msg.hdr.id !=3D header.id) + continue; + + rm_queue_bulk_read(rdev, offset + sizeof(cmd->cq_msg.hdr), + (u32 *)&cmd->cq_msg.data, + sizeof(cmd->cq_msg.data)); + + rm_queue_write(rdev, offset, value); + + list_del(&cmd->list); + complete(&cmd->executed); + return 0; + } + + vdev_err(vdev, "Unknown cmd ID %d found in CQ", header.id); + return -EFAULT; +} + +static void rm_check_msg(struct work_struct *w) +{ + struct rm_device *rdev =3D to_rdev_msg_monitor(w); + int ret; + + guard(mutex)(&rdev->queue); + + rdev->sq.cidx =3D rm_queue_get_cidx(rdev, RM_QUEUE_SQ); + rdev->cq.pidx =3D rm_queue_get_pidx(rdev, RM_QUEUE_CQ); + + while (rdev->cq.cidx < rdev->cq.pidx) { + ret =3D rm_process_msg(rdev); + if (ret) + break; + + rdev->cq.cidx++; + + rm_queue_set_cidx(rdev, RM_QUEUE_CQ, rdev->cq.cidx); + } +} + +static void rm_sched_work(struct timer_list *t) +{ + struct rm_device *rdev =3D to_rdev_msg_timer(t); + + /* Schedule a work in the general workqueue */ + schedule_work(&rdev->msg_monitor); + /* Periodic timer */ + mod_timer(&rdev->msg_timer, jiffies + RM_COMPLETION_TIMER); +} + +void rm_queue_fini(struct rm_device *rdev) +{ + timer_delete_sync(&rdev->msg_timer); + cancel_work_sync(&rdev->msg_monitor); +} + +int rm_queue_init(struct rm_device *rdev) +{ + struct versal_pci_device *vdev =3D rdev->vdev; + struct rm_queue_header header =3D {0}; + int ret; + + INIT_LIST_HEAD(&rdev->submitted_cmds); + ret =3D devm_mutex_init(&vdev->pdev->dev, &rdev->queue); + if (ret) + return ret; + + rm_queue_bulk_read(rdev, RM_HDR_OFF, (u32 *)&header, sizeof(header)); + + if (header.magic !=3D RM_QUEUE_HDR_MAGIC_NUM) { + vdev_err(vdev, "Invalid RM queue header"); + return -ENODEV; + } + + if (!header.version) { + vdev_err(vdev, "Invalid RM queue header"); + return -ENODEV; + } + + sema_init(&rdev->sq.data_lock, 1); + sema_init(&rdev->cq.data_lock, 1); + rdev->queue_size =3D header.size; + rdev->sq.offset =3D header.sq_off; + rdev->cq.offset =3D header.cq_off; + rdev->sq.type =3D RM_QUEUE_SQ; + rdev->cq.type =3D RM_QUEUE_CQ; + rdev->sq.data_size =3D rdev->queue_buffer_size - RM_CMD_CQ_BUFFER_SIZE; + rdev->cq.data_size =3D RM_CMD_CQ_BUFFER_SIZE; + rdev->sq.data_offset =3D rdev->queue_buffer_start + + RM_CMD_CQ_BUFFER_OFFSET + RM_CMD_CQ_BUFFER_SIZE; + rdev->cq.data_offset =3D rdev->queue_buffer_start + + RM_CMD_CQ_BUFFER_OFFSET; + rdev->sq.cidx =3D header.sq_cidx; + rdev->cq.cidx =3D header.cq_cidx; + + rdev->sq.pidx =3D rm_queue_get_pidx(rdev, RM_QUEUE_SQ); + rdev->cq.pidx =3D rm_queue_get_pidx(rdev, RM_QUEUE_CQ); + + if (rdev->cq.cidx !=3D rdev->cq.pidx) { + vdev_warn(vdev, "Clearing stale completions"); + rdev->cq.cidx =3D rdev->cq.pidx; + rm_queue_set_cidx(rdev, RM_QUEUE_CQ, rdev->cq.cidx); + } + + /* Create and schedule timer to do recurring work */ + INIT_WORK(&rdev->msg_monitor, &rm_check_msg); + timer_setup(&rdev->msg_timer, &rm_sched_work, 0); + mod_timer(&rdev->msg_timer, jiffies + RM_COMPLETION_TIMER); + + return 0; +} diff --git a/drivers/accel/amd_vpci/versal-pci-rm-queue.h b/drivers/accel/a= md_vpci/versal-pci-rm-queue.h new file mode 100644 index 000000000000..80e587b5a12a --- /dev/null +++ b/drivers/accel/amd_vpci/versal-pci-rm-queue.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Driver for Versal PCIe device + * + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. + */ + +#ifndef __RM_QUEUE_H +#define __RM_QUEUE_H + +struct rm_device; + +/* rm queue hardware setup */ +int rm_queue_init(struct rm_device *rdev); +void rm_queue_fini(struct rm_device *rdev); + +/* rm queue common API */ +int rm_queue_send_cmd(struct rm_cmd *cmd, unsigned long timeout); +void rm_queue_withdraw_cmd(struct rm_cmd *cmd); + +#endif /* __RM_QUEUE_H */ diff --git a/drivers/accel/amd_vpci/versal-pci-rm-service.h b/drivers/accel= /amd_vpci/versal-pci-rm-service.h new file mode 100644 index 000000000000..a16198944e17 --- /dev/null +++ b/drivers/accel/amd_vpci/versal-pci-rm-service.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Driver for Versal PCIe device + * + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. + */ + +#ifndef __RM_SERVICE_H +#define __RM_SERVICE_H + +#define RM_HDR_OFF 0x0 +#define RM_HDR_MAGIC_NUM 0x564D5230 +#define RM_QUEUE_HDR_MAGIC_NUM 0x5847513F +#define RM_PCI_IO_BAR_OFF 0x2010000 +#define RM_PCI_IO_SIZE SZ_4K +#define RM_PCI_SHMEM_BAR_OFF 0x8000000 +#define RM_PCI_SHMEM_SIZE SZ_128M +#define RM_PCI_SHMEM_HDR_SIZE 0x28 + +#define RM_QUEUE_HDR_MAGIC_NUM_OFF 0x0 +#define RM_IO_SQ_PIDX_OFF 0x0 +#define RM_IO_CQ_PIDX_OFF 0x100 + +#define RM_CMD_ID_MIN 1 +#define RM_CMD_ID_MAX (BIT(17) - 1) +#define RM_CMD_SQ_HDR_OPS_MSK GENMASK(15, 0) +#define RM_CMD_SQ_HDR_SIZE_MSK GENMASK(14, 0) +#define RM_CMD_SQ_SLOT_SIZE SZ_512 +#define RM_CMD_CQ_SLOT_SIZE SZ_16 +#define RM_CMD_CQ_BUFFER_SIZE SZ_1M +#define RM_CMD_CQ_BUFFER_OFFSET 0x0 +#define RM_CMD_LOG_PAGE_TYPE_MASK GENMASK(15, 0) +#define RM_CMD_VMR_CONTROL_MSK GENMASK(10, 8) +#define RM_CMD_VMR_CONTROL_PS_MASK BIT(9) + +#define RM_CMD_WAIT_CONFIG_TIMEOUT secs_to_jiffies(10) +#define RM_CMD_WAIT_DOWNLOAD_TIMEOUT secs_to_jiffies(300) + +#define RM_COMPLETION_TIMER (HZ / 10) +#define RM_HEALTH_CHECK_TIMER (HZ) + +#define RM_INVALID_SLOT 0 + +enum rm_queue_opcode { + RM_QUEUE_OP_LOAD_XCLBIN =3D 0x0, + RM_QUEUE_OP_GET_LOG_PAGE =3D 0x8, + RM_QUEUE_OP_LOAD_FW =3D 0xA, + RM_QUEUE_OP_LOAD_APU_FW =3D 0xD, + RM_QUEUE_OP_VMR_CONTROL =3D 0xE, + RM_QUEUE_OP_IDENTIFY =3D 0x202, +}; + +struct rm_cmd_sq_hdr { + __u16 opcode; + __u16 msg_size; + __u16 id; + __u16 reserved; +} __packed; + +struct rm_cmd_cq_hdr { + __u16 id; + __u16 reserved; +} __packed; + +struct rm_cmd_sq_bin { + __u64 address; + __u32 size; + __u32 reserved1; + __u32 reserved2; + __u32 reserved3; + __u64 reserved4; +} __packed; + +struct rm_cmd_sq_log_page { + __u64 address; + __u32 size; + __u32 reserved1; + __u32 type; + __u32 reserved2; +} __packed; + +struct rm_cmd_sq_ctrl { + __u32 status; +} __packed; + +struct rm_cmd_sq_data { + union { + struct rm_cmd_sq_log_page page; + struct rm_cmd_sq_bin bin; + struct rm_cmd_sq_ctrl ctrl; + }; +} __packed; + +struct rm_cmd_cq_identify { + __u16 major; + __u16 minor; + __u32 reserved; +} __packed; + +struct rm_cmd_cq_log_page { + __u32 len; + __u32 reserved; +} __packed; + +struct rm_cmd_cq_control { + __u16 status; + __u16 reserved1; + __u32 reserved2; +} __packed; + +struct rm_cmd_cq_data { + union { + struct rm_cmd_cq_identify identify; + struct rm_cmd_cq_log_page page; + struct rm_cmd_cq_control ctrl; + __u32 reserved[2]; + }; + __u32 rcode; +} __packed; + +struct rm_cmd_sq_msg { + struct rm_cmd_sq_hdr hdr; + struct rm_cmd_sq_data data; +} __packed; + +struct rm_cmd_cq_msg { + struct rm_cmd_cq_hdr hdr; + struct rm_cmd_cq_data data; +} __packed; + +struct rm_cmd { + struct rm_device *rdev; + struct list_head list; + struct completion executed; + struct rm_cmd_sq_msg sq_msg; + struct rm_cmd_cq_msg cq_msg; + enum rm_queue_opcode opcode; + __u8 *buffer; + ssize_t size; +}; + +enum rm_queue_type { + RM_QUEUE_SQ, + RM_QUEUE_CQ +}; + +enum rm_cmd_log_page_type { + RM_CMD_LOG_PAGE_AXI_TRIP_STATUS =3D 0x0, + RM_CMD_LOG_PAGE_FW_ID =3D 0xA, +}; + +struct rm_queue { + enum rm_queue_type type; + __u32 pidx; + __u32 cidx; + __u32 offset; + __u32 data_offset; + __u32 data_size; + struct semaphore data_lock; +}; + +struct rm_queue_header { + __u32 magic; + __u32 version; + __u32 size; + __u32 sq_off; + __u32 sq_slot_size; + __u32 cq_off; + __u32 sq_cidx; + __u32 cq_cidx; +}; + +struct rm_header { + __u32 magic; + __u32 queue_base; + __u32 queue_size; + __u32 status_off; + __u32 status_len; + __u32 log_index; + __u32 log_off; + __u32 log_size; + __u32 data_start; + __u32 data_end; +}; + +struct rm_device { + struct versal_pci_device *vdev; + + struct rm_header rm_metadata; + __u32 queue_buffer_start; + __u32 queue_buffer_size; + __u32 queue_base; + + /* Lock to queue access */ + struct mutex queue; + struct rm_queue sq; + struct rm_queue cq; + __u32 queue_size; + + struct timer_list msg_timer; + struct work_struct msg_monitor; + struct timer_list health_timer; + struct work_struct health_monitor; + struct list_head submitted_cmds; + + __u32 firewall_tripped; +}; + +#endif /* __RM_SERVICE_H */ diff --git a/drivers/accel/amd_vpci/versal-pci.h b/drivers/accel/amd_vpci/v= ersal-pci.h index 890da1d6bcc9..be69dda8da73 100644 --- a/drivers/accel/amd_vpci/versal-pci.h +++ b/drivers/accel/amd_vpci/versal-pci.h @@ -26,6 +26,7 @@ dev_dbg(&(vdev)->pdev->dev, fmt, ##args) =20 struct versal_pci_device; +struct rm_cmd; =20 struct axlf_header { __u64 length; --=20 2.34.1 From nobody Sat Feb 7 08:13:38 2026 Received: from BL0PR03CU003.outbound.protection.outlook.com (mail-eastusazon11012030.outbound.protection.outlook.com [52.101.53.30]) (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 64EE12848BE for ; Mon, 26 Jan 2026 19:28:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.53.30 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769455718; cv=fail; b=YZQLarb9gLAba3FxSF/ofiTN0cUksCkyn9qZRRTDSGV0F8cXQx+ZST3i5z0kLNi5hj4R+KCxgfKxGu0ug1ORL1p59K81ENWyjTVBfF2sP2aIAcexfIgcraytCZdxjS643gq6aLRxHcvOjdBhFqtKQiq2wHkb3qAe77N1wPDmFYk= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769455718; c=relaxed/simple; bh=8ToZzs2ETpMVG3eahRfUj4DlauhnO/NuxPLzCndaTIE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jY1wlCwDS7NpU5ac9ySuR5GsqxP4uYISTDCTlTXij9WsVmSc+fO49yb9KQYw+6lGTm0bYadf2dhUk3WeFXeuztvbqnG6B5CZ+PuP5HN+48nb9nQ0bJandttJI07mo88zwK+HAOvKEUVUF4sgKWWJ6mHg8/E+ZzDHrLMcLydRwPY= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=NmjRpFWo; arc=fail smtp.client-ip=52.101.53.30 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="NmjRpFWo" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ag0WQDxyrKSPD1y1j0nwdpsa/AnlT6J8+0ByJg51IuLl5pwDkiQwt2dbs8PBsc+9oNYT2F9Mz8s6I1AC1MG8CyP46hSEF9P3SnWWkx+UBCIYlRp6Y6/d+StTWgbRStpLAzPzXnD3s9MUWDJGcA9PdguwHL1YjCYiZrLe0R+LxWJhrZfxKoDZzYM5ABrLiqKmxcFnOntwK2hluY9MZ/mLuZdArJZtonEVbFgMzDzapr5KbQ5Bt8mHE0Rij9Vuo/KDs2BXOGCcf2K0XvmYScKhd/jhSoyUHYNA9SY9xS9dJDSux7xRnXIEACBS0e54hNoGFbnLzg3TTgcUy1dv6IPH1w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=3VJPLQUi7csC26ppEbottIPkqMXLTl8vNpmKiOK3pYk=; b=eLZWalCiMwejw21xF1FwwYpbgbY5s6KcJjeJi0X3IzTRZVdHh2QAuapl/PVrwADUGdOtueKJk4TM/HXRwvXgPYnEBhutoTAYLFNHOiuaRtdB+xiVAg92peCt2GulvoROnv7xy67y8vAk6SZOcuG/eSVWDEl4Rwq7MLoCVzDEaOEISrFes28Q7NrJogQX9E2SKONxSvdZRKWowDkchte+AEIOjLraJA8KaS+6kxQss+MHfqd1PvcYDbN8lz+A0FM+zLjkvGRZ7R078BOHAUVgrb5kSD8J8Zehk6NLpljwjyqt6yDFY/9hFGyfCcRTgKC0JtoTe6K0B50CeOFjw5Wvew== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=3VJPLQUi7csC26ppEbottIPkqMXLTl8vNpmKiOK3pYk=; b=NmjRpFWoAqlkQvm7iLh4aSDqmT7XjGQoXxAAVJkLm+JLPy5Bq03TJLLvpzv7pDVu28R+E+XWqAmr5cT60vGQgbMdzWB1poCp5XL/o4cu+Wfh6IBTGZ3JVnacCcUHfMMi5/FM9ZePa6Jpn7vwqfMyPrlO5/qex+k/9vtrvWtAnzM= Received: from BL1PR13CA0168.namprd13.prod.outlook.com (2603:10b6:208:2bd::23) by SA3PR12MB9160.namprd12.prod.outlook.com (2603:10b6:806:399::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9520.11; Mon, 26 Jan 2026 19:28:22 +0000 Received: from MN1PEPF0000F0E1.namprd04.prod.outlook.com (2603:10b6:208:2bd:cafe::e9) by BL1PR13CA0168.outlook.office365.com (2603:10b6:208:2bd::23) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9564.7 via Frontend Transport; Mon, 26 Jan 2026 19:28:14 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=satlexmb08.amd.com; pr=C Received: from satlexmb08.amd.com (165.204.84.17) by MN1PEPF0000F0E1.mail.protection.outlook.com (10.167.242.39) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9564.3 via Frontend Transport; Mon, 26 Jan 2026 19:28:21 +0000 Received: from satlexmb08.amd.com (10.181.42.217) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 26 Jan 2026 13:28:02 -0600 Received: from xsjdavidzha51.xilinx.com (10.180.168.240) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Mon, 26 Jan 2026 13:28:02 -0600 From: David Zhang To: , , , , CC: , , , , Nishad Saraf Subject: [PATCH V2 4/5] accel/amd_vpci: Add Remote Management (RM) queue service APIs Date: Mon, 26 Jan 2026 11:27:31 -0800 Message-ID: <20260126192732.1507084-5-yidong.zhang@amd.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260126192732.1507084-1-yidong.zhang@amd.com> References: <20260126192732.1507084-1-yidong.zhang@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: MN1PEPF0000F0E1:EE_|SA3PR12MB9160:EE_ X-MS-Office365-Filtering-Correlation-Id: ff7e5a65-c82c-4c76-e62f-08de5d1110ee X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|36860700013|1800799024|82310400026; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?PA47OLVZdk430wVxk9kh8Ub2aXPW80TlWHgUDo6iyIL0n71jDH1Wi2YzUYSj?= =?us-ascii?Q?tgQZLAaCFT6jK0d8f7GaqQJ72KG4D/hGvvF5E75XG0uSaQNiMlWMfcoi5Hhp?= =?us-ascii?Q?90SlKAxl6Px9XCTDEY+3gdWaYgEI9nctYz765DYDmGa63N+Kc3jnNtvSXJks?= =?us-ascii?Q?K6oblROul8qBZHKDRp2lw2DRPdWjnC+kOVXCPjG4YYnI6BVNdNlHqfqVnUgA?= =?us-ascii?Q?o3T5dVn1azSmj/TvzeqtcRmhQNt5koG+odS+ha1K1Pug0K7g3vZGOXpOwUFr?= =?us-ascii?Q?0S7xvHJaST8aBSjr8oakZZvLKEqBjY4QfgVJG30iHKOmKObW1ltPHb0qoixx?= =?us-ascii?Q?Ls0XBpU0EAUHjK/Y0i+I2FD2nF5CfqlDNhYdzPTC+AcgS6nxzalGyEsE2NoT?= =?us-ascii?Q?utpnS9b7NzKoFwyG8cYCZgXt5P+MewExoQFwURERA7ulC1uJ3scesr3R8qRl?= =?us-ascii?Q?hp1dAS/wWyyGMyHIBWtMkrBDgohidEpqjepqPBxR2GHpRgKFbYS8LgeLtR0+?= =?us-ascii?Q?HDlwIuT/pfHNm2TYtYZwnXN1KhsXwy75UrckJ39DuCyLZba5Vh4wXFmWTKbW?= =?us-ascii?Q?YCpbERSCZGVrTaaSsfAWMqsRj2fw6w08IALf2h9uTcGPuJ6qwfMgGREQ1oVT?= =?us-ascii?Q?Hyds8EYq9hFbKncJjWoHifiCx4OJ8d+suRLa/HNYO4wZAlqLQtyAWFlCMc6T?= =?us-ascii?Q?73CHzuMfbkwuhLE2JH/zr1GUC7a/Um9NX3FOcNJQTjOSVoPc274AKlWIhCRF?= =?us-ascii?Q?lOrUNd55WinP2yzQPV75/63vtPN+JVZ78aUH+EKw1DTq9WZ4QbfAyzTD2EkA?= =?us-ascii?Q?YOSPoYGYdA41rArDr4JulYTtzcAM/LEojO19bWwXMzm+coraRZ1mdOH6Xvbz?= =?us-ascii?Q?1i8braBLeOuk2KDtAsmriuQDemPYMs8OnYi+JEAJ512dER7MUiqlIYsfm1C6?= =?us-ascii?Q?sl+RRJVYzEMlUPrB60i1pmIpaTyCoCUoZauMSktMjh41xCU8Rw9/Lh2YKddR?= =?us-ascii?Q?fiXr/bkrinqVQqcMdPSVQMRL8cZCZAd4aWPSlEyYE6E+irG6DQXF/7Fzhy+Q?= =?us-ascii?Q?Imd0caxo6MqwyMa7CSexVf6GZMApsDKouDlSgD0hmJJw+DKjPMkXymEQ0xMF?= =?us-ascii?Q?PNa4LP4lmIlJWzm94flqziuCnoAURkDKtbUFTccWfDuCLbnhlqlUtpe+gfPE?= =?us-ascii?Q?A0l+mi9w+lKS8Tvdfd7JedPNyp8XYLGEPXHKT44ANp3Uy2c5vnrLMVIsPvtN?= =?us-ascii?Q?6IPGOTrcywGJlq5gxGPoNPD/TJ/Tpj8ohw8cmFxS3OjCPgFlHPwRMxEirI38?= =?us-ascii?Q?eF1/XNUc3l677F26TIZGA2krOOLEy21ss9Yebzf4pWkFbnviBcRpTdL6he8o?= =?us-ascii?Q?fmbf//TAOe8/iyo84PmPn0F66NMANh2uzp761wqLNSwyfR9HkqeunZ0+Q7bw?= =?us-ascii?Q?PlZzoHuwmkwa1PtQcsOW4hQdDi2CHqNdNku1X12tCKzI7/Fw7H80O3sIhs5/?= =?us-ascii?Q?LZqrzuKCjrJGMiwZ1Zgs+2kyejMf29nylbZzfupp6H3kEj0mHHlA0cQYUYKk?= =?us-ascii?Q?FYeehAruqf4eSQ0RsZMZPTqcxjdMJ5V8ErC4Ip3C6shwdT2fV3uaG3R/6XV8?= =?us-ascii?Q?aAhJbruXnUGBThiXm2/cWfTy72ptuGU7xAwKDezNBJXS/mM1e+nQEfKAJJSK?= =?us-ascii?Q?cwf1ng=3D=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:satlexmb08.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230040)(376014)(36860700013)(1800799024)(82310400026);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jan 2026 19:28:21.2750 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: ff7e5a65-c82c-4c76-e62f-08de5d1110ee X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[satlexmb08.amd.com] X-MS-Exchange-CrossTenant-AuthSource: MN1PEPF0000F0E1.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA3PR12MB9160 Content-Type: text/plain; charset="utf-8" This patch introduces a set of APIs for allowing the PCIe driver submit commands, transfer binary payloads and retrieve firmware metadata. Key features: - RM queue command APIs: - create and destroy RM queue commands - Initialized command data payloads - Send and poll for command completion - Service-level operations: - Retrieve firmware ID - Program accelerator and APU firmware images - Periodic health monitoring Co-developed-by: Nishad Saraf Signed-off-by: Nishad Saraf Signed-off-by: David Zhang --- drivers/accel/amd_vpci/Makefile | 3 +- drivers/accel/amd_vpci/versal-pci-main.c | 43 +- drivers/accel/amd_vpci/versal-pci-rm-queue.c | 14 +- .../accel/amd_vpci/versal-pci-rm-service.c | 497 ++++++++++++++++++ .../accel/amd_vpci/versal-pci-rm-service.h | 20 + drivers/accel/amd_vpci/versal-pci.h | 1 + 6 files changed, 567 insertions(+), 11 deletions(-) create mode 100644 drivers/accel/amd_vpci/versal-pci-rm-service.c diff --git a/drivers/accel/amd_vpci/Makefile b/drivers/accel/amd_vpci/Makef= ile index 9e4e56ac2dee..bacd305783dd 100644 --- a/drivers/accel/amd_vpci/Makefile +++ b/drivers/accel/amd_vpci/Makefile @@ -4,4 +4,5 @@ obj-$(CONFIG_DRM_ACCEL_AMD_VPCI) :=3D versal-pci.o =20 versal-pci-y :=3D \ versal-pci-main.o \ - versal-pci-rm-queue.o + versal-pci-rm-queue.o \ + versal-pci-rm-service.o diff --git a/drivers/accel/amd_vpci/versal-pci-main.c b/drivers/accel/amd_v= pci/versal-pci-main.c index 36f88d5aee95..f8d32f9c0e0c 100644 --- a/drivers/accel/amd_vpci/versal-pci-main.c +++ b/drivers/accel/amd_vpci/versal-pci-main.c @@ -8,6 +8,8 @@ #include =20 #include "versal-pci.h" +#include "versal-pci-rm-service.h" +#include "versal-pci-rm-queue.h" =20 #define DRV_NAME "amd-versal-pci" =20 @@ -21,6 +23,29 @@ static inline u32 versal_pci_devid(struct versal_pci_dev= ice *vdev) PCI_DEVID(vdev->pdev->bus->number, vdev->pdev->devfn)); } =20 +static int versal_pci_upload_fw(struct versal_pci_device *vdev, + enum rm_queue_opcode opcode, + const char *data, + size_t size) +{ + struct rm_cmd *cmd; + int ret; + + ret =3D rm_queue_create_cmd(vdev->rdev, opcode, &cmd); + if (ret) + return ret; + + ret =3D rm_queue_data_init(cmd, data, size); + if (ret) + goto done; + + ret =3D rm_queue_send_cmd(cmd, RM_CMD_WAIT_DOWNLOAD_TIMEOUT); + +done: + rm_queue_destroy_cmd(cmd); + return ret; +} + static int versal_pci_load_shell(struct versal_pci_device *vdev, char *fw_= name) { const struct firmware *fw; @@ -57,7 +82,8 @@ static int versal_pci_load_shell(struct versal_pci_device= *vdev, char *fw_name) goto release_firmware; } =20 - /* TODO upload fw to card */ + ret =3D versal_pci_upload_fw(vdev, RM_QUEUE_OP_LOAD_FW, + (char *)xsabin, xsabin->header.length); if (ret) { vdev_err(vdev, "failed to load xsabin %s : %d", fw_name, ret); goto release_firmware; @@ -159,6 +185,7 @@ static void versal_pci_device_teardown(struct versal_pc= i_device *vdev) { versal_pci_cfs_fini(&vdev->cfs_subsys); versal_pci_fw_fini(vdev); + versal_pci_rm_fini(vdev->rdev); } =20 static int versal_pci_uuid_parse(struct versal_pci_device *vdev, uuid_t *u= uid) @@ -187,7 +214,11 @@ static int versal_pci_fw_init(struct versal_pci_device= *vdev) { int ret; =20 - /* TODO request compatible fw_id from card */ + ret =3D rm_queue_get_fw_id(vdev->rdev); + if (ret) { + vdev_warn(vdev, "Failed to get fw_id"); + return -EINVAL; + } =20 ret =3D versal_pci_uuid_parse(vdev, &vdev->intf_uuid); =20 @@ -198,6 +229,13 @@ static int versal_pci_device_setup(struct versal_pci_d= evice *vdev) { int ret; =20 + vdev->rdev =3D versal_pci_rm_init(vdev); + if (IS_ERR(vdev->rdev)) { + ret =3D PTR_ERR(vdev->rdev); + vdev_err(vdev, "Failed to init remote queue, err %d", ret); + return ret; + } + ret =3D versal_pci_fw_init(vdev); if (ret) { vdev_err(vdev, "Failed to init fw, err %d", ret); @@ -213,6 +251,7 @@ static int versal_pci_device_setup(struct versal_pci_de= vice *vdev) return 0; =20 comm_chan_fini: + versal_pci_rm_fini(vdev->rdev); versal_pci_fw_fini(vdev); =20 return ret; diff --git a/drivers/accel/amd_vpci/versal-pci-rm-queue.c b/drivers/accel/a= md_vpci/versal-pci-rm-queue.c index eeda07065487..97e5911f18ed 100644 --- a/drivers/accel/amd_vpci/versal-pci-rm-queue.c +++ b/drivers/accel/amd_vpci/versal-pci-rm-queue.c @@ -23,37 +23,35 @@ static inline struct rm_device *to_rdev_msg_timer(struc= t timer_list *t) =20 static inline u32 rm_io_read(struct rm_device *rdev, u32 offset) { - /* TODO */ - return 0; + return rm_reg_read(rdev, RM_PCI_IO_BAR_OFF + offset); } =20 static inline int rm_io_write(struct rm_device *rdev, u32 offset, u32 valu= e) { - /* TODO */ + rm_reg_write(rdev, RM_PCI_IO_BAR_OFF + offset, value); return 0; } =20 static inline u32 rm_queue_read(struct rm_device *rdev, u32 offset) { - /* TODO */ - return 0; + return rm_reg_read(rdev, RM_PCI_SHMEM_BAR_OFF + rdev->queue_base + offset= ); } =20 static inline void rm_queue_write(struct rm_device *rdev, u32 offset, u32 = value) { - /* TODO */ + rm_reg_write(rdev, RM_PCI_SHMEM_BAR_OFF + rdev->queue_base + offset, valu= e); } =20 static inline void rm_queue_bulk_read(struct rm_device *rdev, u32 offset, u32 *value, u32 size) { - /* TODO */ + rm_bulk_reg_read(rdev, RM_PCI_SHMEM_BAR_OFF + rdev->queue_base + offset, = value, size); } =20 static inline void rm_queue_bulk_write(struct rm_device *rdev, u32 offset, u32 *value, u32 size) { - /* TODO */ + rm_bulk_reg_write(rdev, RM_PCI_SHMEM_BAR_OFF + rdev->queue_base + offset,= value, size); } =20 static inline u32 rm_queue_get_cidx(struct rm_device *rdev, enum rm_queue_= type type) diff --git a/drivers/accel/amd_vpci/versal-pci-rm-service.c b/drivers/accel= /amd_vpci/versal-pci-rm-service.c new file mode 100644 index 000000000000..974e5ed3a80e --- /dev/null +++ b/drivers/accel/amd_vpci/versal-pci-rm-service.c @@ -0,0 +1,497 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Versal PCIe device + * + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. + */ + +#include +#include +#include + +#include "versal-pci.h" +#include "versal-pci-rm-service.h" +#include "versal-pci-rm-queue.h" + +static DEFINE_IDA(rm_cmd_ids); + +static void rm_uninstall_health_monitor(struct rm_device *rdev); + +static inline struct rm_device *to_rdev_health_monitor(struct work_struct = *w) +{ + return container_of(w, struct rm_device, health_monitor); +} + +static inline struct rm_device *to_rdev_health_timer(struct timer_list *t) +{ + return container_of(t, struct rm_device, health_timer); +} + +u32 rm_reg_read(struct rm_device *rdev, u32 offset) +{ + return readl(rdev->vdev->io_regs + offset); +} + +void rm_reg_write(struct rm_device *rdev, u32 offset, const u32 value) +{ + writel(value, rdev->vdev->io_regs + offset); +} + +void rm_bulk_reg_read(struct rm_device *rdev, u32 offset, u32 *value, size= _t size) +{ + void __iomem *src =3D rdev->vdev->io_regs + offset; + void *dst =3D (void *)value; + + memcpy_fromio(dst, src, size); + /* Barrier after reading data from device */ + rmb(); +} + +void rm_bulk_reg_write(struct rm_device *rdev, u32 offset, const void *val= ue, size_t size) +{ + void __iomem *dst =3D rdev->vdev->io_regs + offset; + + memcpy_toio(dst, value, size); + /* Barrier after writing data to device */ + wmb(); +} + +static inline u32 rm_shmem_read(struct rm_device *rdev, u32 offset) +{ + return rm_reg_read(rdev, RM_PCI_SHMEM_BAR_OFF + offset); +} + +static inline void rm_shmem_bulk_read(struct rm_device *rdev, u32 offset, + u32 *value, u32 size) +{ + rm_bulk_reg_read(rdev, RM_PCI_SHMEM_BAR_OFF + offset, value, size); +} + +static inline void rm_shmem_bulk_write(struct rm_device *rdev, u32 offset, + const void *value, u32 size) +{ + rm_bulk_reg_write(rdev, RM_PCI_SHMEM_BAR_OFF + offset, value, size); +} + +void rm_queue_destroy_cmd(struct rm_cmd *cmd) +{ + ida_free(&rm_cmd_ids, cmd->sq_msg.hdr.id); + kfree(cmd); +} + +static int rm_queue_copy_response(struct rm_cmd *cmd, void *buffer, ssize_= t len) +{ + struct rm_cmd_cq_log_page *result =3D &cmd->cq_msg.data.page; + u64 off =3D cmd->sq_msg.data.page.address; + + if (!result->len || len < result->len) { + vdev_err(cmd->rdev->vdev, "Invalid response or buffer size"); + return -EINVAL; + } + + rm_shmem_bulk_read(cmd->rdev, off, (u32 *)buffer, result->len); + return 0; +} + +static void rm_queue_payload_fini(struct rm_cmd *cmd) +{ + up(&cmd->rdev->cq.data_lock); +} + +static int rm_queue_payload_init(struct rm_cmd *cmd, + enum rm_cmd_log_page_type type) +{ + struct rm_device *rdev =3D cmd->rdev; + int ret; + + ret =3D down_interruptible(&rdev->cq.data_lock); + if (ret) + return ret; + + cmd->sq_msg.data.page.address =3D rdev->cq.data_offset; + cmd->sq_msg.data.page.size =3D rdev->cq.data_size; + cmd->sq_msg.data.page.reserved1 =3D 0; + cmd->sq_msg.data.page.type =3D FIELD_PREP(RM_CMD_LOG_PAGE_TYPE_MASK, + type); + return 0; +} + +void rm_queue_data_fini(struct rm_cmd *cmd) +{ + up(&cmd->rdev->sq.data_lock); +} + +int rm_queue_data_init(struct rm_cmd *cmd, const char *buffer, ssize_t siz= e) +{ + struct rm_device *rdev =3D cmd->rdev; + int ret; + + if (!size || size > rdev->sq.data_size) { + vdev_err(rdev->vdev, "Unsupported file size"); + return -ENOMEM; + } + + ret =3D down_interruptible(&rdev->sq.data_lock); + if (ret) + return ret; + + rm_shmem_bulk_write(cmd->rdev, rdev->sq.data_offset, buffer, size); + + cmd->sq_msg.data.bin.address =3D rdev->sq.data_offset; + cmd->sq_msg.data.bin.size =3D size; + return 0; +} + +int rm_queue_create_cmd(struct rm_device *rdev, enum rm_queue_opcode opcod= e, + struct rm_cmd **cmd_ptr) +{ + struct rm_cmd *cmd =3D NULL; + int ret, id; + u16 size; + + if (rdev->firewall_tripped) + return -ENODEV; + + cmd =3D kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + cmd->rdev =3D rdev; + + switch (opcode) { + case RM_QUEUE_OP_LOAD_XCLBIN: + fallthrough; + case RM_QUEUE_OP_LOAD_FW: + fallthrough; + case RM_QUEUE_OP_LOAD_APU_FW: + size =3D sizeof(struct rm_cmd_sq_bin); + break; + case RM_QUEUE_OP_GET_LOG_PAGE: + size =3D sizeof(struct rm_cmd_sq_log_page); + break; + case RM_QUEUE_OP_IDENTIFY: + size =3D 0; + break; + case RM_QUEUE_OP_VMR_CONTROL: + size =3D sizeof(struct rm_cmd_sq_ctrl); + break; + default: + vdev_err(rdev->vdev, "Invalid cmd opcode %d", opcode); + ret =3D -EINVAL; + goto error; + } + + cmd->opcode =3D opcode; + cmd->sq_msg.hdr.opcode =3D FIELD_PREP(RM_CMD_SQ_HDR_OPS_MSK, opcode); + cmd->sq_msg.hdr.msg_size =3D FIELD_PREP(RM_CMD_SQ_HDR_SIZE_MSK, size); + + id =3D ida_alloc_range(&rm_cmd_ids, RM_CMD_ID_MIN, RM_CMD_ID_MAX, GFP_KER= NEL); + if (id < 0) { + vdev_err(rdev->vdev, "Failed to alloc cmd ID: %d", id); + ret =3D id; + goto error; + } + cmd->sq_msg.hdr.id =3D id; + + init_completion(&cmd->executed); + + *cmd_ptr =3D cmd; + return 0; +error: + kfree(cmd); + return ret; +} + +static int rm_queue_verify(struct rm_device *rdev) +{ + struct versal_pci_device *vdev =3D rdev->vdev; + struct rm_cmd_cq_identify *result; + struct rm_cmd *cmd; + u32 major, minor; + int ret; + + ret =3D rm_queue_create_cmd(rdev, RM_QUEUE_OP_IDENTIFY, &cmd); + if (ret) + return ret; + + ret =3D rm_queue_send_cmd(cmd, RM_CMD_WAIT_CONFIG_TIMEOUT); + if (ret) + goto error; + + result =3D &cmd->cq_msg.data.identify; + major =3D result->major; + minor =3D result->minor; + vdev_dbg(vdev, "VMR version %d.%d", major, minor); + if (!major) { + vdev_err(vdev, "VMR version is unsupported"); + ret =3D -EOPNOTSUPP; + } + +error: + rm_queue_destroy_cmd(cmd); + return ret; +} + +static int rm_check_apu_status(struct rm_device *rdev, bool *status) +{ + struct rm_cmd_cq_control *result; + struct rm_cmd *cmd; + int ret; + + ret =3D rm_queue_create_cmd(rdev, RM_QUEUE_OP_VMR_CONTROL, &cmd); + if (ret) + return ret; + + ret =3D rm_queue_send_cmd(cmd, RM_CMD_WAIT_CONFIG_TIMEOUT); + if (ret) + goto error; + + result =3D &cmd->cq_msg.data.ctrl; + *status =3D FIELD_GET(RM_CMD_VMR_CONTROL_PS_MASK, result->status); + + rm_queue_destroy_cmd(cmd); + return 0; + +error: + rm_queue_destroy_cmd(cmd); + return ret; +} + +static int rm_download_apu_fw(struct rm_device *rdev, char *data, ssize_t = size) +{ + struct rm_cmd *cmd; + int ret; + + ret =3D rm_queue_create_cmd(rdev, RM_QUEUE_OP_LOAD_APU_FW, &cmd); + if (ret) + return ret; + + ret =3D rm_queue_data_init(cmd, data, size); + if (ret) + goto destroy_cmd; + + ret =3D rm_queue_send_cmd(cmd, RM_CMD_WAIT_DOWNLOAD_TIMEOUT); + +destroy_cmd: + rm_queue_destroy_cmd(cmd); + return ret; +} + +int rm_queue_boot_apu(struct rm_device *rdev) +{ + char *bin =3D "xilinx/xrt-versal-apu.xsabin"; + const struct firmware *fw =3D NULL; + bool status; + int ret; + + ret =3D rm_check_apu_status(rdev, &status); + if (ret) { + vdev_err(rdev->vdev, "Failed to get APU status"); + return ret; + } + + if (status) { + vdev_dbg(rdev->vdev, "APU online. Skipping APU firmware download"); + return 0; + } + + ret =3D request_firmware(&fw, bin, &rdev->vdev->pdev->dev); + if (ret) { + vdev_warn(rdev->vdev, "Request APU firmware %s failed %d", bin, ret); + return ret; + } + + vdev_dbg(rdev->vdev, "Starting... APU firmware download"); + ret =3D rm_download_apu_fw(rdev, (char *)fw->data, fw->size); + vdev_dbg(rdev->vdev, "Finished... APU firmware download %d", ret); + + if (ret) + vdev_err(rdev->vdev, "Failed to download APU firmware, ret:%d", ret); + + release_firmware(fw); + + return ret; +} + +static void rm_check_health(struct work_struct *w) +{ + struct rm_device *rdev =3D to_rdev_health_monitor(w); + u32 max_len =3D PAGE_SIZE; + struct rm_cmd *cmd; + int ret; + + ret =3D rm_queue_create_cmd(rdev, RM_QUEUE_OP_GET_LOG_PAGE, &cmd); + if (ret) + return; + + ret =3D rm_queue_payload_init(cmd, RM_CMD_LOG_PAGE_AXI_TRIP_STATUS); + if (ret) + goto destroy_cmd; + + ret =3D rm_queue_send_cmd(cmd, RM_CMD_WAIT_CONFIG_TIMEOUT); + if (ret =3D=3D -ETIME || ret =3D=3D -EINVAL) + goto payload_fini; + + if (ret) { + u32 log_len =3D cmd->cq_msg.data.page.len; + + if (log_len > max_len) { + vdev_warn(rdev->vdev, "msg size %d is greater than requested %d", + log_len, max_len); + log_len =3D max_len; + } + + if (log_len) { + char *buffer =3D vzalloc(log_len); + + if (!buffer) + goto payload_fini; + + ret =3D rm_queue_copy_response(cmd, buffer, log_len); + if (ret) { + vfree(buffer); + goto payload_fini; + } + + vdev_warn(rdev->vdev, "%s", buffer); + vfree(buffer); + + } else { + vdev_err(rdev->vdev, "firewall check ret%d", ret); + } + + rdev->firewall_tripped =3D 1; + } + +payload_fini: + rm_queue_payload_fini(cmd); +destroy_cmd: + rm_queue_destroy_cmd(cmd); + + vdev_dbg(rdev->vdev, "check result: %d", ret); +} + +static void rm_sched_health_check(struct timer_list *t) +{ + struct rm_device *rdev =3D to_rdev_health_timer(t); + + if (rdev->firewall_tripped) { + vdev_err(rdev->vdev, "Firewall tripped, health check paused. Please rese= t card"); + return; + } + /* Schedule a work in the general workqueue */ + schedule_work(&rdev->health_monitor); + /* Periodic timer */ + mod_timer(&rdev->health_timer, jiffies + RM_HEALTH_CHECK_TIMER); +} + +static void rm_uninstall_health_monitor(struct rm_device *rdev) +{ + timer_delete_sync(&rdev->health_timer); + cancel_work_sync(&rdev->health_monitor); +} + +static void rm_install_health_monitor(struct rm_device *rdev) +{ + INIT_WORK(&rdev->health_monitor, &rm_check_health); + timer_setup(&rdev->health_timer, &rm_sched_health_check, 0); + mod_timer(&rdev->health_timer, jiffies + RM_HEALTH_CHECK_TIMER); +} + +void versal_pci_rm_fini(struct rm_device *rdev) +{ + rm_uninstall_health_monitor(rdev); + rm_queue_fini(rdev); +} + +struct rm_device *versal_pci_rm_init(struct versal_pci_device *vdev) +{ + struct rm_header *header; + struct rm_device *rdev; + u32 status; + int ret; + + rdev =3D devm_kzalloc(&vdev->pdev->dev, sizeof(*rdev), GFP_KERNEL); + if (!rdev) + return ERR_PTR(-ENOMEM); + + rdev->vdev =3D vdev; + header =3D &rdev->rm_metadata; + + rm_shmem_bulk_read(rdev, RM_HDR_OFF, (u32 *)header, sizeof(*header)); + if (header->magic !=3D RM_HDR_MAGIC_NUM) { + vdev_err(vdev, "Invalid RM header 0x%x", header->magic); + ret =3D -ENODEV; + goto err; + } + + status =3D rm_shmem_read(rdev, header->status_off); + if (!status) { + vdev_err(vdev, "RM status is not ready"); + ret =3D -ENODEV; + goto err; + } + + rdev->queue_buffer_size =3D header->data_end - header->data_start + 1; + rdev->queue_buffer_start =3D header->data_start; + rdev->queue_base =3D header->queue_base; + + ret =3D rm_queue_init(rdev); + if (ret) { + vdev_err(vdev, "Failed to init cmd queue, ret %d", ret); + ret =3D -ENODEV; + goto err; + } + + ret =3D rm_queue_verify(rdev); + if (ret) { + vdev_err(vdev, "Failed to verify cmd queue, ret %d", ret); + ret =3D -ENODEV; + goto queue_fini; + } + + ret =3D rm_queue_boot_apu(rdev); + if (ret) { + vdev_err(vdev, "Failed to bringup APU, ret %d", ret); + ret =3D -ENODEV; + goto queue_fini; + } + + rm_install_health_monitor(rdev); + + return rdev; +queue_fini: + rm_queue_fini(rdev); +err: + return ERR_PTR(ret); +} + +int rm_queue_get_fw_id(struct rm_device *rdev) +{ + struct rm_cmd *cmd; + int ret; + + ret =3D rm_queue_create_cmd(rdev, RM_QUEUE_OP_GET_LOG_PAGE, &cmd); + if (ret) + return ret; + + ret =3D rm_queue_payload_init(cmd, RM_CMD_LOG_PAGE_FW_ID); + if (ret) + goto destroy_cmd; + + ret =3D rm_queue_send_cmd(cmd, RM_CMD_WAIT_CONFIG_TIMEOUT); + if (ret) + goto payload_fini; + + ret =3D rm_queue_copy_response(cmd, rdev->vdev->fw_id, sizeof(rdev->vdev-= >fw_id)); + if (ret) + goto payload_fini; + + vdev_info(rdev->vdev, "fw_id %s", rdev->vdev->fw_id); + +payload_fini: + rm_queue_payload_fini(cmd); +destroy_cmd: + rm_queue_destroy_cmd(cmd); + + return ret; +} diff --git a/drivers/accel/amd_vpci/versal-pci-rm-service.h b/drivers/accel= /amd_vpci/versal-pci-rm-service.h index a16198944e17..487c7ae2a4bc 100644 --- a/drivers/accel/amd_vpci/versal-pci-rm-service.h +++ b/drivers/accel/amd_vpci/versal-pci-rm-service.h @@ -206,4 +206,24 @@ struct rm_device { __u32 firewall_tripped; }; =20 +/* rm service init api */ +struct rm_device *versal_pci_rm_init(struct versal_pci_device *vdev); +void versal_pci_rm_fini(struct rm_device *rdev); + +/* rm services APIs */ +int rm_queue_create_cmd(struct rm_device *rdev, enum rm_queue_opcode opcod= e, + struct rm_cmd **cmd_ptr); +void rm_queue_destroy_cmd(struct rm_cmd *cmd); + +int rm_queue_data_init(struct rm_cmd *cmd, const char *buffer, ssize_t siz= e); +void rm_queue_data_fini(struct rm_cmd *cmd); +int rm_queue_get_fw_id(struct rm_device *rdev); +int rm_queue_boot_apu(struct rm_device *rdev); + +/* rm bar register operation APIs */ +u32 rm_reg_read(struct rm_device *rdev, u32 offset); +void rm_reg_write(struct rm_device *rdev, u32 offset, const u32 value); +void rm_bulk_reg_read(struct rm_device *rdev, u32 offset, u32 *value, size= _t size); +void rm_bulk_reg_write(struct rm_device *rdev, u32 offset, const void *val= ue, size_t size); + #endif /* __RM_SERVICE_H */ diff --git a/drivers/accel/amd_vpci/versal-pci.h b/drivers/accel/amd_vpci/v= ersal-pci.h index be69dda8da73..092cac6afa26 100644 --- a/drivers/accel/amd_vpci/versal-pci.h +++ b/drivers/accel/amd_vpci/versal-pci.h @@ -51,6 +51,7 @@ struct fw_info { struct versal_pci_device { struct pci_dev *pdev; =20 + struct rm_device *rdev; struct fw_info fw; =20 void __iomem *io_regs; --=20 2.34.1 From nobody Sat Feb 7 08:13:38 2026 Received: from SN4PR0501CU005.outbound.protection.outlook.com (mail-southcentralusazon11011000.outbound.protection.outlook.com [40.93.194.0]) (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 38924283FC4 for ; Mon, 26 Jan 2026 19:28:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.194.0 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769455715; cv=fail; b=fE7HARipatg6+RTLpUYGMRB4k8lMhVb+s9+pNEtGGQ8ToKyeGhryTf03qoVkMlvNoDNSd1gEddbEMoR4RkwpITgeQc946h0bHuYgGmalS2h4fD/2BuHziM+2pjSb1AjWo5rt1/SYurN0zhGk06pjTEDxmxXxXwVG1F/3e40ysbA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769455715; c=relaxed/simple; bh=KGgp1LelVCGfmpssjz6IUFhbUphHfFy4wcn/UUhW0D4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Gx4YkTJNQcq1YdXvmDsizD8qSCVey7Y217nK/kj5yr+1/kaLupZ2nSVsue/fQmMJJPAlj8kfrDU6G6eUMgIK6LawGyh8tIdiGxOiPAj9wg/6pf73kfIOklw+DoAFpKR0qLnZYWgni1r1Gv4vp6fg12CEtaKZD5YXpkvosGpEtPM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com; spf=fail smtp.mailfrom=amd.com; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b=aLp66i9s; arc=fail smtp.client-ip=40.93.194.0 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amd.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=amd.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amd.com header.i=@amd.com header.b="aLp66i9s" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=glYHpj0/QG38/iHsDbbgUp4dMy2vYVgbpJauhdonkD621OzrRUfq3D3iVuX0dAIDhCp6fiVqeMZlB5Ld30fAwm3jW79E26W/LGdG01o6GDZHrqmBF1kJNlx+IAbnwNL9Ixf14QPb5/sZpPeZZfDpXStAfhIAcNdEVqzLpW2Kt15FBJb2d2mi3b9nM5nVvBtVR4Khtr5FTime8x61zULNRDgDbqocZZ00izP7Eb7fLuyJnTY8KWlxWHvFiED8K3FGbG4CYNZTKJShQKb1v2a/CrMXmHfgxFCWQJpKXTnOG1YdfCydnHNn1nPSt5h34OgulC2Gdmo9A9OHr1H0UZx9oA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=w1QFkkImaolvsdX5EJRjaov+4nRfKO71oyXi2s3hQYM=; b=fyRcH2y0dNmZEa8P3LCdv/lyhzHefNysz0PcnZRdOqq08NnvJ0gs8IrO9ByZNtLrZhhCm6azXKGShAJioTwW1Qxcs2ATeHt3NtB9Rwi6BIDHLO2uWhZwbPLnDqyY4QAdtTcN2zwzOo7gKdyo6MuGVg6bLEK303MlpsVRz75W2XKBfs9+Rw1ZZ4L7rvYacuY0XrxgCou3l+jR6LyG8cj/RaPU3pcCteuGkNeYJ65jk22EnwMs9IimSskEeodT3Ql5wRlEl1F4YjuQc0qowjae5g6hdg7I1sCURD5luPkcRUMum/WmEXLf713aWZkOYKj02yts1+h2SxtCuKI9/b/UOA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=kernel.org smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=w1QFkkImaolvsdX5EJRjaov+4nRfKO71oyXi2s3hQYM=; b=aLp66i9s1S6Dfv4sFRrSG5T5aGVrnEgwExcnhwQeWw+BajzjUtUOnb+zI2j4II8OgMiZKU9SB0OjPchqtN79m6OAQxMTk3O/7Jkb0lOGpLQZKtcFv45soNUCO/fderpkWVVCVFCSGKKKJwJVpFqlkV806iGknQIt8j8b9F3T4Dk= Received: from MN0PR03CA0011.namprd03.prod.outlook.com (2603:10b6:208:52f::13) by DS2PR12MB9592.namprd12.prod.outlook.com (2603:10b6:8:27c::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.15; Mon, 26 Jan 2026 19:28:22 +0000 Received: from MN1PEPF0000F0E3.namprd04.prod.outlook.com (2603:10b6:208:52f:cafe::90) by MN0PR03CA0011.outlook.office365.com (2603:10b6:208:52f::13) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9542.16 via Frontend Transport; Mon, 26 Jan 2026 19:28:11 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=satlexmb08.amd.com; pr=C Received: from satlexmb08.amd.com (165.204.84.17) by MN1PEPF0000F0E3.mail.protection.outlook.com (10.167.242.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9564.3 via Frontend Transport; Mon, 26 Jan 2026 19:28:22 +0000 Received: from satlexmb08.amd.com (10.181.42.217) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.17; Mon, 26 Jan 2026 13:28:03 -0600 Received: from xsjdavidzha51.xilinx.com (10.180.168.240) by satlexmb08.amd.com (10.181.42.217) with Microsoft SMTP Server id 15.2.2562.17 via Frontend Transport; Mon, 26 Jan 2026 13:28:03 -0600 From: David Zhang To: , , , , CC: , , , , Nishad Saraf Subject: [PATCH V2 5/5] accel/amd_vpci: Add communication channel service Date: Mon, 26 Jan 2026 11:27:32 -0800 Message-ID: <20260126192732.1507084-6-yidong.zhang@amd.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260126192732.1507084-1-yidong.zhang@amd.com> References: <20260126192732.1507084-1-yidong.zhang@amd.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: MN1PEPF0000F0E3:EE_|DS2PR12MB9592:EE_ X-MS-Office365-Filtering-Correlation-Id: 088c4a54-a3e4-4d56-9154-08de5d1111a0 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|36860700013|1800799024|376014|82310400026; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?cFpHbQR4RpI7qHWxEDnHCbsfL/+Cz6LiyHCiGo3FgNvgFoHdA//k/b9fpU+l?= =?us-ascii?Q?lUB/Qf1LQZ1Nwg07VUAhQGRY4yh2W8islpve4U+fpwxIH0btmlbWUkQ4RrT/?= =?us-ascii?Q?c6p8SCqw711ApDjY0lmuLTV3IhLMPed9gHlVamdkDsJw61ITqzQDML3iml8C?= =?us-ascii?Q?OebjarZWK1BoSS9dpb57yelTYkX1Yj+bdAPS8LCRWp9xz5+oOrmzvDmNI8qU?= =?us-ascii?Q?5jJx8lG3UsQYRM/J3ee+2tgkSBJBfr388zshI6/dX4X8Er8MBo3w41hjHD1S?= =?us-ascii?Q?TyO81qSuw1SsCfMai5ZDEoOUGj6Xt5zOp+gHcEFLaUUh9Rfji224PzgretQu?= =?us-ascii?Q?abP1Wq4nNAYovel8Vya1iqTdWO+Osn5Bk9tPKG8p7l0vwoGH0j2oPcPHPqDA?= =?us-ascii?Q?DRtWbwuV7UWagJmtmQpWCdkCc0VkA8qAtuIxvyUN8Bi0t6o4QjZGAWC6T7W7?= =?us-ascii?Q?pRPReXQtg5MmAxVZmiJrPCkGKgOWqB8YCuL4EB3nTCE5bonugDoPjwurmScG?= =?us-ascii?Q?bzEdSHDBW+p++0/KNXWVjxNZ4iCBv3WtxVbdoKuyjtT9r2ixli6MsNNTZSfZ?= =?us-ascii?Q?41jniDlQGYGGtp9fMveAd0NwSi6uzuPApN6jydbObgGVl3RrZVJ39yvkzURc?= =?us-ascii?Q?1rtI8A2Z5tjDDSG8pZFzaxLKXaBGooLDM9DYrIWQMkkz9sBXs6q/J3OdluiF?= =?us-ascii?Q?3ULPpsbcoMIGn25xGyfFcEd37lDBOEM6hdkCtJwqsjTGbmJWuAJ9qzVIJsY0?= =?us-ascii?Q?dAW7KiTGR7P7MBGPNoOZYQWZJr5Mz7CaAfwCVGykqXdZ4ELxrRXkTFeee1Rd?= =?us-ascii?Q?qhyJoBqawA6c2TxgcXeLFlnHbIHdeoJzwZh9gxY17ciOufoqaZI1A4NuNIfG?= =?us-ascii?Q?5DCCcq3Jo31P9KA2LHh5gdDWpOP2LjJF7i+a3QOHzc9YT9j6GF6M83RaohaE?= =?us-ascii?Q?VMs//tZdXuOxM7UyZ0rsXnZqX45uuR9ZijIz8JVCwZVXthXwMpYiEjgSVHay?= =?us-ascii?Q?6bMujA5acILpQbjzzJwN3uu8WlfDOOu0Nf/rbh+n2CKFIawMfp6VopAqYRx+?= =?us-ascii?Q?LkNBuhpyqwGExCr1RaPM6t/Sap2MbBabjIPOrR/9G6KbWqR8Z5c2CG5JJyAD?= =?us-ascii?Q?M3g2mNrUMorkyUXsywvQa3mY5GO7LoIKOrkN4hah/ysIxFWgpc4cxMq3BIcr?= =?us-ascii?Q?AFxKBd1RUGEv+1Th09l9M/PfjodfU+xalooPQY+eMczRIO5V/ynkvAz/KsUw?= =?us-ascii?Q?q/70Ay22Det2xmZbzU/t59DvX+jDd/mpKQg1Xtl/clNdIGB2I193FucDsMVp?= =?us-ascii?Q?7gogmwyctKGicZ1LbnTxytJH17y+5fY+nBwwr+wIT+NkkpmBieOrK/UI7ANl?= =?us-ascii?Q?IbzbivSjF9jbss+MFoOa07TTTy0X5pRu/DcE5/ugindPHJIha/TARjimIkRP?= =?us-ascii?Q?3MB+1VFNkQPpWNrsqIYpZou8nGOui2YOYX1tr8X9AClmlgswHhf3OitgGI0F?= =?us-ascii?Q?47xKbYTxv2AS8eIbO2DDklP1J5ncS9wl61rwknAAdJnBptG4P99ZCrPA/fp8?= =?us-ascii?Q?g1UgTkx0F//SrlrMbaI/v0jnb3F1dt7MmtevGC8Ug1U4S71U98Sy0lColSFc?= =?us-ascii?Q?ExnvAK7d1WYvyHnDWY7az9BdzIJ8od3Q4I1E4JXuvdgho9quhWbk4medRizn?= =?us-ascii?Q?UKGLIA=3D=3D?= X-Forefront-Antispam-Report: CIP:165.204.84.17;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:satlexmb08.amd.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230040)(36860700013)(1800799024)(376014)(82310400026);DIR:OUT;SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Jan 2026 19:28:22.4394 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 088c4a54-a3e4-4d56-9154-08de5d1111a0 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d;Ip=[165.204.84.17];Helo=[satlexmb08.amd.com] X-MS-Exchange-CrossTenant-AuthSource: MN1PEPF0000F0E3.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS2PR12MB9592 Content-Type: text/plain; charset="utf-8" This patch introduces the communication channel (comm_chan) service, which enables communication between the management PF driver and the user PF driver. The comm_chan service provides a shared-memory-based command channel located in a BAR-mapped region. The user PF driver issues requests by writing command messages into this region. The management PF driver periodically polls the region and process any pending requests. Supported operations include firmware (xclbin) reloads, where the management PF invokes 'versal_pci_load_xclbin' to reprogram the embedded firmware through the remote management queue service. This service provides the foundation for dynamic firmware updates and other management requests from the user PFs. Co-developed-by: Nishad Saraf Signed-off-by: Nishad Saraf Signed-off-by: David Zhang --- drivers/accel/amd_vpci/Makefile | 3 +- drivers/accel/amd_vpci/versal-pci-comm-chan.c | 295 ++++++++++++++++++ drivers/accel/amd_vpci/versal-pci-comm-chan.h | 14 + drivers/accel/amd_vpci/versal-pci-main.c | 82 ++++- drivers/accel/amd_vpci/versal-pci.h | 6 + 5 files changed, 396 insertions(+), 4 deletions(-) create mode 100644 drivers/accel/amd_vpci/versal-pci-comm-chan.c create mode 100644 drivers/accel/amd_vpci/versal-pci-comm-chan.h diff --git a/drivers/accel/amd_vpci/Makefile b/drivers/accel/amd_vpci/Makef= ile index bacd305783dd..8adfde3490fd 100644 --- a/drivers/accel/amd_vpci/Makefile +++ b/drivers/accel/amd_vpci/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_DRM_ACCEL_AMD_VPCI) :=3D versal-pci.o versal-pci-y :=3D \ versal-pci-main.o \ versal-pci-rm-queue.o \ - versal-pci-rm-service.o + versal-pci-rm-service.o \ + versal-pci-comm-chan.o diff --git a/drivers/accel/amd_vpci/versal-pci-comm-chan.c b/drivers/accel/= amd_vpci/versal-pci-comm-chan.c new file mode 100644 index 000000000000..fef6fff4e501 --- /dev/null +++ b/drivers/accel/amd_vpci/versal-pci-comm-chan.c @@ -0,0 +1,295 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for Versal PCIe device + * + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. + */ + +#include +#include + +#include "versal-pci.h" +#include "versal-pci-comm-chan.h" + +#define COMM_CHAN_PROTOCOL_VERSION 1 +#define COMM_CHAN_PCI_BAR_OFF 0x2000000 +#define COMM_CHAN_TIMER (HZ / 10) +#define COMM_CHAN_DATA_LEN 16 +#define COMM_CHAN_DATA_TYPE_MASK GENMASK(7, 0) +#define COMM_CHAN_DATA_EOM_MASK BIT(31) +#define COMM_CHAN_MSG_END BIT(31) + +#define COMM_CHAN_REG_WRDATA_OFF 0x0 +#define COMM_CHAN_REG_RDDATA_OFF 0x8 +#define COMM_CHAN_REG_STATUS_OFF 0x10 +#define COMM_CHAN_REG_ERROR_OFF 0x14 +#define COMM_CHAN_REG_RIT_OFF 0x1C +#define COMM_CHAN_REG_IS_OFF 0x20 +#define COMM_CHAN_REG_IE_OFF 0x24 +#define COMM_CHAN_REG_CTRL_OFF 0x2C +#define COMM_CHAN_REGS_SIZE SZ_4K + +#define COMM_CHAN_IRQ_DISABLE_ALL 0 +#define COMM_CHAN_IRQ_RECEIVE_ENABLE BIT(1) +#define COMM_CHAN_IRQ_CLEAR_ALL GENMASK(2, 0) +#define COMM_CHAN_CLEAR_FIFO GENMASK(1, 0) +#define COMM_CHAN_RECEIVE_THRESHOLD 15 + +enum comm_chan_req_ops { + COMM_CHAN_REQ_OPS_UNKNOWN =3D 0, + COMM_CHAN_REQ_OPS_HOT_RESET =3D 5, + COMM_CHAN_REQ_OPS_GET_PROTOCOL_VERSION =3D 19, + COMM_CHAN_REQ_OPS_LOAD_XCLBIN_UUID =3D 20, + COMM_CHAN_REQ_OPS_MAX, +}; + +enum comm_chan_msg_type { + COMM_CHAN_MSG_INVALID =3D 0, + COMM_CHAN_MSG_START =3D 2, + COMM_CHAN_MSG_BODY =3D 3, +}; + +enum comm_chan_msg_service_type { + COMM_CHAN_MSG_SRV_RESPONSE =3D BIT(0), + COMM_CHAN_MSG_SRV_REQUEST =3D BIT(1), +}; + +struct comm_chan_hw_msg { + struct { + __u32 type; + __u32 payload_size; + } header; + struct { + __u64 id; + __u32 flags; + __u32 size; + __u32 payload[COMM_CHAN_DATA_LEN - 6]; + } body; +} __packed; + +struct comm_chan_srv_req { + __u64 flags; + __u32 opcode; + __u32 data[]; +}; + +struct comm_chan_srv_ver_resp { + __u32 version; +}; + +struct comm_chan_srv_uuid_resp { + __u32 ret; +}; + +struct comm_chan_msg { + __u64 id; + __u32 flags; + __u32 len; + __u32 bytes_read; + __u32 data[10]; +}; + +struct comm_chan_device { + struct versal_pci_device *vdev; + struct timer_list timer; + struct work_struct work; +}; + +static inline struct comm_chan_device *to_ccdev_work(struct work_struct *w) +{ + return container_of(w, struct comm_chan_device, work); +} + +static inline struct comm_chan_device *to_ccdev_timer(struct timer_list *t) +{ + return container_of(t, struct comm_chan_device, timer); +} + +static inline u32 comm_chan_read(struct comm_chan_device *cdev, u32 offset) +{ + return readl(cdev->vdev->io_regs + COMM_CHAN_PCI_BAR_OFF + offset); +} + +static inline void comm_chan_write(struct comm_chan_device *cdev, u32 offs= et, const u32 value) +{ + writel(value, cdev->vdev->io_regs + COMM_CHAN_PCI_BAR_OFF + offset); +} + +static u32 comm_chan_set_uuid_resp(void *payload, int ret) +{ + struct comm_chan_srv_uuid_resp *resp =3D (struct comm_chan_srv_uuid_resp = *)payload; + u32 resp_len =3D sizeof(*resp); + + resp->ret =3D (u32)ret; + + return resp_len; +} + +static u32 comm_chan_set_protocol_resp(void *payload) +{ + struct comm_chan_srv_ver_resp *resp =3D (struct comm_chan_srv_ver_resp *)= payload; + u32 resp_len =3D sizeof(*resp); + + resp->version =3D COMM_CHAN_PROTOCOL_VERSION; + + return resp_len; +} + +static void comm_chan_write_response(struct comm_chan_device *ccdev, + struct comm_chan_hw_msg *response, + u64 msg_id, u32 size) +{ + response->header.type =3D COMM_CHAN_MSG_START | COMM_CHAN_MSG_END; + response->header.payload_size =3D size; + + response->body.flags =3D COMM_CHAN_MSG_SRV_RESPONSE; + response->body.size =3D size; + response->body.id =3D msg_id; + + for (int i =3D 0; i < COMM_CHAN_DATA_LEN; i++) + comm_chan_write(ccdev, COMM_CHAN_REG_WRDATA_OFF, ((u32 *)response)[i]); +} + +static void comm_chan_send_response(struct comm_chan_device *ccdev, u64 ms= g_id, int ret) +{ + struct versal_pci_device *vdev =3D ccdev->vdev; + struct comm_chan_hw_msg response =3D {0}; + u32 size; + + vdev_err(vdev, "return response ret: %d", ret); + size =3D comm_chan_set_uuid_resp(response.body.payload, ret); + + comm_chan_write_response(ccdev, &response, msg_id, size); +} + +static void comm_chan_opcode_response(struct comm_chan_device *ccdev, u64 = msg_id, void *payload) +{ + struct comm_chan_srv_req *req =3D (struct comm_chan_srv_req *)payload; + struct versal_pci_device *vdev =3D ccdev->vdev; + struct comm_chan_hw_msg response =3D {0}; + u32 size; + int ret; + + switch (req->opcode) { + case COMM_CHAN_REQ_OPS_GET_PROTOCOL_VERSION: + size =3D comm_chan_set_protocol_resp(response.body.payload); + break; + case COMM_CHAN_REQ_OPS_LOAD_XCLBIN_UUID: + ret =3D versal_pci_load_xclbin(vdev, (uuid_t *)req->data); + size =3D comm_chan_set_uuid_resp(response.body.payload, ret); + break; + default: + vdev_err(vdev, "Unsupported request opcode: %d", req->opcode); + size =3D comm_chan_set_uuid_resp(response.body.payload, -EOPNOTSUPP); + break; + } + + vdev_dbg(vdev, "Response opcode: %d", req->opcode); + comm_chan_write_response(ccdev, &response, msg_id, size); +} + +#define STATUS_IS_READY(status) ((status) & BIT(1)) +#define STATUS_IS_ERROR(status) ((status) & BIT(2)) + +static void comm_chan_check_request(struct work_struct *w) +{ + struct comm_chan_device *ccdev =3D to_ccdev_work(w); + u32 status =3D 0, request[COMM_CHAN_DATA_LEN] =3D {0}; + struct comm_chan_hw_msg *hw_msg; + u8 type, eom; + int i; + + status =3D comm_chan_read(ccdev, COMM_CHAN_REG_IS_OFF); + if (!STATUS_IS_READY(status)) + return; + if (STATUS_IS_ERROR(status)) { + vdev_err(ccdev->vdev, "An error has occurred with comms"); + return; + } + + /* ACK status */ + comm_chan_write(ccdev, COMM_CHAN_REG_IS_OFF, status); + + for (i =3D 0; i < COMM_CHAN_DATA_LEN; i++) + request[i] =3D comm_chan_read(ccdev, COMM_CHAN_REG_RDDATA_OFF); + + hw_msg =3D (struct comm_chan_hw_msg *)request; + type =3D FIELD_GET(COMM_CHAN_DATA_TYPE_MASK, hw_msg->header.type); + eom =3D FIELD_GET(COMM_CHAN_DATA_EOM_MASK, hw_msg->header.type); + + /* + * Only support fixed size 64B messages, therefor every msg should + * have EndOfMsg(eom) as 1. Ignore invalid messages. + */ + if (!eom || type !=3D COMM_CHAN_MSG_START) { + vdev_err(ccdev->vdev, "Unsupported eom 0x%x but type 0x%x", eom, type); + goto enotsupp; + } + + if (hw_msg->body.flags !=3D COMM_CHAN_MSG_SRV_REQUEST) { + vdev_err(ccdev->vdev, "Unsupported service request"); + goto enotsupp; + } + + if (hw_msg->body.size > sizeof(hw_msg->body.payload)) { + vdev_err(ccdev->vdev, "msg is too big: %d", hw_msg->body.size); + goto enotsupp; + } + + /* Now decode and respond appropriately */ + comm_chan_opcode_response(ccdev, hw_msg->body.id, hw_msg->body.payload); + return; + +enotsupp: + comm_chan_send_response(ccdev, hw_msg->body.id, -EOPNOTSUPP); +} + +static void comm_chan_sched_work(struct timer_list *t) +{ + struct comm_chan_device *ccdev =3D to_ccdev_timer(t); + + /* Schedule a work in the general workqueue */ + schedule_work(&ccdev->work); + /* Periodic timer */ + mod_timer(&ccdev->timer, jiffies + COMM_CHAN_TIMER); +} + +static void comm_chan_config(struct comm_chan_device *ccdev) +{ + /* Disable interrupts */ + comm_chan_write(ccdev, COMM_CHAN_REG_IE_OFF, COMM_CHAN_IRQ_DISABLE_ALL); + /* Clear request and response FIFOs */ + comm_chan_write(ccdev, COMM_CHAN_REG_CTRL_OFF, COMM_CHAN_CLEAR_FIFO); + /* Clear interrupts */ + comm_chan_write(ccdev, COMM_CHAN_REG_IS_OFF, COMM_CHAN_IRQ_CLEAR_ALL); + /* Setup RIT reg */ + comm_chan_write(ccdev, COMM_CHAN_REG_RIT_OFF, COMM_CHAN_RECEIVE_THRESHOLD= ); + /* Enable RIT interrupt */ + comm_chan_write(ccdev, COMM_CHAN_REG_IE_OFF, COMM_CHAN_IRQ_RECEIVE_ENABLE= ); + + /* Create and schedule timer to do recurring work */ + INIT_WORK(&ccdev->work, &comm_chan_check_request); + timer_setup(&ccdev->timer, &comm_chan_sched_work, 0); + mod_timer(&ccdev->timer, jiffies + COMM_CHAN_TIMER); +} + +void versal_pci_comm_chan_fini(struct comm_chan_device *ccdev) +{ + /* First stop scheduling new work then cancel work */ + timer_delete_sync(&ccdev->timer); + cancel_work_sync(&ccdev->work); +} + +struct comm_chan_device *versal_pci_comm_chan_init(struct versal_pci_devic= e *vdev) +{ + struct comm_chan_device *ccdev; + + ccdev =3D devm_kzalloc(&vdev->pdev->dev, sizeof(*ccdev), GFP_KERNEL); + if (!ccdev) + return ERR_PTR(-ENOMEM); + + ccdev->vdev =3D vdev; + + comm_chan_config(ccdev); + return ccdev; +} diff --git a/drivers/accel/amd_vpci/versal-pci-comm-chan.h b/drivers/accel/= amd_vpci/versal-pci-comm-chan.h new file mode 100644 index 000000000000..a6ad3228c3ff --- /dev/null +++ b/drivers/accel/amd_vpci/versal-pci-comm-chan.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Driver for Versal PCIe device + * + * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved. + */ + +#ifndef __VERSAL_PCI_COMM_CHAN_H +#define __VERSAL_PCI_COMM_CHAN_H + +struct comm_chan_device *versal_pci_comm_chan_init(struct versal_pci_devic= e *vdev); +void versal_pci_comm_chan_fini(struct comm_chan_device *ccdev); + +#endif /* __VERSAL_PCI_COMM_CHAN_H */ diff --git a/drivers/accel/amd_vpci/versal-pci-main.c b/drivers/accel/amd_v= pci/versal-pci-main.c index f8d32f9c0e0c..ad3f4645cd5e 100644 --- a/drivers/accel/amd_vpci/versal-pci-main.c +++ b/drivers/accel/amd_vpci/versal-pci-main.c @@ -8,6 +8,7 @@ #include =20 #include "versal-pci.h" +#include "versal-pci-comm-chan.h" #include "versal-pci-rm-service.h" #include "versal-pci-rm-queue.h" =20 @@ -98,6 +99,67 @@ static int versal_pci_load_shell(struct versal_pci_devic= e *vdev, char *fw_name) return ret; } =20 +int versal_pci_load_xclbin(struct versal_pci_device *vdev, uuid_t *xuuid) +{ + const char *xclbin_location =3D "xilinx/xclbins"; + char fw_name[128]; + const struct firmware *fw; + struct axlf *xclbin; + int ret; + + ret =3D snprintf(fw_name, sizeof(fw_name), "%s/%pUb_%s.xclbin", + xclbin_location, xuuid, vdev->fw_id); + if (ret >=3D sizeof(fw_name)) { + vdev_err(vdev, "uuid is too long"); + return -EINVAL; + } + + vdev_info(vdev, "trying to load %s", fw_name); + ret =3D request_firmware(&fw, fw_name, &vdev->pdev->dev); + if (ret) { + vdev_warn(vdev, "request xclbin fw %s failed %d", fw_name, ret); + return ret; + } + + xclbin =3D (struct axlf *)fw->data; + if (memcmp(xclbin->magic, VERSAL_XCLBIN_MAGIC_ID, sizeof(VERSAL_XCLBIN_MA= GIC_ID))) { + vdev_err(vdev, "Invalid fpga firmware"); + ret =3D -EINVAL; + goto release_firmware; + } + + if (!fw->size || + fw->size !=3D xclbin->header.length || + fw->size < sizeof(*xclbin)) { + vdev_err(vdev, "Invalid xclbin size %zu", fw->size); + ret =3D -EINVAL; + goto release_firmware; + } + + if (!uuid_equal(&vdev->intf_uuid, &xclbin->header.rom_uuid)) { + vdev_err(vdev, "base shell doesn't match uuid %pUb", &xclbin->header.uui= d); + ret =3D -EINVAL; + goto release_firmware; + } + + ret =3D versal_pci_upload_fw(vdev, RM_QUEUE_OP_LOAD_XCLBIN, + (char *)xclbin, xclbin->header.length); + if (ret) { + vdev_err(vdev, "failed to load xclbin %s : %d", fw_name, ret); + goto release_firmware; + } + + vdev_info(vdev, "Downloaded xclbin %pUb of size %lld Bytes", + &xclbin->header.uuid, xclbin->header.length); + + uuid_copy(&vdev->xclbin_uuid, &xclbin->header.uuid); + +release_firmware: + release_firmware(fw); + + return ret; +} + static inline struct versal_pci_device *item_to_vdev(struct config_item *i= tem) { return container_of(to_configfs_subsystem(to_config_group(item)), @@ -160,10 +222,13 @@ static const struct config_item_type versal_pci_cfs_t= able =3D { static int versal_pci_cfs_init(struct versal_pci_device *vdev) { struct configfs_subsystem *subsys =3D &vdev->cfs_subsys; + char dev_name[64]; + + snprintf(dev_name, sizeof(dev_name), "%s%x", DRV_NAME, versal_pci_devid(v= dev)); =20 - snprintf(subsys->su_group.cg_item.ci_namebuf, - sizeof(subsys->su_group.cg_item.ci_namebuf), - "%s%x", DRV_NAME, versal_pci_devid(vdev)); + scnprintf(subsys->su_group.cg_item.ci_namebuf, + sizeof(subsys->su_group.cg_item.ci_namebuf), + "%s", dev_name); =20 subsys->su_group.cg_item.ci_type =3D &versal_pci_cfs_table; =20 @@ -185,6 +250,7 @@ static void versal_pci_device_teardown(struct versal_pc= i_device *vdev) { versal_pci_cfs_fini(&vdev->cfs_subsys); versal_pci_fw_fini(vdev); + versal_pci_comm_chan_fini(vdev->ccdev); versal_pci_rm_fini(vdev->rdev); } =20 @@ -236,6 +302,13 @@ static int versal_pci_device_setup(struct versal_pci_d= evice *vdev) return ret; } =20 + vdev->ccdev =3D versal_pci_comm_chan_init(vdev); + if (IS_ERR(vdev->ccdev)) { + ret =3D PTR_ERR(vdev->ccdev); + vdev_err(vdev, "Failed to init comm channel, err %d", ret); + goto rm_fini; + } + ret =3D versal_pci_fw_init(vdev); if (ret) { vdev_err(vdev, "Failed to init fw, err %d", ret); @@ -251,6 +324,9 @@ static int versal_pci_device_setup(struct versal_pci_de= vice *vdev) return 0; =20 comm_chan_fini: + versal_pci_comm_chan_fini(vdev->ccdev); + +rm_fini: versal_pci_rm_fini(vdev->rdev); versal_pci_fw_fini(vdev); =20 diff --git a/drivers/accel/amd_vpci/versal-pci.h b/drivers/accel/amd_vpci/v= ersal-pci.h index 092cac6afa26..ef02cefd8f48 100644 --- a/drivers/accel/amd_vpci/versal-pci.h +++ b/drivers/accel/amd_vpci/versal-pci.h @@ -26,6 +26,7 @@ dev_dbg(&(vdev)->pdev->dev, fmt, ##args) =20 struct versal_pci_device; +struct comm_chan_device; struct rm_cmd; =20 struct axlf_header { @@ -52,13 +53,18 @@ struct versal_pci_device { struct pci_dev *pdev; =20 struct rm_device *rdev; + struct comm_chan_device *ccdev; struct fw_info fw; =20 void __iomem *io_regs; + uuid_t xclbin_uuid; uuid_t intf_uuid; __u8 fw_id[UUID_STRING_LEN + 1]; =20 struct configfs_subsystem cfs_subsys; }; =20 +/* versal pci driver APIs */ +int versal_pci_load_xclbin(struct versal_pci_device *vdev, uuid_t *xclbin_= uuid); + #endif /* __VERSAL_PCI_H */ --=20 2.34.1