aboutsummaryrefslogblamecommitdiff
path: root/packages/numap/internal/sysfs/pci.go
blob: 9e714b1399e56b6c9ae262a4f2083e7d6eea38cf (plain) (tree)
















































































































































                                                                          
package sysfs

import (
	"fmt"
	"io/ioutil"
	"path"
	"path/filepath"
	"strconv"
	"strings"
)

const (
	sysFsPCIDevicesPath = "/sys/bus/pci/devices/"
)

type PCIDevice struct {
	NumaNode             int
	ID                   string
	Device, Vendor       uint64
	SubVendor, SubDevice uint64
	Class                uint64
	MSIs                 []int
}

func ScanPCIDevices() []PCIDevice {
	devices, err := ioutil.ReadDir(sysFsPCIDevicesPath)
	if err != nil {
		panic(err)
	}

	pciDevices := []PCIDevice{}

	for _, device := range devices {
		dpath := filepath.Join(sysFsPCIDevicesPath, device.Name())
		pcid, err := NewPCIDevice(dpath, device.Name())
		if err != nil {
			panic(err)
		}
		pciDevices = append(pciDevices, pcid)
	}
	return pciDevices
}

func getPCIDeviceClass(path string) (uint64, error) {
	return ContentUint64(filepath.Join(path, "class"))
}

func getPCIDeviceVendor(path string) (uint64, error) {
	return ContentUint64(filepath.Join(path, "vendor"))
}

func getPCIDeviceId(path string) (uint64, error) {
	return ContentUint64(filepath.Join(path, "device"))
}

func getPCIDeviceSubsystemDevice(path string) (uint64, error) {
	return ContentUint64(filepath.Join(path, "subsystem_device"))
}

func getPCIDeviceSubsystemVendor(path string) (uint64, error) {
	return ContentUint64(filepath.Join(path, "subsystem_vendor"))
}

func getPCIDeviceNumaNode(path string) int {
	content, err := ioutil.ReadFile(filepath.Join(path, "numa_node"))
	if err != nil {
		panic(err)
	}
	nodeNum, err := strconv.Atoi(strings.TrimSpace(string(content)))
	if err != nil {
		panic(err)
	}
	return nodeNum
}

func getPCIDeviceMSIx(p string) []int {
	g := fmt.Sprintf("%s/*", filepath.Join(p, "msi_irqs"))
	files, err := filepath.Glob(g)
	if err != nil {
		panic(err)
	}
	if len(files) == 0 {
		return []int{}
	}

	msix := []int{}

	for _, f := range files {
		content, err := ioutil.ReadFile(f)
		if err != nil {
			panic(err)
		}
		if strings.TrimSpace(string(content)) == "msix" {
			base := path.Base(f)
			v, err := strconv.Atoi(base)
			if err != nil {
				panic(err)
			}
			msix = append(msix, v)
		}
	}
	return msix
}

func NewPCIDevice(path, name string) (PCIDevice, error) {
	nodeNum := getPCIDeviceNumaNode(path)

	device, err := getPCIDeviceId(path)
	if err != nil {
		return PCIDevice{}, err
	}

	vendor, err := getPCIDeviceVendor(path)
	if err != nil {
		return PCIDevice{}, err
	}

	subvendor, err := getPCIDeviceSubsystemVendor(path)
	if err != nil {
		return PCIDevice{}, err
	}

	subdevice, err := getPCIDeviceSubsystemDevice(path)
	if err != nil {
		return PCIDevice{}, err
	}

	deviceClass, err := getPCIDeviceClass(path)
	if err != nil {
		return PCIDevice{}, err
	}

	msix := getPCIDeviceMSIx(path)

	return PCIDevice{
		ID:        name,
		Device:    device,
		Class:     deviceClass,
		NumaNode:  nodeNum,
		Vendor:    vendor,
		SubVendor: subvendor,
		SubDevice: subdevice,
		MSIs:      msix,
	}, nil
}