Skip to content

Commit 30062f0

Browse files
hoshinolinajannau
authored andcommitted
drm/asahi: file: Implement ASAHI_GEM_BIND_OBJECT
Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent 8453ae5 commit 30062f0

2 files changed

Lines changed: 149 additions & 0 deletions

File tree

drivers/gpu/drm/asahi/driver.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ impl drv::Driver for AsahiDriver {
8585
ioctl::AUTH | ioctl::RENDER_ALLOW, crate::file::File::submit),
8686
(ASAHI_GET_TIME, drm_asahi_get_time,
8787
ioctl::AUTH | ioctl::RENDER_ALLOW, crate::file::File::get_time),
88+
(ASAHI_GEM_BIND_OBJECT, drm_asahi_gem_bind_object,
89+
ioctl::AUTH | ioctl::RENDER_ALLOW, crate::file::File::gem_bind_object),
8890
}
8991
}
9092

drivers/gpu/drm/asahi/file.rs

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,16 @@ impl SyncItem {
160160
}
161161
}
162162

163+
pub(crate) enum Object {
164+
TimestampBuffer(Arc<mmu::KernelMapping>),
165+
}
166+
163167
/// State associated with a client.
164168
pub(crate) struct File {
165169
id: u64,
166170
vms: xarray::XArray<KBox<Vm>>,
167171
queues: xarray::XArray<Arc<Mutex<KBox<dyn queue::Queue>>>>,
172+
objects: xarray::XArray<KBox<Object>>,
168173
}
169174

170175
/// Convenience type alias for our DRM `File` type.
@@ -192,6 +197,7 @@ impl drm::file::DriverFile for File {
192197
id,
193198
vms: xarray::XArray::new(xarray::flags::ALLOC1),
194199
queues: xarray::XArray::new(xarray::flags::ALLOC1),
200+
objects: xarray::XArray::new(xarray::flags::ALLOC1),
195201
},
196202
GFP_KERNEL,
197203
)?)
@@ -212,6 +218,12 @@ impl File {
212218
unsafe { self.map_unchecked(|s| &s.queues) }
213219
}
214220

221+
fn objects(self: Pin<&Self>) -> Pin<&xarray::XArray<KBox<Object>>> {
222+
// SAFETY: Structural pinned projection for objects.
223+
// We never move out of this field.
224+
unsafe { self.map_unchecked(|s| &s.objects) }
225+
}
226+
215227
/// IOCTL: get_param: Get a driver parameter value.
216228
pub(crate) fn get_params(
217229
device: &AsahiDevice,
@@ -721,6 +733,141 @@ impl File {
721733
Ok(0)
722734
}
723735

736+
/// IOCTL: gem_bind_object: Map or unmap a GEM object as a special object.
737+
pub(crate) fn gem_bind_object(
738+
device: &AsahiDevice,
739+
data: &mut uapi::drm_asahi_gem_bind_object,
740+
file: &DrmFile,
741+
) -> Result<u32> {
742+
mod_dev_dbg!(
743+
device,
744+
"[File {} VM {}]: IOCTL: gem_bind_object op={:?} handle={:#x?} flags={:#x?} {:#x?}:{:#x?} object_handle={:#x?}\n",
745+
file.inner().id,
746+
data.vm_id,
747+
data.op,
748+
data.handle,
749+
data.flags,
750+
data.offset,
751+
data.range,
752+
data.object_handle
753+
);
754+
755+
if data.extensions != 0 {
756+
cls_pr_debug!(Errors, "gem_bind_object: Unexpected extensions\n");
757+
return Err(EINVAL);
758+
}
759+
760+
if data.pad != 0 {
761+
cls_pr_debug!(Errors, "gem_bind_object: Unexpected pad\n");
762+
return Err(EINVAL);
763+
}
764+
765+
if data.vm_id != 0 {
766+
cls_pr_debug!(Errors, "gem_bind_object: Unexpected vm_id\n");
767+
return Err(EINVAL);
768+
}
769+
770+
match data.op {
771+
uapi::drm_asahi_bind_object_op_ASAHI_BIND_OBJECT_OP_BIND => {
772+
Self::do_gem_bind_object(device, data, file)
773+
}
774+
uapi::drm_asahi_bind_object_op_ASAHI_BIND_OBJECT_OP_UNBIND => {
775+
Self::do_gem_unbind_object(device, data, file)
776+
}
777+
_ => {
778+
cls_pr_debug!(Errors, "gem_bind_object: Invalid op {}\n", data.op);
779+
Err(EINVAL)
780+
}
781+
}
782+
}
783+
784+
pub(crate) fn do_gem_bind_object(
785+
device: &AsahiDevice,
786+
data: &mut uapi::drm_asahi_gem_bind_object,
787+
file: &DrmFile,
788+
) -> Result<u32> {
789+
if (data.range | data.offset) as usize & mmu::UAT_PGMSK != 0 {
790+
cls_pr_debug!(
791+
Errors,
792+
"gem_bind_object: Range/offset not page aligned: {:#x} {:#x}\n",
793+
data.range,
794+
data.offset
795+
);
796+
return Err(EINVAL); // Must be page aligned
797+
}
798+
799+
if data.flags != uapi::ASAHI_BIND_OBJECT_USAGE_TIMESTAMPS {
800+
cls_pr_debug!(Errors, "gem_bind_object: Invalid flags {:#x}\n", data.flags);
801+
return Err(EINVAL);
802+
}
803+
804+
let offset = data.offset.try_into()?;
805+
let end_offset = data
806+
.offset
807+
.checked_add(data.range)
808+
.ok_or(EINVAL)?
809+
.try_into()?;
810+
let bo = gem::lookup_handle(file, data.handle)?;
811+
812+
let mapping = Arc::new(
813+
device
814+
.data()
815+
.gpu
816+
.map_timestamp_buffer(bo, offset..end_offset)?,
817+
GFP_KERNEL,
818+
)?;
819+
let obj = KBox::new(Object::TimestampBuffer(mapping), GFP_KERNEL)?;
820+
let handle = file.inner().objects().alloc(obj)? as u64;
821+
822+
data.object_handle = handle as u32;
823+
Ok(0)
824+
}
825+
826+
pub(crate) fn do_gem_unbind_object(
827+
_device: &AsahiDevice,
828+
data: &mut uapi::drm_asahi_gem_bind_object,
829+
file: &DrmFile,
830+
) -> Result<u32> {
831+
if data.range != 0 || data.offset != 0 {
832+
cls_pr_debug!(
833+
Errors,
834+
"gem_unbind_object: Range/offset not zero: {:#x} {:#x}\n",
835+
data.range,
836+
data.offset
837+
);
838+
return Err(EINVAL);
839+
}
840+
841+
if data.flags != 0 {
842+
cls_pr_debug!(
843+
Errors,
844+
"gem_unbind_object: Invalid flags {:#x}\n",
845+
data.flags
846+
);
847+
return Err(EINVAL);
848+
}
849+
850+
if data.handle != 0 {
851+
cls_pr_debug!(
852+
Errors,
853+
"gem_unbind_object: Invalid handle {}\n",
854+
data.handle
855+
);
856+
return Err(EINVAL);
857+
}
858+
859+
if file
860+
.inner()
861+
.objects()
862+
.remove(data.object_handle as usize)
863+
.is_none()
864+
{
865+
Err(ENOENT)
866+
} else {
867+
Ok(0)
868+
}
869+
}
870+
724871
/// IOCTL: queue_create: Create a new command submission queue of a given type.
725872
pub(crate) fn queue_create(
726873
device: &AsahiDevice,

0 commit comments

Comments
 (0)