2016-10-19 5 views
0

이것은 내가 작업하고있는 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); 

답변

1

프로브의 특정 인스턴스는 PF 또는 VF에 대한 여부를 판단하기위한 "정확한"방법은 무엇인가?

당신은이 간단한 조건문을 사용할 수 있습니다

if (pdev->is_physfn) { .... } 
if (pdev->is_virtfn) { .... }