xref: /linux/drivers/gpu/nova-core/dma.rs (revision 220994d61cebfc04f071d69049127657c7e8191b)
19bcc046aSAlexandre Courbot // SPDX-License-Identifier: GPL-2.0
29bcc046aSAlexandre Courbot 
39bcc046aSAlexandre Courbot //! Simple DMA object wrapper.
49bcc046aSAlexandre Courbot 
59bcc046aSAlexandre Courbot use core::ops::{Deref, DerefMut};
69bcc046aSAlexandre Courbot 
79bcc046aSAlexandre Courbot use kernel::device;
89bcc046aSAlexandre Courbot use kernel::dma::CoherentAllocation;
99bcc046aSAlexandre Courbot use kernel::page::PAGE_SIZE;
109bcc046aSAlexandre Courbot use kernel::prelude::*;
119bcc046aSAlexandre Courbot 
129bcc046aSAlexandre Courbot pub(crate) struct DmaObject {
139bcc046aSAlexandre Courbot     dma: CoherentAllocation<u8>,
149bcc046aSAlexandre Courbot }
159bcc046aSAlexandre Courbot 
169bcc046aSAlexandre Courbot impl DmaObject {
new(dev: &device::Device<device::Bound>, len: usize) -> Result<Self>179bcc046aSAlexandre Courbot     pub(crate) fn new(dev: &device::Device<device::Bound>, len: usize) -> Result<Self> {
189bcc046aSAlexandre Courbot         let len = core::alloc::Layout::from_size_align(len, PAGE_SIZE)
199bcc046aSAlexandre Courbot             .map_err(|_| EINVAL)?
209bcc046aSAlexandre Courbot             .pad_to_align()
219bcc046aSAlexandre Courbot             .size();
229bcc046aSAlexandre Courbot         let dma = CoherentAllocation::alloc_coherent(dev, len, GFP_KERNEL | __GFP_ZERO)?;
239bcc046aSAlexandre Courbot 
249bcc046aSAlexandre Courbot         Ok(Self { dma })
259bcc046aSAlexandre Courbot     }
269bcc046aSAlexandre Courbot 
from_data(dev: &device::Device<device::Bound>, data: &[u8]) -> Result<Self>279bcc046aSAlexandre Courbot     pub(crate) fn from_data(dev: &device::Device<device::Bound>, data: &[u8]) -> Result<Self> {
289bcc046aSAlexandre Courbot         Self::new(dev, data.len()).map(|mut dma_obj| {
29*3606620bSAlexandre Courbot             // TODO[COHA]: replace with `CoherentAllocation::write()` once available.
309bcc046aSAlexandre Courbot             // SAFETY:
319bcc046aSAlexandre Courbot             // - `dma_obj`'s size is at least `data.len()`.
329bcc046aSAlexandre Courbot             // - We have just created this object and there is no other user at this stage.
339bcc046aSAlexandre Courbot             unsafe {
349bcc046aSAlexandre Courbot                 core::ptr::copy_nonoverlapping(
359bcc046aSAlexandre Courbot                     data.as_ptr(),
369bcc046aSAlexandre Courbot                     dma_obj.dma.start_ptr_mut(),
379bcc046aSAlexandre Courbot                     data.len(),
389bcc046aSAlexandre Courbot                 );
399bcc046aSAlexandre Courbot             }
409bcc046aSAlexandre Courbot 
419bcc046aSAlexandre Courbot             dma_obj
429bcc046aSAlexandre Courbot         })
439bcc046aSAlexandre Courbot     }
449bcc046aSAlexandre Courbot }
459bcc046aSAlexandre Courbot 
469bcc046aSAlexandre Courbot impl Deref for DmaObject {
479bcc046aSAlexandre Courbot     type Target = CoherentAllocation<u8>;
489bcc046aSAlexandre Courbot 
deref(&self) -> &Self::Target499bcc046aSAlexandre Courbot     fn deref(&self) -> &Self::Target {
509bcc046aSAlexandre Courbot         &self.dma
519bcc046aSAlexandre Courbot     }
529bcc046aSAlexandre Courbot }
539bcc046aSAlexandre Courbot 
549bcc046aSAlexandre Courbot impl DerefMut for DmaObject {
deref_mut(&mut self) -> &mut Self::Target559bcc046aSAlexandre Courbot     fn deref_mut(&mut self) -> &mut Self::Target {
569bcc046aSAlexandre Courbot         &mut self.dma
579bcc046aSAlexandre Courbot     }
589bcc046aSAlexandre Courbot }
59