通过pci-sysfs来查询当前设备支持的最多几个vf

来源:互联网 发布:商业数据保密协议范本 编辑:程序博客网 时间:2024/05/22 05:49
当通过pci_alloc_dev 来申请pci_dev的时候会指定dev->dev.type = &pci_dev_type;
struct pci_dev *pci_alloc_dev(struct pci_bus *bus)
{
    struct pci_dev *dev;

    dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
    if (!dev)
        return NULL;

    INIT_LIST_HEAD(&dev->bus_list);
    dev->dev.type = &pci_dev_type;
    dev->bus = pci_bus_get(bus);

    return dev;
}
也就是说每个pci device都有一个pci_dev_type。
pci_dev_type的定义在pci/pci-sysfs.c中
static const struct attribute_group *pci_dev_attr_groups[] = {
    &pci_dev_attr_group,
    &pci_dev_hp_attr_group,
#ifdef CONFIG_PCI_IOV
    &sriov_dev_attr_group,
#endif
    NULL,
};

struct device_type pci_dev_type = {
    .groups = pci_dev_attr_groups,
};
这里可以发现所谓的pci_dev_type 就是一组接口可以读写当前的pci device.
例如 通过lscpi查到vga的id为0007:91:00.0
root@ubuntu:~# lspci
0002:80:00.0 PCI bridge: Device 19e5:1610 (rev 01)
0007:91:00.0 VGA compatible controller: Device 19e5:1711 (rev 01)

就可以在通过下面的命令读到boot_vga 这个变量
root@ubuntu:/sys/bus/pci/devices/0007:91:00.0# pwd
/sys/bus/pci/devices/0007:91:00.0
root@ubuntu:/sys/bus/pci/devices/0007:91:00.0# cat boot_vga
0

具体的code 分析为:
在pci_dev_attr_groups中调用
static struct attribute *pci_dev_dev_attrs[] = {
    &vga_attr.attr,
    NULL,
};

static ssize_t boot_vga_show(struct device *dev, struct device_attribute *attr,
                 char *buf)
{
    struct pci_dev *pdev = to_pci_dev(dev);
    struct pci_dev *vga_dev = vga_default_device();

    if (vga_dev)
        return sprintf(buf, "%u\n", (pdev == vga_dev));

    return sprintf(buf, "%u\n",
        !!(pdev->resource[PCI_ROM_RESOURCE].flags &
           IORESOURCE_ROM_SHADOW));
}
static struct device_attribute vga_attr = __ATTR_RO(boot_vga);
看到原来boot_vga 这个代表的是当前是被是否是vga设备,如果是的话就返回0.而全面前面cat boot_vga 等于0,也表明当前的设备就是vga设备。

下面是重点,当前设备如果支持vf的话,就可以通过sriov_dev_attr_group-
static struct attribute_group sriov_dev_attr_group = {
    .attrs = sriov_dev_attrs,
    .is_visible = sriov_attrs_are_visible,
};
如果当前设备不支持vf的话
static umode_t sriov_attrs_are_visible(struct kobject *kobj,
                       struct attribute *a, int n)
{
    struct device *dev = kobj_to_dev(kobj);

    if (!dev_is_pf(dev))
        return 0;

    return a->mode;
}

就没有办法看到sriov_dev_attrs
其定义如下:
static struct attribute *sriov_dev_attrs[] = {
    &sriov_totalvfs_attr.attr,
    &sriov_numvfs_attr.attr,
    NULL,
};

static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
static struct device_attribute sriov_numvfs_attr =
        __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
               sriov_numvfs_show, sriov_numvfs_store);

这样我们就通过sriov_totalvfs 这个变量查看当前dev支持多少个vf.
static ssize_t sriov_totalvfs_show(struct device *dev,
                   struct device_attribute *attr,
                   char *buf)
{
    //得到pci_dev *pdev
    struct pci_dev *pdev = to_pci_dev(dev);

    return sprintf(buf, "%u\n", pci_sriov_get_totalvfs(pdev));
}
从pci_sriov_get_totalvfs 中就可以看出原来是从pci_dev的dev->sriov->total_VFs 得到这个设备可以支持的最多的vf
int pci_sriov_get_totalvfs(struct pci_dev *dev)
{
    if (!dev->is_physfn)
        return 0;

    if (dev->sriov->driver_max_VFs)
        return dev->sriov->driver_max_VFs;

    return dev->sriov->total_VFs;
}


0 0
原创粉丝点击