projects/linux·blob master · refs

91 lines · 2.3 KiB

1// SPDX-License-Identifier: GPL-2.0
2
3use core::num::NonZero;
4
5use kernel::{
6 device,
7 pci,
8 prelude::*, //
9};
10
11use crate::{
12 fsp::{
13 Fsp,
14 VgpuMode, //
15 },
16 gpu::Chipset, //
17};
18
19mod hal;
20
21/// vGPU state detected during GPU construction.
22#[derive(Debug, Clone, Copy)]
23pub(crate) enum VgpuState {
24 /// vGPU mode is not enabled for this boot.
25 Disabled,
26 /// vGPU mode is enabled for this boot.
27 Enabled {
28 /// Total number of SR-IOV VFs supported by this device.
29 total_vfs: NonZero<u16>,
30 },
31}
32
33/// vGPU state manager.
34pub(crate) struct VgpuManager {
35 state: VgpuState,
36}
37
38impl VgpuManager {
39 /// Creates a vGPU manager by querying SR-IOV and the FSP PRC vGPU knob.
40 pub(crate) fn new(
41 pdev: &pci::Device<device::Core<'_>>,
42 chipset: Chipset,
43 fsp: Option<&mut Fsp<'_>>,
44 ) -> Self {
45 let state = Self::detect_state(pdev, chipset, fsp).unwrap_or_else(|e| {
46 dev_warn!(
47 pdev,
48 "vGPU state detection failed: {:?}; disabling vGPU\n",
49 e
50 );
51 VgpuState::Disabled
52 });
53 dev_dbg!(pdev, "vGPU state: {:?}\n", state);
54
55 Self { state }
56 }
57
58 /// Detects the vGPU state from the chipset, SR-IOV capability and FSP PRC knob.
59 fn detect_state(
60 pdev: &pci::Device<device::Core<'_>>,
61 chipset: Chipset,
62 fsp: Option<&mut Fsp<'_>>,
63 ) -> Result<VgpuState> {
64 if !hal::vgpu_hal(chipset).supports_vgpu() {
65 return Ok(VgpuState::Disabled);
66 }
67
68 let Some(total_vfs) = pdev.sriov_get_totalvfs() else {
69 return Ok(VgpuState::Disabled);
70 };
71
72 if total_vfs.get() < 2 {
73 // The current vGPU path does not support single-VF SR-IOV devices yet.
74 // Treat one total VF as vGPU-disabled for now; single-VF support can relax
75 // this gate once the manager handles that topology.
76 return Ok(VgpuState::Disabled);
77 }
78
79 let fsp = fsp.ok_or(ENODEV)?;
80
81 match fsp.read_vgpu_mode(pdev.as_ref())? {
82 VgpuMode::Enabled => Ok(VgpuState::Enabled { total_vfs }),
83 VgpuMode::Disabled => Ok(VgpuState::Disabled),
84 }
85 }
86
87 /// Returns the detected vGPU state for this boot.
88 pub(crate) fn state(&self) -> VgpuState {
89 self.state
90 }
91}