zl程序教程

您现在的位置是:首页 >  系统

当前栏目

linux内核radeon gpu源码解析5 —— drm_get_pci_dev函数详解2

Linux内核源码 详解 函数 解析 get GPU
2023-09-14 09:09:19 时间

上一篇讲到了drm_get_pci_dev函数的第1个函数:drm_dev_alloc。

不知读者还有没有印象,前一篇文章中讲drm_get_pci_dev函数的第1个函数drm_dev_alloc的时候,在函数注释中有这样一段话:

/*******************************************************************************************

 * Initialize a new DRM device. No device registration is done.
 * Call drm_dev_register() to advertice the device to user space and register it
 * with other core subsystems
. This should be done last in the device
 * initialization sequence to make sure userspace can't access an inconsistent
 * state.

********************************************************************************************/

注释的大致意思是说,注册DRM设备但是没有初始化,需要在初始化的最后调用drm_dev_register()进行注册。

这一篇就来讲这个drm_get_pci_dev函数的第2个函数:drm_dev_register。

调用处:ret = drm_dev_register(dev, ent->driver_data);

源码如下:

drivers/gpu/drm/drm_drv.c

/**
 * drm_dev_register - Register DRM device
 * @dev: Device to register
 * @flags: Flags passed to the driver's .load() function
 *
 * Register the DRM device @dev with the system, advertise device to user-space
 * and start normal device operation. @dev must be allocated via drm_dev_alloc()
 * previously.
 *
 * Never call this twice on any device!
 *
 * NOTE: To ensure backward compatibility with existing drivers method this
 * function calls the &drm_driver.load method after registering the device
 * nodes, creating race conditions. Usage of the &drm_driver.load methods is
 * therefore deprecated, drivers must perform all initialization before calling
 * drm_dev_register().
 *
 * RETURNS:
 * 0 on success, negative error code on failure.
 */
int drm_dev_register(struct drm_device *dev, unsigned long flags)
{
	struct drm_driver *driver = dev->driver;
	int ret;

	mutex_lock(&drm_global_mutex);

	ret = drm_minor_register(dev, DRM_MINOR_RENDER);
	if (ret)
		goto err_minors;

	ret = drm_minor_register(dev, DRM_MINOR_PRIMARY);
	if (ret)
		goto err_minors;

	ret = create_compat_control_link(dev);
	if (ret)
		goto err_minors;

	dev->registered = true;

	if (dev->driver->load) {
		ret = dev->driver->load(dev, flags);
		if (ret)
			goto err_minors;
	}

	if (drm_core_check_feature(dev, DRIVER_MODESET))
		drm_modeset_register_all(dev);

	ret = 0;

	DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
		 driver->name, driver->major, driver->minor,
		 driver->patchlevel, driver->date,
		 dev->dev ? dev_name(dev->dev) : "virtual device",
		 dev->primary->index);

	goto out_unlock;

err_minors:
	remove_compat_control_link(dev);
	drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
	drm_minor_unregister(dev, DRM_MINOR_RENDER);
out_unlock:
	mutex_unlock(&drm_global_mutex);
	return ret;
}
EXPORT_SYMBOL(drm_dev_register);

重点讲一下这一段程序:

if (dev->driver->load) {
        ret = dev->driver->load(dev, flags);
        if (ret)
            goto err_minors;

}

dev就是drm_dev_alloc函数中新分配并初始化的那个dev。dev->driver就是前一篇文章中最后提到的dev->driver = driver;,也就是说dev->driver实际上指向了kms_driver。那么dev->driver->load不言而喻,当然就指向struct drm_driver kms_driver 中的
.load = radeon_driver_load_kms,

这个函数是所有和GPU初始化相关的内容的起始点 。下一篇我们重点介绍。

在此顺便列出

DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
         driver->name, driver->major, driver->minor,
         driver->patchlevel, driver->date,
         dev->dev ? dev_name(dev->dev) : "virtual device",
         dev->primary->index);

中各个成员的值:

driver->name为kms_driver中的.name = DRIVER_NAME,DRIVER_NAME宏定义的值根据不同的驱动而不同,在radeon驱动中为如下定义(drivers/gpu/drm/radeon/radeon_drv.h中):

#define DRIVER_NAME		"radeon"

如果是在amdgpu驱动中,则为(drivers/gpu/drm/amd/amdgpu/amdgpu_drv.h中):

#define DRIVER_NAME		"amdgpu"

如果是在nouveau驱动中,则为(drivers/gpu/drm/nouveau/nouveau_drv.h中):

#define DRIVER_NAME		"nouveau"

如果是在loongson驱动中,则为(drivers/gpu/drm/loongson/loongson_drv.c中):

#define DRIVER_NAME "loongson-drm"

driver->major为kms_driver中的.major = KMS_DRIVER_MAJOR,KMS_DRIVER_MAJOR宏定义的值同样根据不同的驱动而不同,在radeon驱动中为如下定义(drivers/gpu/drm/radeon/radeon_drv.c中):

#define KMS_DRIVER_MAJOR	2

如果是在amdgpu驱动中,则为(drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c中):

#define KMS_DRIVER_MAJOR	3

注意,这个宏定义只在radeon和amdgpu驱动中有,其他驱动中无此宏定义。

driver->minor为kms_driver中的.minor = KMS_DRIVER_MINOR,KMS_DRIVER_MINOR宏定义的值同样根据不同的驱动而不同,在radeon驱动中为如下定义(drivers/gpu/drm/radeon/radeon_drv.c中):

#define KMS_DRIVER_MINOR	50

如果是在amdgpu驱动中,则为(drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c中):

#define KMS_DRIVER_MINOR	27

注意,这个宏定义同样只在radeon和amdgpu驱动中有,其他驱动中无此宏定义。

driver->patch_level为kms_driver中的.patchlevel = KMS_DRIVER_PATCHLEVEL,KMS_DRIVER_PATCHLEVEL宏定义只存在于radeon驱动(drivers/gpu/drm/radeon/radeon_drv.c)和amdgpu驱动(drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c)中,且值相同:

#define KMS_DRIVER_PATCHLEVEL	0

driver->date为kms_driver中的.date = DRIVER_DATE,DRIVER_DATE宏定义的值根据不同的驱动而不同,在radeon驱动中为如下定义(drivers/gpu/drm/radeon/radeon_drv.h中):

#define DRIVER_DATE		"20080528"

如果是在amdgpu驱动中,则为(drivers/gpu/drm/amd/amdgpu/amdgpu_drv.h中):

#define DRIVER_DATE		"20150101"

如果是在nouveau驱动中,则为(drivers/gpu/drm/nouveau/nouveau_drv.h中):

#define DRIVER_DATE		"20120801"

如果是在loongson驱动中,则为(drivers/gpu/drm/loongson/loongson_drv.c中):

#define DRIVER_DATE "20180328"