From nobody Sat Feb 7 23:10:59 2026 Received: from PH7PR06CU001.outbound.protection.outlook.com (mail-westus3azon11010051.outbound.protection.outlook.com [52.101.201.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9B16F2FFDF7; Thu, 29 Jan 2026 13:32:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.201.51 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693545; cv=fail; b=A05I9kG1QYWWGbuc2fxF9YXMr/duSCXZcDCU5BHSXTs5M0A15AcgtppgEfY9bX+oSvJ1Sf6IHtvfH4uQQeki+PUch19y6pqKQs4G5HV31tCM4Hbc8tq86FzY4atvagVEYWFsbMdq+FdwXbcvfTVbXhKYf3313+JYoQBqWHHXyXw= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693545; c=relaxed/simple; bh=X4lDluXAUVw2Jbvj0d4PEL7Nz0HYbGEfpGwR91vlZEM=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=Zp5RBu1FHs0EPeP21WqYY+u1fRCUInQxr21IKqR8ttEk3OMFJIMmAyYEJ3zxAAhUKNWhfSixeES1YW5bl84LAyjbXoa9qeEjTdGqQgVxwdq4UcjyKL60p7UceXjfMZrfUhs7mab3miFSxuPsuNrdaTza/YCW/zJBC/zprXp6ptc= 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=d2XFCggs; arc=fail smtp.client-ip=52.101.201.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="d2XFCggs" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=MeDre/0GBq0ljJuQSsEPoi8OMzelTVv9CdfY/263BX8PtgnJydddhZpoqy4KERz8slBjZkpE1cr2STRdP7S25xsjKXLDV1xaWmLkx2GJQqWUCukMXaTRm6Ve4gAHWtJqwE/FIRGFFeavFLRb8d71MBdX3bjhLqsuemZav6syyS9IVAIDl2yskrP388gl2gZn7Dy9H/I+Re5vVoPfDw9uMnecIDVsH1C8Mm4LPOl+pbcGVRgIBu5+sIFRRIvH2LC/cUI6735XLGLa2UNQpthNnjCVq5iQVnc+mbbm1fwVm9U1fQdkm5AGtd2g3Kt7FnLJA3O1DuRyyq9fZcdkckiWBw== 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=tF4Dv14QeTk6cfVVrVAx1HCjOJTQUtO3tlA6prdEAmHA9g+Exiq5Px9zuivS6hwP1w2Y6rnHkZj/N4OuQosqCgrrhqvWbtQodLAilgZ4lcMfOWEKqK4QMDnr8Si4YZZr1ep8//OwoTD4d2ydbogMezUBRzvgu7eXkGLP+bmnUHsIbve2JfGk3cMQGAz2gTzq7A6k6YlJbT6rpQj03UiKg2KVA3/tK3PVRItnDE7agpJgqzGs5zOsIf6fvasovdnRRtN5b+vgBz6LMOwwj4YHTnezOnGncbvq96Fa3ahqb/3tMM2pBajx3z3Lgtto6afsQuoQaxaIPX/s8iFK+PgRXw== 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=d2XFCggsKDsB3NJkSBr9UZsn4mXjninRyc7YJzaK5OoUVXVVNmJJ6ckXBKFtZStzpzZtAEOSo1UWr/8oWGihwFiqoeRVa7wh6R5tHFlgrWl7EQBbcAOHGz/OzHB+SolkAA9c7aGIp7TyftHOykEvggk3IdOQFEu/8FkB7ws1y4LavP6JNLRdyI/3LoTEQjA7RQn2xmGmYgIjr0wycQhAzp+tPMdemdnTp2K08M3r8z9SCmlN71jMsaY37u+HuWke2wQ+MFGxlZTfMgQAc53FhUL3KUZz8I9DvxEHorjSgNkPCt/kAPPnDZ5FgO8jHoxwhhOEWEX/eCSQiU1oITeumw== 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 DS0PR12MB7770.namprd12.prod.outlook.com (2603:10b6:8:138::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.15; Thu, 29 Jan 2026 13:32:16 +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; Thu, 29 Jan 2026 13:32:16 +0000 From: Alexandre Courbot Date: Thu, 29 Jan 2026 22:32:01 +0900 Subject: [PATCH v5 1/7] rust: enable the `generic_arg_infer` feature Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260129-register-v5-1-c4587c902514@nvidia.com> References: <20260129-register-v5-0-c4587c902514@nvidia.com> In-Reply-To: <20260129-register-v5-0-c4587c902514@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: TYCP286CA0257.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:455::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_|DS0PR12MB7770:EE_ X-MS-Office365-Filtering-Correlation-Id: 37416b9b-480e-41d3-5bc9-08de5f3ad168 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|376014|7416014|1800799024|366016|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?NjlOSEwvNTFTd1AyUGpyRDZ3cXpQZks0Y0paa2VCWEl6UVhRSE5acnlnekps?= =?utf-8?B?ODRKdHNCdS9rY0s0cDZiQ01BcG4wS0VWVDhubU4vaHplRGZhUndqZ3NPRHNJ?= =?utf-8?B?UWRlMjNwalRsc2VDcFFqSzMrQlpUdmxZMDhFWktMUTUyclZDcXZNOGh3NFgv?= =?utf-8?B?YlBRUTJVeWx5Q29kbTZ0a2lhZDNndkdzOFpWUXdXd1pKemRORFZYTmtaUTRE?= =?utf-8?B?aWs4S0lRUE1FWEI1OFg2cXRxK1A0bUhPQlY0cHZsWXIvTXR6SVl3V0pjYXNI?= =?utf-8?B?VS80WmEyK082U3BtRFlvWG5PdUFFNFpOOGFhdW9UVTE4WktzaGY1ZGo5NXIy?= =?utf-8?B?QlhaUDFJd1pDWmF5a25yVEI4cWlJallLWlF0WmhwYWxOaEVYNXd1QzVvbTU5?= =?utf-8?B?WTcwOG9ZT2xVQnFxaWVtQmlFcGFRTHo0djh6cFl5bDJDelVELzZYcEpmV1ky?= =?utf-8?B?K1lubE1sVmlMZXp6dTYyeFF0WlN3RWpHT3MyNnJ4VFlET3cwdUsybHJkZWd0?= =?utf-8?B?TkNVSTlkYjRoQ1k0UE5ZY1pVSCt0RWFXTUNOdUNZY2tGcEMraUNUOXltSjhn?= =?utf-8?B?T0lhWHVoWFdhVm5MZzBKWjRZY1ZDbTZtcW5mSU4weFBhaVMxYnJWSlVUZS9U?= =?utf-8?B?bjR4cW1GL1dUdDBvTjQzR3BsdFNIaGg2OGJ0bE42S0NYOVVuWnJJM0NoR25O?= =?utf-8?B?dkQ1WXVZN1d0VjhpMTFTMW01Q2xlSHNUTGZ1cnJBc1ZmZlNDclFNa3pLVE9Z?= =?utf-8?B?NFhCQi95aU9hakNuNk9DMXJkK29MZmhTa0haL21wZHg5VXBITndNc1BBWXp4?= =?utf-8?B?NVl6MmJudGFOQzA0L0xhU1kveGxRTTk5ZFBoZWlieEFOSHVCWnRLVUUzTkZT?= =?utf-8?B?Z2cvT2RzTndyVjZJUDN1SDN3M1NVZUd2UVJqOTZtdlJER2RhY05oWnlDcjd5?= =?utf-8?B?dDV4MDhCT04vN1BNQ2ozdVErNXdTNXdRN3ZsZTg3bHQwQmovSmRvR1Z0d29o?= =?utf-8?B?SUg2WWRoRXNoUVZJLzg1WElKc0pGL0I0ZG1hTTdnMXlUYnkzODMvM3M0dlJy?= =?utf-8?B?aU02RWdaWXVyUS8xeXBSa0dRR3NzalppY2V0Zm1aSk11dm1UWEpIVWZvV0VO?= =?utf-8?B?K2JUNGpPRXZZSms2ckxYeDRqYUk4dnlZYTlCTHhvbjB0YWtmNVdCMmlWYmpE?= =?utf-8?B?dDlwVEFxN0haeFRkdjlJWXhmZGpLeDRlcmlQb2tlQktVeDBkL1BHQ1pvV2NM?= =?utf-8?B?R3I3ZU02RlZQZUtmc3IxWGhkTzhYVS92YWFNTHp1S0tzU0p0dGlJRUNKSlZk?= =?utf-8?B?MWJ4VzZobCtudVhCdFVvWmkrMDhwaW45U01sNWxZMk9GSkVUNUV6MWs4K2tY?= =?utf-8?B?bUwrWUE2cysxM0NjQkJlNWxZNzhOTTNSb3doSGNYMDgycm5tcndaakh2aURz?= =?utf-8?B?Ly8zU3VpR0dJWEpDNG5STlJ0THZYTitKV2lGcm5aUDdPR2N0VXkyaWxpL0I0?= =?utf-8?B?ZWFPN0tnZnkxZEVXRkthNUp6Ylp1SXdmMWFFcEtqbTc1Z3ptODJoSmJOWHVm?= =?utf-8?B?OW80UmFBeGh6SGpZakJsOVlSc2lVVEVlSmlrOW5sMzEvbVJKWEY1OWNwYjlp?= =?utf-8?B?S1k5ZVQxOEZ2ZE9Qd1NDRnVVZjNTRTcxVXpBUGlrYU16aXhiVTgvQ29jVTl3?= =?utf-8?B?ZUVMbGxNT0tzTXFPOU9RcDBZdERUSHFqZlcwYS9RU05VYVFybHdkSC9jWDR0?= =?utf-8?B?QTFQZTFoaFppci9ONmtVNW1laVErNUc3QUlIYWxwRkJERis4dVd1VmVEZWRm?= =?utf-8?B?dnNBN3BUNXVVNXhyNVpUYVpFdU5NVU45VWNscUpmVzdZRkw4ME5BNDllc25N?= =?utf-8?B?UWtWRk4rMVRkYU5MUGw5STk3VnJ6cjJUN3EvcVNqTVJtY29qN0VNM0ZmWm41?= =?utf-8?B?Y1cvSWY1c3YwVk42Z0ExMCtaOTBibHZxcnJrOFlZT09CY3JOMjBmeHRQa3Rv?= =?utf-8?B?Ti9XYWpTdW5KaUk0cm9mUG4zZE8wSkdQSkVOTlFoMXlnOGErVlFGdFlZaHBj?= =?utf-8?B?STBvem9udTNUT3JsR3V1UUd1Z2lMdSsxYy9XUkIzODdXTy9taXE5VmhyU21N?= =?utf-8?B?dHhvdmh4dGZWbG5RbUY3S1lsVEcySno4RW5idmNrSlFEODJoVUdBTlZ5cjkx?= =?utf-8?B?dGc9PQ==?= 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)(10070799003)(376014)(7416014)(1800799024)(366016)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?UUdJcDBPUGNaWWwwTzg0MUFZQlQ5Q3B1eU05Z1hyamdwT1cydExNaThRQjdp?= =?utf-8?B?bWJvcFFRN0ZBK2J5TDdsVU1ZNVo5QUpYc000MTdFbVZkangzbEpBbFdVYWdU?= =?utf-8?B?TlhoZlFtQjJuY0xuNzJPVUt6VEpqTFhYcE1mVDhwcGZDL3MrL1hZeFZhWmhu?= =?utf-8?B?QlQrQTduMmdlWUh6RGg1cS9UMGdENWptYXhRNXRodlRyOXQ5aFhzOHJ2dmFI?= =?utf-8?B?MFhKZVBmd3hKNGRZUWtjTmJEN09heElMNm1UakVDZzE2b3BiSUYzS1lhOHNw?= =?utf-8?B?dFlLcUhnMS85MXNhUEk1RWF0R3Y4djNXbHNISlFNNTV4aXArR0JIbHl4bGRJ?= =?utf-8?B?Q3NOSGxGbzRkb3dzOVc1aThFN0dhN29XUUtPTjFuK05uODlRTWUyTFFxMnZl?= =?utf-8?B?Vkhaa3VKRzZlZG94aHVmaGYrd25waUFUZGhDNkx0dmw4dm52ZnJmQTI3T3Jo?= =?utf-8?B?T3NXdzI0SUpYcmdZYzFydldQOTI1NkxnOWFIeWFVZXVYNTdXSE1xU3VMTURS?= =?utf-8?B?dGVqRTlHcE5wcHRlUm41bm5EY1RrbUw4UU9OaDMrK1kyUk92bHNZWlcrdXZk?= =?utf-8?B?WkUyai9Gbk93aE9WYmxPb0FrUGJEVUJLbC83cGppT2tKVVpGa21Kd21FcUE2?= =?utf-8?B?SXY4SktHK2hPVE9yVG9VMmxUL3g5dWJSVlgxVlNFdGdkR2JZNVVMRXJQZFRr?= =?utf-8?B?TXVmMTVhbWMwdnNsUWJuMkRUTWJueFc5TkNSUTljZDJEcHJZaDFwYnJoWlFC?= =?utf-8?B?MWdNcXRQYTZaa1oyZTZCajFhRFp5cnRzZEVXZTB6bE9FeWQvbjJ1UC9NMDBW?= =?utf-8?B?aDFOQ0FwRFo4VFFNazNWYVExcnliNXhLQ2dHck43NmZFZU1abll4Szh4MGZa?= =?utf-8?B?R3pXUEhmRlZrOWdYSllZR2ZuTVR3VFBkYncyKzRWNG0xZUNtSHh0RmxRa2NN?= =?utf-8?B?MVAwdi9vQ0JHUVc1OFlVM3VmSTR3aWxTVEZ4bzhXdzREeFdTbjIyaU8yU2xH?= =?utf-8?B?Y2FJRkRDNEc4OTRramNoUHAxbWEwcURFaXh5dnR3dlVyOUkzSkhLbjNXRjlB?= =?utf-8?B?bk1POElYQnN0TmczUVJCZEdwM0EwcUlGcC8vdDBId0JoQmpONnEzWDYzMnh0?= =?utf-8?B?eWFaMm8wTTcvTmxjK2VmNHBNNzhnUFlRQlZ2Zmo1dkdHcnJmNW53TDh0Vyty?= =?utf-8?B?a3lHbVA2aXFxVHdsRC83M2dNb0M1Tkl3TGY2OWlSc25nb01rMXRDa2I4YTl4?= =?utf-8?B?UGtlWVVQTEV1YTlpYys2elJtNnRZSnUxUDJGd3RKMnJUdmZ1WlgxL1JEaWNS?= =?utf-8?B?M1RzZDRnT0crV3MydTIyZXJPYmNGWFd0L3pZZnRXUkJpQms1dlJSWlJJNUsw?= =?utf-8?B?Z2NQVzJKSFNoMXFUL0RBVmpscFBPMVYyOUp3dmJaSkF5WWV0VGptSWh5WUdl?= =?utf-8?B?V2toQ2R1RHFVZFZVNXllbThpaTlQV0V1ZjB2b3U4Sk9kUTlDWmpvYzBFQ2ZL?= =?utf-8?B?T3Z4QVkvcEl1YkNCUUkvWWZsaGZuaEFlUncyMWp4NFVwTUFIN095U0JUdUFK?= =?utf-8?B?TDN2MUZpU0h5Y0dkcS9wK2VUSjRWTDZuVkJqWkw0OHFkUG1wTVVmYnVjcnRx?= =?utf-8?B?djc2RXl2bmYyQXdyc0hCMDBlWGQvQ0xpZUhHclY5V3M1cUdVSnJDQitXMjUy?= =?utf-8?B?YjlTd1NtNk5jTWdaNUhNTWdDWHFKZyttdmlhTW1Nczh6b0wxT1k1SUVLaGsr?= =?utf-8?B?SXQwUm8xeWk2Snl4WUxiQmJUZ1d5dWIyM0xvWW94UnFpVGgxSVU1RE95MS9R?= =?utf-8?B?aHFOeDZDRWMwUVN3RERRTzNsS1RCQWZ2QUxZSGFlM2VqNnRsMUVxZG12TUhk?= =?utf-8?B?czBJSHczUTNRZ1JINUJWclFHNUk5MXJ3V2RyU2t6R2JnbkpNbURPRVNUTnNS?= =?utf-8?B?dDhvWVVlNTh5NnZkSm9EdWRWTS9Ycm9GYzRJVGorTnRuYWRMWDRqTUxSaGQw?= =?utf-8?B?WTlPQUdGMFUzYVl0Tmd6K1Fhd2JFb3NBME1ScWlZRWxBck9lV2x6dGF5TXFJ?= =?utf-8?B?SmxMRW91elpJWnh6UlR3L3BldlJkcDV5WkJZMmtPbWplL1VRdWlOVzRDRk1H?= =?utf-8?B?S2V4SGxSUTdUQnpTVTJzeDhPd2cwZXVoTTY0QWV3VElyd3ZDdFBrejhXa3Jj?= =?utf-8?B?bEhuam1aMm45Z1JyTXZzYngrS2N5YXpsQkZqdmRxeHFLRzdNT25PeDh2ZDZC?= =?utf-8?B?MTQxbElIRDNhaExsd3ozZXZoV2ZneW83OFMreEw1RmdhYjZFQVBMUlhqY1Bx?= =?utf-8?B?aEZONGluVjRjSjZUUXVmVkI5bE9TRXhzNm9HSWNWQ2tWQWI5c0Iyd1g2NEdY?= =?utf-8?Q?ek9HOICgI2PEVarQsebOVn5en4UdCssFTgaYE81VPWlpq?= X-MS-Exchange-AntiSpam-MessageData-1: dKHlKK0EvNXkuQ== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 37416b9b-480e-41d3-5bc9-08de5f3ad168 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Jan 2026 13:32:16.3913 (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: D4da8Celq3B8QR98rowO6Vcbe6WJcj3BT3yL5V4+n3KtqHArjBgbBm73LE8pwkwZIcj00XuAY1Jp7KYlqTPByg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS0PR12MB7770 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 23:10:59 2026 Received: from BYAPR05CU005.outbound.protection.outlook.com (mail-westusazon11010001.outbound.protection.outlook.com [52.101.85.1]) (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 41D582F360A; Thu, 29 Jan 2026 13:32:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.85.1 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693551; cv=fail; b=NIw/OTLCA+wjB29K0Qw39B1r8rU2DfNh5WF3ezcI0BsUSHcuDgeSBT6D1sASWZl9StjxY35iHF2Q3CBM06x+rgQbBJdUZj1UB4AvyE/Xdd6CQstz7FNLrfZ+qFpY/SZZ9fO6s9jM914Si4H5o0nomUwg+FQ0JbN9mNAIx4d9ZPg= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693551; c=relaxed/simple; bh=ZhioN8KBZT/wvf75jeqP8lquVwLRvcEAC56oZUbOobc=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=tlTcj3Ewp6UqVF0PyOO2cC8TjQuNJvjygQWp48VZuWy1KXrsiMwhhBW2K4fE4eP8c/7hXiofRPqrKUd4r0KRrw0oByDxaIIR1rpSyPN3Wxd5EOQLf1MoxhC3UiAeNc2kf33g3FMvEBtRN8++e0gs1mRBSk9Zr4bxhAV3DXyofpA= 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=AKZwbN/a; arc=fail smtp.client-ip=52.101.85.1 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="AKZwbN/a" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=XTxHg6cJoAAHq//i8moT+ZVL3kdAuOXUu8egqQIasoOGoLAlvfJ7ZiEhuMcuEg1g3b8uOyLKVPqb96ucY24hgzHd3miwTL3H21k/jGFJ1eW/OGRScVIlG4drX4JjV31v3QDt4ClRwhS3WrZXP4yIK3jrt+rmvz7X9RY3Gs8QxOAsI4HRu6RhniizILmJAS+8TVSKECSbUbUbKb6p0spgPnNLsbodzQEDTFtG82ceUdi24XD05fi+9NVsQnknI0PYB3IuE3u/UsucrWW0NiENb+sO6+sc6BR8GyBrcfw40ykAAkVoT/kWrwfXsioOmx5V+hOFseoit4gmn8xCuBXh7w== 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=Wpwz2N1ah5rqXmin1HxtL8btAVChqiLbdKUlvOyXBsA=; b=sE1LcXyabD5GL4owjkxS7J2IhQdnCftoN66ydejejQ+y7FHtZM/7b47ce5uqRCwp9PKtb2xDNyhngn63IAFor8vjiZwkV5Po2MSsX5KbAeYOPk+mqz6Tw8+eWUgHpWWQfuuS9WHZfnUSRhQ0lhwcFpp5NXXX/xizFs6OC+fiqlQvjcpNaxNbBHfoB4xvOMZoTUicH2MSGlVp9gk0YCmwRcew14tqny9c5SKZrtIXKgNoivZpd9A61Ix9/I9sjhE5g8CeDNEMLI88uI8UdHkivyBh0+c9PpH77mD0A8+PS5HpNiSC6Jp8axIfYRxnyyRSdJPKN4II6GdJ9v8bPP94eg== 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=Wpwz2N1ah5rqXmin1HxtL8btAVChqiLbdKUlvOyXBsA=; b=AKZwbN/aLr2uEg7BEnkDTLqnJcoYxsQIMOycGZpElLr1EB+BTJ/Pd4JWUgePdEEFspe9AsNCjoCiHtHoxlgctlygmifJ1nEoBi6l1lVS8ySrU2A0NWsoAxp5XdJUZ7yQ+jTG2LyTCogM03OGCxd0w/GWn2uzJJ5XdiRfFntwZNXpU+fHvaCmESJ6qFvQHN5x3g+/JXNksJbosZ4hp6eygI15czxvuM3Y6lHGyVxmf6oWkBMN581NKhcsAy7tQtp2pbs0i1/GfHPLaSu8FM8k3f2TwW5gVElwnFA+FOThhSFZ54U4GakJ5s0jcAYnD/c6HdnYGBRVypkJmT/7OBgDJQ== 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 DS0PR12MB7770.namprd12.prod.outlook.com (2603:10b6:8:138::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.15; Thu, 29 Jan 2026 13:32:25 +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; Thu, 29 Jan 2026 13:32:20 +0000 From: Alexandre Courbot Date: Thu, 29 Jan 2026 22:32:02 +0900 Subject: [PATCH v5 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: <20260129-register-v5-2-c4587c902514@nvidia.com> References: <20260129-register-v5-0-c4587c902514@nvidia.com> In-Reply-To: <20260129-register-v5-0-c4587c902514@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: TY4P286CA0009.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:26d::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_|DS0PR12MB7770:EE_ X-MS-Office365-Filtering-Correlation-Id: 497ad24f-8eb1-4bbe-049e-08de5f3ad3dd X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|376014|7416014|1800799024|366016|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?SlMwSVhNemd3WkJJZXNnM2xCSUNmS1MvenAxQ0Q2bVlxZEdJMWxoai8zbjVq?= =?utf-8?B?bFdjOXJRdjg5MWxCejk2TzhUeWVQWWxmMXlDMVhOcWVXK2Jac0dwdFRWVmVn?= =?utf-8?B?aml2THExbDZqaXRtS3NaYTZmUHJqR1VtMVFmakcxR3Y3MEQ1MXdycjVzL2E0?= =?utf-8?B?MWpFZTM0MlJpQWpkRGEzcmJJNVphRWJoZjZ6d01PSW5pUmFmcm03citqcnJ0?= =?utf-8?B?eVRsazhMejIxQmlzM1l6OTRaQzJPMHNxWm5ldm1vTStiYm5ETjk3a1BFcDdG?= =?utf-8?B?c1VOZ3JraGREc0M3cGg4QmIzQkdzN21UYURVWFdXWGJFejdiNDdJUUQzeTJL?= =?utf-8?B?c0JmY0UyQStuK1o4cTRWYndpcm45ZTA0cTJ2czRXcWUzcFN5T0wvbU96Uzh2?= =?utf-8?B?RVU4QVNNMENDRktDNGlrTXJaNGVTRE1VNXJFM0hNbk16a29LQkEyMFJaYUZr?= =?utf-8?B?bkFUelpNZklzN1RrekNkTVBPeUQyS0dLT2orWFMwMjdKOXNCRGwvZ3FWYjVN?= =?utf-8?B?dVhzSzFmalZLNTdqbVFmaURiQXZLQVQwdFdKWmUrM01LNS84NjZjNmtBQVBC?= =?utf-8?B?RVpQS1VmM3YwakIvcmFKVmhFQVdMSzZUekhZOWdMWGxOQ2hZUUtxZnB2YXAw?= =?utf-8?B?UjB6d1cwWnhXWTJCM3NkWGszbU5zaUJvbVlMeDJZU3M0Um9qRXVDRUV0ZUJz?= =?utf-8?B?dUZWY25vcURsWUlHMzVSTmZrNUlPVWFXVlRFT3UvQXdRcFJxL2s2eVpWQW4x?= =?utf-8?B?VzlvNG1YWS9SZU5MQkNOWC9TTEpQT3d5aVZkNnJhMXd1aTkxRi9JZ3JWQTZR?= =?utf-8?B?ZW80NnFhaGhlay9tMHdjbVVjdnF4TWI1UGNJL1RXUWhGWEVDOUs2V2crL3ds?= =?utf-8?B?SVJ4bmJ0M2VtTDFiR0k1Qmk0azB3M0x4c2t3TVRObnpFTmxpODNTUUYxVmRY?= =?utf-8?B?cGZES0xONXB4dUk4WW1kMjE5NXp4WU9ZZEpFWlVZUzZyaHdjeTFZWjJubE9a?= =?utf-8?B?UmhEdWJFR3JaVHhoa2JWdzNQOUJTUENNdktUWEVMS1pGTzQwVXVSbGs0LzVi?= =?utf-8?B?OVFZTE5DeUEzRnVEZHFmZ0ZYa29MYnFycnQrQ2k0TlU1T0RjcVd0ZkFDUTg5?= =?utf-8?B?YTgrOXRWNVhCcVBQV2dTS3BkK3pWTnFGdFp5RGdaeURjRUNNc28zRlFZS29o?= =?utf-8?B?YjFuNUNiSkR6dWw2MU55SGNheHR6b1BsT1N5bkpWY2xONDRhV080SmorVHJl?= =?utf-8?B?b0NWWU16V2E0M2hBT2JaQnRodXJNSFFYaWw5dDQ5bU5DRmVIWi9Va0NtSnAw?= =?utf-8?B?b1B6VG05MjFINmU3YzdvYkV4MHpBZDRkbitsSURPeWxSQjhtOC9zNm5DUDd2?= =?utf-8?B?T3ZwM0kwUC9OTkZ3ZTJWU2k0WEMxaGs2ZWJWOXgzeGZOVUprZHJXVGxoUlVC?= =?utf-8?B?dk8rY1ZtNi80NDJaVWhEcVdzMW5aeURZU0RiamZ5OHM1WEdTNFFmZEFldCtp?= =?utf-8?B?cStPeXpMSDYwV1NiWmcxU1JGR1l3d05GNTQrQTdieVdzdEZ0bE1nSGtrbU5C?= =?utf-8?B?aHl0YU1DdUQvcXBQT0dIeFlsb0oyNGw2R3E3RjljSDZ5blNENjBBdkpaRWox?= =?utf-8?B?Njg5UTRtWmZuZkx3M1BWVWFWOW5JWUowNG1tSXVLeU00Mnp3WkEzSnR1RVl6?= =?utf-8?B?ek5ScVpvTkR2bE9RS1BMSEo4dGVZM2NyZlVkYVlYNnZ2STNkRTh6bkh6VEgy?= =?utf-8?B?RmhtY215VE1BTnQrSWlQVVBFcU9ib1M1OFljKzVZdXJyZWxocWpQM29qVk1M?= =?utf-8?B?YXIrSlk3MHJJaGNWSThDM2x2dFg1VWpUbEVDVldndEVIbFZ5NHh5dStzOUtH?= =?utf-8?B?Ykx5T2RYc1JDaVo2MXVtMVFsYjNEbjdvQlBMTzNVcnhWc3RrYmFORmpPOHlK?= =?utf-8?B?eFEvUi9aSW94blFkakZ3cE56M3IyVkw4ck9jN0Y0dyttZ2dNTVg2VU9YWUJL?= =?utf-8?B?enc0S201SWxnc3JOeHVHL1V6NzNNQkV6Mms5VVIwYlVKNnFDeFI1N05yUThJ?= =?utf-8?B?MzN0Ni9GK1VBY2hpcjhEWmV2cGNySE1NRUlXUmVMTUU1QlZRRFdEU0xvWFhM?= =?utf-8?B?dEZoSGxrR2xqQjFPUEE3eWYrWDRHT3Npejh0UDJKSDE1VDlPSWI3NEEwQmpZ?= =?utf-8?B?QVE9PQ==?= 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)(10070799003)(376014)(7416014)(1800799024)(366016)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?bFVWaFBGanV0MEpQNFp5M3NpcUhlZjNsSXlmZm4rQjNDQ0NJZUg2R05oWHJX?= =?utf-8?B?TTJZdEhERUJ4OGxOTlJtY2hXVEdhWXJIN0lUeU1rZmJSdWFMVE1ZU2E5czBS?= =?utf-8?B?aDZERCtCQno5K05yRzF5bU1sSUtQYU54d2ptdXhQYWNlWmYxSnVIU3hKc0JD?= =?utf-8?B?RFBRZEhDa2NGRUFSL3BoTXdHTzRBZ2kyN2x3Mm5rS0NmWXdETVBNYWJxYnlu?= =?utf-8?B?bitjWEI0cG4rejA1REErWG1mVG1FMGprVXVYeDVtdit0VllXQ2dPcFN4QlM0?= =?utf-8?B?ajQvL09NZjFpbFNRbDcrRzRoSVAvM2VxSlhVUmNyVFBqVmFqUnB1YUxNNnFu?= =?utf-8?B?T2w0NmxEV0lUeXl5VmJLWTZ6R3hKUFpzeDllVHV2V3BlZFhENHVMeHVUUDRL?= =?utf-8?B?Y3NoQ21sbDhua1Q0clM4d01vaTNYQ0Z1TzZCdVNESnJhSjVNNkE2UXhvNWdZ?= =?utf-8?B?dW9MWjl5NDRDek5XQkg0dVVDQUNCMWRHT2QwYmVEdDNZcDZUOUphK1lLaG16?= =?utf-8?B?RVduY2NMWUpyVWtPM0FjNHZiUnpUdU5QSEVGaXYxeGR5enVFU0pTRnB5ZFll?= =?utf-8?B?dnN0VW1CNGw5WGtiSG1hZEdyWXdtZ2Y1RHlSeTNqK3pyR0xodVJWVEpyM3di?= =?utf-8?B?T1V2YXRNcEFIaHdtRWQvZlZiaUYyYnlOaStCd25nbW51K21aS09CK25ZSXRt?= =?utf-8?B?OFdvdnp3VVJ1WlBVdG9zNldTOGZzRjc4VGE5dEQ5bXo0VDFoRWdqTjQ0bEwx?= =?utf-8?B?cXdjZEF4N1BuNi8weFR4SkJ0djlBdlVhWW9DT0t4bVVSNnlNME1VMDBrRUpV?= =?utf-8?B?M0dxdTR0RkUyRFpQVmdFbmJZd2dpak1WcEptSXhEWlRZTEJ3SXpmNi9QQjFS?= =?utf-8?B?ZkFFc3luRGs3MTNFSWcwQmh6RExLanhYZ3VRK1FheGs4b3FubStheEUxellB?= =?utf-8?B?QkZsNlZPZndlOE9OT0thMEFONnFzNzRmREpkakVtT0tjaEs1Nnpnc01BZXkw?= =?utf-8?B?NkhqaXkyUmtrWXlyeHYzV0RONFFSNC9uTGxDRTVJenlNTTdXRWdWRmV5R2Yw?= =?utf-8?B?QUFKYk9yMkwyNmJPOUNaSWs0U0l4VXJlaDhYNWd4eHQySFRET25KV01VRkRj?= =?utf-8?B?d1dHQlZFaVdyODVrdnRkNnk3UnEvVmMyWkh5WHk3STE0dmNQRWtFdVl5dTN0?= =?utf-8?B?T1RNcjBqK1R1THB4SUprRWREMiswR0tIZlM5TVk0aUF6dUF1aHpibEd0a2NR?= =?utf-8?B?TllkK3hMbCsrZEw4R3hQdlYzL0dVYUZheU9VNFZYZDRCbmNGRURJd1VIMUlk?= =?utf-8?B?eStkZlg3ZUU4eTJ3YlRzcEx1Y1pVWk1nZjJiNU9nWkcyRkkvRGcyOEFxUkM4?= =?utf-8?B?a2Jwb29JRlI0aC8xWEUrK3pLMjZWZ1lSL3NORHR6aGFtTlcvS3NUNjhqLzhR?= =?utf-8?B?WS8rTHFVNkwweWNJNURteGdUVXBzdWhnQWorK3h5VGJZWnJDYnZmVFJGUmJz?= =?utf-8?B?Mml0cDA1MEFmVUpnV3h2emlId0Q4R0RWMXBwTjJEN01ySUxyRVJPUk0zdXF1?= =?utf-8?B?ck1pZ3k1ajZLMU9SZmRXaTRNaytPMDNBcjh2YlNpQjY4MHVaSVNVT1hySnJL?= =?utf-8?B?SFNqemRXS2FYMnAvQlJMSmF6MkZvWHdXbTFpYVhOZEEyK1k4NXEzVzhzL0E2?= =?utf-8?B?SVJ1NTJZRmFRU2xzSjkraUJraG93K0g5WHNlYVY3VHdzRk5TZUo2RXcrNTZG?= =?utf-8?B?d0djRHkzT3ViZ3BTdUV1OGFjWm11cW1aYTZLNEFybThnc2lmNHFpSUcvSHFm?= =?utf-8?B?Yzc5MkNBVm02VHAxNXNOVVJVUFhpZTMzTExESkFNZ1BRQTJQU0hmQkdnaXAz?= =?utf-8?B?Z01ZV21Ga2tBZjY1ZFNGWE51SkZPM2lrazhtS1ZraFk1VFRaeDNRMDR5Tk5w?= =?utf-8?B?eTdxbE1uUEx0Q0EwbmgwaWpVRTdJOFNCVmlQWGY2UzY3ZDBuVTFQdTJ1d1Yz?= =?utf-8?B?UE9XSlFxYUljSFNsYy9lbmZ1ODlLM1dObzdqYVdVeCsrRUc5aHkvdFh5VlZs?= =?utf-8?B?NCtneVpVN3k3bmo3cGllYU5wYVUwNlVQNUt2UUtQdmRUVWdJRG54cngzK2ho?= =?utf-8?B?dEszcnFYcnl2R1doVU5EYUcyQUlCYnpYNytka29YaHVIa0dkcUsxOXBSb3lq?= =?utf-8?B?eDFUUjNwTkM0SXlBYW1RMTdmTHVQVStNL0JsVGFJeEhhTzJBNDdxTmE3K012?= =?utf-8?B?cE9FK0FsdzdrWXJpR3dxdUE4bnR2d2VNN1EyK3l1Ym5BODAxY1diV2RrWlhZ?= =?utf-8?B?WDBlTUt6emEwa3Z4K1hIWnl6SXUxWis2Yzhwdi9TYm16cXU0UW5IMHdBeXdz?= =?utf-8?Q?vgIC8GWpfn7UxnoLOk55VrhfyYZSr+VZlbxDpbbiA3o8l?= X-MS-Exchange-AntiSpam-MessageData-1: TjZjWmPj8p+YRA== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 497ad24f-8eb1-4bbe-049e-08de5f3ad3dd X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Jan 2026 13:32:20.1655 (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: EN5zb9pzZCHq7F3a6VFJgb5m534sglvvx6/S7jGnxzvDoQLmvxvXThUQxd5e3sypJoxlhun/+mnE64yiEWT7Hw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS0PR12MB7770 Shifting a `Bounded` left or right changes the number of bits required to represent the value. Add methods that perform the shift and return a `Bounded` with the appropriately adjusted bit width. These methods are particularly useful for bitfield extraction. Suggested-by: Alice Ryhl Reviewed-by: Alice Ryhl Reviewed-by: Gary Guo Tested-by: Dirk Behme Acked-by: Miguel Ojeda Signed-off-by: Alexandre Courbot Reviewed-by: Daniel Almeida --- 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 23:10:59 2026 Received: from BYAPR05CU005.outbound.protection.outlook.com (mail-westusazon11010001.outbound.protection.outlook.com [52.101.85.1]) (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 A6D993074A1; Thu, 29 Jan 2026 13:32:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.85.1 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693554; cv=fail; b=t7DPCXjbZtk6kZp5FwSmAL16FruwQjYvUOlELHgzgxC/AEK0yw01UTSj6w1aFoSBQSHaAwwNL6vMD+vRYcCqBWjqWiRalklixUikO48tjfkHeWX/91ZC7k2mMtYv0zSMTNErcTolfRhLIgGJAPdQLAr0rJaa51mquwUL3zRKZ/w= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693554; c=relaxed/simple; bh=dkzuEw31qGUX95GaaYlhqJ3i8VuHE33Lnqv5Skh8PtE=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=JD3DxOBOm1jsh797WB1IlrZTG5nk0mcMGAEncW5X9xjgQxc4V4lvjpsoRX7d/ezeRfxCYsIyM6VC11ShK0mn9U+fzry/27CgnpZ3a6no2x/iIFmMM3zUl0yD0kmfISL6hPRrerrDaTpYfMJV2pom80zEuzNKg8D7YquUTM9u2kU= 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=uG9hSyCx; arc=fail smtp.client-ip=52.101.85.1 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="uG9hSyCx" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=rkgQKzW/YaL3bz1mHedGbZE6V+9gyhsIT4W7UrCSzz+l5G9O7kncChcYRfqkpBsOtnrj5mdbw/pnwZH2BY4HHrjJlA5faCoWUBhbiy8MBIWWWMJnclVJIvAdiBHTk6hl8PVmsFVXgZhyHjXTdJv/aNDBoYM4PmAWVx4bZEsEqM4P+wLHwf7eoIpG6G1qkuBE8aRE0etZKTjry8ScAFEqsQ0eSfIOwytmz47X8aYKdgcidbjEs2qO6Kkj+8bABU8v0qoaTx5Yw5OyLFmgs8jne/1i+WHOeW9/0szt67XXKvKCJ8h/PdzWD001BnMHUMfrGQqMChzGyldiOCemEpb17w== 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=Pk49ZTtnsXU8BVfdRKDX7CWsEM/5YwOf5cmpMatZxU6aCSrXQl+X6UppM/V9b0SgGIwLZrFegvtY6Nz1TOZLH/2ECKCRqLlzJKqvis+A8Qp2b8OeoeUkfOiMi8DVRxpUL/XJ/2W1DZr+g+MaxvQEDYaln+LDf3yJ8Zw6DSVs6DcGsk2orNnAD6aaaUJLfW6y5c1IzdPbFi9AnT/XueV2bpOLh/k0HJU8HoTnnYHyc+KZzguD1yPATldtVCjr41DtUwwQ1SRHX/izzao2rnqKSke8IbsQXDbdkfxHStfKHnyG7maBEjQB/s7np52t5vBMN6mXtpTSzDCqm3jen3aaGw== 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=uG9hSyCxSB+n1gtYhfEJgaqUDp1CiiQX7/lwwNbY9P97glW0M+gY2qB7AgtDqExxDtxYhbgotCXIl/pokTh5ThSzPDvJqXlFkrPcAztb4b/lDJnasDeWjyU27sLKLH+KmSGtAbaFBWwHrbxW1Ejf4uPCVq0AmkCY0vADcw47pLfvYsefaQgZlSXO/kcKt4EbUFwMzgokxLz1cSOnVnxxo3t7U9rP1mX8nd9QZdddfoYhAseL3Uhnf9gZ1IPcXepPeusZ0wJuJS/iJnq4HhR5coauvPjKjGVjOCQ0gCswO7qN0ELiBv4ZoxgXv0byjujWC5AJQ4S51cfQsGDFwrEuVA== 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 DS0PR12MB7770.namprd12.prod.outlook.com (2603:10b6:8:138::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9542.15; Thu, 29 Jan 2026 13:32:26 +0000 Received: from CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989]) by CH2PR12MB3990.namprd12.prod.outlook.com ([fe80::7de1:4fe5:8ead:5989%6]) with mapi id 15.20.9542.010; Thu, 29 Jan 2026 13:32:26 +0000 From: Alexandre Courbot Date: Thu, 29 Jan 2026 22:32:03 +0900 Subject: [PATCH v5 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: <20260129-register-v5-3-c4587c902514@nvidia.com> References: <20260129-register-v5-0-c4587c902514@nvidia.com> In-Reply-To: <20260129-register-v5-0-c4587c902514@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: TYCP286CA0371.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:79::7) 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_|DS0PR12MB7770:EE_ X-MS-Office365-Filtering-Correlation-Id: 8625e3ea-9c4a-4da8-9cf5-08de5f3ad5ee X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|376014|7416014|1800799024|366016|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?cDRHc08rcVIyaUNRd2prNHFzeUM3YlVqdzR0RW0veTQ3T3ExMGZtSXQraWFp?= =?utf-8?B?dXZiTnB3SnBkRWx5WllWN1NZbk9mQjdsUTMvUjQyN1hZdlJjQnRJQVRsZ2Y0?= =?utf-8?B?OWp4L28xTlR6U1AvbVFtSmRJSXhjbDFXVzZOcnVxNjRxbk5CRkFvRVc1RlBq?= =?utf-8?B?UUM0YXkwQitBNjhRVjFtK3BPaFYva0hlcDA5QjQ5YUZOQ1htd096WGRkZmsy?= =?utf-8?B?b0wvR0htU3lMOXRKOW45Y05Ock5XSUExVVRMOU5pTGkxQ1NaT1d2WXZCUFFY?= =?utf-8?B?QVFCRnM4RzRiZDZxU3ZhREpmRVJVd1hzZnJsU2JNZks0cTU0L0paQU9HMUNo?= =?utf-8?B?bjlHNWx5NUN6Tk5YelVVSmROMkk3MUdPTEpPcDFmcVpIVG9ENDFRakYrOHZt?= =?utf-8?B?bEplOTAyU2hnZmYxRVd1ZjZKd0hxUGRWaDZiSGx1WWQ1L21odXNpOTlzdm9B?= =?utf-8?B?WTNKbWQwajNYV3d2OHNIS1pIZy9HcGVYNEJqYUMyeTNxazNXaHYzOU5vVHM0?= =?utf-8?B?K2hobXIza2dpbjdWUU1keFhFa29ZNUlqMFNVbjc0R1Y4SlhYUld3UGdFKzg5?= =?utf-8?B?eVdzcWRFbEFWQ2d6VkFiZUxReE9QanQ0ZXhWczh1dUJCUm4ySDRlS2Q5bWNN?= =?utf-8?B?ZjNQUFpWMkZYeVRxaUdVbU1ISGlqVmhjaExXSnFUeEp2Uk1OZnlocHVyUkh6?= =?utf-8?B?WTJuREE0U1IzR2Mva2U0bURNT1J2V0h1UkpDMGVmUmhMcXE4WHQwMkFKYWdh?= =?utf-8?B?MUdVUGx3aXE2RzVNaHM4NENkQ21TaER5WjV3YmpWNnpUdzRBc1ZvSUQ0engv?= =?utf-8?B?YjFiVVg5aVRBYmNkKzVwLzJQWFcrRlNIUjN0ZFE0bVhTWDBKUDNSNm90azl1?= =?utf-8?B?Z2xNQkRTancrakxCUXB1amVvd1BtQjBTZG1EM09TQTY4ZjJxenZEQ2h1ajVX?= =?utf-8?B?OGZUM1BwU1cralI1KzFIZDN6SkFVZWdNdWZDYWpianFtNDRoOUhLYmFraDlW?= =?utf-8?B?YWZ6dkxLdXhLckV4ZEcweEFXL0ZpZEsrVHZPMmpCWnlBZVJMVFFsR0hyblZF?= =?utf-8?B?VFVUSEYwYnRQdkFpTXE0OGNZbFNTbDBGN01CdmxKVHQzcGVVOVk1Q1A1TFFJ?= =?utf-8?B?bS9yblFoQmw3ZWFzQmJRbEp4ZnhicThXMzlmZG9ncnpyOUhtOERqMk1UTUUw?= =?utf-8?B?aS96d3FBYlA1alJ4Q2tuMGpmTXlkck5ETGxPNVdLVVdhcTErVEhFb2Vuclhj?= =?utf-8?B?bVpQNzk3SkI4RGRTM2VUeGdTOVB0YXBXL3VSNTVwNzI3UHZPNERTWGFQZ015?= =?utf-8?B?YitkZHEycHJXU1RjVnBhRy8rVTJUMk5oRDd5emNXTHdsdXZFOGlsOHVpUWlj?= =?utf-8?B?OFRrZWhsVE5RUUYwRUpSZk1COFM2MDBrR3drbHJsaXQ4Sld4YVg0S2E2Nit6?= =?utf-8?B?K2FtWDA1WVVjQnBxUDZ4dXNoOWQ2eXdmZHVhUGovUXNMRkYvbkJXUWw3R0dY?= =?utf-8?B?R3VMUllldE1lUGI3SkRyc3E4aUF4aUFvRXFzeWdDZmZwVDJmMmVZRUxaemxo?= =?utf-8?B?a3Z5Y0wybVlobFdIU3R5VmI0dTQrdTY1QmQzVi82K05iTXhMTk5PUnJRR3dw?= =?utf-8?B?N2EzVzFzTzE4WWhGaThEU0ZlQTBHczUyTnVRTkMyL3pFTmFnaGdpcnJ5cnUr?= =?utf-8?B?K0M1VDdENm5SUGh0cE1KdlZVaUVZRThtK1RoK2pBYlpMKyszcVgyV3poT0Zi?= =?utf-8?B?UWpJTUhjeUJiQkNkeHl0bFNEOURSbXlRSjc4Z0YvbkgxaUNvN1ZJYXFzYnY2?= =?utf-8?B?TVAxYldsend1b0Y1NVphLzdPSXNEeGFxS0N3YmQ5ZEd3d2tJRjI3WXhoOTFI?= =?utf-8?B?Q0U0b1p6bmN1TmxIekFaSUxRNUpyQStYbEdZcTlJZFluMlVsbWhXQ3dqMkJU?= =?utf-8?B?Mk14UmpyS0ZOWWdzNjd0TllqMUh0N0RhQmhuS2pxWjhueG9DbWVHYmtZSEtH?= =?utf-8?B?RHJ1SzQ0c2lyNDFQbmhTTllKbkpSYXd1dSt6bzRiZUZhUzRwMEw2Nm1pWi9Q?= =?utf-8?B?NFBPVyszN3Vvc2pRMGZMS2lIckZIVHBzaGhaaE16VkI2M1F5eTZEV3RIZFdY?= =?utf-8?B?SGUvbCtOaTJUZlk3MmIzZ2prZHo1bVBudXdkZTkyVEtkQWtCRzhGdWc1RUlh?= =?utf-8?B?NVE9PQ==?= 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)(10070799003)(376014)(7416014)(1800799024)(366016)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?VElXTVg5RG5GMTJ0V28ydmNHTjVoUS82cDhQOFBDbTNQVUM5aUl3R0xYTkV4?= =?utf-8?B?a3pYUktUdXBhQmVjUXRZdzYzTnNKbFBKMnY3MHArN2x4QWtPRkZHbnE5ck1m?= =?utf-8?B?alRBbFZkSlZTT0Jpak4wYlhiMlFSMnBtRk9RU0l1U25pbHhHVGZ1MEFFT0VV?= =?utf-8?B?bk5UNlJab1JNMDQxZXlxSzR6TUNEVlc3RExjc1FKM2N6azkrY1hIcnF6VXIy?= =?utf-8?B?ZU01T2VBYUtEZTdBMzV2bFE0Z2YySjZZSXZqcWx4aXY3b25NcFFteFNxNU1L?= =?utf-8?B?cnFDVmVxMW1RYlZmZThkVHNUaFVhL2IxVXBIaWwrRVZscGp6ZEJrSGlIL2lC?= =?utf-8?B?dndwaTlTand0anROZFdBWjhDN0pFOU43S2liR285bjJGK0VGc3Q2eDlTcVlu?= =?utf-8?B?c1ZPS251dFkzNGg3cWwzY1ZyZmZRd0w1bmJXWWV4R21nOGxLRUV2UkwvaE5E?= =?utf-8?B?MUExTUd6cEwzK2ZDVmNMb1h6aWlMNE1zMGZjREtHRWxTNStlK2psNmk1YWtj?= =?utf-8?B?MjNlRVYrL3picVpSSzFKbXFMR0xBeWp3YkZkcGd6YUJmUjdPWlpiSWFVM1Mz?= =?utf-8?B?eUM0bVNxdkdLYzY2VTFjMEZiTXRQc1Z3SFVKSGEzL3AxNmRPL3BXR0lWNWp3?= =?utf-8?B?K0o2QitRVGIvN0R1a3R6L1o2T3BLKzQyZEJYRDQ4Z1BrSVRtdjFqaUQxT1pt?= =?utf-8?B?UkwrOFlNK09PM2JEdjJ2OG0yYzZkTjBMNzY1RndrdFA5MWxSdjBrTnZjK29h?= =?utf-8?B?ZTdmZ0wzeWYrSGp5SEsvTG1Iem9aeHdxb1R1cE5CRnZDTGN6Y3ZQYUVucXdQ?= =?utf-8?B?bkFmNWlnTm1Ua1hEZ2xrWmVlcnBIRXBNbDZUeDFIRG5ONDdocEtrZ1lwc1ha?= =?utf-8?B?R01ZRzFoaHh5cVRJOUl5Z00xYlhFREdBdnpBaEpoMkRoOTkzSGZGTzl5U0lT?= =?utf-8?B?LzRXZnB6MzBXN1IrOGZTLzBGRFIwQWtwemZOMGorMExDYkVLeDRQcHRLdTFh?= =?utf-8?B?WWV5aTFtUXVuc2xMa0t1NmtZY0NmR1NSTjl5TWIxZ1AwM3g0NURHb1JWVXBH?= =?utf-8?B?L2tiYVQzUzZaY2prN1N2NEtnanVnWmM0UHlFZmtRbnlFVGp1V01FRWpoRk9U?= =?utf-8?B?VlE2eGRBL2pUVjFGMFE2L04rVndjZ3Era05tb1FSejFHekhtVjR4K1hvV2dU?= =?utf-8?B?ZzhDZThpVHdzZ015R3NPdEVBN2xsbTMzazhQNWVDM0MvZjFrTVBLakNuZlph?= =?utf-8?B?czNXRkFET2pud09xRzJ4SG5HYi83cVFoaFY0ZlVRd1locmtHeVlnY2wxTDdu?= =?utf-8?B?cENnOUZuaVhKWTZ5Ni9OZUlWajFJSDNhQ09pZ3cvNXJ2STlJSzBOMzZCbnR1?= =?utf-8?B?UVZqdkxuY3Z5bndnVXR3NDAvN05jeGlIUFlXK0NwUGFtYTNtSEFZdWNMbE42?= =?utf-8?B?NDU2dGJtdWFnTDdwOTVvRjZuamQ0MlRzV2grQjkybmFmbkRYT0ttdFJVNlZP?= =?utf-8?B?VjJHMGUxcXVoNG1GREdZQzMycjgwK3NqcHdPU2ZQQkc4ZEg0ZUUycHYyOHd3?= =?utf-8?B?cTVXSjVJM1JsVnBQbVpxMXM2ejlRUFZVNG1adE8xbm0vQVJWcTd4anRPK3FM?= =?utf-8?B?Vkh3VEJYUEVZZTFDOVg1V21vYzZRdy9ERzUzRUFSVWpZaFgxVHk3Zy92ZlZn?= =?utf-8?B?QytQclB5V1o3MjhuNm00Nld1YnpuOWNPT3VEYW13WGFtNTdtSXVtWS80OWIr?= =?utf-8?B?NVZOeEVzZFBpTFhZSE94ekMvZVg0ck90SHM0SFIxUllNckxxNVBVN3NnQUJa?= =?utf-8?B?ZHRaTFJOaXM5Ly9sRXA2VUFEV1NSMWFCcmR4UW5IUkIwblZqR1djV1J4eDFO?= =?utf-8?B?Y01PUkgwRndlbEQrTThrdFBLYnB2K2JZSUNMWWFHWXM2dnZySDFJbTdKblNj?= =?utf-8?B?RGhjVlRqeGtXSjJpb2V2VlRycW9MMzd3eDg5NUhhN1VyWk9LSDlwWmllUDNu?= =?utf-8?B?RlA4bUg5QXZ4UTRIZlA4SVg1RjRldkE0Y2xPTERET05kWTJ6citIbHoxQnQ1?= =?utf-8?B?cWI0cUdmL3l4K0NLZXNJVWd0ZWg5RTgwY0FFSFVOVzNkL0ZuR1hwTUdMMDN6?= =?utf-8?B?eUd2cS90ZXdud1k0bUNKdXp1U0pacnVZbFRzK2JBeks2UXJSb0s0THVBSmdx?= =?utf-8?B?TmdqNEljenp1VmNyQlBwMzNXMmUvRXVURGRjcDhQRFgwcmNCYUNBK1lWM1BQ?= =?utf-8?B?a2pnVDRVanFqWkIwejY2Zm1kQ01tcXBqWlgzMHB6Umk2TEpUWldKM0dlNzZY?= =?utf-8?B?dzVaRlR0VlZwcFYwb3AvS2c1YlJiMCtXNXg4RXNBS0ViZDdkOFYrUFhpRlRM?= =?utf-8?Q?lbkgB56vXLnRPq4gOrR+c3Gh9GRLQ2ZjQ+5X4GVMNFsx2?= X-MS-Exchange-AntiSpam-MessageData-1: f9ioFMCNWGUsrA== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8625e3ea-9c4a-4da8-9cf5-08de5f3ad5ee X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Jan 2026 13:32:23.8054 (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: SKRYYXEdhhDbp/tPDqvjIQPGF85G4Uzljujsz4jH1y9jeCFMImdScNdMc7+U7UPH8R3d2PRFItrCUcwHuCbchw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DS0PR12MB7770 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 Reviewed-by: Daniel Almeida --- 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 23:10:59 2026 Received: from DM5PR21CU001.outbound.protection.outlook.com (mail-centralusazon11011058.outbound.protection.outlook.com [52.101.62.58]) (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 B5D8C313E3F; Thu, 29 Jan 2026 13:32:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.62.58 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693555; cv=fail; b=UqltcTZGv2Ne2llPCr9eavhrdgpisQGYrjlTWtd3LYeoNCx4fJjYOev3ypO1rVSsAiXdti5lVxqhuvNN/EzSkzwoYkACvaycklKxP4j/ECJltllvDPV1qFJhZkXruqpmCDt8rqDQTlbERv1P8HtzH8JapkfWJ1XNqDIzEWq2Q/4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693555; c=relaxed/simple; bh=5NOnpB+JkmYoNSdg0KQsq9hm7oPd1cdUicHldYc6Cwk=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=cmqQtS+FNbtoheWigyUforTMBBETiALkp7RiyXYOatu8KFtr4D3kAkm7aQwhOedlMQtNEigNjIjtlY9Cg4mwIGA4NJU3WCVNq+jGyxyLrI7kIxbpWw2slvQZmwgAC1jQZORiuQ2eY9aICq2F6rg6yVZmmz4IiicBJ+7n8jaBvIk= 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=WnovwmDZ; arc=fail smtp.client-ip=52.101.62.58 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="WnovwmDZ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=GcqXXvu+zBB7XXUrI8Ddv083gsxKHCjYa2CgqenjgCldDmKkeoU2Pmqwfm2QBuY8muDb9+Tp6vTQwaXUU2gAk16+GfS6W57yT86oXh/wcqyJdxvmTNEIE7hL31Y6/tuXGTb8Wxeh0u9ptUb17dbAxs6iOGOQubmsW6awz9A5+BJ/psnidps0q49ktUr050s/eVjokDWd9aqbY3fN5qObpJmfmMNKQsNL8MLDGBTrhl6zdfiWXjvVC6xaoMXWOOx7wabfbd25TlCUjkHw5mBVVnjrmH7Nva95pd9ooLwJ296uOniFUHc85JxJV1X+p/B3cuQCLrCv+NC6/rZxRZpxFA== 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=KCaPYtsn9FRpILDKzbzJGI5untDKuBfxhC2CFvrtIIZuKMfNSdnW6Sl8iZPW6JfreM9PiJVb67ZtYMPh0LcWiR/t7euWfjWjwz9xy5tjQVqLro8QYg/jUt9XbVNrlHr/BbmCgCDjpsVXgO01Nc/JVCxItSUOdnRoyKPUai0KHzGG/9sma1Bs7lVJoIyp4eXu3rrsjPS3UuVOIR7lGiyGn1+WcBKs+byyUN6vSuQAq1RTMw01cCAFsm1U7F1DuSORiTGjPbeam6KmgLJ3ym7ay4bleG9vhbpx/xYJKtYXHd8h7Kxgz7m+X46969/HU+o6yaL5Fe3f1tcEULQ2jfNxKA== 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=WnovwmDZAdgSeiJoyBPP0eZ+n4CSQDFrcuZOWTlNuklD2kK1EVnQpXGKm4ec6zPV/i47zcW7bF3fxldfD0lub1HexSAisJ1FhJmzLqVB2P7aN+U02CFKazHAuUoXimkQAO2EmB1mzkip0B9Y01/sXRCU4Gdk1nKqFKkaQ2jHG2M/3lSKxSbIUd6Ti+aeBQ6G2cSKRxfNxQVU/7Ayxyz+iTr+AOhPtqb073qYtXszhw3SEBiK/J+L8dIS9voAJIokfPGow3mHxRgYYeyFZrgF2SAX+WuQdiSXJE9QrUX0EpWj6XYfiZ7bibcu4SLb8wmY0Lw5/082m9V/SeCeTaBE4A== 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 SN7PR12MB8146.namprd12.prod.outlook.com (2603:10b6:806:323::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9564.10; Thu, 29 Jan 2026 13:32:28 +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; Thu, 29 Jan 2026 13:32:28 +0000 From: Alexandre Courbot Date: Thu, 29 Jan 2026 22:32:04 +0900 Subject: [PATCH v5 4/7] rust: num: add `into_inner` method to `Bounded` Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260129-register-v5-4-c4587c902514@nvidia.com> References: <20260129-register-v5-0-c4587c902514@nvidia.com> In-Reply-To: <20260129-register-v5-0-c4587c902514@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: TYCP286CA0238.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:3c7::11) 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_|SN7PR12MB8146:EE_ X-MS-Office365-Filtering-Correlation-Id: d1df6ccd-1bd5-426a-4563-08de5f3ad87c X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|1800799024|7416014|376014|366016|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?cWE2SjNpMlZxcWFMVFdvQnJnYWxJYUxmTUFHa0NVZmp0NFY0SVY2TW42bHRv?= =?utf-8?B?N1FDdlNBdXhMU3dNVnM5d3N4Y1pLMmVNRGRFTGZaeWFhQU1IQ1NmeTZwdU03?= =?utf-8?B?Mll6TW00K3NDZEpaWm1GZG9CbGx5WUl4VTFxR0hoM1pQNlUrYUgra2VucXY4?= =?utf-8?B?blo2SlFlSko3MDJzWkoyeEVIMlpRVzRNODRPQm5WdDgzMVAzUGxkQ1BPSGdG?= =?utf-8?B?VlF4dzk0QS9saHZBYnFjOGRkbnN6cVhlRXNNVFAwcTZUbXNFMkM5RzloQ0w1?= =?utf-8?B?L3dmNVlsY3dCRHI0UWQxVVNpbkZwNEtGdytGZ2JQSEdpamlSRFcwY0Y5VG1o?= =?utf-8?B?OWJIOXVyWUdCUU5hUW50MTF0VDY4T013THI0bXA1aWdMQkdBbkZuTlJCOXl2?= =?utf-8?B?N29TWi9yVmxyd0gwYkowU1loUTVqZVpuMXlLZXR2L0xYbDZzalQ1bWFBNGh4?= =?utf-8?B?WmlCSFh2TXFJVzBmWTlsZWhYcjNBZzA0UzNVMGRTWDgrOTFJdlllNUxhYmdZ?= =?utf-8?B?WGZVQ2c5ekNiazA5cVcrdndtR28xOFBSTnN6dVNVQkNoZkM0cE5wVjBpRm5s?= =?utf-8?B?UVVOWjkxSlJib1FGam00bU5JL0V5Vm9KeXlielZXb0ltelp5Qi9KdXBiNGJG?= =?utf-8?B?bU9vazB5b3BUU3ZjbkRGbWVudjdIREdMeC9ibXdUSVJGTEVGdmMyaS9ad1dE?= =?utf-8?B?WXhOWVFpK0JST2JzbEFLRFpBb1VvK09xa3FoYk9mREw5dmprSE0ybmNTMjV4?= =?utf-8?B?U21oQjZRUXpFN0gzdENZRlhoTWIzODVweHVaMVR4S25YOWIxbE1OVlIyM1NW?= =?utf-8?B?SDAxTXpLM0t0NHV5bExNUVlqRTZiWlR6dHhSR1dpWlFXOG92dENneGdnckVW?= =?utf-8?B?ZjFKM0ZPS3NDTVhUdWxGTUJ5d1pFTmdUbnFOMDhmMHgzN1VLTDJ1UkVJZDcv?= =?utf-8?B?V1F6emx2cjhXeGczbFNxcGFQQ2NuVjRXdDlMZVVmZnJQSTU1dEI0c3RoWDNn?= =?utf-8?B?MkdQRFJBNW9Tb1ZBN1VPRHN2bENrN0ttbkUwNS9haExMSU1UbXlyNEVjKy8w?= =?utf-8?B?VzRvNW45czZQbHQ0anYxa1M2UzM2bm9kOU5jTStiVWdBc0Y2elk5RlA2SnFH?= =?utf-8?B?UUpQSm85Ly93T3ZkdkJqVVkwbkJMQXgwcml3Zit3M2xDS3VBZ1hEQllqMGRD?= =?utf-8?B?bjRMZk1uSU5TVEVXNlNYY1lUeXh4TGJuSGV6cksvclArOGF3bjZTRHlzT0o2?= =?utf-8?B?RlI0VEwwRko0dnRVdXh3Qm1GeHRJckFybUl0UHZUQmRxeTNiUEZxUnVmNE1v?= =?utf-8?B?WURKaTRxUXdCQWhYL0N3QWhlL3ZVMElaMVorSUxHdHJZTGJQSENEWE9jUGYz?= =?utf-8?B?WFM4T1FHanRMRkhMcVRpNDZlL0hqU2ZXWTEyN2lRcE8zSVBoUnhyMWx1RFdI?= =?utf-8?B?Z0RtL3NsaWJweUQxZ2NlSlNrZjhZOXZGckx4VGxWV2RsRkRlM0NkT0ZvWXc3?= =?utf-8?B?Vyt3Wk0vUXBuR0FadGxnZzdCZjB0NWFZOFEzNUVMWlF6VlZXT1RXM09pdFZS?= =?utf-8?B?cTFVdjJEL1VuK0ZPWmQ4bFNjZmZUWXJ3S3lKZllySm1mN09xMWV6bTNkM1dF?= =?utf-8?B?dndzMWhRL0pDYXJ5Lyt4dFVteGJOa0JlbkNjTEhKeG02Zll0Q1craTlCemdB?= =?utf-8?B?dzNHcUd0d1NLaW5IenRxKzQ0UTBobHltbU0vZ0M3U3djcHBOQ3ZNY2JXQ0g4?= =?utf-8?B?MmNaeUNCRk8yWGEyQUZNSCtVOWZneUtnZmhUNWRUbkswaXBYQ1pvbGttSlF0?= =?utf-8?B?T0NSVTgrNWZXOGdDd1hNZ2lTZ0ZIRTVJay9LTEwxemo1anFXczYyMWMzWHIz?= =?utf-8?B?K3Bwa2lnK05hM1lmMkdNdWlobG5VbTV5TDBuTGo0OTdQVDJXcXJYVXhYN3FL?= =?utf-8?B?T2hwWTNNT3R0QW5uRDI4VjdCYnJJaWtjSU93Mk0wQmkwbS9LQlkxT0IxUDlv?= =?utf-8?B?SW1PWjYwbUxhRXlRMENaUGRWU2NjNkNNc1dBWFJWaWRDWWc5b1NRVnd5V3dz?= =?utf-8?B?dndTNnJGYk5SUUl3c0hEcmljSDc1SGE3eHBqVG9kcUlQSi9hK2pEeE1pQ3RQ?= =?utf-8?B?NmxsL2ZlOWFlUkVSN1RuQXdvaVIwMmVyZVZNcVpBV0pqZlFyaldwK2QvVHpT?= =?utf-8?B?bUE9PQ==?= 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)(10070799003)(1800799024)(7416014)(376014)(366016)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?em9EOGQ2Mzk4aUJ6WTc3SDBtVUw3WDBsMWtwcVdmRW9mK2ZKdFc0Y0I3aWFL?= =?utf-8?B?V0N2bFFTUjVSUjRSUERtc080aXY0V1VXMzJSVFNkR0FQVi8yTWY3UnYwTGNj?= =?utf-8?B?cWM4VmdHeGFpTU93am5hMWtuVzg0NlJROHUyY2IzSzl4dmtIbkxDWURPZXhX?= =?utf-8?B?REV3QXh5RFk0aUZDSUxnMW5YUC91V1k1akxhb043N1NoNE11NkorQTVoVXRB?= =?utf-8?B?N0cvbFVyVzZxd1pyYUxDNHdFNndZMU1aVTFubEJBSXdLSXk1M3dDOExVa0sx?= =?utf-8?B?WXZLdzhOcXFKRVFhMndnbTFOeTV6SEkxemFhbHZmZ0o0Z1craVc4L2pWWVVU?= =?utf-8?B?WHFYUkROTXlJZkxsR1ZERlRoR0VwaHA2ZkJhdmJWNkRVQUVpUDgxZ3JsVVhu?= =?utf-8?B?enhRM01RL0VnWUJMYnZoQnk1ZUhUamhUclh0Ym4vKy9GbHBWWU5GZ0NhcE5B?= =?utf-8?B?MCs5bzFqWklpeWdxSVNJT01KODB6TzVLN3MzUVA1Sjd4NFVWNEt6eUE2YVU1?= =?utf-8?B?Wlh1UG1FNkdlYjJJS0pqdVlTdnd3Q0tPZGNjSExBYmxwTUVSWlNHS2prWk9k?= =?utf-8?B?SURmeTF5blFKL2xYYVNDM3VTQTlxaVNMYmNDTmt5UmFrWmNRR05teGdMdHF1?= =?utf-8?B?MnJtcWRiWjBVbmxSTitFVThPNjYyaFk2UkhFRWl6ZEpwT2lmWUxtNU1jZXRk?= =?utf-8?B?c2J3c01WMVJhTS9IeENBZU02SGFhTllyZDFzcjhkV3lVOFo5MU4zYTVsdkRv?= =?utf-8?B?SWNIVm9PNStuQmo0T2wrYlBNOU5DUlo0U3NGc3BEWi9CWmlJM2FSMWVpTnNX?= =?utf-8?B?SUpZcVh0NXpDVHpiSFBOcmJ5VHA1ei9DdlNVaHByNVB1b3lZdzF4UkFlTUth?= =?utf-8?B?R2dFYTcvcDdDOXlWVHZWWkxKZlpSRGR1ZEQ4Q09lcjFCK1FSK3Q0aHFkT0Y4?= =?utf-8?B?SGpoT1p3Y2x1OE82QmwxeENGRU8rRkI1ZXRNTWFaSFZ3RkN2L1hWS3owUlR0?= =?utf-8?B?UjVQUzFaRmxLa3hNRWFtdlFBNlhCenB0ZUpLb1JlSFZLMWZhMnM2MnlLaU1H?= =?utf-8?B?VU55N3hWVW0wQ0M5SkFZOXhkaG12L2pna1FBSnFrTGo5SVpabDdxM3p3OGdF?= =?utf-8?B?T2Z6eG1RQm5vTWpUTytEZ2JpeTgzUjBORmIzMTZKZzJVRy83TVpRbTllVlh0?= =?utf-8?B?MzVaNnRwYkdrU1ZVR21HQlJUSld3NXNaY20yR1hDb2QxMTI5Smx5U1JwSktK?= =?utf-8?B?L0Joc1BQOGxrYXJOYVdNdDdySmVtS0pzS3FuM2R4U2FDWnpMbGJETmhYSGxz?= =?utf-8?B?emU2dkNHQlBzSzFXZXdBWjZXZTlDT3N5RkVQUUM0QTBhVmozeitvQUdRUXhk?= =?utf-8?B?VnpMRTVCV210dnh5Q2EyU3dOUGJpeGdIZG5wOFZ0a2R5N3FvWnpCcGtWcU5i?= =?utf-8?B?citvanJMYm9GUzNaYzV4S0JnREZVV1ZUdWVzbzZ2WmE5M1NDblFvdVYyNmJY?= =?utf-8?B?ZW9RNGlualdnSXlqN09jMzZnUG9iL0U1WW15bWF2dWdsVDNuQ2FpZmtndWlB?= =?utf-8?B?K29EMkNJMjBYZzdqOUdzTHdoQ3BaeFJkMGZZTk5zdDlJYmJOZTRPUzBNdStG?= =?utf-8?B?K25IMkZnNFBnSERNdk1mNEFNVlFPS251ODhtYmVEUmZqdktjTnN0RjRLcFc2?= =?utf-8?B?cjg2UnUxRUx4VHpsQjBmbnFtRU9rWitJRnhleGlsWlFMUzZMNExsNWtpV2k5?= =?utf-8?B?bGlsWjB1Y1J2VnJseDVOZGNlRENyRmlTT1NWSGVLVjBnVFVHQlN3VG5qWW1V?= =?utf-8?B?dzYwZDh1MVlhZGgvSVhCQnZIK3ZDam11RFNZZGtZMlFQM0ZWY0JkVjQrZWdS?= =?utf-8?B?ZEowZ2VYaWpPZXB0bE9ZUDFpeDRkbUh4OGluZ3RJVnluTmhZZWY5UEtHWlBy?= =?utf-8?B?NXpES3FEWjFSK21xbFJZN2lrMS9zT0lXOWdVU3MrdGJ4aTkrWFQ3Qm1uMXBV?= =?utf-8?B?UExZQ1RpT29GNEFtdnllY2Y2UDlyN2tYVHFuT2RvN0d0ZjBYWUljOXdLaVM5?= =?utf-8?B?cHhXK243bk5FZENyTEFHN1VabFFqaVArZkUvd2ZjLzZQbjhLVW85TkVVL3Q3?= =?utf-8?B?OVJJNk9TSEJzM3Vlb0ZJREEzL3lqajlaellHSVpmQ3h6TmtKazFXbHUreWFj?= =?utf-8?B?TS9FQmd5WUdYWE5CSk1DcCtKUW16a1kvQXlXUGhhaGFDQ3FQTTMxRkVBbGdB?= =?utf-8?B?dVdEK1ExekZjaTNOenp5aW1naDZvc3g0ZDRKWldvdEZ0dW51K0Q2UTI2L0F2?= =?utf-8?B?V1FiTDNVL25mV01oZHgxTEdWdDNKb2xnYlpnemhWL09yYzZ5Sy9HWkR2Ryta?= =?utf-8?Q?9sfmcFxLmSmiPT3oQz/Hoy9RYKkAa3UTbgmEYC4PuSIpt?= X-MS-Exchange-AntiSpam-MessageData-1: tAuMx6ECqnXFWQ== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: d1df6ccd-1bd5-426a-4563-08de5f3ad87c X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Jan 2026 13:32:27.9956 (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: zevty+6mBzy3cCtYgCGciqq4wng348FIsVVF/a+ttwz1k49UQHHt79OIOiOWsMUy87kIrQpjGsJGba8aXXYs5g== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB8146 This is useful to access the inner value in const contexts. Signed-off-by: Alexandre Courbot Reviewed-by: Daniel Almeida --- 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 23:10:59 2026 Received: from SA9PR02CU001.outbound.protection.outlook.com (mail-southcentralusazon11013068.outbound.protection.outlook.com [40.93.196.68]) (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 5216C308F05; Thu, 29 Jan 2026 13:32:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.196.68 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693563; cv=fail; b=p8YBso2mYbdp7ODmzmJyeXfkEgX1eaFpkttEncf5054DCwh4NSjjpXCyA6ebLhuBSaDfPY/+Cyz6mPS8M8EumbYMV0WZqjlYCv2lBD1qxD9DKZKnH5zwK2x8vgRYLSRxqxnuLOgNgYaCZVXytfmRboYGjaQKVpHXRl6l485H7YU= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693563; c=relaxed/simple; bh=YQeamm+I9ktGWOVTJVevD60gSoea7A26viD2qLCcy6s=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=OXUPEPw+VPRKpTAzvao7nU+PtOYcXjyo3gF9F1cpNQLQ2AKQ/dJmeG2wDiYgAR6tO0ND4WT3VduovNyo/RcMGodZ8bg64spUMEVSzvo+wyVTA9W6/h+P3f4xo70oMtZGNwcGuRIZ6xQcWM3D5jWfTjFLy+8opQvpzS2oD2dsvts= 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=CEUWaFpu; arc=fail smtp.client-ip=40.93.196.68 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="CEUWaFpu" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=waLjpblkpdEUQPw2OaODyKtAb3hTvrixn6sSej4rAvUVRAJZG4YcSzpeNurASvrnvJILu9RzJiF0ZXbUehst5ORDF+vmLdGemIf2mwx3/fLqeyZt3C7biidxEtJqnoicqgrskWNo8ycd5ANWUou2Oj2ECn6bSL72eC9Fqds+1ArBjV3m3gF9aml06+zejp2c9ysehNbYlL5+WBNKgYcsHf3CINEHz9bMJFcxW8pZBCebq6/LHynP8bYhCAh24dBv2s3aT7ni5sjE84bCMZgw8aMu7i4BRJYWVZ8MWhx2gR8PW74qRgHk67Kf/HwrmQ4Hnhokh/r54V+g+yqf9ww+Rg== 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=ombNWhgee0xS7DHVbt6S18r+qf/hAAFOavMOSs7QMCo=; b=vywMifpuYwmb7QGU39OBWwkTurbbWxSEmW4ImnZGybWxFwb/Ph9uW1XyQt/T4Iaz3KdI0kVLJ/awTlci1vXcHqLfJh883CcQ0UXkseiEouermagVQ8SkosdTmPKWzIlz0gPuT7dsNz2GwU4WfgXFEhTX55t+H9bkOniH4J4dk/sYFvDvsG+uxzuChxhTaxuSY4xy4vBEpmLR1554JUE9mNShlBXDjQtpymwdZniLXkGNoEBCoAjaxlktMdWFPv3mnyMYeLf4zjAE9TxDHzb0Nhh62Cpiqg+F1s1jhCrfKI/oUbdz7st1L8gXPQH2dW0tsNZuwPzDjKMIhdIoFc7VnQ== 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=ombNWhgee0xS7DHVbt6S18r+qf/hAAFOavMOSs7QMCo=; b=CEUWaFpugY4OOSGqSMN6JnSuII3gFuL3XKZwxj4Tr/kh8nOoa5dLIEpxyFXPupbH6p7/URj70ycsIR7UZMhjOFB5o5Up/Ft0d/2L4irdFn0KHzKD9feIvxk5xWdJSry6oYeJActW1zevU6H06PZQkaXzk7X+TSHPPQg6zjDwg6bSACyAw2LfPxpqj6dTwi/LuKattA6GvFh9oiZP/MpAXpQOCnXR2jfslpJB7wOsw6pM7R04MuulqrCihoApLAy/9fpuxHPKLMYHyxXCoZ/awbkHs78s7rM9FAJC6uD2hV33SZ/eMN/zcoSu04r65jKZQ1IPRmrT1jhqVl/VImm9xw== 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 SN7PR12MB8146.namprd12.prod.outlook.com (2603:10b6:806:323::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9564.10; Thu, 29 Jan 2026 13:32:32 +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; Thu, 29 Jan 2026 13:32:31 +0000 From: Alexandre Courbot Date: Thu, 29 Jan 2026 22:32:05 +0900 Subject: [PATCH v5 5/7] rust: io: add `register!` macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260129-register-v5-5-c4587c902514@nvidia.com> References: <20260129-register-v5-0-c4587c902514@nvidia.com> In-Reply-To: <20260129-register-v5-0-c4587c902514@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: TYCP286CA0361.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:79::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_|SN7PR12MB8146:EE_ X-MS-Office365-Filtering-Correlation-Id: 76d7c65a-163b-4d0e-23db-08de5f3adabb X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|1800799024|7416014|376014|366016|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?YUtqOHEzR3ZTZnNrTXMzcFd5TUs1WFErNzcrTDRKcGxtVGZMUVdsME85UzRK?= =?utf-8?B?OFJwQy9VTEdwY3k0OUQ4dHA5ZzFKbk9vUU45bEc1dEFXTWgzYkpmOWxvYjVo?= =?utf-8?B?bXZkTVU5RXhPS0pvNndBc3R2eTFJN1pZY0NRWVNwVHowTS9hd29xMW9HOHNY?= =?utf-8?B?Z0dTWDZxcjRuYURDRjlsbVFLczlPbmh5RnhpM1VobzFvNTBENTNTZnlIZ0xY?= =?utf-8?B?WGlva3RkTDl2KytNMmpqMXBmbGxNeE1FdkRuRHpkd3J2ZHdOYzAyZCtXQkdE?= =?utf-8?B?SjM5dDAweUdMZzhMaC9udHN6RG5OYXJxdk9FdVFzVUpsRnZyd1ROOHJ2aHVX?= =?utf-8?B?WitRV2piaVVUTTA2MUlhOEw5ZUFDNWFCOU8zbElvMHBYUnBnVFREVXh0dWcw?= =?utf-8?B?ZUZGNHNvM0Ixbms5eGpqVjdWTzBiUjY1MUZYaytkK0xRRDE4WXRzTXVOY2hx?= =?utf-8?B?cW1vT0RrdTI3UDdrMlRXZk1XZFRDUnJxUGd6OElXdW5DdnlpcVVTa09sQnhQ?= =?utf-8?B?VndNNmJtUi84ZFZLekRoWmpZLzZ0eWtsd2tSWjFtMnpWZUprYm4rVytaTDVP?= =?utf-8?B?VUNBUUROQ0syendjOU1XalhxN3lEeDMrZmhkbUdCcWVxZlJkVEl3VU9lc0ZR?= =?utf-8?B?c2ZZTjByUFZwR2w5WVJWNlNJQ1V4emMwSVkyMlpFakZoV3ZKRGJkLzloZDA1?= =?utf-8?B?NDZCOExkMytkSGlUUkFxc3EvMXRNU0QvM3J1MDc2RU1RWUFJazF2NVk3Q08x?= =?utf-8?B?N1BIWUVIVDRVOUpSdkRtVTZIV1JpRFVCSWtjMUJrMStPaVYzMWJyckd0REFw?= =?utf-8?B?clNxOVY4a2QwZENFTTNDdXhLVkJjcFFlc01yVmEzeThzUFpIbWZDS2RFRm1B?= =?utf-8?B?cStuMGRobXJ3Rm1rL0RtbzdBSVhGMDg2NHhXZllBOUNWVVZyd3NWNkNqcWdQ?= =?utf-8?B?R1UwSWNrMC92bFBQVyt0cnlBUDVFUUN5cjNOb0F0ZjZhcHhJcENvSGFtZlRI?= =?utf-8?B?TUlTSzRJcGYrTkNjbG13UDF4YUpmNFZydExNQ2I5bEJRdU5hbXZ3L0hBNmxT?= =?utf-8?B?OEZ4SkVNWSs1RWRUU0Z3VGZ0QkYrSVJrQzJHeGZUK3VUOW1qQ2lZangyMGI4?= =?utf-8?B?cWs2NVZsUlFlS1NTRFFyQ01hQlByQSt5R0RSdVRKanlsSWJqYzBOQ1pScy92?= =?utf-8?B?akJiRzZmNVVvRjV4V0Fic2ZqOU8rei9JTjhQS2tQS1N3bmpJazBuWEFvVHJt?= =?utf-8?B?WmdDSEdqdnRLNWtRTVNnc2ZFUFhoc3dRL2ZmTVJkRExwWUNFaEVFSSt3Yjhs?= =?utf-8?B?R0Q4Q3VJRGhVTjR1dE84Vm93VVhINndRaStYUVU5Z28xNkVmTzYrcnpiU3Fi?= =?utf-8?B?YkF6TG9EczdVMS91QkROTEN4R2FTQnppaUd1UVMvMkhRVzFhYTE0Y2lkWjRN?= =?utf-8?B?OWVQTzhJMnJzWUxHTGx0enkvK3luMWlKZjllNFpjNVR2TlBNc1RFdjBMajNQ?= =?utf-8?B?S1ZVTmUzTy84YUZrZWp0eTlVT0E4OUtlYVMwSG4rdWQwN0pzaUQ5ZUpVUXZU?= =?utf-8?B?SFh0cDh1Slo4S0dFOWh5emRESFRsVGR6TE5BMkV2V3RKT1pSN3VkNkxNYWRr?= =?utf-8?B?SUNMOGxqSTByZ0JSU0VIM2FMVzlYTnpwbXYyTDBsMHQ2ZlJUbnUrMmh0ZnhS?= =?utf-8?B?RVhvYVRqUzNuU3RjbVdVanR4bllwbnhtdzlzb0YxQ1NYSXR1cXUxaWs4RVhU?= =?utf-8?B?akZUWWZzTWJFS2ZBcCtIUDVlenJhS2ZEY3kyWkJoNi9wMDVYbWM3WCs4cjVx?= =?utf-8?B?dlYxTzc2T1RHRDFlK3d2cEhLK3VTb2h4RmxjYUxoOXRaQ2V4NDVCSUtBcGNZ?= =?utf-8?B?NWN1OCt2L2FPNUxXVWtrbmYzVk13ZEpVeU5pT3BrT1hNeFd5YWo0N0k5akxL?= =?utf-8?B?czZWcEM3ZzRTQTNjd0pZVEtWSzlIWi95bFRXVnM5MUdGcDVvemx5b0Rod2ps?= =?utf-8?B?NE0rQ1gwSk1yTGNQVzI0L3lwUHNhUVpNT3FKRWd3QTNTRTdQaHJxZUpuYkZk?= =?utf-8?B?WFVkTGRZZVJnUFM3SlZXblBaS25EZU9Za0xqTEovNUJnVEp4RDlKcU96czNl?= =?utf-8?B?RTNJQldleDlaSlYxKy9HMWc3dTIvS3k4RVpFVlhtNDIwZW9ycGZuSUhoSkE2?= =?utf-8?B?U1E9PQ==?= 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)(10070799003)(1800799024)(7416014)(376014)(366016)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?M1RVRk1wNGZqYmw1TG8rZk1HMFFBdjdLcHNqdDI0S0pnK0s4akJxbE1MK1RC?= =?utf-8?B?bUw3ODB6WU92U2d3c2FLUEdQbVUxdE5lVXFzRkZOOUJBcU5vZDZpYUJIcXRT?= =?utf-8?B?MTJqbXZyVHpySnBSaHhZdjRwdVNkMjIzSHBwU25EbnR1bHFNTzBxdytNQWpn?= =?utf-8?B?UmJsKytUaEkrY1QyZzlUZ2RZeTc0NC9RY3dJa3dLVUZuOHRJcFFSQTNYNUwx?= =?utf-8?B?eHFTdElLQnJubmZwVm4xcmRnaTFvOTFuTlhQdGE4VlJ0ZFAxeUJSS21laU5m?= =?utf-8?B?ZEs5eHZGRFFueVVUV3hneHpkRDlwOXJGb1hnSE4vckxSMXJxNWI4VUZpRVJW?= =?utf-8?B?SGhRR1JITTh1cWQvK3RFblJNTEJNbEtsT3A0SkxTTmNmQ1BnQzFTY0VaeGFv?= =?utf-8?B?RjRta2t1VXdZY3I0MGlCWkpybEFBbmUxc0F6RHZnZU15T2pEYlhlbk51SThp?= =?utf-8?B?MGc0bVRYY3J3M0hwUi9KVHBiKzRha0R4YjZjbktNZkYwTnBSQ3NtVkdqNk4z?= =?utf-8?B?cnV4Y3pRbDZJL0tubGpNaVFlbFFWS0VOY0VBQTBoUlVuK2NlZW9qaktqMHR2?= =?utf-8?B?eW9DekwwZ3orYzZPanhOQ01tQ1JHMUFVVUx3bG01bTZwcWxzZUVHb1RRS29X?= =?utf-8?B?eUdsRTNza004UmppVHZuMjJPMkUxRlBFM1JYRUxVd3lUY1lNMlA1SFJtQ1RS?= =?utf-8?B?S1luRHJ3WitTNlJwd25Id05yWWYrME40dm1sMDl3Q09JYjh6c0JweVBuQnNH?= =?utf-8?B?MVprYnhybUtVbFNSUkFnYXVMOFV3R1BmNnBuVkRES3RDZWp1NnpCZTR4RWFj?= =?utf-8?B?S0g1aG5TWDMrZXAzL0pJTHFVdzlFRmpNbGJUeDhZSHJiUmxENXdqdVM2K1c1?= =?utf-8?B?T3dHV1dIakdZQ1lTVm55SXhKNldVdElJTm5sYmgzUkJEQnBYUDJuMU9CZElX?= =?utf-8?B?d3RqZlF3dEw3Tm14Ym5IR250amFEY1hOK3JibjdpOENMYmJLMTU1ZFhCOS9V?= =?utf-8?B?Zm5uVG5wbklIMDVFN2hyYlRpSCsrWmtTZm1kZWVadTB4dGJpREk3TUN5bVhO?= =?utf-8?B?TU54bkt5OVB5L0VNdTc3UVhqazJSeVBDZ0ZvcG5NREwzY3R1SHhZcVhIcmZn?= =?utf-8?B?QXo2Mk5SaHdvWW50N0FnQWtGT1JOMjZuSVQ2NVhYVkxLbWUvcDhKc1ArQmc5?= =?utf-8?B?TDFzN1dBUWdmOXVvenh5L1JQZzFsWXVkZ1RjVEUrREx4bUNLT3lPb3doeFFt?= =?utf-8?B?Tm5VLytrN1BXSTdEb0R6NWt4S0xpV1V4dUd1ZXlYMWIyOVU3bXZoR3Y1aTFt?= =?utf-8?B?UFVEbmdHL0g4ZjJybUtodkhTYW9CdVpXTk1hMHRnd3J0SUNGeVpYUENCb1lJ?= =?utf-8?B?Z3dnWDVuVVRsdUFHT3g3TWdJemhKT2VINVVWRWVOQkViek9DNmJtT3cwejFk?= =?utf-8?B?c2JabS9LNVdFbmJvZnBJRHNlRk1KQ0owZVY5U3pOQzVqd0hRT3VuSVZlWUNm?= =?utf-8?B?OW5OeHppWUtNekFUeUxRYUoxV3pBWVp2a2RidVJkUVNzdEdSeUFlanRTaEQ5?= =?utf-8?B?VHRhNGloRDVzRUlmNTZTTkc5YTdUTGtwbjNwRm4rYmpEVHoyKzlNdVNtampL?= =?utf-8?B?bXBZQ0VzeXh5SGI2Qjc2ZkFTQlZnelREQVUyQmV4Tlh2aXpKVVRnM0xsQlBD?= =?utf-8?B?WW5Ibk5CNVRqTUdYUjNoc2g0V2MrWnBtQXp1OUlhLzF0Ym5hRW5aeFF1ODRB?= =?utf-8?B?cG9RdEtYS1FKVzExM2I4Z2tWMTR6S2ZGT2w5VGVaek1LbnZ6SlE0TXlicVB2?= =?utf-8?B?WFJUN3E4RjJZZHh3OGQzeW5ZV1U5NmNHSVRsVjc5RGlnUURrMmYrOVhxb0hK?= =?utf-8?B?dnREVWUxK2hRb1VRbWtMQk94eXdwbE9Ka3N3clp5OXNKYnlQQU43WU5PWjRF?= =?utf-8?B?NnRpQnhsaVVmdkFETW1QSmIxNkhNMVBhRjR5cFVIenU0cGt1YlVoQnI4WjV6?= =?utf-8?B?dGE5UHh0S0o2YkZ3UVFlYXlzS0ova0QySDUxaUdXaksxV0pucjdQMDdVTUQ5?= =?utf-8?B?Y09kdGo5UHB2QkNMNmhDR2ptMXpkdnBLWXVPNEdFTG11cXNDRDRHaFo2VERi?= =?utf-8?B?OFd1bFJRZXJEYXQ0UUFNeDBjK3AxYW9NSlhkNnFvKzRZdUgrVzZ2WVF5dlI1?= =?utf-8?B?UEQxVFRNM3FSRG0vK3U3TjhlVTY0eVpGcHZ1MFdCN1pIeGJUZ1o0d05kdEV1?= =?utf-8?B?ZlB1dFY2NnM3RzFrc0xlYk1DOEM2TW8zTW9IYlV1OGt0dTBsWENRb2FGdVVo?= =?utf-8?B?Z2tMaXZZeWtGcU5ZRkg1K2NZU0ZndU1saDY0VGhUdzlPaGs5RGJMSlpjZTh1?= =?utf-8?Q?f37hKEn/nMFQco3MMlYDyUvH0/9QMf7hsvGzQWPZwneOW?= X-MS-Exchange-AntiSpam-MessageData-1: PzfJkdv1YN1nyg== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 76d7c65a-163b-4d0e-23db-08de5f3adabb X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Jan 2026 13:32:31.8687 (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: OCYjLm6nxfwPOyu4iW67hgST7eaN+wE1zpT+LhG74eh57KPCsTiuh+0ObtnmAIUUTNH8TPJDyTzl6Qb1O/S5Mg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB8146 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 Suggested-by: Danilo Krummrich --- rust/kernel/io.rs | 1 + rust/kernel/io/register.rs | 1286 ++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 1287 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..9d6c265e70c7 --- /dev/null +++ b/rust/kernel/io/register.rs @@ -0,0 +1,1286 @@ +// 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 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. +#[doc(hidden)] +pub trait RegisterIo: Sized { + /// Read a value from the given offset in the I/O region. + fn read(io: &I, offset: usize) -> Self + where + I: IoKnownSize + IoCapable; + + /// Write a value to the given offset in the I/O region. + fn write(self, io: &I, offset: usize) + where + I: IoKnownSize + IoCapable; +} + +impl RegisterIo for u8 { + #[inline(always)] + fn read(io: &I, offset: usize) -> Self + where + I: IoKnownSize + IoCapable, + { + io.read8(offset) + } + + #[inline(always)] + fn write(self, io: &I, offset: usize) + where + I: IoKnownSize + IoCapable, + { + io.write8(self, offset) + } +} + +impl RegisterIo for u16 { + #[inline(always)] + fn read(io: &I, offset: usize) -> Self + where + I: IoKnownSize + IoCapable, + { + io.read16(offset) + } + + #[inline(always)] + fn write(self, io: &I, offset: usize) + where + I: IoKnownSize + IoCapable, + { + io.write16(self, offset) + } +} + +impl RegisterIo for u32 { + #[inline(always)] + fn read(io: &I, offset: usize) -> Self + where + I: IoKnownSize + IoCapable, + { + io.read32(offset) + } + + #[inline(always)] + fn write(self, io: &I, offset: usize) + where + I: IoKnownSize + IoCapable, + { + io.write32(self, offset) + } +} + +impl RegisterIo for u64 { + #[inline(always)] + fn read(io: &I, offset: usize) -> Self + where + I: IoKnownSize + IoCapable, + { + io.read64(offset) + } + + #[inline(always)] + fn write(self, io: &I, offset: usize) + where + 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 `with_` +/// for runtime values and `with_const_` 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_const_major_revision::<3>() +/// .with_const_minor_revision::<10>() +/// // Run-time value. +/// .with_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_const_major_revision::<3>() +/// .with_const_minor_revision::<10>() +/// .with_vendor_id(obtain_vendor_id()) +/// ); +/// +/// // Constant values can also be built using the const setters. +/// const V: BOOT_0 =3D BOOT_0::zeroed() +/// .with_const_major_revision::<3>() +/// .with_const_minor_revision::<10>(); +/// # } +/// ``` +/// +/// Fields can also be transparently converted from/to an arbitrary type b= y using the 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.with_start(true)); +/// +/// // Start `CPU1`. +/// CPU_CTL::update(&bar, &CPU1, |r| r.with_start(true)); +/// +/// // Aliases can also be defined for relative register. +/// register! { +/// /// Alias to CPU core control. +/// pub CPU_CTL_ALIAS(u32) =3D> CpuCtlBase + CPU_CTL { +/// /// Start the aliased CPU core. +/// 1:1 alias_start; +/// } +/// } +/// +/// // Start the aliased `CPU0`. +/// CPU_CTL_ALIAS::update(&bar, &CPU0, |r| r.with_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, stride =3D 8] @ 0x000000c0 { +/// 31:0 value; +/// } +/// +/// /// Scratch registers bank 1. +/// pub SCRATCH_INTERLEAVED_1(u32)[16, stride =3D 8] @ 0x000000c4 { +/// 31:0 value; +/// } +/// } +/// # Ok(()) +/// # } +/// ``` +/// +/// ## Relative arrays of registers +/// +/// Combining the two features described in the sections above, arrays of = registers accessible from +/// a base can also be defined: +/// +/// ```no_run +/// use kernel::register; +/// use kernel::io::register::RegisterBase; +/// +/// # fn test>(bar= : &T) +/// # -> Result<(), Error>{ +/// # fn get_scratch_idx() -> usize { +/// # 0x15 +/// # } +/// // Type used as parameter of `RegisterBase` to specify the base. +/// pub struct CpuCtlBase; +/// +/// // ZST describing `CPU0`. +/// struct Cpu0; +/// impl RegisterBase for Cpu0 { +/// const BASE: usize =3D 0x100; +/// } +/// // Singleton of `CPU0` used to identify it. +/// const CPU0: Cpu0 =3D Cpu0; +/// +/// // ZST describing `CPU1`. +/// struct Cpu1; +/// impl RegisterBase for Cpu1 { +/// const BASE: usize =3D 0x200; +/// } +/// // Singleton of `CPU1` used to identify it. +/// const CPU1: Cpu1 =3D Cpu1; +/// +/// // 64 per-cpu scratch registers, arranged as a contiguous array. +/// register! { +/// /// Per-CPU scratch registers. +/// pub CPU_SCRATCH(u32)[64] @ CpuCtlBase + 0x00000080 { +/// 31:0 value; +/// } +/// } +/// +/// 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, stride =3D 8] @ CpuCtlBase = + 0x00000d00 { +/// 31:0 value; +/// } +/// +/// /// Scratch registers bank 1. +/// pub CPU_SCRATCH_INTERLEAVED_1(u32)[16, stride =3D 8] @ CpuCtlBase = + 0x00000d04 { +/// 31:0 value; +/// } +/// } +/// # Ok(()) +/// # } +/// ``` +/// [`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 =3D $stride:expr)? ])? + $(@ $($base:ident +)? $offset:literal)? + $(=3D> $alias:ident $(+ $alias_offset:ident)? $([$alias_id= x:expr])? )? + { $($fields:tt)* } + )* + ) =3D> { + $( + $crate::register!( + @reg $(#[$attr])* $vis $name ($storage) $([$size $(, stride = =3D $stride)?])? + $(@ $($base +)? $offset)? + $(=3D> $alias $(+ $alias_offset)? $([$alias_idx])? )? + { $($fields)* } + ); + )* + }; + + // All the rules below are private helpers. + + // Creates a register at a fixed offset of the MMIO space. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) @ $offse= t:literal + { $($fields:tt)* } + ) =3D> { + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!(@io_fixed $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> { + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::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> { + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::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> { + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!(@io_relative $name($storage) @ $base + $alias::O= FFSET ); + }; + + // Creates an array of registers at a fixed offset of the MMIO space. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) + [ $size:expr, stride =3D $stride:expr ] @ $offset:literal { $(= $fields:tt)* } + ) =3D> { + static_assert!(::core::mem::size_of::<$storage>() <=3D $stride); + + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!(@io_array $name($storage) [ $size, stride =3D $s= tride ] @ $offset); + }; + + // Shortcut for contiguous array of registers (stride =3D=3D size of e= lement). + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) [ $size:= expr ] @ $offset:literal + { $($fields:tt)* } + ) =3D> { + $crate::register!( + $(#[$attr])* $vis $name($storage) [ $size, stride =3D ::core::= mem::size_of::<$storage>() ] + @ $offset { $($fields)* } + ); + }; + + // Creates an alias of register `idx` of array of registers `alias` wi= th its own fields. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) =3D> $al= ias:ident [ $idx:expr ] + { $($fields:tt)* } + ) =3D> { + static_assert!($idx < $alias::SIZE); + + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!(@io_fixed $name($storage) @ $alias::OFFSET + $id= x * $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 =3D $stride:expr ] + @ $base:ident + $offset:literal { $($fields:tt)* } + ) =3D> { + static_assert!(::core::mem::size_of::<$storage>() <=3D $stride); + + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::register!( + @io_relative_array $name($storage) [ $size, stride =3D $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> { + $crate::register!( + $(#[$attr])* $vis $name($storage) [ $size, stride =3D ::core::= mem::size_of::<$storage>() ] + @ $base + $offset { $($fields)* } + ); + }; + + // Creates an alias of register `idx` of relative array of registers `= alias` with its own + // fields. + ( + @reg $(#[$attr:meta])* $vis:vis $name:ident ($storage:ty) + =3D> $base:ident + $alias:ident [ $idx:expr ] { $($fields:tt)*= } + ) =3D> { + static_assert!($idx < $alias::SIZE); + + $crate::register!( + @bitfield $(#[$attr])* $vis struct $name($storage) { $($fields= )* } + ); + $crate::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> { + $crate::register!(@bitfield_core + #[allow(non_camel_case_types)] + $(#[$attr])* $vis $name $storage + ); + $crate::register!(@bitfield_fields $vis $name $storage { $($fields= )* }); + }; + + // 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>, + { + let io =3D io.deref(); + + 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>, + { + let io =3D io.deref(); + + <$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 io =3D io.deref(); + 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 io =3D io.deref(); + 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 =3D $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 io =3D io.deref(); + 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 io =3D io.deref(); + 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, stride = =3D $stride: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 io =3D io.deref(); + 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 io =3D io.deref(); + 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 { + $( + $crate::register!(@private_field_accessors $vis $name $storage : $= hi:$lo $field); + $crate::register!( + @public_field_accessors $(#[doc =3D $doc])* $vis $name $storag= e : $hi:$lo $field + $(?=3D> $try_into_type)? + $(=3D> $into_type)? + ); + )* + } + + $crate::register!(@debug $name { $($field;)* }); + }; + + // Private field accessors working with the 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 [<__with_ $field>]( + mut self, + value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>, + ) -> Self + { + const MASK: $storage =3D $name::[<$field:upper _MASK>]; + const SHIFT: u32 =3D $name::[<$field:upper _SHIFT>]; + + let value =3D value.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.[<__with_ $field>](value.into()) + } + + ); + }; + + // Public accessors for fields fallibly (`?=3D>`) converted to a type. + ( + @public_field_accessors $(#[doc =3D $doc:expr])* $vis:vis $name:id= ent $storage:ty : + $hi:tt:$lo:tt $field:ident ?=3D> $try_into_type:ty + ) =3D> { + ::kernel::macros::paste!( + + $(#[doc =3D $doc])* + #[doc =3D "Returns the value of this field."] + #[inline(always)] + $vis fn $field(self) -> + Result< + $try_into_type, + <$try_into_type as ::core::convert::TryFrom< + ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> + >>::Error + > + { + self.[<__ $field>]().try_into() + } + + $(#[doc =3D $doc])* + #[doc =3D "Sets this field to the given `value`."] + #[inline(always)] + $vis fn [](self, value: $try_into_type) -> Self + { + self.[<__with_ $field>](value.into()) + } + + ); + }; + + // Public accessors for fields not converted to a type. + ( + @public_field_accessors $(#[doc =3D $doc:expr])* $vis:vis $name:id= ent $storage:ty : + $hi:tt:$lo:tt $field:ident + ) =3D> { + ::kernel::macros::paste!( + + $(#[doc =3D $doc])* + #[doc =3D "Returns the value of this field."] + #[inline(always)] + $vis fn $field(self) -> + ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> + { + self.[<__ $field>]() + } + + $(#[doc =3D $doc])* + #[doc =3D "Sets this field to the compile-time constant `VALUE`."] + #[inline(always)] + $vis const fn [](self) = -> Self { + self.[<__with_ $field>]( + ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new= ::() + ) + } + + $(#[doc =3D $doc])* + #[doc =3D "Sets this field to the given `value`."] + #[inline(always)] + $vis fn []( + self, + value: T, + ) -> Self + where T: Into<::kernel::num::Bounded<$storage, { $hi + 1 - $lo= }>>, + { + self.[<__with_ $field>](value.into()) + } + + $(#[doc =3D $doc])* + #[doc =3D "Tries to set this field to `value`, returning an error = if it is out of range."] + #[inline(always)] + $vis fn []( + self, + value: T, + ) -> ::kernel::error::Result + where T: ::kernel::num::TryIntoBounded<$storage, { $hi + 1 - $= lo }>, + { + Ok( + self.[<__with_ $field>]( + value.try_into_bounded().ok_or(::kernel::error::code::= EOVERFLOW)? + ) + ) + } + + ); + }; + + // `Debug` implementation. + (@debug $name:ident { $($field:ident;)* }) =3D> { + impl ::kernel::fmt::Debug for $name { + fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kerne= l::fmt::Result { + f.debug_struct(stringify!($name)) + .field("", &::kernel::prelude::fmt!("{:#x}", self= .0)) + $( + .field(stringify!($field), &self.$field()) + )* + .finish() + } + } + }; +} --=20 2.52.0 From nobody Sat Feb 7 23:10:59 2026 Received: from SA9PR02CU001.outbound.protection.outlook.com (mail-southcentralusazon11013068.outbound.protection.outlook.com [40.93.196.68]) (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 D36D634FF61; Thu, 29 Jan 2026 13:32:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.196.68 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693560; cv=fail; b=fh7b8VbB5j3BCuCynf5uWTUKTU6D3z9HVK4UVP5ThJ+lpmThw45FG81FfWt6N4Lh6UL2i8Zwp7FEJd96CbQWK38d+JTyRf1qbMXchxVjm2z8SH/as26yv7FzyE8/uD1IDWQZ3xuHqUkTVvkydnmi9O6sxojTykNFNTe6gjmXHXk= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693560; c=relaxed/simple; bh=6MiXBt4lDx3bpMkX0Lw2s942vGdsWZGwxkBHCJOfzCI=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=FznbLWsHcEEq2tQjIdvj08GK1Var1sOqrSSSJSaiEw6WZR3oNy0PaA1kz6GwKD99tbLalvROfL7h4TgCDPjJEW2riDDmWg0TCdWVpMRRHJE8J4MzbmwzuA0ARbcteyNJMqDGFHI719BdZQyTwQqM/haXWjagxRjloH0TdA3O7SQ= 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=TCOL4Nux; arc=fail smtp.client-ip=40.93.196.68 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="TCOL4Nux" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=uqghel9EmOSnxnH1i9hmYwtO2lKp1cLk5YcWYRypOd4Eaqc9MK+GSO3c60i6Fvjizmx6+zsefncEgXkRHQOz1mjtuTk2evZuePTgvehZP/aNsjhRp90+KadHdiTtycDtu4CF4JwDTB9L2DXuxNeLtbG44ej+JGpryh9RZw81FkzXjtWBRSTg/WIOruj58bYUOBxdfKR8SbW3Io4dF0yKOE7TWM0UqXFneMxad5ikDWk6fcMRdpXZWhW91pXY8JWSVu0vIdaKzmp80XD7jCw4cjHNwq/41NIUHm6WTdTuEv4H53RhEH5Rgs3kG5NZJ04yqx9w1Zp8qI9Ps93KMjYycw== 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=erNDtKyH6VHGO5jv2oZNK/1Ju4ma6zgs1RHsz7tXJS8=; b=WZZD3nXhcOch7xFjTuyLO95qo3y4Nb3tO5urEk+oP30wnBNY1DcLGGNvg24pf5iCx7SG6c/79Ok4v9k1+wnGjPe4LDChcAtHzLU6+5DWeLNynJhbthuw4CPKCcbp9tjduLO9ti9DqSIxuA3seO2eVhi+NyqpgNKB1dKJ+MqHqDBPM/k2N06ebgHDZP+DmSU3im7G4KwISrR9N7JGpJWktQ/L8A0jI9RYjeI1+dA0rRruMfL7Tn85JQBPD5aAth42W3GHPYuYe3dgahFyHgXv1O03VfWWkq4xnFqQxUqEGpn1cu9C+RT3ASpF+XLoMHvMe6Ct4C98M+ubBYqxOam5bA== 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=erNDtKyH6VHGO5jv2oZNK/1Ju4ma6zgs1RHsz7tXJS8=; b=TCOL4NuxBXHsSJFcF6J71hSy1bIP6CXLaAzhvH2rzJbiTYeScoBh01B+L8uXnkZG6Ok7YarmHV6tXYCGgUrG7uP6MPGU1mgQEk1IQPzmalSexWv3kav2vrdRcb5oOqU9BcIIYGwuvjEKm6PU3knYz9YrRiIQMGEbYQeqdbQI5Upgt8nCodnJT6f/pZ5cd2tCrr8FFVcMqxV7hpk36qlQ1adO+crqG/z6OieopJmhsHA68vmNyljQFY6AZwg68Tg9dN721S1/9LSJBMNtihgHai8nL6iiHOrFp7C+GGfU4JxXNAvm5tOI7TGgCxOCYU9F2riBjFlCGdzyVxm+XRZbAQ== 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 SN7PR12MB8146.namprd12.prod.outlook.com (2603:10b6:806:323::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9564.10; Thu, 29 Jan 2026 13:32:36 +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; Thu, 29 Jan 2026 13:32:36 +0000 From: Alexandre Courbot Date: Thu, 29 Jan 2026 22:32:06 +0900 Subject: [PATCH v5 6/7] sample: rust: pci: use `register!` macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260129-register-v5-6-c4587c902514@nvidia.com> References: <20260129-register-v5-0-c4587c902514@nvidia.com> In-Reply-To: <20260129-register-v5-0-c4587c902514@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 , Zhi Wang X-Mailer: b4 0.14.3 X-ClientProxiedBy: TY4P286CA0028.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:2b0::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_|SN7PR12MB8146:EE_ X-MS-Office365-Filtering-Correlation-Id: 7313e742-a38d-408d-9c48-08de5f3add1d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|1800799024|7416014|376014|366016|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?czJrL2VrdlorZTVUaEt6b3lRVWxLeFpyQnRRd1F1TVBYRmhFOCtqM0hvckRX?= =?utf-8?B?cGhiVFQ3UWVrL1hmUmdsaHI3dGJnSkxPOHdKNlNieVlnaTlzNHJmY2JxaEZL?= =?utf-8?B?SndST2dVYzQ5MFpOZG5mTXhzZDNMT0g2SWhFcGRNYUlvZ0p3MTV0bUlnM0pG?= =?utf-8?B?WHNBUE1xdDhKQWZLTEhlRW1sek9nWllhWCs4M1JkQ3lxQWRQa3hvMDJZNmg5?= =?utf-8?B?OUluemhiWlh3UDRkdWNtbkt6bE9oVk55V3Vta3k1MHI0VkFQVzhaWGlWeHZS?= =?utf-8?B?SVNUT2NOWjBxWnRGZSt1ekg5NFNQTXgrRkZPRys1akllYXBsV0ZWMEFHMTRK?= =?utf-8?B?Q2dIK2luTkZabkhqM1FlSnpBZlBZQ0FHYW51ck8wYnM0WUErOFNwMXVSWGNr?= =?utf-8?B?ekFkd2llMlNwd3RIdFpKbmhIbCt3SFBVNDFsdk9LazFUUE5FT0dUWS8yM2Mr?= =?utf-8?B?Wm1YWVFxUXRoNWtUbnk2U1lBUWlMTkJFK1pFUDkzVXBhRXpvSmF3K1I3MklE?= =?utf-8?B?ZXMrTHJxc2l3MVBxSHc4dWhHWEFPVGRqR092S3EvUFlFWUxjVmhKZzJQNjA1?= =?utf-8?B?T3lPdjU5RmQvbjA4dWdqOElCTXpWM2ZCRzNwTEtkdzBNSzVtWC9Rdi9PVGl4?= =?utf-8?B?RXJ3Szc0clF5WUJDdFlhMGdLRnJ0aEViQitrZGo1VjBjaWNVTFJodDBnaXUy?= =?utf-8?B?WVU5NUhPRXExRFpFTEFwZkhKaEZBdWpSUjhSdkd6cGlIZ1ZtNFAyMG9yNWlU?= =?utf-8?B?ZUxFczlOWGliWm14UWIydG1JdjhjSXRZSTBRQk81WEk4Z1RWUUp1WlBSZzh6?= =?utf-8?B?SUtodUxuSUxPdTZ1ZU81SmpQZ0J3V09CMi9iSVIvVjJxenY1YWNhckNlQUZL?= =?utf-8?B?NG9EMnJ1bW5xZ3FmN3RYRGNKWXFsOGJIMWphRHVzTXhjL3ZGWFd2RGdnaTdF?= =?utf-8?B?Yzk3Mm5ORlEzOTdobkNNVlVpTmpMNHhrRjkvSGo4OE94bTNHZHdOVU42SldW?= =?utf-8?B?MzlFUlJRTGY2WlNkRlBOS1hvUk1oMXZNWFZteXk2YWhmVTZaZm1xYXkxSGFm?= =?utf-8?B?WUdaQWJsMldMejVVOE9iN3FleVdNNWVla0RFYzVZT2hFRUNxT2VSR1FiQnZZ?= =?utf-8?B?bEpRUUlDUnJQYkEyV2Jwd3RKT1dOdlp3MGhvZzEwY3RCS0lydXpscVErUHdl?= =?utf-8?B?NEpGcjc4eXlTajFEWDZhWEQ2YitqY1U0TmMzVzdTS2E5cVcwaHRPYkx4V01B?= =?utf-8?B?MVZDNk45a2FLY0NsZ0NuUmdxRUQ1bjA4L012YmZIOUloclQ1OHp1bHlJS2dx?= =?utf-8?B?UjUrckZmcnRNeGZxR2RNUHNIZk5yUGwxeU1ZZXFteS93UHFXQUVOcSt2VWtJ?= =?utf-8?B?TmpabEpXTG5lR1ZKN2xXZ0l6dmtHbzRXWi9uU29UQjB2THM5bGpIbVdyY3Bm?= =?utf-8?B?TWF2aFF1VmtJcXRmRzhkL0pwWmNYaW1CdVp3enFHS21JM0R4dEprUy9sYVJ2?= =?utf-8?B?M3pTSkFEUDl5MXAvSHMxdzV3SlpEMi93MlpRVXNyZW11d2YwbTdHdEJYRGRC?= =?utf-8?B?bFpPOHU3VW52bGMvZnBWbGF4eWxITTJSYjh4N0tXL3M5THN1aFJvNXRwU3c5?= =?utf-8?B?K2hNSHVvYXFPYWIxVUIvd0tHblk5Y25tdk9hK2RPNkVySHpDYjBkZDcxUEph?= =?utf-8?B?bVRoRVUzSHk4ODNqQ2FUTWR3Vi9yTEJnaTIvUTFxemM2ZUhVa1llMFp2djl2?= =?utf-8?B?WHViMWorTnhua2I0WitzNEM1SXpYa3JWWkE0QVFtd3gxUFBMVSs5Rlg0TmQz?= =?utf-8?B?cGI0ODkyei8xczJlTnNlc1Nvek9tUGEwNHMrZTJKZDNKRi9GYnY3eDBxWWdm?= =?utf-8?B?aXNZSDdNSkhoLzJuSWlQTzBUNnFuT3hXeEdCeUR2K2U3aUNPdGpTMjJpODQ2?= =?utf-8?B?NmNTbHJPZWdKZmlhejdiUG1LektwcVY5SnVNaEtYT3hSZmtBYnU3NFp3R0VM?= =?utf-8?B?enVSSDJQSWZmYkREWUhTMGVNVzdZQi9XeTQxQVBVNklMNTJmNS9HeVhWZlV0?= =?utf-8?B?RE9NZDJoMkUvWjMwdzRRVzdHeEdPVlp6WTZFUksxd3hWcnBzZStMSGZxRFFP?= =?utf-8?B?VVhIcVlmRi9reVRvU3Y4ZXdGOGRBenpMZXZyVnExR2lkR3JvOFZ1NG5KZi9P?= =?utf-8?B?a2c9PQ==?= 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)(10070799003)(1800799024)(7416014)(376014)(366016)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?dGgyZmc1amo4YlhEYmZsYVNvSkxFa2RWcDBkaC9kcnJUMWlVeXlEOWc2eWhC?= =?utf-8?B?ZnJoUzJJNkNHSFVrWmQ2WEZKWjVDWmpYNmhrTllzOWNWbGVrVWJ2UU02LzVj?= =?utf-8?B?a0wvRHFwZmFVcXpDZDlSZXIvSUM3NEpsQ2pSRTVWcVBVWlpvNituSUQrVEhQ?= =?utf-8?B?T1c4UDdZYkRnWTBzZStoZW5UOHgzS3QwU2JGS3FqNDNSaTArVUFZNjdNeXE1?= =?utf-8?B?cGFDWUVhM2J3ek9KUzFWUzNIalUwZkxVY0k2a202Snh4dzJ5Ri8zV0lnQXRw?= =?utf-8?B?TDZBU1hyWmtEanB0c2hEa0phZC9XWEVhU2RFODEwb0Jwd25IWURYd01VRlNl?= =?utf-8?B?ZHpwTnpTSHhqeFBuWmxHTjJGRnI2QTF6UTZtbEhBYkZpQlJ0TnBxdWRlWXJv?= =?utf-8?B?bUppWnltVmlNcGpEbzN4aTkrUTZOQzdjZG9LTTdhSU9QVnZOWEtERmRWWnNS?= =?utf-8?B?RzRMZUMxdHNCdHYvNXN6T1hOMXR0aE5IanhCd2wwU2JuaTQzSlZvNEF1MVBE?= =?utf-8?B?eXNzNWlTajkrbzNma09FTWZMakRSSFd0Vm12bmNEK3pDRW5pUi9xSCtvdW5i?= =?utf-8?B?dmRyZkhZVnYzTzk5V2FUc1JsOXZFZ1R3Q2dZalFmWjVKMWpVbGl5T09jcnpi?= =?utf-8?B?RDhMOVEvRzEzTGlFS0ZldkhxNE55MlRYbTh2RFM2T0xGNmF5SFl6WU5NL3hV?= =?utf-8?B?NGNOSDBTaVhDZ0lwTjlKS1ZUYjQ1ZTVJaFNmZ0xSR3VETm5IbE16YUc2Q0ha?= =?utf-8?B?enBrOUlSSE1tekRsZFAvSVNvTWVrYzZjdVRwY2szbkptK3Y3bEpxWjZDRGdU?= =?utf-8?B?dnJLR2V4R2FTY1pqaTRneTJhZy9CS0ZlbE5mNDhKaWZyT3NRdEtoN3NrdEpn?= =?utf-8?B?dWE3c1Zpa0JiNnhKRnREcjh3NGsrV2ltUFNDRitvWEdabVlCdFpNcU1TUzQz?= =?utf-8?B?ZEhPMjNlZEUyZERhRWRCS3JucW5rdFRQRlg2TDN3UVZrdWxkVHJQQjFidWJ1?= =?utf-8?B?cHVlbWU2L0lTOTFjUkN4UXArMVdsamxObUZEYWdBeHUrU2lUOFF2M1dIaVVs?= =?utf-8?B?RlBEMnQ5KzlvTCt4dHF5ZWVwTjdBSW85bnBiaFJaZUZnNmh5QUJ0MXNUT2Iy?= =?utf-8?B?bG4vU2tIRHcxUThMa0ZNTmsxQ3VqR1RHRzlGYmt6eTV0VER0OVh5NDZndFZR?= =?utf-8?B?ZWNvUkJzMkpJb2ZsbHFCOC9DMTFoVHRFSnNlTHRKbnR4RmFwSlFtdTZNT2wz?= =?utf-8?B?Ynd0S2M2N2FDUDEybkdibDM1SDZhc2RiM2Y2MzNqSG1sVWRsekYrUnAxdG1G?= =?utf-8?B?VkdPQ0JsNmhiUkJGYXFHNEFHR3pMelhIQ2dEK1MxRFYrK0ZlV0ttSWVucnBC?= =?utf-8?B?bmJ1NVJCTE43SVlZOXhuLy8zYjdBenBKUWlnL0U4MmhOU0pPbGwwYnVQVlFJ?= =?utf-8?B?KzREbFJsaFFtSHRoYnFJYmZnd2tlUkREdUYxR3BDYUgvU0NIL21VNGlCY1Bz?= =?utf-8?B?VG5OakNDTUxhMXNESHpVSW9JUVF2NWpRNDV3UkorcjhZb0hLQTVMUVF6SWdQ?= =?utf-8?B?WnIwbEdvT1NLUVVEQ1dqaFczR2pROFA0czJMTU9jdS85T3NEN2grN2lUNGIx?= =?utf-8?B?eEhvN1lVNlEzY0dMQThrMHNpSTg0TmV2b3RTR0VXS1JwNDVxV08vdUlkbmZa?= =?utf-8?B?OGhUeDc4QlJCUG55SzhtRjF0bEFIVXlEUTRJVmJWYm9ZOU9hcXhnblZkOW5s?= =?utf-8?B?dUl3UkdQOEZSWGZRb2FPWHhWOUFLRTFyaXd1Rjk5ZnVxSmFoTldjTlQzaHVR?= =?utf-8?B?UGFyeWlaWklFUnNMRk13cXA5blpMWm5NQThpYTJSbnBnUHlaS2hwenlYNnFz?= =?utf-8?B?aURYSExpVVRnVmVKamlzNVhrT1RzaDN4SS94VjdDUWFiMWtDNGN0bzJESmk2?= =?utf-8?B?WXdRRUE3bCs0dEhPeGxKQmFjOSt4ZjkyclI5SXR6ZXRsazBtY3JIVlp5VW5x?= =?utf-8?B?NEVGUm1VbFJTbUdlWEE5Q2lXM3Z3QnMvUjh4Y1d3NWJ6cWZvVEd4czNwY3hv?= =?utf-8?B?OUdieGRmOGVEdDBtSVlqMGdpTFhmUTUyUlJDL3pYMFRoOTQ3dG5wOUczTDhj?= =?utf-8?B?ZTRRVzFsTVl2Wk9mZW1xeW1SZ1MzZlBkbVRYWEtxMG9yUFNSbGZkR3JPSHRT?= =?utf-8?B?enlzWHBYYmpkb3M4OGd5MUhtWnVYQTJoYzVLL0taSXc1OWRGamoxWmFQYWV5?= =?utf-8?B?bW5Jci85dWx5TXZkRFNNZGFNSUdYZ1daWlhXRGFiRjdiNkhUSWxzTnZZczFR?= =?utf-8?B?ZFJ2T0dzNVF1Vi9GdGtvbWZ6RmxxRTBnODBhd1kvNWd5QnFqNWlrNDNXbXlR?= =?utf-8?Q?gsGWFbjQ8+I/S39wBKUjA4iaXLJmR0SQ0SoE5P84wbTfu?= X-MS-Exchange-AntiSpam-MessageData-1: FWfBgPonBBfZAg== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 7313e742-a38d-408d-9c48-08de5f3add1d X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Jan 2026 13:32:35.6901 (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: NSRp/Q37zNruLx1ohyStv1KUVJm8DQTry5yTft988EfKNNNq8vqeSHjQHFMBXabGPnO1sTAF7tFQMtz+PNJbrA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB8146 Convert the direct IO accesses to properly defined registers. Tested-by: Zhi Wang Signed-off-by: Alexandre Courbot --- 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 23:11:00 2026 Received: from PH0PR06CU001.outbound.protection.outlook.com (mail-westus3azon11011053.outbound.protection.outlook.com [40.107.208.53]) (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 6386630C348; Thu, 29 Jan 2026 13:32:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.208.53 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693581; cv=fail; b=kfOVKYzv92b3CS14sLdkykbcM7rVNrmCzPLAoj05FRk2ccPqbi5HCjSRkHBCrW72/JDPmRAStFY9YKydBaRBM9dRTS7Nhtxf/XRl2WReZ2WEy2rd4/h87HEig1wW1ehew4UPzA0BTe2a8GTPnUgXSkxAqLBQC2ny7bTTgE0WX2Q= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769693581; c=relaxed/simple; bh=84GgaeUK76MqxYiLtftWiaa1VTpis6lhPo4+6tn9S9M=; h=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To: To:Cc:MIME-Version; b=RTt2mtY69u2BPbn/FRj3sWs+YyUCjLD39OLrSvVI4U9g1Ue6LW9k2kH0KoSVwNWJYdAU5Momb5EMNmpT9v0Y3k8zE3z8DetZIgmIcGYYtXoPxPZ9H2oV3l79zLGa0ATu+ZbNNK7ustr3Oqo3ucXoApA+R/qBp2NmyqOrrXzxols= 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=uNMijKD+; arc=fail smtp.client-ip=40.107.208.53 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="uNMijKD+" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=A+ktt3C2OScBbvSsZHB4keGwwPtfhgqcl4qG//tzn6tliSQRHRhxLNiHI4Jq0ZctuZkPg6qv7xLtGLaVRJyrfhyX7sTVln1tXIyo1htnx0OT+IGeAqOyIigmyRW3TDeEKxARRPZJIaxgYvAeXUr/X17OA50v+YWJWSKlbLdRZ7xSSTUeTRm8oqVRilWmxdb+omdBwOBZN5L5tgZA5Qp352j2mVbNW3l22YIVzamreMXlWSWR7krmvKP32sbSPaV+B38n9gqNmUMFniGu9LJE50q1QhlZdadF3c8qH5qs4djsCIhsQ1Nv2K97ByylCH96p6uTM/rs9CM0MpZaVLhLCQ== 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=oqQBkLUCF5QIXSLvyFriHiYerpueabINsmH/dfLFJBo=; b=lcwphmTBN3WT7ZrGN390IbgC/Bb+ViDRGPaZxOlMsLsimA0mnWnKcJoHPgT62SAx0AstoDDLkBl+9CgI1BLYEg4ziAxqw4KiTv0KQzsH0riowPwyy2ZG66XFQNxiatZpam3D3IyK4RYJZJfT2YI9jtrqVPXmZNHZms67YfWoc1rTniqgq4AWcLlAAv3EFnxxfAIgLNNC+Omwij9yE0YL7b4D/k1rJTjTOW+ETM7b/5xwDliBMf4P53QXBS3Zjw8hoJi89MTXQ1iSPlJxCSvapDZQJ9ySRa0ZlOQndk9rbckYt20K8jSkv9ICZ7fIGU/bAAjDSzVOxoXfeuhAI4tF4Q== 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=oqQBkLUCF5QIXSLvyFriHiYerpueabINsmH/dfLFJBo=; b=uNMijKD+Uhy/yv8jZ2/bXqulNzVLghbPA2OIe6oT3Ze9mANOR8lwae2secny2LCoo6xyulpibQH4jP7f888r8MooKdCnTm34hUiRhRxTMj2xLU7BPo8TKSINE1CKXXywu/WAjHduN+ohViwRUE3mbIqGxBgr/OlxjIYQlsjxdBHj6fDyyG2keVh1RaWJB6SVtkeiqLvEPvIYPdBSRUody9av3m0q1Q2dt9QIrxznEPk2oZ8QnQz0ZitwgIHaiqpMMwlLmvAdYh1gzorCb+xfNvl7nkT0cbzb+8FmTRejkIEVAWhPEMVB+Xv1I3rILEz/Py/g39sZ6SD7Hh9upd3HkQ== 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 SN7PR12MB8146.namprd12.prod.outlook.com (2603:10b6:806:323::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9564.10; Thu, 29 Jan 2026 13:32:40 +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; Thu, 29 Jan 2026 13:32:40 +0000 From: Alexandre Courbot Date: Thu, 29 Jan 2026 22:32:07 +0900 Subject: [PATCH FOR REFERENCE v5 7/7] gpu: nova-core: use the kernel `register!` macro Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260129-register-v5-7-c4587c902514@nvidia.com> References: <20260129-register-v5-0-c4587c902514@nvidia.com> In-Reply-To: <20260129-register-v5-0-c4587c902514@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: TYCP286CA0007.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:26c::12) To CH2PR12MB3990.namprd12.prod.outlook.com (2603:10b6:610:28::18) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH2PR12MB3990:EE_|SN7PR12MB8146:EE_ X-MS-Office365-Filtering-Correlation-Id: b9744ba6-d42a-4b29-c1af-08de5f3adfd7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|1800799024|7416014|376014|366016|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?WVZzeW0rNWt4Y0UvT3dvNUJmMGxJblYrTlRJOURCTHNwL1BFWDJobDJQK3JI?= =?utf-8?B?RFlJRnJXczlnNlU1N3J6QnVHdGNZNXNERU0rK3dxTFQ2Tm94RXJLTDhsQ3pt?= =?utf-8?B?SFlaVFVNYWl3NDhobXB1bzZqRW9hWlM1SlZpOGJYOFlmUkpaU3RFOGRGSHps?= =?utf-8?B?QmFBQWNVTDN1MHBDZzRPOU4rcUxNS2QvY0JnSTlBd3Y3YnJJaHNLYVBWOUZL?= =?utf-8?B?U29mNFlFZnFFa3drd0FVbXVPaTlEckxaUERkTFRwSzNxQ0NiTC9rV3h4STJU?= =?utf-8?B?S2k0L2JEN0QrSU9ETG5zT0FpaFpFemdmZTkxNXJGQVk3MzdnTlR0YTNQZDJY?= =?utf-8?B?bHc2TXVSWVBpdmZucjBLeFhGcnordFlFV3VxY2NMOTA4RkxtNks0NUw4ZHp2?= =?utf-8?B?akJxR3VKTXlpSEdVb1NNQnV1QmxOTjVaMFlqcGZzODI4UUxOQkNjdzA2eEdY?= =?utf-8?B?S0drWkd5SU1ScDhBd1FUZ0l3dkVuWVhSVHd1RUVIOVhKQUpGR2E1VnNOdHRJ?= =?utf-8?B?Y00zWjZKOElGSFh0UHdmckV2MTQyVWk4aFMwWnFEYkpxL0xpY2JwQkUzOHpM?= =?utf-8?B?Vk9wMndKZHEweWV0aHBWNjNKd0FqemlyV1h5b2k3NlFxTXAxd1A1eVV0MEFW?= =?utf-8?B?UWxOZmFIVmdrS3JReHRBU0hwbnFtdjV4bU1vMHcwR2NoeUJaQ3VldGFqWHhG?= =?utf-8?B?R3VYQzl1SHRxWHQ4cVU3ZndabzJxUEJ4dW50KzRNYzc2TksrMEpiWmZTTjVv?= =?utf-8?B?YUlFd3haaDRudkMvK09WT3V6TEV6d1hKbmpYMisyWUg3YzlSUjhkWVNuZ244?= =?utf-8?B?bUQ5Uy9lTFZweVRSTzAwZExIK2QxOWZmN2JzMndpN2dwdEJTQmxrYUlWK3JU?= =?utf-8?B?Tmh1dVN6dDFKVHBySzNIZ0paV1NwVjQ3ZXpiMXdSZTFDNGRITVVjcXd6RndB?= =?utf-8?B?OUhKcy92WE15eXpwaHk4SVhlTnB1RjNLUmFQOTBmK2d3TlkzNUsvWWlPc290?= =?utf-8?B?NzhTZ0h1cW9PYUpYOWR1S0lleHROZEVjSXlKY0dqeGRqSTZOYXdNZkZmN2Vz?= =?utf-8?B?ZHpLL3VBMVhudXNxdEQzazM2R0F4VEsxNjdSNyt5VWhIYnVsbU1SVTl0MTl5?= =?utf-8?B?OE44S2QvQkRXYng1dG41YUg1SmdzVlhWaTRQWEFkRFkyUHNlbTF1dkcwYUZY?= =?utf-8?B?MkY3NGJNNjNWeDVaOVZzQ25RV0o3ZGtnbmF3aUpRVlMxTHE1S3V1V0xmOXdN?= =?utf-8?B?dW1FeUdSVG5JV3JZYStIMFNuSFhjUFFBN0pnd3RFY0xKbktXUEhHdEdMMmht?= =?utf-8?B?dHB3UlRHT3dicmwvNzJ5eWxuRFRTWnJZMzJIR1dIdVNKdmpMLzJXTjQ1ekZ1?= =?utf-8?B?RC9DWXVDdVFxQ2lFSGpGNXZxTGJMS3A2ck1tZ0hyUzFtMlFTQ3M3OW1IZjJ6?= =?utf-8?B?Tk5JTUdUdlJQMFFqNytIczFTZStJVENZbi8raGluRmh5eVYrdGErTXZPZHRX?= =?utf-8?B?dHhuRzUxbnFTejM4VTFvZUVYcUN2a21iS3RpQVV0eDYzN3pFdEhlRG0ycTkx?= =?utf-8?B?Uit6VS9iaGx0UnVEclNObE1JZVpVVmdLaklLVGg2V3gvSWErZW93VTNkd2kv?= =?utf-8?B?WVV0L3h3UGJkOTNOajk3UHlxWTYrWnJKNTllcVdURlZtemdvSG9XaEZBanBX?= =?utf-8?B?eFNLMDdZMW5CUUR4U1hlOGdjSEl5Wk5KMnF2c3VUOGZXZVNSbDkvaW5LOVp6?= =?utf-8?B?MFpWNnNZMW1LbnBLRTRCVXNQWFNZcm1pUkpkaUNtQStoYi9la3RTTXRDREJi?= =?utf-8?B?NzZNS1hySHdZU1RxeGs3S0kxbFFxeEMyWERGVmZ0VmZDWWZ1RjBhWXc1R0xt?= =?utf-8?B?NHgxd2YzMGI2ak1xVWRLa3p2U2IrVWUvZU1HWThBL0ZLYlV2MUlNNklCZXFl?= =?utf-8?B?UHRWRWF0QTRkeUw5bTkyVmxKSFB4Y0ZwUnVtU0dmS2x6NlRRV1lWZTM5bGM5?= =?utf-8?B?WWtMRkVmeVJWb1djMEg5aTE0Z1JaZEtWUE9HcXUvajQyWUN0NHNLK2w3K3pk?= =?utf-8?B?UFY0dFZVcWlLSWkwOHpqZWJpTmNJMXc1K0s4MDZLcUlTa1hHeUdRZWZVNnlw?= =?utf-8?B?YzVNSklyRHJZdlN1ZFcrQXZGSjJYR3F1ZURxbzIydWo5UXB3enJQRTNNZ215?= =?utf-8?Q?VulhpX70jPDf4tkXiaAgQ2E=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)(10070799003)(1800799024)(7416014)(376014)(366016)(921020);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 2 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?SWd0NzFsWkNiZkFUTHhQbUVsVUhuK3dCRDc4OXo3K2d6V1VMZk9Pbmd3ZUVG?= =?utf-8?B?bkNnTmQ0SXVqMktuYjhVTUJZVTZoaWdGT3M2WUhhblJEWEwzMkZxMEdFSTMx?= =?utf-8?B?OWdWNHBuc3NydlByRmlma3poYlA2Z3RMVElJbzhnWXZ1aTk2U2NRT1ZBc3RI?= =?utf-8?B?RDBEK05BaUYvRjVUQWtWKzYrc2VRYnlQZzF1eVk4SkFKdjRLZVdaSUR4T1Nh?= =?utf-8?B?OUVHUGI4WHcrS1QrV2hRZ2srM2s2SU5MQlJpL1JYZ29NYk03Y2xmTGVWRHlC?= =?utf-8?B?L2V6VzZEY3crVlRDVmFmSFBFUWZIQWdYVjR3eDRsSU02KzJVV3hsYjNJMjQz?= =?utf-8?B?Y0Z5L3djakw3R29hRTFzNVBjYlgzQnlSUnU4d1VpYThaNHhjTnY1R1doSi9y?= =?utf-8?B?WUFwM3YvUzlOTnBnbmxaYlZLY1R6TTJEMnhwdlpxOVREby8xdm5hUXhlRXhZ?= =?utf-8?B?eTEyUHlJc0pub2twcW55Zy9Sd3ZBV1A4RU5hb3dWK3Z1bW9md3c0Yk41WjU0?= =?utf-8?B?S3l4VjhJYnVqcklpa1ZKdS9yc0MrenVQK1hva3hhdW5IcVBTU0R0dXJuUGRW?= =?utf-8?B?TXh0elgwRllTemFCUGJXNnc4N1VySjVmRjdRYVZPUmF4b1B6UFFESUs3MzlS?= =?utf-8?B?YWJoUWxUVjhwK2ZDTWRNZnMwRTFlVnB6RjFqdkxyaW1nSTZUR1BHc210VWVS?= =?utf-8?B?VGcyV0JwcERwSWVuSldCQzcwSTFQeVBTL0RBKy9QOTJIUExwYlB4U2RLbVQy?= =?utf-8?B?OEYvVDhaaVN2MXZQVXgyMUpGdHNGV1czaUdiS3JVcHowcG9KMklVUW5OMEVC?= =?utf-8?B?UkVoWDBLSTI2OGdHT2F2bkhmeU8xYnhlQlllTDBqTU52dk9zdnNQMkZTdDFx?= =?utf-8?B?cml3V1ZUaVI3UUg0Y1k4MzRKZ0psNHN1dnE2T3FwSXNNQmgwcFBkZXBqb2V1?= =?utf-8?B?aEpEN1BlbDFFSk9GUnYra1J2cUtVWldlVlRkT0dqalhRNHd6bFVBMk1idkx0?= =?utf-8?B?ODJkbGRJRzY2dTRhRnRWb1d4YkVkQi9xdXZSWEFjMmpuM1RQaml1cHVQWm9H?= =?utf-8?B?cnM2QS9kRVEzcVVzVXh0R3RpVVBsRUlrZjBHUEtCSVpTbzRhSkFHWW5zdFVQ?= =?utf-8?B?MXE1Q0xWdHJ6cEVmaE5IU2dJc2I5enA5eWpabGFFcW84WVF2dkxEcllJOW5H?= =?utf-8?B?emNUVFduclN0YUdoZmh5YzhDYlh5OUt4QVdpVTlTM3dGVXpMRGNTWU96UWNt?= =?utf-8?B?WGJNYnVpUVhXeUlWUHlLM0ZhMjBOcW1QdFpCdlFtVUJYVU4xZE50OGgzbXVJ?= =?utf-8?B?SGVLVjJjQU5QMkcyT3FrYmxsbjZMbXRNVy9TbG9lb25HdVcxSDFOME5SdTVh?= =?utf-8?B?ekpJVkRhbUNsK3U2ME9FcXllMGQ4UG9NVUk0Yk8ydno1Qlc4Q2wzOGRyNG43?= =?utf-8?B?ajNNcm02Slo4SDl6bnlxdEw0UGRZYU9BcGJtdEV3OFNHeUpLamRPRDdpYnlj?= =?utf-8?B?Z1RwRmxvYjhFelI0N1g0cjVJekpxNmlScXB0Y0VuT2gzWGdoMU0vaXhSVTFP?= =?utf-8?B?eWx5dVpRNytUS1I1RW5rVUQ4Y2FzdDJEOE55S2ZBZUU3d1FiUHQ4U2VNeldK?= =?utf-8?B?OFlYZmw0SC9BOFBvMlhyc3IzYUEwM1h1Z1F5bE4xcis0enN3Vi9uemVWL2RY?= =?utf-8?B?NzkxT0dPalBSd2JpQmFnNFFLLzdGRXRYdjVITFVaZG5SMWdsZ1BuTGlKNlhU?= =?utf-8?B?VFlTOVB4Z1l2QXJibklpYzd1Qzdxd0xmZUYwdGg4cE9PUWRWSU9NMFVjYmZu?= =?utf-8?B?aWtJOHBvdk5Zemx2UEJTTHg5STR6ZXJzT3NMSnh4QjAveG1GSUFmb2RQRnBL?= =?utf-8?B?QUdoNUNOSGJ0aG5VMHN5T2tlNnA3V09VNUJ2dkZaT3R2K1dnSTM4WjhrYXRl?= =?utf-8?B?ZFRQQi9TQnJYOFEzTUtDUXZJd0dkT1VJcWlGZGpTa2pQVmhvcTBxVW5aZnYw?= =?utf-8?B?bWdRc1ovOWtNL0JRaFJYSlFMNGdMcUxwODIyTWpNQ0lURTBXM2FkZmN1dnlF?= =?utf-8?B?MTNyTUZyY2RvS0RFQjN6cnEyWFZqNVlUSFppOUg3SDRGTDloQ0NTY3lNNWhK?= =?utf-8?B?ZEpSbVNTTmhhMWRVSEc0Visza0l2b255MHBKSk9tbWpZdFJiNDVKWTRTMkt5?= =?utf-8?B?c0kwaTlZWnRIdTZTSkRnM3ZQa1pVa0RzT3E3VTltNFRoODBWZjVSL0lXdGRN?= =?utf-8?B?WitjWGJUUVQyZXd5VlpwVk80RHd2WU00SmRhNXRSYXVvbFMvdDg2SHVrVXFR?= =?utf-8?B?YjF1eGFLMHlVUkxRcGhRUGVPOWJEUEppZkU0d3RxSnNmcnV3Z2NNbkdKSDFw?= =?utf-8?Q?SeyF4W91zT09C337HymKRXlc0QjrXDww0BNum4T9sfOQt?= X-MS-Exchange-AntiSpam-MessageData-1: 614AyZ7BrE4kuw== X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: b9744ba6-d42a-4b29-c1af-08de5f3adfd7 X-MS-Exchange-CrossTenant-AuthSource: CH2PR12MB3990.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Jan 2026 13:32:40.6944 (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: /X8I0Zqps5ob5ABw+wtuvGFMOHGWOwFUwhHcU9TEu60XCg90cdDG99ECQUY5J2bpULOdKOsGgN1ykC/10nmEnA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN7PR12MB8146 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 | 205 ++++----- drivers/gpu/nova-core/falcon/gsp.rs | 14 +- drivers/gpu/nova-core/falcon/hal/ga102.rs | 25 +- drivers/gpu/nova-core/falcon/sec2.rs | 13 +- drivers/gpu/nova-core/fb/hal/ga100.rs | 19 +- drivers/gpu/nova-core/fb/hal/tu102.rs | 4 +- 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, 420 insertions(+), 1128 deletions(-) diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon= .rs index 82c661aef594..cf8a93f69ca8 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 @@ -384,8 +353,8 @@ pub(crate) fn new(dev: &device::Device, chipset: Chipse= t) -> Result { =20 /// Resets DMA-related registers. pub(crate) fn dma_reset(&self, bar: &Bar0) { - regs::NV_PFALCON_FBIF_CTL::update(bar, &E::ID, |v| v.set_allow_phy= s_no_ctx(true)); - regs::NV_PFALCON_FALCON_DMACTL::default().write(bar, &E::ID); + regs::NV_PFALCON_FBIF_CTL::update(bar, &E::ID, |v| v.with_allow_ph= ys_no_ctx(true)); + regs::NV_PFALCON_FALCON_DMACTL::zeroed().write(bar, &E::ID); } =20 /// Wait for memory scrubbing to complete. @@ -413,12 +382,12 @@ fn reset_eng(&self, bar: &Bar0) -> Result { Delta::from_micros(150), ); =20 - regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.set_rese= t(true)); + regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.with_res= et(true)); =20 // TIMEOUT: falcon engine should not take more than 10us to reset. fsleep(Delta::from_micros(10)); =20 - regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.set_rese= t(false)); + regs::NV_PFALCON_FALCON_ENGINE::update(bar, &E::ID, |v| v.with_res= et(false)); =20 self.reset_wait_mem_scrubbing(bar)?; =20 @@ -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() + .with_value(regs::NV_PMC_BOOT_0::read(bar).as_raw()) .write(bar, &E::ID); =20 Ok(()) @@ -495,29 +464,27 @@ 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) + .with_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_with_base(dma_start >> 40)? .write(bar, &E::ID); =20 - let cmd =3D regs::NV_PFALCON_FALCON_DMATRFCMD::default() - .set_size(DmaTrfCmdSize::Size256B) - .set_imem(target_mem =3D=3D FalconMem::Imem) - .set_sec(if sec { 1 } else { 0 }); + let cmd =3D regs::NV_PFALCON_FALCON_DMATRFCMD::zeroed() + .with_size(DmaTrfCmdSize::Size256B) + .with_imem(target_mem =3D=3D FalconMem::Imem) + .with_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_with_offs(load_offsets.dst_start + pos)? .write(bar, &E::ID); - regs::NV_PFALCON_FALCON_DMATRFFBOFFS::default() - .set_offs(src_start + pos) + regs::NV_PFALCON_FALCON_DMATRFFBOFFS::zeroed() + .with_offs(src_start + pos) .write(bar, &E::ID); cmd.write(bar, &E::ID); =20 @@ -539,8 +506,8 @@ fn dma_wr>( pub(crate) fn dma_load>(&self, bar: &B= ar0, fw: &F) -> Result { self.dma_reset(bar); regs::NV_PFALCON_FBIF_TRANSCFG::update(bar, &E::ID, 0, |v| { - v.set_target(FalconFbifTarget::CoherentSysmem) - .set_mem_type(FalconFbifMemType::Physical) + v.with_target(FalconFbifTarget::CoherentSysmem) + .with_mem_type(FalconFbifMemType::Physical) }); =20 self.dma_wr(bar, fw, FalconMem::Imem, fw.imem_load_params(), true)= ?; @@ -549,8 +516,8 @@ 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() - .set_value(fw.boot_addr()) + regs::NV_PFALCON_FALCON_BOOTVEC::zeroed() + .with_value(fw.boot_addr()) .write(bar, &E::ID); =20 Ok(()) @@ -572,11 +539,11 @@ 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() - .set_startcpu(true) + true =3D> regs::NV_PFALCON_FALCON_CPUCTL_ALIAS::zeroed() + .with_startcpu(true) .write(bar, &E::ID), - false =3D> regs::NV_PFALCON_FALCON_CPUCTL::default() - .set_startcpu(true) + false =3D> regs::NV_PFALCON_FALCON_CPUCTL::zeroed() + .with_startcpu(true) .write(bar, &E::ID), } =20 @@ -586,14 +553,14 @@ pub(crate) fn start(&self, bar: &Bar0) -> Result<()> { /// Writes values to the mailbox registers if provided. pub(crate) fn write_mailboxes(&self, bar: &Bar0, mbox0: Option, m= box1: Option) { if let Some(mbox0) =3D mbox0 { - regs::NV_PFALCON_FALCON_MAILBOX0::default() - .set_value(mbox0) + regs::NV_PFALCON_FALCON_MAILBOX0::zeroed() + .with_value(mbox0) .write(bar, &E::ID); } =20 if let Some(mbox1) =3D mbox1 { - regs::NV_PFALCON_FALCON_MAILBOX1::default() - .set_value(mbox1) + regs::NV_PFALCON_FALCON_MAILBOX1::zeroed() + .with_value(mbox1) .write(bar, &E::ID); } } @@ -657,8 +624,8 @@ 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() - .set_value(app_version) + regs::NV_PFALCON_FALCON_OS::zeroed() + .with_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..fa8f6324c412 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,8 +39,8 @@ impl Falcon { /// Clears the SWGEN0 bit in the Falcon's IRQ status clear register to /// allow GSP to signal CPU for processing new messages in message que= ue. pub(crate) fn clear_swgen0_intr(&self, bar: &Bar0) { - regs::NV_PFALCON_FALCON_IRQSCLR::default() - .set_swgen0(true) + regs::NV_PFALCON_FALCON_IRQSCLR::zeroed() + .with_swgen0(true) .write(bar, &Gsp::ID); } =20 diff --git a/drivers/gpu/nova-core/falcon/hal/ga102.rs b/drivers/gpu/nova-c= ore/falcon/hal/ga102.rs index 69a7a95cac16..6c337b9d3752 100644 --- a/drivers/gpu/nova-core/falcon/hal/ga102.rs +++ b/drivers/gpu/nova-core/falcon/hal/ga102.rs @@ -26,8 +26,8 @@ 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() - .set_core_select(PeregrineCoreSelect::Falcon) + regs::NV_PRISCV_RISCV_BCR_CTRL::zeroed() + .with_core_select(PeregrineCoreSelect::Falcon) .write(bar, &E::ID); =20 // TIMEOUT: falcon core should take less than 10ms to report being= enabled. @@ -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,24 +68,25 @@ 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() - .set_value(params.pkc_data_offset) + regs::NV_PFALCON2_FALCON_BROM_PARAADDR::zeroed() + .with_value(params.pkc_data_offset) .write(bar, &E::ID, 0); - regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::default() - .set_value(u32::from(params.engine_id_mask)) + regs::NV_PFALCON2_FALCON_BROM_ENGIDMASK::zeroed() + .with_value(u32::from(params.engine_id_mask)) .write(bar, &E::ID); - regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::default() - .set_ucode_id(params.ucode_id) + regs::NV_PFALCON2_FALCON_BROM_CURR_UCODE_ID::zeroed() + .with_ucode_id(params.ucode_id) .write(bar, &E::ID); - regs::NV_PFALCON2_FALCON_MOD_SEL::default() - .set_algo(FalconModSelAlgo::Rsa3k) + regs::NV_PFALCON2_FALCON_MOD_SEL::zeroed() + .with_algo(FalconModSelAlgo::Rsa3k) .write(bar, &E::ID); =20 Ok(()) 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..84a5be84846b 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,15 +22,17 @@ 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() + .with_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) + .with_adr_39_08((addr >> FLUSH_SYSMEM_ADDR_SHIFT) as u32) .write(bar); } =20 diff --git a/drivers/gpu/nova-core/fb/hal/tu102.rs b/drivers/gpu/nova-core/= fb/hal/tu102.rs index eec984f4e816..9e3c20ba6d7e 100644 --- a/drivers/gpu/nova-core/fb/hal/tu102.rs +++ b/drivers/gpu/nova-core/fb/hal/tu102.rs @@ -21,8 +21,8 @@ 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() - .set_adr_39_08(addr) + regs::NV_PFB_NISO_FLUSH_SYSMEM_ADDR::zeroed() + .with_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..4fffd16e3dde 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() + .with_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