pcie的资源主要有三种,分别是io/mem/bus.再调用pci_create_root_bus的时候,这三种资源要提前准备好
[ 13.419865] pci_bus 0002:80: root bus resource [mem 0xa8800000-0xaffeffff window]
[ 13.419865] pci_bus 0002:80: root bus resource [mem 0xa8800000-0xaffeffff window]
[ 13.434941] pci_bus 0002:80: root bus resource [io 0x0000-0xffff window]
[ 13.434941] pci_bus 0002:80: root bus resource [io 0x0000-0xffff window]
[ 13.448617] pci_bus 0002:80: root bus resource [bus 80-87]
[ 13.448617] pci_bus 0002:80: root bus resource [bus 80-87]
例如在pci_scan_bus中首先添加到resources中
struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
void *sysdata)
{
LIST_HEAD(resources);
struct pci_bus *b;
pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
pci_add_resource(&resources, &busn_resource);
b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
if (b) {
pci_scan_child_bus(b);
} else {
pci_free_resource_list(&resources);
}
return b;
}
重点看一下资源是如何添加到resources 中
void pci_add_resource(struct list_head *resources, struct resource *res)
{
pci_add_resource_offset(resources, res, 0);
}
void pci_add_resource_offset(struct list_head *resources, struct resource *res,
resource_size_t offset)
{
struct resource_entry *entry;
entry = resource_list_create_entry(res, 0);
if (!entry) {
printk(KERN_ERR "PCI: can't add host bridge window %pR\n", res);
return;
}
entry->offset = offset;
resource_list_add_tail(entry, resources);
}
在pci_add_resource_offset中首先通过resource_list_create_entry 申请memory,并给resource_entry 中的__res 赋值
struct resource_entry *resource_list_create_entry(struct resource *res,
size_t extra_size)
{
struct resource_entry *entry;
entry = kzalloc(sizeof(*entry) + extra_size, GFP_KERNEL);
if (entry) {
INIT_LIST_HEAD(&entry->node);
entry->res = res ? res : &entry->__res;
}
return entry;
}
一般res 不为null。
在pci_add_resource_offset 得到entry中再给offset赋值0.最后将resources 插入到resources 列表中.
回到pci_scan_bus 中将io/mem/bus 资源插入到resources 这个list中后,然后将可以通过pci_create_root_bus来创建root bus后,就可以通过pci_scan_child_bus来scan 子总线.
[ 13.419865] pci_bus 0002:80: root bus resource [mem 0xa8800000-0xaffeffff window]
[ 13.419865] pci_bus 0002:80: root bus resource [mem 0xa8800000-0xaffeffff window]
[ 13.434941] pci_bus 0002:80: root bus resource [io 0x0000-0xffff window]
[ 13.434941] pci_bus 0002:80: root bus resource [io 0x0000-0xffff window]
[ 13.448617] pci_bus 0002:80: root bus resource [bus 80-87]
[ 13.448617] pci_bus 0002:80: root bus resource [bus 80-87]
例如在pci_scan_bus中首先添加到resources中
struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops,
void *sysdata)
{
LIST_HEAD(resources);
struct pci_bus *b;
pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
pci_add_resource(&resources, &busn_resource);
b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
if (b) {
pci_scan_child_bus(b);
} else {
pci_free_resource_list(&resources);
}
return b;
}
重点看一下资源是如何添加到resources 中
void pci_add_resource(struct list_head *resources, struct resource *res)
{
pci_add_resource_offset(resources, res, 0);
}
void pci_add_resource_offset(struct list_head *resources, struct resource *res,
resource_size_t offset)
{
struct resource_entry *entry;
entry = resource_list_create_entry(res, 0);
if (!entry) {
printk(KERN_ERR "PCI: can't add host bridge window %pR\n", res);
return;
}
entry->offset = offset;
resource_list_add_tail(entry, resources);
}
在pci_add_resource_offset中首先通过resource_list_create_entry 申请memory,并给resource_entry 中的__res 赋值
struct resource_entry *resource_list_create_entry(struct resource *res,
size_t extra_size)
{
struct resource_entry *entry;
entry = kzalloc(sizeof(*entry) + extra_size, GFP_KERNEL);
if (entry) {
INIT_LIST_HEAD(&entry->node);
entry->res = res ? res : &entry->__res;
}
return entry;
}
一般res 不为null。
在pci_add_resource_offset 得到entry中再给offset赋值0.最后将resources 插入到resources 列表中.
回到pci_scan_bus 中将io/mem/bus 资源插入到resources 这个list中后,然后将可以通过pci_create_root_bus来创建root bus后,就可以通过pci_scan_child_bus来scan 子总线.