drivers: Correct isPCIeDevice logic

Currently, isPCIeDevice() attempts to determine if a (host) device is
PCI-Express capable by looking up its link speed via the PCI slots
information in sysfs.  This is a) complicated and b) wrong.  PCI-e
devices don't have to have slots information, so this frequently fails.

Instead determine if devices are PCI-e by checking for the presence of
PCIe extended configuration space by looking at the size of the "config"
file in sysfs.

Forward ported from 6bf93b23 in the Kata 1.x runtime repository.

Fixes: #611

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
David Gibson 2020-08-19 16:06:22 +10:00
parent c422d061cb
commit 92dfa4634b
2 changed files with 12 additions and 29 deletions

View File

@ -89,9 +89,6 @@ var SysIOMMUPath = "/sys/kernel/iommu_groups"
// SysBusPciDevicesPath is static string of /sys/bus/pci/devices // SysBusPciDevicesPath is static string of /sys/bus/pci/devices
var SysBusPciDevicesPath = "/sys/bus/pci/devices" var SysBusPciDevicesPath = "/sys/bus/pci/devices"
// SysBusPciSlotsPath is static string of /sys/bus/pci/slots
var SysBusPciSlotsPath = "/sys/bus/pci/slots"
var getSysDevPath = getSysDevPathImpl var getSysDevPath = getSysDevPathImpl
// DeviceInfo is an embedded type that contains device data common to all types of devices. // DeviceInfo is an embedded type that contains device data common to all types of devices.

View File

@ -9,6 +9,7 @@ package drivers
import ( import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os"
"path/filepath" "path/filepath"
"strings" "strings"
@ -22,6 +23,8 @@ const (
PCIDomain = "0000" PCIDomain = "0000"
PCIeKeyword = "PCIe" PCIeKeyword = "PCIe"
PCIConfigSpaceSize = 256
) )
type PCISysFsType string type PCISysFsType string
@ -52,23 +55,17 @@ func isPCIeDevice(bdf string) bool {
if len(strings.Split(bdf, ":")) == 2 { if len(strings.Split(bdf, ":")) == 2 {
bdf = PCIDomain + ":" + bdf bdf = PCIDomain + ":" + bdf
} }
slots, err := ioutil.ReadDir(config.SysBusPciSlotsPath)
configPath := filepath.Join(config.SysBusPciDevicesPath, bdf, "config")
fi, err := os.Stat(configPath)
if err != nil { if err != nil {
deviceLogger().WithError(err).WithField("path", config.SysBusPciSlotsPath).Warn("failed to list pci slots") deviceLogger().WithField("dev-bdf", bdf).WithField("error", err).Warning("Couldn't stat() configuration space file")
return false return false //Who knows?
} }
b := strings.Split(bdf, ".")[0]
for _, slot := range slots { // Plain PCI devices hav 256 bytes of configuration space,
address := getPCISlotProperty(slot.Name(), PCISysFsSlotsAddress) // PCI-Express devices have 4096 bytes
if b == address { return fi.Size() > PCIConfigSpaceSize
maxBusSpeed := getPCISlotProperty(slot.Name(), PCISysFsSlotsMaxBusSpeed)
if strings.Contains(maxBusSpeed, PCIeKeyword) {
return true
}
}
}
deviceLogger().WithField("dev-bdf", bdf).Debug("can not find slot for bdf of pci device")
return false
} }
// read from /sys/bus/pci/devices/xxx/property // read from /sys/bus/pci/devices/xxx/property
@ -85,17 +82,6 @@ func getPCIDeviceProperty(bdf string, property PCISysFsProperty) string {
return rlt return rlt
} }
// read from /sys/bus/pci/slots/xxx/property
func getPCISlotProperty(slot string, property PCISysFsProperty) string {
propertyPath := filepath.Join(config.SysBusPciSlotsPath, slot, string(property))
rlt, err := readPCIProperty(propertyPath)
if err != nil {
deviceLogger().WithError(err).WithField("path", propertyPath).Warn("failed to read pci slot property")
return ""
}
return rlt
}
func readPCIProperty(propertyPath string) (string, error) { func readPCIProperty(propertyPath string) (string, error) {
var ( var (
buf []byte buf []byte