get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/2225776/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2225776,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2225776/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-pci/patch/20260421-io_projection-v2-3-4c251c692ef4@garyguo.net/",
    "project": {
        "id": 28,
        "url": "http://patchwork.ozlabs.org/api/1.2/projects/28/?format=api",
        "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,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260421-io_projection-v2-3-4c251c692ef4@garyguo.net>",
    "list_archive_url": null,
    "date": "2026-04-21T14:56:14",
    "name": "[v2,03/11] rust: io: use pointer types instead of address",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "b7131528c6f597dcd78786ded246553efceb5c1c",
    "submitter": {
        "id": 76823,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/76823/?format=api",
        "name": "Gary Guo",
        "email": "gary@garyguo.net"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-pci/patch/20260421-io_projection-v2-3-4c251c692ef4@garyguo.net/mbox/",
    "series": [
        {
            "id": 500833,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/500833/?format=api",
            "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/2225776/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2225776/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-pci+bounces-52842-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=tkQEhTUZ;\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-52842-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=\"tkQEhTUZ\"",
            "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)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g0QcN1Y2Dz1yGt\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 01:04:20 +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 03AF230B5BA8\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 21 Apr 2026 14:56:59 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id EBAD73DA5CD;\n\tTue, 21 Apr 2026 14:56:37 +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 B04AF3D9021;\n\tTue, 21 Apr 2026 14:56:33 +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=1776783397; cv=fail;\n b=OLLvDmjFNUtOJEGBz2a1CcvL6PNyKCvGk1854qdwvcrVWAjUI6HsPECkSVSoFuY417+4MGAIya6gV3sqlQ3tg9+7IU+KpWvMFuZL8PucKSBI0t8uLKhd2SQWA0pPtVb/aSb81B4wzRWDmHHogTHw5bIdN88Qfy1/DUx/qxG9+gM=",
            "i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=HaGwfNv72mYchzzfVvgspeUAuI2IivVFBPgtTeRZbM8DB7aj8ph6hjLfsavrr4OkaDa7R6dU2bW41BUD1xczxYmplHOuIRopjHRUCZD64DFWeEJPRPOIXQtlU303m9sphuUAiYLstFfq1sy4aMmdnDtMQLuC9ShBCSvrrjSBSzkYlPe1pGck6IqJ1kNXs08bEkGfXMDIk4H9GIy1sWJN9CteXURlHH7J3rVRqDPd6Wj3s9rLYIahEeFaDfA/ziYEHfg0nrBAtMEHcSTj5hcph21jZC2k0gBx6MHIJW/07MvH4RKZbb3ki2j4KO5gToq5HJ/8Iq0mposWb0IA2mVUnA=="
        ],
        "ARC-Message-Signature": [
            "i=2; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776783397; c=relaxed/simple;\n\tbh=+v90d6nPJJL+5nNeYYRyZ5OswaRENd0OB2njGVD8jPs=;\n\th=From:Date:Subject:Content-Type:Message-Id:References:In-Reply-To:\n\t To:Cc:MIME-Version;\n b=QD5t00Y0aOuruoAcgbAUzw8u22rErtXZ2Sy39WKCxa1ve0UKcPmQKo47tZwar/1bBqwkA4U+VG5kQ4wleJi1Gf2XDJAiImpsNvKHGENraYFhhf/kzrBzLrl9zKxqhjPGelOqin60D+itESs26k3sLBhqpW7C2LoTLQ4IEBIMFto=",
            "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=LMrf3c+zwtgjUAEfo1PPqVecL3lCus38m4GaKEn0YNE=;\n b=roYH/ekkbH0gAlrjf8/DPh842k2rVGlT3UQRnbKg9wg1bH9/vViiSff1ud08twTma32+/MjHwYsyZ5NTH4VwMNzHXcOicndXmHkFMyKgiynHRghwTztEfbg1NVvadkL88SaAO/mVK0yVShJ7t595kANo5x5mHWFAE58Z7yR/pizjRWiiCFdr3SwRDq/sI4rV3/UhPtYhwH6tWs4HHk8qOaMecODqpNFKOa0pSuq6/O9R8pnWyto3w0KOMXSCe8JI7VyaAOksMfkIe1HQbMDFGEqOSoMioyxe9kx4KdzaZAPMIJzt9CkdnzpGPKzLBmwnAqGABMPe/KxtT+PaBxfUyw=="
        ],
        "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=tkQEhTUZ; 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=LMrf3c+zwtgjUAEfo1PPqVecL3lCus38m4GaKEn0YNE=;\n b=tkQEhTUZ61ZhGpzOKQRAkuDB0Ly1iKddFS8/n9jWBEiqDV/sIDG8p5Qk3nzPX/wNGsEqH/4cn2ZVK8rbnS9Hzc3KZE9HItMsKkcXyARfOzwVHUA5mL+v9woWxB0Am7zA5YVXHcsh1IefRb8wpWIiOpXxeTrJCABcerLHtg/mxik=",
        "From": "Gary Guo <gary@garyguo.net>",
        "Date": "Tue, 21 Apr 2026 15:56:14 +0100",
        "Subject": "[PATCH v2 03/11] rust: io: use pointer types instead of address",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20260421-io_projection-v2-3-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=19161;\n i=gary@garyguo.net; s=20221204; h=from:subject:message-id;\n bh=+v90d6nPJJL+5nNeYYRyZ5OswaRENd0OB2njGVD8jPs=;\n b=vDuEVX4OICrx6bQ7VPCc+PjRpdD5QenD1dHrTb3fP1soxlglMrTgxHWFC/Pgx/QR55uYDaPZF\n 4XiArnKHTapAdTxdAJR9HTNY7MqyWut9f7ldElTDRIiEHGPWx2g0AzF",
        "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": "c3dac4c9-99d0-4c0d-71e0-08de9fb62a9d",
        "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\tr7i6aAoXO9YKwdyiGKUS/f4fYtuhO8bM7SAcvasLLwGpad3OfhLSydN3XkH/vlSMnrE5/YVdP0RBRNIhkPzDUtb7jZddBuxccDsSWRwmKwOS1pKMFbrb/7AvPmk5w+riAJ9CT36kMeS+Gg3i3bQuQ1+U3ieHFmweX41L0TW8r1RZnjRBw0f3QDi+6YyFr50yuB/6FjMTNtUk52BFuKX+NgcLC4lY387m1XjmHQycM779P2TL6ggfjyhoLxxp+cfU4dDmcZVbmwj1lUVT2gOvW1u2PcBizxFq91ThLJxXhxjaTAOzgo/7ao8pdyx0q2+aAl9QMFS5PbvKzF1ZuM0OpnTq7H0UEG9MI/H9yyYH4lMsKW+u0ldXyz6B1eWPjKZdfZtoePTLqQkKvgy7LNS9hvbaVNDt7hM15IVxqhWpnUigm/GFG9ZHdxvhc4gPzcM8/meKQKUgHtaIN7vgn5XpkNGD2oBa/eJpe8ZEIko+05XTN/UQ/Dq+nu+7DXUlSQdnA+cjKlPe5rrgXxx3wqqNXAcycr7drOTp90Zsk+IFPfw+3olqSRu+PD44sI4WSrneixt9PjvKvP+WoRB+Eh3Qcw2c4dMK7wvSV8+t+nBkvkuAq37osGrfLTsJta/nE+g2eJoE3zgkaP9wVOqqGTdwjZy1SDZtS9Ze/PxD7SBbFlvqJoAb91un5rfIwOvob1TsutPHx/ktJrGILV6adHi+W/u0mcNwPzTW+K7b05jZIy/mKkx3Yk60lRAKtB3HaFPeAZe4ffQh0id2PMjfwB5tdA==",
        "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?vFztxhXR1cJMzM1lTzURu2X97BWc?=\n\t=?utf-8?q?Gdoe4bxxfnPxiLBOvhPsSC8akIpt56vudInjRlU0z0RE+7thwO7dbeO7KFxSQzCQQ?=\n\t=?utf-8?q?uz+Y0AG2Sc2In0fJMUT4GYd/735C8tTmnXPa+gxoAvDX9GIIQcK/bWARFVGKwPNws?=\n\t=?utf-8?q?E+XCPbEzAWrZBLy2n6z6FRSy+QX0SBeJWxn4tx1SVNMFP5i7BqztPYMMm7FKVzwRK?=\n\t=?utf-8?q?E8HUAwhXSW2m3KLkD6BpfX646nq8+7+Fqd4mm0hakj5Fz7tl196zKKFN2HrbbIF9D?=\n\t=?utf-8?q?b6PJU7dxzsq12cv4dGmulND5IM7nYI49hL10NSlZqSGNfodUiQzASr1NoQ9s1l+d5?=\n\t=?utf-8?q?sWdLW+A6QvSl5oMHT57xUEgXuHuxAYZqG0W+vLU4cXjApY4y5MS1pu+our82cP1ah?=\n\t=?utf-8?q?D8XtsPyDyp/lrLqx5lGB3do0xFAHZHt4V9gnMJfGd8cZkrMBjrNFUrqZOvMPrptF/?=\n\t=?utf-8?q?k9E6n/d65SH8xZRrhFC78ADMFx3N1RlqOuawBPtOFCONrYm2Y9ieAqlNGjKpBmJZ0?=\n\t=?utf-8?q?wRYYFUp7Db+2IyyWW5xyAGrTpsoL1g5feXLjNvADe26qM8D3zewS0lzuOrSobnqrs?=\n\t=?utf-8?q?KDtszUhdh1JXK2unJuS4l8ftd+jxJ0lb9owdjtQ7y9S2OwupxXdULNAIXodAPqhtu?=\n\t=?utf-8?q?3Wva2nFGiX8SKM3GmptKzbBWyBK8v9prm5902+2ugQ9mdBCiHvNo2nHIjrpNiEequ?=\n\t=?utf-8?q?f57YtBgAuo7zAyzG1qj1o/QTiAGtMB62Upelyn1VK6uLW+CNzHxIIzNxAOm3pkNU8?=\n\t=?utf-8?q?t3Vhmro3bK1pkJvAXpPwMJfdKOZ2p3J4MibXn4ossfIO58MhhHH2ZN8+o9phVoLrY?=\n\t=?utf-8?q?crJYkx9obCY6uehqxhwvwJORgFqve98ZftCGcGlixzi0TMc5gOosmAZ1HRzT8BOPs?=\n\t=?utf-8?q?RsaM1kXQ8lQyPP11wN80nBYs84p/fa2CDr5pFPt74BuOXsC2N1E5D51rZVGX3BidJ?=\n\t=?utf-8?q?bRvYr409LkyMYGfxBdR3W9q91ilmwm6GmXKPLIrFMIn/Yv+XkbmOzNYDNys74TkjE?=\n\t=?utf-8?q?SEW6eNCOJat/OjucIqaB6SEtrugy0Ub7OWh6eYZQ7T+++CPQtapal7NhYNaV2Yzx0?=\n\t=?utf-8?q?J2nDzVyAbgSPSXH6TKgkrOOVOoCyHALc2uwKtcWiAqN7a8x4tHrJSeVHUQdwXparV?=\n\t=?utf-8?q?24ByaA+XKYAXcz7gU8Fg9haPa4uQyBugxwD/epd5opkvNZ/PxH3x/OoduyQfwAjrX?=\n\t=?utf-8?q?dm+90Ayn1eO1MRri7jejv+DxD4M6/fugO/62SEfIDsi+qCYa+i+tHcFCXUfze/fcg?=\n\t=?utf-8?q?tdoCf2RRHM96KqsT+fU0lidE3F5y8UA/L2NcTikr12Axiryv3yx48XUU5b+ok62wB?=\n\t=?utf-8?q?LCgC1J7F9g2E/hnkGUPggpt7+fuRoa8NhSrSAjLRtU8TR3TYqBzCoFO6qg7RzfQIJ?=\n\t=?utf-8?q?/IZwAbUecmyQJ778FdmEGs8p7N4pxEG66MFtk5m99EJIg19f2n0lbgdIdhOUTY0vr?=\n\t=?utf-8?q?Zy/YItacCI8yPQLGob4KOK22dP7TFRfCK6GI72jUq3i4T/uIj2IEf5cj+GsfSTx56?=\n\t=?utf-8?q?PW2ekMz47vhV0QQ5LI9rE2Y9Q8J9E/cQwBy3yGxgJK0MBOWXYrjQqLMDp2QkZMMo8?=\n\t=?utf-8?q?TmFVzBVUOamdKh8pH+lEAcur+kHVohkFzI+xR0SCgdXkOOa7E3wJ0g6GChEvqSqOq?=\n\t=?utf-8?q?0owp/ngpIvJjIHO/iHcJ9rjC71grFYlA=3D=3D?=",
        "X-OriginatorOrg": "garyguo.net",
        "X-MS-Exchange-CrossTenant-Network-Message-Id": "\n c3dac4c9-99d0-4c0d-71e0-08de9fb62a9d",
        "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:28.1880\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 hZcMwBZCgR2Ml0FPY5vTc3uhkoRdzqcFg7l8CbxSViYmnI7T4kOGC1IiXxEEiuDjjJN0fGDCE4mx6YAROvplBA==",
        "X-MS-Exchange-Transport-CrossTenantHeadersStamped": "CWLP265MB5523"
    },
    "content": "This carries the size information with the pointer type and metadata, makes\nit possible to use I/O projections and paves the way for IO view types.\n\nWith this change, minimum size information becomes available through types;\nso `KnownSize::MIN_SIZE` can be used and `IoKnownSize` trait is no longer\nnecessary. The trait is kept for compatibility and can be removed when\nusers stop using it for bounds.\n\nPCI config space uses only offsets and not pointers like MMIO; for this\nnull pointers (with proper size metadata) is used. This is okay as I/O\ntrait impl and I/O projections can operate on invalid pointers, and for PCI\nconfig space we will only use address info and ignore the provenance.\n\nSigned-off-by: Gary Guo <gary@garyguo.net>\n---\n rust/kernel/devres.rs |   2 +-\n rust/kernel/io.rs     | 123 +++++++++++++++++++++-----------------------------\n rust/kernel/io/mem.rs |   2 +-\n rust/kernel/pci/io.rs |  74 ++++++++++++++++++------------\n 4 files changed, 99 insertions(+), 102 deletions(-)",
    "diff": "diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs\nindex 3e22c63efb98..ea86e9c62cdf 100644\n--- a/rust/kernel/devres.rs\n+++ b/rust/kernel/devres.rs\n@@ -101,7 +101,7 @@ struct Inner<T> {\n /// impl<const SIZE: usize> Drop for IoMem<SIZE> {\n ///     fn drop(&mut self) {\n ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.\n-///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };\n+///         unsafe { bindings::iounmap(self.0.as_ptr().cast()); };\n ///     }\n /// }\n ///\ndiff --git a/rust/kernel/io.rs b/rust/kernel/io.rs\nindex 0b9c97c0a1d7..1682f2a0d20d 100644\n--- a/rust/kernel/io.rs\n+++ b/rust/kernel/io.rs\n@@ -105,8 +105,8 @@ pub fn new_region(addr: usize, size: usize) -> Result<Self> {\n impl<T: ?Sized + KnownSize> MmioRaw<T> {\n     /// Returns the base address of the MMIO region.\n     #[inline]\n-    pub fn addr(&self) -> usize {\n-        self.addr.addr()\n+    pub fn as_ptr(&self) -> *mut T {\n+        self.addr\n     }\n \n     /// Returns the size of the MMIO region.\n@@ -166,7 +166,7 @@ pub fn size(&self) -> usize {\n /// impl<const SIZE: usize> Drop for IoMem<SIZE> {\n ///     fn drop(&mut self) {\n ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.\n-///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };\n+///         unsafe { bindings::iounmap(self.0.as_ptr().cast()); };\n ///     }\n /// }\n ///\n@@ -217,14 +217,14 @@ pub trait IoCapable<T> {\n     /// # Safety\n     ///\n     /// The range `[address..address + size_of::<T>()]` must be within the bounds of `Self`.\n-    unsafe fn io_read(&self, address: usize) -> T;\n+    unsafe fn io_read(&self, address: *mut T) -> T;\n \n     /// Performs an I/O write of `value` at `address`.\n     ///\n     /// # Safety\n     ///\n     /// The range `[address..address + size_of::<T>()]` must be within the bounds of `Self`.\n-    unsafe fn io_write(&self, value: T, address: usize);\n+    unsafe fn io_write(&self, value: T, address: *mut T);\n }\n \n /// Describes a given I/O location: its offset, width, and type to convert the raw value from and\n@@ -291,23 +291,35 @@ fn offset(self) -> usize {\n /// For MMIO regions, all widths (u8, u16, u32, and u64 on 64-bit systems) are typically\n /// supported. For PCI configuration space, u8, u16, and u32 are supported but u64 is not.\n pub trait Io {\n-    /// Returns the base address of this mapping.\n-    fn addr(&self) -> usize;\n+    /// Type of this I/O region. For untyped I/O regions, [`Region`] type can be used.\n+    type Type: ?Sized + KnownSize;\n+\n+    /// Returns the base pointer of this mapping.\n+    ///\n+    /// This is a pointer to capture metadata. The specific meaning of the pointer depends on\n+    /// I/O backend and is not necessarily valid.\n+    fn as_ptr(&self) -> *mut Self::Type;\n+\n+    /// Returns the absolute I/O address for a given `offset`,\n+    /// performing compile-time bound checks.\n+    // Always inline to optimize out error path of `build_assert`.\n+    #[inline(always)]\n+    fn io_addr_assert<U>(&self, offset: usize) -> *mut U {\n+        build_assert!(offset_valid::<U>(offset, Self::Type::MIN_SIZE));\n \n-    /// Returns the maximum size of this mapping.\n-    fn maxsize(&self) -> usize;\n+        self.as_ptr().wrapping_byte_add(offset).cast()\n+    }\n \n     /// Returns the absolute I/O address for a given `offset`,\n     /// performing runtime bound checks.\n     #[inline]\n-    fn io_addr<U>(&self, offset: usize) -> Result<usize> {\n-        if !offset_valid::<U>(offset, self.maxsize()) {\n+    fn io_addr<U>(&self, offset: usize) -> Result<*mut U> {\n+        let ptr = self.as_ptr();\n+        if !offset_valid::<U>(offset, Self::Type::size(ptr)) {\n             return Err(EINVAL);\n         }\n \n-        // Probably no need to check, since the safety requirements of `Self::new` guarantee that\n-        // this can't overflow.\n-        self.addr().checked_add(offset).ok_or(EINVAL)\n+        Ok(ptr.wrapping_byte_add(offset).cast())\n     }\n \n     /// Fallible 8-bit read with runtime bounds check.\n@@ -386,7 +398,7 @@ fn try_write64(&self, value: u64, offset: usize) -> Result\n     #[inline(always)]\n     fn read8(&self, offset: usize) -> u8\n     where\n-        Self: IoKnownSize + IoCapable<u8>,\n+        Self: IoCapable<u8>,\n     {\n         self.read(offset)\n     }\n@@ -395,7 +407,7 @@ fn read8(&self, offset: usize) -> u8\n     #[inline(always)]\n     fn read16(&self, offset: usize) -> u16\n     where\n-        Self: IoKnownSize + IoCapable<u16>,\n+        Self: IoCapable<u16>,\n     {\n         self.read(offset)\n     }\n@@ -404,7 +416,7 @@ fn read16(&self, offset: usize) -> u16\n     #[inline(always)]\n     fn read32(&self, offset: usize) -> u32\n     where\n-        Self: IoKnownSize + IoCapable<u32>,\n+        Self: IoCapable<u32>,\n     {\n         self.read(offset)\n     }\n@@ -413,7 +425,7 @@ fn read32(&self, offset: usize) -> u32\n     #[inline(always)]\n     fn read64(&self, offset: usize) -> u64\n     where\n-        Self: IoKnownSize + IoCapable<u64>,\n+        Self: IoCapable<u64>,\n     {\n         self.read(offset)\n     }\n@@ -422,7 +434,7 @@ fn read64(&self, offset: usize) -> u64\n     #[inline(always)]\n     fn write8(&self, value: u8, offset: usize)\n     where\n-        Self: IoKnownSize + IoCapable<u8>,\n+        Self: IoCapable<u8>,\n     {\n         self.write(offset, value)\n     }\n@@ -431,7 +443,7 @@ fn write8(&self, value: u8, offset: usize)\n     #[inline(always)]\n     fn write16(&self, value: u16, offset: usize)\n     where\n-        Self: IoKnownSize + IoCapable<u16>,\n+        Self: IoCapable<u16>,\n     {\n         self.write(offset, value)\n     }\n@@ -440,7 +452,7 @@ fn write16(&self, value: u16, offset: usize)\n     #[inline(always)]\n     fn write32(&self, value: u32, offset: usize)\n     where\n-        Self: IoKnownSize + IoCapable<u32>,\n+        Self: IoCapable<u32>,\n     {\n         self.write(offset, value)\n     }\n@@ -449,7 +461,7 @@ fn write32(&self, value: u32, offset: usize)\n     #[inline(always)]\n     fn write64(&self, value: u64, offset: usize)\n     where\n-        Self: IoKnownSize + IoCapable<u64>,\n+        Self: IoCapable<u64>,\n     {\n         self.write(offset, value)\n     }\n@@ -637,7 +649,7 @@ fn try_update<T, L, F>(&self, location: L, f: F) -> Result\n     fn read<T, L>(&self, location: L) -> T\n     where\n         L: IoLoc<T>,\n-        Self: IoKnownSize + IoCapable<L::IoType>,\n+        Self: IoCapable<L::IoType>,\n     {\n         let address = self.io_addr_assert::<L::IoType>(location.offset());\n \n@@ -670,7 +682,7 @@ fn read<T, L>(&self, location: L) -> T\n     fn write<T, L>(&self, location: L, value: T)\n     where\n         L: IoLoc<T>,\n-        Self: IoKnownSize + IoCapable<L::IoType>,\n+        Self: IoCapable<L::IoType>,\n     {\n         let address = self.io_addr_assert::<L::IoType>(location.offset());\n         let io_value = value.into();\n@@ -715,7 +727,7 @@ fn write_reg<T, L, V>(&self, value: V)\n     where\n         L: IoLoc<T>,\n         V: LocatedRegister<Location = L, Value = T>,\n-        Self: IoKnownSize + IoCapable<L::IoType>,\n+        Self: IoCapable<L::IoType>,\n     {\n         let (location, value) = value.into_io_op();\n \n@@ -748,7 +760,7 @@ fn write_reg<T, L, V>(&self, value: V)\n     fn update<T, L, F>(&self, location: L, f: F)\n     where\n         L: IoLoc<T>,\n-        Self: IoKnownSize + IoCapable<L::IoType> + Sized,\n+        Self: IoCapable<L::IoType>,\n         F: FnOnce(T) -> T,\n     {\n         let address = self.io_addr_assert::<L::IoType>(location.offset());\n@@ -762,41 +774,25 @@ fn update<T, L, F>(&self, location: L, f: F)\n     }\n }\n \n-/// Trait for types with a known size at compile time.\n-///\n-/// This trait is implemented by I/O backends that have a compile-time known size,\n-/// enabling the use of infallible I/O accessors with compile-time bounds checking.\n-///\n-/// Types implementing this trait can use the infallible methods in [`Io`] trait\n-/// (e.g., `read8`, `write32`), which require `Self: IoKnownSize` bound.\n-pub trait IoKnownSize: Io {\n-    /// Minimum usable size of this region.\n-    const MIN_SIZE: usize;\n-\n-    /// Returns the absolute I/O address for a given `offset`,\n-    /// performing compile-time bound checks.\n-    // Always inline to optimize out error path of `build_assert`.\n-    #[inline(always)]\n-    fn io_addr_assert<U>(&self, offset: usize) -> usize {\n-        build_assert!(offset_valid::<U>(offset, Self::MIN_SIZE));\n+// For compatibility only.\n+#[doc(hidden)]\n+pub trait IoKnownSize: Io {}\n \n-        self.addr() + offset\n-    }\n-}\n+impl<T: Io + ?Sized> IoKnownSize for T {}\n \n /// Implements [`IoCapable`] on `$mmio` for `$ty` using `$read_fn` and `$write_fn`.\n macro_rules! impl_mmio_io_capable {\n     ($mmio:ident, $(#[$attr:meta])* $ty:ty, $read_fn:ident, $write_fn:ident) => {\n         $(#[$attr])*\n         impl<T: ?Sized> IoCapable<$ty> for $mmio<T> {\n-            unsafe fn io_read(&self, address: usize) -> $ty {\n+            unsafe fn io_read(&self, address: *mut $ty) -> $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             }\n \n-            unsafe fn io_write(&self, value: $ty, address: usize) {\n+            unsafe fn io_write(&self, value: $ty, address: *mut $ty) {\n                 // SAFETY: By the trait invariant `address` is a valid address for MMIO operations.\n-                unsafe { bindings::$write_fn(value, address as *mut c_void) }\n+                unsafe { bindings::$write_fn(value, address.cast()) }\n             }\n         }\n     };\n@@ -816,23 +812,15 @@ unsafe fn io_write(&self, value: $ty, address: usize) {\n );\n \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-        self.0.addr()\n-    }\n+    type Type = T;\n \n-    /// Returns the maximum size of this mapping.\n+    /// Returns the base address of this mapping.\n     #[inline]\n-    fn maxsize(&self) -> usize {\n-        self.0.size()\n+    fn as_ptr(&self) -> *mut T {\n+        self.0.as_ptr()\n     }\n }\n \n-impl<T: ?Sized + KnownSize> IoKnownSize for Mmio<T> {\n-    const MIN_SIZE: usize = T::MIN_SIZE;\n-}\n-\n impl<T: ?Sized + KnownSize> Mmio<T> {\n     /// Converts an `MmioRaw` into an `Mmio` instance, providing the accessors to the MMIO mapping.\n     ///\n@@ -856,21 +844,14 @@ pub unsafe fn from_raw(raw: &MmioRaw<T>) -> &Self {\n pub struct RelaxedMmio<T: ?Sized>(Mmio<T>);\n \n impl<T: ?Sized + KnownSize> Io for RelaxedMmio<T> {\n-    #[inline]\n-    fn addr(&self) -> usize {\n-        self.0.addr()\n-    }\n+    type Type = T;\n \n     #[inline]\n-    fn maxsize(&self) -> usize {\n-        self.0.maxsize()\n+    fn as_ptr(&self) -> *mut T {\n+        self.0.as_ptr()\n     }\n }\n \n-impl<T: ?Sized + KnownSize> IoKnownSize for RelaxedMmio<T> {\n-    const MIN_SIZE: usize = T::MIN_SIZE;\n-}\n-\n impl<T: ?Sized> Mmio<T> {\n     /// Returns a [`RelaxedMmio`] reference that performs relaxed I/O operations.\n     ///\ndiff --git a/rust/kernel/io/mem.rs b/rust/kernel/io/mem.rs\nindex a6292f4ebfa4..f87a29f90e79 100644\n--- a/rust/kernel/io/mem.rs\n+++ b/rust/kernel/io/mem.rs\n@@ -284,7 +284,7 @@ pub fn new<'a>(io_request: IoRequest<'a>) -> impl PinInit<Devres<Self>, Error> +\n impl<const SIZE: usize> Drop for IoMem<SIZE> {\n     fn drop(&mut self) {\n         // SAFETY: Safe as by the invariant of `Io`.\n-        unsafe { bindings::iounmap(self.io.addr() as *mut c_void) }\n+        unsafe { bindings::iounmap(self.io.as_ptr().cast()) }\n     }\n }\n \ndiff --git a/rust/kernel/pci/io.rs b/rust/kernel/pci/io.rs\nindex e048370fb8c1..63c35eaab6c3 100644\n--- a/rust/kernel/pci/io.rs\n+++ b/rust/kernel/pci/io.rs\n@@ -10,11 +10,11 @@\n     io::{\n         Io,\n         IoCapable,\n-        IoKnownSize,\n         Mmio,\n         MmioRaw, //\n     },\n     prelude::*,\n+    ptr::KnownSize,\n     sync::aref::ARef, //\n };\n use core::{\n@@ -60,14 +60,37 @@ pub const fn into_raw(self) -> usize {\n pub trait ConfigSpaceKind {\n     /// The size of this configuration space in bytes.\n     const SIZE: usize;\n+\n+    /// Region type for this kind of config space. This should be [`crate::io::Region<SIZE>`].\n+    type Region: ?Sized + KnownSize;\n+\n+    /// Obtain pointer with actual size information.\n+    fn null_ptr_from_size(size: ConfigSpaceSize) -> *mut Self::Region;\n }\n \n impl ConfigSpaceKind for Normal {\n     const SIZE: usize = 256;\n+\n+    type Region = crate::io::Region<256>;\n+\n+    #[inline]\n+    fn null_ptr_from_size(size: ConfigSpaceSize) -> *mut Self::Region {\n+        core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut::<u8>(), size.into_raw())\n+            as *mut Self::Region\n+    }\n }\n \n impl ConfigSpaceKind for Extended {\n     const SIZE: usize = 4096;\n+\n+    type Region = crate::io::Region<4096>;\n+\n+    #[inline]\n+    fn null_ptr_from_size(_: ConfigSpaceSize) -> *mut Self::Region {\n+        // Small optimization. For a extended config space, we already know that the size\n+        // is 4096.\n+        core::ptr::slice_from_raw_parts_mut(core::ptr::null_mut::<u8>(), 4096) as *mut Self::Region\n+    }\n }\n \n /// The PCI configuration space of a device.\n@@ -87,28 +110,28 @@ pub struct ConfigSpace<'a, S: ConfigSpaceKind = Extended> {\n macro_rules! impl_config_space_io_capable {\n     ($ty:ty, $read_fn:ident, $write_fn:ident) => {\n         impl<'a, S: ConfigSpaceKind> IoCapable<$ty> for ConfigSpace<'a, S> {\n-            unsafe fn io_read(&self, address: usize) -> $ty {\n+            unsafe fn io_read(&self, address: *mut $ty) -> $ty {\n+                // CAST: The offset is cast to `i32` because the C functions expect a 32-bit\n+                // signed offset parameter. PCI configuration space size is at most 4096 bytes,\n+                // so the value always fits within `i32` without truncation or sign change.\n+                let addr = address.addr() as i32;\n                 let mut val: $ty = 0;\n \n                 // Return value from C function is ignored in infallible accessors.\n-                let _ret =\n-                    // SAFETY: By the type invariant `self.pdev` is a valid address.\n-                    // CAST: The offset is cast to `i32` because the C functions expect a 32-bit\n-                    // signed offset parameter. PCI configuration space size is at most 4096 bytes,\n-                    // so the value always fits within `i32` without truncation or sign change.\n-                    unsafe { bindings::$read_fn(self.pdev.as_raw(), address as i32, &mut val) };\n-\n+                // SAFETY: By the type invariant `self.pdev` is a valid address.\n+                let _ = unsafe { bindings::$read_fn(self.pdev.as_raw(), addr, &mut val) };\n                 val\n             }\n \n-            unsafe fn io_write(&self, value: $ty, address: usize) {\n+            unsafe fn io_write(&self, value: $ty, address: *mut $ty) {\n+                // CAST: The offset is cast to `i32` because the C functions expect a 32-bit\n+                // signed offset parameter. PCI configuration space size is at most 4096 bytes,\n+                // so the value always fits within `i32` without truncation or sign change.\n+                let addr = address.addr() as i32;\n+\n                 // Return value from C function is ignored in infallible accessors.\n-                let _ret =\n-                    // SAFETY: By the type invariant `self.pdev` is a valid address.\n-                    // CAST: The offset is cast to `i32` because the C functions expect a 32-bit\n-                    // signed offset parameter. PCI configuration space size is at most 4096 bytes,\n-                    // so the value always fits within `i32` without truncation or sign change.\n-                    unsafe { bindings::$write_fn(self.pdev.as_raw(), address as i32, value) };\n+                // SAFETY: By the type invariant `self.pdev` is a valid address.\n+                let _ = unsafe { bindings::$write_fn(self.pdev.as_raw(), addr, value) };\n             }\n         }\n     };\n@@ -120,23 +143,15 @@ unsafe fn io_write(&self, value: $ty, address: usize) {\n impl_config_space_io_capable!(u32, pci_read_config_dword, pci_write_config_dword);\n \n impl<'a, S: ConfigSpaceKind> Io for ConfigSpace<'a, S> {\n-    /// Returns the base address of the I/O region. It is always 0 for configuration space.\n-    #[inline]\n-    fn addr(&self) -> usize {\n-        0\n-    }\n+    type Type = S::Region;\n \n-    /// Returns the maximum size of the configuration space.\n+    /// Returns the base address of the I/O region. It is always 0 for configuration space.\n     #[inline]\n-    fn maxsize(&self) -> usize {\n-        self.pdev.cfg_size().into_raw()\n+    fn as_ptr(&self) -> *mut Self::Type {\n+        S::null_ptr_from_size(self.pdev.cfg_size())\n     }\n }\n \n-impl<'a, S: ConfigSpaceKind> IoKnownSize for ConfigSpace<'a, S> {\n-    const MIN_SIZE: usize = S::SIZE;\n-}\n-\n /// A PCI BAR to perform I/O-Operations on.\n ///\n /// I/O backend assumes that the device is little-endian and will automatically\n@@ -219,7 +234,7 @@ unsafe fn do_release(pdev: &Device, ioptr: usize, num: i32) {\n \n     fn release(&self) {\n         // SAFETY: The safety requirements are guaranteed by the type invariant of `self.pdev`.\n-        unsafe { Self::do_release(&self.pdev, self.io.addr(), self.num) };\n+        unsafe { Self::do_release(&self.pdev, self.io.as_ptr().addr(), self.num) };\n     }\n }\n \n@@ -267,6 +282,7 @@ pub fn iomap_region<'a>(\n     }\n \n     /// Returns the size of configuration space.\n+    #[inline]\n     pub fn cfg_size(&self) -> ConfigSpaceSize {\n         // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`.\n         let size = unsafe { (*self.as_raw()).cfg_size };\n",
    "prefixes": [
        "v2",
        "03/11"
    ]
}