From nobody Sat Feb 7 17:20:33 2026 Received: from PH0PR06CU001.outbound.protection.outlook.com (mail-westus3azon11011022.outbound.protection.outlook.com [40.107.208.22]) (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 732A129CB57; Wed, 28 Jan 2026 02:37:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.208.22 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567862; cv=fail; b=kjl/GMuHnMKT5j1eyjNC4jwOFlb7XcyCq6LwMIN4N+9wPNWv0F3q19oD3cLNBx9d+Jvu24vAX5b/wsEPwC4yYb6xiNyzf/JWU/TNHGWbiviviBID6KUHfwiuZcdXb35SeX3bpGZ2l7WvoLB9sT7l7vdKhu39Eur6te0+FHNVfR8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567862; c=relaxed/simple; bh=X4lDluXAUVw2Jbvj0d4PEL7Nz0HYbGEfpGwR91vlZEM=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=MwMHcT5mR7ruxoLjlMHDD6Ib7qEgaqTwfqW5wchagTKHaUpUNtZ77Ex0sczx5tkmbQTF90LJ8VCaMSB+QlTdA6gcl3eq5AAtY+yjnkABTpY2Nbi4z3nnhZHSPY3y+LOcX2PCD00hN23Bu3uUx0H5+mrUiYDd+az+NUkYiDwRNuE= 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=AFL5nMwx; arc=fail smtp.client-ip=40.107.208.22 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="AFL5nMwx" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=ZCPLC1q76xVDNEIhTsR2GsWX0Cj5nEdNLdipy3JuZ3gzojAxs33Gdw5Oh0iCzNJFi6zkAB4pJOcFo5YiRbBrJJrpoRwcDinjnFD/hKnOH+wU5rsbZ7x+rRGJV+TqmUfw6PvppRCmYcMi/ymUeVfqxztuUd/50/7pIquV5m9IwPF7sKryFZB0OriXFCA4De26waxazwT88u11HIoNYH9T1fD1awRmxPLWmKwUYCZXPsuv4kewfOYej+OgBYrx4M+XA+XoL6MZomwNn9gbTEUmrA1EBuZexG+JG5lJishYD24KqcXGzWb01EjUfk+uqWKfRL0LaBtun4GWcVtdP24VdA== 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=KSfvAxLz+4SDIFzSHfVLJiFUaRGC75c5uP82GVaXaRI=; b=jA+24vhzZ+YI32ph5VAOB7szQeCD+KewLrTpC3XJ6qnx6anXlaqO0eJXdna6YIEPbelnCjvqWjcD0bdnU6mQYPegeIZ/vOFuV5Usxcv8EEyxzBlgRkf6GRAo3AAHTZ5YuV5vem3vOLGAzpLW+706TwXJjcjSQA0n1S+nuddkrJIgwUlyIA8gKA2QD7b7xQqnaise5YbtZmG4CKgm5g2zd1OecZSCZ7UoMrEV6FRztaUdQF7XyL9cMhxShlRMuTRNkqofNG3TruR/j+K+ey5P/bXeYifKdbSqsAXG2jlgjjHqP1N4NLcWxelvieQTl8u0dycP8Mv3hnIMohhgRl3n6g== 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=KSfvAxLz+4SDIFzSHfVLJiFUaRGC75c5uP82GVaXaRI=; b=AFL5nMwxGQVY6ZViKGlkuOnbZhJmyvFuZf4jEMQKjrzhrOtwnWkGH3vu5r07KIDO1eB5dMGUBcCdtwKjAjIzgXmWJuG1LbEoog8jCFlzzUHgRKw4sMcmiDekr/RLwcLNb8wJq6U3zEM3Pmj7HQxUbNmVJQbCKpyrtln9qUG9/ygLb0VGAiVUljdzQvAGNZCVuTdk//fnm0XiBHXZ2NrDBsfIPQc3MEzZxJTrMZjiOHH7cL/GiALkVL2ZzrD7ch4vTLO+RNajSY5j/P2EXYty775O68Sg/DSbRs9WpLNPbKD2iLAEEMyJ7tcQilqBtykxcLgKRJoDs7yaAIiNiX7GnQ== 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 PH7PR12MB5654.namprd12.prod.outlook.com (2603:10b6:510:137::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.14; Wed, 28 Jan 2026 02:37:39 +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.9542.010; Wed, 28 Jan 2026 02:37:39 +0000 From: Alexandre Courbot Date: Wed, 28 Jan 2026 11:37:27 +0900 Subject: [PATCH v4 1/7] rust: enable the `generic_arg_infer` feature Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260128-register-v4-1-aee3a33d9649@nvidia.com> References: <20260128-register-v4-0-aee3a33d9649@nvidia.com> In-Reply-To: <20260128-register-v4-0-aee3a33d9649@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross 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: TY4P286CA0116.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:37c::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_|PH7PR12MB5654:EE_ X-MS-Office365-Filtering-Correlation-Id: 8a51f512-96a9-4fab-2a99-08de5e163416 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?NjVFV3VDSFBMRXpqRmttYzlTS3JLaFFGWTFHa3FSdmdOLzh2VnNVQzg2bFlS?= =?utf-8?B?ZExucWxYZEhnSzJFNTEzdkgrTXF1Y1VzTllGNkxrN1NrcW0zMmFkK0s1SzdD?= =?utf-8?B?MFROWm50aTdZVDZVK2tQYkhjYmpmNEZZdHRaclNORWpnVkw3clI1bWwwaHhx?= =?utf-8?B?MURLMGMzRXpoanZLUWJzQ2MyM2FMbHFXYko0MXJSamRQME1ObmdtUmRkS1R5?= =?utf-8?B?bldkSHpldmZ6U2E3WUFIYmZOVHJCZ0lDL205MSthQkNuR3FmU0owYkpUWklR?= =?utf-8?B?SlNSeVZWTzZ4TjhNV3UzSVhpdDlsZjVVMXgvTk1KRmdoY2lTTGN4SGNvcmlM?= =?utf-8?B?MkpsQ1d3WkNMdkdSK2JFM2RLbzcyOHFyUVpVR1FKTG1USWNtcmNaaFdPQjhO?= =?utf-8?B?TElzT1NyMHdtV2svOFk4Nlg5aG12a3lKTmJvd29leGtsb3c5K2NYZ1Z1WkU4?= =?utf-8?B?bEtIemJpNytUUEp2Uk85WmNwK0NVdGF4MkVFaHNOdUk1OXNXRjdzMjY0YkdO?= =?utf-8?B?M1ZNakRTZjNVbUFIcnlJZlg3bzBtV1dCa2tGcVd1K0V4bmNxZUNhd290ZzFw?= =?utf-8?B?Z3EveWx3VlE1MnFoQjZxQzBuc0RwdnFYb0xsNkZLV05EWk1MRk8rVUFtdk1V?= =?utf-8?B?TFRzTTlITmU1UUdOYVZFLzRxRDAwK2E2Mk9TbS9mdEN0aWNkSVl5UmpRSEZL?= =?utf-8?B?ZDd3MXNRdVIvK2JpV2NwcWdpMG1RRWZaZU1IRGc3aUpEck9OSlZEYjU1UWlv?= =?utf-8?B?MlJrWktPSTAwWHZZN3duTDVxYmJnRmR2dWFJSkpPR3hpaVlrNXovVXRVNE5R?= =?utf-8?B?R0s5OXhGU2dkWGYzWVNuNVNQS2NzN1dIaDgwSUZUT1hvUUNrTVV4M3pUTC91?= =?utf-8?B?NFdCclFZeGxDTkM5OFBZelJWdnZ3V3g4Z0xUR01jeTQwaEFMalhrV1B3WDA0?= =?utf-8?B?aThPTlhMYUxkSktoZEg3THdYQ3NEckJDNnNrWkY3N0xNVktGcnNua2g3WTVn?= =?utf-8?B?Tm5oaWF1VGtObUdCek1EM0Z0Y1BsZUJEcUlKSEhCS3pYeDNLaVBQZyttMVZM?= =?utf-8?B?bW1SMEZlNU1YOTZNdE9mLzZzUWNPNXFhWXczYUltUEdEK1dNeDhyd3piK2dj?= =?utf-8?B?cUhLcmF5MWRCOWhBTklSbEdQOFNnQmFkRWtMS1V0WmM5KzBZUURjTXFGa2U5?= =?utf-8?B?WGhER3VzcStsSzViNVUvS0dhTnVIWW81ellVS1BnY2ZNR2s1QmpsYUlTaVBO?= =?utf-8?B?cEVHRkJBT0Y3aE5GQzh6Y2tTdk5jVytOWjV5blBpbk9jU09mYVB4N2I3Yzgy?= =?utf-8?B?T0s4blU0Q1ZQWklVNnJ3bzFlVmwreUZ3OXNiL21FUDZYTTh0OVl2U2lxNEF4?= =?utf-8?B?ZU05UHBRbVpvS1ZFckdPeGZqQ0l1WmhzZDVObHBsRC9TVFhsNHRHL1ZzaWFj?= =?utf-8?B?d1h1ZTZGc05adTMrOXhTR29wdnRDUU1zbjIxZlQ0TmdocE9nNGEvL3hRM3Ft?= =?utf-8?B?TjUrb2xoNjhwL0ZSc3NBcVIydFpFcWFnYkRJYzlJVXc1YjJ3UkRnR2k5VTJp?= =?utf-8?B?dGFPd2Iwa29VRmpPaVU3UXIwcEVVaC9VbENEeDBDSXoxWk43R3RBQk5oT0l5?= =?utf-8?B?WmdCMDEwQWdYVk9rSjV5RmtpOXRmUDNqckUwV2N3dWJOd0dsVncrd01HMElq?= =?utf-8?B?dkxCemU5RkU4b0p5UUtNUEgzTDlBd3JpQ0xVdDY2WElrd0MxSlRLNHI5eXJI?= =?utf-8?B?TVJaWFJzbmZBd1NYbEtaeEdQdE1QcW5lakZweUlHRVZZdWZ1VzJuMjJReStY?= =?utf-8?B?NU14S0prQ252dzYvbUt1eUlYSmRYdW4venBsOXhWU2M4Q0FJVEhYY3c5K1dh?= =?utf-8?B?NXN2azBDUXI5aERjTmhUTmphYUFWVUFqSU11amlwZ1NOejlZRWkrT0hPRnRK?= =?utf-8?B?L3VoZ2JTbUNuWDNhbm5wU1p4c0toby9YbkNNTVlSdlFmNXRrM2FhakU3RUdr?= =?utf-8?B?bDZieWhDU1JOa3EyVXF4aEJNNVVFV0c1REdRc2c3NlhHY0F2OTFGRU5qbmxC?= =?utf-8?B?U2N1R3FzeU5ZMG9IM05QekJ0OHpDTVBSbEpwNUs1OWRuekpkcTQ2aWllQlVW?= =?utf-8?B?K0hDVHZMTTJKM0pqeGZad0FGRU5ybllQK0o3bUI3R3dEU1dVZm5DQ3FiYzhq?= =?utf-8?B?L0E9PQ==?= 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)(1800799024)(366016)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?MUhOZ1hic08rWFZLT0JzejNkSVBTVnFSYXh0cGpSMGJWSHBRaHFEaGJtaEpU?= =?utf-8?B?V1E5Vlpvdnp3L2lmVmFDUjFQWXJBc0czZ3BMdWV0WWZzME9yWFl6RGdEZGxa?= =?utf-8?B?YlNnQ0Y3ZE9PR1lvTmxYUXNxeks3OHRQdGVkSFAzUXh2MFpuMTJidHkxVXZl?= =?utf-8?B?SG5NRHpRdFRXZzlPdkJqZzl1UExGNi9lbUZFcFY2YXVhWFFKQWtYMzg1T29x?= =?utf-8?B?ZkNsSmswRlI4dXI3Tk4xUnpja1ZBaFRUM2VmcGQ2SzBWODVKdktNMUpscGNa?= =?utf-8?B?RnZKZ09WR2NSS3g1Y2t1anBFVlNJNThRQVZ4YnlRa1hhck9BWmRJdWJPK0pi?= =?utf-8?B?R2U0ek9pMHJvU3d1UDdMRXBvNFhMVE1UZVNYVXlFUWo5a0lrRUJXbm9pbjNa?= =?utf-8?B?dCtGd2J5bUxzZmcweGlEQ3V1dGJ0ZVNTWXVBOFN5MzFaWXY5U3ErR25kSEdV?= =?utf-8?B?bTQ3YzNlM3cvdGJONEFJUmlWRDZscmJFQnhMS2xkcjJHamk5QWxWL2ZVV3Rh?= =?utf-8?B?NW8wQUNoOWVUdGpxU3AwSmVWdk1mR1dHaXJDYUNFUlJ3bW9jU3VYSDBWc0Iy?= =?utf-8?B?KzRudWJUUjJpZExpSHoxVzI2bjVOUU5Qc1dGeG5DWXlOV2xuWVBNYkFOTkdJ?= =?utf-8?B?dy8xZzBRK2lUeWVUZzRJaXZqaUUzVmRGNXNPOGlLMHh2NHRiMC9ncE5OS2h1?= =?utf-8?B?QzBmU2FMRFFzeEw1SXZhcU5ib1NIMUFLc3JpdnhtVEIrL0pma1JHbUhZUk1Y?= =?utf-8?B?U1o4STY3S3p0Wmc0TDNBWnhjRndCRlhjcURFU0FYOEE0L2g3cm5wangyaXg0?= =?utf-8?B?YVVSMllrMEFYS21KN2VHaVZzd2lqQ3NuSXR2RGo2dGs2VjByRWhQeFFMSzhm?= =?utf-8?B?WVpjcTVxekhWNThGcndISlB4NHpTZFd5YzBMTHp1OFZvUVhYc1JpV05rOVU0?= =?utf-8?B?K0JNUFZQaFA1eTFXYWJRT0I3RjNMdDUvMnhYdVpuTGVxSFBTOGFCYkNucEhi?= =?utf-8?B?MS9pSGlvMFgvNEFHakp1MVh4NVczV3JsQ3Y4My9OTWMxQ2ZTWmxIdldsZUZp?= =?utf-8?B?YWp4WFBJRjVuTGxOcXJpWUtwV3RaZW9PbHZqZyt0RmZTTUdFNEhsK0FCUFlh?= =?utf-8?B?T0gyWE8vUDFhdnRCRWFEUjNDN3J2TGJRTHQvNUpCYm96YWZFZ2xEVDhtUk9s?= =?utf-8?B?Mk9waHZYOHRwVlk0cm5Vdy9VNXFhL0lKSlNxZWRKWkR2LzNYUlkxc2czV0Ru?= =?utf-8?B?YjZnZHd3MWVvTXNyYmNVU2MxNUprZ0x3WmsvY3hFY2d6MVRFK2VPdmZ4eDAw?= =?utf-8?B?bnA2dUNsUzVHVTRLV1Z3SWFiS0VVSlJKL3FDdmNsVVBEOFc2a20rQkJBZ0VO?= =?utf-8?B?Z2lrRWxGY005VGZCaGZJdCt5UmxBeUNmYkoxSmQvK0w4MHpyYy9sdWwwZC9M?= =?utf-8?B?aEJWUVFacml2OFptVmFWcnpEQi9iQ0hlKzk5L3FMR1ZlWFJmdjJNNm54cUxY?= =?utf-8?B?ZmVkZjFOUXlCbDc3VmVKOWZPeHlsanVRUjhtbFlzTDc5Rm00aTY2bi9XakRE?= =?utf-8?B?TDJzWWtWY3JTMXl5L0dpQ2pUMy9uWjZDaitzRXQwUjFOSEZYd3FnL1pkTUJn?= =?utf-8?B?aVpRaVo5Yk1CY3VnYkUxWFZabkhXYnNIVVFyRDU2QUNNTk00YUdDMWlTWUlm?= =?utf-8?B?dmUvQW9LNWI2K2cxSVVxMkM0MkYwMGRWNTByeHgzWXYrSmZkSFJGSXVmSnYy?= =?utf-8?B?emN0ZzNyemR2ZnhwVThmdGxFTDBGV05mb2RhczJwSi9YZnROeWJJQVVucDVR?= =?utf-8?B?eS9Oajhwa1NPWVRlWWRMekZYUFpkNUhQdzRUREF1Tzk1OTVOTjVpcWxaeG5m?= =?utf-8?B?V3JzZWZRc3VXbitvcVRGdGtYSHNVOXRMRlU2djVrZlgvUFdVV0VjSExBUGRu?= =?utf-8?B?dmoxN0NOaFlISEQvSE1TRHlseHdkTENzQld1RFprVGlEYjFoNTVWa1UwT3Rk?= =?utf-8?B?WFJUek9xaXZ3enBwbnVsMVJCQ3o5MmxFaVB3eGJNUExINndiUUNTRzBiWHZH?= =?utf-8?B?WVAreVBlNmZOdk9LMmR4NENNeWZNOVgrU2NiU01IaTdEajVlNURtZ3JlVkxR?= =?utf-8?B?Nk5tODlUYzJwYUQxOG5wem1tdlZUYXg0RWVIUlFxZnhRM0RxNzEvY0JZQVlQ?= =?utf-8?B?L0JIUURDVFUyRkh4eFRkdFl5elFUVlZoWnNvbE4rcy9SRlV3Yi81WFU0dmVL?= =?utf-8?B?bGlhTHM2WWpsb0FQKy84aDRORGVlVFpnbXpwSnI3RGxtUVIzWmtuY2xlVWtW?= =?utf-8?B?L0YwVmpsM0Vya1FEbTJkUHV1QWVoYkFRZkRVUjFGeHp1YWJ5cFNQV1gvQjZ4?= =?utf-8?Q?UjqYjzhrd/i1jg/vP/9t4FHij+CKztjTXvKv3I1crQoQu?= X-MS-Exchange-AntiSpam-MessageData-1: EggVfsBFO6pCJQ== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8a51f512-96a9-4fab-2a99-08de5e163416 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Jan 2026 02:37:39.0916 (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: FfDwkHXCLbwDa98g02xW0UaeY8q6qoO7K8XQlI9Xds6UjiaP6X3YoTO+2WGtQrD4PxDb0/sB9hoEXiwCxcEA9g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5654 This feature is stable since 1.89, and used in subsequent patches. Tested-by: Dirk Behme Reviewed-by: Gary Guo 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 6d637e2fed1b..122ad64880cd 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 5037f4715d74..4637aa11e870 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -312,12 +312,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.52.0 From nobody Sat Feb 7 17:20:33 2026 Received: from CY7PR03CU001.outbound.protection.outlook.com (mail-westcentralusazon11010023.outbound.protection.outlook.com [40.93.198.23]) (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 BDE742BD5B4; Wed, 28 Jan 2026 02:37:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.198.23 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567868; cv=fail; b=d45PRkyIHQ41MztvRx4RUdXGeL2xLIFe7KE4KAacFt1VFmU06yaEoXSO8UWmWgUajJLMUH5p8dayli25LqNKbbGJkGJzrCJT6dVTJFLBOT8gGYspJYJAcWF9O2++Ikq14hZDaE+xxte2HfEttBNSR2y7YuhQfb3uOOaXwF3hZug= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567868; c=relaxed/simple; bh=gMwZJcZwnz+Dwmq6yPXR4f62Bn02pJRf7vCz9aclv9c=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=BeU20tRp+I/YekCL2JRgtMu4Hl46+R/4XMt43TDZn/y0qDSPyovpXK9E3omjOTQp7HLg3jJEo35P4D5IgdKCrk9w464GgLKcDG74EamaTS83S4iVGudRu1LqXXSSGfOzo793l/u5X1s6etEN7cuFukXiZSZjZ/cK860r5ns6nqk= 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=XW8GglUA; arc=fail smtp.client-ip=40.93.198.23 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="XW8GglUA" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Cc1lw2Kj+vP7fpWIWGXn8DXEGRqNmjkx4oe5A9t/n0wo1I0nRRdHYyRY76v1ucS9X7PIlYk94UEaeh9MCoT69SQfSRtuAHxHKKwMPJbZuOw0XLpoqkAhNgE3RBAtxVhWenYzsQaTvnF8NHCUXvCSelo7wigtRWbEiBtZBJKm0aYpouCjxm8AsyK5wulzbMV28Kl0rrJUcXLXCiQjnvHPLPYL0v/F+DLSNoWFpi0AQJYObXV2nexk6a722SpDOoXpFWVRhZAbVjdBZgtToSn6Q7iacF8u7Iy0QNe0sEPgD0tcFlFr0XUZBJm1OhV38vRNyXVP06hTvUz4yhhsoUx/LA== 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=5i8MM7XGusRzleGPGBqvmgJJGtc5boefXrw/KDKRlPQ=; b=GTgHQ/gUpKRfDqyReuOtfbZ4usDV4jNVFq68r34DB9rsbY69nJBb3wVnQk9wleBPKw+6Lu6Wol3nNd2vIruHc37TM/JzQnvB//uix6BZFAOwLYtlDnLDNsekwjV5trGvbagZCesH0fyMAdkk0ytpPqkKTet9ZOItDZOdgZqgKKLcPpyjsh7Qs76r/6suNiiTRq7MQY5m7Avyk1vRwHZeXwIpYCzvl/ItRi178uabWe4guIJd6hPMY6xupfDsOvVwd7IWJ4E9bpJQSyhYhPO37l7ZbZL8zsHiXwqXpsAd5L1Eum9pYlnZAG+3Ijg8dEo4PuRpWsNrTy9jMCZlg0s7Pg== 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=5i8MM7XGusRzleGPGBqvmgJJGtc5boefXrw/KDKRlPQ=; b=XW8GglUAZ36yaNjhUKwy0tftCnTdKGWWQkPVsrhp4n1o1GOoOWAZxpmN907xL4JRYwOMioZQpecWOKwG6tFP/S0DkKaIcbUzdrRn7tqEXlhaPmFUZuNh2oeX+mucmEKgg254Qiadi3EbSXT60PdJa0Gp5tciLiWTFf6udSaZXZLFOVu60Ri1kIeF1696wFdU0LAPjo8eGj27mvUag4xYFbI/ZYkyqbBHKEnHwRPqmzGR1fBkGPpljMWwFfu0/MpCcW3ehB+AJUVj5cYshdwtoSmZIgVBvHKPn6+lA8x40ulZGMHbIkCCZAjblrxzXmVJDLDC8E58ZsIi8FK1gNB/Bg== 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 PH7PR12MB5654.namprd12.prod.outlook.com (2603:10b6:510:137::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.14; Wed, 28 Jan 2026 02:37: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.9542.010; Wed, 28 Jan 2026 02:37:42 +0000 From: Alexandre Courbot Date: Wed, 28 Jan 2026 11:37:28 +0900 Subject: [PATCH v4 2/7] rust: num: add `shr` and `shl` methods to `Bounded` Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260128-register-v4-2-aee3a33d9649@nvidia.com> References: <20260128-register-v4-0-aee3a33d9649@nvidia.com> In-Reply-To: <20260128-register-v4-0-aee3a33d9649@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross 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: TYCPR01CA0003.jpnprd01.prod.outlook.com (2603:1096:405::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_|PH7PR12MB5654:EE_ X-MS-Office365-Filtering-Correlation-Id: ee098fbd-11ee-4dff-c002-08de5e16364f X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?WkNaT21jTGRlcEFxRnZ2NUtDN3d4OEFsUjJtcXR3WndrcExDTW5vUVVaMzlL?= =?utf-8?B?RWNJNmZFcFhHK0lDNzNlNmRJa2NqRitxblU4ZDZiUWlncVNHQ0ZqZ0lwQUR3?= =?utf-8?B?Q3M4cnZZMzRrMUpZTFhDd25iTzljbmg5dEdUY2c5bjNnSmJGUWhrL1JBOFFL?= =?utf-8?B?b2pFdlI5T2d0WHcyUXRkRldReW00QUV1MW1jeEQzTGtsZy83dUd3VzJHVU5I?= =?utf-8?B?OWhaME9uclVZdjJLT25GWTRqYXVGaStLdldxMXpuOEFURlAxU2NWT1ZlUzZw?= =?utf-8?B?RWc1MVl6djlXWTlMeDVaS0pyU0MrR0xVbHRCNDJTQlJUaVdrSzZOMVp5akVL?= =?utf-8?B?dTJIVEp1M1dJZnlVRXlWc1JlRnZiTDhqVldTbVR4Z2dnbWowdUVnU1pxWEFC?= =?utf-8?B?bzFRN0FDb2xTTnd4bGpLRkdlMXpkNmwrODNLMHorZlJRTXdCaCs4R283ZTVG?= =?utf-8?B?d3RyTkZkb2dpTWhFZGZ6Y1hlWHhpaFN3cS9VaUpoZi80ZVF1WGNtMUJDNUg5?= =?utf-8?B?cGROL3dLdk4vVkhvc3pVbnc2R1RYcHczRXFBeGFnOStDcEhNRUVtcU94MHdt?= =?utf-8?B?bm9KYlM2YU01K3VDMGpWZWdwaklUTGkxSk8rbGhVVGgxYUc5SzU5OUdJYmtW?= =?utf-8?B?MTBSenhKVHF1NTdWTXk3L29NRzBZNE44VXZDb1JYVnFycUxmMC9GamQ4TzR1?= =?utf-8?B?bGxmbXJDNGMvZWhKa3VRbVJ4ZG5xR0paMThqUGttTUZuVXJhWUJnUTJEOERi?= =?utf-8?B?cEZQK056Z3pzeXFQUXNYYUxGUUdEUUlyT2p4M3VpVHhJSkxzTHVYcGhmMEVp?= =?utf-8?B?ZGpQMjluKzhsYUhFTUptV29Qay95V1V2OXlTOFdSZ0d4bWpSMC9Xc3c4QU42?= =?utf-8?B?WnJCMDNNUjZRZWM5QWxFeEllM1pBUHdtWHBTSkRTK1VyRFMxS1duSzh1NS8x?= =?utf-8?B?bjRLSU8yYWtpUHozUThCcGx1QUNBYjhjRlhEYmtBcC93SVRQbUM0SEdDM29m?= =?utf-8?B?WUp1Q3crczg5N1dEdUFJYTE1Mm9NVCtrdDJrRTVLSGJSRG82MHduRVM5eFZL?= =?utf-8?B?QlhSc0tKV05lYXJHM09QaCtnYnFjM2Y3TGx0NXJNVEo4RlRHdVdSK3psbHM2?= =?utf-8?B?aXZxalAyT1RJZWRzYUJKMVpuQlBXdUpINXAveFB0eGZmblNYcURxcDVHZm0z?= =?utf-8?B?b1g2Yjd1YSsvSlBFT1BPOGMwOWtSQXYwNUc2ME5HUmxNRmprd3RtaVFOaE10?= =?utf-8?B?WWFJaVpWczJ5QlpnZnM2U0pmaWp6TnRLaWxlRk1KcnJMMFZnbWNTdkY3d2M5?= =?utf-8?B?Q3RYbGRJYjZOdmNCSERVQVhKSDdWNlF2L1JqYy91K0htTk5MaUJtYTZ4RGxN?= =?utf-8?B?NXRuUGJFOTh5S2JHYlkwam9UdUg0Mi9NZUVGK1Z3QTB5dU5IVXBuSEZrbUU3?= =?utf-8?B?SVlzdWl3REJzQ09uTHIwakNnYlIvVGRKWTQ5aFlyMW0wMkJMbEk0dXkzbk1u?= =?utf-8?B?eFNPL0RDcitjdFIyQTZxREFnRFlnYy82L1JoT3BvR2orVUM3NWtLNFNLclFp?= =?utf-8?B?dkExRnVKUE5PeTJaMWRuMjZiK2lHc25JQ1hZMGszUU03Z0VIeld0RnJYZE5D?= =?utf-8?B?NEdUWGNIWlNDMnRTRUdSOHFGSGRwQk1oUTVmdUNlREFkYlFkSXBvMFR5VHRM?= =?utf-8?B?SlloOE1wZGppak9XRjR2YXl5bDJ1SXJwNjI1MmkzODJaVFVZYlZUN21wZnNx?= =?utf-8?B?ekVTdmFCdXh6cEU2UEZ5Y2JzczhIVGNKTXpZMXVjU0NlaE1vSHI1cTh2citQ?= =?utf-8?B?ZGhVditKYkdSRDc4dHhKTlhrem80S0hiNVN2YlQ4NnYwWmhKdmt3L0d0ZEV2?= =?utf-8?B?V2ZkR2MxZFNzaTQ2aEY4OUhEY1ZZOS9mUzN3VWN1ZWNwV0dMbmlmN0JFblZa?= =?utf-8?B?MUdtcTNERm9ZOE1oTnNOZjJtenFIYms3QTVjdHJ2RWtma1pBRkhzWU5FbSs2?= =?utf-8?B?d3F0bGFjYjlGeFBtMHd0VDFWczRWbG1pSVZrQVFmVzdzK1VtNm53RFRDcVFN?= =?utf-8?B?ZkQyQkM4dkFERlg5S1F0YURpMWs3SzQreVZZdU5yYnMxQi9BeXJUUUxMZS90?= =?utf-8?B?UHBtdDdWWStwU0NBMnlpRklCblVPVzhXUDVPVEhadmxuNlMxR2Q2ZDZJR242?= =?utf-8?B?aXc9PQ==?= 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)(1800799024)(366016)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?cnovWmtuaWNjK0NGdjBYREJ3VXNxaTQwQlg2OHZYOG5xWG92WWpBNFltMWFC?= =?utf-8?B?Z245Mm5LbUlJblFSeUpsaWc5S0tLUlk5SEFQcEtscmtGSFhDUHVtTWVUQ2gy?= =?utf-8?B?VTRHbzlOeGJ3bWtTemY3TkoyZ05DY3B0L0dQQzVyOFVBR1J3WFlEemZlQjA2?= =?utf-8?B?Z0lDUFZOM2l3SkllMXVaWlNVaFFQNjEwb1c5dnE4LzRVNjN6cDNzTnNYNmxy?= =?utf-8?B?YXo0bHAyUDNMWWRteTFmL1YzY0J3VTdDbWJlaE1FK0piYW5uTlVTdlFZZERl?= =?utf-8?B?UTZWeGV6ekZyWVlpREFpOGJoVDBnMWE1V0NlRGJUb2d6c2tiVTVkb2ZRQWFq?= =?utf-8?B?SEpRUTFTQWVQWW9ibnkzdzNqeE5iOVdXVWVpME1hcytHNFp3R0JpaVM4Z2dq?= =?utf-8?B?Q1h0U0N5T05BMjFaUFhSb0dRYjBFZDVvSDJkUThSWUlUOU95dTUwNGw5L3hz?= =?utf-8?B?cGdJaWJLNGtEUjlKZzZLMEdablR0VGRCL1hxT3JqTXIxcHhzNXRQRTZTYzE5?= =?utf-8?B?WDZmZnBJbnV0U1orODU2Q2ZpRlI1dUZUMEVvL3hpdkpWVnp4dkZ1R3V6Umkv?= =?utf-8?B?cTYxOGJPN29CNHNrM0U5b0NUWVlJZlpqQWxrUVFPalgwV2FxalkvZ21PQlBD?= =?utf-8?B?K2psTTJNZCtGTVNDaDlvaWdnRXg5TjYrR1E0bWRDOTNkT2Z3N04zdUR1cWJN?= =?utf-8?B?Y1hvU1Bubm9wOFVZWHNtaHB6Ly9yT3BWNnQ3SFRpQlVkZTd1MzI3ZWpDL2Ux?= =?utf-8?B?dzUyU2dEY1plYjFMc3ltSndRQXIvaTFSNXFNU2dmZzl5Nkdvd0NWakt3SFRO?= =?utf-8?B?WFROelVJTEFtR3JtYXFWSXBJSDQwUWJGSW5OTjlKZVJGb3d0RitzczdMelMv?= =?utf-8?B?dUwrV3hKYi9XVS83VlV4NjlZUU5FTG1ZUGFrcGxjblhQRlBEdXh4QWR5SXlR?= =?utf-8?B?VThrRm9HK01scGxoRUNDWHAxYzlVVXBxVG5Ja01nRlhjVmZDZ0h6MlBUTTdG?= =?utf-8?B?UHZpRWVDZGN2cTZUb0ZZSjN3NVMxdmJUKzZzZHp0am1KdnJPZEN0ZHNCV00v?= =?utf-8?B?ekdOMFZyNGVOd0lVclArZHh6YkdSVGRIb2U2S2dvVUhhMXJkTU1abzI5NGlx?= =?utf-8?B?NUpCMW82M2pGNDRYZFVTUFdRQmxaR3RGWFBpM0hOUmpmREhPaWJ1NW8rUmc3?= =?utf-8?B?QURJL0Zrekd3Z0EwUU5nOTEySVBvSFhHUFBlakg4WVhFNG5wdUs0dEpXbjZR?= =?utf-8?B?U1FRL3JnMU5CWFErSFlQaXRudmxMbmlmY3dnS29YQ2dqL2RtNmRMaVYxWEhH?= =?utf-8?B?S0RGcEE0WW1FUHQ3bi8rUXVkLzc1NGtJUjRYMyt1S2FRRkl0YTZxeHd2ZGNt?= =?utf-8?B?bDY4RW5yVVBUelFyZ3FQcFNJbjNkTkNxUnlsZ3RISEkwaUMrUmZEZmFLNDF2?= =?utf-8?B?T2N6VGNEczliTkc1bHI2MnMxMFZaaUVFM1JiN0FndU1tQnZscG02T3BzQTFB?= =?utf-8?B?UXlnRm81MURYeGRPU1lMSVduN1R4S0RGN21DM29uYUsvdHlRMU9lQ0lWUTd1?= =?utf-8?B?bEk5TjFFWDVHYXJsTm8wQlQzVjhhMWU5Z3psc2Z6b0liSXpPalhLN1V1Z2hG?= =?utf-8?B?VitOUnRlQVlrUXNUbGVhVzByVzVlZHFYQlR2NWMyc3RINXhSOG80L21TKzB2?= =?utf-8?B?anYvZzl6UkRFQUMwTlozRllGT0s3ZHZUdkltOVJMT3Y4aFhEQVd4K3dLTVZ0?= =?utf-8?B?MjM3RFE0Q0szVzRBZjZpUVdndS8wUXlvWG1CU0RocnVqVlFWR2g5YmEwaHZZ?= =?utf-8?B?aEEraHBkNGZFb0pWK2FYRzBOaGxzWHZ4Ti80M3BxWnN1VEpJTDMzelJseGND?= =?utf-8?B?RzlsQkxoL1Q0QWRCMDNwMklTbysrWTNGVkhSdDUwNThXa1NEdHBjVWcrbkV3?= =?utf-8?B?Qy9uYmZVd0VDSVFTaDBVeUpLVE53bDZHL2Jmd2ZnZ0tSY2NwWUhwZExzR05r?= =?utf-8?B?eVhiZXRHM1o4emhnZDdCMjlFYnNnckRsZitLdi95aXYxMWkxMzhiaE9CTjFp?= =?utf-8?B?aHZhcnRYT21Ia3RmSHlDYVFYRGdhdUZzbEdXQW1oT1VTMGx1c3lhdHRZdWIx?= =?utf-8?B?c1hRTzlZNVIyQWdpWVk1NEpETnQ0MzZuRTlqQmJoVVovSllUd0h0cXhhdWU2?= =?utf-8?B?dVZBaEtqUGhPbkhubVJXUGlza3pZWDJxTUpJc0NsanVjT2M2b21KUHVyMGRP?= =?utf-8?B?RW9SNDRlbWdpbU9rL2FrQTA1bkhaTko4UXd6VDVjcUMyNE1rekVqWk5PZEYx?= =?utf-8?B?RWNTbEJLczZlWFFJOERZY3h4M1IzNjhmb01hdmIzdFEzZlgraHpWcTgxaGlB?= =?utf-8?Q?DmBM7MiA3cHaK8WgYsyUMFofBcREEBPYlcKrts0dDoDeK?= X-MS-Exchange-AntiSpam-MessageData-1: fGGmUttQ2mhgUw== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: ee098fbd-11ee-4dff-c002-08de5e16364f X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Jan 2026 02:37:42.8157 (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: pTaBiwBVYajaGYnncTv/zS0+isNWIdNLaWgRbbOhU5jMWQoG3mv4mCVtfkjup0kBxMeFPuEeZSaafkhZ0fRtfw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5654 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 Tested-by: Dirk Behme Acked-by: Miguel Ojeda Signed-off-by: Alexandre Courbot Reviewed-by: Gary Guo --- 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 f870080af8ac..4b929762d5c2 100644 --- a/rust/kernel/num/bounded.rs +++ b/rust/kernel/num/bounded.rs @@ -470,6 +470,48 @@ pub fn cast(self) -> Bounded // `N` bits, and with the same signedness. 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 >=3D N - SHIFT) } + + // 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=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=3D N + SHIFT`. + unsafe { Bounded::__new(self.0 << SHIFT) } + } } =20 impl Deref for Bounded --=20 2.52.0 From nobody Sat Feb 7 17:20:33 2026 Received: from SJ2PR03CU001.outbound.protection.outlook.com (mail-westusazon11012047.outbound.protection.outlook.com [52.101.43.47]) (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 F40871CAA6C; Wed, 28 Jan 2026 02:37:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.43.47 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567872; cv=fail; b=ldCxfojzDlkIdTiyhqvLAsy4wHxBV0jRkIlsPBlZeE4zXF7UciaAr/S3mLcmOeWa04zxjCmn6cof/fs+SmjuLqpSGPZ+kmuAM9U45Rsl+0AmPoXlEl+3h8rY1dyI7BC3Vgl95sItGoLw1FbgwrhcupmLm+TFpqnOA2cAtBqKzts= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567872; c=relaxed/simple; bh=dkzuEw31qGUX95GaaYlhqJ3i8VuHE33Lnqv5Skh8PtE=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=jdJ35uBQr9zelpneCwGO3T3TnKm99g1q3f9i2JFygxE8nPZ8KUOmCA+Rik7XAbe71icG91VEDyP0IwXSk5w4/XGcANaZ14P0U0KebyY8k4PwXPE/V5fl4up+WeN1X99Nxy2dXLUGH/gXFEHo5M2dnrvF8bpRcRDwPg3lfbZof+s= 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=Pn0LucXF; arc=fail smtp.client-ip=52.101.43.47 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="Pn0LucXF" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=LRWVDOPHacAsopwagDAps8Spa5v5176RqTi3bSHj0/GyWRm4BkDkM2PoS64sCT2cdc+ifF8/4KAXxDLXuDc9w1G3ZdpE0N3LdMMnk44GGciid3iyZXICkPUpu335NTDuFvA7cG8+Yjzcg5cWkSsD5oLR7FxHoDum2I5WvLSk8E4Hvz4jJDSMyc4uwaEN4dMrajBTLDL4KTj0Tg7NHvGbHyWXwZYU+iR6rLQKvkfHUI4m0VJ/gvNTRMy3sBx9ijEwufUS22iYI12q9SKvf5dLNOUFCCYMuIDi6WetUFXMoqNStkSVZXHCQg7ZdBc0DS0CJ/vY2fkJLjYTHDTdQE3/bg== 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=WXxG/pJR1S9Wu2Se3FnoEPi63iJcl7H5qAdi7l7Ci3g=; b=VDAfLdrJGKLYPIU6OwrwBY/sJYvgThdVJMO5lo6PV4Ea+tH95H8ljD55oiWU3lMJ1IzPo1cGXMyrO7/HwvBcj2jyEcnIKTHcO1HzXHq165fw7TOAh/KD2McioKgh14RuHf28HWpNYYmwWIyq+ONfscNG3YMRmaEcv8GLu2RpKwGK9L134aQY1N/zfxucfjuSOaEzOyNSJMjnUpzXhc5Wx33lhbH/oriMFYqsf3YAnUTlIXDXYP5u9wytRiaqzudjrr2T6lADL0fSM3Vgu85EfCqS+GFtDzZ37aXPwlxYOHM8bdH9F3iVvyDLC5VzcEvS3soJm56+8hNgw+pdN2n53A== 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=WXxG/pJR1S9Wu2Se3FnoEPi63iJcl7H5qAdi7l7Ci3g=; b=Pn0LucXFfM4rCkrx1Y4FV4SfQ6etCWuFsDNFpCXe/ZtEnvQQYwZvuGDrviB9kod9GKk7efxS7qCWUliaAvQMSQErRjhlOHyEiT6CXG4mXzYZ5j4YGhA9YbL4Z4kDHcP3Ac7MsUMzBTxmoSCZQwzNg2iSnrBwZzNmTNS4j0d+/72GbD5nJ/chPzCGzlmwitvgCVvOH1LZDhnGVSAPBkO+mawt+5NAAselWZmQtvoQOcFrSj6wGBmzYfB4ElSsURtRNJJmb0652aGlvmq9AZnQv+QL3tRswX5mIq2bTH2RdJ7nF9Rc4EiiM6AhaToWxb9Gq5eL3EXAXdSqmSjMXwIDNg== 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 PH7PR12MB5654.namprd12.prod.outlook.com (2603:10b6:510:137::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.14; Wed, 28 Jan 2026 02:37:46 +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.9542.010; Wed, 28 Jan 2026 02:37:46 +0000 From: Alexandre Courbot Date: Wed, 28 Jan 2026 11:37:29 +0900 Subject: [PATCH v4 3/7] rust: num: add `as_bool` method to `Bounded<_, 1>` Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260128-register-v4-3-aee3a33d9649@nvidia.com> References: <20260128-register-v4-0-aee3a33d9649@nvidia.com> In-Reply-To: <20260128-register-v4-0-aee3a33d9649@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross 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: TY4P286CA0093.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:369::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_|PH7PR12MB5654:EE_ X-MS-Office365-Filtering-Correlation-Id: b85aa5f2-07c8-40b3-6581-08de5e16388f X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?aEdrOEdXWTJ2d25tTldYSWhMMWl5Sk1GbnFaT0dWOVNKbUdVUnJEb21rbmNM?= =?utf-8?B?MUtDbkZrQlNFTy9aRUY3NFl4MCs1cFJ4WUZzVXAwb01jN25DVmx5cytsdG10?= =?utf-8?B?ZGlERCttcExaZThyMTV5bk9RTXNSUk80M3ozdWlnUXM2dG9nSllVSHBkMm5U?= =?utf-8?B?cXNYdHd5S1JqT0lNZnA2ODZFbUFEeVduMmtDV0l3Qjc5QkJIeWxYRTdDbi8v?= =?utf-8?B?Uy9PRXlhZ2IzWlpCeW51VnBuK0lpQUxXVXpHRVlXa0FqYStxcHFtN0RBZ1E4?= =?utf-8?B?Vm14a2lvNnJEaG9Zc3RYOGwvQU5lM3pUbjBDZE9QNTh5dnJqZFh5cGFRUGww?= =?utf-8?B?eU9Zb0ZoaDJZQlNkOEpwN1RXQm9IUm1kOFU1WW9DUEd0Tyt6MmprZ1JQVVQy?= =?utf-8?B?L01HanVGSnlxZEF2ZGorNzFPbCtiYnJDVkFLZXBDR2h2T2luTERYQi9SRFpJ?= =?utf-8?B?VFhSYm1pYzFxaW1aSytqNlVyVGsyYk8ydm8zZVJ4b2plSVJkcWx0OGtzclJq?= =?utf-8?B?dEhZdDM3ZnFucjZoRDZ5ZlJEV2N2dVV0bmIxRm9ieGZPWGIyaCtjenljYnJC?= =?utf-8?B?OWNLOUpEamJQNkNEdWNKNytGUHhRRGh6VkNOaU5YamZRZ2Z1a2tqNmkzSjVV?= =?utf-8?B?cjlsdnZoUjByUWE4dnJTK1A4Qk1YUUtRamFQVXloVDU5K1U1M2wwa0VnUjVh?= =?utf-8?B?YzJtRjhVeEVnM1NEY1lselJ0eUNrU29od0k0STJHWUtZdERpa3VuMEdYNDhq?= =?utf-8?B?a0phSUNab1BZblYvRDYzSURoUVB1a0xWM25GaDNMdFpOOFlBN1kzYXBMUW1J?= =?utf-8?B?bUMzQklWUmcvbmJRUk5aV2lsaFhDT0pYTGJFQS9SR1YvcEQyeEVraDM5djhR?= =?utf-8?B?aWV1SytvTTdaUXMrU0xxSDBKdkJRVkNwUEVsUEVkRWcybmY2dEhjcjJnU09r?= =?utf-8?B?VFhja0RzNVMvbGxKdXZBN2lEV2Vob0d1ZDNoZ2wrWlNMRm1SQ1RPZDdVVzM4?= =?utf-8?B?SmpGZ2ZjUTgvWHcvVVVnc2dLbEdUdTlodVFBWnBETi9wSkdrUXpKeERxVnBL?= =?utf-8?B?Q3dzS3A5ME1Fd05ENmx2ejNtamZ3cjhhSk1TbkoyYjdKZ282YUtsR0Q1b2hq?= =?utf-8?B?YmpoTjFKMDlUTlJhWllKZkl3eWtTUHlLL2lmL1JsdUt3T041OHI1VC9rZ0I4?= =?utf-8?B?dzRXdTI3NlVWUW1zdXBOaVg5NzBTSStzWENXeWlBUFpIVlE2Qy9OeVdxbVVw?= =?utf-8?B?Z0FCN2tsbWdhYjBNU1IyL1pEbW4wdDRrc3o1U0dpcWlGc21EcTBCOWQxeDdS?= =?utf-8?B?VnZORzZyWEdMOTRvMXBaQXB0R1B5VEQvSm91Tys1VlhOMjBUS3lFT00xcGRr?= =?utf-8?B?YnRQb09yNWVlNjhXcXBENXMzUk9WUTRkRlNQYlVrUG01eTQvZjBVSWdQZDN6?= =?utf-8?B?cXdOTXVLOHVpTzA2Ri9wTjVVN20vUWVKZVZhb3RZU3lBTXY2UkcrZ1dteHpk?= =?utf-8?B?QXA3VzNlRmFKMER6a0QyYkk5c3VoN25ZT2ErQUU3RTZickJhU3BKbnNBT3B0?= =?utf-8?B?Vm41TEFJWFpjVnNFeDMwdUZXbTlsc3VNSDlKS3RkS1J0MWpTdjk5VjNOSEg3?= =?utf-8?B?MjZmcCtJaUplLzJzQWpuQ0xPWFhZZkx4RVpQY1JsZkVFdE1wdHJEK24zNy82?= =?utf-8?B?c0VBUU04ckJ0cHErMW5HMjFmSUs5MmVqSzJEOUQ4V2h0TExhOFFSWXBZTFRK?= =?utf-8?B?ZGZaVmplK203bUROaWV3MXMzNkEzdUh5bjR0eWF3eC8xZ2IyVWNadlY4T1hJ?= =?utf-8?B?K0dnNXlNa3dMb0pjdjlPS0ZXbEtqVzhYejB5T1J6YzdHR1J1V08wZ2NJSWsr?= =?utf-8?B?V1FUQkV1V1dmd3dDRkwxNG0wVUNyTzJEUnNuVE5yaHpoVHhvT0ZXcU1YVUQ1?= =?utf-8?B?RG4wN1ZQT0l3NHFpbkE5b2k1ckt3bGRtZFQ1SjRkc3cvQkQ0eHFvTHVVYlhl?= =?utf-8?B?QXVwY1IwY05KZkJVUEVDSGNGejRpTmlBVDBOQ0Mva2U1RVRCWXJ0a0Nrd3h6?= =?utf-8?B?STVUMWNZU01JODNMTHlYK2xPQWVSOGFYait3VEVjei9QYWh5Yzdja2xEelgv?= =?utf-8?B?MjdlUVI5UU00WkNMRTlnWjlsOWxKamh3K3lVV2tZWEovNXplcnJsR1ZXeW9P?= =?utf-8?B?Ymc9PQ==?= 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)(1800799024)(366016)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?dlNtM3hkWjhlK3UzREprL0NsSitsc2ltUHZUcGNLRXVQN0dLM1ptKzNpLzl2?= =?utf-8?B?K2s1ZlBkVFFkdGgwS2FUNkR2NWxTYmlnRG9CYnFkNWQ4WDhyNVlORDdzOG1k?= =?utf-8?B?QkR6MWFMQ2ltZnZ4NWM2VytCR09CNUx0eUN4Z20zdStQeXo0MENhUmNCeWt6?= =?utf-8?B?Y3ZYOGR4Rmg4ejdDdDk4OXROUms4QTZUTVBCWHlnc1V4RXAzZHlKaXphNnBM?= =?utf-8?B?bzVNS1VIcThhSS9XR09jdmxFWXNXVDVjZnM1YTgvSzVLb0dJYVAxRm1NQW1u?= =?utf-8?B?RElpT2YvSzg3Z1FlN0NuejhmSkE5bUViYmNHNG5BRWVXK3EyU3RjRnk0Y3Jy?= =?utf-8?B?VjUxL2ZvSTVQMEZmWkJJTHU2MjE0aWREc05XZ0R6VSs2SmFleGgxaWYzN0Va?= =?utf-8?B?Rm1uYlVVY0gyK3krWjR0c0JvbHY0WXZyUkdWcnVEZ21uYTlPNHlYbFgyL3pp?= =?utf-8?B?N0VYRG5SU0JiazV0VnQxZDJBM2hWNkZzeWU4TFQwWXJ1LzVXOUhGSWY5VGN3?= =?utf-8?B?YThIRGNIZFZVWFFETk9ESkJJRk85RzJCZzAxV0JJYjE4S0pxS0RwTUZ1VE44?= =?utf-8?B?S0lRT1JLUHBRanJja21VNTgrWXp6Mi84bTB6dENkV1NtdEQ1V3l2QTVucXBJ?= =?utf-8?B?Y2tzaDB5RUZqekFleWxUemFISTV4VDVoNHhIRXhrRlFtYW9Rbk1Hc2FIVk1q?= =?utf-8?B?VFlhdmZld1ZQZGNrNzhsYlNJc2F0Sk1HUFZYQnE0N1FqbzU4eGtUQkh1SXpO?= =?utf-8?B?bDdGWndMSVh4TTFDTEVrN3NXRXJHZ2JDNkY2cy9VQ0N1TlptNW9hdXcvYUY3?= =?utf-8?B?UnpKeWNQeGtZZU5NVjkxYnFpUHdRYXNGYjIzQTRGRStwQ05xVmxweVo0dEhV?= =?utf-8?B?ZEpMa2NrY1VmN2NXaGUyV0pNeDZ0V3MwVEZJcFk4WmNyVG1RUEtaQlU3cFlD?= =?utf-8?B?amVsb015Ujk5ekEzaVZNc2ZZVUJ0c3d4VFViV0tjQjJPTi9NazFQcDI0MGJM?= =?utf-8?B?d1FuK3FQbUU4My8welVhTHdJOGNxUFp6TVliemx4R2ZVYWlGUVE1N1N6SUp6?= =?utf-8?B?Z1lXNEFHNm5hMldWR2Zla1M3Q1JJRkVZbWZDREZRcWFDc1lNYmpDQXFSdHFl?= =?utf-8?B?MjU1UVJOZTh1d0VudTZicFJWeFAyUWduVkNvM3ZVd2duK0JHT0JHV3JaSTBH?= =?utf-8?B?TllndTE4MkIyM1ZwSnI2VzVQOC9SSEVBQzlxQW1ZVVFVa0hJNjJBcytMNzVT?= =?utf-8?B?ZzJYQnZwenM1Q3AxQ25wZ253MzQ4THhGQXRzZmRjdC9PZGw4K0VJaHRhZmtO?= =?utf-8?B?eTFpZFByQUhUb3BSSWx0bFl3RHdTTVZ0SWRPR2ZRYzBjVExwNC8yTG9wR204?= =?utf-8?B?b0xzdWdtcWdwUkJkME1BZW9OU2NFcFJ2MEM4c0pBYTA3Zlcwa2poRTlxZnVm?= =?utf-8?B?MDBsUFZOTVlKWVRFc2x0TXV4M1JubVlteHgvN0hsSVFMWXIzODM0WkdtYzU3?= =?utf-8?B?NmVrQjY0TmVsNHlmYnErc2VReUR3a0dZbHRHdjhKaWRZK0hxWTRSTHpkQXlZ?= =?utf-8?B?OVIvYXJEeG80bUZHU1FzcFhMd3haNHF3K2hmbmN6eVNmZ1NIN0dPSWhmOW01?= =?utf-8?B?SWd2N3FQeFIyYmdKWWYyVVRIQ3ZoK043bW5VSE1iWWdlVmtRSnJqeHlYNGdy?= =?utf-8?B?VThmcExibWhVQjA3RTg5YzRBZ1MwYjRieHBHNGI0RzJsMXdaMHVTM092WnZ5?= =?utf-8?B?SkN4Snh3a3ZXa2dGNkRHMjNFOEdhYXdGWnppdkJPTTAxVEJaNkNDak5sNklH?= =?utf-8?B?RlVjWm5iaEJVc1FGNUFUbzdtRWJEenRaZ0VmSVdWVXBCTEoyTkQ4UllqbHc3?= =?utf-8?B?QmRFMGJ1NjBPUDZrc2hwdW5CRHF4c0VNUFIrZ1pxdHVCY1pmQW1HWjF0c09G?= =?utf-8?B?TThUbzg0Y2hpc1RUaTVmYWhVa212K2xoaHUzdDZaVE1xWlR5cXhTN1h3ZFBX?= =?utf-8?B?dzczYzBXSEFvUHYzbXhzbW9pZm1PS3JjSklyTm9lT0pWVkVrUnE2dERWLzhK?= =?utf-8?B?amFrQWVtSk1JMWVvbkpRVXYxUzNVencxQ1BRc0QrNHJibmFTMWJoVGsrUnh6?= =?utf-8?B?MnBmOEplbUhoUDZJMWtYdWJwYUw3N0RITjVpVFZvM1F1QjZGakJzcHBSVXM5?= =?utf-8?B?aVZvQyticTVlRWRrYjJZa2pJVDArcmtHZDdWWXhqRS9JOU93SW9PVzJ0ZWdX?= =?utf-8?B?ODNYeThHRWtOOWdXenNXemN3UTJUNWIySnJYNDJYZ1NFS3ByUDh1K0VNT1ZO?= =?utf-8?B?ZHcxQTUxcWlCUjNWMENDM3Izc0hOZkxlOHhDSE02VTkzVkMvNVpjWmM3L1hW?= =?utf-8?Q?OoKCCSE8Mq7Bz4muHSiw0xftpHrKyw7TvQ0+SrqLrd+Fj?= X-MS-Exchange-AntiSpam-MessageData-1: HZMbs2uWrC7sFg== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: b85aa5f2-07c8-40b3-6581-08de5e16388f X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Jan 2026 02:37:46.5678 (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: rwwMs/5EjGHmVfJa49CBrU3ZpdJa2dlQabKySCgaLuaTgCauOCIoc1aoYatwjtTZwDeksmJaLADILvoAJGuIbA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5654 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 `as_bool` method as a simpler shortcut. Reviewed-by: Alice Ryhl Reviewed-by: Gary Guo 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 4b929762d5c2..b41ca6df1525 100644 --- a/rust/kernel/num/bounded.rs +++ b/rust/kernel/num/bounded.rs @@ -1098,3 +1098,24 @@ fn from(value: bool) -> Self { Self::__new(T::from(value)) } } + +impl Bounded +where + T: Integer + Zeroable, +{ + /// Returns the value of this [`Bounded`] as a [`bool`]. + /// + /// This is a shorter way of writing `bool::from(self)`. + /// + /// # Examples + /// + /// ``` + /// use kernel::num::Bounded; + /// + /// assert_eq!(Bounded::::new::<0>().as_bool(), false); + /// assert_eq!(Bounded::::new::<1>().as_bool(), true); + /// ``` + pub fn as_bool(self) -> bool { + self.into() + } +} --=20 2.52.0 From nobody Sat Feb 7 17:20:33 2026 Received: from PH8PR06CU001.outbound.protection.outlook.com (mail-westus3azon11012056.outbound.protection.outlook.com [40.107.209.56]) (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 63DD929B8DB; Wed, 28 Jan 2026 02:37:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.209.56 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567874; cv=fail; b=BEscx5kdwyk42PN3jOFxnyKUPqOXXC2A0HXEaW9IKvUHgfEGLxVFpUNyTxaTEuhKdc8J30qg+ujiMZqxiKridj+2gPVSPziFD5IbR8q1Y4nuQ0UUPfttYNaVXES8r36OIgYyGb7EqStZDpbhN0R2Rzr4mvRclny0y8C3DjSNl7M= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567874; c=relaxed/simple; bh=5NOnpB+JkmYoNSdg0KQsq9hm7oPd1cdUicHldYc6Cwk=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=OwmCWIP6aebhJe7r6mau1+Ql1OLdL2x5w2Mb+lL97tfID0bUonk7xocR7KgSlLnurmmhbMI4fYFgpaIcVuI36FMJttvReGM+4YfYW+g9GuEW2RnsKGsxZxR9L1wX+JUQaiinWa6eKnDiSj/sPBw8+beZVD+QfFRhbcxgEZQQGb0= 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=KnjgrX3x; arc=fail smtp.client-ip=40.107.209.56 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="KnjgrX3x" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=eZAw5OIp8od7IAUos7CBuYq2rlEzQcl4UDsUW21v4YPxpBJ7KPfkzKnBWg5njN3oFOcZSAVnxJ9+VzSiDLsSqDtOivD9EUd8YFq79ICQd1vMczWvL65FPdvz4mm9S8T4g/3gq/7gaJMoEZh9X8RuTmeXNkyuxoZFLwloz4TYtORrz41rZ+NjBjCwGPY0KjBostdBsfygXwYHgFMfNpmI8nn3h2uBdReue9RLTHdKNOQS/QMyr/UG/rMiaw3mjNIPyq8SgBF7cyzpUtXMXjOwe4396qIPWEN6P6UiOMKOPKeDQ/7tAWtIrMoUaZ/1r4XGavk0s5MdIN/8d/rBgeiuVQ== 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=91pNgxioMuH+sfUTVSRDOfhFd5wIMV0Ph9XbSJHEEOg=; b=fvwuSJ6g51otgVCNClbOvTBC2RjR5MRWuxqrY+uBC4dRn+XUXJ2M6lWjJQI3oxyB9LDyRKoJPJ/T/jeCaf+MH6IDEXGNSj2r1whe19bgdNnESCaiLJzd7zYyquuQYHv/hCMwLvHN5LL4auuE6GVzP8Hf505kNJam/B9xDpibY7i0f8RueYxV6URiLNYyU0qT5FfQdj4lBD2eUxJGdWIOCiyQQlRn3af4CV4FTukUwVUFdGclqw7KysErcn7MVnRB5LEcEydhbyn8FxBcPnkkNDVosZo3+alHieuwAzYSLKqBCHbifJqSsBEWC6t0geZI58vwj/WbxDlH82AomAxJgQ== 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=91pNgxioMuH+sfUTVSRDOfhFd5wIMV0Ph9XbSJHEEOg=; b=KnjgrX3xWyk6NnJ8cbasStg26aaDMkAswagbbML9LiG9BLXMUUsl681JSmylEoaKYxuC522qK3e5GK5VxscrYC2h6+TRBrhcZlXTgAzuu02XkEZ+j0TLKPCfWU6Gh0R3nJ0vI/KGZcKwZFP+HdjhkzKC4LKD7YcaCECH5gQlMzp66pQDpWuVdFq1h91iTMf0bjQ5S1HgsJyFKOBOtpHgCzI+x5yg30JuC2Oqy4bf05u/oO4MA9W92SVVhY/dwiIvlve5P3Es9XALj/f1RlAuVCjOEdjZglC4/vCCiytxvOF+00gOe4BYJvQhVlKDhPGb9Bq1vlw/nn1LYiDCWET0Nw== 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 PH7PR12MB5654.namprd12.prod.outlook.com (2603:10b6:510:137::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.14; Wed, 28 Jan 2026 02:37:50 +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.9542.010; Wed, 28 Jan 2026 02:37:50 +0000 From: Alexandre Courbot Date: Wed, 28 Jan 2026 11:37:30 +0900 Subject: [PATCH v4 4/7] rust: num: add `into_inner` method to `Bounded` Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260128-register-v4-4-aee3a33d9649@nvidia.com> References: <20260128-register-v4-0-aee3a33d9649@nvidia.com> In-Reply-To: <20260128-register-v4-0-aee3a33d9649@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross 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: TY4P286CA0030.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:2b2::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_|PH7PR12MB5654:EE_ X-MS-Office365-Filtering-Correlation-Id: b6c5fb4c-4832-416a-aa67-08de5e163b06 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?UGtKKy9lUk1idFNEdFp5eTY2ay81K3kweStTdlBieEtXMWs2Wm9PaUFrdjBM?= =?utf-8?B?amVKKzN4UHArMUt0OHJoSUxkUUJ0bVZCU1pOODd3dERtZGJLaVN2YkhZRlcv?= =?utf-8?B?akJMSXJMcXFVQjQ3bHdtRVRkeHJ0K2VGOWNkUXZ5WWQ4UUtVcWVwUW5qajlL?= =?utf-8?B?ZGFKSW1ZbU1SeWhXZlpickNpTEY5Rm5Pa3BmSlhaWGd1SGhaZm5mME5yMjZ1?= =?utf-8?B?VWRUVXFkemJvTjVEN3gvRzNSZkhMVE52RGZnMGNoVzhpVjVIZ0Y1MEpJY3JY?= =?utf-8?B?VTRZVGtBcHlQN0ExcGRZV2Z5QkNKcFFsQ0c5YVBtWjBvQVcyMkVDaWtjazFE?= =?utf-8?B?a0NSSm5SZDI1Q2FPa0RvWjVDSENhVmoyalZGdFpzMU8vR0pVMnZUR0ZXRUxK?= =?utf-8?B?TWRyV3NQbzlRcmhNTytyQlp4VU40K0Npc2pVVTRDTWRMamJFekEyOTNTYmM0?= =?utf-8?B?T3l2UGdTeXkrRW1nTWhXaGVnWHZFN2piQlN2czlNcGNESnF4VkZ5OHg3MTB4?= =?utf-8?B?VWNPYUNkWWhTU0RaUThONDQ2VlNSUmtOV0pNQ1AvampoTU5TRkRPRHpLTzFZ?= =?utf-8?B?RkhjN2d3YzBlRS9vL2c4MTc5VWErRVhHcDBaeGcvd0J5dWRQbjAzay9ZV2xD?= =?utf-8?B?OEMyaXozcXVkbDNxUGR4L1ZvZTRBZldna2tUdXphWFUvdlgwMDBPUmVXdTFo?= =?utf-8?B?QjRyUGxsUDlsUnc2N05qU3JwbzIwQm1xdGRzMkl2akVmVEhwMkJLK1o5bTVL?= =?utf-8?B?dzl0cWZZUzNQcHUrcE9RbnQ1TzJxaWxpS1pVTHNnNUdUbU13OWt0STdsSzUr?= =?utf-8?B?dzNZL00vRk5wajNTUkFmbmU4aXY4c0lTeitIaHhkNGUwcEdpL1VxTmRhY2Rt?= =?utf-8?B?cmtMYndISXBYRjJmMzRtc2Q3U2pZT0pZM1YzUDR2T0JrMG95bzFuWkJCS2lY?= =?utf-8?B?UG5uODdLNi94aHlhaWlaeUZ3Mk02U1ZTeHJQWk9XTDZMWUlwTm1Rc0xZbjE2?= =?utf-8?B?U3c1OVd6YzdVVUJ1c3Z1QUw0dFpIaXlpL214WGYrZlVKVDIyVFZma2VTL2FK?= =?utf-8?B?UmFRWXZBT0N0ZnhIQmhqSm94MEJDd0R1Mm9ycWQ5SXVXUUtnOWdnRFJ6eDdx?= =?utf-8?B?QXUxZ2xXcmh4bFFEV1YrMnltMFFFWkc1WkVNNVlqaEk3a09tS0Y3OWJqaXg5?= =?utf-8?B?ZE9LQ05najJFUEZVc1M3ZnZOTWgyMnRMK2RDaTI5N0trdks5ckJ6S1hjVDhE?= =?utf-8?B?T2lWNTV3WDZCczZBMU9qWGk4VG94N0F4Vm5NMDFRWXVxNEZpbnFKUVYyNXJW?= =?utf-8?B?aDFobU1xQnBFdDhmTkxxZFZJVEdVdG10dHFmT0M5NWlkK1RTZjljWUVTM21Q?= =?utf-8?B?aVZoZXpscmxlQnFVU1YxWkJnM3dVeHUvSStHQStyV0xEWjlQNktmeDcwMmlN?= =?utf-8?B?a2svdHpCbHBTM2ZmdWY1RjEvRnA3bEl3c3JZa2QzUFlkMmtYd2hRd1hXRnhq?= =?utf-8?B?ckpVVkFiSmJJaG90RGM0dC91dTF0R0VqZGlYSmpjMEVpdU8wcmtxMUlvRTdQ?= =?utf-8?B?ckJJM2crWU5QdlArc01qS3R6TEk5SGtSWTNZY1RnOVNNSzh5ZndwbjJYZjgw?= =?utf-8?B?Qy9lRUozTU04RkdKdWk4QXhwajBoS3BpZUNKbzZ1U0Fkak53dE1aVTNRNzNS?= =?utf-8?B?UUFkTzdKa3dtSVUwaHRVL3gwZmpwNVp5RytNd3A4SDBtQklCeXBpcHJ5Q2hw?= =?utf-8?B?b0lXWEZtZDk1QWV0Z0JpVk5MWVJnUk5MSWFKaWhvM3ZINWFiRm9PZzE2R1ZF?= =?utf-8?B?TnNqK0JGb0tSZGxqZWI5QnJ4K1Z5S0V5YVRIMVQxK1JhcDVwZkh3OXV6cDRa?= =?utf-8?B?R0Q0R3F5eVlxVGg1SlZuL3JKQlpGK25uR1dtZVZOYWpyRm1FRGx4L0U3Uito?= =?utf-8?B?NzArQmdhYk45Yk1YSWF1OTNON0FvWXc0a2szQnhLM09vbnd5dC9ibGlBM2VZ?= =?utf-8?B?KzlZNzJnRVQySEpINEdyRUxEa0QyZlhmTnVwbkxUUkRNNHVVSXlCSmI3Nk1m?= =?utf-8?B?WWJ6aW8xVVQwTjZZeUxyajE3dG44Q1JGSDhMMnE1U3FWV296MmJ2RHRvVDhj?= =?utf-8?B?UkVkOVIxZWJTZ0dJRmNnbUFwTE4zdHgrOHk0UEJoaUF5RG5lck5oQW4yU01u?= =?utf-8?B?b3c9PQ==?= 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)(1800799024)(366016)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?S3hOaXpJU2JNMFhzMkhPOCtkbWwvUFNOcWdoTks1alFWTldETlFzRy9FUGRN?= =?utf-8?B?TEZ1bzRsOTVHdFhIa1lPUHgyaGdCeG5nWVoyRGM1c2lsM1Q1K0hPZkg4ZGk4?= =?utf-8?B?SHdnSDB2WGhFZFVLZXd2YngyUGxqWS9idUxqakM3RDE4RjNGV2hKbWVscXVh?= =?utf-8?B?elNWZnVQc2I3VzVvSm1DUWdqZlVEZEVUb1UzcjZ1Q252aXdtNEpmdUVOb05x?= =?utf-8?B?djJyNHp3TlVRWHB6N0JRZ0ZUc3ZubDRjMGRYc2xJWVE2eTU2aHQxMWFDSy90?= =?utf-8?B?cUMyb1EzZTFERVZPWitOWDdPMGxtZGdhM1FmdUNCNXpXSDJzVEhtMUVEczE4?= =?utf-8?B?RzZ5YlF5ejViVWFKRlEvQUN1WHlQSDZqYjl0UDZIUkVWeC81VysyeWIrNUVq?= =?utf-8?B?bTJFOHpTT2ZWaUpOUFZneFhNc2ZLK0dvK0t2WHNYelFJbXJpZk4yRjgwOHpP?= =?utf-8?B?NHppY1B4T3E3WEYrNEZMLzZRV256aU44SWM5ZXdsNzlmNThIQ2lLY3A3VEJz?= =?utf-8?B?T0o4RFlwMGo5aFZZOVBqRmlnUTByWlNUaUhJS21SRTJ2NlpNMHlycUx5aita?= =?utf-8?B?Z0QxZmZMUUVUYktDMGZOeHVxNGQxWHVYbjNQSXg5Sk5PcmpnUExKUFJHUldx?= =?utf-8?B?dG03MTBvUU0xVUtGeEFzZWNBN242eDc0ZU5sWWxxN0tCRjZmOE44eHUrbi9k?= =?utf-8?B?cCtwem4zTGRQeWp2RHNMM1RrVjBGWjl5YUVKcFBkUzFNNDdTZXpSeVZ2aEpZ?= =?utf-8?B?MnpxVkNWenFjekw4dzlVcTZIQ3N0bXBxaC8wa2J4RklaOG00Mzl1T3VxRkZN?= =?utf-8?B?cUJYQ0RHUWNnOW5sSnhQdHc0aitjTGMzRXdYcHNFN0dZdmR0Z0dwY1IzL0hP?= =?utf-8?B?SWZSeTJrcXpsREZlUms5WHJMTlVUemJyamxjR1dvRThaM0lZcVV2QWthU1Ew?= =?utf-8?B?eUpDb0dYQ3RPOGljalNSOVBRVnI0ZVFDa1hpYjZwZFRNYngzQnNVOVg5N3VE?= =?utf-8?B?dndjcHl5dGQvZm41RTZWaVRNQUY0UzJSQm82VmRmbWtoV01XbWR5Zk1sOFd2?= =?utf-8?B?dzVhVEMvZWxjejNVVmVOaTVFSnczaTBrN2lJenkxczJwajFEVk9jVnFrUlNN?= =?utf-8?B?TzB0K0NwN2ttUTJDaVMwaFl6K3k1d1N0c1kxRzFFdkRuR2czZm1wQ3BEVkN0?= =?utf-8?B?bTl0MjlmZ1A2UlMwUEtQdWsxL0VPQ1l6dzg5akR2azl3MjYvVDZjU1IvRWsw?= =?utf-8?B?aE5hVjc1Yms2N2xMbDQ3bDgwU0Q1Qk5GMHU2VjZDa3pZV2VlcWJRUWJlREpI?= =?utf-8?B?MjR6YndSNFlKcVlrbTZKck5nQlFEM0VwQVpMaHdrNk1WdnBXa2xMVXFIcGtt?= =?utf-8?B?bTQzUklCUXFEU1ZBRTlKQk5OM0hwekhIRXViNEJnYUpIdE9NdlpXME5sTXRz?= =?utf-8?B?N2VpcllIUXMvbTB4emVkN1Y2MXFOdy9GY3RxMHpCaXpGRzM2MlNML0ZHK3Fs?= =?utf-8?B?TGVLQ3hHTXp1aGVWQ1IzQitHZ2ljMzJqMmpvT2F0cmlNNGZrUytBSG4xQUJx?= =?utf-8?B?SXJuQjdYYURSbnVXRlFUNU8wT3RycjNNY0svV2Fjb1VPbmo4SklySFp0QmdD?= =?utf-8?B?U2hsK1Vremsza3ZjS0ZROEhkQmJYeDhldjlDd0Y4V0VrV05DUklMNCs0dnkx?= =?utf-8?B?dlprSnNtbm56U29NamxDdHYvbExzR2ZGMDV1S1hicGVMY05WSGFFR2VWZUQ5?= =?utf-8?B?R1BneWlnRElEcEdWQU9aU3hvcWVnUDAybG9xL3Btb3pwMGhzUEFRODNpR0ZL?= =?utf-8?B?b25WRHBLQTgzNjhLZlVZZjNEbC9MVytRVGtxUlRpNXlSMWpYWS85MlhKZEE0?= =?utf-8?B?WGxDd3VBM002c005bWJMWnNxNTRGMWFoVVE1bktBeS9uQlBxcTl0aHRyOUEv?= =?utf-8?B?MU1RUm9OeW9TZ1RxNGRmeVJUSFB2Wm1Dd0haNTdCQWJiZkpUaWNwRmF6bkwx?= =?utf-8?B?RjdvQnY4L0dpb25DRldBdDFyUlptcDNMaHQ4YXJHaWExbG1UVHlMaTlQalZm?= =?utf-8?B?LzNjMEdwR2lVeU5FK28zVSs4QlBFeHFMSldNdjVubDB5SnpjZHNteFpWS3Jy?= =?utf-8?B?YVdhbFQzYU53UU56NjRHdU5DMlB3Wld5bEJRakl3V0VsLzNEc1ZmcGVTY2I0?= =?utf-8?B?Uk5GdjJRZGoxek1QVzZtMXZNWEJCV004WXdFTXV3VlJiNFQ3RzlLNUpocFR4?= =?utf-8?B?T0NyeWdDbk5DN2hxZFdLbHpaYTkxWGRoV0ExYUUvYUIrTTEzY2orWENlSW5a?= =?utf-8?B?ODQwMU5LWFFtcFIvVHp4eUNMK0gvTG01T2pURmtqMjQxbmdLSyt5ZzhvNXlm?= =?utf-8?Q?jHQjnJCcYdpXyMNl1OSxH0IvMYwYuF7PFOzuJtD6H6Tcs?= X-MS-Exchange-AntiSpam-MessageData-1: LxC6nJ82lVLvWQ== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: b6c5fb4c-4832-416a-aa67-08de5e163b06 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Jan 2026 02:37:50.7395 (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: lv3OtAY7B/XSXM0pboE4Ej7Z3DResHCqv7BqLRSQsmNkW1ceZWgVyfO33dQStkx/kDGV2aWiYZqm1MBcOZ39+w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5654 This is useful to access the inner value in const contexts. Signed-off-by: Alexandre Courbot --- rust/kernel/num/bounded.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/rust/kernel/num/bounded.rs b/rust/kernel/num/bounded.rs index b41ca6df1525..850827033f67 100644 --- a/rust/kernel/num/bounded.rs +++ b/rust/kernel/num/bounded.rs @@ -388,6 +388,22 @@ pub fn get(self) -> T { *self.deref() } =20 + /// Returns the wrapped value as the backing type. + /// + /// This is a const-friendly variant of [`Self::get`] that can be used= in const contexts. + /// + /// # Examples + /// + /// ``` + /// use kernel::num::Bounded; + /// + /// const V: u32 =3D Bounded::::new::<7>().into_inner(); + /// assert_eq!(V, 7u32); + /// ``` + pub const fn into_inner(self) -> T { + self.0 + } + /// Increases the number of bits usable for `self`. /// /// This operation cannot fail. --=20 2.52.0 From nobody Sat Feb 7 17:20:33 2026 Received: from CH1PR05CU001.outbound.protection.outlook.com (mail-northcentralusazon11010008.outbound.protection.outlook.com [52.101.193.8]) (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 E45382BEC3F; Wed, 28 Jan 2026 02:38:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.193.8 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567885; cv=fail; b=fh9ZpRjvSZ/fjFKaAgVRn2qNxDazYAzWRhW1vcUpvX9ROhKvO0A5H+tb0O66vIg/qkaaW7VIH7WyhvXo/mzWItW/8TcVpghybFtMieDYJliAY896ixa9iIhVHa9bHEiUzHEeQmlI4KY80UCva4LkNyA8oSWKU81FKUVEn3BveqU= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567885; c=relaxed/simple; bh=FrQI53criELzCbZuURyUUM1YRWCNXu/M3rZjFPNb0fs=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=LMznV6hBmgk/F4Vi39DglMeUVGrCYL0tQv8pQ6qTBAWwG3vJi1bld0leTAOMQmO1Fkv9i3S0f7+oeY8Oc5yk951eSTcZfpRaqZmnRsRbblmmr8AXNPCzjSa/djFiyTGPJHLVB+yKUvx+fbsUyzwdPo8D+5Qn40y+fGdsglBg2h4= 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=XJ3PFtIk; arc=fail smtp.client-ip=52.101.193.8 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="XJ3PFtIk" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Mb76g3QiOqqfBFvhbVPW/toAwHXaav0nz3Icsfq8h2JVAGxH78IOKxwvm7W1DWgkjujO5Zvdj8mbF4DXcFodA8TctOY2EF6ATCwztw+oOKmw/Kf7OrAAWBLhojIMJ3Mrheu6dbQfsoZI/h8hMF4sgiXeaDOOn5rOrjNTf5TQs2dWJSWEsapP3KDwM4VTSggM9Pnc5KkCF1R2hZ/W+m3DN9p+f3RiKR+9iVsiVvhmZY/IYxidLn0qsm4a9EWc7/wLfjqXQT+GObDBt7ULjdPEJjL9HZvOTTUnG1dcTEyJXtzTteSAPJXmBhmi5jgokspt82mMdwurnajIJHKopZ2A0Q== 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=fpEFfxbiT074w9mhRV+CECIBRW+N0L7Zr8XZQDTgQJc=; b=KXqtA2AiStZhH8hnPooKSXatzAFLErXvboOkpGpqamVzIjbWY+51dYTiWE7dB1+w14/BiozIofMQ0LM+eKHWTBSr0J8eRiKJQFKl8YQjfGl86wy7jkwkzQYT7ZYf3DohFxdSiRsF2AMPksSA3tVWS7Nyn3l0QPCAM6+5GfJQwCnlQ/Lt1r8lmezAAe5Cnust2eIp07SHQPMYbfGf++UH/Md1M7LUzOZjej5Ct6jdyg0dDzigKRvCeQh9N15TiblCOxEh0OOF97r/Ih5K3qa1xWtl2ZC0x8WpB0Qx7WaMHV6YsJitvkQe/2VEe+7JGO3wncPJZcSUZA36kIRGJ02BDw== 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=fpEFfxbiT074w9mhRV+CECIBRW+N0L7Zr8XZQDTgQJc=; b=XJ3PFtIk9AhgA1zd6gPTbRseCd8aBkKc/YLh6loK8U/RAywjD2S/sZmTP93ubw2nyJwJzxj+D8AyTJcrZ1VF8Nt8LYKGYw7LHf5InsyUC/fx+YfxDT5TjoFZ7Lyb7tfTvMDxo3gUyI2jH+554Rp0dbhBhruuAmNr4BeDmZRWlmMu0PIt7kCZ/mAftjfLk0/t0NBAk01tDtnjtIqDnAPdpKF8d/4lHQXzEvDSMZi/dFTjy2MtD2UR4X8r8B1ZbB8URH/0Hi/eXupbfrJCdY49GdEgjVbyuS1ARsHpOabNqT9lHVwh1j8eFXqrVhvnsOpf57H+f128e40doHsTvdVU6w== 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 PH7PR12MB5654.namprd12.prod.outlook.com (2603:10b6:510:137::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.14; Wed, 28 Jan 2026 02:37:54 +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.9542.010; Wed, 28 Jan 2026 02:37:54 +0000 From: Alexandre Courbot Date: Wed, 28 Jan 2026 11:37:31 +0900 Subject: [PATCH v4 5/7] rust: io: add `register!` macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260128-register-v4-5-aee3a33d9649@nvidia.com> References: <20260128-register-v4-0-aee3a33d9649@nvidia.com> In-Reply-To: <20260128-register-v4-0-aee3a33d9649@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross 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: TYWP286CA0029.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:262::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_|PH7PR12MB5654:EE_ X-MS-Office365-Filtering-Correlation-Id: ce15c3ec-bb7f-417b-bca1-08de5e163d52 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?NXFzeFBSNUxldVlEOGhwVTdmaENFbHhib3VDZjJKSlBFYjVCTDYxUWpoRnBr?= =?utf-8?B?aWZKK0NHbVEwY0VuaHgzU091ZUg4a3Y0TXg5WjAzYU5RMCsza3lwdHcwL1cx?= =?utf-8?B?dVRhRWRoaU5xS2taL2RaUko3OFJvY0I4QmxzZm44YlhpUUsrN1BLVVQ4cUs1?= =?utf-8?B?L3l0c2EycnRrSGVscGxmRFVwYlNjSjZxWlZtdUI4VGlNTnZBYVV2VkgybjNU?= =?utf-8?B?T3llOTVzVCtxMThLR2VYZFczT2dzTU1Gdkc5OHJNcHVrRnZhLzRNYXllV0xQ?= =?utf-8?B?aFgzZUtIQjFuQkUwTWNJUTNkRVlPYWRXYkFaM3M4OE1jbjd3K2RSM1ZBenl0?= =?utf-8?B?MTNqSDY4Mmhrd0hUbnUreGEwdWkrenNBWjFsZTZyZTAwMkhtdFdOVzBZU0s3?= =?utf-8?B?cGRwK3hlQ3pwSFFnNWpvaVNOK2JFS3IzT3VTZEV1L0tmWjBwdklVc2FINmEw?= =?utf-8?B?T1Nvc21xdVVPTFJtemlrR1ZkZTdMOGp2YkgrUDcxcU5sRDdHMnJRd3FhSXZB?= =?utf-8?B?NWtSYnVUdGNERUhJZ2xDOTd5dHhkc3k0RE5DODFCT3FCZ04vS1IvOFFMT1No?= =?utf-8?B?a3JrOWtiYUNHRlh6cDM2UGVmcXNNT01Ea1llSzYybFVHNTJ4cjFsOGdBM2Vh?= =?utf-8?B?MEZPMTVWU0V0Y1k3Q2pZS1NpRWNnbjJ5Z2hrVm8zM25WZ0k5VWZxYXduRUZK?= =?utf-8?B?R0xmSGxiZnZod1o3aTZkU0owSjhuTEZKN2p2dlgyS3RtbTdnNXBvcm5mVGdT?= =?utf-8?B?QUIrZ3JsTkxHdTVlUlhrcXU1OUtUM3ludXBwSXNJaGFFaCtXYWhvTysxVFdE?= =?utf-8?B?UVBzL21lNnVtdWpRQUtDbUNVT05oVWhUN3lORUlndk5zV0xPY1lQdlg4UVRn?= =?utf-8?B?SjBaZWNNa2E2bVhNMlJCcGluRTNBbCsybXJveVRNaHhybWo3R1pqaWc4aXFu?= =?utf-8?B?MkZ3ajBSSUQrT1Z6VUc3SWt6a2lHcVNrNU1GT3lOMHJyWW1heDl6TG1CMHdk?= =?utf-8?B?VFQ5OXNvODY4L1lyUzZpN0VaRmRTZDJFMStidHpHdWNYZGsvL25TNzhwTUFa?= =?utf-8?B?NlJWQ1R2cDcvOG5ESndoeTZpdHA2dWlDUlpvUU0wdzFxNEg3YisxNmorUkhy?= =?utf-8?B?bHlNbnYxQmhiZ3o3TnNLdDdybnBUVTJsT2hrYW9oYXRpR2piMUl6bjU3bVda?= =?utf-8?B?VEdRcjlZN010VzNJRFB0bGlnMnA5bW02eUtDWm5XUDdqODVPOVJsQW93NFh6?= =?utf-8?B?ZFA0VnBMVWI4b1pYVXhhSUpzWi9lU01NWDQ4d2M5bnF4Zm9DU0lYNWZWN24z?= =?utf-8?B?MWF4b3VadDNFS0tMZmdsbGp5bWk5Y3VzMGdHYWhaUnB5a2tkMFMwUlU2N2Mw?= =?utf-8?B?V0dkSWZrQ0ROSFJ4OCtDUUF0VFlTMjArUk1oTTk2WjZWejQwbmpzbzJOQTdt?= =?utf-8?B?QnIxSFVlTlNtZUFOK3BPVFJqK1FVMFhBTXEzL0U4NkNyYUt0WXplWUdJL0xB?= =?utf-8?B?YTJGUmR0WXpYUzlmbnBHU1I5c2QzbEtOL0IwRlVLR21VK3dXb0dOYzFFTHdP?= =?utf-8?B?dVBRQXV5TGdiclVBRHZDNHc3V0Y1bGp5VnBWc3dWbVp1THROV0ViOUFuQjBx?= =?utf-8?B?WjM0MU81SlJDYTc1U3Q1dWk0ZDNQb0RBbnJMT2IvUTFoYVd1bUZmK1IwbVdV?= =?utf-8?B?QWRXc2RIK1BaWmRLV0xhMU9NUFhuTVlnb1ROaGRaVGhGbW9idHZ1MUpvZ2Ni?= =?utf-8?B?MGtEZFdGSms0eVpneGFFYWZzNlN1NytudnpGbnVBaG1kWUpEVkZFZG4rYXhr?= =?utf-8?B?b1p1dHJGN3JFaGlkK0swUEdncjVUZEdqMTRkSVBzZjJCVU5EMGVKTS9scHp2?= =?utf-8?B?eUxnckJ3TzB2dUF2Z2c4UUwwUmxoK3FEL0VOV0F2WFMvU21CbEh3RDBWNlhR?= =?utf-8?B?dHYwSCtvWkVwUkV1a0c1NnRneVdPb1FXUkN6aW5rMk01enBPbHpoUzEwYmgy?= =?utf-8?B?S1Z5T0hBUkdyaHROVnN0WENqblBMWUpvWUdabkY1SjlKc01NNDB0enYyaTA2?= =?utf-8?B?SjhjbnUvakpJMDJIMVpSMG1zTmdWM1k4UXFjL0NGOUFabUNUc1luT2NqYVJo?= =?utf-8?B?Rlh3aDEzNXJuUTA2Wm1ibU9GUS9rQVRncFBFY09JdW15dThIUWZ3b0dyMUY4?= =?utf-8?B?aUE9PQ==?= 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)(1800799024)(366016)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?c2dLTTMyL1Z0RVRQaDV4Y0JFU2V2TjVYSmpuajM5VjI3bE1SRkVZSXpibU5H?= =?utf-8?B?c0owb2JHWFhPbmR6RHUvK3JkUGxQM0h3K1l5c3hOV1J3a2Nzb3VOWlRtMXNm?= =?utf-8?B?WWF4Nlh1dHNyOXl1aTdMY0Z2Qk53aGRraHlheTBqRVhHOFpKQkpueUI1OVpF?= =?utf-8?B?bjhSenNOZCsyL09WYTBndFdEVzhhKys2L0FrMEVZOUVxb2luWDJocmxCUzcy?= =?utf-8?B?Z1NoTFpGaTJQOXNWRzVuR0lOT3MxMXovaG1maWNyYVdpdUJzRXo3NTh2R3hR?= =?utf-8?B?OS9uQXNoYWZ1cXp1YmxtNDRUSCtuZUl2OXVNend6N2d2MGxBVFF4M05zOS9Z?= =?utf-8?B?RDlzQmN4ZDZBaTUvRlBBZmgzTzFqQTZhR29vdFNHUDVRU3l0cytXNmNJSSs3?= =?utf-8?B?VWpwd09ycWs3M2h1a01aa2tWeXZpa0E0eGRNOHYrUUNCOU4yaFRHcnN4OVlp?= =?utf-8?B?ZEdpQ2ZZYlY4SFVZZU9OY2hPZ2p5R05TaFdNUnFiOEJBcnZlY0YvYTdpc3I0?= =?utf-8?B?RWVFU3h2MGlBSC9YN2hqWVpzc0tNYzRqNENUamczVGw0bHc0MVJGNmtKdnVi?= =?utf-8?B?VHhRTGw0WDJ3MEliUEx2SzZla2krVEdsVjRPMi9TMTcvWW5GVFZIaFIvWCtV?= =?utf-8?B?S0dQbzllVUhmQ0FNckp4WCtuMGVYYzcyeFhvVDM0bk8rbkQ4WUxPV1hBazVq?= =?utf-8?B?VUk3RG1GcGtaaWp4aFFwZUlPUE5adnkzSElzS2FjNWhueW1SbzBjUzRwZm9y?= =?utf-8?B?dHQzekpnRndPQUxoZEk1bnhrOUNhRVpodEQyejc5WDM1K1F4UVk1ek5QeXFV?= =?utf-8?B?ZWZ1Rmp6d1EyVjByRzZRYlNyc1l2MzhsMW5OcmZ1NE1XdlRWaVFzdjFwSldR?= =?utf-8?B?MlBOcS9kTTE4ZElnbTlZaTdwc3U5TDI1aTlZZWgyckdPMkdsNWg3ZVg4dlZM?= =?utf-8?B?QitJS0JTMmV0S0M2b20vNk9zekEyRnBkTExWQ2Rrd0o0RVdONEcxLzRTUnRU?= =?utf-8?B?cU1VUU1OaXcxMFA0ZkhhenR2L1p0RUJSN0hvRUgvUWtYK2I1Z2xhazFIV2dv?= =?utf-8?B?U0ZzL1U5dHpNdHIwSVlSUWptY05yUGZOQWZWV0NpVXhoNEkxUnpLSDVIYW04?= =?utf-8?B?RUp4QU5yUy9BNHNyeUlwYzVrNEM2cXdETVAvVWJvRE5vdkdZQzZFWS95QU5P?= =?utf-8?B?K1hKaGxBazNzS3BMejIyRmwyVWNiSWpOMWVvQ0h5Y2lEOWlPdGEzTzQ5eE5x?= =?utf-8?B?SHg4V1htYUVFYmM4c1ZBZzQyeW4rTC9LSkJPU0U1ZG5HMTJVN2hwam5mNmVm?= =?utf-8?B?UmR3UGl6bldma01zbG5aQk9ISldjcEljdEtMK1VaQUw5bU5aeFpwZzUyTTh3?= =?utf-8?B?MUl6Zy9IU3NtcW9yQ3lJMFhEdGVCLy9TaDJtbW9yL3BZWmdsYWxUVE1pejlR?= =?utf-8?B?eExuaUxmRXpiNHgvTVhoc3BxSTBUNWwySHZzZXRQZWVZZFE3cXQzc3NNYlBp?= =?utf-8?B?UUFCRUtNUC9ldlVUUkFQcGxWZWhoMDRNeVpRdzI5bXJ0K01zSXlYME9xM0ti?= =?utf-8?B?NmVqaTBuVFUrQkxnbDdUc3p3b25Rd3VNWE9QaElmZDlYcm1MVEtSTG5JZlhz?= =?utf-8?B?RWhoQ1pYakJ1L2JrZ1A0T1RUQTBCSk0xazhPUnk3b2JuV0NWSDNBeEVCYTNL?= =?utf-8?B?bEV6UTJyYzJINGtiZWVxSStvbEd2NmRqZTJadXUya2RMOFM3SXVMZW40OWU0?= =?utf-8?B?ZkZIZU9BZnZLQ09nMlRZb1k5bmpyVThHaTVMN0xUbDUyN04xWHRGZFlZZkhZ?= =?utf-8?B?VzdvTm9sSlZvUGJ1ZWVsbnlqUGZEYlExTjhEcXcwWlJNZzlhWkFDSm1NTmJm?= =?utf-8?B?Y1dJb2c0SmZiSDBudHFUVUdzMWVQTkNmaDZvWHBKaThvZmRTZG1YQnVWR2xZ?= =?utf-8?B?a1FGUThvUlM4RnJyWjRGbHhYQUJDQUR3U3pHYU80NTd4cnp0alhqbjhhMFda?= =?utf-8?B?bi8yQW9VN3lQYWVDclNvdGVqaUYxeWsxc1FuMkEwVUh2S3k4ZHp6b0xkVGlR?= =?utf-8?B?K3FvYkxVbjRZb1Eyd25rNlZ6ME9qQVc4aDFoZnJ1SWN2NnA2OG1UaU1DcTE5?= =?utf-8?B?eWxFTm1FbGxNTjJOM0U2a1RUeGJoaDE3dU1MUWh2anZZQTJOYjd2R01LbWpU?= =?utf-8?B?V1BPcUoxaGdCaXNZKzh2bHgveXhrdWFJUzBWTFZYa0VHWkdPWTRhcGRsdG5w?= =?utf-8?B?RGdrRWc5SC9ZY1J0a3JJMXkrbkh1UkVhUW4wNFZaRnlxMGpFTGU5M2kyYnNo?= =?utf-8?B?cDRUelVOSnNHUld4UHhiSENWKytSQnBBM1l0d1puaDc5ZHZlWDFUQzYzTk5z?= =?utf-8?Q?JlNlbUJFxi0cjnv2/0QPQ6a10/5cxg8EJ+iTAk/t0MO2h?= X-MS-Exchange-AntiSpam-MessageData-1: tKl1U7wKwUPCTg== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: ce15c3ec-bb7f-417b-bca1-08de5e163d52 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Jan 2026 02:37:54.7173 (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: wK9UH5ZcmS5unlljSBdL65M9OdrdS+mDFqna3gKmRItOQotybdhicfYf632TLxFKRqGvZ5tjmXbJmkayen5BHA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5654 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. Tested-by: Dirk Behme Signed-off-by: Alexandre Courbot --- rust/kernel/io.rs | 1 + rust/kernel/io/register.rs | 1287 ++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 1288 insertions(+) diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs index 056a3ec71647..112f43ecbf88 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; diff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs new file mode 100644 index 000000000000..fc85dcd1f09a --- /dev/null +++ b/rust/kernel/io/register.rs @@ -0,0 +1,1287 @@ +// 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::ops::Deref; + +use crate::io::{ + IoCapable, + IoKnownSize, // +}; + +/// 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 providing I/O read/write operations for register storage types. +/// +/// This trait is implemented for all integer types on which I/O can be pe= rformed, allowing the +/// `register!` macro to generate appropriate I/O accessor methods based o= n the register's storage +/// type. +pub trait RegisterIo: Sized { + /// Read a value from the given offset in the I/O region. + fn read(io: &T, offset: usize) -> Self + where + T: Deref, + I: IoKnownSize + IoCapable; + + /// Write a value to the given offset in the I/O region. + fn write(self, io: &T, offset: usize) + where + T: Deref, + I: IoKnownSize + IoCapable; +} + +impl RegisterIo for u8 { + #[inline(always)] + fn read(io: &T, offset: usize) -> Self + where + T: Deref, + I: IoKnownSize + IoCapable, + { + io.read8(offset) + } + + #[inline(always)] + fn write(self, io: &T, offset: usize) + where + T: Deref, + I: IoKnownSize + IoCapable, + { + io.write8(self, offset) + } +} + +impl RegisterIo for u16 { + #[inline(always)] + fn read(io: &T, offset: usize) -> Self + where + T: Deref, + I: IoKnownSize + IoCapable, + { + io.read16(offset) + } + + #[inline(always)] + fn write(self, io: &T, offset: usize) + where + T: Deref, + I: IoKnownSize + IoCapable, + { + io.write16(self, offset) + } +} + +impl RegisterIo for u32 { + #[inline(always)] + fn read(io: &T, offset: usize) -> Self + where + T: Deref, + I: IoKnownSize + IoCapable, + { + io.read32(offset) + } + + #[inline(always)] + fn write(self, io: &T, offset: usize) + where + T: Deref, + I: IoKnownSize + IoCapable, + { + io.write32(self, offset) + } +} + +#[cfg(CONFIG_64BIT)] +impl RegisterIo for u64 { + #[inline(always)] + fn read(io: &T, offset: usize) -> Self + where + T: Deref, + I: IoKnownSize + IoCapable, + { + io.read64(offset) + } + + #[inline(always)] + fn write(self, io: &T, offset: usize) + where + T: Deref, + I: IoKnownSize + IoCapable, + { + io.write64(self, offset) + } +} + +/// 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`] 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 `BOOT_0` type which can be read from or written to offs= et `0x100` of an `Io` +/// region. For instance, `minor_revision` consists of the 4 least signifi= cant bits of the +/// register. +/// +/// 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 `set_` +/// for runtime values and `with_` for constant values. All setters return= the updated register +/// value. +/// +/// ```no_run +/// use kernel::register; +/// 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 BOOT_0::read(&bar); +/// pr_info!("chip revision: {}.{}", boot0.major_revision().get(), boot0.m= inor_revision().get()); +/// +/// // Update some fields and write the new value back. +/// boot0 +/// // Constant values. +/// .with_major_revision::<3>() +/// .with_minor_revision::<10>() +/// // Run-time value. +/// .set_vendor_id(obtain_vendor_id()) +/// .write(&bar); +/// +/// // Or, just read and update the register in a single step. +/// BOOT_0::update(&bar, |r| r +/// .with_major_revision::<3>() +/// .with_minor_revision::<10>() +/// .set_vendor_id(obtain_vendor_id()) +/// ); +/// +/// // Constant values can also be built using the const setters. +/// const V: BOOT_0 =3D BOOT_0::zeroed() +/// .with_major_revision::<3>() +/// .with_minor_revision::<10>(); +/// # } +/// ``` +/// +/// Fields can also be transparently converted from/to an arbitrary type b= y using the bitfield `=3D>` +/// and `?=3D>` syntaxes. +/// +/// If present, doccomments above register or fields definitions are added= 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; +/// } +/// } +/// +/// // 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! { +/// /// 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`. +/// CPU_CTL_ALIAS::update(&bar, &CPU0, |r| r.set_alias_start(true)); +/// # } +/// ``` +/// +/// ## Arrays of registers +/// +/// Some I/O areas contain consecutive registers that can be interpreted i= n the 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 specify their size= inside `[` and `]` +/// brackets, and add an `idx` parameter to their `read`, `write` and `upd= ate` methods: +/// +/// ```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 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 exit status code. +/// pub FIRMWARE_STATUS(u32) =3D> SCRATCH[8] { +/// 7:0 status; +/// } +/// } +/// 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 registers bank 0. +/// pub SCRATCH_INTERLEAVED_0(u32)[16 ; 8] @ 0x000000c0 { +/// 31:0 value; +/// } +/// +/// /// Scratch registers bank 1. +/// pub SCRATCH_INTERLEAVED_1(u32)[16 ; 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; +/// } +/// } +/// +/// 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_i= dx)?.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 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! { +/// /// Scratch registers bank 0. +/// pub CPU_SCRATCH_INTERLEAVED_0(u32)[16 ; 8] @ CpuCtlBase + 0x00000d= 00 { +/// 31:0 value; +/// } +/// +/// /// Scratch registers bank 1. +/// pub CPU_SCRATCH_INTERLEAVED_1(u32)[16 ; 8] @ CpuCtlBase + 0x00000d= 04 { +/// 31:0 value; +/// } +/// } +/// # Ok(()) +/// # } +/// ``` +/// [`Io`]: kernel::io::Io +#[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:expr)? ])? $(@ $offset:literal)? + $(@ $base:ident + $base_offset:literal)? + $(=3D> $alias:ident $(+ $alias_offset:ident)? $([$alias_id= x:expr])? )? + { $($fields:tt)* } + )* + ) =3D> { + $( + ::kernel::register!( + @reg $(#[$attr])* $vis $name ($storage) $([$size $(; $stride)?= ])? + $(@ $offset)? + $(@ $base + $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> { + ::kernel::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + ::kernel::register!(@io_fixed $name($storage) @ $offset); + }; + + // 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> { + ::kernel::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + ::kernel::register!(@io_fixed $name($storage) @ $alias::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> { + ::kernel::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + ::kernel::register!(@io_relative $name($storage) @ $base + $offset= ); + }; + + // 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> { + ::kernel::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + ::kernel::register!(@io_relative $name($storage) @ $base + $alias:= :OFFSET ); + }; + + // 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:expr ] @ $offset:literal { $($fields:tt= )* } + ) =3D> { + static_assert!(::core::mem::size_of::<$storage>() <=3D $stride); + + ::kernel::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + ::kernel::register!(@io_array $name($storage) [ $size ; $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> { + ::kernel::register!( + $(#[$attr])* $vis $name($storage) [ $size ; ::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::SIZE); + + ::kernel::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + ::kernel::register!(@io_fixed $name($storage) @ $alias::OFFSET + $= idx * $alias::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:expr ] + @ $base:ident + $offset:literal { $($fields:tt)* } + ) =3D> { + static_assert!(::core::mem::size_of::<$storage>() <=3D $stride); + + ::kernel::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + ::kernel::register!( + @io_relative_array $name($storage) [ $size ; $stride ] @ $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> { + ::kernel::register!( + $(#[$attr])* $vis $name($storage) [ $size ; ::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::SIZE); + + ::kernel::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + ::kernel::register!( + @io_relative $name($storage) @ $base + $alias::OFFSET + $idx *= $alias::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> { + ::kernel::register!(@bitfield_core + #[allow(non_camel_case_types)] + $(#[$attr])* $vis $name $storage + ); + ::kernel::register!(@bitfield_fields $vis $name $storage { $($fiel= ds)* }); + }; + + // Generates the IO accessors for a fixed offset register. + (@io_fixed $name:ident ($storage:ty) @ $offset:expr) =3D> { + #[allow(dead_code)] + impl $name { + /// Absolute offset of the register. + pub const OFFSET: usize =3D $offset; + + /// Read the register from its address in `io`. + #[inline(always)] + pub fn read(io: &T) -> Self where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + { + Self(<$storage as $crate::io::register::RegisterIo>::read(= io, Self::OFFSET)) + } + + /// Write the value contained in `self` to the register addres= s in `io`. + #[inline(always)] + pub fn write(self, io: &T) where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + { + <$storage as $crate::io::register::RegisterIo>::write(self= .0, io, Self::OFFSET) + } + + /// Read the register from its address in `io` and run `f` on = its value to obtain a new + /// value to write back. + /// + /// Note that this operation is not atomic. In concurrent cont= exts, external + /// synchronization may be required to prevent race conditions. + #[inline(always)] + pub fn update( + io: &T, + f: F, + ) where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + 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 ($storage:ty) @ $base:ident + $offset:expr )= =3D> { + #[allow(dead_code)] + impl $name { + /// Relative offset of the register. + pub 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 fn read( + io: &T, + #[allow(unused_variables)] + base: &B, + ) -> Self where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + B: $crate::io::register::RegisterBase<$base>, + { + let offset =3D >::BASE + Self::OFFSET; + + Self(<$storage as $crate::io::register::RegisterIo>::read(= io, offset)) + } + + /// 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 fn write( + self, + io: &T, + #[allow(unused_variables)] + base: &B, + ) where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + B: $crate::io::register::RegisterBase<$base>, + { + let offset =3D >::BASE + Self::OFFSET; + + <$storage as $crate::io::register::RegisterIo>::write(self= .0, io, 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. + /// + /// Note that this operation is not atomic. In concurrent cont= exts, external + /// synchronization may be required to prevent race conditions. + #[inline(always)] + pub fn update( + io: &T, + base: &B, + f: F, + ) where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + B: $crate::io::register::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 ($storage:ty) [ $size:expr ; $stride:expr ] @ $= offset:literal) =3D> { + #[allow(dead_code)] + impl $name { + /// Absolute offset of the register array. + pub const OFFSET: usize =3D $offset; + /// Number of elements in the array of registers. + pub const SIZE: usize =3D $size; + /// Number of bytes separating each element of the array of re= gisters. + pub const STRIDE: usize =3D $stride; + + /// Read the array register at index `idx` from its address in= `io`. + #[inline(always)] + pub fn read( + io: &T, + idx: usize, + ) -> Self where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + { + build_assert!(idx < Self::SIZE); + + let offset =3D Self::OFFSET + (idx * Self::STRIDE); + + Self(<$storage as $crate::io::register::RegisterIo>::read(= io, offset)) + } + + /// Write the value contained in `self` to the array register = with index `idx` in `io`. + #[inline(always)] + pub fn write( + self, + io: &T, + idx: usize + ) where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + { + build_assert!(idx < Self::SIZE); + + let offset =3D Self::OFFSET + (idx * Self::STRIDE); + + <$storage as $crate::io::register::RegisterIo>::write(self= .0, io, offset) + } + + /// Read the array register at index `idx` in `io` and run `f`= on its value to obtain a + /// new value to write back. + /// + /// Note that this operation is not atomic. In concurrent cont= exts, external + /// synchronization may be required to prevent race conditions. + #[inline(always)] + pub fn update( + io: &T, + idx: usize, + f: F, + ) where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + 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 if the + /// access was out-of-bounds. + #[inline(always)] + pub fn try_read( + io: &T, + idx: usize, + ) -> ::kernel::error::Result where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + { + if idx < Self::SIZE { + Ok(Self::read(io, idx)) + } else { + Err(::kernel::error::code::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 if the + /// access was out-of-bounds. + #[inline(always)] + pub fn try_write( + self, + io: &T, + idx: usize, + ) -> ::kernel::error::Result where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + { + if idx < Self::SIZE { + Ok(self.write(io, idx)) + } else { + Err(::kernel::error::code::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 if the + /// access was out-of-bounds. + /// + /// Note that this operation is not atomic. In concurrent cont= exts, external + /// synchronization may be required to prevent race conditions. + #[inline(always)] + pub fn try_update( + io: &T, + idx: usize, + f: F, + ) -> ::kernel::error::Result where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + F: ::core::ops::FnOnce(Self) -> Self, + { + if idx < Self::SIZE { + Ok(Self::update(io, idx, f)) + } else { + Err(::kernel::error::code::EINVAL) + } + } + } + }; + + // Generates the IO accessors for an array of relative registers. + ( + @io_relative_array $name:ident ($storage:ty) [ $size:expr ; $strid= e:expr ] + @ $base:ident + $offset:literal + ) =3D> { + #[allow(dead_code)] + impl $name { + /// Relative offset of the register array. + pub const OFFSET: usize =3D $offset; + /// Number of elements in the array of registers. + pub const SIZE: usize =3D $size; + /// Number of bytes separating each element of the array of re= gisters. + pub 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 fn read( + io: &T, + #[allow(unused_variables)] + base: &B, + idx: usize, + ) -> Self where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + B: $crate::io::register::RegisterBase<$base>, + { + build_assert!(idx < Self::SIZE); + + let offset =3D >::BASE + + Self::OFFSET + (idx * Self::STRIDE); + + Self(<$storage as $crate::io::register::RegisterIo>::read(= io, offset)) + } + + /// 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 fn write( + self, + io: &T, + #[allow(unused_variables)] + base: &B, + idx: usize + ) where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + B: $crate::io::register::RegisterBase<$base>, + { + build_assert!(idx < Self::SIZE); + + let offset =3D >::BASE + + Self::OFFSET + (idx * Self::STRIDE); + + <$storage as $crate::io::register::RegisterIo>::write(self= .0, io, 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. + /// + /// Note that this operation is not atomic. In concurrent cont= exts, external + /// synchronization may be required to prevent race conditions. + #[inline(always)] + pub fn update( + io: &T, + base: &B, + idx: usize, + f: F, + ) where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + B: $crate::io::register::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 if the + /// access was out-of-bounds. + #[inline(always)] + pub fn try_read( + io: &T, + base: &B, + idx: usize, + ) -> ::kernel::error::Result where + T: ::core::ops::Deref, + I: ::kernel::io::IoKnownSize + ::kernel::io::IoCapable<$st= orage>, + B: $crate::io::register::RegisterBase<$base>, + { + if idx < Self::SIZE { + Ok(Self::read(io, base, idx)) + } else { + Err(::kernel::error::code::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 if the + /// access was out-of-bounds. + #[inline(always)] + pub 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<$st= orage>, + B: $crate::io::register::RegisterBase<$base>, + { + if idx < Self::SIZE { + Ok(self.write(io, base, idx)) + } else { + Err(::kernel::error::code::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 if the + /// access was out-of-bounds. + /// + /// Note that this operation is not atomic. In concurrent cont= exts, external + /// synchronization may be required to prevent race conditions. + #[inline(always)] + pub 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<$st= orage>, + B: $crate::io::register::RegisterBase<$base>, + F: ::core::ops::FnOnce(Self) -> Self, + { + if idx < Self::SIZE { + Ok(Self::update(io, base, idx, f)) + } else { + Err(::kernel::error::code::EINVAL) + } + } + } + }; + + // 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($storage); + + #[allow(dead_code)] + impl $name { + /// Creates a bitfield from a raw value. + $vis const fn from_raw(value: $storage) -> Self { + Self(value) + } + + /// Creates a zeroed bitfield value. + /// + /// This is a const alternative to the `Zeroable::zeroed()` tr= ait method. + $vis const fn zeroed() -> Self { + Self(0) + } + + /// Returns the raw value of this bitfield. + /// + /// This is similar to the [`From`] implementation, but is sho= rter to invoke in + /// most cases. + $vis const fn as_raw(self) -> $storage { + self.0 + } + } + + // SAFETY: `$storage` is `Zeroable` and `$name` is transparent. + unsafe impl ::pin_init::Zeroable for $name {} + + impl ::core::convert::From<$name> for $storage { + fn from(val: $name) -> $storage { + val.as_raw() + } + } + + impl ::core::convert::From<$storage> for $name { + 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 { + $( + ::kernel::register!(@private_field_accessors $vis $name $storage := $hi:$lo $field); + ::kernel::register!( + @public_field_accessors $(#[doc =3D $doc])* $vis $name $storag= e : $hi:$lo $field + $(?=3D> $try_into_type)? + $(=3D> $into_type)? + ); + )* + } + + ::kernel::register!(@debug $name { $($field;)* }); + }; + + // Private field accessors working with the correct `Bounded` type for= the 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.0 << ALIGN_TOP + ); + val.shr::() + } + + const fn [<__set_ $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.into_inner() << SHIFT; + self.0 =3D (self.0 & !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.[<__set_ $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.[<__set_ $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) -> Sel= f { + self.[<__set_ $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.[<__set_ $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.[<__set_ $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= .0)) + $( + .field(stringify!($field), &self.$field()) + )* + .finish() + } + } + }; +} --=20 2.52.0 From nobody Sat Feb 7 17:20:33 2026 Received: from CH1PR05CU001.outbound.protection.outlook.com (mail-northcentralusazon11010008.outbound.protection.outlook.com [52.101.193.8]) (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 61C3A286D72; Wed, 28 Jan 2026 02:38:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.193.8 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567882; cv=fail; b=DKXiGcobyXY6hNlz4QcT5XpSNtVX4TflcVQvXEHoa2MljBNNc5N9D0oSMVJP+dHrNAo69xOe6hGAzxuwUEtNlT4dMRP1ttGMwBxGIh35VbX3f4Ln+8hIb1DD1GTPQ2OeJ8faKUkSdrOUjXKOfuB9Cwn5juIH+uw+0QqvKfq74g4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567882; c=relaxed/simple; bh=NcOB0KTjmSMVqkxjEDxbyVk3/qDkhNMKwnwLpeYFN3g=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=e39fLQEHuaJkYffYVpYgKkEKCX/vloOlJQAdl2i5R2gvjKcA+QtayG3TF58bshxHowafQGORg1WEKXp0PnyxYq/d68J8LGJuY0LLOzqCbig5dPDMA2q5accNLqPD6JsoYpwsZQyKVYMoPz3PkziI8a2wnM5lj45VqRdLihZiS1w= 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=rvGN8RGY; arc=fail smtp.client-ip=52.101.193.8 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="rvGN8RGY" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=rH8+e/xMqjcX3qhi3qQwsMYsxz6SPQD6TlXsjEZ1CNFATazR5KDO0R1PXYDKncKkOeGlTDgKmFgNGi5t0HEk0BXLgL4BxpMGNpcdpQzvS6sKtVlszCrLy9uUWiUtjUmLH2Qpp5/wmLmzi3V4RRvSzuhBfr1XogjH2b0u/GxPSftbQNDIE1SKtmCXPvoUU0ksXsZXF4dqYV84cUbxwKdN6HDsOoQRgtsHwK1FR9bhhfFQCScfeHQO/Gil5GrH0UNms5kK7KzTUO4EblSAlFlShbXsd0ut+Yqxu2WBNRmntNEgolm0Az4phvbqNJm6BE6rcUT1G5JQQlFHkQ51D9tf2g== 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=6jBdQu6GetQOFtmsL631n5vo03qTOEBIJojMceXek6I=; b=A6byl/1zJquN4mBIWpRRexo4CM22L16Tybgt7zC+yeKQzE/bqdwHkkxhYJzlPtP6LLYgRZnAAfxLS+OcfKpZprs7zBue8BOq9p02Sn513nhNIakNwEATjSQWUDKVnFpVPDmBvQcJqcAXVYrsmS5xI89L/57yZYtDkLFq1Oe3zlKMMLdecMOuJ9kzkeblLj0IGbeLdqoawDIf0JtFpYEDzTfvkU/sE+vY9yZff5e/M7yckblDuEjdssI0aU5a4FmkbLB6fqNF+ZiOYkLgxAQ9KVVHp1FuhaDii8TqREBH2HvKflzUfJ5VaUbcG1JznDe64xWXFcnWds76LhUHkwz3nQ== 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=6jBdQu6GetQOFtmsL631n5vo03qTOEBIJojMceXek6I=; b=rvGN8RGYOiqn+quOslQkl1TgkCmkU08wT+1GCR/MNc7qqi7uQGY+gIe3FMMwll5F89Br9zC1Xxr4eBunknsLIaNqoTrUQl955srBMjxvBSXBfFA31LrMa68FXgY4FttqRdIIv0/NZKSQSw8xDSOkwp7BqJaK1FJOUHyrkD7++tw8tFszWJUVCktFGHnhoeVMVPp3F3WcWlRvoNDl/tx5UBmlbUZfBpFQQVx3QYzYZ/cQ/vNEc86RSNyqpZy6SeC+3i3gT1vUPvuxYaXDffKvPiCw9CKpI80rWAPw5JqKerg7bzMmlficOKFdvWGLxY6ztkaDHuCjQcPo5VI5TyPoIg== 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 PH7PR12MB5654.namprd12.prod.outlook.com (2603:10b6:510:137::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.14; Wed, 28 Jan 2026 02:37:58 +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.9542.010; Wed, 28 Jan 2026 02:37:58 +0000 From: Alexandre Courbot Date: Wed, 28 Jan 2026 11:37:32 +0900 Subject: [PATCH v4 6/7] sample: rust: pci: use `register!` macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260128-register-v4-6-aee3a33d9649@nvidia.com> References: <20260128-register-v4-0-aee3a33d9649@nvidia.com> In-Reply-To: <20260128-register-v4-0-aee3a33d9649@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross 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: TY4PR01CA0126.jpnprd01.prod.outlook.com (2603:1096:405:379::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_|PH7PR12MB5654:EE_ X-MS-Office365-Filtering-Correlation-Id: e25a834f-a2a2-43df-6f6b-08de5e163fc1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?SUtmdGdrWTBMdzlOaXhrQytkNHdmemNUazJFWWRscjk2Mm5pTnNTdHozSzlC?= =?utf-8?B?bHM4RnY1TVRwd3JReUZoZlJDaXhoSTB3eGpaNy9zN21TU1BsZ1MxZDBMRVhG?= =?utf-8?B?MUpPMnJJRVFYOWVYZGFkMHlKRGZHekNjSHgwd2V2UW42RmRZQ1BPN09nMnh2?= =?utf-8?B?VVZnYitHWnpWQlNOSjRzRC93L1JKcDE0QnNtdnU1Z2NzYURVL2dqbGJWVDF2?= =?utf-8?B?V0tNN3p1UVVsMVErRHhQSUQxT0N6NnNjVmFnenVYTjIxSFMwbUg2TjQ1MEI4?= =?utf-8?B?SkI0RlFXMWdidXpRRTEyUFE2ZGY0WHFMTDZ1MDZUd3NZTlZ0blRQNURpV1Q1?= =?utf-8?B?cGdWZW94aXRhcFhBT0l1RmxkSDJrMm5MTUNVSk1Rd0kwZEFDMU9CYjQ2ek5n?= =?utf-8?B?WGxqUXdHRjBZZmpUaHhJR1FCeEtRQTBOSi9keXhKYjRMYzlLM0w4ekJQZUVj?= =?utf-8?B?WU5iVEZRaEg4UGhyc2UvOEgxandvWDQxVWV0RWJwNWVSNm5lTGNHMUdhTng1?= =?utf-8?B?T0xWSHhhMEt0WDZYSGFsbUErdVBncFYwMjdOUXVDY2VDb2ovL05RajFxb2hN?= =?utf-8?B?QTE4MWhueHo3RnBqRXVtMXRpVmpIcmZCNitCdkVoNndkbmlWSk9mMVdKKzJp?= =?utf-8?B?czIrY2lOaVpvQ01tYzZqNG9EMGlPYTROWVRJc0JIbDVHQ1daUlRCRTZKUVBp?= =?utf-8?B?WUtCQmdwSU81Rkdsd0VNVGM2SHVFb2JuVEdHUzdGWDc5cjBzd2ZYWHlPRzM0?= =?utf-8?B?SmxCOXRaVm16TzJIbGpSTVB1bUd4NlpjSGJJa0w2MElTaVpvQ1AyTjJEdDBM?= =?utf-8?B?NkFOMnVwOGZsVTkzYWRYR1pKUGVIWXRRSEwvbWowbW5TY3VSY213R1pEU2hK?= =?utf-8?B?RzNlQjErTnRLL1haRWt4UGw2WmU0bU81NGpSbjdvaEE0Z0Jhb0pNUHNjYVlx?= =?utf-8?B?Q0RoeVg5S2YzUGRZUUs4UCt6eFdlTTZiZWplZlp2L2krT0JuTmwvaUZIOUJ4?= =?utf-8?B?cElPNnNoRHEraEJ0aStQOFQyYi9sMlcrbS9SbWpzOVpaN3FObk9PeTc4blha?= =?utf-8?B?MHNLYkNIUm9xNjg4ajIwcWsraitvL2NWcWdLaGxqdU5Cd2hhSCtJS1VhOFFG?= =?utf-8?B?REczRUEwODFMS1YrTmZCSG9NNU1rUEp2ZFpaVmJ5QTNBVHk3STI3UFdZQmdn?= =?utf-8?B?Uk9mNVNZcUFqeW1pRStNWXpSYUhQTTF6Z2RNTHZtdkE4Unc1aHBjY3NtTjg5?= =?utf-8?B?WCtSM1VheVFDaEt6RDQzbldBWlhCaExpR0RYS0hhdXFJTllndmRVTW10VVE3?= =?utf-8?B?TWk0YmNhZGcxOVZ2cEIzb2tNa3kvQmRSeEh0eGZUbkppWHRkRjRoempHbjN2?= =?utf-8?B?VEFVZ1ovVWQvR3lqaXJNYzlFVHFzdnh5amxnUDQ4WElPdjBNTnMrZ3oyWEJG?= =?utf-8?B?bXZKK1plQUt4bzhWNXNHMUlNTGRZd2w0aGJLOHhsYVNPbldidFBhbVBFS1Jj?= =?utf-8?B?dCtaQ2VtUWVFNTg1VE5HU0k0M1ZqUEQyeDRzQ3hIU3FNOGtGa0NnT3V2UGlF?= =?utf-8?B?UnpDS1JpcXQ1a1B1ZVIvTDg1dmFxZ2tJcm1FTGdQRjJ2ZUVDL3RqSTJsdVlB?= =?utf-8?B?ZkdvT3JtTldXbUdsNzVrZU81eWpwdy93SzhUR1Jlbng4aENmUVpEZVE0T0dz?= =?utf-8?B?U2hXTVVhZTZpTUZMUXlYTE5rQWo5ZStJVll0T1lIbzlsSi9mRHVBOHJXbEdO?= =?utf-8?B?dFFJMTZpUkdaOHpRNUY4WGVUUmMvOE9ESmp1Y3YvdGRnN1FGcllKUllmL0pj?= =?utf-8?B?dWVqcmN2K2k3YW1XQTZhUXVpeU9sMS9Ra3htTmNzbFlWYjcvUFZxSDhaOGs2?= =?utf-8?B?bWlBNXV6T1lUWm9HS01mYnlERktPc3NsZGNHaW45cDV6M08xRFNkOUgxa3pB?= =?utf-8?B?WXB3MDdTNGdyNjNhdFREU0lTcWhRZWxhQjZTK3ZEc0J0Smk0NnZXWWFPaUhX?= =?utf-8?B?TVpqcXlrK0d1YWloWmZwSnBTOXpDcTFONG5oMlNLNnlGOHRXR1BiYmFXTmZN?= =?utf-8?B?MXVBZDI0YWpYVmMybkdxWUpVZS9NZWs1OEsyU283ZUlFeUkycHpqK21QcWRD?= =?utf-8?B?SWlaa3J6Y010U0JveE9NcVZteStiSjFmOCs3Y2xEMTdFbk5LOEFjMi80ZXk1?= =?utf-8?B?Mnc9PQ==?= 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)(1800799024)(366016)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?U1pMN1ZPdHEwY1VRVWFHL2g5dUlEMkVHL1dEWUlKTlBwV3FBdEZKQnluRGNO?= =?utf-8?B?L2taaVNWTUwwWWZ2TGR1SGlLQVlGcHBHem5TUDNPMVJneUREeGduaEFpV3lT?= =?utf-8?B?eTlnbDNudWR1TnNOc3RTTDRZRjFYSmVULzk2M1BiNjREM25pcVhWN090dVB1?= =?utf-8?B?aTdoVktoV0xKSDArTlhsN01obDlCNFNMdGlzTlpKanVkNU9FMXhrOEdjcGVF?= =?utf-8?B?aU0wb0tRdWRNOTVBUEpaeTJWaVU5YXczb0dXMGJ0SjRhQnhnTk1lUnBiSW5j?= =?utf-8?B?MnF5UHhDSitxdDMybFFOTzJSZFErZk9odjdIYWM5cWlITkxmdUhxZjlWS1FR?= =?utf-8?B?NmhRUGRnaUhJOUVudnlmdGd3eWFWTDJyTFp3VkNLLzErKzN5MjR6NzhxbDFE?= =?utf-8?B?YUdSY0MxdnhuQ2s2SEJYUHdKcTZjSS9nUThrc2JlWVp4dHNQU3NXS1VmSGRD?= =?utf-8?B?RjhGck9NMDVVbnpMKzRjZGV5QVk0d2w1QXk3MUZqQWh0M0p2MWlDckFvYlFS?= =?utf-8?B?Z0Y5cUwwTUxoWTJJS0p5MnA5YnNtR1NBUmNHOGpGb054UnViT2JWZG5rZDlj?= =?utf-8?B?d3VrSGl0MU1RVXFGcDYrb2Rja3V3dU1iak9nVEFqeGd3UmRQbDAwV29HWVBR?= =?utf-8?B?dFVTaS9Lb2ZSY0N3RTU2M0tTN2VuMFpaZkJlbXNVTE5IaGJlN1dPenRMNGU0?= =?utf-8?B?ZGgrOWZMSGNNQXJ6c0FMZzZ2T3IyRWJXY3ZEY3lSMU5wcFpPbjZ0L003QldP?= =?utf-8?B?c2ZrV1hXYzF3cFpyN0k4ZDJiU2ZqUUs0dW5wSjFHUWNZZHE2THlBVmEyOGZC?= =?utf-8?B?VG9zQ0ZJT0RQaXUvK0xHQ3IyV2ppVGlTWUs3LzlaTGsvNEE0WlZpdkNBeml5?= =?utf-8?B?NzRHVFoyMGQ5dUE1T1ZLcmtEQU9HdDRKMldseTE4TGNjcTVwcWZFdE9HVjZn?= =?utf-8?B?SGwweHlTVVg1SGIvcUYvODZCa2hxN2x3YVhibUxkTDU1QmtnektuQTFjZHRC?= =?utf-8?B?VGcvM0l2SlQ3ZStRc0tHNUdObmE1SXUxQlBMdjZrWHBJUkVoNTdyMkpGc296?= =?utf-8?B?Z1loN1BuWEFZZWhMTWk1WFBUN1dRN0prZ2lqUXVQUjFuVVVqRXpZMlcwa0RS?= =?utf-8?B?ajhpMXJUWjdHblFxNUlEcXZNWTF6R1ljN3R6eXk4S0tDWmRickJGRk1DMyt0?= =?utf-8?B?UThPS3hjTFdBTlZBQ2ZOTml1cmJpLy9PcnNTTitiZUVIT1hGTTJ4QlE3a1pN?= =?utf-8?B?Z1RSQi8reWxFK0dOK0dQYmdSTnZDNENaN08rVUVOb2NSWU9FUVJOSFE3aFZt?= =?utf-8?B?cUJWZkswTWJ0emtJSnVMUGZkbmFuVFgyek9xSGlwSHFWcENvenJENUxma2Yv?= =?utf-8?B?T0h0cDZ6SS9IQkUydU5ZYnJFSDVLODRDckwvMFlWWHVxY3lCcG16TEdxV1B5?= =?utf-8?B?MFI5RmZmOWppSUFOQnJHSmxQcjAwejZzaWluT0RYVTJjMGRZMzF3aGt2N2tO?= =?utf-8?B?N1JDRmxWMTJta3E3ZW0yTHpwVm9DT2I5SGQ3UkJSYm9FWGhNMjVRcnVnbDZG?= =?utf-8?B?SFdaUWVBbCtZaHh4RlNxc1JGdXNodW14Ni9TSHovNHFzRWJwbG5teElXWll4?= =?utf-8?B?UXE5VUxvV25OVUZXUnM3MjhDU1JMU1RaQWlaQUE4R0dlUm9Bd083dFpmN21E?= =?utf-8?B?VWlaUHZOa01vRXMwcFpyamlreEpRZFVYUU5nZGV1MFozKzBOUCtBY1JFRUxE?= =?utf-8?B?WlFoMU95bjA3cUtLR1IrYnZSUzFia3B1SE9ETm1xaHplMWd5ekcrMHZIUHZ0?= =?utf-8?B?eGRQRkVJTlBNRU9PMk1PNFdtNXJnSUp6YnRUd2dJaTlIblArbWVyYkFVeXlk?= =?utf-8?B?OTNUakorWHBIeUFBRnBCMzdvMkJnT2ptMC8rdWJOVWdnZDVNWFhoR0lyNkkv?= =?utf-8?B?NytSMUxLVThzeFlpdnVMVUZXWUg5Z0hDWjlOaVoyMG1nMUhPK2FpY1VOWFhh?= =?utf-8?B?NjE0TGZDWkVvc0YvUncwaGVxM3o0eTBxZTd6OExRMUZuVGhHUkpoRGd1Zi9W?= =?utf-8?B?V0F3NUpJRDVhS3NIcnZBVTBHUllWc1VEYzBVNGwyKzdEanJ4WGxXeVJkNlk1?= =?utf-8?B?bVkvVDZIMlcrejJyNUMzNzdKQy9WSElCbmFlaG5rT3UrdDFmT28rNlVQcEpD?= =?utf-8?B?TlpqR0ZCdUF0MHpGNzZUME5WdUJ5RjFpS1RDUUROUmI1ZzZQYWwrRHBLdXdN?= =?utf-8?B?VHFQOEF6MDVkczdoVnNQTFRhRzN2aTlYM21SRWU2RllzamFZZmk4T2ZtUlBI?= =?utf-8?B?ZmtwYWE2QndQWHpmV3pSMXY0bm5xcGJLY2lFQS84OWNQSy85cFFrMlVYUGdh?= =?utf-8?Q?99JHaSDjnLt/nYYMuXaB/G6TT1G2gNBeJcm5mb4x82rE7?= X-MS-Exchange-AntiSpam-MessageData-1: 13PIwkYMRX2B4g== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: e25a834f-a2a2-43df-6f6b-08de5e163fc1 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Jan 2026 02:37:58.7021 (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: Z7HwR9fah/uFBdIWog5NpAVQ6r834q4/xChV8KWxCVyXf0yH5TwJwRX5iVIO8zTY/9gxYH0YxHYpicRFhTFIJg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5654 Convert the direct IO accesses to properly defined registers. Signed-off-by: Alexandre Courbot Tested-by: Zhi Wang --- samples/rust/rust_driver_pci.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/samples/rust/rust_driver_pci.rs b/samples/rust/rust_driver_pci= .rs index 4dfb8a6a4707..df2232d6b71f 100644 --- a/samples/rust/rust_driver_pci.rs +++ b/samples/rust/rust_driver_pci.rs @@ -70,24 +70,37 @@ fn testdev(index: &TestIndex, bar: &Bar0) -> Result { 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. + ::kernel::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.as_ref(), "pci-testdev config space read8 rev ID: {:x}\n", - config.read8(0x8) + REVISION_ID::read(&&config).revision_id() ); =20 dev_info!( pdev.as_ref(), "pci-testdev config space read16 vendor ID: {:x}\n", - config.read16(0) + VENDOR_ID::read(&&config).vendor_id() ); =20 dev_info!( pdev.as_ref(), "pci-testdev config space read32 BAR 0: {:x}\n", - config.read32(0x10) + BAR::read(&&config, 0).value() ); } } --=20 2.52.0 From nobody Sat Feb 7 17:20:33 2026 Received: from PH8PR06CU001.outbound.protection.outlook.com (mail-westus3azon11012044.outbound.protection.outlook.com [40.107.209.44]) (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 445792BDC0B; Wed, 28 Jan 2026 02:38:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.209.44 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567897; cv=fail; b=SIi67Tn2a/UBsI/AVO03YWyC7rJEuuvHDmETEO70bOSv90to0fUxEMjRyhi1JZ/xhqRuEzEs8jrssv25W9+GyaD0VzuUfMAo3cunLHUhITAvbfgrTqsUUBcbC1nCVtcJOMuxHbN+xwZlBKLwIUEom13aGRFcHtGfmEnDqPFVW+Y= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769567897; c=relaxed/simple; bh=CiXz0cJqt+R2E7LCwZZ90Lk0DdDlG0JgowTZuIRuC8E=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=rwk4OU4rQpeJ8ckmCE7JoltWJiz4wme6R1m3IUKCvGVQIVq1zGHzzP9pR6VZDzondnfBQSebitUvW2nUH91bIRYsWH9DjArKDND2pPnoxd2bD+LddOXDxIkixdM6n/Z+dEIAyRHIEqxzKaY8hPJNXmCGZiI8DL/MoDaa+5usbdQ= 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=qg5HLbPY; arc=fail smtp.client-ip=40.107.209.44 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="qg5HLbPY" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=GUKbYT7wp0uboZBPIx1ktwcuERnb1ZR4z1ga+HRLkekETFg16moeq/B7nTcV7fr9SDFWXtm2EqTgt1u6VV4N3aIqvxglrJDVMyKa1X5VksDSG1qDkkax6NaPKQJDvs//EodP/3WXNMtVEHBPOj0zY6+DmAoZDwpDZw7rgtV2sscT9ziwDU9DgAWx2Sq5iUmG+pqwsjdnUMppSjkcEU3K3xv2I8mgpiR22Kq49h+dQO9D3Bgfh478LkdovsOVRvIzUphjoEVcGJZPPbb1nOnEbc2C6HNcVLAJlHOGZMoB4tqaYTV6RtZhx8g0upjBf3yVAhsPs47DUfo8cizu+nK+Jg== 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=+aFBhztmB8AC9/IYYJufYivAMUNcBY0XIY+zAte3jzE=; b=MBc13ov0fZi4foqqmLi5aAtmKNSdonkTHchwBHWYFyKbs8SvZaa4lLlgbUYEm7L83/F+aGbwV9+AWdZ7OXXJu9NYU8nI7g8V+u8936o8nNnkla0qM+1BJSLXDLtu+0AozTcPC5vI4p5SaDPkL+oBH44OLos1JGnTA+uma6aTxQgDzwHB4rmFuKkBjTHE7ksc7xTrnRAeFF8erBmuQ9INBPKgboAgJU2Pm38qL35Pgqwh2Qx/5h57fJlSWyf/Okvarj/ZlU0ym+aohsg8yOCjhhH06uQ+i8X7cxxyhSUz2B6u8xNk2e6ztWhI58t0K0YnmjPqaU+ycBxTRBjH/9O88g== 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=+aFBhztmB8AC9/IYYJufYivAMUNcBY0XIY+zAte3jzE=; b=qg5HLbPY9oEOgvKmks8Xce95fzupNAZAZN2Jqmt6HUy4yNv8fLX9pChF3nLEk2vNTikfj7hhpCrQvFBPAMfIAQJNYr8YDQvcsPusiBmDSnaJwPkANyKp88uajt73aVlHOgBeyzRFuMX5dj0A/HDDqGIsx+mPOIMGpH0q/Gn3WWFCshLNjjJ7aFzzGyC4Y414zYmZFPVLXY+/3bsnOk7JMZ9vwE1LtR5pGrKvzslzL3nTxefzE4iIcnkEBmB7LE6m2Y9EIGZY/+co7VON9+zB43IbKjZ3ErBYUuunsR66tA/TIfEFZsMcNMqhnF+wM7WtekBxKaBNiBdkV/La2q/SbA== 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 PH7PR12MB5654.namprd12.prod.outlook.com (2603:10b6:510:137::21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.14; Wed, 28 Jan 2026 02:38:02 +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.9542.010; Wed, 28 Jan 2026 02:38:02 +0000 From: Alexandre Courbot Date: Wed, 28 Jan 2026 11:37:33 +0900 Subject: [PATCH FOR REFERENCE v4 7/7] gpu: nova-core: use the kernel `register!` macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260128-register-v4-7-aee3a33d9649@nvidia.com> References: <20260128-register-v4-0-aee3a33d9649@nvidia.com> In-Reply-To: <20260128-register-v4-0-aee3a33d9649@nvidia.com> To: Danilo Krummrich , Alice Ryhl , Daniel Almeida , Miguel Ojeda , Boqun Feng , Gary Guo , =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= , Benno Lossin , Andreas Hindborg , Trevor Gross 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: TY4PR01CA0109.jpnprd01.prod.outlook.com (2603:1096:405:378::10) 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_|PH7PR12MB5654:EE_ X-MS-Office365-Filtering-Correlation-Id: b2f8fb5b-aa33-42ea-741c-08de5e1641b9 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|366016|10070799003|7416014|376014|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?aG9zUFMxUGNwRGhYeG5qSnNleHVXNU0wWlRnb21ROFlwMTdwWklBVEd2VW9H?= =?utf-8?B?UjNyOUg0aitZdjQrTUxDTnlIWGxqejI3MHorRVFzQk9ia2NkWDNGaHJxYytp?= =?utf-8?B?cnU4U2ZoTlZ4c0F4N3Fqd2NRdGRyL0c4Y2tPTit6RWxmMFh1enIrdldVZDVo?= =?utf-8?B?SjI4MFZlVTVhVVQwT3NzdTdkTWRzanc1WnU5YlB4V0xJOEZ1N29oNkJERTNW?= =?utf-8?B?bER3dHRWdVB6OW5INTBQSnNMdzRrY2Q3S0VQTThGcDBYTW1uYmRsNVV5eFN0?= =?utf-8?B?YXBtYUpxMlB4TUlsUS9WcVRrTVkzZWtKSDhaVElYV3VwUWJuZVh5MXVZR0dP?= =?utf-8?B?Vzh6elhySlZIV0lLRUJIdkZTKzcxeUZIT0cyZndLbTNJMDI1U0ZCNUdkL29J?= =?utf-8?B?ZDcrQjZ1R1h4M2dnWGhZT2kwWVhKMEdWVHU4NGNVK2pJcUFJbU1ERFNNY0Nk?= =?utf-8?B?MjBGM2c2YzhKTDVVajVrRnYyREdCcGpMUzhGMFQ3YzllTE1zbUJjT3I5OUdi?= =?utf-8?B?czNJTkVyQ2JMdmpFeklwbXVZZFZ3ajRMMTlqQUdvMkJ1a0tXK1gzcUlzOGRV?= =?utf-8?B?dVF4MTh1dEcwTjRMbkVOalRVU25Kc05iOFFudzVPZXA3bmwrV1A4bVppMEk0?= =?utf-8?B?dDd0ZDltTjd2UnJ1ZDFWME9TWlJGUDN3bGdrZ3ZsTXhJWjUvRy96bUJvRFdk?= =?utf-8?B?d3lJeU0wd3o4T0d3YUZRemxFT1dOUXZoQk82VFZlS3FkdStoR1QxQ2U2bFRi?= =?utf-8?B?OU0vL1dtZFJuWU1sUjdEbUMxeTIvb1dBV0NvNUovVjIyR1pDeE9jclVRUmp3?= =?utf-8?B?WTA3UkRHQTJ5emhFbDdEalRRd05DWGhlOUFlY0RGbFlwcGtuYnZrazdoZGZq?= =?utf-8?B?VnZmUkRvWW9xUWtsQ2pKNzFwRXUwRkxzS3d2Ty9LdWJLWGswT3RQM2xlbFhG?= =?utf-8?B?azVNOGFsdFZ1aWJUVWdYSlpWTHUxbEhiK2l0ZHNMN1ZMSUg0SkNaQ1BTYjlL?= =?utf-8?B?WWcxdERrejhjQkkwR0thOVU5TEdTL0dyN2JsQnRoTDNKNS9Pbjl2Umh4MVBJ?= =?utf-8?B?TWRkSlk4QzVPdDFDWHZOTGVJTHpQTHc2ZjI0MjlhSE9Ta0VnSEJCTWpEbndl?= =?utf-8?B?RGhwbUtxZTdzd2RveGtmdVR3VXU0U0xRNjB4SXkwVUs4dXZDZVRyWGE1Ykc3?= =?utf-8?B?RlEyY1ZVMm5uc3BQV2VubnMzVmYzM3BscjZBOFJDQUxqdW5SOFlVdFVkNUtz?= =?utf-8?B?bnRpaEdYbDhuOEV2aG01c2FMOTVkM3FmZ1EzZ1FvYW0wNk5SMEVhcDdZSmlN?= =?utf-8?B?eFlUUHY5UVJsYUNPNU9YYVVnZkgyRFk1azNoZm9saFJGMmYxYzl4OGRUd1I4?= =?utf-8?B?UVB6dlJKL3A5alhjQkxTd3VsQUYyc3BSbzRqWXBCbHFiQlZxTnd0WHZhZ2ty?= =?utf-8?B?cTZta2plMUFydU1pVDhDcUs0Q2NjZHZFWXhwd1ZuMnA4QVBqd1E5NlAzd21r?= =?utf-8?B?NWd6VjU0dlk2Mi92bTRMSW0rQlNhZ21nZkF2aDVld21yaHlpamFZc0E1TmZB?= =?utf-8?B?Sk0wcFVnRWxHUFdyMlpwZm1icWVramthQlJwT0wxeDFpY3AxbkNpd0g4RFE5?= =?utf-8?B?K3JQdUtnVEVEWElNQmp5TnJ6dUdDSTh1d2w4TmR1NzZJK0VuZ3U2eGdRMFhM?= =?utf-8?B?QjNyOWtjQVhna1V2TTZWODljSFVuWnpUbUM4a2gwSGJJM2NNTGNLd3AxL1Q3?= =?utf-8?B?Wm5IYlhVVlNNY05CRmtWbERvT0RJTUlZS0dwRVNQRHNzbHdiUUc1OHdyWFJj?= =?utf-8?B?UFhBdWxKSU4zL0Q0SW8yQU8zY1c2ZjRFbkZuUVpDWS9rRGRrN0d3cFRrL0hy?= =?utf-8?B?WFhMclBqRzJrMW9vY2lKR3Q4Uk9qQkI4bXZNaDVLUDJMSGh6dkRzL3VxbEs5?= =?utf-8?B?NHVtMnBkREZLQjlXMjlMNzFJVy9kUGs0SGpoUnh2VVVEa3dXaFc5dndHMFZJ?= =?utf-8?B?Tjd1TmtyYW1QcVZ6WlFhSGI5ZUlCSjVWRitSZ2FLZkxxMjNlVlFtKzlvYi91?= =?utf-8?B?eVk0M1ExV1FaSXRlb1UraENpb2ZMNVVpZUhPdUF1Yyt4clA5N1ZIenVtK3Nz?= =?utf-8?B?WmlNb21WT3dzUnFZOEdnZ3ZlTExaT1g4bjdUN0pSOFZuL3V3ekExQTErc3Nv?= =?utf-8?Q?X6kfMTk5dYUp5cqbRt5TjW0=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)(1800799024)(366016)(10070799003)(7416014)(376014)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?TGdIOWhNOGppSW9hZHFNcHdqYnBCYjZtQm9IK251dFljZkQwWW10VTk0NTVt?= =?utf-8?B?cjc0MURxK1hRNzF5ekhERjVsWU5LbzJmVHRONGdaeUJONVhVaENqOUZhN3po?= =?utf-8?B?WHJ5V2xxQUxKdG5RSk42SExpKzNxK3BVc2JFV1RoZW9rRUtXUkpBNEdhdlZ0?= =?utf-8?B?U0NFZkVTbFoxbzBmZUV6aXM2UEorcW5kVnk2VnVJQjhEVytxZlBqcStXelJI?= =?utf-8?B?dDVTbkhFS252NHg2TjRGVDdFM0t0ajdUSTZwYi9rZ2FMck9zTExKMHh4L0hR?= =?utf-8?B?Qm9BNkZsVFJGK1pjRTlXWUZuc2g3ZVFubmJneWZ2WGRxVnRhOUNGbnJFTDBX?= =?utf-8?B?SWF0elA2ZlN0UkZ2MUIxaXdTRmUrNFRZeFZxZjBEdFhpWW04RmU1RVlQSnV0?= =?utf-8?B?ZmhSVlBhSVNKWUd5MWg1UmtyZE9hUks3WFJZZmxWeWlPTHVoV0NIOGp4TmYy?= =?utf-8?B?VUExdk9CNUlrUlI3ZnhtWllpdEVwOGtYM2RVRzBPa0VVSFFjdTZYWkhwNXVB?= =?utf-8?B?VW15VW9zNE9BZGRpd2NDZGE4dk5QQmZWQU8wcUR2RDQ3OG5QVEFwdzVaUEsz?= =?utf-8?B?VVNLaDNReUFDSXFKMTJWT29hcmtMeVhTM0FabEVtRTNSV2JObHVBQ2ZnNUpH?= =?utf-8?B?dytGamhhZ1AyQXJNTXhXQldhVnZuS2dEa04zRUxlNVdVQktIOEZlbjdMbDEv?= =?utf-8?B?VXZBekNiNFltMWlEMHJ5RTFlOEFYSzNWdE1SNmgyeHIwdGdMa1ZrNjlKWUJt?= =?utf-8?B?SzFiaTFQYWE2aCtRRzcvTlRQakZILy9XMWFnSFc0NUNBRE96NXpleEVidmFI?= =?utf-8?B?Um1sbHNwTGxWUDlsZWpWaG92SVZmWDJpZWdCT2E3aW1KVlpnNTVwTy9Fblcz?= =?utf-8?B?K1pRMGd1di9GUGFZaTc0RnByR243VkQ4eXplVDNhKzMvdm5iTXdxdTZyblVy?= =?utf-8?B?SDdNc3BaRW1TdmhpUmJIWXQ5UGhIcXFvQzJselhIVXZZNE9CRDRxQkxMTWox?= =?utf-8?B?bGpYbUVLZmRLa2VmWGVDR2RaeEVKU3lrRURCZDlnS281dUZRcm5zWmc0RjY4?= =?utf-8?B?dytJOVNsbVlDdzVta2FhYVJNeVllOWFGL3lxVWZDNHlNTGgwNDZ6bWlJdkt5?= =?utf-8?B?R0xKTk1pelRzbVJyUnE4ZS9KSlJQMTRCS1RSakFabGU4Tld0dTkzRXFFMGwv?= =?utf-8?B?TzB6bXN1QVZtR3lIa3Y5dGZKalBtYWx4VENKMm5lbFBlZkhvWkZCM3VSZnpt?= =?utf-8?B?STJSazlSS2V1WDIrTzh6Y1dyV0s3WWszbVdzYnpOMVFwK0dnWTlhc0ZjNUVy?= =?utf-8?B?MExXS2NWK2xmMVpFRitUNEJaZVVhRUZVTm4xeitRaDk5bGVucitjWWdpaXlq?= =?utf-8?B?ektBQS9HdTk4OUh5QzBaZmttUGhIYlZTZyt4dUYyUU40VEM5REo3SGtjS0dS?= =?utf-8?B?alFmRHNIWTVUOUNaSllBWGZWNGJCZ3pEWjFKUFk3eWFUZ0tKWDZHbXpuWm0r?= =?utf-8?B?UE5PWDNyWHVOazJwZWJRTHRGTkZZUnJNaklhaXNOYVZlcFlnQTNDdkhydnZY?= =?utf-8?B?aCt6QlI1WkVwQzI3UlJWaXVZYkpwRllpQU5HemRQdCtiWDlRdWxHbm5jbHo3?= =?utf-8?B?VTlzS0FPbEpxcHhNenlkbmRDK2x0L00zdldLY3p6UjFvYmYzdTBBVlAwemFZ?= =?utf-8?B?ZmhiakRQTGdtamdQVnNtWkFkZGUyekFVSURQd2Fsd3I2RTRWbERTUE5ydTlv?= =?utf-8?B?YWNrSDltSTlHMWhBQUU1K0JoM1Y0T0wwckZXMW1YcnF2bW4rTEZ2dzduNVR5?= =?utf-8?B?bGI4cW5uWHcyemhmOUdURGpPbkhkUnh2Z0dybjROdHN6blNCa2h1Um51RTJa?= =?utf-8?B?c3hoeW91NFBvbk55ODJDLzRIYnpDeVdncjJhdUJoRjZvSEVmMmM0NmNqbkdt?= =?utf-8?B?RUtGUUdNYWY3bWczQXlZcGw0cithdFRjMTBrS1UwNGhQWDlRczA2QWpBeENy?= =?utf-8?B?TzV6aEorVUExazNKeHBqQ0VzNVRoRlpYdWZzbWduZFh3Y1lrYk9sRGtaMHBV?= =?utf-8?B?TXhzYnZxd2NUMHVhcy9LMFpyNjNzd0hWbGhiZnNlOWpZTk5PUHlCWVJSSlhY?= =?utf-8?B?TkxSU1Bhb1NGcG9jdlU3akpyOFJXZEtVY2NHdFcyOFVFS3VFTzRmc1poNmxL?= =?utf-8?B?S3JwZmN3UkpxUndBdEtxV2oxSmtnZjlwaERvbkRmMkRWbFA0aU9OTWpnWldm?= =?utf-8?B?M2dBNDZlOEQwSDJ4bDEvemE5S0VwYXZtS1BKUnlUWnlvSTM1L21NTk1rSzdT?= =?utf-8?B?RGZYU2VKbWVQdjlUZEt5Vzl6OVk2SWY0dWE0eWNVVlNVQXpMaXdhZkQvdUpa?= =?utf-8?Q?9ZGLNmVCiUMKotGi/s68Dm45J5E94R33d9DPF2pVZW3lf?= X-MS-Exchange-AntiSpam-MessageData-1: f2UFnQ17IUIiXA== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: b2f8fb5b-aa33-42ea-741c-08de5e1641b9 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Jan 2026 02:38:02.2881 (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: 4HNeoUdjZw6jVvY/Kc+G3qDY59UQhV10r7ruM9GqmnjNXzOcdbVUiBeu9zJzm5eEu9yuB/FtObk47aQBiJPrwQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB5654 Replace the nova-core internal `register!` macro by the one defined in the `kernel` crate and remove our own private implementations. Tested-by: Dirk Behme Signed-off-by: Alexandre Courbot --- drivers/gpu/nova-core/falcon.rs | 175 +++---- drivers/gpu/nova-core/falcon/gsp.rs | 12 +- drivers/gpu/nova-core/falcon/hal/ga102.rs | 15 +- drivers/gpu/nova-core/falcon/sec2.rs | 13 +- drivers/gpu/nova-core/fb/hal/ga100.rs | 17 +- drivers/gpu/nova-core/fb/hal/tu102.rs | 2 +- drivers/gpu/nova-core/gpu.rs | 31 +- drivers/gpu/nova-core/gsp/cmdq.rs | 4 +- drivers/gpu/nova-core/regs.rs | 494 +++++++++++--------- drivers/gpu/nova-core/regs/macros.rs | 739 --------------------------= ---- 10 files changed, 397 insertions(+), 1105 deletions(-) diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon= .rs index 82c661aef594..1b9283018c13 100644 --- a/drivers/gpu/nova-core/falcon.rs +++ b/drivers/gpu/nova-core/falcon.rs @@ -9,7 +9,11 @@ use kernel::{ device, dma::DmaAddress, - io::poll::read_poll_timeout, + io::{ + poll::read_poll_timeout, + register::RegisterBase, // + }, + num::Bounded, prelude::*, sync::aref::ARef, time::{ @@ -27,7 +31,6 @@ IntoSafeCast, // }, regs, - regs::macros::RegisterBase, // }; =20 pub(crate) mod gsp; @@ -35,11 +38,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) } } }; @@ -47,10 +50,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, @@ -59,16 +60,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, @@ -85,46 +86,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 @@ -138,16 +131,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, @@ -160,24 +153,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), } @@ -185,21 +176,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), } @@ -207,33 +196,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 { @@ -246,10 +226,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). @@ -257,14 +235,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, @@ -276,34 +254,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 @@ -385,7 +354,7 @@ pub(crate) fn new(dev: &device::Device, chipset: Chipse= t) -> Result { /// 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); + regs::NV_PFALCON_FALCON_DMACTL::zeroed().write(bar, &E::ID); } =20 /// Wait for memory scrubbing to complete. @@ -431,8 +400,8 @@ pub(crate) fn reset(&self, bar: &Bar0) -> Result { self.hal.select_core(self, bar)?; self.reset_wait_mem_scrubbing(bar)?; =20 - regs::NV_PFALCON_FALCON_RM::default() - .set_value(regs::NV_PMC_BOOT_0::read(bar).into()) + regs::NV_PFALCON_FALCON_RM::zeroed() + .set_value(regs::NV_PMC_BOOT_0::read(bar).as_raw()) .write(bar, &E::ID); =20 Ok(()) @@ -495,28 +464,26 @@ fn dma_wr>( =20 // Set up the base source DMA address. =20 - regs::NV_PFALCON_FALCON_DMATRFBASE::default() + regs::NV_PFALCON_FALCON_DMATRFBASE::zeroed() // 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) + regs::NV_PFALCON_FALCON_DMATRFBASE1::zeroed() + .try_set_base(dma_start >> 40)? .write(bar, &E::ID); =20 - let cmd =3D regs::NV_PFALCON_FALCON_DMATRFCMD::default() + let cmd =3D regs::NV_PFALCON_FALCON_DMATRFCMD::zeroed() .set_size(DmaTrfCmdSize::Size256B) .set_imem(target_mem =3D=3D FalconMem::Imem) - .set_sec(if sec { 1 } else { 0 }); + .set_sec(sec); =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) + regs::NV_PFALCON_FALCON_DMATRFMOFFS::zeroed() + .try_set_offs(load_offsets.dst_start + pos)? .write(bar, &E::ID); - regs::NV_PFALCON_FALCON_DMATRFFBOFFS::default() + regs::NV_PFALCON_FALCON_DMATRFFBOFFS::zeroed() .set_offs(src_start + pos) .write(bar, &E::ID); cmd.write(bar, &E::ID); @@ -549,7 +516,7 @@ pub(crate) fn dma_load>= (&self, bar: &Bar0, fw: &F) self.hal.program_brom(self, bar, &fw.brom_params())?; =20 // Set `BootVec` to start of non-secure code. - regs::NV_PFALCON_FALCON_BOOTVEC::default() + regs::NV_PFALCON_FALCON_BOOTVEC::zeroed() .set_value(fw.boot_addr()) .write(bar, &E::ID); =20 @@ -572,10 +539,10 @@ pub(crate) fn wait_till_halted(&self, bar: &Bar0) -> = Result<()> { /// 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() + true =3D> regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::zeroed() .set_startcpu(true) .write(bar, &E::ID), - false =3D> regs::NV_PFALCON_FALCON_CPUCTL::default() + false =3D> regs::NV_PFALCON_FALCON_CPUCTL::zeroed() .set_startcpu(true) .write(bar, &E::ID), } @@ -586,13 +553,13 @@ 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() + regs::NV_PFALCON_FALCON_MAILBOX0::zeroed() .set_value(mbox0) .write(bar, &E::ID); } =20 if let Some(mbox1) =3D mbox1 { - regs::NV_PFALCON_FALCON_MAILBOX1::default() + regs::NV_PFALCON_FALCON_MAILBOX1::zeroed() .set_value(mbox1) .write(bar, &E::ID); } @@ -657,7 +624,7 @@ pub(crate) fn is_riscv_active(&self, bar: &Bar0) -> boo= l { =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() + regs::NV_PFALCON_FALCON_OS::zeroed() .set_value(app_version) .write(bar, &E::ID); } diff --git a/drivers/gpu/nova-core/falcon/gsp.rs b/drivers/gpu/nova-core/fa= lcon/gsp.rs index 67edef3636c1..32b28e22c741 100644 --- a/drivers/gpu/nova-core/falcon/gsp.rs +++ b/drivers/gpu/nova-core/falcon/gsp.rs @@ -1,7 +1,10 @@ // SPDX-License-Identifier: GPL-2.0 =20 use kernel::{ - io::poll::read_poll_timeout, + io::{ + poll::read_poll_timeout, + register::RegisterBase, // + }, prelude::*, time::Delta, // }; @@ -14,10 +17,7 @@ PFalcon2Base, PFalconBase, // }, - regs::{ - self, - macros::RegisterBase, // - }, + regs, }; =20 /// Type specifying the `Gsp` falcon engine. Cannot be instantiated. @@ -39,7 +39,7 @@ 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() + regs::NV_PFALCON_FALCON_IRQSCLR::zeroed() .set_swgen0(true) .write(bar, &Gsp::ID); } diff --git a/drivers/gpu/nova-core/falcon/hal/ga102.rs b/drivers/gpu/nova-c= ore/falcon/hal/ga102.rs index 69a7a95cac16..c567d7d81f2a 100644 --- a/drivers/gpu/nova-core/falcon/hal/ga102.rs +++ b/drivers/gpu/nova-core/falcon/hal/ga102.rs @@ -26,7 +26,7 @@ fn select_core_ga102(bar: &Bar0) -> Result { let bcr_ctrl =3D regs::NV_PRISCV_RISCV_BCR_CTRL::read(bar, &E::ID); if bcr_ctrl.core_select() !=3D PeregrineCoreSelect::Falcon { - regs::NV_PRISCV_RISCV_BCR_CTRL::default() + regs::NV_PRISCV_RISCV_BCR_CTRL::zeroed() .set_core_select(PeregrineCoreSelect::Falcon) .write(bar, &E::ID); =20 @@ -59,7 +59,7 @@ 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 { + let reg_fuse_version: u16 =3D if engine_id_mask & 0x0001 !=3D 0 { regs::NV_FUSE_OPT_FPF_SEC2_UCODE1_VERSION::read(bar, ucode_idx).da= ta() } else if engine_id_mask & 0x0004 !=3D 0 { regs::NV_FUSE_OPT_FPF_NVDEC_UCODE1_VERSION::read(bar, ucode_idx).d= ata() @@ -68,23 +68,24 @@ fn signature_reg_fuse_version_ga102( } else { dev_err!(dev, "unexpected engine_id_mask {:#x}", 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() + regs::NV_PFALCON2_FALCON_BROM_PARAADDR::zeroed() .set_value(params.pkc_data_offset) .write(bar, &E::ID, 0); - regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::default() + regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::zeroed() .set_value(u32::from(params.engine_id_mask)) .write(bar, &E::ID); - regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::default() + regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::zeroed() .set_ucode_id(params.ucode_id) .write(bar, &E::ID); - regs::NV_PFALCON2_FALCON_MOD_SEL::default() + regs::NV_PFALCON2_FALCON_MOD_SEL::zeroed() .set_algo(FalconModSelAlgo::Rsa3k) .write(bar, &E::ID); =20 diff --git a/drivers/gpu/nova-core/falcon/sec2.rs b/drivers/gpu/nova-core/f= alcon/sec2.rs index b57d362e576a..5d836e2d17dd 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. diff --git a/drivers/gpu/nova-core/fb/hal/ga100.rs b/drivers/gpu/nova-core/= fb/hal/ga100.rs index e0acc41aa7cd..efdb602d949d 100644 --- a/drivers/gpu/nova-core/fb/hal/ga100.rs +++ b/drivers/gpu/nova-core/fb/hal/ga100.rs @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 =20 -use kernel::prelude::*; +use kernel::{ + num::Bounded, + prelude::*, // +}; =20 use crate::{ driver::Bar0, @@ -19,12 +22,14 @@ pub(super) fn read_sysmem_flush_page_ga100(bar: &Bar0) = -> u64 { } =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) + regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR_HI::zeroed() + .set_adr_63_40( + Bounded::::from(addr) + .shr::() + .cast(), + ) .write(bar); - regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default() + regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::zeroed() // 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) diff --git a/drivers/gpu/nova-core/fb/hal/tu102.rs b/drivers/gpu/nova-core/= fb/hal/tu102.rs index eec984f4e816..37da571e9962 100644 --- a/drivers/gpu/nova-core/fb/hal/tu102.rs +++ b/drivers/gpu/nova-core/fb/hal/tu102.rs @@ -21,7 +21,7 @@ pub(super) fn write_sysmem_flush_page_gm107(bar: &Bar0, a= ddr: u64) -> Result { u32::try_from(addr >> FLUSH_SYSMEM_ADDR_SHIFT) .map_err(|_| EINVAL) .map(|addr| { - regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::default() + regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::zeroed() .set_adr_39_08(addr) .write(bar) }) diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs index 629c9d2dc994..e42b1aec95b4 100644 --- a/drivers/gpu/nova-core/gpu.rs +++ b/drivers/gpu/nova-core/gpu.rs @@ -4,6 +4,7 @@ device, devres::Devres, fmt, + num::Bounded, pci, prelude::*, sync::Arc, // @@ -122,24 +123,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 +144,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(), } } } diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/= cmdq.rs index 3991ccc0c10f..0a7b00fc399e 100644 --- a/drivers/gpu/nova-core/gsp/cmdq.rs +++ b/drivers/gpu/nova-core/gsp/cmdq.rs @@ -475,8 +475,8 @@ 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) + regs::NV_PGSP_QUEUE_HEAD::zeroed() + .set_address(0u32) .write(bar); } =20 diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs index 82cc6c0790e5..dbc6fa121ef9 100644 --- a/drivers/gpu/nova-core/regs.rs +++ b/drivers/gpu/nova-core/regs.rs @@ -1,12 +1,5 @@ // 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::prelude::*; =20 use crate::{ @@ -29,20 +22,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". @@ -50,13 +87,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 { @@ -89,35 +119,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. @@ -134,10 +179,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 { @@ -145,10 +186,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. /// @@ -167,29 +204,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. @@ -198,16 +236,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. @@ -218,10 +257,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. @@ -238,48 +281,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; -}); + NV_FUSE_OPT_FPF_GSP_UCODE1_VERSION[NV_FUSE_OPT_FPF_SIZE] @ 0x008241c0 { + 15:0 data; + } +} =20 // PFALCON =20 -register!(NV_PFALCON_FALCON_IRQSCLR @ PFalconBase[0x00000004] { - 4:4 halt as bool; - 6:6 swgen0 as bool; -}); +nv_reg! { + NV_PFALCON_FALCON_IRQSCLR @ PFalconBase + 0x00000004 { + 4:4 halt =3D> bool; + 6:6 swgen0 =3D> bool; + } =20 -register!(NV_PFALCON_FALCON_MAILBOX0 @ PFalconBase[0x00000040] { - 31:0 value as u32; -}); + NV_PFALCON_FALCON_MAILBOX0 @ PFalconBase + 0x00000040 { + 31:0 value =3D> u32; + } =20 -register!(NV_PFALCON_FALCON_MAILBOX1 @ PFalconBase[0x00000044] { - 31:0 value as u32; -}); + NV_PFALCON_FALCON_MAILBOX1 @ PFalconBase + 0x00000044 { + 31:0 value =3D> u32; + } =20 -// 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; -}); + /// Used to store version information about the firmware running + /// on the Falcon processor. + NV_PFALCON_FALCON_OS @ PFalconBase + 0x00000080 { + 31:0 value =3D> u32; + } =20 -register!(NV_PFALCON_FALCON_RM @ PFalconBase[0x00000084] { - 31:0 value as u32; -}); + NV_PFALCON_FALCON_RM @ PFalconBase + 0x00000084 { + 31:0 value =3D> u32; + } =20 -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+)"; -}); + 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_HWCFG2 { /// Returns `true` if memory scrubbing is completed. @@ -288,108 +410,42 @@ pub(crate) fn mem_scrubbing_done(self) -> bool { } } =20 -register!(NV_PFALCON_FALCON_CPUCTL @ PFalconBase[0x00000100] { - 1:1 startcpu as bool; - 4:4 halted as bool; - 6:6 alias_en as bool; -}); - -register!(NV_PFALCON_FALCON_BOOTVEC @ PFalconBase[0x00000104] { - 31:0 value as u32; -}); - -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; -}); - -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; -}); - -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; -}); - -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; -}); - /* 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 -register!(NV_PRISCV_RISCV_CPUCTL @ PFalcon2Base[0x00000388] { - 0:0 halted as bool; - 7:7 active_stat as bool; -}); +nv_reg! { + NV_PRISCV_RISCV_CPUCTL @ PFalcon2Base + 0x00000388 { + 0:0 halted =3D> bool; + 7:7 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_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. @@ -397,15 +453,19 @@ pub(crate) fn mem_scrubbing_done(self) -> bool { 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.52.0