From nobody Fri Sep 25 06:46:56 2026 Received: from DM5PR21CU001.outbound.protection.outlook.com (mail-centralusazon11011028.outbound.protection.outlook.com [52.101.62.28]) (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 3ADE547F3DA; Tue, 15 Sep 2026 20:57:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.62.28 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505868; cv=fail; b=ee3Fscjrr98ckjpDXrC7IJ29mxdIda9EnyjX4IlkWRi3sbjqX8/BIg6jBOPDHMekZqSYfARCODPF6eP3vs4aE3eGDTCKCNjRVhpoqcMPhDqe9z7z7HftVWMstAdA12DzSCVYFOs1XPiXs4/NRLcRUQayOHfvF4yrh8/2dl/dXus= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505868; c=relaxed/simple; bh=A0AZPXwbE2B/6ZO7IqSuVZ2g0K6QaV7JMa62RRGaapo=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=IM0P1LYol/e/EhWkKr4KjmY1CBzkh6UWYJfooAtEI3XRVjLFXp1zVndJ1idg0htCQaDPfevs3N6RJRIY0W3h0sJWZj7S9B5+WkpiMwrrPoq2Tnf8DJxA+nJFzPOY67UmVj68mYmUxKZq4Nw7RJ222h+r2c6sXliJUYXJgnn6IMc= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=FRRVHOcQ; arc=fail smtp.client-ip=52.101.62.28 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="FRRVHOcQ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=YPNr2asR224XuL+xoSARQbpxroxZMpWPnRFFqj4K1LZ7BYYUBa3+Tofi28wSCSXc2O5Q9ngKP7/K2QCv0DZwjn75559cB7+/QX6NAb4UVIjCT2+3ngjKx8iDelPDlQYivJh83YoBpGMZRg42Tb7aMfGSyGabYrIKPVwTKabJPm+c51kgKWz9pqQsuZJuYcfypnuNpyQzGyNl1vhxG4OCndq1L/iFygZgtdnRHEzWjIBDh7xY3lprEMypGtGz5uHCRW2DqxY8BOzqfA1PHmHvh1s31tlbBQK3EibKATOZg1H8f7G8L/kexswinJUAYIwYH4CgoeKOTiOK7atip2bnFQ== 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=Uzg6S/pmKEEK/2ko1+KSky4BY+Ww4e2mMC1YECpI+IE=; b=bemq0DT5DOujYuQH75eAvkp/NkTURDcf24PVUKQS+a0ImTiewC6fdkNqyp9wjQGLRaaQG0haaTUlNh6qxuVLMRxQ4hoZLDn/ESljf1aQ5OwfjXINV1i8EDjV943vSYtJ77rToWHi3Il6/lRkhSlW0DRC4sousHetn6qQ8K6oVtjH19tT3M1v8oFlPOuqZEz6RWJRJwavfW92bEbV3t7Q+LdB/bz6WE7hBxt8GygJAMmE2T+chM8ENtNaXV8ZxKb97oUslHhFS1ZbNaKcRjvf0L9A9gPzGs2DQFB0M2EQa1WsxZDlqnWGSU5KehaCSRvpR9u6anVXhtW0Loju5xK8Kg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.232) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Uzg6S/pmKEEK/2ko1+KSky4BY+Ww4e2mMC1YECpI+IE=; b=FRRVHOcQrL0zlsDIwF/2H32/px8WVeEgNxaxnMMQiwpVXcKlJMwOfdmeiU2zRlVceoTnMc3qiFTmHmPnwL/P51p8zpOS+yHTivYqF70OaPXIAGV+Bgw5lclF5OvO8lO7xrRCo2Tzyg4yFBTxLTWYmvl3MMO9ImCJp5Sp7hJ2NFJJS3zxTl91I+EXX/ZxaGcedHp02TmklbmI38LGGpcQEJlY7wXiTViDKWn9uWI8QvHlbTkcjKTq95OlRmKWJZXBXo8rK6r04I1W775HjOIlsnxfpoUfHiLLLkKfgOvJdtZvfvusFzTQSZ/vSL8fb0Dqw+u4DlBeXdHnxmekfVuKvQ== Received: from DS7P221CA0032.NAMP221.PROD.OUTLOOK.COM (2603:10b6:8:25e::9) by DS0PR12MB8245.namprd12.prod.outlook.com (2603:10b6:8:f2::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.406.9; Tue, 15 Sep 2026 20:57:35 +0000 Received: from DS2PEPF000061C8.namprd02.prod.outlook.com (2603:10b6:8:25e:cafe::88) by DS7P221CA0032.outlook.office365.com (2603:10b6:8:25e::9) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.9 via Frontend Transport; Tue, 15 Sep 2026 20:57:35 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.232) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.232 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.232; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.232) by DS2PEPF000061C8.mail.protection.outlook.com (10.167.23.75) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:57:35 +0000 Received: from drhqmail201.nvidia.com (10.126.190.180) by mail.nvidia.com (10.127.129.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:17 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail201.nvidia.com (10.126.190.180) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:16 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:57:09 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Peter Colberg , Zhi Wang Subject: [PATCH 01/14] PCI: add driver flag to opt into disabling SR-IOV on remove() Date: Tue, 15 Sep 2026 23:56:45 +0300 Message-ID: <20260915205659.76841-2-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DS2PEPF000061C8:EE_|DS0PR12MB8245:EE_ X-MS-Office365-Filtering-Correlation-Id: f9673ea9-396c-467b-ffb2-08df136bf857 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|36860700016|376014|7416014|23010399003|1800799024|82310400026|56012099006|5023799004|6133799003|11063799006|18002099003|22082099003|3023799007|10067099003; X-Microsoft-Antispam-Message-Info: 0sLLuD6/SwHllzhn2mPk4yRE1CUQvc91BBxtVFl8rbDYnB12uHGAjbR78ViRV0MuBVrIdH+tAeDg7mp3QIdZeenxQUXjtCvqja118bxc6HqMP3Vvnm4oi5MK6DEHU/Qcl8g47wGadlJAk4Yl9AE9OiNdvA8TKfgQtw5+SUxCc3Fr2aplTAjDdvBf4JVcqpUl0k0vMI3JiLtYVLHB3YfwInoC1aBGgWjVUUT6/Jaq9d/vHskf/6mxabqL2ktbjPmGvuN7mrow14uIfnZTAKrVLcCWl13lvzJy4k+DpjUxZSIN4Sg5eKgIcmWaXk945pXB438Rem2ZJ3ABVs4mv3PhPo8W6mbUwPVFc6Mh2Tv655R0wte27Ft8RuDieKBtIuSqx4mlPiHvEcBJ09i0TcK7+clpGK2bg9ba+t+qpVMflYN/LOBtcXTKaLr4jiwNGkEmzQeu+DWjHStGULO941LOOx6UDf7Qyzw6t7XKaeTQN9kDhOAenWhZW70rfALB7rf6xaOl8IgazXJRDkZ2oUPnNS/4OHRay2tVqeRVKN1OkIDXAW4xjFVk0bTD3iafLbmoLfqSK4MiPe+ZUgJIaGG2iE41Xm7gdOEPLEM5odw6mLM5xnVTPXvCOPOUUiZ9mym0SGPrMa0ZMgQNE2ncSsauq1eQ/DHN3h+ET77IIsaZePLT5ToqDs3TWe7pyjLPGYUih/e9WgxrdPKNYh3iUnTx4Q== X-Forefront-Antispam-Report: CIP:216.228.118.232;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge1.nvidia.com;CAT:NONE;SFS:(13230040)(36860700016)(376014)(7416014)(23010399003)(1800799024)(82310400026)(56012099006)(5023799004)(6133799003)(11063799006)(18002099003)(22082099003)(3023799007)(10067099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 59H46dzXyZ841u0epvvabVKYzUEkesuGjGepdbyDvfCQFoVSZZQGc+SZWgmVbxyUdAvOyM47K4EiqCxdWgaQ88kfkjoiWmBp5poefO4VkdaXYZWphs+Y6YMnjIOYquu6Q86cChJV9J9MgXDA9S7geGoK4Fk2uIW1IzHFPg4u9C6UjyOIw2K5yF3JMM8bb1Z7JNY5/fm6irPkqXinEJ/4zZZRLPv8sLi96p2Qofqu0p5pJsmlBTOBFjX2rw6Z0F7aenawglVFZAQVqVnhOLqYCA3Y04Woqcg5KGdoJr6gVZnR7MTCg+n0B8ODjvnhenAdGfAU10EiRvbTDh36goJSNoWB//GEVflzjm9kpVqDEuvp04jVsfgfsqAwtYmCGQ55II3ZoZpg05+L5co6IXU1ypU+nx328lH/AP6t8iUkpxJ4wzD9nGgQ1TgNRlxWHoVg X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:57:35.7804 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: f9673ea9-396c-467b-ffb2-08df136bf857 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.232];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: DS2PEPF000061C8.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS0PR12MB8245 Content-Type: text/plain; charset="utf-8" From: Peter Colberg Add a flag managed_sriov to the pci_driver structure that allows a driver to opt into disabling the Single Root I/O Virtualization (SR-IOV) capability of the device when the driver is unbound. Add a new function pci_iov_disable() that is invoked before the remove() callback of a PCI driver and checks for the presence of the new flag. If the flag is set, invoke the sriov_configure() callback to allow the driver to gracefully disable SR-IOV. Warn if the driver fails to do so and forcibly disable SR-IOV using sriov_disable(). Since a (broken) driver may theoretically re-enable SR-IOV during its remove() callback, extend pci_iov_remove() to forcibly disable SR-IOV after remove() if needed and only if the flag managed_sriov is set. Create a persistent managed device link from each VF to its PF before the VF can probe when managed_sriov is set. The driver core therefore waits for an in-progress VF probe and unbinds a bound VF before unbinding the PF driver. Altogether the flag ensures that when a Virtual Function (VF) is bound to a driver, the corresponding Physical Function (PF) is bound to a driver, too, since the VF devices are destroyed when the PF driver is unbound. This guarantee is a prerequisite for exposing a safe Rust API that allows a VF driver to obtain the PF device for a VF device and subsequently access the device private data of the PF device. Suggested-by: Danilo Krummrich Signed-off-by: Peter Colberg Signed-off-by: Zhi Wang --- drivers/pci/iov.c | 52 +++++++++++++++++++++++++++++++++++++++- drivers/pci/pci-driver.c | 3 ++- drivers/pci/pci.h | 2 ++ include/linux/pci.h | 10 ++++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 9d408fb8ac25..ee5eff209e15 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -382,6 +382,17 @@ int pci_iov_add_virtfn(struct pci_dev *dev, int id) } =20 pci_device_add(virtfn, virtfn->bus); + /* + * managed_sriov makes the VF driver binding depend on the PF driver + * binding. Add the device link before the VF can probe so supplier + * unbind waits for an in-progress probe and unbinds the VF first. + */ + if (dev->driver && dev->driver->managed_sriov && + !device_link_add(&virtfn->dev, &dev->dev, 0)) { + pci_err(virtfn, "failed to link VF to managed SR-IOV PF\n"); + rc =3D -EINVAL; + goto failed1; + } rc =3D pci_iov_sysfs_link(dev, virtfn, id); if (rc) goto failed1; @@ -1015,20 +1026,59 @@ void pci_iov_release(struct pci_dev *dev) sriov_release(dev); } =20 +/** + * pci_iov_disable - disable SR-IOV before PF driver is detached + * @dev: the PCI device + * + * Invoke sriov_configure() callback to allow the driver to gracefully dis= able + * SR-IOV. Warn if the driver fails to do so and forcibly disable SR-IOV. + */ +void pci_iov_disable(struct pci_dev *dev) +{ + struct pci_driver *drv =3D dev->driver; + struct pci_sriov *iov =3D dev->sriov; + + if (WARN_ON(!drv)) + return; + + if (!dev->is_physfn || !iov->num_VFs || !drv->managed_sriov) + return; + + if (!drv->sriov_configure) { + sriov_disable(dev); + return; + } + + drv->sriov_configure(dev, 0); + + if (WARN_ON(iov->num_VFs)) + sriov_disable(dev); +} + /** * pci_iov_remove - clean up SR-IOV state after PF driver is detached * @dev: the PCI device */ void pci_iov_remove(struct pci_dev *dev) { + struct pci_driver *drv =3D dev->driver; struct pci_sriov *iov =3D dev->sriov; =20 + if (WARN_ON(!drv)) + return; + if (!dev->is_physfn) return; =20 iov->driver_max_VFs =3D iov->total_VFs; - if (iov->num_VFs) + + if (iov->num_VFs && !drv->managed_sriov) { pci_warn(dev, "driver left SR-IOV enabled after remove\n"); + return; + } + + if (WARN_ON(iov->num_VFs)) + sriov_disable(dev); } =20 /** diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index e16aa59dd7ac..d71d72aeefd2 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -523,6 +523,7 @@ static void pci_device_remove(struct device *dev) struct pci_dev *pci_dev =3D to_pci_dev(dev); struct pci_driver *drv =3D pci_dev->driver; =20 + pci_iov_disable(pci_dev); if (drv->remove) { pm_runtime_get_sync(dev); /* @@ -536,8 +537,8 @@ static void pci_device_remove(struct device *dev) pm_runtime_put_noidle(dev); } pcibios_free_irq(pci_dev); - pci_dev->driver =3D NULL; pci_iov_remove(pci_dev); + pci_dev->driver =3D NULL; =20 /* Undo the runtime PM settings in local_pci_probe() */ pm_runtime_put_sync(dev); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index ba3c3fddddc2..6392da39a5e4 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -986,6 +986,7 @@ static inline void pci_restore_pasid_state(struct pci_d= ev *pdev) { } #ifdef CONFIG_PCI_IOV int pci_iov_init(struct pci_dev *dev); void pci_iov_release(struct pci_dev *dev); +void pci_iov_disable(struct pci_dev *dev); void pci_iov_remove(struct pci_dev *dev); void pci_iov_update_resource(struct pci_dev *dev, int resno); resource_size_t pci_sriov_resource_alignment(const struct pci_dev *dev, @@ -1021,6 +1022,7 @@ static inline int pci_iov_init(struct pci_dev *dev) return -ENODEV; } static inline void pci_iov_release(struct pci_dev *dev) { } +static inline void pci_iov_disable(struct pci_dev *dev) { } static inline void pci_iov_remove(struct pci_dev *dev) { } static inline void pci_iov_update_resource(struct pci_dev *dev, int resno)= { } static inline resource_size_t pci_sriov_resource_alignment(const struct pc= i_dev *dev, diff --git a/include/linux/pci.h b/include/linux/pci.h index d31a8d107b1e..bc0d36204940 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1025,6 +1025,15 @@ struct module; * how to manage the DMA themselves and set this flag so that * the IOMMU layer will allow them to setup and manage their * own I/O address space. + * @managed_sriov: Disable SR-IOV on remove(). + * If set, the Single Root I/O Virtualization (SR-IOV) + * capability of the device is disabled when the driver is + * unbound from the device, by calling sriov_configure() + * before remove(). The PCI core creates a managed device link + * from each Virtual Function (VF) to its Physical Function (PF) + * before the VF is probed. The presence of this flag therefore + * guarantees that when a VF is bound to a driver, the PF is bound + * to a driver, too, and that the VF is unbound first. */ struct pci_driver { const char *name; @@ -1043,6 +1052,7 @@ struct pci_driver { struct device_driver driver; struct pci_dynids dynids; bool driver_managed_dma; + bool managed_sriov; }; =20 #define to_pci_driver(__drv) \ From nobody Fri Sep 25 06:46:56 2026 Received: from BL2PR02CU003.outbound.protection.outlook.com (mail-eastusazon11011050.outbound.protection.outlook.com [52.101.52.50]) (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 5493A435515; Tue, 15 Sep 2026 20:57:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.52.50 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505877; cv=fail; b=ikQbuBhw0mkVZka46wZGR7wTdbfGutecPhUrZlaz9ONRUPeSdblbrzoV8exhiCwgXaG/ihUy8lLZtcT/sDH51TIKJ+G02nDbqVZBgGfx+Kp+s2BNFIK4c7/UZsjLqAYfoEoVjTiAIbR5Vyz+pfgP7pbAGsnnIi58/jtjb8vY0Uc= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505877; c=relaxed/simple; bh=AjitKJWSs/fKI1hR5qqZEnr/4E+C7LvUaAW0W9aD2RQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NmoFt1RVKQ4GNNqATzLGy40yWMltZ/vQRHjg9NgGiPRAK+7ek3J9lwO2j4iDejv8QkF50vb2i1ZGdGpkR1bhBxmv2sjyZHuYFRuLagRhR/TiyVKcxqppiT9ER3yOr/PQAQwIZolye7FRAWImofjvgSgAYGF7Pqtu/lKO0FiMw6Y= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=J1JFsV6G; arc=fail smtp.client-ip=52.101.52.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="J1JFsV6G" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=T7rp9cmaWwWjP97x7u7fhcpgf9O720Vd+Zsjb7661YFttSQG8+diBm1j+ZLHb3gDLiokqBBGd2WV3EeQ+Oq9ejpGT4eahFRCXzZBsX9NfJuYhNvD/v3QdC2tahtNaHpWCPrEDZjZrzLfjdS/IUwzW3tYq267ApW6FWWSYi+riIKLCAfbYQRBIbgEW6kCEI5wBqt4exTe0hxolW2wlnbaR2AnAI5ve/f7CUD/0agyika2CsdQI57O73B7zdeJdAQmOMKxCgjA5zFoFsPhPpZcooJAEmDiSyGAC9wC4c6iLh28UjyX2QCH1YEiHsv++56RoNKes0DZjNYTvgGq7R1tjA== 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=Vh56UPWXsjtfGYweC5+xsnEEBdssplJ8kHCVviVzuqQ=; b=D+UdC4eZYRQb5lqK3A4M91+l7LdimyjeOgTZcRZwVGu96Kl8GZYolHnKKemaePMrtIBiQduZ4aS54Lf/paLRvbDvDInElbyYWUl64ncNwoeSWbgzcbeQGY0maIjN9fP5DeKBbKpHSd6k8e08n2MiO7BkfSbShbLOjsA4rUYxb5g+ahntK4X3llMCEqW/WV+NlosGX5clfnBy6g1SdohynhspaUM+nSnfalLazo5zrV9zg4NAr6w/AwdR23nx4bTzKc1z/yrzsKC09EXX7K0SZQcqqV5cNtMAyL2Pm+2j2nULbs6wAsZ0DVunuPniCeCEjzaaRp6ZGaCGkYBmp+9tmA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.232) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Vh56UPWXsjtfGYweC5+xsnEEBdssplJ8kHCVviVzuqQ=; b=J1JFsV6GoWWXoxJEkJWEQJ9nfjls4mOj4oUcXHu6JCR921rOamNl/5N9aMuEuXraU7wtCgCtvtzPSqpqvMJpjYZnvesDpOjkq3y1h58M9JAe1WvB9r9M4GKXrS09E0WEkld548p0P+lNKr82Dh7s1qZW2LmL5UFKscerXM60HL/o3Hx3HbP2KshN1DVaSkeyXZqwT9XAWazYrwsdIbtQgvbK7bPbXnR7g5p0HOcm2tgsJSPZuqBTO6wcbQriBYrpc6lGL1ERx8BAE3Gw+Cc6pSQ20N3VBQf9FOZ+AYmSNA+ehqOCWzc016IlSHdujwwjO63csMQtQFVUAymQ5GPA7w== Received: from CH0PR03CA0445.namprd03.prod.outlook.com (2603:10b6:610:10e::31) by DS2PR12MB9591.namprd12.prod.outlook.com (2603:10b6:8:27c::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.406.12; Tue, 15 Sep 2026 20:57:46 +0000 Received: from DS2PEPF000061C4.namprd02.prod.outlook.com (2603:10b6:610:10e:cafe::27) by CH0PR03CA0445.outlook.office365.com (2603:10b6:610:10e::31) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.9 via Frontend Transport; Tue, 15 Sep 2026 20:57:46 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.232) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.232 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.232; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.232) by DS2PEPF000061C4.mail.protection.outlook.com (10.167.23.71) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:57:46 +0000 Received: from drhqmail201.nvidia.com (10.126.190.180) by mail.nvidia.com (10.127.129.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:25 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail201.nvidia.com (10.126.190.180) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:24 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:57:17 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Peter Colberg , Zhi Wang Subject: [PATCH 02/14] rust: pci: add {enable,disable}_sriov(), to control SR-IOV capability Date: Tue, 15 Sep 2026 23:56:46 +0300 Message-ID: <20260915205659.76841-3-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DS2PEPF000061C4:EE_|DS2PR12MB9591:EE_ X-MS-Office365-Filtering-Correlation-Id: 104f2caa-ab28-4325-1d55-08df136bfe90 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|23010399003|82310400026|1800799024|36860700016|7416014|376014|10067099003|3023799007|6133799003|18002099003|22082099003|56012099006|11063799006; X-Microsoft-Antispam-Message-Info: Itz9FOO1ed+3zPXI2dFG4PgIaJzquPK1Ce0i/6e28MEfl+BvKOI9FFCxbaKogT4w0IxFhIrnPY+lm9otGL6djOehpzEbQXhkjcg5BbtGsdozQalhV01vjQEClMDKeQWFp2sV1o25k1TW+TC/W8C/AsFx9bZ6hJeQxDzkCIClVUbBEPhvnammnAvjKzWfJ6QXERWvKClax/gl7hTBseWjOPFs6P2tQRHWJC+r+kWbiK8c4TSW6rTXbsFkkKEGXrdF+/BUj5y7ALwy3MW7/59HNi0YoFslNnKhOBeKJusDxDpEt8nGa/AaEX017JpQSHKUcS3IscbNCiiPew3boWlmMcPIKqnwBuadzGA8CKNr8B1/y468LakwOmV8yQWu37EsyMLjk7mJDLwlCunKOUvlzEZUOfuyNQTtH9em+yvLMwsyBa/XzyGIJp65ZxxSUmI/rDGK4bmLy5KZXCj/8g7n+X9lMIQ3727yyq5khoRn3WRtDfVvGdep1ZW8ffQxyEVcStyIyaVGo13F91b89WsHAHK9W7rThL7A8dW4kchEgfnIirM3wsGED13rm4Ei7xmhlRh+R+waghKi3RTegA502bcwOSoE4hkg2NWDRaSG8CyjlnMfg5dCGKs8SfpSINW3TNPR5TICgjHoJ0ryB7C4NYMa4jlKKNXerQW+GZgt0HYGOzmZXM1VMfpmEpPu3bjcowFm7cU1E1iPIC0YNpHmHw== X-Forefront-Antispam-Report: CIP:216.228.118.232;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge1.nvidia.com;CAT:NONE;SFS:(13230040)(23010399003)(82310400026)(1800799024)(36860700016)(7416014)(376014)(10067099003)(3023799007)(6133799003)(18002099003)(22082099003)(56012099006)(11063799006);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: OUaGGUIO4R0k1oaV2IWwB1II8WIDMHzlPZ4nqIQ/+R2lnG1JL7dLevBQVGKoJsht2k2bGi9cmumZhozvXNEv05dHB3/jCmONl7IZMHu09XGPxG+bxtisJv3Q8KX4yFGnFumIP7odKCfExeru1sdmZv2GXqjHJTv0HnEHt5avSYval7HdkqehttFa6zTtkH2zrvsR2H9gftCYnfE7ZwOvCfgrosb/UTGjZi6GE0yZcDisFIY+fyocUPVxU5vfsVg80siiCNfho5v1zwdU38WsWHzsoJqvqlVo3oEg0HO4dOmUONsqg2BGZ6uStzeClH2biXjG+wLkrjh/1cBfLwWjBc3dGNdAuAJGvP2L+zq0tv6mF8r2WVFfaQ+KcmSG8cs33/eUxJ2+yr7Y+XrUn5z6A3rlZdj5LFT0WaeJWY43i+k8516vZacLD5Uo3yOzUKru X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:57:46.0775 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 104f2caa-ab28-4325-1d55-08df136bfe90 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.232];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: DS2PEPF000061C4.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS2PR12MB9591 Content-Type: text/plain; charset="utf-8" From: Peter Colberg Add methods to enable and disable the Single Root I/O Virtualization (SR-IOV) capability for a PCI device. The wrapped C methods take care of validating whether the device is a Physical Function (PF), whether SR-IOV is currently disabled (or enabled), and whether the number of requested VFs does not exceed the total number of supported VFs. Set the flag managed_sriov to always disable SR-IOV when a Rust PCI driver is unbound from a PF device. This ensures that when a Virtual Function (VF) is bound to a driver, the corresponding Physical Function (PF) is bound to a driver, too, which is a prerequisite for exposing a safe Rust API that allows a VF driver to obtain the PF device for a VF device and subsequently access the private data of the PF driver. Suggested-by: Danilo Krummrich Signed-off-by: Peter Colberg Signed-off-by: Zhi Wang --- rust/kernel/pci.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 641f2000eb52..63fd8167e4ac 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -93,6 +93,7 @@ unsafe fn register( (*pdrv.get()).probe =3D Some(Self::probe_callback); (*pdrv.get()).remove =3D Some(Self::remove_callback); (*pdrv.get()).id_table =3D T::ID_TABLE.as_ptr(); + (*pdrv.get()).managed_sriov =3D true; } =20 // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`. @@ -506,6 +507,38 @@ pub fn set_master(&self) { // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid = `struct pci_dev`. unsafe { bindings::pci_set_master(self.as_raw()) }; } + + /// Enable the Single Root I/O Virtualization (SR-IOV) capability for = this device, + /// where `nr_virtfn` is number of Virtual Functions (VF) to enable. + #[cfg(CONFIG_PCI_IOV)] + pub fn enable_sriov(&self, nr_virtfn: i32) -> Result { + // SAFETY: + // `self.as_raw` returns a valid pointer to a `struct pci_dev`. + // + // `pci_enable_sriov()` checks that the enable operation is valid: + // - the device is a Physical Function (PF), + // - SR-IOV is currently disabled, and + // - `nr_virtfn` does not exceed the total number of supported VFs. + // + // The Core device context inherits from the Bound device context, + // which guarantees that the PF device is bound to a driver. + to_result(unsafe { bindings::pci_enable_sriov(self.as_raw(), nr_vi= rtfn) }) + } + + /// Disable the Single Root I/O Virtualization (SR-IOV) capability for= this device. + #[cfg(CONFIG_PCI_IOV)] + pub fn disable_sriov(&self) { + // SAFETY: + // `self.as_raw` returns a valid pointer to a `struct pci_dev`. + // + // `pci_disable_sriov()` checks that the disable operation is vali= d: + // - the device is a Physical Function (PF), and + // - SR-IOV is currently enabled. + // + // The Core device context inherits from the Bound device context, + // which guarantees that the PF device is bound to a driver. + unsafe { bindings::pci_disable_sriov(self.as_raw()) }; + } } =20 // SAFETY: `pci::Device` is a transparent wrapper of `struct pci_dev`. From nobody Fri Sep 25 06:46:56 2026 Received: from DM5PR21CU001.outbound.protection.outlook.com (mail-centralusazon11011009.outbound.protection.outlook.com [52.101.62.9]) (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 91D22455184; Tue, 15 Sep 2026 20:58:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.62.9 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505882; cv=fail; b=autbEkC2HXXuKwV/folF/bXrviv8Oc2ANewA7e824+WF2RVlLG/LzYWHiZd7oU3YUEc9ZFLsC5XX9wWic4fu+DTfBaBqqH5rlPWjO6R+ENR1/n/ZJQbqL/vtQeP2Tg07Y+1SmcGYAul8jBXfIJV434YRTStEc/vr43OIF0JXPi8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505882; c=relaxed/simple; bh=3n6hRSwfC6nGRHYei+AzmgwIFDzjIyNOgbnR/eCYYAc=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NtPUKZHXVRYlUHTDIwNm4C+qsrJ78ZTWz6GR/Y7DOWqj8rktgQH8JPOUE+vzArhy85UWsa2MBgXl6/d35/+c6VOxC2zCJhTjFMGhlMXgwYBJupnOKZ1wSrKLRWyxAur2RWvQUhEL9bQ/AwOLMMdS1ebcsWo1U9jQ0vrCVEX6lFM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=pWLdpI7C; arc=fail smtp.client-ip=52.101.62.9 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="pWLdpI7C" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=hn5zyLgZSxeMKJTBFrWFoZ5YHDIzGC1ZRL89d4rlHoFQ7pXaO0ndCVVXtwfSxIMbMgCgZitGAs5fWyfauqTd/oT22dqtF2jYmTnZYhKglvg7Y3SPlvE2dgZEZTvesjqxxlZujtk4dSDmx+WqdgkUr+9vxXdUPj6BdvEZVIZazAhr5MZPXsnSGhJqtukl1jSWy84hIdrFvrae/uEnSv4oDEEA8Jm5SXb4JdzaCeuvuosjaiE/NY5f8MomYl7Ml0peedbqQQsfw1pcM+I6oLfzsjhz6gUgzqJLokju8Xvlov6WHdhrCaZ7HRgjdtHiYXeqPIpGLLxkUlWrdQcXNq25pg== 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=QY6itu5/Rp+hZTrgVIT1b3sybrtUnpU+GJ5C6gZwZc8=; b=fPXoVi6gn/LuXLu4EX+QbaZuWVIS5/edJwaVfNvRjoIRNzjCAKsJAVUnJSbRwyZxPfu29Kqlf+QmamizsR0P909nmRW/Dt1EXKnfleLexjupWSU+UY6DZ9u5qGXqlHd5a9RjelOm/lbW+xw+8kqGJ788DyZi+2JiTUMk75cRbTQZ5xrVduLKuos+B9VTeFiDbzRzc88isOGX5bn9kAfqXg11A6sDehp8YaShtwdOsR4yz5MRdgn/PLwA5tZ7p/PbEw8R0kNU4uHFwoSKTVFaBTSaCOP9iFsLb2+Pcsd+xA5URDTegUO4dLa3iirNDdDuA/WvLgSBDdHxSJNQW3DyaQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.232) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=QY6itu5/Rp+hZTrgVIT1b3sybrtUnpU+GJ5C6gZwZc8=; b=pWLdpI7C3hhQhsJGywx2qx41eTP/P/e/cxbwyutj5jmOcrgp7wT/Yit25gLe/YhnjIWkm4gjSZkTaJOdoyWmG+t5haz4mA0pCRpRF85hFZsLoOCfsmhjHWSYyPRYn9O+TBnRlAh/uwIyqqvVmJyha0p8MuHH5qo8MencCEuzMH6IMxNpNbojWSmUURybSlEH93fMjkTKo8sS4bGlYgdj7n12Ftwoi1Mb/mFU1TzLZF2r0bE6uqTio8AQoqBZwk76l14K4T7QZPxU1vUH0pEi2ylTzLfuhex8izMTsFtTDsin8BYGWytxrsJnbV2kvRLgwnbXBVnfTBaLck9BYpxcxg== Received: from CH0PR03CA0447.namprd03.prod.outlook.com (2603:10b6:610:10e::24) by DS0PR12MB8198.namprd12.prod.outlook.com (2603:10b6:8:f2::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.9; Tue, 15 Sep 2026 20:57:51 +0000 Received: from DS2PEPF000061C4.namprd02.prod.outlook.com (2603:10b6:610:10e:cafe::a8) by CH0PR03CA0447.outlook.office365.com (2603:10b6:610:10e::24) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.9 via Frontend Transport; Tue, 15 Sep 2026 20:57:51 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.232) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.232 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.232; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.232) by DS2PEPF000061C4.mail.protection.outlook.com (10.167.23.71) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:57:50 +0000 Received: from drhqmail202.nvidia.com (10.126.190.181) by mail.nvidia.com (10.127.129.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:33 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail202.nvidia.com (10.126.190.181) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:32 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:57:25 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Peter Colberg , Zhi Wang Subject: [PATCH 03/14] rust: pci: add vtable attribute to pci::Driver trait Date: Tue, 15 Sep 2026 23:56:47 +0300 Message-ID: <20260915205659.76841-4-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DS2PEPF000061C4:EE_|DS0PR12MB8198:EE_ X-MS-Office365-Filtering-Correlation-Id: 2e8e26f0-c92a-4faa-38f2-08df136c0164 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|7416014|36860700016|1800799024|23010399003|82310400026|10067099003|11063799006|56012099006|22082099003|18002099003; X-Microsoft-Antispam-Message-Info: 0luX1avVtCLNsVEEP6RS9FiZ2sGtPMb1wZBOK0cADB8OFWo5D7d9WF+rdCa4BGX58G4sIL8/g2Mz1PW1PeeAvkZoR8LR8gWfPLSk2jAk16MhxNY0B1Qu/cDXdRLQ7OTyh1do8a3LcEEjeSMMDmcNWb1RC1aWCXwU4E++tK5E+7UY0+zVFUPPxZfwhbwyhPtprOVHySYaE9IVHL20gin63Fivc+7EswSKZQSEHgS0Eg2dFw3SuYEZC6I0Y4pzVjddHysbCJotmXERJpjdw+imsALJaMmmLEKRRzqKGlMFduct69eBW2HF7qmXcYh1O2CvwgH9lLDk/JXUJVlmeJuraE7zfOerUsFNAn6Bb0Mmx59HT9h4H3zbniQZAgXlUiBGgc8I4OsLPDG+bhGC95CKamCkrFTHMzp0B6lXytN05jCcehsgJjpx1BTPnTNIEJw5zEVPUNDDymRyCRIUxwN/g3S1hPecMQxEYnmfssg9MoG0UNUAVQSin73wkfeJR8nPf3ATi7m3Vlv9+FTh1ftcZMs5NIEYXJexbf6uom0iYSqp7QbDZ7GRMQVy0J5FEdqvLo8hMlkw+a5DRyM20uBQtT5i9yS9keVXhJx0Ktv125x8ioxIQwy15dm1kWBFu5EnpiGW2/rQXp9XFsbZFO7djqf9Oit1BFvWo9jzCo9oINlF5KkZ6tJa3s593J27ifbLo9LTMzfiJ3J786GLzfmUAQ== X-Forefront-Antispam-Report: CIP:216.228.118.232;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge1.nvidia.com;CAT:NONE;SFS:(13230040)(376014)(7416014)(36860700016)(1800799024)(23010399003)(82310400026)(10067099003)(11063799006)(56012099006)(22082099003)(18002099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: G2fkfTW7qK1JZOx+wTNgNcEMqLMbGlphW0eRpqD0lT74F+NLXmmBHR2hh8p4pLRRpe3jItFj+wP9hyqMkOzKdKTbLi+n8BkY/ilPJUoG2rPplls9ZarL0Pxm5beMlGHoS92FixPn1Wp+WEsjx8AYWO6IgiZdjrvyLIZqsseUFL06UI3xq4Ny4XBOkRzlpjnp8s44ztp9+N+XoWcfYXIdKA5pBKxls61xQz0nA2YEGq0ZKFhYt92kCEd2XMlaDrvczlHPrR6n2WnRNNJtGMikEFoBlf5e8F+TEMti9YmZlMoPyq0xYQ812zijbkOj4jai4jh2RCUOGHs3nMuetw4oqCW/b03IC4U+v+J/k1ujSVGT4gvmI/tMcykKU3xrgA+soqig9eSLEvI+il5DUtV8pxT4VTfT1cuXbA/N2IfRZB4FfHth1qRrTtuVT+qYvsuN X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:57:50.9076 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 2e8e26f0-c92a-4faa-38f2-08df136c0164 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.232];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: DS2PEPF000061C4.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS0PR12MB8198 Content-Type: text/plain; charset="utf-8" From: Peter Colberg Add the #[vtable] attribute to pci::Driver trait and implementations, to prepare a subsequent patch that adds an optional bus callback sriov_configure() to enable or disable the SR-IOV capability. Suggested-by: Danilo Krummrich Signed-off-by: Peter Colberg Signed-off-by: Zhi Wang --- drivers/gpu/nova-core/driver.rs | 1 + rust/kernel/pci.rs | 2 ++ samples/rust/rust_dma.rs | 1 + samples/rust/rust_driver_auxiliary.rs | 1 + samples/rust/rust_driver_pci.rs | 1 + 5 files changed, 6 insertions(+) diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index 1f6fe2d97cab..a5b9a50cbaca 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -94,6 +94,7 @@ pub(crate) fn bar1_resource_index(pdev: &pci::Device) -> Result { ] ); =20 +#[vtable] impl pci::Driver for NovaCoreDriver { type IdInfo =3D (); type Data<'bound> =3D NovaCore<'bound>; diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 63fd8167e4ac..24b682d4d6da 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -282,6 +282,7 @@ macro_rules! pci_device_table { /// ] /// ); /// +/// #[vtable] /// impl pci::Driver for MyDriver { /// type IdInfo =3D (); /// type Data<'bound> =3D Self; @@ -297,6 +298,7 @@ macro_rules! pci_device_table { ///``` /// Drivers must implement this trait in order to get a PCI driver registe= red. Please refer to the /// `Adapter` documentation for an example. +#[vtable] pub trait Driver { /// The type holding information about each device id supported by the= driver. // TODO: Use `associated_type_defaults` once stabilized: diff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs index ffb693544673..804d55a63005 100644 --- a/samples/rust/rust_dma.rs +++ b/samples/rust/rust_dma.rs @@ -69,6 +69,7 @@ unsafe impl kernel::transmute::FromBytes for MyStruct {} [(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())] ); =20 +#[vtable] impl pci::Driver for DmaSampleDriver { type IdInfo =3D (); type Data<'bound> =3D DmaSampleData<'bound>; diff --git a/samples/rust/rust_driver_auxiliary.rs b/samples/rust/rust_driv= er_auxiliary.rs index 0bee16faecc6..6cff9bf8c80c 100644 --- a/samples/rust/rust_driver_auxiliary.rs +++ b/samples/rust/rust_driver_auxiliary.rs @@ -90,6 +90,7 @@ struct ParentData<'bound> { [(pci::DeviceId::from_id(pci::Vendor::REDHAT, 0x5), ())] ); =20 +#[vtable] impl pci::Driver for ParentDriver { type IdInfo =3D (); type Data<'bound> =3D ParentData<'bound>; diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index 13b035a95756..50c8709739c6 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -139,6 +139,7 @@ fn config_space(pdev: &pci::Device) { } } =20 +#[vtable] impl pci::Driver for SampleDriver { type IdInfo =3D TestIndex; type Data<'bound> =3D SampleDriverData<'bound>; From nobody Fri Sep 25 06:46:56 2026 Received: from PH8PR06CU001.outbound.protection.outlook.com (mail-westus3azon11012046.outbound.protection.outlook.com [40.107.209.46]) (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 9CAC5471D01; Tue, 15 Sep 2026 20:58:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.209.46 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505885; cv=fail; b=oMx48WSo648ecn8B/NGiG4CeJ/Pmt5D44EambIvMa7PGdlup/FTpTKcFx4+5XEIIr+tZbQocK0DMKTmocJ7D2jJQYCvVpM4mTxU2jE7chqrAF0NfDxss42QmGbQn6lY29A4ttxBVM/jF0iiWdLYpui+dJi0gufqEmn3XLJIP++U= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505885; c=relaxed/simple; bh=AnpRuMZOJ0sN3lGyNAogiWnmCT2arJ4eNJIqgxVScbM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ZsNZgUP3fIiOEt7KhcXpDR/XhcY86FYroNEZTLteYQ9d0YNciDYIX6elGkIqC/0d6GHGwHVP9/4ju97BA9Ws7umuoauRHA6SMD//6pAykFS20otGhMH6GMzXvSfpAWdAvBxM4IMO7RbdI+lBHbEDw9kJJchdBdxUW0HXfmUgfNY= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=lJjsyhGY; arc=fail smtp.client-ip=40.107.209.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="lJjsyhGY" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=JDzOFl8aPgoYKpqKAsWtGaK9ndINl7sXVlbrvH38k2ABpx9DdOPMPd2Cbfp0w+FzB5e2LDT3XdJ8Pt5h4otOkU7vWmWctAVcbeMxoUWPpcc32n/RAWzn0XePlZKbOPJH7bNqCgvxQojIZbrsGyRa2zssVG3O1JyjSkpUcpmATzsNF0G2RYU4WCEYCELsacfmzGJjtYE5gtx2JA6AlkspmjLiNcnEOvbEXKdWYlhap4uEsrKpFD28Tvuqx/yapY52WttXnQ3sxcKyX4MG9OdntbV4wI89Os/IhbA4U4ht7yC3vFDzMRaV7km2pWiVSE5s82p11pT/FUTj/XEtNTDVkw== 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=dfbZRefirlZO/d9Hb8/3uiPeg7dxv3G6HDySXVE5Vgk=; b=OgQ7xlzc4Gi0vxkGwGm0l7CcpZET33DNC5XgVE16WT5t13J63XYZU+RFh9ElQwz2reUK3OLI2Gpp4zx0KbTq2rQhrNOD4vj4LseSMUiIupXgnKGwPDUs4hkJ8od8cbWmjbzsc7SFOAtk+4FXfE24Avohg+FQ7GuOy47SIIufYnYEEmHUXCnON8iLF3XODhngHtl1JMuK3gbMCYrbNzgMvAHZEx1LtLlN4N8unasBSE//M5E+VFWpUnwGzbTrM/1c1waD+ObfPQv+yUoDc2OmdYtFf2lu3DFa4QC2hOXJ9vbFz4Ll9YGygf3y5iX7xTXHPhXvMdmrSiIy8sAw00Z8dQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.233) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=dfbZRefirlZO/d9Hb8/3uiPeg7dxv3G6HDySXVE5Vgk=; b=lJjsyhGYcVW3NU3xwlUrxR9XvBRf0iqgc9yVkoZqENkWXt8Qg3A0ucT6KB8Wpp1L/rOXETTALZz8tAy8uAy/TqCkHIoOPu0Ab2IH62dnhCIy9iPW80izuxZnmRnIl+WCmtNIRq/8yMvtZNit+PGnh/jrvWcSCc8NWDmN8OfkrHSvbBnhCqKtBSg/orJ/7SVSh23m8KOkOecB+BJtCmcT9mhSNceXnl9NdZL072jCKHxDmP3By0T1bfdDtDhsX857fnhRnkB1CPMvyakidMw3wimZP/zKcxdyLobs8uF/YigwFKTH1Oi9abzo3yjITZuIzbudk7/4vxPe/dAIgLUSiw== Received: from BY1P220CA0018.NAMP220.PROD.OUTLOOK.COM (2603:10b6:a03:5c3::8) by CY8PR12MB7433.namprd12.prod.outlook.com (2603:10b6:930:53::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.11; Tue, 15 Sep 2026 20:58:00 +0000 Received: from CO1PEPF000075F1.namprd03.prod.outlook.com (2603:10b6:a03:5c3:cafe::10) by BY1P220CA0018.outlook.office365.com (2603:10b6:a03:5c3::8) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.9 via Frontend Transport; Tue, 15 Sep 2026 20:57:59 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.233) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.233 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.233; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.233) by CO1PEPF000075F1.mail.protection.outlook.com (10.167.249.40) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:57:59 +0000 Received: from drhqmail202.nvidia.com (10.126.190.181) by mail.nvidia.com (10.127.129.6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:40 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail202.nvidia.com (10.126.190.181) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:40 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:57:33 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Peter Colberg , Zhi Wang Subject: [PATCH 04/14] rust: pci: add bus callback sriov_configure(), to control SR-IOV from sysfs Date: Tue, 15 Sep 2026 23:56:48 +0300 Message-ID: <20260915205659.76841-5-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000075F1:EE_|CY8PR12MB7433:EE_ X-MS-Office365-Filtering-Correlation-Id: 895487ba-56da-4d04-57df-08df136c0672 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|82310400026|1800799024|36860700016|376014|23010399003|7416014|10067099003|56012099006|5023799004|11063799006|6133799003|18002099003|22082099003; X-Microsoft-Antispam-Message-Info: rSDQ8fZ7PlJJRQjwp+XIAXUvBQSGDVonPDQhCypM7yK8FPgUQ5bhEl9E5FRDG6oY6OMWG67GkWnSRChmvXkDsaaEOU4dS/mh5YaokmdjBdXJ1PcN/pjkGcqtNFcP6d25C7IA7FXZZQMd1MzwojEwAg9CcjSSLFYUwFjd2HsDY+X3rz6KAVMPYCxQp8PWzOItngjbtZwQFS8WtBgC5eSAQkFmgf9ngY2brkt1hD0JUC6NvsmELJHDtN/lPetMtMrzQRKTGxuMsPoZKZvlnWwB+QWDIUP4KTqLEe2RmsUI3a2YIpACtaacDtTXH7ivviC+mF33JRzAns20Fx9pHGxbfYEQ1nTgIYMsI1WcnYjTg1Diaw68ZCTj6+2maBWV5r3usxqEJwk6Xx/4b1DI9CxAtvOpRwWLgBvK40WhpR7DNNZ1AsKZfBJgHCCJEhaJg4+WYfs9NyEILhm7SBPISiJTQsNDakLjKVNtLYm0YAbdkRiU2iooAa/PGdzgQfKlcIffxTP3F0+9hnACx4MOKW1azt2UqdSWOrEEICW5MGUQJcZt7bzXDwATwnTX8lZhsPJGEiDP2kMUl+wGNbA8PKM6bCDF5rbVuZfz6YT1076oEeiH7xI8gtcmWbh9zQfJ423zJGH6Dk/g/B3hcGqi17X5TD04Fzc8KzuSabQ/kBXgai4AWht6vtc5z4lfux++O8t0bBjoSpY9k4F70tnNsgKyaQ== X-Forefront-Antispam-Report: CIP:216.228.118.233;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge2.nvidia.com;CAT:NONE;SFS:(13230040)(82310400026)(1800799024)(36860700016)(376014)(23010399003)(7416014)(10067099003)(56012099006)(5023799004)(11063799006)(6133799003)(18002099003)(22082099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: svKW+GPyqJrIZQke0CyKvYUQKpXJvMHf/Page8sY9TPTnkL6D4jFxCV7M54ESXS13ABe9V2LgNcP4zk1LmAT4vth2H44/01J8iZgNsFuN2UckFAk6oBSRFiBn90GikH6qc0d8J0IqB3d+aOBIqg3gxfl2bGLkTpr+wySNtfbCD2J/0zIx19ibsPgLMYHk1kwCFGtZWZ6rEkh4m8wLnc7wo9TYgqOLC3VDfJSUBWkpabcDOPJFANKs+o/oqbOQxazAHhs+kkkhz/odyiuc9JV4n02Un6PyybXUiTCXzGSKApPZXZrGUKitC7JjLxZGkVfSNVgikwUKKE6/c3cOj4lASKsKHTqLgYgPsWGd9ZJXB3LZN960sMBbh7AiiknscRGGeFtQ1H5Bmoi10N6bpXGsg6BY67lvKr3LHcv3Bgm0ftCNt8M7e8VfxKHkUCbQnfr X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:57:59.4546 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 895487ba-56da-4d04-57df-08df136c0672 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.233];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000075F1.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY8PR12MB7433 Content-Type: text/plain; charset="utf-8" From: Peter Colberg Add an optional bus callback sriov_configure() to pci::Driver trait, using the vtable attribute to query if the driver implements the callback. The callback is invoked when a user-space application writes the number of VFs to the sysfs file `sriov_numvfs` to enable SR-IOV, or zero to disable SR-IOV for a PCI device. Suggested-by: Danilo Krummrich Signed-off-by: Peter Colberg Signed-off-by: Zhi Wang --- rust/kernel/pci.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 24b682d4d6da..7f50c1c96a4f 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -94,6 +94,10 @@ unsafe fn register( (*pdrv.get()).remove =3D Some(Self::remove_callback); (*pdrv.get()).id_table =3D T::ID_TABLE.as_ptr(); (*pdrv.get()).managed_sriov =3D true; + #[cfg(CONFIG_PCI_IOV)] + if T::HAS_SRIOV_CONFIGURE { + (*pdrv.get()).sriov_configure =3D Some(Self::sriov_configu= re_callback); + } } =20 // SAFETY: `pdrv` is guaranteed to be a valid `DriverType`. @@ -150,6 +154,20 @@ extern "C" fn remove_callback(pdev: *mut bindings::pci= _dev) { =20 T::unbind(pdev, data); } + + #[cfg(CONFIG_PCI_IOV)] + extern "C" fn sriov_configure_callback( + pdev: *mut bindings::pci_dev, + nr_virtfn: c_int, + ) -> c_int { + // SAFETY: The PCI bus only ever calls the sriov_configure callbac= k with a valid pointer to + // a `struct pci_dev`. + // + // INVARIANT: `pdev` is valid for the duration of `sriov_configure= _callback()`. + let pdev =3D unsafe { &*pdev.cast::>>() }; + + from_result(|| T::sriov_configure(pdev, nr_virtfn)) + } } =20 /// Declares a kernel module that exposes a single PCI driver. @@ -336,6 +354,44 @@ fn probe<'bound>( fn unbind<'bound>(dev: &'bound Device>, this: Pin<&Se= lf::Data<'bound>>) { let _ =3D (dev, this); } + + /// Single Root I/O Virtualization (SR-IOV) configure. + /// + /// Called when a user-space application enables or disables the SR-IO= V capability for a + /// [`Device`] by writing the number of Virtual Functions (VF), `nr_vi= rtfn` or zero to the + /// sysfs file `sriov_numvfs` for this device. Implementing this callb= ack is optional. + /// + /// Further, and unlike for a PCI driver written in C, when a PF devic= e with enabled VFs is + /// unbound from its bound [`Driver`], the `sriov_configure()` callbac= k is invoked to disable + /// SR-IOV before the `unbind()` callback. This guarantees that when a= VF device is bound to a + /// driver, the underlying PF device is bound to a driver, too. + /// + /// Upon success, this callback must return the number of VFs that wer= e enabled, or zero if + /// SR-IOV was disabled. + /// + /// See [PCI Express I/O Virtualization]. + /// + /// [PCI Express I/O Virtualization]: https://docs.kernel.org/PCI/pci-= iov-howto.html + /// + /// # Examples + /// + /// ``` + /// # use kernel::{device::Core, pci, prelude::*}; + /// #[cfg(CONFIG_PCI_IOV)] + /// fn sriov_configure(dev: &pci::Device>, nr_virtfn: i32) ->= Result { + /// if nr_virtfn =3D=3D 0 { + /// dev.disable_sriov(); + /// } else { + /// dev.enable_sriov(nr_virtfn)?; + /// } + /// Ok(nr_virtfn) + /// } + /// ``` + #[cfg(CONFIG_PCI_IOV)] + fn sriov_configure(dev: &Device>, nr_virtfn: i32) -> = Result { + let _ =3D (dev, nr_virtfn); + build_error!(crate::error::VTABLE_DEFAULT_ERROR) + } } =20 /// The PCI device representation. From nobody Fri Sep 25 06:46:56 2026 Received: from DM1PR04CU001.outbound.protection.outlook.com (mail-centralusazon11010021.outbound.protection.outlook.com [52.101.61.21]) (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 12459361975; Tue, 15 Sep 2026 20:58:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.61.21 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505898; cv=fail; b=UzAA3/wELzx0hdAYEHJjTEUoLRWOW260hwa1ooSAYasbg5al3zuTbatf3qbfYNiw+Pp2h2fzbaweGlHaBFTsclKVzAyJrhCH7TfvZpVaN7GKH1kFkEvNIcu3iPyq6sPRJl94UTfj+BhFM33rmH6oh+z5L/jydrtRipC2MnyzDEQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505898; c=relaxed/simple; bh=zgU9yxGMVb4XZJM0v7A/kpcT3PKF+EzqstSz1NlSF2s=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=S9csrHhu1rAZSugb7e6CQEzppMNOhijpBMXflob0nA5aOFIa/VDYubHrfx8Rl32Iu6wiRfgzvon3mlZV+u8eQK2GBk776sUDAndonzsbcgDmGLBaTMyF7QH+oKBNVgyR8QtvHs1rgQczE7RfBT21o+prKoQQytCrrh7yOflHFAM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=FV8usa4k; arc=fail smtp.client-ip=52.101.61.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="FV8usa4k" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Pt3NIgYt3ZGITqPnIowoFEuW5ohoNnaIEZhjRI1KEnxgmT2AzcMNDON+vMaIUFt0r2hCXofIC5kN0mzj5JCPXURZ/t/4Ipcx37rNVatCcq4QbzUkgYvZPuxwueSc0aoB2bK8YkPjyTWOPHEXs4uMFP8zwCpHD0SM2rQSVveJF2jZ1m2Nb7hqfWyXdDqmDDwOfXnY/j8ysR6JBeeEFZTAVGJN78Jb6fa/5CmY2ZwMLWtxntVgnQyC7m6VmjCZeCa3Q6XbFeKY+V81rAMcFPOslL5xOGMPhYHUvRcJrGQ5OVuh13Pmf5laAF2MSoR/dLCTIbVM/iFwXy4WfsRhpZICsw== 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=KqG5+r02RbRq30AaEL6hJ7fOFSh56QrMlOixmT/0BnI=; b=f/VqddiYAftL/ECX8HDKV7o9rq6vDMGI0k8Ie3qh7vt2ijE/QzS1BSS6zHFyOAj3OaA2LkW+3JNmYMKochmxav4c90DwY8Q0yaTVUFhOH9GAzaz9oQRauiJR/HDI7TYarpIyZGNsYwhwK2Qt/IKk8YPJwg75VIbE8BJGpS0y+MdovCIZSfhCJ4EBb9mlb7E/aTRvxfwQezapj5KE10dbjlrdCukgP1xn+WD2KfBqdHERa4u9//QPqFNA8K1sUwsXcbPPHlLtbVYc1ljkTAhiCzJpygYPNVPyzhyTECnvIuGcqb58MRQ6a3kL6o8Z7gzhpo2w7EkL/NpFq5sexRd8bg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.233) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=KqG5+r02RbRq30AaEL6hJ7fOFSh56QrMlOixmT/0BnI=; b=FV8usa4kLN9f7dEB/ZbErbBCg8rNMmMUcLjRRmwL5ni1qELHDc+fLTGhMEnc1e8ONmHi6OhzQ13K2ZpweSnnppW9br0wRGedtCXx79lObx2dcP0wUj0dj4hw9apLk1KOlaI686iwjGTeGrGara9SRZ2zmFbDhMaEAMJfNRiCdhSZZMQH+o1jJtDyVFzsu9fnXmcWGyKkVQdUkM6PfU7fOGTq18NNz7N+0hK6vskT0sSAH7h2D9yRMx8HWJ9Ngrontepwesg+EwaYo/PqlLYAAYIaHeyanLi9a1mDsMrDVfTsl0xOsXsQtbvDe1IE65szpKAwom1lBk1dhzwIywXXSg== Received: from MW4PR03CA0352.namprd03.prod.outlook.com (2603:10b6:303:dc::27) by SJ0PR12MB6735.namprd12.prod.outlook.com (2603:10b6:a03:479::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.11; Tue, 15 Sep 2026 20:58:11 +0000 Received: from CO1PEPF000075EF.namprd03.prod.outlook.com (2603:10b6:303:dc:cafe::42) by MW4PR03CA0352.outlook.office365.com (2603:10b6:303:dc::27) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.406.12 via Frontend Transport; Tue, 15 Sep 2026 20:58:11 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.233) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.233 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.233; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.233) by CO1PEPF000075EF.mail.protection.outlook.com (10.167.249.38) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:58:11 +0000 Received: from drhqmail201.nvidia.com (10.126.190.180) by mail.nvidia.com (10.127.129.6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:49 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail201.nvidia.com (10.126.190.180) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:48 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:57:41 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Alistair Popple , Joel Fernandes , Peter Colberg , Zhi Wang Subject: [PATCH 05/14] rust: pci: add is_virtfn(), to check for VFs Date: Tue, 15 Sep 2026 23:56:49 +0300 Message-ID: <20260915205659.76841-6-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000075EF:EE_|SJ0PR12MB6735:EE_ X-MS-Office365-Filtering-Correlation-Id: 42a4dec5-6f37-4c7f-4e5b-08df136c0d83 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|23010399003|82310400026|36860700016|1800799024|376014|7416014|10067099003|6133799003|22082099003|18002099003|56012099006|11063799006; X-Microsoft-Antispam-Message-Info: za22NXHg8wCiwNtx7colZO1yW4Spiyt2KdVj1v6R/utwA+seIQhl6qiFEnYJ+FgYQDypUERYoEpV2/W25dCB27YDTl3neXlZCktCbN67ACJPYhBf/TkkfptDqwRp3w+N9CeGk4/6toBEX9j3tqBxQ9pwxRxHmluLDPOVnIUM0P7MQKSNdBF0EW9knCYEOiV6dhpkXnv68vpXYljSTU7aQXtFZ1FWl77bYDmvZA/JLI9Kf5z8o65ASjMivAoqSAvW1VikA8ubxyhisb+EcOB5zWmLvWesbwQaVt2xGbWrSrJeYMFtTVj04Mew/UAzRfLdi3McOkMIYjlgQKqunV41d/yo3xL5EGVvR6F04H0MuZGA6Vthso4+zKNf6riNJ/Sf1Xbm/bDl3Grb2fEcrgQQIxfgjzUA8agrRMAAP4cRNig2a/UMeZLCjlht2wP0jSuafIkGaxrGjLp0isCiGnmJsD1j3EK58rtNQUeha8oKxyf0qDZ6q8QUYeO9Eq0t++OnuH5Qp0zFIJJUNQSBu3WDF2GI84EihnTzPWyUjULhUr9v2lUJ1gYS2B05ga006kVozZuN9IPR57VIxhktsYQ99pnYmyYiWhQdcQu8FNDlwzykvKhB0nxqRW4mIEeZOfRNnlx5fsVHgj4CtBCuFl6pkwbLxMgTWr+O8J7vYbBDJ8veCZjGWOJ4JVKAyi79SRyxHqnvafy7kO+rulJcJ2sl2A== X-Forefront-Antispam-Report: CIP:216.228.118.233;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge2.nvidia.com;CAT:NONE;SFS:(13230040)(23010399003)(82310400026)(36860700016)(1800799024)(376014)(7416014)(10067099003)(6133799003)(22082099003)(18002099003)(56012099006)(11063799006);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: vrLYx5HY8n4PZ/IgSNrqqQcqEhHimZHBVyCDyTV7+dEKNzc10XpyroZH4iC8daTLDrUubM/wQwNZAuxh0LFVdhSF6fG2xAoTNMzn+WDJPQbcnmTM3RzcFp78MKKjR2ktKvjkZc/KIKD0PhuLNY4VrJ2QHJ54G1wXPTOCz98shv8tkWPIiOplQW6H8b5mE6D/qExDrcaQ+GSX3DMDOkt8afNXx9XBL0XHtiyXkqdM2offehmCbvT5AvhltdGpz6CB4CP7C/tiIB/utYzPx5TPYmuFEAkBJNJFsEGsOygQdIq7E32LCvywVm7SPEcQ9gT3fJPl5lP9og2wB2DZkM/UtmQYMBd7D5GYZBP++G07u+Q2mbZuWaLbyIhaq1yBeoSywmgVWgPe/1/ICFieIAwMXwNmadkaxJ1G0e5H9cV/0kwPjXJVBkte6rlJb+QkdhXT X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:58:11.2980 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 42a4dec5-6f37-4c7f-4e5b-08df136c0d83 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.233];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000075EF.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR12MB6735 Content-Type: text/plain; charset="utf-8" From: John Hubbard Add a method to check if a PCI device is a Virtual Function (VF) created through Single Root I/O Virtualization (SR-IOV). Signed-off-by: John Hubbard Reviewed-by: Alistair Popple Reviewed-by: Joel Fernandes Signed-off-by: Peter Colberg Signed-off-by: Zhi Wang --- rust/kernel/pci.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 7f50c1c96a4f..844d73a83670 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -507,6 +507,14 @@ pub fn resource_start(&self, bar: u32) -> Result { Ok(unsafe { bindings::pci_resource_start(self.as_raw(), bar.try_in= to()?) }) } =20 + /// Returns `true` if this device is a Virtual Function (VF). + #[inline] + #[expect(dead_code)] + pub(crate) fn is_virtfn(&self) -> bool { + // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. + unsafe { (*self.as_raw()).is_virtfn() !=3D 0 } + } + /// Returns the size of the given PCI BAR resource. pub fn resource_len(&self, bar: u32) -> Result { if !Bar::index_is_valid(bar) { From nobody Fri Sep 25 06:46:56 2026 Received: from CY7PR03CU001.outbound.protection.outlook.com (mail-westcentralusazon11010046.outbound.protection.outlook.com [40.93.198.46]) (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 153714052AF; Tue, 15 Sep 2026 20:58:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.198.46 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505904; cv=fail; b=iF1orcoF+cbSDo1rYdqig59mWoaFweMZFn4povjFi565Mk42d8/7DTzFgnXdrm763xrb2p+0JddhhZGd4Erx9ISo2GqDK1XtU6L4HkrCL2fDVKWR4KBTfyLuH2WUfxapFOw5daeKIRJ84si2Qo47oUhmWlmQfIa0zLCeqG3+pmI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505904; c=relaxed/simple; bh=enu+If6GhGZz1FD2UOuYLO1JEKzke6vsLtBz8fA7L2g=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=tISTa/tHMMraKUQwc9icbMET8lBIlrkR/l0w1M/e5+l8DyMppJ7PmjdmMkz7jS3HekXr/nhrJdwLs1IXE88TdU77Tmv185QVRYa/upuyk7x6fvighu2Y6L8ELIKWJnEfTPJQAd1Tkw3qdynh/BUAZpc6B39HBdTlMtrtowfAXCU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=OdLCtlan; arc=fail smtp.client-ip=40.93.198.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="OdLCtlan" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=cIwomLdeoZ8jcyPt2rKwKUzwcOlDq2qRjcdMhhgguvKUGBgjj1t8fUHj9FFIN7ctkQsBOrwVLFg3l5Guh/UKAnu552rLWcG0eocqJKTZ70mWxnnZ2OFGY8+y1RFfBz0mDheafobacYQAHuQUJvVXyECWbgUgkiOOFJX4m51gw0LLRXrQKgmJv5CaXOxE2nzRO2cKxTroWX25mc6QrcHfuf1dkLmP8pElCDaS5DqnxIrsgedI5sAXR6ITzp3Z/dhZntlL0n36ko8/04QIC+yPaJ7NVyZI1eRIoiCiZTCuZGcaHlYb7autlm2yIZpn7mYTIhQ9rXnGcfEghiDsgS9C2g== 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=yIXAzzqoQ0vtVIWPX8D3EGJyxH/EGYUXiyd/KFiJ1yk=; b=s6qDQhlGdLb0WDMBUjKepwJVc4CnbrBl7EoKL/1JXvr+kOtfAKUZAt0WBy4Hj6s1ad4o5YoNpa1WKmmc3toes/tfLGRNaryCTC0xXR/0RElWQctu/VbnoMEd93grfJRniN5sCuMRNBEtFdEPrLGdikbe3HT3wHMfrguHho+QR33LaMvTEzL/9cP9S8WUHA8Djeqp0FMWhf31o4Dzc6Kd8NSzOISUULwvZzRYgC6nRNiQCG/yYWHg+Si0LdRKqwzFzekqc+jMKjpSwc62cFnC1gF4xa0FthACNfSOS+YvpSjRwRJOoddv6ZFwkw8IGv/WLcO2aHnBdnXSeH51j+YCYQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.232) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=yIXAzzqoQ0vtVIWPX8D3EGJyxH/EGYUXiyd/KFiJ1yk=; b=OdLCtlan8CgXlcuoTqn0I2iPA/HMOoMChYCY4xxSDYlI/p6xTEQZD6ttaS2E/6OpG2KAZl68eyp63JSxwdEX2k7lU3Rja7aopqnrhOZmzEph3NISWJifgBB5iB57yMUQSQgax9ddhNSOYb16q/tcLJF6RISzckFpExMXQIwUxmfxEEYqRFsTy0lOaXfNxOokZ90Keav04nA2vtOWvFBTC84Ss+DMmqpBsDK2z0PT8GctyYe/l+O2tqRX7s143g4fPDy9Z9qw7Chd3B5SNhhJ8U42rXuGFPI1t4zvo+9llDGvgS3wnCGkCDYLi8zLViUP5CjWyROSSQvvFKEqjPqbYw== Received: from SJ0PR13CA0190.namprd13.prod.outlook.com (2603:10b6:a03:2c3::15) by CHAPR12MB999249.namprd12.prod.outlook.com (2603:10b6:610:300::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.11; Tue, 15 Sep 2026 20:58:17 +0000 Received: from BY1PEPF0001AE1D.namprd04.prod.outlook.com (2603:10b6:a03:2c3:cafe::4f) by SJ0PR13CA0190.outlook.office365.com (2603:10b6:a03:2c3::15) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.9 via Frontend Transport; Tue, 15 Sep 2026 20:58:17 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.232) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.232 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.232; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.232) by BY1PEPF0001AE1D.mail.protection.outlook.com (10.167.242.106) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:58:17 +0000 Received: from drhqmail202.nvidia.com (10.126.190.181) by mail.nvidia.com (10.127.129.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:57 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail202.nvidia.com (10.126.190.181) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:57:56 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:57:49 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Peter Colberg , Joel Fernandes , Zhi Wang Subject: [PATCH 06/14] rust: pci: add is_physfn(), to check for PFs Date: Tue, 15 Sep 2026 23:56:50 +0300 Message-ID: <20260915205659.76841-7-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BY1PEPF0001AE1D:EE_|CHAPR12MB999249:EE_ X-MS-Office365-Filtering-Correlation-Id: 3268aebb-f517-4e85-0677-08df136c10dd X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|7416014|376014|36860700016|1800799024|23010399003|82310400026|56012099006|11063799006|10067099003|6133799003|22082099003|18002099003; X-Microsoft-Antispam-Message-Info: 9lJ3w3hV1sizOfnNJ4wdBW3dgrXRrOFOFp22JMJoMwZdxq6OA/M7D94Ai7XEL2VYy6P+cXx1GlCxua3DGCflb1W/oL04dHJNk4PAeOnkKW2pQCrllOP5WNxqLRfUMKa2zFVcQlIn+MouyoC+Ohquj2RoBR3ipJt38OLsz4S5EK1P5guqYT2Igg+cpt991sp9CX6a3N9QIlbHRIwr/wYanIcdLcUf3Z38e+QXWEbQD+LZ1dYabYDHR/dS1sCCyRvv6VbqPJEbn/M+ZIEkghCDxAv3Sg8GSWpkJVFRW0INHcSx9/v9JWtzfF4iU4y4uLo9XioTUR3EhRqsVjJNRnecdtu+l+lsDQhaE6YubO+ViUML0SvuGT1KjIpBqgdCYXhwpDXyLDGJsnCJ+zongayHeT/bubfywqS/6l4Wb57ETBp4K+H9Zx2Fzb0b5yrLdOjG62K5TtB+xB3gmmVcViDxW+KT3L2iTsnDxauQPAa0y0Fck4yBzNuVAVFqptsHx1evAaezWyaGApiwShyALCKmQWVYsRZnoYfNnsD0YS3FHb2LVIwy3xKJsjR+3NIuDaoMvfzGJoWjNDphfL9IoW8uJJVQ4l9zB3ztem6Gm3pZjubSRwlTHGs26vIcmmYgBUQ7jrIgJ3cDTNBd4svq8AfBCZDh/tqnsV4iKWO3cUj/HKUVG6mmKWj0J3yiJ3u1fsDfU7eH1s/FvAXstUwyGPUGcA== X-Forefront-Antispam-Report: CIP:216.228.118.232;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge1.nvidia.com;CAT:NONE;SFS:(13230040)(7416014)(376014)(36860700016)(1800799024)(23010399003)(82310400026)(56012099006)(11063799006)(10067099003)(6133799003)(22082099003)(18002099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: ReG5XL9ni++y3hV6ac8KRZxKXyZ9uOvVGwtTD5Wz7owTClUMU+ZPwIM01LeY/CpVZYUlIJM17q+9gTDIYUfXwKR/HArbt4TU2Ytd9RpVU0oJJq/wkDMWmUE2ab3iV9obSJ+kyuUCrMuzhVzIMPyCq08wrQC5nIvttG/PBt4T2SgqrLcjg5kvcRcA7SgaCJolCqzf3nlKfT8ZQ6E8tMbY5g1WgMqdrYgSCtFFl3bShYkWOkA4mftIJ1yb5H2QBb7Fg2YUTXndBLMac6GPt7jNBotJYxoQjlsTqom4DwN+2kEw7/R1RZdpzXtHdZsZtYCfSveeswHiHAViswkiA5LV82iS+7qbyUbTdj0xbpbVKcBIUusP6lPG+Y3uRonakVetQK9PIHX36+wpxQxt29t67JGyjIvLfxSPeZn7g9V/szQbSg4mJZge5aD8RZqyFRer X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:58:17.0039 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 3268aebb-f517-4e85-0677-08df136c10dd X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.232];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: BY1PEPF0001AE1D.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CHAPR12MB999249 Content-Type: text/plain; charset="utf-8" From: Peter Colberg Add a method to check if a PCI device is a Physical Function (PF). zhiw: Keep this role check private to the PCI SR-IOV implementation instead of extending the public `Device` API. Add a dead-code expectation because this standalone API commit has no in-tree caller. Reviewed-by: Joel Fernandes Signed-off-by: Peter Colberg Signed-off-by: Zhi Wang --- rust/kernel/pci.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index 844d73a83670..ed42511911d7 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -507,6 +507,14 @@ pub fn resource_start(&self, bar: u32) -> Result { Ok(unsafe { bindings::pci_resource_start(self.as_raw(), bar.try_in= to()?) }) } =20 + /// Returns `true` if this device is a Physical Function (PF). + #[inline] + #[expect(dead_code)] + pub(crate) fn is_physfn(&self) -> bool { + // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. + unsafe { (*self.as_raw()).is_physfn() !=3D 0 } + } + /// Returns `true` if this device is a Virtual Function (VF). #[inline] #[expect(dead_code)] From nobody Fri Sep 25 06:46:56 2026 Received: from SJ2PR03CU001.outbound.protection.outlook.com (mail-westusazon11012016.outbound.protection.outlook.com [52.101.43.16]) (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 BE7BB4078E4; Tue, 15 Sep 2026 20:58:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.43.16 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505918; cv=fail; b=o14bBrgjQ+I9YNOMnt6B33Of7g6jnM7U3KpEnota7bpER/wmPTvPKbcSofrEUeaiegDhiWvpmSwU/0lGS6fEU2mje16KQNF70skAITbukYUBeVl14O2tlIiYdKYVkpMtvOz4/jNVHOyRrx0dwzuCk9KqspFdh5MPvcavm71X/A0= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505918; c=relaxed/simple; bh=Phqft+sj8b1tyXU2yiK2+TbcZSHILXgo9TAbkm+11MU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oLTPIVbmneGe+YoLivP6R218lZBnQa11ZzFNxy3yKcrb82/cxLr3Fz4HrUjJvs950eKWjT3nSMxohd/rJ6m+6T63kRMZOO8QaEglkKmmsuFJVZO+A/zaH4pOfejrG+hUaPxwOZA5r59XkIMcFmKXVrc3PKvBxPiRkDg/ThIk9gg= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=ZdTutd7g; arc=fail smtp.client-ip=52.101.43.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="ZdTutd7g" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=PA1P2CEvwxRIaEs9UCJFVQ41G085Hio8pxPDXj0D8qptgF8lbmL2A7eesz8G2WCaAZwUm2OUcdrlC73vZrEi3g+v1TGjmgJej2RNspi7RWwpJvppHf9I9VoqnJFY2p8syquXzUzfl1AC3pnhhGO6tCDk58zzCh45rRIU4h/WPKhVJg9+JN4+TcmyIXOK+9fQ3xabUzfVDeglxzPbTyH1lvqmzwgsREdNLfn7jpGFusDFDrULu90PxjeiiVryRVeBtsPR2KTGfVuaiiVjbTdnVnt4z7y+tCMU7/kkpWaP+mFzI5xWxlZpQLIEyc0moTuf3TrIATepAkp4w2L2mBcYvw== 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=slYFLAfdpSF6E+uRfebiDOLx6yzaWxm+KCZefbrwxEw=; b=HYMIwYoXDvRIeTO2mXPuHqDvP4Rf+6YUJLPlf+G4Vq9+/KjIGxCd9Of3IuVrcJJblOQnH6XnmXtiQrPe1Hq/AkXcm/hf/hw8mJaOFEHtVwx0m0Vbjv5uHPkBlz672fM4ERmeP/ZRuAs9tavOvq8K/PGzzGWEUpuwTdN+MlinSKBeS6cDUuC79vd1wvb4gtNCx86HgxMTfHoXXqlMVWCA/OsIVFVQjAaIwvXdnn0b6J+mmB9/jlEnPdgHmXg+4GUvBSVLf1wsttARd3V5iSeoZBoHSTpouPBGWQPWzFj3EZeDeYgLB3CwhisU/SbOls0hbetBa117UwGo6L332VHxig== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.233) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=slYFLAfdpSF6E+uRfebiDOLx6yzaWxm+KCZefbrwxEw=; b=ZdTutd7gofQK26e8DLzk1fy2X/yHOEJMQLE9dI2iS0Sg1om+SJECOdXE/TvJ1lde2x4LQYQG93zBHXjFjxcgd3w6aGhFlOTdwIohzeFQmkX1Si6N27Gv0XB2YQBS+xb8ALu0JdsTzge/xAjYD9FgjWFOFXa4WGnQx72Bh7jS6dnCrHDG8ORUl3YGDmSGTXcjEWSlOlGeGiDA3lf9ojd1h0qWrRaFQCRDB59Kju0jMcRDCQEG4RKlc0eNJM2eBQ9fN88yDOF5f4XOoEJzivciXeh39DoqCbMciEWzzAzTfA3u9qEKE69+NhJYhO/bRho8ukKDpjIzpGNJq0a0QyCpQA== Received: from SJ2P221CA0010.NAMP221.PROD.OUTLOOK.COM (2603:10b6:a03:5db::19) by SA3PR12MB9159.namprd12.prod.outlook.com (2603:10b6:806:3a0::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.9; Tue, 15 Sep 2026 20:58:28 +0000 Received: from CO1PEPF000075F2.namprd03.prod.outlook.com (2603:10b6:a03:5db:cafe::45) by SJ2P221CA0010.outlook.office365.com (2603:10b6:a03:5db::19) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.9 via Frontend Transport; Tue, 15 Sep 2026 20:58:28 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.233) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.233 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.233; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.233) by CO1PEPF000075F2.mail.protection.outlook.com (10.167.249.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:58:28 +0000 Received: from drhqmail201.nvidia.com (10.126.190.180) by mail.nvidia.com (10.127.129.6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:05 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail201.nvidia.com (10.126.190.180) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:04 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:57:57 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Peter Colberg , Zhi Wang Subject: [PATCH 07/14] rust: pci: add num_vf(), to return number of VFs Date: Tue, 15 Sep 2026 23:56:51 +0300 Message-ID: <20260915205659.76841-8-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000075F2:EE_|SA3PR12MB9159:EE_ X-MS-Office365-Filtering-Correlation-Id: cc6e966e-5dce-4f2c-fa20-08df136c179a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|23010399003|36860700016|82310400026|376014|1800799024|7416014|56012099006|11063799006|10067099003|22082099003|18002099003|6133799003; X-Microsoft-Antispam-Message-Info: ezIowKfblObDE06qCsAWwy9VuqM9n2y/k77ORd2oevx/+ttDSMLxN2WwR5ciRqujByZCw8J/BgnPmT8I1F5w67+rCaFEpbo6rf9iFk81WEhbyuj+itQeLs3eLy1rPQU27pUZi4ZxKjSRqvgdUTvAH0QptnfxK+LdFBibf97mhTWVosIwPsqmz0cV9iI4viXTCnIx4/y3xFBa7LCPgAfvdIp2yJARkKPwXlKv2dNtz2nV1RoblaPfKow0ESZMPYymfaOYFS0X3nz2AQ6GC8u9YRIg44mGZodyHi3C8r3LSv6zsWNzoD/ZOKLB3c/TKJ7ZDYhUwGa6VScAqn/4OR7Xe8meZP12NL7q2urBRscw98NmlFFVazdfiPLnQ4x3PWKnaNqcVlW5QdLc/SB/VzPN+THDYuMBRjRByDIHxD3byg26Bre95krJPF2mC29iKZHzn0xDfglqYTSs9Laf1GNh5DLbOs6wwp7gnx5OrQe9l4NcTITYoEGhGpAwPI632JwI6R/57HXgta9EedaevwC9/MIN+Fsn6nABafnWJ223FhdA61PBnUs32lil1pzIhFFnF/H4hWeDgLkxME6oOXQ4neFFemJb0M2/tW9P9oNHsrUCSATLnwIuQpcRLisYBZVZC42TXvLMZDKz5BYLitr6+2wJNjyeqQ5VTHHH3AHmHgGMAq+8SD3wk9kWmIx+HLxz5qQckS3dBupwDjCe6bcu0g== X-Forefront-Antispam-Report: CIP:216.228.118.233;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge2.nvidia.com;CAT:NONE;SFS:(13230040)(23010399003)(36860700016)(82310400026)(376014)(1800799024)(7416014)(56012099006)(11063799006)(10067099003)(22082099003)(18002099003)(6133799003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 6LE+L2n3w0sPqCAz7zdywjhxalr232eat60ShIvnYRNXsr8uxzVyC5jukJPG5Y47fP1RmFewcbenoJLfedN4/G07pUoxzB5CY5hjFBSb/UPV87dXVN3IbAhTD9p1Gz86BOHcFmF4r1IAYmDSPllVH5/n2hCj/6KMxNge29b4Jg+TfgZpJ96rzbiCOPegaag873bCy2rd8lqmqIh9QGAIAfyQmsYZg9zhY3JPED4mVnZsEztpW33foQslEe6gYi/7aQC+Js/6TaR2qGHL1LMcQoXE+hcqVKLXcPaZFj9IN3j9TUmV2YtB+Fte/wxXKu39siS9C8eygBZQlRA2RgPr2fO6mOW+J+RgpypkFYp2up61XyWaGUNnncU0srtMFCrBTMc4UpwjIs2ir6U9rklCnUvOm9RAvCqWyYRhyUDtF6wHWNT54I86qTqIIazluEgP X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:58:28.2354 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: cc6e966e-5dce-4f2c-fa20-08df136c179a X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.233];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000075F2.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA3PR12MB9159 Content-Type: text/plain; charset="utf-8" From: Peter Colberg Add a method to return the number of Virtual Functions (VF) enabled for a Physical Function (PF). zhiw: Keep this helper private to the PCI SR-IOV implementation instead of extending the public `Device` API. Add a dead-code expectation because this standalone API commit has no in-tree caller. Signed-off-by: Peter Colberg Signed-off-by: Zhi Wang --- rust/kernel/pci.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index ed42511911d7..f2d71daef83a 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -523,6 +523,14 @@ pub(crate) fn is_virtfn(&self) -> bool { unsafe { (*self.as_raw()).is_virtfn() !=3D 0 } } =20 + /// Returns the number of Virtual Functions (VF) enabled for a Physica= l Function (PF). + #[cfg(CONFIG_PCI_IOV)] + #[expect(dead_code)] + pub(crate) fn num_vf(&self) -> i32 { + // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. + unsafe { bindings::pci_num_vf(self.as_raw()) } + } + /// Returns the size of the given PCI BAR resource. pub fn resource_len(&self, bar: u32) -> Result { if !Bar::index_is_valid(bar) { From nobody Fri Sep 25 06:46:56 2026 Received: from CH1PR05CU001.outbound.protection.outlook.com (mail-northcentralusazon11010070.outbound.protection.outlook.com [52.101.193.70]) (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 C38814A2638; Tue, 15 Sep 2026 20:58:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.193.70 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505940; cv=fail; b=t0PtinXDo5mfmntBUSzIWpA1W39SSquskkEVJmg8etxf5iWwJnkuEMv6bK7IAEj37vuaHXWsBAX8GTriml1iWeu3CGNY0bpzF7nHygav/IiixiyNjePJkB1UpRS2EOHxr4OkqfjPxNjeOiZduvS037sMzpYaPreP9U1u7rmimoI= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505940; c=relaxed/simple; bh=0vm/IVja61Xk/JoSTJ0MgsmYaqIZQoBtIkNIFTefg+U=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ZHxfhMAnZmw/wktGcUOH5jOjccj5/NN1BgWppUoQh/0tVZ3Nt/2SJtISfJb219AZ1sqo1cuUoy/gQuNYX8Gg2z2Sla0tGFLSqpTFcXGr375uulv+gWc7GCu610UQz59/YFtqeneVcK2YtQ5NGiqt2i00w9LhaJrHBU9PKPi5J8k= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=f7vM3z/w; arc=fail smtp.client-ip=52.101.193.70 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="f7vM3z/w" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Xft9p4f19a/PbAdq/sTS7BbKMN8064cYCXg3/ZNskQAnaNBzzvitYc+QfLwvMWTd7O9E9FoO1kx1lUDMm6VRz4sV0J5ChOr+UVms7Fk5L1sUQiAbLiqrzdyMps72fCCRJC/RbW5RpwZCiHs1gNSyNWjc1hJso4w0+2FNV2sLRO/hkeMpnzjysDYw2z81xMDGXmh23wZdno3mCj6KEJso1aiDb3taPn2XFrhb53tOKlLK9/eRKPexwP0mBEaGwCVDme880D5Ziv/tL9Wn5A36p3weDmPZInjpxpQACHsoHS5Hm5+uzr4Vbp/W3SSKWqeE8182EgEjvepKLWX6XSatgQ== 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=Ur0wIalZLSJpV+OsGWLrSR1OwRCMyjVMx2jiCw6elDU=; b=cnXudBo4WdZ0HaOme862qY+VvL/njeDNv5DfCVE/ep2drCoKF3fTyrDm0t6Y0wSWg63h5i/TCKk6umaDTW+mEEoV6T+hsyh0KPI9tXRreZ4kpilxIcqVitFq9zWsl/M6KeXiIKvwDFhUsMVn3pBswb1VjlvXHuq4Z0Fm1YR7DNs2x6IEPb+0uQ7MLcQLSvjvXI6GQPDpbeoGowiVDgJujQ/kFVBxVIKbQb96Wrt8btHvEpWcJTV00A9lrbOKT3gADRX/i/rBVaghJRjVC1LD2kmGxQW9w5+MpnWyS+7y2+/Xa7Ki02Xeb7tBRFJzqeg734D6EHc/NQlhx7h9RuQ4fQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.233) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Ur0wIalZLSJpV+OsGWLrSR1OwRCMyjVMx2jiCw6elDU=; b=f7vM3z/wOg6NHPdh4HDP85Ogwaj6kC1vj9BVKDpVeTMJO/2uDGicjXIw8ACi7ahmAa1DiMAGWqKBhl7kmCFtewfy/OsFGtAI4X7F/z2yr7cgW7l+CqMp5jMyTBf54LlBEZTyyg92oUAbc3G+z1X+1qah2V9h3UX7NQdrupn6U5ymjDaPheEp0CXGkZBGkI/ITAoTyTGrry33t3ienE+RhG+HUKMr/2CocbzLaB5oLSGDET8AgkZMGA5UnURL37k35AWvkq8+YdTOpEv7jpKMfvhObH/5LmBeAvfC2oPa2zwQ8fdlkMHUTjKhcHIGEsjoVDwi4+t/euojkvV3iwyQnw== Received: from SJ0PR03CA0041.namprd03.prod.outlook.com (2603:10b6:a03:33e::16) by PH7PR12MB5735.namprd12.prod.outlook.com (2603:10b6:510:1e2::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.406.12; Tue, 15 Sep 2026 20:58:41 +0000 Received: from CO1PEPF000075F3.namprd03.prod.outlook.com (2603:10b6:a03:33e:cafe::65) by SJ0PR03CA0041.outlook.office365.com (2603:10b6:a03:33e::16) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.406.12 via Frontend Transport; Tue, 15 Sep 2026 20:58:40 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.233) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.233 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.233; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.233) by CO1PEPF000075F3.mail.protection.outlook.com (10.167.249.42) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:58:40 +0000 Received: from drhqmail202.nvidia.com (10.126.190.181) by mail.nvidia.com (10.127.129.6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:13 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail202.nvidia.com (10.126.190.181) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:12 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:58:05 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Zhi Wang Subject: [PATCH 08/14] rust: pci: add typed SR-IOV PF registration data Date: Tue, 15 Sep 2026 23:56:52 +0300 Message-ID: <20260915205659.76841-9-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000075F3:EE_|PH7PR12MB5735:EE_ X-MS-Office365-Filtering-Correlation-Id: 55b35334-6129-403f-ec7f-08df136c1ef0 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|23010399003|376014|7416014|1800799024|82310400026|36860700016|6133799003|18002099003|22082099003|13003099007|3023799007|10067099003|56012099006|5023799004|11063799006; X-Microsoft-Antispam-Message-Info: o5SphEeJT7elqO1JLMuvMFsHuCSaGku947EKgpGqMob0/XQo0ORepSw+CNvNTl30kJI+ZT1CHEoyjc8CBV1y713Ruu1wV1WY7mJuKlodX1nRSFi3Q6v8m9p4sWSDfTJzIFiKIsKyIajQtKK9ck0KKYB9K2TS3dUQ2w4Eewtry9VsUszKDgvReluWKcxNSSl4EPxpp3VVZOJ15OcdUzSZjVDDOq7Jy0Z5NXs1YvRjym3Hxnbufd3yUZPeRv2N+J4El3C01pNrBoyl1il2CGj09p/NdOI0kUIFl5WOWQvfDGazw410UWdjI/p0+BoMa+C7VDbgR7nzud+JsioxtxKQFFDOs4Z3OcwI29UG71bd8kZRNRNtV1hic5AalsfMhBBmyb69fvytXM2x/yM+6AL6lbjp2L+e6+GboqoqR9E3g4sPB8sNwbmjmsyfxk5PwOGypvkdt8uddcQRsbGgpOJICYBMdPE/eqrIgIk84mcC1S7o64Am6bmBCjJ2IwT50HlVRwqr7t4HJJinMupyvJaX2XQWZxsH4VIS+pbhzpPMIYR/vHuP+6QLJAY4mNyHvaw/QkPSnvyJj42g9rORQPMllcj3+uDeTmc4XXUFdyd/aqwPPVfi2fZMQDd9CbEbMW5D89lF5qFDop/75t47xGr4+6oya2vhrxgWP+FlWOrKG8aKCdoZK513F3aJLlDZ+4OthfobJB2thOpVGKKtpWR78g== X-Forefront-Antispam-Report: CIP:216.228.118.233;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge2.nvidia.com;CAT:NONE;SFS:(13230040)(23010399003)(376014)(7416014)(1800799024)(82310400026)(36860700016)(6133799003)(18002099003)(22082099003)(13003099007)(3023799007)(10067099003)(56012099006)(5023799004)(11063799006);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: nppHVbg9UF8pZk5QZvvgteEdJ+i69Dh7dzsYW06wOJLzIX/FgftK/DUxCRIeKV9xitFIhpvKLX5LRyZ6iHwwIvrBW1ssxO6dlvJrtMroaHaKhBlloe0uKDSlBydCzOk9QEVbThcn0grtMS/VYn/nXj1B0nIuY2jMx/aHDVs07nQmp2BAMqpnLdLgxk3j2JHrCOdLEqK+hGsADX8HTzY4VChX/YZXSOHVow5Ve2U1yZtSPuNIl+AEgdy+RXt9XyP/HdiF6DinJt+1HMb7eIpyqOMKsiLsq40MXrA67BLzNkM5xD29QON6KOodC8KnATksM41Ny/5GP2XbSMLMeeCe6Yau+doBRaEoH1gOH508m9YbaayW0jNk5fsUGZ6Xb6pBxHjiGibhZbr9dsR7+wtNCdJ6swLui1do+ruy79oQ+jMtnHvlbQIbcaDqZBzo4cyM X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:58:40.5377 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 55b35334-6129-403f-ec7f-08df136c1ef0 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.233];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: CO1PEPF000075F3.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5735 Content-Type: text/plain; charset="utf-8" A VF driver may need to invoke PF-owned functionality without gaining access to all private data belonging to the PF driver. The PCI device alone cannot identify the restricted data type or express how long a borrow remains valid. Add a Rust registration slot to `struct pci_dev` and `VfRegistration` to publish a `ForLt`-encoded payload. The registration is initialized and pinned inline in the PF driver data, then publishes its address as the final step of its own initialization. It remains inactive on conventional PCI functions and rejects VFs. Check that no VFs or other registration exist before publication. Pinned drop disables SR-IOV before withdrawing the pointer and dropping the payload. Managed SR-IOV ordering additionally removes every VF before PF unbind. Add `vf_registration_data_with()` for higher-ranked access and `vf_registration_data()` for covariant data. `TypeId` rejects mismatched Rust types without exposing the PF device or its complete driver data. Keep SR-IOV operations behind a verified `pci::sriov::Device` view and pass a pinned reference to the PCI driver data into `sriov_configure()`. PF and VF consumers continue to use the ordinary `pci::Driver` abstraction. Expose `is_virtfn()` so PF drivers can reject VFs before initializing hardware and publishing their registration. Co-developed-by: Danilo Krummrich Signed-off-by: Danilo Krummrich Signed-off-by: Zhi Wang --- include/linux/pci.h | 6 + rust/kernel/pci.rs | 69 +++++---- rust/kernel/pci/sriov.rs | 299 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 345 insertions(+), 29 deletions(-) create mode 100644 rust/kernel/pci/sriov.rs diff --git a/include/linux/pci.h b/include/linux/pci.h index bc0d36204940..1ccc7fee7495 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -352,6 +352,9 @@ struct rcec_ea; * Such bridges are allocated additional MMIO and bus * number resources to allow for hierarchy expansion. * @is_pciehp: PCIe Hot-Plug Capable bridge. + * @vf_registration_data_rust: Rust registration data published by the PF + * before enabling VFs and retained until all VFs are + * removed. The PF driver must use managed_sriov. */ struct pci_dev { struct list_head bus_list; /* Node in per-bus list */ @@ -551,6 +554,9 @@ struct pci_dev { u16 ats_cap; /* ATS Capability offset */ u8 ats_stu; /* ATS Smallest Translation Unit */ #endif +#if defined(CONFIG_PCI_IOV) && defined(CONFIG_RUST) + void *vf_registration_data_rust; +#endif #ifdef CONFIG_PCI_PRI u16 pri_cap; /* PRI Capability offset */ u32 pri_reqs_alloc; /* Number of PRI requests allocated */ diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs index f2d71daef83a..46edc8007d78 100644 --- a/rust/kernel/pci.rs +++ b/rust/kernel/pci.rs @@ -37,6 +37,8 @@ mod id; mod io; mod irq; +#[cfg(CONFIG_PCI_IOV)] +pub mod sriov; =20 pub use self::cap::{ ExtCapId, @@ -64,6 +66,8 @@ IrqVector, IrqVectorRegistration, // }; +#[cfg(CONFIG_PCI_IOV)] +pub use self::sriov::VfRegistration; =20 /// An adapter for the registration of PCI drivers. pub struct Adapter(T); @@ -160,13 +164,18 @@ extern "C" fn sriov_configure_callback( pdev: *mut bindings::pci_dev, nr_virtfn: c_int, ) -> c_int { - // SAFETY: The PCI bus only ever calls the sriov_configure callbac= k with a valid pointer to - // a `struct pci_dev`. - // - // INVARIANT: `pdev` is valid for the duration of `sriov_configure= _callback()`. + // SAFETY: The PCI bus invokes this callback with a valid device b= ound to this driver. The + // `CoreInternal` context is valid for the callback's duration. let pdev =3D unsafe { &*pdev.cast::>>() }; =20 - from_result(|| T::sriov_configure(pdev, nr_virtfn)) + // SAFETY: `sriov_configure` is called only after a successful pro= be and before unbind, so + // the stored pointer has type `T::Data<'_>` and remains valid thr= oughout this callback. + let data =3D unsafe { pdev.as_ref().drvdata_borrow::>(= ) }; + + from_result(|| { + let dev =3D sriov::Device::try_from_pci(pdev)?; + T::sriov_configure(dev, data, nr_virtfn) + }) } } =20 @@ -355,41 +364,44 @@ fn unbind<'bound>(dev: &'bound Device>, this: Pin<&Self::Data<' let _ =3D (dev, this); } =20 - /// Single Root I/O Virtualization (SR-IOV) configure. + /// Configures Single Root I/O Virtualization (SR-IOV) for a Physical = Function (PF). /// - /// Called when a user-space application enables or disables the SR-IO= V capability for a - /// [`Device`] by writing the number of Virtual Functions (VF), `nr_vi= rtfn` or zero to the - /// sysfs file `sriov_numvfs` for this device. Implementing this callb= ack is optional. + /// The PCI core invokes this callback when userspace writes the numbe= r of Virtual Functions + /// (VFs), or zero, to the PF's `sriov_numvfs` sysfs file. For managed= SR-IOV it is also called + /// with zero before [`Self::unbind`] when the PF still has enabled VF= s. /// - /// Further, and unlike for a PCI driver written in C, when a PF devic= e with enabled VFs is - /// unbound from its bound [`Driver`], the `sriov_configure()` callbac= k is invoked to disable - /// SR-IOV before the `unbind()` callback. This guarantees that when a= VF device is bound to a - /// driver, the underlying PF device is bound to a driver, too. + /// `dev` is a verified SR-IOV PF in the [`device::Core`] callback con= text. It can be converted + /// to the underlying PCI device through [`sriov::Device::as_pci`]. `t= his` is the private data + /// returned by [`Self::probe`]. Both remain valid for the duration of= the callback. /// - /// Upon success, this callback must return the number of VFs that wer= e enabled, or zero if - /// SR-IOV was disabled. - /// - /// See [PCI Express I/O Virtualization]. - /// - /// [PCI Express I/O Virtualization]: https://docs.kernel.org/PCI/pci-= iov-howto.html + /// Upon success, return the number of VFs that were enabled, or zero = if SR-IOV was disabled. /// /// # Examples /// /// ``` /// # use kernel::{device::Core, pci, prelude::*}; - /// #[cfg(CONFIG_PCI_IOV)] - /// fn sriov_configure(dev: &pci::Device>, nr_virtfn: i32) ->= Result { + /// # struct Data; + /// fn sriov_configure( + /// dev: &pci::sriov::Device>, + /// _this: Pin<&Data>, + /// nr_virtfn: i32, + /// ) -> Result { /// if nr_virtfn =3D=3D 0 { /// dev.disable_sriov(); /// } else { /// dev.enable_sriov(nr_virtfn)?; /// } + /// /// Ok(nr_virtfn) /// } /// ``` #[cfg(CONFIG_PCI_IOV)] - fn sriov_configure(dev: &Device>, nr_virtfn: i32) -> = Result { - let _ =3D (dev, nr_virtfn); + fn sriov_configure<'bound>( + dev: &'bound sriov::Device>, + this: Pin<&Self::Data<'bound>>, + nr_virtfn: i32, + ) -> Result { + let _ =3D (dev, this, nr_virtfn); build_error!(crate::error::VTABLE_DEFAULT_ERROR) } } @@ -508,24 +520,23 @@ pub fn resource_start(&self, bar: u32) -> Result { } =20 /// Returns `true` if this device is a Physical Function (PF). + #[cfg(CONFIG_PCI_IOV)] #[inline] - #[expect(dead_code)] pub(crate) fn is_physfn(&self) -> bool { // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. unsafe { (*self.as_raw()).is_physfn() !=3D 0 } } =20 /// Returns `true` if this device is a Virtual Function (VF). + #[cfg(CONFIG_PCI_IOV)] #[inline] - #[expect(dead_code)] - pub(crate) fn is_virtfn(&self) -> bool { + pub fn is_virtfn(&self) -> bool { // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. unsafe { (*self.as_raw()).is_virtfn() !=3D 0 } } =20 /// Returns the number of Virtual Functions (VF) enabled for a Physica= l Function (PF). #[cfg(CONFIG_PCI_IOV)] - #[expect(dead_code)] pub(crate) fn num_vf(&self) -> i32 { // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. unsafe { bindings::pci_num_vf(self.as_raw()) } @@ -593,7 +604,7 @@ pub fn set_master(&self) { /// Enable the Single Root I/O Virtualization (SR-IOV) capability for = this device, /// where `nr_virtfn` is number of Virtual Functions (VF) to enable. #[cfg(CONFIG_PCI_IOV)] - pub fn enable_sriov(&self, nr_virtfn: i32) -> Result { + pub(crate) fn enable_sriov(&self, nr_virtfn: i32) -> Result { // SAFETY: // `self.as_raw` returns a valid pointer to a `struct pci_dev`. // @@ -609,7 +620,7 @@ pub fn enable_sriov(&self, nr_virtfn: i32) -> Result { =20 /// Disable the Single Root I/O Virtualization (SR-IOV) capability for= this device. #[cfg(CONFIG_PCI_IOV)] - pub fn disable_sriov(&self) { + pub(crate) fn disable_sriov(&self) { // SAFETY: // `self.as_raw` returns a valid pointer to a `struct pci_dev`. // diff --git a/rust/kernel/pci/sriov.rs b/rust/kernel/pci/sriov.rs new file mode 100644 index 000000000000..efbe444e0733 --- /dev/null +++ b/rust/kernel/pci/sriov.rs @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Abstractions for PCI Single Root I/O Virtualization (SR-IOV) drivers. + +use super::Device as PciDevice; +use crate::{ + bindings, + device, // + prelude::*, + types::{ + CovariantForLt, + ForLt, // + }, +}; +use core::{ + any::TypeId, + marker::PhantomPinned, + num::NonZero, // +}; + +/// A PCI Physical Function (PF) with an SR-IOV capability. +/// +/// This capability view is created only after the PCI abstraction verifie= s that the device is an +/// SR-IOV PF. Its device context follows the same hierarchy as [`PciDevic= e`]. +#[repr(transparent)] +pub struct Device(PciDevice= ); + +impl Device { + pub(super) fn try_from_pci(pdev: &PciDevice) -> Result<&Self> { + // SAFETY: `pdev.as_raw()` is a valid pointer to a `struct pci_dev= `. + if unsafe { (*pdev.as_raw()).is_physfn() =3D=3D 0 } { + return Err(ENODEV); + } + + // CAST: `Device` is a transparent capability view of `PciDevice` = with the same context. + // SAFETY: The check above establishes the PF invariant, and the r= eturned reference cannot + // outlive `pdev`. + Ok(unsafe { &*core::ptr::from_ref(pdev).cast() }) + } + + /// Returns the underlying PCI device with the same device context. + #[inline] + pub fn as_pci(&self) -> &PciDevice { + &self.0 + } +} + +impl AsRef> for Device { + #[inline] + fn as_ref(&self) -> &PciDevice { + self.as_pci() + } +} + +impl AsRef> for Device { + #[inline] + fn as_ref(&self) -> &device::Device { + self.as_pci().as_ref() + } +} + +impl<'a> Device> { + /// Returns the total number of VFs, or [`None`] if SR-IOV is unavaila= ble. + #[inline] + pub fn total_vfs(&self) -> Option> { + self.as_pci().sriov_get_totalvfs() + } + + /// Enables `nr_virtfn` Virtual Functions (VFs). + #[inline] + pub fn enable_sriov(&self, nr_virtfn: i32) -> Result { + self.as_pci().enable_sriov(nr_virtfn) + } + + /// Disables all Virtual Functions (VFs). + #[inline] + pub fn disable_sriov(&self) { + self.as_pci().disable_sriov(); + } +} + +impl Device { + /// Returns the number of currently enabled Virtual Functions (VFs). + #[inline] + pub fn num_vfs(&self) -> i32 { + self.as_pci().num_vf() + } +} + +// SAFETY: `Device` is a transparent wrapper around `PciDevice`, and neith= er type's layout +// depends on its device context. +kernel::impl_device_context_deref!(unsafe { Device }); + +#[repr(C)] +#[pin_data] +struct VfRegistrationData<'a, F: ForLt + 'static> { + type_id: TypeId, + #[pin] + data: F::Of<'a>, +} + +static_assert!( + core::mem::offset_of!(VfRegistrationData<'static, CovariantForLt!(())>= , type_id) =3D=3D 0 +); + +impl<'a, F: ForLt + 'static> VfRegistrationData<'a, F> { + fn new(data: D) -> impl PinInit + use<'a, D, F> + where + D: PinInit, Error> + 'a, + { + try_pin_init!(Self { + type_id: TypeId::of::(), + data <- data, + }) + } +} + +/// Typed data published by a Physical Function (PF) for its Virtual Funct= ions (VFs). +/// +/// The registration is initialized in place as part of the PF driver's pi= nned data. On an SR-IOV +/// PF it publishes the inline payload after initialization; on a conventi= onal PCI function it is +/// inactive. A VF is rejected. Bound VFs access the payload through +/// [`PciDevice::vf_registration_data()`] or [`PciDevice::vf_registration_= data_with()`]. +/// +/// Managed SR-IOV removes all VFs before the PF driver is unbound. As a f= allback, pinned drop also +/// disables SR-IOV before withdrawing the payload. +#[pin_data(PinnedDrop)] +pub struct VfRegistration<'a, F: ForLt + 'static> { + pdev: &'a PciDevice, + #[pin] + inner: VfRegistrationData<'a, F>, + published: bool, + #[pin] + _pin: PhantomPinned, +} + +impl<'a, F: ForLt + 'static> VfRegistration<'a, F> +where + for<'b> F::Of<'b>: Send + Sync, +{ + /// Publishes typed PF data for bound VF drivers. + /// + /// This returns a pin-initializer so the registration and payload can= be embedded directly in + /// the PF driver's pinned data. + /// + /// Initialization returns [`ENODEV`] for a VF and [`EBUSY`] if the PF= has enabled VFs or + /// already has a registration. + /// + /// # Safety + /// + /// The caller must invoke this during the PCI driver's probe and embe= d the result in the driver + /// data. On an SR-IOV PF, no VF may be enabled before probe successfu= lly installs the complete + /// driver data, and the driver must use managed SR-IOV. The registrat= ion must be dropped before + /// anything its payload borrows and must not be forgotten. Probe must= have exclusive access to + /// the PF registration slot. On a conventional PCI function, the regi= stration remains + /// inactive. + pub unsafe fn new<'core, D>( + pdev: &'a PciDevice>, + data: D, + ) -> impl PinInit + use<'a, 'core, D, F> + where + D: PinInit, Error> + 'a, + { + pin_init::pin_init_scope(move || { + if pdev.is_virtfn() { + return Err(ENODEV); + } + + let published =3D pdev.is_physfn(); + if published { + if pdev.num_vf() !=3D 0 { + return Err(EBUSY); + } + + if !pdev.vf_registration_data_rust().is_null() { + return Err(EBUSY); + } + } + + Ok(try_pin_init!(Self { + pdev, + inner <- VfRegistrationData::new(data), + published, + _pin: PhantomPinned, + _: { + if *published { + pdev.set_vf_registration_data_rust( + core::ptr::from_ref(inner.as_ref().get_ref()).= cast_mut().cast(), + ); + } + }, + })) + }) + } +} + +#[pinned_drop] +impl PinnedDrop for VfRegistration<'_, F> { + fn drop(self: Pin<&mut Self>) { + if !self.published { + return; + } + + // SAFETY: `self.pdev` is the PF on which this registration was pu= blished. The call is a + // no-op on the normal managed-SR-IOV teardown path, where all VFs= are already disabled. + unsafe { bindings::pci_disable_sriov(self.pdev.as_raw()) }; + self.pdev + .set_vf_registration_data_rust(core::ptr::null_mut()); + } +} + +// SAFETY: The registration and its inline payload may be released from an= other thread after the +// PCI core has removed all VFs. +unsafe impl Send for VfRegistration<'_, F> where for<'a> F::Of<'= a>: Send {} + +// SAFETY: VF consumers receive shared references only, and the payload su= pports shared access. +unsafe impl Sync for VfRegistration<'_, F> where for<'a> F::Of<'= a>: Send + Sync {} + +impl PciDevice { + fn vf_registration_data_rust(&self) -> *mut core::ffi::c_void { + // SAFETY: `self.as_raw()` is a valid pointer to a `struct pci_dev= `. + unsafe { (*self.as_raw()).vf_registration_data_rust } + } + + fn set_vf_registration_data_rust(&self, data: *mut core::ffi::c_void) { + // SAFETY: Publication and withdrawal are serialized by PCI probe = and managed teardown. + unsafe { (*self.as_raw()).vf_registration_data_rust =3D data }; + } +} + +impl PciDevice { + /// # Safety + /// + /// The returned borrow must be confined by a closure higher-ranked in= dependently over its + /// borrow and data lifetimes, or `F` must be covariant in its encoded= lifetime. + unsafe fn vf_registration_data_pinned(&self) -> Re= sult>> { + if !self.is_virtfn() { + return Err(ENODEV); + } + + // SAFETY: A VF's `physfn` pointer remains valid for the VF's life= time. Managed SR-IOV also + // keeps the PF driver bound until this VF is unbound. + let pf_dev =3D unsafe { (*self.as_raw()).__bindgen_anon_1.physfn }; + if pf_dev.is_null() { + return Err(ENODEV); + } + + // SAFETY: The PF cannot withdraw the pointer until managed teardo= wn has removed this VF. + let ptr =3D unsafe { (*pf_dev).vf_registration_data_rust }; + if ptr.is_null() { + return Err(ENOENT); + } + + // SAFETY: The published pointer addresses a `VfRegistrationData`,= whose first field is a + // `TypeId`. + let type_id =3D unsafe { ptr.cast::().read() }; + if type_id !=3D TypeId::of::() { + return Err(EINVAL); + } + + // SAFETY: The type check identifies `F`; lifetime parameters do n= ot affect layout, and the + // inline data remains pinned for this VF borrow. + let data =3D unsafe { + let registration =3D ptr.cast::>(); + &raw const (*registration).data + }; + + // SAFETY: `data` is structurally pinned in the PF driver's pinned= registration. + Ok(unsafe { Pin::new_unchecked(&*data) }) + } + + /// Accesses typed data published by this VF's PF through a closure. + /// + /// Returns [`ENODEV`] if this device is not a VF, [`ENOENT`] if its P= F has not published + /// data, or [`EINVAL`] if the registered type does not match `F`. + /// + /// The closure's borrow and the registration data's lifetime are inde= pendent, so a borrow of + /// the context cannot be stored in invariant registration data. + pub fn vf_registration_data_with( + &self, + f: impl for<'borrow, 'data> FnOnce(Pin<&'borrow F::Of<'data>>) -> = R, + ) -> Result { + // SAFETY: The higher-ranked closure prevents the borrow from esca= ping or being stored in + // invariant data by keeping its lifetime independent of the erase= d data lifetime. + let data =3D unsafe { self.vf_registration_data_pinned::()? }; + Ok(f(data)) + } + + /// Returns typed data published by this VF's PF. + /// + /// This direct accessor is available only when the encoded data is co= variant in its lifetime. + /// Use [`Self::vf_registration_data_with()`] for invariant data. + /// + /// It returns the same errors as [`Self::vf_registration_data_with()`= ]. + pub fn vf_registration_data(&self) -> Res= ult>> { + // SAFETY: `CovariantForLt` permits shortening the encoded lifetim= e to this borrow. + unsafe { self.vf_registration_data_pinned::() } + } +} From nobody Fri Sep 25 06:46:56 2026 Received: from CY7PR03CU001.outbound.protection.outlook.com (mail-westcentralusazon11010055.outbound.protection.outlook.com [40.93.198.55]) (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 9DCD22B9BA; Tue, 15 Sep 2026 20:58:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.198.55 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505934; cv=fail; b=E9X1XGnWshiiBUwD6AOhtaXzbIYW6+JzhOUGmhVffMp0PNpy9VoFo1JEzcAhxts0Tavsn+3VPzJGCJCk2zh0wiM1peXk55+X4X5l/x5b+R0f2QhfgOBx5dfZMHXE7DxB8kcuov/8+X2F5peI4OCYxtCIZO21GCVk51WRlAKwUMc= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505934; c=relaxed/simple; bh=x3q3BOeuNy67iijUqBs5WXC9YTvX6+Cex39KRulHhfc=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NIDFmi/l5PkExnQ6qsuoZ6KrvQfyFDQLw3FOJUjqHPA9IrtpLq2woWOKDlq7M0YLcvUclQzr10GXhSD5kJWfqyZKTtHrOaoyC/45w5LuhzkaRcw82ir4Uj6RFkQivn+kU2AExeErVxh1+kF1P5+C0sOEZdek/836VKJFKGGcP4Q= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=YB4JXUPf; arc=fail smtp.client-ip=40.93.198.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="YB4JXUPf" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=aeB5ll1p+6T5o+jSJnsZDou5YOAG27YtraPgcE4IPaJEQg5Hncmd22nDkU/0COP1EAILM7LGGenZw6Et2bs/bbo4hgltlEWgt5OPcB7BXUy7oXVUphWZrvMg9ORW15CfAjjVgYP6G/2X92xhG4v71lCHG1i6cSjzj6TSUGaJYt+h7IFy8YZEAVm8rD7poz07OSk93cm63NH1GOgZSmnhSN2Y/MEVPFHvKTEjlg8Tp7NULLCm9O6WYabyO54w89jgnPwmA4NmW4FJaPh/WziH0DO7YnOMUiZAJuNBawNwIfavUB+O6DO9mS6w0iR/UXgREQKPpKkzqxrAFHDBtPWXBA== 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=88TsNAgqBy7WRNzcoEp8+ipP2HN5JX7XYGuQ+ml9mBE=; b=xy0Llu3IThmsk4A1/NZ/DfzGL40t5zOyHYEIGuBaT7kqTXVPa0x/ZoKQHkpZI5Foj4eEQh4pw2xIyRb1G/19jGfgX85xnP22k9lU55f0gXoimX4qluN+DLxOKysLUB1RPMGHH8KBiI7fgg5VREL9LUjQ04Uq+rZYfZ5aXM098yFwmdWmkPjjA2SJy+vLge6Cg4vJ5sNA5qNlTcgFdBoI1BnZhiyJbEV7KrGrvTrArimygXAPXHeu0bW9cvFPxKsZpCqsXqQ9zGFISfoiDUcfVA6VG18oonVGX8WD26WJ0GLOVUctKxY2tkFaXbsQcVVM6R/ttZRlbZtx+SCoRdGngQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.232) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=88TsNAgqBy7WRNzcoEp8+ipP2HN5JX7XYGuQ+ml9mBE=; b=YB4JXUPfGHvSMj7Qipd9eZIwRR4mr1X4eSOYCJ87ftuP3ZwIW508wkRmXfX8XvOtIuerhTV6+LgKB7rZXmr2Q3AGmvp2jL5QbipbNyNA6X25SZYsUqRsMezEV+2vsbQ6SCkvqztJAvJC09JUyCoqp+5SeJBcu9Nat5KrRcwTNp446NZylWl1ttdHQQl4IhBhFzublHwHv/82FLM/jed8Vrb+X+dUXSnVzFmXSSMbiJfTXMY3OQG82e6oS5asXFK+ZVZcKRd5jbq0MFkYQxndhKd7Ngd77h9phFpeEN+0mP5VcsBcXmYwjwk9WLSHhTSXa342hZpHqRXEIu/qSfBR0A== Received: from SJ0PR13CA0183.namprd13.prod.outlook.com (2603:10b6:a03:2c3::8) by SN7PR12MB8602.namprd12.prod.outlook.com (2603:10b6:806:26d::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.406.12; Tue, 15 Sep 2026 20:58:43 +0000 Received: from BY1PEPF0001AE1D.namprd04.prod.outlook.com (2603:10b6:a03:2c3:cafe::26) by SJ0PR13CA0183.outlook.office365.com (2603:10b6:a03:2c3::8) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.9 via Frontend Transport; Tue, 15 Sep 2026 20:58:42 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.232) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.232 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.232; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.232) by BY1PEPF0001AE1D.mail.protection.outlook.com (10.167.242.106) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:58:42 +0000 Received: from drhqmail201.nvidia.com (10.126.190.180) by mail.nvidia.com (10.127.129.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:20 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail201.nvidia.com (10.126.190.180) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:20 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:58:13 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Peter Colberg , Zhi Wang Subject: [PATCH 09/14] samples: rust: add Rust SR-IOV VF driver sample Date: Tue, 15 Sep 2026 23:56:53 +0300 Message-ID: <20260915205659.76841-10-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BY1PEPF0001AE1D:EE_|SN7PR12MB8602:EE_ X-MS-Office365-Filtering-Correlation-Id: f75db98b-0a95-44f1-ed41-08df136c2050 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|36860700016|82310400026|376014|7416014|1800799024|23010399003|10067099003|6133799003|22082099003|18002099003|11063799006|56012099006|5023799004|13003099007; X-Microsoft-Antispam-Message-Info: B7E3RKZKIRPU/KPKdXAphrz+HGh3u0f2lgPqastBh4c6/LElX5062Ar4EYNWTiLl9WSOA5fTe7Nqve8Cc+0m+rh3RvfTPIbBRol+bt+9aqKRIxa+Arsput0sm0vzatiPdgb0Pio6QeA+thqW5+4a9pzwBWKrlMGD6JZcP88l2mY4szsg9SO44m5WG0SKOxLu7dmndh/V3+fauRgrrJRz2P7VeRJiZRZY1fFkAc6OBOHirvucqH4hsTIs8XrbdM/St5ZUT6R767XAy7JzUlHV3IZFhainfU4mV6bVzqN8KSvgDkfaGFFp4A8XuNqDcL5AStV2WO7v1N4G/ad1WIL0kiTxEkwXOM1eZ1LEHUL+GGg08ihGnK9Ggg2X2370slplr8rNTTbazN/DQfEcnGi/WYmGGzM3dypf4BhjWV7wj2zorNMmAl7aPNuD66fy2IuBdBZkmw/+EXZUkhAQ5VRyKvVxVV/kSrQHovgKV2/W1zTErcUMRP+t3Yoh1cVlKPTXdIYaefuEeN9J2seeIb1xBJBTdkPNuvAF3c3VxCOOT4AJVQcu3lVOedIKaC32AVoHp6s7RL0MxNFJ/jwZ01Ryq1xXjkKMSCDGBhwABOJvuO2retGe1WdMlitOBLr/13ABHQGk1fVZVhnbeW742jxpRXChpfYP66olRUn5Y2hjUzwBdmviwOaCHIustMiC1a8AABPE7FG+H6CdG8HSxZQi2A== X-Forefront-Antispam-Report: CIP:216.228.118.232;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge1.nvidia.com;CAT:NONE;SFS:(13230040)(36860700016)(82310400026)(376014)(7416014)(1800799024)(23010399003)(10067099003)(6133799003)(22082099003)(18002099003)(11063799006)(56012099006)(5023799004)(13003099007);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: 5srs3tOqXB20yYawhVXSIAC5ADuWI8RUyu4qMeMo32Au5DxAIE0PE7T709iYA0kUrbasHl7zpm2jsX+xPq/yG9gFeVq6+m48ueI9WxdbIm5mymuqZ1Lt095xMI5/hPOs3p3wbgNiTeH3j5jmwiJxHPBYfdFtppDrYXFJNWtKKAOEmyc4Yrh8WJWeeR+5+Bwn+ir7igcWeJt3ujL6Ye54KOamooOr0n8XinW5s5sAR/f33GmIWfsmJy0HG7ga8DNTFljURxMIG+w6X1wN0Fg06K1gBJuM2QbTwEkC0tOLhptcV0Hr7jv10NB1hU0noK7y2mUEII545tJDmtNvDZztNlE8VyC2cSiRmMdPXb7U1VYyaqHKnLIpLeIkIh6JK15kvMbctBFRq6Z7BPQ5DHo+tZLDC85veOLRuF8K4vFdl7jyIU39SnK0mXT9nRml7C7a X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:58:42.9262 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: f75db98b-0a95-44f1-ed41-08df136c2050 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.232];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: BY1PEPF0001AE1D.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB8602 From: Peter Colberg Add a new SR-IOV driver sample that demonstrates how to enable and disable the Single Root I/O Virtualization capability for a PCI device. The sample may be exercised using QEMU's 82576 (igb) emulation. Implement the PF and VF as ordinary PCI drivers. Publish pinned PF data with a mutex-protected counter inline in the PF driver data, then borrow and invoke it explicitly from VF probe. Register the VF driver first so it is ready before the PF can enable VFs. Link: https://www.qemu.org/docs/master/system/devices/igb.html Signed-off-by: Peter Colberg Co-developed-by: Zhi Wang Signed-off-by: Zhi Wang --- MAINTAINERS | 1 + samples/rust/Kconfig | 11 ++ samples/rust/Makefile | 1 + samples/rust/rust_driver_sriov.rs | 241 ++++++++++++++++++++++++++++++ 4 files changed, 254 insertions(+) create mode 100644 samples/rust/rust_driver_sriov.rs diff --git a/MAINTAINERS b/MAINTAINERS index 2389df80ba50..5e168398e963 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21141,6 +21141,7 @@ F: rust/helpers/pci.c F: rust/kernel/pci.rs F: rust/kernel/pci/ F: samples/rust/rust_driver_pci.rs +F: samples/rust/rust_driver_sriov.rs =20 PCIE BANDWIDTH CONTROLLER M: Ilpo J=C3=A4rvinen diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index 31d62533ef25..737670fd68f8 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -128,6 +128,17 @@ config SAMPLE_RUST_DRIVER_PLATFORM =20 If unsure, say N. =20 +config SAMPLE_RUST_DRIVER_SRIOV + tristate "SR-IOV Driver" + depends on PCI_IOV + help + This option builds the Rust SR-IOV driver sample. + + To compile this as a module, choose M here: + the module will be called rust_driver_sriov. + + If unsure, say N. + config SAMPLE_RUST_DRIVER_USB tristate "USB Driver" depends on USB =3D y diff --git a/samples/rust/Makefile b/samples/rust/Makefile index b986b681cde5..238a11d5ec39 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_SAMPLE_RUST_DRIVER_I2C) +=3D rust_driver_i2= c.o obj-$(CONFIG_SAMPLE_RUST_I2C_CLIENT) +=3D rust_i2c_client.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) +=3D rust_driver_pci.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) +=3D rust_driver_platform.o +obj-$(CONFIG_SAMPLE_RUST_DRIVER_SRIOV) +=3D rust_driver_sriov.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) +=3D rust_driver_usb.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) +=3D rust_driver_faux.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_AUXILIARY) +=3D rust_driver_auxiliary.o diff --git a/samples/rust/rust_driver_sriov.rs b/samples/rust/rust_driver_s= riov.rs new file mode 100644 index 000000000000..ae1e1babb66b --- /dev/null +++ b/samples/rust/rust_driver_sriov.rs @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Rust SR-IOV driver sample based on QEMU's 82576 ([igb]) emulation. +//! +//! To make this driver probe, QEMU must be run with `-device igb`. +//! +//! Further, enable [vIOMMU] with interrupt remapping using, e.g., +//! +//! `-M q35,accel=3Dkvm,kernel-irqchip=3Dsplit -device intel-iommu,intrema= p=3Don,caching-mode=3Don` +//! +//! and append `intel_iommu=3Don` to the guest kernel arguments. +//! +//! [igb]: https://www.qemu.org/docs/master/system/devices/igb.html +//! [vIOMMU]: https://wiki.qemu.org/Features/VT-d + +use kernel::{ + device::{ + Bound, + Core, // + }, + driver, + new_mutex, + pci, + prelude::*, + sync::{ + aref::ARef, + Mutex, // + }, + types::CovariantForLt, + InPlaceModule, // +}; + +const PF_DRIVER_NAME: &CStr =3D c"rust_driver_sriov_pf"; +const VF_DRIVER_NAME: &CStr =3D c"rust_driver_sriov_vf"; + +struct SamplePfDriver; +struct SampleVfDriver; + +#[pin_data] +struct PfApi<'bound> { + pdev: &'bound pci::Device, + #[pin] + requests: Mutex, +} + +type PfApiForLt =3D CovariantForLt!(PfApi<'_>); + +impl PfApi<'_> { + fn submit(self: Pin<&Self>, vf: &pci::Device) -> Result { + let mut requests =3D self.requests.lock(); + let request =3D (*requests).checked_add(1).ok_or(EOVERFLOW)?; + *requests =3D request; + drop(requests); + + dev_info!( + self.pdev, + "Handle PF request {} from VF devfn {:#x}.\n", + request, + vf.dev_id() + ); + + Ok(request) + } +} + +#[pin_data(PinnedDrop)] +struct PfDriverData<'bound> { + // Keep the device alive until the registration stops exposing `PfApi:= :pdev`. + #[pin] + _registration: pci::VfRegistration<'bound, PfApiForLt>, + pdev: ARef, +} + +#[pin_data(PinnedDrop)] +struct VfDriverData { + pdev: ARef, +} + +kernel::pci_device_table!( + PF_TABLE, + ::IdInfo, + [( + // E1000_DEV_ID_82576 + pci::DeviceId::from_id(pci::Vendor::INTEL, 0x10c9), + () + )] +); + +kernel::pci_device_table!( + VF_TABLE, + ::IdInfo, + [( + // E1000_DEV_ID_82576_VF + pci::DeviceId::from_id(pci::Vendor::INTEL, 0x10ca), + () + )] +); + +#[vtable] +impl pci::Driver for SamplePfDriver { + type IdInfo =3D (); + type Data<'bound> =3D PfDriverData<'bound>; + + const ID_TABLE: pci::IdTable =3D &PF_TABLE; + + fn probe<'bound>( + pdev: &'bound pci::Device>, + _info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit, Error> + 'bound { + pin_init::pin_init_scope(move || { + dev_info!( + pdev, + "Probe Rust SR-IOV PF sample (PCI ID: {}, 0x{:x}).\n", + pdev.vendor_id(), + pdev.device_id() + ); + + pdev.enable_device_mem()?; + pdev.set_master(); + + Ok(try_pin_init!(PfDriverData { + // SAFETY: + // - probe has exclusive access to this PF before SR-IOV i= s enabled; + // - the registration is pinned in the PF driver data and = dropped before `pdev`; + // - no other registration is created for this PF; and + // - VFs are enabled only after probe by `sriov_configure`. + _registration <- unsafe { + pci::VfRegistration::new( + pdev, + try_pin_init!(PfApi { + pdev, + requests <- new_mutex!(0), + }), + ) + }, + pdev: pdev.into(), + })) + }) + } + + fn sriov_configure<'bound>( + dev: &'bound pci::sriov::Device>, + this: Pin<&Self::Data<'bound>>, + nr_virtfn: i32, + ) -> Result { + if nr_virtfn =3D=3D 0 { + dev_info!( + this.pdev, + "Disable SR-IOV (PCI ID: {}, 0x{:x}).\n", + this.pdev.vendor_id(), + this.pdev.device_id() + ); + dev.disable_sriov(); + } else { + dev_info!( + this.pdev, + "Enable SR-IOV (PCI ID: {}, 0x{:x}).\n", + this.pdev.vendor_id(), + this.pdev.device_id() + ); + dev.enable_sriov(nr_virtfn)?; + } + + assert_eq!(dev.num_vfs(), nr_virtfn); + Ok(nr_virtfn) + } +} + +#[vtable] +impl pci::Driver for SampleVfDriver { + type IdInfo =3D (); + type Data<'bound> =3D VfDriverData; + + const ID_TABLE: pci::IdTable =3D &VF_TABLE; + + fn probe<'bound>( + pdev: &'bound pci::Device>, + _info: Option<&'bound Self::IdInfo>, + ) -> impl PinInit, Error> + 'bound { + pin_init::pin_init_scope(move || { + dev_info!( + pdev, + "Probe Rust SR-IOV VF sample (PCI ID: {}, 0x{:x}).\n", + pdev.vendor_id(), + pdev.device_id() + ); + + let pdev_bound: &'bound pci::Device =3D pdev; + let pf_api =3D pdev_bound.vf_registration_data::()= ?; + + pdev.enable_device_mem()?; + pdev.set_master(); + + let request =3D pf_api.submit(pdev)?; + dev_info!(pdev, "Submitted request {} through PF data.\n", req= uest); + + Ok(try_pin_init!(VfDriverData { pdev: pdev.into() })) + }) + } +} + +#[pinned_drop] +impl PinnedDrop for PfDriverData<'_> { + fn drop(self: Pin<&mut Self>) { + dev_info!(self.pdev, "Remove Rust SR-IOV PF sample.\n"); + } +} + +#[pinned_drop] +impl PinnedDrop for VfDriverData { + fn drop(self: Pin<&mut Self>) { + dev_info!(self.pdev, "Remove Rust SR-IOV VF sample.\n"); + } +} + +#[pin_data] +struct SampleModule { + // Keep the VF driver registered while PF removal tears down its VFs. + #[pin] + _pf: driver::Registration>, + #[pin] + _vf: driver::Registration>, +} + +impl InPlaceModule for SampleModule { + fn init(module: &'static ThisModule) -> impl PinInit { + try_pin_init!(Self { + // The VF driver must be ready before the PF can enable VFs. + _vf <- driver::Registration::new(VF_DRIVER_NAME, module), + _pf <- driver::Registration::new(PF_DRIVER_NAME, module), + }) + } +} + +module! { + type: SampleModule, + name: "rust_driver_sriov", + authors: ["Peter Colberg"], + description: "Rust SR-IOV driver", + license: "GPL v2", +} From nobody Fri Sep 25 06:46:56 2026 Received: from CH5PR02CU005.outbound.protection.outlook.com (mail-northcentralusazon11012041.outbound.protection.outlook.com [40.107.200.41]) (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 900AD4A2600; Tue, 15 Sep 2026 20:59:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.200.41 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505948; cv=fail; b=N7b5fQXI7mEwDpeJS+eI+o+9LsuCkdwwY2H2cYZrYZsv5DyDToUCwyP6+dhpZszZv/MGQQ2syREVXDvzB1lsWiwYuHu6J50c/D0ivAR2eQRJNfS0SA/CbQNXjq+/2wmy/hpY4OSZidni2VapRVVkDoIKK/uH/qN6Tauy18fV5wU= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505948; c=relaxed/simple; bh=9Vt4baizVfky/CNspr3mtc0sBizc+BiMIjfe/iD23GQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=UjC2ifyL2kFeuosQ4lrc4iblNdK/4+Z8zbCg1qo0HZST+QkDDzXBMgEejvOfjocWABu389fQMRLXkdVkWDjBtJ5ibonOmFHlMMqtyDENloeVjitN9FWx44r4xy6+emVbUyCKRyQpLO/fWMO4HxCA9zbumxKWH4ZlgppX9IZCIrM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=pX/W40kT; arc=fail smtp.client-ip=40.107.200.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="pX/W40kT" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=WiOLxngw4VtAnJR2xoh44eJTjQrOH2szESghuCrp5J6cnG1B/+rIkNzAQT7D+5H2FfQB8LI16M3C73RLRm7GmiEuQBcOHmO4SNmwHsHUIaVi33+8+njT/kn2gn5zNK1b5jjywTPH0FQA/Thbw08uw14jrfShmZGz5SJVjPzZQobYDTcT17XEUtbUphxHOslwEN0nrIB6LKXrsaXMtdwnlZ72JPuM98ccBQyTkoHw+jgs/lGtnF2IiDewofaCZhOe31V6EvCn6K4/YBhxXhYAQYE1/FUk0t/THf8yLpAEAo7/axB1I0lHnMBaGQ2rjDSEmft8YKczt9jOk0DaiIKv5w== 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=/Yb66hh/wcjhZEhupPkdCOUGkHEFRiHJRZS3CCglUcU=; b=RcIAaE7uQnbePJXUD/y/rBhaXbyvmF6IZ4RUlIiOSNHHjclhVxg4l88Z/hLUWdsdaTzhcuSa6q79FeY/RoxHOJsQSVMIHAgFJMKEqSnwlt4t92PPG2YGcUQxnDtkt8g1a6+XcHwtd1R9XfF0iM/NuvlwgY+9QqpZym5PT1MuES0ODYEAHQK+b+cOBm1ywLTkw6tqv6yokvns9zduOm/Ch4V3f7v2batbII6aG1mj0g/yeY5qBdIt0UmFt9XbGOr/H/cCVFMl5QIXUUbN+064x+RSx1Sv8rgjnYsJbMY8vwz0eJhPD3FeGOqkVICZJwfSIdtKZSpGQOOkRDr0ybnbfQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.232) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=/Yb66hh/wcjhZEhupPkdCOUGkHEFRiHJRZS3CCglUcU=; b=pX/W40kTXw29WJUrY2S0lvfhbRmID8lxbTMegHT2fLV8nwdt9cJqckCe4bsWKVr52qPDMmOZTmG25FMf44ZByux44GBEhWMQqpvQIemGA815ZAMLatrhr8M3enHs6DO3tVZxdfN9vIKfS2J+gMuEYaXnX5DtPOnTAyYmS9kJthzp1nCxmg7yygyP9mrTjH14sbIbGSByoHGQDUN4Fd+FTLWJBmPPSgjUQq6K/Y/nZYKI3HV7nKUOjtGNIYWqefFKesMIJWwAJxggwCzxuEvFTJ67t7kJXWlTiao0WRfUQfmsptW88xz7GdIRemP+tOimsDi694dZ1xSUPv3ChoU8sQ== Received: from BY1P220CA0013.NAMP220.PROD.OUTLOOK.COM (2603:10b6:a03:59d::17) by SJ0PR12MB6806.namprd12.prod.outlook.com (2603:10b6:a03:478::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.406.12; Tue, 15 Sep 2026 20:58:48 +0000 Received: from BY1PEPF0001AE1B.namprd04.prod.outlook.com (2603:10b6:a03:59d:cafe::1) by BY1P220CA0013.outlook.office365.com (2603:10b6:a03:59d::17) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.9 via Frontend Transport; Tue, 15 Sep 2026 20:58:48 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.232) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.232 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.232; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.232) by BY1PEPF0001AE1B.mail.protection.outlook.com (10.167.242.103) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:58:47 +0000 Received: from drhqmail201.nvidia.com (10.126.190.180) by mail.nvidia.com (10.127.129.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:28 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail201.nvidia.com (10.126.190.180) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:28 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:58:20 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Zhi Wang Subject: [PATCH 10/14] rust: add C-to-Rust FFI descriptors and trampolines Date: Tue, 15 Sep 2026 23:56:54 +0300 Message-ID: <20260915205659.76841-11-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BY1PEPF0001AE1B:EE_|SJ0PR12MB6806:EE_ X-MS-Office365-Filtering-Correlation-Id: 357138d8-ad79-429d-08eb-08df136c2351 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|23010399003|1800799024|7416014|376014|82310400026|36860700016|13003099007|6133799003|3023799007|10067099003|22082099003|56012099006|11063799006|5023799004|18002099003; X-Microsoft-Antispam-Message-Info: DNNX/8xdB3t8+PP75w327ztsPbDYAfffYkE/76L5UIK6M/cL3MRzJbdLGVCmb6ab96rPveA0Da0zkSKRA/fUgRe5bMW1EICWtqljavQOadiE6mYMtYPb89xriXDXD5obQ9nAcYOa5RzNd1yW8DYiJqLnOBIZCXHV/wm/5CElQGeyW5ocUj5MF5/Fc62tFIXCUIGkOAMFJAYTU+NqDPAlbrSqbMH3dLrguZi1SQNBPahjEj0XY2R3qRLpOlTXaRwQye1EJhj1xhiGs4V6+vCAGp80TYWzJrDPAs9LAhnSCbGCGOHX2nUVy0QEbEoFj9pCoZWukxH1WqB7a0xACOldAd3pNjb20JIrmx8nwY3dmV3pb/aNHgLa/xoTWeXZPzxkeGAIQaPvqKuYMUnPQMC4jX0z1pGzvVVxf+sZUUsQRnXN4LG9NSO0PlCODuD0IjDX9F6uW0T535HkCqA54/XiUCby214T8WXDVuVeXyKFa1zkWa6LFRJhwn0CS/k+sBMl4PYon7KoU0iyeG0UBmnbjmnvbxkqQmxfx3tx5AD17pSxkJN1uW4aCxsoUJk30i90ANFj6tvMxgXvkwqbMySP7tqNkGIovzoJkXT3XSfMVTO06SwRR6QnAydgfghQ94L/YigGgsPT0Svak7pVQEdkUXWsq0jOP8qyDDnzhqYDrdp8Ir4aRzVAb2p8cQzyiZlp7TtjgxqCwErAvgWsyUsVbw== X-Forefront-Antispam-Report: CIP:216.228.118.232;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge1.nvidia.com;CAT:NONE;SFS:(13230040)(23010399003)(1800799024)(7416014)(376014)(82310400026)(36860700016)(13003099007)(6133799003)(3023799007)(10067099003)(22082099003)(56012099006)(11063799006)(5023799004)(18002099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: SAtE3mLAPHebqoUZSBrnplzukoUFeIn55PL1KXvvJRCVFtUCMM1Q6RGdPipY5joMRM9lEg6b2x5LSmhkdjMkyNTqnv9PWfiFuWMQga25LWMPqrmft8Zliup9RlrL79htzC8+ziuK2mcbCVp7gWZ58rcGi+L1LiZkbE0puFalIOJJ6/PjHxDo6PFFnQI4R1gmUXNTlW2Cs2X+Aod+S2HBriKHTP2XYhoirlxpBnPdQdLVa3bANzo6h348dj4KKW0W26MNGKaHZoMnWAMg1k1jIiS7i55RDKcV3B0TdrlTWmxyQyQ2f6NeeaRcZnKWizdo/sJPMElmHjTRjsoCNwZQyuVjNVXeKUz+xpQjcah84PsKROOxos8O489doDR3AD+eBHhwYbXcnsj870QdYkhTlTtzVsp5mgyDXXg8gxWn52MJeRQrQfzsyJVZNUEqKAiO X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:58:47.9558 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 357138d8-ad79-429d-08eb-08df136c2351 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.232];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: BY1PEPF0001AE1B.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR12MB6806 Content-Type: text/plain; charset="utf-8" Rust drivers may need to expose a restricted operations table to C consumers. Passing an opaque Rust pointer alone neither identifies the expected operations-table ABI nor provides type-checked C-compatible trampolines. Add `struct rust_ffi` with a stable 128-bit ABI token, version fields, an operations-table size, and an opaque pinned context. Add `rust_ffi_borrow()` to validate those fields independently of the transport that publishes the descriptor. The token is an ABI type tag and does not provide device identity, authorization, or lifetime management. Add matching Rust `Token`, `Abi`, and `Descriptor` abstractions and an `ffi_vtable` procedural macro. The macro checks the complete bindgen operations-table layout while generating private C ABI trampolines that recover a `Pin<&T>`. A sealed return conversion keeps raw return values unchanged and maps `Result<()>` and `Result` to conventional C integer results. The publishing transport remains responsible for keeping the descriptor and context alive and pinned until every consumer has stopped calling it. Signed-off-by: Zhi Wang --- MAINTAINERS | 2 + include/linux/rust_ffi.h | 88 ++++++++++++ rust/bindings/bindings_helper.h | 1 + rust/kernel/interop.rs | 5 +- rust/kernel/interop/ffi.rs | 239 ++++++++++++++++++++++++++++++++ rust/macros/ffi_vtable.rs | 148 ++++++++++++++++++++ rust/macros/lib.rs | 90 ++++++++++++ 7 files changed, 571 insertions(+), 2 deletions(-) create mode 100644 include/linux/rust_ffi.h create mode 100644 rust/kernel/interop/ffi.rs create mode 100644 rust/macros/ffi_vtable.rs diff --git a/MAINTAINERS b/MAINTAINERS index 5e168398e963..9f70dc14bf78 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -24003,8 +24003,10 @@ M: Alexandre Courbot L: rust-for-linux@vger.kernel.org S: Maintained T: git https://github.com/Rust-for-Linux/linux.git interop-next +F: include/linux/rust_ffi.h F: rust/kernel/interop.rs F: rust/kernel/interop/ +F: rust/macros/ffi_vtable.rs =20 RUST [NUM] M: Alexandre Courbot diff --git a/include/linux/rust_ffi.h b/include/linux/rust_ffi.h new file mode 100644 index 000000000000..b3bdcb70ed72 --- /dev/null +++ b/include/linux/rust_ffi.h @@ -0,0 +1,88 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_RUST_FFI_H +#define _LINUX_RUST_FFI_H + +#include +#include + +/** + * struct rust_ffi_token - Stable identifier for a Rust FFI ABI + * @high: Most significant half of the identifier + * @low: Least significant half of the identifier + * + * A token is the ABI type tag for the opaque operations table. It tells a + * consumer which C type and semantics may be used to access @ops. It is n= ot a + * device identifier, secret, permission check, or lifetime handle. Provid= ers + * and consumers must use the same pair of constants. + */ +struct rust_ffi_token { + u64 high; + u64 low; +}; + +/** + * struct rust_ffi - C ABI descriptor for calls into Rust + * @token: Stable identifier for the FFI ABI + * @abi_major: ABI major version + * @abi_minor: ABI minor version + * @ops_size: Size of the operations table in bytes + * @ops: C ABI operations table + * @context: Immutable provider context passed to operations + * + * Providers must fully initialize this descriptor before publishing it and + * must keep the descriptor, operations table, and context alive and immut= able + * while it is published. A published callable descriptor has non-NULL @ops + * and @context pointers. A NULL @ops indicates that no C-callable FFI is + * available. + * + * Minor versions may only append operations to the table. Consumers reque= st + * an ABI major version, a minimum ABI minor version, and the size of the = table + * prefix they use. + */ +struct rust_ffi { + struct rust_ffi_token token; + u16 abi_major; + u16 abi_minor; + size_t ops_size; + const void *ops; + const void *context; +}; + +/** + * rust_ffi_borrow - Validate and borrow a Rust FFI descriptor + * @ffi: Descriptor to borrow + * @token: Required FFI ABI token + * @abi_major: Required ABI major version + * @min_abi_minor: Minimum required ABI minor version + * @required_ops_size: Minimum required size of the operations table + * + * This validates only the descriptor contents. The caller must arrange for + * @ffi, its operations table, and its context to remain alive and immutab= le + * for the entire borrow. + * + * Return: @ffi on success, or an ERR_PTR() value on failure. + */ +static inline const struct rust_ffi * +rust_ffi_borrow(const struct rust_ffi *ffi, + const struct rust_ffi_token *token, + u16 abi_major, u16 min_abi_minor, size_t required_ops_size) +{ + if (!token) + return ERR_PTR(-EINVAL); + + if (!ffi || !ffi->ops || !ffi->context) + return ERR_PTR(-ENOENT); + + if (ffi->token.high !=3D token->high || ffi->token.low !=3D token->low) + return ERR_PTR(-ENOENT); + + if (ffi->abi_major !=3D abi_major || ffi->abi_minor < min_abi_minor) + return ERR_PTR(-EPROTONOSUPPORT); + + if (ffi->ops_size < required_ops_size) + return ERR_PTR(-EMSGSIZE); + + return ffi; +} + +#endif /* _LINUX_RUST_FFI_H */ diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 930e63290cdd..6a30455768b4 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -85,6 +85,7 @@ #include #include #include +#include #include #include #include diff --git a/rust/kernel/interop.rs b/rust/kernel/interop.rs index 3b371d782a59..9241f3650468 100644 --- a/rust/kernel/interop.rs +++ b/rust/kernel/interop.rs @@ -3,7 +3,8 @@ //! Infrastructure for interfacing Rust code with C kernel subsystems. //! //! This module is intended for low-level, unsafe Rust infrastructure code -//! that interoperates between Rust and C. It is *not* for use directly in -//! Rust drivers. +//! that interoperates between Rust and C. Drivers should normally use the +//! generated adapters and safe subsystem abstractions built on top of it. =20 +pub mod ffi; pub mod list; diff --git a/rust/kernel/interop/ffi.rs b/rust/kernel/interop/ffi.rs new file mode 100644 index 000000000000..a8c16a29110a --- /dev/null +++ b/rust/kernel/interop/ffi.rs @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! C-compatible descriptors for calls into Rust. +//! +//! An FFI descriptor contains an operations table plus an opaque, pinned = Rust context. This +//! module deliberately does not publish the descriptor or manage its life= time. A transport, such +//! as PCI SR-IOV, must keep the context alive and pinned for as long as a= consumer can call through +//! the descriptor. + +use crate::{ + bindings, + types::ForLt, // +}; +use core::{ + ffi::c_void, + pin::Pin, // +}; + +/// A transport-independent token identifying an FFI ABI. +/// +/// Consumers compare this token before interpreting an opaque operations-= table pointer. It is an +/// ABI type tag, not a device identifier, secret, authorization capabilit= y, or lifetime handle. +/// +/// This is a transparent wrapper around +/// [`struct rust_ffi_token`](srctree/include/linux/rust_ffi.h). +#[derive(Clone, Copy)] +#[repr(transparent)] +pub struct Token(bindings::rust_ffi_token); + +impl Token { + /// Creates an FFI token from its most and least significant halves. + pub const fn new(high: u64, low: u64) -> Self { + Self(bindings::rust_ffi_token { high, low }) + } + + /// Returns the most significant half of the token. + pub const fn high(self) -> u64 { + self.0.high + } + + /// Returns the least significant half of the token. + pub const fn low(self) -> u64 { + self.0.low + } +} + +impl PartialEq for Token { + fn eq(&self, other: &Self) -> bool { + self.high() =3D=3D other.high() && self.low() =3D=3D other.low() + } +} + +impl Eq for Token {} + +/// Defines the identity, Rust context, and raw operations-table type of a= n FFI ABI. +/// +/// Implementations are normally paired with an operations table generated= by [`ffi_vtable`]. The +/// Rust provider and every C consumer must share the corresponding C defi= nition. +/// +/// [`ffi_vtable`]: crate::macros::ffi_vtable +/// +/// # Safety +/// +/// Implementers must ensure that: +/// +/// - [`RawOps`](Self::RawOps) has a stable C-compatible layout and [`OPS`= ](Self::OPS) is a fully +/// initialized instance of that layout; +/// - for every possible data lifetime, every callback in `OPS` interprets= its context as a pinned +/// [`ForLt::Of`] value with that lifetime, only borrows it for the dura= tion of the callback, and +/// does not leak or otherwise extend references derived from it; +/// - [`TOKEN`](Self::TOKEN) and the ABI version uniquely identify that la= yout and its semantics; +/// and +/// - changing `RawOps` incompatibly also changes the ABI major version. +pub unsafe trait Abi: 'static { + /// Rust context type expected by the operations-table callbacks. + /// + /// The context may be invariant in its encoded data lifetime. + type Context: ForLt + 'static; + + /// Raw C-compatible operations-table type. + type RawOps: Sync + 'static; + + /// Static operations table published for this ABI. + const OPS: &'static Self::RawOps; + + /// Token shared by providers and consumers of this FFI ABI. + const TOKEN: Token; + + /// ABI major version, incremented for incompatible changes. + const ABI_MAJOR: u16; + + /// ABI minor version, incremented for compatible extensions. + const ABI_MINOR: u16; +} + +/// A C-compatible descriptor for an opaque Rust context and operations ta= ble. +/// +/// This is a transparent wrapper around +/// [`struct rust_ffi`](srctree/include/linux/rust_ffi.h). It neither owns= nor borrows the +/// operations table or Rust context at the type level. The transport that= publishes it must ensure +/// that `ops` remains valid and that `context` remains alive at a stable = address until all +/// consumers have stopped using the descriptor. +#[repr(transparent)] +pub struct Descriptor(bindings::rust_ffi); + +impl Descriptor { + /// Creates a descriptor for a pinned Rust context. + /// + /// The descriptor does not retain the provider's Rust type or lifetim= e. A transport must not + /// publish it for longer than `context` remains alive and pinned. + pub fn new<'borrow, 'data, A>(context: Pin<&'borrow ::Of<'data>>) -> Self + where + A: Abi, + for<'b> ::Of<'b>: Send + Sync, + { + Self(bindings::rust_ffi { + token: A::TOKEN.0, + abi_major: A::ABI_MAJOR, + abi_minor: A::ABI_MINOR, + ops_size: core::mem::size_of::(), + ops: core::ptr::from_ref(A::OPS).cast(), + context: core::ptr::from_ref(context.get_ref()).cast(), + }) + } + + /// Returns the FFI ABI token. + pub const fn token(&self) -> Token { + Token(self.0.token) + } + + /// Returns the FFI ABI major version. + pub const fn abi_major(&self) -> u16 { + self.0.abi_major + } + + /// Returns the FFI ABI minor version. + pub const fn abi_minor(&self) -> u16 { + self.0.abi_minor + } + + /// Returns the size in bytes of the raw operations table. + pub const fn ops_size(&self) -> usize { + self.0.ops_size + } + + /// Returns the operations-table pointer. + pub const fn ops(&self) -> *const c_void { + self.0.ops + } + + /// Returns the provider-context pointer. + pub const fn context(&self) -> *const c_void { + self.0.context + } + + /// Returns a raw pointer to the underlying C descriptor. + pub const fn as_raw(&self) -> *const bindings::rust_ffi { + core::ptr::from_ref(&self.0) + } +} + +/// Implementation details for generated FFI adapters. +#[doc(hidden)] +pub mod __private { + use crate::{ + error::{ + from_result, + Result, // + }, + ffi::c_int, + types::ForLt, // + }; + use core::{ + ffi::c_void, + pin::Pin, // + }; + + mod sealed { + use super::{ + c_int, + Result, // + }; + + pub trait Sealed {} + + impl Sealed for T {} + impl Sealed for Result<()> {} + impl Sealed for Result {} + } + + /// Converts a Rust operation return value into the return type of its= C callback. + /// + /// The C return type is supplied by the raw operations-table field. T= his trait is sealed so + /// generated adapters can select only the conversions defined by this= module. + pub trait FfiReturn: sealed::Sealed { + /// Performs the return-value conversion. + fn into_ffi(self) -> C; + } + + impl FfiReturn for T { + #[inline] + fn into_ffi(self) -> T { + self + } + } + + impl FfiReturn for Result<()> { + #[inline] + fn into_ffi(self) -> c_int { + from_result(|| self.map(|()| 0)) + } + } + + impl FfiReturn for Result { + #[inline] + fn into_ffi(self) -> c_int { + from_result(|| self) + } + } + + /// Accesses a pinned Rust context through a higher-ranked closure. + /// + /// # Safety + /// + /// `context` must have been obtained from a `Pin<&F::Of<'data>>` for = some data lifetime and + /// must point to that live, properly aligned value, which remains pin= ned and valid for shared + /// access throughout this call. The pointed-to value must not be muta= ted except through + /// synchronization-safe interior mutability. + pub unsafe fn with_context( + context: *const c_void, + f: impl for<'borrow, 'data> FnOnce(Pin<&'borrow F::Of<'data>>) -> = R, + ) -> R { + // SAFETY: The caller guarantees a live, pinned context of this li= fetime family. The + // higher-ranked closure keeps the borrow independent of the erase= d data lifetime, so it + // cannot escape or be stored in the context's invariant data. + let context =3D unsafe { Pin::new_unchecked(&*context.cast::>()) }; + f(context) + } +} diff --git a/rust/macros/ffi_vtable.rs b/rust/macros/ffi_vtable.rs new file mode 100644 index 000000000000..ad3176d1f8e1 --- /dev/null +++ b/rust/macros/ffi_vtable.rs @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0 + +use proc_macro2::TokenStream; +use quote::{ + format_ident, + quote, // +}; +use syn::{ + parse::{ + Parse, + ParseStream, // + }, + Attribute, + Error, + FnArg, + Ident, + ImplItem, + ItemImpl, + Path, + Result, + ReturnType, + Token, // +}; + +pub(crate) struct FfiVtableArgs { + table: Ident, + ops: Path, +} + +impl Parse for FfiVtableArgs { + fn parse(input: ParseStream<'_>) -> Result { + let table =3D input.parse()?; + let _: Token![:] =3D input.parse()?; + let ops =3D input.parse()?; + + Ok(Self { table, ops }) + } +} + +fn has_conditional(attributes: &[Attribute]) -> bool { + attributes + .iter() + .any(|attribute| attribute.path().is_ident("cfg") || attribute.pat= h().is_ident("cfg_attr")) +} + +pub(crate) fn ffi_vtable(args: FfiVtableArgs, item: ItemImpl) -> Result { + if item.trait_.is_some() + || !item.generics.params.is_empty() + || item.generics.where_clause.is_some() + { + return Err(Error::new_spanned( + &item, + "`#[ffi_vtable]` requires a concrete, non-generic inherent imp= l", + )); + } + if has_conditional(&item.attrs) { + return Err(Error::new_spanned( + &item, + "`#[ffi_vtable]` does not support conditionally compiled impls= ", + )); + } + + let ops =3D &args.ops; + let table =3D &args.table; + let self_ty =3D &item.self_ty; + let private =3D quote!(::kernel::interop::ffi::__private); + let mut fields =3D Vec::new(); + + for impl_item in &item.items { + let ImplItem::Fn(method) =3D impl_item else { + continue; + }; + let signature =3D &method.sig; + if has_conditional(&method.attrs) + || !signature.generics.params.is_empty() + || signature.generics.where_clause.is_some() + { + return Err(Error::new_spanned( + method, + "`#[ffi_vtable]` requires unconditional, non-generic metho= ds", + )); + } + + let mut argument_names =3D Vec::new(); + let mut argument_types =3D Vec::new(); + for argument in &signature.inputs { + let FnArg::Typed(argument) =3D argument else { + continue; + }; + + let index =3D argument_names.len(); + argument_names.push(format_ident!("__ffi_vtable_arg_{index}")); + argument_types.push(&argument.ty); + } + + let method_name =3D &signature.ident; + let rust_output =3D match &signature.output { + ReturnType::Default =3D> quote!(()), + ReturnType::Type(_, ty) =3D> quote!(#ty), + }; + + fields.push(quote! { + #method_name: ::core::option::Option::Some({ + unsafe extern "C" fn callback<__FfiVtableReturn>( + __ffi_vtable_context: *const ::core::ffi::c_void, + #(#argument_names: #argument_types),* + ) -> __FfiVtableReturn + where + #rust_output: #private::FfiReturn<__FfiVtableReturn>, + { + let __ffi_vtable_call =3D |__ffi_vtable_this: ::core::= pin::Pin<&#self_ty>| { + // Infer the receiver within the closure's context= lifetime. + let __ffi_vtable_method: unsafe fn( + ::core::pin::Pin<&_>, + #(#argument_types),* + ) -> #rust_output =3D <#self_ty>::#method_name; + + #private::FfiReturn::<__FfiVtableReturn>::into_ffi( + // SAFETY: An unsafe method relies on the C ca= ller satisfying its + // argument contract. + unsafe { + __ffi_vtable_method(__ffi_vtable_this, #(#= argument_names),*) + }, + ) + }; + + // SAFETY: The publisher keeps the context live and pi= nned while callbacks run. + unsafe { + #private::with_context::<::kernel::types::ForLt!(#= self_ty), _>( + __ffi_vtable_context, + __ffi_vtable_call, + ) + } + } + + callback::<_> + }) + }); + } + + Ok(quote! { + #item + + static #table: #ops =3D #ops { + #(#fields),* + }; + }) +} diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs index 9b76efe1476f..c9bd09148301 100644 --- a/rust/macros/lib.rs +++ b/rust/macros/lib.rs @@ -16,6 +16,7 @@ =20 mod concat_idents; mod export; +mod ffi_vtable; mod fmt; mod for_lt; mod helpers; @@ -263,6 +264,95 @@ pub fn export(attr: TokenStream, input: TokenStream) -= > TokenStream { export::export(parse_macro_input!(input)).into() } =20 +/// Generates a C-compatible operations table for a concrete Rust implemen= tation. +/// +/// The attribute declares the name of the table to generate and its bindg= en-generated raw +/// operations type: +/// +/// ``` +/// use core::{ +/// ffi::{ +/// c_int, +/// c_void, // +/// }, +/// pin::Pin, // +/// }; +/// use kernel::{ +/// macros::ffi_vtable, +/// prelude::*, // +/// }; +/// +/// #[repr(C)] +/// struct ExampleOps { +/// submit: Option c_int>, +/// reset: Option c_int>, +/// version: Option u16>, +/// } +/// +/// struct Provider; +/// +/// #[ffi_vtable(EXAMPLE_OPS: ExampleOps)] +/// impl Provider { +/// fn submit(self: Pin<&Self>, requester_id: u16) -> Result { +/// Ok(c_int::from(requester_id)) +/// } +/// +/// fn reset(self: Pin<&Self>) -> Result { +/// Ok(()) +/// } +/// +/// fn version(self: Pin<&Self>) -> u16 { +/// 1 +/// } +/// } +/// +/// # fn main() { +/// assert!(EXAMPLE_OPS.submit.is_some()); +/// assert!(EXAMPLE_OPS.reset.is_some()); +/// assert!(EXAMPLE_OPS.version.is_some()); +/// # } +/// ``` +/// +/// Each method becomes a field of the same name in `EXAMPLE_OPS`. The gen= erated C callback has an +/// additional `*const c_void` context as its first argument. It recovers = a `Pin<&Provider>` from +/// that context inside a higher-ranked closure and forwards the remaining= arguments. This also +/// supports implementations such as `impl Provider<'_>` whose data lifeti= me is invariant. The +/// closure keeps that data lifetime independent of the callback's borrow.= Return values are +/// forwarded unchanged, except that a [`Result`] is converted into= a `c_int`, preserving a +/// successful value, and a [`Result<()>`] is converted into zero on succe= ss. Both return a negative +/// errno on failure. +/// Initializing the raw bindgen type with a struct literal checks the fie= ld names and callback +/// signatures at compile time. +/// +/// The attribute supports concrete inherent impls. Methods must otherwise= use ABI-shaped argument +/// and return types. They must be non-async, non-generic Rust methods wit= h a `self: Pin<&Self>` +/// receiver. A method may be safe when its arguments require no validity = assumptions beyond their +/// Rust types. It must be `unsafe fn` when calling it relies on additiona= l C-side guarantees, such +/// as the validity of a raw pointer argument. Every field of the raw oper= ations structure must have +/// a matching method; optional methods and conditionally compiled impls, = methods, or arguments are +/// not supported yet. Argument and return types must spell out concrete t= ypes instead of using +/// `Self`. +/// +/// [`Result`]: ../kernel/error/type.Result.html +/// [`Result<()>`]: ../kernel/error/type.Result.html +/// +/// # Safety contract +/// +/// The code publishing the generated table must pass a non-null context p= ointer to a valid pinned +/// instance of the implementation type, with the same lifetime family, an= d keep that instance alive +/// and valid for shared access for every callback. Callers must uphold th= e safety contract of each +/// unsafe method. The macro emits private function-pointer callbacks and = does not export symbols +/// for them. +#[proc_macro_attribute] +pub fn ffi_vtable(attr: TokenStream, input: TokenStream) -> TokenStream { + ffi_vtable::ffi_vtable( + parse_macro_input!(attr as ffi_vtable::FfiVtableArgs), + parse_macro_input!(input as syn::ItemImpl), + ) + .unwrap_or_else(|error| error.into_compile_error()) + .into() +} + /// Like [`core::format_args!`], but automatically wraps arguments in [`ke= rnel::fmt::Adapter`]. /// /// This macro allows generating `fmt::Arguments` while ensuring that each= argument is wrapped with From nobody Fri Sep 25 06:46:56 2026 Received: from BL2PR02CU003.outbound.protection.outlook.com (mail-eastusazon11011021.outbound.protection.outlook.com [52.101.52.21]) (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 2BA162B9BA; Tue, 15 Sep 2026 20:58:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.52.21 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505942; cv=fail; b=pDwCL1pIq36CI9VQjoIdiGRqrs9qPUC0rabEFafbdjOBkErN5OoqRE43gqxW2ettyQCxU//+8Sjen5w6jKRV3a/mfYVhPWA+IJLQ8y/cUFmIAZDECKpq2N6hXPrxIkoquvqi4Xmdzn7Qu6N8bznLfG/HFXUaZu+G15z01SZuJxQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505942; c=relaxed/simple; bh=yL2USA5/K0s+wBkxqK6TzwNOal+vKORQon34dw9eInU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=utGfnx0jdcn+X0NvmWk7t4BWfQFp490jz9tVzlVm3nDSOUOWs0MLkCtnov1zyvScaPvtCORU7Q4L4eOjuleFabsRu7EEzp40C41HtFSMI1N4b861N0Snb5fCPbh29+2DfWjDnKqmEVZi/GrdJAf6YKTBVHm8+dGeYIgvIh9XFcc= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=bOxcYolP; arc=fail smtp.client-ip=52.101.52.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="bOxcYolP" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Zk4IALS+kO30tP6VNG9ut8yh2KJty/Rr7yC5jI68u+SPFWhU3LEpNvnTT4D9aRmAeBZhxt6gUU1B8krjBMXCzEuq6Gw7WrRC3Z7Urfyh/ONlk+ntaVrw8xfx4IojWYSYqmbf9vu3qCqkjezLVYReFnY/HlZEkcaJ839Zr09yyk/VyzQoRUKT2nuvxyAFpL5T8t+DFEU0RQ5RjMT4RHrDrqboaCznO+gissBhQZAg3ptemByLdYCTwU7D1Wz/L+81WNmqkbf/+zxh3Gbaai+eSKrdYpadiQKsMamJxKAslA/31w+QjqVEv7dfRDuFLcK5Ucf2BkO++JWNqYPPj4iswQ== 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=be0C6kz4NKeFeICVK1TQ9UVq4OMPLYozpM2zWyVYpLU=; b=UG3GryMw25mxMWbg34nSskjiLSez1mTR8mCo3E23esYcLKul2wpmO+r7rqUpEssYjUTduoU4eS7X5DGtTlKjQtRZ8gru+8Lk6fBmveb/IHW62oe7jW4ir7i+bAlagMIU+YNH23RpV0qfIxqIL1ud3SbR6Y9t92d/AsneB3okqc3wQJIQ4QquN36RLU7E/KoeupKPD7fLgqI5MlHC+2eZjETL18jS3A0mXnGOFaadjvzITiNlBiGZnKrWF/7JOBtkMJzm+1kg5NU0T+JM6CZ3Fx12Kk7E1i6jfM6e4KxNKKWAzIYkt4uLsiIr+t1ey/8d+pfV7HSQ7vUyOORBVDUEOA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.232) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=be0C6kz4NKeFeICVK1TQ9UVq4OMPLYozpM2zWyVYpLU=; b=bOxcYolPABBpePT8UcTJ66+zZr9jaHp0Mz0JJxazp1ZGEpitj+8psKtxUFSOjfhd2DXyyLhTWC/LgcVsxtoCLHeu52QiJq+FzZxMTa4Oh2lIIJTqEC1kqy252ZCIQeBCP3O5OFXzASqPIXDlmlYhs65wI4r6SdTm75MlTEJE4JToJg+8jXBxPUnPJfKIjBlB7MGv1n0FtJ/QI6k+96zjZt1vPRZ8DdQjw/KWksD+KWpKBLHWgT+8nlRIjysBYRPAq1DUANCcQBjDxULSZahxuaENVeL3mLJuev6bG3gvTTY1mKHZvh1TECk1mZRA+3ydpij1ot5L7fx0GtM4PpH/7Q== Received: from BY1P220CA0009.NAMP220.PROD.OUTLOOK.COM (2603:10b6:a03:59d::7) by EAYPR12MB999182.namprd12.prod.outlook.com (2603:10b6:303:2c1::6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.406.11; Tue, 15 Sep 2026 20:58:53 +0000 Received: from BY1PEPF0001AE1B.namprd04.prod.outlook.com (2603:10b6:a03:59d:cafe::af) by BY1P220CA0009.outlook.office365.com (2603:10b6:a03:59d::7) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.11 via Frontend Transport; Tue, 15 Sep 2026 20:58:53 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.232) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.232 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.232; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.232) by BY1PEPF0001AE1B.mail.protection.outlook.com (10.167.242.103) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:58:53 +0000 Received: from drhqmail202.nvidia.com (10.126.190.181) by mail.nvidia.com (10.127.129.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:36 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail202.nvidia.com (10.126.190.181) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:36 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:58:28 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Zhi Wang Subject: [PATCH 11/14] rust: pci: add C FFI support to typed SR-IOV PF registration data Date: Tue, 15 Sep 2026 23:56:55 +0300 Message-ID: <20260915205659.76841-12-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BY1PEPF0001AE1B:EE_|EAYPR12MB999182:EE_ X-MS-Office365-Filtering-Correlation-Id: bf1f3628-f4fa-401e-a52d-08df136c2657 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|23010399003|376014|1800799024|7416014|82310400026|36860700016|5023799004|6133799003|11063799006|56012099006|10067099003|22082099003|18002099003; X-Microsoft-Antispam-Message-Info: lRGt77+BfCVgPI9cCEaXfezFUnwMUdT14OZvbjiwiTV2Pl6ChYH7Kv4/tfvaUgl9zySONqqB7VqV4+7hQ2jAFiU7uipz+i1ziYTKt4DCC/FEbrg9nKkjhFhLWELlJT5EJ5ax8OrM0RtndplhCWDqFO7EYfJr9bvzmSjEzowzYXMUM8nivoAdhEqPoOe4fDjHr5JvzwEi/p6tMnU6wnrsKLvOECEf1BfsiN4CxpRPwalfZzFilDLfxqxiiVDZTrweIhQFW+GslE7OGPKhyzenNs5Th+VZbDjIxhOuerUDa/9x2r9OmQXMYR/OXpv5RvUblYhCa7c560RHg03Jb1N4QkKEa4HW+thec+tVkX7nP6rwUoumJDzTAqTt8X47eMiY54eR7gDFVV9Q8tmV3ygAtha7QXvr8C1UfOjGU5G/Idn9tdzcPW+TPj9IDu1731nWh5yaqlukloyHcDemqWtyJYnHLxIKEvhFS43rFZ4bVzW+Vn2FAJ8wgjsFr7I3YeotEfCQTyhImPjkHAPhyDE0nbpN3V84cJxnxZEXO3/M5aB1ctjhjybsTOBi2jTWbP5O9oVH6lM3P5V+S1Kbq+2MFRebxE3S3cHBro2x3by+8UMxbpQLk7qauJSiB4kT0Qb+8G8zV6qrO3nf5llH1S7NODyu68XNCStOewO2vBy2u0w5SRrFVIE3fAoJIvySgeo+HTBP88dVWpnXFMpxoQwBpw== X-Forefront-Antispam-Report: CIP:216.228.118.232;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge1.nvidia.com;CAT:NONE;SFS:(13230040)(23010399003)(376014)(1800799024)(7416014)(82310400026)(36860700016)(5023799004)(6133799003)(11063799006)(56012099006)(10067099003)(22082099003)(18002099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: rHaV5Qa/OdEvVxpr4GqEH9s9nsoboUjEEImy8CimWrjhWAvLMHs9EH3AKGRZk9sWay81RQwXEZIPum1UYjcyD114IsMb5eJ9xO6yWd7Wu+X0XIdc141NSdoDF1oKAGJW+bZjoMzsgk31PI2H+YtqU5APE+mz5ZitK/m1pqZUJQkdQth41Px4tbSKIiuXE4VcFK9gyEEWEi4l4gTGfnx1rfuHgqShyNfYW5wNu9CGQuTNtwc2iphF86JFHGiw1XngIKWLlHoc1CRlS00+gV1deNUb9wiPNS7v/plSA5+39KRoTIB74wd8MMyd8en0MHRJgcI8LXyEQQN9IzdZUmkJ2f59TLIhKOytdi1IKd3mungriv2h8E3dsdC46Zvb/QPJIiao0p0vdpnllROmSKaw/zzQoHzC/SzfHMeG6/wSbNrXZ6oubIEYtEUJQK27L7va X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:58:53.0134 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: bf1f3628-f4fa-401e-a52d-08df136c2657 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.232];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: BY1PEPF0001AE1B.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: EAYPR12MB999182 Content-Type: text/plain; charset="utf-8" Rust VF drivers can borrow PF-owned registration data directly, but C VF drivers need an ABI-checked operations table and a pinned context. Place an optional struct rust_ffi descriptor at offset zero in the registration header while retaining the Rust TypeId. Initialize registrations created with new() with an empty descriptor, and add new_ffi() to construct a descriptor for the same pinned payload. Add pci_iov_borrow_rust_pf_data() to locate the PF descriptor and validate the token, ABI version, and operations-table size. Require managed SR-IOV so device-link ordering and registration teardown keep the descriptor and its context alive until the VF driver is unbound. Signed-off-by: Zhi Wang --- drivers/pci/iov.c | 51 +++++++++++++++++ include/linux/pci.h | 34 +++++++++++- rust/kernel/interop/ffi.rs | 15 ++++- rust/kernel/pci/sriov.rs | 110 ++++++++++++++++++++++++++++--------- 4 files changed, 179 insertions(+), 31 deletions(-) diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index ee5eff209e15..0f3ae75b8a7c 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,56 @@ void *pci_iov_get_pf_drvdata(struct pci_dev *dev, struct= pci_driver *pf_driver) } EXPORT_SYMBOL_GPL(pci_iov_get_pf_drvdata); =20 +#ifdef CONFIG_RUST +/** + * pci_iov_borrow_rust_pf_data - Validate and borrow Rust data from a VF's= PF + * @dev: VF PCI device + * @token: Required FFI ABI token + * @abi_major: Required ABI major version + * @min_abi_minor: Minimum required ABI minor version + * @required_ops_size: Minimum required size of the operations table + * + * This may be called from a VF driver's probe() callback or from a contex= t in + * which the VF driver is known to remain attached. If probe() succeeds, t= he + * returned pointer, its operations table, and its context are borrowed un= til + * the VF driver is fully unbound, including the return of its remove() ca= llback + * when present. If probe() fails, the caller must discard the borrow befo= re + * returning. The caller must drain all work that can use the FFI before t= he + * borrow ends. + * + * The PF must publish an immutable descriptor before enabling VFs, use + * managed_sriov, and retain the descriptor until its remove() callback. + * Managed SR-IOV installs a device link from every VF to its PF before th= e VF + * can probe. The driver core therefore waits for an in-progress VF probe = and + * unbinds a bound VF before invoking the PF driver's remove() callback. + * + * Return: A borrowed FFI descriptor, or an ERR_PTR() value on failure. + */ +const struct rust_ffi * +pci_iov_borrow_rust_pf_data(struct pci_dev *dev, + const struct rust_ffi_token *token, + u16 abi_major, u16 min_abi_minor, + size_t required_ops_size) +{ + const struct rust_ffi *ffi; + struct pci_dev *pf_dev; + struct pci_driver *pf_driver; + + if (!dev->is_virtfn) + return ERR_PTR(-EINVAL); + + pf_dev =3D pci_physfn(dev); + pf_driver =3D READ_ONCE(pf_dev->driver); + if (!pf_driver || !READ_ONCE(pf_driver->managed_sriov)) + return ERR_PTR(-ENODEV); + + ffi =3D READ_ONCE(pf_dev->vf_registration_data_rust); + return rust_ffi_borrow(ffi, token, abi_major, min_abi_minor, + required_ops_size); +} +EXPORT_SYMBOL_GPL(pci_iov_borrow_rust_pf_data); +#endif + /* * Per SR-IOV spec sec 3.3.10 and 3.3.11, First VF Offset and VF Stride may * change when NumVFs changes. diff --git a/include/linux/pci.h b/include/linux/pci.h index 1ccc7fee7495..4a7189ee247f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -339,6 +339,8 @@ struct pcie_link_state; struct pci_sriov; struct pci_p2pdma; struct rcec_ea; +struct rust_ffi; +struct rust_ffi_token; =20 /* struct pci_dev - describes a PCI device * @@ -352,9 +354,10 @@ struct rcec_ea; * Such bridges are allocated additional MMIO and bus * number resources to allow for hierarchy expansion. * @is_pciehp: PCIe Hot-Plug Capable bridge. - * @vf_registration_data_rust: Rust registration data published by the PF - * before enabling VFs and retained until all VFs are - * removed. The PF driver must use managed_sriov. + * @vf_registration_data_rust: Rust registration data beginning with a + * struct rust_ffi, published by the PF before + * enabling VFs and retained until all VFs are removed. + * The PF driver must use managed_sriov. */ struct pci_dev { struct list_head bus_list; /* Node in per-bus list */ @@ -2614,6 +2617,22 @@ int pci_iov_virtfn_bus(struct pci_dev *dev, int id); int pci_iov_virtfn_devfn(struct pci_dev *dev, int id); int pci_iov_vf_id(struct pci_dev *dev); void *pci_iov_get_pf_drvdata(struct pci_dev *dev, struct pci_driver *pf_dr= iver); +#ifdef CONFIG_RUST +const struct rust_ffi * +pci_iov_borrow_rust_pf_data(struct pci_dev *dev, + const struct rust_ffi_token *token, + u16 abi_major, u16 min_abi_minor, + size_t required_ops_size); +#else +static inline const struct rust_ffi * +pci_iov_borrow_rust_pf_data(struct pci_dev *dev, + const struct rust_ffi_token *token, + u16 abi_major, u16 min_abi_minor, + size_t required_ops_size) +{ + return ERR_PTR(-EOPNOTSUPP); +} +#endif int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn); void pci_disable_sriov(struct pci_dev *dev); =20 @@ -2656,6 +2675,15 @@ static inline void *pci_iov_get_pf_drvdata(struct pc= i_dev *dev, return ERR_PTR(-EINVAL); } =20 +static inline const struct rust_ffi * +pci_iov_borrow_rust_pf_data(struct pci_dev *dev, + const struct rust_ffi_token *token, + u16 abi_major, u16 min_abi_minor, + size_t required_ops_size) +{ + return ERR_PTR(-EOPNOTSUPP); +} + static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) { return -ENODEV; } =20 diff --git a/rust/kernel/interop/ffi.rs b/rust/kernel/interop/ffi.rs index a8c16a29110a..ea23bfecad32 100644 --- a/rust/kernel/interop/ffi.rs +++ b/rust/kernel/interop/ffi.rs @@ -99,10 +99,23 @@ pub unsafe trait Abi: 'static { /// [`struct rust_ffi`](srctree/include/linux/rust_ffi.h). It neither owns= nor borrows the /// operations table or Rust context at the type level. The transport that= publishes it must ensure /// that `ops` remains valid and that `context` remains alive at a stable = address until all -/// consumers have stopped using the descriptor. +/// consumers have stopped using the descriptor. The default value exposes= no operations. #[repr(transparent)] pub struct Descriptor(bindings::rust_ffi); =20 +impl Default for Descriptor { + fn default() -> Self { + Self(bindings::rust_ffi { + token: bindings::rust_ffi_token { high: 0, low: 0 }, + abi_major: 0, + abi_minor: 0, + ops_size: 0, + ops: core::ptr::null(), + context: core::ptr::null(), + }) + } +} + impl Descriptor { /// Creates a descriptor for a pinned Rust context. /// diff --git a/rust/kernel/pci/sriov.rs b/rust/kernel/pci/sriov.rs index efbe444e0733..a2590b66f78b 100644 --- a/rust/kernel/pci/sriov.rs +++ b/rust/kernel/pci/sriov.rs @@ -6,6 +6,10 @@ use crate::{ bindings, device, // + interop::ffi::{ + Abi, + Descriptor, // + }, prelude::*, types::{ CovariantForLt, @@ -91,26 +95,45 @@ pub fn num_vfs(&self) -> i32 { // depends on its device context. kernel::impl_device_context_deref!(unsafe { Device }); =20 +#[repr(C)] +struct VfRegistrationHeader { + ffi: Descriptor, + type_id: TypeId, +} + +static_assert!(core::mem::offset_of!(VfRegistrationHeader, ffi) =3D=3D 0); + #[repr(C)] #[pin_data] struct VfRegistrationData<'a, F: ForLt + 'static> { - type_id: TypeId, + header: VfRegistrationHeader, #[pin] data: F::Of<'a>, } =20 static_assert!( - core::mem::offset_of!(VfRegistrationData<'static, CovariantForLt!(())>= , type_id) =3D=3D 0 + core::mem::offset_of!(VfRegistrationData<'static, CovariantForLt!(())>= , header) =3D=3D 0 ); =20 impl<'a, F: ForLt + 'static> VfRegistrationData<'a, F> { - fn new(data: D) -> impl PinInit + use<'a, D, F> + fn new(data: D, make_descriptor: M) -> impl PinInit= + use<'a, D, F, M> where D: PinInit, Error> + 'a, + M: FnOnce(Pin<&F::Of<'a>>) -> Descriptor + 'a, { - try_pin_init!(Self { - type_id: TypeId::of::(), + try_pin_init!(&this in Self { + header: VfRegistrationHeader { + ffi: Descriptor::default(), + type_id: TypeId::of::(), + }, data <- data, + _: { + // SAFETY: `data` has been initialized in place and will r= emain pinned at this + // address. + let data =3D unsafe { Pin::new_unchecked(&(*this.as_ptr())= .data) }; + // SAFETY: `header.ffi` is initialized and exclusively own= ed during construction. + unsafe { (*this.as_ptr()).header.ffi =3D make_descriptor(d= ata) }; + }, }) } } @@ -138,28 +161,14 @@ impl<'a, F: ForLt + 'static> VfRegistration<'a, F> where for<'b> F::Of<'b>: Send + Sync, { - /// Publishes typed PF data for bound VF drivers. - /// - /// This returns a pin-initializer so the registration and payload can= be embedded directly in - /// the PF driver's pinned data. - /// - /// Initialization returns [`ENODEV`] for a VF and [`EBUSY`] if the PF= has enabled VFs or - /// already has a registration. - /// - /// # Safety - /// - /// The caller must invoke this during the PCI driver's probe and embe= d the result in the driver - /// data. On an SR-IOV PF, no VF may be enabled before probe successfu= lly installs the complete - /// driver data, and the driver must use managed SR-IOV. The registrat= ion must be dropped before - /// anything its payload borrows and must not be forgotten. Probe must= have exclusive access to - /// the PF registration slot. On a conventional PCI function, the regi= stration remains - /// inactive. - pub unsafe fn new<'core, D>( + fn new_with_descriptor<'core, D, M>( pdev: &'a PciDevice>, data: D, - ) -> impl PinInit + use<'a, 'core, D, F> + make_descriptor: M, + ) -> impl PinInit + use<'a, 'core, D, F, M> where D: PinInit, Error> + 'a, + M: FnOnce(Pin<&F::Of<'a>>) -> Descriptor + 'a, { pin_init::pin_init_scope(move || { if pdev.is_virtfn() { @@ -179,7 +188,7 @@ pub unsafe fn new<'core, D>( =20 Ok(try_pin_init!(Self { pdev, - inner <- VfRegistrationData::new(data), + inner <- VfRegistrationData::new(data, make_descriptor), published, _pin: PhantomPinned, _: { @@ -192,6 +201,53 @@ pub unsafe fn new<'core, D>( })) }) } + + /// Publishes typed PF data for bound VF drivers. + /// + /// This returns a pin-initializer so the registration and payload can= be embedded directly in + /// the PF driver's pinned data. + /// + /// Initialization returns [`ENODEV`] for a VF and [`EBUSY`] if the PF= has enabled VFs or + /// already has a registration. + /// + /// # Safety + /// + /// The caller must invoke this during the PCI driver's probe and embe= d the result in the driver + /// data. On an SR-IOV PF, no VF may be enabled before probe successfu= lly installs the complete + /// driver data, and the driver must use managed SR-IOV. The registrat= ion must be dropped before + /// anything its payload borrows and must not be forgotten. Probe must= have exclusive access to + /// the PF registration slot. On a conventional PCI function, the regi= stration remains + /// inactive. + pub unsafe fn new<'core, D>( + pdev: &'a PciDevice>, + data: D, + ) -> impl PinInit + use<'a, 'core, D, F> + where + D: PinInit, Error> + 'a, + { + Self::new_with_descriptor(pdev, data, |_| Descriptor::default()) + } + + /// Publishes typed PF data with an FFI operations table for C VF driv= ers. + /// + /// Rust VFs access the same payload through [`PciDevice::vf_registrat= ion_data()`] or + /// [`PciDevice::vf_registration_data_with()`]. + /// + /// # Safety + /// + /// The caller must uphold the requirements of [`Self::new()`]. A C co= nsumer must stop calling + /// and discard the borrow before returning from a failed VF probe, or= before its VF remove + /// callback returns after a successful probe. + pub unsafe fn new_ffi<'core, A, D>( + pdev: &'a PciDevice>, + data: D, + ) -> impl PinInit + use<'a, 'core, A, D, F> + where + A: Abi, + D: PinInit, Error> + 'a, + { + Self::new_with_descriptor(pdev, data, Descriptor::new::) + } } =20 #[pinned_drop] @@ -251,9 +307,9 @@ unsafe fn vf_registration_data_pinned(&self) -> Result().read() }; + // SAFETY: The published pointer addresses a `VfRegistrationData`,= whose first field is + // its header. + let type_id =3D unsafe { (&raw const (*ptr.cast::()).type_id).read() }; if type_id !=3D TypeId::of::() { return Err(EINVAL); } From nobody Fri Sep 25 06:46:56 2026 Received: from CH1PR05CU001.outbound.protection.outlook.com (mail-northcentralusazon11010021.outbound.protection.outlook.com [52.101.193.21]) (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 3CF7748820C; Tue, 15 Sep 2026 20:59:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.193.21 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505954; cv=fail; b=OKLnM58u2Xi5Cb1Negr1kOALwS8ZDnpzM4Gpq42WkOtXYKOB0Lk4orJ5e3RMCHq0NGDyxgxKKNa4bf7Muu3ZfZ1shaMmLdXX64vew8+2iwfvH7j0vYL7PPxi94UjevzxYFeMFZMpWI3eFXZGhuwdLmOSIMoMrsYihbDLCYx8f+k= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505954; c=relaxed/simple; bh=ZOscDNBBgmBiGa0M9iCngfWW5mJi4zATwb7ZkqqanvQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KTHSlXZz4DF2FHS+QWaXz//OJGjLilIQiwgBRp4qk5GbgmmEYuzvyJWi/wZ+oDGxK/x5IKrcWUSZPGdV8JTVmt/x4imJWMZTr6oylZXJT+Xdo/JdUTZmT4T51FP1JG2JY5HjNORXYyskenJwMLNWBcXwYKhPxOesrtqM721wwzw= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=aY6tPo4D; arc=fail smtp.client-ip=52.101.193.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="aY6tPo4D" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=i2ABh1tO+qB2rQgvuna4cWcfe5cywe4D3rdI37xz/7UIUPTYmnqyMUEcoKwiKjXBN6JkX61t0j5ZQ+asoL3rT9Wn29qYQW0xZkz4zZ+Inv3CdpF+oSY+kKTzWUvz4dHvUdtAHxWinFLdCU/UaEKC6idRhPvm0w4AyNRJFXaUg+6qaNOJrltKK94gOguIJsEya0Z0VkZ0I1b2HBZ9/1JGWICAI5Gapwu73LDYd7h1nsrLU85EsrDFcHKqnhP5Yis34sJnB8RAwsqqZoFFrLtd0QQoAGVkPFoBkrrwlq5ING6ZoTU217sbdSNhYrm0rQ5hzkM6D78/HIxNvdtlHmJwZg== 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=0lv9kmeqDQhMYynQH2CQDcdH1AfpdkKhV23DQhQJQFg=; b=BwjFAOFonT3KVGypUPYmwcq8qc3pKWAPfCh53uQ8ZMphXQjpANHKoxsgR+AgJ+/Nh5rEsZj/GkWsu6bkBAMMwP25vf88wlKUI6rTjb0bHB6JebGrgPcV4O+Ta808klINyY9NI5csGik6eqzPYVehfbgTvlWYk99eEXW/maPvvowI0WB7S3r31e0EUx0n1bEXUN5gfafulbwfLzsc0i3ANritgNH4hKbZ7wCUTypXfmVIV0MWYgrmsR8cnhv+D3ehwGwSW4eZof833nSdL2ShsljFZWvt3Ob5fl49DFBZOrrVuSUDYc8/sdSh+8rfWJR9/B8FnzOba2IVQjN7BLfi+Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.232) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=0lv9kmeqDQhMYynQH2CQDcdH1AfpdkKhV23DQhQJQFg=; b=aY6tPo4Duv3DM1tTHekHpudw/3weZK2sH0Jxvqs3hWTZd8CT+rbStPYpjuBLQQEDvvjXZiBHNBHCgxaIs2CWRMEoni+bWH5CAtrVIm+7LH+xSbi3piQVsEVfsPXFq953Rgps2qFN7hLTKHn8bawmuuF4addXDPqTmsqmJGju8JcYZJomjzWVNct9TPyRmH9YgTiEYvOLv6Z0wrCb77nWVNmlsEUQwBELe4P8e7irGaS4X8CHp4Cd2nCPSqZlcxJylLIbstQViOcQXyZ0L6MKon/J9JrVoKyxib/6qIDcsv06i+7mVlRR/DsGNXtczIOZa0DkxWrhSRB5f31vd3HoGw== Received: from MW4PR04CA0331.namprd04.prod.outlook.com (2603:10b6:303:8a::6) by BL1PR12MB5707.namprd12.prod.outlook.com (2603:10b6:208:386::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.406.12; Tue, 15 Sep 2026 20:58:59 +0000 Received: from BY1PEPF0001AE1C.namprd04.prod.outlook.com (2603:10b6:303:8a:cafe::5) by MW4PR04CA0331.outlook.office365.com (2603:10b6:303:8a::6) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.406.12 via Frontend Transport; Tue, 15 Sep 2026 20:58:58 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.232) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.232 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.232; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.232) by BY1PEPF0001AE1C.mail.protection.outlook.com (10.167.242.105) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:58:58 +0000 Received: from drhqmail201.nvidia.com (10.126.190.180) by mail.nvidia.com (10.127.129.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:44 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail201.nvidia.com (10.126.190.180) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:44 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:58:36 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Zhi Wang Subject: [PATCH 12/14] samples: rust: add C SR-IOV VF driver that calls into a Rust PF driver Date: Tue, 15 Sep 2026 23:56:56 +0300 Message-ID: <20260915205659.76841-13-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BY1PEPF0001AE1C:EE_|BL1PR12MB5707:EE_ X-MS-Office365-Filtering-Correlation-Id: 5d84cea1-3469-4a2d-40e2-08df136c29b3 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|23010399003|82310400026|7416014|1800799024|36860700016|376014|11063799006|5023799004|6133799003|56012099006|3023799007|10067099003|22082099003|18002099003|13003099007; X-Microsoft-Antispam-Message-Info: 0tLC9rtTHlYW7+VZCK0fNlwYxhMy1U0ALq7pFcXPHVBuvRflA5CsMn4BGr/G8Mw3xncZFNejWVDNzYmcoSjkDELLJyKFZTdW348NypxuW73Gbf1YjdCiV6lsC/nVIyIVL7iXew4q6iE7SdaLu7ckRDMv5mSEoA/TF5dTY/xfzXtZ6nMygDJoFiWXj4LcPsWUreSj8vWEOXctW2mDqUzr9dPllgK8xe/LsMkErjCmeZF9lHiefwNsbGbNW/9rO1NB9KhgFU9enKwSzUwntigg2nLZg4+ZJwK6f4R1E/9zGPYXvBcwdlaprH0kyCf8WGI/D5GeVLa0AFrKeBa6ntbjan9/Ds61Qh2eLZLaVLPcTIB2dAEwDtzhLPthofnqb5x5YzsUfyoVuRup/PSLRZQNeoFchyu3ol8WKuJP5hbPvUSNKGjuqb+U484B4SebTQrGuhNvCNXIH6iUY4vpTysN6iId3SSLvOTUppRDRFkvmjr2NqX2nmLdPmL556H/zj9HZntpbF7MMb/f6bu7FaJUrLfVNSpGIAhYUzJWDel+UB8sGHnuIqw02YMAnJ5aK5uKrOP4wAkwx24GG2U1kg6E1maii051DaZNwqpkb4eoHbdFtkiFM0oYJeI7pIth/xlyH50gdaSJOvVAKgr2rlIb1mqePPuosCGdN4Z5niF4FPSHi3S4yZLEta+1eJ5jYc+evbB8KDAXEjluthCUsoO7XA== X-Forefront-Antispam-Report: CIP:216.228.118.232;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge1.nvidia.com;CAT:NONE;SFS:(13230040)(23010399003)(82310400026)(7416014)(1800799024)(36860700016)(376014)(11063799006)(5023799004)(6133799003)(56012099006)(3023799007)(10067099003)(22082099003)(18002099003)(13003099007);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: o09t4W9W/2jiAhPnp3981dej4qDlaiGpVaCkkODCVKgJ7oxm4RmjHV5IUY7+UayzSTw7Mk+YnWzuy6wrPYYlVYUFrgMV/dmPrxv0OVVfFVAdXQnHL25PcVzcoVBUnfBtfHS+FE+jpBHsZSIIHLU05uPsAkKD5x5GSlIja5C6pqZKTC3/PKGwg+jPQCyf5xpbgxsXgmZSZrH4su/SngjbOCxZkzo1AOv4ZVSS4Dxz7m+6kiQIZJ3oMiCWex7/GPfCpFhl8DPDBPGTFKlGe+fCzeISame1M4qSRbYZhLkc4Rqkh8bXmHqRQ5qU1WAMXwk2vH+ygKtdDW7yDHIAr13JK09VxaZOFh3vdPkHRhq2IF2AGSJKroDvb4XYLd4rDTCCd63N8kgws3RccIXrqErYVNMjJ7ybQdWFPNCS5nJdJwcAkZ08MOocTVaIdc1kSOeL X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:58:58.6614 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 5d84cea1-3469-4a2d-40e2-08df136c29b3 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.232];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: BY1PEPF0001AE1C.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BL1PR12MB5707 C drivers need a type-checked way to invoke functionality implemented by Rust PF drivers without receiving the PF driver's complete private data. The Rust SR-IOV sample currently demonstrates only a Rust VF consumer. Add an optional C VF module that borrows the sample's published PF data through a `struct rust_ffi` descriptor. Validate the ABI token, version, and operations-table size before calling an automatically generated Rust trampoline. Route Rust and C VF requests through the same PF handler. The generated C callback forwards the requester's PCI ID and translates the Rust `Result` into the C errno convention. The C driver uses the borrow only while its VF remains bound, so all users must be drained before its remove callback returns. Signed-off-by: Zhi Wang --- MAINTAINERS | 2 +- rust/bindings/bindings_helper.h | 4 ++ samples/rust/Kconfig | 17 +++++++- samples/rust/Makefile | 1 + samples/rust/rust_driver_sriov.h | 27 ++++++++++++ samples/rust/rust_driver_sriov.rs | 43 ++++++++++++++++--- samples/rust/rust_driver_sriov_c_vf.c | 61 +++++++++++++++++++++++++++ 7 files changed, 146 insertions(+), 9 deletions(-) create mode 100644 samples/rust/rust_driver_sriov.h create mode 100644 samples/rust/rust_driver_sriov_c_vf.c diff --git a/MAINTAINERS b/MAINTAINERS index 9f70dc14bf78..e03ebe44c341 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21141,7 +21141,7 @@ F: rust/helpers/pci.c F: rust/kernel/pci.rs F: rust/kernel/pci/ F: samples/rust/rust_driver_pci.rs -F: samples/rust/rust_driver_sriov.rs +F: samples/rust/rust_driver_sriov* =20 PCIE BANDWIDTH CONTROLLER M: Ilpo J=C3=A4rvinen diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 6a30455768b4..2467305c4842 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -112,6 +112,10 @@ #include #endif =20 +#if IS_ENABLED(CONFIG_SAMPLE_RUST_DRIVER_SRIOV) +#include "../../samples/rust/rust_driver_sriov.h" +#endif + /* `bindgen` gets confused at certain things. */ const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN =3D ARCH_SLAB_MINALIGN; const size_t RUST_CONST_HELPER_ARCH_KMALLOC_MINALIGN =3D ARCH_KMALLOC_MINA= LIGN; diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index 737670fd68f8..3747f3fe23dd 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -132,13 +132,28 @@ config SAMPLE_RUST_DRIVER_SRIOV tristate "SR-IOV Driver" depends on PCI_IOV help - This option builds the Rust SR-IOV driver sample. + This option builds the Rust SR-IOV PF and VF driver sample. =20 To compile this as a module, choose M here: the module will be called rust_driver_sriov. =20 If unsure, say N. =20 +config SAMPLE_RUST_DRIVER_SRIOV_C_VF + tristate "C VF consumer for the Rust SR-IOV driver" + depends on SAMPLE_RUST_DRIVER_SRIOV + help + This option builds a C VF driver that accesses PF data through FFI + published by the Rust SR-IOV PF sample. + + To compile this as a module, choose M here: the module will be called + rust_driver_sriov_c_vf. Load it before rust_driver_sriov and enable + VFs only after both drivers are registered. Ensure that no other VF + driver has claimed the device; driver_override may be used for a + deterministic test. + + If unsure, say N. + config SAMPLE_RUST_DRIVER_USB tristate "USB Driver" depends on USB =3D y diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 238a11d5ec39..b52f07df52de 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_SAMPLE_RUST_DRIVER_I2C) +=3D rust_driver_i2= c.o obj-$(CONFIG_SAMPLE_RUST_I2C_CLIENT) +=3D rust_i2c_client.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) +=3D rust_driver_pci.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) +=3D rust_driver_platform.o +obj-$(CONFIG_SAMPLE_RUST_DRIVER_SRIOV_C_VF) +=3D rust_driver_sriov_c_vf.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_SRIOV) +=3D rust_driver_sriov.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_USB) +=3D rust_driver_usb.o obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) +=3D rust_driver_faux.o diff --git a/samples/rust/rust_driver_sriov.h b/samples/rust/rust_driver_sr= iov.h new file mode 100644 index 000000000000..1d4dff4e3414 --- /dev/null +++ b/samples/rust/rust_driver_sriov.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _SAMPLES_RUST_DRIVER_SRIOV_H +#define _SAMPLES_RUST_DRIVER_SRIOV_H + +#include + +#define RUST_DRIVER_SRIOV_FFI_TOKEN_HIGH 0x6c8686c04f7a4ba1ULL +#define RUST_DRIVER_SRIOV_FFI_TOKEN_LOW 0x77ab9a3c4d3cfb34ULL +#define RUST_DRIVER_SRIOV_FFI_ABI_MAJOR 1U +#define RUST_DRIVER_SRIOV_FFI_ABI_MINOR 0U + +/** + * struct rust_driver_sriov_ops - Operations published by the Rust PF samp= le + * @submit: Submit one request for a requester ID and return 0 or a negati= ve + * errno + * + * The context passed to each operation must be the context from the borro= wed + * struct rust_ffi. It remains valid until the VF driver is fully unbound, + * including the return of its remove() callback when present. + * + * @submit may sleep and must not be called from atomic context. + */ +struct rust_driver_sriov_ops { + int (*submit)(const void *context, u16 requester_id); +}; + +#endif /* _SAMPLES_RUST_DRIVER_SRIOV_H */ diff --git a/samples/rust/rust_driver_sriov.rs b/samples/rust/rust_driver_s= riov.rs index ae1e1babb66b..f3e37586b0f4 100644 --- a/samples/rust/rust_driver_sriov.rs +++ b/samples/rust/rust_driver_sriov.rs @@ -10,15 +10,24 @@ //! //! and append `intel_iommu=3Don` to the guest kernel arguments. //! +//! The optional `rust_driver_sriov_c_vf` module demonstrates a C VF calli= ng the same PF data +//! through an FFI operations table. +//! Load that module before this one and enable VFs only after both driver= s are registered. +//! //! [igb]: https://www.qemu.org/docs/master/system/devices/igb.html //! [vIOMMU]: https://wiki.qemu.org/Features/VT-d =20 use kernel::{ + bindings, device::{ Bound, Core, // }, driver, + interop::ffi::{ + Abi, + Token, // + }, new_mutex, pci, prelude::*, @@ -45,8 +54,9 @@ struct PfApi<'bound> { =20 type PfApiForLt =3D CovariantForLt!(PfApi<'_>); =20 +#[kernel::macros::ffi_vtable(SAMPLE_FFI_OPS: bindings::rust_driver_sriov_o= ps)] impl PfApi<'_> { - fn submit(self: Pin<&Self>, vf: &pci::Device) -> Result { + fn submit(self: Pin<&Self>, requester_id: u16) -> Result { let mut requests =3D self.requests.lock(); let request =3D (*requests).checked_add(1).ok_or(EOVERFLOW)?; *requests =3D request; @@ -54,15 +64,34 @@ fn submit(self: Pin<&Self>, vf: &pci::Device) ->= Result { =20 dev_info!( self.pdev, - "Handle PF request {} from VF devfn {:#x}.\n", + "Handle PF request {} from VF requester ID {:#06x}.\n", request, - vf.dev_id() + requester_id ); =20 - Ok(request) + Ok(()) } } =20 +struct SampleFfiAbi; + +// SAFETY: +// - `RawOps` and the token/version constants come from the C header share= d with consumers; +// - `SAMPLE_FFI_OPS` is initialized as that raw type by `ffi_vtable`; and +// - every callback recovers the context as the pinned `PfApi` published b= elow. +unsafe impl Abi for SampleFfiAbi { + type Context =3D PfApiForLt; + type RawOps =3D bindings::rust_driver_sriov_ops; + + const OPS: &'static Self::RawOps =3D &SAMPLE_FFI_OPS; + const TOKEN: Token =3D Token::new( + bindings::RUST_DRIVER_SRIOV_FFI_TOKEN_HIGH, + bindings::RUST_DRIVER_SRIOV_FFI_TOKEN_LOW, + ); + const ABI_MAJOR: u16 =3D bindings::RUST_DRIVER_SRIOV_FFI_ABI_MAJOR as = u16; + const ABI_MINOR: u16 =3D bindings::RUST_DRIVER_SRIOV_FFI_ABI_MINOR as = u16; +} + #[pin_data(PinnedDrop)] struct PfDriverData<'bound> { // Keep the device alive until the registration stops exposing `PfApi:= :pdev`. @@ -125,7 +154,7 @@ fn probe<'bound>( // - no other registration is created for this PF; and // - VFs are enabled only after probe by `sriov_configure`. _registration <- unsafe { - pci::VfRegistration::new( + pci::VfRegistration::new_ffi::( pdev, try_pin_init!(PfApi { pdev, @@ -191,8 +220,8 @@ fn probe<'bound>( pdev.enable_device_mem()?; pdev.set_master(); =20 - let request =3D pf_api.submit(pdev)?; - dev_info!(pdev, "Submitted request {} through PF data.\n", req= uest); + pf_api.submit(pdev.dev_id())?; + dev_info!(pdev, "Submitted request through PF data.\n"); =20 Ok(try_pin_init!(VfDriverData { pdev: pdev.into() })) }) diff --git a/samples/rust/rust_driver_sriov_c_vf.c b/samples/rust/rust_driv= er_sriov_c_vf.c new file mode 100644 index 000000000000..50df98867361 --- /dev/null +++ b/samples/rust/rust_driver_sriov_c_vf.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +#include "rust_driver_sriov.h" + +#define E1000_DEV_ID_82576_VF 0x10ca + +static const struct rust_ffi_token ffi_token =3D { + .high =3D RUST_DRIVER_SRIOV_FFI_TOKEN_HIGH, + .low =3D RUST_DRIVER_SRIOV_FFI_TOKEN_LOW, +}; + +static int rust_driver_sriov_c_vf_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + const struct rust_driver_sriov_ops *ops; + const struct rust_ffi *ffi; + int ret; + + ffi =3D pci_iov_borrow_rust_pf_data(pdev, &ffi_token, + RUST_DRIVER_SRIOV_FFI_ABI_MAJOR, + RUST_DRIVER_SRIOV_FFI_ABI_MINOR, + sizeof(*ops)); + if (IS_ERR(ffi)) + return dev_err_probe(&pdev->dev, PTR_ERR(ffi), + "failed to borrow PF FFI\n"); + + ops =3D ffi->ops; + if (!ops->submit) + return dev_err_probe(&pdev->dev, -EOPNOTSUPP, + "PF FFI does not implement submit\n"); + + ret =3D ops->submit(ffi->context, pci_dev_id(pdev)); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to submit through PF FFI\n"); + + pci_info(pdev, "submitted request through Rust PF FFI\n"); + + return 0; +} + +static const struct pci_device_id rust_driver_sriov_c_vf_id_table[] =3D { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, E1000_DEV_ID_82576_VF) }, + { } +}; +MODULE_DEVICE_TABLE(pci, rust_driver_sriov_c_vf_id_table); + +static struct pci_driver rust_driver_sriov_c_vf_driver =3D { + .name =3D "rust_driver_sriov_c_vf", + .id_table =3D rust_driver_sriov_c_vf_id_table, + .probe =3D rust_driver_sriov_c_vf_probe, +}; +module_pci_driver(rust_driver_sriov_c_vf_driver); + +MODULE_AUTHOR("Rust for Linux Contributors"); +MODULE_DESCRIPTION("C VF consumer for the Rust SR-IOV driver sample"); +MODULE_LICENSE("GPL"); From nobody Fri Sep 25 06:46:56 2026 Received: from SN4PR2101CU001.outbound.protection.outlook.com (mail-southcentralusazon11012024.outbound.protection.outlook.com [40.93.195.24]) (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 E35154A3F11; Tue, 15 Sep 2026 20:59:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.195.24 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505957; cv=fail; b=LUVy9TinVJlI1W38BIsaG5T8APJFqk6/FAp4+uov9yA7qLBNXAe4SLrcvRqKtdDtAstXOthJIh7B9QavmZ4znWt4HkjYzHjZXS/eAvyDLUFq33XaoM26gpgebErA8GdWRor9pzcRp/jBEyXBWRIcgK5byDIrNEAP6Ot7FlSMLIQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505957; c=relaxed/simple; bh=T6+vzu2EWDk9W7ksuK5a37pL+UsFszsm1/k5CMKzALw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kr/1zCdgDYo5KulS1iaPKAREx8GXcQGZcDukzEAW2mvAgfAjqtpbCWenPHA9mSkISJqWqGmn2O9c3C+dB9LnrLu7Tp7V8UqvMF82QzFrx0auFB/jng8t4qrMD7WqT9K96qBQhJ2bxjPRFnZH8wOzqrShUcfmD5rGg5f736dhNgg= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=tTL/JLy6; arc=fail smtp.client-ip=40.93.195.24 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="tTL/JLy6" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=PQ6HLswdQOSIUPmgN6OP4cDCokNTkm8svFxm023A96HIQ71Irpsi5edxXzsNXNUYbyyhZ+Iaal/Y8u2bqhB+pmqVm3y9g8K9JhCQdv4KqZTDGHQdeiFHOd42M2S4yUev9xoYokxkPlX4cMTYIPNFishe8NZT4yP4dg0pSUbuUyuu8R+W/hhrPFYsos0GfzcwXHJ4rAadfOtkNsm/svnIKKOOasjv6RaqCUjF3o1KnUESt01ZK76xcM6Qgd3unhljTqGpqBtT7qQknVZMsFp1GpQ/ZPbqd7J02yp0Ob+HRl7xMV2MEc13DRGEstVlEdIszpNJn6CWPpK6Na3Xpggq7Q== 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=1+7UIvDo56YK5eOI621J2q3jOzcgO3Pxxopbgs97lnU=; b=Ww/5SFvVaw4a5vH117HeWjGqIcfr/0QJhRxcrVpytvHJxh08ViMrzMeKVxLHnfTWkha4Xtuv3ktsPL+hJffOyEFkqtjz3NqcUDEjdGergZsBqga6LCWmLQo8oqF3MqOAPHeS+W72AjGQ7Jp0w89jXFOpd6uX7NthYZQhqLMp4GKaUrpt9ECaUZ+NpZQ9t0mjWWNF6c+gG6AmyD7FtIvXmzTCFd8fUlLdTtmn7Lr/XRLAcSh6G1TBb4x6jkkfIPl6PRy2XyZK4rYvKV7eR0CjXIdDxedwlV3TDKGv7L+SHiqx1as+qudy14XyhDbNqSIAfBZS0MDmXA0LP6V24FcM3A== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.232) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=1+7UIvDo56YK5eOI621J2q3jOzcgO3Pxxopbgs97lnU=; b=tTL/JLy6d5uOCVjlumqYF/1VBODo15BRkKYIF147jNTbYvdYMKnZxxHtizvCc3aUVnA5VBqiu0lOLXBPgB2+Soe2EnHz/VGEIslsczAXAG6zBSxzQTv619nIBLgQ0A/l1UkbitTMbjB/mxaBc2MN6LStgm5EAS9VgSSB2RVMZKg+xIy4ulXXMw/wpeDBCneixsq1dxjT50g0ZUR8RggwWU5RX3JIbQuRYuk0gj7wGUaUGDqH3FhxOfq6Ti0dMvoBlc6Yd1iRVQCNBAA2TW8TyUPYy4A5NRaWdXr1fziBR6AqxhENY3lyMdbpawMYACteAQs7H2uAczsl0L2IPKqZBA== Received: from SJ0PR05CA0038.namprd05.prod.outlook.com (2603:10b6:a03:33f::13) by IA0PR12MB8303.namprd12.prod.outlook.com (2603:10b6:208:3de::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.9; Tue, 15 Sep 2026 20:59:05 +0000 Received: from BY1PEPF0001AE17.namprd04.prod.outlook.com (2603:10b6:a03:33f:cafe::87) by SJ0PR05CA0038.outlook.office365.com (2603:10b6:a03:33f::13) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.428.6 via Frontend Transport; Tue, 15 Sep 2026 20:59:05 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.232) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.232 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.232; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.232) by BY1PEPF0001AE17.mail.protection.outlook.com (10.167.242.107) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:59:05 +0000 Received: from drhqmail201.nvidia.com (10.126.190.180) by mail.nvidia.com (10.127.129.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:52 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail201.nvidia.com (10.126.190.180) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:58:52 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:58:44 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Zhi Wang Subject: [PATCH 13/14] gpu: nova-core: publish typed SR-IOV PF data for VF drivers Date: Tue, 15 Sep 2026 23:56:57 +0300 Message-ID: <20260915205659.76841-14-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BY1PEPF0001AE17:EE_|IA0PR12MB8303:EE_ X-MS-Office365-Filtering-Correlation-Id: b464ed5c-1586-4d29-898a-08df136c2d81 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|82310400026|7416014|376014|1800799024|23010399003|36860700016|6133799003|22082099003|18002099003|10067099003|11063799006|56012099006; X-Microsoft-Antispam-Message-Info: fubDuxQZ9rOo4uk1mNIXgBF3EB1NPUY0ht8zUF0L8T7uCaHKNXazXXptb5DNQBvENw2Bx+Tch2PdMXROhGtQHeiB4FEcyT/VDNDK20uVS98ydOX/gyIidnPR/qw8YU2f+eitaRA+TanvUZqlNF7qFhO/HqebmOHh+awpwVjHVMCgkhIQTAysbbkVCenRjxu7EG7s4otdpGbzvzpMpLmFjj4n4WKSL2320wJD/9PPU6q9sWa1fPJStTgJYFxpraB6SF0rfn1jQ+QI3wTBw1ITX6abInGAVc8frzWvfQNtiPYYo0oxVO6obb0xwZFQ68KmttTLaU3s+1PMhjIOVc8baDzVTxyXshNluNg1dM35LkILVxroOqkvNDPAQatwpGPBGhcnB2fZGBhOCRmzJkNZzWQfgiszOE1Sd01IWEZmmq+R6hAjbKslsXzuQ18o0cfXhBq1PZgHlCWw5U6D8qL3p26b12PPi+wc2I0HSIh8y/K8ZUWnpWRmSADqn55RwbNqqrvEgL3wEnACEiiJAvF9/ynL9AIL6MOtE4d0NZ1avYrB9PrBJWoQtHL3y/5JOtXP9bEkbHCeKOiDx8fVT1rcQPlEEh6WXwU4YLF5C7w5Qzg93z7t4Asu6i8w+fkH/Rm3qfGyVO65WjyEWeLxUbBDLKjnMEH1Tqn4NqdldV6Wcgj3bfVAzddDO6WtdDliMfjkDiLwR3PvcVOwbx359qjMQg== X-Forefront-Antispam-Report: CIP:216.228.118.232;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge1.nvidia.com;CAT:NONE;SFS:(13230040)(82310400026)(7416014)(376014)(1800799024)(23010399003)(36860700016)(6133799003)(22082099003)(18002099003)(10067099003)(11063799006)(56012099006);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: mqytFh7Pj4lDuka8hY7qkgjTAW1j+nJjWhTBevukNFmdsvhO158bd75Rq2a/RdiTWVSAn9KQlYWzsruyVDPxqm6X1AsY9C+6ZnA8JVv6bCHeqUS3ND/qtcqKHc4w8QmugpaBlrYkrH8nTpfPECO+y5jS2ZI2ixZ6kFWjMp4haNrls6IP0zfyZfEU5JNBCGwW4T3tFIcY65nwM4vfgmz5a6e3CRcpf0zM61xd0CGfYWxpoLgx6H3LH0zNW3l8JvUo2c6X6xDFEA79YWZxU9miBVMrbPzqWffVHTNn3kMuVkIFtbUyuYiW9lltDKISiG20sNujPb9VBqA9Zo0o81WiTth/Vw6axFUhNQ1gyeU6NxKmxcIpwcCupxAzoCbWjqGnJv2Q4W181Hryk0qErxsraBg3EDZFg8QGCxlh/G7VnJx80nwa8+Q/S+6GcClO1xj0 X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:59:05.0554 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b464ed5c-1586-4d29-898a-08df136c2d81 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.232];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: BY1PEPF0001AE17.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: IA0PR12MB8303 Content-Type: text/plain; charset="utf-8" Nova-core is the PF-side GPU driver, but it does not implement the PCI callback for `sriov_numvfs`. Userspace therefore cannot enable or disable VFs on GPUs bound to the driver, and no typed PF data is available before a VF is created. Embed a `VfRegistration` in the pinned `NovaCore` driver data and publish unit data, `()`, as a typed readiness marker on SR-IOV PFs. The registration remains inactive on conventional PCI functions and rejects VFs, so nova-core can keep using the ordinary `pci::Driver` abstraction with or without `CONFIG_PCI_IOV`. Implement `sriov_configure()` using the verified PF view and pinned driver data. Managed SR-IOV removes every VF before the inline registration and the rest of `NovaCore` are dropped. Signed-off-by: Zhi Wang --- drivers/gpu/nova-core/driver.rs | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver= .rs index a5b9a50cbaca..1373417386a2 100644 --- a/drivers/gpu/nova-core/driver.rs +++ b/drivers/gpu/nova-core/driver.rs @@ -35,6 +35,10 @@ =20 #[pin_data] pub(crate) struct NovaCore<'bound> { + #[cfg(CONFIG_PCI_IOV)] + #[allow(clippy::type_complexity)] + #[pin] + _vf_registration: pci::VfRegistration<'bound, CovariantForLt!(())>, #[pin] pub(crate) gpu: Gpu<'bound>, bar: pci::Bar<'bound, BAR0_SIZE>, @@ -107,10 +111,18 @@ fn probe<'bound>( pin_init::pin_init_scope(move || { dev_dbg!(pdev, "Probe Nova Core GPU driver.\n"); =20 - pdev.enable_device_mem()?; - pdev.set_master(); - Ok(try_pin_init!(NovaCore { + #[cfg(CONFIG_PCI_IOV)] + // SAFETY: + // - probe has exclusive access before SR-IOV can be enabl= ed; + // - the registration is pinned in driver data and is its = first field; + // - no other registration is created for this device; and + // - the PCI adapter uses managed SR-IOV. + _vf_registration <- unsafe { pci::VfRegistration::new(pdev= , Ok(())) }, + _: { + pdev.enable_device_mem()?; + pdev.set_master(); + }, bar: pdev.iomap_region_sized::(0, c"nova-core/b= ar0")?, bar1: { let bar1_idx =3D bar1_resource_index(pdev)?; @@ -149,4 +161,19 @@ fn probe<'bound>( })) }) } + + #[cfg(CONFIG_PCI_IOV)] + fn sriov_configure<'bound>( + dev: &'bound pci::sriov::Device>, + _this: Pin<&Self::Data<'bound>>, + nr_virtfn: i32, + ) -> Result { + if nr_virtfn =3D=3D 0 { + dev.disable_sriov(); + } else { + dev.enable_sriov(nr_virtfn)?; + } + + Ok(nr_virtfn) + } } From nobody Fri Sep 25 06:46:56 2026 Received: from CH4PR04CU002.outbound.protection.outlook.com (mail-northcentralusazon11013040.outbound.protection.outlook.com [40.107.201.40]) (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 7BFFB49EC4D; Tue, 15 Sep 2026 20:59:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.201.40 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505962; cv=fail; b=L5ljX6zocFyYdLWLhaZGbTFF/767cXBOnig1tiPnA5x+KpFrCf28mn//ovfg6mgZmxzyGBtviASZ/XHIFGeZNTXEDeVCdymlr87QwE5D03uzL/SyMJrJEEbg8jr0dF8NhqWGKocl7jAHbimRNZYBEZduDgplDUs7dhGEjVy68XE= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789505962; c=relaxed/simple; bh=Ks811RhNsdB+AEOzsClsav3MBw7URUSZuTenKi8LtwM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=E0oyb4LWWVOc5GoIqb8USbMT0t3in/b0gMl2IlTODRcDpZMz63m43AmtvBeWbpRzXlgGUGRSyu9l5gYSayDjqLyJALOm4WplSFw6TlQILa8RfEjrdGdPDatdR+dbzUF8aq68Ww9hLMx8vXaoklVv4OMEh/avcRhRG0YQeRFCfkU= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=sxIK/qf8; arc=fail smtp.client-ip=40.107.201.40 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="sxIK/qf8" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=nAIsriIDLzccv5roAdIJsJmArQ2C2XJ171hFRGJ5NDqLqHH8fRJRBkHjsl3eZWWLkwpvapybdBIeD30Ol7lZQufU5mMrjV814y8dEJ2qHu9lZ5r//pOi9DYYNSKL+V6GA9OiD4lQFxTudvhJf+eRgUz6w7ufOKwy4/oWxChTvMOQfAjVkejjMMLznd0WLhwP7kPjozjWbYyXPkicjsK+Nf2p/Qh0xWeRPE/QN2IoxgULw00s1y+FftFwOEUamp8nhxHfrI4Sl7rr9BHLaEwDt4OoXndBwRpT6kIlKahmtsIy3pHClfU5Jw9OoudSvxS2hmlJUbXTIn5X1M95bR0QQg== 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=59MoSNbF2i54C1QGr5kXh03IIvaul41eARPdGXDdk3I=; b=unSMYS9Yy2+lbMALk4sgYRurA4wNsK5wyYY1S3CUmI1Orzw78xcZgO0uPiMeQFqcS8WbPeaoeB2hZ+7XKaMkKkpCGUEQRiY7mpfzJrlIK5UuEJTCcNGKBrc8tNOTPwlfQctCxb3p3/LBQRqo3MB6z2wMZ/zYXqXngdG+xx3l0ZwclL1bKhk2aveauBjd8XcdpfCVxqXx/pRLz9Vb22OO9KDn0bVaLd8sBkQF1EfoHt+2DtB+HfS/JcuQNPRX6Y0i5D4iVVrjpEg6/RR9m3JmncmLLfsszHeuYMoKTpZBjnIj6gG/j28vOKKAI5RXItx0C0YyRu9HGZNn/ddcnYcc3Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.232) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=59MoSNbF2i54C1QGr5kXh03IIvaul41eARPdGXDdk3I=; b=sxIK/qf8ixNuHwEfRIUeMtZMw11tGiuUSQ2Ukr/Y2VkRuQlQZHBH8Z2H5JiB4NGBSQDwtbizMBWrSH9svBdFNuDhqyR/VDrBKkRodI6tDJATiDfrOwpz5S0F69tVPFQCxpwZcySYdXtlWHltSV8sl+yAvNGNaikvym53ywhpgTZgddASicWytP5csfkjco79Ya+MgZJ8/p84XpkDrFl5Rjw5YdbQc6CltUtDqGzGiJiGT4wPpqx9bvl9UxifqxMnHPZcZYN/8U8akuSViLtohT3R0oWeHDq+lf7e3rauJ18QLumszoz4IqKdegIcRYcDrY/VpbW3f7+0g3DwVYxjtA== Received: from SJ0PR05CA0060.namprd05.prod.outlook.com (2603:10b6:a03:33f::35) by SJ0PR12MB8167.namprd12.prod.outlook.com (2603:10b6:a03:4e6::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.406.12; Tue, 15 Sep 2026 20:59:10 +0000 Received: from BY1PEPF0001AE17.namprd04.prod.outlook.com (2603:10b6:a03:33f:cafe::5a) by SJ0PR05CA0060.outlook.office365.com (2603:10b6:a03:33f::35) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.21.406.6 via Frontend Transport; Tue, 15 Sep 2026 20:59:10 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.232) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.232 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.232; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.232) by BY1PEPF0001AE17.mail.protection.outlook.com (10.167.242.107) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.21.428.7 via Frontend Transport; Tue, 15 Sep 2026 20:59:10 +0000 Received: from drhqmail201.nvidia.com (10.126.190.180) by mail.nvidia.com (10.127.129.5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:59:00 -0700 Received: from drhqmail201.nvidia.com (10.126.190.180) by drhqmail201.nvidia.com (10.126.190.180) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.49; Tue, 15 Sep 2026 13:59:00 -0700 Received: from inno-dell.home (10.127.8.9) by mail.nvidia.com (10.126.190.180) with Microsoft SMTP Server id 15.2.2562.49 via Frontend Transport; Tue, 15 Sep 2026 13:58:52 -0700 From: Zhi Wang To: , CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Zhi Wang Subject: [PATCH 14/14] Documentation: rust: explain SR-IOV PF data sharing with VFs Date: Tue, 15 Sep 2026 23:56:58 +0300 Message-ID: <20260915205659.76841-15-zhiw@nvidia.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260915205659.76841-1-zhiw@nvidia.com> References: <20260915205659.76841-1-zhiw@nvidia.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-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BY1PEPF0001AE17:EE_|SJ0PR12MB8167:EE_ X-MS-Office365-Filtering-Correlation-Id: 5d75c8a0-999c-4bdd-2fec-08df136c30fd X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|36860700016|82310400026|1800799024|23010399003|376014|7416014|22082099003|18002099003|56012099006|11063799006|5023799004|3023799007|10067099003|6133799003; X-Microsoft-Antispam-Message-Info: h+qspjJNgF02t5ztOkdcOZFiLZL7K7g36HcGmlKnNvYUh4q672R9PV/HxnB7Szd+qqOYsNfEEJ4a5zUAlJgYNBOcyvMg1/MdbWwtK2xoh22nSgdqSOrFfpNsE/VOQJjX9aT3oC8zFknP0dG46k2CmNQUa2OBtz+ZrUrg0XqFGQqNcEGnfRQt3/jnNYEpeNnxud+xUPPnIf4/yYdJrLMKrcQZxAMSs4idL1FH5ie9LuTJWFuokJpy+LiKL9exlVH1h2FVrxMFyK7ck5hEcA6rRuxcNVnpw0xHB2+rh9WH+gdb2wGoDVBpoms1BZ7+3m2zYCWQcTdhr0XB4JOLoHy1fWMFa7omwcsZdT1jAog37s8HwSWQH5uuEZPOVGhvjf7cjvW5b+daMBBfKOGfaKTFEhSgW4xEC7vKnJbCr4o/Yw82EW64j5yTpbsAKfoZy+EVz+Mci0U1Qu+rS77js2YeCKLnSK4i1KewF+zUi2tohJv/ay2u9xdMxZpx3ZWEGj8S03p71qLmZjKI1I4kUzP9Djr4ROFzGGgZMVcCT10jbjY8wwauHzJ2wn8XeYBWg4QhsZ0W9hTKaeEs0JSfs67xFEMxnwtvs02Ni0N9s8Cj6r/dAetalBfWQPe7UHc68+J1fsrU2R1lfBXZjOLOAiYwbnAJmzhBZPJ2Cx6a7apjxIKieTlLcwYLgFfhafrIgsaMgKkEruu7MbH/RpVhfZ/31A== X-Forefront-Antispam-Report: CIP:216.228.118.232;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge1.nvidia.com;CAT:NONE;SFS:(13230040)(36860700016)(82310400026)(1800799024)(23010399003)(376014)(7416014)(22082099003)(18002099003)(56012099006)(11063799006)(5023799004)(3023799007)(10067099003)(6133799003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: HlLQFtmQpoZssBrkH2OUbkDXI7L1+fd+asPsxnHuzYS9ijhNJVRXqptLhaeo2zo2BJ9G9U8mHbPEHP0fwpj6rzJg2miL49pPurSBI5vx7Rp2VR8xZUJxRrSkaGJxfxoxm4cmz9i/zSQ3S3TYO6JqEOWGaoD/os0UBtg1dctJw8BcmCcvBF0lfCDdVYNEHULcebBPOgH605tFjbZ3AZ0EZY8ARYm9sPhf62oU6lMV/37GJMxODfeXLZXJrhSTxbYjAFihnsJP4ByTiovW0p/aalT3V2jVOm/vM+O7DetI9e/96GJ+YOm/guwWacfjWFtfGOZRcoMmGdm+MCqDFwFjGhxticokB/R0F40wgMXoCQkkZe7poa0WHwh06N6H0cPQb7pQ3biRJy/YAR1BROgEs82X2t79IOd+teB1zY1yPKoXl5K4mJUKSbLfMNLfR10d X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Sep 2026 20:59:10.9059 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 5d75c8a0-999c-4bdd-2fec-08df136c30fd X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.232];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: BY1PEPF0001AE17.namprd04.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR12MB8167 Content-Type: text/plain; charset="utf-8" Rust and C VF drivers may need a narrow PF-owned interface without gaining access to all private data belonging to the PF driver. The typed PF registration and C FFI abstractions span PCI topology, type checking, driver lifetime, and synchronization, which need a single explanation. The design embeds one pinned PF/VF contract inline in ordinary PCI driver data. Rust consumers borrow it as `Pin<&T>`; C consumers borrow a checked operations table and context. Both paths invoke the same Rust implementation, while managed SR-IOV orders VF teardown before PF data destruction. Document the ownership and borrowing model, in-place initialization, publication and teardown rules, FFI versioning and trampolines, locking and asynchronous drain requirements, and limitations. Illustrate the storage, lifetime, and Rust and C call paths with ASCII diagrams. Signed-off-by: Zhi Wang --- Documentation/rust/index.rst | 1 + Documentation/rust/pci-sriov-pf-data.rst | 330 +++++++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 332 insertions(+) create mode 100644 Documentation/rust/pci-sriov-pf-data.rst diff --git a/Documentation/rust/index.rst b/Documentation/rust/index.rst index b78ed0efa784..a3e8924d678a 100644 --- a/Documentation/rust/index.rst +++ b/Documentation/rust/index.rst @@ -37,6 +37,7 @@ more details. coding-guidelines arch-support testing + pci-sriov-pf-data =20 You can also find learning materials for Rust in its section in :doc:`../process/kernel-docs`. diff --git a/Documentation/rust/pci-sriov-pf-data.rst b/Documentation/rust/= pci-sriov-pf-data.rst new file mode 100644 index 000000000000..acc6f3582386 --- /dev/null +++ b/Documentation/rust/pci-sriov-pf-data.rst @@ -0,0 +1,330 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. _pci_rust_sriov_pf_data: + +=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 +Sharing Rust PF data with SR-IOV VF drivers +=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 + +An SR-IOV Physical Function (PF) and its Virtual Functions (VFs) are +independent PCI devices. Their drivers may live in different modules, and= a +VF driver may be written in either Rust or C. Nevertheless, a VF often ne= eds +to invoke a small PF-owned interface for coordination with the physical +device. + +This document describes how a Rust PF driver can publish pinned data for i= ts +VFs without exposing its complete private ``drvdata``. It supplements the +general SR-IOV description in :doc:`../PCI/pci-iov-howto`. + +The idea +=3D=3D=3D=3D=3D=3D=3D=3D + +The PF publishes one deliberately chosen data object through +``VfRegistration`` before enabling VFs. The registration and object are +initialized inline in the PF's pinned driver data. A Rust VF receives a t= yped +``Pin<&T>``. A C VF receives a checked ``struct rust_ffi`` descriptor who= se +operations call the same object through generated C ABI trampolines. + +The published object is an explicit PF/VF contract, not a replacement for = PF +``drvdata``. PCI supplies the route to the correct PF and orders driver +teardown; the chosen object supplies only the data and operations that the= PF +intends to share. VFs borrow that object and never own it. + +There is no global interface registry. PCI topology selects the provider: +the consumer is a VF and its ``physfn`` identifies the PF. The consumer p= ath +then checks that the selected PF published the expected Rust type or C ABI. + +:: + + PF driver data (pinned) + +--------------------------------+ + | VfRegistration | + | +-----------------------------+ + | | rust_ffi (at offset 0) |<----+ + | | TypeId | pinned T |<--+ | + | +-----------------------------+ | | + | remaining PF data | | | + +--------------------------------+ | | + | | + PF struct pci_dev | | + +----------------------------+ | | + | vf_registration_data_rust -+-------+ | + +----------------------------+ | + | + Rust VF: TypeId check -> Pin<&T> -------+ + C VF: token/ABI/size -> ops/context ----+ + +The design separates four concerns: + +* PCI topology selects the actual PF for a VF. +* Rust ``TypeId`` or the C FFI token and version check the requested + interface. +* A managed device link and the inline registration determine the lifetime + of the borrow. +* The published data type supplies any synchronization needed by concurrent + callers. + +The FFI descriptor does not hold a second copy of the PF data. Its +``context`` points at the same pinned object that a Rust VF borrows direct= ly. +For example, both Rust and C VFs in the SR-IOV sample eventually call +``PfApi::submit()``. The C path adds only an ABI trampoline and return-va= lue +conversion. + +Lifetime foundation +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The published pointer is borrowed; it is not a reference-counted handle. +Its lifetime is based on managed SR-IOV and a persistent managed device li= nk +from each VF consumer to its PF supplier. + +The PCI core creates that link before the VF is allowed to probe. The link +remains after a failed probe or a normal driver unbind so it also protects= a +later bind. The driver core consequently waits for an in-progress VF probe +and unbinds every bound VF consumer before unbinding the PF supplier. On = PF +removal, managed SR-IOV also invokes ``sriov_configure(0)`` before the PF +driver's remove callback if VFs are still enabled. VF unbind, including +destruction of its driver data, completes before PF removal proceeds. + +:: + + PF probe + | + +-- initialize and pin VfRegistration and its data + | + +-- publish as the registration's final initialization step + | + PF probe returns and installs all PF driver data + | + sriov_configure(n) enables VFs + | + +-- PCI creates each VF + | + +-- PCI adds a managed link: VF consumer -> PF supplier + | + +-- VF probe borrows and uses the PF data + | + PF unbind is requested + | + +-- driver core unbinds every VF consumer + | | + | +-- VF remove stops and drains all PF calls + | | + | +-- VF driver data is destroyed + | + +-- if VFs remain, PCI invokes sriov_configure(0) + | + +-- disabling SR-IOV destroys VF devices and links + | + +-- PF remove runs + | + +-- PF driver data is destroyed + | + +-- registration disables any remaining VFs + | + +-- registration withdraws and drops the data + +Disabling VFs through ``sriov_numvfs`` follows the shorter part of the same +ordering: VF drivers are removed before their VF devices disappear, while = the +PF driver remains bound and its registration remains published. + +If ``sriov_configure(0)`` does not disable all VFs during PF unbind, the P= CI +core warns and forcibly disables SR-IOV. The lifetime guarantee therefore +does not depend on a successful driver callback. + +A successful VF probe may retain the borrow in its driver data for the +duration of that binding. A failed probe must discard the borrow before +returning. A VF remove callback must stop and drain all work that could u= se +the PF data before the callback returns. These rules also apply to raw +descriptor and context pointers retained by a C VF. + +Publishing PF data +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +PF and VF drivers use the ordinary ``pci::Driver`` abstraction. +``VfRegistration::new()`` publishes ``ForLt``-encoded data for Rust +consumers. ``VfRegistration::new_ffi()`` publishes the same data and adds= a +C-callable FFI descriptor. Both return a pin-initializer rather than an +allocated registration handle. The PF embeds it with ``<-`` in a +``#[pin]`` field of its driver data:: + + #[pin_data] + struct PfData<'a> { + #[pin] + vf_registration: pci::VfRegistration<'a, MyApiForLt>, + // Fields borrowed by MyApi follow the registration. + } + +The constructor rejects a VF. On a conventional PCI function without an +SR-IOV capability it creates an inactive registration, allowing one PF-side +driver to continue supporting devices with and without SR-IOV. + +The constructors are unsafe because the PF driver establishes conditions +that cannot be expressed entirely in the type system. A provider must: + +* Call the constructor during PCI probe, before any VF can be enabled. It + publishes only when that function is an SR-IOV PF. +* Publish at most one registration for a PF. +* Initialize it in the pinned PF driver data and do not forget that data. +* Enable VFs only after PF probe has returned and installed that driver da= ta. +* Use managed SR-IOV so VF consumers are unbound before the registration is + dropped. +* Declare it before any PF driver fields borrowed by the published object,= so + the registration is dropped first. + +The published type must be ``Send + Sync`` for every lifetime because VFs = may +call it from different threads. + +The Rust PCI adapter opts drivers into managed SR-IOV. Its +``sriov_configure`` callback receives a checked ``pci::sriov::Device`` and= a +pinned reference to the PF driver data. It enables or disables VFs with +``enable_sriov()`` and ``disable_sriov()``. + +Rust VF consumers +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +A Rust VF implements ``pci::Driver`` and explicitly requests PF data during +probe. The accessor verifies that the PCI device is a VF, follows its PF +relationship, checks that data was published, compares its ``TypeId``, and +returns a pinned shared reference. The VF does not receive the PF's +``pci::Device``, the PF driver object, or an untyped pointer. + +PF and VF drivers may be registered by separate modules. They must share = the +exact ``ForLt`` type that identifies the PF data. Defining look-alike typ= es +independently does not work because they have different ``TypeId`` values. +When separate Rust crates are used, put the shared definition in a crate t= hat +both can import. + +``vf_registration_data()`` is the direct accessor for data encoded by +``CovariantForLt``. ``vf_registration_data_with()`` supports invariant +data; its higher-ranked closure prevents that data from escaping with a +shortened lifetime. A domain-specific VF handle may store only the VF dev= ice +and use the closure accessor for each operation, rather than retaining a +separate raw PF pointer. + +If one module registers both drivers, register the VF driver first. This +ensures that it is ready before the PF can enable VFs. PF-only and VF-only +modules register their ordinary PCI drivers independently. + +C VF consumers +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +The common C descriptor is declared in ``include/linux/rust_ffi.h``:: + + struct rust_ffi + +---------------------------------------------------+ + | token | ABI version | ops size | ops | context | + +---------------------------------------------------+ + +The token identifies the type and semantics of an operations table. It is +not a PCI device identifier, a secret, an authorization check, a registry +key, or a lifetime handle. PCI locates the PF before comparing the token. + +A driver-specific header defines the stable token, ABI version, and C +operations structure shared by the Rust provider and C consumers. ABI +compatibility follows these rules: + +* The major version must match exactly. +* A provider's minor version must be at least the consumer's requested min= or + version. +* A minor-version update may only append operations to the table. +* ``ops_size`` must cover the table prefix used by the consumer. + +The Rust provider implements ``interop::ffi::Abi`` and applies +``#[ffi_vtable]`` to methods on its PF data. The macro verifies the compl= ete +bindgen operations-table layout and generates a private static operations +table and private C ABI trampolines. It does not generate the C header. A +trampoline recovers ``Pin<&T>`` from ``context`` and invokes the same Rust +method used by Rust VFs. It converts ``Result<()>`` into zero or a negati= ve +errno, and ``Result`` into its successful value or a negative errno. + +:: + + Rust VF C VF + vf_registration_data() borrow + ABI checks + + TypeId check | + | v + v ops->submit(context, id) + Pin<&PfApi> | + | generated trampoline + +------------------+-------------------+ + | + v + PfApi::submit() -> Result + | | + Rust error C 0 or -errno + +A C VF includes ``linux/rust_ffi.h`` directly or through its driver-specif= ic +header and borrows the interface during probe. The essential call sequence +is:: + + const struct my_pf_ops *ops; + const struct rust_ffi *ffi; + int ret; + + ffi =3D pci_iov_borrow_rust_pf_data(vf, &my_token, + MY_ABI_MAJOR, + MY_ABI_MINOR, + sizeof(*ops)); + if (IS_ERR(ffi)) + return PTR_ERR(ffi); + + ops =3D ffi->ops; + if (!ops->submit) + return -EOPNOTSUPP; + + ret =3D ops->submit(ffi->context, pci_dev_id(vf)); + if (ret) + return ret; + +The PCI helper verifies that the device is a VF, that its PF is bound to a +managed SR-IOV driver, and that the descriptor satisfies the requested tok= en, +version, and size. It returns a borrow, so there is no matching ``put`` +operation. The size check does not prove that an individual operation is +implemented, so the consumer must still check each callback it needs. The +pointers must not be used after VF probe fails or after VF remove returns. + +Synchronization and teardown +=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 + +All VFs of a PF borrow the same object and may call it concurrently. Pinn= ing +keeps the object's address stable; it does not serialize access. The PF d= ata +must use interior synchronization appropriate for each operation, such as a +mutex for sleepable methods or an atomic for a simple counter. + +The sample uses ``Mutex`` for its request count to demonstrate shared, +synchronized PF state. The count is an internal implementation detail and +is not returned through the C ABI. Both consumers see only whether +``submit()`` succeeded. + +Document for every C operation whether it may sleep and which calling +contexts are permitted. Before VF removal returns, cancel or flush any wo= rk +that could still call an operation. Do not wait for such work while holdi= ng +a lock that the operation itself needs. + +Disabling SR-IOV through sysfs removes VFs synchronously while holding the= PF +device lock. A VF remove path must not wait for an FFI operation that must +acquire that same lock, or the two paths can deadlock. + +The managed device link supplies driver-presence and teardown ordering, but +not runtime-PM integration. Operations that access powered PF hardware mu= st +arrange runtime PM separately. + +Examples +=3D=3D=3D=3D=3D=3D=3D=3D + +The complete examples are: + +* ``samples/rust/rust_driver_sriov.rs``: a Rust PF and Rust VF sharing a + pinned PF object with a mutex-protected counter; +* ``samples/rust/rust_driver_sriov.h``: the C ABI token, version, and + operations table; +* ``samples/rust/rust_driver_sriov_c_vf.c``: a C VF borrowing and calling = the + Rust PF object; and +* ``drivers/gpu/nova-core/driver.rs``: a regular Rust PCI driver publishing + unit data as a typed PF-readiness marker without a C ABI. + +The Rust and C sample VF drivers match the same device ID, so only one can +bind to a given VF. Use the module ordering described by their Kconfig he= lp +or ``driver_override`` to select the C path deterministically. + +See also :doc:`../driver-api/device_link` for the general device-link mode= l. diff --git a/MAINTAINERS b/MAINTAINERS index e03ebe44c341..922cfddcb2dc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21137,6 +21137,7 @@ L: linux-pci@vger.kernel.org S: Maintained C: irc://irc.oftc.net/linux-pci T: git git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci.git +F: Documentation/rust/pci-sriov-pf-data.rst F: rust/helpers/pci.c F: rust/kernel/pci.rs F: rust/kernel/pci/