1. 故事从从PCI初始化说起
关于drm_driver和drm_device是对drm设备的抽象,我们就不在这赘述了.有兴趣的,可以去内核doc中学习drm_device具体是什么.
h2. PCI/PCIE的初始工作
目前市面上使用的设备基本上都是PCI的,较少的设备还是使用的platform(估计是上古神兽了).那PCI是怎么初始化的就不在本文赘述,感兴趣的同学可以去内核中driver/pci文件中看一下
TIP:arch下边会有对pci扫描的过程,可以结合起来,容易理解
在amdgpu的初始化时候amdgpu_init(),使用verdor,device的方式绑定将他的pci设备进行绑定,在绑定的时候会与对应的设备做一下设备特性的标记(在这,amdgpu做的是CHIP_FAMILY的标记)
值得注意的是在amdgpu初始化是,将drm_driver单独放在了全局变量中,目的是什么?请想一下多设备能不能用
具体代码
对于CHIP_FAMILY的标记
struct pci_device_id {
__u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/
__u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
__u32 class, class_mask; /* (class,subclass,prog-if) triplet */
kernel_ulong_t driver_data; /* Data private to the driver */
};
ent->driver_data就是load时的flags
DRM_INFO("amdgpu kernel modesetting enabled.\n");
driver = &kms_driver;
pdriver = &amdgpu_kms_pci_driver;
driver->num_ioctls = amdgpu_max_kms_ioctl;
amdgpu_register_atpx_handler();
/* let modprobe override vga console setting */
return pci_register_driver(pdriver);
pci总线在扫描到有amd的ep时候,调用probe的hook,去启动对应的pci设备.我们在amd驱动中就是看见的.
还有一个点.没有解释.那就是初始化时候,需要amdgpu_sync_init和amdgpu_fence_slab_init,这个是做什么的?等以后弄明白了,再追加描述吧 开始probe
amdgpu的开发是向前兼容性强的.所以,在驱动初始化的时候发现,amdgpu会判断是不是启动了老设备
#ifdef CONFIG_DRM_AMDGPU_SI
#ifdef CONFIG_DRM_AMDGPU_CIK
目前看amdgpu支持的老radeon设备
#ifdef CONFIG_DRM_AMDGPU_SI
case CHIP_VERDE:
case CHIP_TAHITI:
case CHIP_PITCAIRN:
case CHIP_OLAND:
case CHIP_HAINAN:
#endif
#ifdef CONFIG_DRM_AMDGPU_CIK
case CHIP_BONAIRE:
case CHIP_HAWAII:
case CHIP_KAVERI:
case CHIP_KABINI:
case CHIP_MULLINS:
#endif
但是前提是打开了对应的bootargs的支持,如何打开在我之前的wiki上有说.回到load代码.amdgpu_kick_out_firmware_fb目的是移除冲突的amdgpudrmfb,让当前设备作为amdgpudrmfb.
然后我们看见了最重要的角色 drm_dev_alloc.
为啥? 不加他,drm都没初始化,后边的代码全启动失败.不信你试试,不panic你来找我(我给你写BUG())…
接下来pci_enable_device
使能pci设备.具体干啥的,那就看这个函数,就是让ep的mem和io干活了. pci_set_drvdata设备pdev中的dev->driver_data保存成drm_device设备,这麽做就是想用户态发现来filp的操作,能找见drm_device,架子上基本都是这么干的,记住就可以了
drm_dev_alloc
通过全局变量kms_driver,申请对应的drm_device. 这个函数里面会注册sys下的drm节点,初始化gem的vm_node管理器.,
最终的角色,也是probe中最中的目的drm_dev_register(dev, ent->driver_data)
将drm_device注册到drmcore. 第二个参数就是刚说到的,pci注册时的CHIP_FAMILY,这个函数里面还是有门道的.
我们看{{collapse(代码)
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);
意思是,先load一下drm设备,再初始化kms的设备drm_modeset_register_all,这样在kms之前,gpu硬件能全部准备完成
社区的意思是不想使用drm_driver里面的load这个hook了?咋整呢?有啥想法不?
drm_dev_register之前将所有准备工作做好.也就是把load提出来
- 接下来就是drm_driver的load阶段了.