From 6cd5a67c8bdbb9f2fb23c6525431d1c23f73f47e Mon Sep 17 00:00:00 2001
From: "Rob Herring (Arm)" <robh@kernel.org>
Date: Thu, 1 Aug 2024 14:55:40 -0600
Subject: [PATCH] drm: panthor-rs: Add rust driver stub

Based on nova stub.

Missing the workqueue init done in module_init in C driver. Need to
check if that really needs to be per module rather than per driver
instance.

Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
---
 drivers/gpu/drm/Kconfig                     |   1 +
 drivers/gpu/drm/Makefile                    |   1 +
 drivers/gpu/drm/panthor-rs/Kconfig          |  25 +++
 drivers/gpu/drm/panthor-rs/Makefile         |   8 +
 drivers/gpu/drm/panthor-rs/driver.rs        | 145 +++++++++++++++++
 drivers/gpu/drm/panthor-rs/file.rs          | 164 ++++++++++++++++++++
 drivers/gpu/drm/panthor-rs/gem.rs           |  29 ++++
 drivers/gpu/drm/panthor-rs/panthor.rs       |  21 +++
 drivers/gpu/drm/panthor-rs/panthor_device.c |   7 +
 drivers/gpu/drm/panthor-rs/panthor_device.h |   2 +
 rust/bindings/bindings_helper.h             |   2 +
 rust/kernel/drm/gem/mod.rs                  |   1 +
 rust/uapi/uapi_helper.h                     |   1 +
 13 files changed, 407 insertions(+)
 create mode 100644 drivers/gpu/drm/panthor-rs/Kconfig
 create mode 100644 drivers/gpu/drm/panthor-rs/Makefile
 create mode 100644 drivers/gpu/drm/panthor-rs/driver.rs
 create mode 100644 drivers/gpu/drm/panthor-rs/file.rs
 create mode 100644 drivers/gpu/drm/panthor-rs/gem.rs
 create mode 100644 drivers/gpu/drm/panthor-rs/panthor.rs

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 1cb5a4f192933..f6019a4c53206 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -452,6 +452,7 @@ source "drivers/gpu/drm/lima/Kconfig"
 source "drivers/gpu/drm/panfrost/Kconfig"
 
 source "drivers/gpu/drm/panthor/Kconfig"
+source "drivers/gpu/drm/panthor-rs/Kconfig"
 
 source "drivers/gpu/drm/aspeed/Kconfig"
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 784229d4504dc..f13d37d6d7687 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -209,6 +209,7 @@ obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo/
 obj-$(CONFIG_DRM_LIMA)  += lima/
 obj-$(CONFIG_DRM_PANFROST) += panfrost/
 obj-$(CONFIG_DRM_PANTHOR) += panthor/
+obj-$(CONFIG_DRM_PANTHOR_RS) += panthor-rs/
 obj-$(CONFIG_DRM_ASPEED_GFX) += aspeed/
 obj-$(CONFIG_DRM_MCDE) += mcde/
 obj-$(CONFIG_DRM_TIDSS) += tidss/
