Linux网络驱动之Fixed-Link(24)

张开发
2026/5/3 11:40:20 15 分钟阅读
Linux网络驱动之Fixed-Link(24)
接前一篇文章Linux网络驱动之Fixed-Link23三、深入了解上一回在解析platform_device_register_full函数的时候讲到了其中调用的platform_device_add函数。上一回讲过platform_device_add函数的作用是添加平台设备到设备层级中也就是将一个构造好的platform_device设备真正挂接到platform总线上。前文书讲到的platform_device_register函数和platform_device_register_full函数底层最终都是调用platform_device_add函数。本回就来详细解析platform_device_add函数代码。为了便于理解和回顾再次贴出platform_device_add函数代码在drivers/base/platform.c中如下/** * platform_device_add - add a platform device to device hierarchy * pdev: platform device were adding * * This is part 2 of platform_device_register(), though may be called * separately _iff_ pdev was allocated by platform_device_alloc(). */ int platform_device_add(struct platform_device *pdev) { u32 i; int ret; if (!pdev) return -EINVAL; if (!pdev-dev.parent) pdev-dev.parent platform_bus; pdev-dev.bus platform_bus_type; switch (pdev-id) { default: dev_set_name(pdev-dev, %s.%d, pdev-name, pdev-id); break; case PLATFORM_DEVID_NONE: dev_set_name(pdev-dev, %s, pdev-name); break; case PLATFORM_DEVID_AUTO: /* * Automatically allocated device ID. We mark it as such so * that we remember it must be freed, and we append a suffix * to avoid namespace collision with explicit IDs. */ ret ida_alloc(platform_devid_ida, GFP_KERNEL); if (ret 0) goto err_out; pdev-id ret; pdev-id_auto true; dev_set_name(pdev-dev, %s.%d.auto, pdev-name, pdev-id); break; } for (i 0; i pdev-num_resources; i) { struct resource *p, *r pdev-resource[i]; if (r-name NULL) r-name dev_name(pdev-dev); p r-parent; if (!p) { if (resource_type(r) IORESOURCE_MEM) p iomem_resource; else if (resource_type(r) IORESOURCE_IO) p ioport_resource; } if (p) { ret insert_resource(p, r); if (ret) { dev_err(pdev-dev, failed to claim resource %d: %pR\n, i, r); goto failed; } } } pr_debug(Registering platform device %s. Parent at %s\n, dev_name(pdev-dev), dev_name(pdev-dev.parent)); ret device_add(pdev-dev); if (ret 0) return ret; failed: if (pdev-id_auto) { ida_free(platform_devid_ida, pdev-id); pdev-id PLATFORM_DEVID_AUTO; } while (i--) { struct resource *r pdev-resource[i]; if (r-parent) release_resource(r); } err_out: return ret; } EXPORT_SYMBOL_GPL(platform_device_add);platform_device_add函数一上来先检测参数struct platform_device *pdev是否为空如果为空就直接返回-EINVAL。代码片段如下if (!pdev) return -EINVAL;这段代码主要是为了增加健壮性。接下来判断平台设备platform_devicepdev所属的devstruct device的parent是否为空如果为空就将dev的parent设置为platform_bus也就是说未指定父设备时默认挂在platform_bus下。然后将dev的bus总线设置为platform_bus_type。代码片段如下if (!pdev-dev.parent) pdev-dev.parent platform_bus; pdev-dev.bus platform_bus_type;platform_bus的定义和初始化在kernel/linux-5.10-origin/drivers/base/platform.c中代码如下struct device platform_bus { .init_name platform, }; EXPORT_SYMBOL_GPL(platform_bus);platform_bus_type的定义和初始化也在drivers/base/platform.c中代码如下struct bus_type platform_bus_type { .name platform, .dev_groups platform_dev_groups, .match platform_match, .uevent platform_uevent, .dma_configure platform_dma_configure, .pm platform_dev_pm_ops, }; EXPORT_SYMBOL_GPL(platform_bus_type);platform_device_add函数的作用是添加平台设备到设备层级么这里就是找到了更确切地说是认了个“父亲”“认祖归宗”了。platform_device_add函数后续内容的解析请看下回。

更多文章