From nobody Fri Apr 17 01:39:55 2026 Received: from PH8PR06CU001.outbound.protection.outlook.com (mail-westus3azon11012069.outbound.protection.outlook.com [40.107.209.69]) (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 B7BC837FF4F; Tue, 24 Feb 2026 14:22:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.209.69 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942937; cv=fail; b=DCiofVYKNpWd81qXgJm2xCBlfvtX4mUUUg7J2I7CqCGD7KUjfbRfYJf3OAppuoel4vQl/eCzN5EDPjgJ5KBqemm54hRqWuyFAfM8pQtfGDF87h5hY/N8zP4mZ1qEXJnb5h8pV0iZtVpn6hoJLgPaz8gdPXHIk8r13URC/V32Ehk= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942937; c=relaxed/simple; bh=0FP89CQyif/oPbzDEF0KNnDxci3xeSqE0b59wHIER0w=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=uXc8flx5C8jY91uDs8GhHqgtA9ECoPtlg9TOPrZNeHufNYy90Uw8POeWSKEaxlX8n4grlYC9aOzqW7AWUqaDEjQ62eKQeTXYjxGNtulP5aosFqXCXkYX2TFC3vjyptCQZ19Y96/ZUh+Dos2V/ZduvLaPZbIDEUey7PFRP19JoRE= 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=gPOdubpS; arc=fail smtp.client-ip=40.107.209.69 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="gPOdubpS" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Ey+YyENiaPF/r/CUUaWfrFDtNmrby3CHViGZDhzL4x6al6Zt1OESg5Grn0HuAXHKTQUPz/r6EuwZpzar3fBdJwmsvjGSV0/Ub6NzDtohHidZvpAoLQvjgTP9lizjLwKwVFKJZxBvF8r4eXev7TxX5s4JcIdIkj8oAx/4F6BWrr2P91e8U63nVmj7z8qd9dr9qPeAgKfyNZ+7433JIxOIXYNkRx04pk2FYJ90EniF4XIat5Y/Y9BnhtdZV083C75Lm72pUP0AiGbV36SAWFqDzKghRLfmx7KkY3CyHMw7bEm6fpe7ASHfO4e2VY+4QA44UNX6KY4IgZXxruyzPGI3zw== 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=ae4UeDgfUfzoEEPMB/DfNXHA5UjZCs21uT8+xeI1MT8=; b=WcolQdg7cWKu4imQtnor2+v2rnB102zB+e24Cv4KI1yDtCyPAlsLKyL9ONDxfxtl7q9O2KLWMZlMYXBvEcxUI9DUQFXiwOrD3Ee9Iqc/AAxUGOxdo828pPNsEQTnXyzsDpeUt/wfX7Vn80q7+XfLWruEznqfe3jWaxz7BUwt0UYPWPKS3XLQ0nplXaEQtPsFs30FEM6ghKzOveEIq+mGIqIE0aSZy5dPdcUj9tKftCYyes6IxbpKGM1j8gom263wSPRDYwFidxnb9dNz/OwxlwI72D2aQH+BGJ4qDcs/szBrFrJ3pIoqITMsy16O3FlR9JCdOpC6rbnAbSU1Qiv35Q== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none 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=ae4UeDgfUfzoEEPMB/DfNXHA5UjZCs21uT8+xeI1MT8=; b=gPOdubpShtX0BvX68mQCLv2U8d7cDHWYYuv/9qedDfYXqfYem/FUSy1oifXF1GWIKJT34ygJ90GSpwXCR/0lBaWE6Dqf0BQhGyrcF5bzJTAZdtBFhvEGak+gd5obpO9hEkvddph8X+6VyeNJzU8g/Yh18dL3owuFHVvtIkNTxAFIV9tDCWJBIkCgX8qIQqLP7O/2ty+rd2eFAWW66SaBqhD0cg444WqyDtSMD+TvTa9Pq4VKqnYJkUsra8i/1jdHpM5FKIYYgi4rH7CsLtMSUUQmJHG4JGrS7Hv9zL/KiLbjaEWR5CeWNKgAii3H6vk+Znm7RDo23dDy1bocQrOgFQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by SN7PR12MB7811.namprd12.prod.outlook.com (2603:10b6:806:34f::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 14:22:11 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%6]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 14:22:11 +0000 From: Alexandre Courbot Date: Tue, 24 Feb 2026 23:21:39 +0900 Subject: [PATCH v7 01/10] rust: enable the `generic_arg_infer` feature Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260224-register-v7-1-aad44f760f33@nvidia.com> References: <20260224-register-v7-0-aad44f760f33@nvidia.com> In-Reply-To: <20260224-register-v7-0-aad44f760f33@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Boqun Feng Cc: Yury Norov , John Hubbard , Alistair Popple , Joel Fernandes , Timur Tabi , Edwin Peer , Eliot Courtney , Dirk Behme , Steven Price , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Courbot X-Mailer: b4 0.14.3 X-ClientProxiedBy: TYCP286CA0341.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:38e::9) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR12MB3990:EE_|SN7PR12MB7811:EE_ X-MS-Office365-Filtering-Correlation-Id: 5c12e2d2-fcb5-4d0f-9b0f-08de73b019a1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|7416014|376014|921020|7053199007; X-Microsoft-Antispam-Message-Info: =?utf-8?B?djFrMC9GbDlvME5PUXVVVG9NVll4MHlXYjlVc1p4ODJNRFMyb1ZYQU1kSWZE?= =?utf-8?B?OFlRSi9BNFNyUUxmc09NSDFXSUZ4dkduNlVhQUJYdjZqdEx2ZWxLTHhtRzZT?= =?utf-8?B?blVuNE1OeUlpUGVzaTl3dzZDNStoTTRZR21mY1creFZoMlh5NlVPRmQzS05a?= =?utf-8?B?d3hKYzZhc1I2ZDFnUnB0T2tUNVUwU0ZoZlZqY29ucnB1WFJWS2F0OVFoV0ww?= =?utf-8?B?ajJjeHVta3RYODBjQnk5TVQyL2JxVWV1TWoxQU5pUDRHc2pxS3k0SGFkRVBX?= =?utf-8?B?d1Q4TjNCcklNK3BzZkR2ejF5ZVVuRG9jWmJBaUNVMlg0WnY0MW9TUEUvRG5m?= =?utf-8?B?VFByQk4vcjNYZkhIVTFMdDM5ZWJOS3NaVGRWUlFuRWVDVE05TUw5MHBPQ3M3?= =?utf-8?B?U2cybjFJMkRwVVFrdmtQeGpLam11WGw5VDQ2ZkhMTXlubzlpYzYrL3VPMnFX?= =?utf-8?B?c2w1RUp3QXlzM3RveWN0MG05cGxLWWl2WkZNN3hYcENzUGxFVU80NGc5eCtQ?= =?utf-8?B?RTA1TWFRVmxrdlluS0RvamEvbzlwd2pjTkNycEYvZlZxdnFPN1FINTVoMUNj?= =?utf-8?B?Vk9FRlUwUnJSYjkzYWp1ZUkwTHVmQTRQOWp5bkEzTHdid1ZvdEpQMnY1VGZX?= =?utf-8?B?dmN6cHc1NTlmS1J6M2RteUpMT3kxc05TMzViWDVPSFNONEl0T2hqZHdVUFRS?= =?utf-8?B?ZVhDcmVvTkdEWU1zS3RqZDhEV0lkVCtFcWw3NngrcFFQMldBckVkOExqa1Zj?= =?utf-8?B?ZjV5TzVLV2NZL0xzRG5vbzl3bXdVYzEzRTNGUGNQd29za1J5Z0hVTW11ajIz?= =?utf-8?B?dTNtTWdqZ3AvcWo3eEQyNmRNQ0ZpbTFiYXRaRXlDNHVoaGttZk1OQUt2a1du?= =?utf-8?B?VHpPSmQ1VExUZlg4NnRBKytCbnVlTmJyZG45QTFtdFlaTnBmUk05NE8rYXVU?= =?utf-8?B?ejRxUklWcG5ZcHJXZjB3RHNiTUJNcy9VUm9GMGxlcXBwRmtaY3RhUVh1SWZZ?= =?utf-8?B?YXY0TmVHbkRjS0pjUGx1UzJYQy9qSFZnQ0pZRW5vSjZlQ3AxZTkydGFONmg0?= =?utf-8?B?OU9CTjNDL0p5ZCsyb3FpTERRcTdDRnpxZzc0Q0U3aG9hQkpqMW5BRVA2SjBk?= =?utf-8?B?TEVlM0s2d3dRbWJGZTNER0tLbFFDcWI4T2FyRkF1aWRPZU05cFl2aFhESkhX?= =?utf-8?B?MDQ4dmpLYklNM2hnTlErUUZFRmowWUlTRG5XbmdzYXpRM1V4MUZQWklYL0Nu?= =?utf-8?B?cjlSRWs5YVlCb0RHWU5oMy9qZWlaQzBGcUlFRTZtbUxXVkNLWkRIRG1aWHJy?= =?utf-8?B?aGtFVHc1VHFQRTBaN1ZJZTYxY3N2VTg0SUticlYvQVpVTk1CQTJlK0czLytQ?= =?utf-8?B?MFNxOXk0Y2YvM3E5VU85c0tFdTdPUzJYRDFCaGYydGlVeUlBeVpqajF3anBQ?= =?utf-8?B?NmJOYUFleWZKMzdWeDlnOXVLbEowTnJiSGNoWE8zZCtrWHA4TEJEL1ZOTFJs?= =?utf-8?B?RjZiZUdKUG1PQ0hFdlVHek9TQ0syYWN5aEVCSzJ3cnBITlpXYUFaSWZVNWZK?= =?utf-8?B?RC9xWm9HWDNoTWxVSEtFVkdBaDY3K2hRb2kyVjFDbWE1UVF0bVVpdHhvRDBk?= =?utf-8?B?L0tGZldWWjZ3OFJtWnJRU01RVms4UlhBbTBGMlRZem5qSnc2NWNYL1NzNlkz?= =?utf-8?B?VDdCS2ptTUE3cWUwZ29KcldhM1BTVmE3dHBHamRlQ0lLYWg1aXpsUHFGdzNo?= =?utf-8?B?bU8ySUo3NUpKRTFTK08yOTlYN3JmbTYzOFdqNHpRVEtUT0hMeC9mdk92enJj?= =?utf-8?B?c3VoYzRqUVBleFI3aFB3cVc4RThTeDkzRHlZN3kxWGxMQU1SV05EeHN0eTdr?= =?utf-8?B?WmVBbUFJZVp5NVR4czYySW9wdUJialVSM1pleFVCM3ZxYTRwNjFxcXlvWUw2?= =?utf-8?B?cTNkOTkyWUhCTWcweFF6Q3lNTUtMOG9QWE5aTDBzY3had2JrRGxhM3JuM3R6?= =?utf-8?B?Qm1PRjRQS29CREMycXJFaXhLMGF1SVNZazZsSktMSGVQTjE1eVdMOHNaRlhN?= =?utf-8?B?dE1iK1R4ZmxnS1FuM09YeFpGaEFpTVFOMU51T2QyR2YzdytwUmowVUVwUFpU?= =?utf-8?B?aDhsQmNIUVNtTlVUbm5HU1lIbFpJM01VdkRyVHFoajhVNHRYTEVsNTl3R3dk?= =?utf-8?B?L1E9PQ==?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(7416014)(376014)(921020)(7053199007);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?QWdaRk1HczlOTEdwVGtQYUEwQ1NLajBWdXZVNDlDU2VMT0RUUWtkbGJScXZa?= =?utf-8?B?bGpSbUVpOWoramx3YXpreUx5Qjg4WktiRlUzZjlrRUptM0JiKzlxZVpwc05n?= =?utf-8?B?YzFsSDA0a3E5V09SZnZ0U0NMTnpYcnhjU2w5T2JhUkpybTF0ajBDaThOK0x3?= =?utf-8?B?TW9lek0xNHgxZTF0RXl0QjdQNFEzUjFnaHhIbkJZS0NzL2RQbTFZTnhpWFVZ?= =?utf-8?B?Q0oxNlZyOE5OQ29DOENTTFVSOElSY2pMd3lqMmhRUDB4MWhmTEdEbDNHTlFq?= =?utf-8?B?SlVsTEQwZVUvaXJIdmlNQStrb3EraVUzZHNmS2VERGR6c3drQXJnS2xSWGZs?= =?utf-8?B?cGdzZU4wOXNOblprOUVwcGhWek1CTmFsUzkrWmU5YlVHc09JNnhMRG03QVlR?= =?utf-8?B?SXg5M0FrV0ttcU5PN1A1ZkpIMnMxNEpjUDRsK2ZCczZmN1hWRVMxTVoyRFRO?= =?utf-8?B?V2o4OTNpZ0dMYVNwT1pkQjNHMDRidmRlTExnOTI3NkF6TFJKRC9sSmUyMjdx?= =?utf-8?B?cXlVV2p3TW1TVUtwTEpFT1pENm41VFJtalh2SGIxYk9zN2xhSUlpRzNtaG40?= =?utf-8?B?dldDYnQ0NUw5UGphRGZiUGY3QUpKSG1VZVRWZnpiRkFRTDhoandhV1RERTZi?= =?utf-8?B?cWJqUDB1WkhTRG16ZEpZSW5WQnUyd3h5K2RGK0tOVnlWMmJQSHBMd3VhNFZv?= =?utf-8?B?cEVBWHV2Q2JPWmhEaEZ6aWwwR2tvb3dLZFYzUjVMcDdHRDEyN2p5YndweGla?= =?utf-8?B?NDlHS2tCN0QxVGk4WXJFVlBLSUJMMUhCbDNzdjIxRW9FWmdHbkRkSXBhazNh?= =?utf-8?B?WTZoeEV0MDMzNDZ4UHJUcHlhNzc0RWhZcnE2VCs5NXdBVzl0U0FiSkxzZlVi?= =?utf-8?B?TmN1dFZFdG90ekxGNmxvUzU0anFyQUk4RFN0UTJwSm9uRHBPNjNSK0kwV2hF?= =?utf-8?B?bWh1UEM1UWlweng3VVA4OEg4Q0Q4OEtOdnlxUjVUb1dWcmZxY2xOdmpwaG1M?= =?utf-8?B?UTNUa3h6aWVHNXhUOEVJK1hoL093dDNkN3pkUFcwR2FYL3BxWUNkVEdWL2g3?= =?utf-8?B?SHB2aW9pN0VXYWhWbGJIMlJzckMrY1NPOGIvcFlOWUhJb0NGTi9RZjdsNVNZ?= =?utf-8?B?UFllc2x2V2lYM1BIN2taZ2VjYWs2ZTFsSFNJeHZjdGFKZFh2YkZMY3VHYXJR?= =?utf-8?B?Y0puTy9rZnR0ejJ5WHdMMVJ6d1VzRGhNUHBFVlhZOXBVc0RkZUZlOWFTNFQ5?= =?utf-8?B?NnlldzB1bkJPSHdxK1NWcCtLV2JmMGpnZFRVU2ZNQ3kwbDZvYWdWVDlCdjJG?= =?utf-8?B?K2FWNnloOE1rdnJ3OW0zcHFzT01iYkZtSmZKTnNpRUI3ckFDLy9NajNVdTEx?= =?utf-8?B?SiswOTVFNWlFMGNqRXFqMUZrZ2w4YjBTV3MrVnROQXVGMnNXY3owZ21qcVhS?= =?utf-8?B?K1duS0ZaRU00NnNSQWRxUlhNYzMrUEFwZTUrOERLQmFxTTBPaTFGNjB3dVJ6?= =?utf-8?B?OWR5NG82TGVqbUd6REUwV01NSU9vYkIwQTQ0NFhxcWFGSmowcHZIQjE0eXdu?= =?utf-8?B?bmlab21sWWRQV09SVC9BTEROZnF3cDNNNU1TNFM4a1h6ZStSVnJ2ZzVPWE1M?= =?utf-8?B?eXF2SC9GL041Uzg5N0xzUU9vM3E4bkFKUjJNS0FpUXJUQ0Y0YVNXMUdMT0JV?= =?utf-8?B?Rkd2VG5jRmhST0FvWlVvdFhIMTJmUDJLRmx5NlFKbkhCb3o0eWVrYyszTmhi?= =?utf-8?B?NkFTSmtDZjZ4ckRiRmNBYWZzZG9tNkIvL0pCNFBEdkt0YVNtZWNjc3oyMktn?= =?utf-8?B?Z1RsT2NkMExTdFpVbi9oYTRWV1pWU1VES0RaS0FFdE9Td2t4NjRwenp4Ym9m?= =?utf-8?B?di9wMGdBRytXTEhLNERYaTg1Y0JPOC9EWTJCUWVzazNWTE9OWkVnSS9UTGxv?= =?utf-8?B?Uy84L3lZbXV6bEx3U2R0aktHVzIybW1Oa25GWW1FM0M3Y3dDUmVtVHZhQWly?= =?utf-8?B?bEhqcUY3eDZvd3k5SXBTYmgwZzEwaER6YXhEdERHQXRySjBLRnY0UEVzOEhK?= =?utf-8?B?amNpUk1ZWWtPK0M2V3l1K0ZJS1JZcGU5bWkzUFBYNTNyVVF2alhhQkNMNThH?= =?utf-8?B?YUViUTNwL1dnNFRTSXNsd0JyM3ZyN1MxK2lZZTZHdFRObmJrWmpMTjc4Sjk1?= =?utf-8?B?LzB1RkJaUHlwWFFXdjVWbmF1TEsyNmxyQ2svdmxyT3lTTlZ4b2tBU2lZZmw3?= =?utf-8?B?YzZ5d2RhMkZYYlUvVUkxUnZtRDdxL2xwUjAzMWNqUXcyc094SmNMd3hHKzVE?= =?utf-8?B?UHh3dFlwUC9YV2JiWHJvUmoxMFl1WWVXSDBSVEZuMWZLWnVxMGZxRXU5ZWFl?= =?utf-8?Q?TSsq3h5c/8rx/6BRdvhB+dS8sMpqjVKY2tgU8oNk9w/Q3?= X-MS-Exchange-AntiSpam-MessageData-1: H4pUMGWpZvponA== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 5c12e2d2-fcb5-4d0f-9b0f-08de73b019a1 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 14:22:11.7425 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: 8d0qJ7AD9Hv8Lw08jzUGrgOK+B2cBZOlP3x776Zci/CRSIpnxrSGFw82CpgnovqBQswJe4h/3DgPREf9kqJzlw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7811 This feature is stable since 1.89, and used in subsequent patches. Reviewed-by: Gary Guo Tested-by: Dirk Behme Acked-by: Miguel Ojeda Signed-off-by: Alexandre Courbot --- rust/kernel/lib.rs | 3 +++ scripts/Makefile.build | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 3da92f18f4ee..cddeae8b6cb2 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -37,6 +37,9 @@ #![feature(const_ptr_write)] #![feature(const_refs_to_cell)] // +// Stable since Rust 1.89.0. +#![feature(generic_arg_infer)] +// // Expected to become stable. #![feature(arbitrary_self_types)] // diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 32e209bc7985..923886735299 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -314,12 +314,13 @@ $(obj)/%.lst: $(obj)/%.c FORCE # - Stable since Rust 1.82.0: `feature(asm_const)`, # `feature(offset_of_nested)`, `feature(raw_ref_op)`. # - Stable since Rust 1.87.0: `feature(asm_goto)`. +# - Stable since Rust 1.89.0: `feature(generic_arg_infer)`. # - Expected to become stable: `feature(arbitrary_self_types)`. # - To be determined: `feature(used_with_arg)`. # # Please see https://github.com/Rust-for-Linux/linux/issues/2 for details = on # the unstable features in use. -rust_allowed_features :=3D asm_const,asm_goto,arbitrary_self_types,lint_re= asons,offset_of_nested,raw_ref_op,used_with_arg +rust_allowed_features :=3D asm_const,asm_goto,arbitrary_self_types,generic= _arg_infer,lint_reasons,offset_of_nested,raw_ref_op,used_with_arg =20 # `--out-dir` is required to avoid temporaries being created by `rustc` in= the # current working directory, which may be not accessible in the out-of-tree --=20 2.53.0 From nobody Fri Apr 17 01:39:55 2026 Received: from BL0PR03CU003.outbound.protection.outlook.com (mail-eastusazon11012040.outbound.protection.outlook.com [52.101.53.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 DFA9A39E6D8; Tue, 24 Feb 2026 14:22:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.53.40 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942941; cv=fail; b=IHYdYnKJYTOlqgq/VULweVg1ozVOi14Rv0SdjeWeucIfYhvkN21EivYZIq87+LVr/51z2Xf1Pa1f5dqiyTt23xZMjpiGmisxnHx/9NWRezBkjxvGrQynujvYR5X3U0Okc0VC7Gbo9nmRDGZez4NYPLLebd0yr8Rho+6lLllAsdQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942941; c=relaxed/simple; bh=TcC/0HgSiNIqEHyMERhzbunfuxnhABk0R6879fRIrvE=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=rTxAsf+R6ah2IpyT28XlQLmDreAAxKWbSRtzxwdz/I+3pKQ9NudCl+QuAezXzzeYSjvcr44+ZSFL360s7U9h/a42X90Vdf17PS1A4K94WRVhZGvxJzTi9/n3mqwWAfLOqcchCikTnI0ZhM66KlmhDdmDPXkrrSLDa1PXvbM14y0= 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=auhB+gjl; arc=fail smtp.client-ip=52.101.53.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="auhB+gjl" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=yOJwIgf57jiH8Oks9WaMq0MwaIYtq3RW3qli6PxAdLxLBTWvV2MRNHaFZhN4eZ6sbOwATgHpuNkbqjZEhTiP8gUSvQODfo3rXdlmzlgmo/8GVNSsRj+Er/GTmxFgZ8DIXex8zkKcFNWQVyXLlQC0kW978sX3x4kktWnEm++U2DWVKHRAtPYiB+w0RrynHmhs3xyF3BitPCXgDpwvU/S+MrkZEuuF2+Lz+YSJYMMwTlq/GhHK8MFZKB9ZgRPuJ0NMytrrKUj8w2UY56soOivdJ727EKVFc/FA7r0Ip7AMUsAZ1mGmjbVazANyjwfMTpNiNZiX6O0AlrQ4f/T3v4EkbQ== 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=CSznYsY1ajD8r+TxMVK8h1CuRPjgUYV87ErETI4erGs=; b=llaRG+o3rCOizHW2+vnySCvZGnvSqgu4c1G7yA1c8QtYS5kD8bPGm1wWXoMevVPFezub2a6+2blpeIAPpPj0RBZ078vKHBDHw90bf3jcht2SoDfUgTse0z32nW2/TlVPu2bIT1nhg59bGe9lvtusaSNhuLSRnpgLmaBIKCKFQdKUU1zdL6AhoGjU/eQzxt4YD4+tI65rzgWovWzMvUPowXAXDecEyq68U3gqs95PvH1zx1CDoWlkYBWyIqEv/FPmtm0IAKdWqkqt5jhPDF2u19sF6JQmVCW647ahmr70pSbq1Js0IIrZCtUccWrR10TKm21U1oz9rkElb5WsmGz0SA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none 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=CSznYsY1ajD8r+TxMVK8h1CuRPjgUYV87ErETI4erGs=; b=auhB+gjlJroOT9BxpTN9pFUfv48UvSukxCGDT+Eu1WsanG+8Q7CUV7epNbHogwGKuK4UiFFkpAAIVF2bsF9CvVKngH0ixOtEnP80v4/h7FrZIVan+4q/lAZIb6JcycG/G9uAu6vjkakcn4qJozSA3s4DJCcfdkDbmj4fig/pB/EhmUJJtuaayB4NXSLX1yhZYZvtlTV1Hf/L+tElCU8WiM3tcI9nwQhpGNzGAA7v8YVDbNH7ORQNocKB9+P+sD+FD0ofYOEq459k2UAq+8av0qgb/RdEQqSE+cHul+ln5jaRFf8RqNR0r81SyJxVQRkGroFd9QGNukkOmSefpBKQAg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by SN7PR12MB7811.namprd12.prod.outlook.com (2603:10b6:806:34f::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 14:22:15 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%6]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 14:22:15 +0000 From: Alexandre Courbot Date: Tue, 24 Feb 2026 23:21:40 +0900 Subject: [PATCH v7 02/10] rust: num: add `shr` and `shl` methods to `Bounded` Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260224-register-v7-2-aad44f760f33@nvidia.com> References: <20260224-register-v7-0-aad44f760f33@nvidia.com> In-Reply-To: <20260224-register-v7-0-aad44f760f33@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Boqun Feng Cc: Yury Norov , John Hubbard , Alistair Popple , Joel Fernandes , Timur Tabi , Edwin Peer , Eliot Courtney , Dirk Behme , Steven Price , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Courbot X-Mailer: b4 0.14.3 X-ClientProxiedBy: TYCP286CA0007.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:26c::12) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR12MB3990:EE_|SN7PR12MB7811:EE_ X-MS-Office365-Filtering-Correlation-Id: 276eda58-30ce-48bd-f3b1-08de73b01bd0 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|7416014|376014|921020|7053199007; X-Microsoft-Antispam-Message-Info: =?utf-8?B?V1RCTjNXNGt6eGdKeEJRVUxtaS9uaFgzSnMwUVRrUEdtUmxrbS9hdUJ4bG9L?= =?utf-8?B?ZElPcUcxa1FSM0w0ejNYUlJTTTNyREQ5TXBvVVI0Y0txMUQvMTdVNkNNaUQz?= =?utf-8?B?TStkRlRYclBlM0NNVEkrcEFxQnlTY2NLbk85MDdCc3FTNWJrSTROS0N1UXhC?= =?utf-8?B?U0kyOXVQSGliK3V2dzZITU1rdVJTUGhIUHRVOGxSMURYZmRFSlNFUEV3VjJH?= =?utf-8?B?Qm9TY1kwbStMSTVoYm5YdXdUWjRxWmpaeDV0cUFEbGpHcTd4Wkh4MUFmMjNq?= =?utf-8?B?dGtFa1VEZ0g2ZlZoYkk3dTZESWFqZFlzZmkyUlJYYU4vNTR5V2VoVTQ4aTJ2?= =?utf-8?B?Sko0ZVBJN3hZUmlWYXF5TGpWZTVMVmIzVUxPUUI2dS9sNERkblBxVHMxNTUz?= =?utf-8?B?SkNYc0NWdVYxc3hUVUlyaGNnNVdpSlNSdlZaQTk0UC96MWtISUN1aGRkYWhQ?= =?utf-8?B?WWZUVGZyN3BoNE1ueDdqV1N5Qlk4T3dKenJvZWI5anA2cEdScklNa3o1L1B2?= =?utf-8?B?NEtLbzViemdVZEp2b0I4ckx0KzVqUkpjZmNLclhIS0IrcTBKaWVNNmZYSVZ1?= =?utf-8?B?cElVNENnUUpSWm50SHNzZjVqalpoR0NHUk1DZjIzd0ZmcjFNczBNVUVjRzVL?= =?utf-8?B?VDBYRDRzdG9RYjFIZWtiTGc0WVFFWUFwalFzcStpRTYrazYyaG5xelZFTkt1?= =?utf-8?B?ajVwTFRIbDJwcTIyaFlHVUhlenpocnNycnp3SFp5QjFMb0NuNGdKWURsakxo?= =?utf-8?B?NWp2M0NjRWMzMWpGSVRmdnA2N3pIQUZOU0taQVFIK1NITjAzSVdtbk9Jc3Yw?= =?utf-8?B?MnFpTUtTSnY3QU5aR1d2YXNKaGdDVklmeW9ZdXBpWHNLTHo4YUNHOHFPcGlh?= =?utf-8?B?ME1uQm5YR1BDTXNPVm8vUE16L1RhUTBKTjFTaUZ5L0NmejZVSE5CN01FYXV0?= =?utf-8?B?ZzJqOHNxRHJlTWZNd1I3UmVjTStmcDBObXhPUVYvWlFKZkNKVFhzUWVuTmpt?= =?utf-8?B?MzlyaXA4dzZmMFVNQTFRTzArQmF5anh2QkZuR3lnaG1aYmlQaXYxckk2RC8v?= =?utf-8?B?dkFhMVg3SEswdHh4RWFqekZtRTBVUldUTGZHN1RRQmVHVmhCZTYwNXRhSlpl?= =?utf-8?B?cUJLY3ovbUgwTXIzUHRDbm5FbGZ2cUphd3JnNlRGMDlmOGlyeFBPS1F4NEpN?= =?utf-8?B?L2lEdWVVWWQzeHRGcHFoalBWa0g1WjR2alhZNFhMbVFCenlzNXlTOXNpbmRp?= =?utf-8?B?UzdYbnFBQ2hvMEZucHBkNEFkK0k3OSs4dUw3K0xnV0lNWUY3RW9nbVdaOHNG?= =?utf-8?B?MG5TMkhQR29CekVUMnR6SlMzVU1YNW1xVTJ0L2d6Z2ZVVlIzeW8zVVYzQS9n?= =?utf-8?B?WW5VZlUwNjUwdHJ0Y1JUckFGcVd0OUFHbXZhQkJQQlRUSU1GS1FSSHBoZjd5?= =?utf-8?B?WVNYVUJFWGUvQTV6dmFOOTk3dEdUN2d5Z2MvbEFzWUo1bDA4TXRrcUlGdmNi?= =?utf-8?B?cjNjZElYVHg0STRCZk1McWx2a3RoLzkvQWtPckVzWDBrZ2hnalpZSGFNSkVB?= =?utf-8?B?TDJCZnhtNS93QTRqalN0SEVIZVdyMGhmU01qczB2V2tOSUpaOUNFSXdJZVZo?= =?utf-8?B?T0dFZEJPcTFLdlRRM2FhNkpzT2FGaTRLTStWRjF2MS9kTVhPZjBFZzBJTkJL?= =?utf-8?B?YWlqdnh1NGFQSEpRUkU2dmdESGY3dGxYWXJ5SngyUGk1Ukk5VVNBU3pVcTVk?= =?utf-8?B?eU0yTmFUZGI0L3dITTlHV0lIQ09ScC9seFQwQ0djZUFaaG1CRitKck1TeDJQ?= =?utf-8?B?NVAzMEtyU0hLRkswMndUZjA2RXBXWG1TQytnRER1K0szQVl1Q000dm4rVjh4?= =?utf-8?B?QlF4bW5BYUFadzVFN0pBVjF3QzBrS3hzbGlHS0d3NzRCUGFxbUlndWkvRStY?= =?utf-8?B?U3N6dnlULytHQWJubU9zM0kvdkVWK3R6c2w1RTM3bEVPZEx2MVZjd2tmWUxC?= =?utf-8?B?Vi9hQ2NlUmtSaXUyWTdsMlg0eDJxVVMrZFJmSjFML3lwZVJWTU5FNXI2ZE5C?= =?utf-8?B?dmdpayszL2V4SnI0QTA3ME8vdUJzR0RSZ2JJU2poM1ZiL2xlTjI1U2dSSG1Q?= =?utf-8?B?UXQrWFQ0cHFWajBMQkJlcHhjWW5qRzltQS93NEpydzQ4eXdGNnJzUkhqODhp?= =?utf-8?B?emc9PQ==?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(7416014)(376014)(921020)(7053199007);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?dWxOS0d0NUJneG9lY0o0U0FYNmVXRjlmazYybU5NYTdsNnM4aTg1NUFoM2hl?= =?utf-8?B?TTVmTWlEU2J5QW1sUlFBaHh4dFlZT3p1OXBzdVVHbUNHSGNWUmQ5WmhSYlU2?= =?utf-8?B?Ynd5ZTJTTkw5SUlUYnpyM3FOYTExRU1RNitBUWNOWUlEZHJUQ0VzaWl1bS92?= =?utf-8?B?Q1hIMDJvRGo0eW1ydTgrVUZhdnhudkp0UFk0NDZqVTdwRGRoaEN5V2haOTdm?= =?utf-8?B?eTcrK0s4SEtUMWtrM29CbHNTcXVoOVE2WWFuMUR3amR1ZzVvYzZvSDdHaVM5?= =?utf-8?B?T1lueHZnVTVXUitVbm9RQUU1NURyM2VLZ1QrMFdXaGtyOCtmQU94TXdFMVJZ?= =?utf-8?B?VHFwdldGenlDZHp5aUNDSVBva3d6RWlMVXYvMStrc0lpSWlpMy9vZDhyUFpD?= =?utf-8?B?QXFXSHJ6UVhDRFdBUDZhS29HU2tpcm45Qks4Y2hiVStCaFhZdTgyU2ZwTFBS?= =?utf-8?B?S3U2Z2FVQ1J0L1A0cDdoT001SDA4Rk42bU9DWDFkaVdIazYzSnVwUWFNY0Fv?= =?utf-8?B?Wm5WWFExb3lzZHBPenRPVVVYZ2lUdnh6WmRqdEdIb0JkTXZjTGpsSDhUZmEv?= =?utf-8?B?L1hjNFZydVgyb2JQYVpKajBseVZGdzIrZC8xTGV4OVdraUFkOWc0OFZIaEIv?= =?utf-8?B?Vy94OTg2S2taekV3OXNkNW1yaTlJd0Jjcm9IUkdaVloxOUovNTR6dC9ERXI5?= =?utf-8?B?VFdnY1RvcDYzWE9yTTlUdFVjaStNYlloWXJ6MWNoNTA2TktwRDNVQzk1STBZ?= =?utf-8?B?YklPSFNhZFh6N1kzRVI3dEE4dHVhbENOY1dEMXAzTThQQ0NZdHAwUlhJNFA0?= =?utf-8?B?b0JqSkNnMEZJQ09WTTJiQkNGUXBlSW01cG16dFQ0UUs2NGttdTNhdzFHSHBH?= =?utf-8?B?aE5Gc3ZUZzl3cERFNThJOWh2REZ6UDRMUisyem5VR3FEc08zaXFvZHJEYUxx?= =?utf-8?B?dFlmVk9DNnk1ZjVDRnJjem1zSjY4UUxiczI0cmtqQ0Q2SjNxdGM2bVQ3b0VR?= =?utf-8?B?anpFa2NobG5rRWVIQzREM1dhamliRy9TK2piQ2R5bTRQUVFPVnVKanE2NFJR?= =?utf-8?B?cFo3NFlqeFh2MHYyb3pZVGdrcWRpYXV2MzBlcHAycmN2L2MwcjBhaXVxUEVa?= =?utf-8?B?aVhmQmJNMXpobStFaEtNVXdxQm9lZWovVFRlMU9ESjlpa1JTVFUwWEVxNmJO?= =?utf-8?B?QWZyQW85bjA1cXhSdmhvRE5CTURUNGdwVDJTTE5iY280TUhrdFZjcmJVRVNC?= =?utf-8?B?T3Jzc2NLakJrNDQwbGN2VGxXV0daeE1mS1A3NlZWWG9CQVlvdEtlNVNtQXBq?= =?utf-8?B?cDB1WktwcnZZOVEyOTBTRTYzQ3pPVUpMSG5vRG5Qak5UdXBjeUI2NUM1Smlq?= =?utf-8?B?SHJQL0VHcmJiZ0FsdnFYeDlVNmQvbW1SellKenpRZlZKajBLZSt2MG5ST3Ri?= =?utf-8?B?M0ZKZjdqOUFNeThtSG5VcEMzUE0rWEtSbmFoQXUxa2ZVVzlCUU9OMmVRbXhT?= =?utf-8?B?c1N4c2RRVFVoVlRyRThDcnFXZE04emVEdzZJekhrL1NQU3V1bUk3MGhVV0VF?= =?utf-8?B?VHpOdlZReUEyd0xzS1B3T2llTm9oUDRLSWdkK05SUEVldFRGWjBxbEFaeDZI?= =?utf-8?B?bmN0TUtYMTFrSDdES2NZQWxyRUVxd2MvdjhDMDc0Q1NqWEFybTR4M1JqQklY?= =?utf-8?B?b2tyM1V5UnRReGpWZWozeUVWaFVJYzBoMnlLbVdWMUZ5VFJjeGx4eDlhVHI3?= =?utf-8?B?akZPMzhrTTI5cXFGREVabFdpSFZVYVlLVkJJY21ZYXNqUERlMjJPaWp1emlQ?= =?utf-8?B?RFhyRTlhQWhUQUVwcERMTENERHhucmtOcnhHdXlqS0hjWGEwNytwOUppdW82?= =?utf-8?B?aWhDem9sdXpMSnowQ0VqNldLRkh1TFF4bGw1Qlh6WXBMdDBjRHV6dW14ZGZl?= =?utf-8?B?NmFrVEJWZVI5d0Y2M1lNSnpyUkxTQ2M1Rm5ZelFHcGhWdUhBeXpMVHNJZG9m?= =?utf-8?B?b0xSekhXK3NLSk1GUldGbzVqN2hDLzZZMm1DY0NjWVBrSTU3dmx5ZXRmVHN2?= =?utf-8?B?VGt1S0VOV3F3TDFtMXhteGFaUUxiQXVTa1JuVmg5bEpsb3R2UENiWk95Tmti?= =?utf-8?B?RlB6ZU5HeWhCY0Y4V2MzenhGb3ZlVlRpSGhoMmp6d2Y1MnZVaWlKYmFxd3NY?= =?utf-8?B?V2hxdUZzTnpldFZ4ZGpZbkxNdnYxbWR4SUliYzR2OWkvOHV6RXZZUC92ZFpO?= =?utf-8?B?UGFJU051Yy8rK2dMQ3huSDNmY290VmZtNHZxM1FuMnFCeFY4RGxOSmZlUWox?= =?utf-8?B?RVFHeVFvMXZSSFAvbE1XcmNGZEN2Ry9WSU1wZjhENndUMi9XODR2NUwxc3Qv?= =?utf-8?Q?rZYBvDAbxPKBK7ccUgXPPD+wFKjNTDKIkh9/xSnQzWCsh?= X-MS-Exchange-AntiSpam-MessageData-1: d+sN7y3uCUfwFw== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 276eda58-30ce-48bd-f3b1-08de73b01bd0 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 14:22:15.5660 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: xLVqdtCMOwR8boN7UzonJkRxfiID1FjweXGRlEeYvR5PJagTVj11NpJFSpemmvJ7Ae6kBr5Ez0ETunBiQ4nXMw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7811 Shifting a `Bounded` left or right changes the number of bits required to represent the value. Add methods that perform the shift and return a `Bounded` with the appropriately adjusted bit width. These methods are particularly useful for bitfield extraction. Suggested-by: Alice Ryhl Reviewed-by: Alice Ryhl Reviewed-by: Gary Guo Reviewed-by: Daniel Almeida Tested-by: Dirk Behme Acked-by: Miguel Ojeda Signed-off-by: Alexandre Courbot --- rust/kernel/num/bounded.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/rust/kernel/num/bounded.rs b/rust/kernel/num/bounded.rs index fa81acbdc8c2..2f5f13ecd3d6 100644 --- a/rust/kernel/num/bounded.rs +++ b/rust/kernel/num/bounded.rs @@ -473,6 +473,48 @@ pub fn cast(self) -> Bounded // `N` bits, and with the same signedness. unsafe { Bounded::__new(value) } } + + /// Right-shifts `self` by `SHIFT` and returns the result as a `Bounde= d<_, RES>`, where `RES >=3D + /// N - SHIFT`. + /// + /// # Examples + /// + /// ``` + /// use kernel::num::Bounded; + /// + /// let v =3D Bounded::::new::<0xff00>(); + /// let v_shifted: Bounded:: =3D v.shr::<8, _>(); + /// + /// assert_eq!(v_shifted.get(), 0xff); + /// ``` + pub fn shr(self) -> Bounded { + const { assert!(RES + SHIFT >=3D N) } + + // SAFETY: We shift the value right by `SHIFT`, reducing the numbe= r of bits needed to + // represent the shifted value by as much, and just asserted that = `RES >=3D N - SHIFT`. + unsafe { Bounded::__new(self.0 >> SHIFT) } + } + + /// Left-shifts `self` by `SHIFT` and returns the result as a `Bounded= <_, RES>`, where `RES >=3D + /// N + SHIFT`. + /// + /// # Examples + /// + /// ``` + /// use kernel::num::Bounded; + /// + /// let v =3D Bounded::::new::<0xff>(); + /// let v_shifted: Bounded:: =3D v.shl::<8, _>(); + /// + /// assert_eq!(v_shifted.get(), 0xff00); + /// ``` + pub fn shl(self) -> Bounded { + const { assert!(RES >=3D N + SHIFT) } + + // SAFETY: We shift the value left by `SHIFT`, augmenting the numb= er of bits needed to + // represent the shifted value by as much, and just asserted that = `RES >=3D N + SHIFT`. + unsafe { Bounded::__new(self.0 << SHIFT) } + } } =20 impl Deref for Bounded --=20 2.53.0 From nobody Fri Apr 17 01:39:55 2026 Received: from CH4PR04CU002.outbound.protection.outlook.com (mail-northcentralusazon11013042.outbound.protection.outlook.com [40.107.201.42]) (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 37E343A0B13; Tue, 24 Feb 2026 14:22:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.201.42 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942944; cv=fail; b=edxI3g5+L2k16gQI3Q3JcSf8TLBXZF3t/6fHQ0wZq/682ZAnKnazvqyXg75V2ZuILEHkuT71bBwexvq9j3JQA5FTMAknSEGUKwSCGyeNj3AsA6EJg0tUH5KoumlPmiZVZ7SOZcFz+8nX5XTD+EFk2uW4jro33gQOwqyYbCdmtIU= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942944; c=relaxed/simple; bh=g6pxC7YDKxn8dWDn1GgkniFa+rnZSH2UAw9aQPrd5WE=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=hN4L4MD/zqgUngZmQE5rd2AVxjaWD3YcxqTPvwGn2frCp4VnI9w84v/tYcmt6ps5QOv+UYtCRL4fSyCyCf4mnoSvKPwY2jfLnLSdYtG8sUv1V3rMqw8YVyXV1lQmNsK6A5kxOSsean1vZ8yCljit5/5fKfezF79C9DzNpMKpn2c= 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=X1URbqTv; arc=fail smtp.client-ip=40.107.201.42 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="X1URbqTv" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=eRHIPjIrXEl97JiytwrngIyL+20bCmboPEZpkvSrhsYHifsCeqopMeeRbcypOK2N3QshZxqzjDCSsSI+LhypjgT4Z8Bl2SuL8k94gVZP/Zi8F+FZRR7kwi3a2HOsA65lJkVUITn3PDEKLxYl+68TyCYlTHPJmWt8AJFDQR3A+Xs2QDUsYzleI272TP5/VNUabTg4h8RgmUPBJ6bL3F1wcrDHkOoFTHwfZLvMiGgwuO1rfsdxmjVbf1f7DURUrbC+AwQg0ZY/mL3AycXfe7A9vpvcvnp40utGIPbEUp3O6GVvTZ8SWUh6WkcVTYUZrh2F83kIxtFLnPoQDWFpXRUrpQ== 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=4dnFWA9MUzwJOAGqB5UIX9vY/f4AMIt2w8I5b+B/Cx4=; b=lVdZsYZfWh4gZGWS8yuw+vTlR/ElR4KT9Y6gBBtMbOMHAKqIase8aH0shIZOJMdzRgV9Bdy5kwZiui0MmbcXA1j0+3dTdswpMUcilKdo2+ma+olRPsW4439OG/2dKEyjeyI865hiv5cC2rEViBqtuPb3fRInksDOBrOGnBugeQtFhLBb5CZq8rK13Q/p5umWnJOYKHzcHFKrBGPecK8XwF9/mCMeazRJIB0Ek01RJGzPFbN8q7J+kOCQ0/ZkY3hGik0+hTZtgODY7m4qewFAjc+3yii2RL425CUZnE/tcaMQ0+5ACVEGGfoTKFjLVO+KaerN4taya+twb6BZclykDQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none 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=4dnFWA9MUzwJOAGqB5UIX9vY/f4AMIt2w8I5b+B/Cx4=; b=X1URbqTvq6xRI7qe5dZ05dniMHLFIvMa1St36Bq3Cu1GsLYV8RfXPdwOImnxKStsgtvxTA967SZe2IglPBoEke1/5CxlQcX+6zUuNdh+2Nn6nHhWIW5HObzoeKmZdJ8secBwkT86iwyFHt5wZC1uD3XSQz7DlPBs7AztM+OpNaNqWMWgbgrjS7esNLoB6P5b66XpIFc+usy1txY8Q0W1Yad89JwtcogxUJe7D5t7rbyLBTSvhVEj6uenEoAqZiwvq0WMfrL1SvMyJOjT8Iu6FMwDANV4DeAcrOWVD+hZ4OQGJ2ieZtMoxEdNv+pzAMCpopvwNq8bc13z2hCctejIfA== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by SN7PR12MB7811.namprd12.prod.outlook.com (2603:10b6:806:34f::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 14:22:19 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%6]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 14:22:19 +0000 From: Alexandre Courbot Date: Tue, 24 Feb 2026 23:21:41 +0900 Subject: [PATCH v7 03/10] rust: num: add `into_bool` method to `Bounded` Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260224-register-v7-3-aad44f760f33@nvidia.com> References: <20260224-register-v7-0-aad44f760f33@nvidia.com> In-Reply-To: <20260224-register-v7-0-aad44f760f33@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Boqun Feng Cc: Yury Norov , John Hubbard , Alistair Popple , Joel Fernandes , Timur Tabi , Edwin Peer , Eliot Courtney , Dirk Behme , Steven Price , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Courbot X-Mailer: b4 0.14.3 X-ClientProxiedBy: TYCP286CA0028.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:263::15) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR12MB3990:EE_|SN7PR12MB7811:EE_ X-MS-Office365-Filtering-Correlation-Id: a64a5e52-01e4-4ad4-a33e-08de73b01e15 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|7416014|376014|921020|7053199007; X-Microsoft-Antispam-Message-Info: =?utf-8?B?RTdGT3FTUUI4aFgyVEg2R3Jobmtad0lZSERsNkI3WnFSeHBpRWRNRnJFcE8x?= =?utf-8?B?Q2RiaHVCMXlXWDZqUHpWTjFqdXZ1WHRRVjhZcDhrMC83Tmdha0R0VldjZ2lS?= =?utf-8?B?RDlmVDFXWmJGVnlUcDcrZ3M1VGw5M1A2UmJoNGRWYTBTais5RHhHOExTZWxm?= =?utf-8?B?OCtHajlkMlo3Q3VMQjhCZWNCQng1VUZjd0U2dGwzSmVlYThqMVRsdVM4NUxV?= =?utf-8?B?VnRHOTRhV3E5WlNWaEJqUWgyOXd5V0tTZDZ4UlFzRjZGdTNXc0pGcmwxNzZB?= =?utf-8?B?K1JQUGhvL25GS2UzQkdTNDNLallFczNJeUZpTVRIb2g4M2w2SUxLcGhOSUN1?= =?utf-8?B?bVBhZklmNjIzOU5jZExvUXN2U2dTVXp3T3ZWQi92UnBLNTVGZVFXbzhsY3FL?= =?utf-8?B?cWdnRThodmZtZ0t5SE5YKzRiNHZjVGJQblRxVURrNTQrNkFNWlJnOXBsLy9Q?= =?utf-8?B?LzJ3SlF6SEt1MjJKR3Jqdnk5M3hSdWxHTzcreDA1THVkVnVVdUxINFNZOTE4?= =?utf-8?B?MVRiODlnWTRvRVpET3dLN3pFUlNSMUxHdnVIWmVYN1ZOekJ3bjFxSzVvYTl2?= =?utf-8?B?VDh5aUJnOEZPSHJCNDllM0VwRm1QSnV4OVp0NU9MYll4dzJxYTdOOU0zOEVJ?= =?utf-8?B?cGhXbVVWTDVVV2lxQXlzRzluU1pTb3FaVlJwUHk3QmJwTXM5WmdUeXk1UVFu?= =?utf-8?B?L3hDL3JxNERDV0Y1MzJKUVUxOVN1WGlXTmJtK2FKTUtiL0JCUFZSVnhTaTVT?= =?utf-8?B?ZXBOeHFCdm9YcjFESDZUdDA5bGlNQ2J3djd4SW01V2w3dFQ2Tklqd3R4Zk53?= =?utf-8?B?VDJoNVNZODVjWWRlMlJUMXJJMzJwVTBLYkp1Q1ZpTzJaaTIybnJmZTl4Ymo0?= =?utf-8?B?RzVoWnJVaW5pOEV6SW85SFNjWWxoMkVzVkNrcGE1Z1BqMDRCb2o0bER0dk52?= =?utf-8?B?VFpuWW5wM0FlM2xGQ2F3cVhLeWt6Z0dBOXlrVFZwaFRoZisxSlpocDk5Vk9R?= =?utf-8?B?UU9IV1h3U1RWc25zTnI1OUlQTGhFOHVOT21RTzRkMnZQRHhqVWhBYzMydmJG?= =?utf-8?B?cHlVTkpOQm54aEFYSTZrY1VMVW5PTE5tazIrSFJXY09Days5aXdaZ3pzQXYy?= =?utf-8?B?K0RpWTl1VmxmSWxYMmdxbEVtSFd6TWFBanYzY1BlR3BranZSTFZ5MU9JcGZX?= =?utf-8?B?dW45ZUNIdklGN05INGk4cE9rVTIrN2czUi90K0MrS0RnTk4vRWU0REF5dmNV?= =?utf-8?B?MlpXQjFtc2pDYnNKc1Rac3E2bzgwOFpsMldqOHRGNWZpVm1nRm1ZQ3ZKRmps?= =?utf-8?B?bTRuN2M0WTZTbzc0NmEyai9qZkEvQUloUTNiS0ttSVFraWxRaDZYbnVwcmxM?= =?utf-8?B?MjZNYUpIb1UwY3ozNzlNWCs4UVhaNEFRd004eG5ZaXdiODlUWVNtMEIwbDlQ?= =?utf-8?B?RllGL2E4SlE4M2hLOFFPb0U1SVVGZnRXL21GWjV2d0VlMVdqYXRkTzVZQXBI?= =?utf-8?B?MjF2dWlsTGZoa1c5ZVBhV3JHMjltRmVEOXQ4NEpJcm5odTVYdVFrOTdRc0s3?= =?utf-8?B?UjNudDBUQ0c4Q3hIYW85WTVOazU0K1kzenFBWHZ6bmVpK3dKUDYwa1BEZ3FT?= =?utf-8?B?YWx3R1NLMll2ZUQ5STloajNJS1lrWFMwVDlVYTlJcHVGL1J4TFFkZ3B5QzB6?= =?utf-8?B?TktUK0FCUWxuTU83UXlSQjdIQ0pzNGEvSkc2QjZqc0RoODFmM2IvUmY0Ymo5?= =?utf-8?B?dWlZZTN0Uno4V0xrYVFQRE1tSmVBY3VwY01FRXVqT21DSWx5T0dCSVNaQXds?= =?utf-8?B?YjBZT1YyVWRHT080NmRzSmdjT2RvQmUrNUNPTUM5eitLeEh2bG0vVktvcWhW?= =?utf-8?B?ZkM2bWxIMXZqLzA4NzlWWWl1TUN6TnNZWHNpRVdud1U4TGRPbXNvSFpTQlVh?= =?utf-8?B?ekFJRWF4UmdKQ1RDQ3JTUFoyVkdtTlo1eURNQkpXazh5Z2ZIZDhhdzBVejR0?= =?utf-8?B?M1kxMysxc2VXQ0p2bVR6K25GQ3ErTUpJNUcyOGhXOVp2Zkt1cE84R2xhM1VI?= =?utf-8?B?VEE0bW1KWGxHQ29vdnY0WkI2UWEwUFh2cytLZG1NUXN4MnMrRTIwQ0E0bXRO?= =?utf-8?B?YWRnMFBsSmxQZjFzTjdkVk9TNldmSWJLa3pubXB1cEN0cDQ3UDBtY0U4TVRD?= =?utf-8?B?VXc9PQ==?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(7416014)(376014)(921020)(7053199007);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?d05mQW92Y092ZVpPMTROaXFMU3BXMGJUZzBEbkxGMWVXTnFodEQ2VkpWL0hU?= =?utf-8?B?RSs5MUN6aFNRVXdvUGdQbEV3dmw1blA2KzREQ1MvV0lXaUdkSjZKeXhRSjV3?= =?utf-8?B?YzV3MWdmTGI4Q05hbmlKYXJ6SW1jOVdOUVBhZFB1bzE1aVhzN2xMUHVVcjhW?= =?utf-8?B?UHZOYzZwWm1aVUV3TFNPU0JMbVZVOW80eHErRFI2TnJoMHVmODhOL2hkUXA3?= =?utf-8?B?a1BxeldXcDl6QjhZNytjNmJhNjFCcDVTVmF0T1Q2WmpmN1hyZlNtc0czWXRH?= =?utf-8?B?Q0ZlcFlyUkZuUjFlOFhhNFRMeGdmN2tVZ0M4dGhOaEpvdHp3R3Q1M1dCWFpw?= =?utf-8?B?anErcjF1c09LM3FhbnA4OXAyc1IyU0lUZitCQi9LZ2RNVS9mVDJzbEpFQ0Jq?= =?utf-8?B?Ym90UWpGZE5oY1VkWXlLZTFtNlk4K2VRSnpzU2ZrZGVEeUcrTjVLU2ZBWm5Q?= =?utf-8?B?NG4yNVNOR0IwcEtabUt5SEFTZkdvRWtJWmt3aHNUQkNDdHhmTmpvdmJwV3N3?= =?utf-8?B?UjJJb1lkNFJEaHFFcHkrR1pMclZocmRSUFJtOExQYnZmQTMvQ1ZPMUlnemNy?= =?utf-8?B?T0JYdURZeEFWTEZ0S2JTZXAxOUpGSVlQOU84RWh5UWpWcjd1MUpWRzN1VlVI?= =?utf-8?B?bTJTYmVaVTBBbG9lbkhtdkE3V0RuVFBjUG81TStVS3YzUGZNQXl6Y2U2Nnox?= =?utf-8?B?aERVQ0w2MVZ0dlh3UWpGY2w5MUpkQkNiQTZ5ZEdJb0pWenlNMTdUWklqTnFj?= =?utf-8?B?a2k5TzZXUy9OaWFMZXdhTlVxaHdEMnowdWhqbTRnMkQzbzI3K291NXVkSjhz?= =?utf-8?B?cS8rbXliUFdEbTRwSmhqMUxHTUozOTBKWkgwMWZOQjJpVkUxdDZkaDZMdkUr?= =?utf-8?B?YWtYM3RmeERxL3A3NzRWWHg4U01TK0NlTSs4NGZZZ2ZJM1A4RG94NS8yL0sz?= =?utf-8?B?RlhONmgxRktzbjFzaHhNOUZDMmdYRVlZV3Y5bDEzNE1jRjgzajZGY0FsSTFi?= =?utf-8?B?WnJ2NVlRSnR1SFc0SnhYc1NIbzRjWjZIVXQybFVEeVA1djVOd1YvdmpjSDY5?= =?utf-8?B?TlNWVTJWUnlyTTErRW1rcys0TCs2cU54Tmx0UUdYSzNEcGt5TDlHTlQ1N1dr?= =?utf-8?B?bnpabmFrMnZXVVppdW9nMHpZUUNhbTBjSUFHQ0tyd3R4ZURNTFhFUjhHNnlN?= =?utf-8?B?Y2xXZkNURU9wYXMyT0F1SkcwUG85U292QTdmWDlzZXpPWmpqdS92eU5UWXl3?= =?utf-8?B?WktPRmFLL1EvMjhIY2Frd1ZRamJyQ1NVdXVtdFpTaU1OSW9uTC9odlpleDRR?= =?utf-8?B?QXF0REpvakVTSGQ5QjEzNDloSnJwNXVRK3lWQS9aM0tMYVkxQlRjL2tSanNR?= =?utf-8?B?bFNDaEJlOW9XUGdnYXJkTHJuZG5hY1Y3L1RlY1hSeTRyK1BpajZhT0pQaHFV?= =?utf-8?B?Z1NUeGFHQUVLbHZUZ3FTRmNvbzlncVhiMXVGb3dCQ3lqZGtZMVZmRkpPTHNq?= =?utf-8?B?RXlEdnBmN1pGRU14Q2lMcnBwZnEwY3l5Kzlmd09ZT2dURWZ2SVZhRHNZRHRh?= =?utf-8?B?bHhDTkE3UHEwdXVMWUt4M1BFVFRCcnEyK2ZrU0d4RXhpaHpOcUVuZ0lFejVj?= =?utf-8?B?SDNTbkZlTUtkOHdGaG50eVJ0Z3phSWg3d3VFbi9MT25aL1F0TndMa1ZJUEhN?= =?utf-8?B?b2NHcENTR0p4OGhWYUFZU1JLYUFrSTNHbHptQnpESTkzOFdvbWh3bHNFUCsv?= =?utf-8?B?b3dGQlliOXU0cTB2ZUNDZUEyYlBVQXpWODY4Y29nS3JyTHVmR2xKRGpxTzhS?= =?utf-8?B?UkxiTDJGb2FranIvZjNvRUp4Y1JLbXR2MGtRamhndURoUHVHVEc2aTRyeXNB?= =?utf-8?B?Yk8vbXAxclNaMXZ5WUxWYkVtdEgwV1lnM3lGcUpmOGprYjZ0WDRKaU5ET2xx?= =?utf-8?B?bzV6Tkw1QkhhMXRlR1BKUlBLZ2tNSWpneDUzTUVBRStoZmNFNDU4L0FrYWk4?= =?utf-8?B?Y2FuMGV0aldORnRVNXljdHNiQ0RycGxxMTVmNGhWSmtrWkdXQVd0VThzbG8w?= =?utf-8?B?YlZxbGdKb2lzWjBra0h2d2FNZTJvOXd6QjRKeG5JSkFoNHlZRFhFT3NuOGRz?= =?utf-8?B?SUhVeDBKWkorckNXR2Q3Uk1iTXZqelczOTVDcXAxbXJKTVoxUkFMSlhFaEN1?= =?utf-8?B?ZUJjOEllZ2J3S3dMWGVURHF4Rlo1OGdzWFVBTEkyWW1YeHVVeU5PUGlCc0Z4?= =?utf-8?B?VXF1N2h0Q0VBcmVQdVR2UFlCK1RYQ0tPYTVTZ0xkRHQxZzhIbi9NOU9ncTJE?= =?utf-8?B?SHBiYUw1MHdIOFBQalJFWmRlZ1lHNGdqNFd0WkRtTU5OcVpEYXdHTDhLTHFR?= =?utf-8?Q?EVONAwqGTzBl4dKcphSvaYOEXg9CdZ/tf/SzNGBWu0OVL?= X-MS-Exchange-AntiSpam-MessageData-1: 3pCvTKj+G/JoqA== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: a64a5e52-01e4-4ad4-a33e-08de73b01e15 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 14:22:19.1095 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: svndvme5Hbu9a6Jv81CDkwplpEy3YzW7cytv2mXjNJgcfK1SiCvXTX+/VKaOx+I+gKne3GH1rXVofVFwp9Uxsw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7811 Single-bit numbers are typically treated as booleans. There is an `Into` implementation for those, but invoking it from contexts that lack type expectations is not always convenient. Add an `into_bool` method as a simpler shortcut. Reviewed-by: Alice Ryhl Reviewed-by: Gary Guo Reviewed-by: Daniel Almeida Tested-by: Dirk Behme Acked-by: Miguel Ojeda Signed-off-by: Alexandre Courbot --- rust/kernel/num/bounded.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/rust/kernel/num/bounded.rs b/rust/kernel/num/bounded.rs index 2f5f13ecd3d6..d28d118abd8e 100644 --- a/rust/kernel/num/bounded.rs +++ b/rust/kernel/num/bounded.rs @@ -1101,3 +1101,24 @@ fn from(value: bool) -> Self { unsafe { Self::__new(T::from(value)) } } } + +impl Bounded +where + T: Integer + Zeroable, +{ + /// Converts this [`Bounded`] into a [`bool`]. + /// + /// This is a shorter way of writing `bool::from(self)`. + /// + /// # Examples + /// + /// ``` + /// use kernel::num::Bounded; + /// + /// assert_eq!(Bounded::::new::<0>().into_bool(), false); + /// assert_eq!(Bounded::::new::<1>().into_bool(), true); + /// ``` + pub fn into_bool(self) -> bool { + self.into() + } +} --=20 2.53.0 From nobody Fri Apr 17 01:39:55 2026 Received: from SA9PR02CU001.outbound.protection.outlook.com (mail-southcentralusazon11013051.outbound.protection.outlook.com [40.93.196.51]) (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 4742139B4AF; Tue, 24 Feb 2026 14:22:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.196.51 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942947; cv=fail; b=LzhTjkJaU9KuK1LMDvAkSnKyRiDAkfoLVhyOLoVndBpTj9MNdsb5e70IjlYQGkyHrz31FAT7hdmcfgO2o8wY8w0C1250y2cFWcHSU5JHk50W69+xE27IsoR/tZCMgcR2eYYpv3chOlhkCwNDr7v1xiYtcsxSMfj3WbEcikdoP5g= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942947; c=relaxed/simple; bh=/6FS+f9LJD+ykvstPp/esTg5M/Vi2gdGcPdIKyp7zQM=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=hsOMIzaBwQCswxrFpdi3LiW4mP93uuslPpRcffziqeYBbZnUWgo4pr7Mi2J29gqk6u25TIGxF0ou1bDK+5Od4uDC0Yb27mwRmWep5BYMR9MDa4zdIiSosXegkL4uYqytvSFtIZlJJi3lvJJxzg6wv7ESIv8dIb0fuE+FhV/v39k= 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=pPcGiS1C; arc=fail smtp.client-ip=40.93.196.51 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="pPcGiS1C" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=jR5Thc3wYtjjN7emRdDvogPbgFFLzhMvZ4iTmM9LdcYYT2y1ZfzQyyp4GguQkC6odjsYZiCew0v/aNBc9IrNWQzUdRJG0TjmatN5D6QwL8HEkOc07DqlxpqnfkYtfCWj+rn/PS5kwg9ouUvPrhNz4hfswXo7o+IlT4abWlv1jN/krb+jxyEMRfE0FRSX5+bHiTtv/+zpalDVIpTERX4Buz3yny+pf5VSXA4TPHy+/i/0rKiZtzWl8PAP2znsWMu9/ROMlVXNGsW4whX/Jl8kgrFXzFLz/Ea1C242cQwUg8H7imPa6YiAZ7LSCBQ++IRacbhuFB7gyTGe9kB3TN4KZQ== 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=NEpzwvMsTGgwfIdOlMnm44rPFMDaT7DWwdb2Pr12dRM=; b=kjY5Fyfb0yMG+Q07rE4SzUZBBFY5gAPU6XIS+vn2hnOGIDE6Talrpc+GDL6Bg1VskHMf16zKtKqTXMY9bQ/EKh2OnYV95m8II0ixXHCDuOGzMfWtxXARU7Dl/AP4WTUQxcwMjBtsWd3CNnUQU9VA1gE9YstbGcciCfKByOydgObOVBfKTzHJ82lH0Iq3OrtE95ZU4GLdiP+4SKiVW7f9I7FkHemlGeaBrawpori+jLRXEDEbAgKdq3z/UK7duj0auMDg2409qtjW5HTin41vxeJOgfd3Wx5iK0Dkza0aHPKvcIGEQZ6LKlcrlP+9b3XQ9CWceGI72qq3S8Wo+vARtw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none 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=NEpzwvMsTGgwfIdOlMnm44rPFMDaT7DWwdb2Pr12dRM=; b=pPcGiS1C4oemOBEV9h22xp/chEi/cXBwzxVk4/Z8+ZrthcdkcbljrxPeT2Re4P3/QzmUD1eXLHEWj0mdDcdoWDECC1xQKVQo+xMW4R6Is/zlbVidaNJGIC8Bg7A+8sNKJXa3W+NwXUL1zAbw0XCUIerwH0l67pm6j/d2dBSu7ioohQcLJswz4096c4Hm6vpK8aVbkXlhVTGDyM5aR0wPUisuc8cKXREWUVcjdzaIKbFYUvZX7vAs9UHLHBNTGibmAu65t8qkoufvbzZFwVqENW/y4HFKcXmUH/QvmQFt3bfj7vB+ZfDPxlcFkSd+aH3MciP6g11gAe9adrg+DYQBJQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by SN7PR12MB7811.namprd12.prod.outlook.com (2603:10b6:806:34f::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 14:22:23 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%6]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 14:22:23 +0000 From: Alexandre Courbot Date: Tue, 24 Feb 2026 23:21:42 +0900 Subject: [PATCH v7 04/10] rust: num: make Bounded::get const Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260224-register-v7-4-aad44f760f33@nvidia.com> References: <20260224-register-v7-0-aad44f760f33@nvidia.com> In-Reply-To: <20260224-register-v7-0-aad44f760f33@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Boqun Feng Cc: Yury Norov , John Hubbard , Alistair Popple , Joel Fernandes , Timur Tabi , Edwin Peer , Eliot Courtney , Dirk Behme , Steven Price , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Courbot X-Mailer: b4 0.14.3 X-ClientProxiedBy: TY4P286CA0013.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:26d::6) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR12MB3990:EE_|SN7PR12MB7811:EE_ X-MS-Office365-Filtering-Correlation-Id: 881027da-824a-499d-f40c-08de73b02066 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?SFB6d291blFGbkhpajk3d3ZQeXlDcHJsMzNxQWEyQmhXK3FPZHNlM1hZNEtC?= =?utf-8?B?a3hSMXk3a1hzeUFSSlVlM0g0b3BuSVZoZ0FMNFdQcWlWRDJCM2dDakpGb2Zr?= =?utf-8?B?RTNEamQ3UDgyZU9YaUk1YklhdnFRcnlyMVd0aWt2UEJyYVBNQ0t5eTZNd0hN?= =?utf-8?B?NU9tb3NGUnhWdE5UekI4anl4OHVwWnpDdDc2U29kSGhXKytBOStERzhsV3pX?= =?utf-8?B?aUtDdUlzbFJlTThJUllxNDFMVlU5VHF0WVJpNEQ5WlhIcTUxM3phM3RGcEhB?= =?utf-8?B?MUh5Y0ovc1VBTXd5RHNJY2RhSm5Demlmd0lYQmVibzNIamphVGVkTUVHcTFi?= =?utf-8?B?aEhmei9SNldXS3MvVFZwMlJSWWVETm5SVXB0Z1hjR0JCVUdSVWZYS0hva0tm?= =?utf-8?B?ZnFyVW5GTnBPbTFDb1NPdFAycWNtZHR3VlRRTGJjWStiKzRTSERYK0MySU9y?= =?utf-8?B?SzlVazkwdDlLSi9nQjVXT3F2OEdkUXFiSmt2V1JxZ0RsaTJOcGd0ZzZWYzRl?= =?utf-8?B?SjFEMkR4NDZ6YkRNcDA4dTNtdkhsZytKYU03K1hHTTNDWTNLVkxnOWFHNFV4?= =?utf-8?B?ZnpmbDNUa3BFRWJmamJwVktYOEZZS0NKaFBmUEJodmZXd1ZienhxTHVCZk5X?= =?utf-8?B?U3J3ZFN0MDlzOGpDb2RldWU3Nmw2YWtaWFlRM0tNNmFGSlV5NEVkYlZZcTBl?= =?utf-8?B?SlNOVzVYMTNVbnFLK2FMRVRKN1p4TUFoZTBFNnNpWkNQQzZTVUFhdHZ1SUh0?= =?utf-8?B?Q3BDM1FkMTBKbUM3OW5YWkN3a1NJR1dTT01qdmVDL3F3REVkWEtBSG1nZnNv?= =?utf-8?B?YWQrdks0cUtHclRBQjR3MjNBblZVVkZBeFEvM0tJcmplYmRFRVRmdWNDM1NC?= =?utf-8?B?RlQvNU5TNGJTY1lWUjJURGhLT0Y1czl1WEFnZWFiTlZKUVA5OUxUdEpoODJD?= =?utf-8?B?WHlMdzRoeWlUN1NPTFExSWhVTUlScXNlTCtoS2FFV0FqNEJ4MFBUaWtYTkwy?= =?utf-8?B?Z1ZVdzR1MEx4UnRWSVBrVVRwQVNrRkR2K2tHL3ZvNWJjQnhCQmhQR01VWlhm?= =?utf-8?B?SDdyZGx3WGQ0bC9SdCtER1A4U0xCVlAyQytzT0RacnBjeDY2ZEtlbzMwbXho?= =?utf-8?B?LzNQdjlLc0tLZVkzQkh4WU1venZ3VllzVmpvdVpQSmhEUG1wTjJUNm5MVGcx?= =?utf-8?B?WUNHalZWY09VUDl5N0JranZUQ3Y4NGszM1UxTkdYTVVaSmxTWXB6Z29NcmJv?= =?utf-8?B?VFZ0K2RkdUlxUUNoWnowSkNRSFhyWFBVU1VOalF1NkF4QVJiTEpLNDdBczN6?= =?utf-8?B?N1lWb2duM3VTeFZlbFpvKzNkSVFidzdIbkZlVDBaVjcrL2JkNkN2QXN6eFBl?= =?utf-8?B?V0xjdzEwOUFpQTRXSTIvV2w4eStOOVI0cWhLNnBnbm1iTEFPM0JLZVB5MHcw?= =?utf-8?B?M0ZUWjVtNXJzbnZwRmQxZ3Y5WXJKL2ZvS1pKTDN6NTlwQVRXRkRBbWdEUlVN?= =?utf-8?B?OFd6MVRPUW9zbmQ4dndyUDYyMFBNL2psWitGNGFEOGp3bWFOUHphT1pJMVdv?= =?utf-8?B?YWx0WWIyQTYwU3dMTDUvNmhncjF4YWFBckZ2UUdxRWNlUURETFJHNk9UTnh0?= =?utf-8?B?eldMeFpCZVlWa05xZWVjQ1pCd2ZyWitRK09ZRXlvc2ViaTlzcEY3WDl6VDRW?= =?utf-8?B?RzYrSWFmZllzZVZEWEFvUjVuVzcyZkZGREJLSGd4Skd5d240TzZ6dTdVQVha?= =?utf-8?B?aGpyOWJnc29ZVmF0K0x0T25aYjdqNkU3dnR6NFVIRFRuTEhvTzBKRzhtUXZz?= =?utf-8?B?SXpDSnlFWXFOY2xvd0RJam1aNUl2T216cW1pUXdGK1FQMzh4ME5OcGpIL2J6?= =?utf-8?B?dFNjZnVjSENKYWhxOGFKejJ2emFoWUJBRzdnSWllajg5UGphTlZLRTVXN3VX?= =?utf-8?B?dmNnaEM4MElkcDFtM3Q5c0RPVWN3djNqYVNOQ1k0RnJoTnVLcVlyU0lvR1Bn?= =?utf-8?B?Q3ZoMStXblB0dVYrd2Z2NUVyVld4RkhVWFlWYXBDa1NyQkcyVHZRaUZkcCtU?= =?utf-8?B?Ynk3UE5YSXk0OC9DVTkyTjVuelNMVmJ1b3FIWU5sT3VaZGRVeWdrQW1hbUF3?= =?utf-8?B?eURLd3RlTVZFR3didUJHU2I3VlM0RlpQM3lLbW1yNEVRckVxTkpFcTZrQUhC?= =?utf-8?B?WWc9PQ==?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?cFExNnFvYkNkQ21UOXhrQnRnV2R0d0FZcXRkMG5TWWx3eEpaRkNrODlJR3U2?= =?utf-8?B?ZnFiOTBCMk9JSUkvdnJTc1lhVlFlQ3c2cEFLMmg3WG1rMUdEU1hGRkRPKzRJ?= =?utf-8?B?Tm9Va0lXNTc5ZVhPQUZkODRMNnBXdndPOWVQR2xlUEFEMi9ZV296YlMvT3FI?= =?utf-8?B?WEtkRnNiYktQSWdmbDFCYWpsd3RSeWVnc1RmejJRYjdUY3d0bThON1NIbWli?= =?utf-8?B?WnJBNDk5SkM0OTA3eExEL05zS2JYcjBVUS9TdkQ2WWZaTnhCYlFBaUtudnFT?= =?utf-8?B?bFVPYkhLZFBnN20wcFFIWnFHbmJBbUF2cGRmQkRJZDlNVXVrTUdGRGpvUWpz?= =?utf-8?B?SVpKN0NYa2drL0tReGNYTk5FZFF2TXNFbU1PdHFKVTYzYWkzUzREdjhVMXN1?= =?utf-8?B?eTFYTkVyTjhUbi9LVVc3UmpHRk1Qay9Wak9oUHE2ZmF1cUE4TmlGcHNldnpE?= =?utf-8?B?anY4UWxvc0ZxRXJ2NGZDSS81NDdjb1k0Z2xveXRNREh3Y0p2dUVqai9rbE5H?= =?utf-8?B?VkhnNFRTUDBkNzJ5UktrUlpiNG1qYnBqRXRMOUsrWXpTZ1dtYUZnWkNLWGxj?= =?utf-8?B?bHcrRTRpc1VRVnkzU09KUk9HTzZZVUs3QmNLcCs0MStWK1VqK0k3TURSWi9l?= =?utf-8?B?cm5oK25oVUdoYTRhWWk2Q01CQXUwTjUzK0JrZkZIVkQwTHc5ZWlVSjluWFp3?= =?utf-8?B?aEZkOHZydk9PdHczM0FRbkwrWllEcXg2Mkt5MU5KUDkwb2RLWWlrY2E4ZDUx?= =?utf-8?B?VmpVVWtEaEVjWXFhUm44cWVyWnZpVHU4eGM2QXladzkrSjJIY2ltWTY5aVlJ?= =?utf-8?B?VENlekVkdG1mdzBCMHZjUlVTU2taUkRiR2RCK3hnRXVqMFhpcmpPeGdjRDRy?= =?utf-8?B?RzByaFRKZCsrbWlSQmd1cHFqU2w0S29LSzQycnA1aXB6MmlvUUNBbjFqMXF6?= =?utf-8?B?WjhocnJxQzM3UWEzbVlLVDRyemVNRGF5L3NkQUY5Vy8zaHdzaFZnbU94NkVX?= =?utf-8?B?UkQrUmZXMlZMenRjVS8rSHJPUS9ZYm0rd1dVTDBjL09MajZtUklkalgyNVJK?= =?utf-8?B?ZGlmNVlvb0ozYkladkp1MWtpSE9PMTVGODB6Z3hSQTFnejE2MWhqcnJlMU5S?= =?utf-8?B?bno4QkxyWkJ1amlRU2t2VVdOaVJrcjRLV2ZsSUxTZmRkTDExRElhdXZ3ZVMz?= =?utf-8?B?VEZMeDA1T1l3cE9TZlhocndrc1d2U2p5Y2JmT09NVis5bng2QUk1NmJWVC8w?= =?utf-8?B?cndXL1V5WjJNQnk1bXFOd1ZsWnJRVlM4a2g2V1FVL0l4blJCZ2N4N3dXYTc0?= =?utf-8?B?V3QyeXlyUUdlUDVmYWlFRXo5YTQ5UkhnMk0rYWpzWU9MRnpRNW1OSXk3NEtm?= =?utf-8?B?NXhxejBvaDYzK0lEdFY1UWVaMm9aeWhiM1ZZK0g5cXJsRkNEeU5rRzhBQytm?= =?utf-8?B?N2QyS0daMVBWa0dkN0dIaTNPQlI1QXMwWjhneUkxWDV6SlpPaUFybmRWZUZX?= =?utf-8?B?Tm5zUE9QTVFsOHFFZ1ViOFRBcnJNZmVMdHFxa01qdGtsTU8vQ1dSSFFiRkJh?= =?utf-8?B?S1ZxcHZSck80YWg5S1NGQWVOUkhvY2diVjh0NWREM05Db1BFcWhUa3RuZ2ND?= =?utf-8?B?ZzROeG5LQUJuUmtoUjFlSmJNYyt2cjh3Tmh3Tjg0aHh5VHk4WTVWKzNCNHdN?= =?utf-8?B?dG9OUDdWZDZoVnF0bytwdlhtM0lyY2p2Rnh2TUhEcytHT2huSXBYMjEwcUk1?= =?utf-8?B?VnQ2eEQwbkJUL0N0ODdMWFp5M1NibmpsWEpvTkduNnZnL2xTUU0zRUhTM1Fl?= =?utf-8?B?QkcvVndOK3FRVFFFMU9PVE9SbUM1YnZEaEZRUzNnREpkaW1UMkdaRGpLbEVa?= =?utf-8?B?enBIVkhkZmczQkVTdVhiK05IeXpBNnZOenhYL2krK2paUTVJQTBRQUViclQ2?= =?utf-8?B?eStzcVhnZHJpelYvUkYzQTlWUk1wK01kMk5VQWJ4OXRoSVBlMitvbnJUVS81?= =?utf-8?B?Yy9Ca1NFdTNkUWZWNlQvK1U1bHFJNEV1WHh4S2p6RTFvZGhkOEhad0gvMmZ5?= =?utf-8?B?b1ZGcjhURXFSeTM2RU5TQmp6TTBsMDV6NDJmWDhQaDBPb0JDZVFNbWFFaW5s?= =?utf-8?B?MzE4Tmg1YllJc0pUQW94NnE3MWs4eCttYTlHdHpESXZQeWw5aTZidzJPRHg4?= =?utf-8?B?cWh6YUlNRHcwSEgrK2lhamxvZ3MzWWlaYUN3N2k2U1VYYzU4c2ZBdXkxSEVU?= =?utf-8?B?ZVh1WjBCY0paS2VtSmlLR3hiSGFpcmhwb0wwakcxRC9tUHhHUDRNTlJYNmhk?= =?utf-8?B?YkEyUXVwdmszeitVOWV0MXdZYmtEcXBUalUvaWxxelNpdjZzVTlTekNsdk9a?= =?utf-8?Q?Vqk4Hmznk9x80JvgIer0phjKWnvC0CAK+T8Dn7Sc7k6ak?= X-MS-Exchange-AntiSpam-MessageData-1: SHx7bYcumlAPFQ== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 881027da-824a-499d-f40c-08de73b02066 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 14:22:22.9632 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: Xp7EMsod7v8jTLYE+Jy5PyXS/loB8HXGaSGk5DYvISJqmVIktVPkfA+41RIYKeOlGelo0tv+9+1ms5lGDiCGQw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7811 There is a need to access the inner value of a `Bounded` in const context, notably for bitfields and registers. Remove the invariant check of `Bounded::get`, which allows us to make it const. Signed-off-by: Alexandre Courbot Reviewed-by: Gary Guo Tested-by: Dirk Behme --- rust/kernel/num/bounded.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rust/kernel/num/bounded.rs b/rust/kernel/num/bounded.rs index d28d118abd8e..bbab6bbcb315 100644 --- a/rust/kernel/num/bounded.rs +++ b/rust/kernel/num/bounded.rs @@ -379,6 +379,9 @@ pub fn from_expr(expr: T) -> Self { =20 /// Returns the wrapped value as the backing type. /// + /// This is similar to the [`Deref`] implementation, but doesn't enfor= ce the size invariant of + /// the [`Bounded`], which might produce slightly less optimal code. + /// /// # Examples /// /// ``` @@ -387,8 +390,8 @@ pub fn from_expr(expr: T) -> Self { /// let v =3D Bounded::::new::<7>(); /// assert_eq!(v.get(), 7u32); /// ``` - pub fn get(self) -> T { - *self.deref() + pub const fn get(self) -> T { + self.0 } =20 /// Increases the number of bits usable for `self`. --=20 2.53.0 From nobody Fri Apr 17 01:39:55 2026 Received: from SN4PR0501CU005.outbound.protection.outlook.com (mail-southcentralusazon11011071.outbound.protection.outlook.com [40.93.194.71]) (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 052D83A0B1C; Tue, 24 Feb 2026 14:22:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.194.71 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942952; cv=fail; b=pCxsHYDwinfLYRci0ljonBVKyw1rvbSdEWdIbcJTUXvURZw3yU5Tn4zpd/ZGNlRFDX7bInyuKbZH6YNJmivUU6xkStpPEh8u7BS9LcqnncVtgh2gTZ7pwymgzxPfA5TE9BFLgTOmXiGbB4wKMAORuJTxA5eph1dYBfO1lCISaTQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942952; c=relaxed/simple; bh=Rx5To5YtmxhdVoxcODIf2BvjtE2cU2ARwvFDZrH6WNc=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=Ko7U/URlLoHvFU0rPTfWMF6lKeQeGD5XdwENKRNuHVg+BO9SfKSB4M+KwQ07g/6Z3kzVjx8eQDfCszaXl7TobqXcizRvR66DTisQkXlK/FWI9A5QYx3lm6cyai3F8Eei5oTCKMqAbGl+LCxQU5Zf3XmA/BYA1wfNxHlxjFSikA4= 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=XOfNOr8+; arc=fail smtp.client-ip=40.93.194.71 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="XOfNOr8+" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=aZWUoEG9loX3BM74D8oF4VjHdtXzfc+VpQJ1SMtMy2VSkJJIRAKGmFCnHOK3F2nHfwFlR1TRvAS20f69gp35qoShEXivJdLIf8dz+r/XPxpm8a5INHHevuFqSHiFGXr5NMN1v17W/4SKrfFy9BDZh3Mrm/EdBEYfTDgvc0+1wSaZs6TwoPB06bp/8n2zw57T+UQtFd0v8Pw5VBG1RU20YdcJeXkFg6MqH2hKCpu+DJdskNGQcml3Pwgsz05FjfVTKioVfxHAXlPyx+vgLjsTlIDxFvqcyqbrIIo12O/cIvWRIkuC6rk+J+m0SCMJ8VX4YECIdRt5dRseYRb1+Vn9hw== 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=0gCXctdlO0zbY/G0m0+Z5fOuX0W4QxODveRR/V5UphI=; b=ZwPIHw5+ikMl7uhr6+hcGdeMKECldlC2sPzETI0EwicR6+RnJ6bOu3hTyb59ksfRw1fQWu7HJWJrmp2Pn7halCUJR8AUZHEPu9QKvNBoSxQ/NBfTYHgZcz5Ccq1kXZbNghvYL1/3HYECk5V+34dKE3GzR5aAyA/731Rx1Ougx6HDmx+N+W28L9I5OYAuQW6jzhS4Nv/elJtmkEK7mNVvo2nx0bPEX/olvoYLSWIzonjZU8zZNC3ov5dOr+iMnIHPi6LB4POA4lCJWRa8luv46byapIctR2BSKpt59LQ/T/zLtHiuv/51WrN9KVr7eF6XXk4q2WU/HFefGDRCWr7i1g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none 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=0gCXctdlO0zbY/G0m0+Z5fOuX0W4QxODveRR/V5UphI=; b=XOfNOr8+1vgbAuwbByTucJIHEZ8UQY3UDq5D3mYzt+C0mQiWZN+IRrT1qVHRAR1oe8aCj6z9C7Xy3gC/5AdbQWpqxZfYJ3+pGIKNItIje79EHGEpjFHY8/GQJRoiF0aFEwTYAgP80/s9yrhEvpO3xzBHO8ji0tWU3jsy3OOf6A7Ngr36PWOyB9Kq+wtr8IhFdj9v6bJ7z1eemx4JMqnBoTMCH1jAk+5ueSPKkIy0hj2WJfmEbx3bmA13+BN86W+VNBqhfUr1ygEjE3Vt8lhtLcd+MHaF7xFQCJWw2ZnQH/jcJOBp/IFLbFv+WHSuQGwECgzBbNLzQt2kMXcBSRUxzQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by SN7PR12MB7811.namprd12.prod.outlook.com (2603:10b6:806:34f::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 14:22:26 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%6]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 14:22:26 +0000 From: Alexandre Courbot Date: Tue, 24 Feb 2026 23:21:43 +0900 Subject: [PATCH v7 05/10] rust: io: add IoLoc and IoWrite types Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260224-register-v7-5-aad44f760f33@nvidia.com> References: <20260224-register-v7-0-aad44f760f33@nvidia.com> In-Reply-To: <20260224-register-v7-0-aad44f760f33@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Boqun Feng Cc: Yury Norov , John Hubbard , Alistair Popple , Joel Fernandes , Timur Tabi , Edwin Peer , Eliot Courtney , Dirk Behme , Steven Price , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Courbot X-Mailer: b4 0.14.3 X-ClientProxiedBy: TYCPR01CA0169.jpnprd01.prod.outlook.com (2603:1096:400:2b2::12) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR12MB3990:EE_|SN7PR12MB7811:EE_ X-MS-Office365-Filtering-Correlation-Id: e8785b49-7315-4a1e-d123-08de73b0227d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|7416014|376014|921020|7053199007; X-Microsoft-Antispam-Message-Info: =?utf-8?B?K3VWUkM1THBES1VpWFBKYm9yQk0xTzR4cmJhQmRBNVNDZGVjZ2FUWXV5Tit6?= =?utf-8?B?cDIvVWN6Skx1dS9HODZqQk5TTGhQVGowQTNYY014TmhkWGpiMDNOYnVCMCtQ?= =?utf-8?B?UkhxeWREUHJkQUtHNzZ4cHlyL2hwY3lJaENXQ1ZRZzFaYUJuNTdQcnVEUGw0?= =?utf-8?B?c2NiU3l5NlBCdmtwQ0dueFJXZjRZcm5EZGxWRnZwbGpmNUdHZzlRUUpnK0tK?= =?utf-8?B?azFQSkZ2SVdPVzBzRUdQN2RBMFAvampsSzhJRXhvS1F1eEZ0RlpWWXNpcmN3?= =?utf-8?B?azFmcC9TbXVpRlFkaWNFbFl5Y1hzdXJMaDY1UDFWV1lOUk44b2sxRy9Cc3Fl?= =?utf-8?B?NTR5RFdiaFFGcVNpL0wwRnRNaDNCblNtV2FsdnVUYW5DWE9mTUR3R295S0to?= =?utf-8?B?cHFFRjY2ZXR1OEo1WnZ6MlA3ZGIzUlpZWExqb0RZcFdYbWxWSlVlUzJkOFdP?= =?utf-8?B?dkZ0TnIxUnMwSzhGWU9HZVJydFFtMmhFUXdGUWRrbVErUGFoTUVBc3pTSzRu?= =?utf-8?B?dzFxa3dGSDFoUVAwdmZiMlpwTU9lZTI3WlAyaDJQMlVJcHk1MFA5N3JqdVhm?= =?utf-8?B?THczQmR5RnB4RmozOFNoSWR5VDg4QTdsWnlxZ3JSUFE3anlIZFhmR0drZnpx?= =?utf-8?B?UHdBd0xFZ2R3eHVQOXNoNDJtVzRFa0xhSmFXWUVaMGlSNDlZMFZhUzRaQmhs?= =?utf-8?B?d09kRWdiL242bUUxdTRUeHJaSXVIR2lEU2MxL1JQQXlma1pTUEVsd2F4ZXRs?= =?utf-8?B?dW1QNTBLR2M1M0FXR0JjTndvU1dZcVZrS1pkMkk4ejZ0bTZXbHYrYW0yU2c1?= =?utf-8?B?dXhxaFo2OUpDZkwvSGJsRnVJZzhBalJwaUpBUDlkUnFyQ1hXR0RXMXhmRDdm?= =?utf-8?B?Kzdlc00wem16ZlRCQzBJS29hWGQvcEpIYjhiUktIdjNQTkdhMVVIQW1ERTM4?= =?utf-8?B?QWtuQlhXcURYQUZGSVdvTlZSZ1ZWMUUyTU9OWXZhSVFSYWgxT2Y3dEE4OXZF?= =?utf-8?B?ajVNbTZndFlNbU5veE5GNXFQa3JqakJOczJvcjVaei9kMXByeE52VVcrU3Qx?= =?utf-8?B?UzFUOHBjVEwybTd1aEdxcXFGeHdzRFRqVFdSeGZGUnZZRGFxdkx2d2YvSEhq?= =?utf-8?B?RThObXpaQm0xSjRRZ2FpT3Z3WFV6UFd2YzlVa0xNV3dTeVo1R1lPOFoyRlNp?= =?utf-8?B?dTUxNG5waDFtb3I4TXBNWEVsL3RPdGFCZVJuSFhSb2NQUTF2RHRwbWMxMmpJ?= =?utf-8?B?NWN0bExiazNIcVc1WVFSR0d0aGppYVI0KzdUZU5yOEhGdTg0UnU1MytSRVdN?= =?utf-8?B?cCtMemZ3Wkl3UUgyd2hEZUJ4VkppUCttUzVFMG1SUGptYndYK0Y3SVVmeXgx?= =?utf-8?B?UDA1YmZndDIyZmFyMnZNemJhcWIxZmlFYWgxdkZqVlQ3UFBQN01pV1ZFcVY3?= =?utf-8?B?LzA5eDBsM3JjNzdDeUllM1BmTXI0MUxNN3RsM1Raa1N4REZiN3JCTS9lMVlP?= =?utf-8?B?amFMUXZPc2prNS9TYXgwb1psSFdYSTN2RTRrQ09uV3N2YjJnVTF2VEY4S3Zs?= =?utf-8?B?YUNWWVpNMU9vMDdrOFI0UmVaUlNrVEhCRzJmLzNPWk1ieEFFK0UrSENxTGlK?= =?utf-8?B?ZUtqSmRVd0RVcUNSK1JlNTNTUjdJY0pSTk1ja1lJbFFWQXFYcEdDR1c0ZEQv?= =?utf-8?B?dENsWGpNMURyU1pNUFZhL3RWT05ubGdkRjR0d1lENU9qVm1mRnU1Qkl4eHdJ?= =?utf-8?B?aWlGaFUxRmxsQWYwZm9QY3VZTnlzcllnSUg4Snhwc3RTRjFxMWpUZE1lUlQr?= =?utf-8?B?ZHd4UXJYa1dnU3NZNHJkbTJOVE9KWjVSNUFwR0k4Z2xKMWx5eDArQXV6S2ZX?= =?utf-8?B?NVFtU0NhUWpJYzFEU0NOV1JzbzE1QUNwSG5iaXhTQnJOa1VJbXNRbjlNREpt?= =?utf-8?B?cnVLVlZKRmk0UC9XdW5jdUJTOE9kOStTcE5HWEw0K3d2VUJMaDRCWEpwTGpS?= =?utf-8?B?NVlTeDdOSmhMUlRYTEpPR0dsZUFyeG45VTNodENuTnZhYjN0Mk5wcE9TdHNk?= =?utf-8?B?QlU4SzJQRFFMZXdWUTFQaUwrYUdSYy9QUDk0NXF2ajIrVG1OY3AwZUxKaVh5?= =?utf-8?B?ZndIWkErWDhuckw2TkZiOStEUnFiUFBzVC9HU2ppMzVaTXFVOUxLdUJ3MEls?= =?utf-8?B?bEE9PQ==?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(7416014)(376014)(921020)(7053199007);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?bU9CSHRrM1lpNVFyVGd1RHBkZSsrdGo4bjR4eldMQWl0R1E2cUJRUm5MWlUx?= =?utf-8?B?dk5qenViSDRNZlcyMzdNOU9aMnRsK2xFV2ZkUHVWOG9jb0Jrdy9hVE5hZ3BK?= =?utf-8?B?TmpSdlJwTWRacG5YNVFwZ3dCVHYrMzM3YzBEMU03WnZHRU9sSDFrVWRuVUFN?= =?utf-8?B?MDJwbDhvdTFZSXQ3Zk50bVJwN0ZJT3Z3ZUZyODlvL3Zid0RydEdhci95b3FL?= =?utf-8?B?MDhzUzF3KzVHUUg0YVVIRTNhbDlDRTF1T3ZFeER6S1pHWEFsT2x4Tkd3aHpv?= =?utf-8?B?OThTK09lakFNbXVGc0ZKYVQwUGpoZDJnOWVxcmgxWXRWeDFVaGtIS0F0YVJl?= =?utf-8?B?WStEVDFWbUVRc0JjL1hGTS9rbDF1RjRMdFB1ck9Yc2tOOTlkMVgrYmxyRWI3?= =?utf-8?B?KzdDdDBiUXRRbVFtdnV3ejhBY29IT255N2loK1hFcDZqRVc3VXl1TGZ1enFx?= =?utf-8?B?UHNKS1dVeCs0dWR1dkNmcDUzcE5hOHlLWDFCWWppT3hpRnNvN29ET2wyc0h6?= =?utf-8?B?TjRFZmRKdDY0bEs5ZjloeVE0akxUZ3lGZTRmS1JMMm5pUU43ZUd5ZTJSQVZi?= =?utf-8?B?d2FkYWFZeTFkYW9xNWhSVzlIUXVFR2E4SzZBV09aYnUzRitMbUZDY2x0R3dO?= =?utf-8?B?cEs1QU1SRUMzWk5kTkxONmNvdGVKNzNwRjc3VDJDclpIazFVMm4xT0MwR0RD?= =?utf-8?B?K1RLaFJoQnRSVEpjOGRTaDBDc1Nib1lXYVFmdzBCMWt5TVFudHpiY2FJQnpO?= =?utf-8?B?VFBWZFFMTk5QajNRRythTXF5bGVKY2pLUUE0VGkzZWhRbnlVNTh1em8yTmNx?= =?utf-8?B?WDhjTzl2OWpXVlgyUWt0amoxQUJNODRNZmZXNklOZ2UvaDEybUJoWXNZS0xB?= =?utf-8?B?cEY4dUMxNDdnSDdIWC82Ymt4SHFaRlRyVGJLMlQycWNRMVQraFZpWVBIdnFH?= =?utf-8?B?VkZ4M0RNVG0vSk1nVzRDYyt6cmQ2QS83K0V0bXFtamk0YUsrWHNaTVhLWk55?= =?utf-8?B?RFAzODVUTjBaYk5UMjRIM0I3VDlTU1h5dEVFRWtIZlNFTkxHaXk3eHR2UUNJ?= =?utf-8?B?YktpQVFnc0FyRjUxbDd1SGxCRHdVK2tad2FUQlltYURsblNiTC9mYThtRTlo?= =?utf-8?B?OHZJRk96bEpTQXR5VXMzaWM5VXlkUzNza2xYQnEvV0ROVWpNd3VYUytQdDlW?= =?utf-8?B?Z3FhdjJnUVAzaWk5b2ZXN0MwNmx5MSttN2h6TWhRRVRqc1I5cGVZWmlhTDRO?= =?utf-8?B?TmVTVHM3dGxhYU5WaFFQQU1EUWJHaXhvM2t2N0RUL0xxeXFSdWZGdHJZTHFH?= =?utf-8?B?TnlkSThTVHJnc2NwVENDazQ1cksva1ZOZkhuSUdGcENkcnFVTXkxeStsVDBa?= =?utf-8?B?V0NXcGhOTGhGeGlocGxib09ZRlk4aW13SUNWV2h2OHMxNUUrTUtzZ1FYVy9u?= =?utf-8?B?YVhtSTFtWXlVQVM4bnBFT21STkt1V1RTYU5ZdGVKZ1ltRVp1Nk1pWXhNTm84?= =?utf-8?B?YUJrRE9ZTmVZRGdpekoxSW8zbEc5bTNWckNFYlMwVzVDeTFySXdqVTF0dTJv?= =?utf-8?B?RnVWT3pGWkFUdnJDR1BuRlh5dTAydm1ZQnpXd0Z0OFdLNFlkL0lSaHdORXRF?= =?utf-8?B?Z0NBWG1QMFVPYmlhcnVZNEVhZTNJSVJiWE9sMStJQ1NHLytNWkZ4bGRjT3RH?= =?utf-8?B?WFZsd3dQSGNWL20xSGJkREJLa3ZsczhDdmNnQUxSWGNGcDFaNWZjY1UrajRV?= =?utf-8?B?Vm9mR3MvWkg5cGEwcjJJenNnY2RtdmFVMmhOektRMGdhanl6ZVM2ZEwzU2Rp?= =?utf-8?B?S2RrSy9IRVRFdzE5SnRNVEpOdUd1dVlPRGNzcFk2ejFhY2NiV09RQ3lzb0hj?= =?utf-8?B?bnVDcGdhU09xL1B1ZUpkL0VXcTN5cHhhTFJyRWhqeVhFSDFJOHhiTGlEaEk2?= =?utf-8?B?OTNpd0ZLS2VzWThaUWJCYkRtZHZYVlJhZDU0emNzbDlocmZERkVpRzIzVEZZ?= =?utf-8?B?TFpiRFpGWHZ4L1A4R2FBNmhsYk1WYWw2ZzBvRWxBeDNsWkNSNGRqVWRDSHlS?= =?utf-8?B?UXZHM3h6dkhxMjdvOE1uUFZ5VnNMelJLQmIvUmJ3SEwrSTdQSU5VdXVjbks4?= =?utf-8?B?RXZKZExicTNJcDB6RE9uWDNZRXVRK1ZLaDNvRWsrb2hHSWNaNE54N1ZwYWlS?= =?utf-8?B?STNJeWdUbFhxM2F5Q1lJTFpXT1JzK3BYWmsvTldHaWp2NEwvRU1YL2hhOHFC?= =?utf-8?B?T2ZNWndyYkU3SXB2SEduZnlPWEZYQlFGQnhuTjFteStabDBoWU9zYVM2VG5a?= =?utf-8?B?VmhpdzcxckRFRThzQjAzQ3F3a0JxeEpPcGxGY3kzZC9qakttdSsxT3o0OE5B?= =?utf-8?Q?nfYGtAjWVT6+oyDqHdc2ec183mVPMBGR0z+eWBIU0Xxsd?= X-MS-Exchange-AntiSpam-MessageData-1: 2/Pnx57WiqCbnA== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: e8785b49-7315-4a1e-d123-08de73b0227d X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 14:22:26.6548 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: ksEDJf9wE/Vqq2KRRsqhAJVA0FaZXvfpo1p+qUYjW1QI1ItwcsGREMzvr3NqURqnq1TqA/vTdR6tSfXUv4v2Aw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7811 I/O accesses are defined by the following properties: - For reads, a start address, a width, and a type to interpret the read value as, - For writes, the same as above, and a value to write. Introduce the `IoLoc` trait, which allows implementing types to specify the address a type expects to be accessed at, as well as the width of the access, and the user-facing type used to perform the access. This allows read operations to be made generic with the `read` method over an `IoLoc` argument. Write operations need a value to write on top of the `IoLoc`: fulfill that purpose with the `IoWrite` type, which is the combination of an `IoLoc` and a value of the type it expects. This allows write operations to be made generic with the `write` method over a single `IoWrite` argument. The main purpose of these new entities is to allow register types to be written using these generic `read` and `write` methods of `Io`. Co-developed-by: Gary Guo Signed-off-by: Alexandre Courbot Tested-by: Dirk Behme --- rust/kernel/io.rs | 241 ++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 241 insertions(+) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index b150743ffa4f..fdd2549d8e13 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -173,6 +173,158 @@ pub trait IoCapable { unsafe fn io_write(&self, value: T, address: usize); } =20 +/// Describes a given I/O location: its offset, width, and return type. +/// +/// This trait is the key abstraction allowing [`Io::read`], [`Io::write`]= , and [`Io::update`] +/// to work uniformly with both raw `usize` offsets (for primitive types l= ike `u32`) and typed +/// ones. +/// +/// An `IoLoc` carries three pieces of information: +/// +/// - The offset to access (returned by [`IoLoc::offset`]), +/// - The width of the access (determined by [`IoLoc::IoType`]), +/// - The type `T` in which data is returned or provided. +/// +/// `T` and `IoType` may differ: for instance, a typed register has `T` = =3D the register type with +/// its bitfields, and `IoType` =3D its backing primitive (e.g. `u32`), wi= th `Into` conversions +/// between them. +/// +/// An `IoLoc` can be passed directly to [`Io::read`] or [`Io::try_read`] = to obtain a value, or +/// turned into an [`IoWrite`] via [`IoLoc::set`] to be passed to [`Io::wr= ite`] or +/// [`Io::try_write`]. +pub trait IoLoc: Copy +where + T: Into, + Self::IoType: Into, +{ + /// Size (`u8`, `u16`, etc) of the I/O performed on the returned [`off= set`](IoLoc::offset). + type IoType; + + /// Returns the offset of this location. + fn offset(self) -> usize; + + /// Turns this location into an [`IoWrite`] with the initial `value`. + fn set(self, value: T) -> IoWrite { + IoWrite { value, loc: self } + } + + /// Turns this location into an [`IoWrite`] with the initial value `0`. + fn zeroed(self) -> IoWrite + where + T: Zeroable, + { + self.set(pin_init::zeroed()) + } + + /// Turns this location into an [`IoWrite`] with the initial [`Default= `] value of `T`. + fn default(self) -> IoWrite + where + T: Default, + { + self.set(Default::default()) + } + + /// Turns this location into an [`IoWrite`] initialized from `0` and t= ransformed by `f`. + /// + /// This is a shortcut for `self.zeroed().update(f)`. + fn init(self, f: F) -> IoWrite + where + T: Zeroable, + F: FnOnce(T) -> T, + { + self.zeroed().update(f) + } + + /// Turns this location into an [`IoWrite`] initialized from `0` and t= ransformed by `f`. + /// + /// `f` is expected to return a [`Result`]. + /// + /// This is a shortcut for `self.zeroed().try_update(f)`. + fn try_init(self, f: F) -> Result, E> + where + T: Zeroable, + F: FnOnce(T) -> Result, + { + self.zeroed().try_update(f) + } + + /// Turns this location into an [`IoWrite`] initialized from [`Default= `] and transformed + /// by `f`. + /// + /// This is a shortcut for `self.default().update(f)`. + fn init_default(self, f: F) -> IoWrite + where + T: Default, + F: FnOnce(T) -> T, + { + self.default().update(f) + } + + /// Turns this location into an [`IoWrite`] initialized from [`Default= `] and transformed by + /// `f`. + /// + /// `f` is expected to return a [`Result`]. + /// + /// This is a shortcut for `self.default().try_update(f)`. + fn try_init_default(self, f: F) -> Result, E> + where + T: Default, + F: FnOnce(T) -> Result, + { + self.default().try_update(f) + } +} + +/// A pending I/O write operation, bundling a value with the [`IoLoc`] it = should be written to. +/// +/// Created by [`IoLoc::set`], [`IoLoc::zeroed`], [`IoLoc::default`], [`Io= Loc::init`], or +/// [`IoLoc::init_default`], and consumed by [`Io::write`] or [`Io::try_wr= ite`] to perform the +/// actual write. +/// +/// The value can be modified before writing using [`IoWrite::update`] or = [`IoWrite::try_update`], +/// enabling a builder pattern: +/// +/// ```ignore +/// io.write(REGISTER.init(|v| v.with_field(x))); +/// ``` +pub struct IoWrite +where + R: IoLoc, + T: Into, +{ + value: T, + loc: R, +} + +impl IoWrite +where + R: IoLoc, + T: Into, +{ + /// Transforms the value to be written by applying `f`, returning the = modified [`IoWrite`]. + #[inline(always)] + pub fn update(mut self, f: F) -> Self + where + F: FnOnce(T) -> T, + { + self.value =3D f(self.value); + + self + } + + /// Transforms the value to be written by applying `f`, returning the = modified [`IoWrite`] on + /// success. + #[inline(always)] + pub fn try_update(mut self, f: F) -> Result + where + F: FnOnce(T) -> Result, + { + self.value =3D f(self.value)?; + + Ok(self) + } +} + /// Types implementing this trait (e.g. MMIO BARs or PCI config regions) /// can perform I/O operations on regions of memory. /// @@ -406,6 +558,95 @@ fn write64(&self, value: u64, offset: usize) // SAFETY: `address` has been validated by `io_addr_assert`. unsafe { self.io_write(value, address) } } + + /// Generic fallible read with runtime bounds check. + #[inline(always)] + fn try_read(&self, r: R) -> Result + where + R: IoLoc, + T: Into, + Self: IoCapable, + { + let address =3D self.io_addr::(r.offset())?; + + // SAFETY: `address` has been validated by `io_addr`. + Ok(unsafe { self.io_read(address) }.into()) + } + + /// Generic fallible write with runtime bounds check. + #[inline(always)] + fn try_write(&self, op: IoWrite) -> Result + where + R: IoLoc, + T: Into, + Self: IoCapable, + { + let address =3D self.io_addr::(op.loc.offset())?; + + // SAFETY: `address` has been validated by `io_addr`. + unsafe { self.io_write(op.value.into(), address) }; + Ok(()) + } + + /// Generic fallible update with runtime bounds check. + /// + /// Caution: this does not perform any synchronization. Race condition= s can occur in case of + /// concurrent access. + #[inline(always)] + fn try_update(&self, r: R, f: F) -> Result + where + R: IoLoc, + T: Into, + Self: IoCapable, + F: FnOnce(T) -> T, + { + let v =3D self.try_read(r)?; + self.try_write(r.set(f(v))) + } + + /// Generic infallible read with compile-time bounds check. + #[inline(always)] + fn read(&self, r: R) -> T + where + R: IoLoc, + T: Into, + Self: IoKnownSize + IoCapable, + { + let address =3D self.io_addr_assert::(r.offset()); + + // SAFETY: `address` has been validated by `io_addr_assert`. + unsafe { self.io_read(address) }.into() + } + + /// Generic infallible write with compile-time bounds check. + #[inline(always)] + fn write(&self, op: IoWrite) + where + R: IoLoc, + T: Into, + Self: IoKnownSize + IoCapable, + { + let address =3D self.io_addr_assert::(op.loc.offset()); + + // SAFETY: `address` has been validated by `io_addr_assert`. + unsafe { self.io_write(op.value.into(), address) } + } + + /// Generic infallible update with compile-time bounds check. + /// + /// Caution: this does not perform any synchronization. Race condition= s can occur in case of + /// concurrent access. + #[inline(always)] + fn update(&self, r: R, f: F) + where + R: IoLoc, + T: Into, + Self: IoKnownSize + IoCapable + Sized, + F: FnOnce(T) -> T, + { + let v =3D self.read(r); + self.write(r.set(f(v))); + } } =20 /// Trait for types with a known size at compile time. --=20 2.53.0 From nobody Fri Apr 17 01:39:55 2026 Received: from SN4PR0501CU005.outbound.protection.outlook.com (mail-southcentralusazon11011025.outbound.protection.outlook.com [40.93.194.25]) (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 A479C3A0B3A; Tue, 24 Feb 2026 14:22:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.194.25 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942956; cv=fail; b=ElasQsRTCV0PfbFwM6tNkLIlOuPrVApFxDXkW+Dll/py981QXyeSwJfqpO+vpxXptDRbmQ1qV3IAQj4073mv1ditWyvvJHqqNjEvHCTLwlokQtq4NhdgzA2+YHejrl7uPdYhsrfPsdz+M885/XFtIwoz850sL1WAo1fWqH8/37g= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942956; c=relaxed/simple; bh=wGjhG/9RSyaTAXnnmpH7dJPCHyn3GhHAEbEOXTnjTJ4=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=KOqm9/Ip0qgYXiB8sjdvXvx0/wgTjYuruleE/2/megw8+ucDS9SJS7TWSgdJSj/lOM2CXiGro8307ZdYJ5U3umPtfjnB+A6S+qVXpqVCc0DxfX2qzKQAA1xU1gXafZ38Yuqxe6ic7RNrd7wFJfPlBK2zW3Jqmlda2ZJDvOXEfXQ= 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=RWg4JXaq; arc=fail smtp.client-ip=40.93.194.25 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="RWg4JXaq" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=kqNkHo1Gl75OiCT6WVmFrtSoH3Q+D2AaGptthNmcMvVZciq+o0/gmpHzchSoMbbt4WdFTNREn1CVXdZHnhReCCN4X1MGupXhG201Aji/BBv+iCr5zx8GoQDw5DftuzMuhSnelWcfEG0M+Q5HfmfLBz3ZCcYSdwHCw22V5M8SeTdjVJ030f7jacimeTlhz3BUJF8Z20KCvy0qiaH8lVj9n9WYO8MMrNVikTFeOhzXrdm+NiZZLwSLbTvggXvCHQg3CHTzkZ7pjdrXpywuTBpyDcbrLD4dvp0xYBd79vD2YHktLnKsrex1NJ1D1IFttUrY97CX4LCBOWtP9EYvl5dJbw== 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=KfZkMnUs5cw7NtIB0JmEB9QkrrltwWG90h5c5CiN8Vo=; b=D6QQcvB+RP4YCIZSUvIs60RPwZVmn30VIDuspVMVizo5jNgPBQQ8/B6WPfYgXZSjNoLbCZ1rqU4Ivef5xlDDYkJQB4ob1xc3I6sgKDvHgoYpaV447MjoMYJ8uxu4yfXEW6ptjNQNxN9Zwjit2sWP4hz3qK2aeG+E+zIc3bs2u1L0X6DC2Ir3MxcyM4aStRVNFW4HTUAKEb4NBwM19DFedLq8wcfWkIX51XeKba6FO5YuL4oqOXoMPrczrDmQ5j2naj/MV+A2kSNjSJDYcuu4Iw3073G+3+S8z5pmtbBU7PViVoqFF7iomiG7xFGFiUafaU6qDeXSKWm566PRJ74IpA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none 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=KfZkMnUs5cw7NtIB0JmEB9QkrrltwWG90h5c5CiN8Vo=; b=RWg4JXaqRo2vJp77fn6vOl/XQ422QtbSL5oIaCyI0Pk0loZ0Jtao8Z1yeSbSIYk4Hj2hVvCOEpwl+RE2zx89j6y+yVI+5ufjXT1k9e5hYpUTnKy42gVSFeAlYBOBOrI+Vv6Tci9Lv8KjETygihQe1DhDiGUebtwIVnjPFTUssVRwjAQmknmihfsJWd9BjwziipUnPrAMz2JHb4rLjLMgwgeKqLx0XyuCW0ZSiYvxXaLtmyzvHuQ9Oumjb9QMO1FgJoDF4MJw0LIkNYtjjoFGlE6rEfBbc4LovxPntnxaox1SrGJGmmfrZM7faOHlKCtvAccZgedQtZtMKQ+NCJqjyg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by SN7PR12MB7811.namprd12.prod.outlook.com (2603:10b6:806:34f::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 14:22:30 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%6]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 14:22:30 +0000 From: Alexandre Courbot Date: Tue, 24 Feb 2026 23:21:44 +0900 Subject: [PATCH v7 06/10] rust: io: use generic read/write accessors for primitive accesses Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260224-register-v7-6-aad44f760f33@nvidia.com> References: <20260224-register-v7-0-aad44f760f33@nvidia.com> In-Reply-To: <20260224-register-v7-0-aad44f760f33@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Boqun Feng Cc: Yury Norov , John Hubbard , Alistair Popple , Joel Fernandes , Timur Tabi , Edwin Peer , Eliot Courtney , Dirk Behme , Steven Price , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Courbot X-Mailer: b4 0.14.3 X-ClientProxiedBy: TYCP286CA0305.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:38b::16) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR12MB3990:EE_|SN7PR12MB7811:EE_ X-MS-Office365-Filtering-Correlation-Id: aaae5ce9-4c7b-4ed3-11f8-08de73b024be X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?bDduakxmMTNQb1NhSTFSbStkV3I4OWVBNVhCQTlQSUVvUW95L2ZraE9Nc0ND?= =?utf-8?B?MjdUNnUrbmx6QmVpdEdkMy9La1dSZUxLTjkyVmV0TjQvc0tuQ01iSnNwa2cz?= =?utf-8?B?Y3lua1R0alNITXIyTnFyYU1NOXZVWW9rdjRJS29jRCtwL2RicHdRdW5rRVdO?= =?utf-8?B?NGlyR3czUG9XTHJqQ0xCV1hCblpWL2VrclV5bEFJSjN6M2ZodWIxSjJqR2ZM?= =?utf-8?B?VDVnMGpzeGlSb2RCdzNyTGNUd3AzQUFuUk1Xa3h6dTc4OWNMMGt1S3VUUkg0?= =?utf-8?B?blNOV0ZMdTdIWHk0MTZsWnNORUcwN3ppK0t6TEh1bjlSVGY5WmlMdWtYUjVv?= =?utf-8?B?RnRRK0lYdnNYU2FhSWRNdVBMSE50M1RRMldVajNRVE5FcEd4OE9xZ2p0K1Bp?= =?utf-8?B?Qi96dGd6dzE4eE04U0dmOGtVWXFJTjhGNEVCR3JUM051YmE3MlZoWjVMbS8r?= =?utf-8?B?VkdKazNsTGVTZ2c3ZDJhUWNJamd0ejFDaStxbWdkeldYM3pxRkFCVk1WRkFO?= =?utf-8?B?SWJ1YjZVWkZURVdERmdYOXdyVUpIK3BwcXZ1SGg0QmRZaG9IOEl2bW5jVi9Y?= =?utf-8?B?UkVUdHZTSUQwTmo1MmxuMHpQc0k5T2ttRDl4MGc5T09KU1NwRURWZGFadTBC?= =?utf-8?B?UnZIamk4VE0ydmlub1BTc1RlS2xvV3pvWTk5dHNlbktNcE9UbGVkbjc1djg3?= =?utf-8?B?MmVDNmF5SDhzT2pLQ0JZTXo3cWhkODEzVmE0T0YyYkZKUVkvNG9jaGxEMDVk?= =?utf-8?B?aTNXUDJQVDVtUDU3QjVpcGdGYXB6YWg3THRpODhVL3lKTjc0WjdQMUQ5NW45?= =?utf-8?B?bjNPYklKWjBTem5aZEwyWkg3S1NrVERQZFBJVTREMkVTMzc2WTBoZlhiRzhV?= =?utf-8?B?dlRlbkNoNVA5UEZEeDM0UUthQ3dFSjhiWStsa2Q2MnFYcWlnWEtrV3czL2pL?= =?utf-8?B?Rm5uT3hDMStpN1FvSkRWRWJpc0Z0c3B3NGtSN2tyQ25YNFlkLzJNa2g5VlNP?= =?utf-8?B?eUxvdyt1Z212dHV5N2FuaE5mYnNVdUZaQ1JFaWZHTmFrTXRWT2lDVUF2V1R6?= =?utf-8?B?c0FDUHNMUlpzTDFtVlVlejlrYnFCMzRRWWc0aTdmenBRVkQ1RFkzK2dJUzFt?= =?utf-8?B?WWVsMjE1Q0JwTlo0OHMvRGZGZGZVWU5yQWdmLzNUM2ZkK29iYUhVaWJJRDRa?= =?utf-8?B?RU1rc2hnam10NUpEYXpvRk5lTkx2MThNeEFQdHRhenhpdXhzMFJFNmpHU25O?= =?utf-8?B?dXBZaVdTYU5TZUt3RlczL2M3clZNQkJrYlNCMFdtemlneTkvMzROSkNKWkpt?= =?utf-8?B?ck9HQmRmZlU4S243UVNNSGpabWZsRzN3YTZhQmFkOUJHNXh4YkNKQVU5SUxW?= =?utf-8?B?ZjlKajlsTzJtQjJFd20zeFNoZTBuV3RMVUdwSW8wY1dzeStDcUJ5YlYxeUsr?= =?utf-8?B?RWE2L2R2WDNad3RRQ0ExWDQyR0VKcUh6NFF2dEN2QytRUm5Mb0duUVBHNmQz?= =?utf-8?B?U3MzT3JwQW41cUptU1BqTytVeDRTaG1KaDVwVjU3dnVFNjZHVWRQaVBqZnBL?= =?utf-8?B?OGd3MU42RTZJTjliYnRYbnhhRXNMZVB2S1IzU05KSFpqNHFmWStRWEVkZWZi?= =?utf-8?B?VXh5ajlPcGhiK2FaUWU4a1JmSk5XYTlvMkRJZkhMc0VmeFVCVE5GV1duYUp4?= =?utf-8?B?bFZKb1NiUm9ZY1NMZWFNenozdS9VbFBvNnArejNDV3I3akRtTFdvRmdYclBR?= =?utf-8?B?L3FzRjZJcUJLdStQQ3FBb1RXY0RPUFFaVGtFdndMcGJ2ajdvM3JQeDBqYzZR?= =?utf-8?B?SkNSQTJ6TUNsZDF5Wjg5bGFPdTBsd3ZBRHlnSDJRZ3JNK0lKOFFJQytpb1R1?= =?utf-8?B?ejFIUGtaL0tldXVIS3FxejJzZjhGS0lwclZ4S2ROT1NuaVQvY2xnNmIraGx4?= =?utf-8?B?dU1RY2dJcUhjTTlGYVByTkpuTFdmSjZtOVUvUVJKQTcybFY2a3RBTEMvVDJN?= =?utf-8?B?RXYranpodUNHemp4YUFLQ0t2NlErb0JrTnIxaTRhSEtudVpYQTdCS0dvTkd1?= =?utf-8?B?OC92L09wc09mTjYzRmhWUjNEWTI4TUpCTDhrNjlSeE5uVjRjRGp1Z2VtcGNr?= =?utf-8?B?aU5iS3hVaDhRMTV6V25VUGh5YVkvOFJQZzQ2MkVWNlI4WjRSN3A1cGRRV0ht?= =?utf-8?B?Y0E9PQ==?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?VWc2TXVKRWF4aTFsanF6YmhHdTRKSEhMZld2T3pMeUlDMXpDZDBibVJQY2VE?= =?utf-8?B?ZHZIdktOK3lmMmR3c1FaMnBNSE5OUGlyQmVVZXU2aGdDeDIxNmVtaWxiem5C?= =?utf-8?B?bWlOWUVHU3M0YmtxVmRpK0QyQzdkbTlZKzl3cjR4eEVDcWdDODVhZitTbzlG?= =?utf-8?B?SGcwMXY1ZjFjUHgzTEFySnJydnJoV29yVjV1NEZZVEZYRmVpNEx5azgyT2Fn?= =?utf-8?B?OFZnM0hYRjcwRlJERGs5UWczTy9CZ2FOQkJ5cHFycXBUeXU3L2Q4blFlLzdQ?= =?utf-8?B?ZFlwdFJZVm05K3Ztc0tDSmhKRURSOXZ1V3c5ZHBCeHUzSE8valVvT0ZUSlVh?= =?utf-8?B?YnRMOU9sNTFpK2xnQkhIaUJ1Y1VGRVNmNk4wRkI1MWhEbURRYjlTV1JWN1NG?= =?utf-8?B?YXI5S0R5WmhCZjF5ZDZWeTlFdmROQUFobWtEcUVFZmNKV3JFSW9QV3J5T3Yy?= =?utf-8?B?NDk4akFmS1VXZFpFQjN2R1JHKzJMZ2J6TFdoSktFaERZa1VQRXFDWlAzaW82?= =?utf-8?B?WFpncXI4SjNTdkQ3UWdWT05taGRWQktGMnhNekJncWxMd0p0enZqVHFJUGx5?= =?utf-8?B?Y1B6TVVNNytYQk1hUFA2YjlqakpVR1VFZFdjb3F2WmN1cEdkaVR6MjBnMFNn?= =?utf-8?B?K3duc0ZhcUpPVEphZWZ6Y0xaZDNZTlg1VU5aeWpQWkwxNnVlTEVTM3grUWF0?= =?utf-8?B?Wlkzbmp0UWJWWlNPUEdVWWxadEQ0R0NUR1Z4alpTSW91QWRIeVdNWmxNVExJ?= =?utf-8?B?VTZUM2V2NW9zVVNTZnV3WGxWazl2WnRhSjhQaVMzOFA2VVczZW5MNUg3VmR6?= =?utf-8?B?OHdpNjdYYVh2Z1RSdlBSZDB6TkdudE5WNG5FWW9waXZwV1B1U2E3MTM5YndM?= =?utf-8?B?SXdqcEQyU1BCMkFtQUtBS3V4Tyt4Yld4STFTZVpzMmlKYjd5T0ZySnhJcTBU?= =?utf-8?B?MWdCdENWOEw4SmNPRTBsU2pWZzZrOGEvZHRFUlhjZFBOYmJmYnN4V2JuU0NF?= =?utf-8?B?cHpxRnFIQzg5MGxIalAxYW1uQ2l0NWdOMm9aaTBoL2d2b3FPWEJiVGR4VCtm?= =?utf-8?B?ZTNFK0FIY2s0a283SzhWbnhBcWRSaFZodGVHZlhwVlhXWmxRaXQrNGp6OCtn?= =?utf-8?B?dEZ3aHFLY3E0RWZSQ2hRZ0xGcWlzRFN5bW9DQkMrNDFMc2RXVUNGREdzYm82?= =?utf-8?B?UTJZQVczdHRreHdySGNDVmVqZlNJV2xPS2MyUlJpeDNybWFMc2s3bzZzYVg0?= =?utf-8?B?NVdMNWh1aGx5S1BtS0RBam9HbDZqQU5HTFN3Rmd6NnE1TlAwZXhJTW1NbG1k?= =?utf-8?B?aW5GZ2RxRFd3WTMwTk1LUG0xTU9EdVY0czJwK1VDTHRsUGtlVDVrVllVKzA2?= =?utf-8?B?WUpZV0cwcmkycytWdzc4QW9jUVV0VGVDY3RpOVF4T1RrNFBuNmoxR3F3dDM3?= =?utf-8?B?M095OTJXVmJtSXhkMWltNGlhTWJQRWg5T2NveW5oTHYzY3ducmoyZkpuTjd6?= =?utf-8?B?U2hWaGE2M25jWTA2WURTQlc5SmVnWStVN1Nic0Z1WEI5UXhRUzV6WENnbDBk?= =?utf-8?B?eGp3YVZTaUt6b2Z1a0dBUTNCNjcyN3pGcVA3WmFzQzNyc0lzWTlZWUdWQWZM?= =?utf-8?B?WTF0UFNad2M0c3NaK2hVdFB5QjFqWUlSQjlNRnJIUDNxYVB5UjJXdXVGVXhM?= =?utf-8?B?MVFDcy9zRGM0U2F5SFhuQ3pZb05rckJVeTRjM3FUUEhoeEp1bVAyNDU0c2E3?= =?utf-8?B?NGZHZXNmRWZibzRLZG1ERForRnNnSGlJbkNjRkt0d3p1NjlaWm1TVDJkOUdY?= =?utf-8?B?RERROW1qUmdTeGh4NVZ6QXRQRDBWMUxKZzZWTXZ4bmU3RHZJeHVyeUo1dm16?= =?utf-8?B?Z0tYY0RDcWIvMWxNd2JXMlRoS3g3YVhmVmZlNTFSTUdPajNSbWpPMSs4YWlG?= =?utf-8?B?S1ErVU5FUFh0dW5nd2dlWWhEeVhYT1gwQVAwVFpYcUFCS2EzZG1aZDB4SmtF?= =?utf-8?B?RG9NVXA1UGxuVEhVZWVHMnR5YmVaZzVSc0s5eE8vc1V3dktPcVp2b011TUFG?= =?utf-8?B?RWwweFNhQjNleUVqWFJNU0VnMlJaYXhWY3dIcWVmSE04c0IxdEo4bHJocFdv?= =?utf-8?B?eXJKbGlaRkM4akhuV0Z5NTNkZnlEb2FiUk14KytsZlE5ZmFiZGxyOTZvbkZn?= =?utf-8?B?QVhFYW9pbk95Q0Q5NGhrSW93R2VadXY1V3BTdE5HMk1GcllHQjQycEpUVE5a?= =?utf-8?B?YnhPbXo5OFZGbkVkM29QcVZzSHBJUXNUUGR0K1dIK1lETER1TVJjM0NxM1I5?= =?utf-8?B?aVdQY3pIQzhCL2dGYzZnYXAxaHlvQmdNWGlLb1c1YW1RcnlrN0VlK1RRSUk2?= =?utf-8?Q?30S9OWOGp7F8ecADA89RkK9q5ISOCyiV+c0XOPJwpuit0?= X-MS-Exchange-AntiSpam-MessageData-1: PBAtvVDEKkYC4w== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: aaae5ce9-4c7b-4ed3-11f8-08de73b024be X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 14:22:30.2298 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: aArpMCrzG2vEP6B/4BJMejoGDL8sremlfLVWAPu6/JRyKsPXr3VdVBHHVQDsISqmEvxTaURGVlFw91vDys+Bqg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7811 By providing the required `IoLoc` implementations on `usize`, we can leverage the generic accessors and reduce the number of unsafe blocks in the module. Signed-off-by: Alexandre Courbot Tested-by: Dirk Behme --- rust/kernel/io.rs | 103 +++++++++++++++++++-------------------------------= ---- 1 file changed, 35 insertions(+), 68 deletions(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index fdd2549d8e13..256eba16ccc8 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -275,6 +275,25 @@ fn try_init_default(self, f: F) -> Result, E> } } =20 +/// Implements [`IoLoc<$ty>`] for [`usize`], allowing to use `usize` as a = parameter of +/// [`Io::read`] and [`Io::write`]. +macro_rules! impl_usize_ioloc { + ($($ty:ty),*) =3D> { + $( + impl IoLoc<$ty> for usize { + type IoType =3D $ty; + + fn offset(self) -> usize { + self + } + } + )* + } +} + +// Provide the ability to read any primitive type from a [`usize`]. +impl_usize_ioloc!(u8, u16, u32, u64); + /// A pending I/O write operation, bundling a value with the [`IoLoc`] it = should be written to. /// /// Created by [`IoLoc::set`], [`IoLoc::zeroed`], [`IoLoc::default`], [`Io= Loc::init`], or @@ -369,10 +388,7 @@ fn try_read8(&self, offset: usize) -> Result where Self: IoCapable, { - let address =3D self.io_addr::(offset)?; - - // SAFETY: `address` has been validated by `io_addr`. - Ok(unsafe { self.io_read(address) }) + self.try_read(offset) } =20 /// Fallible 16-bit read with runtime bounds check. @@ -381,10 +397,7 @@ fn try_read16(&self, offset: usize) -> Result where Self: IoCapable, { - let address =3D self.io_addr::(offset)?; - - // SAFETY: `address` has been validated by `io_addr`. - Ok(unsafe { self.io_read(address) }) + self.try_read(offset) } =20 /// Fallible 32-bit read with runtime bounds check. @@ -393,10 +406,7 @@ fn try_read32(&self, offset: usize) -> Result where Self: IoCapable, { - let address =3D self.io_addr::(offset)?; - - // SAFETY: `address` has been validated by `io_addr`. - Ok(unsafe { self.io_read(address) }) + self.try_read(offset) } =20 /// Fallible 64-bit read with runtime bounds check. @@ -405,10 +415,7 @@ fn try_read64(&self, offset: usize) -> Result where Self: IoCapable, { - let address =3D self.io_addr::(offset)?; - - // SAFETY: `address` has been validated by `io_addr`. - Ok(unsafe { self.io_read(address) }) + self.try_read(offset) } =20 /// Fallible 8-bit write with runtime bounds check. @@ -417,11 +424,7 @@ fn try_write8(&self, value: u8, offset: usize) -> Resu= lt where Self: IoCapable, { - let address =3D self.io_addr::(offset)?; - - // SAFETY: `address` has been validated by `io_addr`. - unsafe { self.io_write(value, address) }; - Ok(()) + self.try_write(offset.set(value)) } =20 /// Fallible 16-bit write with runtime bounds check. @@ -430,11 +433,7 @@ fn try_write16(&self, value: u16, offset: usize) -> Re= sult where Self: IoCapable, { - let address =3D self.io_addr::(offset)?; - - // SAFETY: `address` has been validated by `io_addr`. - unsafe { self.io_write(value, address) }; - Ok(()) + self.try_write(offset.set(value)) } =20 /// Fallible 32-bit write with runtime bounds check. @@ -443,11 +442,7 @@ fn try_write32(&self, value: u32, offset: usize) -> Re= sult where Self: IoCapable, { - let address =3D self.io_addr::(offset)?; - - // SAFETY: `address` has been validated by `io_addr`. - unsafe { self.io_write(value, address) }; - Ok(()) + self.try_write(offset.set(value)) } =20 /// Fallible 64-bit write with runtime bounds check. @@ -456,11 +451,7 @@ fn try_write64(&self, value: u64, offset: usize) -> Re= sult where Self: IoCapable, { - let address =3D self.io_addr::(offset)?; - - // SAFETY: `address` has been validated by `io_addr`. - unsafe { self.io_write(value, address) }; - Ok(()) + self.try_write(offset.set(value)) } =20 /// Infallible 8-bit read with compile-time bounds check. @@ -469,10 +460,7 @@ fn read8(&self, offset: usize) -> u8 where Self: IoKnownSize + IoCapable, { - let address =3D self.io_addr_assert::(offset); - - // SAFETY: `address` has been validated by `io_addr_assert`. - unsafe { self.io_read(address) } + self.read(offset) } =20 /// Infallible 16-bit read with compile-time bounds check. @@ -481,10 +469,7 @@ fn read16(&self, offset: usize) -> u16 where Self: IoKnownSize + IoCapable, { - let address =3D self.io_addr_assert::(offset); - - // SAFETY: `address` has been validated by `io_addr_assert`. - unsafe { self.io_read(address) } + self.read(offset) } =20 /// Infallible 32-bit read with compile-time bounds check. @@ -493,10 +478,7 @@ fn read32(&self, offset: usize) -> u32 where Self: IoKnownSize + IoCapable, { - let address =3D self.io_addr_assert::(offset); - - // SAFETY: `address` has been validated by `io_addr_assert`. - unsafe { self.io_read(address) } + self.read(offset) } =20 /// Infallible 64-bit read with compile-time bounds check. @@ -505,10 +487,7 @@ fn read64(&self, offset: usize) -> u64 where Self: IoKnownSize + IoCapable, { - let address =3D self.io_addr_assert::(offset); - - // SAFETY: `address` has been validated by `io_addr_assert`. - unsafe { self.io_read(address) } + self.read(offset) } =20 /// Infallible 8-bit write with compile-time bounds check. @@ -517,10 +496,7 @@ fn write8(&self, value: u8, offset: usize) where Self: IoKnownSize + IoCapable, { - let address =3D self.io_addr_assert::(offset); - - // SAFETY: `address` has been validated by `io_addr_assert`. - unsafe { self.io_write(value, address) } + self.write(offset.set(value)) } =20 /// Infallible 16-bit write with compile-time bounds check. @@ -529,10 +505,7 @@ fn write16(&self, value: u16, offset: usize) where Self: IoKnownSize + IoCapable, { - let address =3D self.io_addr_assert::(offset); - - // SAFETY: `address` has been validated by `io_addr_assert`. - unsafe { self.io_write(value, address) } + self.write(offset.set(value)) } =20 /// Infallible 32-bit write with compile-time bounds check. @@ -541,10 +514,7 @@ fn write32(&self, value: u32, offset: usize) where Self: IoKnownSize + IoCapable, { - let address =3D self.io_addr_assert::(offset); - - // SAFETY: `address` has been validated by `io_addr_assert`. - unsafe { self.io_write(value, address) } + self.write(offset.set(value)) } =20 /// Infallible 64-bit write with compile-time bounds check. @@ -553,10 +523,7 @@ fn write64(&self, value: u64, offset: usize) where Self: IoKnownSize + IoCapable, { - let address =3D self.io_addr_assert::(offset); - - // SAFETY: `address` has been validated by `io_addr_assert`. - unsafe { self.io_write(value, address) } + self.write(offset.set(value)) } =20 /// Generic fallible read with runtime bounds check. --=20 2.53.0 From nobody Fri Apr 17 01:39:55 2026 Received: from SN4PR0501CU005.outbound.protection.outlook.com (mail-southcentralusazon11011057.outbound.protection.outlook.com [40.93.194.57]) (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 E158F3A0B29; Tue, 24 Feb 2026 14:22:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.194.57 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942968; cv=fail; b=tW1RuW8AU4TSuv/5wq7Vz+m0q5PpLNYlTTmgtiFhE9Los7IoFgjhzYz/7qTuivzAI/+wK1hGVE6bBHb5w4hBmlj/k84En9gb6EM/eRpLwEMkDDXI0n4GTtkYuCPKBPgcr3u8xvY+5xya7+PLzbHKrhyZqb8JU7fma3DOastdKSs= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942968; c=relaxed/simple; bh=1t41KhOGMrCuvNQzZPYAxm6BbF/tPWND49QvJ9YbdwQ=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=V9ebGiW0/EjGM9kbnJGk6x6iVu9f9uLye5LJfIlVa1K5NfiShNOOT9Xv1I5hDrUmf4qUxyXOjgo8XNDmHfOz31LHFcD02oD/lMqLkbkqD5gxpOjSa2w35iBq8vMEeNZwBq/vpjMcoT+FKPNj20CsecpQzAIu00zXk2Q1LupeMHk= 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=NmJnkheI; arc=fail smtp.client-ip=40.93.194.57 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="NmJnkheI" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=n8Rt1NaxzoTEUsO19fv60ShP0QbCJf9rjYQegzqymXPCy6RtS62+224WbZnPb7EPIH7j3NqQHUVvh+XttUZbcY4TuQP+k7/8R6WPnKfh3HIjapUoZDer8rxw0OYqOZowxGDbLzNBeFmKMNM8HXJLcQTbLh//QLjJWN22xDhBkoxJYShYMmiqptXeWXdCbtcasrDNWnUpIC5MGeHtDH86fC2TKdrnYC4orhwHTTgH8pwwedGWKMqwJj+QhAOOBzcu3CswcsBRnsszF2GY0FM5GnIqFph7c2WRSzhAzZ946qUK3GcrtgVElAX78UjzuyHzAGBWCZg1wYCtis40O+68hQ== 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=crjP7qZHploSN/6qwQRhwleK98enPPXENR8gQor8DP8=; b=jMqHEWxrlV1qa19TrnPzQerW+nSZEJ1zImCIv3YmF1F6yzBpJ3ziV/Lk+pB+uZq133kDLAFPhSW3uC3tlRsSlVWCvm69DxxE/DQtEtGY83+71rMf3T9Ojz85DTLxmWuNW7eqLmnNPqqeGDTwF0d7XMK7z3Q/OjypGsrTBw68FjQKJOS6MVWhwGJDg+pQZ6yugP5JMss7MODpen2vX1Dq5pm7lkR76bwcMaHPDyu1X8TsIE6UBibOg6P7hN6HNrj27kAWIZjp8fJrmZOQgd1DOcnx9IKA7KKinQasc1T6krd7iopjrXkQiwAAJ28VKdUqFG6mAyVYYF/A+TApktnaGg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none 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=crjP7qZHploSN/6qwQRhwleK98enPPXENR8gQor8DP8=; b=NmJnkheIUb/g48cdzPtfjARVQBEiq/NHaF/GtTKs+1gqcZRpHQpn7Cj3038dW5QMKCShBR4h9Of+xWlib1IfD0d1DIcixkNKvgXSomqqqmphVw0BAoQGSPgl6Rzid9lKnsiWdy6VsYyikYxcIANqVXqcRGivGBw45oNcwRrWSlwlN9cfbrhvUYKALfpNH/y5kQ7QDb26n50Ihf9hWqZYck8Mu/53h91geMWXWzKkb+/LOtWVnuvpdnLidEbYLN8DXUv42aMCk2yZDhJx9mKfp8UpaBk2WBICrBlyJg71TAz86l5z5cqJRhhNKDF+zMVr2QxXUaDa0dztLnaqJUl3Ag== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by SN7PR12MB7811.namprd12.prod.outlook.com (2603:10b6:806:34f::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 14:22:34 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%6]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 14:22:34 +0000 From: Alexandre Courbot Date: Tue, 24 Feb 2026 23:21:45 +0900 Subject: [PATCH v7 07/10] rust: io: add `register!` macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260224-register-v7-7-aad44f760f33@nvidia.com> References: <20260224-register-v7-0-aad44f760f33@nvidia.com> In-Reply-To: <20260224-register-v7-0-aad44f760f33@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Boqun Feng Cc: Yury Norov , John Hubbard , Alistair Popple , Joel Fernandes , Timur Tabi , Edwin Peer , Eliot Courtney , Dirk Behme , Steven Price , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Courbot X-Mailer: b4 0.14.3 X-ClientProxiedBy: TYCP286CA0162.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:383::17) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR12MB3990:EE_|SN7PR12MB7811:EE_ X-MS-Office365-Filtering-Correlation-Id: fa5197bd-3af9-481e-c646-08de73b026fb X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|7416014|376014|921020|7053199007; X-Microsoft-Antispam-Message-Info: =?utf-8?B?dmpYMVo2N1hHSmhFeUVLcVBtV3BBSzNnNnYvdDhWdzNGQmZ3bm9TYkpLTnBV?= =?utf-8?B?bHgzcjlIcXBxTmdwZUxlL1BMWlMzbHAwcFc5MXFzVnFoeWZIcm5iMTBlYTA1?= =?utf-8?B?dzhIK3RXYjFYdm5BaSs3bFF2N0x0dUkvL0VPTFovQnVoWWVocW1Nbk1EUENB?= =?utf-8?B?dnhYbEtlbkViTmxDQVhFVU8rY043NUthRzFzOVpTb0dLT2tieVBNNHVabVh3?= =?utf-8?B?Sk5lU0YyOUdkN2F4elg0azBJeE5zSS9rSExKZnltUm0zOXJsWUdwZnJqaDFC?= =?utf-8?B?aVRiYXduNEt5Qk5lOFRHQ3FxZ1Awem9DdGovamhpSnRWR0V1NVlydUd2V2hI?= =?utf-8?B?ZS81OGhHSDVsMVJsaGZUZDA5N2tHdXdWSVZxVHB6RnArVjBVQVlvUzFVb2hW?= =?utf-8?B?MmFaWTNqa1BIdlNsM3kvNXlYbUlmQm5SQ21ubHI0TDQrTFNwdU94dmdVd0Jj?= =?utf-8?B?VXNhUCthSGc5eUZYTnY1c29qL2FkWkRBSE9sYUprZ0dPdkxJOHdUOXkwL3FZ?= =?utf-8?B?SXhFQWM2YUVoNlpiNUZOK1hvZklHZmFoNzFqRGFwdWNudnBxMHFLa0VvZlND?= =?utf-8?B?UWlSNy9waUljRVUrYW1neHFPNTJ5OHhJN0x0L0wra2s2UW53K1Bja0VybW83?= =?utf-8?B?MmxjMEJRWGhpSmxxMVY5WnBLN1A0RzJ4SDdmK2dhUHMyTHI4ZFNobEUxZ2Vp?= =?utf-8?B?WUpBVmpWR1VhWUNjWCtPMGRKdzdDWlg0aEt0YVFZMU4yTC9rcVZ6ZW80QVVE?= =?utf-8?B?MU5jZU5PY0dmeER5bmJvYXZuVzRHSTZQWjVEK3dTN3dKSDBuTXBGYnFHMmpo?= =?utf-8?B?SXovS0pBbW5hT0tnR0ljQk9mV1VQK1k3K1FlcW5pVi90eThyaDB5T0Y5aDl1?= =?utf-8?B?Z0RhemR4SGQyajZLN3N5eUlITjhzdHhEb093U2FKNTlZMkZpajlkTk42bWMr?= =?utf-8?B?NFFXbTFUSG1EWkFhM09sWHJxVDFwVVVkbVM4Uk4xVHVES0ZXMDAvUXhaREhR?= =?utf-8?B?RDJkT1ZTOGhjVjBXbENNNTdQdmdBcmVQUWZoTjU2dDQ0bEFIall1VXdNNVBL?= =?utf-8?B?UFp4WERWMzlDL0pzMzdWUTM3cFVMYWw3YkFnOFNkcDMwUEloRUsxRVNHZ3k1?= =?utf-8?B?Q09ZcGtWb2szbFZueGxYc1k1UFpUWFI2ZGkrN2pvbzlBZjlKMHNvaHltTkdx?= =?utf-8?B?Q0JyV0NOM2tZRmN6TlF4SjIwVVBNZWdIM1dpK3M2MFRudnZiNGNWcUZEZlA1?= =?utf-8?B?TS95UWZNWjZ3TTc5QzgxOFVhZlF1eGlpL3l0bE9tWlRlMmM4R29TWUZNdlZk?= =?utf-8?B?ZnFNYVJyb0l6MHdDcGZWbWNDRWJjd2psVHg3NklKSlJmaCtsbTg2KyttM29S?= =?utf-8?B?V0QrQTdCRmdDSElHWmtCSXJqbmdkWCtEc3RLdWkvZ09jWFRZWVhMRlpvZ2du?= =?utf-8?B?U2hXK3libGpLdGNzbG91OG5ZaDI2WCtsZDNJMzRFN1NrNmVtSlFVbTU3cHhS?= =?utf-8?B?ZFVGckw0ZnlYSTRCNndkZk40ZVd0ZW5ha1N5cjJia09seXlaMGVWTndZTDkv?= =?utf-8?B?MEdWUUZuKy8vL2RqREljL2xUdWUvNW53N0FuZkRydWtiQi9nWjUzYmFQcGdn?= =?utf-8?B?ZXVJMnp1T2JGMVZtb3lXbE9JTjRGUndvc25qYzl0U3RNcDFMVlFFVFlvTUda?= =?utf-8?B?YzFRMi9KczFxWUhYeVBWUE8xNGpTL0ZpeHBUbEdmaU9xYnA5MUxGVmVGK3J6?= =?utf-8?B?SkFndE1VWk9EZHgyeitWeGxoc0kwVHFuakRxUE1LT0kzSUlvQldHTzBYdnJ2?= =?utf-8?B?bHJGeC9BVENKVDBpRnd0KytaWE1XV0JtcWJLREdVVzZ3em9qci94anpzbDlz?= =?utf-8?B?MXlRNDFLYmZWRVEyVU1wMHdrTW1qckJEemxsaENQMDVMR2gzUlZ1emhKcXdQ?= =?utf-8?B?WmpjOFM0NjlaeitSM08wdGZWd1pWSkZDRlZ2SWJWM3krTmRoTWtNc01YV1ZN?= =?utf-8?B?YXp3YmVxS0Q5ZkVvcW4rcEo3Q0l2YSs2TzNyQVFWbTFVcDM0MWdEMitpcWti?= =?utf-8?B?OEV6dkhNQlhZcS80TU1aNGVMVG81MWJpMTVGYWtsektJeTJITUlzUk1wWG14?= =?utf-8?B?MHpTUmg2dzY1cVhJT2VqOEFjdlJBdTIzajFLZHZuMFUvUFVsL0ZTVUlMaVZ0?= =?utf-8?Q?CHg4Ehh/wTxhzV6takaX/3I=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(7416014)(376014)(921020)(7053199007);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?cTJ1dXdlb0FWK2dRSWV4UFJ0eUxBUVUrR1I0dnJxVWlUQVJSZXlZLytiWnNF?= =?utf-8?B?am5zZG8vS3hNOXF6dS9ZbWJUQVk5Y0xlNVNESXMyeHoyaThYb1hUcVRkWjFZ?= =?utf-8?B?czJ5S3R3eWpXRjBtRHVBdUZkMjJUL1QwdWlqR1hBYkdNdEdENk1ySi9iK1p4?= =?utf-8?B?Rmg0bHJlQUFUOEpLWXFlVWZoZjZBL3FBUVJnYmk0ZnNRc3VrSXlrZHliVTBQ?= =?utf-8?B?SGFsMHZYRGloNGU5UW11YUxKbUpUSEJUeDBadE92UzJhV1hQbElBc01YQWhW?= =?utf-8?B?NlduZEk2dHVubXk4OGxsa3ZNd2tQTE9KejRQQ3pZeFlGS1A3WUhRb1JiREVY?= =?utf-8?B?dW1CZWZ3ZlhBc1VCQnhsVHp0cDhaWWtLSGFrbk55c1FtRXpQRHRFTHJ5SFh0?= =?utf-8?B?TXlZWWFOWFYzMkJRWWZPSFhHc0ZCbVpGSWtBVnJ5ajdlMy9nR00vZ2lFOEtC?= =?utf-8?B?Mnl1ZTQ4bTd0TnVQQUorekZCY3pWK0F5WitMK1hCOGNhZ0MrTWVudW1Vck1l?= =?utf-8?B?aXByaHg2TDRVc2R0REppUlk1bVRCMk1GV0VQcGZON3dBS3dwdmRIckxQbWU0?= =?utf-8?B?eGZiSk9EZUZWTzBGd1FDdFhoUExNWDZVSElISUd5cXgyNjNZM0dNTm5uckha?= =?utf-8?B?R0wvWTMvVTBTS3JaN0VlL21XdGVTN2hQMlUvYS9PUXZPN3F1dmdvQnhjd1Vt?= =?utf-8?B?MmM4cExjWEQxTkNwM2NXaWZjTC8wM0I2UDRVNEFxOWVsbkFrL2ZQaEo3TFBv?= =?utf-8?B?RXRGdjF2cFg1c2JVWjBxMVlGMDVRVStDdGFaT1BqYUxRVU5jcWVpT0tlUTJK?= =?utf-8?B?TW1DSkRVT0xTdG10QTBYbWZmOWZhalorWGtyNldYVU5PMWNpaVY5dm1vZTVq?= =?utf-8?B?dzJmaXdSK1IxVUx6Mi9WV1VxQTNWOEtnV1czWHBBU1V6REJrT0p6ckRsUTR5?= =?utf-8?B?VHFCbDA2ZFN4SVBRTlhEUjZWN1dUNGJtdW9BcnlJOENNaHo0Z0piemtWK3hL?= =?utf-8?B?SG1BQkRONnRKdDBTZ0dWUXhnM01heFVVYzVnR1E4VXMxWWk2NDNKai9KKzVs?= =?utf-8?B?eDZJdXVneE5QbXBSc29HSWl6UEpsSXhwK2ZjNlVSUDRHd2M0T2NDbzNBUFV4?= =?utf-8?B?bHF2SkloYjNxNmZLN2F3dWhpaHlySmMzK0lyczNqMWduUzZPVkZFdHpIYzVl?= =?utf-8?B?VURFTi9pQUk4YzEvWkpVWnNmZXFQRStpNFJxTlZnek0wZUozT01qb0dRdjY0?= =?utf-8?B?THlsM2JjelMxRVdDdmJHNUtvaHdoemY4M2x5MTdKaEJQQ2c2Tzk5VWJhb0Y2?= =?utf-8?B?VGR1VnAyeHVHalFjZS84Mk9HWVpBdlF2Y09MYlBXWkM1SSt0cXFjdHEzajhZ?= =?utf-8?B?N3ZIWFBaOExmZVdocVNLSVRMT3BoNzZrK2h1U1V0RjVZRHdIZjNHd0J5dnJX?= =?utf-8?B?L2thV2VZeDBMZ21LY2NLanJyNTdxK3RlRGFBSjMxWG15RnAzSjdSY3dsbGZU?= =?utf-8?B?cVpVWUlqNXRwOThHRy9lTDQ2aUJib3U4NDI5bllSdFdpRVhvR1F5bjZ4ZkFP?= =?utf-8?B?NGlXQ1pMOXh3d3N6UlZ4cHVOWVVCRVpjL1orcDQ1aGlQck9MOCswNTluTDJz?= =?utf-8?B?KzY5SHdtQlh0MFJsOGZKZForYWxqMEluRGRoUXNtanowZWlKTmViZGZRNGtO?= =?utf-8?B?WWRWYTFFMktzOVQvZVFxL0pCQ3lNTUdxeS95TEdwVTJuYzQ3S2pJRTRKOFBx?= =?utf-8?B?dG5FbzJJeVplVjdwU3drdnFBVjRiVGhOcngycE5yTFpVL2M2T29YRXFOMUNK?= =?utf-8?B?MTFONGlVSlFGY0tJSlhkdVdKQ0VsaFM1Ly8xYi9uSmhPYi9hUjZreEIrN3Rp?= =?utf-8?B?UHJkU1FYSXNRT0dsMTBOSFpzamkvQXNlTXZMVjRKK3lPUlNtdS9DaVhlUm1n?= =?utf-8?B?R0lDN0tscjlxVnJDOWE0QWVDQXA3c0FLZ0d6N0tXOVc5OHFmQS9mZ0t6M3BY?= =?utf-8?B?NjNRZVBpTVVWeXJlTTZyTmQ3YXFSNWtSQ0V2RExvK2lwUXVMNkdzMXU1RlpH?= =?utf-8?B?QTZadU5rT0dLaVNrRU0rMjYxaDArT2plQ2h0bm5yUUpqbXB1TFJ5T2ozZ3Nj?= =?utf-8?B?cEhhVDljMkNSanY3dkVhZ3JOSS9wSjEyQTBhTGFLaGpkNkNveDFNUVFmNDh1?= =?utf-8?B?OSttOG44TmF2R0J1Q0J0dGN4dVRYZDZxNnVUZ2RVczBOb0ZydDhTNnR1QWxC?= =?utf-8?B?R2tzQ1oyOE9KWStiYys1S0drWU53THI1a3ZpWVNSbHRXZjZpNFN3QTBsSE5L?= =?utf-8?B?ZnZUc0RPM0xiZ3A3Y3dMSGc3SXQrdDNXS0huMlc2eC8yQ3dvSTM3UU5YWFFF?= =?utf-8?Q?yWu4dajw3eHQ4s/Zz8nxGUBcgC13qtYTbIUnvk+IlSk6W?= X-MS-Exchange-AntiSpam-MessageData-1: eiucoW7XfsDPig== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: fa5197bd-3af9-481e-c646-08de73b026fb X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 14:22:34.1783 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: /10xs/iHgCGOgq6xquVbZ0rZJiZcpd5bn92qO3A3LhA7JoZF8jPoMLNMkpmd339R5/GD9wAzwiVBeoEbST2XSQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7811 Add a macro for defining hardware register types with I/O accessors. Each register field is represented as a `Bounded` of the appropriate bit width, ensuring field values are never silently truncated. Fields can optionally be converted to/from custom types, either fallibly or infallibly. The address of registers can be direct, relative, or indexed, supporting most of the patterns in which registers are arranged. Suggested-by: Danilo Krummrich Link: https://lore.kernel.org/all/20250306222336.23482-6-dakr@kernel.org/ Co-developed-by: Gary Guo Signed-off-by: Alexandre Courbot Tested-by: Dirk Behme --- rust/kernel/io.rs | 5 +- rust/kernel/io/register.rs | 1125 ++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 1129 insertions(+), 1 deletion(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 256eba16ccc8..690c25de979d 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -11,6 +11,7 @@ =20 pub mod mem; pub mod poll; +pub mod register; pub mod resource; =20 pub use resource::Resource; @@ -177,7 +178,7 @@ pub trait IoCapable { /// /// This trait is the key abstraction allowing [`Io::read`], [`Io::write`]= , and [`Io::update`] /// to work uniformly with both raw `usize` offsets (for primitive types l= ike `u32`) and typed -/// ones. +/// ones (like those generated by the [`register!`] macro). /// /// An `IoLoc` carries three pieces of information: /// @@ -192,6 +193,8 @@ pub trait IoCapable { /// An `IoLoc` can be passed directly to [`Io::read`] or [`Io::try_read`] = to obtain a value, or /// turned into an [`IoWrite`] via [`IoLoc::set`] to be passed to [`Io::wr= ite`] or /// [`Io::try_write`]. +/// +/// [`register!`]: kernel::register! pub trait IoLoc: Copy where T: Into, diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs new file mode 100644 index 000000000000..498cb3b9dfb5 --- /dev/null +++ b/rust/kernel/io/register.rs @@ -0,0 +1,1125 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! A macro to define register layout and accessors. +//! +//! A single register typically includes several fields, which are accesse= d through a combination +//! of bit-shift and mask operations that introduce a class of potential m= istakes, notably because +//! not all possible field values are necessarily valid. +//! +//! The [`register!`] macro in this module provides an intuitive and reada= ble syntax for defining a +//! dedicated type for each register. Each such type comes with its own fi= eld accessors that can +//! return an error if a field's value is invalid. +//! +//! [`register!`]: kernel::register! + +use core::marker::PhantomData; + +use crate::io::IoLoc; + +/// Trait providing a base address to be added to the offset of a relative= register to obtain +/// its actual offset. +/// +/// The `T` generic argument is used to distinguish which base to use, in = case a type provides +/// several bases. It is given to the `register!` macro to restrict the us= e of the register to +/// implementors of this particular variant. +pub trait RegisterBase { + /// Base address to which register offsets are added. + const BASE: usize; +} + +/// Trait implemented by all registers. +pub trait Register: Copy { + /// Backing primitive type of the register. + type Storage; +} + +/// Trait implemented by registers with a fixed offset. +pub trait FixedRegister: Register { + /// Offset of the register. + const OFFSET: usize; +} + +/// Location of a fixed register. +#[derive(Clone, Copy)] +pub struct FixedRegisterLoc(PhantomData); + +impl FixedRegisterLoc { + /// Returns the location of `T`. + #[inline(always)] + // We do not implement `Default` so we can be const. + #[allow(clippy::new_without_default)] + pub const fn new() -> Self { + Self(PhantomData) + } +} + +impl IoLoc for FixedRegisterLoc +where + T: FixedRegister + From + Into, +{ + type IoType =3D T::Storage; + + fn offset(self) -> usize { + T::OFFSET + } +} + +/// Trait implemented by relative registers. +pub trait RelativeRegister: Register { + /// Family of bases applicable to this register. + type BaseFamily; + + /// Offset of the register relative to its base. + const OFFSET: usize; +} + +/// Location of a relative register. +/// +/// This can either be an immediately accessible regular [`RelativeRegiste= r`], or a +/// [`RelativeRegisterArray`] that needs one additional resolution through +/// [`RelativeRegisterLoc::at`]. +pub struct RelativeRegisterLoc(PhantomData, PhantomData); + +// `Clone` and `Copy` unfortunately cannot be derived without requiring `B= ` to also implement them. +impl Clone for RelativeRegisterLoc +where + B: ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl Copy for RelativeRegisterLoc where B: ?Sized {} + +impl RelativeRegisterLoc +where + B: ?Sized, +{ + /// Returns the location of a relative register or register array. + #[inline(always)] + // We do not implement `Default` so we can be const. + #[allow(clippy::new_without_default)] + pub const fn new() -> Self { + Self(PhantomData, PhantomData) + } +} + +impl IoLoc for RelativeRegisterLoc +where + T: RelativeRegister + From + Into, + B: RegisterBase + ?Sized, +{ + type IoType =3D T::Storage; + + fn offset(self) -> usize { + B::BASE + T::OFFSET + } +} + +/// Trait implemented by arrays of registers. +pub trait RegisterArray: Register { + /// Start offset of the registers array. + const OFFSET: usize; + /// Number of elements in the registers array. + const SIZE: usize; + /// Number of bytes between the start of elements in the registers arr= ay. + const STRIDE: usize; +} + +/// Location of an array register. +#[derive(Clone, Copy)] +pub struct RegisterArrayLoc(usize, PhantomData); + +impl RegisterArrayLoc { + /// Returns the location of register `T` at position `idx`, with build= -time validation. + #[inline(always)] + pub fn new(idx: usize) -> Self { + ::kernel::build_assert!(idx < T::SIZE); + + Self(idx, PhantomData) + } + + /// Attempts to return the location of register `T` at position `idx`,= with runtime validation. + #[inline(always)] + pub fn try_new(idx: usize) -> Option { + if idx < T::SIZE { + Some(Self(idx, PhantomData)) + } else { + None + } + } +} + +impl IoLoc for RegisterArrayLoc +where + T: RegisterArray + From + Into, +{ + type IoType =3D T::Storage; + + fn offset(self) -> usize { + T::OFFSET + self.0 * T::STRIDE + } +} + +/// Trait implemented by arrays of relative registers. +pub trait RelativeRegisterArray: Register { + /// Family of bases applicable to this register array. + type BaseFamily; + + /// Offset of the registers array relative to its base. + const OFFSET: usize; + /// Number of elements in the registers array. + const SIZE: usize; + /// Number of bytes between each element in the registers array. + const STRIDE: usize; +} + +/// Location to a relative array register. +pub struct RelativeRegisterArrayLoc< + T: RelativeRegisterArray, + B: RegisterBase + ?Sized, +>(usize, PhantomData, PhantomData); + +// `Clone` and `Copy` unfortunately cannot be derived without requiring `B= ` to also implement them. +impl Clone for RelativeRegisterArrayLoc +where + T: RelativeRegisterArray, + B: RegisterBase + ?Sized, +{ + fn clone(&self) -> Self { + *self + } +} + +impl Copy for RelativeRegisterArrayLoc +where + T: RelativeRegisterArray, + B: RegisterBase + ?Sized, +{ +} + +impl RelativeRegisterArrayLoc +where + T: RelativeRegisterArray, + B: RegisterBase + ?Sized, +{ + /// Returns the location of register `T` from the base `B` at index `i= dx`, with build-time + /// validation. + #[inline(always)] + pub fn new(idx: usize) -> Self { + ::kernel::build_assert!(idx < T::SIZE); + + Self(idx, PhantomData, PhantomData) + } + + /// Attempts to return the location of register `T` from the base `B` = at index `idx`, with + /// runtime validation. + #[inline(always)] + pub fn try_new(idx: usize) -> Option { + if idx < T::SIZE { + Some(Self(idx, PhantomData, PhantomData)) + } else { + None + } + } +} + +/// Methods exclusive to [`RelativeRegisterLoc`]s created with a [`Relativ= eRegisterArray`]. +impl RelativeRegisterLoc +where + T: RelativeRegisterArray, + B: RegisterBase + ?Sized, +{ + /// Returns the location of the register at position `idx`, with build= -time validation. + #[inline(always)] + pub fn at(self, idx: usize) -> RelativeRegisterArrayLoc { + RelativeRegisterArrayLoc::new(idx) + } + + /// Attempts to return the location of the register at position `idx`,= with runtime validation. + #[inline(always)] + pub fn try_at(self, idx: usize) -> Option> { + RelativeRegisterArrayLoc::try_new(idx) + } +} + +impl IoLoc for RelativeRegisterArrayLoc +where + T: RelativeRegisterArray + From + Into, + B: RegisterBase + ?Sized, +{ + type IoType =3D T::Storage; + + fn offset(self) -> usize { + B::BASE + T::OFFSET + self.0 * T::STRIDE + } +} + +/// Defines a dedicated type for a register, including getter and setter m= ethods for its fields and +/// methods to read and write it from an [`Io`](kernel::io::Io) region. +/// +/// # Example +/// +/// ``` +/// use kernel::register; +/// +/// register! { +/// /// Basic information about the chip. +/// pub BOOT_0(u32) @ 0x00000100 { +/// /// Vendor ID. +/// 15:8 vendor_id; +/// /// Major revision of the chip. +/// 7:4 major_revision; +/// /// Minor revision of the chip. +/// 3:0 minor_revision; +/// } +/// } +/// ``` +/// +/// This defines a 32-bit `BOOT_0` type which can be read from or written = to offset `0x100` of an +/// `Io` region, with the described fields. For instance, `minor_revision`= consists of the 4 least +/// significant bits of the type. +/// +/// Fields are instances of [`Bounded`](kernel::num::Bounded) and can be r= ead by calling their +/// getter method, which is named after them. They also have setter method= s prefixed with `with_` +/// for runtime values and `with_const_` for constant values. All setters = return the updated +/// register value. +/// +/// ```no_run +/// use kernel::register; +/// use kernel::io::IoLoc; +/// use kernel::num::Bounded; +/// +/// # register! { +/// # pub BOOT_0(u32) @ 0x00000100 { +/// # 15:8 vendor_id; +/// # 7:4 major_revision; +/// # 3:0 minor_revision; +/// # } +/// # } +/// # fn test>(bar= : T) { +/// # fn obtain_vendor_id() -> u8 { 0xff } +/// // Read from the register's defined offset (0x100). +/// let boot0 =3D bar.read(BOOT_0); +/// pr_info!("chip revision: {}.{}", boot0.major_revision().get(), boot0.m= inor_revision().get()); +/// +/// // Update some fields and write the new value back. +/// bar.write(BOOT_0.set(boot0 +/// // Constant values. +/// .with_const_major_revision::<3>() +/// .with_const_minor_revision::<10>() +/// // Run-time value. +/// .with_vendor_id(obtain_vendor_id()) +/// )); +/// +/// // Or, build a new value from zero and write it: +/// bar.write(BOOT_0.init(|r| r +/// .with_const_major_revision::<3>() +/// .with_const_minor_revision::<10>() +/// .with_vendor_id(obtain_vendor_id()) +/// )); +/// +/// // Or, read and update the register in a single step. +/// bar.update(BOOT_0, |r| r +/// .with_const_major_revision::<3>() +/// .with_const_minor_revision::<10>() +/// .with_vendor_id(obtain_vendor_id()) +/// ); +/// +/// // Constant values can also be built using the const setters. +/// const V: BOOT_0 =3D pin_init::zeroed::() +/// .with_const_major_revision::<3>() +/// .with_const_minor_revision::<10>(); +/// # } +/// ``` +/// +/// Fields can also be transparently converted from/to an arbitrary type b= y using the `=3D>` and +/// `?=3D>` syntaxes. +/// +/// If present, doc comments above register or fields definitions are adde= d to the relevant item +/// they document (the register type itself, or the field's setter and get= ter methods). +/// +/// Note that multiple registers can be defined in a single `register!` in= vocation. This can be +/// useful to group related registers together. +/// +/// ``` +/// use kernel::register; +/// +/// register! { +/// pub BOOT_0(u8) @ 0x00000100 { +/// 7:4 major_revision; +/// 3:0 minor_revision; +/// } +/// +/// pub BOOT_1(u8) @ 0x00000101 { +/// 7:5 num_threads; +/// 4:0 num_cores; +/// } +/// }; +/// ``` +/// +/// It is possible to create an alias of an existing register with new fie= ld definitions by using +/// the `=3D> ALIAS` syntax. This is useful for cases where a register's i= nterpretation depends on +/// the context: +/// +/// ``` +/// use kernel::register; +/// +/// register! { +/// /// Scratch register. +/// pub SCRATCH(u32) @ 0x00000200 { +/// /// Raw value. +/// 31:0 value; +/// } +/// +/// /// Boot status of the firmware. +/// pub SCRATCH_BOOT_STATUS(u32) =3D> SCRATCH { +/// /// Whether the firmware has completed booting. +/// 0:0 completed; +/// } +/// } +/// ``` +/// +/// In this example, `SCRATCH_BOOT_STATUS` uses the same I/O address as `S= CRATCH`, while also +/// providing its own `completed` field. +/// +/// ## Relative registers +/// +/// A register can be defined as being accessible from a fixed offset of a= provided base. For +/// instance, imagine the following I/O space: +/// +/// ```text +/// +-----------------------------+ +/// | ... | +/// | | +/// 0x100--->+------------CPU0-------------+ +/// | | +/// 0x110--->+-----------------------------+ +/// | CPU_CTL | +/// +-----------------------------+ +/// | ... | +/// | | +/// | | +/// 0x200--->+------------CPU1-------------+ +/// | | +/// 0x210--->+-----------------------------+ +/// | CPU_CTL | +/// +-----------------------------+ +/// | ... | +/// +-----------------------------+ +/// ``` +/// +/// `CPU0` and `CPU1` both have a `CPU_CTL` register that starts at offset= `0x10` of their I/O +/// space segment. Since both instances of `CPU_CTL` share the same layout= , we don't want to define +/// them twice and would prefer a way to select which one to use from a si= ngle definition. +/// +/// This can be done using the `Base + Offset` syntax when specifying the = register's address. +/// +/// `Base` is an arbitrary type (typically a ZST) to be used as a generic = parameter of the +/// [`RegisterBase`] trait to provide the base as a constant, i.e. each ty= pe providing a base for +/// this register needs to implement `RegisterBase`. Here is the abo= ve example translated +/// into code: +/// +/// ```no_run +/// use kernel::register; +/// use kernel::io::register::RegisterBase; +/// +/// // Type used to identify the base. +/// pub struct CpuCtlBase; +/// +/// // ZST describing `CPU0`. +/// struct Cpu0; +/// impl RegisterBase for Cpu0 { +/// const BASE: usize =3D 0x100; +/// } +/// // Singleton of `CPU0` used to identify it. +/// const CPU0: Cpu0 =3D Cpu0; +/// +/// // ZST describing `CPU1`. +/// struct Cpu1; +/// impl RegisterBase for Cpu1 { +/// const BASE: usize =3D 0x200; +/// } +/// // Singleton of `CPU1` used to identify it. +/// const CPU1: Cpu1 =3D Cpu1; +/// +/// # fn test>(bar= : T) { +/// // This makes `CPU_CTL` accessible from all implementors of `RegisterB= ase`. +/// register! { +/// /// CPU core control. +/// pub CPU_CTL(u32) @ CpuCtlBase + 0x10 { +/// /// Start the CPU core. +/// 0:0 start; +/// } +/// } +/// +/// // Start `Cpu0`. +/// bar.update(CPU_CTL::of::(), |r| r.with_start(true)); +/// +/// // Start `Cpu1`. +/// bar.update(CPU_CTL::of::(), |r| r.with_start(true)); +/// +/// // Aliases can also be defined for relative register. +/// register! { +/// /// Alias to CPU core control. +/// pub CPU_CTL_ALIAS(u32) =3D> CpuCtlBase + CPU_CTL { +/// /// Start the aliased CPU core. +/// 1:1 alias_start; +/// } +/// } +/// +/// // Start the aliased `CPU0`. +/// bar.update(CPU_CTL_ALIAS::of::(), |r| r.with_alias_start(true)); +/// # } +/// ``` +/// +/// ## Arrays of registers +/// +/// Some I/O areas contain consecutive registers that share the same field= layout. These areas can +/// be defined as an array of identical registers, allowing them to be acc= essed by index with +/// compile-time or runtime bound checking. Simply specify their size insi= de `[` and `]` brackets, +/// and use the `at` method to obtain the correct location: +/// +/// ```no_run +/// use kernel::register; +/// +/// # fn test>(bar= : T) +/// # -> Result<(), Error>{ +/// # fn get_scratch_idx() -> usize { +/// # 0x15 +/// # } +/// // Array of 64 consecutive registers with the same layout starting at = offset `0x80`. +/// register! { +/// /// Scratch registers. +/// pub SCRATCH(u32)[64] @ 0x00000080 { +/// 31:0 value; +/// } +/// } +/// +/// // Read scratch register 0, i.e. I/O address `0x80`. +/// let scratch_0 =3D bar.read(SCRATCH::at(0)).value(); +/// // Read scratch register 15, i.e. I/O address `0x80 + (15 * 4)`. +/// let scratch_15 =3D bar.read(SCRATCH::at(15)).value(); +/// +/// // This is out of bounds and won't build. +/// // let scratch_128 =3D bar.read(SCRATCH::at(128)).value(); +/// +/// // Runtime-obtained array index. +/// let idx =3D get_scratch_idx(); +/// // Access on a runtime index returns an error if it is out-of-bounds. +/// let some_scratch =3D bar.read(SCRATCH::try_at(idx).ok_or(EINVAL)?).val= ue(); +/// +/// // Alias to a particular register in an array. +/// // Here `SCRATCH[8]` is used to convey the firmware exit code. +/// register! { +/// /// Firmware exit status code. +/// pub FIRMWARE_STATUS(u32) =3D> SCRATCH[8] { +/// 7:0 status; +/// } +/// } +/// let status =3D bar.read(FIRMWARE_STATUS).status(); +/// +/// // Non-contiguous register arrays can be defined by adding a stride pa= rameter. +/// // Here, each of the 16 registers of the array are separated by 8 byte= s, meaning that the +/// // registers of the two declarations below are interleaved. +/// register! { +/// /// Scratch registers bank 0. +/// pub SCRATCH_INTERLEAVED_0(u32)[16, stride =3D 8] @ 0x000000c0 { +/// 31:0 value; +/// } +/// +/// /// Scratch registers bank 1. +/// pub SCRATCH_INTERLEAVED_1(u32)[16, stride =3D 8] @ 0x000000c4 { +/// 31:0 value; +/// } +/// } +/// # Ok(()) +/// # } +/// ``` +/// +/// ## Relative arrays of registers +/// +/// Combining the two features described in the sections above, arrays of = registers accessible from +/// a base can also be defined: +/// +/// ```no_run +/// use kernel::register; +/// use kernel::io::register::RegisterBase; +/// +/// # fn test>(bar= : T) +/// # -> Result<(), Error>{ +/// # fn get_scratch_idx() -> usize { +/// # 0x15 +/// # } +/// // Type used as parameter of `RegisterBase` to specify the base. +/// pub struct CpuCtlBase; +/// +/// // ZST describing `CPU0`. +/// struct Cpu0; +/// impl RegisterBase for Cpu0 { +/// const BASE: usize =3D 0x100; +/// } +/// // Singleton of `CPU0` used to identify it. +/// const CPU0: Cpu0 =3D Cpu0; +/// +/// // ZST describing `CPU1`. +/// struct Cpu1; +/// impl RegisterBase for Cpu1 { +/// const BASE: usize =3D 0x200; +/// } +/// // Singleton of `CPU1` used to identify it. +/// const CPU1: Cpu1 =3D Cpu1; +/// +/// // 64 per-cpu scratch registers, arranged as a contiguous array. +/// register! { +/// /// Per-CPU scratch registers. +/// pub CPU_SCRATCH(u32)[64] @ CpuCtlBase + 0x00000080 { +/// 31:0 value; +/// } +/// } +/// +/// // Read scratch register 0 of CPU0. +/// let cpu0_scratch_0 =3D bar.read(CPU_SCRATCH::of::().at(0)).value= (); +/// // Read scratch register 15 of CPU1. +/// let cpu1_scratch_15 =3D bar.read(CPU_SCRATCH::of::().at(15)).val= ue(); +/// +/// // This won't build. +/// // let cpu0_scratch_128 =3D bar.read(CPU_SCRATCH::of::().at(128)= ).value(); +/// +/// // Runtime-obtained array index. +/// let scratch_idx =3D get_scratch_idx(); +/// // Access on a runtime index returns an error if it is out-of-bounds. +/// let cpu0_scratch =3D bar.read( +/// CPU_SCRATCH::of::().try_at(scratch_idx).ok_or(EINVAL)? +/// ).value(); +/// +/// // `SCRATCH[8]` is used to convey the firmware exit code. +/// register! { +/// /// Per-CPU firmware exit status code. +/// pub CPU_FIRMWARE_STATUS(u32) =3D> CpuCtlBase + CPU_SCRATCH[8] { +/// 7:0 status; +/// } +/// } +/// +/// let cpu0_status =3D bar.read(CPU_FIRMWARE_STATUS::of::()).status= (); +/// +/// // Non-contiguous register arrays can be defined by adding a stride pa= rameter. +/// // Here, each of the 16 registers of the array are separated by 8 byte= s, meaning that the +/// // registers of the two declarations below are interleaved. +/// register! { +/// /// Scratch registers bank 0. +/// pub CPU_SCRATCH_INTERLEAVED_0(u32)[16, stride =3D 8] @ CpuCtlBase = + 0x00000d00 { +/// 31:0 value; +/// } +/// +/// /// Scratch registers bank 1. +/// pub CPU_SCRATCH_INTERLEAVED_1(u32)[16, stride =3D 8] @ CpuCtlBase = + 0x00000d04 { +/// 31:0 value; +/// } +/// } +/// # Ok(()) +/// # } +/// ``` +#[macro_export] +macro_rules! register { + // Entry point for the macro, allowing multiple registers to be define= d in one call. + // It matches all possible register declaration patterns to dispatch t= hem to corresponding + // `@reg` rule that defines a single register. + ( + $( + $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) + $([ $size:expr $(, stride =3D $stride:expr)? ])? + $(@ $($base:ident +)? $offset:literal)? + $(=3D> $alias:ident $(+ $alias_offset:ident)? $([$alias_id= x:expr])? )? + { $($fields:tt)* } + )* + ) =3D> { + $( + $crate::register!( + @reg $(#[$attr])* $vis $name ($storage) $([$size $(, stride = =3D $stride)?])? + $(@ $($base +)? $offset)? + $(=3D> $alias $(+ $alias_offset)? $([$alias_idx])? )? + { $($fields)* } + ); + )* + }; + + // All the rules below are private helpers. + + // Creates a register at a fixed offset of the MMIO space. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $offse= t:literal + { $($fields:tt)* } + ) =3D> { + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!(@io_fixed $(#[$attr])* $vis $name($storage) @ $o= ffset); + }; + + // Creates an alias register of fixed offset register `alias` with its= own fields. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $al= ias:ident + { $($fields:tt)* } + ) =3D> { + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!( + @io_fixed $(#[$attr])* $vis $name($storage) @ + <$alias as $crate::io::register::FixedRegister>::OFFSET + ); + }; + + // Creates a register at a relative offset from a base address provide= r. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $base:= ident + $offset:literal + { $($fields:tt)* } + ) =3D> { + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!(@io_relative $vis $name($storage) @ $base + $off= set ); + }; + + // Creates an alias register of relative offset register `alias` with = its own fields. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $ba= se:ident + $alias:ident + { $($fields:tt)* } + ) =3D> { + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!( + @io_relative $vis $name($storage) @ + $base + <$alias as $crate::io::register::RelativeRegister>::OF= FSET + ); + }; + + // Creates an array of registers at a fixed offset of the MMIO space. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) + [ $size:expr, stride =3D $stride:expr ] @ $offset:literal { $(= $fields:tt)* } + ) =3D> { + static_assert!(::core::mem::size_of::<$storage>() <=3D $stride); + + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!(@io_array $vis $name($storage) [ $size, stride = =3D $stride ] @ $offset); + }; + + // Shortcut for contiguous array of registers (stride =3D=3D size of e= lement). + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:= expr ] @ $offset:literal + { $($fields:tt)* } + ) =3D> { + $crate::register!( + $(#[$attr])* $vis $name($storage) [ $size, stride =3D ::core::= mem::size_of::<$storage>() ] + @ $offset { $($fields)* } + ); + }; + + // Creates an alias of register `idx` of array of registers `alias` wi= th its own fields. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $al= ias:ident [ $idx:expr ] + { $($fields:tt)* } + ) =3D> { + static_assert!($idx < <$alias as $crate::io::register::RegisterArr= ay>::SIZE); + + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!(@io_fixed $(#[$attr])* $vis $name($storage) + @ <$alias as $crate::io::register::RegisterArray>::OFFSET + + $idx * <$alias as $crate::io::register::RegisterArray>::= STRIDE + ); + }; + + // Creates an array of registers at a relative offset from a base addr= ess provider. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) + [ $size:expr, stride =3D $stride:expr ] + @ $base:ident + $offset:literal { $($fields:tt)* } + ) =3D> { + static_assert!(::core::mem::size_of::<$storage>() <=3D $stride); + + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!( + @io_relative_array $vis $name($storage) [ $size, stride =3D $s= tride ] @ $base + $offset + ); + }; + + // Shortcut for contiguous array of relative registers (stride =3D=3D = size of element). + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:= expr ] + @ $base:ident + $offset:literal { $($fields:tt)* } + ) =3D> { + $crate::register!( + $(#[$attr])* $vis $name($storage) [ $size, stride =3D ::core::= mem::size_of::<$storage>() ] + @ $base + $offset { $($fields)* } + ); + }; + + // Creates an alias of register `idx` of relative array of registers `= alias` with its own + // fields. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) + =3D> $base:ident + $alias:ident [ $idx:expr ] { $($fields:tt)*= } + ) =3D> { + static_assert!($idx < <$alias as $crate::io::register::RelativeReg= isterArray>::SIZE); + + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!( + @io_relative $vis $name($storage) @ $base + + <$alias as $crate::io::register::RelativeRegisterArray>:= :OFFSET + + $idx * <$alias as $crate::io::register::RelativeRegister= Array>::STRIDE + ); + }; + + // Generates the bitfield for the register. + // + // `#[allow(non_camel_case_types)]` is added since register names typi= cally use + // `SCREAMING_CASE`. + ( + @bitfield $(#[$attr:meta])* $vis:vis struct $name:ident($storage:t= y) { $($fields:tt)* } + ) =3D> { + $crate::register!(@bitfield_core + #[allow(non_camel_case_types)] + $(#[$attr])* $vis $name $storage + ); + $crate::register!(@bitfield_fields $vis $name $storage { $($fields= )* }); + + impl $crate::io::register::Register for $name { + type Storage =3D $storage; + } + }; + + // Implementations of fixed registers. + (@io_fixed $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $off= set:expr) =3D> { + impl $crate::io::register::FixedRegister for $name { + const OFFSET: usize =3D $offset; + } + + $(#[$attr])* + $vis const $name: $crate::io::register::FixedRegisterLoc<$name> = =3D + $crate::io::register::FixedRegisterLoc::<$name>::new(); + }; + + // Implementations of relative registers. + (@io_relative $vis:vis $name:ident ($storage:ty) @ $base:ident + $offs= et:expr ) =3D> { + impl $crate::io::register::RelativeRegister for $name + { + type BaseFamily =3D $base; + const OFFSET: usize =3D $offset; + } + + #[allow(dead_code)] + impl $name { + /// Returns the location of the register with base `B`. + #[inline(always)] + $vis const fn of>= () + -> $crate::io::register::RelativeRegisterLoc<$name, B> { + $crate::io::register::RelativeRegisterLoc::new() + } + } + }; + + // Implementations of array registers. + (@io_array $vis:vis $name:ident ($storage:ty) [ $size:expr, stride =3D= $stride:expr ] + @ $offset:literal) =3D> { + impl $crate::io::register::RegisterArray for $name { + const OFFSET: usize =3D $offset; + const SIZE: usize =3D $size; + const STRIDE: usize =3D $stride; + } + + #[allow(dead_code)] + impl $name { + /// Returns the location of the register at index `idx`, with = build-time validation. + #[inline(always)] + $vis fn at(idx: usize) -> $crate::io::register::RegisterArrayL= oc<$name> { + $crate::io::register::RegisterArrayLoc::new(idx) + } + + /// Attempts to return the location of the register at index `= idx`, with runtime + /// validation. + #[inline(always)] + $vis fn try_at(idx: usize) -> Option<$crate::io::register::Reg= isterArrayLoc<$name>> { + $crate::io::register::RegisterArrayLoc::try_new(idx) + } + } + }; + + // Implementations of relative array registers. + ( + @io_relative_array $vis:vis $name:ident ($storage:ty) [ $size:expr= , stride =3D $stride:expr ] + @ $base:ident + $offset:literal + ) =3D> { + impl $crate::io::register::RelativeRegisterArray for $name { + type BaseFamily =3D $base; + const OFFSET: usize =3D $offset; + const SIZE: usize =3D $size; + const STRIDE: usize =3D $stride; + } + + #[allow(dead_code)] + impl $name { + /// Returns the location of the register array with base `B`. + /// + /// An individual register from the array still needs to be ad= dressed using + /// [`RelativeRegisterLoc::at`] or [`RelativeRegisterLoc::try_= at`]. + #[inline(always)] + $vis const fn of>= () + -> $crate::io::register::RelativeRegisterLoc<$name, B> { + $crate::io::register::RelativeRegisterLoc::new() + } + } + }; + + // Defines the wrapper `$name` type and its conversions from/to the st= orage type. + (@bitfield_core $(#[$attr:meta])* $vis:vis $name:ident $storage:ty) = =3D> { + $(#[$attr])* + #[repr(transparent)] + #[derive(Clone, Copy, PartialEq, Eq)] + $vis struct $name { + inner: $storage, + } + + #[allow(dead_code)] + impl $name { + /// Creates a bitfield from a raw value. + #[inline(always)] + $vis const fn from_raw(value: $storage) -> Self { + Self{ inner: value } + } + + /// Turns this bitfield into its raw value. + /// + /// This is similar to the [`From`] implementation, but is sho= rter to invoke in + /// most cases. + #[inline(always)] + $vis const fn into_raw(self) -> $storage { + self.inner + } + } + + // SAFETY: `$storage` is `Zeroable` and `$name` is transparent. + unsafe impl ::pin_init::Zeroable for $name {} + + impl ::core::convert::From<$name> for $storage { + #[inline(always)] + fn from(val: $name) -> $storage { + val.into_raw() + } + } + + impl ::core::convert::From<$storage> for $name { + #[inline(always)] + fn from(val: $storage) -> $name { + Self::from_raw(val) + } + } + }; + + // Definitions requiring knowledge of individual fields: private and p= ublic field accessors, + // and `Debug` implementation. + (@bitfield_fields $vis:vis $name:ident $storage:ty { + $($(#[doc =3D $doc:expr])* $hi:literal:$lo:literal $field:ident + $(?=3D> $try_into_type:ty)? + $(=3D> $into_type:ty)? + ; + )* + } + ) =3D> { + #[allow(dead_code)] + impl $name { + $( + $crate::register!(@private_field_accessors $vis $name $storage : $= hi:$lo $field); + $crate::register!( + @public_field_accessors $(#[doc =3D $doc])* $vis $name $storag= e : $hi:$lo $field + $(?=3D> $try_into_type)? + $(=3D> $into_type)? + ); + )* + } + + $crate::register!(@debug $name { $($field;)* }); + }; + + // Private field accessors working with the exact `Bounded` type for t= he field. + ( + @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt= :$lo:tt $field:ident + ) =3D> { + ::kernel::macros::paste!( + $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive =3D $lo..=3D$hi; + $vis const [<$field:upper _MASK>]: $storage =3D + ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1); + $vis const [<$field:upper _SHIFT>]: u32 =3D $lo; + ); + + ::kernel::macros::paste!( + fn [<__ $field>](self) -> + ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> { + // Left shift to align the field's MSB with the storage MSB. + const ALIGN_TOP: u32 =3D $storage::BITS - ($hi + 1); + // Right shift to move the top-aligned field to bit 0 of the s= torage. + const ALIGN_BOTTOM: u32 =3D ALIGN_TOP + $lo; + + // Extract the field using two shifts. `Bounded::shr` produces= the correctly-sized + // output type. + let val =3D ::kernel::num::Bounded::<$storage, { $storage::BIT= S }>::from( + self.inner << ALIGN_TOP + ); + val.shr::() + } + + const fn [<__with_ $field>]( + mut self, + value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>, + ) -> Self + { + const MASK: $storage =3D <$name>::[<$field:upper _MASK>]; + const SHIFT: u32 =3D <$name>::[<$field:upper _SHIFT>]; + + let value =3D value.get() << SHIFT; + self.inner =3D (self.inner & !MASK) | value; + + self + } + ); + }; + + // Public accessors for fields infallibly (`=3D>`) converted to a type. + ( + @public_field_accessors $(#[doc =3D $doc:expr])* $vis:vis $name:id= ent $storage:ty : + $hi:literal:$lo:literal $field:ident =3D> $into_type:ty + ) =3D> { + ::kernel::macros::paste!( + + $(#[doc =3D $doc])* + #[doc =3D "Returns the value of this field."] + #[inline(always)] + $vis fn $field(self) -> $into_type + { + self.[<__ $field>]().into() + } + + $(#[doc =3D $doc])* + #[doc =3D "Sets this field to the given `value`."] + #[inline(always)] + $vis fn [](self, value: $into_type) -> Self + { + self.[<__with_ $field>](value.into()) + } + + ); + }; + + // Public accessors for fields fallibly (`?=3D>`) converted to a type. + ( + @public_field_accessors $(#[doc =3D $doc:expr])* $vis:vis $name:id= ent $storage:ty : + $hi:tt:$lo:tt $field:ident ?=3D> $try_into_type:ty + ) =3D> { + ::kernel::macros::paste!( + + $(#[doc =3D $doc])* + #[doc =3D "Returns the value of this field."] + #[inline(always)] + $vis fn $field(self) -> + Result< + $try_into_type, + <$try_into_type as ::core::convert::TryFrom< + ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> + >>::Error + > + { + self.[<__ $field>]().try_into() + } + + $(#[doc =3D $doc])* + #[doc =3D "Sets this field to the given `value`."] + #[inline(always)] + $vis fn [](self, value: $try_into_type) -> Self + { + self.[<__with_ $field>](value.into()) + } + + ); + }; + + // Public accessors for fields not converted to a type. + ( + @public_field_accessors $(#[doc =3D $doc:expr])* $vis:vis $name:id= ent $storage:ty : + $hi:tt:$lo:tt $field:ident + ) =3D> { + ::kernel::macros::paste!( + + $(#[doc =3D $doc])* + #[doc =3D "Returns the value of this field."] + #[inline(always)] + $vis fn $field(self) -> + ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> + { + self.[<__ $field>]() + } + + $(#[doc =3D $doc])* + #[doc =3D "Sets this field to the compile-time constant `VALUE`."] + #[inline(always)] + $vis const fn [](self) = -> Self { + self.[<__with_ $field>]( + ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new= ::() + ) + } + + $(#[doc =3D $doc])* + #[doc =3D "Sets this field to the given `value`."] + #[inline(always)] + $vis fn []( + self, + value: T, + ) -> Self + where T: Into<::kernel::num::Bounded<$storage, { $hi + 1 - $lo= }>>, + { + self.[<__with_ $field>](value.into()) + } + + $(#[doc =3D $doc])* + #[doc =3D "Tries to set this field to `value`, returning an error = if it is out of range."] + #[inline(always)] + $vis fn []( + self, + value: T, + ) -> ::kernel::error::Result + where T: ::kernel::num::TryIntoBounded<$storage, { $hi + 1 - $= lo }>, + { + Ok( + self.[<__with_ $field>]( + value.try_into_bounded().ok_or(::kernel::error::code::= EOVERFLOW)? + ) + ) + } + + ); + }; + + // `Debug` implementation. + (@debug $name:ident { $($field:ident;)* }) =3D> { + impl ::kernel::fmt::Debug for $name { + fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kerne= l::fmt::Result { + f.debug_struct(stringify!($name)) + .field("", &::kernel::prelude::fmt!("{:#x}", self= .inner)) + $( + .field(stringify!($field), &self.$field()) + )* + .finish() + } + } + }; +} --=20 2.53.0 From nobody Fri Apr 17 01:39:55 2026 Received: from SN4PR0501CU005.outbound.protection.outlook.com (mail-southcentralusazon11011057.outbound.protection.outlook.com [40.93.194.57]) (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 6E0A939C62B; Tue, 24 Feb 2026 14:22:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.194.57 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942965; cv=fail; b=ozKRB69x0mg8kRHpfFXryXnB3Js3QmwclmCMgqodE1wb8f+Lh/MvFtE0dR/jZcT2VBNZfNSrJjtSsG3M/Df2f10N4UrpLOe8QZxusiUaLaH3ecG2RNm3W5Bnol6CbIRxWY2wkB2Bt6pMFIUPN5BnzZz1zEFbxOA6vzAsGvKn1E4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942965; c=relaxed/simple; bh=CSm+/IVDVPZLjsUhm6x6SiUwcFe+6FzQL/zgb9tK9SA=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=K02QM3aBzGPZoDMxOn0jMsQvZHbo3xqg5wMOypzAC/tY6esRbh8vQGs0gkJMdLCurol7M/mkdq0rAEwyK13l6dL7spOSi1WAAFR4OYp4i8SAi9ofIBzfe/QL+uB3BG+fGB4r7b8bDd+8blVBczO0mruo/ttUBtDJIcfR/9p3lS0= 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=BoYciG7W; arc=fail smtp.client-ip=40.93.194.57 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="BoYciG7W" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=UxOriR3pqnLJicJt/UZqasHj9tTkyyMbDviKqL7e6jJ8tZHhDxd7HEauhfdqbNkhlJKKY2gtR5p/KK0ERiOPmfWJByqmWddgyuHKz420Hef3e3CHI+1y6qUBXcQnpFRSg9uac2YPhFmZHXXwbCr1uN+IylqLFYXb8C7uLeAfd+d1YWnkNVevLluChNcH3Qk6neXrOOjnBQGo1OkT9r3HQhWimBJeXEtIckaMxHr0ZzZvoYovrQIaCHBJXzvMUBa/K+ZQwQ3d6luv4H5q7CQb8KYt71CYUaiXcrJxld529fUbgdqJLP20d33W2wAu97i92OQ+FBhssEhzo8pvmmiiGg== 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=ReqsngoF46d6nRQcJt0bwvpLcRSl5OF2INSU9yhApf8=; b=kCRgjGgIM4aKxLXEO9ONWoRlXs/ivZ8sVa88aARZqbjwROop/X6NyJz7U+VWMX/ggWfY/Uhcf7oHpaNWckhO4nVocG/G1GSZOQjaOEbMC1upNtVwqWWdx9UL7hHOSmrbEK6WiTT9YAqOfa2C0BCpjbe/RyarZYEhRUTPAfw5wZboo5tuMjTJsAWJVLvbTMCsCg8136MAt3nyrFf56MhUftjQ2bzvWnJryDkjlW7pfFxc8WWjxUc1CcQL44MUJbCK+ul4iDI5jjwUaoagAMbMiWigNhq+e81WbdxSbaDACkm6vH0rC2UZY4+L7NmNyX0jG0I5Rz/eAUyzeaNtva/khQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none 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=ReqsngoF46d6nRQcJt0bwvpLcRSl5OF2INSU9yhApf8=; b=BoYciG7WqIzn053RI9P1n/PGJuk+UDqXfQ29cvPOWftuPfzuVTq+Z4+7XZYHXHiURvItpJGWD/c0YFTuZiOhtQPRmofvEq3q6veIGlrnWOrQaZ0L1PKOr2a8hwv0cA2mSQXRefySJ8SZqNXl+NfxV8S42+HF/18wNRDET0xiOS6a0MQ8TcBXaesg7wxIf+xzs+mtr1+uvOOqnPEFnRasAOtaGGynoAup7W4UiqBL1b1SWejSUjOOhFieU0s4dJ1vXxhLzjqV/lrUkKM1bY2K2/W1MKdCzDkDR2o3mEtN9uQeOG0vQ5NNFv/RtqfPFsxFt9m2ffFPq/iPhX2bjeGXOA== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by SN7PR12MB7811.namprd12.prod.outlook.com (2603:10b6:806:34f::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 14:22:38 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%6]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 14:22:38 +0000 From: Alexandre Courbot Date: Tue, 24 Feb 2026 23:21:46 +0900 Subject: [PATCH v7 08/10] sample: rust: pci: use `register!` macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260224-register-v7-8-aad44f760f33@nvidia.com> References: <20260224-register-v7-0-aad44f760f33@nvidia.com> In-Reply-To: <20260224-register-v7-0-aad44f760f33@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Boqun Feng Cc: Yury Norov , John Hubbard , Alistair Popple , Joel Fernandes , Timur Tabi , Edwin Peer , Eliot Courtney , Dirk Behme , Steven Price , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Courbot X-Mailer: b4 0.14.3 X-ClientProxiedBy: TYCP286CA0047.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:2b5::18) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR12MB3990:EE_|SN7PR12MB7811:EE_ X-MS-Office365-Filtering-Correlation-Id: 3c3a0e91-becc-4f1a-d566-08de73b0294c X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?ZklxOEppbUVyaXdGSEhjcEZEbllMU0hQZUtCRkoybmJCR0Jsa3RyNHRqVENi?= =?utf-8?B?VUhNTmlYUDJXQWE5OEZUNXYyVm9ZQnpmTURyazYyOUt5VHRCbVYrSDBPSEo2?= =?utf-8?B?RFNGQUd0U0paOGNoNjN1R1RvTURRY1ZjcEh4NjF1S0FvczNIQ0hFckFydGlr?= =?utf-8?B?SnRjakRFOWJ0eWJ6QlRjQUJNdzZYVEJmNyt6MEhpVkR6SFFTa3RPVGh1U1lX?= =?utf-8?B?S1NCblBnOVpyUGY3c0Z2UmhvK0ZFanlyR21YVE11VVVleEE1ZnZHeW5wTUM4?= =?utf-8?B?ODFIdG1aa2Iwbk9qS1p0QjcrUEJNMEpFaGxRVjhmbDFtVUJUVGgrK2RFTjk0?= =?utf-8?B?QzZWbG5qbGdsRlhrdXpVTDBOZDJyZGxlaFNCNlR1K1FXTS92LzhGdTRYb1hw?= =?utf-8?B?K04zOGN3TFNYZGdLVnNqeDRzVmRmUVJFU2tMTWFMRDd0Z3ZURUdLbW9wQTNI?= =?utf-8?B?bStGWU13QXo1N09MQmRnQjQydTgrYWhsRWV4YzBnRGNLWmxUTjhROHVMc01v?= =?utf-8?B?Ky9Ga0J5NkYya3BvU1N0Z3dkUHBDZllRb0hEWkNmM3N4b3FCc2dVZU9DK0h5?= =?utf-8?B?dTFGZlZ5amR2UFhwVzBjcUZ6TDAwa3pJRURGS1BCbXh1bTFhTWpKbnYxb1p5?= =?utf-8?B?VnVybUZmVEE1RDhDclV6SlplYWEyd3NIS2xFL2cyUzJlcm96UVlZMXordDM3?= =?utf-8?B?MHFwTEFFdFVSdTl5QWFlMkNmeXpPVDA0TlkvZTRCa2hzN3FGdEl3MTBiWW43?= =?utf-8?B?YUhQaXlNVHhUTzFiemlGTzZBNXFYRk9nUFJ1cTAzTm1rRm5kdHV0TFEram5u?= =?utf-8?B?TTRoNWV6dzJ0STdGTVdEbWI3d2Mzc3ljWkFTcjg4MjRaenh5bk1LNUU1TG5a?= =?utf-8?B?bElKbGJqUHpkcUFVamw3M2N5VUZqWE50U1pyZ2RNcHZRY3JwQk05QzNqTlpM?= =?utf-8?B?RkUzdG9UZjR1S0QzN1BvVEFoaDhONktFYmNQSFUyaXZ0d2hKQzYvNC8vN0lu?= =?utf-8?B?d0hEclVnUjMwZExxUndtc01idXJDL01ESytld3h3KzlQM2ZaMUFtOTY5VWdD?= =?utf-8?B?N3g3UVdaOGlSSzc0NndlYXE0WVhCa2wyTGFOUEdURzZDT2UrSXliZ2kxNi8v?= =?utf-8?B?Ukh1ZEZUaStPZHc1Y3M1Nk5iOEdERTVJaStRZkhXRk5NQnlQOW0rSkxTY2Ja?= =?utf-8?B?NE5jaGY0TVRZWHdoaGZSalc3NkYxTlF0ZGc5TzlVWUQvVFRrZ3psdHpIQXh1?= =?utf-8?B?MlpsR0F2L0tqak40bVRkYTV1NE05YTVreEVCazA0ZmlMQmRDV21nZGFrdm8z?= =?utf-8?B?TkdnVzEzMXJnNFlKZmw4Y0V1ZXd3REpIODdBVjIwRENhT0d2UFhSMFVIZ2pC?= =?utf-8?B?YkFqeDQvWnR5SzNDcnAvTUtNSXVCVFFkTkw0SEZqZGd3S3RwMFhHZkdBYWx1?= =?utf-8?B?VmNrWWlUbEFKa3RJbDRCRnZOL3ZKNDVRSEhSRW1XejdxTXYvOGUwdTEvWWFF?= =?utf-8?B?ZFhzQ2pTUHlOUE5XWE5ESFdmWVZrSnZjWmNXK1dEOVlIN2dtcFJlak5VTW5m?= =?utf-8?B?QnFNYzVxWjE3SGtxTXdvaVRiWWxMZW93ek1tZWVscE0wUjNsU1VzSVNzOGZy?= =?utf-8?B?L2MwYWJyMlpsdlA5K3k5OC9BVmUyNTlpSFNhcGFyWTVCRG9IRXZVNXIvYTZD?= =?utf-8?B?aWNscmhLRVZTcXZvQmRJS1o5VUxrWkoyTm9oRUdnclpsWmlCK09weWNxKytX?= =?utf-8?B?dUQyR2o4VWpxN0pTVGdTVUMvR3YzZlJKSVFtRGRJUnMwOUdRQ2JVSDFOaDRl?= =?utf-8?B?V2RlSHpvMkMvUGdRaGdadEpkV2ZreTQxajJ4V0czR3VKbDh0Q0NCNXJNWVFy?= =?utf-8?B?NTlLd2hqa2Q3NDAvcGNyUjBzeFh1YTJtSm1ZV3U3OHVTK3JERkxHMUxHQUtC?= =?utf-8?B?bXZ5bFV1LzBWa1hkRXBqUVdubm5ndUxWNTlpVTZuQm5PV1FNZ25VTFc1bUh0?= =?utf-8?B?R0R0Q1I4NnV6SE1ScEEzRXdURFd4SFFMN25XbjZQWm5IT1NoWmRucXNnNTBi?= =?utf-8?B?dnJuTEpodWFmQ0xQVDBlUVhUOXVhSlUvM2VmVTlaaEpFb2V3UWV3eTk3cmRF?= =?utf-8?B?UStjM0VzV1BRTEFQbWRHL0txZ1ZnNlhhcVBZZzJVYlhRdnNXYkFFMy9RaFho?= =?utf-8?B?b0E9PQ==?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?akZHTmZMSTZ1d1BmMEVmN0pmU2praDJpT3dCWndKc0lJeE1IV2U3Q2NWZnBt?= =?utf-8?B?cDZIUGhxQXhzTktGeEVWQXVMZ0plbzI3UDBHNGwwUzcyWlN4UVZ6STlSTTJ4?= =?utf-8?B?cnhCWkZaSmJSTDdRWEZvYkR2YmdsYzBONkl3dGpteUM0VjlRSE1LRDIxM0FM?= =?utf-8?B?UVBjZEIyZGlhaXJzSVB5cTZNYzRmNms3NEgvUFR6WmhVNmxjQzNhcUZwSmpH?= =?utf-8?B?b3lvdXhRWnNQZnpqNURmNDR0ai9QdjZVbTkrOHorUWdjNzNoUHlES2Zkd2Ew?= =?utf-8?B?cmIzcWUwYkYwMmkvOHk2RmhLZURTSEtGU1JzOUVxSGJrN0hLekgrcXVOeHFE?= =?utf-8?B?V3M1aFFmRWEzMWY1RnRyOUtEeEplUm9UNjcvdi9PTVU1VG1DWlhxblk4OFpk?= =?utf-8?B?MXByRTMwQU1jdVhmb05WRTB6MFhBWkF6Q0VSZmFuaEE4T2NkRFFoOUVNYktL?= =?utf-8?B?eGlPVWp6dXIyZm5yOFdqQmZMcWNyNERXcE5GU3FWd0JQYlpDRmxUVUszdUpn?= =?utf-8?B?czVIaGlsNi9MazZWTThndDB0WlBneFhVVXVZbEVSZjBCTGozTUZnb280T1I0?= =?utf-8?B?U1RKREVRcnJVNjRvY0doRml4S2JqejdHcUJBZEdxYUN2bVBYQmlYcDY4dUd4?= =?utf-8?B?VzdOcVpMTW9WRUhZNHl5MWNEdzJLU3pYeHBNSUhxa1NFNEVMcFUvWThFWUJS?= =?utf-8?B?YUVVMFRpU1QxNU9kcjRQaEhTNHhYMjFEM3Q5NGJIMFBFVEI3V1drR2RHc1p3?= =?utf-8?B?VURtVmNIeDA5aml5UVNwQkFkdUpMaTRua01oMGJWcHZNRzY1OXh6TUZDOWV1?= =?utf-8?B?ajJQeXJlM0RwVlJGcWR5QUMvYUxySlUxZW0yN2ZldmZxc0NrNkNXa2VLR1ZS?= =?utf-8?B?bHFsWGNjdXFxcWtVaXVmV1Jvb1AwOWJJZzZjclZDOVAxS0Q0R2V4WktIYVdq?= =?utf-8?B?ZWpvc2RrSFJTVGVxNUdHcUlKSTRGYW1KVGF1Z25waEVMelpDcVlVY0FRR1pK?= =?utf-8?B?RTU4TEJiUWxwWEwzMFh3MlJwMnNvLzJLWnNWQXlQdnpHNE1GUTVxQ1dvVG1E?= =?utf-8?B?THNnRzdGcSt6UElhVm5VMWw2SWY5anVEcENQTnBkYjVkS1JzQUIwZUR2cmR1?= =?utf-8?B?eDVpMkp2ckpKY29ncWNXR0dEbkozeGpUN25JK0pnRi9IS0lqQklKRFpEd01h?= =?utf-8?B?aERjWlBlTXNXVy8xSGx6aVlibzZPemMvZXBZYUV0bUlBMi85MFkrLzNpdG5m?= =?utf-8?B?UTQ4QmhxdjhzQmY0WGNMOStKM3NSKzhKeml4cWlHREFPYURNRWhGNVR2RmUz?= =?utf-8?B?aFhZcmRMa2hWbWFGR0g4SmF2RnIrUitpaWZhdGJBRDRMRG9mS1FuRURhTkdN?= =?utf-8?B?eUd5VjYyZmdWek1qTC9tVmlId3o1c2ZPYndVQWphaFFkcndUN0xCcXF1RHIw?= =?utf-8?B?YVBKcUdSdmdsZGx0YW04R1J1WDZ4eEJ1VnVCR2xNL3IrSU1Fb08vZXVpc1RX?= =?utf-8?B?UFJKNGZGOE9lRmhUN084ZThZaFZJMDI4dUlrWjhRaDZDby93ZHVLSmltVXJ5?= =?utf-8?B?S1BadENiR1NQYW1LUEV4a3NQTUVRRmxLTGlpNkFZcExNZjVpS2R1Y2dZeURy?= =?utf-8?B?MTFUZ3RFMHBZSGZxVlZVYkF1cmNldnBZWENNOVVRUnh1bjI5c2cxT1dQTWJn?= =?utf-8?B?clZhQnFxdDBLSDBRYWtnY0x4TGRkODZNeld4aU42ZEc4V0wxK3dhYnNSM2Ja?= =?utf-8?B?anZBbWR3anZLd01ENkx6anZDZWdHMXNmelpodWFxM1MzZGtpYVRwQ1lib2lo?= =?utf-8?B?czA0OWZDZ3lITHhNbm1hV1hSSDBPdnpOSFRjMy82ZTJNVXh5SEl6N25CU3RK?= =?utf-8?B?Z3I2QVV4YlIrUVNLY1c2NEZkSy8rODJMcU40T0NYNkIxYzk5alpGdTVRZW9r?= =?utf-8?B?RjFKQWlkOHRJN0h6R2ZYb2VoT01jdUd0akFVZENTZ2FienN1WFhuak83dmV6?= =?utf-8?B?VngvTmJ2L2hyajB1OUxUaUlINkRJWnhvakhMU0haRXFLMlRNNG1PSUpiMi85?= =?utf-8?B?TUt6b0ZNUTRqYUVvUWxDeVA1aFlxUDZyWVkvNEtlbzAwY0JqSkpaSFdoZFNo?= =?utf-8?B?L1BqVUVhamRVcDJrSkdKdktTN2U5bk40MHVQSkFTeDJ2UjNWNFU0aisyNSt0?= =?utf-8?B?R3lUeXZkWjJzaUVUeVAya3E5Um9nN1pselhDV3g5UHhCWFFlbUlZbmdDbU1w?= =?utf-8?B?QzhtbzJzdFpaTVVQcTJMdzlVbW8ySk8xTjRXTWhmK3JXYlVTaFM2bHRIRGFG?= =?utf-8?B?cmh4Tkl4UENkMkh5UFpTY0NVTVpVQ1Jab21vb2xXcjhoSHgvUXZCdi91eE13?= =?utf-8?Q?YBxQtObQLDazLCgbEJO6gMVOVdOCidz3JbLRr7kzfneZp?= X-MS-Exchange-AntiSpam-MessageData-1: wxvlU6r8s+cOkw== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 3c3a0e91-becc-4f1a-d566-08de73b0294c X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 14:22:37.8920 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: yhNWJGiKK1CV/Ur3Ap14pZ7AvgcgF4WOLsU3iqfKnGkVV7g33PR5onUmpYALfUlZjrlY2e0TGaz0Raaj+ukwHA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7811 Convert the direct IO accesses to properly defined registers. Signed-off-by: Alexandre Courbot Tested-by: Dirk Behme --- samples/rust/rust_driver_pci.rs | 84 +++++++++++++++++++++++++++++++------= ---- 1 file changed, 64 insertions(+), 20 deletions(-) diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index d3d4a7931deb..0a5284d2f5e9 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -8,27 +8,58 @@ device::Bound, device::Core, devres::Devres, - io::Io, + io::{ + Io, + IoLoc, // + }, + num::Bounded, pci, prelude::*, + register, sync::aref::ARef, // }; =20 -struct Regs; +mod regs { + use super::*; =20 -impl Regs { - const TEST: usize =3D 0x0; - const OFFSET: usize =3D 0x4; - const DATA: usize =3D 0x8; - const COUNT: usize =3D 0xC; - const END: usize =3D 0x10; + register! { + pub(super) TEST(u8) @ 0x0 { + 7:0 index =3D> TestIndex; + } + + pub(super) OFFSET(u32) @ 0x4 { + 31:0 offset; + } + + pub(super) DATA(u8) @ 0x8 { + 7:0 data; + } + + pub(super) COUNT(u32) @ 0xC { + 31:0 count; + } + } + + pub(super) const END: usize =3D 0x10; } =20 -type Bar0 =3D pci::Bar<{ Regs::END }>; +type Bar0 =3D pci::Bar<{ regs::END }>; =20 #[derive(Copy, Clone, Debug)] struct TestIndex(u8); =20 +impl From> for TestIndex { + fn from(value: Bounded) -> Self { + Self(value.into()) + } +} + +impl From for Bounded { + fn from(value: TestIndex) -> Self { + value.0.into() + } +} + impl TestIndex { const NO_EVENTFD: Self =3D Self(0); } @@ -54,40 +85,53 @@ struct SampleDriver { impl SampleDriver { fn testdev(index: &TestIndex, bar: &Bar0) -> Result { // Select the test. - bar.write8(index.0, Regs::TEST); + bar.write(regs::TEST.init(|r| r.with_index(*index))); =20 - let offset =3D bar.read32(Regs::OFFSET) as usize; - let data =3D bar.read8(Regs::DATA); + let offset =3D bar.read(regs::OFFSET).into_raw() as usize; + let data =3D bar.read(regs::DATA).into(); =20 // Write `data` to `offset` to increase `count` by one. // // Note that we need `try_write8`, since `offset` can't be checked= at compile-time. bar.try_write8(data, offset)?; =20 - Ok(bar.read32(Regs::COUNT)) + Ok(bar.read(regs::COUNT).into()) } =20 fn config_space(pdev: &pci::Device) { let config =3D pdev.config_space(); =20 - // TODO: use the register!() macro for defining PCI configuration = space registers once it - // has been move out of nova-core. + // Some PCI configuration space registers. + register! { + VENDOR_ID(u16) @ 0x0 { + 15:0 vendor_id; + } + + REVISION_ID(u8) @ 0x8 { + 7:0 revision_id; + } + + BAR(u32)[6] @ 0x10 { + 31:0 value; + } + } + dev_info!( pdev, "pci-testdev config space read8 rev ID: {:x}\n", - config.read8(0x8) + config.read(REVISION_ID).revision_id() ); =20 dev_info!( pdev, "pci-testdev config space read16 vendor ID: {:x}\n", - config.read16(0) + config.read(VENDOR_ID).vendor_id() ); =20 dev_info!( pdev, "pci-testdev config space read32 BAR 0: {:x}\n", - config.read32(0x10) + config.read(BAR::at(0)).value() ); } } @@ -111,7 +155,7 @@ fn probe(pdev: &pci::Device, info: &Self::IdInfo)= -> impl PinInit(0, c"rust_= driver_pci"), + bar <- pdev.iomap_region_sized::<{ regs::END }>(0, c"rust_= driver_pci"), index: *info, _: { let bar =3D bar.access(pdev.as_ref())?; @@ -131,7 +175,7 @@ fn probe(pdev: &pci::Device, info: &Self::IdInfo)= -> impl PinInit, this: Pin<&Self>) { if let Ok(bar) =3D this.bar.access(pdev.as_ref()) { // Reset pci-testdev by writing a new test index. - bar.write8(this.index.0, Regs::TEST); + bar.write(regs::TEST.init(|r| r.with_index(this.index))); } } } --=20 2.53.0 From nobody Fri Apr 17 01:39:55 2026 Received: from MW6PR02CU001.outbound.protection.outlook.com (mail-westus2azon11012046.outbound.protection.outlook.com [52.101.48.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 27E9C3A0E90; Tue, 24 Feb 2026 14:22:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.48.46 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942983; cv=fail; b=kyuWCH4EHLfkM5JHYjOENDLZvAymI5JM8RVuYe8Qsf1MVZXdnWDPJPx+GJn4id6uxYqW9KFvN38F84FSsTS/Q1H9j84lhcKejeVO+lijytO8DOLqlqTeyVDXHBKUWWy24fAuufAaRnqB4YSjRtIiSVbXvdb7Qtx71m/mWzJJqqQ= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942983; c=relaxed/simple; bh=Q0g7AiY7ig3nIt1aJ/6STg+cb7lhH6vn/7c6gufb5Ok=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=dnk+DOVrki/ziuX77g5wsVth0cRrcRw85lzijViIZNvi75ibl6STGvPPGhCQfCKuCBdwJapnRyjhkrpiZx25IjVNFvgJtD2vw44z9UWQFJcdRPC+CXGRK4g02Jx11uDwcrHnvHg3qfSiOUDnqSO0pyKpQVNJU/LlT88M7UCDvRc= 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=GxEwJFvU; arc=fail smtp.client-ip=52.101.48.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="GxEwJFvU" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=GWIpm2knvviEOX4HdD76l5bNfFOY32GASnEEPHfks88qXZL6kA+dsX2oJ48nTJdjaYIN2holSaaMwJP5szyL9AsNgS9FU6WavMk2wOSch2U5FFCfHT91Fz1D5UYh/DfvclNweKdTB+gCF/3F1mzIZ8m15aUCrTrN64GVjH2LptwcEJLiEeZW+WSoZJtbavtpHZSo+AFePm8ca/9Rr47nkGA4rz2BepHEYPvKZgasiEjIVXXTyb8Mozy24Ne9VsBCJUZ2MsXvGPHZYNR7VA751uLOS7fKxKTP7ggyTEH8LCB1IuzsvTSrueY5n77zeFgBbXfUp4SbEwnDVqU7ConfLA== 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=zvDN32ySBATuFY9TE5CR9+MZ/Wa6i7Sn1wNKnBSFNYM=; b=Mykoru/6XVqoyeX4PCCkr0Y+gKyATvtamwuywXVpSVLUyOMv3AI7dZVja3IASJixEl04dLiss8+XpGQbX7GT6ruLh3ieNNQUKLsT5TLuFRSEAkLWGLI9knw79ZNakuxbk03op3laDX0I/nrmNiaPCRLENrN7CE0aKI6p4PyvOOAj6NnHIXAmHWdhTttOr/QJ9PG6k0850NZEaZIeGBIoap/oz04HMPYJ6KjTrMJVlRrgl9dSY8A5SetjcXX1WfwOjuJJdKYSukXgtRtQ8ZAqGYS1A7AwWqyl+SFVpG2+8UDnHtL7rLvYUKzOfWAiGWAKrdM+PxkXx/x6WnUQj2JFRg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none 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=zvDN32ySBATuFY9TE5CR9+MZ/Wa6i7Sn1wNKnBSFNYM=; b=GxEwJFvUOKImEJcn7IeIZlwzMJlUax70ZD7q+dzsf5htEgdsl/nyAH+Voi88Rcmksb92vE7AKQzAdrlwanKnq3YZt9YqGgsKSril0BtRixZBNo3a2Kml3Tt3K/Y3Si9psv2UsPrsgiwy6yOzai6YopefFMf+AProK42xEq04TTzjpbEVqft2mm3M++f3oW5bEk85MG7KIGlfoTzw3xwCs9SUor9X6gDgkg8ivDzq1HUemo8P500480TUi7KZl09cBnICyp0wXFOiCPe+IoLhzH5/2aod54D7+7bcKDxto7x08fw0WhxHED5ipKitQhmjBlICRhbOAopBXOMviw6Nzg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by SN7PR12MB7811.namprd12.prod.outlook.com (2603:10b6:806:34f::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 14:22:42 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%6]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 14:22:41 +0000 From: Alexandre Courbot Date: Tue, 24 Feb 2026 23:21:47 +0900 Subject: [PATCH FOR REFERENCE v7 09/10] gpu: nova-core: use the kernel `register!` macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260224-register-v7-9-aad44f760f33@nvidia.com> References: <20260224-register-v7-0-aad44f760f33@nvidia.com> In-Reply-To: <20260224-register-v7-0-aad44f760f33@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Boqun Feng Cc: Yury Norov , John Hubbard , Alistair Popple , Joel Fernandes , Timur Tabi , Edwin Peer , Eliot Courtney , Dirk Behme , Steven Price , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Courbot X-Mailer: b4 0.14.3 X-ClientProxiedBy: TY4P286CA0014.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:26d::8) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR12MB3990:EE_|SN7PR12MB7811:EE_ X-MS-Office365-Filtering-Correlation-Id: 6d6010ec-7b1c-4933-17ff-08de73b02b5b X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?QzdOMzdXRTRld29mMVk4VDlRMnhJblZFT1c3dlM2Z2I5MFhnblRZWlFhaTVn?= =?utf-8?B?Q3pRYU92dTJQWFYveEw4aHRCVEpMQ2RqRVFwalJwOWZVMUNaOXBaUDZ2cHM4?= =?utf-8?B?UEsvbjl1SDdQZVBzamhsTktXUG1GQVNjQW5TUERsdVBjN1dUdGNqWUZXQ3R0?= =?utf-8?B?MDQxMEt5V2hqajYvRC9KTVlEZW11Y05PdFlwY2lTNjF2WDZTRXhTdWJlZlc2?= =?utf-8?B?aEtXTVRFY1BScmdZaGlyVTExT0F6NnpQWGF6cWFsRStBclBNR3FjOERTb3Fp?= =?utf-8?B?SUNmRlY1VVh6S2hsRHQ1OEFaa3VWQWt3SHJVTG5IdXFnMGZWK2g1YVd3Z2h2?= =?utf-8?B?UDlMZnRjY0x2eFF3Nm16WGNUcEVaTk5BcXdNU2I0Wml0UUZIdHNlRmJUUUYw?= =?utf-8?B?MTFydTBja2RaVy9HdEU0WWtIWmRkdlJKTDNqMmVrekY0eDluZmVjTjVsbGJX?= =?utf-8?B?MTlCQkVTTDJlMFBURWJOQk9VK3lTaTFSdUM4T1BZelZwNkVva0pjSEQxSDNs?= =?utf-8?B?ZlhHMHptTkZhbVRJbERIb2NyNzd5SmNYSlFVZllpVmVHUFhHUm5IQ1RuN2RN?= =?utf-8?B?VDVFRWFnUGprRTFqTzUrT1p4Mzd2S1AzZUJXRHl1UXpWUmxiWWdnL2FjSi9R?= =?utf-8?B?ZVJsNlAydFNlRjc4UUx2UlJaTVliQmNjamlRdXAxVFdZeEI2NTlrU25vb2JM?= =?utf-8?B?SDFXQXJ3ZGxNUWZobWZvTlN0b0dwYTZ0akJIOTBtK3FUNnp4eXQ2b0VLcHhm?= =?utf-8?B?ZXVITVkyaW8rTjFmM09raE1sMUxUU1pnRC9BNGVpT0d1T0o5VG9XUWlQM1Z4?= =?utf-8?B?REtxQ2h6MUVybHNCNitOTS9Odmc4QlRYRUg0R2JrMCtFVExqc2ZJMmdSOE5D?= =?utf-8?B?ZTRDU1BweFd3NkJDZmlRd245TUg1SHRmTzhBUHdiSWxQblZIY214Wm5jalYz?= =?utf-8?B?MlhRSEdtaEJYTkRuWjdkamh3M01NMklhQm0zVDl4Nm85RVJSdnY3WEt3VFZX?= =?utf-8?B?UEZaM0QrRjBqQ3BmUWFwWC9pYk9LcjU5OEpab3B5WENPK01WRGljQmc1anlQ?= =?utf-8?B?NjlxV0cvbnc2bFZxa1AzK0VGS0h0UldjSTRJbGFCclVPbG1SSGhLdWZXMnNR?= =?utf-8?B?MzBDdUpHR2ZLbU9Lay9FRW1MRjFCcUx2VjZUcTJxdTBQUDRhNXBaVUpzRERj?= =?utf-8?B?bGk4Y2IxaVdocE40bXlWZXliL05TQlBoeFlIVUN2eDBjcVJHVTNNcGYxbXls?= =?utf-8?B?bGgzNkdLdmpyR2phZ2NMZDQzUXpNZThNRGc2L1AwMGJXNmhGNVcwZjBidE9i?= =?utf-8?B?L3hwMG8wcnpnVXYvelV4RjBNS052NUR3ZmlHeE5wMS90UU9MZENkSUVoUDRa?= =?utf-8?B?ZnNabUdUZk1YUDVERGtVOVVETmRURWYxNzd3dC8zcnBpU01IbVRsTUFyZ1Fp?= =?utf-8?B?REtyOS9LbUQyMkFpelIwWVBVN3l3c04vdWZGMjBGYzZHb0crcjhLWkZKWkcz?= =?utf-8?B?K2RrSzNYcnR5RUpjMWFGQmtWVW00U3NUN2xGdm0rbmtwVWFSVHZ0cVIxdnBx?= =?utf-8?B?bDlzclM3dEVZczB0YThLSEhoOUFRZ1o4M2k5elhZaktLQVg5eFA5RjFTdEdV?= =?utf-8?B?R2tqV08yLzE0aXl5RXhKL090Y1JCeHkydG50bkxpMGFuRExlSFdNRXd2ajNx?= =?utf-8?B?dEhSWEZLTkZrVGdNalFDT3hUVmxXa0k5MVhraE5nT1doa09udEVJNlBzNG52?= =?utf-8?B?azZuSFhSVnZrQjFkK205aXFBb3dObFBUUGhLdURlQU0wdkM4dTRVMmhkRFBm?= =?utf-8?B?WFZDMWdaaCt2UlVMSllsSzhFc1VDWDhtZjA4bEpTMTNrY3l3dkcwZ3FYLzFz?= =?utf-8?B?cmd0YjVjTlo2VW9vZ3pmYnlRNHR6YllwbmxXQmhjT1VJcHhCQnJEeVdadllj?= =?utf-8?B?OVBReTRZTXJVSnhnVlBlWThoZWEyb084dnkwRjVTMXZHaVBYMFcxMEwzYWF1?= =?utf-8?B?cXF6TS9kS3Y1S2doTUxHQmdTTCtDYUVweXh0MzhJSHRkeWdhMTZZU1NWN3NZ?= =?utf-8?B?blJLZTRyV2ljUVIybzJ4ZjJTK0Q2WkN3S1kwUlpucitxQWhWTytjYnRLeFRr?= =?utf-8?B?Q05oTFpvdWZIMHFKYlNhT3MwMU93SldjUzdQNHBuVC8yd1ZieEtQN0hMY3ZT?= =?utf-8?B?UkE9PQ==?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?VmV6L1VkekRjV1pBRjROK1p3ZUptcGc5S2NLaDNDVkVIbWNXTjRjajlEVmxJ?= =?utf-8?B?aC8vcXdxTldaZFBST1VyR3JuQ2VEaTBQb0pSdnJZd05oUTRRSTZOcUo2UGpU?= =?utf-8?B?WjRZMEF2SWhkRzVqTkVjYjY5U1ZQaFZhdDF2YWR1L0JHRk01YTZLVXU0MTJv?= =?utf-8?B?cVVZcWlEU3NqNnh0TUFXOVRSa1ZsQ1pUUmNtK0hCc004dWZ0ZWYyL28xenBP?= =?utf-8?B?K1hCUW1Scmp0VEluZzlSRERad2Y2SkZKMWNJVmJwRDM4NTg1UXZpaHZNV09X?= =?utf-8?B?V2N5Uk9LaWwvSjNJZDdFcmx3ZWd3ck02UU4yZldMSW1BRE13M0U2NHk3dGlG?= =?utf-8?B?eTNZUmtNeTFRTk00ek1hUkRZWkY5dnlnWWZqcEhSYitrbzNLbTNxQ0NYRkNI?= =?utf-8?B?ZTZTSHMzNzJOMU5SclFPN0txODZmcTBRQit5RENyRVBNWFkxRGliSDcyN0hG?= =?utf-8?B?Wks0VVNQekRHdTh6VElvVUtYdHB5SktTd2ttcThkQkx1Z2owYXpjZGRNTmdO?= =?utf-8?B?eXV5RzRoTit0Y1dQMnl0Smd3eXE5M0tjNXFIVXJkdmg5UkJybVdBNmt1YjRX?= =?utf-8?B?RVhrejJSUTM5dFVjR085Y0s2dCtDN1pJU3dmNlZoNitpYjRrNFlmNmdkeXhT?= =?utf-8?B?amdOcmYxaXY0RnBHbXVoK1BxenRSTHl6cDQ1cnFPM0R2ZWk0RGRCR2NZSUtI?= =?utf-8?B?Zis4OU1yL2RGQTlOVks1cEcwS2gyMkswK1padFBySVY5VGlLNjcxVnVxdTY1?= =?utf-8?B?c3RLbVEyOHFPcFNLOXlFZTNWTWtuZWpyNks0NVE4cDcvVzRJMDhjWUxtQjdo?= =?utf-8?B?WkFRdHdjRGFxSlJSaVZIT21sNldweGIyb015MnFudXE3VmRQeEF5ZTdYOWRW?= =?utf-8?B?bzhRMEd1bUVzdkppNnBHam8xUXVjY3ZDTWR3M3pZSWt6T2c4dmhjcVlKVXJF?= =?utf-8?B?YWRzRTNCdGxwZkU0a1EwdEpQR3JWQWVqYnQ4dCtFODB4a3RGZkRIV1d3TWJG?= =?utf-8?B?Vll6cUhmaDBEdlhTVDZsbnlQb1g5a1FycSttS1ZJWXQ2bTMrb0EwbCs5M1N1?= =?utf-8?B?OGgzcm1Sbk9oTk92SkQzdy94eDlSallwSFVLMVp1SGZmY053c3grOExiUnNl?= =?utf-8?B?UmxtWnNQTmZUQ3dIUFdjWjEzYmZFQW13OWhOQUt5eFRFRkd6cHNuMVNMQkN1?= =?utf-8?B?aExIZzJHT1BXelhseGVLQStqd0x4cUd1VjBpUklKeGtyTGpQbHV6RWlVY1RJ?= =?utf-8?B?ZmxndHRwWU4vVDdnb1FMMVZ6MElnUU9GOVNiN25pZVh0SW5zdTRJMXBMcWdp?= =?utf-8?B?TDFXTjJ3UVpyYlI3eVFQbGpDVXBrU0ZMYi9LRmpzNU1sRlRKdXl6Z2tvcWFG?= =?utf-8?B?UFlNdnBoV0Vqb0prc3oyUUZ5SnBKbDlELzBFeEhUeTFnZXc5VmNrUk5iMmMv?= =?utf-8?B?V2s2VENUZTMwV0VzNHA2REpObnVVbnIvZTQzczA3MDh2d0R6dXIwNXpkeTRv?= =?utf-8?B?RXlGYzN3OGFiNS9YRm90NlZ5dmRLRjFqVzFkK1ZNRHhOeFZzZ0RLWG9yM1Zn?= =?utf-8?B?RzU3U1NJa3lDL3FER1B0N3JiTzViN0owbnVENDhKTlhDS0RmekkzNVdYN1dq?= =?utf-8?B?TzBXNHAzVjBBRnJsbWI5bnloUTEwQWhKY2JHbG9mYWZjMXozZzArc2RHc2Yz?= =?utf-8?B?S3pEdmFza0huNEJFZWJNQ2k0NlRRdGRmMzY2cEZUdHVQdWw3NHM1aU9DTm5R?= =?utf-8?B?Q0FvaDNJdG9UMTBKbVA5eUE1SVAxcXJaZldrdEpmSGZDRnJGUmpUaVNYWkZZ?= =?utf-8?B?ZitWMWNBVTBvV0FKOWV2Y0FUejhpQ2J2QjlQZEVVdGRqYzJWelF5NDYrZTZq?= =?utf-8?B?Wi9JNHhKcG9qVFdVNXVPaEFqSjRsRXFhMXEzaFB4MmZOang3UnIxalN3TEFE?= =?utf-8?B?UE8ySGoxSUNwaFFteTg4bHQwZUUwbTN6YzJXaHoybTNsSnI1c1NiTGRRaVRQ?= =?utf-8?B?YVdOZkZHbzRseXBzY3pZTGhoVDlSY0UrZmRSLzFIUXVudnRPWWdKZEh3cnla?= =?utf-8?B?aTRlbFc0K3FRMkdyT0R2VHVYNXc4V0NCd3VYY0poVWIvYURNZWVOZUM1bGZi?= =?utf-8?B?QlExMFFjQVlQMDIvZnVBZ2ZBRlVTMVJSR2pmQkNud3BlOVBYTS91L21VTm9W?= =?utf-8?B?blpxbEprQmJjUy9YWkRCTUpjYlBsMHBBYjIwT2N5QTlmNi9qUWhndW0rbDVh?= =?utf-8?B?WGhrZUxrQjZRQVFVS0g5YVF2cVVlNWxqdE82TERCVzVDL1FVbXN2eHVpQjEy?= =?utf-8?B?ZE54SjkyT25jQlZ3emVxTTJBbW41THdUdmxUeVk2alYray9KZGU5MFUydlZN?= =?utf-8?Q?FSKImSYxCzFznLJQmx8fe7JvzkOEHdRtvRbDkjL3D16RB?= X-MS-Exchange-AntiSpam-MessageData-1: lOyOcSrf4pj/Mg== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6d6010ec-7b1c-4933-17ff-08de73b02b5b X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 14:22:41.6331 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: oLInRP5jENHEZ37Odo1naJ95NyoOFBMqsF78rTOe1c6xZYyFpjtfgdwTvKxPaEmnJ+SKCCzz+ovpztezC+TsJQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7811 Replace the nova-core internal `register!` macro by the one defined in the `kernel` crate and remove our own private implementations. Signed-off-by: Alexandre Courbot Tested-by: Dirk Behme --- drivers/gpu/nova-core/falcon.rs | 249 +++++----- drivers/gpu/nova-core/falcon/gsp.rs | 23 +- drivers/gpu/nova-core/falcon/hal/ga102.rs | 65 +-- drivers/gpu/nova-core/falcon/hal/tu102.rs | 11 +- drivers/gpu/nova-core/falcon/sec2.rs | 17 +- drivers/gpu/nova-core/fb.rs | 6 +- drivers/gpu/nova-core/fb/hal/ga100.rs | 40 +- drivers/gpu/nova-core/fb/hal/ga102.rs | 7 +- drivers/gpu/nova-core/fb/hal/tu102.rs | 22 +- drivers/gpu/nova-core/gfw.rs | 11 +- drivers/gpu/nova-core/gpu.rs | 36 +- drivers/gpu/nova-core/gsp/boot.rs | 11 +- drivers/gpu/nova-core/gsp/cmdq.rs | 10 +- drivers/gpu/nova-core/regs.rs | 544 ++++++++++++---------- drivers/gpu/nova-core/regs/macros.rs | 739 --------------------------= ---- 15 files changed, 565 insertions(+), 1226 deletions(-) diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon= .rs index 37bfee1d0949..140f00185115 100644 --- a/drivers/gpu/nova-core/falcon.rs +++ b/drivers/gpu/nova-core/falcon.rs @@ -12,7 +12,13 @@ DmaAddress, DmaMask, // }, - io::poll::read_poll_timeout, + io::{ + poll::read_poll_timeout, + register::RegisterBase, + Io, + IoLoc, // + }, + num::Bounded, prelude::*, sync::aref::ARef, time::{ @@ -30,7 +36,6 @@ IntoSafeCast, // }, regs, - regs::macros::RegisterBase, // }; =20 pub(crate) mod gsp; @@ -38,11 +43,11 @@ pub(crate) mod sec2; =20 // TODO[FPRI]: Replace with `ToPrimitive`. -macro_rules! impl_from_enum_to_u8 { - ($enum_type:ty) =3D> { - impl From<$enum_type> for u8 { +macro_rules! impl_from_enum_to_bounded { + ($enum_type:ty, $length:literal) =3D> { + impl From<$enum_type> for Bounded { fn from(value: $enum_type) -> Self { - value as u8 + Bounded::from_expr(value as u32) } } }; @@ -50,10 +55,8 @@ fn from(value: $enum_type) -> Self { =20 /// Revision number of a falcon core, used in the [`crate::regs::NV_PFALCO= N_FALCON_HWCFG1`] /// register. -#[repr(u8)] -#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub(crate) enum FalconCoreRev { - #[default] Rev1 =3D 1, Rev2 =3D 2, Rev3 =3D 3, @@ -62,16 +65,16 @@ pub(crate) enum FalconCoreRev { Rev6 =3D 6, Rev7 =3D 7, } -impl_from_enum_to_u8!(FalconCoreRev); +impl_from_enum_to_bounded!(FalconCoreRev, 4); =20 // TODO[FPRI]: replace with `FromPrimitive`. -impl TryFrom for FalconCoreRev { +impl TryFrom> for FalconCoreRev { type Error =3D Error; =20 - fn try_from(value: u8) -> Result { + fn try_from(value: Bounded) -> Result { use FalconCoreRev::*; =20 - let rev =3D match value { + let rev =3D match value.get() { 1 =3D> Rev1, 2 =3D> Rev2, 3 =3D> Rev3, @@ -88,46 +91,38 @@ fn try_from(value: u8) -> Result { =20 /// Revision subversion number of a falcon core, used in the /// [`crate::regs::NV_PFALCON_FALCON_HWCFG1`] register. -#[repr(u8)] -#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] pub(crate) enum FalconCoreRevSubversion { - #[default] Subversion0 =3D 0, Subversion1 =3D 1, Subversion2 =3D 2, Subversion3 =3D 3, } -impl_from_enum_to_u8!(FalconCoreRevSubversion); +impl_from_enum_to_bounded!(FalconCoreRevSubversion, 2); =20 // TODO[FPRI]: replace with `FromPrimitive`. -impl TryFrom for FalconCoreRevSubversion { - type Error =3D Error; - - fn try_from(value: u8) -> Result { +impl From> for FalconCoreRevSubversion { + fn from(value: Bounded) -> Self { use FalconCoreRevSubversion::*; =20 - let sub_version =3D match value & 0b11 { + match value.get() { 0 =3D> Subversion0, 1 =3D> Subversion1, 2 =3D> Subversion2, 3 =3D> Subversion3, - _ =3D> return Err(EINVAL), - }; - - Ok(sub_version) + // SAFETY: `value` comes from a 2-bit `Bounded`, and we just c= hecked all possible + // values. + _ =3D> unsafe { core::hint::unreachable_unchecked() }, + } } } =20 -/// Security model of a falcon core, used in the [`crate::regs::NV_PFALCON= _FALCON_HWCFG1`] -/// register. -#[repr(u8)] -#[derive(Debug, Default, Copy, Clone)] /// Security mode of the Falcon microprocessor. /// /// See `falcon.rst` for more details. +#[derive(Debug, Copy, Clone)] pub(crate) enum FalconSecurityModel { /// Non-Secure: runs unsigned code without privileges. - #[default] None =3D 0, /// Light-Secured (LS): Runs signed code with some privileges. /// Entry into this mode is only possible from 'Heavy-secure' mode, wh= ich verifies the code's @@ -141,16 +136,16 @@ pub(crate) enum FalconSecurityModel { /// Also known as High-Secure, Privilege Level 3 or PL3. Heavy =3D 3, } -impl_from_enum_to_u8!(FalconSecurityModel); +impl_from_enum_to_bounded!(FalconSecurityModel, 2); =20 // TODO[FPRI]: replace with `FromPrimitive`. -impl TryFrom for FalconSecurityModel { +impl TryFrom> for FalconSecurityModel { type Error =3D Error; =20 - fn try_from(value: u8) -> Result { + fn try_from(value: Bounded) -> Result { use FalconSecurityModel::*; =20 - let sec_model =3D match value { + let sec_model =3D match value.get() { 0 =3D> None, 2 =3D> Light, 3 =3D> Heavy, @@ -163,24 +158,22 @@ fn try_from(value: u8) -> Result { =20 /// Signing algorithm for a given firmware, used in the [`crate::regs::NV_= PFALCON2_FALCON_MOD_SEL`] /// register. It is passed to the Falcon Boot ROM (BROM) as a parameter. -#[repr(u8)] -#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub(crate) enum FalconModSelAlgo { /// AES. - #[expect(dead_code)] Aes =3D 0, /// RSA3K. - #[default] Rsa3k =3D 1, } -impl_from_enum_to_u8!(FalconModSelAlgo); +impl_from_enum_to_bounded!(FalconModSelAlgo, 8); =20 // TODO[FPRI]: replace with `FromPrimitive`. -impl TryFrom for FalconModSelAlgo { +impl TryFrom> for FalconModSelAlgo { type Error =3D Error; =20 - fn try_from(value: u8) -> Result { - match value { + fn try_from(value: Bounded) -> Result { + match value.get() { + 0 =3D> Ok(FalconModSelAlgo::Aes), 1 =3D> Ok(FalconModSelAlgo::Rsa3k), _ =3D> Err(EINVAL), } @@ -188,21 +181,19 @@ fn try_from(value: u8) -> Result { } =20 /// Valid values for the `size` field of the [`crate::regs::NV_PFALCON_FAL= CON_DMATRFCMD`] register. -#[repr(u8)] -#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub(crate) enum DmaTrfCmdSize { /// 256 bytes transfer. - #[default] Size256B =3D 0x6, } -impl_from_enum_to_u8!(DmaTrfCmdSize); +impl_from_enum_to_bounded!(DmaTrfCmdSize, 3); =20 // TODO[FPRI]: replace with `FromPrimitive`. -impl TryFrom for DmaTrfCmdSize { +impl TryFrom> for DmaTrfCmdSize { type Error =3D Error; =20 - fn try_from(value: u8) -> Result { - match value { + fn try_from(value: Bounded) -> Result { + match value.get() { 0x6 =3D> Ok(Self::Size256B), _ =3D> Err(EINVAL), } @@ -210,33 +201,24 @@ fn try_from(value: u8) -> Result { } =20 /// Currently active core on a dual falcon/riscv (Peregrine) controller. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum PeregrineCoreSelect { /// Falcon core is active. - #[default] Falcon =3D 0, /// RISC-V core is active. Riscv =3D 1, } +impl_from_enum_to_bounded!(PeregrineCoreSelect, 1); =20 -impl From for PeregrineCoreSelect { - fn from(value: bool) -> Self { - match value { +impl From> for PeregrineCoreSelect { + fn from(value: Bounded) -> Self { + match bool::from(value) { false =3D> PeregrineCoreSelect::Falcon, true =3D> PeregrineCoreSelect::Riscv, } } } =20 -impl From for bool { - fn from(value: PeregrineCoreSelect) -> Self { - match value { - PeregrineCoreSelect::Falcon =3D> false, - PeregrineCoreSelect::Riscv =3D> true, - } - } -} - /// Different types of memory present in a falcon core. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub(crate) enum FalconMem { @@ -252,10 +234,8 @@ pub(crate) enum FalconMem { /// Defines the Framebuffer Interface (FBIF) aperture type. /// This determines the memory type for external memory access during a DM= A transfer, which is /// performed by the Falcon's Framebuffer DMA (FBDMA) engine. See falcon.r= st for more details. -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone)] pub(crate) enum FalconFbifTarget { - /// VRAM. - #[default] /// Local Framebuffer (GPU's VRAM memory). LocalFb =3D 0, /// Coherent system memory (System DRAM). @@ -263,14 +243,14 @@ pub(crate) enum FalconFbifTarget { /// Non-coherent system memory (System DRAM). NoncoherentSysmem =3D 2, } -impl_from_enum_to_u8!(FalconFbifTarget); +impl_from_enum_to_bounded!(FalconFbifTarget, 2); =20 // TODO[FPRI]: replace with `FromPrimitive`. -impl TryFrom for FalconFbifTarget { +impl TryFrom> for FalconFbifTarget { type Error =3D Error; =20 - fn try_from(value: u8) -> Result { - let res =3D match value { + fn try_from(value: Bounded) -> Result { + let res =3D match value.get() { 0 =3D> Self::LocalFb, 1 =3D> Self::CoherentSysmem, 2 =3D> Self::NoncoherentSysmem, @@ -282,34 +262,25 @@ fn try_from(value: u8) -> Result { } =20 /// Type of memory addresses to use. -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone)] pub(crate) enum FalconFbifMemType { /// Virtual memory addresses. - #[default] Virtual =3D 0, /// Physical memory addresses. Physical =3D 1, } +impl_from_enum_to_bounded!(FalconFbifMemType, 1); =20 /// Conversion from a single-bit register field. -impl From for FalconFbifMemType { - fn from(value: bool) -> Self { - match value { +impl From> for FalconFbifMemType { + fn from(value: Bounded) -> Self { + match bool::from(value) { false =3D> Self::Virtual, true =3D> Self::Physical, } } } =20 -impl From for bool { - fn from(value: FalconFbifMemType) -> Self { - match value { - FalconFbifMemType::Virtual =3D> false, - FalconFbifMemType::Physical =3D> true, - } - } -} - /// Type used to represent the `PFALCON` registers address base for a give= n falcon engine. pub(crate) struct PFalconBase(()); =20 @@ -318,13 +289,10 @@ fn from(value: FalconFbifMemType) -> Self { =20 /// Trait defining the parameters of a given Falcon engine. /// -/// Each engine provides one base for `PFALCON` and `PFALCON2` registers. = The `ID` constant is used -/// to identify a given Falcon instance with register I/O methods. +/// Each engine provides one base for `PFALCON` and `PFALCON2` registers. pub(crate) trait FalconEngine: Send + Sync + RegisterBase + RegisterBase += Sized { - /// Singleton of the engine, used to identify it with register I/O met= hods. - const ID: Self; } =20 /// Represents a portion of the firmware to be loaded into a particular me= mory (e.g. IMEM or DMEM). @@ -394,8 +362,10 @@ pub(crate) fn new(dev: &device::Device, chipset: Chips= et) -> Result { =20 /// Resets DMA-related registers. pub(crate) fn dma_reset(&self, bar: &Bar0) { - regs::NV_PFALCON_FBIF_CTL::update(bar, &E::ID, |v| v.set_allow_phy= s_no_ctx(true)); - regs::NV_PFALCON_FALCON_DMACTL::default().write(bar, &E::ID); + bar.update(regs::NV_PFALCON_FBIF_CTL::of::(), |v| { + v.with_allow_phys_no_ctx(true) + }); + bar.write(regs::NV_PFALCON_FALCON_DMACTL::of::().zeroed()); } =20 /// Reset the controller, select the falcon core, and wait for memory = scrubbing to complete. @@ -404,9 +374,10 @@ pub(crate) fn reset(&self, bar: &Bar0) -> Result { self.hal.select_core(self, bar)?; self.hal.reset_wait_mem_scrubbing(bar)?; =20 - regs::NV_PFALCON_FALCON_RM::default() - .set_value(regs::NV_PMC_BOOT_0::read(bar).into()) - .write(bar, &E::ID); + bar.write( + regs::NV_PFALCON_FALCON_RM::of::() + .init(|r| r.with_value(bar.read(regs::NV_PMC_BOOT_0).into_= raw())), + ); =20 Ok(()) } @@ -475,36 +446,37 @@ fn dma_wr>( =20 // Set up the base source DMA address. =20 - regs::NV_PFALCON_FALCON_DMATRFBASE::default() - // CAST: `as u32` is used on purpose since we do want to strip= the upper bits, which - // will be written to `NV_PFALCON_FALCON_DMATRFBASE1`. - .set_base((dma_start >> 8) as u32) - .write(bar, &E::ID); - regs::NV_PFALCON_FALCON_DMATRFBASE1::default() - // CAST: `as u16` is used on purpose since the remaining bits = are guaranteed to fit - // within a `u16`. - .set_base((dma_start >> 40) as u16) - .write(bar, &E::ID); + bar.write(regs::NV_PFALCON_FALCON_DMATRFBASE::of::().init(|r| + // CAST: `as u32` is used on purpose since we do want = to strip the upper bits, + // which will be written to `NV_PFALCON_FALCON_DMATRFB= ASE1`. + r.with_base((dma_start >> 8) as u32))); + bar.write( + regs::NV_PFALCON_FALCON_DMATRFBASE1::of::() + .try_init(|r| r.try_with_base(dma_start >> 40))?, + ); =20 - let cmd =3D regs::NV_PFALCON_FALCON_DMATRFCMD::default() - .set_size(DmaTrfCmdSize::Size256B) + let cmd =3D regs::NV_PFALCON_FALCON_DMATRFCMD::zeroed() + .with_size(DmaTrfCmdSize::Size256B) .with_falcon_mem(target_mem); =20 for pos in (0..num_transfers).map(|i| i * DMA_LEN) { // Perform a transfer of size `DMA_LEN`. - regs::NV_PFALCON_FALCON_DMATRFMOFFS::default() - .set_offs(load_offsets.dst_start + pos) - .write(bar, &E::ID); - regs::NV_PFALCON_FALCON_DMATRFFBOFFS::default() - .set_offs(src_start + pos) - .write(bar, &E::ID); - cmd.write(bar, &E::ID); + bar.write( + regs::NV_PFALCON_FALCON_DMATRFMOFFS::of::() + .try_init(|r| r.try_with_offs(load_offsets.dst_start += pos))?, + ); + bar.write( + regs::NV_PFALCON_FALCON_DMATRFFBOFFS::of::() + .init(|r| r.with_offs(src_start + pos)), + ); + + bar.write(regs::NV_PFALCON_FALCON_DMATRFCMD::of::().set(cmd= )); =20 // Wait for the transfer to complete. // TIMEOUT: arbitrarily large value, no DMA transfer to the fa= lcon's small memories // should ever take that long. read_poll_timeout( - || Ok(regs::NV_PFALCON_FALCON_DMATRFCMD::read(bar, &E::ID)= ), + || Ok(bar.read(regs::NV_PFALCON_FALCON_DMATRFCMD::of::(= ))), |r| r.idle(), Delta::ZERO, Delta::from_secs(2), @@ -524,9 +496,9 @@ fn dma_load>(&self, bar= : &Bar0, fw: &F) -> Result } =20 self.dma_reset(bar); - regs::NV_PFALCON_FBIF_TRANSCFG::update(bar, &E::ID, 0, |v| { - v.set_target(FalconFbifTarget::CoherentSysmem) - .set_mem_type(FalconFbifMemType::Physical) + bar.update(regs::NV_PFALCON_FBIF_TRANSCFG::of::().at(0), |v| { + v.with_target(FalconFbifTarget::CoherentSysmem) + .with_mem_type(FalconFbifMemType::Physical) }); =20 self.dma_wr(bar, fw, FalconMem::ImemSecure, fw.imem_sec_load_param= s())?; @@ -535,9 +507,9 @@ fn dma_load>(&self, bar= : &Bar0, fw: &F) -> Result self.hal.program_brom(self, bar, &fw.brom_params())?; =20 // Set `BootVec` to start of non-secure code. - regs::NV_PFALCON_FALCON_BOOTVEC::default() - .set_value(fw.boot_addr()) - .write(bar, &E::ID); + bar.write( + regs::NV_PFALCON_FALCON_BOOTVEC::of::().init(|r| r.with_val= ue(fw.boot_addr())), + ); =20 Ok(()) } @@ -546,7 +518,7 @@ fn dma_load>(&self, bar= : &Bar0, fw: &F) -> Result pub(crate) fn wait_till_halted(&self, bar: &Bar0) -> Result<()> { // TIMEOUT: arbitrarily large value, firmwares should complete in = less than 2 seconds. read_poll_timeout( - || Ok(regs::NV_PFALCON_FALCON_CPUCTL::read(bar, &E::ID)), + || Ok(bar.read(regs::NV_PFALCON_FALCON_CPUCTL::of::())), |r| r.halted(), Delta::ZERO, Delta::from_secs(2), @@ -557,13 +529,16 @@ pub(crate) fn wait_till_halted(&self, bar: &Bar0) -> = Result<()> { =20 /// Start the falcon CPU. pub(crate) fn start(&self, bar: &Bar0) -> Result<()> { - match regs::NV_PFALCON_FALCON_CPUCTL::read(bar, &E::ID).alias_en()= { - true =3D> regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::default() - .set_startcpu(true) - .write(bar, &E::ID), - false =3D> regs::NV_PFALCON_FALCON_CPUCTL::default() - .set_startcpu(true) - .write(bar, &E::ID), + match bar + .read(regs::NV_PFALCON_FALCON_CPUCTL::of::()) + .alias_en() + { + true =3D> bar.write( + regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::of::().init(|r| r= .with_startcpu(true)), + ), + false =3D> { + bar.write(regs::NV_PFALCON_FALCON_CPUCTL::of::().init(|= r| r.with_startcpu(true))) + } } =20 Ok(()) @@ -572,26 +547,24 @@ pub(crate) fn start(&self, bar: &Bar0) -> Result<()> { /// Writes values to the mailbox registers if provided. pub(crate) fn write_mailboxes(&self, bar: &Bar0, mbox0: Option, m= box1: Option) { if let Some(mbox0) =3D mbox0 { - regs::NV_PFALCON_FALCON_MAILBOX0::default() - .set_value(mbox0) - .write(bar, &E::ID); + bar.write(regs::NV_PFALCON_FALCON_MAILBOX0::of::().init(|r|= r.with_value(mbox0))); } =20 if let Some(mbox1) =3D mbox1 { - regs::NV_PFALCON_FALCON_MAILBOX1::default() - .set_value(mbox1) - .write(bar, &E::ID); + bar.write(regs::NV_PFALCON_FALCON_MAILBOX1::of::().init(|r|= r.with_value(mbox1))); } } =20 /// Reads the value from `mbox0` register. pub(crate) fn read_mailbox0(&self, bar: &Bar0) -> u32 { - regs::NV_PFALCON_FALCON_MAILBOX0::read(bar, &E::ID).value() + bar.read(regs::NV_PFALCON_FALCON_MAILBOX0::of::()) + .value() } =20 /// Reads the value from `mbox1` register. pub(crate) fn read_mailbox1(&self, bar: &Bar0) -> u32 { - regs::NV_PFALCON_FALCON_MAILBOX1::read(bar, &E::ID).value() + bar.read(regs::NV_PFALCON_FALCON_MAILBOX1::of::()) + .value() } =20 /// Reads values from both mailbox registers. @@ -650,8 +623,6 @@ pub(crate) fn load>(&se= lf, bar: &Bar0, fw: &F) -> =20 /// Write the application version to the OS register. pub(crate) fn write_os_version(&self, bar: &Bar0, app_version: u32) { - regs::NV_PFALCON_FALCON_OS::default() - .set_value(app_version) - .write(bar, &E::ID); + bar.write(regs::NV_PFALCON_FALCON_OS::of::().init(|r| r.with_va= lue(app_version))); } } diff --git a/drivers/gpu/nova-core/falcon/gsp.rs b/drivers/gpu/nova-core/fa= lcon/gsp.rs index 67edef3636c1..40330ce3a617 100644 --- a/drivers/gpu/nova-core/falcon/gsp.rs +++ b/drivers/gpu/nova-core/falcon/gsp.rs @@ -1,7 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 =20 use kernel::{ - io::poll::read_poll_timeout, + io::{ + poll::read_poll_timeout, + register::RegisterBase, + Io, + IoLoc, // + }, prelude::*, time::Delta, // }; @@ -14,13 +19,9 @@ PFalcon2Base, PFalconBase, // }, - regs::{ - self, - macros::RegisterBase, // - }, + regs, }; =20 -/// Type specifying the `Gsp` falcon engine. Cannot be instantiated. pub(crate) struct Gsp(()); =20 impl RegisterBase for Gsp { @@ -31,23 +32,19 @@ impl RegisterBase for Gsp { const BASE: usize =3D 0x00111000; } =20 -impl FalconEngine for Gsp { - const ID: Self =3D Gsp(()); -} +impl FalconEngine for Gsp {} =20 impl Falcon { /// Clears the SWGEN0 bit in the Falcon's IRQ status clear register to /// allow GSP to signal CPU for processing new messages in message que= ue. pub(crate) fn clear_swgen0_intr(&self, bar: &Bar0) { - regs::NV_PFALCON_FALCON_IRQSCLR::default() - .set_swgen0(true) - .write(bar, &Gsp::ID); + bar.write(regs::NV_PFALCON_FALCON_IRQSCLR::of::().init(|r| r.= with_swgen0(true))); } =20 /// Checks if GSP reload/resume has completed during the boot process. pub(crate) fn check_reload_completed(&self, bar: &Bar0, timeout: Delta= ) -> Result { read_poll_timeout( - || Ok(regs::NV_PGC6_BSI_SECURE_SCRATCH_14::read(bar)), + || Ok(bar.read(regs::NV_PGC6_BSI_SECURE_SCRATCH_14)), |val| val.boot_stage_3_handoff(), Delta::ZERO, timeout, diff --git a/drivers/gpu/nova-core/falcon/hal/ga102.rs b/drivers/gpu/nova-c= ore/falcon/hal/ga102.rs index 8f62df10da0a..ec15c096d62e 100644 --- a/drivers/gpu/nova-core/falcon/hal/ga102.rs +++ b/drivers/gpu/nova-core/falcon/hal/ga102.rs @@ -5,6 +5,8 @@ use kernel::{ device, io::poll::read_poll_timeout, + io::Io, + io::IoLoc, prelude::*, time::Delta, // }; @@ -25,15 +27,16 @@ use super::FalconHal; =20 fn select_core_ga102(bar: &Bar0) -> Result { - let bcr_ctrl =3D regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID); + let bcr_ctrl =3D bar.read(regs::NV_PRISCV_RISCV_BCR_CTRL::of::()); if bcr_ctrl.core_select() !=3D PeregrineCoreSelect::Falcon { - regs::NV_PRISCV_RISCV_BCR_CTRL::default() - .set_core_select(PeregrineCoreSelect::Falcon) - .write(bar, &E::ID); + bar.write( + regs::NV_PRISCV_RISCV_BCR_CTRL::of::() + .init(|r| r.with_core_select(PeregrineCoreSelect::Falcon)), + ); =20 // TIMEOUT: falcon core should take less than 10ms to report being= enabled. read_poll_timeout( - || Ok(regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID)), + || Ok(bar.read(regs::NV_PRISCV_RISCV_BCR_CTRL::of::())), |r| r.valid(), Delta::ZERO, Delta::from_millis(10), @@ -60,34 +63,42 @@ fn signature_reg_fuse_version_ga102( =20 // `ucode_idx` is guaranteed to be in the range [0..15], making the `r= ead` calls provable valid // at build-time. - let reg_fuse_version =3D if engine_id_mask & 0x0001 !=3D 0 { - regs::NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION::read(bar, ucode_idx).da= ta() + let reg_fuse_version: u16 =3D if engine_id_mask & 0x0001 !=3D 0 { + bar.read(regs::NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION::at(ucode_idx)) + .data() } else if engine_id_mask & 0x0004 !=3D 0 { - regs::NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION::read(bar, ucode_idx).d= ata() + bar.read(regs::NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION::at(ucode_idx)) + .data() } else if engine_id_mask & 0x0400 !=3D 0 { - regs::NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION::read(bar, ucode_idx).dat= a() + bar.read(regs::NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION::at(ucode_idx)) + .data() } else { dev_err!(dev, "unexpected engine_id_mask {:#x}\n", engine_id_mask); return Err(EINVAL); - }; + } + .into(); =20 // TODO[NUMM]: replace with `last_set_bit` once it lands. Ok(u16::BITS - reg_fuse_version.leading_zeros()) } =20 fn program_brom_ga102(bar: &Bar0, params: &FalconBromPara= ms) -> Result { - regs::NV_PFALCON2_FALCON_BROM_PARAADDR::default() - .set_value(params.pkc_data_offset) - .write(bar, &E::ID, 0); - regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::default() - .set_value(u32::from(params.engine_id_mask)) - .write(bar, &E::ID); - regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::default() - .set_ucode_id(params.ucode_id) - .write(bar, &E::ID); - regs::NV_PFALCON2_FALCON_MOD_SEL::default() - .set_algo(FalconModSelAlgo::Rsa3k) - .write(bar, &E::ID); + bar.write( + regs::NV_PFALCON2_FALCON_BROM_PARAADDR::of::() + .at(0) + .init(|r| r.with_value(params.pkc_data_offset)), + ); + bar.write( + regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::of::() + .init(|r| r.with_value(u32::from(params.engine_id_mask))), + ); + bar.write( + regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::of::() + .init(|r| r.with_ucode_id(params.ucode_id)), + ); + bar.write( + regs::NV_PFALCON2_FALCON_MOD_SEL::of::().init(|r| r.with_algo(F= alconModSelAlgo::Rsa3k)), + ); =20 Ok(()) } @@ -120,14 +131,14 @@ fn program_brom(&self, _falcon: &Falcon, bar: &Bar= 0, params: &FalconBromParam } =20 fn is_riscv_active(&self, bar: &Bar0) -> bool { - let cpuctl =3D regs::NV_PRISCV_RISCV_CPUCTL::read(bar, &E::ID); - cpuctl.active_stat() + bar.read(regs::NV_PRISCV_RISCV_CPUCTL::of::()) + .active_stat() } =20 fn reset_wait_mem_scrubbing(&self, bar: &Bar0) -> Result { // TIMEOUT: memory scrubbing should complete in less than 20ms. read_poll_timeout( - || Ok(regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID)), + || Ok(bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::())), |r| r.mem_scrubbing_done(), Delta::ZERO, Delta::from_millis(20), @@ -136,12 +147,12 @@ fn reset_wait_mem_scrubbing(&self, bar: &Bar0) -> Res= ult { } =20 fn reset_eng(&self, bar: &Bar0) -> Result { - let _ =3D regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID); + let _ =3D bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::()); =20 // According to OpenRM's `kflcnPreResetWait_GA102` documentation, = HW sometimes does not set // RESET_READY so a non-failing timeout is used. let _ =3D read_poll_timeout( - || Ok(regs::NV_PFALCON_FALCON_HWCFG2::read(bar, &E::ID)), + || Ok(bar.read(regs::NV_PFALCON_FALCON_HWCFG2::of::())), |r| r.reset_ready(), Delta::ZERO, Delta::from_micros(150), diff --git a/drivers/gpu/nova-core/falcon/hal/tu102.rs b/drivers/gpu/nova-c= ore/falcon/hal/tu102.rs index 7de6f24cc0a0..cd4ac53e32af 100644 --- a/drivers/gpu/nova-core/falcon/hal/tu102.rs +++ b/drivers/gpu/nova-core/falcon/hal/tu102.rs @@ -3,7 +3,10 @@ use core::marker::PhantomData; =20 use kernel::{ - io::poll::read_poll_timeout, + io::{ + poll::read_poll_timeout, + Io, // + }, prelude::*, time::Delta, // }; @@ -49,14 +52,14 @@ fn program_brom(&self, _falcon: &Falcon, _bar: &Bar0= , _params: &FalconBromPar } =20 fn is_riscv_active(&self, bar: &Bar0) -> bool { - let cpuctl =3D regs::NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS::rea= d(bar, &E::ID); - cpuctl.active_stat() + bar.read(regs::NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS::of::()) + .active_stat() } =20 fn reset_wait_mem_scrubbing(&self, bar: &Bar0) -> Result { // TIMEOUT: memory scrubbing should complete in less than 10ms. read_poll_timeout( - || Ok(regs::NV_PFALCON_FALCON_DMACTL::read(bar, &E::ID)), + || Ok(bar.read(regs::NV_PFALCON_FALCON_DMACTL::of::())), |r| r.mem_scrubbing_done(), Delta::ZERO, Delta::from_millis(10), diff --git a/drivers/gpu/nova-core/falcon/sec2.rs b/drivers/gpu/nova-core/f= alcon/sec2.rs index b57d362e576a..91ec7d49c1f5 100644 --- a/drivers/gpu/nova-core/falcon/sec2.rs +++ b/drivers/gpu/nova-core/falcon/sec2.rs @@ -1,12 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 =20 -use crate::{ - falcon::{ - FalconEngine, - PFalcon2Base, - PFalconBase, // - }, - regs::macros::RegisterBase, +use kernel::io::register::RegisterBase; + +use crate::falcon::{ + FalconEngine, + PFalcon2Base, + PFalconBase, // }; =20 /// Type specifying the `Sec2` falcon engine. Cannot be instantiated. @@ -20,6 +19,4 @@ impl RegisterBase for Sec2 { const BASE: usize =3D 0x00841000; } =20 -impl FalconEngine for Sec2 { - const ID: Self =3D Sec2(()); -} +impl FalconEngine for Sec2 {} diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs index c62abcaed547..6b392588f766 100644 --- a/drivers/gpu/nova-core/fb.rs +++ b/drivers/gpu/nova-core/fb.rs @@ -4,6 +4,7 @@ =20 use kernel::{ device, + io::Io, prelude::*, ptr::{ Alignable, @@ -134,7 +135,10 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw= : &GspFirmware) -> Result< let base =3D fb.end - NV_PRAMIN_SIZE; =20 if hal.supports_display(bar) { - match regs::NV_PDISP_VGA_WORKSPACE_BASE::read(bar).vga= _workspace_addr() { + match bar + .read(regs::NV_PDISP_VGA_WORKSPACE_BASE) + .vga_workspace_addr() + { Some(addr) =3D> { if addr < base { const VBIOS_WORKSPACE_SIZE: u64 =3D usize_= as_u64(SZ_128K); diff --git a/drivers/gpu/nova-core/fb/hal/ga100.rs b/drivers/gpu/nova-core/= fb/hal/ga100.rs index e0acc41aa7cd..9deb0a32b7b9 100644 --- a/drivers/gpu/nova-core/fb/hal/ga100.rs +++ b/drivers/gpu/nova-core/fb/hal/ga100.rs @@ -1,6 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 =20 -use kernel::prelude::*; +use kernel::{ + io::{ + Io, + IoLoc, // + }, + num::Bounded, + prelude::*, // +}; =20 use crate::{ driver::Bar0, @@ -13,26 +20,31 @@ struct Ga100; =20 pub(super) fn read_sysmem_flush_page_ga100(bar: &Bar0) -> u64 { - u64::from(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::read(bar).adr_39_08()) = << FLUSH_SYSMEM_ADDR_SHIFT - | u64::from(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI::read(bar).adr_= 63_40()) + u64::from(bar.read(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR).adr_39_08()) <= < FLUSH_SYSMEM_ADDR_SHIFT + | u64::from(bar.read(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI).adr_6= 3_40()) << FLUSH_SYSMEM_ADDR_SHIFT_HI } =20 pub(super) fn write_sysmem_flush_page_ga100(bar: &Bar0, addr: u64) { - regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI::default() - // CAST: `as u32` is used on purpose since the remaining bits are = guaranteed to fit within - // a `u32`. - .set_adr_63_40((addr >> FLUSH_SYSMEM_ADDR_SHIFT_HI) as u32) - .write(bar); - regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default() - // CAST: `as u32` is used on purpose since we want to strip the up= per bits that have been - // written to `NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI`. - .set_adr_39_08((addr >> FLUSH_SYSMEM_ADDR_SHIFT) as u32) - .write(bar); + bar.write(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI.init(|r| { + r.with_adr_63_40( + Bounded::::from(addr) + .shr::() + .cast(), + ) + })); + + bar.write( + regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR + // CAST: `as u32` is used on purpose since we want to strip th= e upper bits that have + // been written to `NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI`. + .init(|r| r.with_adr_39_08((addr >> FLUSH_SYSMEM_ADDR_SHIFT) a= s u32)), + ); } =20 pub(super) fn display_enabled_ga100(bar: &Bar0) -> bool { - !regs::ga100::NV_FUSE_STATUS_OPT_DISPLAY::read(bar).display_disabled() + !bar.read(regs::ga100::NV_FUSE_STATUS_OPT_DISPLAY) + .display_disabled() } =20 /// Shift applied to the sysmem address before it is written into diff --git a/drivers/gpu/nova-core/fb/hal/ga102.rs b/drivers/gpu/nova-core/= fb/hal/ga102.rs index 734605905031..4b9f0f74d0e7 100644 --- a/drivers/gpu/nova-core/fb/hal/ga102.rs +++ b/drivers/gpu/nova-core/fb/hal/ga102.rs @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 =20 -use kernel::prelude::*; +use kernel::{ + io::Io, + prelude::*, // +}; =20 use crate::{ driver::Bar0, @@ -9,7 +12,7 @@ }; =20 fn vidmem_size_ga102(bar: &Bar0) -> u64 { - regs::NV_USABLE_FB_SIZE_IN_MB::read(bar).usable_fb_size() + bar.read(regs::NV_USABLE_FB_SIZE_IN_MB).usable_fb_size() } =20 struct Ga102; diff --git a/drivers/gpu/nova-core/fb/hal/tu102.rs b/drivers/gpu/nova-core/= fb/hal/tu102.rs index eec984f4e816..67327adaa04f 100644 --- a/drivers/gpu/nova-core/fb/hal/tu102.rs +++ b/drivers/gpu/nova-core/fb/hal/tu102.rs @@ -1,6 +1,12 @@ // SPDX-License-Identifier: GPL-2.0 =20 -use kernel::prelude::*; +use kernel::{ + io::{ + Io, + IoLoc, // + }, + prelude::*, // +}; =20 use crate::{ driver::Bar0, @@ -13,26 +19,24 @@ pub(super) const FLUSH_SYSMEM_ADDR_SHIFT: u32 =3D 8; =20 pub(super) fn read_sysmem_flush_page_gm107(bar: &Bar0) -> u64 { - u64::from(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::read(bar).adr_39_08()) = << FLUSH_SYSMEM_ADDR_SHIFT + u64::from(bar.read(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR).adr_39_08()) <= < FLUSH_SYSMEM_ADDR_SHIFT } =20 pub(super) fn write_sysmem_flush_page_gm107(bar: &Bar0, addr: u64) -> Resu= lt { // Check that the address doesn't overflow the receiving 32-bit regist= er. u32::try_from(addr >> FLUSH_SYSMEM_ADDR_SHIFT) .map_err(|_| EINVAL) - .map(|addr| { - regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default() - .set_adr_39_08(addr) - .write(bar) - }) + .map(|addr| bar.write(regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR.init(|r|= r.with_adr_39_08(addr)))) } =20 pub(super) fn display_enabled_gm107(bar: &Bar0) -> bool { - !regs::gm107::NV_FUSE_STATUS_OPT_DISPLAY::read(bar).display_disabled() + !bar.read(regs::gm107::NV_FUSE_STATUS_OPT_DISPLAY) + .display_disabled() } =20 pub(super) fn vidmem_size_gp102(bar: &Bar0) -> u64 { - regs::NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE::read(bar).usable_fb_size() + bar.read(regs::NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE) + .usable_fb_size() } =20 struct Tu102; diff --git a/drivers/gpu/nova-core/gfw.rs b/drivers/gpu/nova-core/gfw.rs index 9121f400046d..fb75dd10a172 100644 --- a/drivers/gpu/nova-core/gfw.rs +++ b/drivers/gpu/nova-core/gfw.rs @@ -19,7 +19,10 @@ //! Note that the devinit sequence also needs to run during suspend/resume. =20 use kernel::{ - io::poll::read_poll_timeout, + io::{ + poll::read_poll_timeout, + Io, // + }, prelude::*, time::Delta, // }; @@ -58,9 +61,11 @@ pub(crate) fn wait_gfw_boot_completion(bar: &Bar0) -> Re= sult { Ok( // Check that FWSEC has lowered its protection level befor= e reading the GFW_BOOT // status. - regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK:= :read(bar) + bar.read(regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LE= VEL_MASK) .read_protection_level0() - && regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOO= T::read(bar).completed(), + && bar + .read(regs::NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_= GFW_BOOT) + .completed(), ) }, |&gfw_booted| gfw_booted, diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index 9b042ef1a308..ca2c153cf87f 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -4,6 +4,8 @@ device, devres::Devres, fmt, + io::Io, + num::Bounded, pci, prelude::*, sync::Arc, // @@ -122,24 +124,19 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Res= ult { } =20 /// Enum representation of the GPU generation. -/// -/// TODO: remove the `Default` trait implementation, and the `#[default]` -/// attribute, once the register!() macro (which creates Architecture item= s) no -/// longer requires it for read-only fields. -#[derive(fmt::Debug, Default, Copy, Clone)] +#[derive(fmt::Debug, Copy, Clone)] #[repr(u8)] pub(crate) enum Architecture { - #[default] Turing =3D 0x16, Ampere =3D 0x17, Ada =3D 0x19, } =20 -impl TryFrom for Architecture { +impl TryFrom> for Architecture { type Error =3D Error; =20 - fn try_from(value: u8) -> Result { - match value { + fn try_from(value: Bounded) -> Result { + match u8::from(value) { 0x16 =3D> Ok(Self::Turing), 0x17 =3D> Ok(Self::Ampere), 0x19 =3D> Ok(Self::Ada), @@ -148,23 +145,26 @@ fn try_from(value: u8) -> Result { } } =20 -impl From for u8 { +impl From for Bounded { fn from(value: Architecture) -> Self { - // CAST: `Architecture` is `repr(u8)`, so this cast is always loss= less. - value as u8 + match value { + Architecture::Turing =3D> Bounded::::new::<0x16>().cast= (), + Architecture::Ampere =3D> Bounded::::new::<0x17>().cast= (), + Architecture::Ada =3D> Bounded::::new::<0x19>().cast(), + } } } =20 pub(crate) struct Revision { - major: u8, - minor: u8, + major: Bounded, + minor: Bounded, } =20 impl From for Revision { fn from(boot0: regs::NV_PMC_BOOT_42) -> Self { Self { - major: boot0.major_revision(), - minor: boot0.minor_revision(), + major: boot0.major_revision().cast(), + minor: boot0.minor_revision().cast(), } } } @@ -201,13 +201,13 @@ fn new(dev: &device::Device, bar: &Bar0) -> Result { // from an earlier (pre-Fermi) era, and then using boot42 to p= recisely identify the GPU. // Somewhere in the Rubin timeframe, boot0 will no longer have= space to add new GPU IDs. =20 - let boot0 =3D regs::NV_PMC_BOOT_0::read(bar); + let boot0 =3D bar.read(regs::NV_PMC_BOOT_0); =20 if boot0.is_older_than_fermi() { return Err(ENODEV); } =20 - let boot42 =3D regs::NV_PMC_BOOT_42::read(bar); + let boot42 =3D bar.read(regs::NV_PMC_BOOT_42); Spec::try_from(boot42).inspect_err(|_| { dev_err!(dev, "Unsupported chipset: {}\n", boot42); }) diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/= boot.rs index be427fe26a58..154a2bc4655e 100644 --- a/drivers/gpu/nova-core/gsp/boot.rs +++ b/drivers/gpu/nova-core/gsp/boot.rs @@ -5,6 +5,7 @@ dma::CoherentAllocation, dma_write, io::poll::read_poll_timeout, + io::Io, pci, prelude::*, time::Delta, // @@ -55,7 +56,7 @@ fn run_fwsec_frts( ) -> Result<()> { // Check that the WPR2 region does not already exists - if it does= , we cannot run // FWSEC-FRTS until the GPU is reset. - if regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI::read(bar).higher_bound() != =3D 0 { + if bar.read(regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI).higher_bound() !=3D= 0 { dev_err!( dev, "WPR2 region already exists - GPU needs to be reset to pro= ceed\n" @@ -78,7 +79,9 @@ fn run_fwsec_frts( fwsec_frts.run(dev, falcon, bar)?; =20 // SCRATCH_E contains the error code for FWSEC-FRTS. - let frts_status =3D regs::NV_PBUS_SW_SCRATCH_0E_FRTS_ERR::read(bar= ).frts_err_code(); + let frts_status =3D bar + .read(regs::NV_PBUS_SW_SCRATCH_0E_FRTS_ERR) + .frts_err_code(); if frts_status !=3D 0 { dev_err!( dev, @@ -91,8 +94,8 @@ fn run_fwsec_frts( =20 // Check that the WPR2 region has been created as we requested. let (wpr2_lo, wpr2_hi) =3D ( - regs::NV_PFB_PRI_MMU_WPR2_ADDR_LO::read(bar).lower_bound(), - regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI::read(bar).higher_bound(), + bar.read(regs::NV_PFB_PRI_MMU_WPR2_ADDR_LO).lower_bound(), + bar.read(regs::NV_PFB_PRI_MMU_WPR2_ADDR_HI).higher_bound(), ); =20 match (wpr2_lo, wpr2_hi) { diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/= cmdq.rs index 46819a82a51a..c23aa822cdb6 100644 --- a/drivers/gpu/nova-core/gsp/cmdq.rs +++ b/drivers/gpu/nova-core/gsp/cmdq.rs @@ -16,7 +16,11 @@ DmaAddress, // }, dma_write, - io::poll::read_poll_timeout, + io::{ + poll::read_poll_timeout, + Io, + IoLoc, // + }, prelude::*, sync::aref::ARef, time::Delta, @@ -475,9 +479,7 @@ fn calculate_checksum>(it: T) = -> u32 { =20 /// Notifies the GSP that we have updated the command queue pointers. fn notify_gsp(bar: &Bar0) { - regs::NV_PGSP_QUEUE_HEAD::default() - .set_address(0) - .write(bar); + bar.write(regs::NV_PGSP_QUEUE_HEAD.init(|r| r.with_address(0u32))); } =20 /// Sends `command` to the GSP. diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs index ea0d32f5396c..63d448e90406 100644 --- a/drivers/gpu/nova-core/regs.rs +++ b/drivers/gpu/nova-core/regs.rs @@ -1,13 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 =20 -// Required to retain the original register names used by OpenRM, which ar= e all capital snake case -// but are mapped to types. -#![allow(non_camel_case_types)] - -#[macro_use] -pub(crate) mod macros; - use kernel::{ + io::Io, prelude::*, time, // }; @@ -35,20 +29,64 @@ num::FromSafeCast, }; =20 +// All nova-core registers are 32-bit and `pub(crate)`. Wrap the `register= !` macro to avoid +// repeating this information for every register. +macro_rules! nv_reg { + ( + $( + $(#[$attr:meta])* $name:ident $([ $size:expr $(; $stride:expr)= ? ])? + $(@ $offset:literal)? + $(@ $base:ident + $base_offset:literal)? + $(=3D> $alias:ident $(+ $alias_offset:ident)? $([$alias_id= x:expr])? )? + $(, $comment:literal)? { $($fields:tt)* } + )* + )=3D> { + $( + ::kernel::register!( + @reg $(#[$attr])* pub(crate) $name(u32) $([$size $(; $stride)?= ])? + $(@ $offset)? + $(@ $base + $base_offset)? + $(=3D> $alias $(+ $alias_offset)? $([$alias_idx])? )? + $(, $comment)? { $($fields)* } + ); + )* + }; +} + // PMC =20 -register!(NV_PMC_BOOT_0 @ 0x00000000, "Basic revision information about th= e GPU" { - 3:0 minor_revision as u8, "Minor revision of the chip"; - 7:4 major_revision as u8, "Major revision of the chip"; - 8:8 architecture_1 as u8, "MSB of the architecture"; - 23:20 implementation as u8, "Implementation version of the architect= ure"; - 28:24 architecture_0 as u8, "Lower bits of the architecture"; -}); +nv_reg! { + /// Basic revision information about the GPU. + NV_PMC_BOOT_0 @ 0x00000000 { + /// Minor revision of the chip. + 3:0 minor_revision; + /// Major revision of the chip. + 7:4 major_revision; + /// Meta-variable `newbase` repeats 0 times, but `offset` repeats = 1 time. + 8:8 architecture_1; + /// Implementation version of the architecture. + 23:20 implementation; + /// Lower bits of the architecture. + 28:24 architecture_0; + } + + /// Extended architecture information. + NV_PMC_BOOT_42 @ 0x00000a00 { + /// Minor revision of the chip. + 15:12 minor_revision; + /// Major revision of the chip. + 19:16 major_revision; + /// Implementation version of the architecture. + 23:20 implementation; + /// Architecture value. + 29:24 architecture ?=3D> Architecture; + } +} =20 impl NV_PMC_BOOT_0 { pub(crate) fn is_older_than_fermi(self) -> bool { // From https://github.com/NVIDIA/open-gpu-doc/tree/master/manuals= : - const NV_PMC_BOOT_0_ARCHITECTURE_GF100: u8 =3D 0xc; + const NV_PMC_BOOT_0_ARCHITECTURE_GF100: u32 =3D 0xc; =20 // Older chips left arch1 zeroed out. That, combined with an arch0= value that is less than // GF100, means "older than Fermi". @@ -56,13 +94,6 @@ pub(crate) fn is_older_than_fermi(self) -> bool { } } =20 -register!(NV_PMC_BOOT_42 @ 0x00000a00, "Extended architecture information"= { - 15:12 minor_revision as u8, "Minor revision of the chip"; - 19:16 major_revision as u8, "Major revision of the chip"; - 23:20 implementation as u8, "Implementation version of the architect= ure"; - 29:24 architecture as u8 ?=3D> Architecture, "Architecture value"; -}); - impl NV_PMC_BOOT_42 { /// Combines `architecture` and `implementation` to obtain a code uniq= ue to the chipset. pub(crate) fn chipset(self) -> Result { @@ -76,8 +107,8 @@ pub(crate) fn chipset(self) -> Result { =20 /// Returns the raw architecture value from the register. fn architecture_raw(self) -> u8 { - ((self.0 >> Self::ARCHITECTURE_RANGE.start()) & ((1 << Self::ARCHI= TECTURE_RANGE.len()) - 1)) - as u8 + ((self.inner >> Self::ARCHITECTURE_RANGE.start()) + & ((1 << Self::ARCHITECTURE_RANGE.len()) - 1)) as u8 } } =20 @@ -86,7 +117,7 @@ fn fmt(&self, f: &mut kernel::fmt::Formatter<'_>) -> ker= nel::fmt::Result { write!( f, "boot42 =3D 0x{:08x} (architecture 0x{:x}, implementation 0x{:= x})", - self.0, + self.inner, self.architecture_raw(), self.implementation() ) @@ -95,35 +126,50 @@ fn fmt(&self, f: &mut kernel::fmt::Formatter<'_>) -> k= ernel::fmt::Result { =20 // PBUS =20 -register!(NV_PBUS_SW_SCRATCH @ 0x00001400[64] {}); +nv_reg! { + NV_PBUS_SW_SCRATCH[64] @ 0x00001400 {} =20 -register!(NV_PBUS_SW_SCRATCH_0E_FRTS_ERR =3D> NV_PBUS_SW_SCRATCH[0xe], - "scratch register 0xe used as FRTS firmware error code" { - 31:16 frts_err_code as u16; -}); + /// Scratch register 0xe used as FRTS firmware error code. + NV_PBUS_SW_SCRATCH_0E_FRTS_ERR =3D> NV_PBUS_SW_SCRATCH[0xe] { + 31:16 frts_err_code; + } +} =20 // PFB =20 -// The following two registers together hold the physical system memory ad= dress that is used by the -// GPU to perform sysmembar operations (see `fb::SysmemFlush`). +nv_reg! { + /// Low bits of the physical system memory address used by the GPU to = perform sysmembar + /// operations (see [`crate::fb::SysmemFlush`]). + NV_PFB_NISO_FLUSH_SYSMEM_ADDR @ 0x00100c10 { + 31:0 adr_39_08; + } =20 -register!(NV_PFB_NISO_FLUSH_SYSMEM_ADDR @ 0x00100c10 { - 31:0 adr_39_08 as u32; -}); + /// High bits of the physical system memory address used by the GPU to= perform sysmembar + /// operations (see [`crate::fb::SysmemFlush`]). + NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI @ 0x00100c40 { + 23:0 adr_63_40; + } =20 -register!(NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI @ 0x00100c40 { - 23:0 adr_63_40 as u32; -}); + NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE @ 0x00100ce0 { + 3:0 lower_scale; + 9:4 lower_mag; + 30:30 ecc_mode_enabled =3D> bool; + } =20 -register!(NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE @ 0x00100ce0 { - 3:0 lower_scale as u8; - 9:4 lower_mag as u8; - 30:30 ecc_mode_enabled as bool; -}); + NV_PGSP_QUEUE_HEAD @ 0x00110c00 { + 31:0 address; + } =20 -register!(NV_PGSP_QUEUE_HEAD @ 0x00110c00 { - 31:0 address as u32; -}); + NV_PFB_PRI_MMU_WPR2_ADDR_LO @ 0x001fa824 { + /// Bits 12..40 of the lower (inclusive) bound of the WPR2 region. + 31:4 lo_val; + } + + NV_PFB_PRI_MMU_WPR2_ADDR_HI @ 0x001fa828 { + /// Bits 12..40 of the higher (exclusive) bound of the WPR2 region. + 31:4 hi_val; + } +} =20 impl NV_PFB_PRI_MMU_LOCAL_MEMORY_RANGE { /// Returns the usable framebuffer size, in bytes. @@ -140,10 +186,6 @@ pub(crate) fn usable_fb_size(self) -> u64 { } } =20 -register!(NV_PFB_PRI_MMU_WPR2_ADDR_LO@0x001fa824 { - 31:4 lo_val as u32, "Bits 12..40 of the lower (inclusive) bound of = the WPR2 region"; -}); - impl NV_PFB_PRI_MMU_WPR2_ADDR_LO { /// Returns the lower (inclusive) bound of the WPR2 region. pub(crate) fn lower_bound(self) -> u64 { @@ -151,10 +193,6 @@ pub(crate) fn lower_bound(self) -> u64 { } } =20 -register!(NV_PFB_PRI_MMU_WPR2_ADDR_HI@0x001fa828 { - 31:4 hi_val as u32, "Bits 12..40 of the higher (exclusive) bound of= the WPR2 region"; -}); - impl NV_PFB_PRI_MMU_WPR2_ADDR_HI { /// Returns the higher (exclusive) bound of the WPR2 region. /// @@ -173,29 +211,30 @@ pub(crate) fn higher_bound(self) -> u64 { // These scratch registers remain powered on even in a low-power state and= have a designated group // number. =20 -// Boot Sequence Interface (BSI) register used to determine -// if GSP reload/resume has completed during the boot process. -register!(NV_PGC6_BSI_SECURE_SCRATCH_14 @ 0x001180f8 { - 26:26 boot_stage_3_handoff as bool; -}); - -// Privilege level mask register. It dictates whether the host CPU has pri= vilege to access the -// `PGC6_AON_SECURE_SCRATCH_GROUP_05` register (which it needs to read GFW= _BOOT). -register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK @ 0x00118128, - "Privilege level mask register" { - 0:0 read_protection_level0 as bool, "Set after FWSEC lowers its pr= otection level"; -}); - -// OpenRM defines this as a register array, but doesn't specify its size a= nd only uses its first -// element. Be conservative until we know the actual size or need to use m= ore registers. -register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_05 @ 0x00118234[1] {}); - -register!( - NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT =3D> NV_PGC6_AON_SECURE= _SCRATCH_GROUP_05[0], - "Scratch group 05 register 0 used as GFW boot progress indicator" { - 7:0 progress as u8, "Progress of GFW boot (0xff means completed= )"; +nv_reg! { + /// Boot Sequence Interface (BSI) register used to determine + /// if GSP reload/resume has completed during the boot process. + NV_PGC6_BSI_SECURE_SCRATCH_14 @ 0x001180f8 { + 26:26 boot_stage_3_handoff =3D> bool; } -); + + /// Privilege level mask register. It dictates whether the host CPU ha= s privilege to access the + /// `PGC6_AON_SECURE_SCRATCH_GROUP_05` register (which it needs to rea= d GFW_BOOT). + NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_PRIV_LEVEL_MASK @ 0x00118128 { + /// Set after FWSEC lowers its protection level. + 0:0 read_protection_level0 =3D> bool; + } + + /// OpenRM defines this as a register array, but doesn't specify its s= ize and only uses its + /// first element. Be conservative until we know the actual size or ne= ed to use more registers. + NV_PGC6_AON_SECURE_SCRATCH_GROUP_05[1] @ 0x00118234 {} + + /// Scratch group 05 register 0 used as GFW boot progress indicator. + NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT =3D> NV_PGC6_AON_SECURE= _SCRATCH_GROUP_05[0] { + /// Progress of GFW boot (0xff means completed). + 7:0 progress; + } +} =20 impl NV_PGC6_AON_SECURE_SCRATCH_GROUP_05_0_GFW_BOOT { /// Returns `true` if GFW boot is completed. @@ -204,16 +243,17 @@ pub(crate) fn completed(self) -> bool { } } =20 -register!(NV_PGC6_AON_SECURE_SCRATCH_GROUP_42 @ 0x001183a4 { - 31:0 value as u32; -}); - -register!( - NV_USABLE_FB_SIZE_IN_MB =3D> NV_PGC6_AON_SECURE_SCRATCH_GROUP_42, - "Scratch group 42 register used as framebuffer size" { - 31:0 value as u32, "Usable framebuffer size, in megabytes"; +nv_reg! { + NV_PGC6_AON_SECURE_SCRATCH_GROUP_42 @ 0x001183a4 { + 31:0 value; } -); + + /// Scratch group 42 register used as framebuffer size. + NV_USABLE_FB_SIZE_IN_MB =3D> NV_PGC6_AON_SECURE_SCRATCH_GROUP_42 { + /// Usable framebuffer size, in megabytes. + 31:0 value; + } +} =20 impl NV_USABLE_FB_SIZE_IN_MB { /// Returns the usable framebuffer size, in bytes. @@ -224,10 +264,14 @@ pub(crate) fn usable_fb_size(self) -> u64 { =20 // PDISP =20 -register!(NV_PDISP_VGA_WORKSPACE_BASE @ 0x00625f04 { - 3:3 status_valid as bool, "Set if the `addr` field is valid"; - 31:8 addr as u32, "VGA workspace base address divided by 0x10000"; -}); +nv_reg! { + NV_PDISP_VGA_WORKSPACE_BASE @ 0x00625f04 { + /// Set if the `addr` field is valid. + 3:3 status_valid =3D> bool; + /// VGA workspace base address divided by 0x10000. + 31:8 addr; + } +} =20 impl NV_PDISP_VGA_WORKSPACE_BASE { /// Returns the base address of the VGA workspace, or `None` if none e= xists. @@ -244,73 +288,127 @@ pub(crate) fn vga_workspace_addr(self) -> Option { =20 pub(crate) const NV_FUSE_OPT_FPF_SIZE: usize =3D 16; =20 -register!(NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION @ 0x00824100[NV_FUSE_OPT_FP= F_SIZE] { - 15:0 data as u16; -}); +nv_reg! { + NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION[NV_FUSE_OPT_FPF_SIZE] @ 0x0082410= 0 { + 15:0 data; + } =20 -register!(NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION @ 0x00824140[NV_FUSE_OPT_FPF= _SIZE] { - 15:0 data as u16; -}); + NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION[NV_FUSE_OPT_FPF_SIZE] @ 0x00824140= { + 15:0 data; + } =20 -register!(NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION @ 0x008241c0[NV_FUSE_OPT_FPF_= SIZE] { - 15:0 data as u16; -}); - -// PFALCON - -register!(NV_PFALCON_FALCON_IRQSCLR @ PFalconBase[0x00000004] { - 4:4 halt as bool; - 6:6 swgen0 as bool; -}); - -register!(NV_PFALCON_FALCON_MAILBOX0 @ PFalconBase[0x00000040] { - 31:0 value as u32; -}); - -register!(NV_PFALCON_FALCON_MAILBOX1 @ PFalconBase[0x00000044] { - 31:0 value as u32; -}); - -// Used to store version information about the firmware running -// on the Falcon processor. -register!(NV_PFALCON_FALCON_OS @ PFalconBase[0x00000080] { - 31:0 value as u32; -}); - -register!(NV_PFALCON_FALCON_RM @ PFalconBase[0x00000084] { - 31:0 value as u32; -}); - -register!(NV_PFALCON_FALCON_HWCFG2 @ PFalconBase[0x000000f4] { - 10:10 riscv as bool; - 12:12 mem_scrubbing as bool, "Set to 0 after memory scrubbing is com= pleted"; - 31:31 reset_ready as bool, "Signal indicating that reset is complete= d (GA102+)"; -}); - -impl NV_PFALCON_FALCON_HWCFG2 { - /// Returns `true` if memory scrubbing is completed. - pub(crate) fn mem_scrubbing_done(self) -> bool { - !self.mem_scrubbing() + NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION[NV_FUSE_OPT_FPF_SIZE] @ 0x008241c0 { + 15:0 data; } } =20 -register!(NV_PFALCON_FALCON_CPUCTL @ PFalconBase[0x00000100] { - 1:1 startcpu as bool; - 4:4 halted as bool; - 6:6 alias_en as bool; -}); +// PFALCON =20 -register!(NV_PFALCON_FALCON_BOOTVEC @ PFalconBase[0x00000104] { - 31:0 value as u32; -}); +nv_reg! { + NV_PFALCON_FALCON_IRQSCLR @ PFalconBase + 0x00000004 { + 4:4 halt =3D> bool; + 6:6 swgen0 =3D> bool; + } =20 -register!(NV_PFALCON_FALCON_DMACTL @ PFalconBase[0x0000010c] { - 0:0 require_ctx as bool; - 1:1 dmem_scrubbing as bool; - 2:2 imem_scrubbing as bool; - 6:3 dmaq_num as u8; - 7:7 secure_stat as bool; -}); + NV_PFALCON_FALCON_MAILBOX0 @ PFalconBase + 0x00000040 { + 31:0 value =3D> u32; + } + + NV_PFALCON_FALCON_MAILBOX1 @ PFalconBase + 0x00000044 { + 31:0 value =3D> u32; + } + + /// Used to store version information about the firmware running + /// on the Falcon processor. + NV_PFALCON_FALCON_OS @ PFalconBase + 0x00000080 { + 31:0 value =3D> u32; + } + + NV_PFALCON_FALCON_RM @ PFalconBase + 0x00000084 { + 31:0 value =3D> u32; + } + + NV_PFALCON_FALCON_HWCFG2 @ PFalconBase + 0x000000f4 { + 10:10 riscv =3D> bool; + /// Set to 0 after memory scrubbing is completed. + 12:12 mem_scrubbing =3D> bool; + /// Signal indicating that reset is completed (GA102+). + 31:31 reset_ready =3D> bool; + } + + NV_PFALCON_FALCON_CPUCTL @ PFalconBase + 0x00000100 { + 1:1 startcpu =3D> bool; + 4:4 halted =3D> bool; + 6:6 alias_en =3D> bool; + } + + NV_PFALCON_FALCON_BOOTVEC @ PFalconBase + 0x00000104 { + 31:0 value =3D> u32; + } + + NV_PFALCON_FALCON_DMACTL @ PFalconBase + 0x0000010c { + 0:0 require_ctx =3D> bool; + 1:1 dmem_scrubbing =3D> bool; + 2:2 imem_scrubbing =3D> bool; + 6:3 dmaq_num; + 7:7 secure_stat =3D> bool; + } + + NV_PFALCON_FALCON_DMATRFBASE @ PFalconBase + 0x00000110 { + 31:0 base =3D> u32; + } + + NV_PFALCON_FALCON_DMATRFMOFFS @ PFalconBase + 0x00000114 { + 23:0 offs; + } + + NV_PFALCON_FALCON_DMATRFCMD @ PFalconBase + 0x00000118 { + 0:0 full =3D> bool; + 1:1 idle =3D> bool; + 3:2 sec; + 4:4 imem =3D> bool; + 5:5 is_write =3D> bool; + 10:8 size ?=3D> DmaTrfCmdSize; + 14:12 ctxdma; + 16:16 set_dmtag; + } + + NV_PFALCON_FALCON_DMATRFFBOFFS @ PFalconBase + 0x0000011c { + 31:0 offs =3D> u32; + } + + NV_PFALCON_FALCON_DMATRFBASE1 @ PFalconBase + 0x00000128 { + 8:0 base; + } + + NV_PFALCON_FALCON_HWCFG1 @ PFalconBase + 0x0000012c { + /// Core revision. + 3:0 core_rev ?=3D> FalconCoreRev; + /// Security model. + 5:4 security_model ?=3D> FalconSecurityModel; + /// Core revision subversion. + 7:6 core_rev_subversion =3D> FalconCoreRevSubversion; + } + + NV_PFALCON_FALCON_CPUCTL_ALIAS @ PFalconBase + 0x00000130 { + 1:1 startcpu =3D> bool; + } + + /// Actually known as `NV_PSEC_FALCON_ENGINE` and `NV_PGSP_FALCON_ENGI= NE` depending on the + /// falcon instance. + NV_PFALCON_FALCON_ENGINE @ PFalconBase + 0x000003c0 { + 0:0 reset =3D> bool; + } + + NV_PFALCON_FBIF_TRANSCFG[8] @ PFalconBase + 0x00000600 { + 1:0 target ?=3D> FalconFbifTarget; + 2:2 mem_type =3D> FalconFbifMemType; + } + + NV_PFALCON_FBIF_CTL @ PFalconBase + 0x00000624 { + 7:7 allow_phys_no_ctx =3D> bool; + } +} =20 impl NV_PFALCON_FALCON_DMACTL { /// Returns `true` if memory scrubbing is completed. @@ -319,117 +417,81 @@ pub(crate) fn mem_scrubbing_done(self) -> bool { } } =20 -register!(NV_PFALCON_FALCON_DMATRFBASE @ PFalconBase[0x00000110] { - 31:0 base as u32; -}); - -register!(NV_PFALCON_FALCON_DMATRFMOFFS @ PFalconBase[0x00000114] { - 23:0 offs as u32; -}); - -register!(NV_PFALCON_FALCON_DMATRFCMD @ PFalconBase[0x00000118] { - 0:0 full as bool; - 1:1 idle as bool; - 3:2 sec as u8; - 4:4 imem as bool; - 5:5 is_write as bool; - 10:8 size as u8 ?=3D> DmaTrfCmdSize; - 14:12 ctxdma as u8; - 16:16 set_dmtag as u8; -}); - impl NV_PFALCON_FALCON_DMATRFCMD { /// Programs the `imem` and `sec` fields for the given FalconMem pub(crate) fn with_falcon_mem(self, mem: FalconMem) -> Self { - self.set_imem(mem !=3D FalconMem::Dmem) - .set_sec(if mem =3D=3D FalconMem::ImemSecure { 1 } else { 0 }) + let this =3D self.with_imem(mem !=3D FalconMem::Dmem); + + match mem { + FalconMem::ImemSecure =3D> this.with_const_sec::<1>(), + _ =3D> this.with_const_sec::<0>(), + } } } =20 -register!(NV_PFALCON_FALCON_DMATRFFBOFFS @ PFalconBase[0x0000011c] { - 31:0 offs as u32; -}); - -register!(NV_PFALCON_FALCON_DMATRFBASE1 @ PFalconBase[0x00000128] { - 8:0 base as u16; -}); - -register!(NV_PFALCON_FALCON_HWCFG1 @ PFalconBase[0x0000012c] { - 3:0 core_rev as u8 ?=3D> FalconCoreRev, "Core revision"; - 5:4 security_model as u8 ?=3D> FalconSecurityModel, "Security mode= l"; - 7:6 core_rev_subversion as u8 ?=3D> FalconCoreRevSubversion, "Core= revision subversion"; -}); - -register!(NV_PFALCON_FALCON_CPUCTL_ALIAS @ PFalconBase[0x00000130] { - 1:1 startcpu as bool; -}); - -// Actually known as `NV_PSEC_FALCON_ENGINE` and `NV_PGSP_FALCON_ENGINE` d= epending on the falcon -// instance. -register!(NV_PFALCON_FALCON_ENGINE @ PFalconBase[0x000003c0] { - 0:0 reset as bool; -}); - impl NV_PFALCON_FALCON_ENGINE { /// Resets the falcon pub(crate) fn reset_engine(bar: &Bar0) { - Self::read(bar, &E::ID).set_reset(true).write(bar, &E::ID); + bar.update(Self::of::(), |r| r.with_reset(true)); =20 // TIMEOUT: falcon engine should not take more than 10us to reset. time::delay::fsleep(time::Delta::from_micros(10)); =20 - Self::read(bar, &E::ID).set_reset(false).write(bar, &E::ID); + bar.update(Self::of::(), |r| r.with_reset(false)); } } =20 -register!(NV_PFALCON_FBIF_TRANSCFG @ PFalconBase[0x00000600[8]] { - 1:0 target as u8 ?=3D> FalconFbifTarget; - 2:2 mem_type as bool =3D> FalconFbifMemType; -}); - -register!(NV_PFALCON_FBIF_CTL @ PFalconBase[0x00000624] { - 7:7 allow_phys_no_ctx as bool; -}); +impl NV_PFALCON_FALCON_HWCFG2 { + /// Returns `true` if memory scrubbing is completed. + pub(crate) fn mem_scrubbing_done(self) -> bool { + !self.mem_scrubbing() + } +} =20 /* PFALCON2 */ =20 -register!(NV_PFALCON2_FALCON_MOD_SEL @ PFalcon2Base[0x00000180] { - 7:0 algo as u8 ?=3D> FalconModSelAlgo; -}); +nv_reg! { + NV_PFALCON2_FALCON_MOD_SEL @ PFalcon2Base + 0x00000180 { + 7:0 algo ?=3D> FalconModSelAlgo; + } =20 -register!(NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID @ PFalcon2Base[0x00000198]= { - 7:0 ucode_id as u8; -}); + NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID @ PFalcon2Base + 0x00000198 { + 7:0 ucode_id =3D> u8; + } =20 -register!(NV_PFALCON2_FALCON_BROM_ENGIDMASK @ PFalcon2Base[0x0000019c] { - 31:0 value as u32; -}); + NV_PFALCON2_FALCON_BROM_ENGIDMASK @ PFalcon2Base + 0x0000019c { + 31:0 value =3D> u32; + } =20 -// OpenRM defines this as a register array, but doesn't specify its size a= nd only uses its first -// element. Be conservative until we know the actual size or need to use m= ore registers. -register!(NV_PFALCON2_FALCON_BROM_PARAADDR @ PFalcon2Base[0x00000210[1]] { - 31:0 value as u32; -}); + /// OpenRM defines this as a register array, but doesn't specify its s= ize and only uses its + /// first element. Be conservative until we know the actual size or ne= ed to use more registers. + NV_PFALCON2_FALCON_BROM_PARAADDR[1] @ PFalcon2Base + 0x00000210 { + 31:0 value =3D> u32; + } +} =20 // PRISCV =20 -// RISC-V status register for debug (Turing and GA100 only). -// Reflects current RISC-V core status. -register!(NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS @ PFalcon2Base[0x000002= 40] { - 0:0 active_stat as bool, "RISC-V core active/inactive status"; -}); - // GA102 and later -register!(NV_PRISCV_RISCV_CPUCTL @ PFalcon2Base[0x00000388] { - 0:0 halted as bool; - 7:7 active_stat as bool; -}); +nv_reg! { + // RISC-V status register for debug (Turing and GA100 only). + // Reflects current RISC-V core status. + NV_PRISCV_RISCV_CORE_SWITCH_RISCV_STATUS @ PFalcon2Base + 0x00000240 { + // RISC-V core active/inactive status. + 0:0 active_stat =3D> bool; + } =20 -register!(NV_PRISCV_RISCV_BCR_CTRL @ PFalcon2Base[0x00000668] { - 0:0 valid as bool; - 4:4 core_select as bool =3D> PeregrineCoreSelect; - 8:8 br_fetch as bool; -}); + NV_PRISCV_RISCV_CPUCTL @ PFalcon2Base + 0x00000388 { + 0:0 halted =3D> bool; + 7:7 active_stat =3D> bool; + } + + NV_PRISCV_RISCV_BCR_CTRL @ PFalconBase + 0x00001668 { + 0:0 valid =3D> bool; + 4:4 core_select =3D> PeregrineCoreSelect; + 8:8 br_fetch =3D> bool; + } +} =20 // The modules below provide registers that are not identical on all suppo= rted chips. They should // only be used in HAL modules. @@ -437,15 +499,19 @@ pub(crate) fn reset_engine(bar: &Bar= 0) { pub(crate) mod gm107 { // FUSE =20 - register!(NV_FUSE_STATUS_OPT_DISPLAY @ 0x00021c04 { - 0:0 display_disabled as bool; - }); + nv_reg! { + NV_FUSE_STATUS_OPT_DISPLAY @ 0x00021c04 { + 0:0 display_disabled =3D> bool; + } + } } =20 pub(crate) mod ga100 { // FUSE =20 - register!(NV_FUSE_STATUS_OPT_DISPLAY @ 0x00820c04 { - 0:0 display_disabled as bool; - }); + nv_reg! { + NV_FUSE_STATUS_OPT_DISPLAY @ 0x00820c04 { + 0:0 display_disabled =3D> bool; + } + } } diff --git a/drivers/gpu/nova-core/regs/macros.rs b/drivers/gpu/nova-core/r= egs/macros.rs deleted file mode 100644 index ed624be1f39b..000000000000 --- a/drivers/gpu/nova-core/regs/macros.rs +++ /dev/null @@ -1,739 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -//! `register!` macro to define register layout and accessors. -//! -//! A single register typically includes several fields, which are accesse= d through a combination -//! of bit-shift and mask operations that introduce a class of potential m= istakes, notably because -//! not all possible field values are necessarily valid. -//! -//! The `register!` macro in this module provides an intuitive and readabl= e syntax for defining a -//! dedicated type for each register. Each such type comes with its own fi= eld accessors that can -//! return an error if a field's value is invalid. Please look at the [`bi= tfield`] macro for the -//! complete syntax of fields definitions. - -/// Trait providing a base address to be added to the offset of a relative= register to obtain -/// its actual offset. -/// -/// The `T` generic argument is used to distinguish which base to use, in = case a type provides -/// several bases. It is given to the `register!` macro to restrict the us= e of the register to -/// implementors of this particular variant. -pub(crate) trait RegisterBase { - const BASE: usize; -} - -/// Defines a dedicated type for a register with an absolute offset, inclu= ding getter and setter -/// methods for its fields and methods to read and write it from an `Io` r= egion. -/// -/// Example: -/// -/// ```no_run -/// register!(BOOT_0 @ 0x00000100, "Basic revision information about the G= PU" { -/// 3:0 minor_revision as u8, "Minor revision of the chip"; -/// 7:4 major_revision as u8, "Major revision of the chip"; -/// 28:20 chipset as u32 ?=3D> Chipset, "Chipset model"; -/// }); -/// ``` -/// -/// This defines a `BOOT_0` type which can be read or written from offset = `0x100` of an `Io` -/// region. It is composed of 3 fields, for instance `minor_revision` is m= ade of the 4 least -/// significant bits of the register. Each field can be accessed and modif= ied using accessor -/// methods: -/// -/// ```no_run -/// // Read from the register's defined offset (0x100). -/// let boot0 =3D BOOT_0::read(&bar); -/// pr_info!("chip revision: {}.{}", boot0.major_revision(), boot0.minor_r= evision()); -/// -/// // `Chipset::try_from` is called with the value of the `chipset` field= and returns an -/// // error if it is invalid. -/// let chipset =3D boot0.chipset()?; -/// -/// // Update some fields and write the value back. -/// boot0.set_major_revision(3).set_minor_revision(10).write(&bar); -/// -/// // Or, just read and update the register in a single step: -/// BOOT_0::update(&bar, |r| r.set_major_revision(3).set_minor_revision(10= )); -/// ``` -/// -/// The documentation strings are optional. If present, they will be added= to the type's -/// definition, or the field getter and setter methods they are attached t= o. -/// -/// It is also possible to create a alias register by using the `=3D> ALIA= S` syntax. This is useful -/// for cases where a register's interpretation depends on the context: -/// -/// ```no_run -/// register!(SCRATCH @ 0x00000200, "Scratch register" { -/// 31:0 value as u32, "Raw value"; -/// }); -/// -/// register!(SCRATCH_BOOT_STATUS =3D> SCRATCH, "Boot status of the firmwa= re" { -/// 0:0 completed as bool, "Whether the firmware has completed boo= ting"; -/// }); -/// ``` -/// -/// In this example, `SCRATCH_0_BOOT_STATUS` uses the same I/O address as = `SCRATCH`, while also -/// providing its own `completed` field. -/// -/// ## Relative registers -/// -/// A register can be defined as being accessible from a fixed offset of a= provided base. For -/// instance, imagine the following I/O space: -/// -/// ```text -/// +-----------------------------+ -/// | ... | -/// | | -/// 0x100--->+------------CPU0-------------+ -/// | | -/// 0x110--->+-----------------------------+ -/// | CPU_CTL | -/// +-----------------------------+ -/// | ... | -/// | | -/// | | -/// 0x200--->+------------CPU1-------------+ -/// | | -/// 0x210--->+-----------------------------+ -/// | CPU_CTL | -/// +-----------------------------+ -/// | ... | -/// +-----------------------------+ -/// ``` -/// -/// `CPU0` and `CPU1` both have a `CPU_CTL` register that starts at offset= `0x10` of their I/O -/// space segment. Since both instances of `CPU_CTL` share the same layout= , we don't want to define -/// them twice and would prefer a way to select which one to use from a si= ngle definition -/// -/// This can be done using the `Base[Offset]` syntax when specifying the r= egister's address. -/// -/// `Base` is an arbitrary type (typically a ZST) to be used as a generic = parameter of the -/// [`RegisterBase`] trait to provide the base as a constant, i.e. each ty= pe providing a base for -/// this register needs to implement `RegisterBase`. Here is the abo= ve example translated -/// into code: -/// -/// ```no_run -/// // Type used to identify the base. -/// pub(crate) struct CpuCtlBase; -/// -/// // ZST describing `CPU0`. -/// struct Cpu0; -/// impl RegisterBase for Cpu0 { -/// const BASE: usize =3D 0x100; -/// } -/// // Singleton of `CPU0` used to identify it. -/// const CPU0: Cpu0 =3D Cpu0; -/// -/// // ZST describing `CPU1`. -/// struct Cpu1; -/// impl RegisterBase for Cpu1 { -/// const BASE: usize =3D 0x200; -/// } -/// // Singleton of `CPU1` used to identify it. -/// const CPU1: Cpu1 =3D Cpu1; -/// -/// // This makes `CPU_CTL` accessible from all implementors of `RegisterB= ase`. -/// register!(CPU_CTL @ CpuCtlBase[0x10], "CPU core control" { -/// 0:0 start as bool, "Start the CPU core"; -/// }); -/// -/// // The `read`, `write` and `update` methods of relative registers take= an extra `base` argument -/// // that is used to resolve its final address by adding its `BASE` to t= he offset of the -/// // register. -/// -/// // Start `CPU0`. -/// CPU_CTL::update(bar, &CPU0, |r| r.set_start(true)); -/// -/// // Start `CPU1`. -/// CPU_CTL::update(bar, &CPU1, |r| r.set_start(true)); -/// -/// // Aliases can also be defined for relative register. -/// register!(CPU_CTL_ALIAS =3D> CpuCtlBase[CPU_CTL], "Alias to CPU core c= ontrol" { -/// 1:1 alias_start as bool, "Start the aliased CPU core"; -/// }); -/// -/// // Start the aliased `CPU0`. -/// CPU_CTL_ALIAS::update(bar, &CPU0, |r| r.set_alias_start(true)); -/// ``` -/// -/// ## Arrays of registers -/// -/// Some I/O areas contain consecutive values that can be interpreted in t= he same way. These areas -/// can be defined as an array of identical registers, allowing them to be= accessed by index with -/// compile-time or runtime bound checking. Simply define their address as= `Address[Size]`, and add -/// an `idx` parameter to their `read`, `write` and `update` methods: -/// -/// ```no_run -/// # fn no_run() -> Result<(), Error> { -/// # fn get_scratch_idx() -> usize { -/// # 0x15 -/// # } -/// // Array of 64 consecutive registers with the same layout starting at = offset `0x80`. -/// register!(SCRATCH @ 0x00000080[64], "Scratch registers" { -/// 31:0 value as u32; -/// }); -/// -/// // Read scratch register 0, i.e. I/O address `0x80`. -/// let scratch_0 =3D SCRATCH::read(bar, 0).value(); -/// // Read scratch register 15, i.e. I/O address `0x80 + (15 * 4)`. -/// let scratch_15 =3D SCRATCH::read(bar, 15).value(); -/// -/// // This is out of bounds and won't build. -/// // let scratch_128 =3D SCRATCH::read(bar, 128).value(); -/// -/// // Runtime-obtained array index. -/// let scratch_idx =3D get_scratch_idx(); -/// // Access on a runtime index returns an error if it is out-of-bounds. -/// let some_scratch =3D SCRATCH::try_read(bar, scratch_idx)?.value(); -/// -/// // Alias to a particular register in an array. -/// // Here `SCRATCH[8]` is used to convey the firmware exit code. -/// register!(FIRMWARE_STATUS =3D> SCRATCH[8], "Firmware exit status code"= { -/// 7:0 status as u8; -/// }); -/// -/// let status =3D FIRMWARE_STATUS::read(bar).status(); -/// -/// // Non-contiguous register arrays can be defined by adding a stride pa= rameter. -/// // Here, each of the 16 registers of the array are separated by 8 byte= s, meaning that the -/// // registers of the two declarations below are interleaved. -/// register!(SCRATCH_INTERLEAVED_0 @ 0x000000c0[16 ; 8], "Scratch registe= rs bank 0" { -/// 31:0 value as u32; -/// }); -/// register!(SCRATCH_INTERLEAVED_1 @ 0x000000c4[16 ; 8], "Scratch registe= rs bank 1" { -/// 31:0 value as u32; -/// }); -/// # Ok(()) -/// # } -/// ``` -/// -/// ## Relative arrays of registers -/// -/// Combining the two features described in the sections above, arrays of = registers accessible from -/// a base can also be defined: -/// -/// ```no_run -/// # fn no_run() -> Result<(), Error> { -/// # fn get_scratch_idx() -> usize { -/// # 0x15 -/// # } -/// // Type used as parameter of `RegisterBase` to specify the base. -/// pub(crate) struct CpuCtlBase; -/// -/// // ZST describing `CPU0`. -/// struct Cpu0; -/// impl RegisterBase for Cpu0 { -/// const BASE: usize =3D 0x100; -/// } -/// // Singleton of `CPU0` used to identify it. -/// const CPU0: Cpu0 =3D Cpu0; -/// -/// // ZST describing `CPU1`. -/// struct Cpu1; -/// impl RegisterBase for Cpu1 { -/// const BASE: usize =3D 0x200; -/// } -/// // Singleton of `CPU1` used to identify it. -/// const CPU1: Cpu1 =3D Cpu1; -/// -/// // 64 per-cpu scratch registers, arranged as an contiguous array. -/// register!(CPU_SCRATCH @ CpuCtlBase[0x00000080[64]], "Per-CPU scratch r= egisters" { -/// 31:0 value as u32; -/// }); -/// -/// let cpu0_scratch_0 =3D CPU_SCRATCH::read(bar, &Cpu0, 0).value(); -/// let cpu1_scratch_15 =3D CPU_SCRATCH::read(bar, &Cpu1, 15).value(); -/// -/// // This won't build. -/// // let cpu0_scratch_128 =3D CPU_SCRATCH::read(bar, &Cpu0, 128).value(); -/// -/// // Runtime-obtained array index. -/// let scratch_idx =3D get_scratch_idx(); -/// // Access on a runtime value returns an error if it is out-of-bounds. -/// let cpu0_some_scratch =3D CPU_SCRATCH::try_read(bar, &Cpu0, scratch_id= x)?.value(); -/// -/// // `SCRATCH[8]` is used to convey the firmware exit code. -/// register!(CPU_FIRMWARE_STATUS =3D> CpuCtlBase[CPU_SCRATCH[8]], -/// "Per-CPU firmware exit status code" { -/// 7:0 status as u8; -/// }); -/// -/// let cpu0_status =3D CPU_FIRMWARE_STATUS::read(bar, &Cpu0).status(); -/// -/// // Non-contiguous register arrays can be defined by adding a stride pa= rameter. -/// // Here, each of the 16 registers of the array are separated by 8 byte= s, meaning that the -/// // registers of the two declarations below are interleaved. -/// register!(CPU_SCRATCH_INTERLEAVED_0 @ CpuCtlBase[0x00000d00[16 ; 8]], -/// "Scratch registers bank 0" { -/// 31:0 value as u32; -/// }); -/// register!(CPU_SCRATCH_INTERLEAVED_1 @ CpuCtlBase[0x00000d04[16 ; 8]], -/// "Scratch registers bank 1" { -/// 31:0 value as u32; -/// }); -/// # Ok(()) -/// # } -/// ``` -macro_rules! register { - // Creates a register at a fixed offset of the MMIO space. - ($name:ident @ $offset:literal $(, $comment:literal)? { $($fields:tt)*= } ) =3D> { - bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)= * } ); - register!(@io_fixed $name @ $offset); - }; - - // Creates an alias register of fixed offset register `alias` with its= own fields. - ($name:ident =3D> $alias:ident $(, $comment:literal)? { $($fields:tt)*= } ) =3D> { - bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)= * } ); - register!(@io_fixed $name @ $alias::OFFSET); - }; - - // Creates a register at a relative offset from a base address provide= r. - ($name:ident @ $base:ty [ $offset:literal ] $(, $comment:literal)? { $= ($fields:tt)* } ) =3D> { - bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)= * } ); - register!(@io_relative $name @ $base [ $offset ]); - }; - - // Creates an alias register of relative offset register `alias` with = its own fields. - ($name:ident =3D> $base:ty [ $alias:ident ] $(, $comment:literal)? { $= ($fields:tt)* }) =3D> { - bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)= * } ); - register!(@io_relative $name @ $base [ $alias::OFFSET ]); - }; - - // Creates an array of registers at a fixed offset of the MMIO space. - ( - $name:ident @ $offset:literal [ $size:expr ; $stride:expr ] $(, $c= omment:literal)? { - $($fields:tt)* - } - ) =3D> { - static_assert!(::core::mem::size_of::() <=3D $stride); - bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)= * } ); - register!(@io_array $name @ $offset [ $size ; $stride ]); - }; - - // Shortcut for contiguous array of registers (stride =3D=3D size of e= lement). - ( - $name:ident @ $offset:literal [ $size:expr ] $(, $comment:literal)= ? { - $($fields:tt)* - } - ) =3D> { - register!($name @ $offset [ $size ; ::core::mem::size_of::() = ] $(, $comment)? { - $($fields)* - } ); - }; - - // Creates an array of registers at a relative offset from a base addr= ess provider. - ( - $name:ident @ $base:ty [ $offset:literal [ $size:expr ; $stride:ex= pr ] ] - $(, $comment:literal)? { $($fields:tt)* } - ) =3D> { - static_assert!(::core::mem::size_of::() <=3D $stride); - bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)= * } ); - register!(@io_relative_array $name @ $base [ $offset [ $size ; $st= ride ] ]); - }; - - // Shortcut for contiguous array of relative registers (stride =3D=3D = size of element). - ( - $name:ident @ $base:ty [ $offset:literal [ $size:expr ] ] $(, $com= ment:literal)? { - $($fields:tt)* - } - ) =3D> { - register!($name @ $base [ $offset [ $size ; ::core::mem::size_of::= () ] ] - $(, $comment)? { $($fields)* } ); - }; - - // Creates an alias of register `idx` of relative array of registers `= alias` with its own - // fields. - ( - $name:ident =3D> $base:ty [ $alias:ident [ $idx:expr ] ] $(, $comm= ent:literal)? { - $($fields:tt)* - } - ) =3D> { - static_assert!($idx < $alias::SIZE); - bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)= * } ); - register!(@io_relative $name @ $base [ $alias::OFFSET + $idx * $al= ias::STRIDE ] ); - }; - - // Creates an alias of register `idx` of array of registers `alias` wi= th its own fields. - // This rule belongs to the (non-relative) register arrays set, but ne= eds to be put last - // to avoid it being interpreted in place of the relative register arr= ay alias rule. - ($name:ident =3D> $alias:ident [ $idx:expr ] $(, $comment:literal)? { = $($fields:tt)* }) =3D> { - static_assert!($idx < $alias::SIZE); - bitfield!(pub(crate) struct $name(u32) $(, $comment)? { $($fields)= * } ); - register!(@io_fixed $name @ $alias::OFFSET + $idx * $alias::STRIDE= ); - }; - - // Generates the IO accessors for a fixed offset register. - (@io_fixed $name:ident @ $offset:expr) =3D> { - #[allow(dead_code)] - impl $name { - pub(crate) const OFFSET: usize =3D $offset; - - /// Read the register from its address in `io`. - #[inline(always)] - pub(crate) fn read(io: &T) -> Self where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - { - Self(io.read32($offset)) - } - - /// Write the value contained in `self` to the register addres= s in `io`. - #[inline(always)] - pub(crate) fn write(self, io: &T) where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - { - io.write32(self.0, $offset) - } - - /// Read the register from its address in `io` and run `f` on = its value to obtain a new - /// value to write back. - #[inline(always)] - pub(crate) fn update( - io: &T, - f: F, - ) where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - F: ::core::ops::FnOnce(Self) -> Self, - { - let reg =3D f(Self::read(io)); - reg.write(io); - } - } - }; - - // Generates the IO accessors for a relative offset register. - (@io_relative $name:ident @ $base:ty [ $offset:expr ]) =3D> { - #[allow(dead_code)] - impl $name { - pub(crate) const OFFSET: usize =3D $offset; - - /// Read the register from `io`, using the base address provid= ed by `base` and adding - /// the register's offset to it. - #[inline(always)] - pub(crate) fn read( - io: &T, - #[allow(unused_variables)] - base: &B, - ) -> Self where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - B: crate::regs::macros::RegisterBase<$base>, - { - const OFFSET: usize =3D $name::OFFSET; - - let value =3D io.read32( - >::BASE = + OFFSET - ); - - Self(value) - } - - /// Write the value contained in `self` to `io`, using the bas= e address provided by - /// `base` and adding the register's offset to it. - #[inline(always)] - pub(crate) fn write( - self, - io: &T, - #[allow(unused_variables)] - base: &B, - ) where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - B: crate::regs::macros::RegisterBase<$base>, - { - const OFFSET: usize =3D $name::OFFSET; - - io.write32( - self.0, - >::BASE = + OFFSET - ); - } - - /// Read the register from `io`, using the base address provid= ed by `base` and adding - /// the register's offset to it, then run `f` on its value to = obtain a new value to - /// write back. - #[inline(always)] - pub(crate) fn update( - io: &T, - base: &B, - f: F, - ) where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - B: crate::regs::macros::RegisterBase<$base>, - F: ::core::ops::FnOnce(Self) -> Self, - { - let reg =3D f(Self::read(io, base)); - reg.write(io, base); - } - } - }; - - // Generates the IO accessors for an array of registers. - (@io_array $name:ident @ $offset:literal [ $size:expr ; $stride:expr ]= ) =3D> { - #[allow(dead_code)] - impl $name { - pub(crate) const OFFSET: usize =3D $offset; - pub(crate) const SIZE: usize =3D $size; - pub(crate) const STRIDE: usize =3D $stride; - - /// Read the array register at index `idx` from its address in= `io`. - #[inline(always)] - pub(crate) fn read( - io: &T, - idx: usize, - ) -> Self where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - { - build_assert!(idx < Self::SIZE); - - let offset =3D Self::OFFSET + (idx * Self::STRIDE); - let value =3D io.read32(offset); - - Self(value) - } - - /// Write the value contained in `self` to the array register = with index `idx` in `io`. - #[inline(always)] - pub(crate) fn write( - self, - io: &T, - idx: usize - ) where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - { - build_assert!(idx < Self::SIZE); - - let offset =3D Self::OFFSET + (idx * Self::STRIDE); - - io.write32(self.0, offset); - } - - /// Read the array register at index `idx` in `io` and run `f`= on its value to obtain a - /// new value to write back. - #[inline(always)] - pub(crate) fn update( - io: &T, - idx: usize, - f: F, - ) where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - F: ::core::ops::FnOnce(Self) -> Self, - { - let reg =3D f(Self::read(io, idx)); - reg.write(io, idx); - } - - /// Read the array register at index `idx` from its address in= `io`. - /// - /// The validity of `idx` is checked at run-time, and `EINVAL`= is returned is the - /// access was out-of-bounds. - #[inline(always)] - pub(crate) fn try_read( - io: &T, - idx: usize, - ) -> ::kernel::error::Result where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - { - if idx < Self::SIZE { - Ok(Self::read(io, idx)) - } else { - Err(EINVAL) - } - } - - /// Write the value contained in `self` to the array register = with index `idx` in `io`. - /// - /// The validity of `idx` is checked at run-time, and `EINVAL`= is returned is the - /// access was out-of-bounds. - #[inline(always)] - pub(crate) fn try_write( - self, - io: &T, - idx: usize, - ) -> ::kernel::error::Result where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - { - if idx < Self::SIZE { - Ok(self.write(io, idx)) - } else { - Err(EINVAL) - } - } - - /// Read the array register at index `idx` in `io` and run `f`= on its value to obtain a - /// new value to write back. - /// - /// The validity of `idx` is checked at run-time, and `EINVAL`= is returned is the - /// access was out-of-bounds. - #[inline(always)] - pub(crate) fn try_update( - io: &T, - idx: usize, - f: F, - ) -> ::kernel::error::Result where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - F: ::core::ops::FnOnce(Self) -> Self, - { - if idx < Self::SIZE { - Ok(Self::update(io, idx, f)) - } else { - Err(EINVAL) - } - } - } - }; - - // Generates the IO accessors for an array of relative registers. - ( - @io_relative_array $name:ident @ $base:ty - [ $offset:literal [ $size:expr ; $stride:expr ] ] - ) =3D> { - #[allow(dead_code)] - impl $name { - pub(crate) const OFFSET: usize =3D $offset; - pub(crate) const SIZE: usize =3D $size; - pub(crate) const STRIDE: usize =3D $stride; - - /// Read the array register at index `idx` from `io`, using th= e base address provided - /// by `base` and adding the register's offset to it. - #[inline(always)] - pub(crate) fn read( - io: &T, - #[allow(unused_variables)] - base: &B, - idx: usize, - ) -> Self where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - B: crate::regs::macros::RegisterBase<$base>, - { - build_assert!(idx < Self::SIZE); - - let offset =3D >::BASE + - Self::OFFSET + (idx * Self::STRIDE); - let value =3D io.read32(offset); - - Self(value) - } - - /// Write the value contained in `self` to `io`, using the bas= e address provided by - /// `base` and adding the offset of array register `idx` to it. - #[inline(always)] - pub(crate) fn write( - self, - io: &T, - #[allow(unused_variables)] - base: &B, - idx: usize - ) where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - B: crate::regs::macros::RegisterBase<$base>, - { - build_assert!(idx < Self::SIZE); - - let offset =3D >::BASE + - Self::OFFSET + (idx * Self::STRIDE); - - io.write32(self.0, offset); - } - - /// Read the array register at index `idx` from `io`, using th= e base address provided - /// by `base` and adding the register's offset to it, then run= `f` on its value to - /// obtain a new value to write back. - #[inline(always)] - pub(crate) fn update( - io: &T, - base: &B, - idx: usize, - f: F, - ) where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - B: crate::regs::macros::RegisterBase<$base>, - F: ::core::ops::FnOnce(Self) -> Self, - { - let reg =3D f(Self::read(io, base, idx)); - reg.write(io, base, idx); - } - - /// Read the array register at index `idx` from `io`, using th= e base address provided - /// by `base` and adding the register's offset to it. - /// - /// The validity of `idx` is checked at run-time, and `EINVAL`= is returned is the - /// access was out-of-bounds. - #[inline(always)] - pub(crate) fn try_read( - io: &T, - base: &B, - idx: usize, - ) -> ::kernel::error::Result where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - B: crate::regs::macros::RegisterBase<$base>, - { - if idx < Self::SIZE { - Ok(Self::read(io, base, idx)) - } else { - Err(EINVAL) - } - } - - /// Write the value contained in `self` to `io`, using the bas= e address provided by - /// `base` and adding the offset of array register `idx` to it. - /// - /// The validity of `idx` is checked at run-time, and `EINVAL`= is returned is the - /// access was out-of-bounds. - #[inline(always)] - pub(crate) fn try_write( - self, - io: &T, - base: &B, - idx: usize, - ) -> ::kernel::error::Result where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - B: crate::regs::macros::RegisterBase<$base>, - { - if idx < Self::SIZE { - Ok(self.write(io, base, idx)) - } else { - Err(EINVAL) - } - } - - /// Read the array register at index `idx` from `io`, using th= e base address provided - /// by `base` and adding the register's offset to it, then run= `f` on its value to - /// obtain a new value to write back. - /// - /// The validity of `idx` is checked at run-time, and `EINVAL`= is returned is the - /// access was out-of-bounds. - #[inline(always)] - pub(crate) fn try_update( - io: &T, - base: &B, - idx: usize, - f: F, - ) -> ::kernel::error::Result where - T: ::core::ops::Deref, - I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable, - B: crate::regs::macros::RegisterBase<$base>, - F: ::core::ops::FnOnce(Self) -> Self, - { - if idx < Self::SIZE { - Ok(Self::update(io, base, idx, f)) - } else { - Err(EINVAL) - } - } - } - }; -} --=20 2.53.0 From nobody Fri Apr 17 01:39:55 2026 Received: from SN4PR0501CU005.outbound.protection.outlook.com (mail-southcentralusazon11011057.outbound.protection.outlook.com [40.93.194.57]) (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 8881F3A0B3A; Tue, 24 Feb 2026 14:22:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.194.57 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942970; cv=fail; b=ABUZNzjoFIYPI4WcoabbRGSTadRGHbbPlwbZI2X8y6rhSFMIdAQhrU7PeKctkCs8D0l+Mk3CrUeNYaKTOyavcexU3lYUc4EbcVRgRnW9+vxS5oRjXiOD6QGDsSZuyokPMRdOTnnZHXKRZvYfu8iVES+BaJBNXZWL0SOrRpX6/HY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771942970; c=relaxed/simple; bh=/y6RnGW2swTVELS5Nlo+4AckPhk7/L2JAGf26Oc2oEQ=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=KaCrSqhJIaN+/8HP+LohtHqkFp3Au/wrcxTlYQFl7D2u80U+ywHrIGJTaHq+GNVAkNjzRPB8y0gW0D+asORd2xudYBAj10K8y7SkKR+l2CDSRHi/yH6puT31VGKRha36Y5hvPnDKgHaolNTBkfAMtPqzEIxbQKKqoQq+vdcAm1A= 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=PKgB5FUy; arc=fail smtp.client-ip=40.93.194.57 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="PKgB5FUy" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=P+YgeNsrXxyg2BPKv9UHe+CQMongTWJMJMb4qgvgnOgypMWrUIfg1IpjWkXU/byoEYFdwc29D/do6Y/JBCjABIQsgrKe20Iq5VjrtEK8FtJLFQeljJYn6Uf9x8nKFRJGFMk69K3KCjacaLSDNxkhEH6yfRTuY7oYgSpT9PjRJNLlXX/RJmW6aW/6ieUDjM9KaKX7tUMH9yAbroIlVTcNT0QnsXfA7Xva9ip0+zZjUjq+3Pdit4ar14U/+h7wmm9tkklXbnzItBSxdnVjVSh1cDVfTzu564UIf9mLugCiw6dVAQ1BHROz4/NskvwiSpHdTZHLtdH9iIyS7bEChn17xw== 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=fndS12wnNkUryPM+B1QsCHHaUFfv0ftRDgCYvef62RY=; b=SiJgZL/ao+nCdVijypdMTmwtnJb1Zdjh8jMR6rkSCz3ngK93h+btJjbMHWoI7dZDLi5pQ2mtfOX1GeiiMwH0EQg0DUerGZ4KdFxxtWTZlBtlDpo/c1NTPNtzZC1EL6cVptkyKOaTBdzMUJDEYzmcFsiZMzmyX8aq0n6LbSwno7t6v3WpSWL+3y12BQ63h63fPi08LTc4B+sScAzMHR4WmHoGXMV6Z6wiaKLJTDZEU9DntBqMC2/jkDu2pXk9Hf+jhQaDdQWfy9ubGpVG+Nrhn7LWkF00AV8JPSuqP7186wf9MfKSxkt/bYaWMrrLT4bQR4+F/pKnyAXg00BLtikqlw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com; dkim=pass header.d=nvidia.com; arc=none 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=fndS12wnNkUryPM+B1QsCHHaUFfv0ftRDgCYvef62RY=; b=PKgB5FUy52OBJqt5nppdBQqObuyhEFO5ekE4drJEJATz79y25bxgzHr3dsH+asbmi8M8L1dK3JrHevELd7QnNgsCyhaCNpkmHZYE3gCn/2xzZU7/DVBR5ohx6A6ORamFe2BeUWuDpuSmj2IDjRPlf8ujDg0gcsnAmu4l1ck87b8xffcsYCkpJhlvCekNApOKUq5GubwOngSpqeaU15bhlCT/wBGq5X/aMwQ0XSy4N/TkcbCyfGNt5llfoztATY2vwUwDckCrv4DwTml48Hn1Ca1KyDhEpMrsizM7s3H+mbhzDT/3FPoEHVuvxh+Iklft62NNgGXUaOmYbm+g6FE9jg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) by SN7PR12MB7811.namprd12.prod.outlook.com (2603:10b6:806:34f::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 14:22:45 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%6]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 14:22:45 +0000 From: Alexandre Courbot Date: Tue, 24 Feb 2026 23:21:48 +0900 Subject: [PATCH v7 10/10] RFC: rust: io: allow fixed register values directly in `write` Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260224-register-v7-10-aad44f760f33@nvidia.com> References: <20260224-register-v7-0-aad44f760f33@nvidia.com> In-Reply-To: <20260224-register-v7-0-aad44f760f33@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross , Boqun Feng Cc: Yury Norov , John Hubbard , Alistair Popple , Joel Fernandes , Timur Tabi , Edwin Peer , Eliot Courtney , Dirk Behme , Steven Price , rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Alexandre Courbot X-Mailer: b4 0.14.3 X-ClientProxiedBy: TYCP301CA0070.JPNP301.PROD.OUTLOOK.COM (2603:1096:405:7d::12) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR12MB3990:EE_|SN7PR12MB7811:EE_ X-MS-Office365-Filtering-Correlation-Id: b8134b38-da19-43a1-03bb-08de73b02dba X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?eDI3OURJVkUxdkRTVzZhcTdkcTNkZWtZb2I4bU1SYWFERk9RTW82YWpVa28x?= =?utf-8?B?RkV3VklrRSthNTlZeTBteWVTTkpoYXI3RUwycS9DRGZCeDdXakRwM1VVamJv?= =?utf-8?B?OXArM1dzY2ZsaUt0a0tHY095dlpZbDBGUVV1aDFxR0JaUzBuS2hYdnp5Wk1v?= =?utf-8?B?Y2FJYmVMYjhSUHlBbUo2L21DdnRPQWdGSTN1S3h1ZDZEQzRmRm1JTGZMV0lZ?= =?utf-8?B?MUw3dlhSejZJWStrNFRqZ1hzc2oxNkYyZ1QvVmlwK2FITVNkdXNDeVMvSzdD?= =?utf-8?B?MHF3WHI0alZvNzlLWWZLMGdWMEFobjVIU3BJdlhpNTB5RG1FSm1NSncxS28w?= =?utf-8?B?VVFFdjh4NUdDQmxQbWd1Nm5HNzhxc1lRU2hNSitGT21zY3V1SURUTjcxUHFX?= =?utf-8?B?emFHbTZTL200QjR1SkREbVBsaHVYOVlHTERwQVQ1eU5SRHAzMFN1ZHR6N1R4?= =?utf-8?B?YmxSNGNTd3N5aFJ0cW1ZTEtPM3d4RUpRaXlBa1ZQczlWVnZ3SzNNTEw2MWVn?= =?utf-8?B?U1hzKzkwbnNoWGNPQWFtN3NJTk14bGFQNkp4ejZiYUR4TFZHR3J3cytYbWF4?= =?utf-8?B?ejc3TStuQmZaMFVIeTR4TzRCaEIrb21ubWEwaTRvWlZTVTdLaWVWWElvMkpB?= =?utf-8?B?cVlQTHFVNll2Umh1VVZ1NUtsMFJhcTlXTjNWM0RkQ29ONXpwcERJeXhiWW5s?= =?utf-8?B?REc5SXR3bUhSdXNSeEJ5UzYxcVM2dUNwdUZtQVhpZnBKYlh1VG5HSHB1dzZT?= =?utf-8?B?MStMci8wS0JiNWJsN2d3ektvcU5DM0l2MGZzT2dxMEhiM0RiNTk1OWgvbjB5?= =?utf-8?B?Vk5icDZWaG9teFF0SS9FYk5uRktxNU1PQ2phcUlKclBLVGVDZ2JwZWMrMS9s?= =?utf-8?B?ajQzRzFTcXFSSUowU0JZc1l2bjhSd1dRU29NUkpGbzRPZTVjUFYydUx4Yllw?= =?utf-8?B?eGZYV0JWMUVyWWUvNHl1aC9iNUlCdkpDQUEyZnJramJFSEFoMUJad0Ftd3pt?= =?utf-8?B?aWErV0l2Qi9UMElIaEV3M29naTNMQ3hySytRUk95Q29CclFEVktOM2JqOXQw?= =?utf-8?B?T095REd0SWI2MDRIVGoxQ3dSTWhUYWZjS25GRUZyYlRWK2M1Z0xJSkpwOUJo?= =?utf-8?B?S2hYRER4M2JIekVLTkROY3krYVhkS2lEM1R4VGQ2NEhNUktkaFB4Z0NjZkU2?= =?utf-8?B?a3J1SHE1WExTTCt1cTEvVzJ0cmQxaHhtemJxNE9xUERQMGNCNWtGYVVhT3FW?= =?utf-8?B?MkU3OTdhQWJqRXJQWHExdVI1d0Zhc0NJRWFYc21YUWJhMEMvcVZ1QlNiRzFY?= =?utf-8?B?ZGlLdUl6VFV5K2M5cGwvdzhld056emtaRGo5cUpoRTAzSjRGcWVNQU4xbStZ?= =?utf-8?B?SzFGeTZQeWRZOHpWUjVRa3BSNVlXZnlXL1YrK1diSWxMbDlMaG9SOWFOcHdk?= =?utf-8?B?WlpaaG9IaDFRSFYzczhsSWdqTUNrMHM2VDFYZnpJZjdWK1J0WThURlhyTmNZ?= =?utf-8?B?ckJtUGRGZERxYVJhWTM5SUo4eGJRdmlpMDd3ME5CNGhPNGNhWXN4ZmU1d0V1?= =?utf-8?B?MXEzWEFlWmp6d2w2dC9TOVc3RC9XWE5mRXk5cGhTQWVvWmFGZmlRaWU3RDRY?= =?utf-8?B?ZWhiYXJrcnZsQWNzQURId0NvUThNVHhFK2JDZUxVMEFvcEY2TmdNM2VXUGQ3?= =?utf-8?B?bjJYbjYrUHR1ZWd3NjE3WDFJeEo3Qno0Q1krVWtRajZUMEJPektvM0NFVzR2?= =?utf-8?B?cm9YTFFpUXlpb0FDaTQ4UmZrZ0JERjBVeVRpeU4rT1RwK0szUkhwRHd2ang4?= =?utf-8?B?c1NPZWZpTGpUMXA3ZHkvdTNkQ0RzN1hIYnZpcmdUQlZhbFA2ajRWMEwxamU2?= =?utf-8?B?VW5ZWEFDTjZsRVJERjhNZHpUZ0VzSVMvR2NPZENEOENrZXZ0a1NVeS9jMkhv?= =?utf-8?B?cUZJRnVORWtYaEkvSDkydEhCeWt1WUhWaG5IbnhYQU1GeTcxcnhrUVZySmdp?= =?utf-8?B?WVlZZzE1eFNSS3pRbFZybkN1U0xlS0hnZXA0OTlzM2QwVGxzR0FQMXAraEdE?= =?utf-8?B?VUNweUNJV24yZnRxYkNnUFdWNjBIZStGSmRZeUVFVEwwWmdrK1E5MWVGMDFK?= =?utf-8?B?eEVwZzQxaFZiQmRNdkhxaWlmYlhJTE9uM3Z1b2dmZGhGR3lsU1ZGWlc2K2Rj?= =?utf-8?B?cmc9PQ==?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:CH2PR12MB3990.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?anVyOTVHYVdpRU5ra3JjeVh4c2ZQbnVLZ1MvTHN0MkxKd1c1d01OMEFweDk5?= =?utf-8?B?UkJSU1dPcVdRRWpxYUgzZU12WGJkTHBLSEIxZG02WnFTemZpMzQ4WGZxaUhW?= =?utf-8?B?RkhiOXJEdGtKQTZMRTJEN3l2TTZoU2JJeEQwMTBOd284R3JIaCtPVlFmTjNE?= =?utf-8?B?MFVkZWR6SVlWTFBVUGJIc0tYLzhueUg4TDlIS2xjaHpUc2I1ZFNvYXNFaUln?= =?utf-8?B?KzFISUYwdzFLTk11VWl3S2ZYNUtJeVVqa1VIQUNrWTdJeGRFNE1wWjlHQzdW?= =?utf-8?B?MTBCOURRN2grYTB6aytCZ3pISGJrMjlWamVIT2hxMll0UXdrU1laWGZNNGdw?= =?utf-8?B?c1J5WVZOaExDbWlxblkwZllsemswUFc5dmxjb1ljZzJJYy9QTFI2Zkt5N0ZG?= =?utf-8?B?RlplTnlGY3paWTl1UTVTQURVTnhpb1Brb2tKRGRLSlVGU0JyYnVSVCs5OWtQ?= =?utf-8?B?ek9BbUFTcmJKTllLT0FVeXNjQkR3dlRxUk5mQlFOM1hPYXF2YS9kSzkyemtp?= =?utf-8?B?SkwxeEJucXVEN0gvYjJabEphdkRBZXRDRlplODMyKzVqTVU4N2pFTkZheWVV?= =?utf-8?B?aWV2bUhrK1ZTQkE3MG5Ma2dkMytVc253RG5HVElYaHFMRnFKWkxLKzdJaCsy?= =?utf-8?B?aVFRRFN5VHEvamkwODhqTGxvUy95YjUxZjBGb09oblpJTVJBb1pWZFkvOXY1?= =?utf-8?B?MXhjV3RGSWtIN0M4WWlkcVY0ZW1qQ3RtWTY2bEIzQ0QvWHdySWZCeG9USDN1?= =?utf-8?B?VldIK1lKWDdvQ3d4eURKS2hKbDlwNDNuQ0kybDJLYWMzaUdUbklHRGUvTUtU?= =?utf-8?B?UlROVitPQTI2bU9MMFhrRklUVnNMQ0s0K2lBeEZvY1ZYb0FHRnJTbW0zNFNP?= =?utf-8?B?UlJTdDgzWGljVVF2eGVSejdDL3ltM0FjTFBiVENsNkNKNVovQVhsZXZWdFZu?= =?utf-8?B?a0FBelNDKzdNWXpXcnIzU0psbDZVU2dKYytLRExzd2k5WlZ1d2Voc1NyenRM?= =?utf-8?B?QWd0ZGNnZTVNdXh1YlFwYWs5QWNCTjJ5WDBhclRwVG51bjhlUldBeDRUbFVK?= =?utf-8?B?UFpLZHFZaHQvdVZpbnNHdFBhSmZsV24xV0JHQjZvNS9xdzg4ZytKbDBiTkZX?= =?utf-8?B?OTdvMXY1N01vajdDT2pJVUJLbGVWWDRyWFA5eUlQdXh0OFltQXowR1lpQk5O?= =?utf-8?B?R2RBZVdnZmVJeEFwamRaY3AxTmJ1RnpXZm1ZNkVLSy82WXR2Rm9UaVVvRG85?= =?utf-8?B?WlI5a0hIRWo3NWt1Qkhna29vdFNsMVNpUnpGRFJDMzdYUG9Xd1ViR3VKdDhU?= =?utf-8?B?Qy9rT1hZbHBiOVZxZFYxRERMT0xSZ2U4WGVSWUw3MHhxa1ZVYlkrRWRyeElB?= =?utf-8?B?ajdNdFNzbDBFbWl4b1VRa21Nc1czUGxabUJkNXVrN3pRLzZ0djhjKzlxSW5X?= =?utf-8?B?bkNsS1cvVmpmbEZORFdITDRybVZCb3oxeUpNRmQxVTg2TGdLVHhzVGJsUmJu?= =?utf-8?B?bCtXcnY0WE9CS2lZQzFoT3R4TU9hUFlSUmE2MS9OYmpnOTV1V1B6dGc0bWZ3?= =?utf-8?B?MERYRW1JSDdzSEFrM283K2RzTGlHTVduZi9tL3FaNGlRaHdxem94ZGlIazJB?= =?utf-8?B?dm9DMmxCOTJoMWxPUmpmN3plNkc2Z0sySHQ0MEhGbW02UWE4UVo0RUpUT1pa?= =?utf-8?B?NCtrS0tJTTUvc3FoRGRRSTlhL0RtT05QZVdBUExNYjkrZTJVMFdIdXArd1J1?= =?utf-8?B?OGgrbTU5UEFjeElIUHdZR0VNV3hweng4ajNhUFB1eTBRa0lBZHdSNEhQUk91?= =?utf-8?B?QnJQSklEaWpyYlFPRFpWNFZOR1BIZitocy9zK28zbFFmYURwOUlQRFhQajYy?= =?utf-8?B?N3NNS0tQbjhHTUV5bDYxb0JjNUU2ZlBLQTg2MjNaRWhRN01scXBESCtaaGJa?= =?utf-8?B?cWxmbldyTFZOTERGaFRSS2xpL3JxZmxUSjNOL3VDeWNBUFhCN2h6cDZuakVF?= =?utf-8?B?L2RhaHNtN3RqS0R1OS9USnRiQjVmRlRYQXVycFVCVENuTVgvaHFCanhEakNE?= =?utf-8?B?N3Evd1h2aXA0MUFvUm9HMkZJdU80SENOZ1JhcVorTDNSUHNuZU9hL0pQeHhJ?= =?utf-8?B?bUVwbzlJSVh0cVJHK1JhSkc2N3F3VUZjREh4d3NyNUdoWVpERWcvTHl3TUxo?= =?utf-8?B?Si9JNXQvY2F4WElVMUVUZGttVVdZTEJKRzFzVHMyNVNJTStRcGVyWkhKd2lB?= =?utf-8?B?enFqWHdkTHUyZTd3TjA0SkYwL01LWkdybjNmNWdxWUhpOFc2N0cxTG1JTFpQ?= =?utf-8?B?OGxlTG1oenpaSTFTKzBZUzZSWnRINFpDR0xGaHFNMVJacUlCcWtnS20yVSti?= =?utf-8?Q?BlwNjFcByoQFmZiPyTo/mPYY/HjpSZVj9wb0YBZi6FAF8?= X-MS-Exchange-AntiSpam-MessageData-1: 0LWo4aPaNW8DWg== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: b8134b38-da19-43a1-03bb-08de73b02dba X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 14:22:45.3275 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: soO+gfbmvJyaYYGAeDURm+U1tYJEfosNJiV3O3suCSccOjoVlVxL5pUrbCDOHGBtQdRsyPX9mtxwXyCh298tiA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB7811 When reading and writing a fixed register, we end up specifying the destination register in the `write` operation even though it is already carried in the type of its value. I.e. we need to write let tcr =3D io.read(TCR); io.write(TCR.set(tcr.with_unf(false))); when the following should be enough: let tcr =3D io.read(TCR); // `tcr` is of type `TCR`, which carries the offset we need to write // to. io.write(tcr.with_unf(false)); This patch allows the second syntax to be used, by making `write` accept any type that can be `Into`'ed an `IoWrite`, and providing the required `Into` implementation for fixed registers. A similar trick could be used for relative registers if we include their base into their type (not done in this patch). However, array registers won't be able to use this shortcut (at least not without increasing their size to carry their originating index), which introduces a slight inconsistency about the capabilities of each register value. Hence this RFC to discuss whether the syntactical benefit outweighs the consistency cost. Signed-off-by: Alexandre Courbot Tested-by: Dirk Behme --- rust/kernel/io.rs | 8 ++++++-- rust/kernel/io/register.rs | 14 ++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 690c25de979d..b83472846d3c 100644 --- a/rust/kernel/io.rs +++ b/rust/kernel/io.rs @@ -545,12 +545,14 @@ fn try_read(&self, r: R) -> Result =20 /// Generic fallible write with runtime bounds check. #[inline(always)] - fn try_write(&self, op: IoWrite) -> Result + fn try_write(&self, op: I) -> Result where R: IoLoc, T: Into, + I: Into>, Self: IoCapable, { + let op =3D op.into(); let address =3D self.io_addr::(op.loc.offset())?; =20 // SAFETY: `address` has been validated by `io_addr`. @@ -590,12 +592,14 @@ fn read(&self, r: R) -> T =20 /// Generic infallible write with compile-time bounds check. #[inline(always)] - fn write(&self, op: IoWrite) + fn write(&self, op: I) where R: IoLoc, T: Into, + I: Into>, Self: IoKnownSize + IoCapable, { + let op =3D op.into(); let address =3D self.io_addr_assert::(op.loc.offset()); =20 // SAFETY: `address` has been validated by `io_addr_assert`. diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs index 498cb3b9dfb5..68e6ff1a2f89 100644 --- a/rust/kernel/io/register.rs +++ b/rust/kernel/io/register.rs @@ -305,12 +305,12 @@ fn offset(self) -> usize { /// pr_info!("chip revision: {}.{}", boot0.major_revision().get(), boot0.m= inor_revision().get()); /// /// // Update some fields and write the new value back. -/// bar.write(BOOT_0.set(boot0 +/// bar.write(boot0 /// // Constant values. /// .with_const_major_revision::<3>() /// .with_const_minor_revision::<10>() /// // Run-time value. -/// .with_vendor_id(obtain_vendor_id()) +/// .with_vendor_id(obtain_vendor_id() /// )); /// /// // Or, build a new value from zero and write it: @@ -806,6 +806,16 @@ impl $crate::io::register::FixedRegister for $name { const OFFSET: usize =3D $offset; } =20 + impl From<$name> for $crate::io::IoWrite< + $name, $crate::io::register::FixedRegisterLoc<$name> + > { + fn from(value: $name) -> Self { + use $crate::io::IoLoc; + + $crate::io::register::FixedRegisterLoc::<$name>::new().set= (value) + } + } + $(#[$attr])* $vis const $name: $crate::io::register::FixedRegisterLoc<$name> = =3D $crate::io::register::FixedRegisterLoc::<$name>::new(); --=20 2.53.0