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