xref: /linux/drivers/gpu/nova-core/dma.rs (revision 9bcc046a929f73358bf23678306b31d927a7e088)
1*9bcc046aSAlexandre Courbot // SPDX-License-Identifier: GPL-2.0
2*9bcc046aSAlexandre Courbot 
3*9bcc046aSAlexandre Courbot //! Simple DMA object wrapper.
4*9bcc046aSAlexandre Courbot 
5*9bcc046aSAlexandre Courbot // To be removed when all code is used.
6*9bcc046aSAlexandre Courbot #![expect(dead_code)]
7*9bcc046aSAlexandre Courbot 
8*9bcc046aSAlexandre Courbot use core::ops::{Deref, DerefMut};
9*9bcc046aSAlexandre Courbot 
10*9bcc046aSAlexandre Courbot use kernel::device;
11*9bcc046aSAlexandre Courbot use kernel::dma::CoherentAllocation;
12*9bcc046aSAlexandre Courbot use kernel::page::PAGE_SIZE;
13*9bcc046aSAlexandre Courbot use kernel::prelude::*;
14*9bcc046aSAlexandre Courbot 
15*9bcc046aSAlexandre Courbot pub(crate) struct DmaObject {
16*9bcc046aSAlexandre Courbot     dma: CoherentAllocation<u8>,
17*9bcc046aSAlexandre Courbot }
18*9bcc046aSAlexandre Courbot 
19*9bcc046aSAlexandre Courbot impl DmaObject {
20*9bcc046aSAlexandre Courbot     pub(crate) fn new(dev: &device::Device<device::Bound>, len: usize) -> Result<Self> {
21*9bcc046aSAlexandre Courbot         let len = core::alloc::Layout::from_size_align(len, PAGE_SIZE)
22*9bcc046aSAlexandre Courbot             .map_err(|_| EINVAL)?
23*9bcc046aSAlexandre Courbot             .pad_to_align()
24*9bcc046aSAlexandre Courbot             .size();
25*9bcc046aSAlexandre Courbot         let dma = CoherentAllocation::alloc_coherent(dev, len, GFP_KERNEL | __GFP_ZERO)?;
26*9bcc046aSAlexandre Courbot 
27*9bcc046aSAlexandre Courbot         Ok(Self { dma })
28*9bcc046aSAlexandre Courbot     }
29*9bcc046aSAlexandre Courbot 
30*9bcc046aSAlexandre Courbot     pub(crate) fn from_data(dev: &device::Device<device::Bound>, data: &[u8]) -> Result<Self> {
31*9bcc046aSAlexandre Courbot         Self::new(dev, data.len()).map(|mut dma_obj| {
32*9bcc046aSAlexandre Courbot             // TODO: replace with `CoherentAllocation::write()` once available.
33*9bcc046aSAlexandre Courbot             // SAFETY:
34*9bcc046aSAlexandre Courbot             // - `dma_obj`'s size is at least `data.len()`.
35*9bcc046aSAlexandre Courbot             // - We have just created this object and there is no other user at this stage.
36*9bcc046aSAlexandre Courbot             unsafe {
37*9bcc046aSAlexandre Courbot                 core::ptr::copy_nonoverlapping(
38*9bcc046aSAlexandre Courbot                     data.as_ptr(),
39*9bcc046aSAlexandre Courbot                     dma_obj.dma.start_ptr_mut(),
40*9bcc046aSAlexandre Courbot                     data.len(),
41*9bcc046aSAlexandre Courbot                 );
42*9bcc046aSAlexandre Courbot             }
43*9bcc046aSAlexandre Courbot 
44*9bcc046aSAlexandre Courbot             dma_obj
45*9bcc046aSAlexandre Courbot         })
46*9bcc046aSAlexandre Courbot     }
47*9bcc046aSAlexandre Courbot }
48*9bcc046aSAlexandre Courbot 
49*9bcc046aSAlexandre Courbot impl Deref for DmaObject {
50*9bcc046aSAlexandre Courbot     type Target = CoherentAllocation<u8>;
51*9bcc046aSAlexandre Courbot 
52*9bcc046aSAlexandre Courbot     fn deref(&self) -> &Self::Target {
53*9bcc046aSAlexandre Courbot         &self.dma
54*9bcc046aSAlexandre Courbot     }
55*9bcc046aSAlexandre Courbot }
56*9bcc046aSAlexandre Courbot 
57*9bcc046aSAlexandre Courbot impl DerefMut for DmaObject {
58*9bcc046aSAlexandre Courbot     fn deref_mut(&mut self) -> &mut Self::Target {
59*9bcc046aSAlexandre Courbot         &mut self.dma
60*9bcc046aSAlexandre Courbot     }
61*9bcc046aSAlexandre Courbot }
62