注意:这篇文章上次更新于458天前,文章内容可能已经过时。
This article was last updated458 days ago, the content may be outdated.
在这篇文章中,我们将讨论高通 WLAN 驱动程序中的对象管理器模块(Object Manager)。
主要数据结构
在整个 WLAN 驱动程序中,对象管理器模块主要负责管理 3 个对象:
- psoc(Physical System on Chip)
- pdev(Physical Device)
- vdev(Virtual Device)
他们之间的关系如下已经在开篇图中有所展示。
在全局的 wlan_objmgr_global 对象中包括了有一个 psoc 的指针数组,在每个psoc 对象中又包括了一个 soc_objmgr 对象,这个对象中包括了一个 pdev 的指针数组,和一个 vdev 的指针数组。
每一个 pdev 对象中又包括了一个 pdev_objmgr 对象,这个对象中包括了一个 psoc 的指针,指向了当前 pdev 对象所属的 psoc 对象。
每一个 vdev 对象中又包括了一个 vdev_objmgr 对象,这个对象中包括了一个 pdev 的指针,指向了当前 vdev 对象所属的 pdev 对象。
在整个 WLAN 驱动程序中,几乎所有的配置、状态信息都会附加在这些对象上来进行管理。
对象创建
wlan_objmgr_global 对象创建
在驱动加载函数中 hdd_driver_load 会调用到 wlan_objmgr_global_obj_init 函数来进行内存的分配和初始化。
整个调用流程如下:
hdd_driver_load =>
hdd_component_init =>
dispatcher_init =>
wlan_objmgr_global_obj_init
1 | /* Global object, it is declared globally */ |
值得注意的是,在 dispatcher_init 会初始化大量的 WLAN Driver 内部组件,包括 scan、wifi_pos、dfs 等。
其中,第一个被初始化的就是 wlan_objmgr_global 对象,因为其它组件的对象最终都会附加在这个对象上。
以上过程的最终源头是 module_init(hdd_module_init); , 也就是说在驱动模块被加载时就会调用到这个函数。
在驱动模块被加载时的 dispatcher_init 函数中,其他模块会在 wlan_objmgr_global 对象上注册回调函数。
这些回调函数会在 psoc 对象创建时被调用。
以 scan 模块为例:
在 ucfg_scan_init 函数中会调用到 wlan_objmgr_register_psoc_create_handler 函数来注册回调函数。
1 | QDF_STATUS ucfg_scan_init(void) |
wlan_objmgr_register_psoc_create_handler 会在 wlan_objmgr_global 对象维护的 psoc_create_handler 的表中注册 scan 模块的回调函数。
1 | QDF_STATUS wlan_objmgr_register_psoc_create_handler( |
psoc 对象创建
psoc 对象的创建是在 HDD 上下文创建的过程中被调用的。
而 hdd_context_create 是在驱动程序的 probe 函数中被调用的。probe 函数的调用会晚于 module_init(hdd_module_init);。
在 wlan_objmgr_psoc_obj_create 函数为 psoc 对象分配内存并进行初始化。
然后通过 for 循环调用 g_umac_glb_obj->psoc_create_handler 中注册的回调函数。
对于 scan 模块来说,这个回调函数是 wlan_scan_psoc_created_notification。参数列表是 NULL。
最后会调用 wlan_objmgr_psoc_object_attach 函数来将 psoc 对象附加到 wlan_objmgr_global 对象上。
1 | struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version, |
pdev 对象创建
在驱动程序的 probe 函数中首先通过 hdd_context_create 创建出了 psoc 对象。
然后在 hdd_wlan_startup 函数中,会创建 pdev 对象。
1 | static int __hdd_soc_probe(struct device *dev, |
pdev 的创建过程已经在如下代码的注释中给出了解释,其中,pdev 的创建也需要通过 for 循环来调用其他组件在 wlan_objmgr_global 对象中注册的 pdev 创建时的回调函数。
1 | struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create( |
vdev 对象创建
vdev 的创建和销毁与 Linux 内核网络设备接口是紧密相关的。
比如,当网络设备打开时(如ifconfig up或ip link set up), 内核会调用网络设备驱动程序中的 ndo_open 函数。
ndo: network device operations
在高通 WLAN 驱动程序中,ndo_open 函数是 hdd_open 函数。
点击展开:
1 | struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( |
In this article, we’ll discuss the Object Manager module in the Qualcomm WLAN driver.
The code location is as follows:
https://github.com/WANG-Guangxin/wlan-driver/tree/5113495b16420b49004c444715d2daae2066e7dc/qca-wifi-host-cmn/umac/cmn_services/obj_mgr
Main Data Structures
Throughout the WLAN driver, the Object Manager module is mainly responsible for managing 3 objects:
- psoc (Physical System on Chip)
- pdev (Physical Device)
- vdev (Virtual Device)
The relationships between them are shown in the diagram at the beginning of the article.
The global wlan_objmgr_global object contains an array of psoc pointers. Each psoc object contains a soc_objmgr object, which includes an array of pdev pointers and an array of vdev pointers.
Each pdev object contains a pdev_objmgr object, which includes a psoc pointer pointing to the psoc object that the current pdev object belongs to.
Each vdev object contains a vdev_objmgr object, which includes a pdev pointer pointing to the pdev object that the current vdev object belongs to.
Throughout the WLAN driver, almost all configuration and state information is attached to these objects for management.
Object Creation
Creation of the wlan_objmgr_global Object
In the driver load function, hdd_driver_load calls wlan_objmgr_global_obj_init to allocate and initialize the memory.
The overall call flow is as follows:
hdd_driver_load =>
hdd_component_init =>
dispatcher_init =>
wlan_objmgr_global_obj_init
1 | /* Global object, it is declared globally */ |
It’s worth noting that dispatcher_init initializes a large number of internal WLAN driver components, including scan, wifi_pos, dfs, etc.
Among them, the wlan_objmgr_global object is the first to be initialized, because the objects of all other components will eventually be attached to this object.
The ultimate source of the above process is module_init(hdd_module_init); — that is, this function is called when the driver module is loaded.
In the dispatcher_init function, which runs when the driver module is loaded, other modules register callback functions on the wlan_objmgr_global object.
These callbacks are invoked when the psoc object is created.
Take the scan module as an example:
In the ucfg_scan_init function, wlan_objmgr_register_psoc_create_handler is called to register the callback.
1 | QDF_STATUS ucfg_scan_init(void) |
wlan_objmgr_register_psoc_create_handler registers the scan module’s callback in the psoc_create_handler table maintained by the wlan_objmgr_global object.
1 | QDF_STATUS wlan_objmgr_register_psoc_create_handler( |
Creation of the psoc Object
The psoc object is created during the HDD context creation process.
hdd_context_create is called from the driver’s probe function. The probe function is called later than module_init(hdd_module_init);.
The wlan_objmgr_psoc_obj_create function allocates memory for the psoc object and initializes it.
Then, a for loop invokes the callbacks registered in g_umac_glb_obj->psoc_create_handler.
For the scan module, this callback is wlan_scan_psoc_created_notification, and the argument list is NULL.
Finally, wlan_objmgr_psoc_object_attach is called to attach the psoc object to the wlan_objmgr_global object.
1 | struct wlan_objmgr_psoc *wlan_objmgr_psoc_obj_create(uint32_t phy_version, |
Creation of the pdev Object
In the driver’s probe function, the psoc object is first created via hdd_context_create.
Then, in the hdd_wlan_startup function, the pdev object is created.
1 | static int __hdd_soc_probe(struct device *dev, |
The pdev creation process is explained in the comments of the code below. Note that creating the pdev also requires a for loop to invoke the pdev creation callbacks that other components registered on the wlan_objmgr_global object.
1 | struct wlan_objmgr_pdev *wlan_objmgr_pdev_obj_create( |
Creation of the vdev Object
The creation and destruction of the vdev is closely related to the Linux kernel’s network device interface.
For example, when a network device is brought up (e.g., ifconfig up or ip link set up), the kernel calls the ndo_open function in the network device driver.
ndo: network device operations
In the Qualcomm WLAN driver, the ndo_open function is hdd_open.
Click to expand:
1 | struct wlan_objmgr_vdev *wlan_objmgr_vdev_obj_create( |


