From nobody Fri Apr 17 00:17:58 2026 Received: from CY7PR03CU001.outbound.protection.outlook.com (mail-westcentralusazon11010059.outbound.protection.outlook.com [40.93.198.59]) (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 0611D1B4F09; Tue, 24 Feb 2026 22:40:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.93.198.59 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771972821; cv=fail; b=E9Djt85VkKi2EEj4T70am7RLzfGqrS4LCSdcQPoeQbMLi5nfHQo4d8tLN1ZerqrjqX6p+Bfn2954ZIzrtZlsdD/7KMUPv+pET5pI7i+63eDdzjaMWzubKZHanmNeiAhfmY0XpxHQnOe8AkpwP5GM2YbKnuGj/4wN6kkZ38K0Yg0= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771972821; c=relaxed/simple; bh=6CYNZsfQfv/O64TUtJiUmHnrwshvuNXEXzaG0x9Xc5c=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=ZSkfekN4aigcebzrSw1VmwHVFFHu7jv7JB5dkC+2AopBfai4Qt9mYWxJSLM64+H5DGxvzguLR5zSb7uUDBtXMhaf5EIQniE0Aq/BjRuQ7PBFj7UEbpTnvQLtPuyFUF79lOfhNcX1BBSNQZUWz/Mtl02a9nYcC1L8DfBAR0o0yoQ= 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=tPuitM++; arc=fail smtp.client-ip=40.93.198.59 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="tPuitM++" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=yhpGCaaCiPosdTI+Hzgb7xgxXLHDacsFVeCmwQSGU5zvx1BLUW/eig7WNpCRP0mZ82CPAC6ZAe/e1UD9N932PMEeIjSC0LQhnc/CskHjSz6qsxmKRiNOsirQjYBoaVII9EpgAMCw6Z0lMSB8asFihkNrzJgW6XuU9SE8GmS2ojxyaSMaLr0GoQgsjcN8C2khc5gLFWPqNC84kzl0uw00G2ZLulucLoiPsaBeIQlC2N/XRG0WiTBvGN13FnAihPsKaQEPvwVWJdZSPf+vOEUMuKL0YQ2MdQz0qDzvblFKtrMiRhW3Zz1IT7SUPpxRuIb3QefqqC9S25LaNf1vd/fK+A== 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=QTKgckHqENZNSWGfsHIpHTsn7t6tLd8/f+Yki4Kw6eE=; b=FEp4CtbmzsYizzL0Iw4uwZdp92NitusFwsxZA2EqhGavv9GtyxIfayz1hA/0sNssk5wWiGWU2ONzloQCG1HpG9H2VpydTfnoP44g7MiX2VYa5Kwus6S3xNBriVUlbpSJH5i/ydShLKNl8ejTnzwuaq6/q6DQDoqC4DB57pE4gv/Mo24Q+4GHPyaLWc+MGZz+Asc0ZQLkpUkaLQ3geHTLq9cheAgQfLRTgB6s4PQu75fbfvPqWrFOIYV7cp4aOVLQNWO4APUjyXKe07Im6qCsjHGCBypwZkLgojsC3pTtZOK3qNrjuDYTuYVZrtDOBun7sOobQ/vtITALg4hrMeveFA== 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=QTKgckHqENZNSWGfsHIpHTsn7t6tLd8/f+Yki4Kw6eE=; b=tPuitM++B+au/z3cfN3JVdjs6RftXtI9mGOUFEEeOu8juAFXfNpW5qkUbXoZv5ytO/K/ewlqfDE5mj08/eeNhrpTb/NwvNJdZ91xOL/UID8wdE8HZlyDJdkTsKXWM1MA5MksxqYBOM+S/ZO5kRYHae3jkqPi+KfvxyH7YrQqZvXLEYRzA0FmcgVRX8i+hn5d3YxxXz5zK88EYGH6biejXFkW8kGMH6vKuGnP10guRMNpw1ipnYz+fTYRVuON9ZPIeH3zs4jV/jOE4mkHzspo7oDXlW+51mRTsc9Zz2mO5FmZgJ2LzXgJf8OhAbV9HweOAkKwU/O/uJ4JZkJgPLP9Xw== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from DS0PR12MB6486.namprd12.prod.outlook.com (2603:10b6:8:c5::21) by PH0PR12MB7816.namprd12.prod.outlook.com (2603:10b6:510:28c::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 22:40:13 +0000 Received: from DS0PR12MB6486.namprd12.prod.outlook.com ([fe80::88a9:f314:c95f:8b33]) by DS0PR12MB6486.namprd12.prod.outlook.com ([fe80::88a9:f314:c95f:8b33%4]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 22:40:13 +0000 From: Joel Fernandes To: linux-kernel@vger.kernel.org Cc: Miguel Ojeda , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Dave Airlie , Daniel Almeida , Koen Koning , dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, rust-for-linux@vger.kernel.org, Nikola Djukic , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jonathan Corbet , Alex Deucher , =?UTF-8?q?Christian=20K=C3=B6nig?= , Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , Huang Rui , Matthew Auld , Matthew Brost , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Helge Deller , Alex Gaynor , Boqun Feng , John Hubbard , Alistair Popple , Timur Tabi , Edwin Peer , Alexandre Courbot , Andrea Righi , Andy Ritger , Zhi Wang , Balbir Singh , Philipp Stanner , Elle Rhumsaa , alexeyi@nvidia.com, Eliot Courtney , joel@joelfernandes.org, linux-doc@vger.kernel.org, amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org, linux-fbdev@vger.kernel.org, Joel Fernandes Subject: [reference PATCH v11 1/4] gpu: Move DRM buddy allocator one level up (part one) Date: Tue, 24 Feb 2026 17:40:02 -0500 Message-Id: <20260224224005.3232841-2-joelagnelf@nvidia.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260224224005.3232841-1-joelagnelf@nvidia.com> References: <20260224224005.3232841-1-joelagnelf@nvidia.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: MN0PR05CA0006.namprd05.prod.outlook.com (2603:10b6:208:52c::31) To DS0PR12MB6486.namprd12.prod.outlook.com (2603:10b6:8:c5::21) 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: DS0PR12MB6486:EE_|PH0PR12MB7816:EE_ X-MS-Office365-Filtering-Correlation-Id: 5a36273c-9472-4f7c-00f8-08de73f5acbb X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|7416014|376014|366016; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?XkHSaJiRxfVP0PpJo0ODVy38XXoOia4Jklh4VX5jajtt9y7EvfP219HtajQ7?= =?us-ascii?Q?KxMlNtkSK3isco3zB7lEQxCDaZNCJrmAcFA04TU29JxKPt3Pt9z+Esj8EUft?= =?us-ascii?Q?JfReq5vsavAZfeBFN7OkDZhnQWuxYd4XmXFjvn3XlMXUMpb+9j4+Bla1pPq6?= =?us-ascii?Q?8yVq8Xl/WDy/YWaynkvwSErTIlNuZ/A1XL7PqllLGC4BTu4Hq+HOxCcg5oyV?= =?us-ascii?Q?RMoUCMSOO2ONYY3c6BgTtXQ+CcZIlEDUHHm0FoX9UiVzQ2oEl6oH8GHmCyPM?= =?us-ascii?Q?aN+19hT/jwIsZMoYVClMzANGoiiA7ozZltcxXBwCzo7CxBYst0TxP2yDG2X5?= =?us-ascii?Q?F+R/5T155HUyFcZOwFOwNFts73zf3mHiDM20ImqcJtCQkPNyI1THESH9MIIE?= =?us-ascii?Q?gMK7wVTlDK6Rz39IPvS3m1tlTOvvm1h0kIgKiwqkut5ywfZSVNf37tG4d1IW?= =?us-ascii?Q?3ipz5YGqSD5XJx7LBKFVDOywiFheI/ZuLP2nx8kVz6P85aHaPGda4PJO3pZ4?= =?us-ascii?Q?kR2v9YOvTPqMRr+0hds8/Vici5kO4Y6w2F/iehRgEgMasERtPckOwyO9Fphd?= =?us-ascii?Q?7ecYpdMyn0RCZZiYBVxJ+7JXRg768W6w/uxeV4jMDPVSnYk18DITudgphhNo?= =?us-ascii?Q?ruxE7ujtYAiCB/HwlC+HhAhhw1MbEdpMP1XYZ9d8MEP6xg0yDatiWvYwAZWJ?= =?us-ascii?Q?xbP1Z2QKoR/gACnO3ZouqWYoXj0L24fjh7iSbUzFkUv+UopgnVUSQrC7XZTA?= =?us-ascii?Q?SCWsfvowPaDtuz8xud9tszS7xJCVpUCMZZQrzh2wfR8NKd5IdLEixfE/YxmY?= =?us-ascii?Q?eBKIIZGMxiVV2DzQ824Www56yWZZ4oKuLuvYHwnTVE6G36DQvcQT++3Wrdmf?= =?us-ascii?Q?xkQekO2qBgjhiGuFyysjKzR+vdF2UizkPvYUt6kB6cn6ZwP5Sa+YxSQh+lKX?= =?us-ascii?Q?/5qo9QDwHSEKwyIxKRBarimxX+3kdWyDa0D3kKHHWYp30HHbEEQASpAxnAoH?= =?us-ascii?Q?u0AVxfbcLRRWnQ+0cBCRV15BplTTSsgKwYmATLuQrZtaBQ4LCmCVnnu4TIeu?= =?us-ascii?Q?KbXxJzfZ7zqgdheqP0K49xC/8/NaCiYbNRu77s8YLyIZLr6cVZIlFoBDcvSC?= =?us-ascii?Q?ccz4Kn35JDAnnv3Bm9ktPfW1vSgENXYzUPTvGWrCVIPraE64ElEr4wI/Tcy+?= =?us-ascii?Q?hR2mQ6I9r28vpZ2nbg3tlag4wY6nnHSVgSUBR9h75K+IhZAQ4qA7+FTcdbwa?= =?us-ascii?Q?OQTHUIY9OB5raVUXVg0lxg4y7Z+4U4XrJl3i3CVXm0iTc0tSTRhwjfN0v6Pu?= =?us-ascii?Q?AVmwajgGrh2lUEuu0ac25RdwY9JtrXcPQgplAVYGHKUq1tYKl2GZFYXSc7sc?= =?us-ascii?Q?uQbrzmEmtWiOMAVrxBcggBioV6tQNf9E9nlO1uALXAe9w/Xi1Ev1ti+V99fC?= =?us-ascii?Q?AchGQZ6hzRtPIIPOPG2d+/QVRbi9I84EPipiN8LiczFu98jBANHMvFSQVFdY?= =?us-ascii?Q?7WA93H4ZIpW/tfsABf6S+UMKwz4DYDx/a50+UmEzH6vMnfdWNYGw26bOUIEd?= =?us-ascii?Q?85NYj3VwOECxcmvujvU=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DS0PR12MB6486.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(7416014)(376014)(366016);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?cMmORnjn7ixxF8m8b7NYYBsmhdq4hg7jGVcpylWptnzfVmEPP98jHU1TQu+S?= =?us-ascii?Q?5vTW6aIZ2Fbl10ygZFJ2sYnvH92cU8qapzkC9h404PBrTKKKyo9ANWbImtsz?= =?us-ascii?Q?Q57go+DfzZiNkn0+p9QSZvBbsOrMLex14YV6ftmLIHXQsO+u3XPCUhPeMqBq?= =?us-ascii?Q?Hzy1YHm0U+uELrSEadTZw+izpDVcE4OszSs17JO30mCXgm+ITPA5kcpTeUp6?= =?us-ascii?Q?AVEQ6U4DPoXQN06GxNwGJ7ZN+wZRvW7xUrNDgvd9WsqPENpk3IvlZDtjnTy7?= =?us-ascii?Q?myL6+lsFgMVQfsVadBPQN5ROGDFg3vV5PAPOIaRml5uJzQ8s9osoIrC1lS/U?= =?us-ascii?Q?9CHCcZGByX4xSWiQU9aGDcDYxLAHZ/iwMpTGF/S1do3epZ2yXGhQDd+6V/xv?= =?us-ascii?Q?y4ROao2D32XksGgZ0M2ZMree2/GNlP7elV/UNemYmTUnMUteUKlljJlKGXC4?= =?us-ascii?Q?D8jxpn735l7+4pJelmOP6LlBP3AZ5o7fYdDzkG1ECrd8I+TISxjVUWYOa4YX?= =?us-ascii?Q?v7LmQHr7pn6MwYvRvlp/ZnHn+MwbP6Mw9I3rV+avj3B6IBjzIFitQKSJvmnd?= =?us-ascii?Q?C6XtDLgeTeAYb6oTUajvTfLtiXOSGb7K/W0l7CS+maTcsV0QB2mB8vLjYvUj?= =?us-ascii?Q?gTLcB/keCjLupW3QRo09t+t+y5t6CmHtMJK1VJlmN72J9ClzbhFkFD/qk9Fc?= =?us-ascii?Q?60xoJ/G2bWFpi2YNMshmo6SaXLm3MOJglAfLu0uNgsfjRA6B53KlpIlABP6l?= =?us-ascii?Q?5jbH/KuXXvHEwaMsF4Cahk0D1oo8RykPqONPSVccjEJsaYjmNUHrkInhW9pA?= =?us-ascii?Q?zsxmMwmh9QYkbrt2q/caTagtXt89DmcT33F7Xhe7WK2n5pUcC4bUGV0Slhle?= =?us-ascii?Q?vonf75sKf0n62EyJWBOlNcBMUlFm0wnWJxlJXH1yEr9O+nuUlavheluClUy1?= =?us-ascii?Q?9N09vBdbAWfpUvIR88qjKM/N7GEOfKRELtHPxy1Yp7crKcvc/E+mo/7+ZC19?= =?us-ascii?Q?wEAHUxkBLFOqOnn6cigTmL1zmkBu/JeOjrp3oHsM/npM17lrnCjb26Ep1gA3?= =?us-ascii?Q?HuTVNWSW00ML3L3ioKFgBjMQOZEAa4u7+wegIwdjzAZStnC9DB/HA9jLJBoo?= =?us-ascii?Q?0sFxD3I8WfKGSquoCZ/dYqhDGmEhbGYPcX3m5OxSDag93/Aev8Ggbk9wJ4wz?= =?us-ascii?Q?gAsSssl/K2ZnBKLKRhF/W8CgR87McaDxqk1cuncCv0W5pRH+YhN+20JVVHvc?= =?us-ascii?Q?pJy72dQIDErtR92qoUEVwKpw/9mhUOqHvyVxhTXYysxIPVKwESScUwH9i3Xn?= =?us-ascii?Q?/ndBA+VkxarpWo5wteN4mSojLb+OcLlXc4U0kND2uz64GgBJm3TDPZmITZbc?= =?us-ascii?Q?L50aGza1Dml2EOi7uCvB5ghD81ToYqawTkz5+kR++El1La4OIlDj1zkMHQ3h?= =?us-ascii?Q?OJrIFI+UMxHl+gz1rX0H3PKkwhUFKmU1IemfuVGu8pSAXSD60pmbQgQm9QTf?= =?us-ascii?Q?YSYBxa4twIOcinwPOoWhecjpP3IwjIfJMTNK1r3Vu/UnD5j7MMwxm5Ko8A+Q?= =?us-ascii?Q?yjyui0ji2Bg5XFhdDKbftRXgqzHjVNhQ32rRu/Od5E8Nq/U9dgs5h88Hfxzs?= =?us-ascii?Q?GlUGKfu3XV5BT26FHSgAALMhm4v9s7RmES1gBZGwm2pJpx2ljBAhKpG5zoS1?= =?us-ascii?Q?jEJWp9F1IEc6jOnyBURO28ZzE/9ESxwMjQ9iknH+4XAa08sSXrhTWhEU5ABO?= =?us-ascii?Q?sXoznjRP+Q=3D=3D?= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 5a36273c-9472-4f7c-00f8-08de73f5acbb X-MS-Exchange-CrossTenant-AuthSource: DS0PR12MB6486.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 22:40:13.7043 (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: 0LfdBTflOvp0GG6P6rzkfNODFKIrSrOrGi1ETEMRzPpYR0yKtm3EpG5ClamAFNshvF3MiCKpiAEt97/A2XrBjg== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR12MB7816 Content-Type: text/plain; charset="utf-8" Move the DRM buddy allocator one level up so that it can be used by GPU drivers (example, nova-core) that have usecases other than DRM (such as VFIO vGPU support). Modify the API, structures and Kconfigs to use "gpu_buddy" terminology. Adapt the drivers and tests to use the new API. The commit cannot be split due to bisectability, however no functional change is intended. Verified by running K-UNIT tests and build tested various configurations. Signed-off-by: Joel Fernandes Reviewed-by: Dave Airlie [airlied: I've split this into two so git can find copies easier. I've also just nuked drm_random library, that stuff needs to be done elsewhere and only the buddy tests seem to be using it]. Signed-off-by: Dave Airlie --- Documentation/gpu/drm-mm.rst | 6 +++--- drivers/gpu/Makefile | 2 +- drivers/gpu/{drm/drm_buddy.c =3D> buddy.c} | 2 +- drivers/gpu/drm/Kconfig | 4 ---- drivers/gpu/drm/Kconfig.debug | 1 - drivers/gpu/drm/Makefile | 3 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h | 2 +- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 2 +- drivers/gpu/drm/i915/i915_scatterlist.c | 2 +- drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 2 +- drivers/gpu/drm/tests/Makefile | 1 - drivers/gpu/drm/tests/drm_exec_test.c | 2 -- drivers/gpu/drm/tests/drm_mm_test.c | 2 -- drivers/gpu/drm/ttm/tests/ttm_mock_manager.h | 2 +- drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h | 2 +- drivers/gpu/tests/Makefile | 4 ++++ .../{drm/tests/drm_buddy_test.c =3D> tests/gpu_buddy_test.c} | 4 ++-- drivers/gpu/{drm/lib/drm_random.c =3D> tests/gpu_random.c} | 2 +- drivers/gpu/{drm/lib/drm_random.h =3D> tests/gpu_random.h} | 0 include/{drm/drm_buddy.h =3D> linux/gpu_buddy.h} | 0 20 files changed, 19 insertions(+), 26 deletions(-) rename drivers/gpu/{drm/drm_buddy.c =3D> buddy.c} (99%) create mode 100644 drivers/gpu/tests/Makefile rename drivers/gpu/{drm/tests/drm_buddy_test.c =3D> tests/gpu_buddy_test.c= } (99%) rename drivers/gpu/{drm/lib/drm_random.c =3D> tests/gpu_random.c} (97%) rename drivers/gpu/{drm/lib/drm_random.h =3D> tests/gpu_random.h} (100%) rename include/{drm/drm_buddy.h =3D> linux/gpu_buddy.h} (100%) diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index f22433470c76..ceee0e663237 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -526,10 +526,10 @@ DRM GPUVM Function References DRM Buddy Allocator =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 -DRM Buddy Function References ------------------------------ +Buddy Allocator Function References (GPU buddy) +----------------------------------------------- =20 -.. kernel-doc:: drivers/gpu/drm/drm_buddy.c +.. kernel-doc:: drivers/gpu/buddy.c :export: =20 DRM Cache Handling and Fast WC memcpy() diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile index 36a54d456630..c5292ee2c852 100644 --- a/drivers/gpu/Makefile +++ b/drivers/gpu/Makefile @@ -2,7 +2,7 @@ # drm/tegra depends on host1x, so if both drivers are built-in care must be # taken to initialize them in the correct order. Link order is the only way # to ensure this currently. -obj-y +=3D host1x/ drm/ vga/ +obj-y +=3D host1x/ drm/ vga/ tests/ obj-$(CONFIG_IMX_IPUV3_CORE) +=3D ipu-v3/ obj-$(CONFIG_TRACE_GPU_MEM) +=3D trace/ obj-$(CONFIG_NOVA_CORE) +=3D nova-core/ diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/buddy.c similarity index 99% rename from drivers/gpu/drm/drm_buddy.c rename to drivers/gpu/buddy.c index fd34d3755f7c..4cc63d961d26 100644 --- a/drivers/gpu/drm/drm_buddy.c +++ b/drivers/gpu/buddy.c @@ -10,7 +10,7 @@ #include #include =20 -#include +#include #include =20 enum drm_buddy_free_tree { diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index d3d52310c9cc..ca2a2801e77f 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -269,10 +269,6 @@ config DRM_SCHED config DRM_PANEL_BACKLIGHT_QUIRKS tristate =20 -config DRM_LIB_RANDOM - bool - default n - config DRM_PRIVACY_SCREEN bool default n diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug index 05dc43c0b8c5..3b7886865335 100644 --- a/drivers/gpu/drm/Kconfig.debug +++ b/drivers/gpu/drm/Kconfig.debug @@ -69,7 +69,6 @@ config DRM_KUNIT_TEST select DRM_EXPORT_FOR_TESTS if m select DRM_GEM_SHMEM_HELPER select DRM_KUNIT_TEST_HELPERS - select DRM_LIB_RANDOM select DRM_SYSFB_HELPER select PRIME_NUMBERS default KUNIT_ALL_TESTS diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index ec2c5ff82382..5c86bc908955 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -78,7 +78,6 @@ drm-$(CONFIG_DRM_CLIENT) +=3D \ drm_client_event.o \ drm_client_modeset.o \ drm_client_sysrq.o -drm-$(CONFIG_DRM_LIB_RANDOM) +=3D lib/drm_random.o drm-$(CONFIG_COMPAT) +=3D drm_ioc32.o drm-$(CONFIG_DRM_PANEL) +=3D drm_panel.o drm-$(CONFIG_OF) +=3D drm_of.o @@ -114,7 +113,7 @@ drm_gpusvm_helper-$(CONFIG_ZONE_DEVICE) +=3D \ =20 obj-$(CONFIG_DRM_GPUSVM) +=3D drm_gpusvm_helper.o =20 -obj-$(CONFIG_DRM_BUDDY) +=3D drm_buddy.o +obj-$(CONFIG_DRM_BUDDY) +=3D ../buddy.o =20 drm_dma_helper-y :=3D drm_gem_dma_helper.o drm_dma_helper-$(CONFIG_DRM_FBDEV_EMULATION) +=3D drm_fbdev_dma.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h b/drivers/gpu/drm= /amd/amdgpu/amdgpu_vram_mgr.h index 5f5fd9a911c2..874779618056 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h @@ -24,7 +24,7 @@ #ifndef __AMDGPU_VRAM_MGR_H__ #define __AMDGPU_VRAM_MGR_H__ =20 -#include +#include =20 struct amdgpu_vram_mgr { struct ttm_resource_manager manager; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915= /gem/i915_gem_ttm.c index f65fe86c02b5..eeda5daa544f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -5,7 +5,7 @@ =20 #include =20 -#include +#include #include #include #include diff --git a/drivers/gpu/drm/i915/i915_scatterlist.c b/drivers/gpu/drm/i915= /i915_scatterlist.c index 4d830740946d..30246f02bcfe 100644 --- a/drivers/gpu/drm/i915/i915_scatterlist.c +++ b/drivers/gpu/drm/i915/i915_scatterlist.c @@ -7,7 +7,7 @@ #include "i915_scatterlist.h" #include "i915_ttm_buddy_manager.h" =20 -#include +#include #include =20 #include diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/dr= m/i915/i915_ttm_buddy_manager.c index d5c6e6605086..6b256d95badd 100644 --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c @@ -5,7 +5,7 @@ =20 #include =20 -#include +#include #include #include #include diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index 87d5d5f9332a..d2e2e3d8349a 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_DRM_KUNIT_TEST) +=3D \ drm_atomic_test.o \ drm_atomic_state_test.o \ drm_bridge_test.o \ - drm_buddy_test.o \ drm_cmdline_parser_test.o \ drm_connector_test.o \ drm_damage_helper_test.o \ diff --git a/drivers/gpu/drm/tests/drm_exec_test.c b/drivers/gpu/drm/tests/= drm_exec_test.c index 3a20c788c51f..2fc47f3b463b 100644 --- a/drivers/gpu/drm/tests/drm_exec_test.c +++ b/drivers/gpu/drm/tests/drm_exec_test.c @@ -16,8 +16,6 @@ #include #include =20 -#include "../lib/drm_random.h" - struct drm_exec_priv { struct device *dev; struct drm_device *drm; diff --git a/drivers/gpu/drm/tests/drm_mm_test.c b/drivers/gpu/drm/tests/dr= m_mm_test.c index aec9eccdeae9..e24a619059d8 100644 --- a/drivers/gpu/drm/tests/drm_mm_test.c +++ b/drivers/gpu/drm/tests/drm_mm_test.c @@ -16,8 +16,6 @@ #include #include =20 -#include "../lib/drm_random.h" - enum { BEST, BOTTOMUP, diff --git a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h b/drivers/gpu/drm= /ttm/tests/ttm_mock_manager.h index e4c95f86a467..96ea8c9aae34 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h +++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h @@ -5,7 +5,7 @@ #ifndef TTM_MOCK_MANAGER_H #define TTM_MOCK_MANAGER_H =20 -#include +#include =20 struct ttm_mock_manager { struct ttm_resource_manager man; diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h b/drivers/gpu/drm/x= e/xe_ttm_vram_mgr_types.h index a71e14818ec2..babeec5511d9 100644 --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h @@ -6,7 +6,7 @@ #ifndef _XE_TTM_VRAM_MGR_TYPES_H_ #define _XE_TTM_VRAM_MGR_TYPES_H_ =20 -#include +#include #include =20 /** diff --git a/drivers/gpu/tests/Makefile b/drivers/gpu/tests/Makefile new file mode 100644 index 000000000000..8e7654e87d82 --- /dev/null +++ b/drivers/gpu/tests/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +gpu_buddy_tests-y =3D gpu_buddy_test.o gpu_random.o +obj-$(CONFIG_DRM_KUNIT_TEST) +=3D gpu_buddy_tests.o diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/tests/gpu= _buddy_test.c similarity index 99% rename from drivers/gpu/drm/tests/drm_buddy_test.c rename to drivers/gpu/tests/gpu_buddy_test.c index e6f8459c6c54..b905932da990 100644 --- a/drivers/gpu/drm/tests/drm_buddy_test.c +++ b/drivers/gpu/tests/gpu_buddy_test.c @@ -10,9 +10,9 @@ #include #include =20 -#include +#include =20 -#include "../lib/drm_random.h" +#include "gpu_random.h" =20 static unsigned int random_seed; =20 diff --git a/drivers/gpu/drm/lib/drm_random.c b/drivers/gpu/tests/gpu_rando= m.c similarity index 97% rename from drivers/gpu/drm/lib/drm_random.c rename to drivers/gpu/tests/gpu_random.c index 0e9dba1ef4af..ddd1f594b5d5 100644 --- a/drivers/gpu/drm/lib/drm_random.c +++ b/drivers/gpu/tests/gpu_random.c @@ -6,7 +6,7 @@ #include #include =20 -#include "drm_random.h" +#include "gpu_random.h" =20 u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state) { diff --git a/drivers/gpu/drm/lib/drm_random.h b/drivers/gpu/tests/gpu_rando= m.h similarity index 100% rename from drivers/gpu/drm/lib/drm_random.h rename to drivers/gpu/tests/gpu_random.h diff --git a/include/drm/drm_buddy.h b/include/linux/gpu_buddy.h similarity index 100% rename from include/drm/drm_buddy.h rename to include/linux/gpu_buddy.h --=20 2.34.1 From nobody Fri Apr 17 00:17:58 2026 Received: from PH8PR06CU001.outbound.protection.outlook.com (mail-westus3azon11012032.outbound.protection.outlook.com [40.107.209.32]) (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 EB8DA34B404; Tue, 24 Feb 2026 22:40:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.209.32 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771972852; cv=fail; b=AWoF0GVKSA6RwN5G8Iza0zoB6eLNyo0u+g/EA5SEPRlJC6RQZ4RxPgL4h12ANerohQaNG3Dhjv4KDfzR+JiwgFKvSjkMHpgjK9D3dMJR0HWwm0Id/pEKEa7Uns6JMVO2tuRs5KHJT7j6HZwVtB364nY/u58pVDqQwrTYtTp+oM4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771972852; c=relaxed/simple; bh=aJAs+vEq3TLVYCqNsEXTc7b54v619/Jl6EnNsqcw8vQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=naGSd051qsDpB0YRq2KrcC4Ctg8LnoPfb+jUW0GDhSSoIfefo7PChHmTbCrhRiyfaiYmJsLdMxBYCQgYHUETieOz5gKVLwWLGU41sip6VamkVBxiXhOUov4Pq+MK+KVwIjWetrsB7YLSE+FVyLvbedn10NBKL3iKUhqs+LZymgY= 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=DJzyKRdP; arc=fail smtp.client-ip=40.107.209.32 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="DJzyKRdP" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=flJL0raWhkcUEV6gHghxvsyFAMEo8xJNDIMVUQvbt3n1/MSuyLtBDLtkcowfb2HuLEbHuTtLE028owoK9RTmywgrzGNR8J9uTHrTMwST+eDaXqvw27huIY0afwWPUjzTsJ2agvRnbgZqtTwHaoXQihnU5W8y9maVdswu22UNc1dpYJv6h9cgYXN+MfVqmSE2tDsVvezN8Cs+GlQzYvj3BF8W4xYE+e8Cgfk1P1i+hXIYlrPhQsEqrTXxzZzJwGeA3iG/BWz9k4NGC2XIGgEYeQPcC7KFTMmj2U97HfKTRF+Ok+OhOIbuq+qBSbikCdDYPp42bCEkkjsMGJ+P8BbVBQ== 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=On68GUi7IYDricIQ9WRvB5IuoNnm6w4u9DMdbJReF1E=; b=qrs42z08HP3mrBBFMxLAogNqB7LC2zs3IeXvtutnXAopNngva3tDlO/Y/O/B2LPRn/9EoYLdn5+2BOIfTOb/FmOgrCz+U49QBGPhcvAbGBXY39kgkVJ4ijiUQbmU+TqIrUVR3nsnfqvEmUIBTzq4GwySvJI/ioz0gRDdcpIszQbt2PYCCDUDRGbVQx1xiwQNW1YkhRNGGBACOgVX8+BoNhFBpTrGnPeEfIG2MbQikjdjTRBPaX4nNGEaXpYrUrJOtSLKrIye3I2/pSfOWYKh6aifbOmuoD9AK+luXjxTk8Hv24LdVLEGkhbA9vVvsw5+k2f5avWbJXcfljHXIChpdw== 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=On68GUi7IYDricIQ9WRvB5IuoNnm6w4u9DMdbJReF1E=; b=DJzyKRdPnzh0KWsr18Gv83A3SwtNmU+BQqJt6IQRMqUt94f2Q0CcIuZiPrF7DXs4hEmP+8D6qL5gizOH5zCxSI2KJMLTKHqmpI9RuwJPzvEXhO1w6F9bwOCFXvIWQsa4n51IJTI/slUCjunZ38GXNfsfU3tpxI73T9y3MPNYOUV1H3zZxmKXL+oI5R2vdjHoTHs2JnhQsiFaE9oH1UHnqQKhrRIlessmT+yLzVjkYQwFcjW/ZbCqPnoLZmRkSAwY9VVZVDVFzVksAYXUKzOm1ZKuBOqv4FWvlxmCTGteL+gtZOozRj/pRxt6UHeNlYUNiTpxfRptpAZDLg3gvsMgYQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from DS0PR12MB6486.namprd12.prod.outlook.com (2603:10b6:8:c5::21) by PH0PR12MB7816.namprd12.prod.outlook.com (2603:10b6:510:28c::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 22:40:15 +0000 Received: from DS0PR12MB6486.namprd12.prod.outlook.com ([fe80::88a9:f314:c95f:8b33]) by DS0PR12MB6486.namprd12.prod.outlook.com ([fe80::88a9:f314:c95f:8b33%4]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 22:40:15 +0000 From: Joel Fernandes To: linux-kernel@vger.kernel.org Cc: Miguel Ojeda , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Dave Airlie , Daniel Almeida , Koen Koning , dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, rust-for-linux@vger.kernel.org, Nikola Djukic , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jonathan Corbet , Alex Deucher , =?UTF-8?q?Christian=20K=C3=B6nig?= , Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , Huang Rui , Matthew Auld , Matthew Brost , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Helge Deller , Alex Gaynor , Boqun Feng , John Hubbard , Alistair Popple , Timur Tabi , Edwin Peer , Alexandre Courbot , Andrea Righi , Andy Ritger , Zhi Wang , Balbir Singh , Philipp Stanner , Elle Rhumsaa , alexeyi@nvidia.com, Eliot Courtney , joel@joelfernandes.org, linux-doc@vger.kernel.org, amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org, linux-fbdev@vger.kernel.org, Joel Fernandes Subject: [reference PATCH v11 2/4] gpu: Move DRM buddy allocator one level up (part two) Date: Tue, 24 Feb 2026 17:40:03 -0500 Message-Id: <20260224224005.3232841-3-joelagnelf@nvidia.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260224224005.3232841-1-joelagnelf@nvidia.com> References: <20260224224005.3232841-1-joelagnelf@nvidia.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: MN0PR05CA0025.namprd05.prod.outlook.com (2603:10b6:208:52c::13) To DS0PR12MB6486.namprd12.prod.outlook.com (2603:10b6:8:c5::21) 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: DS0PR12MB6486:EE_|PH0PR12MB7816:EE_ X-MS-Office365-Filtering-Correlation-Id: 8943b040-dd16-4249-b50f-08de73f5ada2 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|7416014|376014|366016|13003099007; X-Microsoft-Antispam-Message-Info: =?utf-8?B?NVo0SUJVVkpiSFBSTDhWSWM5dTZNMlcyQWk5SS9UdWJOb0ZCTHA0djNnMzI2?= =?utf-8?B?WlQrSGRSVGJ2Z1R2T01mN0JKemhKeDJ6MWpMdGVGSWFvMWxXc2lpSThPMEVt?= =?utf-8?B?M2MyRDZhcTlyMnFnNCs5ZFVjZG9la0NYbUJ4eGFaZ3pLeVJBTzZ5MkxobDF6?= =?utf-8?B?VkxFbzZZTDMwcEUzM040Y1BhRXppUFdQSzJ6RUpjeHdwakt0alJlRTFWWUVV?= =?utf-8?B?RU1RNmFaNHdhcUVqTWNNZ1VQNmVsejBRcTZsdHc3U0d1d2E4bXhZRitLdkph?= =?utf-8?B?c1A5VDNqRHpTdTJaS3VSb2xUNEQvTzFhT2VxR29NeHJaQVFkcm1veUF0Q0k3?= =?utf-8?B?QkxybjFxYm9HTWdnTDNZczA1MHRkdFRna3M3L1ZET25VRnFvSHJkbEhtSWs3?= =?utf-8?B?bVJhQ1RBYU1rNXhVUGkwdTFKVGpDUlRLcEduV080dUVUcHh1VEsyNFlBQnc2?= =?utf-8?B?VmllQnVsQ1NQdXd2SDlEOE5Gd2NvdFNCbGRFdGVvWTY1OUpxNWVHM09rQmk2?= =?utf-8?B?cGxxS05mWStZVWNFTVcyUG9JNXJsSXcwRkhGenIwTnBhd3pjS2VkUW44VFU4?= =?utf-8?B?MXVVS2N4TjRsS1RsT2pqVDdUbElPcWZ2T0FGaHEyazE4dVBIUjNyNHl3UUFV?= =?utf-8?B?aVlBZEcvS1Q2OU5Qb1NFbFRjei8xVGM4c0N0eDVPNm01S29LZWF4UFNVRkhi?= =?utf-8?B?QTlhSURFOXp2OFlYdzd2cVNCSjVwdTltWUJGK0cxcFExVVQ1ZGIvWmtxVlpx?= =?utf-8?B?WWRwWDNkbm85YlQ5UEIyeWhmZWFVUmwxeVpycm15SnNQQUdtN2dpS3lvSHFD?= =?utf-8?B?c2I0ZUR6L203M2poTHlvaFZURzMvUGU4TWtsNzhsbUk5UHpicFVzd21ZUnZX?= =?utf-8?B?TFRpaHZtY2xGbzJxVVptN1lPcUhGSjlocFk2Y3BHZUlobG15M2F1ekkrT08v?= =?utf-8?B?VU9tMGlSUTZZV2RCdWdMUGNRTXdxMm01WnNUNytGRkdFQnJLZlFHbUZRMHdO?= =?utf-8?B?NGplM0Fyd0lFRGQ0Y0dGU3ZNRGUxNitIeWhDWW9UT0F6THhMYWY2RlI0Zzc2?= =?utf-8?B?czA4S2xFdmtRNS9YOFE0RTE2MmJYdjlSMUhMdGF6bWNDRGtUSFpMT1Y5Nzdw?= =?utf-8?B?OVg5bTVGS2xUTjlmaGxIUE5ZbXd4NWxqRW1NbTRJeFhjb0NNMzJXS1luZzJ2?= =?utf-8?B?M1JCL2wyQjBqS1ErRkxRQzhNME1kUEJGRnlLR3V3WVFnKzZ6ZitsZmxIelI0?= =?utf-8?B?V1g1WUFYYlhEckRZdzNkR2VSRXcvM1BUU2hab2xNMVM1WFhKc0hxVGt4NE41?= =?utf-8?B?MmxRcXN6YmVxWXdGVzE4bkFZS2hOTmZjc2lIcktwMGkvdTAyb3l5UDZoQ2Rh?= =?utf-8?B?aHo2bHBySTFkSzRKMzVRR2VwVTd6S1Iyc0VzZStZejk4cUx2Vk5ncUxSM3Ar?= =?utf-8?B?Ui9GdmxoRFdQZnFzSmRnQTNnRjNVbDM1Zmp3WVR5SWdFSCthNEw4aXpHTUJV?= =?utf-8?B?OEFIcmkrckgxMU1oeTliK2Fxd1B0Kzk5Y3VaRVBka0tBVjBHbkJkR2dvT2ZP?= =?utf-8?B?NHZONThYSDF3Mk5GTVdHa2JYU1NzQ0pFMXdjQUh6MjJ1NTM2SXQxaDl3bFE2?= =?utf-8?B?bjJPU2F6T0hGcVZ0WUFJOFovRm93ZkdvNi9ZMzZvNVlCYTZPcDFjV2RpTllI?= =?utf-8?B?ZTJZVVlwNTRzTUg0TkVnOFg3dG8veWZRY2piSTEvampST1o3RU9ETHl6ODdr?= =?utf-8?B?cGZpcUhoQ0ptRmp3OWVvdWRYc2FzdGg3bU9rbFMvNUFMZGRqK3Y3ZU5nVm1q?= =?utf-8?B?QWlsWlJGa0g4UGo4QkdrYldzSVdob0J4WUp5L1lUY08xZ1U1NGQ0UGRpWDBl?= =?utf-8?B?dTZXbFlWT3FmUXBqdUVrNzNZNEZWd2JmY3RPemtnNERyN1IzWjhSSlkxMnRa?= =?utf-8?B?K2RXQjhyM0lzc25hWlJSdGRCODgzTU5xcm5GOWpLaXhmei9xd3pWQWRJUUVK?= =?utf-8?B?L25DNitrLzFXTU9ib05hci9EMzI1MStKd0RPK0xvYWIrVzJadWdTRUQ0d2JR?= =?utf-8?B?MzJITlJSbmtheUJ5K2ZPOUNvQ2NHNDIvU2xzVTJMcXFxSXluSmZuY1pLa0lt?= =?utf-8?Q?82Gg=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DS0PR12MB6486.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(7416014)(376014)(366016)(13003099007);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?utf-8?B?ZFJFbTlmL0hGYkNLV3dRUGhHUVVjclZubWRwck9LMUUwSmRVanhSYUdDLzV1?= =?utf-8?B?L0VtVHVqMytQV201Zll4WWpiRzFzN1hqS1NXVWJsOUUraXhIZ3k1S0NaQ0Fs?= =?utf-8?B?VXlnQ2g2QVovVUJ5Z3U3Q3pWODMzRUxJVXdvcWZOZzJsV0ZUMzE5ejdOSFFK?= =?utf-8?B?S1QvTXF5US9PRFowbnpZVlhyNGtzRW9aWHBDdzkxdzVPQnExanBxTXc3T0Qw?= =?utf-8?B?bThqQlhLRHIwN2gvQzhVeGFYSzhaOE0wZW53Zld6NHlUb3lQTkd3clRqOU1r?= =?utf-8?B?VGkxdGkyQnVtNDZIU21UclNZZjdNM2QzbVl5N0NERVB6VHNiUVVMZHZzM2wr?= =?utf-8?B?b3hDMEF1VDRFQjhLZGdzd2thcEdPaHB4d1UwMWpOd2QrUDJTOGxHSTVreG1q?= =?utf-8?B?QWp6ODFNVWdyYlZLejkreFhkVDBwcTZzWVdGVmo0Y0ZURzcreFE2MFhEVzJB?= =?utf-8?B?YVFyNmx4M1hmbUJEQkpsS0JnU1Q3dVI1Y3ZnRUpTMXgwZGtqM255dG9ZRkZn?= =?utf-8?B?bkJxdlRqM05sVStwYmlOMFlNNmJibTZXdTBCanhGYWEzaktEc2d5R2RudUhs?= =?utf-8?B?RWExZ3VaV1RSQ1piZGF2M3UzQWc2KzFXT2NBOHB6VGxyZFRsOHpvUDRlSUd0?= =?utf-8?B?dm1Db3JlSjVlYWtLZ1ovK0lBa0xMdUxIZjBjYkprK2xsUEwyaVpnRlhQV2Zq?= =?utf-8?B?Y1ZOT0hpM0dDd2lQcG0xbGUyTE9HeWgzZVJnd3hCMS9OTkpOVUpwNzJPTkhT?= =?utf-8?B?cmVIVUkzOCt6UnhHeVhRZHBOcHNvR2VxTmhiUkV4clNrdWhtNTVnN05YUW5o?= =?utf-8?B?RHNhMkNMZENIcXV2VFJrLzdOOThRbm9LdFBMcVZSZ21oekltdmVKbFQrNVZ2?= =?utf-8?B?a2RyNjdvanNhTnNaWXRnSXRDVitoVXRhTkc1cmRvTmQzSUZYbkJJdGxGQi94?= =?utf-8?B?V0lJZmNVOWNqUVdmK3JTaVBxcHBTakJRalcvZnJqY1dHcWR1NlA3c2VqeFl4?= =?utf-8?B?T2tYaWtWTXQrZEJCUjFHUS8zMHpFWkdOVUlqM1JwL1FEUnVaUlI2VTdQVVND?= =?utf-8?B?Y3pIWHYrOXBySmU3UFMwZ3U0L053TVZYK296L014SEVxbHdvNXVrMEhyd0pH?= =?utf-8?B?c1RMalBhbDRMcXg3ZDZQWVNieHgzckZGTC8vUkM4cytDUklSaW9CeVh4OW0w?= =?utf-8?B?RnprUW5zcTUzb29HTS9kRzRVcWRGK2I5eDZOS1BrWGZmTzBWODNoNGJTTmdD?= =?utf-8?B?V0YvbFhFNmR4QU84VithejUva1NJL2EwZTBwOGxoMGJQYjhPN0lRZGlidlNv?= =?utf-8?B?cEdHeDA1R20yNFV3RFR3enhXb0Zxcy9jVXRFdFQxNWM2c3EyL2lVenV2VkpO?= =?utf-8?B?WmsxQllOYjhWeWVJY21xa3dPZkRaalNXdjBLWUdlRW1WT1JUWTFLclNIVkh2?= =?utf-8?B?THR4MEprd1FkZmFCZlFSeWI2MVhCdzRlc2JLYy9jMzFUbDFQOFp1TEJkZDdI?= =?utf-8?B?TW9VQ2RTM0kvczB5UjhaMzBoZmc4U0JPNmJJVDJDeFY5MXBFZTVuTENSUFcv?= =?utf-8?B?dmo2SU1GOHg3bVVHS3JUVVZxNEJ5bDVBaWhYS2JFck9MQ0ExQWNtbExQNENS?= =?utf-8?B?dklpU01nc28vT0FEMmlmNGkyNTIvY3lIdURLZ24rKzAwejEzZjBlcEJRNVkz?= =?utf-8?B?RFRKU3BrRjZxTCtIdSthS0VwWWs0WjJ2aHFaU2pBZDhxMzJTREF5bGlabnZF?= =?utf-8?B?bVR1RFZxZ09VOU83em56SEdVa2dyUXMxLytVVGJUbmYxS0pVMFNaQVdPSVdm?= =?utf-8?B?SGxKTXdHb0REblRKeE1Lb3lidUJ0RHdhUW0zZWliQVdEYUp3eGtDNE1PTWJC?= =?utf-8?B?SndOY0xhMkRYLzRXNWsxbzdUZ1o0cStYbjZ6ZW9UWmp5RFdqVU1BOGIrQVQ5?= =?utf-8?B?cWt0cFBNNG9STGhZSXpMV0V3OVhtd0dIQnNWNFpBajg5OVl1cHRxUEpHTHRK?= =?utf-8?B?Q3JSdFRwdmdkTFZNTmhEZDg4Yk51STU3QUJSODQvS1dDY29aL3lIcDlwWGFV?= =?utf-8?B?ZmJhSGJOd2RCa1FtVDVON0NrZExBWXF1cXhPZTZxVDc2eUVmeGF0cy8yOHlZ?= =?utf-8?B?QUNOT2FuQnYyV21SWHYvR0JyeFdFUUkvaEh3aW1SNFNGenhVV1UzS2lYWjh5?= =?utf-8?B?VHZpaVgzeTh6Ky9LMkZEZjhUOElyblk2UldnQ01MOUFEYytBc3FQaXNKNnpS?= =?utf-8?B?N3VRUEJheC96aWFVZmpUcmJrRURHNUswZ1lWSW1HTzJrZWYxZnI4ZU02ODdS?= =?utf-8?B?N3JnNko5N2Z1YXdXbE1PY2l0NHVLbjMwSlB1ZWxMMklrT0tycWMyUT09?= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: 8943b040-dd16-4249-b50f-08de73f5ada2 X-MS-Exchange-CrossTenant-AuthSource: DS0PR12MB6486.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 22:40:15.3292 (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: A9Gj8ZgvCZ6E8HgFuB3Quf/p6n/NolSzsfHut/yozx6Bj5/dTLUZI/dmAfyUoC2KEn/NhsC7HYbeQ3OhK5EmPQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR12MB7816 Move the DRM buddy allocator one level up so that it can be used by GPU drivers (example, nova-core) that have usecases other than DRM (such as VFIO vGPU support). Modify the API, structures and Kconfigs to use "gpu_buddy" terminology. Adapt the drivers and tests to use the new API. The commit cannot be split due to bisectability, however no functional change is intended. Verified by running K-UNIT tests and build tested various configurations. Signed-off-by: Joel Fernandes Reviewed-by: Dave Airlie [airlied: I've split this into two so git can find copies easier. I've also just nuked drm_random library, that stuff needs to be done elsewhere and only the buddy tests seem to be using it]. Signed-off-by: Dave Airlie --- Documentation/gpu/drm-mm.rst | 6 + MAINTAINERS | 8 +- drivers/gpu/Kconfig | 13 + drivers/gpu/Makefile | 1 + drivers/gpu/buddy.c | 556 +++++++++--------- drivers/gpu/drm/Kconfig | 1 + drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_res_cursor.h | 12 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 79 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h | 18 +- drivers/gpu/drm/drm_buddy.c | 77 +++ drivers/gpu/drm/i915/i915_scatterlist.c | 8 +- drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 55 +- drivers/gpu/drm/i915/i915_ttm_buddy_manager.h | 4 +- .../drm/i915/selftests/intel_memory_region.c | 20 +- .../gpu/drm/ttm/tests/ttm_bo_validate_test.c | 4 +- drivers/gpu/drm/ttm/tests/ttm_mock_manager.c | 18 +- drivers/gpu/drm/ttm/tests/ttm_mock_manager.h | 2 +- drivers/gpu/drm/xe/xe_res_cursor.h | 34 +- drivers/gpu/drm/xe/xe_svm.c | 12 +- drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 71 +-- drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h | 2 +- drivers/gpu/tests/Makefile | 2 +- drivers/gpu/tests/gpu_buddy_test.c | 412 ++++++------- drivers/gpu/tests/gpu_random.c | 16 +- drivers/gpu/tests/gpu_random.h | 18 +- drivers/video/Kconfig | 1 + include/drm/drm_buddy.h | 18 + include/linux/gpu_buddy.h | 120 ++-- 30 files changed, 853 insertions(+), 739 deletions(-) create mode 100644 drivers/gpu/Kconfig create mode 100644 drivers/gpu/drm/drm_buddy.c create mode 100644 include/drm/drm_buddy.h diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index ceee0e663237..32fb506db05b 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -532,6 +532,12 @@ Buddy Allocator Function References (GPU buddy) .. kernel-doc:: drivers/gpu/buddy.c :export: =20 +DRM Buddy Specific Logging Function References +---------------------------------------------- + +.. kernel-doc:: drivers/gpu/drm/drm_buddy.c + :export: + DRM Cache Handling and Fast WC memcpy() =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/MAINTAINERS b/MAINTAINERS index 0dc318c94c99..f1e5a8011d2f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8905,15 +8905,17 @@ T: git https://gitlab.freedesktop.org/drm/misc/kern= el.git F: drivers/gpu/drm/ttm/ F: include/drm/ttm/ =20 -DRM BUDDY ALLOCATOR +GPU BUDDY ALLOCATOR M: Matthew Auld M: Arun Pravin R: Christian Koenig L: dri-devel@lists.freedesktop.org S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git -F: drivers/gpu/drm/drm_buddy.c -F: drivers/gpu/drm/tests/drm_buddy_test.c +F: drivers/gpu/drm_buddy.c +F: drivers/gpu/buddy.c +F: drivers/gpu/tests/gpu_buddy_test.c +F: include/linux/gpu_buddy.h F: include/drm/drm_buddy.h =20 DRM AUTOMATED TESTING diff --git a/drivers/gpu/Kconfig b/drivers/gpu/Kconfig new file mode 100644 index 000000000000..ebb2ad4b7ea0 --- /dev/null +++ b/drivers/gpu/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 + +config GPU_BUDDY + bool + help + A page based buddy allocator for GPU memory. + +config GPU_BUDDY_KUNIT_TEST + tristate "KUnit tests for GPU buddy allocator" if !KUNIT_ALL_TESTS + depends on GPU_BUDDY && KUNIT + default KUNIT_ALL_TESTS + help + KUnit tests for the GPU buddy allocator. diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile index c5292ee2c852..5cd54d06e262 100644 --- a/drivers/gpu/Makefile +++ b/drivers/gpu/Makefile @@ -6,3 +6,4 @@ obj-y +=3D host1x/ drm/ vga/ tests/ obj-$(CONFIG_IMX_IPUV3_CORE) +=3D ipu-v3/ obj-$(CONFIG_TRACE_GPU_MEM) +=3D trace/ obj-$(CONFIG_NOVA_CORE) +=3D nova-core/ +obj-$(CONFIG_GPU_BUDDY) +=3D buddy.o diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c index 4cc63d961d26..603c59a2013a 100644 --- a/drivers/gpu/buddy.c +++ b/drivers/gpu/buddy.c @@ -11,27 +11,17 @@ #include =20 #include -#include - -enum drm_buddy_free_tree { - DRM_BUDDY_CLEAR_TREE =3D 0, - DRM_BUDDY_DIRTY_TREE, - DRM_BUDDY_MAX_FREE_TREES, -}; =20 static struct kmem_cache *slab_blocks; =20 -#define for_each_free_tree(tree) \ - for ((tree) =3D 0; (tree) < DRM_BUDDY_MAX_FREE_TREES; (tree)++) - -static struct drm_buddy_block *drm_block_alloc(struct drm_buddy *mm, - struct drm_buddy_block *parent, +static struct gpu_buddy_block *gpu_block_alloc(struct gpu_buddy *mm, + struct gpu_buddy_block *parent, unsigned int order, u64 offset) { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; =20 - BUG_ON(order > DRM_BUDDY_MAX_ORDER); + BUG_ON(order > GPU_BUDDY_MAX_ORDER); =20 block =3D kmem_cache_zalloc(slab_blocks, GFP_KERNEL); if (!block) @@ -43,30 +33,30 @@ static struct drm_buddy_block *drm_block_alloc(struct d= rm_buddy *mm, =20 RB_CLEAR_NODE(&block->rb); =20 - BUG_ON(block->header & DRM_BUDDY_HEADER_UNUSED); + BUG_ON(block->header & GPU_BUDDY_HEADER_UNUSED); return block; } =20 -static void drm_block_free(struct drm_buddy *mm, - struct drm_buddy_block *block) +static void gpu_block_free(struct gpu_buddy *mm, + struct gpu_buddy_block *block) { kmem_cache_free(slab_blocks, block); } =20 -static enum drm_buddy_free_tree -get_block_tree(struct drm_buddy_block *block) +static enum gpu_buddy_free_tree +get_block_tree(struct gpu_buddy_block *block) { - return drm_buddy_block_is_clear(block) ? - DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE; + return gpu_buddy_block_is_clear(block) ? + GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE; } =20 -static struct drm_buddy_block * +static struct gpu_buddy_block * rbtree_get_free_block(const struct rb_node *node) { - return node ? rb_entry(node, struct drm_buddy_block, rb) : NULL; + return node ? rb_entry(node, struct gpu_buddy_block, rb) : NULL; } =20 -static struct drm_buddy_block * +static struct gpu_buddy_block * rbtree_last_free_block(struct rb_root *root) { return rbtree_get_free_block(rb_last(root)); @@ -77,33 +67,33 @@ static bool rbtree_is_empty(struct rb_root *root) return RB_EMPTY_ROOT(root); } =20 -static bool drm_buddy_block_offset_less(const struct drm_buddy_block *bloc= k, - const struct drm_buddy_block *node) +static bool gpu_buddy_block_offset_less(const struct gpu_buddy_block *bloc= k, + const struct gpu_buddy_block *node) { - return drm_buddy_block_offset(block) < drm_buddy_block_offset(node); + return gpu_buddy_block_offset(block) < gpu_buddy_block_offset(node); } =20 static bool rbtree_block_offset_less(struct rb_node *block, const struct rb_node *node) { - return drm_buddy_block_offset_less(rbtree_get_free_block(block), + return gpu_buddy_block_offset_less(rbtree_get_free_block(block), rbtree_get_free_block(node)); } =20 -static void rbtree_insert(struct drm_buddy *mm, - struct drm_buddy_block *block, - enum drm_buddy_free_tree tree) +static void rbtree_insert(struct gpu_buddy *mm, + struct gpu_buddy_block *block, + enum gpu_buddy_free_tree tree) { rb_add(&block->rb, - &mm->free_trees[tree][drm_buddy_block_order(block)], + &mm->free_trees[tree][gpu_buddy_block_order(block)], rbtree_block_offset_less); } =20 -static void rbtree_remove(struct drm_buddy *mm, - struct drm_buddy_block *block) +static void rbtree_remove(struct gpu_buddy *mm, + struct gpu_buddy_block *block) { - unsigned int order =3D drm_buddy_block_order(block); - enum drm_buddy_free_tree tree; + unsigned int order =3D gpu_buddy_block_order(block); + enum gpu_buddy_free_tree tree; struct rb_root *root; =20 tree =3D get_block_tree(block); @@ -113,42 +103,42 @@ static void rbtree_remove(struct drm_buddy *mm, RB_CLEAR_NODE(&block->rb); } =20 -static void clear_reset(struct drm_buddy_block *block) +static void clear_reset(struct gpu_buddy_block *block) { - block->header &=3D ~DRM_BUDDY_HEADER_CLEAR; + block->header &=3D ~GPU_BUDDY_HEADER_CLEAR; } =20 -static void mark_cleared(struct drm_buddy_block *block) +static void mark_cleared(struct gpu_buddy_block *block) { - block->header |=3D DRM_BUDDY_HEADER_CLEAR; + block->header |=3D GPU_BUDDY_HEADER_CLEAR; } =20 -static void mark_allocated(struct drm_buddy *mm, - struct drm_buddy_block *block) +static void mark_allocated(struct gpu_buddy *mm, + struct gpu_buddy_block *block) { - block->header &=3D ~DRM_BUDDY_HEADER_STATE; - block->header |=3D DRM_BUDDY_ALLOCATED; + block->header &=3D ~GPU_BUDDY_HEADER_STATE; + block->header |=3D GPU_BUDDY_ALLOCATED; =20 rbtree_remove(mm, block); } =20 -static void mark_free(struct drm_buddy *mm, - struct drm_buddy_block *block) +static void mark_free(struct gpu_buddy *mm, + struct gpu_buddy_block *block) { - enum drm_buddy_free_tree tree; + enum gpu_buddy_free_tree tree; =20 - block->header &=3D ~DRM_BUDDY_HEADER_STATE; - block->header |=3D DRM_BUDDY_FREE; + block->header &=3D ~GPU_BUDDY_HEADER_STATE; + block->header |=3D GPU_BUDDY_FREE; =20 tree =3D get_block_tree(block); rbtree_insert(mm, block, tree); } =20 -static void mark_split(struct drm_buddy *mm, - struct drm_buddy_block *block) +static void mark_split(struct gpu_buddy *mm, + struct gpu_buddy_block *block) { - block->header &=3D ~DRM_BUDDY_HEADER_STATE; - block->header |=3D DRM_BUDDY_SPLIT; + block->header &=3D ~GPU_BUDDY_HEADER_STATE; + block->header |=3D GPU_BUDDY_SPLIT; =20 rbtree_remove(mm, block); } @@ -163,10 +153,10 @@ static inline bool contains(u64 s1, u64 e1, u64 s2, u= 64 e2) return s1 <=3D s2 && e1 >=3D e2; } =20 -static struct drm_buddy_block * -__get_buddy(struct drm_buddy_block *block) +static struct gpu_buddy_block * +__get_buddy(struct gpu_buddy_block *block) { - struct drm_buddy_block *parent; + struct gpu_buddy_block *parent; =20 parent =3D block->parent; if (!parent) @@ -178,19 +168,19 @@ __get_buddy(struct drm_buddy_block *block) return parent->left; } =20 -static unsigned int __drm_buddy_free(struct drm_buddy *mm, - struct drm_buddy_block *block, +static unsigned int __gpu_buddy_free(struct gpu_buddy *mm, + struct gpu_buddy_block *block, bool force_merge) { - struct drm_buddy_block *parent; + struct gpu_buddy_block *parent; unsigned int order; =20 while ((parent =3D block->parent)) { - struct drm_buddy_block *buddy; + struct gpu_buddy_block *buddy; =20 buddy =3D __get_buddy(block); =20 - if (!drm_buddy_block_is_free(buddy)) + if (!gpu_buddy_block_is_free(buddy)) break; =20 if (!force_merge) { @@ -198,31 +188,31 @@ static unsigned int __drm_buddy_free(struct drm_buddy= *mm, * Check the block and its buddy clear state and exit * the loop if they both have the dissimilar state. */ - if (drm_buddy_block_is_clear(block) !=3D - drm_buddy_block_is_clear(buddy)) + if (gpu_buddy_block_is_clear(block) !=3D + gpu_buddy_block_is_clear(buddy)) break; =20 - if (drm_buddy_block_is_clear(block)) + if (gpu_buddy_block_is_clear(block)) mark_cleared(parent); } =20 rbtree_remove(mm, buddy); - if (force_merge && drm_buddy_block_is_clear(buddy)) - mm->clear_avail -=3D drm_buddy_block_size(mm, buddy); + if (force_merge && gpu_buddy_block_is_clear(buddy)) + mm->clear_avail -=3D gpu_buddy_block_size(mm, buddy); =20 - drm_block_free(mm, block); - drm_block_free(mm, buddy); + gpu_block_free(mm, block); + gpu_block_free(mm, buddy); =20 block =3D parent; } =20 - order =3D drm_buddy_block_order(block); + order =3D gpu_buddy_block_order(block); mark_free(mm, block); =20 return order; } =20 -static int __force_merge(struct drm_buddy *mm, +static int __force_merge(struct gpu_buddy *mm, u64 start, u64 end, unsigned int min_order) @@ -241,7 +231,7 @@ static int __force_merge(struct drm_buddy *mm, struct rb_node *iter =3D rb_last(&mm->free_trees[tree][i]); =20 while (iter) { - struct drm_buddy_block *block, *buddy; + struct gpu_buddy_block *block, *buddy; u64 block_start, block_end; =20 block =3D rbtree_get_free_block(iter); @@ -250,18 +240,18 @@ static int __force_merge(struct drm_buddy *mm, if (!block || !block->parent) continue; =20 - block_start =3D drm_buddy_block_offset(block); - block_end =3D block_start + drm_buddy_block_size(mm, block) - 1; + block_start =3D gpu_buddy_block_offset(block); + block_end =3D block_start + gpu_buddy_block_size(mm, block) - 1; =20 if (!contains(start, end, block_start, block_end)) continue; =20 buddy =3D __get_buddy(block); - if (!drm_buddy_block_is_free(buddy)) + if (!gpu_buddy_block_is_free(buddy)) continue; =20 - WARN_ON(drm_buddy_block_is_clear(block) =3D=3D - drm_buddy_block_is_clear(buddy)); + WARN_ON(gpu_buddy_block_is_clear(block) =3D=3D + gpu_buddy_block_is_clear(buddy)); =20 /* * Advance to the next node when the current node is the buddy, @@ -271,10 +261,10 @@ static int __force_merge(struct drm_buddy *mm, iter =3D rb_prev(iter); =20 rbtree_remove(mm, block); - if (drm_buddy_block_is_clear(block)) - mm->clear_avail -=3D drm_buddy_block_size(mm, block); + if (gpu_buddy_block_is_clear(block)) + mm->clear_avail -=3D gpu_buddy_block_size(mm, block); =20 - order =3D __drm_buddy_free(mm, block, true); + order =3D __gpu_buddy_free(mm, block, true); if (order >=3D min_order) return 0; } @@ -285,9 +275,9 @@ static int __force_merge(struct drm_buddy *mm, } =20 /** - * drm_buddy_init - init memory manager + * gpu_buddy_init - init memory manager * - * @mm: DRM buddy manager to initialize + * @mm: GPU buddy manager to initialize * @size: size in bytes to manage * @chunk_size: minimum page size in bytes for our allocations * @@ -296,7 +286,7 @@ static int __force_merge(struct drm_buddy *mm, * Returns: * 0 on success, error code on failure. */ -int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size) +int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size) { unsigned int i, j, root_count =3D 0; u64 offset =3D 0; @@ -318,9 +308,9 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 = chunk_size) mm->chunk_size =3D chunk_size; mm->max_order =3D ilog2(size) - ilog2(chunk_size); =20 - BUG_ON(mm->max_order > DRM_BUDDY_MAX_ORDER); + BUG_ON(mm->max_order > GPU_BUDDY_MAX_ORDER); =20 - mm->free_trees =3D kmalloc_array(DRM_BUDDY_MAX_FREE_TREES, + mm->free_trees =3D kmalloc_array(GPU_BUDDY_MAX_FREE_TREES, sizeof(*mm->free_trees), GFP_KERNEL); if (!mm->free_trees) @@ -340,7 +330,7 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 = chunk_size) mm->n_roots =3D hweight64(size); =20 mm->roots =3D kmalloc_array(mm->n_roots, - sizeof(struct drm_buddy_block *), + sizeof(struct gpu_buddy_block *), GFP_KERNEL); if (!mm->roots) goto out_free_tree; @@ -350,21 +340,21 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u6= 4 chunk_size) * not itself a power-of-two. */ do { - struct drm_buddy_block *root; + struct gpu_buddy_block *root; unsigned int order; u64 root_size; =20 order =3D ilog2(size) - ilog2(chunk_size); root_size =3D chunk_size << order; =20 - root =3D drm_block_alloc(mm, NULL, order, offset); + root =3D gpu_block_alloc(mm, NULL, order, offset); if (!root) goto out_free_roots; =20 mark_free(mm, root); =20 BUG_ON(root_count > mm->max_order); - BUG_ON(drm_buddy_block_size(mm, root) < chunk_size); + BUG_ON(gpu_buddy_block_size(mm, root) < chunk_size); =20 mm->roots[root_count] =3D root; =20 @@ -377,7 +367,7 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 = chunk_size) =20 out_free_roots: while (root_count--) - drm_block_free(mm, mm->roots[root_count]); + gpu_block_free(mm, mm->roots[root_count]); kfree(mm->roots); out_free_tree: while (i--) @@ -385,16 +375,16 @@ int drm_buddy_init(struct drm_buddy *mm, u64 size, u6= 4 chunk_size) kfree(mm->free_trees); return -ENOMEM; } -EXPORT_SYMBOL(drm_buddy_init); +EXPORT_SYMBOL(gpu_buddy_init); =20 /** - * drm_buddy_fini - tear down the memory manager + * gpu_buddy_fini - tear down the memory manager * - * @mm: DRM buddy manager to free + * @mm: GPU buddy manager to free * * Cleanup memory manager resources and the freetree */ -void drm_buddy_fini(struct drm_buddy *mm) +void gpu_buddy_fini(struct gpu_buddy *mm) { u64 root_size, size, start; unsigned int order; @@ -404,13 +394,13 @@ void drm_buddy_fini(struct drm_buddy *mm) =20 for (i =3D 0; i < mm->n_roots; ++i) { order =3D ilog2(size) - ilog2(mm->chunk_size); - start =3D drm_buddy_block_offset(mm->roots[i]); + start =3D gpu_buddy_block_offset(mm->roots[i]); __force_merge(mm, start, start + size, order); =20 - if (WARN_ON(!drm_buddy_block_is_free(mm->roots[i]))) + if (WARN_ON(!gpu_buddy_block_is_free(mm->roots[i]))) kunit_fail_current_test("buddy_fini() root"); =20 - drm_block_free(mm, mm->roots[i]); + gpu_block_free(mm, mm->roots[i]); =20 root_size =3D mm->chunk_size << order; size -=3D root_size; @@ -423,31 +413,31 @@ void drm_buddy_fini(struct drm_buddy *mm) kfree(mm->free_trees); kfree(mm->roots); } -EXPORT_SYMBOL(drm_buddy_fini); +EXPORT_SYMBOL(gpu_buddy_fini); =20 -static int split_block(struct drm_buddy *mm, - struct drm_buddy_block *block) +static int split_block(struct gpu_buddy *mm, + struct gpu_buddy_block *block) { - unsigned int block_order =3D drm_buddy_block_order(block) - 1; - u64 offset =3D drm_buddy_block_offset(block); + unsigned int block_order =3D gpu_buddy_block_order(block) - 1; + u64 offset =3D gpu_buddy_block_offset(block); =20 - BUG_ON(!drm_buddy_block_is_free(block)); - BUG_ON(!drm_buddy_block_order(block)); + BUG_ON(!gpu_buddy_block_is_free(block)); + BUG_ON(!gpu_buddy_block_order(block)); =20 - block->left =3D drm_block_alloc(mm, block, block_order, offset); + block->left =3D gpu_block_alloc(mm, block, block_order, offset); if (!block->left) return -ENOMEM; =20 - block->right =3D drm_block_alloc(mm, block, block_order, + block->right =3D gpu_block_alloc(mm, block, block_order, offset + (mm->chunk_size << block_order)); if (!block->right) { - drm_block_free(mm, block->left); + gpu_block_free(mm, block->left); return -ENOMEM; } =20 mark_split(mm, block); =20 - if (drm_buddy_block_is_clear(block)) { + if (gpu_buddy_block_is_clear(block)) { mark_cleared(block->left); mark_cleared(block->right); clear_reset(block); @@ -460,34 +450,34 @@ static int split_block(struct drm_buddy *mm, } =20 /** - * drm_get_buddy - get buddy address + * gpu_get_buddy - get buddy address * - * @block: DRM buddy block + * @block: GPU buddy block * * Returns the corresponding buddy block for @block, or NULL * if this is a root block and can't be merged further. * Requires some kind of locking to protect against * any concurrent allocate and free operations. */ -struct drm_buddy_block * -drm_get_buddy(struct drm_buddy_block *block) +struct gpu_buddy_block * +gpu_get_buddy(struct gpu_buddy_block *block) { return __get_buddy(block); } -EXPORT_SYMBOL(drm_get_buddy); +EXPORT_SYMBOL(gpu_get_buddy); =20 /** - * drm_buddy_reset_clear - reset blocks clear state + * gpu_buddy_reset_clear - reset blocks clear state * - * @mm: DRM buddy manager + * @mm: GPU buddy manager * @is_clear: blocks clear state * * Reset the clear state based on @is_clear value for each block * in the freetree. */ -void drm_buddy_reset_clear(struct drm_buddy *mm, bool is_clear) +void gpu_buddy_reset_clear(struct gpu_buddy *mm, bool is_clear) { - enum drm_buddy_free_tree src_tree, dst_tree; + enum gpu_buddy_free_tree src_tree, dst_tree; u64 root_size, size, start; unsigned int order; int i; @@ -495,60 +485,60 @@ void drm_buddy_reset_clear(struct drm_buddy *mm, bool= is_clear) size =3D mm->size; for (i =3D 0; i < mm->n_roots; ++i) { order =3D ilog2(size) - ilog2(mm->chunk_size); - start =3D drm_buddy_block_offset(mm->roots[i]); + start =3D gpu_buddy_block_offset(mm->roots[i]); __force_merge(mm, start, start + size, order); =20 root_size =3D mm->chunk_size << order; size -=3D root_size; } =20 - src_tree =3D is_clear ? DRM_BUDDY_DIRTY_TREE : DRM_BUDDY_CLEAR_TREE; - dst_tree =3D is_clear ? DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE; + src_tree =3D is_clear ? GPU_BUDDY_DIRTY_TREE : GPU_BUDDY_CLEAR_TREE; + dst_tree =3D is_clear ? GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE; =20 for (i =3D 0; i <=3D mm->max_order; ++i) { struct rb_root *root =3D &mm->free_trees[src_tree][i]; - struct drm_buddy_block *block, *tmp; + struct gpu_buddy_block *block, *tmp; =20 rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) { rbtree_remove(mm, block); if (is_clear) { mark_cleared(block); - mm->clear_avail +=3D drm_buddy_block_size(mm, block); + mm->clear_avail +=3D gpu_buddy_block_size(mm, block); } else { clear_reset(block); - mm->clear_avail -=3D drm_buddy_block_size(mm, block); + mm->clear_avail -=3D gpu_buddy_block_size(mm, block); } =20 rbtree_insert(mm, block, dst_tree); } } } -EXPORT_SYMBOL(drm_buddy_reset_clear); +EXPORT_SYMBOL(gpu_buddy_reset_clear); =20 /** - * drm_buddy_free_block - free a block + * gpu_buddy_free_block - free a block * - * @mm: DRM buddy manager + * @mm: GPU buddy manager * @block: block to be freed */ -void drm_buddy_free_block(struct drm_buddy *mm, - struct drm_buddy_block *block) +void gpu_buddy_free_block(struct gpu_buddy *mm, + struct gpu_buddy_block *block) { - BUG_ON(!drm_buddy_block_is_allocated(block)); - mm->avail +=3D drm_buddy_block_size(mm, block); - if (drm_buddy_block_is_clear(block)) - mm->clear_avail +=3D drm_buddy_block_size(mm, block); + BUG_ON(!gpu_buddy_block_is_allocated(block)); + mm->avail +=3D gpu_buddy_block_size(mm, block); + if (gpu_buddy_block_is_clear(block)) + mm->clear_avail +=3D gpu_buddy_block_size(mm, block); =20 - __drm_buddy_free(mm, block, false); + __gpu_buddy_free(mm, block, false); } -EXPORT_SYMBOL(drm_buddy_free_block); +EXPORT_SYMBOL(gpu_buddy_free_block); =20 -static void __drm_buddy_free_list(struct drm_buddy *mm, +static void __gpu_buddy_free_list(struct gpu_buddy *mm, struct list_head *objects, bool mark_clear, bool mark_dirty) { - struct drm_buddy_block *block, *on; + struct gpu_buddy_block *block, *on; =20 WARN_ON(mark_dirty && mark_clear); =20 @@ -557,13 +547,13 @@ static void __drm_buddy_free_list(struct drm_buddy *m= m, mark_cleared(block); else if (mark_dirty) clear_reset(block); - drm_buddy_free_block(mm, block); + gpu_buddy_free_block(mm, block); cond_resched(); } INIT_LIST_HEAD(objects); } =20 -static void drm_buddy_free_list_internal(struct drm_buddy *mm, +static void gpu_buddy_free_list_internal(struct gpu_buddy *mm, struct list_head *objects) { /* @@ -571,43 +561,43 @@ static void drm_buddy_free_list_internal(struct drm_b= uddy *mm, * at this point. For example we might have just failed part of the * allocation. */ - __drm_buddy_free_list(mm, objects, false, false); + __gpu_buddy_free_list(mm, objects, false, false); } =20 /** - * drm_buddy_free_list - free blocks + * gpu_buddy_free_list - free blocks * - * @mm: DRM buddy manager + * @mm: GPU buddy manager * @objects: input list head to free blocks - * @flags: optional flags like DRM_BUDDY_CLEARED + * @flags: optional flags like GPU_BUDDY_CLEARED */ -void drm_buddy_free_list(struct drm_buddy *mm, +void gpu_buddy_free_list(struct gpu_buddy *mm, struct list_head *objects, unsigned int flags) { - bool mark_clear =3D flags & DRM_BUDDY_CLEARED; + bool mark_clear =3D flags & GPU_BUDDY_CLEARED; =20 - __drm_buddy_free_list(mm, objects, mark_clear, !mark_clear); + __gpu_buddy_free_list(mm, objects, mark_clear, !mark_clear); } -EXPORT_SYMBOL(drm_buddy_free_list); +EXPORT_SYMBOL(gpu_buddy_free_list); =20 -static bool block_incompatible(struct drm_buddy_block *block, unsigned int= flags) +static bool block_incompatible(struct gpu_buddy_block *block, unsigned int= flags) { - bool needs_clear =3D flags & DRM_BUDDY_CLEAR_ALLOCATION; + bool needs_clear =3D flags & GPU_BUDDY_CLEAR_ALLOCATION; =20 - return needs_clear !=3D drm_buddy_block_is_clear(block); + return needs_clear !=3D gpu_buddy_block_is_clear(block); } =20 -static struct drm_buddy_block * -__alloc_range_bias(struct drm_buddy *mm, +static struct gpu_buddy_block * +__alloc_range_bias(struct gpu_buddy *mm, u64 start, u64 end, unsigned int order, unsigned long flags, bool fallback) { u64 req_size =3D mm->chunk_size << order; - struct drm_buddy_block *block; - struct drm_buddy_block *buddy; + struct gpu_buddy_block *block; + struct gpu_buddy_block *buddy; LIST_HEAD(dfs); int err; int i; @@ -622,23 +612,23 @@ __alloc_range_bias(struct drm_buddy *mm, u64 block_end; =20 block =3D list_first_entry_or_null(&dfs, - struct drm_buddy_block, + struct gpu_buddy_block, tmp_link); if (!block) break; =20 list_del(&block->tmp_link); =20 - if (drm_buddy_block_order(block) < order) + if (gpu_buddy_block_order(block) < order) continue; =20 - block_start =3D drm_buddy_block_offset(block); - block_end =3D block_start + drm_buddy_block_size(mm, block) - 1; + block_start =3D gpu_buddy_block_offset(block); + block_end =3D block_start + gpu_buddy_block_size(mm, block) - 1; =20 if (!overlaps(start, end, block_start, block_end)) continue; =20 - if (drm_buddy_block_is_allocated(block)) + if (gpu_buddy_block_is_allocated(block)) continue; =20 if (block_start < start || block_end > end) { @@ -654,17 +644,17 @@ __alloc_range_bias(struct drm_buddy *mm, continue; =20 if (contains(start, end, block_start, block_end) && - order =3D=3D drm_buddy_block_order(block)) { + order =3D=3D gpu_buddy_block_order(block)) { /* * Find the free block within the range. */ - if (drm_buddy_block_is_free(block)) + if (gpu_buddy_block_is_free(block)) return block; =20 continue; } =20 - if (!drm_buddy_block_is_split(block)) { + if (!gpu_buddy_block_is_split(block)) { err =3D split_block(mm, block); if (unlikely(err)) goto err_undo; @@ -684,19 +674,19 @@ __alloc_range_bias(struct drm_buddy *mm, */ buddy =3D __get_buddy(block); if (buddy && - (drm_buddy_block_is_free(block) && - drm_buddy_block_is_free(buddy))) - __drm_buddy_free(mm, block, false); + (gpu_buddy_block_is_free(block) && + gpu_buddy_block_is_free(buddy))) + __gpu_buddy_free(mm, block, false); return ERR_PTR(err); } =20 -static struct drm_buddy_block * -__drm_buddy_alloc_range_bias(struct drm_buddy *mm, +static struct gpu_buddy_block * +__gpu_buddy_alloc_range_bias(struct gpu_buddy *mm, u64 start, u64 end, unsigned int order, unsigned long flags) { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; bool fallback =3D false; =20 block =3D __alloc_range_bias(mm, start, end, order, @@ -708,12 +698,12 @@ __drm_buddy_alloc_range_bias(struct drm_buddy *mm, return block; } =20 -static struct drm_buddy_block * -get_maxblock(struct drm_buddy *mm, +static struct gpu_buddy_block * +get_maxblock(struct gpu_buddy *mm, unsigned int order, - enum drm_buddy_free_tree tree) + enum gpu_buddy_free_tree tree) { - struct drm_buddy_block *max_block =3D NULL, *block =3D NULL; + struct gpu_buddy_block *max_block =3D NULL, *block =3D NULL; struct rb_root *root; unsigned int i; =20 @@ -728,8 +718,8 @@ get_maxblock(struct drm_buddy *mm, continue; } =20 - if (drm_buddy_block_offset(block) > - drm_buddy_block_offset(max_block)) { + if (gpu_buddy_block_offset(block) > + gpu_buddy_block_offset(max_block)) { max_block =3D block; } } @@ -737,25 +727,25 @@ get_maxblock(struct drm_buddy *mm, return max_block; } =20 -static struct drm_buddy_block * -alloc_from_freetree(struct drm_buddy *mm, +static struct gpu_buddy_block * +alloc_from_freetree(struct gpu_buddy *mm, unsigned int order, unsigned long flags) { - struct drm_buddy_block *block =3D NULL; + struct gpu_buddy_block *block =3D NULL; struct rb_root *root; - enum drm_buddy_free_tree tree; + enum gpu_buddy_free_tree tree; unsigned int tmp; int err; =20 - tree =3D (flags & DRM_BUDDY_CLEAR_ALLOCATION) ? - DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE; + tree =3D (flags & GPU_BUDDY_CLEAR_ALLOCATION) ? + GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE; =20 - if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) { + if (flags & GPU_BUDDY_TOPDOWN_ALLOCATION) { block =3D get_maxblock(mm, order, tree); if (block) /* Store the obtained block order */ - tmp =3D drm_buddy_block_order(block); + tmp =3D gpu_buddy_block_order(block); } else { for (tmp =3D order; tmp <=3D mm->max_order; ++tmp) { /* Get RB tree root for this order and tree */ @@ -768,8 +758,8 @@ alloc_from_freetree(struct drm_buddy *mm, =20 if (!block) { /* Try allocating from the other tree */ - tree =3D (tree =3D=3D DRM_BUDDY_CLEAR_TREE) ? - DRM_BUDDY_DIRTY_TREE : DRM_BUDDY_CLEAR_TREE; + tree =3D (tree =3D=3D GPU_BUDDY_CLEAR_TREE) ? + GPU_BUDDY_DIRTY_TREE : GPU_BUDDY_CLEAR_TREE; =20 for (tmp =3D order; tmp <=3D mm->max_order; ++tmp) { root =3D &mm->free_trees[tree][tmp]; @@ -782,7 +772,7 @@ alloc_from_freetree(struct drm_buddy *mm, return ERR_PTR(-ENOSPC); } =20 - BUG_ON(!drm_buddy_block_is_free(block)); + BUG_ON(!gpu_buddy_block_is_free(block)); =20 while (tmp !=3D order) { err =3D split_block(mm, block); @@ -796,18 +786,18 @@ alloc_from_freetree(struct drm_buddy *mm, =20 err_undo: if (tmp !=3D order) - __drm_buddy_free(mm, block, false); + __gpu_buddy_free(mm, block, false); return ERR_PTR(err); } =20 -static int __alloc_range(struct drm_buddy *mm, +static int __alloc_range(struct gpu_buddy *mm, struct list_head *dfs, u64 start, u64 size, struct list_head *blocks, u64 *total_allocated_on_err) { - struct drm_buddy_block *block; - struct drm_buddy_block *buddy; + struct gpu_buddy_block *block; + struct gpu_buddy_block *buddy; u64 total_allocated =3D 0; LIST_HEAD(allocated); u64 end; @@ -820,31 +810,31 @@ static int __alloc_range(struct drm_buddy *mm, u64 block_end; =20 block =3D list_first_entry_or_null(dfs, - struct drm_buddy_block, + struct gpu_buddy_block, tmp_link); if (!block) break; =20 list_del(&block->tmp_link); =20 - block_start =3D drm_buddy_block_offset(block); - block_end =3D block_start + drm_buddy_block_size(mm, block) - 1; + block_start =3D gpu_buddy_block_offset(block); + block_end =3D block_start + gpu_buddy_block_size(mm, block) - 1; =20 if (!overlaps(start, end, block_start, block_end)) continue; =20 - if (drm_buddy_block_is_allocated(block)) { + if (gpu_buddy_block_is_allocated(block)) { err =3D -ENOSPC; goto err_free; } =20 if (contains(start, end, block_start, block_end)) { - if (drm_buddy_block_is_free(block)) { + if (gpu_buddy_block_is_free(block)) { mark_allocated(mm, block); - total_allocated +=3D drm_buddy_block_size(mm, block); - mm->avail -=3D drm_buddy_block_size(mm, block); - if (drm_buddy_block_is_clear(block)) - mm->clear_avail -=3D drm_buddy_block_size(mm, block); + total_allocated +=3D gpu_buddy_block_size(mm, block); + mm->avail -=3D gpu_buddy_block_size(mm, block); + if (gpu_buddy_block_is_clear(block)) + mm->clear_avail -=3D gpu_buddy_block_size(mm, block); list_add_tail(&block->link, &allocated); continue; } else if (!mm->clear_avail) { @@ -853,7 +843,7 @@ static int __alloc_range(struct drm_buddy *mm, } } =20 - if (!drm_buddy_block_is_split(block)) { + if (!gpu_buddy_block_is_split(block)) { err =3D split_block(mm, block); if (unlikely(err)) goto err_undo; @@ -880,22 +870,22 @@ static int __alloc_range(struct drm_buddy *mm, */ buddy =3D __get_buddy(block); if (buddy && - (drm_buddy_block_is_free(block) && - drm_buddy_block_is_free(buddy))) - __drm_buddy_free(mm, block, false); + (gpu_buddy_block_is_free(block) && + gpu_buddy_block_is_free(buddy))) + __gpu_buddy_free(mm, block, false); =20 err_free: if (err =3D=3D -ENOSPC && total_allocated_on_err) { list_splice_tail(&allocated, blocks); *total_allocated_on_err =3D total_allocated; } else { - drm_buddy_free_list_internal(mm, &allocated); + gpu_buddy_free_list_internal(mm, &allocated); } =20 return err; } =20 -static int __drm_buddy_alloc_range(struct drm_buddy *mm, +static int __gpu_buddy_alloc_range(struct gpu_buddy *mm, u64 start, u64 size, u64 *total_allocated_on_err, @@ -911,13 +901,13 @@ static int __drm_buddy_alloc_range(struct drm_buddy *= mm, blocks, total_allocated_on_err); } =20 -static int __alloc_contig_try_harder(struct drm_buddy *mm, +static int __alloc_contig_try_harder(struct gpu_buddy *mm, u64 size, u64 min_block_size, struct list_head *blocks) { u64 rhs_offset, lhs_offset, lhs_size, filled; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; unsigned int tree, order; LIST_HEAD(blocks_lhs); unsigned long pages; @@ -943,8 +933,8 @@ static int __alloc_contig_try_harder(struct drm_buddy *= mm, block =3D rbtree_get_free_block(iter); =20 /* Allocate blocks traversing RHS */ - rhs_offset =3D drm_buddy_block_offset(block); - err =3D __drm_buddy_alloc_range(mm, rhs_offset, size, + rhs_offset =3D gpu_buddy_block_offset(block); + err =3D __gpu_buddy_alloc_range(mm, rhs_offset, size, &filled, blocks); if (!err || err !=3D -ENOSPC) return err; @@ -954,18 +944,18 @@ static int __alloc_contig_try_harder(struct drm_buddy= *mm, lhs_size =3D round_up(lhs_size, min_block_size); =20 /* Allocate blocks traversing LHS */ - lhs_offset =3D drm_buddy_block_offset(block) - lhs_size; - err =3D __drm_buddy_alloc_range(mm, lhs_offset, lhs_size, + lhs_offset =3D gpu_buddy_block_offset(block) - lhs_size; + err =3D __gpu_buddy_alloc_range(mm, lhs_offset, lhs_size, NULL, &blocks_lhs); if (!err) { list_splice(&blocks_lhs, blocks); return 0; } else if (err !=3D -ENOSPC) { - drm_buddy_free_list_internal(mm, blocks); + gpu_buddy_free_list_internal(mm, blocks); return err; } /* Free blocks for the next iteration */ - drm_buddy_free_list_internal(mm, blocks); + gpu_buddy_free_list_internal(mm, blocks); =20 iter =3D rb_prev(iter); } @@ -975,9 +965,9 @@ static int __alloc_contig_try_harder(struct drm_buddy *= mm, } =20 /** - * drm_buddy_block_trim - free unused pages + * gpu_buddy_block_trim - free unused pages * - * @mm: DRM buddy manager + * @mm: GPU buddy manager * @start: start address to begin the trimming. * @new_size: original size requested * @blocks: Input and output list of allocated blocks. @@ -993,13 +983,13 @@ static int __alloc_contig_try_harder(struct drm_buddy= *mm, * Returns: * 0 on success, error code on failure. */ -int drm_buddy_block_trim(struct drm_buddy *mm, +int gpu_buddy_block_trim(struct gpu_buddy *mm, u64 *start, u64 new_size, struct list_head *blocks) { - struct drm_buddy_block *parent; - struct drm_buddy_block *block; + struct gpu_buddy_block *parent; + struct gpu_buddy_block *block; u64 block_start, block_end; LIST_HEAD(dfs); u64 new_start; @@ -1009,22 +999,22 @@ int drm_buddy_block_trim(struct drm_buddy *mm, return -EINVAL; =20 block =3D list_first_entry(blocks, - struct drm_buddy_block, + struct gpu_buddy_block, link); =20 - block_start =3D drm_buddy_block_offset(block); - block_end =3D block_start + drm_buddy_block_size(mm, block); + block_start =3D gpu_buddy_block_offset(block); + block_end =3D block_start + gpu_buddy_block_size(mm, block); =20 - if (WARN_ON(!drm_buddy_block_is_allocated(block))) + if (WARN_ON(!gpu_buddy_block_is_allocated(block))) return -EINVAL; =20 - if (new_size > drm_buddy_block_size(mm, block)) + if (new_size > gpu_buddy_block_size(mm, block)) return -EINVAL; =20 if (!new_size || !IS_ALIGNED(new_size, mm->chunk_size)) return -EINVAL; =20 - if (new_size =3D=3D drm_buddy_block_size(mm, block)) + if (new_size =3D=3D gpu_buddy_block_size(mm, block)) return 0; =20 new_start =3D block_start; @@ -1043,9 +1033,9 @@ int drm_buddy_block_trim(struct drm_buddy *mm, =20 list_del(&block->link); mark_free(mm, block); - mm->avail +=3D drm_buddy_block_size(mm, block); - if (drm_buddy_block_is_clear(block)) - mm->clear_avail +=3D drm_buddy_block_size(mm, block); + mm->avail +=3D gpu_buddy_block_size(mm, block); + if (gpu_buddy_block_is_clear(block)) + mm->clear_avail +=3D gpu_buddy_block_size(mm, block); =20 /* Prevent recursively freeing this node */ parent =3D block->parent; @@ -1055,26 +1045,26 @@ int drm_buddy_block_trim(struct drm_buddy *mm, err =3D __alloc_range(mm, &dfs, new_start, new_size, blocks, NULL); if (err) { mark_allocated(mm, block); - mm->avail -=3D drm_buddy_block_size(mm, block); - if (drm_buddy_block_is_clear(block)) - mm->clear_avail -=3D drm_buddy_block_size(mm, block); + mm->avail -=3D gpu_buddy_block_size(mm, block); + if (gpu_buddy_block_is_clear(block)) + mm->clear_avail -=3D gpu_buddy_block_size(mm, block); list_add(&block->link, blocks); } =20 block->parent =3D parent; return err; } -EXPORT_SYMBOL(drm_buddy_block_trim); +EXPORT_SYMBOL(gpu_buddy_block_trim); =20 -static struct drm_buddy_block * -__drm_buddy_alloc_blocks(struct drm_buddy *mm, +static struct gpu_buddy_block * +__gpu_buddy_alloc_blocks(struct gpu_buddy *mm, u64 start, u64 end, unsigned int order, unsigned long flags) { - if (flags & DRM_BUDDY_RANGE_ALLOCATION) + if (flags & GPU_BUDDY_RANGE_ALLOCATION) /* Allocate traversing within the range */ - return __drm_buddy_alloc_range_bias(mm, start, end, + return __gpu_buddy_alloc_range_bias(mm, start, end, order, flags); else /* Allocate from freetree */ @@ -1082,15 +1072,15 @@ __drm_buddy_alloc_blocks(struct drm_buddy *mm, } =20 /** - * drm_buddy_alloc_blocks - allocate power-of-two blocks + * gpu_buddy_alloc_blocks - allocate power-of-two blocks * - * @mm: DRM buddy manager to allocate from + * @mm: GPU buddy manager to allocate from * @start: start of the allowed range for this block * @end: end of the allowed range for this block * @size: size of the allocation in bytes * @min_block_size: alignment of the allocation * @blocks: output list head to add allocated blocks - * @flags: DRM_BUDDY_*_ALLOCATION flags + * @flags: GPU_BUDDY_*_ALLOCATION flags * * alloc_range_bias() called on range limitations, which traverses * the tree and returns the desired block. @@ -1101,13 +1091,13 @@ __drm_buddy_alloc_blocks(struct drm_buddy *mm, * Returns: * 0 on success, error code on failure. */ -int drm_buddy_alloc_blocks(struct drm_buddy *mm, +int gpu_buddy_alloc_blocks(struct gpu_buddy *mm, u64 start, u64 end, u64 size, u64 min_block_size, struct list_head *blocks, unsigned long flags) { - struct drm_buddy_block *block =3D NULL; + struct gpu_buddy_block *block =3D NULL; u64 original_size, original_min_size; unsigned int min_order, order; LIST_HEAD(allocated); @@ -1137,14 +1127,14 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, if (!IS_ALIGNED(start | end, min_block_size)) return -EINVAL; =20 - return __drm_buddy_alloc_range(mm, start, size, NULL, blocks); + return __gpu_buddy_alloc_range(mm, start, size, NULL, blocks); } =20 original_size =3D size; original_min_size =3D min_block_size; =20 /* Roundup the size to power of 2 */ - if (flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION) { + if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) { size =3D roundup_pow_of_two(size); min_block_size =3D size; /* Align size value to min_block_size */ @@ -1157,8 +1147,8 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, min_order =3D ilog2(min_block_size) - ilog2(mm->chunk_size); =20 if (order > mm->max_order || size > mm->size) { - if ((flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION) && - !(flags & DRM_BUDDY_RANGE_ALLOCATION)) + if ((flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) && + !(flags & GPU_BUDDY_RANGE_ALLOCATION)) return __alloc_contig_try_harder(mm, original_size, original_min_size, blocks); =20 @@ -1171,7 +1161,7 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, BUG_ON(order < min_order); =20 do { - block =3D __drm_buddy_alloc_blocks(mm, start, + block =3D __gpu_buddy_alloc_blocks(mm, start, end, order, flags); @@ -1182,7 +1172,7 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, /* Try allocation through force merge method */ if (mm->clear_avail && !__force_merge(mm, start, end, min_order)) { - block =3D __drm_buddy_alloc_blocks(mm, start, + block =3D __gpu_buddy_alloc_blocks(mm, start, end, min_order, flags); @@ -1196,8 +1186,8 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, * Try contiguous block allocation through * try harder method. */ - if (flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION && - !(flags & DRM_BUDDY_RANGE_ALLOCATION)) + if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION && + !(flags & GPU_BUDDY_RANGE_ALLOCATION)) return __alloc_contig_try_harder(mm, original_size, original_min_size, @@ -1208,9 +1198,9 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, } while (1); =20 mark_allocated(mm, block); - mm->avail -=3D drm_buddy_block_size(mm, block); - if (drm_buddy_block_is_clear(block)) - mm->clear_avail -=3D drm_buddy_block_size(mm, block); + mm->avail -=3D gpu_buddy_block_size(mm, block); + if (gpu_buddy_block_is_clear(block)) + mm->clear_avail -=3D gpu_buddy_block_size(mm, block); kmemleak_update_trace(block); list_add_tail(&block->link, &allocated); =20 @@ -1221,7 +1211,7 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, } while (1); =20 /* Trim the allocated block to the required size */ - if (!(flags & DRM_BUDDY_TRIM_DISABLE) && + if (!(flags & GPU_BUDDY_TRIM_DISABLE) && original_size !=3D size) { struct list_head *trim_list; LIST_HEAD(temp); @@ -1234,11 +1224,11 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, block =3D list_last_entry(&allocated, typeof(*block), link); list_move(&block->link, &temp); trim_list =3D &temp; - trim_size =3D drm_buddy_block_size(mm, block) - + trim_size =3D gpu_buddy_block_size(mm, block) - (size - original_size); } =20 - drm_buddy_block_trim(mm, + gpu_buddy_block_trim(mm, NULL, trim_size, trim_list); @@ -1251,44 +1241,42 @@ int drm_buddy_alloc_blocks(struct drm_buddy *mm, return 0; =20 err_free: - drm_buddy_free_list_internal(mm, &allocated); + gpu_buddy_free_list_internal(mm, &allocated); return err; } -EXPORT_SYMBOL(drm_buddy_alloc_blocks); +EXPORT_SYMBOL(gpu_buddy_alloc_blocks); =20 /** - * drm_buddy_block_print - print block information + * gpu_buddy_block_print - print block information * - * @mm: DRM buddy manager - * @block: DRM buddy block - * @p: DRM printer to use + * @mm: GPU buddy manager + * @block: GPU buddy block */ -void drm_buddy_block_print(struct drm_buddy *mm, - struct drm_buddy_block *block, - struct drm_printer *p) +void gpu_buddy_block_print(struct gpu_buddy *mm, + struct gpu_buddy_block *block) { - u64 start =3D drm_buddy_block_offset(block); - u64 size =3D drm_buddy_block_size(mm, block); + u64 start =3D gpu_buddy_block_offset(block); + u64 size =3D gpu_buddy_block_size(mm, block); =20 - drm_printf(p, "%#018llx-%#018llx: %llu\n", start, start + size, size); + pr_info("%#018llx-%#018llx: %llu\n", start, start + size, size); } -EXPORT_SYMBOL(drm_buddy_block_print); +EXPORT_SYMBOL(gpu_buddy_block_print); =20 /** - * drm_buddy_print - print allocator state + * gpu_buddy_print - print allocator state * - * @mm: DRM buddy manager - * @p: DRM printer to use + * @mm: GPU buddy manager + * @p: GPU printer to use */ -void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p) +void gpu_buddy_print(struct gpu_buddy *mm) { int order; =20 - drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_= free: %lluMiB\n", - mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avai= l >> 20); + pr_info("chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_free: = %lluMiB\n", + mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >= > 20); =20 for (order =3D mm->max_order; order >=3D 0; order--) { - struct drm_buddy_block *block, *tmp; + struct gpu_buddy_block *block, *tmp; struct rb_root *root; u64 count =3D 0, free; unsigned int tree; @@ -1297,40 +1285,38 @@ void drm_buddy_print(struct drm_buddy *mm, struct d= rm_printer *p) root =3D &mm->free_trees[tree][order]; =20 rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) { - BUG_ON(!drm_buddy_block_is_free(block)); + BUG_ON(!gpu_buddy_block_is_free(block)); count++; } } =20 - drm_printf(p, "order-%2d ", order); - free =3D count * (mm->chunk_size << order); if (free < SZ_1M) - drm_printf(p, "free: %8llu KiB", free >> 10); + pr_info("order-%2d free: %8llu KiB, blocks: %llu\n", + order, free >> 10, count); else - drm_printf(p, "free: %8llu MiB", free >> 20); - - drm_printf(p, ", blocks: %llu\n", count); + pr_info("order-%2d free: %8llu MiB, blocks: %llu\n", + order, free >> 20, count); } } -EXPORT_SYMBOL(drm_buddy_print); +EXPORT_SYMBOL(gpu_buddy_print); =20 -static void drm_buddy_module_exit(void) +static void gpu_buddy_module_exit(void) { kmem_cache_destroy(slab_blocks); } =20 -static int __init drm_buddy_module_init(void) +static int __init gpu_buddy_module_init(void) { - slab_blocks =3D KMEM_CACHE(drm_buddy_block, 0); + slab_blocks =3D KMEM_CACHE(gpu_buddy_block, 0); if (!slab_blocks) return -ENOMEM; =20 return 0; } =20 -module_init(drm_buddy_module_init); -module_exit(drm_buddy_module_exit); +module_init(gpu_buddy_module_init); +module_exit(gpu_buddy_module_exit); =20 -MODULE_DESCRIPTION("DRM Buddy Allocator"); +MODULE_DESCRIPTION("GPU Buddy Allocator"); MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index ca2a2801e77f..f48d00fe28cc 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -220,6 +220,7 @@ config DRM_GPUSVM config DRM_BUDDY tristate depends on DRM + select GPU_BUDDY help A page based buddy allocator =20 diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 5c86bc908955..6ff0f6f10b58 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -113,7 +113,7 @@ drm_gpusvm_helper-$(CONFIG_ZONE_DEVICE) +=3D \ =20 obj-$(CONFIG_DRM_GPUSVM) +=3D drm_gpusvm_helper.o =20 -obj-$(CONFIG_DRM_BUDDY) +=3D ../buddy.o +obj-$(CONFIG_DRM_BUDDY) +=3D drm_buddy.o =20 drm_dma_helper-y :=3D drm_gem_dma_helper.o drm_dma_helper-$(CONFIG_DRM_FBDEV_EMULATION) +=3D drm_fbdev_dma.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/= amdgpu/amdgpu_ras.c index f582113d78b7..149f8f942eae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -5663,7 +5663,7 @@ int amdgpu_ras_add_critical_region(struct amdgpu_devi= ce *adev, struct amdgpu_ras *con =3D amdgpu_ras_get_context(adev); struct amdgpu_vram_mgr_resource *vres; struct ras_critical_region *region; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; int ret =3D 0; =20 if (!bo || !bo->tbo.resource) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h b/drivers/gpu/d= rm/amd/amdgpu/amdgpu_res_cursor.h index be2e56ce1355..8908d9e08a30 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h @@ -55,7 +55,7 @@ static inline void amdgpu_res_first(struct ttm_resource *= res, uint64_t start, uint64_t size, struct amdgpu_res_cursor *cur) { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; struct list_head *head, *next; struct drm_mm_node *node; =20 @@ -71,7 +71,7 @@ static inline void amdgpu_res_first(struct ttm_resource *= res, head =3D &to_amdgpu_vram_mgr_resource(res)->blocks; =20 block =3D list_first_entry_or_null(head, - struct drm_buddy_block, + struct gpu_buddy_block, link); if (!block) goto fallback; @@ -81,7 +81,7 @@ static inline void amdgpu_res_first(struct ttm_resource *= res, =20 next =3D block->link.next; if (next !=3D head) - block =3D list_entry(next, struct drm_buddy_block, link); + block =3D list_entry(next, struct gpu_buddy_block, link); } =20 cur->start =3D amdgpu_vram_mgr_block_start(block) + start; @@ -125,7 +125,7 @@ static inline void amdgpu_res_first(struct ttm_resource= *res, */ static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t= size) { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; struct drm_mm_node *node; struct list_head *next; =20 @@ -146,7 +146,7 @@ static inline void amdgpu_res_next(struct amdgpu_res_cu= rsor *cur, uint64_t size) block =3D cur->node; =20 next =3D block->link.next; - block =3D list_entry(next, struct drm_buddy_block, link); + block =3D list_entry(next, struct gpu_buddy_block, link); =20 cur->node =3D block; cur->start =3D amdgpu_vram_mgr_block_start(block); @@ -175,7 +175,7 @@ static inline void amdgpu_res_next(struct amdgpu_res_cu= rsor *cur, uint64_t size) */ static inline bool amdgpu_res_cleared(struct amdgpu_res_cursor *cur) { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; =20 switch (cur->mem_type) { case TTM_PL_VRAM: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm= /amd/amdgpu/amdgpu_vram_mgr.c index 9d934c07fa6b..cd94f6efb7cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -25,6 +25,7 @@ #include #include #include +#include =20 #include "amdgpu.h" #include "amdgpu_vm.h" @@ -52,15 +53,15 @@ to_amdgpu_device(struct amdgpu_vram_mgr *mgr) return container_of(mgr, struct amdgpu_device, mman.vram_mgr); } =20 -static inline struct drm_buddy_block * +static inline struct gpu_buddy_block * amdgpu_vram_mgr_first_block(struct list_head *list) { - return list_first_entry_or_null(list, struct drm_buddy_block, link); + return list_first_entry_or_null(list, struct gpu_buddy_block, link); } =20 static inline bool amdgpu_is_vram_mgr_blocks_contiguous(struct list_head *= head) { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; u64 start, size; =20 block =3D amdgpu_vram_mgr_first_block(head); @@ -71,7 +72,7 @@ static inline bool amdgpu_is_vram_mgr_blocks_contiguous(s= truct list_head *head) start =3D amdgpu_vram_mgr_block_start(block); size =3D amdgpu_vram_mgr_block_size(block); =20 - block =3D list_entry(block->link.next, struct drm_buddy_block, link); + block =3D list_entry(block->link.next, struct gpu_buddy_block, link); if (start + size !=3D amdgpu_vram_mgr_block_start(block)) return false; } @@ -81,7 +82,7 @@ static inline bool amdgpu_is_vram_mgr_blocks_contiguous(s= truct list_head *head) =20 static inline u64 amdgpu_vram_mgr_blocks_size(struct list_head *head) { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; u64 size =3D 0; =20 list_for_each_entry(block, head, link) @@ -254,7 +255,7 @@ const struct attribute_group amdgpu_vram_mgr_attr_group= =3D { * Calculate how many bytes of the DRM BUDDY block are inside visible VRAM */ static u64 amdgpu_vram_mgr_vis_size(struct amdgpu_device *adev, - struct drm_buddy_block *block) + struct gpu_buddy_block *block) { u64 start =3D amdgpu_vram_mgr_block_start(block); u64 end =3D start + amdgpu_vram_mgr_block_size(block); @@ -279,7 +280,7 @@ u64 amdgpu_vram_mgr_bo_visible_size(struct amdgpu_bo *b= o) struct amdgpu_device *adev =3D amdgpu_ttm_adev(bo->tbo.bdev); struct ttm_resource *res =3D bo->tbo.resource; struct amdgpu_vram_mgr_resource *vres =3D to_amdgpu_vram_mgr_resource(res= ); - struct drm_buddy_block *block; + struct gpu_buddy_block *block; u64 usage =3D 0; =20 if (amdgpu_gmc_vram_full_visible(&adev->gmc)) @@ -299,15 +300,15 @@ static void amdgpu_vram_mgr_do_reserve(struct ttm_res= ource_manager *man) { struct amdgpu_vram_mgr *mgr =3D to_vram_mgr(man); struct amdgpu_device *adev =3D to_amdgpu_device(mgr); - struct drm_buddy *mm =3D &mgr->mm; + struct gpu_buddy *mm =3D &mgr->mm; struct amdgpu_vram_reservation *rsv, *temp; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; uint64_t vis_usage; =20 list_for_each_entry_safe(rsv, temp, &mgr->reservations_pending, blocks) { - if (drm_buddy_alloc_blocks(mm, rsv->start, rsv->start + rsv->size, + if (gpu_buddy_alloc_blocks(mm, rsv->start, rsv->start + rsv->size, rsv->size, mm->chunk_size, &rsv->allocated, - DRM_BUDDY_RANGE_ALLOCATION)) + GPU_BUDDY_RANGE_ALLOCATION)) continue; =20 block =3D amdgpu_vram_mgr_first_block(&rsv->allocated); @@ -403,7 +404,7 @@ int amdgpu_vram_mgr_query_address_block_info(struct amd= gpu_vram_mgr *mgr, uint64_t address, struct amdgpu_vram_block_info *info) { struct amdgpu_vram_mgr_resource *vres; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; u64 start, size; int ret =3D -ENOENT; =20 @@ -450,8 +451,8 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_mana= ger *man, struct amdgpu_vram_mgr_resource *vres; u64 size, remaining_size, lpfn, fpfn; unsigned int adjust_dcc_size =3D 0; - struct drm_buddy *mm =3D &mgr->mm; - struct drm_buddy_block *block; + struct gpu_buddy *mm =3D &mgr->mm; + struct gpu_buddy_block *block; unsigned long pages_per_block; int r; =20 @@ -493,17 +494,17 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_ma= nager *man, INIT_LIST_HEAD(&vres->blocks); =20 if (place->flags & TTM_PL_FLAG_TOPDOWN) - vres->flags |=3D DRM_BUDDY_TOPDOWN_ALLOCATION; + vres->flags |=3D GPU_BUDDY_TOPDOWN_ALLOCATION; =20 if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) - vres->flags |=3D DRM_BUDDY_CONTIGUOUS_ALLOCATION; + vres->flags |=3D GPU_BUDDY_CONTIGUOUS_ALLOCATION; =20 if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CLEARED) - vres->flags |=3D DRM_BUDDY_CLEAR_ALLOCATION; + vres->flags |=3D GPU_BUDDY_CLEAR_ALLOCATION; =20 if (fpfn || lpfn !=3D mgr->mm.size) /* Allocate blocks in desired range */ - vres->flags |=3D DRM_BUDDY_RANGE_ALLOCATION; + vres->flags |=3D GPU_BUDDY_RANGE_ALLOCATION; =20 if (bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC && adev->gmc.gmc_funcs->get_dcc_alignment) @@ -516,7 +517,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_mana= ger *man, dcc_size =3D roundup_pow_of_two(vres->base.size + adjust_dcc_size); remaining_size =3D (u64)dcc_size; =20 - vres->flags |=3D DRM_BUDDY_TRIM_DISABLE; + vres->flags |=3D GPU_BUDDY_TRIM_DISABLE; } =20 mutex_lock(&mgr->lock); @@ -536,7 +537,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_mana= ger *man, =20 BUG_ON(min_block_size < mm->chunk_size); =20 - r =3D drm_buddy_alloc_blocks(mm, fpfn, + r =3D gpu_buddy_alloc_blocks(mm, fpfn, lpfn, size, min_block_size, @@ -545,7 +546,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_mana= ger *man, =20 if (unlikely(r =3D=3D -ENOSPC) && pages_per_block =3D=3D ~0ul && !(place->flags & TTM_PL_FLAG_CONTIGUOUS)) { - vres->flags &=3D ~DRM_BUDDY_CONTIGUOUS_ALLOCATION; + vres->flags &=3D ~GPU_BUDDY_CONTIGUOUS_ALLOCATION; pages_per_block =3D max_t(u32, 2UL << (20UL - PAGE_SHIFT), tbo->page_alignment); =20 @@ -566,7 +567,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_mana= ger *man, list_add_tail(&vres->vres_node, &mgr->allocated_vres_list); =20 if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS && adjust_dcc_size) { - struct drm_buddy_block *dcc_block; + struct gpu_buddy_block *dcc_block; unsigned long dcc_start; u64 trim_start; =20 @@ -576,7 +577,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_mana= ger *man, roundup((unsigned long)amdgpu_vram_mgr_block_start(dcc_block), adjust_dcc_size); trim_start =3D (u64)dcc_start; - drm_buddy_block_trim(mm, &trim_start, + gpu_buddy_block_trim(mm, &trim_start, (u64)vres->base.size, &vres->blocks); } @@ -614,7 +615,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_mana= ger *man, return 0; =20 error_free_blocks: - drm_buddy_free_list(mm, &vres->blocks, 0); + gpu_buddy_free_list(mm, &vres->blocks, 0); mutex_unlock(&mgr->lock); error_fini: ttm_resource_fini(man, &vres->base); @@ -637,8 +638,8 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_man= ager *man, struct amdgpu_vram_mgr_resource *vres =3D to_amdgpu_vram_mgr_resource(res= ); struct amdgpu_vram_mgr *mgr =3D to_vram_mgr(man); struct amdgpu_device *adev =3D to_amdgpu_device(mgr); - struct drm_buddy *mm =3D &mgr->mm; - struct drm_buddy_block *block; + struct gpu_buddy *mm =3D &mgr->mm; + struct gpu_buddy_block *block; uint64_t vis_usage =3D 0; =20 mutex_lock(&mgr->lock); @@ -649,7 +650,7 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_man= ager *man, list_for_each_entry(block, &vres->blocks, link) vis_usage +=3D amdgpu_vram_mgr_vis_size(adev, block); =20 - drm_buddy_free_list(mm, &vres->blocks, vres->flags); + gpu_buddy_free_list(mm, &vres->blocks, vres->flags); amdgpu_vram_mgr_do_reserve(man); mutex_unlock(&mgr->lock); =20 @@ -688,7 +689,7 @@ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *ade= v, if (!*sgt) return -ENOMEM; =20 - /* Determine the number of DRM_BUDDY blocks to export */ + /* Determine the number of GPU_BUDDY blocks to export */ amdgpu_res_first(res, offset, length, &cursor); while (cursor.remaining) { num_entries++; @@ -704,10 +705,10 @@ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *a= dev, sg->length =3D 0; =20 /* - * Walk down DRM_BUDDY blocks to populate scatterlist nodes - * @note: Use iterator api to get first the DRM_BUDDY block + * Walk down GPU_BUDDY blocks to populate scatterlist nodes + * @note: Use iterator api to get first the GPU_BUDDY block * and the number of bytes from it. Access the following - * DRM_BUDDY block(s) if more buffer needs to exported + * GPU_BUDDY block(s) if more buffer needs to exported */ amdgpu_res_first(res, offset, length, &cursor); for_each_sgtable_sg((*sgt), sg, i) { @@ -792,10 +793,10 @@ uint64_t amdgpu_vram_mgr_vis_usage(struct amdgpu_vram= _mgr *mgr) void amdgpu_vram_mgr_clear_reset_blocks(struct amdgpu_device *adev) { struct amdgpu_vram_mgr *mgr =3D &adev->mman.vram_mgr; - struct drm_buddy *mm =3D &mgr->mm; + struct gpu_buddy *mm =3D &mgr->mm; =20 mutex_lock(&mgr->lock); - drm_buddy_reset_clear(mm, false); + gpu_buddy_reset_clear(mm, false); mutex_unlock(&mgr->lock); } =20 @@ -815,7 +816,7 @@ static bool amdgpu_vram_mgr_intersects(struct ttm_resou= rce_manager *man, size_t size) { struct amdgpu_vram_mgr_resource *mgr =3D to_amdgpu_vram_mgr_resource(res); - struct drm_buddy_block *block; + struct gpu_buddy_block *block; =20 /* Check each drm buddy block individually */ list_for_each_entry(block, &mgr->blocks, link) { @@ -848,7 +849,7 @@ static bool amdgpu_vram_mgr_compatible(struct ttm_resou= rce_manager *man, size_t size) { struct amdgpu_vram_mgr_resource *mgr =3D to_amdgpu_vram_mgr_resource(res); - struct drm_buddy_block *block; + struct gpu_buddy_block *block; =20 /* Check each drm buddy block individually */ list_for_each_entry(block, &mgr->blocks, link) { @@ -877,7 +878,7 @@ static void amdgpu_vram_mgr_debug(struct ttm_resource_m= anager *man, struct drm_printer *printer) { struct amdgpu_vram_mgr *mgr =3D to_vram_mgr(man); - struct drm_buddy *mm =3D &mgr->mm; + struct gpu_buddy *mm =3D &mgr->mm; struct amdgpu_vram_reservation *rsv; =20 drm_printf(printer, " vis usage:%llu\n", @@ -930,7 +931,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev) mgr->default_page_size =3D PAGE_SIZE; =20 man->func =3D &amdgpu_vram_mgr_func; - err =3D drm_buddy_init(&mgr->mm, man->size, PAGE_SIZE); + err =3D gpu_buddy_init(&mgr->mm, man->size, PAGE_SIZE); if (err) return err; =20 @@ -965,11 +966,11 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) kfree(rsv); =20 list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, blocks) { - drm_buddy_free_list(&mgr->mm, &rsv->allocated, 0); + gpu_buddy_free_list(&mgr->mm, &rsv->allocated, 0); kfree(rsv); } if (!adev->gmc.is_app_apu) - drm_buddy_fini(&mgr->mm); + gpu_buddy_fini(&mgr->mm); mutex_unlock(&mgr->lock); =20 ttm_resource_manager_cleanup(man); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h b/drivers/gpu/drm= /amd/amdgpu/amdgpu_vram_mgr.h index 874779618056..429a21a2e9b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h @@ -28,7 +28,7 @@ =20 struct amdgpu_vram_mgr { struct ttm_resource_manager manager; - struct drm_buddy mm; + struct gpu_buddy mm; /* protects access to buffer objects */ struct mutex lock; struct list_head reservations_pending; @@ -57,19 +57,19 @@ struct amdgpu_vram_mgr_resource { struct amdgpu_vres_task task; }; =20 -static inline u64 amdgpu_vram_mgr_block_start(struct drm_buddy_block *bloc= k) +static inline u64 amdgpu_vram_mgr_block_start(struct gpu_buddy_block *bloc= k) { - return drm_buddy_block_offset(block); + return gpu_buddy_block_offset(block); } =20 -static inline u64 amdgpu_vram_mgr_block_size(struct drm_buddy_block *block) +static inline u64 amdgpu_vram_mgr_block_size(struct gpu_buddy_block *block) { - return (u64)PAGE_SIZE << drm_buddy_block_order(block); + return (u64)PAGE_SIZE << gpu_buddy_block_order(block); } =20 -static inline bool amdgpu_vram_mgr_is_cleared(struct drm_buddy_block *bloc= k) +static inline bool amdgpu_vram_mgr_is_cleared(struct gpu_buddy_block *bloc= k) { - return drm_buddy_block_is_clear(block); + return gpu_buddy_block_is_clear(block); } =20 static inline struct amdgpu_vram_mgr_resource * @@ -82,8 +82,8 @@ static inline void amdgpu_vram_mgr_set_cleared(struct ttm= _resource *res) { struct amdgpu_vram_mgr_resource *ares =3D to_amdgpu_vram_mgr_resource(res= ); =20 - WARN_ON(ares->flags & DRM_BUDDY_CLEARED); - ares->flags |=3D DRM_BUDDY_CLEARED; + WARN_ON(ares->flags & GPU_BUDDY_CLEARED); + ares->flags |=3D GPU_BUDDY_CLEARED; } =20 int amdgpu_vram_mgr_query_address_block_info(struct amdgpu_vram_mgr *mgr, diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c new file mode 100644 index 000000000000..841f3de5f307 --- /dev/null +++ b/drivers/gpu/drm/drm_buddy.c @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright =C2=A9 2021 Intel Corporation + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +/** + * drm_buddy_block_print - print block information + * + * @mm: DRM buddy manager + * @block: DRM buddy block + * @p: DRM printer to use + */ +void drm_buddy_block_print(struct gpu_buddy *mm, + struct gpu_buddy_block *block, + struct drm_printer *p) +{ + u64 start =3D gpu_buddy_block_offset(block); + u64 size =3D gpu_buddy_block_size(mm, block); + + drm_printf(p, "%#018llx-%#018llx: %llu\n", start, start + size, size); +} +EXPORT_SYMBOL(drm_buddy_block_print); + +/** + * drm_buddy_print - print allocator state + * + * @mm: DRM buddy manager + * @p: DRM printer to use + */ +void drm_buddy_print(struct gpu_buddy *mm, struct drm_printer *p) +{ + int order; + + drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_= free: %lluMiB\n", + mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avai= l >> 20); + + for (order =3D mm->max_order; order >=3D 0; order--) { + struct gpu_buddy_block *block, *tmp; + struct rb_root *root; + u64 count =3D 0, free; + unsigned int tree; + + for_each_free_tree(tree) { + root =3D &mm->free_trees[tree][order]; + + rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) { + BUG_ON(!gpu_buddy_block_is_free(block)); + count++; + } + } + + drm_printf(p, "order-%2d ", order); + + free =3D count * (mm->chunk_size << order); + if (free < SZ_1M) + drm_printf(p, "free: %8llu KiB", free >> 10); + else + drm_printf(p, "free: %8llu MiB", free >> 20); + + drm_printf(p, ", blocks: %llu\n", count); + } +} +EXPORT_SYMBOL(drm_buddy_print); + +MODULE_DESCRIPTION("DRM-specific GPU Buddy Allocator Print Helpers"); +MODULE_LICENSE("Dual MIT/GPL"); diff --git a/drivers/gpu/drm/i915/i915_scatterlist.c b/drivers/gpu/drm/i915= /i915_scatterlist.c index 30246f02bcfe..6a34dae13769 100644 --- a/drivers/gpu/drm/i915/i915_scatterlist.c +++ b/drivers/gpu/drm/i915/i915_scatterlist.c @@ -167,9 +167,9 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(st= ruct ttm_resource *res, struct i915_ttm_buddy_resource *bman_res =3D to_ttm_buddy_resource(res); const u64 size =3D res->size; const u32 max_segment =3D round_down(UINT_MAX, page_alignment); - struct drm_buddy *mm =3D bman_res->mm; + struct gpu_buddy *mm =3D bman_res->mm; struct list_head *blocks =3D &bman_res->blocks; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; struct i915_refct_sgt *rsgt; struct scatterlist *sg; struct sg_table *st; @@ -202,8 +202,8 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(st= ruct ttm_resource *res, list_for_each_entry(block, blocks, link) { u64 block_size, offset; =20 - block_size =3D min_t(u64, size, drm_buddy_block_size(mm, block)); - offset =3D drm_buddy_block_offset(block); + block_size =3D min_t(u64, size, gpu_buddy_block_size(mm, block)); + offset =3D gpu_buddy_block_offset(block); =20 while (block_size) { u64 len; diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/dr= m/i915/i915_ttm_buddy_manager.c index 6b256d95badd..c5ca90088705 100644 --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c @@ -6,6 +6,7 @@ #include =20 #include +#include #include #include #include @@ -16,7 +17,7 @@ =20 struct i915_ttm_buddy_manager { struct ttm_resource_manager manager; - struct drm_buddy mm; + struct gpu_buddy mm; struct list_head reserved; struct mutex lock; unsigned long visible_size; @@ -38,7 +39,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_m= anager *man, { struct i915_ttm_buddy_manager *bman =3D to_buddy_manager(man); struct i915_ttm_buddy_resource *bman_res; - struct drm_buddy *mm =3D &bman->mm; + struct gpu_buddy *mm =3D &bman->mm; unsigned long n_pages, lpfn; u64 min_page_size; u64 size; @@ -57,13 +58,13 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource= _manager *man, bman_res->mm =3D mm; =20 if (place->flags & TTM_PL_FLAG_TOPDOWN) - bman_res->flags |=3D DRM_BUDDY_TOPDOWN_ALLOCATION; + bman_res->flags |=3D GPU_BUDDY_TOPDOWN_ALLOCATION; =20 if (place->flags & TTM_PL_FLAG_CONTIGUOUS) - bman_res->flags |=3D DRM_BUDDY_CONTIGUOUS_ALLOCATION; + bman_res->flags |=3D GPU_BUDDY_CONTIGUOUS_ALLOCATION; =20 if (place->fpfn || lpfn !=3D man->size) - bman_res->flags |=3D DRM_BUDDY_RANGE_ALLOCATION; + bman_res->flags |=3D GPU_BUDDY_RANGE_ALLOCATION; =20 GEM_BUG_ON(!bman_res->base.size); size =3D bman_res->base.size; @@ -89,7 +90,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_m= anager *man, goto err_free_res; } =20 - err =3D drm_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT, + err =3D gpu_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT, (u64)lpfn << PAGE_SHIFT, (u64)n_pages << PAGE_SHIFT, min_page_size, @@ -101,15 +102,15 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resour= ce_manager *man, if (lpfn <=3D bman->visible_size) { bman_res->used_visible_size =3D PFN_UP(bman_res->base.size); } else { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; =20 list_for_each_entry(block, &bman_res->blocks, link) { unsigned long start =3D - drm_buddy_block_offset(block) >> PAGE_SHIFT; + gpu_buddy_block_offset(block) >> PAGE_SHIFT; =20 if (start < bman->visible_size) { unsigned long end =3D start + - (drm_buddy_block_size(mm, block) >> PAGE_SHIFT); + (gpu_buddy_block_size(mm, block) >> PAGE_SHIFT); =20 bman_res->used_visible_size +=3D min(end, bman->visible_size) - start; @@ -126,7 +127,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource= _manager *man, return 0; =20 err_free_blocks: - drm_buddy_free_list(mm, &bman_res->blocks, 0); + gpu_buddy_free_list(mm, &bman_res->blocks, 0); mutex_unlock(&bman->lock); err_free_res: ttm_resource_fini(man, &bman_res->base); @@ -141,7 +142,7 @@ static void i915_ttm_buddy_man_free(struct ttm_resource= _manager *man, struct i915_ttm_buddy_manager *bman =3D to_buddy_manager(man); =20 mutex_lock(&bman->lock); - drm_buddy_free_list(&bman->mm, &bman_res->blocks, 0); + gpu_buddy_free_list(&bman->mm, &bman_res->blocks, 0); bman->visible_avail +=3D bman_res->used_visible_size; mutex_unlock(&bman->lock); =20 @@ -156,8 +157,8 @@ static bool i915_ttm_buddy_man_intersects(struct ttm_re= source_manager *man, { struct i915_ttm_buddy_resource *bman_res =3D to_ttm_buddy_resource(res); struct i915_ttm_buddy_manager *bman =3D to_buddy_manager(man); - struct drm_buddy *mm =3D &bman->mm; - struct drm_buddy_block *block; + struct gpu_buddy *mm =3D &bman->mm; + struct gpu_buddy_block *block; =20 if (!place->fpfn && !place->lpfn) return true; @@ -176,9 +177,9 @@ static bool i915_ttm_buddy_man_intersects(struct ttm_re= source_manager *man, /* Check each drm buddy block individually */ list_for_each_entry(block, &bman_res->blocks, link) { unsigned long fpfn =3D - drm_buddy_block_offset(block) >> PAGE_SHIFT; + gpu_buddy_block_offset(block) >> PAGE_SHIFT; unsigned long lpfn =3D fpfn + - (drm_buddy_block_size(mm, block) >> PAGE_SHIFT); + (gpu_buddy_block_size(mm, block) >> PAGE_SHIFT); =20 if (place->fpfn < lpfn && place->lpfn > fpfn) return true; @@ -194,8 +195,8 @@ static bool i915_ttm_buddy_man_compatible(struct ttm_re= source_manager *man, { struct i915_ttm_buddy_resource *bman_res =3D to_ttm_buddy_resource(res); struct i915_ttm_buddy_manager *bman =3D to_buddy_manager(man); - struct drm_buddy *mm =3D &bman->mm; - struct drm_buddy_block *block; + struct gpu_buddy *mm =3D &bman->mm; + struct gpu_buddy_block *block; =20 if (!place->fpfn && !place->lpfn) return true; @@ -209,9 +210,9 @@ static bool i915_ttm_buddy_man_compatible(struct ttm_re= source_manager *man, /* Check each drm buddy block individually */ list_for_each_entry(block, &bman_res->blocks, link) { unsigned long fpfn =3D - drm_buddy_block_offset(block) >> PAGE_SHIFT; + gpu_buddy_block_offset(block) >> PAGE_SHIFT; unsigned long lpfn =3D fpfn + - (drm_buddy_block_size(mm, block) >> PAGE_SHIFT); + (gpu_buddy_block_size(mm, block) >> PAGE_SHIFT); =20 if (fpfn < place->fpfn || lpfn > place->lpfn) return false; @@ -224,7 +225,7 @@ static void i915_ttm_buddy_man_debug(struct ttm_resourc= e_manager *man, struct drm_printer *printer) { struct i915_ttm_buddy_manager *bman =3D to_buddy_manager(man); - struct drm_buddy_block *block; + struct gpu_buddy_block *block; =20 mutex_lock(&bman->lock); drm_printf(printer, "default_page_size: %lluKiB\n", @@ -293,7 +294,7 @@ int i915_ttm_buddy_man_init(struct ttm_device *bdev, if (!bman) return -ENOMEM; =20 - err =3D drm_buddy_init(&bman->mm, size, chunk_size); + err =3D gpu_buddy_init(&bman->mm, size, chunk_size); if (err) goto err_free_bman; =20 @@ -333,7 +334,7 @@ int i915_ttm_buddy_man_fini(struct ttm_device *bdev, un= signed int type) { struct ttm_resource_manager *man =3D ttm_manager_type(bdev, type); struct i915_ttm_buddy_manager *bman =3D to_buddy_manager(man); - struct drm_buddy *mm =3D &bman->mm; + struct gpu_buddy *mm =3D &bman->mm; int ret; =20 ttm_resource_manager_set_used(man, false); @@ -345,8 +346,8 @@ int i915_ttm_buddy_man_fini(struct ttm_device *bdev, un= signed int type) ttm_set_driver_manager(bdev, type, NULL); =20 mutex_lock(&bman->lock); - drm_buddy_free_list(mm, &bman->reserved, 0); - drm_buddy_fini(mm); + gpu_buddy_free_list(mm, &bman->reserved, 0); + gpu_buddy_fini(mm); bman->visible_avail +=3D bman->visible_reserved; WARN_ON_ONCE(bman->visible_avail !=3D bman->visible_size); mutex_unlock(&bman->lock); @@ -371,15 +372,15 @@ int i915_ttm_buddy_man_reserve(struct ttm_resource_ma= nager *man, u64 start, u64 size) { struct i915_ttm_buddy_manager *bman =3D to_buddy_manager(man); - struct drm_buddy *mm =3D &bman->mm; + struct gpu_buddy *mm =3D &bman->mm; unsigned long fpfn =3D start >> PAGE_SHIFT; unsigned long flags =3D 0; int ret; =20 - flags |=3D DRM_BUDDY_RANGE_ALLOCATION; + flags |=3D GPU_BUDDY_RANGE_ALLOCATION; =20 mutex_lock(&bman->lock); - ret =3D drm_buddy_alloc_blocks(mm, start, + ret =3D gpu_buddy_alloc_blocks(mm, start, start + size, size, mm->chunk_size, &bman->reserved, diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h b/drivers/gpu/dr= m/i915/i915_ttm_buddy_manager.h index d64620712830..1cff018c1689 100644 --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h @@ -13,7 +13,7 @@ =20 struct ttm_device; struct ttm_resource_manager; -struct drm_buddy; +struct gpu_buddy; =20 /** * struct i915_ttm_buddy_resource @@ -33,7 +33,7 @@ struct i915_ttm_buddy_resource { struct list_head blocks; unsigned long flags; unsigned long used_visible_size; - struct drm_buddy *mm; + struct gpu_buddy *mm; }; =20 /** diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers= /gpu/drm/i915/selftests/intel_memory_region.c index 7b856b5090f9..8307390943a2 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -6,7 +6,7 @@ #include #include =20 -#include +#include =20 #include "../i915_selftest.h" =20 @@ -371,7 +371,7 @@ static int igt_mock_splintered_region(void *arg) struct drm_i915_private *i915 =3D mem->i915; struct i915_ttm_buddy_resource *res; struct drm_i915_gem_object *obj; - struct drm_buddy *mm; + struct gpu_buddy *mm; unsigned int expected_order; LIST_HEAD(objects); u64 size; @@ -447,8 +447,8 @@ static int igt_mock_max_segment(void *arg) struct drm_i915_private *i915 =3D mem->i915; struct i915_ttm_buddy_resource *res; struct drm_i915_gem_object *obj; - struct drm_buddy_block *block; - struct drm_buddy *mm; + struct gpu_buddy_block *block; + struct gpu_buddy *mm; struct list_head *blocks; struct scatterlist *sg; I915_RND_STATE(prng); @@ -487,8 +487,8 @@ static int igt_mock_max_segment(void *arg) mm =3D res->mm; size =3D 0; list_for_each_entry(block, blocks, link) { - if (drm_buddy_block_size(mm, block) > size) - size =3D drm_buddy_block_size(mm, block); + if (gpu_buddy_block_size(mm, block) > size) + size =3D gpu_buddy_block_size(mm, block); } if (size < max_segment) { pr_err("%s: Failed to create a huge contiguous block [> %u], largest blo= ck %lld\n", @@ -527,14 +527,14 @@ static u64 igt_object_mappable_total(struct drm_i915_= gem_object *obj) struct intel_memory_region *mr =3D obj->mm.region; struct i915_ttm_buddy_resource *bman_res =3D to_ttm_buddy_resource(obj->mm.res); - struct drm_buddy *mm =3D bman_res->mm; - struct drm_buddy_block *block; + struct gpu_buddy *mm =3D bman_res->mm; + struct gpu_buddy_block *block; u64 total; =20 total =3D 0; list_for_each_entry(block, &bman_res->blocks, link) { - u64 start =3D drm_buddy_block_offset(block); - u64 end =3D start + drm_buddy_block_size(mm, block); + u64 start =3D gpu_buddy_block_offset(block); + u64 end =3D start + gpu_buddy_block_size(mm, block); =20 if (start < resource_size(&mr->io)) total +=3D min_t(u64, end, resource_size(&mr->io)) - start; diff --git a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c b/drivers/gpu= /drm/ttm/tests/ttm_bo_validate_test.c index 6d95447a989d..e32f3c8d7b84 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c +++ b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c @@ -251,7 +251,7 @@ static void ttm_bo_validate_basic(struct kunit *test) NULL, &dummy_ttm_bo_destroy); KUNIT_EXPECT_EQ(test, err, 0); =20 - snd_place =3D ttm_place_kunit_init(test, snd_mem, DRM_BUDDY_TOPDOWN_ALLOC= ATION); + snd_place =3D ttm_place_kunit_init(test, snd_mem, GPU_BUDDY_TOPDOWN_ALLOC= ATION); snd_placement =3D ttm_placement_kunit_init(test, snd_place, 1); =20 err =3D ttm_bo_validate(bo, snd_placement, &ctx_val); @@ -263,7 +263,7 @@ static void ttm_bo_validate_basic(struct kunit *test) KUNIT_EXPECT_TRUE(test, ttm_tt_is_populated(bo->ttm)); KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem); KUNIT_EXPECT_EQ(test, bo->resource->placement, - DRM_BUDDY_TOPDOWN_ALLOCATION); + GPU_BUDDY_TOPDOWN_ALLOCATION); =20 ttm_bo_fini(bo); ttm_mock_manager_fini(priv->ttm_dev, snd_mem); diff --git a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c b/drivers/gpu/drm= /ttm/tests/ttm_mock_manager.c index dd395229e388..294d56d9067e 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c +++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c @@ -31,7 +31,7 @@ static int ttm_mock_manager_alloc(struct ttm_resource_man= ager *man, { struct ttm_mock_manager *manager =3D to_mock_mgr(man); struct ttm_mock_resource *mock_res; - struct drm_buddy *mm =3D &manager->mm; + struct gpu_buddy *mm =3D &manager->mm; u64 lpfn, fpfn, alloc_size; int err; =20 @@ -47,14 +47,14 @@ static int ttm_mock_manager_alloc(struct ttm_resource_m= anager *man, INIT_LIST_HEAD(&mock_res->blocks); =20 if (place->flags & TTM_PL_FLAG_TOPDOWN) - mock_res->flags |=3D DRM_BUDDY_TOPDOWN_ALLOCATION; + mock_res->flags |=3D GPU_BUDDY_TOPDOWN_ALLOCATION; =20 if (place->flags & TTM_PL_FLAG_CONTIGUOUS) - mock_res->flags |=3D DRM_BUDDY_CONTIGUOUS_ALLOCATION; + mock_res->flags |=3D GPU_BUDDY_CONTIGUOUS_ALLOCATION; =20 alloc_size =3D (uint64_t)mock_res->base.size; mutex_lock(&manager->lock); - err =3D drm_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size, + err =3D gpu_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size, manager->default_page_size, &mock_res->blocks, mock_res->flags); @@ -67,7 +67,7 @@ static int ttm_mock_manager_alloc(struct ttm_resource_man= ager *man, return 0; =20 error_free_blocks: - drm_buddy_free_list(mm, &mock_res->blocks, 0); + gpu_buddy_free_list(mm, &mock_res->blocks, 0); ttm_resource_fini(man, &mock_res->base); mutex_unlock(&manager->lock); =20 @@ -79,10 +79,10 @@ static void ttm_mock_manager_free(struct ttm_resource_m= anager *man, { struct ttm_mock_manager *manager =3D to_mock_mgr(man); struct ttm_mock_resource *mock_res =3D to_mock_mgr_resource(res); - struct drm_buddy *mm =3D &manager->mm; + struct gpu_buddy *mm =3D &manager->mm; =20 mutex_lock(&manager->lock); - drm_buddy_free_list(mm, &mock_res->blocks, 0); + gpu_buddy_free_list(mm, &mock_res->blocks, 0); mutex_unlock(&manager->lock); =20 ttm_resource_fini(man, res); @@ -106,7 +106,7 @@ int ttm_mock_manager_init(struct ttm_device *bdev, u32 = mem_type, u32 size) =20 mutex_init(&manager->lock); =20 - err =3D drm_buddy_init(&manager->mm, size, PAGE_SIZE); + err =3D gpu_buddy_init(&manager->mm, size, PAGE_SIZE); =20 if (err) { kfree(manager); @@ -142,7 +142,7 @@ void ttm_mock_manager_fini(struct ttm_device *bdev, u32= mem_type) ttm_resource_manager_set_used(man, false); =20 mutex_lock(&mock_man->lock); - drm_buddy_fini(&mock_man->mm); + gpu_buddy_fini(&mock_man->mm); mutex_unlock(&mock_man->lock); =20 ttm_set_driver_manager(bdev, mem_type, NULL); diff --git a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h b/drivers/gpu/drm= /ttm/tests/ttm_mock_manager.h index 96ea8c9aae34..08710756fd8e 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h +++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h @@ -9,7 +9,7 @@ =20 struct ttm_mock_manager { struct ttm_resource_manager man; - struct drm_buddy mm; + struct gpu_buddy mm; u64 default_page_size; /* protects allocations of mock buffer objects */ struct mutex lock; diff --git a/drivers/gpu/drm/xe/xe_res_cursor.h b/drivers/gpu/drm/xe/xe_res= _cursor.h index 4e00008b7081..5f4ab08c0686 100644 --- a/drivers/gpu/drm/xe/xe_res_cursor.h +++ b/drivers/gpu/drm/xe/xe_res_cursor.h @@ -58,7 +58,7 @@ struct xe_res_cursor { /** @dma_addr: Current element in a struct drm_pagemap_addr array */ const struct drm_pagemap_addr *dma_addr; /** @mm: Buddy allocator for VRAM cursor */ - struct drm_buddy *mm; + struct gpu_buddy *mm; /** * @dma_start: DMA start address for the current segment. * This may be different to @dma_addr.addr since elements in @@ -69,7 +69,7 @@ struct xe_res_cursor { u64 dma_seg_size; }; =20 -static struct drm_buddy *xe_res_get_buddy(struct ttm_resource *res) +static struct gpu_buddy *xe_res_get_buddy(struct ttm_resource *res) { struct ttm_resource_manager *mgr; =20 @@ -104,30 +104,30 @@ static inline void xe_res_first(struct ttm_resource *= res, case XE_PL_STOLEN: case XE_PL_VRAM0: case XE_PL_VRAM1: { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; struct list_head *head, *next; - struct drm_buddy *mm =3D xe_res_get_buddy(res); + struct gpu_buddy *mm =3D xe_res_get_buddy(res); =20 head =3D &to_xe_ttm_vram_mgr_resource(res)->blocks; =20 block =3D list_first_entry_or_null(head, - struct drm_buddy_block, + struct gpu_buddy_block, link); if (!block) goto fallback; =20 - while (start >=3D drm_buddy_block_size(mm, block)) { - start -=3D drm_buddy_block_size(mm, block); + while (start >=3D gpu_buddy_block_size(mm, block)) { + start -=3D gpu_buddy_block_size(mm, block); =20 next =3D block->link.next; if (next !=3D head) - block =3D list_entry(next, struct drm_buddy_block, + block =3D list_entry(next, struct gpu_buddy_block, link); } =20 cur->mm =3D mm; - cur->start =3D drm_buddy_block_offset(block) + start; - cur->size =3D min(drm_buddy_block_size(mm, block) - start, + cur->start =3D gpu_buddy_block_offset(block) + start; + cur->size =3D min(gpu_buddy_block_size(mm, block) - start, size); cur->remaining =3D size; cur->node =3D block; @@ -259,7 +259,7 @@ static inline void xe_res_first_dma(const struct drm_pa= gemap_addr *dma_addr, */ static inline void xe_res_next(struct xe_res_cursor *cur, u64 size) { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; struct list_head *next; u64 start; =20 @@ -295,18 +295,18 @@ static inline void xe_res_next(struct xe_res_cursor *= cur, u64 size) block =3D cur->node; =20 next =3D block->link.next; - block =3D list_entry(next, struct drm_buddy_block, link); + block =3D list_entry(next, struct gpu_buddy_block, link); =20 =20 - while (start >=3D drm_buddy_block_size(cur->mm, block)) { - start -=3D drm_buddy_block_size(cur->mm, block); + while (start >=3D gpu_buddy_block_size(cur->mm, block)) { + start -=3D gpu_buddy_block_size(cur->mm, block); =20 next =3D block->link.next; - block =3D list_entry(next, struct drm_buddy_block, link); + block =3D list_entry(next, struct gpu_buddy_block, link); } =20 - cur->start =3D drm_buddy_block_offset(block) + start; - cur->size =3D min(drm_buddy_block_size(cur->mm, block) - start, + cur->start =3D gpu_buddy_block_offset(block) + start; + cur->size =3D min(gpu_buddy_block_size(cur->mm, block) - start, cur->remaining); cur->node =3D block; break; diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 213f0334518a..cda3bf7e2418 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -747,7 +747,7 @@ static u64 block_offset_to_pfn(struct drm_pagemap *dpag= emap, u64 offset) return PHYS_PFN(offset + xpagemap->hpa_base); } =20 -static struct drm_buddy *vram_to_buddy(struct xe_vram_region *vram) +static struct gpu_buddy *vram_to_buddy(struct xe_vram_region *vram) { return &vram->ttm.mm; } @@ -758,17 +758,17 @@ static int xe_svm_populate_devmem_pfn(struct drm_page= map_devmem *devmem_allocati struct xe_bo *bo =3D to_xe_bo(devmem_allocation); struct ttm_resource *res =3D bo->ttm.resource; struct list_head *blocks =3D &to_xe_ttm_vram_mgr_resource(res)->blocks; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; int j =3D 0; =20 list_for_each_entry(block, blocks, link) { struct xe_vram_region *vr =3D block->private; - struct drm_buddy *buddy =3D vram_to_buddy(vr); + struct gpu_buddy *buddy =3D vram_to_buddy(vr); u64 block_pfn =3D block_offset_to_pfn(devmem_allocation->dpagemap, - drm_buddy_block_offset(block)); + gpu_buddy_block_offset(block)); int i; =20 - for (i =3D 0; i < drm_buddy_block_size(buddy, block) >> PAGE_SHIFT; ++i) + for (i =3D 0; i < gpu_buddy_block_size(buddy, block) >> PAGE_SHIFT; ++i) pfn[j++] =3D block_pfn + i; } =20 @@ -1033,7 +1033,7 @@ static int xe_drm_pagemap_populate_mm(struct drm_page= map *dpagemap, struct dma_fence *pre_migrate_fence =3D NULL; struct xe_device *xe =3D vr->xe; struct device *dev =3D xe->drm.dev; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; struct xe_validation_ctx vctx; struct list_head *blocks; struct drm_exec exec; diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c b/drivers/gpu/drm/xe/xe_t= tm_vram_mgr.c index 6553a19f7cf2..d119217d566a 100644 --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c @@ -6,6 +6,7 @@ =20 #include #include +#include =20 #include #include @@ -16,16 +17,16 @@ #include "xe_ttm_vram_mgr.h" #include "xe_vram_types.h" =20 -static inline struct drm_buddy_block * +static inline struct gpu_buddy_block * xe_ttm_vram_mgr_first_block(struct list_head *list) { - return list_first_entry_or_null(list, struct drm_buddy_block, link); + return list_first_entry_or_null(list, struct gpu_buddy_block, link); } =20 -static inline bool xe_is_vram_mgr_blocks_contiguous(struct drm_buddy *mm, +static inline bool xe_is_vram_mgr_blocks_contiguous(struct gpu_buddy *mm, struct list_head *head) { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; u64 start, size; =20 block =3D xe_ttm_vram_mgr_first_block(head); @@ -33,12 +34,12 @@ static inline bool xe_is_vram_mgr_blocks_contiguous(str= uct drm_buddy *mm, return false; =20 while (head !=3D block->link.next) { - start =3D drm_buddy_block_offset(block); - size =3D drm_buddy_block_size(mm, block); + start =3D gpu_buddy_block_offset(block); + size =3D gpu_buddy_block_size(mm, block); =20 - block =3D list_entry(block->link.next, struct drm_buddy_block, + block =3D list_entry(block->link.next, struct gpu_buddy_block, link); - if (start + size !=3D drm_buddy_block_offset(block)) + if (start + size !=3D gpu_buddy_block_offset(block)) return false; } =20 @@ -52,7 +53,7 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_manage= r *man, { struct xe_ttm_vram_mgr *mgr =3D to_xe_ttm_vram_mgr(man); struct xe_ttm_vram_mgr_resource *vres; - struct drm_buddy *mm =3D &mgr->mm; + struct gpu_buddy *mm =3D &mgr->mm; u64 size, min_page_size; unsigned long lpfn; int err; @@ -79,10 +80,10 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_mana= ger *man, INIT_LIST_HEAD(&vres->blocks); =20 if (place->flags & TTM_PL_FLAG_TOPDOWN) - vres->flags |=3D DRM_BUDDY_TOPDOWN_ALLOCATION; + vres->flags |=3D GPU_BUDDY_TOPDOWN_ALLOCATION; =20 if (place->fpfn || lpfn !=3D man->size >> PAGE_SHIFT) - vres->flags |=3D DRM_BUDDY_RANGE_ALLOCATION; + vres->flags |=3D GPU_BUDDY_RANGE_ALLOCATION; =20 if (WARN_ON(!vres->base.size)) { err =3D -EINVAL; @@ -118,27 +119,27 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_ma= nager *man, lpfn =3D max_t(unsigned long, place->fpfn + (size >> PAGE_SHIFT), lpfn); } =20 - err =3D drm_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT, + err =3D gpu_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT, (u64)lpfn << PAGE_SHIFT, size, min_page_size, &vres->blocks, vres->flags); if (err) goto error_unlock; =20 if (place->flags & TTM_PL_FLAG_CONTIGUOUS) { - if (!drm_buddy_block_trim(mm, NULL, vres->base.size, &vres->blocks)) + if (!gpu_buddy_block_trim(mm, NULL, vres->base.size, &vres->blocks)) size =3D vres->base.size; } =20 if (lpfn <=3D mgr->visible_size >> PAGE_SHIFT) { vres->used_visible_size =3D size; } else { - struct drm_buddy_block *block; + struct gpu_buddy_block *block; =20 list_for_each_entry(block, &vres->blocks, link) { - u64 start =3D drm_buddy_block_offset(block); + u64 start =3D gpu_buddy_block_offset(block); =20 if (start < mgr->visible_size) { - u64 end =3D start + drm_buddy_block_size(mm, block); + u64 end =3D start + gpu_buddy_block_size(mm, block); =20 vres->used_visible_size +=3D min(end, mgr->visible_size) - start; @@ -158,11 +159,11 @@ static int xe_ttm_vram_mgr_new(struct ttm_resource_ma= nager *man, * the object. */ if (vres->base.placement & TTM_PL_FLAG_CONTIGUOUS) { - struct drm_buddy_block *block =3D list_first_entry(&vres->blocks, + struct gpu_buddy_block *block =3D list_first_entry(&vres->blocks, typeof(*block), link); =20 - vres->base.start =3D drm_buddy_block_offset(block) >> PAGE_SHIFT; + vres->base.start =3D gpu_buddy_block_offset(block) >> PAGE_SHIFT; } else { vres->base.start =3D XE_BO_INVALID_OFFSET; } @@ -184,10 +185,10 @@ static void xe_ttm_vram_mgr_del(struct ttm_resource_m= anager *man, struct xe_ttm_vram_mgr_resource *vres =3D to_xe_ttm_vram_mgr_resource(res); struct xe_ttm_vram_mgr *mgr =3D to_xe_ttm_vram_mgr(man); - struct drm_buddy *mm =3D &mgr->mm; + struct gpu_buddy *mm =3D &mgr->mm; =20 mutex_lock(&mgr->lock); - drm_buddy_free_list(mm, &vres->blocks, 0); + gpu_buddy_free_list(mm, &vres->blocks, 0); mgr->visible_avail +=3D vres->used_visible_size; mutex_unlock(&mgr->lock); =20 @@ -200,7 +201,7 @@ static void xe_ttm_vram_mgr_debug(struct ttm_resource_m= anager *man, struct drm_printer *printer) { struct xe_ttm_vram_mgr *mgr =3D to_xe_ttm_vram_mgr(man); - struct drm_buddy *mm =3D &mgr->mm; + struct gpu_buddy *mm =3D &mgr->mm; =20 mutex_lock(&mgr->lock); drm_printf(printer, "default_page_size: %lluKiB\n", @@ -223,8 +224,8 @@ static bool xe_ttm_vram_mgr_intersects(struct ttm_resou= rce_manager *man, struct xe_ttm_vram_mgr *mgr =3D to_xe_ttm_vram_mgr(man); struct xe_ttm_vram_mgr_resource *vres =3D to_xe_ttm_vram_mgr_resource(res); - struct drm_buddy *mm =3D &mgr->mm; - struct drm_buddy_block *block; + struct gpu_buddy *mm =3D &mgr->mm; + struct gpu_buddy_block *block; =20 if (!place->fpfn && !place->lpfn) return true; @@ -234,9 +235,9 @@ static bool xe_ttm_vram_mgr_intersects(struct ttm_resou= rce_manager *man, =20 list_for_each_entry(block, &vres->blocks, link) { unsigned long fpfn =3D - drm_buddy_block_offset(block) >> PAGE_SHIFT; + gpu_buddy_block_offset(block) >> PAGE_SHIFT; unsigned long lpfn =3D fpfn + - (drm_buddy_block_size(mm, block) >> PAGE_SHIFT); + (gpu_buddy_block_size(mm, block) >> PAGE_SHIFT); =20 if (place->fpfn < lpfn && place->lpfn > fpfn) return true; @@ -253,8 +254,8 @@ static bool xe_ttm_vram_mgr_compatible(struct ttm_resou= rce_manager *man, struct xe_ttm_vram_mgr *mgr =3D to_xe_ttm_vram_mgr(man); struct xe_ttm_vram_mgr_resource *vres =3D to_xe_ttm_vram_mgr_resource(res); - struct drm_buddy *mm =3D &mgr->mm; - struct drm_buddy_block *block; + struct gpu_buddy *mm =3D &mgr->mm; + struct gpu_buddy_block *block; =20 if (!place->fpfn && !place->lpfn) return true; @@ -264,9 +265,9 @@ static bool xe_ttm_vram_mgr_compatible(struct ttm_resou= rce_manager *man, =20 list_for_each_entry(block, &vres->blocks, link) { unsigned long fpfn =3D - drm_buddy_block_offset(block) >> PAGE_SHIFT; + gpu_buddy_block_offset(block) >> PAGE_SHIFT; unsigned long lpfn =3D fpfn + - (drm_buddy_block_size(mm, block) >> PAGE_SHIFT); + (gpu_buddy_block_size(mm, block) >> PAGE_SHIFT); =20 if (fpfn < place->fpfn || lpfn > place->lpfn) return false; @@ -296,7 +297,7 @@ static void xe_ttm_vram_mgr_fini(struct drm_device *dev= , void *arg) =20 WARN_ON_ONCE(mgr->visible_avail !=3D mgr->visible_size); =20 - drm_buddy_fini(&mgr->mm); + gpu_buddy_fini(&mgr->mm); =20 ttm_resource_manager_cleanup(&mgr->manager); =20 @@ -327,7 +328,7 @@ int __xe_ttm_vram_mgr_init(struct xe_device *xe, struct= xe_ttm_vram_mgr *mgr, mgr->visible_avail =3D io_size; =20 ttm_resource_manager_init(man, &xe->ttm, size); - err =3D drm_buddy_init(&mgr->mm, man->size, default_page_size); + err =3D gpu_buddy_init(&mgr->mm, man->size, default_page_size); if (err) return err; =20 @@ -375,7 +376,7 @@ int xe_ttm_vram_mgr_alloc_sgt(struct xe_device *xe, if (!*sgt) return -ENOMEM; =20 - /* Determine the number of DRM_BUDDY blocks to export */ + /* Determine the number of GPU_BUDDY blocks to export */ xe_res_first(res, offset, length, &cursor); while (cursor.remaining) { num_entries++; @@ -392,10 +393,10 @@ int xe_ttm_vram_mgr_alloc_sgt(struct xe_device *xe, sg->length =3D 0; =20 /* - * Walk down DRM_BUDDY blocks to populate scatterlist nodes - * @note: Use iterator api to get first the DRM_BUDDY block + * Walk down GPU_BUDDY blocks to populate scatterlist nodes + * @note: Use iterator api to get first the GPU_BUDDY block * and the number of bytes from it. Access the following - * DRM_BUDDY block(s) if more buffer needs to exported + * GPU_BUDDY block(s) if more buffer needs to exported */ xe_res_first(res, offset, length, &cursor); for_each_sgtable_sg((*sgt), sg, i) { diff --git a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h b/drivers/gpu/drm/x= e/xe_ttm_vram_mgr_types.h index babeec5511d9..9106da056b49 100644 --- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h +++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h @@ -18,7 +18,7 @@ struct xe_ttm_vram_mgr { /** @manager: Base TTM resource manager */ struct ttm_resource_manager manager; /** @mm: DRM buddy allocator which manages the VRAM */ - struct drm_buddy mm; + struct gpu_buddy mm; /** @visible_size: Proped size of the CPU visible portion */ u64 visible_size; /** @visible_avail: CPU visible portion still unallocated */ diff --git a/drivers/gpu/tests/Makefile b/drivers/gpu/tests/Makefile index 8e7654e87d82..4183e6e2de45 100644 --- a/drivers/gpu/tests/Makefile +++ b/drivers/gpu/tests/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 =20 gpu_buddy_tests-y =3D gpu_buddy_test.o gpu_random.o -obj-$(CONFIG_DRM_KUNIT_TEST) +=3D gpu_buddy_tests.o +obj-$(CONFIG_GPU_BUDDY_KUNIT_TEST) +=3D gpu_buddy_tests.o diff --git a/drivers/gpu/tests/gpu_buddy_test.c b/drivers/gpu/tests/gpu_bud= dy_test.c index b905932da990..450e71deed90 100644 --- a/drivers/gpu/tests/gpu_buddy_test.c +++ b/drivers/gpu/tests/gpu_buddy_test.c @@ -21,9 +21,9 @@ static inline u64 get_size(int order, u64 chunk_size) return (1 << order) * chunk_size; } =20 -static void drm_test_buddy_fragmentation_performance(struct kunit *test) +static void gpu_test_buddy_fragmentation_performance(struct kunit *test) { - struct drm_buddy_block *block, *tmp; + struct gpu_buddy_block *block, *tmp; int num_blocks, i, ret, count =3D 0; LIST_HEAD(allocated_blocks); unsigned long elapsed_ms; @@ -32,7 +32,7 @@ static void drm_test_buddy_fragmentation_performance(stru= ct kunit *test) LIST_HEAD(clear_list); LIST_HEAD(dirty_list); LIST_HEAD(free_list); - struct drm_buddy mm; + struct gpu_buddy mm; u64 mm_size =3D SZ_4G; ktime_t start, end; =20 @@ -47,7 +47,7 @@ static void drm_test_buddy_fragmentation_performance(stru= ct kunit *test) * quickly the allocator can satisfy larger, aligned requests from a pool= of * highly fragmented space. */ - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, SZ_4K), + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K), "buddy_init failed\n"); =20 num_blocks =3D mm_size / SZ_64K; @@ -55,7 +55,7 @@ static void drm_test_buddy_fragmentation_performance(stru= ct kunit *test) start =3D ktime_get(); /* Allocate with maximum fragmentation - 8K blocks with 64K alignment */ for (i =3D 0; i < num_blocks; i++) - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, SZ_= 8K, SZ_64K, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_= 8K, SZ_64K, &allocated_blocks, 0), "buddy_alloc hit an error size=3D%u\n", SZ_8K); =20 @@ -68,21 +68,21 @@ static void drm_test_buddy_fragmentation_performance(st= ruct kunit *test) } =20 /* Free with different flags to ensure no coalescing */ - drm_buddy_free_list(&mm, &clear_list, DRM_BUDDY_CLEARED); - drm_buddy_free_list(&mm, &dirty_list, 0); + gpu_buddy_free_list(&mm, &clear_list, GPU_BUDDY_CLEARED); + gpu_buddy_free_list(&mm, &dirty_list, 0); =20 for (i =3D 0; i < num_blocks; i++) - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, SZ_= 64K, SZ_64K, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_= 64K, SZ_64K, &test_blocks, 0), "buddy_alloc hit an error size=3D%u\n", SZ_64K); - drm_buddy_free_list(&mm, &test_blocks, 0); + gpu_buddy_free_list(&mm, &test_blocks, 0); =20 end =3D ktime_get(); elapsed_ms =3D ktime_to_ms(ktime_sub(end, start)); =20 kunit_info(test, "Fragmented allocation took %lu ms\n", elapsed_ms); =20 - drm_buddy_fini(&mm); + gpu_buddy_fini(&mm); =20 /* * Reverse free order under fragmentation @@ -96,13 +96,13 @@ static void drm_test_buddy_fragmentation_performance(st= ruct kunit *test) * deallocation occurs in the opposite order of allocation, exposing the * cost difference between a linear freelist scan and an ordered tree loo= kup. */ - ret =3D drm_buddy_init(&mm, mm_size, SZ_4K); + ret =3D gpu_buddy_init(&mm, mm_size, SZ_4K); KUNIT_ASSERT_EQ(test, ret, 0); =20 start =3D ktime_get(); /* Allocate maximum fragmentation */ for (i =3D 0; i < num_blocks; i++) - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, SZ_= 8K, SZ_64K, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, SZ_= 8K, SZ_64K, &allocated_blocks, 0), "buddy_alloc hit an error size=3D%u\n", SZ_8K); =20 @@ -111,28 +111,28 @@ static void drm_test_buddy_fragmentation_performance(= struct kunit *test) list_move_tail(&block->link, &free_list); count++; } - drm_buddy_free_list(&mm, &free_list, DRM_BUDDY_CLEARED); + gpu_buddy_free_list(&mm, &free_list, GPU_BUDDY_CLEARED); =20 list_for_each_entry_safe_reverse(block, tmp, &allocated_blocks, link) list_move(&block->link, &reverse_list); - drm_buddy_free_list(&mm, &reverse_list, DRM_BUDDY_CLEARED); + gpu_buddy_free_list(&mm, &reverse_list, GPU_BUDDY_CLEARED); =20 end =3D ktime_get(); elapsed_ms =3D ktime_to_ms(ktime_sub(end, start)); =20 kunit_info(test, "Reverse-ordered free took %lu ms\n", elapsed_ms); =20 - drm_buddy_fini(&mm); + gpu_buddy_fini(&mm); } =20 -static void drm_test_buddy_alloc_range_bias(struct kunit *test) +static void gpu_test_buddy_alloc_range_bias(struct kunit *test) { u32 mm_size, size, ps, bias_size, bias_start, bias_end, bias_rem; - DRM_RND_STATE(prng, random_seed); + GPU_RND_STATE(prng, random_seed); unsigned int i, count, *order; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; unsigned long flags; - struct drm_buddy mm; + struct gpu_buddy mm; LIST_HEAD(allocated); =20 bias_size =3D SZ_1M; @@ -142,11 +142,11 @@ static void drm_test_buddy_alloc_range_bias(struct ku= nit *test) =20 kunit_info(test, "mm_size=3D%u, ps=3D%u\n", mm_size, ps); =20 - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, ps), + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps), "buddy_init failed\n"); =20 count =3D mm_size / bias_size; - order =3D drm_random_order(count, &prng); + order =3D gpu_random_order(count, &prng); KUNIT_EXPECT_TRUE(test, order); =20 /* @@ -166,79 +166,79 @@ static void drm_test_buddy_alloc_range_bias(struct ku= nit *test) =20 /* internal round_up too big */ KUNIT_ASSERT_TRUE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start, + gpu_buddy_alloc_blocks(&mm, bias_start, bias_end, bias_size + ps, bias_size, &allocated, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc failed with bias(%x-%x), size=3D%u, ps=3D%u\n", bias_start, bias_end, bias_size, bias_size); =20 /* size too big */ KUNIT_ASSERT_TRUE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start, + gpu_buddy_alloc_blocks(&mm, bias_start, bias_end, bias_size + ps, ps, &allocated, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc didn't fail with bias(%x-%x), size=3D%u, ps=3D%u\n", bias_start, bias_end, bias_size + ps, ps); =20 /* bias range too small for size */ KUNIT_ASSERT_TRUE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start + ps, + gpu_buddy_alloc_blocks(&mm, bias_start + ps, bias_end, bias_size, ps, &allocated, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc didn't fail with bias(%x-%x), size=3D%u, ps=3D%u\n", bias_start + ps, bias_end, bias_size, ps); =20 /* bias misaligned */ KUNIT_ASSERT_TRUE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start + ps, + gpu_buddy_alloc_blocks(&mm, bias_start + ps, bias_end - ps, bias_size >> 1, bias_size >> 1, &allocated, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc h didn't fail with bias(%x-%x), size=3D%u, ps=3D%u\= n", bias_start + ps, bias_end - ps, bias_size >> 1, bias_size >> 1); =20 /* single big page */ KUNIT_ASSERT_FALSE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start, + gpu_buddy_alloc_blocks(&mm, bias_start, bias_end, bias_size, bias_size, &tmp, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc i failed with bias(%x-%x), size=3D%u, ps=3D%u\n", bias_start, bias_end, bias_size, bias_size); - drm_buddy_free_list(&mm, &tmp, 0); + gpu_buddy_free_list(&mm, &tmp, 0); =20 /* single page with internal round_up */ KUNIT_ASSERT_FALSE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start, + gpu_buddy_alloc_blocks(&mm, bias_start, bias_end, ps, bias_size, &tmp, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc failed with bias(%x-%x), size=3D%u, ps=3D%u\n", bias_start, bias_end, ps, bias_size); - drm_buddy_free_list(&mm, &tmp, 0); + gpu_buddy_free_list(&mm, &tmp, 0); =20 /* random size within */ size =3D max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps); if (size) KUNIT_ASSERT_FALSE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start, + gpu_buddy_alloc_blocks(&mm, bias_start, bias_end, size, ps, &tmp, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc failed with bias(%x-%x), size=3D%u, ps=3D%u\n", bias_start, bias_end, size, ps); =20 bias_rem -=3D size; /* too big for current avail */ KUNIT_ASSERT_TRUE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start, + gpu_buddy_alloc_blocks(&mm, bias_start, bias_end, bias_rem + ps, ps, &allocated, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc didn't fail with bias(%x-%x), size=3D%u, ps=3D%u\n", bias_start, bias_end, bias_rem + ps, ps); =20 @@ -248,10 +248,10 @@ static void drm_test_buddy_alloc_range_bias(struct ku= nit *test) size =3D max(size, ps); =20 KUNIT_ASSERT_FALSE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start, + gpu_buddy_alloc_blocks(&mm, bias_start, bias_end, size, ps, &allocated, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc failed with bias(%x-%x), size=3D%u, ps=3D%u\n", bias_start, bias_end, size, ps); /* @@ -259,15 +259,15 @@ static void drm_test_buddy_alloc_range_bias(struct ku= nit *test) * unallocated, and ideally not always on the bias * boundaries. */ - drm_buddy_free_list(&mm, &tmp, 0); + gpu_buddy_free_list(&mm, &tmp, 0); } else { list_splice_tail(&tmp, &allocated); } } =20 kfree(order); - drm_buddy_free_list(&mm, &allocated, 0); - drm_buddy_fini(&mm); + gpu_buddy_free_list(&mm, &allocated, 0); + gpu_buddy_fini(&mm); =20 /* * Something more free-form. Idea is to pick a random starting bias @@ -278,7 +278,7 @@ static void drm_test_buddy_alloc_range_bias(struct kuni= t *test) * allocated nodes in the middle of the address space. */ =20 - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, ps), + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps), "buddy_init failed\n"); =20 bias_start =3D round_up(prandom_u32_state(&prng) % (mm_size - ps), ps); @@ -290,10 +290,10 @@ static void drm_test_buddy_alloc_range_bias(struct ku= nit *test) u32 size =3D max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps); =20 KUNIT_ASSERT_FALSE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start, + gpu_buddy_alloc_blocks(&mm, bias_start, bias_end, size, ps, &allocated, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc failed with bias(%x-%x), size=3D%u, ps=3D%u\n", bias_start, bias_end, size, ps); bias_rem -=3D size; @@ -319,24 +319,24 @@ static void drm_test_buddy_alloc_range_bias(struct ku= nit *test) KUNIT_ASSERT_EQ(test, bias_start, 0); KUNIT_ASSERT_EQ(test, bias_end, mm_size); KUNIT_ASSERT_TRUE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start, bias_end, + gpu_buddy_alloc_blocks(&mm, bias_start, bias_end, ps, ps, &allocated, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc passed with bias(%x-%x), size=3D%u\n", bias_start, bias_end, ps); =20 - drm_buddy_free_list(&mm, &allocated, 0); - drm_buddy_fini(&mm); + gpu_buddy_free_list(&mm, &allocated, 0); + gpu_buddy_fini(&mm); =20 /* - * Allocate cleared blocks in the bias range when the DRM buddy's clear a= vail is + * Allocate cleared blocks in the bias range when the GPU buddy's clear a= vail is * zero. This will validate the bias range allocation in scenarios like s= ystem boot * when no cleared blocks are available and exercise the fallback path to= o. The resulting * blocks should always be dirty. */ =20 - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, ps), + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps), "buddy_init failed\n"); =20 bias_start =3D round_up(prandom_u32_state(&prng) % (mm_size - ps), ps); @@ -344,11 +344,11 @@ static void drm_test_buddy_alloc_range_bias(struct ku= nit *test) bias_end =3D max(bias_end, bias_start + ps); bias_rem =3D bias_end - bias_start; =20 - flags =3D DRM_BUDDY_CLEAR_ALLOCATION | DRM_BUDDY_RANGE_ALLOCATION; + flags =3D GPU_BUDDY_CLEAR_ALLOCATION | GPU_BUDDY_RANGE_ALLOCATION; size =3D max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps); =20 KUNIT_ASSERT_FALSE_MSG(test, - drm_buddy_alloc_blocks(&mm, bias_start, + gpu_buddy_alloc_blocks(&mm, bias_start, bias_end, size, ps, &allocated, flags), @@ -356,27 +356,27 @@ static void drm_test_buddy_alloc_range_bias(struct ku= nit *test) bias_start, bias_end, size, ps); =20 list_for_each_entry(block, &allocated, link) - KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false); + KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), false); =20 - drm_buddy_free_list(&mm, &allocated, 0); - drm_buddy_fini(&mm); + gpu_buddy_free_list(&mm, &allocated, 0); + gpu_buddy_fini(&mm); } =20 -static void drm_test_buddy_alloc_clear(struct kunit *test) +static void gpu_test_buddy_alloc_clear(struct kunit *test) { unsigned long n_pages, total, i =3D 0; const unsigned long ps =3D SZ_4K; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; const int max_order =3D 12; LIST_HEAD(allocated); - struct drm_buddy mm; + struct gpu_buddy mm; unsigned int order; u32 mm_size, size; LIST_HEAD(dirty); LIST_HEAD(clean); =20 mm_size =3D SZ_4K << max_order; - KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps)); + KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); =20 KUNIT_EXPECT_EQ(test, mm.max_order, max_order); =20 @@ -389,11 +389,11 @@ static void drm_test_buddy_alloc_clear(struct kunit *= test) * is indeed all dirty pages and vice versa. Free it all again, * keeping the dirty/clear status. */ - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, 5 * ps, ps, &allocated, - DRM_BUDDY_TOPDOWN_ALLOCATION), + GPU_BUDDY_TOPDOWN_ALLOCATION), "buddy_alloc hit an error size=3D%lu\n", 5 * ps); - drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED); + gpu_buddy_free_list(&mm, &allocated, GPU_BUDDY_CLEARED); =20 n_pages =3D 10; do { @@ -406,37 +406,37 @@ static void drm_test_buddy_alloc_clear(struct kunit *= test) flags =3D 0; } else { list =3D &clean; - flags =3D DRM_BUDDY_CLEAR_ALLOCATION; + flags =3D GPU_BUDDY_CLEAR_ALLOCATION; } =20 - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, ps, ps, list, flags), "buddy_alloc hit an error size=3D%lu\n", ps); } while (++i < n_pages); =20 list_for_each_entry(block, &clean, link) - KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), true); + KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), true); =20 list_for_each_entry(block, &dirty, link) - KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false); + KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), false); =20 - drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED); + gpu_buddy_free_list(&mm, &clean, GPU_BUDDY_CLEARED); =20 /* * Trying to go over the clear limit for some allocation. * The allocation should never fail with reasonable page-size. */ - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, 10 * ps, ps, &clean, - DRM_BUDDY_CLEAR_ALLOCATION), + GPU_BUDDY_CLEAR_ALLOCATION), "buddy_alloc hit an error size=3D%lu\n", 10 * ps); =20 - drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED); - drm_buddy_free_list(&mm, &dirty, 0); - drm_buddy_fini(&mm); + gpu_buddy_free_list(&mm, &clean, GPU_BUDDY_CLEARED); + gpu_buddy_free_list(&mm, &dirty, 0); + gpu_buddy_fini(&mm); =20 - KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps)); + KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); =20 /* * Create a new mm. Intentionally fragment the address space by creating @@ -458,34 +458,34 @@ static void drm_test_buddy_alloc_clear(struct kunit *= test) else list =3D &clean; =20 - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, ps, ps, list, 0), "buddy_alloc hit an error size=3D%lu\n", ps); } while (++i < n_pages); =20 - drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED); - drm_buddy_free_list(&mm, &dirty, 0); + gpu_buddy_free_list(&mm, &clean, GPU_BUDDY_CLEARED); + gpu_buddy_free_list(&mm, &dirty, 0); =20 order =3D 1; do { size =3D SZ_4K << order; =20 - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, size, size, &allocated, - DRM_BUDDY_CLEAR_ALLOCATION), + GPU_BUDDY_CLEAR_ALLOCATION), "buddy_alloc hit an error size=3D%u\n", size); total =3D 0; list_for_each_entry(block, &allocated, link) { if (size !=3D mm_size) - KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false); - total +=3D drm_buddy_block_size(&mm, block); + KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), false); + total +=3D gpu_buddy_block_size(&mm, block); } KUNIT_EXPECT_EQ(test, total, size); =20 - drm_buddy_free_list(&mm, &allocated, 0); + gpu_buddy_free_list(&mm, &allocated, 0); } while (++order <=3D max_order); =20 - drm_buddy_fini(&mm); + gpu_buddy_fini(&mm); =20 /* * Create a new mm with a non power-of-two size. Allocate a random size f= rom each @@ -494,44 +494,44 @@ static void drm_test_buddy_alloc_clear(struct kunit *= test) */ mm_size =3D (SZ_4K << max_order) + (SZ_4K << (max_order - 2)); =20 - KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps)); + KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); KUNIT_EXPECT_EQ(test, mm.max_order, max_order); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, SZ_4K << max_= order, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, SZ_4K << max_= order, 4 * ps, ps, &allocated, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc hit an error size=3D%lu\n", 4 * ps); - drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, SZ_4K << max_= order, + gpu_buddy_free_list(&mm, &allocated, GPU_BUDDY_CLEARED); + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, SZ_4K << max_= order, 2 * ps, ps, &allocated, - DRM_BUDDY_CLEAR_ALLOCATION), + GPU_BUDDY_CLEAR_ALLOCATION), "buddy_alloc hit an error size=3D%lu\n", 2 * ps); - drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, SZ_4K << max_ord= er, mm_size, + gpu_buddy_free_list(&mm, &allocated, GPU_BUDDY_CLEARED); + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, SZ_4K << max_ord= er, mm_size, ps, ps, &allocated, - DRM_BUDDY_RANGE_ALLOCATION), + GPU_BUDDY_RANGE_ALLOCATION), "buddy_alloc hit an error size=3D%lu\n", ps); - drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED); - drm_buddy_fini(&mm); + gpu_buddy_free_list(&mm, &allocated, GPU_BUDDY_CLEARED); + gpu_buddy_fini(&mm); } =20 -static void drm_test_buddy_alloc_contiguous(struct kunit *test) +static void gpu_test_buddy_alloc_contiguous(struct kunit *test) { const unsigned long ps =3D SZ_4K, mm_size =3D 16 * 3 * SZ_4K; unsigned long i, n_pages, total; - struct drm_buddy_block *block; - struct drm_buddy mm; + struct gpu_buddy_block *block; + struct gpu_buddy mm; LIST_HEAD(left); LIST_HEAD(middle); LIST_HEAD(right); LIST_HEAD(allocated); =20 - KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps)); + KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps)); =20 /* * Idea is to fragment the address space by alternating block * allocations between three different lists; one for left, middle and * right. We can then free a list to simulate fragmentation. In - * particular we want to exercise the DRM_BUDDY_CONTIGUOUS_ALLOCATION, + * particular we want to exercise the GPU_BUDDY_CONTIGUOUS_ALLOCATION, * including the try_harder path. */ =20 @@ -548,66 +548,66 @@ static void drm_test_buddy_alloc_contiguous(struct ku= nit *test) else list =3D &right; KUNIT_ASSERT_FALSE_MSG(test, - drm_buddy_alloc_blocks(&mm, 0, mm_size, + gpu_buddy_alloc_blocks(&mm, 0, mm_size, ps, ps, list, 0), "buddy_alloc hit an error size=3D%lu\n", ps); } while (++i < n_pages); =20 - KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, + KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, 3 * ps, ps, &allocated, - DRM_BUDDY_CONTIGUOUS_ALLOCATION), + GPU_BUDDY_CONTIGUOUS_ALLOCATION), "buddy_alloc didn't error size=3D%lu\n", 3 * ps); =20 - drm_buddy_free_list(&mm, &middle, 0); - KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, + gpu_buddy_free_list(&mm, &middle, 0); + KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, 3 * ps, ps, &allocated, - DRM_BUDDY_CONTIGUOUS_ALLOCATION), + GPU_BUDDY_CONTIGUOUS_ALLOCATION), "buddy_alloc didn't error size=3D%lu\n", 3 * ps); - KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, + KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, 2 * ps, ps, &allocated, - DRM_BUDDY_CONTIGUOUS_ALLOCATION), + GPU_BUDDY_CONTIGUOUS_ALLOCATION), "buddy_alloc didn't error size=3D%lu\n", 2 * ps); =20 - drm_buddy_free_list(&mm, &right, 0); - KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, + gpu_buddy_free_list(&mm, &right, 0); + KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, 3 * ps, ps, &allocated, - DRM_BUDDY_CONTIGUOUS_ALLOCATION), + GPU_BUDDY_CONTIGUOUS_ALLOCATION), "buddy_alloc didn't error size=3D%lu\n", 3 * ps); /* * At this point we should have enough contiguous space for 2 blocks, * however they are never buddies (since we freed middle and right) so * will require the try_harder logic to find them. */ - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, 2 * ps, ps, &allocated, - DRM_BUDDY_CONTIGUOUS_ALLOCATION), + GPU_BUDDY_CONTIGUOUS_ALLOCATION), "buddy_alloc hit an error size=3D%lu\n", 2 * ps); =20 - drm_buddy_free_list(&mm, &left, 0); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, + gpu_buddy_free_list(&mm, &left, 0); + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, 3 * ps, ps, &allocated, - DRM_BUDDY_CONTIGUOUS_ALLOCATION), + GPU_BUDDY_CONTIGUOUS_ALLOCATION), "buddy_alloc hit an error size=3D%lu\n", 3 * ps); =20 total =3D 0; list_for_each_entry(block, &allocated, link) - total +=3D drm_buddy_block_size(&mm, block); + total +=3D gpu_buddy_block_size(&mm, block); =20 KUNIT_ASSERT_EQ(test, total, ps * 2 + ps * 3); =20 - drm_buddy_free_list(&mm, &allocated, 0); - drm_buddy_fini(&mm); + gpu_buddy_free_list(&mm, &allocated, 0); + gpu_buddy_fini(&mm); } =20 -static void drm_test_buddy_alloc_pathological(struct kunit *test) +static void gpu_test_buddy_alloc_pathological(struct kunit *test) { u64 mm_size, size, start =3D 0; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; const int max_order =3D 3; unsigned long flags =3D 0; int order, top; - struct drm_buddy mm; + struct gpu_buddy mm; LIST_HEAD(blocks); LIST_HEAD(holes); LIST_HEAD(tmp); @@ -620,7 +620,7 @@ static void drm_test_buddy_alloc_pathological(struct ku= nit *test) */ =20 mm_size =3D SZ_4K << max_order; - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, SZ_4K), + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K), "buddy_init failed\n"); =20 KUNIT_EXPECT_EQ(test, mm.max_order, max_order); @@ -630,18 +630,18 @@ static void drm_test_buddy_alloc_pathological(struct = kunit *test) block =3D list_first_entry_or_null(&blocks, typeof(*block), link); if (block) { list_del(&block->link); - drm_buddy_free_block(&mm, block); + gpu_buddy_free_block(&mm, block); } =20 for (order =3D top; order--;) { size =3D get_size(order, mm.chunk_size); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags), "buddy_alloc hit -ENOMEM with order=3D%d, top=3D%d\n", order, top); =20 - block =3D list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + block =3D list_first_entry_or_null(&tmp, struct gpu_buddy_block, link); KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); =20 list_move_tail(&block->link, &blocks); @@ -649,45 +649,45 @@ static void drm_test_buddy_alloc_pathological(struct = kunit *test) =20 /* There should be one final page for this sub-allocation */ size =3D get_size(0, mm.chunk_size); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags), "buddy_alloc hit -ENOMEM for hole\n"); =20 - block =3D list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + block =3D list_first_entry_or_null(&tmp, struct gpu_buddy_block, link); KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); =20 list_move_tail(&block->link, &holes); =20 size =3D get_size(top, mm.chunk_size); - KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags), "buddy_alloc unexpectedly succeeded at top-order %d/%d, it should= be full!", top, max_order); } =20 - drm_buddy_free_list(&mm, &holes, 0); + gpu_buddy_free_list(&mm, &holes, 0); =20 /* Nothing larger than blocks of chunk_size now available */ for (order =3D 1; order <=3D max_order; order++) { size =3D get_size(order, mm.chunk_size); - KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags), "buddy_alloc unexpectedly succeeded at order %d, it should be ful= l!", order); } =20 list_splice_tail(&holes, &blocks); - drm_buddy_free_list(&mm, &blocks, 0); - drm_buddy_fini(&mm); + gpu_buddy_free_list(&mm, &blocks, 0); + gpu_buddy_fini(&mm); } =20 -static void drm_test_buddy_alloc_pessimistic(struct kunit *test) +static void gpu_test_buddy_alloc_pessimistic(struct kunit *test) { u64 mm_size, size, start =3D 0; - struct drm_buddy_block *block, *bn; + struct gpu_buddy_block *block, *bn; const unsigned int max_order =3D 16; unsigned long flags =3D 0; - struct drm_buddy mm; + struct gpu_buddy mm; unsigned int order; LIST_HEAD(blocks); LIST_HEAD(tmp); @@ -699,19 +699,19 @@ static void drm_test_buddy_alloc_pessimistic(struct k= unit *test) */ =20 mm_size =3D SZ_4K << max_order; - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, SZ_4K), + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K), "buddy_init failed\n"); =20 KUNIT_EXPECT_EQ(test, mm.max_order, max_order); =20 for (order =3D 0; order < max_order; order++) { size =3D get_size(order, mm.chunk_size); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags), "buddy_alloc hit -ENOMEM with order=3D%d\n", order); =20 - block =3D list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + block =3D list_first_entry_or_null(&tmp, struct gpu_buddy_block, link); KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); =20 list_move_tail(&block->link, &blocks); @@ -719,11 +719,11 @@ static void drm_test_buddy_alloc_pessimistic(struct k= unit *test) =20 /* And now the last remaining block available */ size =3D get_size(0, mm.chunk_size); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags), "buddy_alloc hit -ENOMEM on final alloc\n"); =20 - block =3D list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + block =3D list_first_entry_or_null(&tmp, struct gpu_buddy_block, link); KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); =20 list_move_tail(&block->link, &blocks); @@ -731,58 +731,58 @@ static void drm_test_buddy_alloc_pessimistic(struct k= unit *test) /* Should be completely full! */ for (order =3D max_order; order--;) { size =3D get_size(order, mm.chunk_size); - KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags), "buddy_alloc unexpectedly succeeded, it should be full!"); } =20 block =3D list_last_entry(&blocks, typeof(*block), link); list_del(&block->link); - drm_buddy_free_block(&mm, block); + gpu_buddy_free_block(&mm, block); =20 /* As we free in increasing size, we make available larger blocks */ order =3D 1; list_for_each_entry_safe(block, bn, &blocks, link) { list_del(&block->link); - drm_buddy_free_block(&mm, block); + gpu_buddy_free_block(&mm, block); =20 size =3D get_size(order, mm.chunk_size); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags), "buddy_alloc hit -ENOMEM with order=3D%d\n", order); =20 - block =3D list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + block =3D list_first_entry_or_null(&tmp, struct gpu_buddy_block, link); KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); =20 list_del(&block->link); - drm_buddy_free_block(&mm, block); + gpu_buddy_free_block(&mm, block); order++; } =20 /* To confirm, now the whole mm should be available */ size =3D get_size(max_order, mm.chunk_size); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags), "buddy_alloc (realloc) hit -ENOMEM with order=3D%d\n", max_order); =20 - block =3D list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + block =3D list_first_entry_or_null(&tmp, struct gpu_buddy_block, link); KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); =20 list_del(&block->link); - drm_buddy_free_block(&mm, block); - drm_buddy_free_list(&mm, &blocks, 0); - drm_buddy_fini(&mm); + gpu_buddy_free_block(&mm, block); + gpu_buddy_free_list(&mm, &blocks, 0); + gpu_buddy_fini(&mm); } =20 -static void drm_test_buddy_alloc_optimistic(struct kunit *test) +static void gpu_test_buddy_alloc_optimistic(struct kunit *test) { u64 mm_size, size, start =3D 0; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; unsigned long flags =3D 0; const int max_order =3D 16; - struct drm_buddy mm; + struct gpu_buddy mm; LIST_HEAD(blocks); LIST_HEAD(tmp); int order; @@ -794,19 +794,19 @@ static void drm_test_buddy_alloc_optimistic(struct ku= nit *test) =20 mm_size =3D SZ_4K * ((1 << (max_order + 1)) - 1); =20 - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, SZ_4K), + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K), "buddy_init failed\n"); =20 KUNIT_EXPECT_EQ(test, mm.max_order, max_order); =20 for (order =3D 0; order <=3D max_order; order++) { size =3D get_size(order, mm.chunk_size); - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags), "buddy_alloc hit -ENOMEM with order=3D%d\n", order); =20 - block =3D list_first_entry_or_null(&tmp, struct drm_buddy_block, link); + block =3D list_first_entry_or_null(&tmp, struct gpu_buddy_block, link); KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n"); =20 list_move_tail(&block->link, &blocks); @@ -814,115 +814,115 @@ static void drm_test_buddy_alloc_optimistic(struct = kunit *test) =20 /* Should be completely full! */ size =3D get_size(0, mm.chunk_size); - KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size, + KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size, size, size, &tmp, flags), "buddy_alloc unexpectedly succeeded, it should be full!"); =20 - drm_buddy_free_list(&mm, &blocks, 0); - drm_buddy_fini(&mm); + gpu_buddy_free_list(&mm, &blocks, 0); + gpu_buddy_fini(&mm); } =20 -static void drm_test_buddy_alloc_limit(struct kunit *test) +static void gpu_test_buddy_alloc_limit(struct kunit *test) { u64 size =3D U64_MAX, start =3D 0; - struct drm_buddy_block *block; + struct gpu_buddy_block *block; unsigned long flags =3D 0; LIST_HEAD(allocated); - struct drm_buddy mm; + struct gpu_buddy mm; =20 - KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, size, SZ_4K)); + KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, size, SZ_4K)); =20 - KUNIT_EXPECT_EQ_MSG(test, mm.max_order, DRM_BUDDY_MAX_ORDER, + KUNIT_EXPECT_EQ_MSG(test, mm.max_order, GPU_BUDDY_MAX_ORDER, "mm.max_order(%d) !=3D %d\n", mm.max_order, - DRM_BUDDY_MAX_ORDER); + GPU_BUDDY_MAX_ORDER); =20 size =3D mm.chunk_size << mm.max_order; - KUNIT_EXPECT_FALSE(test, drm_buddy_alloc_blocks(&mm, start, size, size, + KUNIT_EXPECT_FALSE(test, gpu_buddy_alloc_blocks(&mm, start, size, size, mm.chunk_size, &allocated, flags)); =20 - block =3D list_first_entry_or_null(&allocated, struct drm_buddy_block, li= nk); + block =3D list_first_entry_or_null(&allocated, struct gpu_buddy_block, li= nk); KUNIT_EXPECT_TRUE(test, block); =20 - KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_order(block), mm.max_order, + KUNIT_EXPECT_EQ_MSG(test, gpu_buddy_block_order(block), mm.max_order, "block order(%d) !=3D %d\n", - drm_buddy_block_order(block), mm.max_order); + gpu_buddy_block_order(block), mm.max_order); =20 - KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_size(&mm, block), + KUNIT_EXPECT_EQ_MSG(test, gpu_buddy_block_size(&mm, block), BIT_ULL(mm.max_order) * mm.chunk_size, "block size(%llu) !=3D %llu\n", - drm_buddy_block_size(&mm, block), + gpu_buddy_block_size(&mm, block), BIT_ULL(mm.max_order) * mm.chunk_size); =20 - drm_buddy_free_list(&mm, &allocated, 0); - drm_buddy_fini(&mm); + gpu_buddy_free_list(&mm, &allocated, 0); + gpu_buddy_fini(&mm); } =20 -static void drm_test_buddy_alloc_exceeds_max_order(struct kunit *test) +static void gpu_test_buddy_alloc_exceeds_max_order(struct kunit *test) { u64 mm_size =3D SZ_8G + SZ_2G, size =3D SZ_8G + SZ_1G, min_block_size =3D= SZ_8G; - struct drm_buddy mm; + struct gpu_buddy mm; LIST_HEAD(blocks); int err; =20 - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, SZ_4K), + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K), "buddy_init failed\n"); =20 /* CONTIGUOUS allocation should succeed via try_harder fallback */ - KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size, size, + KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size, size, SZ_4K, &blocks, - DRM_BUDDY_CONTIGUOUS_ALLOCATION), + GPU_BUDDY_CONTIGUOUS_ALLOCATION), "buddy_alloc hit an error size=3D%llu\n", size); - drm_buddy_free_list(&mm, &blocks, 0); + gpu_buddy_free_list(&mm, &blocks, 0); =20 /* Non-CONTIGUOUS with large min_block_size should return -EINVAL */ - err =3D drm_buddy_alloc_blocks(&mm, 0, mm_size, size, min_block_size, &bl= ocks, 0); + err =3D gpu_buddy_alloc_blocks(&mm, 0, mm_size, size, min_block_size, &bl= ocks, 0); KUNIT_EXPECT_EQ(test, err, -EINVAL); =20 /* Non-CONTIGUOUS + RANGE with large min_block_size should return -EINVAL= */ - err =3D drm_buddy_alloc_blocks(&mm, 0, mm_size, size, min_block_size, &bl= ocks, - DRM_BUDDY_RANGE_ALLOCATION); + err =3D gpu_buddy_alloc_blocks(&mm, 0, mm_size, size, min_block_size, &bl= ocks, + GPU_BUDDY_RANGE_ALLOCATION); KUNIT_EXPECT_EQ(test, err, -EINVAL); =20 /* CONTIGUOUS + RANGE should return -EINVAL (no try_harder for RANGE) */ - err =3D drm_buddy_alloc_blocks(&mm, 0, mm_size, size, SZ_4K, &blocks, - DRM_BUDDY_CONTIGUOUS_ALLOCATION | DRM_BUDDY_RANGE_ALLOCATION); + err =3D gpu_buddy_alloc_blocks(&mm, 0, mm_size, size, SZ_4K, &blocks, + GPU_BUDDY_CONTIGUOUS_ALLOCATION | GPU_BUDDY_RANGE_ALLOCATION); KUNIT_EXPECT_EQ(test, err, -EINVAL); =20 - drm_buddy_fini(&mm); + gpu_buddy_fini(&mm); } =20 -static int drm_buddy_suite_init(struct kunit_suite *suite) +static int gpu_buddy_suite_init(struct kunit_suite *suite) { while (!random_seed) random_seed =3D get_random_u32(); =20 - kunit_info(suite, "Testing DRM buddy manager, with random_seed=3D0x%x\n", + kunit_info(suite, "Testing GPU buddy manager, with random_seed=3D0x%x\n", random_seed); =20 return 0; } =20 -static struct kunit_case drm_buddy_tests[] =3D { - KUNIT_CASE(drm_test_buddy_alloc_limit), - KUNIT_CASE(drm_test_buddy_alloc_optimistic), - KUNIT_CASE(drm_test_buddy_alloc_pessimistic), - KUNIT_CASE(drm_test_buddy_alloc_pathological), - KUNIT_CASE(drm_test_buddy_alloc_contiguous), - KUNIT_CASE(drm_test_buddy_alloc_clear), - KUNIT_CASE(drm_test_buddy_alloc_range_bias), - KUNIT_CASE(drm_test_buddy_fragmentation_performance), - KUNIT_CASE(drm_test_buddy_alloc_exceeds_max_order), +static struct kunit_case gpu_buddy_tests[] =3D { + KUNIT_CASE(gpu_test_buddy_alloc_limit), + KUNIT_CASE(gpu_test_buddy_alloc_optimistic), + KUNIT_CASE(gpu_test_buddy_alloc_pessimistic), + KUNIT_CASE(gpu_test_buddy_alloc_pathological), + KUNIT_CASE(gpu_test_buddy_alloc_contiguous), + KUNIT_CASE(gpu_test_buddy_alloc_clear), + KUNIT_CASE(gpu_test_buddy_alloc_range_bias), + KUNIT_CASE(gpu_test_buddy_fragmentation_performance), + KUNIT_CASE(gpu_test_buddy_alloc_exceeds_max_order), {} }; =20 -static struct kunit_suite drm_buddy_test_suite =3D { - .name =3D "drm_buddy", - .suite_init =3D drm_buddy_suite_init, - .test_cases =3D drm_buddy_tests, +static struct kunit_suite gpu_buddy_test_suite =3D { + .name =3D "gpu_buddy", + .suite_init =3D gpu_buddy_suite_init, + .test_cases =3D gpu_buddy_tests, }; =20 -kunit_test_suite(drm_buddy_test_suite); +kunit_test_suite(gpu_buddy_test_suite); =20 MODULE_AUTHOR("Intel Corporation"); -MODULE_DESCRIPTION("Kunit test for drm_buddy functions"); +MODULE_DESCRIPTION("Kunit test for gpu_buddy functions"); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/tests/gpu_random.c b/drivers/gpu/tests/gpu_random.c index ddd1f594b5d5..6356372f7e52 100644 --- a/drivers/gpu/tests/gpu_random.c +++ b/drivers/gpu/tests/gpu_random.c @@ -8,26 +8,26 @@ =20 #include "gpu_random.h" =20 -u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state) +u32 gpu_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state) { return upper_32_bits((u64)prandom_u32_state(state) * ep_ro); } -EXPORT_SYMBOL(drm_prandom_u32_max_state); +EXPORT_SYMBOL(gpu_prandom_u32_max_state); =20 -void drm_random_reorder(unsigned int *order, unsigned int count, +void gpu_random_reorder(unsigned int *order, unsigned int count, struct rnd_state *state) { unsigned int i, j; =20 for (i =3D 0; i < count; ++i) { BUILD_BUG_ON(sizeof(unsigned int) > sizeof(u32)); - j =3D drm_prandom_u32_max_state(count, state); + j =3D gpu_prandom_u32_max_state(count, state); swap(order[i], order[j]); } } -EXPORT_SYMBOL(drm_random_reorder); +EXPORT_SYMBOL(gpu_random_reorder); =20 -unsigned int *drm_random_order(unsigned int count, struct rnd_state *state) +unsigned int *gpu_random_order(unsigned int count, struct rnd_state *state) { unsigned int *order, i; =20 @@ -38,7 +38,7 @@ unsigned int *drm_random_order(unsigned int count, struct= rnd_state *state) for (i =3D 0; i < count; i++) order[i] =3D i; =20 - drm_random_reorder(order, count, state); + gpu_random_reorder(order, count, state); return order; } -EXPORT_SYMBOL(drm_random_order); +EXPORT_SYMBOL(gpu_random_order); diff --git a/drivers/gpu/tests/gpu_random.h b/drivers/gpu/tests/gpu_random.h index 9f827260a89d..b68cf3448264 100644 --- a/drivers/gpu/tests/gpu_random.h +++ b/drivers/gpu/tests/gpu_random.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __DRM_RANDOM_H__ -#define __DRM_RANDOM_H__ +#ifndef __GPU_RANDOM_H__ +#define __GPU_RANDOM_H__ =20 /* This is a temporary home for a couple of utility functions that should * be transposed to lib/ at the earliest convenience. @@ -8,21 +8,21 @@ =20 #include =20 -#define DRM_RND_STATE_INITIALIZER(seed__) ({ \ +#define GPU_RND_STATE_INITIALIZER(seed__) ({ \ struct rnd_state state__; \ prandom_seed_state(&state__, (seed__)); \ state__; \ }) =20 -#define DRM_RND_STATE(name__, seed__) \ - struct rnd_state name__ =3D DRM_RND_STATE_INITIALIZER(seed__) +#define GPU_RND_STATE(name__, seed__) \ + struct rnd_state name__ =3D GPU_RND_STATE_INITIALIZER(seed__) =20 -unsigned int *drm_random_order(unsigned int count, +unsigned int *gpu_random_order(unsigned int count, struct rnd_state *state); -void drm_random_reorder(unsigned int *order, +void gpu_random_reorder(unsigned int *order, unsigned int count, struct rnd_state *state); -u32 drm_prandom_u32_max_state(u32 ep_ro, +u32 gpu_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state); =20 -#endif /* !__DRM_RANDOM_H__ */ +#endif /* !__GPU_RANDOM_H__ */ diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 9884f003247d..a7144d275f54 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -37,6 +37,7 @@ source "drivers/char/agp/Kconfig" =20 source "drivers/gpu/vga/Kconfig" =20 +source "drivers/gpu/Kconfig" source "drivers/gpu/host1x/Kconfig" source "drivers/gpu/ipu-v3/Kconfig" source "drivers/gpu/nova-core/Kconfig" diff --git a/include/drm/drm_buddy.h b/include/drm/drm_buddy.h new file mode 100644 index 000000000000..3054369bebff --- /dev/null +++ b/include/drm/drm_buddy.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright =C2=A9 2021 Intel Corporation + */ + +#ifndef __DRM_BUDDY_H__ +#define __DRM_BUDDY_H__ + +#include + +struct drm_printer; + +/* DRM-specific GPU Buddy Allocator print helpers */ +void drm_buddy_print(struct gpu_buddy *mm, struct drm_printer *p); +void drm_buddy_block_print(struct gpu_buddy *mm, + struct gpu_buddy_block *block, + struct drm_printer *p); +#endif diff --git a/include/linux/gpu_buddy.h b/include/linux/gpu_buddy.h index b909fa8f810a..07ac65db6d2e 100644 --- a/include/linux/gpu_buddy.h +++ b/include/linux/gpu_buddy.h @@ -3,8 +3,8 @@ * Copyright =C2=A9 2021 Intel Corporation */ =20 -#ifndef __DRM_BUDDY_H__ -#define __DRM_BUDDY_H__ +#ifndef __GPU_BUDDY_H__ +#define __GPU_BUDDY_H__ =20 #include #include @@ -12,38 +12,45 @@ #include #include =20 -struct drm_printer; +#define GPU_BUDDY_RANGE_ALLOCATION BIT(0) +#define GPU_BUDDY_TOPDOWN_ALLOCATION BIT(1) +#define GPU_BUDDY_CONTIGUOUS_ALLOCATION BIT(2) +#define GPU_BUDDY_CLEAR_ALLOCATION BIT(3) +#define GPU_BUDDY_CLEARED BIT(4) +#define GPU_BUDDY_TRIM_DISABLE BIT(5) =20 -#define DRM_BUDDY_RANGE_ALLOCATION BIT(0) -#define DRM_BUDDY_TOPDOWN_ALLOCATION BIT(1) -#define DRM_BUDDY_CONTIGUOUS_ALLOCATION BIT(2) -#define DRM_BUDDY_CLEAR_ALLOCATION BIT(3) -#define DRM_BUDDY_CLEARED BIT(4) -#define DRM_BUDDY_TRIM_DISABLE BIT(5) +enum gpu_buddy_free_tree { + GPU_BUDDY_CLEAR_TREE =3D 0, + GPU_BUDDY_DIRTY_TREE, + GPU_BUDDY_MAX_FREE_TREES, +}; =20 -struct drm_buddy_block { -#define DRM_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12) -#define DRM_BUDDY_HEADER_STATE GENMASK_ULL(11, 10) -#define DRM_BUDDY_ALLOCATED (1 << 10) -#define DRM_BUDDY_FREE (2 << 10) -#define DRM_BUDDY_SPLIT (3 << 10) -#define DRM_BUDDY_HEADER_CLEAR GENMASK_ULL(9, 9) +#define for_each_free_tree(tree) \ + for ((tree) =3D 0; (tree) < GPU_BUDDY_MAX_FREE_TREES; (tree)++) + +struct gpu_buddy_block { +#define GPU_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12) +#define GPU_BUDDY_HEADER_STATE GENMASK_ULL(11, 10) +#define GPU_BUDDY_ALLOCATED (1 << 10) +#define GPU_BUDDY_FREE (2 << 10) +#define GPU_BUDDY_SPLIT (3 << 10) +#define GPU_BUDDY_HEADER_CLEAR GENMASK_ULL(9, 9) /* Free to be used, if needed in the future */ -#define DRM_BUDDY_HEADER_UNUSED GENMASK_ULL(8, 6) -#define DRM_BUDDY_HEADER_ORDER GENMASK_ULL(5, 0) +#define GPU_BUDDY_HEADER_UNUSED GENMASK_ULL(8, 6) +#define GPU_BUDDY_HEADER_ORDER GENMASK_ULL(5, 0) u64 header; =20 - struct drm_buddy_block *left; - struct drm_buddy_block *right; - struct drm_buddy_block *parent; + struct gpu_buddy_block *left; + struct gpu_buddy_block *right; + struct gpu_buddy_block *parent; =20 void *private; /* owned by creator */ =20 /* - * While the block is allocated by the user through drm_buddy_alloc*, + * While the block is allocated by the user through gpu_buddy_alloc*, * the user has ownership of the link, for example to maintain within * a list, if so desired. As soon as the block is freed with - * drm_buddy_free* ownership is given back to the mm. + * gpu_buddy_free* ownership is given back to the mm. */ union { struct rb_node rb; @@ -54,15 +61,15 @@ struct drm_buddy_block { }; =20 /* Order-zero must be at least SZ_4K */ -#define DRM_BUDDY_MAX_ORDER (63 - 12) +#define GPU_BUDDY_MAX_ORDER (63 - 12) =20 /* * Binary Buddy System. * * Locking should be handled by the user, a simple mutex around - * drm_buddy_alloc* and drm_buddy_free* should suffice. + * gpu_buddy_alloc* and gpu_buddy_free* should suffice. */ -struct drm_buddy { +struct gpu_buddy { /* Maintain a free list for each order. */ struct rb_root **free_trees; =20 @@ -73,7 +80,7 @@ struct drm_buddy { * block. Nodes are either allocated or free, in which case they will * also exist on the respective free list. */ - struct drm_buddy_block **roots; + struct gpu_buddy_block **roots; =20 /* * Anything from here is public, and remains static for the lifetime of @@ -90,82 +97,81 @@ struct drm_buddy { }; =20 static inline u64 -drm_buddy_block_offset(const struct drm_buddy_block *block) +gpu_buddy_block_offset(const struct gpu_buddy_block *block) { - return block->header & DRM_BUDDY_HEADER_OFFSET; + return block->header & GPU_BUDDY_HEADER_OFFSET; } =20 static inline unsigned int -drm_buddy_block_order(struct drm_buddy_block *block) +gpu_buddy_block_order(struct gpu_buddy_block *block) { - return block->header & DRM_BUDDY_HEADER_ORDER; + return block->header & GPU_BUDDY_HEADER_ORDER; } =20 static inline unsigned int -drm_buddy_block_state(struct drm_buddy_block *block) +gpu_buddy_block_state(struct gpu_buddy_block *block) { - return block->header & DRM_BUDDY_HEADER_STATE; + return block->header & GPU_BUDDY_HEADER_STATE; } =20 static inline bool -drm_buddy_block_is_allocated(struct drm_buddy_block *block) +gpu_buddy_block_is_allocated(struct gpu_buddy_block *block) { - return drm_buddy_block_state(block) =3D=3D DRM_BUDDY_ALLOCATED; + return gpu_buddy_block_state(block) =3D=3D GPU_BUDDY_ALLOCATED; } =20 static inline bool -drm_buddy_block_is_clear(struct drm_buddy_block *block) +gpu_buddy_block_is_clear(struct gpu_buddy_block *block) { - return block->header & DRM_BUDDY_HEADER_CLEAR; + return block->header & GPU_BUDDY_HEADER_CLEAR; } =20 static inline bool -drm_buddy_block_is_free(struct drm_buddy_block *block) +gpu_buddy_block_is_free(struct gpu_buddy_block *block) { - return drm_buddy_block_state(block) =3D=3D DRM_BUDDY_FREE; + return gpu_buddy_block_state(block) =3D=3D GPU_BUDDY_FREE; } =20 static inline bool -drm_buddy_block_is_split(struct drm_buddy_block *block) +gpu_buddy_block_is_split(struct gpu_buddy_block *block) { - return drm_buddy_block_state(block) =3D=3D DRM_BUDDY_SPLIT; + return gpu_buddy_block_state(block) =3D=3D GPU_BUDDY_SPLIT; } =20 static inline u64 -drm_buddy_block_size(struct drm_buddy *mm, - struct drm_buddy_block *block) +gpu_buddy_block_size(struct gpu_buddy *mm, + struct gpu_buddy_block *block) { - return mm->chunk_size << drm_buddy_block_order(block); + return mm->chunk_size << gpu_buddy_block_order(block); } =20 -int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size); +int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size); =20 -void drm_buddy_fini(struct drm_buddy *mm); +void gpu_buddy_fini(struct gpu_buddy *mm); =20 -struct drm_buddy_block * -drm_get_buddy(struct drm_buddy_block *block); +struct gpu_buddy_block * +gpu_get_buddy(struct gpu_buddy_block *block); =20 -int drm_buddy_alloc_blocks(struct drm_buddy *mm, +int gpu_buddy_alloc_blocks(struct gpu_buddy *mm, u64 start, u64 end, u64 size, u64 min_page_size, struct list_head *blocks, unsigned long flags); =20 -int drm_buddy_block_trim(struct drm_buddy *mm, +int gpu_buddy_block_trim(struct gpu_buddy *mm, u64 *start, u64 new_size, struct list_head *blocks); =20 -void drm_buddy_reset_clear(struct drm_buddy *mm, bool is_clear); +void gpu_buddy_reset_clear(struct gpu_buddy *mm, bool is_clear); =20 -void drm_buddy_free_block(struct drm_buddy *mm, struct drm_buddy_block *bl= ock); +void gpu_buddy_free_block(struct gpu_buddy *mm, struct gpu_buddy_block *bl= ock); =20 -void drm_buddy_free_list(struct drm_buddy *mm, +void gpu_buddy_free_list(struct gpu_buddy *mm, struct list_head *objects, unsigned int flags); =20 -void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p); -void drm_buddy_block_print(struct drm_buddy *mm, - struct drm_buddy_block *block, - struct drm_printer *p); +void gpu_buddy_print(struct gpu_buddy *mm); +void gpu_buddy_block_print(struct gpu_buddy *mm, + struct gpu_buddy_block *block); #endif --=20 2.34.1 From nobody Fri Apr 17 00:17:58 2026 Received: from PH0PR06CU001.outbound.protection.outlook.com (mail-westus3azon11011043.outbound.protection.outlook.com [40.107.208.43]) (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 AD5D434D926; Tue, 24 Feb 2026 22:40:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.208.43 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771972826; cv=fail; b=qjxEdgbi0m55omfcn+T0ouvpGMBdpjqCieH28OZLiBtUNk3vuH2Tryh2flp6jDmMfCoZxAgulcCHplKoedFvIbYkoOv5iVLGJG7bePt9oFXFviMNDdrXHCTT+oJ/Pwd4zhrVFUXxMJUTw97RJxKogdG+yL3RQzzpoZXmW/0TXR4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771972826; c=relaxed/simple; bh=Iy7JOK0473ePqm4pIdSs00BytrGzbj7Hu3jTXxOt5KE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=X8pIK+OVdlBiHjae8lEzAfgTceTqwDpwL82UDPijoUqqVfy4fKowQkssJCh8RkDyKCyl/TU7kK1PfRmXzuBx3rySz6qVr+7ZSSF9sr07nn1J82WbMvUrBstCh8WK4Y3wZ3+xA133D8doD1vqlwyv6g+2huB9UFI+29q//xPTT8w= 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=kbE+/ZuA; arc=fail smtp.client-ip=40.107.208.43 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="kbE+/ZuA" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=av73kToyu84kQm20pbQvE08Rzx1oO0LBeq66hGSJ9F1Ng2ET5zMrmI5FV7Rmw9ylILY5+jDaGCRvATL+UM4Sxca2yobYom+fh3RkMd8Y31h4bwoC7uBy5qPAPJlrNEYX5b7N1bwHJLBvuQSu/oAMUEuRTkOFcM6ZjYB6/67qRav4rdAyzfvNN+sNfTq7AT9hBhg/wEPOyQYbya6FQwE1u5qpKukYC7HCAw8q1+BTzLOO4y4WYXwncPU2G0F7m6X1Z/lUaysl1oGVl0eMRbqUB0m1153pc2z55L0apUYcmcDgAs1dHN2ZJHCMA8TG6td9tdpiX/vnyYC2mkME5p+z4A== 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=+R3GxUR30Ce901aqBipSHAbEEdeQtCV+u/rZ5Kf5P0o=; b=qbV0/8Q6lE2ddctuG2be8jv1bDlF/n6CGKSkupqn/aE4Ks5YE/7zzrQutRcXv66VFiGd7vXxPlgfSZUQEyiF3F5ITMAxuLcFi2KBCx0XP6ze2TgpSM08qN+wzMeJMYyHl9QHTLyTUGGUiBiW2yA84vRu/cQtxWu1SR4C0TRmpSKvy0Si/e27WWTwWe+G2lxbtmZr2kvAJYm1epyt0nG3DkfQLNL82qqLEUMHBW1/bry73dxgfPV+Hn26hW5GYT+0oF4HolRa/mVXqXkVpBsMBLGGHn0VAbsm5l21mdxDJf18rVWOU7p5NnCcU27yc0r9ZWwpJXJn8TIZB4kXlUjf7w== 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=+R3GxUR30Ce901aqBipSHAbEEdeQtCV+u/rZ5Kf5P0o=; b=kbE+/ZuAN8mE+DRBeI1EjQSwjB+dI/sx4DlXDVcqkn84Oh0Ng9pSMpQgD4Hm4+mLRzR0+cqbAWA811vgjcXfoa+nDYKY84s61QVI+V5MdlmqtnfTAfybHbZd6zBhF/XyGEqhcAIAxA5Y95PNoVwZxM7aXoaxKonD/GnqiGmtxU17JNOF0acNqDTzSzz/VKDsCe/+x7CQW5BE27XxUsklBrOLfY5Ie5uqHpwtmE7GByw6Php7FErYzzTlehMqWI0/GybNSL85PZzN7gi+cXQYJTE6Eld29dICWl3nhmwBtRrjYQS88zxUVvNyHghtuJTXDp48IrJeEP1OlAAavXOTIg== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from DS0PR12MB6486.namprd12.prod.outlook.com (2603:10b6:8:c5::21) by PH0PR12MB7816.namprd12.prod.outlook.com (2603:10b6:510:28c::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 22:40:17 +0000 Received: from DS0PR12MB6486.namprd12.prod.outlook.com ([fe80::88a9:f314:c95f:8b33]) by DS0PR12MB6486.namprd12.prod.outlook.com ([fe80::88a9:f314:c95f:8b33%4]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 22:40:16 +0000 From: Joel Fernandes To: linux-kernel@vger.kernel.org Cc: Miguel Ojeda , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Dave Airlie , Daniel Almeida , Koen Koning , dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, rust-for-linux@vger.kernel.org, Nikola Djukic , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jonathan Corbet , Alex Deucher , =?UTF-8?q?Christian=20K=C3=B6nig?= , Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , Huang Rui , Matthew Auld , Matthew Brost , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Helge Deller , Alex Gaynor , Boqun Feng , John Hubbard , Alistair Popple , Timur Tabi , Edwin Peer , Alexandre Courbot , Andrea Righi , Andy Ritger , Zhi Wang , Balbir Singh , Philipp Stanner , Elle Rhumsaa , alexeyi@nvidia.com, Eliot Courtney , joel@joelfernandes.org, linux-doc@vger.kernel.org, amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org, linux-fbdev@vger.kernel.org, Joel Fernandes , Peter Senna Tschudin Subject: [reference PATCH v11 3/4] gpu: Fix uninitialized buddy for built-in drivers Date: Tue, 24 Feb 2026 17:40:04 -0500 Message-Id: <20260224224005.3232841-4-joelagnelf@nvidia.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260224224005.3232841-1-joelagnelf@nvidia.com> References: <20260224224005.3232841-1-joelagnelf@nvidia.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: MN2PR13CA0005.namprd13.prod.outlook.com (2603:10b6:208:160::18) To DS0PR12MB6486.namprd12.prod.outlook.com (2603:10b6:8:c5::21) 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: DS0PR12MB6486:EE_|PH0PR12MB7816:EE_ X-MS-Office365-Filtering-Correlation-Id: ef25ae00-3dd0-4cad-c2a0-08de73f5ae97 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|7416014|376014|366016; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?0BWWCafMok3BxXGmM16kBo+ZoS1qdcacIZfuJBEqsnayez9Cz6YhtqBEmnBR?= =?us-ascii?Q?Ny9O5ua7Jz1/iQu/zNp9lLlbTBcEaJgY33E/4E7zOR518zW1Dijn0joBOaqP?= =?us-ascii?Q?ZQZf4L1pbBSI/ONwZ//2oYBFxhc1hzGJ3H3taDyKoaUTuh9d4n83YIhfE3Dd?= =?us-ascii?Q?Dqnv/pU7hBfz0DDJQwf6r0hLzzz76R7iPPKe7AKsR5YHSktppgk+idZl1bjO?= =?us-ascii?Q?E3HeJ+gBHg/2n5fCepsKQxhvWucPIdmACLOL7Muq1Po4yIRrC7Y5ftkrlVrx?= =?us-ascii?Q?WxJbauvIGpwptZ7Z9+C94Pexws2Pth1ihFmO88FvreWNsqf2gsylNNEKkLq8?= =?us-ascii?Q?Jqr8A4BO5oz2lxl/gKusufs4yWwjrLaRGOyBZXi49GgQq6kz9CmEDg4aC5T7?= =?us-ascii?Q?eghg1PXX7Pdu2kT4lf1stv04GfBfMwcxsBye2rRDSUghHvmtyO0730b423D4?= =?us-ascii?Q?l5IUOmpXbY7CJyoWmG0jj1nsdkkiwepm5SQFXKbKW8LpyGgyhBGrSiIx6Y7C?= =?us-ascii?Q?AVOoahhhVa+9SzsI04sj9rAU1lNw5zsL7bUSJXQBXDxcL8ok5KFs1dLnf3wy?= =?us-ascii?Q?m6aLikOOJrO7tZN/8zxP6GYZLILM8CL+GA6GqZFtBcbmrZuuh3GRTnrPYxoU?= =?us-ascii?Q?EAjGJUBYbuGEgPSxVLwoJq5cSshAmFmMnzdVqB0fZJTty8tZDVPKsBxrTmvY?= =?us-ascii?Q?+s1Hx2gkgMv/NP9jnduIXyJTbeuuvTzUYnAdPvb1zFP6iLO374kzSYDL9OAN?= =?us-ascii?Q?4EP0GhtcCrI0JlkQCvZTVYplbixdbjaXlVEYfSsoGiHzZTeM16S0XoRWbTjf?= =?us-ascii?Q?FxA0cixhJaAH2jgijYS4wCmsHA7Mo+nGfsdUv5mjKCkztOJpNNrStmUMYwCN?= =?us-ascii?Q?YDdFyHbTCJOu+di7ePxdaeTT48PMtYVPixoYeuhM3tY0jSBrDLNwrCiX+AJ0?= =?us-ascii?Q?xQuc90TLXte0HwJz+X62loguvIbCiyeK2RKiIQt89tpzFQcF2HprIHfhlON0?= =?us-ascii?Q?zBP6wAobwx30gcFtecg8pzCcABlWCVh3vD3BdmLbpiYHMblPE/kpxBmq3izB?= =?us-ascii?Q?v8dX8oC1SqhaNtE/3Nf1Vt+Y0ilyZlsRk5HUp0dMxH++OwhhTZm8Kiblawt1?= =?us-ascii?Q?QBSl0xniNHlIJK6JadjRv+Wc2vAk5cD5w7nwxvbJbkcqF5gvnbphjoxqp+kr?= =?us-ascii?Q?aYTzrfYp0bo8W3Twgap6z89u/OCrFS30iPUyksYu4WEWAC5nU7pxdSgwCS/4?= =?us-ascii?Q?n4eDO+Sv6fBRYiVmhNrAFb0g9A1fSLdlUCcHBt7lcT1G7CR35LA3h/mySKOb?= =?us-ascii?Q?5xAezPEJ9FNhe7d8BTYtxwyk8T+TUhEH0xQZGiFiUr7b5iOtAOfBWqMbSJq4?= =?us-ascii?Q?BsF7o4rEXrOoS4pOq47PNZymqfKRxvtAwafp4XRTX5QwMtEFT2aT3s8TNRJT?= =?us-ascii?Q?FFK65ayzkQGNaBtqG/oHpz/n5LRSeTtpZ5wP1Lcdu2Pk/ej4ic11a7i//cwW?= =?us-ascii?Q?Si5UzJtiobPGksgJhRKkSsqtioCOFyY6yzqvq5/QsbNzYtLbX5W88p80OcNJ?= =?us-ascii?Q?YDIJ6wsEHidDkI4T9to=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DS0PR12MB6486.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(7416014)(376014)(366016);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?BZ7CImkMdbC2oH4qBoiMCBeEbmmdYe/VNPGuUSHIFpU+kCP3MWmp0ODMcdit?= =?us-ascii?Q?3CooMJwQgPr1Tq/76hSljsv6suw6JDaSEQhuP4KEIRufemRV8a/0x2QBvCs6?= =?us-ascii?Q?TR+rBXebZssyLZ1W+ypGlFQAQu5+ub+biQESMVxgjIGvnIIcAmgt/6ebfHL4?= =?us-ascii?Q?UKbOtvZ0ZcsH3rbq6Ra7rZmyj08Sf3qaJlrU21HZ7RLqZi00EMLMyvIhuVaa?= =?us-ascii?Q?8HIZAU1Gpt4wnTV4yi6syejr33yHm7EOrZUogdqY80H+yCuDe9Nb1Hnmf41d?= =?us-ascii?Q?DgSviqP9wjQYNEULLEid8fsBEmlAd9AIAwXSvb+NYnWXFMANWKhP4JI4hB+g?= =?us-ascii?Q?sqmIn6b8c9QKDNJtuFgaYRw3aMoYXp35aiT2O3rU/k+8jiDnxk4l8OcI1ylQ?= =?us-ascii?Q?cc3GGRgy79Jox3ooMgfsQXCPLka+RWd7fFmbPaj+tj3S8LqliaEGmdbJcEXA?= =?us-ascii?Q?Kq1fkxreoIHXsdVxnvSkk6N4JPNuAgzJFD8qoMUVil7rZUUhum64PisguLI1?= =?us-ascii?Q?xBsIzuRUwUR7NtmWkgPVcF4daIuSzpRdjKgcmZFXHAwmEjNC/XTouQGhPHLv?= =?us-ascii?Q?Gsi1BVxg/YVY0Aac9UhsS2ygFUI6LO/QcdKUdBLoY3nVKQFlCzyvgu0bOtYN?= =?us-ascii?Q?ELaQa39frJ6G98ia2q3r9cBQoNAf0pCL3aQ7eVWvgN/gCY7taGLVoDnqWKgd?= =?us-ascii?Q?DnjORVzqvEzPFAMxIqVnmyX1Mtsh+wqRm9zqgeLYP9IDJJhysPyHmMx+NOtE?= =?us-ascii?Q?36GSASHWP0Co9Ae+zRFqbjpi+5IY9zcwO2GLH5TPex3Qopn4tEJjw8c/bxtG?= =?us-ascii?Q?/V4DRkWrHjgF1FDzaAMxIS7R256RIM1eWwb24ckluetKEgcdauCkjEZp++Jy?= =?us-ascii?Q?UvQ3U0SIZsZlw3NS/RsUFDQNXQEENj1UFNfuWxaWmiMjxsieKXZVLGb7ErK5?= =?us-ascii?Q?MnCvqzEKzeQPGMNUXJaqfhlDPBUKLsB00lEfS7GKtYol32zzQbFrrQG068zY?= =?us-ascii?Q?HUDV0oOpSEtM1SVr0PDsBCjeGa6QVhiu9ti/EhMeup/qnbJzbUhFgi0iOFp1?= =?us-ascii?Q?UWu0MqU+uv83wesgD3A9lrbCVC/wEvIhF/gzYGfQ6xml8W15290FPFQbf1QK?= =?us-ascii?Q?obb7XurwybUAJH1BLbA/uosoHQWwVnaN5xYzAS8fKFmX3EzAfp8fTeQAuAo+?= =?us-ascii?Q?nc0ZEFnnyD+4ymMmZ7CPpR8+qRugeppPsL3PtCyd5M7O6Ap4DkHKbrvwIhJL?= =?us-ascii?Q?FR3P4j7BSPUUTImeOViWSFXsVe4zsXR8/+bEUuFJZ9TZ0vu68iapeBPKRt9f?= =?us-ascii?Q?RFzYxeBGqU3QAsPpC7JWWH+8Q9lkywDWTDXYgdCR2sWjk0/VzxIBLchIf7ZU?= =?us-ascii?Q?rLK1X7rRex+MOZMqu/JVqOdh1PF6cr+oB547paxlsBPB6jXc98OPMPlf7bzg?= =?us-ascii?Q?wMCpRoeCE4L8CQ32XoP/4wuSQDhzE6jXxYsLsXPZ3aab/+wwSjAFg1+S5fJc?= =?us-ascii?Q?qYcY/DwqwAbjAIWh1odMBOh5rOjRickX3yZ6WsDTWboPc2WfHnPkpMnaayq7?= =?us-ascii?Q?wmwlN4Uo/6mGAYMdP2V/TdQLv46Ilwn9V12GM8c5MnuCL+XjZHf4okvDL8jk?= =?us-ascii?Q?MB64kfM2qVGcSB4ZRGdSRo0J8hRr02LpvHRy2HqLJqbh9FAqEKqJb10b33TT?= =?us-ascii?Q?LGWgZggeio1klYS1cQEEjjzel3zUECS7Sk7alSsI5um90OPAj4YfeYs9Hjt+?= =?us-ascii?Q?MOotaPyjFQ=3D=3D?= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: ef25ae00-3dd0-4cad-c2a0-08de73f5ae97 X-MS-Exchange-CrossTenant-AuthSource: DS0PR12MB6486.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 22:40:16.8243 (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: y2jjbDrTm3m3PnWN9A1A0adozSHnb060RN3CnvWu+RePo812+tOUpegxYuM9+hQzV19D9Md0TsQAuHQ8+wxUsQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR12MB7816 Content-Type: text/plain; charset="utf-8" From: Koen Koning Use subsys_initcall instead of module_init for the GPU buddy allocator, so its initialization code runs before any gpu drivers. Otherwise, a built-in driver that tries to use the buddy allocator will run into a kernel NULL pointer dereference because slab_blocks is uninitialized. Specifically, this fixes drm/xe (as built-in) running into a kernel panic during boot, because it uses buddy during device probe. Fixes: ba110db8e1bc ("gpu: Move DRM buddy allocator one level up (part two)= ") Cc: Joel Fernandes Cc: Dave Airlie Cc: intel-xe@lists.freedesktop.org Cc: Peter Senna Tschudin Cc: Matthew Auld Signed-off-by: Koen Koning Reviewed-by: Joel Fernandes Signed-off-by: Joel Fernandes --- Please note: Greg and Danilo suggest fixing this in the Makefile like Koen initially did, so please do so. I am just including this patch here for reference. drivers/gpu/buddy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c index 603c59a2013a..81f57fdf913b 100644 --- a/drivers/gpu/buddy.c +++ b/drivers/gpu/buddy.c @@ -1315,7 +1315,7 @@ static int __init gpu_buddy_module_init(void) return 0; } =20 -module_init(gpu_buddy_module_init); +subsys_initcall(gpu_buddy_module_init); module_exit(gpu_buddy_module_exit); =20 MODULE_DESCRIPTION("GPU Buddy Allocator"); --=20 2.34.1 From nobody Fri Apr 17 00:17:58 2026 Received: from DM1PR04CU001.outbound.protection.outlook.com (mail-centralusazon11010006.outbound.protection.outlook.com [52.101.61.6]) (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 74F6434CFAB; Tue, 24 Feb 2026 22:40:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.61.6 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771972830; cv=fail; b=qrlzZyF1VX8rclhXCjgNsTMqQuUPGFqxdbP8d9p9K4hlh4fheVfQghNQ3B1u9ENzuyR8YHSallpUinlkAz0DDU7TLe2cHYj7d/Wzc8yGUpwhAhG9UvedaXppu6w+H7zNoKxXi+8BCKxwrCCAJP8cLhEMcGGjqpriYShAKqO+9Do= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771972830; c=relaxed/simple; bh=pIqlfSKHdT9RHGA5Y2vzD55+GZleMVfpiVtiqSiXYdM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: Content-Type:MIME-Version; b=RIeQlrxtJI747S+5SVbJqjL187QiKOs4vnfwa/LsTMq32svUtS0JDModTe6xh+4Eeu7+hgz63iCPuAV+Br7G6V1Y8QuBoid1uof+UAmDGDvHV6i1G47mSLVQ49KBMpNr/fTDILBtxtVvvpHA6+K6GV1jXVcXIVXz3uhXkEv0vZM= 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=iwMj0QX6; arc=fail smtp.client-ip=52.101.61.6 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="iwMj0QX6" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=EKeQMD7inyEvcT9l1vpABvH7u85bRMvH1da8zNRATyQh574SBDmKtHhqmEO4NIvJq4BdhEtxHTPbZNy17IVrPQyAfys/XObew9bStEg/TyCf0i9U+zK049h1NivNMhdwkjwTBgvb0gU0wuQPt3xWqSM+lSgByqKFXId6eo2x8rAaMqp0fwH2tVoT/pgs2/Q3sLlDQ7TK1VSOp2UNi9rv83VHICW3Qs5vHQV3hOnIVyzY/OUX8AtIAsjHnZwaKHxpf+Cc1h0xr/f+0mKuS2dsNMau0GKtyK64iEB37wXZZ5ZiWymcA97wII6b6D8s+nXgHVUJ66sOZ7n6GzfF0/mhoQ== 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=cz9q6h4ET6NycbgVaU+e4f2kI294W8WP5YRsCcPOrNY=; b=rSlOHAHOy92KVJYomCmcvydoCFR8yr2YTiyAnKgUJfCIGQd9CQ68n67TfgEE9cLomN73vvc/LHDQWKSc3VnN52Q3hHFCUXT1KUfSKNirfi4XTJRf0tJBBF6OBy/OuLKxWO2dHUDx1jj50l9Y97uWxxP5W0VqF6Y1PhzvLIyotwu6212KsTbngI+XbfcRH0iMMHVMbb8Zo6Ki2FFNfdt171D7XeDQC+lJbl95DlDsX5etpk7xtpb0Djzcip8ZJIpZWfmHJtPhpMnTaGAEGIAMJgYKzu7gpGBeso9ewBhHp3QdDhuAdTB0vRAR3aBAwsbiZT2q7rLLd89YbZjbO66MAA== 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=cz9q6h4ET6NycbgVaU+e4f2kI294W8WP5YRsCcPOrNY=; b=iwMj0QX6idMc29l5RvMIW0QPoEIHxt2Acq5IWj8y4blG5Z0Rt+Nq7O0pOuxlBiXWRG8UMZC7uSs6CNzuTSHEpoWfr3IVypPuxQBgTzNH54qo9rmPbYZDVvDUZJgn6ESqBAkFmKoha72oF6qdWQNKQiehPuN6ptnyPLEJMm8DVbyRW9Ge7z62obmW35TH6qRjR6x5yDdCzH4nSZyOpu6uc1+ZLks38MISgarR0nZGUh20Gs0j1NskKCzDOt7WyFoGH5TbYcPWSVsmCSq6V8W9/XI4SruaMDZAO1ambw3zBFvBN2ybzT+IjabXhYS4sSxCbz2tQ9jWBjFHfyWVUArqlQ== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=nvidia.com; Received: from DS0PR12MB6486.namprd12.prod.outlook.com (2603:10b6:8:c5::21) by PH0PR12MB7816.namprd12.prod.outlook.com (2603:10b6:510:28c::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9632.22; Tue, 24 Feb 2026 22:40:18 +0000 Received: from DS0PR12MB6486.namprd12.prod.outlook.com ([fe80::88a9:f314:c95f:8b33]) by DS0PR12MB6486.namprd12.prod.outlook.com ([fe80::88a9:f314:c95f:8b33%4]) with mapi id 15.20.9632.017; Tue, 24 Feb 2026 22:40:18 +0000 From: Joel Fernandes To: linux-kernel@vger.kernel.org Cc: Miguel Ojeda , Boqun Feng , Gary Guo , =?UTF-8?q?Bj=C3=B6rn=20Roy=20Baron?= , Benno Lossin , Andreas Hindborg , Alice Ryhl , Trevor Gross , Danilo Krummrich , Dave Airlie , Daniel Almeida , Koen Koning , dri-devel@lists.freedesktop.org, nouveau@lists.freedesktop.org, rust-for-linux@vger.kernel.org, Nikola Djukic , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , Simona Vetter , Jonathan Corbet , Alex Deucher , =?UTF-8?q?Christian=20K=C3=B6nig?= , Jani Nikula , Joonas Lahtinen , Rodrigo Vivi , Tvrtko Ursulin , Huang Rui , Matthew Auld , Matthew Brost , Lucas De Marchi , =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , Helge Deller , Alex Gaynor , Boqun Feng , John Hubbard , Alistair Popple , Timur Tabi , Edwin Peer , Alexandre Courbot , Andrea Righi , Andy Ritger , Zhi Wang , Balbir Singh , Philipp Stanner , Elle Rhumsaa , alexeyi@nvidia.com, Eliot Courtney , joel@joelfernandes.org, linux-doc@vger.kernel.org, amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org, linux-fbdev@vger.kernel.org, Joel Fernandes Subject: [PATCH v11 4/4] rust: gpu: Add GPU buddy allocator bindings Date: Tue, 24 Feb 2026 17:40:05 -0500 Message-Id: <20260224224005.3232841-5-joelagnelf@nvidia.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260224224005.3232841-1-joelagnelf@nvidia.com> References: <20260224224005.3232841-1-joelagnelf@nvidia.com> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: MN2PR18CA0027.namprd18.prod.outlook.com (2603:10b6:208:23c::32) To DS0PR12MB6486.namprd12.prod.outlook.com (2603:10b6:8:c5::21) 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: DS0PR12MB6486:EE_|PH0PR12MB7816:EE_ X-MS-Office365-Filtering-Correlation-Id: dab4f29d-723b-4fa5-79d1-08de73f5af52 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|7416014|376014|366016; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?xhEmCyAs8FDbbB9x7Jg5azK1bfTteZAeduddpb+ixe7+bMZdNTe7TaqC6nX2?= =?us-ascii?Q?1wBBihtyY5wjQag09jQr31w3eBVkPVbfhdN6NvnxHMud07GlnH4X2xb4/jqx?= =?us-ascii?Q?rw/9YEk9l1BiSIyTPbxC1YY5GJwy3O9p8c1Kl5EFyNynsI8q94PiNFfduXMx?= =?us-ascii?Q?M2BMsKS+w/4TCBIKhBo97fovoPaujSrDECizl/0RIxVb/QnWKRP/71QLQNZe?= =?us-ascii?Q?fG6TwPKaC2xsvKu6LJ4mZ6F9wADJhOjIMwhi7BIscYYMX4rahI7C0szSP15q?= =?us-ascii?Q?2xPNM6UITvT9mSILXwOlNrHAlzfD286DXPZjytLZJKhkMrBTcLu65Otz19jR?= =?us-ascii?Q?zSo3Uk/iUts5byK9Fm339/i72ulZaCpkdagTvXknrUaYTw+Xv0DgqjVdRGs+?= =?us-ascii?Q?z/r5CsuAUgEhdn07zHDn6azV0vxx1u/kwichqONYXMNt114TZLxWFOAAnMDR?= =?us-ascii?Q?8o51ukUxDpd7fcOOoFTTBgn5vR1m7QPuTGz4pcLhdG8p+v8npdcs9EU5nszZ?= =?us-ascii?Q?6chtCfoeGLJVBA+0w4aRKvuSn+ywdkEeDv/Ri28yIo/g+KEAGBS5kuAOuE/c?= =?us-ascii?Q?Qw3XdWyemGXmPpjfyr4U9eT1MBJxHsFYckPf5ckEM/l80ERMAxieQXrA3oRa?= =?us-ascii?Q?JP+Ys7QIpn6rnWkCf2AbKac+ZC86rritFnTIDfwQY8WRZdiPfzqjG2nMhj7/?= =?us-ascii?Q?Mive+R5iuIchJi+iE41aThRaLtAqaXftFzk4UAk0dnL1Ks4uEvhtB+HEGTCz?= =?us-ascii?Q?s6CHrV+od4IfyvP3jgIra0Xqm/mTGXb/31yPyPv8+fKvMvYkkoCy3+JBZvck?= =?us-ascii?Q?9hBad4tcCWYmlZ7/kJ89XJz+1bbv5+Aszcu2kdpYQI5dw4/32/QWb4ZebBhO?= =?us-ascii?Q?SBOi+s+51EBccS3bK6NOf126apORavIBjhAvk+m/zpy2OSuAQpfe0I0bAT12?= =?us-ascii?Q?v5DX5UrKu6mmdJF+zzkIxXVjEtWF1hK55CwB/0m3d4fkkkdNcrV1kp7tw2Dq?= =?us-ascii?Q?d6y8PkRmmBZmGkvp9eMwDUMzt1iTiVTUJIlRvvjoEHw//Ax8O1Ubh69afkCU?= =?us-ascii?Q?8OJsLs2XnxrutFh0bSGaQP6mmMFrH5IuxNns4deTcFZStEpFh0kpJGGg/8CG?= =?us-ascii?Q?zZckUh69MZ3Rbas0p8zBP67L4mZC77Xc/lO1DMtOvtk/Zkw38Vck2+kBhKqn?= =?us-ascii?Q?bCk/TPWk4qavhiq5CpiMCoh9tYUsL9uS3DItG7H2Vf+E14lzDVVaqIN7bDU/?= =?us-ascii?Q?4+uuviz0EMUK0xGMWkDX+PV9TsOaEmj2B1izEiNsONBp51F9nC+A6xUZYTKr?= =?us-ascii?Q?BL/7dd8BwyCtFarLQ8SQ2NvbJGBP74RLKjZmuO/h5Ar/FK1SPGUPvz2+RTrY?= =?us-ascii?Q?vFg5BeeznLFuDmvp4gJzcoaMKuq3HkxovNiSHPYVazgo0L5g36lZ9Fawc1R3?= =?us-ascii?Q?Jz5auF4cst6EiNaxpzrDWdpv+wG7An36gRemeUt8V3fY3N1w2AlMWqBAco8B?= =?us-ascii?Q?2PIzK4r5+nFEjzjDYbt40QuAfhK3SRN3jf9d+IE65p8KZ6l+td9pJ5o/Iw0+?= =?us-ascii?Q?3irdYIMFOXknfy1Hy98=3D?= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DS0PR12MB6486.namprd12.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(1800799024)(7416014)(376014)(366016);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?0pVL4gHuNnDEg6aKkkMfELM74kBmBV0BqsU+OSOvr2cVEzRCXRkuvM6YZ+mt?= =?us-ascii?Q?wpxPgdrb/OhXNArKhTTtsyqHeYHtsxOJ98H0AaWen6tgmp/fO1TlX38wajfZ?= =?us-ascii?Q?svTi2VzGjCuoLScMv85/bK5rHXognwg/3bjJnARvw4H0jCj2/nIN4PiVSR66?= =?us-ascii?Q?/VjrY806A9SO8PlsJvgCkzIA5cMzrjW6+UhRUOnz/SG9KqKMJg6+xjSx8/7c?= =?us-ascii?Q?RiTXQoaJAeW3ABIgeq7v9OuoUFlrhwDcvij3W1P7jhXpQ5xP+KfZ8KSusRm0?= =?us-ascii?Q?XycQ/12H45gBCFHEdFCuYrTh0OeIhblw4Dd4//i6ByBMZcxUS9Zd17W4PEuy?= =?us-ascii?Q?R/66C9rGYVUIWFRE0Lpk5BBrCoAOQ62edEcA+8QcT3a0uEIWsuG5B3NwuHpB?= =?us-ascii?Q?+KU35YTfw+DVqOtXMKhHDtaQxvJqoJnmQBpFiNPxAOnJU5XD2KOBPM9q2n+J?= =?us-ascii?Q?VCFxSbMSqhqzi31KxB9bNjihTfWuUukVIne3NbOM7twELt37uksT0Yz4aQ97?= =?us-ascii?Q?zIRXe3FqL40nZ+EjJDqcjdSGfelSMzHtSCky7X2qkJzB1HdmofMrvWKpkr6v?= =?us-ascii?Q?+Lwa/wKbRC6UOEgD6nSMmOI3I83/RuXVlrrR5E4VbXMBBdWG4XUqs+u12ecg?= =?us-ascii?Q?7ThkRa04OQg7je4M9vnPonpvEANSDghK9XPLDIJ4MmXPHiyUezM/VEjWbkDQ?= =?us-ascii?Q?4PUHsNbO2aB+VBZCEinfGb8X93FpFIhjieALT73TynU/h51dkv3AtT9UKidV?= =?us-ascii?Q?/OL+5SV5qRn2/WyF60C3MfbcmJ1ICRL3Xlq3Bja76zQVCbRZv7IpqZ7T7j7l?= =?us-ascii?Q?84gHuoe4/ixyc7eeeypUe5PuApsOylfP/fHMysySKFNr1E0SYSk3ialqCrpk?= =?us-ascii?Q?ZO72QX7iakSMfDLXI5BbKLN/lud59lYijNrirUHRQ4jp7W8XcbnghnhkdVjP?= =?us-ascii?Q?9d4XqBrc91qb4vSlVTIySARzLGja9V9z96LdXh76nX0bWlwa3Viicpj2sFH8?= =?us-ascii?Q?KMh53XVyIx7p0g1NsTz17omPtRi8mTwcRbJzypHi7SJzlRkXS8zlsNHfAaF2?= =?us-ascii?Q?tZG1A/f2fjOqm7CnkcVTS14eEU7LJRPACRUX6IHb/H73rVqkTNPYzsjwFsN3?= =?us-ascii?Q?QPuc+HRC8vlSk2XqhCIesRse0xWeI7KkqCTbo6vjVa2fo8PuRwICIvo0zMaD?= =?us-ascii?Q?x8NoO5d15fAcK/8xV3eQULJFBKL2Zk/wdtnjrQ8ITf2zumCAuZXqXVMs0F8v?= =?us-ascii?Q?GxK6mAN+OvCfQRCKF/FXAZYc9Fdopy5S5O7Fm4RjJD+jweXOsGBo+XUCuBQ/?= =?us-ascii?Q?/6SgkK0LudQYIGT2ufwbqqc0de06DEIf9l6t7ORqu0ls1lGVIc5CkWHl/XSJ?= =?us-ascii?Q?GzaqE3cf4k3CRszPs8iubHI0DHl7JBAmXE9GEzNzP6aSkWwT7Di76pNeZeXx?= =?us-ascii?Q?+TTsVOMoFmRUduRd6nxldZaEwPsnRrkgBDKd0vqpfz0glgypid4h6C/QSjbN?= =?us-ascii?Q?0wLK8aSIKcMvt5cXBeZSmONpD3fuSIujdFeZ5zJHi4iIXYCeC/RleOew/uS3?= =?us-ascii?Q?zHAzQHakF1TtluIsT2Vx09ifcus8TL3r1PbfA7MhGOS9CjPwcOItSICjY1sD?= =?us-ascii?Q?/QMjtvsjYuyawY590XIKALqkYeohUh+7pMx536NLLmVjRtH2rQvqtv8uDFua?= =?us-ascii?Q?AlEULirFtz+vCfMpw2kqTurO+iwaVEtHcNgJ+l60XC4cb0Pkfh1yC5CebJtB?= =?us-ascii?Q?9kOmATcDnQ=3D=3D?= X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-Network-Message-Id: dab4f29d-723b-4fa5-79d1-08de73f5af52 X-MS-Exchange-CrossTenant-AuthSource: DS0PR12MB6486.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Feb 2026 22:40:18.0986 (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: miqYjiJrdiUqbdowMoUq7XqwRWUOdTW20PoFJYQ0gyicHCfaN9/fAT+Lo/NEL2XHItBMqfolyoxihiuttRIU9Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH0PR12MB7816 Content-Type: text/plain; charset="utf-8" Add safe Rust abstractions over the Linux kernel's GPU buddy allocator for physical memory management. The GPU buddy allocator implements a binary buddy system useful for GPU physical memory allocation. nova-core will use it for physical memory allocation. Cc: Nikola Djukic Signed-off-by: Joel Fernandes --- MAINTAINERS | 8 + rust/bindings/bindings_helper.h | 11 + rust/helpers/gpu.c | 23 ++ rust/helpers/helpers.c | 1 + rust/kernel/gpu/buddy.rs | 536 ++++++++++++++++++++++++++++++++ rust/kernel/gpu/mod.rs | 5 + rust/kernel/lib.rs | 2 + 7 files changed, 586 insertions(+) create mode 100644 rust/helpers/gpu.c create mode 100644 rust/kernel/gpu/buddy.rs create mode 100644 rust/kernel/gpu/mod.rs diff --git a/MAINTAINERS b/MAINTAINERS index f1e5a8011d2f..6befe3890f78 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -23191,6 +23191,14 @@ S: Maintained T: git https://github.com/Rust-for-Linux/linux.git ffi-next F: rust/kernel/ffi/ =20 +RUST [GPU BUDDY] +M: Joel Fernandes +L: dri-devel@lists.freedesktop.org +L: rust-for-linux@vger.kernel.org +S: Maintained +F: rust/helpers/gpu.c +F: rust/kernel/gpu/ + RUST [NUM] M: Alexandre Courbot R: Yury Norov diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 083cc44aa952..dbb765a9fdbd 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -29,6 +29,7 @@ #include =20 #include +#include #include #include #include @@ -146,6 +147,16 @@ const vm_flags_t RUST_CONST_HELPER_VM_MIXEDMAP =3D VM_= MIXEDMAP; const vm_flags_t RUST_CONST_HELPER_VM_HUGEPAGE =3D VM_HUGEPAGE; const vm_flags_t RUST_CONST_HELPER_VM_NOHUGEPAGE =3D VM_NOHUGEPAGE; =20 +#if IS_ENABLED(CONFIG_GPU_BUDDY) +const unsigned long RUST_CONST_HELPER_GPU_BUDDY_RANGE_ALLOCATION =3D GPU_B= UDDY_RANGE_ALLOCATION; +const unsigned long RUST_CONST_HELPER_GPU_BUDDY_TOPDOWN_ALLOCATION =3D GPU= _BUDDY_TOPDOWN_ALLOCATION; +const unsigned long RUST_CONST_HELPER_GPU_BUDDY_CONTIGUOUS_ALLOCATION =3D + GPU_BUDDY_CONTIGUOUS_ALLOCATION; +const unsigned long RUST_CONST_HELPER_GPU_BUDDY_CLEAR_ALLOCATION =3D GPU_B= UDDY_CLEAR_ALLOCATION; +const unsigned long RUST_CONST_HELPER_GPU_BUDDY_CLEARED =3D GPU_BUDDY_CLEA= RED; +const unsigned long RUST_CONST_HELPER_GPU_BUDDY_TRIM_DISABLE =3D GPU_BUDDY= _TRIM_DISABLE; +#endif + #if IS_ENABLED(CONFIG_ANDROID_BINDER_IPC_RUST) #include "../../drivers/android/binder/rust_binder.h" #include "../../drivers/android/binder/rust_binder_events.h" diff --git a/rust/helpers/gpu.c b/rust/helpers/gpu.c new file mode 100644 index 000000000000..38b1a4e6bef8 --- /dev/null +++ b/rust/helpers/gpu.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include + +#ifdef CONFIG_GPU_BUDDY + +__rust_helper u64 rust_helper_gpu_buddy_block_offset(const struct gpu_budd= y_block *block) +{ + return gpu_buddy_block_offset(block); +} + +__rust_helper unsigned int rust_helper_gpu_buddy_block_order(struct gpu_bu= ddy_block *block) +{ + return gpu_buddy_block_order(block); +} + +__rust_helper u64 rust_helper_gpu_buddy_block_size(struct gpu_buddy *mm, + struct gpu_buddy_block *block) +{ + return gpu_buddy_block_size(mm, block); +} + +#endif /* CONFIG_GPU_BUDDY */ diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 724fcb8240ac..a53929ce52a3 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -32,6 +32,7 @@ #include "err.c" #include "irq.c" #include "fs.c" +#include "gpu.c" #include "io.c" #include "jump_label.c" #include "kunit.c" diff --git a/rust/kernel/gpu/buddy.rs b/rust/kernel/gpu/buddy.rs new file mode 100644 index 000000000000..4383f82c0fc1 --- /dev/null +++ b/rust/kernel/gpu/buddy.rs @@ -0,0 +1,536 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! GPU buddy allocator bindings. +//! +//! C header: [`include/linux/gpu_buddy.h`](srctree/include/linux/gpu_budd= y.h) +//! +//! This module provides Rust abstractions over the Linux kernel's GPU bud= dy +//! allocator, which implements a binary buddy memory allocator. +//! +//! The buddy allocator manages a contiguous address space and allocates b= locks +//! in power-of-two sizes, useful for GPU physical memory management. +//! +//! # Examples +//! +//! ``` +//! use kernel::{ +//! gpu::buddy::{BuddyFlags, GpuBuddy, GpuBuddyAllocParams, GpuBuddyPa= rams}, +//! prelude::*, +//! sizes::*, // +//! }; +//! +//! // Create a 1GB buddy allocator with 4KB minimum chunk size. +//! let buddy =3D GpuBuddy::new(GpuBuddyParams { +//! base_offset_bytes: 0, +//! physical_memory_size_bytes: SZ_1G as u64, +//! chunk_size_bytes: SZ_4K as u64, +//! })?; +//! +//! // Verify initial state. +//! assert_eq!(buddy.size(), SZ_1G as u64); +//! assert_eq!(buddy.chunk_size(), SZ_4K as u64); +//! let initial_free =3D buddy.free_memory_bytes(); +//! +//! // Base allocation params - mutated between calls for field overrides. +//! let mut params =3D GpuBuddyAllocParams { +//! start_range_address: 0, +//! end_range_address: 0, // Entire range. +//! size_bytes: SZ_16M as u64, +//! min_block_size_bytes: SZ_16M as u64, +//! buddy_flags: BuddyFlags::try_new(BuddyFlags::RANGE_ALLOCATION)?, +//! }; +//! +//! // Test top-down allocation (allocates from highest addresses). +//! params.buddy_flags =3D BuddyFlags::try_new(BuddyFlags::TOPDOWN_ALLOCAT= ION)?; +//! let topdown =3D KBox::pin_init(buddy.alloc_blocks(¶ms), GFP_KERNEL= )?; +//! assert_eq!(buddy.free_memory_bytes(), initial_free - SZ_16M as u64); +//! +//! for block in topdown.iter() { +//! assert_eq!(block.offset(), (SZ_1G - SZ_16M) as u64); +//! assert_eq!(block.order(), 12); // 2^12 pages +//! assert_eq!(block.size(), SZ_16M as u64); +//! } +//! drop(topdown); +//! assert_eq!(buddy.free_memory_bytes(), initial_free); +//! +//! // Allocate 16MB - should result in a single 16MB block at offset 0. +//! params.buddy_flags =3D BuddyFlags::try_new(BuddyFlags::RANGE_ALLOCATIO= N)?; +//! let allocated =3D KBox::pin_init(buddy.alloc_blocks(¶ms), GFP_KERN= EL)?; +//! assert_eq!(buddy.free_memory_bytes(), initial_free - SZ_16M as u64); +//! +//! for block in allocated.iter() { +//! assert_eq!(block.offset(), 0); +//! assert_eq!(block.order(), 12); // 2^12 pages +//! assert_eq!(block.size(), SZ_16M as u64); +//! } +//! drop(allocated); +//! assert_eq!(buddy.free_memory_bytes(), initial_free); +//! +//! // Test non-contiguous allocation with fragmented memory. +//! // Create fragmentation by allocating 4MB blocks at [0,4M) and [8M,12M= ). +//! params.end_range_address =3D SZ_4M as u64; +//! params.size_bytes =3D SZ_4M as u64; +//! params.min_block_size_bytes =3D SZ_4M as u64; +//! let frag1 =3D KBox::pin_init(buddy.alloc_blocks(¶ms), GFP_KERNEL)?; +//! assert_eq!(buddy.free_memory_bytes(), initial_free - SZ_4M as u64); +//! +//! params.start_range_address =3D SZ_8M as u64; +//! params.end_range_address =3D (SZ_8M + SZ_4M) as u64; +//! let frag2 =3D KBox::pin_init(buddy.alloc_blocks(¶ms), GFP_KERNEL)?; +//! assert_eq!(buddy.free_memory_bytes(), initial_free - SZ_8M as u64); +//! +//! // Allocate 8MB without CONTIGUOUS - should return 2 blocks from the h= oles. +//! params.start_range_address =3D 0; +//! params.end_range_address =3D SZ_16M as u64; +//! params.size_bytes =3D SZ_8M as u64; +//! let fragmented =3D KBox::pin_init(buddy.alloc_blocks(¶ms), GFP_KER= NEL)?; +//! assert_eq!(buddy.free_memory_bytes(), initial_free - (SZ_16M) as u64); +//! +//! let (mut count, mut total) =3D (0u32, 0u64); +//! for block in fragmented.iter() { +//! // The 8MB allocation should return 2 blocks, each 4MB. +//! assert_eq!(block.size(), SZ_4M as u64); +//! total +=3D block.size(); +//! count +=3D 1; +//! } +//! assert_eq!(total, SZ_8M as u64); +//! assert_eq!(count, 2); +//! drop(fragmented); +//! drop(frag2); +//! drop(frag1); +//! assert_eq!(buddy.free_memory_bytes(), initial_free); +//! +//! // Test CONTIGUOUS failure when only fragmented space available. +//! // Create a small buddy allocator with only 16MB of memory. +//! let small =3D GpuBuddy::new(GpuBuddyParams { +//! base_offset_bytes: 0, +//! physical_memory_size_bytes: SZ_16M as u64, +//! chunk_size_bytes: SZ_4K as u64, +//! })?; +//! +//! // Allocate 4MB blocks at [0,4M) and [8M,12M) to create fragmented mem= ory. +//! params.start_range_address =3D 0; +//! params.end_range_address =3D SZ_4M as u64; +//! params.size_bytes =3D SZ_4M as u64; +//! let hole1 =3D KBox::pin_init(small.alloc_blocks(¶ms), GFP_KERNEL)?; +//! +//! params.start_range_address =3D SZ_8M as u64; +//! params.end_range_address =3D (SZ_8M + SZ_4M) as u64; +//! let hole2 =3D KBox::pin_init(small.alloc_blocks(¶ms), GFP_KERNEL)?; +//! +//! // 8MB contiguous should fail - only two non-contiguous 4MB holes exis= t. +//! params.start_range_address =3D 0; +//! params.end_range_address =3D 0; +//! params.size_bytes =3D SZ_8M as u64; +//! params.buddy_flags =3D BuddyFlags::try_new(BuddyFlags::CONTIGUOUS_ALLO= CATION)?; +//! let result =3D KBox::pin_init(small.alloc_blocks(¶ms), GFP_KERNEL); +//! assert!(result.is_err()); +//! drop(hole2); +//! drop(hole1); +//! +//! # Ok::<(), Error>(()) +//! ``` + +use crate::{ + bindings, + clist_create, + error::to_result, + ffi::clist::CListHead, + new_mutex, + prelude::*, + sync::{ + lock::mutex::MutexGuard, + Arc, + Mutex, // + }, + types::Opaque, // +}; + +/// Flags for GPU buddy allocator operations. +/// +/// These flags control the allocation behavior of the buddy allocator. +#[derive(Clone, Copy, Default, PartialEq, Eq)] +pub struct BuddyFlags(usize); + +impl BuddyFlags { + /// Range-based allocation from start to end addresses. + pub const RANGE_ALLOCATION: usize =3D bindings::GPU_BUDDY_RANGE_ALLOCA= TION; + + /// Allocate from top of address space downward. + pub const TOPDOWN_ALLOCATION: usize =3D bindings::GPU_BUDDY_TOPDOWN_AL= LOCATION; + + /// Allocate physically contiguous blocks. + pub const CONTIGUOUS_ALLOCATION: usize =3D bindings::GPU_BUDDY_CONTIGU= OUS_ALLOCATION; + + /// Request allocation from the cleared (zeroed) memory. The zero'ing = is not + /// done by the allocator, but by the caller before freeing old blocks. + pub const CLEAR_ALLOCATION: usize =3D bindings::GPU_BUDDY_CLEAR_ALLOCA= TION; + + /// Disable trimming of partially used blocks. + pub const TRIM_DISABLE: usize =3D bindings::GPU_BUDDY_TRIM_DISABLE; + + /// Mark blocks as cleared (zeroed) when freeing. When set during free, + /// indicates that the caller has already zeroed the memory. + pub const CLEARED: usize =3D bindings::GPU_BUDDY_CLEARED; + + /// Create [`BuddyFlags`] from a raw value with validation. + /// + /// Use `|` operator to combine flags if needed, before calling this m= ethod. + pub fn try_new(flags: usize) -> Result { + // Flags must not exceed u32::MAX to satisfy the GPU buddy allocat= or C API. + if flags > u32::MAX as usize { + return Err(EINVAL); + } + + // `TOPDOWN_ALLOCATION` only works without `RANGE_ALLOCATION`. Whe= n both are + // set, `TOPDOWN_ALLOCATION` is silently ignored by the allocator.= Reject this. + if (flags & Self::RANGE_ALLOCATION) !=3D 0 && (flags & Self::TOPDO= WN_ALLOCATION) !=3D 0 { + return Err(EINVAL); + } + + Ok(Self(flags)) + } + + /// Get raw value of the flags. + pub(crate) fn as_raw(self) -> usize { + self.0 + } +} + +/// Parameters for creating a GPU buddy allocator. +pub struct GpuBuddyParams { + /// Base offset in bytes where the managed memory region starts. + /// Allocations will be offset by this value. + pub base_offset_bytes: u64, + /// Total physical memory size managed by the allocator in bytes. + pub physical_memory_size_bytes: u64, + /// Minimum allocation unit / chunk size in bytes, must be >=3D 4KB. + pub chunk_size_bytes: u64, +} + +/// Parameters for allocating blocks from a GPU buddy allocator. +pub struct GpuBuddyAllocParams { + /// Start of allocation range in bytes. Use 0 for beginning. + pub start_range_address: u64, + /// End of allocation range in bytes. Use 0 for entire range. + pub end_range_address: u64, + /// Total size to allocate in bytes. + pub size_bytes: u64, + /// Minimum block size for fragmented allocations in bytes. + pub min_block_size_bytes: u64, + /// Buddy allocator behavior flags. + pub buddy_flags: BuddyFlags, +} + +/// Inner structure holding the actual buddy allocator. +/// +/// # Synchronization +/// +/// The C `gpu_buddy` API requires synchronization (see `include/linux/gpu= _buddy.h`). +/// The internal [`GpuBuddyGuard`] ensures that the lock is held for all +/// allocator and free operations, preventing races between concurrent all= ocations +/// and the freeing that occurs when [`AllocatedBlocks`] is dropped. +/// +/// # Invariants +/// +/// The inner [`Opaque`] contains a valid, initialized buddy allocator. +#[pin_data(PinnedDrop)] +struct GpuBuddyInner { + #[pin] + inner: Opaque, + + // TODO: Replace `Mutex<()>` with `Mutex>` once `Mutex::new= ()` + // accepts `impl PinInit`. + #[pin] + lock: Mutex<()>, + /// Base offset for all allocations (does not change after init). + base_offset: u64, + /// Cached chunk size (does not change after init). + chunk_size: u64, + /// Cached total size (does not change after init). + size: u64, +} + +impl GpuBuddyInner { + /// Create a pin-initializer for the buddy allocator. + fn new(params: GpuBuddyParams) -> impl PinInit { + let base_offset =3D params.base_offset_bytes; + let size =3D params.physical_memory_size_bytes; + let chunk_size =3D params.chunk_size_bytes; + + try_pin_init!(Self { + inner <- Opaque::try_ffi_init(|ptr| { + // SAFETY: ptr points to valid uninitialized memory from t= he pin-init + // infrastructure. gpu_buddy_init will initialize the stru= cture. + to_result(unsafe { bindings::gpu_buddy_init(ptr, size, chu= nk_size) }) + }), + lock <- new_mutex!(()), + base_offset: base_offset, + chunk_size: chunk_size, + size: size, + }) + } + + /// Lock the mutex and return a guard for accessing the allocator. + fn lock(&self) -> GpuBuddyGuard<'_> { + GpuBuddyGuard { + inner: self, + _guard: self.lock.lock(), + } + } +} + +#[pinned_drop] +impl PinnedDrop for GpuBuddyInner { + fn drop(self: Pin<&mut Self>) { + let guard =3D self.lock(); + + // SAFETY: guard provides exclusive access to the allocator. + unsafe { + bindings::gpu_buddy_fini(guard.as_raw()); + } + } +} + +// SAFETY: GpuBuddyInner can be sent between threads. +unsafe impl Send for GpuBuddyInner {} + +// SAFETY: GpuBuddyInner is `Sync` because the internal GpuBuddyGuard +// serializes all access to the C allocator, preventing data races. +unsafe impl Sync for GpuBuddyInner {} + +/// Guard that proves the lock is held, enabling access to the allocator. +/// +/// # Invariants +/// +/// The inner `_guard` holds the lock for the duration of this guard's lif= etime. +pub(crate) struct GpuBuddyGuard<'a> { + inner: &'a GpuBuddyInner, + _guard: MutexGuard<'a, ()>, +} + +impl GpuBuddyGuard<'_> { + /// Get a raw pointer to the underlying C `gpu_buddy` structure. + fn as_raw(&self) -> *mut bindings::gpu_buddy { + self.inner.inner.get() + } +} + +/// GPU buddy allocator instance. +/// +/// This structure wraps the C `gpu_buddy` allocator using reference count= ing. +/// The allocator is automatically cleaned up when all references are drop= ped. +/// +/// # Invariants +/// +/// The inner [`Arc`] points to a valid, initialized GPU buddy allocator. +pub struct GpuBuddy(Arc); + +impl GpuBuddy { + /// Create a new buddy allocator. + /// + /// Creates a buddy allocator that manages a contiguous address space = of the given + /// size, with the specified minimum allocation unit (chunk_size must = be at least 4KB). + pub fn new(params: GpuBuddyParams) -> Result { + Ok(Self(Arc::pin_init(GpuBuddyInner::new(params), GFP_KERNEL)?)) + } + + /// Get the base offset for allocations. + pub fn base_offset(&self) -> u64 { + self.0.base_offset + } + + /// Get the chunk size (minimum allocation unit). + pub fn chunk_size(&self) -> u64 { + self.0.chunk_size + } + + /// Get the total managed size. + pub fn size(&self) -> u64 { + self.0.size + } + + /// Get the available (free) memory in bytes. + pub fn free_memory_bytes(&self) -> u64 { + let guard =3D self.0.lock(); + + // SAFETY: guard provides exclusive access to the allocator. + unsafe { (*guard.as_raw()).avail } + } + + /// Allocate blocks from the buddy allocator. + /// + /// Returns a pin-initializer for [`AllocatedBlocks`]. + /// + /// Takes `&self` instead of `&mut self` because the internal [`Mutex`= ] provides + /// synchronization - no external `&mut` exclusivity needed. + pub fn alloc_blocks( + &self, + params: &GpuBuddyAllocParams, + ) -> impl PinInit { + let buddy_arc =3D Arc::clone(&self.0); + let start =3D params.start_range_address; + let end =3D params.end_range_address; + let size =3D params.size_bytes; + let min_block_size =3D params.min_block_size_bytes; + let flags =3D params.buddy_flags; + + // Create pin-initializer that initializes list and allocates bloc= ks. + try_pin_init!(AllocatedBlocks { + buddy: buddy_arc, + list <- CListHead::new(), + flags: flags, + _: { + // Lock while allocating to serialize with concurrent free= s. + let guard =3D buddy.lock(); + + // SAFETY: `guard` provides exclusive access to the buddy = allocator. + to_result(unsafe { + bindings::gpu_buddy_alloc_blocks( + guard.as_raw(), + start, + end, + size, + min_block_size, + list.as_raw(), + flags.as_raw(), + ) + })? + } + }) + } +} + +/// Allocated blocks from the buddy allocator with automatic cleanup. +/// +/// This structure owns a list of allocated blocks and ensures they are +/// automatically freed when dropped. Use `iter()` to iterate over all +/// allocated [`Block`] structures. +/// +/// # Invariants +/// +/// - `list` is an initialized, valid list head containing allocated block= s. +#[pin_data(PinnedDrop)] +pub struct AllocatedBlocks { + #[pin] + list: CListHead, + buddy: Arc, + flags: BuddyFlags, +} + +impl AllocatedBlocks { + /// Check if the block list is empty. + pub fn is_empty(&self) -> bool { + // An empty list head points to itself. + !self.list.is_linked() + } + + /// Iterate over allocated blocks. + /// + /// Returns an iterator yielding [`AllocatedBlock`] values. Each [`All= ocatedBlock`] + /// borrows `self` and is only valid for the duration of that borrow. + pub fn iter(&self) -> impl Iterator> + '_ { + // SAFETY: list contains gpu_buddy_block items linked via __bindge= n_anon_1.link. + let clist =3D clist_create!(unsafe { + self.list.as_raw(), + Block, + bindings::gpu_buddy_block, + __bindgen_anon_1.link + }); + + clist + .iter() + .map(|block| AllocatedBlock { block, alloc: self }) + } +} + +#[pinned_drop] +impl PinnedDrop for AllocatedBlocks { + fn drop(self: Pin<&mut Self>) { + let guard =3D self.buddy.lock(); + + // SAFETY: + // - list is valid per the type's invariants. + // - guard provides exclusive access to the allocator. + // CAST: BuddyFlags were validated to fit in u32 at construction. + unsafe { + bindings::gpu_buddy_free_list( + guard.as_raw(), + self.list.as_raw(), + self.flags.as_raw() as u32, + ); + } + } +} + +/// A GPU buddy block. +/// +/// Transparent wrapper over C `gpu_buddy_block` structure. This type is r= eturned +/// as references during iteration over [`AllocatedBlocks`]. +/// +/// # Invariants +/// +/// The inner [`Opaque`] contains a valid, allocated `gpu_buddy_block`. +#[repr(transparent)] +pub struct Block(Opaque); + +impl Block { + /// Get a raw pointer to the underlying C block. + fn as_raw(&self) -> *mut bindings::gpu_buddy_block { + self.0.get() + } + + /// Get the block's offset in the address space. + pub(crate) fn offset(&self) -> u64 { + // SAFETY: self.as_raw() is valid per the type's invariants. + unsafe { bindings::gpu_buddy_block_offset(self.as_raw()) } + } + + /// Get the block order. + pub(crate) fn order(&self) -> u32 { + // SAFETY: self.as_raw() is valid per the type's invariants. + unsafe { bindings::gpu_buddy_block_order(self.as_raw()) } + } +} + +// SAFETY: `Block` is not modified after allocation for the lifetime +// of `AllocatedBlock`. +unsafe impl Send for Block {} + +// SAFETY: `Block` is not modified after allocation for the lifetime +// of `AllocatedBlock`. +unsafe impl Sync for Block {} + +/// An allocated block with access to the GPU buddy allocator. +/// +/// It is returned by [`AllocatedBlocks::iter()`] and provides access to t= he +/// GPU buddy allocator required for some accessors. +/// +/// # Invariants +/// +/// - `block` is a valid reference to an allocated [`Block`]. +/// - `alloc` is a valid reference to the [`AllocatedBlocks`] that owns th= is block. +pub struct AllocatedBlock<'a> { + block: &'a Block, + alloc: &'a AllocatedBlocks, +} + +impl AllocatedBlock<'_> { + /// Get the block's offset in the address space. + /// + /// Returns the absolute offset including the allocator's base offset. + /// This is the actual address to use for accessing the allocated memo= ry. + pub fn offset(&self) -> u64 { + self.alloc.buddy.base_offset + self.block.offset() + } + + /// Get the block order (size =3D chunk_size << order). + pub fn order(&self) -> u32 { + self.block.order() + } + + /// Get the block's size in bytes. + pub fn size(&self) -> u64 { + self.alloc.buddy.chunk_size << self.block.order() + } +} diff --git a/rust/kernel/gpu/mod.rs b/rust/kernel/gpu/mod.rs new file mode 100644 index 000000000000..8f25e6367edc --- /dev/null +++ b/rust/kernel/gpu/mod.rs @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! GPU subsystem abstractions. + +pub mod buddy; diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs index 58dbb02c5197..b8287601f464 100644 --- a/rust/kernel/lib.rs +++ b/rust/kernel/lib.rs @@ -97,6 +97,8 @@ pub mod firmware; pub mod fmt; pub mod fs; +#[cfg(CONFIG_GPU_BUDDY)] +pub mod gpu; #[cfg(CONFIG_I2C =3D "y")] pub mod i2c; pub mod id_pool; --=20 2.34.1