ixgbe 如何开启vf

在drivers/net/ethernet/intel/ixgbe/ixgbe_main.c 中会注册一个pci driver
static struct pci_driver ixgbe_driver = {
    .name     = ixgbe_driver_name,
    .id_table = ixgbe_pci_tbl,
    .probe    = ixgbe_probe,
    .remove   = ixgbe_remove,
#ifdef CONFIG_PM
    .suspend  = ixgbe_suspend,
    .resume   = ixgbe_resume,
#endif
    .shutdown = ixgbe_shutdown,
    .sriov_configure = ixgbe_pci_sriov_configure,
    .err_handler = &ixgbe_err_handler
};
 每个pcie设备都有一个pci_driver。其中提供了一个sriov_configure 用于开启vf。
int ixgbe_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
{
    if (num_vfs == 0)
        return ixgbe_pci_sriov_disable(dev);
    else
        return ixgbe_pci_sriov_enable(dev, num_vfs);
}
ixgbe_pci_sriov_configure 接受两个参数,一个是struct pci_dev *dev 代表这个pcie 设备,也就是pf,int num_vfs 也就是需要开启的vf的序列号,因为一个pf可以支持多个vf,所以要选择启动哪个vf.pf支持的vf个数是在sriov_init 中就已经初始化好的.
如果num_vfs 不是0的话,就调用ixgbe_pci_sriov_enable
static int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
{
#ifdef CONFIG_PCI_IOV
    struct ixgbe_adapter *adapter = pci_get_drvdata(dev);
    int err = 0;
    int i;
    int pre_existing_vfs = pci_num_vf(dev);
    err = pci_enable_sriov(dev, num_vfs);
    if (err) {
        e_dev_warn("Failed to enable PCI sriov: %d\n", err);
        return err;
    }
    return num_vfs;
#else
    return 0;
#endif
}
要使用vf,kernel必须打开CONFIG_PCI_IOV。随后调用pci_enable_sriov来启动vf
pci_enable_sriov->sriov_enable->pci_iov_add_virtfn
int pci_iov_add_virtfn(struct pci_dev *dev, int id, int reset)
{
    int i;
    int rc = -ENOMEM;
    u64 size;
    char buf[VIRTFN_ID_LEN];
    struct pci_dev *virtfn;
    struct resource *res;
    struct pci_sriov *iov = dev->sriov;
    struct pci_bus *bus;

    mutex_lock(&iov->dev->sriov->lock);
//得到vf的bus
    bus = virtfn_add_bus(dev->bus, pci_iov_virtfn_bus(dev, id));
    if (!bus)
        goto failed;
//申请一个struct pci_dev *virtfn; 作为vf,在kernel中用pci_dev 表示一个pcie end point,从这里能看出vf和pf在kernel中的结构体是一样的
    virtfn = pci_alloc_dev(bus);
    if (!virtfn)
        goto failed0;

    virtfn->devfn = pci_iov_virtfn_devfn(dev, id);
    virtfn->vendor = dev->vendor;
    pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_DID, &virtfn->device);
//初始化virtfn
    rc = pci_setup_device(virtfn);
    if (rc)
        goto failed0;

    virtfn->dev.parent = dev->dev.parent;
    virtfn->physfn = pci_dev_get(dev);
    virtfn->is_virtfn = 1;
    virtfn->multifunction = 0;
//为vf准备bar资源,所以vf是有独立的bar资源的.
    for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
        res = &dev->resource[i + PCI_IOV_RESOURCES];
        if (!res->parent)
            continue;
        virtfn->resource[i].name = pci_name(virtfn);
        virtfn->resource[i].flags = res->flags;
        size = pci_iov_resource_size(dev, i + PCI_IOV_RESOURCES);
        virtfn->resource[i].start = res->start + size * id;
        virtfn->resource[i].end = virtfn->resource[i].start + size - 1;
        rc = request_resource(res, &virtfn->resource[i]);
        BUG_ON(rc);
    }

    if (reset)
        __pci_reset_function(virtfn);
//添加device
    pci_device_add(virtfn, virtfn->bus);
    mutex_unlock(&iov->dev->sriov->lock);

    pci_bus_add_device(virtfn);
    sprintf(buf, "virtfn%u", id);
//为vf建立sysfs接口
    rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
    if (rc)
        goto failed1;
    rc = sysfs_create_link(&virtfn->dev.kobj, &dev->dev.kobj, "physfn");
    if (rc)
        goto failed2;

    kobject_uevent(&virtfn->dev.kobj, KOBJ_CHANGE);

    return 0;

failed2:
    sysfs_remove_link(&dev->dev.kobj, buf);
failed1:
    pci_dev_put(dev);
    mutex_lock(&iov->dev->sriov->lock);
    pci_stop_and_remove_bus_device(virtfn);
failed0:
    virtfn_remove_bus(dev->bus, bus);
failed:
    mutex_unlock(&iov->dev->sriov->lock);

    return rc;
}
 总结一下,要使用vf必须通过pf中的sriov_configure,在kernel中vf和pf都是用pci_dev,且初始化的flow也都是一样的,也就是说vf是一个独立的pcie 设备.且vf本身自己拥有资源.
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值