Skip to content

Commit 6d17ff8

Browse files
Add SubsystemVendor and SubsystemDevice fields to NvidiaPCIDevice
Signed-off-by: Karthik Vetrivel <kvetrivel@nvidia.com>
1 parent 8ff29bb commit 6d17ff8

3 files changed

Lines changed: 113 additions & 28 deletions

File tree

pkg/nvpci/mock.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,24 @@ func createNVIDIAgpuFiles(deviceDir string) error {
167167
return err
168168
}
169169

170+
subsystemVendor, err := os.Create(filepath.Join(deviceDir, "subsystem_vendor"))
171+
if err != nil {
172+
return err
173+
}
174+
_, err = fmt.Fprintf(subsystemVendor, "0x%x", PCINvidiaVendorID)
175+
if err != nil {
176+
return err
177+
}
178+
179+
subsystemDevice, err := os.Create(filepath.Join(deviceDir, "subsystem_device"))
180+
if err != nil {
181+
return err
182+
}
183+
_, err = subsystemDevice.WriteString("0x16c0")
184+
if err != nil {
185+
return err
186+
}
187+
170188
_, err = os.Create(filepath.Join(deviceDir, "nvidia"))
171189
if err != nil {
172190
return err

pkg/nvpci/nvpci.go

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,22 @@ func (s *SriovInfo) IsVF() bool {
107107

108108
// NvidiaPCIDevice represents a PCI device for an NVIDIA product.
109109
type NvidiaPCIDevice struct {
110-
Path string
111-
Address string
112-
Vendor uint16
113-
Class uint32
114-
ClassName string
115-
Device uint16
116-
DeviceName string
117-
Driver string
118-
IommuGroup int
119-
IommuFD string
120-
NumaNode int
121-
Config *ConfigSpace
122-
Resources MemoryResources
123-
SriovInfo SriovInfo
110+
Path string
111+
Address string
112+
Vendor uint16
113+
Class uint32
114+
ClassName string
115+
Device uint16
116+
SubsystemVendor uint16
117+
SubsystemDevice uint16
118+
DeviceName string
119+
Driver string
120+
IommuGroup int
121+
IommuFD string
122+
NumaNode int
123+
Config *ConfigSpace
124+
Resources MemoryResources
125+
SriovInfo SriovInfo
124126
}
125127

126128
// IsVGAController if class == 0x300.
@@ -298,6 +300,32 @@ func (p *nvpci) getNvidiaDeviceByPciBusID(address string, cache map[string]*Nvid
298300
return nil, fmt.Errorf("unable to convert device string to uint16: %v", deviceStr)
299301
}
300302

303+
var subsystemVendorID uint64
304+
subsystemVendor, err := os.ReadFile(path.Join(devicePath, "subsystem_vendor"))
305+
switch {
306+
case err == nil:
307+
subsystemVendorStr := strings.TrimSpace(string(subsystemVendor))
308+
subsystemVendorID, err = strconv.ParseUint(subsystemVendorStr, 0, 16)
309+
if err != nil {
310+
return nil, fmt.Errorf("unable to convert subsystem vendor string to uint16: %v", subsystemVendorStr)
311+
}
312+
case !os.IsNotExist(err):
313+
return nil, fmt.Errorf("unable to read PCI subsystem vendor id for %s: %v", address, err)
314+
}
315+
316+
var subsystemDeviceID uint64
317+
subsystemDevice, err := os.ReadFile(path.Join(devicePath, "subsystem_device"))
318+
switch {
319+
case err == nil:
320+
subsystemDeviceStr := strings.TrimSpace(string(subsystemDevice))
321+
subsystemDeviceID, err = strconv.ParseUint(subsystemDeviceStr, 0, 16)
322+
if err != nil {
323+
return nil, fmt.Errorf("unable to convert subsystem device string to uint16: %v", subsystemDeviceStr)
324+
}
325+
case !os.IsNotExist(err):
326+
return nil, fmt.Errorf("unable to read PCI subsystem device id for %s: %v", address, err)
327+
}
328+
301329
driver, err := getDriver(devicePath)
302330
if err != nil {
303331
return nil, fmt.Errorf("unable to detect driver for %s: %w", address, err)
@@ -391,20 +419,22 @@ func (p *nvpci) getNvidiaDeviceByPciBusID(address string, cache map[string]*Nvid
391419
}
392420

393421
nvdevice := &NvidiaPCIDevice{
394-
Path: devicePath,
395-
Address: address,
396-
Vendor: uint16(vendorID),
397-
Class: uint32(classID),
398-
Device: uint16(deviceID),
399-
Driver: driver,
400-
IommuGroup: int(iommuGroup),
401-
IommuFD: iommuFD,
402-
NumaNode: int(numaNode),
403-
Config: config,
404-
Resources: resources,
405-
DeviceName: deviceName,
406-
ClassName: className,
407-
SriovInfo: sriovInfo,
422+
Path: devicePath,
423+
Address: address,
424+
Vendor: uint16(vendorID),
425+
Class: uint32(classID),
426+
Device: uint16(deviceID),
427+
SubsystemVendor: uint16(subsystemVendorID),
428+
SubsystemDevice: uint16(subsystemDeviceID),
429+
Driver: driver,
430+
IommuGroup: int(iommuGroup),
431+
IommuFD: iommuFD,
432+
NumaNode: int(numaNode),
433+
Config: config,
434+
Resources: resources,
435+
DeviceName: deviceName,
436+
ClassName: className,
437+
SriovInfo: sriovInfo,
408438
}
409439

410440
// Cache physical functions only as VF can't be a root device.

pkg/nvpci/nvpci_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package nvpci
1818

1919
import (
20+
"os"
21+
"path/filepath"
2022
"testing"
2123

2224
"github.com/stretchr/testify/require"
@@ -74,6 +76,41 @@ func TestNvpci(t *testing.T) {
7476
_, err = nvpci.GetGPUByIndex(1)
7577
require.Error(t, err, "No error returned when getting GPU at invalid index")
7678
}
79+
80+
func TestNvpciSubsystem(t *testing.T) {
81+
nvpci, err := NewMockNvpci()
82+
require.Nil(t, err, "Error creating NewMockNvpci")
83+
defer nvpci.Cleanup()
84+
85+
err = nvpci.AddMockA100("0000:80:05.1", 0, nil)
86+
require.Nil(t, err, "Error adding Mock A100 device to MockNvpci")
87+
88+
devices, err := nvpci.GetGPUs()
89+
require.Nil(t, err, "Error getting GPUs")
90+
require.Equal(t, 1, len(devices), "Wrong number of GPU devices")
91+
require.Equal(t, uint16(0x10de), devices[0].SubsystemVendor, "Wrong SubsystemVendor for device")
92+
require.Equal(t, uint16(0x16c0), devices[0].SubsystemDevice, "Wrong SubsystemDevice for device")
93+
}
94+
95+
func TestNvpciSubsystemMissing(t *testing.T) {
96+
nvpci, err := NewMockNvpci()
97+
require.Nil(t, err, "Error creating NewMockNvpci")
98+
defer nvpci.Cleanup()
99+
100+
err = nvpci.AddMockA100("0000:80:05.1", 0, nil)
101+
require.Nil(t, err, "Error adding Mock A100 device to MockNvpci")
102+
103+
deviceDir := filepath.Join(nvpci.pciDevicesRoot, "0000:80:05.1")
104+
require.NoError(t, os.Remove(filepath.Join(deviceDir, "subsystem_vendor")))
105+
require.NoError(t, os.Remove(filepath.Join(deviceDir, "subsystem_device")))
106+
107+
devices, err := nvpci.GetGPUs()
108+
require.Nil(t, err, "Error getting GPUs")
109+
require.Equal(t, 1, len(devices), "Wrong number of GPU devices")
110+
require.Equal(t, uint16(0), devices[0].SubsystemVendor, "SubsystemVendor should default to 0 when sysfs file is absent")
111+
require.Equal(t, uint16(0), devices[0].SubsystemDevice, "SubsystemDevice should default to 0 when sysfs file is absent")
112+
}
113+
77114
func TestNvpciIOMMUFD(t *testing.T) {
78115
testCases := []struct {
79116
Description string

0 commit comments

Comments
 (0)