Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/samples/rust/rust_dma.rs
26282 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
//! Rust DMA api test (based on QEMU's `pci-testdev`).
4
//!
5
//! To make this driver probe, QEMU must be run with `-device pci-testdev`.
6
7
use kernel::{
8
bindings,
9
device::Core,
10
dma::{CoherentAllocation, Device, DmaMask},
11
pci,
12
prelude::*,
13
types::ARef,
14
};
15
16
struct DmaSampleDriver {
17
pdev: ARef<pci::Device>,
18
ca: CoherentAllocation<MyStruct>,
19
}
20
21
const TEST_VALUES: [(u32, u32); 5] = [
22
(0xa, 0xb),
23
(0xc, 0xd),
24
(0xe, 0xf),
25
(0xab, 0xba),
26
(0xcd, 0xef),
27
];
28
29
struct MyStruct {
30
h: u32,
31
b: u32,
32
}
33
34
impl MyStruct {
35
fn new(h: u32, b: u32) -> Self {
36
Self { h, b }
37
}
38
}
39
// SAFETY: All bit patterns are acceptable values for `MyStruct`.
40
unsafe impl kernel::transmute::AsBytes for MyStruct {}
41
// SAFETY: Instances of `MyStruct` have no uninitialized portions.
42
unsafe impl kernel::transmute::FromBytes for MyStruct {}
43
44
kernel::pci_device_table!(
45
PCI_TABLE,
46
MODULE_PCI_TABLE,
47
<DmaSampleDriver as pci::Driver>::IdInfo,
48
[(
49
pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, 0x5),
50
()
51
)]
52
);
53
54
impl pci::Driver for DmaSampleDriver {
55
type IdInfo = ();
56
const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
57
58
fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
59
dev_info!(pdev.as_ref(), "Probe DMA test driver.\n");
60
61
let mask = DmaMask::new::<64>();
62
63
// SAFETY: There are no concurrent calls to DMA allocation and mapping primitives.
64
unsafe { pdev.dma_set_mask_and_coherent(mask)? };
65
66
let ca: CoherentAllocation<MyStruct> =
67
CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?;
68
69
for (i, value) in TEST_VALUES.into_iter().enumerate() {
70
kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1))?;
71
}
72
73
let drvdata = KBox::new(
74
Self {
75
pdev: pdev.into(),
76
ca,
77
},
78
GFP_KERNEL,
79
)?;
80
81
Ok(drvdata.into())
82
}
83
}
84
85
impl Drop for DmaSampleDriver {
86
fn drop(&mut self) {
87
dev_info!(self.pdev.as_ref(), "Unload DMA test driver.\n");
88
89
for (i, value) in TEST_VALUES.into_iter().enumerate() {
90
let val0 = kernel::dma_read!(self.ca[i].h);
91
let val1 = kernel::dma_read!(self.ca[i].b);
92
assert!(val0.is_ok());
93
assert!(val1.is_ok());
94
95
if let Ok(val0) = val0 {
96
assert_eq!(val0, value.0);
97
}
98
if let Ok(val1) = val1 {
99
assert_eq!(val1, value.1);
100
}
101
}
102
}
103
}
104
105
kernel::module_pci_driver! {
106
type: DmaSampleDriver,
107
name: "rust_dma",
108
authors: ["Abdiel Janulgue"],
109
description: "Rust DMA test",
110
license: "GPL v2",
111
}
112
113