xref: /linux/drivers/gpu/nova-core/gsp/fw/commands.rs (revision 53597deca0e38c30e6cd4ba2114fa42d2bcd85bb)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 use kernel::{
4     device,
5     pci,
6     prelude::*,
7     transmute::{
8         AsBytes,
9         FromBytes, //
10     }, //
11 };
12 
13 use crate::gsp::GSP_PAGE_SIZE;
14 
15 use super::bindings;
16 
17 /// Payload of the `GspSetSystemInfo` command.
18 #[repr(transparent)]
19 pub(crate) struct GspSetSystemInfo {
20     inner: bindings::GspSystemInfo,
21 }
22 static_assert!(size_of::<GspSetSystemInfo>() < GSP_PAGE_SIZE);
23 
24 impl GspSetSystemInfo {
25     /// Returns an in-place initializer for the `GspSetSystemInfo` command.
26     #[allow(non_snake_case)]
27     pub(crate) fn init<'a>(dev: &'a pci::Device<device::Bound>) -> impl Init<Self, Error> + 'a {
28         type InnerGspSystemInfo = bindings::GspSystemInfo;
29         let init_inner = try_init!(InnerGspSystemInfo {
30             gpuPhysAddr: dev.resource_start(0)?,
31             gpuPhysFbAddr: dev.resource_start(1)?,
32             gpuPhysInstAddr: dev.resource_start(3)?,
33             nvDomainBusDeviceFunc: u64::from(dev.dev_id()),
34 
35             // Using TASK_SIZE in r535_gsp_rpc_set_system_info() seems wrong because
36             // TASK_SIZE is per-task. That's probably a design issue in GSP-RM though.
37             maxUserVa: (1 << 47) - 4096,
38             pciConfigMirrorBase: 0x088000,
39             pciConfigMirrorSize: 0x001000,
40 
41             PCIDeviceID: (u32::from(dev.device_id()) << 16) | u32::from(dev.vendor_id().as_raw()),
42             PCISubDeviceID: (u32::from(dev.subsystem_device_id()) << 16)
43                 | u32::from(dev.subsystem_vendor_id()),
44             PCIRevisionID: u32::from(dev.revision_id()),
45             bIsPrimary: 0,
46             bPreserveVideoMemoryAllocations: 0,
47             ..Zeroable::init_zeroed()
48         });
49 
50         try_init!(GspSetSystemInfo {
51             inner <- init_inner,
52         })
53     }
54 }
55 
56 // SAFETY: These structs don't meet the no-padding requirements of AsBytes but
57 //         that is not a problem because they are not used outside the kernel.
58 unsafe impl AsBytes for GspSetSystemInfo {}
59 
60 // SAFETY: These structs don't meet the no-padding requirements of FromBytes but
61 //         that is not a problem because they are not used outside the kernel.
62 unsafe impl FromBytes for GspSetSystemInfo {}
63 
64 #[repr(transparent)]
65 pub(crate) struct PackedRegistryEntry(bindings::PACKED_REGISTRY_ENTRY);
66 
67 impl PackedRegistryEntry {
68     pub(crate) fn new(offset: u32, value: u32) -> Self {
69         Self({
70             bindings::PACKED_REGISTRY_ENTRY {
71                 nameOffset: offset,
72 
73                 // We only support DWORD types for now. Support for other types
74                 // will come later if required.
75                 type_: bindings::REGISTRY_TABLE_ENTRY_TYPE_DWORD as u8,
76                 __bindgen_padding_0: Default::default(),
77                 data: value,
78                 length: 0,
79             }
80         })
81     }
82 }
83 
84 // SAFETY: Padding is explicit and will not contain uninitialized data.
85 unsafe impl AsBytes for PackedRegistryEntry {}
86 
87 /// Payload of the `SetRegistry` command.
88 #[repr(transparent)]
89 pub(crate) struct PackedRegistryTable {
90     inner: bindings::PACKED_REGISTRY_TABLE,
91 }
92 
93 impl PackedRegistryTable {
94     #[allow(non_snake_case)]
95     pub(crate) fn init(num_entries: u32, size: u32) -> impl Init<Self> {
96         type InnerPackedRegistryTable = bindings::PACKED_REGISTRY_TABLE;
97         let init_inner = init!(InnerPackedRegistryTable {
98             numEntries: num_entries,
99             size,
100             entries: Default::default()
101         });
102 
103         init!(PackedRegistryTable { inner <- init_inner })
104     }
105 }
106 
107 // SAFETY: Padding is explicit and will not contain uninitialized data.
108 unsafe impl AsBytes for PackedRegistryTable {}
109 
110 // SAFETY: This struct only contains integer types for which all bit patterns
111 // are valid.
112 unsafe impl FromBytes for PackedRegistryTable {}
113 
114 /// Payload of the `GetGspStaticInfo` command and message.
115 #[repr(transparent)]
116 #[derive(Zeroable)]
117 pub(crate) struct GspStaticConfigInfo(bindings::GspStaticConfigInfo_t);
118 
119 impl GspStaticConfigInfo {
120     /// Returns a bytes array containing the (hopefully) zero-terminated name of this GPU.
121     pub(crate) fn gpu_name_str(&self) -> [u8; 64] {
122         self.0.gpuNameString
123     }
124 }
125 
126 // SAFETY: Padding is explicit and will not contain uninitialized data.
127 unsafe impl AsBytes for GspStaticConfigInfo {}
128 
129 // SAFETY: This struct only contains integer types for which all bit patterns
130 // are valid.
131 unsafe impl FromBytes for GspStaticConfigInfo {}
132