本文已参与 [新人创作礼] 活动,一起开启掘金创作之路。
上一篇讲到了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"