@@ -57,10 +57,9 @@ pub trait Device: AsRef<device::Device> {
5757/// # Examples
5858///
5959/// ```
60- /// use kernel::device::Device;
61- /// use kernel::dma::{attrs::*, CoherentAllocation};
60+ /// use kernel::dma::{attrs::*, Device, CoherentAllocation};
6261///
63- /// # fn test(dev: &Device) -> Result {
62+ /// # fn test(dev: &dyn Device) -> Result {
6463/// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN;
6564/// let c: CoherentAllocation<u64> =
6665/// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, attribs)?;
@@ -178,16 +177,15 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
178177 /// # Examples
179178 ///
180179 /// ```
181- /// use kernel::device::Device;
182- /// use kernel::dma::{attrs::*, CoherentAllocation};
180+ /// use kernel::dma::{attrs::*, Device, CoherentAllocation};
183181 ///
184- /// # fn test(dev: &Device) -> Result {
182+ /// # fn test(dev: &dyn Device) -> Result {
185183 /// let c: CoherentAllocation<u64> =
186184 /// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
187185 /// # Ok::<(), Error>(()) }
188186 /// ```
189187 pub fn alloc_attrs (
190- dev : & device :: Device ,
188+ dev : & dyn Device ,
191189 count : usize ,
192190 gfp_flags : kernel:: alloc:: Flags ,
193191 dma_attrs : Attrs ,
@@ -197,6 +195,8 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
197195 "It doesn't make sense for the allocated type to be a ZST"
198196 ) ;
199197
198+ let dev = dev. as_ref ( ) ;
199+
200200 let size = count
201201 . checked_mul ( core:: mem:: size_of :: < T > ( ) )
202202 . ok_or ( EOVERFLOW ) ?;
@@ -229,7 +229,7 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
229229 /// Performs the same functionality as [`CoherentAllocation::alloc_attrs`], except the
230230 /// `dma_attrs` is 0 by default.
231231 pub fn alloc_coherent (
232- dev : & device :: Device ,
232+ dev : & dyn Device ,
233233 count : usize ,
234234 gfp_flags : kernel:: alloc:: Flags ,
235235 ) -> Result < CoherentAllocation < T > > {
@@ -253,6 +253,93 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
253253 self . dma_handle
254254 }
255255
256+ /// Returns the data from the region starting from `offset` as a slice.
257+ /// `offset` and `count` are in units of `T`, not the number of bytes.
258+ ///
259+ /// Due to the safety requirements of slice, the caller should consider that the region could
260+ /// be modified by the device at anytime. For ringbuffer type of r/w access or use-cases where
261+ /// the pointer to the live data is needed, `start_ptr()` or `start_ptr_mut()` could be
262+ /// used instead.
263+ ///
264+ /// # Safety
265+ ///
266+ /// * Callers must ensure that no hardware operations that involve the buffer are currently
267+ /// taking place while the returned slice is live.
268+ /// * Callers must ensure that this call does not race with a write to the same region while
269+ /// while the returned slice is live.
270+ pub unsafe fn as_slice ( & self , offset : usize , count : usize ) -> Result < & [ T ] > {
271+ let end = offset. checked_add ( count) . ok_or ( EOVERFLOW ) ?;
272+ if end >= self . count {
273+ return Err ( EINVAL ) ;
274+ }
275+ // SAFETY:
276+ // - The pointer is valid due to type invariant on `CoherentAllocation`,
277+ // we've just checked that the range and index is within bounds. The immutability of the
278+ // of data is also guaranteed by the safety requirements of the function.
279+ // - `offset` can't overflow since it is smaller than `self.count` and we've checked
280+ // that `self.count` won't overflow early in the constructor.
281+ Ok ( unsafe { core:: slice:: from_raw_parts ( self . cpu_addr . add ( offset) , count) } )
282+ }
283+
284+ /// Performs the same functionality as [`CoherentAllocation::as_slice`], except that a mutable
285+ /// slice is returned.
286+ ///
287+ /// # Safety
288+ ///
289+ /// * Callers must ensure that no hardware operations that involve the buffer are currently
290+ /// taking place while the returned slice is live.
291+ /// * Callers must ensure that this call does not race with a read or write to the same region
292+ /// while the returned slice is live.
293+ pub unsafe fn as_slice_mut ( & self , offset : usize , count : usize ) -> Result < & mut [ T ] > {
294+ let end = offset. checked_add ( count) . ok_or ( EOVERFLOW ) ?;
295+ if end >= self . count {
296+ return Err ( EINVAL ) ;
297+ }
298+ // SAFETY:
299+ // - The pointer is valid due to type invariant on `CoherentAllocation`,
300+ // we've just checked that the range and index is within bounds. The immutability of the
301+ // of data is also guaranteed by the safety requirements of the function.
302+ // - `offset` can't overflow since it is smaller than `self.count` and we've checked
303+ // that `self.count` won't overflow early in the constructor.
304+ Ok ( unsafe { core:: slice:: from_raw_parts_mut ( self . cpu_addr . add ( offset) , count) } )
305+ }
306+
307+ /// Writes data to the region starting from `offset`. `offset` is in units of `T`, not the
308+ /// number of bytes.
309+ ///
310+ /// # Safety
311+ ///
312+ /// * Callers must ensure that no hardware operations that involve the buffer overlaps with
313+ /// this write.
314+ /// * Callers must ensure that this call does not race with a read or write to the same region
315+ /// that overlaps with this write.
316+ ///
317+ /// # Examples
318+ ///
319+ /// ```
320+ /// # fn test(alloc: &mut kernel::dma::CoherentAllocation<u8>) -> Result {
321+ /// let somedata: [u8; 4] = [0xf; 4];
322+ /// let buf: &[u8] = &somedata;
323+ /// // SAFETY: No hw operation on the device and no other r/w access to the region at this point.
324+ /// unsafe { alloc.write(buf, 0)?; }
325+ /// # Ok::<(), Error>(()) }
326+ /// ```
327+ pub unsafe fn write ( & self , src : & [ T ] , offset : usize ) -> Result {
328+ let end = offset. checked_add ( src. len ( ) ) . ok_or ( EOVERFLOW ) ?;
329+ if end >= self . count {
330+ return Err ( EINVAL ) ;
331+ }
332+ // SAFETY:
333+ // - The pointer is valid due to type invariant on `CoherentAllocation`
334+ // and we've just checked that the range and index is within bounds.
335+ // - `offset` can't overflow since it is smaller than `self.count` and we've checked
336+ // that `self.count` won't overflow early in the constructor.
337+ unsafe {
338+ core:: ptr:: copy_nonoverlapping ( src. as_ptr ( ) , self . cpu_addr . add ( offset) , src. len ( ) )
339+ } ;
340+ Ok ( ( ) )
341+ }
342+
256343 /// Returns a pointer to an element from the region with bounds checking. `offset` is in
257344 /// units of `T`, not the number of bytes.
258345 ///
0 commit comments