Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/gpu/nova-core/gsp/commands.rs
38186 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
use core::{
4
array,
5
convert::Infallible, //
6
};
7
8
use kernel::{
9
device,
10
pci,
11
prelude::*,
12
time::Delta,
13
transmute::{
14
AsBytes,
15
FromBytes, //
16
}, //
17
};
18
19
use crate::{
20
driver::Bar0,
21
gsp::{
22
cmdq::{
23
Cmdq,
24
CommandToGsp,
25
MessageFromGsp, //
26
},
27
fw::{
28
commands::*,
29
MsgFunction, //
30
},
31
},
32
sbuffer::SBufferIter,
33
util,
34
};
35
36
/// The `GspSetSystemInfo` command.
37
pub(crate) struct SetSystemInfo<'a> {
38
pdev: &'a pci::Device<device::Bound>,
39
}
40
41
impl<'a> SetSystemInfo<'a> {
42
/// Creates a new `GspSetSystemInfo` command using the parameters of `pdev`.
43
pub(crate) fn new(pdev: &'a pci::Device<device::Bound>) -> Self {
44
Self { pdev }
45
}
46
}
47
48
impl<'a> CommandToGsp for SetSystemInfo<'a> {
49
const FUNCTION: MsgFunction = MsgFunction::GspSetSystemInfo;
50
type Command = GspSetSystemInfo;
51
type InitError = Error;
52
53
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
54
GspSetSystemInfo::init(self.pdev)
55
}
56
}
57
58
struct RegistryEntry {
59
key: &'static str,
60
value: u32,
61
}
62
63
/// The `SetRegistry` command.
64
pub(crate) struct SetRegistry {
65
entries: [RegistryEntry; Self::NUM_ENTRIES],
66
}
67
68
impl SetRegistry {
69
// For now we hard-code the registry entries. Future work will allow others to
70
// be added as module parameters.
71
const NUM_ENTRIES: usize = 3;
72
73
/// Creates a new `SetRegistry` command, using a set of hardcoded entries.
74
pub(crate) fn new() -> Self {
75
Self {
76
entries: [
77
// RMSecBusResetEnable - enables PCI secondary bus reset
78
RegistryEntry {
79
key: "RMSecBusResetEnable",
80
value: 1,
81
},
82
// RMForcePcieConfigSave - forces GSP-RM to preserve PCI configuration registers on
83
// any PCI reset.
84
RegistryEntry {
85
key: "RMForcePcieConfigSave",
86
value: 1,
87
},
88
// RMDevidCheckIgnore - allows GSP-RM to boot even if the PCI dev ID is not found
89
// in the internal product name database.
90
RegistryEntry {
91
key: "RMDevidCheckIgnore",
92
value: 1,
93
},
94
],
95
}
96
}
97
}
98
99
impl CommandToGsp for SetRegistry {
100
const FUNCTION: MsgFunction = MsgFunction::SetRegistry;
101
type Command = PackedRegistryTable;
102
type InitError = Infallible;
103
104
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
105
PackedRegistryTable::init(Self::NUM_ENTRIES as u32, self.variable_payload_len() as u32)
106
}
107
108
fn variable_payload_len(&self) -> usize {
109
let mut key_size = 0;
110
for i in 0..Self::NUM_ENTRIES {
111
key_size += self.entries[i].key.len() + 1; // +1 for NULL terminator
112
}
113
Self::NUM_ENTRIES * size_of::<PackedRegistryEntry>() + key_size
114
}
115
116
fn init_variable_payload(
117
&self,
118
dst: &mut SBufferIter<core::array::IntoIter<&mut [u8], 2>>,
119
) -> Result {
120
let string_data_start_offset =
121
size_of::<PackedRegistryTable>() + Self::NUM_ENTRIES * size_of::<PackedRegistryEntry>();
122
123
// Array for string data.
124
let mut string_data = KVec::new();
125
126
for entry in self.entries.iter().take(Self::NUM_ENTRIES) {
127
dst.write_all(
128
PackedRegistryEntry::new(
129
(string_data_start_offset + string_data.len()) as u32,
130
entry.value,
131
)
132
.as_bytes(),
133
)?;
134
135
let key_bytes = entry.key.as_bytes();
136
string_data.extend_from_slice(key_bytes, GFP_KERNEL)?;
137
string_data.push(0, GFP_KERNEL)?;
138
}
139
140
dst.write_all(string_data.as_slice())
141
}
142
}
143
144
/// Message type for GSP initialization done notification.
145
struct GspInitDone {}
146
147
// SAFETY: `GspInitDone` is a zero-sized type with no bytes, therefore it
148
// trivially has no uninitialized bytes.
149
unsafe impl FromBytes for GspInitDone {}
150
151
impl MessageFromGsp for GspInitDone {
152
const FUNCTION: MsgFunction = MsgFunction::GspInitDone;
153
type InitError = Infallible;
154
type Message = GspInitDone;
155
156
fn read(
157
_msg: &Self::Message,
158
_sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>,
159
) -> Result<Self, Self::InitError> {
160
Ok(GspInitDone {})
161
}
162
}
163
164
/// Waits for GSP initialization to complete.
165
pub(crate) fn wait_gsp_init_done(cmdq: &mut Cmdq) -> Result {
166
loop {
167
match cmdq.receive_msg::<GspInitDone>(Delta::from_secs(10)) {
168
Ok(_) => break Ok(()),
169
Err(ERANGE) => continue,
170
Err(e) => break Err(e),
171
}
172
}
173
}
174
175
/// The `GetGspStaticInfo` command.
176
struct GetGspStaticInfo;
177
178
impl CommandToGsp for GetGspStaticInfo {
179
const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;
180
type Command = GspStaticConfigInfo;
181
type InitError = Infallible;
182
183
fn init(&self) -> impl Init<Self::Command, Self::InitError> {
184
GspStaticConfigInfo::init_zeroed()
185
}
186
}
187
188
/// The reply from the GSP to the [`GetGspInfo`] command.
189
pub(crate) struct GetGspStaticInfoReply {
190
gpu_name: [u8; 64],
191
}
192
193
impl MessageFromGsp for GetGspStaticInfoReply {
194
const FUNCTION: MsgFunction = MsgFunction::GetGspStaticInfo;
195
type Message = GspStaticConfigInfo;
196
type InitError = Infallible;
197
198
fn read(
199
msg: &Self::Message,
200
_sbuffer: &mut SBufferIter<array::IntoIter<&[u8], 2>>,
201
) -> Result<Self, Self::InitError> {
202
Ok(GetGspStaticInfoReply {
203
gpu_name: msg.gpu_name_str(),
204
})
205
}
206
}
207
208
impl GetGspStaticInfoReply {
209
/// Returns the name of the GPU as a string, or `None` if the string given by the GSP was
210
/// invalid.
211
pub(crate) fn gpu_name(&self) -> Option<&str> {
212
util::str_from_null_terminated(&self.gpu_name)
213
}
214
}
215
216
/// Send the [`GetGspInfo`] command and awaits for its reply.
217
pub(crate) fn get_gsp_info(cmdq: &mut Cmdq, bar: &Bar0) -> Result<GetGspStaticInfoReply> {
218
cmdq.send_command(bar, GetGspStaticInfo)?;
219
220
loop {
221
match cmdq.receive_msg::<GetGspStaticInfoReply>(Delta::from_secs(5)) {
222
Ok(info) => return Ok(info),
223
Err(ERANGE) => continue,
224
Err(e) => return Err(e),
225
}
226
}
227
}
228
229