linux-loongson/drivers/gpu/drm/nova/uapi.rs
Danilo Krummrich cdeaeb9dd7 drm: nova-drm: add initial driver skeleton
Add the initial nova-drm driver skeleton.

nova-drm is connected to nova-core through the auxiliary bus and
implements the DRM parts of the nova driver stack.

For now, it implements the fundamental DRM abstractions, i.e. creates a
DRM device and registers it, exposing a three sample IOCTLs.

  DRM_IOCTL_NOVA_GETPARAM
    - provides the PCI bar size from the bar that maps the GPUs VRAM
      from nova-core

  DRM_IOCTL_NOVA_GEM_CREATE
    - creates a new dummy DRM GEM object and returns a handle

  DRM_IOCTL_NOVA_GEM_INFO
    - provides metadata for the DRM GEM object behind a given handle

I implemented a small userspace test suite [1] that utilizes this
interface.

Link: https://gitlab.freedesktop.org/dakr/drm-test [1]
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Acked-by: Dave Airlie <airlied@redhat.com>
Link: https://lore.kernel.org/r/20250424160452.8070-3-dakr@kernel.org
[ Kconfig: depend on DRM=y rather than just DRM. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
2025-05-12 20:48:15 +02:00

62 lines
1.9 KiB
Rust

// SPDX-License-Identifier: GPL-2.0
use kernel::uapi;
// TODO Work out some common infrastructure to avoid boilerplate code for uAPI abstractions.
macro_rules! define_uapi_abstraction {
($name:ident <= $inner:ty) => {
#[repr(transparent)]
pub struct $name(::kernel::types::Opaque<$inner>);
impl ::core::convert::From<&::kernel::types::Opaque<$inner>> for &$name {
fn from(value: &::kernel::types::Opaque<$inner>) -> Self {
// SAFETY: `Self` is a transparent wrapper of `$inner`.
unsafe { ::core::mem::transmute(value) }
}
}
};
}
define_uapi_abstraction!(Getparam <= uapi::drm_nova_getparam);
impl Getparam {
pub fn param(&self) -> u64 {
// SAFETY: `self.get()` is a valid pointer to a `struct drm_nova_getparam`.
unsafe { (*self.0.get()).param }
}
pub fn set_value(&self, v: u64) {
// SAFETY: `self.get()` is a valid pointer to a `struct drm_nova_getparam`.
unsafe { (*self.0.get()).value = v };
}
}
define_uapi_abstraction!(GemCreate <= uapi::drm_nova_gem_create);
impl GemCreate {
pub fn size(&self) -> u64 {
// SAFETY: `self.get()` is a valid pointer to a `struct drm_nova_gem_create`.
unsafe { (*self.0.get()).size }
}
pub fn set_handle(&self, handle: u32) {
// SAFETY: `self.get()` is a valid pointer to a `struct drm_nova_gem_create`.
unsafe { (*self.0.get()).handle = handle };
}
}
define_uapi_abstraction!(GemInfo <= uapi::drm_nova_gem_info);
impl GemInfo {
pub fn handle(&self) -> u32 {
// SAFETY: `self.get()` is a valid pointer to a `struct drm_nova_gem_info`.
unsafe { (*self.0.get()).handle }
}
pub fn set_size(&self, size: u64) {
// SAFETY: `self.get()` is a valid pointer to a `struct drm_nova_gem_info`.
unsafe { (*self.0.get()).size = size };
}
}