Linux PCI pci_dev 的创建

Linux 下PCI驱动架构是Linux BUS,DEVICE,DRIVER架构。下面所有代码来自linux3.13.

struct pci_dev 是描述device的数据结构。

struct pci_driver是描述driver的数据结构。

struct pci_bus是描述bus的数据结构。

device和driver都是挂 bus上的。


PCI 的 driver和device要做匹配验证的时候,验证的是vendor,id,class信息。

static inline const struct pci_device_id * pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
{
	if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
	    (id->device == PCI_ANY_ID || id->device == dev->device) &&
	    (id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) &&
	    (id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) &&
	    !((id->class ^ dev->class) & id->class_mask))
		return id;
	return NULL;
}

这个函数就是pci device和driver匹配的最底层函数。可以看到比较的是vendor,id,class信息。它的调用路径是:

pci_bus_match()->pci_match_device()->pci_match_one_device()


很多人介绍了pci driver该怎么写。但忽略了pci device何时被创建。

当一个pci driver注册到系统时,系统会去匹配pci driver和pci device。但这时其实pci device 已经被创建了,所以才能match。那pci device是在什么时候创建的呢?

答案是系统初始化时。

系统初始化时,会扫描pci总线,发现所有已经连在上面的设备,并为每个社保创建一个struct pci_dev对象。

struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
		struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
	struct pci_host_bridge_window *window;
	bool found = false;
	struct pci_bus *b;
	int max;

	list_for_each_entry(window, resources, list)
		if (window->res->flags & IORESOURCE_BUS) {
			found = true;
			break;
		}

	b = pci_create_root_bus(parent, bus, ops, sysdata, resources); // 创建pci bus
	if (!b)
		return NULL;

	if (!found) {
		dev_info(&b->dev,
		 "No busn resource found for root bus, will use [bus %02x-ff]\n",
			bus);
		pci_bus_insert_busn_res(b, bus, 255);
	}

	max = pci_scan_child_bus(b);	//扫描pci bus,找到pci设备

	if (!found)
		pci_bus_update_busn_res_end(b, max);

	pci_bus_add_devices(b);
	return b;
}
从pci bus的根开始扫描。

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);	//扫描slot

        .
        .
        .
	return max;
}
接着看pci_scan_slot()
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++;

	.
        .
        .
	return nr;
}
继续,
struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn)
{
	struct pci_dev *dev;

	dev = pci_get_slot(bus, devfn);//看看slot上是不是已经有devfn对应的设备了
	if (dev) {
		pci_dev_put(dev);
		return dev;
	}

	dev = pci_scan_device(bus, devfn); //slot上还没有,那就扫描一下
	if (!dev)
		return NULL;

	pci_device_add(dev, bus);

	return dev;
}

继续看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)) //读一读硬件,看看有没有devfn的设备存在
		return NULL;

	dev = pci_alloc_dev(bus); //有硬件设备存在,那就创建一个struct pci_dev的对象来代表它吧
	if (!dev)
		return NULL;

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

	pci_set_of_node(dev); //看看device tree dts里有信息没

	if (pci_setup_device(dev)) { //初始化pci_dev对象,包括vendor,id,class信息。
		pci_bus_put(dev->bus);
		kfree(dev);
		return NULL;
	}

	return dev;
}
好了,基本的步骤就是如此。当然扫描还会一层一层的走下去,因为如果有pci桥,就会多一层。

还有热插拔的设备,插上后会被创建device。

看完struct pci_dev的创建,就能更完整地理解pci驱动的架构了。


On kernel 4.3, the following list shows the sequence of the PCI bus create and scan.

Dec  9 17:43:25 ubuntu kernel: [    0.538740] alexTrace: acpi_init() acpi_disabled=0
Dec  9 17:43:25 ubuntu kernel: [    0.613669] alexTrace: acpi_pci_root_init register pci_root_handler
Dec  9 17:43:25 ubuntu kernel: [    0.775337] alexTrace: acpi_pci_root_add
Dec  9 17:43:25 ubuntu kernel: [    0.781491] alexTrace,pci_acpi_scan_root
Dec  9 17:43:25 ubuntu kernel: [    0.784897] alexTrace: pci_create_root_bus
Dec  9 17:43:25 ubuntu kernel: [    0.789678] alexdebug: pci_scan_child_bus
Dec  9 17:43:25 ubuntu kernel: [    0.789730] alexdebug: pci_scan_slot devfn 0
Dec  9 17:43:25 ubuntu kernel: [    0.789776] alexdebug: pci_scan_single_device devfn=0
Dec  9 17:43:25 ubuntu kernel: [    0.789883] alexdebug: pci_scan_device devfn=0,debugcount=0
Dec  9 17:43:25 ubuntu kernel: [    0.914795] alexdebug: pci_scan_bridge
Dec  9 17:43:25 ubuntu kernel: [    0.914812] alexdebug: pci_scan_child_bus

The first PCI scan starts from ACPI.

If ACPI is disabled, then it starts from pci_legacy_init().




你可能感兴趣的:(linux)