{"id":2225774,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2225774/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-pci/patch/20260421-io_projection-v2-2-4c251c692ef4@garyguo.net/","project":{"id":28,"url":"http://patchwork.ozlabs.org/api/1.1/projects/28/?format=json","name":"Linux PCI development","link_name":"linux-pci","list_id":"linux-pci.vger.kernel.org","list_email":"linux-pci@vger.kernel.org","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<20260421-io_projection-v2-2-4c251c692ef4@garyguo.net>","date":"2026-04-21T14:56:13","name":"[v2,02/11] rust: io: generalize `Mmio` to arbitrary type","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"1bf2dc57f8401d5b3c95a5ad9aed135318c470a3","submitter":{"id":76823,"url":"http://patchwork.ozlabs.org/api/1.1/people/76823/?format=json","name":"Gary Guo","email":"gary@garyguo.net"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-pci/patch/20260421-io_projection-v2-2-4c251c692ef4@garyguo.net/mbox/","series":[{"id":500833,"url":"http://patchwork.ozlabs.org/api/1.1/series/500833/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-pci/list/?series=500833","date":"2026-04-21T14:56:19","name":"rust: I/O type generalization and projection","version":2,"mbox":"http://patchwork.ozlabs.org/series/500833/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2225774/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2225774/checks/","tags":{},"headers":{"Return-Path":"\n <linux-pci+bounces-52838-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-pci@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=garyguo.net header.i=@garyguo.net header.a=rsa-sha256\n header.s=selector1 header.b=PdfOfMNU;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.234.253.10; helo=sea.lore.kernel.org;\n envelope-from=linux-pci+bounces-52838-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net\n header.b=\"PdfOfMNU\"","smtp.subspace.kernel.org;\n arc=fail smtp.client-ip=52.101.196.82","smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=garyguo.net","smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=garyguo.net","dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=garyguo.net;"],"Received":["from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g0Qb54cFCz1yGt\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 01:03:13 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 047733030289\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 21 Apr 2026 14:56:35 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 8BA241A6801;\n\tTue, 21 Apr 2026 14:56:33 +0000 (UTC)","from LO3P265CU004.outbound.protection.outlook.com\n (mail-uksouthazon11020082.outbound.protection.outlook.com [52.101.196.82])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 6C3EF3D6470;\n\tTue, 21 Apr 2026 14:56:31 +0000 (UTC)","from LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:488::16)\n by CWLP265MB5523.GBRP265.PROD.OUTLOOK.COM (2603:10a6:400:1b9::6) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9846.16; Tue, 21 Apr\n 2026 14:56:28 +0000","from LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM\n ([fe80::1c3:ceba:21b4:9986]) by LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM\n ([fe80::1c3:ceba:21b4:9986%4]) with mapi id 15.20.9846.016; Tue, 21 Apr 2026\n 14:56:28 +0000"],"ARC-Seal":["i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776783393; cv=fail;\n b=BsG2eaMp4fZmPXeiNMmse79wOnF1nB+gjF2srxwnAgL198n58WTLH4nGfKtPt9KUZprAZBN7CWB9j57SX3DuqENmLytwlMybLvCTNzr1qCvYVnFWoX0iiSZaHkNV7AWzxCWA1g8Ytoqqx0DhdEnXHJKAWs8fCLzmQhvouZepCYM=","i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=rFE60l3M40jhyfxqTJ3WbjshygQqWA03GuWwXsIA3vMo1n6x3Zl+F4HNxqVjsCbZsXO78DX3panenH+St1Ws5ckjw+nA7qEQwRw+jVijj+sg+0QNZpVhKv9eEC6NiAwmYBvopNUnPzDLnOoM6ctZY2bwYr1PrR184cE5JgHuZH1IAQ3baS2etrY/A/ZOvx1uPmV0B3TK+rCi3HHY8KBeNvlpIiYuBRfhgS7boN+S9i9jkeUns9Lx3/yx1ErGTOCZ+AGXAYeRs9dn4zUHUdMWUjbQEZD/xC7ywonrSGl3cllZVtwYKAc6wcKqHBjnUY9oRBTEaAbS2DL9xY6tBXOD1g=="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776783393; c=relaxed/simple;\n\tbh=faM0ZpteUlJaNJZMTjGbI7mkrrDCMYhjEeLbY0rM2bo=;\n\th=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To:\n\t To:Cc:MIME-Version;\n b=aS83v+UqhyVKs0qa2F6Reef9HFld/ZR/iS4gpJknhMyCleiGqLZfcZEFx3VHkCpKOyE026TEVdDAeziKRdOdFz5tcxvtdAyuic0aw5rZKTWwyLNwE3YeY6qkvhfOZuwnLeqekwFHdaJ9y7JEIFQHRIGfH3ygJWOq4PZfRYFCb+4=","i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n 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;\n bh=RpvjKQBEOTrrEFGy3XscM4znZyZdhB2MI4KZHqsSb6c=;\n b=KOd7sNWS8e3HTQ2d2DtQ1QJc7o3mijFfH3FXoIWhthvVSzuDlDzCwsE5DeV/zsWDPPB7vPT8q4cA7AhjfANWDme5K/dVmQuxtuz95Ti2qoh4/4wb/pKzSPwGZESDE7mB/zupT6h43Ah5x4GS17bDrkzEGAtHC3xljwtVjHmdAfa+1jbWLJAueT/L+3nmGgmm9UlW3JaBZGoCR03wLFgFCTuwnmmDVeZdNRfWoqgfK9jUmnvgH/SyzLMCnXOqbdawteqB2zvZpJzneA4smOWhPG7WOcHSEeGbls8VnzEMpS0XFqUmYzPfTPKtVHpKsy9Q6PlZVRpRhRRioOxeIbYPjA=="],"ARC-Authentication-Results":["i=2; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=garyguo.net;\n spf=pass smtp.mailfrom=garyguo.net;\n dkim=pass (1024-bit key) header.d=garyguo.net header.i=@garyguo.net\n header.b=PdfOfMNU; arc=fail smtp.client-ip=52.101.196.82","i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=garyguo.net; dmarc=pass action=none header.from=garyguo.net;\n dkim=pass header.d=garyguo.net; arc=none"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=garyguo.net;\n s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=RpvjKQBEOTrrEFGy3XscM4znZyZdhB2MI4KZHqsSb6c=;\n b=PdfOfMNUKHNtdorRxVXdTxATKwEaxn4HtyhJmqXVHtKoA/4PKDMfXHhmPSZwm5L7oy4+3rndVgUe6dO7l1NfvAbviGjc4WMBDDXpAK/yt1kCVzfmg9up6MAIcRJMhPIK+YjWmL56AAz427Kt+dqfyt8ZB4ur4cdiivP47plkc+0=","From":"Gary Guo <gary@garyguo.net>","Date":"Tue, 21 Apr 2026 15:56:13 +0100","Subject":"[PATCH v2 02/11] rust: io: generalize `Mmio` to arbitrary type","Content-Type":"text/plain; charset=\"utf-8\"","Content-Transfer-Encoding":"7bit","Message-Id":"<20260421-io_projection-v2-2-4c251c692ef4@garyguo.net>","References":"<20260421-io_projection-v2-0-4c251c692ef4@garyguo.net>","In-Reply-To":"<20260421-io_projection-v2-0-4c251c692ef4@garyguo.net>","To":"Greg Kroah-Hartman <gregkh@linuxfoundation.org>,\n  \"Rafael J. Wysocki\" <rafael@kernel.org>, Danilo Krummrich <dakr@kernel.org>,\n  Miguel Ojeda <ojeda@kernel.org>, Boqun Feng <boqun@kernel.org>,\n  Gary Guo <gary@garyguo.net>,\n =?utf-8?q?Bj=C3=B6rn_Roy_Baron?= <bjorn3_gh@protonmail.com>,\n  Benno Lossin <lossin@kernel.org>, Andreas Hindborg <a.hindborg@kernel.org>,\n  Alice Ryhl <aliceryhl@google.com>, Trevor Gross <tmgross@umich.edu>,\n  Daniel Almeida <daniel.almeida@collabora.com>,\n  Bjorn Helgaas <bhelgaas@google.com>,\n =?utf-8?q?Krzysztof_Wilczy=C5=84ski?= <kwilczynski@kernel.org>,\n  Abdiel Janulgue <abdiel.janulgue@gmail.com>,\n  Robin Murphy <robin.murphy@arm.com>,\n  Alexandre Courbot <acourbot@nvidia.com>, David Airlie <airlied@gmail.com>,\n  Simona Vetter <simona@ffwll.ch>","Cc":"driver-core@lists.linux.dev, rust-for-linux@vger.kernel.org,\n linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org,\n nouveau@lists.freedesktop.org, dri-devel@lists.freedesktop.org","X-Mailer":"b4 0.15.1","X-Developer-Signature":"v=1; a=ed25519-sha256; t=1776783386; l=16534;\n i=gary@garyguo.net; s=20221204; h=from:subject:message-id;\n bh=faM0ZpteUlJaNJZMTjGbI7mkrrDCMYhjEeLbY0rM2bo=;\n b=81Koxp9RJC3hxba8mvXB9afBclGGtwdgEORR2NJq9fXTkJLb+ZFGPnT3+B6KfTXXlIvs4Bs+O\n PGABNSh/1QlDu2wVLUmPExo7yUiXX7d2AHyiU6B+NusmGMXfJ8fpF7f","X-Developer-Key":"i=gary@garyguo.net; a=ed25519;\n pk=vB3uIX95SM4eVrIqo1DWNWKDKD2xzB+yLLLr0yOPYMo=","X-ClientProxiedBy":"LO4P123CA0142.GBRP123.PROD.OUTLOOK.COM\n (2603:10a6:600:193::21) To LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM\n (2603:10a6:600:488::16)","Precedence":"bulk","X-Mailing-List":"linux-pci@vger.kernel.org","List-Id":"<linux-pci.vger.kernel.org>","List-Subscribe":"<mailto:linux-pci+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-pci+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","X-MS-PublicTrafficType":"Email","X-MS-TrafficTypeDiagnostic":"LOVP265MB8871:EE_|CWLP265MB5523:EE_","X-MS-Office365-Filtering-Correlation-Id":"bac75a47-46e5-4887-4111-08de9fb62a5e","X-MS-Exchange-SenderADCheck":"1","X-MS-Exchange-AntiSpam-Relay":"0","X-Microsoft-Antispam":"\n\tBCL:0;ARA:13230040|1800799024|376014|7416014|10070799003|366016|921020|22082099003|18002099003|56012099003;","X-Microsoft-Antispam-Message-Info":"\n\tOF8sboWGzHfUwFY3SIMlSqEGA6LX30q1Ln7K/Bt1cSMIgxTJD2kXsPgX9pmBbQDykFBH4jyk4IB+2Esxo7l2DEtnAeX0DqzPnc48GIq+TZulXbx/49J5+AOtK2cEQjgdq0kKcyGFNOr9lkEiSVRzxW9WDfDyVF/pCEDWzPy2S7beKgOKzCUvINr+Vuj09W0YcjD/9rMpJbxbKiOxmbkWBSW8++UkSaIIrJicUk84X0T+xx9oNKpsSvRxpeD7VjWp5UYnQG6qzawLNCu/Y0ZF/QKBAcYrqaQ7hmKWftMLGrgrmnQZV4ixo4+Xh8m7g9roewyVzMfNkiDDoYEQsvqyRcmwFZwbMt73z183hWpcAL5TaD+FyQy9mBgw5aLRLbsxNLF3FFE1t+ZVJcbeiSYV9WUxSqCGCzIBVMz+AxJ7ICyN9ZduOncFBVcRxyZ0T7x7OwIxqLxE0EsVsfCutoiS1bf5vMmz0JoukkS6YlsTNU5qaynylh/YM7USkBO9b6K+LCwz7we0+FLF7DbGLUaDSIw+FcSFfujQfb3GGFQMXRpkX/pV/cU/HXwZdjZnvDVTZKcQLj8paWTgcLYodUuRqq4nwjpN/2H4Q5k+TAUvqjEDqEPEL2VFSgbg+oVDqnfW2vCD8Smd0INuIdzEu+/jdgtFm1QLFxFS4taK9R9NDuLR1nY9GXI28aSYpQoKh2ge/troeo7+RHibMMTc13Qr/dbt1CEHSqrZsoFUh4mg9Z3eDzUP7mrYcqW8xDQ/VZUJTRlK0dODxN/V+4SCza0lnA==","X-Forefront-Antispam-Report":"\n\tCIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(376014)(7416014)(10070799003)(366016)(921020)(22082099003)(18002099003)(56012099003);DIR:OUT;SFP:1102;","X-MS-Exchange-AntiSpam-MessageData-ChunkCount":"1","X-MS-Exchange-AntiSpam-MessageData-0":"=?utf-8?q?Rsdp9cQ/P0jRJiK3vdp/4BnOnrKe?=\n\t=?utf-8?q?/IRr+nhCRoXyxL4QwLull7j453y7Cf7VVQDm2imKs4rpNfGuG9xn++3gipNl7eN0c?=\n\t=?utf-8?q?9h3fP/qQqqSPumd/u+4darKiqXgFaaM6fMvcBI1U3zFOmRU+73Ii3tbF1J3CApM8l?=\n\t=?utf-8?q?YVqRzuxK0JyRXyKvxMoT+uqRl5H6DDHE1+CYceBRJ+uNgGVRjRT5eCU3xAfuwiXxW?=\n\t=?utf-8?q?KO7/lC7up41h/po+lWCHI3EetfmvyZJlYiWXJVYLBl+MdnH9Iy2HnVm2kKpqImk35?=\n\t=?utf-8?q?cscL50eAPqlSfd6RzHiYcIR6H+GGrI9Tp8yIzf38+gS9JW1BD+q7pFBUAur/XQgQ2?=\n\t=?utf-8?q?SI62vRrABJedougZhvamLIH1RdfZNXNJ0vBWYfVdA0sYupv9MsyYGRPOdKEXSnBwu?=\n\t=?utf-8?q?2t1elw7l0x96D0cdv+oOZ6yhlwAXD8lE6y7b0VaSjIN2UikIWOeiZssCHSqlaGxZ/?=\n\t=?utf-8?q?fKO+Uq/cSB69lMkx53TfmW9CEIzA+CcpuCnurmpFlElDb1Sw8dqlbY8VMiXcP15lN?=\n\t=?utf-8?q?/5aYfbvqXZ/keGppKbQNmbyWjTMx2Gx93qx7ZTK7HyynAPaGyiINA7nabYeL0dw/U?=\n\t=?utf-8?q?RjzftT1MNmlCGll0QgzFka1uzQ+HhYUqJ8eDpnNeOGjy1fKaeih16rCDkdibwV/vr?=\n\t=?utf-8?q?ss7Eq7slb83YXFK4ug0w0J4PQMLMiWNqwW7k3kGfiwYK+ooeMh1odrZri2TKCwyls?=\n\t=?utf-8?q?JGnzwPfLRb/GQ5wa3saKoEp2MrPewq3VEt4OKM4xAbbeZ4sRW6u3OSO45BnmlrLoa?=\n\t=?utf-8?q?iT2/6THv80G/o7Z/lQ24tD1LOkAgZ5pUAAxytnQCrxtZTOwKaxiyXVkShFYEoRARH?=\n\t=?utf-8?q?QajRoKzxANVLuKOlOx1h+mW6suLmmv8x1pJUci3XfDMuTYm9UoMcZNlVGBA46iij0?=\n\t=?utf-8?q?Thsgyf+D+wFXzJOShqzZ7P1I7EXT0UL23uvKnB90CaBd1trx3DO4eRJCuWM1Jatnq?=\n\t=?utf-8?q?pwLEpIHpZenpYT6IXIc6iwYZpDqY9Z6eM+QyIh7QEK7bZFeZ2bgoitv3N4C5odLUt?=\n\t=?utf-8?q?y8Dw3BkvE3z9jYK3/HI8VWgdW6stKYD5tcyqANXAzGLFe2C56gIrhzj5yNk6wi0fM?=\n\t=?utf-8?q?HkODDey93skfAkPMkJhOcsg98IzxWLp3Qv54/ZZ5x6/2sdbs1OBNuE84pNgaDtM3Q?=\n\t=?utf-8?q?0W14QLkhSbA7RxQP9Ynnf1amgQaWbL0JisHNBZYSGOZy10uqrYaTqaseJZxl83OXp?=\n\t=?utf-8?q?Qw4Z1QGwBKQ9oR6YWYRM/4KRMd5iInJkf2qYH7J2iD0FRWZEWuOphUa+2rGYYdbcZ?=\n\t=?utf-8?q?jacZ0CY4rLKXaP+DEPbIaNtQ84Thzg/zIA0GkfVIgHMpWFihgXc4X0GGr+S9rwi1U?=\n\t=?utf-8?q?Xz4FeL6T2EXU0kzonCunD51hZBVUMddfs8/ArR7/5+S2yzKFTg/isWW6bDsofyWLy?=\n\t=?utf-8?q?XWeA7OIy1zGNIX6DbFcCWPdaj663NfNGBsnY77IjtYbDzBVlYha/W5rydYGVMDoHp?=\n\t=?utf-8?q?M7now5WBcKRLrYW32c4rmO5W68lL8L80OdFczvU5SH1h//zzt+8eh15LjPP+0h2S9?=\n\t=?utf-8?q?Ja/uOrsuwVMaxGmiCEAQcKP8tWezBr8XcwEyDzQUMtl5ylrTxGjp40+vMTix8r5z5?=\n\t=?utf-8?q?MDn76RclqVtYAbRe6Kt3hMfMrWNlLWziEaMTQ4w4l96e8KtdxZOK/lMTORhFKoqt/?=\n\t=?utf-8?q?9gfAfkzS5y1pgAOscFXadMCVb4am6PNA=3D=3D?=","X-OriginatorOrg":"garyguo.net","X-MS-Exchange-CrossTenant-Network-Message-Id":"\n bac75a47-46e5-4887-4111-08de9fb62a5e","X-MS-Exchange-CrossTenant-AuthSource":"LOVP265MB8871.GBRP265.PROD.OUTLOOK.COM","X-MS-Exchange-CrossTenant-AuthAs":"Internal","X-MS-Exchange-CrossTenant-OriginalArrivalTime":"21 Apr 2026 14:56:27.7791\n (UTC)","X-MS-Exchange-CrossTenant-FromEntityHeader":"Hosted","X-MS-Exchange-CrossTenant-Id":"bbc898ad-b10f-4e10-8552-d9377b823d45","X-MS-Exchange-CrossTenant-MailboxType":"HOSTED","X-MS-Exchange-CrossTenant-UserPrincipalName":"\n wHUMn/98Q1GvCqu2kP+fUEvPgpahshFQlmq47oS/dN0LZIKclqrDs+bN8/YhtC5+9eGsfa9gPQCaquvcsSHbTQ==","X-MS-Exchange-Transport-CrossTenantHeadersStamped":"CWLP265MB5523"},"content":"Currently, `io::Mmio` always represent an untyped region of a compile-time\nknown minimum size, which is roughly equivalent to `void __iomem*` (but\nwith bound checks). However, it is useful to also be to represent I/O\nmemory of a specific type, e.g. `u32 __iomem*` or `struct foo __iomem*`.\n\nThus, make `Mmio` generic on arbitrary `T`, where `T` is a sized type, or a\nDST that implements `KnownSize`. Similar to the `MmioRaw` change, the\nexisting behaviour is preserved in the form of `Mmio<Region<SIZE>>`. This\nchange brings the MMIO closer to the DMA coherent allocation types that we\nhave, which is already typed.\n\nTo be able to implement `IoKnownSize`, add a `MIN_SIZE` constant to\n`KnownSize` trait to represent compile-time known minimum size of a\nspecific type.\n\nAcked-by: Miguel Ojeda <ojeda@kernel.org>\nSigned-off-by: Gary Guo <gary@garyguo.net>\n---\n rust/kernel/devres.rs      |  2 +-\n rust/kernel/io.rs          | 63 +++++++++++++++++++++++++++-------------------\n rust/kernel/io/mem.rs      |  4 +--\n rust/kernel/io/poll.rs     |  6 +++--\n rust/kernel/io/register.rs | 19 ++++++++------\n rust/kernel/pci/io.rs      |  2 +-\n rust/kernel/ptr.rs         |  7 ++++++\n 7 files changed, 64 insertions(+), 39 deletions(-)","diff":"diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs\nindex 65a4082122af..3e22c63efb98 100644\n--- a/rust/kernel/devres.rs\n+++ b/rust/kernel/devres.rs\n@@ -106,7 +106,7 @@ struct Inner<T> {\n /// }\n ///\n /// impl<const SIZE: usize> Deref for IoMem<SIZE> {\n-///    type Target = Mmio<SIZE>;\n+///    type Target = Mmio<Region<SIZE>>;\n ///\n ///    fn deref(&self) -> &Self::Target {\n ///         // SAFETY: The memory range stored in `self` has been properly mapped in `Self::new`.\ndiff --git a/rust/kernel/io.rs b/rust/kernel/io.rs\nindex d7f2145fa9b9..0b9c97c0a1d7 100644\n--- a/rust/kernel/io.rs\n+++ b/rust/kernel/io.rs\n@@ -44,6 +44,8 @@ pub struct Region<const SIZE: usize = 0> {\n }\n \n impl<const SIZE: usize> KnownSize for Region<SIZE> {\n+    const MIN_SIZE: usize = SIZE;\n+\n     #[inline(always)]\n     fn size(p: *const Self) -> usize {\n         (p as *const [u8]).len()\n@@ -169,7 +171,7 @@ pub fn size(&self) -> usize {\n /// }\n ///\n /// impl<const SIZE: usize> Deref for IoMem<SIZE> {\n-///    type Target = Mmio<SIZE>;\n+///    type Target = Mmio<Region<SIZE>>;\n ///\n ///    fn deref(&self) -> &Self::Target {\n ///         // SAFETY: The memory range stored in `self` has been properly mapped in `Self::new`.\n@@ -187,7 +189,7 @@ pub fn size(&self) -> usize {\n /// # }\n /// ```\n #[repr(transparent)]\n-pub struct Mmio<const SIZE: usize = 0>(MmioRaw<Region<SIZE>>);\n+pub struct Mmio<T: ?Sized>(MmioRaw<T>);\n \n /// Checks whether an access of type `U` at the given `offset`\n /// is valid within this region.\n@@ -462,9 +464,10 @@ fn write64(&self, value: u64, offset: usize)\n     /// use kernel::io::{\n     ///     Io,\n     ///     Mmio,\n+    ///     Region,\n     /// };\n     ///\n-    /// fn do_reads(io: &Mmio) -> Result {\n+    /// fn do_reads(io: &Mmio<Region>) -> Result {\n     ///     // 32-bit read from address `0x10`.\n     ///     let v: u32 = io.try_read(0x10)?;\n     ///\n@@ -496,9 +499,10 @@ fn try_read<T, L>(&self, location: L) -> Result<T>\n     /// use kernel::io::{\n     ///     Io,\n     ///     Mmio,\n+    ///     Region,\n     /// };\n     ///\n-    /// fn do_writes(io: &Mmio) -> Result {\n+    /// fn do_writes(io: &Mmio<Region>) -> Result {\n     ///     // 32-bit write of value `1` at address `0x10`.\n     ///     io.try_write(0x10, 1u32)?;\n     ///\n@@ -534,6 +538,7 @@ fn try_write<T, L>(&self, location: L, value: T) -> Result\n     ///     register,\n     ///     Io,\n     ///     Mmio,\n+    ///     Region,\n     /// };\n     ///\n     /// register! {\n@@ -549,7 +554,7 @@ fn try_write<T, L>(&self, location: L, value: T) -> Result\n     ///     }\n     /// }\n     ///\n-    /// fn do_write_reg(io: &Mmio) -> Result {\n+    /// fn do_write_reg(io: &Mmio<Region>) -> Result {\n     ///\n     ///     io.try_write_reg(VERSION::new(1, 0))\n     /// }\n@@ -579,9 +584,10 @@ fn try_write_reg<T, L, V>(&self, value: V) -> Result\n     /// use kernel::io::{\n     ///     Io,\n     ///     Mmio,\n+    ///     Region,\n     /// };\n     ///\n-    /// fn do_update(io: &Mmio<0x1000>) -> Result {\n+    /// fn do_update(io: &Mmio<Region<0x1000>>) -> Result {\n     ///     io.try_update(0x10, |v: u32| {\n     ///         v + 1\n     ///     })\n@@ -616,9 +622,10 @@ fn try_update<T, L, F>(&self, location: L, f: F) -> Result\n     /// use kernel::io::{\n     ///     Io,\n     ///     Mmio,\n+    ///     Region,\n     /// };\n     ///\n-    /// fn do_reads(io: &Mmio<0x1000>) {\n+    /// fn do_reads(io: &Mmio<Region<0x1000>>) {\n     ///     // 32-bit read from address `0x10`.\n     ///     let v: u32 = io.read(0x10);\n     ///\n@@ -648,9 +655,10 @@ fn read<T, L>(&self, location: L) -> T\n     /// use kernel::io::{\n     ///     Io,\n     ///     Mmio,\n+    ///     Region,\n     /// };\n     ///\n-    /// fn do_writes(io: &Mmio<0x1000>) {\n+    /// fn do_writes(io: &Mmio<Region<0x1000>>) {\n     ///     // 32-bit write of value `1` at address `0x10`.\n     ///     io.write(0x10, 1u32);\n     ///\n@@ -682,6 +690,7 @@ fn write<T, L>(&self, location: L, value: T)\n     ///     register,\n     ///     Io,\n     ///     Mmio,\n+    ///     Region,\n     /// };\n     ///\n     /// register! {\n@@ -697,7 +706,7 @@ fn write<T, L>(&self, location: L, value: T)\n     ///     }\n     /// }\n     ///\n-    /// fn do_write_reg(io: &Mmio<0x1000>) {\n+    /// fn do_write_reg(io: &Mmio<Region<0x1000>>) {\n     ///     io.write_reg(VERSION::new(1, 0));\n     /// }\n     /// ```\n@@ -726,9 +735,10 @@ fn write_reg<T, L, V>(&self, value: V)\n     /// use kernel::io::{\n     ///     Io,\n     ///     Mmio,\n+    ///     Region,\n     /// };\n     ///\n-    /// fn do_update(io: &Mmio<0x1000>) {\n+    /// fn do_update(io: &Mmio<Region<0x1000>>) {\n     ///     io.update(0x10, |v: u32| {\n     ///         v + 1\n     ///     })\n@@ -778,7 +788,7 @@ fn io_addr_assert<U>(&self, offset: usize) -> usize {\n macro_rules! impl_mmio_io_capable {\n     ($mmio:ident, $(#[$attr:meta])* $ty:ty, $read_fn:ident, $write_fn:ident) => {\n         $(#[$attr])*\n-        impl<const SIZE: usize> IoCapable<$ty> for $mmio<SIZE> {\n+        impl<T: ?Sized> IoCapable<$ty> for $mmio<T> {\n             unsafe fn io_read(&self, address: usize) -> $ty {\n                 // SAFETY: By the trait invariant `address` is a valid address for MMIO operations.\n                 unsafe { bindings::$read_fn(address as *const c_void) }\n@@ -805,7 +815,7 @@ unsafe fn io_write(&self, value: $ty, address: usize) {\n     writeq\n );\n \n-impl<const SIZE: usize> Io for Mmio<SIZE> {\n+impl<T: ?Sized + KnownSize> Io for Mmio<T> {\n     /// Returns the base address of this mapping.\n     #[inline]\n     fn addr(&self) -> usize {\n@@ -819,18 +829,18 @@ fn maxsize(&self) -> usize {\n     }\n }\n \n-impl<const SIZE: usize> IoKnownSize for Mmio<SIZE> {\n-    const MIN_SIZE: usize = SIZE;\n+impl<T: ?Sized + KnownSize> IoKnownSize for Mmio<T> {\n+    const MIN_SIZE: usize = T::MIN_SIZE;\n }\n \n-impl<const SIZE: usize> Mmio<SIZE> {\n+impl<T: ?Sized + KnownSize> Mmio<T> {\n     /// Converts an `MmioRaw` into an `Mmio` instance, providing the accessors to the MMIO mapping.\n     ///\n     /// # Safety\n     ///\n     /// Callers must ensure that `addr` is the start of a valid I/O mapped memory region of size\n-    /// `maxsize`.\n-    pub unsafe fn from_raw(raw: &MmioRaw<Region<SIZE>>) -> &Self {\n+    /// `addr.size()`.\n+    pub unsafe fn from_raw(raw: &MmioRaw<T>) -> &Self {\n         // SAFETY: `Mmio` is a transparent wrapper around `MmioRaw`.\n         unsafe { &*core::ptr::from_ref(raw).cast() }\n     }\n@@ -843,9 +853,9 @@ pub unsafe fn from_raw(raw: &MmioRaw<Region<SIZE>>) -> &Self {\n ///\n /// See [`Mmio::relaxed`] for a usage example.\n #[repr(transparent)]\n-pub struct RelaxedMmio<const SIZE: usize = 0>(Mmio<SIZE>);\n+pub struct RelaxedMmio<T: ?Sized>(Mmio<T>);\n \n-impl<const SIZE: usize> Io for RelaxedMmio<SIZE> {\n+impl<T: ?Sized + KnownSize> Io for RelaxedMmio<T> {\n     #[inline]\n     fn addr(&self) -> usize {\n         self.0.addr()\n@@ -857,11 +867,11 @@ fn maxsize(&self) -> usize {\n     }\n }\n \n-impl<const SIZE: usize> IoKnownSize for RelaxedMmio<SIZE> {\n-    const MIN_SIZE: usize = SIZE;\n+impl<T: ?Sized + KnownSize> IoKnownSize for RelaxedMmio<T> {\n+    const MIN_SIZE: usize = T::MIN_SIZE;\n }\n \n-impl<const SIZE: usize> Mmio<SIZE> {\n+impl<T: ?Sized> Mmio<T> {\n     /// Returns a [`RelaxedMmio`] reference that performs relaxed I/O operations.\n     ///\n     /// Relaxed accessors do not provide ordering guarantees with respect to DMA or memory accesses\n@@ -873,18 +883,19 @@ impl<const SIZE: usize> Mmio<SIZE> {\n     /// use kernel::io::{\n     ///     Io,\n     ///     Mmio,\n+    ///     Region,\n     ///     RelaxedMmio,\n     /// };\n     ///\n-    /// fn do_io(io: &Mmio<0x100>) {\n+    /// fn do_io(io: &Mmio<Region<0x100>>) {\n     ///     // The access is performed using `readl_relaxed` instead of `readl`.\n     ///     let v = io.relaxed().read32(0x10);\n     /// }\n     ///\n     /// ```\n-    pub fn relaxed(&self) -> &RelaxedMmio<SIZE> {\n-        // SAFETY: `RelaxedMmio` is `#[repr(transparent)]` over `Mmio`, so `Mmio<SIZE>` and\n-        // `RelaxedMmio<SIZE>` have identical layout.\n+    pub fn relaxed(&self) -> &RelaxedMmio<T> {\n+        // SAFETY: `RelaxedMmio` is `#[repr(transparent)]` over `Mmio`, so `Mmio<T>` and\n+        // `RelaxedMmio<T>` have identical layout.\n         unsafe { core::mem::transmute(self) }\n     }\n }\ndiff --git a/rust/kernel/io/mem.rs b/rust/kernel/io/mem.rs\nindex 9117d417f99c..a6292f4ebfa4 100644\n--- a/rust/kernel/io/mem.rs\n+++ b/rust/kernel/io/mem.rs\n@@ -214,7 +214,7 @@ pub fn new<'a>(io_request: IoRequest<'a>) -> impl PinInit<Devres<Self>, Error> +\n }\n \n impl<const SIZE: usize> Deref for ExclusiveIoMem<SIZE> {\n-    type Target = Mmio<SIZE>;\n+    type Target = Mmio<super::Region<SIZE>>;\n \n     fn deref(&self) -> &Self::Target {\n         &self.iomem\n@@ -289,7 +289,7 @@ fn drop(&mut self) {\n }\n \n impl<const SIZE: usize> Deref for IoMem<SIZE> {\n-    type Target = Mmio<SIZE>;\n+    type Target = Mmio<super::Region<SIZE>>;\n \n     fn deref(&self) -> &Self::Target {\n         // SAFETY: Safe as by the invariant of `IoMem`.\ndiff --git a/rust/kernel/io/poll.rs b/rust/kernel/io/poll.rs\nindex 75d1b3e8596c..2dce2b24b5ff 100644\n--- a/rust/kernel/io/poll.rs\n+++ b/rust/kernel/io/poll.rs\n@@ -48,13 +48,14 @@\n /// use kernel::io::{\n ///     Io,\n ///     Mmio,\n+///     Region,\n ///     poll::read_poll_timeout, //\n /// };\n /// use kernel::time::Delta;\n ///\n /// const HW_READY: u16 = 0x01;\n ///\n-/// fn wait_for_hardware<const SIZE: usize>(io: &Mmio<SIZE>) -> Result {\n+/// fn wait_for_hardware<const SIZE: usize>(io: &Mmio<Region<SIZE>>) -> Result {\n ///     read_poll_timeout(\n ///         // The `op` closure reads the value of a specific status register.\n ///         || io.try_read16(0x1000),\n@@ -135,13 +136,14 @@ pub fn read_poll_timeout<Op, Cond, T>(\n /// use kernel::io::{\n ///     Io,\n ///     Mmio,\n+///     Region,\n ///     poll::read_poll_timeout_atomic, //\n /// };\n /// use kernel::time::Delta;\n ///\n /// const HW_READY: u16 = 0x01;\n ///\n-/// fn wait_for_hardware<const SIZE: usize>(io: &Mmio<SIZE>) -> Result {\n+/// fn wait_for_hardware<const SIZE: usize>(io: &Mmio<Region<SIZE>>) -> Result {\n ///     read_poll_timeout_atomic(\n ///         // The `op` closure reads the value of a specific status register.\n ///         || io.try_read16(0x1000),\ndiff --git a/rust/kernel/io/register.rs b/rust/kernel/io/register.rs\nindex abc49926abfe..1a407fc35edc 100644\n--- a/rust/kernel/io/register.rs\n+++ b/rust/kernel/io/register.rs\n@@ -55,6 +55,7 @@\n //!         register,\n //!         Io,\n //!         IoLoc,\n+//!         Region,\n //!     },\n //!     num::Bounded,\n //! };\n@@ -66,7 +67,7 @@\n //! #         3:0 minor_revision;\n //! #     }\n //! # }\n-//! # fn test(io: &Mmio<0x1000>) {\n+//! # fn test(io: &Mmio<Region<0x1000>>) {\n //! # fn obtain_vendor_id() -> u8 { 0xff }\n //!\n //! // Read from the register's defined offset (0x100).\n@@ -441,6 +442,7 @@ fn into_io_op(self) -> (FixedRegisterLoc<T>, T) {\n ///     io::{\n ///         register,\n ///         Io,\n+///         Region,\n ///     },\n /// };\n /// # use kernel::io::Mmio;\n@@ -452,7 +454,7 @@ fn into_io_op(self) -> (FixedRegisterLoc<T>, T) {\n ///     }\n /// }\n ///\n-/// # fn test(io: &Mmio<0x1000>) {\n+/// # fn test(io: &Mmio<Region<0x1000>>) {\n /// let val = io.read(FIXED_REG);\n ///\n /// // Write from an already-existing value.\n@@ -554,6 +556,7 @@ fn into_io_op(self) -> (FixedRegisterLoc<T>, T) {\n ///             WithBase,\n ///         },\n ///         Io,\n+///         Region,\n ///     },\n /// };\n /// # use kernel::io::Mmio;\n@@ -581,7 +584,7 @@ fn into_io_op(self) -> (FixedRegisterLoc<T>, T) {\n ///     }\n /// }\n ///\n-/// # fn test(io: Mmio<0x1000>) {\n+/// # fn test(io: Mmio<Region<0x1000>>) {\n /// // Read the status of `Cpu0`.\n /// let cpu0_started = io.read(CPU_CTL::of::<Cpu0>());\n ///\n@@ -598,7 +601,7 @@ fn into_io_op(self) -> (FixedRegisterLoc<T>, T) {\n ///     }\n /// }\n ///\n-/// # fn test2(io: Mmio<0x1000>) {\n+/// # fn test2(io: Mmio<Region<0x1000>>) {\n /// // Start the aliased `CPU0`, leaving its other fields untouched.\n /// io.update(CPU_CTL_ALIAS::of::<Cpu0>(), |r| r.with_alias_start(true));\n /// # }\n@@ -633,6 +636,7 @@ fn into_io_op(self) -> (FixedRegisterLoc<T>, T) {\n ///         register,\n ///         register::Array,\n ///         Io,\n+///         Region,\n ///     },\n /// };\n /// # use kernel::io::Mmio;\n@@ -648,7 +652,7 @@ fn into_io_op(self) -> (FixedRegisterLoc<T>, T) {\n ///     }\n /// }\n ///\n-/// # fn test(io: &Mmio<0x1000>)\n+/// # fn test(io: &Mmio<Region<0x1000>>)\n /// #     -> Result<(), Error>{\n /// // Read scratch register 0, i.e. I/O address `0x80`.\n /// let scratch_0 = io.read(SCRATCH::at(0)).value();\n@@ -719,6 +723,7 @@ fn into_io_op(self) -> (FixedRegisterLoc<T>, T) {\n ///             WithBase,\n ///         },\n ///         Io,\n+///         Region,\n ///     },\n /// };\n /// # use kernel::io::Mmio;\n@@ -749,7 +754,7 @@ fn into_io_op(self) -> (FixedRegisterLoc<T>, T) {\n ///     }\n /// }\n ///\n-/// # fn test(io: &Mmio<0x1000>) -> Result<(), Error> {\n+/// # fn test(io: &Mmio<Region<0x1000>>) -> Result<(), Error> {\n /// // Read scratch register 0 of CPU0.\n /// let scratch = io.read(CPU_SCRATCH::of::<Cpu0>().at(0));\n ///\n@@ -791,7 +796,7 @@ fn into_io_op(self) -> (FixedRegisterLoc<T>, T) {\n ///     }\n /// }\n ///\n-/// # fn test2(io: &Mmio<0x1000>) -> Result<(), Error> {\n+/// # fn test2(io: &Mmio<Region<0x1000>>) -> Result<(), Error> {\n /// let cpu0_status = io.read(CPU_FIRMWARE_STATUS::of::<Cpu0>()).status();\n /// # Ok(())\n /// # }\ndiff --git a/rust/kernel/pci/io.rs b/rust/kernel/pci/io.rs\nindex 0335b5068f69..e048370fb8c1 100644\n--- a/rust/kernel/pci/io.rs\n+++ b/rust/kernel/pci/io.rs\n@@ -238,7 +238,7 @@ fn drop(&mut self) {\n }\n \n impl<const SIZE: usize> Deref for Bar<SIZE> {\n-    type Target = Mmio<SIZE>;\n+    type Target = Mmio<crate::io::Region<SIZE>>;\n \n     fn deref(&self) -> &Self::Target {\n         // SAFETY: By the type invariant of `Self`, the MMIO range in `self.io` is properly mapped.\ndiff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs\nindex 3f3e529e9f58..566e68f567a2 100644\n--- a/rust/kernel/ptr.rs\n+++ b/rust/kernel/ptr.rs\n@@ -235,11 +235,16 @@ fn align_up(self, alignment: Alignment) -> Option<Self> {\n ///\n /// This is a generalization of [`size_of`] that works for dynamically sized types.\n pub trait KnownSize {\n+    /// Minimum size of this type known at compile-time.\n+    const MIN_SIZE: usize;\n+\n     /// Get the size of an object of this type in bytes, with the metadata of the given pointer.\n     fn size(p: *const Self) -> usize;\n }\n \n impl<T> KnownSize for T {\n+    const MIN_SIZE: usize = core::mem::size_of::<T>();\n+\n     #[inline(always)]\n     fn size(_: *const Self) -> usize {\n         size_of::<T>()\n@@ -247,6 +252,8 @@ fn size(_: *const Self) -> usize {\n }\n \n impl<T> KnownSize for [T] {\n+    const MIN_SIZE: usize = 0;\n+\n     #[inline(always)]\n     fn size(p: *const Self) -> usize {\n         p.len() * size_of::<T>()\n","prefixes":["v2","02/11"]}