diff --git a/drivers/gpu/drm/panthor-rs/Kconfig b/drivers/gpu/drm/panthor-rs/Kconfig
new file mode 100644
index 0000000000000..9356325f778cd
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/Kconfig
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0 or MIT
+
+config DRM_PANTHOR_RS
+	tristate "Panthor Rust-based (DRM support for ARM Mali CSF-based GPUs)"
+	depends on DRM=y
+	depends on RUST
+	depends on ARM || ARM64 || COMPILE_TEST
+	depends on !GENERIC_ATOMIC64  # for IOMMU_IO_PGTABLE_LPAE
+	depends on MMU
+	depends on DRM_PANTHOR=n
+	select DEVFREQ_GOV_SIMPLE_ONDEMAND
+	select DRM_EXEC
+	select DRM_GEM_SHMEM_HELPER
+	select DRM_GPUVM
+	select DRM_SCHED
+	select IOMMU_IO_PGTABLE_LPAE
+	depends on IOMMU_SUPPORT
+	select PM_DEVFREQ
+	help
+	  DRM driver for ARM Mali CSF-based GPUs.
+
+	  This driver is for Mali (or Immortalis) Valhall Gxxx GPUs.
+
+	  Note that the Mali-G68 and Mali-G78, while Valhall architecture, will
+	  be supported with the panfrost driver as they are not CSF GPUs.
diff --git a/drivers/gpu/drm/panthor-rs/Makefile b/drivers/gpu/drm/panthor-rs/Makefile
new file mode 100644
index 0000000000000..c39521d5ca9e3
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0 or MIT
+
+panthor_rs-y := \
+	panthor.o
+
+obj-$(CONFIG_DRM_PANTHOR_RS) += panthor_rs.o
+
+CFLAGS_panthor_drv.o := -Wno-missing-prototypes -Wno-unused-function -Wno-unused-const-variable
diff --git a/drivers/gpu/drm/panthor-rs/driver.rs b/drivers/gpu/drm/panthor-rs/driver.rs
new file mode 100644
index 0000000000000..546c1df47b95e
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/driver.rs
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+
+//! Top-level GPU driver implementation.
+
+use kernel::{
+    bindings, c_str, drm, drm::drv, drm::ioctl, error::Result, of, platform, prelude::*, sync::Arc,
+};
+
+use core::ffi;
+use kernel::macros::vtable;
+use kernel::types::ARef;
+
+extern "C" {
+    fn panthor_device_init(ptdev: *mut bindings::panthor_device) -> ffi::c_int;
+}
+
+/// Driver metadata
+const INFO: drm::drv::DriverInfo = drm::drv::DriverInfo {
+    major: 0,
+    minor: 0,
+    patchlevel: 0,
+    name: c_str!("panthor"),
+    desc: c_str!("Panthor DRM driver"),
+    date: c_str!("20230801"),
+};
+
+/// Device data for the driver registration.
+///
+/// Holds a reference to the top-level `GpuManager` object.
+#[allow(dead_code)]
+#[pin_data]
+pub(crate) struct PanthorData {
+    #[pin]
+    pub(crate) ptdev: *mut bindings::panthor_device,
+    pub(crate) pdev: platform::Device,
+}
+
+//HACK
+unsafe impl Send for PanthorData {}
+unsafe impl Sync for PanthorData {}
+
+pub(crate) struct PanthorDriver(ARef<PanthorDevice>);
+
+/// Convenience type alias for the DRM device type for this driver.
+pub(crate) type PanthorDevice = kernel::drm::device::Device<PanthorDriver>;
+pub(crate) type PanthorDevRef = ARef<PanthorDevice>;
+
+/// DRM Driver implementation for `PanthorDriver`.
+#[vtable]
+impl drv::Driver for PanthorDriver {
+    /// Our `DeviceData` type, reference-counted
+    type Data = Arc<PanthorData>;
+    /// Our `File` type.
+    type File = crate::file::File;
+    /// Our `Object` type.
+    type Object = crate::gem::Object;
+
+    const INFO: drv::DriverInfo = INFO;
+    const FEATURES: u32 = drv::FEAT_GEM
+        | drv::FEAT_RENDER
+        | drv::FEAT_SYNCOBJ
+        | drv::FEAT_SYNCOBJ_TIMELINE
+        | drv::FEAT_GEM_GPUVA;
+
+    kernel::declare_drm_ioctls! {
+        (PANTHOR_DEV_QUERY,      drm_panthor_dev_query,
+            ioctl::RENDER_ALLOW, crate::file::File::dev_query),
+        (PANTHOR_VM_CREATE,      drm_panthor_vm_create,
+            ioctl::RENDER_ALLOW, crate::file::File::vm_create),
+        (PANTHOR_VM_DESTROY,     drm_panthor_vm_destroy,
+            ioctl::RENDER_ALLOW, crate::file::File::vm_destroy),
+        (PANTHOR_VM_BIND,        drm_panthor_vm_bind,
+            ioctl::RENDER_ALLOW, crate::file::File::vm_bind),
+        (PANTHOR_VM_GET_STATE,   drm_panthor_vm_get_state,
+            ioctl::RENDER_ALLOW, crate::file::File::vm_get_state),
+        (PANTHOR_BO_CREATE,      drm_panthor_bo_create,
+            ioctl::RENDER_ALLOW, crate::file::File::bo_create),
+        (PANTHOR_BO_MMAP_OFFSET, drm_panthor_bo_mmap_offset,
+            ioctl::RENDER_ALLOW, crate::file::File::bo_mmap_offset),
+        (PANTHOR_GROUP_CREATE,   drm_panthor_group_create,
+            ioctl::RENDER_ALLOW, crate::file::File::group_create),
+        (PANTHOR_GROUP_DESTROY,  drm_panthor_group_destroy,
+            ioctl::RENDER_ALLOW, crate::file::File::group_destroy),
+        (PANTHOR_GROUP_SUBMIT,   drm_panthor_group_submit,
+            ioctl::RENDER_ALLOW, crate::file::File::group_submit),
+        (PANTHOR_GROUP_GET_STATE, drm_panthor_group_get_state,
+            ioctl::RENDER_ALLOW, crate::file::File::group_get_state),
+        (PANTHOR_TILER_HEAP_CREATE, drm_panthor_tiler_heap_create,
+            ioctl::RENDER_ALLOW, crate::file::File::tiler_heap_create),
+        (PANTHOR_TILER_HEAP_DESTROY, drm_panthor_tiler_heap_destroy,
+            ioctl::RENDER_ALLOW, crate::file::File::tiler_heap_destroy),
+    }
+}
+
+kernel::of_device_table!(
+    OF_TABLE,
+    MODULE_OF_TABLE,
+    <PanthorDriver as platform::Driver>::IdInfo,
+    [
+        (of::DeviceId::new(c_str!("rockchip,rk3588-mali")), ()),
+        (of::DeviceId::new(c_str!("arm,mali-valhall-csf")), ()),
+    ]
+);
+
+/// Platform Driver implementation for `PanthorDriver`.
+impl platform::Driver for PanthorDriver {
+    type IdInfo = ();
+    const ID_TABLE: platform::IdTable<Self::IdInfo> = &OF_TABLE;
+
+    /// Device probe function.
+    fn probe(
+        pdev: &mut platform::Device,
+        id_info: Option<&Self::IdInfo>,
+    ) -> Result<Pin<KBox<Self>>> {
+        dev_info!(pdev.as_ref(), "Probing...\n");
+
+        let data = Arc::new(
+            PanthorData {
+                ptdev: unsafe { bindings::panthor_device_alloc() },
+                pdev: pdev.clone(),
+            },
+            GFP_KERNEL,
+        )?;
+
+        let drm = drm::device::Device::<PanthorDriver>::new(pdev.as_ref(), data.clone())?;
+
+        unsafe {
+            (*data.ptdev).base = drm.as_raw();
+            panthor_device_init(data.ptdev);
+        }
+
+        drm::drv::Registration::new_foreign_owned(drm.clone(), 0)?;
+
+        dev_info!(pdev.as_ref(), "Probed!\n");
+        Ok(KBox::new(Self(drm), GFP_KERNEL)?.into())
+    }
+}
+
+impl Drop for PanthorDriver {
+    fn drop(&mut self) {
+        let data = self.0.data();
+
+        dev_dbg!(data.pdev.as_ref(), "Remove Panthor GPU driver.\n");
+    }
+}
diff --git a/drivers/gpu/drm/panthor-rs/file.rs b/drivers/gpu/drm/panthor-rs/file.rs
new file mode 100644
index 0000000000000..1146fbefda5bf
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/file.rs
@@ -0,0 +1,164 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+#![allow(clippy::unusual_byte_groupings)]
+
+//! File implementation, which represents a single DRM client.
+//!
+//! This is in charge of managing the resources associated with one GPU client, including an
+//! arbitrary number of submission queues and Vm objects, and reporting hardware/driver
+//! information to userspace and accepting submissions.
+
+//use crate::debug::*;
+use crate::driver::PanthorDevice;
+use crate::driver::PanthorDriver;
+//use crate::{alloc, buffer, driver, gem, mmu, queue, util::RangeExt};
+//use kernel::drm::gem::BaseObject;
+//use kernel::io_buffer::{IoBufferReader, IoBufferWriter};
+use core;
+use core::ffi;
+use core::ptr;
+use kernel::prelude::*;
+use kernel::{
+    drm::file::GenericFile,
+    drm::{self, device::Device as DrmDevice},
+    error::to_result,
+    uapi,
+};
+
+/// Convenience type alias for our DRM `File` type.
+pub(crate) type DrmFile = drm::file::File<File>;
+
+/// State associated with a client.
+pub(crate) struct File();
+
+impl drm::file::DriverFile for File {
+    type Driver = PanthorDriver;
+
+    fn open(_dev: &DrmDevice<Self::Driver>) -> Result<Pin<Box<Self>>> {
+        pr_info!("DRM Device :: open()\n");
+
+        Ok(Box::into_pin(Box::new(Self(), GFP_KERNEL)?))
+    }
+}
+
+impl File {
+    /// IOCTL: dev_query
+    pub(crate) fn dev_query(
+        device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_dev_query,
+        _file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: vm_create
+    pub(crate) fn vm_create(
+        device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_vm_create,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: vm_destroy
+    pub(crate) fn vm_destroy(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_vm_destroy,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: vm_bind
+    pub(crate) fn vm_bind(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_vm_bind,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: vm_get_state
+    pub(crate) fn vm_get_state(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_vm_get_state,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: bo_create
+    pub(crate) fn bo_create(
+        device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_bo_create,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: bo_mmap_offset
+    pub(crate) fn bo_mmap_offset(
+        _device: &PanthorDevice,
+        _data: &mut uapi::drm_panthor_bo_mmap_offset,
+        _file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: group_create
+    pub(crate) fn group_create(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_group_create,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: group_destroy
+    pub(crate) fn group_destroy(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_group_destroy,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: group_get_state
+    pub(crate) fn group_get_state(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_group_get_state,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: tiler_heap_create
+    pub(crate) fn tiler_heap_create(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_tiler_heap_create,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: tiler_heap_destroy
+    pub(crate) fn tiler_heap_destroy(
+        _device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_tiler_heap_destroy,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+
+    /// IOCTL: group_submit
+    pub(crate) fn group_submit(
+        device: &PanthorDevice,
+        data: &mut uapi::drm_panthor_group_submit,
+        file: &DrmFile,
+    ) -> Result<u32> {
+        Ok(0)
+    }
+}
+
+impl Drop for File {
+    fn drop(&mut self) {}
+}
diff --git a/drivers/gpu/drm/panthor-rs/gem.rs b/drivers/gpu/drm/panthor-rs/gem.rs
new file mode 100644
index 0000000000000..8e824bcd591f9
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/gem.rs
@@ -0,0 +1,29 @@
+use core::sync::atomic::{AtomicU64, Ordering};
+
+use kernel::{drm::gem, prelude::*};
+
+use crate::driver::{PanthorDevice, PanthorDriver};
+
+static GEM_ID: AtomicU64 = AtomicU64::new(0);
+
+/// GEM Object implementation
+#[pin_data]
+pub(crate) struct DriverObject {
+    /// ID for debugging
+    id: u64,
+}
+
+pub(crate) type Object = gem::Object<DriverObject>;
+
+impl gem::BaseDriverObject<Object> for DriverObject {
+    fn new(_dev: &PanthorDevice, _size: usize) -> impl PinInit<Self, Error> {
+        let id = GEM_ID.fetch_add(1, Ordering::Relaxed);
+
+        pr_debug!("DriverObject::new() id={}\n", id);
+        DriverObject { id }
+    }
+}
+
+impl gem::DriverObject for DriverObject {
+    type Driver = PanthorDriver;
+}
diff --git a/drivers/gpu/drm/panthor-rs/panthor.rs b/drivers/gpu/drm/panthor-rs/panthor.rs
new file mode 100644
index 0000000000000..a177f8b6eee9e
--- /dev/null
+++ b/drivers/gpu/drm/panthor-rs/panthor.rs
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-only OR MIT
+#![recursion_limit = "2048"]
+
+//! Driver for the Arm Mali CSF-based GPUs.
+
+#![allow(improper_ctypes)]
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+mod driver;
+mod file;
+mod gem;
+
+use kernel::module_platform_driver;
+
+module_platform_driver! {
+    type: driver::PanthorDriver,
+    name: "panthor_rs",
+    author: "Arm",
+    license: "Dual MIT/GPL",
+}
diff --git a/drivers/gpu/drm/panthor-rs/panthor_device.c b/drivers/gpu/drm/panthor-rs/panthor_device.c
index 6dcc4b55c05a0..e4a88a8dcb4e1 100644
--- a/drivers/gpu/drm/panthor-rs/panthor_device.c
+++ b/drivers/gpu/drm/panthor-rs/panthor_device.c
@@ -271,6 +271,13 @@ int panthor_device_init(struct panthor_device *ptdev)
 	return ret;
 }
 
+struct panthor_device *panthor_device_alloc(void)
+{
+	struct panthor_device *ptdev = kzalloc(sizeof(struct panthor_device), GFP_KERNEL);
+	return ptdev;
+}
+
+
 #define PANTHOR_EXCEPTION(id) \
 	[DRM_PANTHOR_EXCEPTION_ ## id] = { \
 		.name = #id, \
diff --git a/drivers/gpu/drm/panthor-rs/panthor_device.h b/drivers/gpu/drm/panthor-rs/panthor_device.h
index 2bdf6270d0680..cfc832110b3ec 100644
--- a/drivers/gpu/drm/panthor-rs/panthor_device.h
+++ b/drivers/gpu/drm/panthor-rs/panthor_device.h
@@ -180,6 +180,8 @@ struct panthor_file {
 };
 
 int panthor_device_init(struct panthor_device *ptdev);
+struct panthor_device *panthor_device_alloc(void);
+
 void panthor_device_unplug(struct panthor_device *ptdev);
 
 /**
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index e1ddee135d12a..8de125de72254 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -32,6 +32,8 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 
+#include <../drivers/gpu/drm/panthor-rs/panthor_device.h>
+
 /* `bindgen` gets confused at certain things. */
 const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
 const size_t RUST_CONST_HELPER_PAGE_SIZE = PAGE_SIZE;
diff --git a/rust/kernel/drm/gem/mod.rs b/rust/kernel/drm/gem/mod.rs
index e4e060d93ad12..d0baf52b7a624 100644
--- a/rust/kernel/drm/gem/mod.rs
+++ b/rust/kernel/drm/gem/mod.rs
@@ -412,5 +412,6 @@ pub(super) const fn create_fops() -> bindings::file_operations {
     fops.mmap = Some(bindings::drm_gem_mmap);
     fops.fop_flags = bindings::FOP_UNSIGNED_OFFSET;
 
+    fops.fop_flags = 1 << 5; // FIXME use FOP_UNSIGNED_OFFSET
     fops
 }
diff --git a/rust/uapi/uapi_helper.h b/rust/uapi/uapi_helper.h
index 19587e55e6041..7a78013c3ecb5 100644
--- a/rust/uapi/uapi_helper.h
+++ b/rust/uapi/uapi_helper.h
@@ -8,6 +8,7 @@
 
 #include <uapi/asm-generic/ioctl.h>
 #include <uapi/drm/drm.h>
+#include <uapi/drm/panthor_drm.h>
 #include <uapi/linux/mdio.h>
 #include <uapi/linux/mii.h>
 #include <uapi/linux/ethtool.h>
-- 
GitLab