虽然Linux内核拥有C语言构建的身体,但它骨子里散发的是面向对象的气质,这一个个的对象就是struct。面对一个内核模块的时候,首先要找出关键的struct和它们之间的关系,才能摸清代码的骨骼脉络。
大致浏览几眼xHCI相关的代码,很容易发现几个貌似重要的struct类型:usb_hcd、xhci_hcd和hc_driver,还有几个全局变量xhci_pci_driver、xhci_hc_driver和xhci_pci_hc_driver,再加上PCI总线相关的类型pci_dev和pci_driver。不要被这些眼花缭乱的名字吓到,今天要做的就是把这些结构之间的关系理顺。下面按照相关代码的执行顺序,看一下这些结构是如何被建立和初始化的。
先上图,下面分析的过程结束之后各个结构体就是这种关系:
1. xhci-pci模块启动,执行xhci_pci_init函数
static int __init xhci_pci_init(void)
{
xhci_init_driver(&xhci_pci_hc_driver, xhci_pci_setup);
#ifdef CONFIG_PM
xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend;
xhci_pci_hc_driver.pci_resume = xhci_pci_resume;
#endif
return pci_register_driver(&xhci_pci_driver);
}
1.1 xhci_pci_init调用xhci_init_driver,初始化xhci_pci_hc_driver变量
xhci_init_driver函数是在xhci.c中定义的,主要作用就是把全局变量xhci_hc_driver的值一股脑赋给另一个全局变量xhci_pci_hc_driver。两者都是struct hc_driver类型,xhci_pci_hc_driver在xhci-pci.c中定义,是真正起作用的xHCI驱动,但它在定义的时候没有进行任何成员的初始化:
static struct hc_driver __read_mostly xhci_pci_hc_driver;
而xhci_hc_driver在xhci.c中定义,它包揽了所有的脏活累活:
static const struct hc_driver xhci_hc_driver = {
.description = "xhci-hcd",
.product_desc = "xHCI Host Controller",
.hcd_priv_size = sizeof(struct xhci_hcd *),
/* * generic hardware linkage */
.irq = xhci_irq,
.flags = HCD_MEMORY | HCD_USB3 | HCD_SHARED,
/* * basic lifecycle operations */
.reset = NULL, /* set in xhci_init_driver() */
.start = xhci_run,
.stop = xhci_stop,
.shutdown = xhci_shutdown,
/* * managing i/o requests and associated device resources */
.urb_enqueue = xhci_urb_enqueue,
.urb_dequeue = xhci_urb_dequeue,
.alloc_dev = xhci_alloc_dev,
.free_dev = xhci_free_dev,
.alloc_streams = xhci_alloc_streams,
.free_streams = xhci_free_streams,
.add_endpoint = xhci_add_endpoint,
.drop_endpoint = xhci_drop_endpoint,
.endpoint_reset = xhci_endpoint_reset,
.check_bandwidth = xhci_check_bandwidth,
.reset_bandwidth = xhci_reset_bandwidth,
.address_device = xhci_address_device,
.enable_device = xhci_enable_device,
.update_hub_device = xhci_update_hub_device,
.reset_device = xhci_discover_or_reset_device,
/* * scheduling support */
.get_frame_number = xhci_get_frame,
/* * root hub support */
.hub_control = xhci_hub_control,
.hub_status_data = xhci_hub_status_data,
.bus_suspend = xhci_bus_suspend,
.bus_resume = xhci_bus_resume,
/* * call back when device connected and addressed */
.update_device = xhci_update_device,
.set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm,
.enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout,
.disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
.find_raw_port_number = xhci_find_raw_port_number,
};
void xhci_init_driver(struct hc_driver *drv, int (*setup_fn)(struct usb_hcd *))
{
BUG_ON(!setup_fn);
*drv = xhci_hc_driver;
drv->reset = setup_fn;
}
xhci_init_driver函数将xhci_hc_driver的值赋给xhci_pci_hc_driver后,前者也就退下了舞台。不信,你看:
(free-electrons是个好网站)
1.2 xhci_pci_init调用pci_register_driver,将xhci_pci_driver注册为PCI设备驱动
xhci_pci_driver是xHCI控制器作为PCI设备对应的驱动,符合PCI设备驱动的标准类型struct pci_driver,在xhci-pci.c中静态定义并初始化:
/* pci driver glue; this is a "new style" PCI driver module */
static struct pci_driv