이것은 내가 작업하고있는 SR-IOV 드라이버의 출발점입니다. 나는 전에 PCIe 드라이버를 한 번도 쓰지 않았다.이 많은 것은 내가 도대체 무슨 일이 일어나고 있는지를 알아내는 것이다. 이 드라이버에서는 특정 공급 업체 ID를 찾고 드라이버를로드 한 다음 로그 파일에 여러 항목을 인쇄하여 어떤 일이 발생했는지 확인합니다. 로드되고 PF와 4 개의 VF가 lspci를 실행할 때 볼 수 있습니다.SR-IOV 드라이버에서 각 VF에 대해 호출되는 프로브입니다. 이것이 PF인지 또는 VF인지 어떻게 알 수 있습니까?
(아마도 내가 그것에 대해 생각하지 않았기 때문에) 예상치 못한 것은 프로브 기능이 각 VF에 대해 실행된다는 것입니다. 사방에 게시 된 인텔 예제 코드는 구조체에 .sriov_configure 멤버가 있습니다. 나는 그것이 부름을받을 것이라고 생각했으나 그렇게하지 않았기 때문에 나는 여기서 뭔가 잘못했을 수도 있습니다.
내 질문은, 내가 VF를 볼 때 PF 및 특정 다른 것들에 대한 프로브에서 특정 작업을 수행하고 싶기 때문에이 특정 프로브 인스턴스가 다음과 같은 경우를 결정하는 "올바른"방법은 무엇입니까? PF 또는 VF?
완벽을 기하기 위해 로그 (많은 로그)와 소스가 아래에 있습니다. em_probe가 여러 번 호출되는 것을 볼 수 있습니다. 미리 감사드립니다.
[ 10.516072] em: em initialize
[ 10.526026] em: ENTER --> em_probe
[ 10.546857] pci_em 0000:04:00.0: enabling device (0100 -> 0102)
[ 10.571659] em: ====== em CONFIG SPACE ======
[ 10.583073] em: VENDOR_ID = 0x1172
[ 10.593789] em: DEVICE_ID = 0xBEAD
[ 10.604454] em: SUBSYSTEM_ID = 0x0011
[ 10.615089] em: SUBSYSTEM VENDOR ID = 0xABCD
[ 10.625698] em: Address Start : 0x00000000FBE00000
[ 10.636847] em: Address End : 0x00000000FBEFFFFF
[ 10.670164] em: Address Length: 0x0000000000100000
[ 10.681285] em: Address Base : 0x000000000000E000
[ 10.692352] em: PCI NUM VF before enable sriov: 0x0000000000000000
[ 10.805976] em: ENTER --> em_probe
[ 10.805984] pci_em 0000:04:00.1: enabling device (0000 -> 0002)
[ 10.805997] em: ====== em CONFIG SPACE ======
[ 10.805998] em: VENDOR_ID = 0xFFFF
[ 10.805999] em: DEVICE_ID = 0xFFFF
[ 10.806001] em: SUBSYSTEM_ID = 0x0011
[ 10.806002] em: SUBSYSTEM VENDOR ID = 0xABCD
[ 10.806015] em: Address Start : 0x0000000090000000
[ 10.806016] em: Address End : 0x0000000090000FFF
[ 10.806018] em: Address Length: 0x0000000000001000
[ 10.806019] em: Address Base : 0x0000000000396000
[ 10.806020] em: PCI NUM VF before enable sriov: 0x0000000000000000
[ 10.806021] em: PCI NUM VF after enable sriov: 0x0000000000000000
[ 10.806025] em: SR-IOV CapID : 0x0000
[ 10.806026] em: SR-IOV CapVer : 0x0000
[ 10.806027] em: EXIT <-- em_probe
[ 10.807806] em: ENTER --> em_probe
[ 10.807855] pci_em 0000:04:00.2: enabling device (0000 -> 0002)
[ 10.807933] em: ====== em CONFIG SPACE ======
[ 10.807934] em: VENDOR_ID = 0xFFFF
[ 10.807935] em: DEVICE_ID = 0xFFFF
[ 10.807938] em: SUBSYSTEM_ID = 0x0011
[ 10.807940] em: SUBSYSTEM VENDOR ID = 0xABCD
[ 10.808018] em: Address Start : 0x0000000090001000
[ 10.808019] em: Address End : 0x0000000090001FFF
[ 10.808026] em: Address Length: 0x0000000000001000
[ 10.808027] em: Address Base : 0x00000000003A6000
[ 10.808033] em: PCI NUM VF before enable sriov: 0x0000000000000000
[ 10.808035] em: PCI NUM VF after enable sriov: 0x0000000000000000
[ 10.808046] em: SR-IOV CapID : 0x0000
[ 10.808048] em: SR-IOV CapVer : 0x0000
[ 10.808049] em: EXIT <-- em_probe
[ 10.811562] em: ENTER --> em_probe
[ 10.811637] pci_em 0000:04:00.3: enabling device (0000 -> 0002)
[ 10.811734] em: ====== em CONFIG SPACE ======
[ 10.811735] em: VENDOR_ID = 0xFFFF
[ 10.811750] em: DEVICE_ID = 0xFFFF
[ 10.811751] em: SUBSYSTEM_ID = 0x0011
[ 10.811765] em: SUBSYSTEM VENDOR ID = 0xABCD
[ 10.812144] em: Address Start : 0x0000000090002000
[ 10.812151] em: Address End : 0x0000000090002FFF
[ 10.812158] em: Address Length: 0x0000000000001000
[ 10.812162] em: Address Base : 0x00000000003CC000
[ 10.812172] em: PCI NUM VF before enable sriov: 0x0000000000000000
[ 10.812180] em: PCI NUM VF after enable sriov: 0x0000000000000000
[ 10.812184] em: SR-IOV CapID : 0x0000
[ 10.812185] em: SR-IOV CapVer : 0x0000
[ 10.812185] em: EXIT <-- em_probe
[ 10.812609] em: ENTER --> em_probe
[ 10.812615] pci_em 0000:04:00.4: enabling device (0000 -> 0002)
[ 10.812626] em: ====== em CONFIG SPACE ======
[ 10.812627] em: VENDOR_ID = 0xFFFF
[ 10.812628] em: DEVICE_ID = 0xFFFF
[ 10.812629] em: SUBSYSTEM_ID = 0x0011
[ 10.812630] em: SUBSYSTEM VENDOR ID = 0xABCD
[ 10.812648] em: Address Start : 0x0000000090003000
[ 10.812649] em: Address End : 0x0000000090003FFF
[ 10.812650] em: Address Length: 0x0000000000001000
[ 10.812651] em: Address Base : 0x00000000003EE000
[ 10.812652] em: PCI NUM VF before enable sriov: 0x0000000000000000
[ 10.812653] em: PCI NUM VF after enable sriov: 0x0000000000000000
[ 10.812657] em: SR-IOV CapID : 0x0000
[ 10.812658] em: SR-IOV CapVer : 0x0000
[ 10.812659] em: EXIT <-- em_probe
[ 10.812695] em: PCI NUM VF after enable sriov: 0x0000000000000004
[ 10.812698] em: SR-IOV CapID : 0x0010
[ 10.812699] em: SR-IOV CapVer : 0x0001
[ 10.812700] em: EXIT <-- em_probe
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
#define em_DEV_NAME "em"
#define NR_VIRTFN 4
#define SR_IOV_CAP_BASE_ADDR 0x200
MODULE_LICENSE("GPL");
static struct pci_device_id em_ids[] = {
{PCI_DEVICE(0x1172,PCI_ANY_ID)},
{0},
};
MODULE_DEVICE_TABLE(pci, em_ids);
static struct {
/* (mmio) control registers i.e. the "register memory region" */
void __iomem *regs_base_addr;
resource_size_t regs_start;
resource_size_t regs_end;
resource_size_t regs_len;
resource_size_t regs_flags;
resource_size_t regs_sys_page_size;
u16 sriov_capid;
u16 sriov_capver;
u16 numvf;
u16 totalvf;
/* irq handling */
unsigned int irq;
} em_dev;
static u16 em_get_vendorid(struct pci_dev *pdev)
{
u16 vendorid;
pci_read_config_word(pdev, PCI_VENDOR_ID, &vendorid);
return vendorid;
}
static u16 em_get_deviceid(struct pci_dev *pdev)
{
u16 deviceid;
pci_read_config_word(pdev, PCI_DEVICE_ID, &deviceid);
return deviceid;
}
static unsigned char em_get_revision(struct pci_dev *pdev)
{
u8 revision;
pci_read_config_byte(pdev, PCI_REVISION_ID, &revision);
return revision;
}
static u16 em_get_subsystemid(struct pci_dev *pdev)
{
u16 subsystemid;
pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsystemid);
return subsystemid;
}
static u16 em_get_subsystemvendorid(struct pci_dev *pdev)
{
u16 subsystemvendorid;
pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsystemvendorid);
return subsystemvendorid;
}
static u16 em_get_iov_capid(struct pci_dev *pdev)
{
u16 result;
pci_read_config_word(pdev, SR_IOV_CAP_BASE_ADDR, &result);
return result;
}
static u16 em_get_iov_version(struct pci_dev *pdev)
{
u16 result;
pci_read_config_word(pdev, SR_IOV_CAP_BASE_ADDR+2, &result);
result = result & 0x000F;
return result;
}
static u16 em_get_num_vf(struct pci_dev *pdev)
{
u16 result;
pci_read_config_word(pdev, SR_IOV_CAP_BASE_ADDR+PCI_SRIOV_NUM_VF, &result);
return result;
}
static u16 em_get_total_vf(struct pci_dev *pdev)
{
u16 result;
pci_read_config_word(pdev, SR_IOV_CAP_BASE_ADDR+PCI_SRIOV_TOTAL_VF, &result);
return result;
}
static int em_probe(struct pci_dev *pdev,
const struct pci_device_id *pdev_id)
{
printk(KERN_ALERT "em: ENTER --> em_probe\n");
u16 subsystemid;
u16 subvendorid;
u16 vendorid;
u16 deviceid;
int err;
struct device *dev = &pdev->dev;
if ((err = pci_enable_device(pdev))) {
dev_err(dev, "em: pci_enable_device probe error %d for device %s\n",
err, pci_name(pdev));
return err;
}
if ((err = pci_request_regions(pdev, em_DEV_NAME)) < 0) {
dev_err(dev, "pci_request_regions error %d\n", err);
goto pci_disable;
}
subsystemid = em_get_subsystemid(pdev);
subvendorid = em_get_subsystemvendorid(pdev);
vendorid = em_get_vendorid(pdev);
deviceid = em_get_deviceid(pdev);
printk (KERN_ALERT "em: ====== em CONFIG SPACE ======\n");
printk (KERN_ALERT "em: VENDOR_ID = 0x%04X\n", vendorid);
printk (KERN_ALERT "em: DEVICE_ID = 0x%04X\n", deviceid);
printk (KERN_ALERT "em: SUBSYSTEM_ID = 0x%04X\n", subsystemid);
printk (KERN_ALERT "em: SUBSYSTEM VENDOR ID = 0x%04X\n", subvendorid);
/* bar0: control registers */
em_dev.regs_start = pci_resource_start(pdev, 0);
em_dev.regs_end = pci_resource_end(pdev, 0);
em_dev.regs_len = pci_resource_len(pdev, 0);
em_dev.regs_base_addr = pci_iomap(pdev, 0, 0x100);
if (!em_dev.regs_base_addr) {
dev_err(dev, "em: cannot ioremap registers of size %lu\n",
(unsigned long)em_dev.regs_len);
goto region_release;
}
printk (KERN_ALERT "em: Address Start : 0x%016X\n", em_dev.regs_start);
printk (KERN_ALERT "em: Address End : 0x%016X\n", em_dev.regs_end);
printk (KERN_ALERT "em: Address Length: 0x%016X\n", em_dev.regs_len);
printk (KERN_ALERT "em: Address Base : 0x%016X\n", em_dev.regs_base_addr);
em_dev.numvf = pci_num_vf(pdev);
printk (KERN_ALERT "em: PCI NUM VF before enable sriov: 0x%016X\n", em_dev.numvf);
pci_enable_sriov(pdev, NR_VIRTFN);
em_dev.numvf = pci_num_vf(pdev);
printk (KERN_ALERT "em: PCI NUM VF after enable sriov: 0x%016X\n", em_dev.numvf);
em_dev.sriov_capid = em_get_iov_capid(pdev);
em_dev.sriov_capver = em_get_iov_version(pdev);
em_dev.totalvf = em_get_total_vf(pdev);
printk (KERN_ALERT "em: SR-IOV CapID : 0x%04X\n", em_dev.sriov_capid);
printk (KERN_ALERT "em: SR-IOV CapVer : 0x%04X\n", em_dev.sriov_capver);
printk(KERN_ALERT "em: EXIT <-- em_probe\n");
return 0;
map_release:
pci_iounmap(pdev, em_dev.regs_base_addr);
region_release:
pci_release_regions(pdev);
pci_disable:
pci_disable_device(pdev);
return -EBUSY;
}
// Validate that the error path in em_probe is modeled after this
// remove function. Everything needs to be backed out in order and cleanly
// or we leave reserved memory in the kernel
static void em_remove(struct pci_dev *pdev)
{
pci_enable_sriov(pdev, NR_VIRTFN);
pci_iounmap(pdev, em_dev.regs_base_addr);
pci_release_regions(pdev);
pci_disable_device(pdev);
}
static int em_sriov_configure(struct pci_dev *dev, int numvfs)
{
printk(KERN_ALERT "em: ENTER --> em_sriov_configure\n");
if (numvfs > 0) {
printk(KERN_ALERT "em: NUMVFS > 0 em_sriov_configure\n");
pci_enable_sriov(dev,numvfs);
return numvfs;
}
if (numvfs == 0) {
printk(KERN_ALERT "em: NUMVFS == 0 em_sriov_configure\n");
pci_disable_sriov(dev);
return 0;
}
printk(KERN_ALERT "em: EXIT <-- em_sriov_configure\n");
}
static struct pci_driver em_pci_driver = {
.name = "pci_em",
.id_table = em_ids,
.probe = em_probe,
.remove = em_remove,
.sriov_configure = em_sriov_configure,
};
static int em_init(void)
{
int err = -ENOMEM;
printk(KERN_ALERT "em: em initialize\n");
/* register pci device driver */
if ((err = pci_register_driver(&em_pci_driver)) < 0) {
pr_err("em: pci_register_driver error\n");
goto exit;
}
return 0;
exit:
return err;
}
static void em_exit(void)
{
printk(KERN_ALERT "em: em exit\n");
pci_unregister_driver(&em_pci_driver);
}
module_init(em_init);
module_exit(em_exit);