PCIE enumeration process code implementation-reprinted to learn to use

In the PCIe debugging process, the problem that the peer EP device cannot be scanned often occurs. During the problem location process, it is very important to understand the pcie enumeration process in the kernel.

The PCIe enumeration process is generally divided into three steps:
1. Create the root node
2. Scan the devices under the root node
3. Assign resources to the devices under the root node

So how to discover the device?
Start the analysis from the function pci_scan_child_bus of the bus scanning pcie device

unsigned int pci_scan_child_bus(struct pci_bus *bus)
{
unsigned int devfn, pass, max = bus->busn_res.start;
struct pci_dev *dev;

dev_dbg(&bus->dev, "scanning bus\n");

/* Go find them, Rover! */
for (devfn = 0; devfn < 0x100; devfn += 8)
    pci_scan_slot(bus, devfn);

/* Reserve buses for SR-IOV capability. */
max += pci_iov_bus_range(bus);

/*
 * After performing arch-dependent fixup of the bus, look behind
 * all PCI-to-PCI bridges on this bus.
 */
if (!bus->is_added) {
    dev_dbg(&bus->dev, "fixups for bus\n");
    pcibios_fixup_bus(bus);
    bus->is_added = 1;
}

for (pass = 0; pass < 2; pass++)
    list_for_each_entry(dev, &bus->devices, bus_list) {
        if (pci_is_bridge(dev))
            max = pci_scan_bridge(bus, dev, max, pass);
    }

/*
 * Make sure a hotplug bridge has at least the minimum requested
 * number of buses.
 */
if (bus->self && bus->self->is_hotplug_bridge && pci_hotplug_bus_size) {
    if (max - bus->busn_res.start < pci_hotplug_bus_size - 1)
        max = bus->busn_res.start + pci_hotplug_bus_size - 1;
}

/*
 * We've scanned the bus and so we know all about what's on
 * the other side of any bridges that may be on this bus plus
 * any devices.
 *
 * Return how far we've got finding sub-buses.
 */
dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max);
return max;

}
EXPORT_SYMBOL_GPL(pci_scan_child_bus);

The core code of this function is

for (devfn = 0; devfn < 0x100; devfn += 8)
pci_scan_slot(bus, devfn);

The bus variable here comes from pci_create_root_bus, which is the bus number
devfn of the created root bus : device and function number.
The method used here is exhaustive, try all devs and functions at once.

pci_scan_slot function:

int pci_scan_slot(struct pci_bus *bus, int devfn)
{
unsigned fn, nr = 0;
struct pci_dev *dev;

if (only_one_child(bus) && (devfn > 0))
    return 0; /* Already scanned the entire slot */

dev = pci_scan_single_device(bus, devfn);
if (!dev)
    return 0;
if (!dev->is_added)
    nr++;

for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) {
    dev = pci_scan_single_device(bus, devfn + fn);
    if (dev) {
        if (!dev->is_added)
            nr++;
        dev->multifunction = 1;
    }
}

/* only one slot has pcie device */
if (bus->self && nr)
    pcie_aspm_init_link_state(bus->self);

return nr;

}

pci_scan_single_device:

struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
{
struct pci_dev *dev;

dev = pci_get_slot(bus, devfn);
if (dev) {
    pci_dev_put(dev);
    return dev;
}

dev = pci_scan_device(bus, devfn);
if (!dev)
    return NULL;

pci_device_add(dev, bus);

return dev;

}

The core function is pci_scan_device:

static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
{
struct pci_dev *dev;
u32 l;

if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
    return NULL;

dev = pci_alloc_dev(bus);
if (!dev)
    return NULL;

dev->devfn = devfn;
dev->vendor = l & 0xffff;
dev->device = (l >> 16) & 0xffff;

pci_set_of_node(dev);

if (pci_setup_device(dev)) {
    pci_bus_put(dev->bus);
    kfree(dev);
    return NULL;
}

return dev;

}

Venderid configuration reads and writes are performed at intervals in the while loop. As can be seen from the above code, there are two reasons for exiting the loop.

  1. config configuration read and write failed (indicating that the link is blocked)
  2. No response to the timeout (the reserved time is 60s, which is already very long, and the first point is more likely to fail)

Therefore, when the peer device cannot be scanned:
1. Confirm whether the link establishment is successful, and the link establishment fails. The peer must not be scanned
. 2. Confirm whether the configuration space of the peer is writable (whether the pcie module of the peer is in the unreset state)
3. Confirm whether the type0, type1, iatu and other parameters are configured correctly. If they are correct, confirm whether the size of the address space accessed by the configuration is sufficient.
————————————————
Copyright Statement: This article is the original article of the CSDN blogger "Hober_yao", which follows the CC 4.0 BY-SA copyright agreement. Please attach the original source link and this statement for reprinting. .
Original link: https://blog.csdn.net/yhb1047818384/java/article/details/71076371

Guess you like

Origin blog.csdn.net/qq_33632004/article/details/105966445