pcie设备驱动无法工作排查

pci_register_driver() (include/linux/pci.h)
  -->pci_register_driver()  (drivers/pci/pci-driver.c)
    -->driver_register()  (drivers/base/driver.c)
      -->bus_add_driver (drivers/base/driver.c)
        -->driver_attach() (drivers/base/dd.c)
          -->__driver_attach()  (drivers/base/dd.c)
            -->driver_match_device()
                pci_bus_match

driver_match_device()
  -->pci_bus_match  (drivers/pci/pci-driver.c)
    -->pci_match_device() (drivers/pci/pci-driver.c)
      -->pci_match_id() (drivers/pci/pci-driver.c)
        -->pci_match_one_device (drivers/pci/pci.h)     

整个驱动的注册后触发使能的过程如上。这里核心位于bus_for_each_dev

int bus_for_each_dev(struct bus_type *bus, struct device *start,
		     void *data, int (*fn)(struct device *, void *))
{
   
	struct klist_iter i;
	struct device *dev;
	int error = 0;

	if (!bus || !bus->p)
		return -EINVAL;

	klist_iter_init_node(&bus->p->klist_devices, &i,
			     (start ? &start->p->knode_bus : NULL));
	while (!error && (dev = next_device(&i)))
		error = fn(dev, data);
	klist_iter_exit(&i);
	return error;
}
EXPORT_SYMBOL_GPL(bus_for_each_dev);

static int pci_bus_match(struct device *dev, struct device_driver *drv)
{
   
	struct pci_dev *pci_dev = to_pci_dev(dev);
	struct pci_driver *pci_drv;
	const struct pci_device_id *found_id;

	if (!pci_dev->match_driver)
		return 0;

	pci_drv = to_pci_driver(drv);
	found_id = pci_match_device(pci_drv, pci_dev);
	if (found_id)
		return 1;

	return 0;
}

static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
						    struct pci_dev *dev)
{
   
	struct pci_dynid *dynid;
	const struct pci_device_id *found_id = NULL;

	/* When driver_override is set, only bind to the matching driver */
	if (dev->driver_override && strcmp(dev->driver_override, drv->name))
		return NULL;

	/* Look at the dynamic ids first, before the static ones */
	spin_lock(&drv->dynids.lock);
	list_for_each_entry(dynid, &drv->dynids.list, node) {
   
		if (pci_match_one_device(&dynid->id, dev)) {
   
			found_id = &dynid->id;
			break;
		}
	}
	spin_unlock(&drv->dynids.lock);

	if (!found_id)
		found_id = pci_match_id(drv->id_table, dev);

	/* driver_override will always match, send a dummy id */
	if (!found_id && dev->driver_override)
		found_id = &pci_device_id_any;

	return found_id;
}

为了查看为什么驱动匹配不到设备,我写了如下测试代码。当然必须重构部分数据结构,因为没有导出。


int test_bus_for_each_dev( void )
{
   
	struct klist_iter i;
	struct device *dev;
	int error = 0;
    struct device *start = NULL;

    struct bus_type *bus = &pci_bus_type;

    printk("pci_bus_type %lx \n", pci_bus_type);

	klist_iter_init_node(&bus->p->klist_devices, &i,
			     ( NULL));
	while (!error && (dev = next_device(&i))){
   
        struct pci_dev *pci_dev = to_pci_dev(dev);
        printk("pci_dev %x %x match driver %x \n", 
            pci_dev->vendor, pci_dev->device, pci_dev->match_driver);
    }
	klist_iter_exit(&i);
	return error;
}

最后发现pci_dev->match_driver没有使能。

相关推荐

  1. pcie设备驱动无法工作排查

    2024-01-18 03:12:03       33 阅读
  2. linux驱动工作原理

    2024-01-18 03:12:03       29 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-18 03:12:03       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-18 03:12:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-18 03:12:03       20 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-18 03:12:03       20 阅读

热门阅读

  1. 排序补充(C语言版)

    2024-01-18 03:12:03       21 阅读
  2. C++在结构(Struct)中使用队列(Queue)

    2024-01-18 03:12:03       34 阅读
  3. Composer安装

    2024-01-18 03:12:03       32 阅读
  4. 前端开发常用的地址

    2024-01-18 03:12:03       38 阅读
  5. 低端单片机彩色屏幕的内存占用疑惑

    2024-01-18 03:12:03       28 阅读
  6. 2024-01-16 创业日记-关于用户需求分析-思考

    2024-01-18 03:12:03       25 阅读
  7. opencv通过轮廓点生成闭合图像

    2024-01-18 03:12:03       34 阅读
  8. repo工具是如何简化我们使用git的?

    2024-01-18 03:12:03       36 阅读