Skip to content

Commit b8bca76

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

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
@@ -86,6 +86,8 @@ impl drv::Driver for AsahiDriver {
8686
ioctl::AUTH | ioctl::RENDER_ALLOW, crate::file::File::submit),
8787
(ASAHI_GET_TIME, drm_asahi_get_time,
8888
ioctl::AUTH | ioctl::RENDER_ALLOW, crate::file::File::get_time),
89+
(ASAHI_GEM_BIND_OBJECT, drm_asahi_gem_bind_object,
90+
ioctl::AUTH | ioctl::RENDER_ALLOW, crate::file::File::gem_bind_object),
8991
}
9092
}
9193

drivers/gpu/drm/asahi/file.rs

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

165+
pub(crate) enum Object {
166+
TimestampBuffer(Arc<mmu::KernelMapping>),
167+
}
168+
165169
/// State associated with a client.
166170
pub(crate) struct File {
167171
id: u64,
168172
vms: xarray::XArray<KBox<Vm>>,
169173
queues: xarray::XArray<Arc<Mutex<KBox<dyn queue::Queue>>>>,
174+
objects: xarray::XArray<KBox<Object>>,
170175
}
171176

172177
/// Convenience type alias for our DRM `File` type.
@@ -197,6 +202,7 @@ impl drm::file::DriverFile for File {
197202
id,
198203
vms: xarray::XArray::new(xarray::flags::ALLOC1),
199204
queues: xarray::XArray::new(xarray::flags::ALLOC1),
205+
objects: xarray::XArray::new(xarray::flags::ALLOC1),
200206
},
201207
GFP_KERNEL,
202208
)?)
@@ -217,6 +223,12 @@ impl File {
217223
unsafe { self.map_unchecked(|s| &s.queues) }
218224
}
219225

226+
fn objects(self: Pin<&Self>) -> Pin<&xarray::XArray<KBox<Object>>> {
227+
// SAFETY: Structural pinned projection for objects.
228+
// We never move out of this field.
229+
unsafe { self.map_unchecked(|s| &s.objects) }
230+
}
231+
220232
/// IOCTL: get_param: Get a driver parameter value.
221233
pub(crate) fn get_params(
222234
device: &AsahiDevice,
@@ -733,6 +745,141 @@ impl File {
733745
Ok(0)
734746
}
735747

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

0 commit comments

Comments
 (0)