pci

    xiaoxiao2021-04-16  59

    在drivers/pci/probe.c中的pci_init_capabilities中会调用pci_ea_init 来初始化Enhanced Allocation。 void pci_ea_init(struct pci_dev *dev) {     int ea;     u8 num_ent;     int offset;     int i;     /* find PCI EA capability in list */     ea = pci_find_capability(dev, PCI_CAP_ID_EA);     if (!ea)         return;     /* determine the number of entries */     pci_bus_read_config_byte(dev->bus, dev->devfn, ea + PCI_EA_NUM_ENT,                     &num_ent);     num_ent &= PCI_EA_NUM_ENT_MASK;     offset = ea + PCI_EA_FIRST_ENT;     /* Skip DWORD 2 for type 1 functions */     if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)         offset += 4;     /* parse each EA entry */     for (i = 0; i < num_ent; ++i)         offset = pci_ea_read(dev, offset); } 在pci_ea_init中先通过pci_find_capability 判断当前设备是否支持PCI_CAP_ID_EA。如果支持的话,在通过PCI_EA_NUM_ENT 读取当前支持多少个EA entry。最后在for循环中通过pci_ea_read来将ea的resource添加到device中 static int pci_ea_read(struct pci_dev *dev, int offset) {     struct resource *res;     int ent_size, ent_offset = offset;     resource_size_t start, end;     unsigned long flags;     u32 dw0, bei, base, max_offset;     u8 prop; //通过long是否是8byte 来决定当前系统是否是64bit     bool support_64 = (sizeof(resource_size_t) >= 8);     pci_read_config_dword(dev, ent_offset, &dw0);     ent_offset += 4;     /* Entry size field indicates DWORDs after 1st */     ent_size = ((dw0 & PCI_EA_ES) + 1) << 2;     if (!(dw0 & PCI_EA_ENABLE)) /* Entry not enabled */         goto out;     bei = (dw0 & PCI_EA_BEI) >> 4;     prop = (dw0 & PCI_EA_PP) >> 8;     /*      * If the Property is in the reserved range, try the Secondary      * Property instead.      */     if (prop > PCI_EA_P_BRIDGE_IO && prop < PCI_EA_P_MEM_RESERVED)         prop = (dw0 & PCI_EA_SP) >> 16;     if (prop > PCI_EA_P_BRIDGE_IO)         goto out; //得到res的指针struct resource *res;     res = pci_ea_get_resource(dev, bei, prop);     if (!res) {         dev_err(&dev->dev, "Unsupported EA entry BEI: %u\n", bei);         goto out;     }     flags = pci_ea_flags(dev, prop);     if (!flags) {         dev_err(&dev->dev, "Unsupported EA properties: %#x\n", prop);         goto out;     }     /* Read Base */     pci_read_config_dword(dev, ent_offset, &base);     start = (base & PCI_EA_FIELD_MASK);     ent_offset += 4;     /* Read MaxOffset */     pci_read_config_dword(dev, ent_offset, &max_offset);     ent_offset += 4;     /* Read Base MSBs (if 64-bit entry) */     if (base & PCI_EA_IS_64) {         u32 base_upper;         pci_read_config_dword(dev, ent_offset, &base_upper);         ent_offset += 4;         flags |= IORESOURCE_MEM_64;         /* entry starts above 32-bit boundary, can't use */         if (!support_64 && base_upper)             goto out;         if (support_64)             start |= ((u64)base_upper << 32);     }     end = start + (max_offset | 0x03);     /* Read MaxOffset MSBs (if 64-bit entry) */     if (max_offset & PCI_EA_IS_64) {         u32 max_offset_upper;         pci_read_config_dword(dev, ent_offset, &max_offset_upper);         ent_offset += 4;         flags |= IORESOURCE_MEM_64;         /* entry too big, can't use */         if (!support_64 && max_offset_upper)             goto out;         if (support_64)             end += ((u64)max_offset_upper << 32);     }     if (end < start) {         dev_err(&dev->dev, "EA Entry crosses address boundary\n");         goto out;     }     if (ent_size != ent_offset - offset) {         dev_err(&dev->dev,             "EA Entry Size (%d) does not match length read (%d)\n",             ent_size, ent_offset - offset);         goto out;     } // 更新resource的值     res->name = pci_name(dev);     res->start = start;     res->end = end;     res->flags = flags;     if (bei <= PCI_EA_BEI_BAR5)         dev_printk(KERN_DEBUG, &dev->dev, "BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",                bei, res, prop);     else if (bei == PCI_EA_BEI_ROM)         dev_printk(KERN_DEBUG, &dev->dev, "ROM: %pR (from Enhanced Allocation, properties %#02x)\n",                res, prop);     else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5)         dev_printk(KERN_DEBUG, &dev->dev, "VF BAR %d: %pR (from Enhanced Allocation, properties %#02x)\n",                bei - PCI_EA_BEI_VF_BAR0, res, prop);     else         dev_printk(KERN_DEBUG, &dev->dev, "BEI %d res: %pR (from Enhanced Allocation, properties %#02x)\n",                bei, res, prop); out:     return offset + ent_size; } 从pci_ea_get_resource 中可以看到ea的resource 分为三类, 第一类是在bei<=PCI_EA_BEI_BAR5和prop <= PCI_EA_P_IO之间 第二类属于PCI_IOV是在bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5 &&          (prop == PCI_EA_P_VF_MEM || prop == PCI_EA_P_VF_MEM_PREFETCH) 第三类bei == PCI_EA_BEI_ROM static struct resource *pci_ea_get_resource(struct pci_dev *dev, u8 bei,                         u8 prop) {     if (bei <= PCI_EA_BEI_BAR5 && prop <= PCI_EA_P_IO)         return &dev->resource[bei]; #ifdef CONFIG_PCI_IOV     else if (bei >= PCI_EA_BEI_VF_BAR0 && bei <= PCI_EA_BEI_VF_BAR5 &&          (prop == PCI_EA_P_VF_MEM || prop == PCI_EA_P_VF_MEM_PREFETCH))         return &dev->resource[PCI_IOV_RESOURCES +                       bei - PCI_EA_BEI_VF_BAR0]; #endif     else if (bei == PCI_EA_BEI_ROM)         return &dev->resource[PCI_ROM_RESOURCE];     else         return NULL; }  这三类从pci_ea_read 中最后的打印log中也可以看到. 总结一下,ea就是给dev的resouce 赋值,这些resource可以分为3类.且可以分为32bit和64bit。这些信息可以从开机log中看到
    转载请注明原文地址: https://ju.6miu.com/read-672764.html

    最新回复(0)