Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does PCI/PCIe devices init/register themselves in the Linux kernel?

When the kernel starts up, the PCI subsystem creates a pci_bus for each physical PCI bus, then the pci_bus is added to pci_root_buses(with PCI configuration). But the PCI device driver registers drivers by pci_register_driver, and it adds PCI driver to pci_bus_type.

My questions:

  • How does pci_bus_type know PCI configuration.
  • What is the relationship between pci_bus_type and pci_root_buses.
like image 844
hooao Avatar asked Jul 16 '15 04:07

hooao


1 Answers

Since the question is partially incomplete, but comments are too small to give a answer I'll try to mix this in a bit.

So the kernel tries to abstract the physical implementation of the PCI(e) bus from the driver developer. Hence a PCI bus on an NVidia Tegra is different to a PCI bus on a Freescale ARM and a x86_64 PCI bus, but it should be possible to register devices against them regardless of the real bus implementation.

The structure pci_root_buses is a list of abstract PCI buses, where the implementation could be different.

You can see this in the bus type structure, where function pointers are defined to allow each real bus to have a different implementation how to treat a device. I think it's best if you read the PCI chapter in LDD3 and have a special look at Boot Time.

Also look at Configuration Time to see how the Kernel matches drivers to hardware. The rough idea of PCI is that the kernel can discover the bus and map memory to each physical PCI device allowing access to the PCI configuration space of the device. The driver developer registers a device class by calling pci_register_driver and therefore telling the kernel which driver functions to use for certain vendor ids.

Looking at LDD3 again it seems the missing mapping that you might be looking for is the probe function:

int (*probe) (struct pci_dev *dev, const struct pci_device_id *id);

Pointer to the probe function in the PCI driver. This function is called by the PCI core when it has a struct pci_dev that it thinks this driver wants to control. A pointer to the struct pci_device_id that the PCI core used to make this decision is also passed to this function. If the PCI driver claims the struct pci_dev that is passed to it, it should initialize the device properly and return 0. If the driver does not want to claim the device, or an error occurs, it should return a negative error value. More details about this function follow later in this chapter.

Kernel data structures

  • Bus type

Further reading

  • Linux Device Drivers 3rd edition - Chapter PCI
  • In Kernel Documentation about PCIe
like image 97
Alexander Oh Avatar answered Nov 10 '22 12:11

Alexander Oh