Skip to content
Snippets Groups Projects
Commit b42257b1 authored by Rob Herring's avatar Rob Herring
Browse files

drm: panthor-rs: Hook-up ioctls to C code


All but bo_mmap_offset hooked up.

Signed-off-by: default avatarRob Herring (Arm) <robh@kernel.org>
parent f09289f2
No related tags found
No related merge requests found
# SPDX-License-Identifier: GPL-2.0 or MIT
panthor_rs-y := \
panthor_devfreq.o \
panthor_device.o \
panthor_drv.o \
panthor_fw.o \
panthor_gem.o \
panthor_gpu.o \
panthor_heap.o \
panthor_mmu.o \
panthor_sched.o \
panthor.o
obj-$(CONFIG_DRM_PANTHOR_RS) += panthor_rs.o
......
......@@ -18,15 +18,58 @@ use core::ffi;
use core::ptr;
use kernel::prelude::*;
use kernel::{
bindings,
drm::file::GenericFile,
drm::{self, device::Device as DrmDevice},
error::to_result,
uaccess::UserSlice,
uapi,
};
/// Convenience type alias for our DRM `File` type.
pub(crate) type DrmFile = drm::file::File<File>;
extern "C" {
fn _panthor_ioctl_dev_query(
ptdev: *mut bindings::panthor_device,
args: *mut uapi::drm_panthor_dev_query,
) -> ffi::c_int;
fn panthor_vm_pool_create_vm(
ptdev: *mut bindings::panthor_device,
pool: *mut bindings::panthor_vm_pool,
data: *mut uapi::drm_panthor_vm_create,
) -> ffi::c_int;
fn panthor_ioctl_vm_bind_async(
args: *mut uapi::drm_panthor_vm_bind,
file: *mut bindings::drm_file,
) -> ffi::c_int;
fn panthor_ioctl_vm_bind_sync(
args: *mut uapi::drm_panthor_vm_bind,
file: *mut bindings::drm_file,
) -> ffi::c_int;
fn panthor_group_submit(
ddev: *mut bindings::drm_device,
args: *mut uapi::drm_panthor_group_submit,
file: *mut bindings::drm_file,
) -> core::ffi::c_int;
fn panthor_tiler_heap_create(
pfile: *mut bindings::panthor_file,
args: *mut uapi::drm_panthor_tiler_heap_create,
) -> core::ffi::c_int;
fn panthor_tiler_heap_destroy(
pfile: *mut bindings::panthor_file,
args: *const uapi::drm_panthor_tiler_heap_destroy,
) -> core::ffi::c_int;
fn _panthor_group_create(
args: *mut uapi::drm_panthor_group_create,
pfile: *mut bindings::panthor_file,
) -> core::ffi::c_int;
fn panthor_group_get_state(
pfile: *mut bindings::panthor_file,
get_state: *mut uapi::drm_panthor_group_get_state,
) -> core::ffi::c_int;
}
/// State associated with a client.
#[repr(C)]
pub(crate) struct File {
......@@ -56,6 +99,12 @@ impl drm::file::DriverFile for File {
}
}
fn struct_to_slice<T>(data: &T) -> &[u8] {
let ptr = data as *const T as *const u8;
let len = core::mem::size_of::<T>();
unsafe { core::slice::from_raw_parts(ptr, len) }
}
impl File {
/// IOCTL: dev_query
pub(crate) fn dev_query(
......@@ -63,6 +112,38 @@ impl File {
data: &mut uapi::drm_panthor_dev_query,
_file: &DrmFile,
) -> Result<u32> {
if data.pointer == 0 {
let size = match data.type_ {
uapi::drm_panthor_dev_query_type_DRM_PANTHOR_DEV_QUERY_GPU_INFO => {
core::mem::size_of::<uapi::drm_panthor_gpu_info>()
}
uapi::drm_panthor_dev_query_type_DRM_PANTHOR_DEV_QUERY_CSIF_INFO => {
core::mem::size_of::<uapi::drm_panthor_csif_info>()
}
_ => return Err(EINVAL),
};
data.size = size as u32;
return Ok(0);
}
let mut write = UserSlice::new(data.pointer as usize, data.size as usize).writer();
let ptdev = device.data().ptdev;
match data.type_ {
// TODO: worry about userspace expect old, smaller size struct
uapi::drm_panthor_dev_query_type_DRM_PANTHOR_DEV_QUERY_GPU_INFO => {
write.write_slice(struct_to_slice::<kernel::bindings::drm_panthor_gpu_info>(
unsafe { &(*ptdev).gpu_info },
))?
}
uapi::drm_panthor_dev_query_type_DRM_PANTHOR_DEV_QUERY_CSIF_INFO => {
write.write_slice(struct_to_slice::<kernel::bindings::drm_panthor_csif_info>(
unsafe { &(*ptdev).csif_info },
))?
}
_ => return Err(EINVAL),
};
Ok(0)
}
......@@ -72,6 +153,16 @@ impl File {
data: &mut uapi::drm_panthor_vm_create,
file: &DrmFile,
) -> Result<u32> {
let devdata = device.data();
to_result(unsafe {
let pfile: *mut bindings::panthor_file = (*file.raw()).driver_priv as *mut _;
let id = panthor_vm_pool_create_vm(devdata.ptdev, (*pfile).vms, data);
if id >= 0 {
data.id = id.try_into()?;
}
id
})?;
Ok(0)
}
......@@ -81,6 +172,14 @@ impl File {
data: &mut uapi::drm_panthor_vm_destroy,
file: &DrmFile,
) -> Result<u32> {
if data.pad != 0 {
return Err(EINVAL);
}
to_result(unsafe {
let pfile: *mut bindings::panthor_file = (*file.raw()).driver_priv as *mut _;
bindings::panthor_vm_pool_destroy_vm((*pfile).vms, data.id)
})?;
Ok(0)
}
......@@ -90,6 +189,13 @@ impl File {
data: &mut uapi::drm_panthor_vm_bind,
file: &DrmFile,
) -> Result<u32> {
//TODO: drm_dev_enter(device., &cookie))
if data.flags == uapi::drm_panthor_vm_bind_flags_DRM_PANTHOR_VM_BIND_ASYNC {
to_result(unsafe { panthor_ioctl_vm_bind_async(data, file.raw() as *mut _) })?;
} else {
to_result(unsafe { panthor_ioctl_vm_bind_sync(data, file.raw() as *mut _) })?;
}
Ok(0)
}
......@@ -99,6 +205,20 @@ impl File {
data: &mut uapi::drm_panthor_vm_get_state,
file: &DrmFile,
) -> Result<u32> {
let pfile: *mut bindings::panthor_file = unsafe { (*file.raw()).driver_priv as *mut _ };
let vm = unsafe { bindings::panthor_vm_pool_get_vm((*pfile).vms, data.vm_id) };
if vm.is_null() {
return Err(EINVAL);
}
if unsafe { bindings::panthor_vm_is_unusable(vm) } {
data.state = uapi::drm_panthor_vm_state_DRM_PANTHOR_VM_STATE_UNUSABLE;
} else {
data.state = uapi::drm_panthor_vm_state_DRM_PANTHOR_VM_STATE_USABLE;
}
unsafe { bindings::panthor_vm_put(vm) };
Ok(0)
}
......@@ -108,6 +228,40 @@ impl File {
data: &mut uapi::drm_panthor_bo_create,
file: &DrmFile,
) -> Result<u32> {
//TODO if (!drm_dev_enter(ddev, &cookie))
// return -ENODEV;
if data.size == 0
|| data.pad != 0
|| (data.flags & !uapi::drm_panthor_bo_flags_DRM_PANTHOR_BO_NO_MMAP != 0)
{
return Err(EINVAL);
}
let mut vm = ptr::null_mut();
if data.exclusive_vm_id != 0 {
let pfile: *mut bindings::panthor_file = unsafe { (*file.raw()).driver_priv as *mut _ };
vm = unsafe { bindings::panthor_vm_pool_get_vm((*pfile).vms, data.exclusive_vm_id) };
if vm.is_null() {
return Err(EINVAL);
}
}
let ret = unsafe {
let ptdev = device.data().ptdev;
bindings::panthor_gem_create_with_handle(
file.raw() as *mut _,
(*ptdev).base,
vm,
&mut data.size as *mut _,
data.flags,
&mut data.handle as *mut _,
)
};
unsafe { bindings::panthor_vm_put(vm) };
to_result(ret)?;
Ok(0)
}
......@@ -120,12 +274,38 @@ impl File {
Ok(0)
}
fn _group_priority_permit(file: &DrmFile, priority: u32) -> Result<u32> {
/* Ensure that priority is valid */
if priority > uapi::drm_panthor_group_priority_PANTHOR_GROUP_PRIORITY_HIGH {
return Err(EINVAL);
}
/* Medium priority and below are always allowed */
if priority <= uapi::drm_panthor_group_priority_PANTHOR_GROUP_PRIORITY_MEDIUM {
return Ok(0);
}
/* Higher priorities require CAP_SYS_NICE or DRM_MASTER */
if unsafe { bindings::capable(uapi::CAP_SYS_NICE.try_into().unwrap()) }
|| file.is_current_master()
{
return Ok(0);
}
Err(EACCES)
}
/// IOCTL: group_create
pub(crate) fn group_create(
_device: &PanthorDevice,
data: &mut uapi::drm_panthor_group_create,
file: &DrmFile,
) -> Result<u32> {
let pfile: *mut bindings::panthor_file = unsafe { (*file.raw()).driver_priv as *mut _ };
Self::_group_priority_permit(file, data.priority.into())?;
to_result(unsafe { _panthor_group_create(data, pfile) })?;
Ok(0)
}
......@@ -135,6 +315,13 @@ impl File {
data: &mut uapi::drm_panthor_group_destroy,
file: &DrmFile,
) -> Result<u32> {
if data.pad != 0 {
return Err(EINVAL);
}
let pfile: *mut bindings::panthor_file = unsafe { (*file.raw()).driver_priv as *mut _ };
to_result(unsafe { bindings::panthor_group_destroy(pfile, data.group_handle) })?;
Ok(0)
}
......@@ -144,6 +331,9 @@ impl File {
data: &mut uapi::drm_panthor_group_get_state,
file: &DrmFile,
) -> Result<u32> {
let pfile: *mut bindings::panthor_file = unsafe { (*file.raw()).driver_priv as *mut _ };
to_result(unsafe { panthor_group_get_state(pfile, data) })?;
Ok(0)
}
......@@ -153,6 +343,9 @@ impl File {
data: &mut uapi::drm_panthor_tiler_heap_create,
file: &DrmFile,
) -> Result<u32> {
let pfile: *mut bindings::panthor_file = unsafe { (*file.raw()).driver_priv as *mut _ };
to_result(unsafe { panthor_tiler_heap_create(pfile, data) })?;
Ok(0)
}
......@@ -162,6 +355,9 @@ impl File {
data: &mut uapi::drm_panthor_tiler_heap_destroy,
file: &DrmFile,
) -> Result<u32> {
let pfile: *mut bindings::panthor_file = unsafe { (*file.raw()).driver_priv as *mut _ };
to_result(unsafe { panthor_tiler_heap_destroy(pfile, data) })?;
Ok(0)
}
......@@ -171,6 +367,10 @@ impl File {
data: &mut uapi::drm_panthor_group_submit,
file: &DrmFile,
) -> Result<u32> {
to_result(unsafe {
let ptdev = device.data().ptdev;
panthor_group_submit((*ptdev).base, data, file.raw() as *mut _)
})?;
Ok(0)
}
}
......
......@@ -747,140 +747,12 @@ static void panthor_submit_ctx_cleanup(struct panthor_submit_ctx *ctx,
kvfree(ctx->jobs);
}
static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct drm_file *file)
{
struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base);
struct drm_panthor_dev_query *args = data;
if (!args->pointer) {
switch (args->type) {
case DRM_PANTHOR_DEV_QUERY_GPU_INFO:
args->size = sizeof(ptdev->gpu_info);
return 0;
case DRM_PANTHOR_DEV_QUERY_CSIF_INFO:
args->size = sizeof(ptdev->csif_info);
return 0;
default:
return -EINVAL;
}
}
switch (args->type) {
case DRM_PANTHOR_DEV_QUERY_GPU_INFO:
return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->gpu_info);
case DRM_PANTHOR_DEV_QUERY_CSIF_INFO:
return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->csif_info);
default:
return -EINVAL;
}
}
#define PANTHOR_VM_CREATE_FLAGS 0
static int panthor_ioctl_vm_create(struct drm_device *ddev, void *data,
struct drm_file *file)
{
struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base);
struct panthor_file *pfile = file->driver_priv;
struct drm_panthor_vm_create *args = data;
int cookie, ret;
if (!drm_dev_enter(ddev, &cookie))
return -ENODEV;
ret = panthor_vm_pool_create_vm(ptdev, pfile->vms, args);
if (ret >= 0) {
args->id = ret;
ret = 0;
}
drm_dev_exit(cookie);
return ret;
}
static int panthor_ioctl_vm_destroy(struct drm_device *ddev, void *data,
struct drm_file *file)
{
struct panthor_file *pfile = file->driver_priv;
struct drm_panthor_vm_destroy *args = data;
if (args->pad)
return -EINVAL;
return panthor_vm_pool_destroy_vm(pfile->vms, args->id);
}
#define PANTHOR_BO_FLAGS DRM_PANTHOR_BO_NO_MMAP
static int panthor_ioctl_bo_create(struct drm_device *ddev, void *data,
struct drm_file *file)
int panthor_group_submit(struct drm_device *ddev, struct drm_panthor_group_submit *args,
struct drm_file *file)
{
struct panthor_file *pfile = file->driver_priv;
struct drm_panthor_bo_create *args = data;
struct panthor_vm *vm = NULL;
int cookie, ret;
if (!drm_dev_enter(ddev, &cookie))
return -ENODEV;
if (!args->size || args->pad ||
(args->flags & ~PANTHOR_BO_FLAGS)) {
ret = -EINVAL;
goto out_dev_exit;
}
if (args->exclusive_vm_id) {
vm = panthor_vm_pool_get_vm(pfile->vms, args->exclusive_vm_id);
if (!vm) {
ret = -EINVAL;
goto out_dev_exit;
}
}
ret = panthor_gem_create_with_handle(file, ddev, vm, &args->size,
args->flags, &args->handle);
panthor_vm_put(vm);
out_dev_exit:
drm_dev_exit(cookie);
return ret;
}
static int panthor_ioctl_bo_mmap_offset(struct drm_device *ddev, void *data,
struct drm_file *file)
{
struct drm_panthor_bo_mmap_offset *args = data;
struct drm_gem_object *obj;
int ret;
if (args->pad)
return -EINVAL;
obj = drm_gem_object_lookup(file, args->handle);
if (!obj)
return -ENOENT;
ret = drm_gem_create_mmap_offset(obj);
if (ret)
goto out;
args->offset = drm_vma_node_offset_addr(&obj->vma_node);
out:
drm_gem_object_put(obj);
return ret;
}
static int panthor_ioctl_group_submit(struct drm_device *ddev, void *data,
struct drm_file *file)
{
struct panthor_file *pfile = file->driver_priv;
struct drm_panthor_group_submit *args = data;
struct drm_panthor_queue_submit *jobs_args;
struct panthor_submit_ctx ctx;
int ret = 0, cookie;
......@@ -981,41 +853,9 @@ static int panthor_ioctl_group_submit(struct drm_device *ddev, void *data,
return ret;
}
static int panthor_ioctl_group_destroy(struct drm_device *ddev, void *data,
struct drm_file *file)
{
struct panthor_file *pfile = file->driver_priv;
struct drm_panthor_group_destroy *args = data;
if (args->pad)
return -EINVAL;
return panthor_group_destroy(pfile, args->group_handle);
}
static int group_priority_permit(struct drm_file *file,
u8 priority)
int _panthor_group_create(struct drm_panthor_group_create *args,
struct panthor_file *pfile)
{
/* Ensure that priority is valid */
if (priority > PANTHOR_GROUP_PRIORITY_HIGH)
return -EINVAL;
/* Medium priority and below are always allowed */
if (priority <= PANTHOR_GROUP_PRIORITY_MEDIUM)
return 0;
/* Higher priorities require CAP_SYS_NICE or DRM_MASTER */
if (capable(CAP_SYS_NICE) || drm_is_current_master(file))
return 0;
return -EACCES;
}
static int panthor_ioctl_group_create(struct drm_device *ddev, void *data,
struct drm_file *file)
{
struct panthor_file *pfile = file->driver_priv;
struct drm_panthor_group_create *args = data;
struct drm_panthor_queue_create *queue_args;
int ret;
......@@ -1026,10 +866,6 @@ static int panthor_ioctl_group_create(struct drm_device *ddev, void *data,
if (ret)
return ret;
ret = group_priority_permit(file, args->priority);
if (ret)
return ret;
ret = panthor_group_create(pfile, args, queue_args);
if (ret >= 0) {
args->group_handle = ret;
......@@ -1040,20 +876,9 @@ static int panthor_ioctl_group_create(struct drm_device *ddev, void *data,
return ret;
}
static int panthor_ioctl_group_get_state(struct drm_device *ddev, void *data,
struct drm_file *file)
{
struct panthor_file *pfile = file->driver_priv;
struct drm_panthor_group_get_state *args = data;
return panthor_group_get_state(pfile, args);
}
static int panthor_ioctl_tiler_heap_create(struct drm_device *ddev, void *data,
struct drm_file *file)
int panthor_tiler_heap_create(struct panthor_file *pfile,
struct drm_panthor_tiler_heap_create *args)
{
struct panthor_file *pfile = file->driver_priv;
struct drm_panthor_tiler_heap_create *args = data;
struct panthor_heap_pool *pool;
struct panthor_vm *vm;
int ret;
......@@ -1092,11 +917,9 @@ static int panthor_ioctl_tiler_heap_create(struct drm_device *ddev, void *data,
return ret;
}
static int panthor_ioctl_tiler_heap_destroy(struct drm_device *ddev, void *data,
struct drm_file *file)
int panthor_tiler_heap_destroy(struct panthor_file *pfile,
const struct drm_panthor_tiler_heap_destroy *args)
{
struct panthor_file *pfile = file->driver_priv;
struct drm_panthor_tiler_heap_destroy *args = data;
struct panthor_heap_pool *pool;
struct panthor_vm *vm;
int ret;
......@@ -1122,8 +945,7 @@ static int panthor_ioctl_tiler_heap_destroy(struct drm_device *ddev, void *data,
return ret;
}
static int panthor_ioctl_vm_bind_async(struct drm_device *ddev,
struct drm_panthor_vm_bind *args,
int panthor_ioctl_vm_bind_async(struct drm_panthor_vm_bind *args,
struct drm_file *file)
{
struct panthor_file *pfile = file->driver_priv;
......@@ -1191,8 +1013,7 @@ static int panthor_ioctl_vm_bind_async(struct drm_device *ddev,
return ret;
}
static int panthor_ioctl_vm_bind_sync(struct drm_device *ddev,
struct drm_panthor_vm_bind *args,
int panthor_ioctl_vm_bind_sync(struct drm_panthor_vm_bind *args,
struct drm_file *file)
{
struct panthor_file *pfile = file->driver_priv;
......@@ -1224,46 +1045,6 @@ static int panthor_ioctl_vm_bind_sync(struct drm_device *ddev,
return ret;
}
#define PANTHOR_VM_BIND_FLAGS DRM_PANTHOR_VM_BIND_ASYNC
static int panthor_ioctl_vm_bind(struct drm_device *ddev, void *data,
struct drm_file *file)
{
struct drm_panthor_vm_bind *args = data;
int cookie, ret;
if (!drm_dev_enter(ddev, &cookie))
return -ENODEV;
if (args->flags & DRM_PANTHOR_VM_BIND_ASYNC)
ret = panthor_ioctl_vm_bind_async(ddev, args, file);
else
ret = panthor_ioctl_vm_bind_sync(ddev, args, file);
drm_dev_exit(cookie);
return ret;
}
static int panthor_ioctl_vm_get_state(struct drm_device *ddev, void *data,
struct drm_file *file)
{
struct panthor_file *pfile = file->driver_priv;
struct drm_panthor_vm_get_state *args = data;
struct panthor_vm *vm;
vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id);
if (!vm)
return -EINVAL;
if (panthor_vm_is_unusable(vm))
args->state = DRM_PANTHOR_VM_STATE_UNUSABLE;
else
args->state = DRM_PANTHOR_VM_STATE_USABLE;
panthor_vm_put(vm);
return 0;
}
static void
panthor_postclose(struct drm_device *ddev, struct drm_file *file)
{
......
......@@ -33,6 +33,9 @@
#include <linux/workqueue.h>
#include <../drivers/gpu/drm/panthor-rs/panthor_device.h>
#include <../drivers/gpu/drm/panthor-rs/panthor_gem.h>
#include <../drivers/gpu/drm/panthor-rs/panthor_mmu.h>
#include <../drivers/gpu/drm/panthor-rs/panthor_sched.h>
/* `bindgen` gets confused at certain things. */
const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment