| 1 | |
| 2 |
|
| 3 | use super::*;
|
| 4 |
|
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | #[repr(C)]
|
| 14 | #[pin_data]
|
| 15 | pub struct GpuVmBo<T: DriverGpuVm> {
|
| 16 | #[pin]
|
| 17 | inner: Opaque<bindings::drm_gpuvm_bo>,
|
| 18 | #[pin]
|
| 19 | data: T::VmBoData,
|
| 20 | }
|
| 21 |
|
| 22 | |
| 23 | |
| 24 | unsafe impl<T: DriverGpuVm> Send for GpuVmBo<T> {}
|
| 25 |
|
| 26 | |
| 27 | |
| 28 | |
| 29 | unsafe impl<T: DriverGpuVm> Sync for GpuVmBo<T> {}
|
| 30 |
|
| 31 | |
| 32 | unsafe impl<T: DriverGpuVm> AlwaysRefCounted for GpuVmBo<T> {
|
| 33 | fn inc_ref(&self) {
|
| 34 | |
| 35 | unsafe { bindings::drm_gpuvm_bo_get(self.inner.get()) };
|
| 36 | }
|
| 37 |
|
| 38 | unsafe fn dec_ref(obj: NonNull<Self>) {
|
| 39 | |
| 40 | |
| 41 | |
| 42 | |
| 43 | unsafe { bindings::drm_gpuvm_bo_put_deferred(obj.as_ptr().cast()) };
|
| 44 | }
|
| 45 | }
|
| 46 |
|
| 47 | impl<T: DriverGpuVm> PartialEq for GpuVmBo<T> {
|
| 48 | #[inline]
|
| 49 | fn eq(&self, other: &Self) -> bool {
|
| 50 | core::ptr::eq(self.as_raw(), other.as_raw())
|
| 51 | }
|
| 52 | }
|
| 53 | impl<T: DriverGpuVm> Eq for GpuVmBo<T> {}
|
| 54 |
|
| 55 | impl<T: DriverGpuVm> GpuVmBo<T> {
|
| 56 | |
| 57 | |
| 58 | |
| 59 | |
| 60 | |
| 61 | |
| 62 | pub(super) const ALLOC_FN: Option<unsafe extern "C" fn() -> *mut bindings::drm_gpuvm_bo> = {
|
| 63 | use core::alloc::Layout;
|
| 64 | let base = Layout::new::<bindings::drm_gpuvm_bo>();
|
| 65 | let rust = Layout::new::<Self>();
|
| 66 | assert!(base.size() <= rust.size());
|
| 67 | if base.size() != rust.size() || base.align() != rust.align() {
|
| 68 | Some(Self::vm_bo_alloc)
|
| 69 | } else {
|
| 70 | |
| 71 | None
|
| 72 | }
|
| 73 | };
|
| 74 |
|
| 75 | |
| 76 | |
| 77 | |
| 78 | |
| 79 | |
| 80 | |
| 81 | pub(super) const FREE_FN: Option<unsafe extern "C" fn(*mut bindings::drm_gpuvm_bo)> = {
|
| 82 | if core::mem::needs_drop::<Self>() {
|
| 83 | Some(Self::vm_bo_free)
|
| 84 | } else {
|
| 85 | |
| 86 | None
|
| 87 | }
|
| 88 | };
|
| 89 |
|
| 90 | |
| 91 | |
| 92 | |
| 93 | |
| 94 | |
| 95 | unsafe extern "C" fn vm_bo_alloc() -> *mut bindings::drm_gpuvm_bo {
|
| 96 | let raw_ptr = KBox::<Self>::new_uninit(GFP_KERNEL | __GFP_ZERO)
|
| 97 | .map(KBox::into_raw)
|
| 98 | .unwrap_or(ptr::null_mut());
|
| 99 |
|
| 100 | |
| 101 | raw_ptr.cast()
|
| 102 | }
|
| 103 |
|
| 104 | |
| 105 | |
| 106 | |
| 107 | |
| 108 | |
| 109 | |
| 110 | unsafe extern "C" fn vm_bo_free(ptr: *mut bindings::drm_gpuvm_bo) {
|
| 111 | |
| 112 | |
| 113 | |
| 114 | |
| 115 | |
| 116 | drop(unsafe { KBox::<Self>::from_raw(ptr.cast()) });
|
| 117 | }
|
| 118 |
|
| 119 | |
| 120 | |
| 121 | |
| 122 | |
| 123 | |
| 124 | |
| 125 | #[inline]
|
| 126 | pub(crate) unsafe fn from_raw<'a>(ptr: *mut bindings::drm_gpuvm_bo) -> &'a Self {
|
| 127 | |
| 128 | unsafe { &*ptr.cast() }
|
| 129 | }
|
| 130 |
|
| 131 | |
| 132 | #[inline]
|
| 133 | pub fn as_raw(&self) -> *mut bindings::drm_gpuvm_bo {
|
| 134 | self.inner.get()
|
| 135 | }
|
| 136 |
|
| 137 | |
| 138 | #[inline]
|
| 139 | pub fn gpuvm(&self) -> &GpuVm<T> {
|
| 140 | |
| 141 | unsafe { GpuVm::<T>::from_raw((*self.inner.get()).vm) }
|
| 142 | }
|
| 143 |
|
| 144 | |
| 145 | #[inline]
|
| 146 | pub fn obj(&self) -> &T::Object {
|
| 147 | |
| 148 | unsafe { <T::Object as IntoGEMObject>::from_raw((*self.inner.get()).obj) }
|
| 149 | }
|
| 150 |
|
| 151 | |
| 152 | #[inline]
|
| 153 | pub fn data(&self) -> &T::VmBoData {
|
| 154 | &self.data
|
| 155 | }
|
| 156 |
|
| 157 | pub(super) fn lock_gpuva(&self) -> crate::sync::MutexGuard<'_, ()> {
|
| 158 | |
| 159 | let ptr = unsafe { &raw mut (*self.obj().as_raw()).gpuva.lock };
|
| 160 | |
| 161 | let mutex = unsafe { crate::sync::Mutex::from_raw(ptr) };
|
| 162 | mutex.lock()
|
| 163 | }
|
| 164 | }
|
| 165 |
|
| 166 | |
| 167 | |
| 168 | |
| 169 | |
| 170 | |
| 171 | |
| 172 | pub(super) struct GpuVmBoAlloc<T: DriverGpuVm>(NonNull<GpuVmBo<T>>);
|
| 173 |
|
| 174 | impl<T: DriverGpuVm> GpuVmBoAlloc<T> {
|
| 175 | |
| 176 | |
| 177 | |
| 178 | |
| 179 | #[inline]
|
| 180 | pub(super) fn new(
|
| 181 | gpuvm: &GpuVm<T>,
|
| 182 | gem: &T::Object,
|
| 183 | value: impl PinInit<T::VmBoData>,
|
| 184 | ) -> Result<GpuVmBoAlloc<T>, AllocError> {
|
| 185 | |
| 186 | |
| 187 | |
| 188 | let raw_ptr = unsafe {
|
| 189 | bindings::drm_gpuvm_bo_create(gpuvm.as_raw(), gem.as_raw()).cast::<GpuVmBo<T>>()
|
| 190 | };
|
| 191 | let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
|
| 192 | |
| 193 | unsafe { pin_init::raw_init(&raw mut (*raw_ptr).data, value) };
|
| 194 | |
| 195 | |
| 196 | Ok(GpuVmBoAlloc(ptr))
|
| 197 | }
|
| 198 |
|
| 199 | |
| 200 | #[inline]
|
| 201 | pub(super) fn as_raw(&self) -> *mut bindings::drm_gpuvm_bo {
|
| 202 | |
| 203 | unsafe { (*self.0.as_ptr()).inner.get() }
|
| 204 | }
|
| 205 |
|
| 206 | |
| 207 | |
| 208 | |
| 209 | #[inline]
|
| 210 | pub(super) fn obtain(self) -> ARef<GpuVmBo<T>> {
|
| 211 | let me = ManuallyDrop::new(self);
|
| 212 | |
| 213 | |
| 214 | let ptr = unsafe { bindings::drm_gpuvm_bo_obtain_prealloc(me.as_raw()) };
|
| 215 |
|
| 216 | |
| 217 | let nonnull = unsafe { NonNull::new_unchecked(ptr.cast()) };
|
| 218 |
|
| 219 | |
| 220 | |
| 221 | let ret = unsafe { ARef::<GpuVmBo<T>>::from_raw(nonnull) };
|
| 222 |
|
| 223 | |
| 224 | |
| 225 | |
| 226 | |
| 227 | if ret.gpuvm().is_extobj(ret.obj()) {
|
| 228 | let resv_lock = ret.gpuvm().raw_resv();
|
| 229 | |
| 230 | |
| 231 | unsafe { bindings::dma_resv_lock(resv_lock, ptr::null_mut()) };
|
| 232 | |
| 233 | unsafe { bindings::drm_gpuvm_bo_extobj_add(ptr) };
|
| 234 | |
| 235 | unsafe { bindings::dma_resv_unlock(resv_lock) };
|
| 236 | }
|
| 237 |
|
| 238 | ret
|
| 239 | }
|
| 240 | }
|
| 241 |
|
| 242 | impl<T: DriverGpuVm> Deref for GpuVmBoAlloc<T> {
|
| 243 | type Target = GpuVmBo<T>;
|
| 244 | #[inline]
|
| 245 | fn deref(&self) -> &GpuVmBo<T> {
|
| 246 | |
| 247 | unsafe { self.0.as_ref() }
|
| 248 | }
|
| 249 | }
|
| 250 |
|
| 251 | impl<T: DriverGpuVm> Drop for GpuVmBoAlloc<T> {
|
| 252 | #[inline]
|
| 253 | fn drop(&mut self) {
|
| 254 | |
| 255 | |
| 256 | unsafe { bindings::drm_gpuvm_bo_put_deferred(self.as_raw()) };
|
| 257 | }
|
| 258 | }
|