Panfrost GPU复位异常问题分析报告
1 关键字
panfrost; gpu; panfrost复位
2 问题描述
2.1 运行环境
-
软件环境:
-
OH版本:3.1release
-
kernel版本:linux-5.10
-
-
硬件环境:
-
SPRD 8541E
-
出于8541E闭源要求,部分详细操作只以文字方式描述。
2.2 问题现象:
在panfrost初始化过程中,GPU复位失败,有如下打印:
Line 2456: [ 4.988016] panfrost 60000000.gpu: gpu soft reset timed out
Line 2457: [ 4.994996] panfrost 60000000.gpu: Fatal error during GPU init
Line 2458: [ 5.000946] panfrost: probe of 60000000.gpu failed with error -110
GPU复位失败导致panfrost初始化失败,后续无法正常完成GPU渲染。
2.3 测试步骤
-
1、dts配置
-
增加panfrost驱动名称
gpu: gpu@fde60000 { - compatible = "sprd,mali-midgard"; + compatible = "sprd,mali-midgard", "arm,mali-t820";
-
修改中断名称
- interrupt-names = "GPU", "MMU", "JOB"; + interrupt-names = "gpu", "mmu", "job";
-
修改时钟名称
- clock-names = "clk_mali", "clk_gpu"; + clock-names = "core", "bus";
-
-
2、kernel内核配置
CONFIG_DRM_GEM_SHMEM_HELPER=y panfrost gem内存管理用到(必选) CONFIG_DRM_SCHED=y GPU命令流调度接口,必须打开(必选) CONFIG_DRM_PANFROST=y 打开panfrost功能(必选)
-
3、编译并下载
-
4、查看串口终端打印。
3 问题原因
3.1 正常机制
正常机制下,panfrost流程如下所示:
初始化成功后,GPU能正常使用。正常打印日志如下:
3.2 异常机制
异常机制下,会在gpu 复位流程中超时退出,如下所示:
超时退出,会有如下明显异常打印:
Line 2456: [ 4.988016] panfrost 60000000.gpu: gpu soft reset timed out Line 2457: [ 4.994996] panfrost 60000000.gpu: Fatal error during GPU init Line 2458: [ 5.000946] panfrost: probe of 60000000.gpu failed with error -110
这个时候读写GPU寄存器都会失败,读取总是返回0。
4、解决方案
造成3.2异常原因是GPU没有上电,参考厂家GPU驱动实现,写寄存器给GPU上电后,功能正常(详细方法不开源)。
5、定位过程
以下是我们处理这个问题时的思路分享:
从流程中可以看出,在出现异常之前,共有以下几个点可能导致GPU复位异常:
-
1、dts配置错误。
-
这是驱动开发的第一步
-
-
2、GPU基地址错误。
-
3、时钟初始化失败。
-
时钟配置错误或者没有打开。
-
-
4、GPU模块没有上电。
-
这是硬件模块开发第一个需要确认的点
-
5.1 dts配置错误
dts的修改,我们是基于原有GPU dts上修改的,修改的方法,我们可以对比主线的上rk3568,通过不断验证,发现最小的改动方式就只有以下三处:
-
增加panfrost驱动:arm,mali-t820
-
修改中断名称为小写。panfrost代码中只认识小写。
-
修改时钟名称为core,bus。
这里经过仔细对比,并没有发现问题。
5.2 GPU基地址错误
GPU的基地址是在dts中配置的。
reg = <0x60000000 0x4000>
从芯片手册文档中我们可以看出与GPU相关的基地址有两个:
-
0x60000000 是GPU控制器基地址
-
0x60100000 是APB总线控制基地址
配置是正确的,我们从以下代码打印也可以看出:
res = platform_get_resource(pfdev->pdev, IORESOURCE_MEM, 0);//从dts中获取GPU基地址
//在这里打印出res->start值
pfdev->iomem = devm_ioremap_resource(pfdev->dev, res);//映射从虚拟地址供程序使用
if (IS_ERR(pfdev->iomem)) {
dev_err(pfdev->dev, "failed to ioremap iomem\n");
err = PTR_ERR(pfdev->iomem);
goto out_pm_domain;
}
打印中,我们可以确认程序解析也没有问题。
5.3 时钟初始化失败
在panfrost中,时钟配置关键代码如下:
static int panfrost_clk_init(struct panfrost_device *pfdev)
{
……
pfdev->clock = devm_clk_get(pfdev->dev, NULL);//得到clk节点
……
rate = clk_get_rate(pfdev->clock);//得到默认时钟值
……
err = clk_prepare_enable(pfdev->clock);//使能GPU时钟
……
pfdev->bus_clock = devm_clk_get_optional(pfdev->dev, "bus");//得到bus时钟
……
if (pfdev->bus_clock) {
rate = clk_get_rate(pfdev->bus_clock);//得到dts配置值
……
err = clk_prepare_enable(pfdev->bus_clock);//使能bus总线
……
}
……
}
从以下代码中可以看出,总线及GPU时钟都有使能,并且并没有使用dts的配置值,因为这里没有set操作。GPU使用的也是默认值,并没有异常。
5.4 GPU模块没有上电
GPU由于是内置模块我们并没有办法通过硬件测量的方法,来确定模块是否已经上电成功。但我们通过对GPU寄存器读写可以发现,不管怎么操作,都对返回值没有任何影响。从现象来看,GPU模块完全没有工作,大概率模块根本就没有上电。
通过对比原厂GPU代码,我们发现8541E与其它芯片有些区别,在电源管理中,并没有给GPU上电,需要单独写寄存器上电。
至此,打印正常,问题解决!
6、知识分享
panfrost的是对ARM 系列GPU驱动的开源实现,它的功能主要是完成对GPU硬件的初始化,以及以job的方式,完成对渲染数据硬件处理。在用户空间,一般和mesa3D配合,完成对2D、3D等GPU的渲染。
当前linux内核中panfrost支持的arm GPU可以通过以下文件查看:
drivers/gpu/drm/panfrost/panfrost_drv.c
static const struct of_device_id dt_match[] = {
/* Set first to probe before the generic compatibles */
{ .compatible = "amlogic,meson-gxm-mali",
.data = &amlogic_data, },
{ .compatible = "amlogic,meson-g12a-mali",
.data = &amlogic_data, },
{ .compatible = "arm,mali-t604", .data = &default_data, },
{ .compatible = "arm,mali-t624", .data = &default_data, },
{ .compatible = "arm,mali-t628", .data = &default_data, },
{ .compatible = "arm,mali-t720", .data = &default_data, },
{ .compatible = "arm,mali-t760", .data = &default_data, },
{ .compatible = "arm,mali-t820", .data = &default_data, },
{ .compatible = "arm,mali-t830", .data = &default_data, },
{ .compatible = "arm,mali-t860", .data = &default_data, },
{ .compatible = "arm,mali-t880", .data = &default_data, },
{ .compatible = "arm,mali-bifrost", .data = &default_data, },
{}
};
最新的panfrost对ARM GPU支持列表: https://docs.mesa3d.org/drivers/panfrost.html
更多推荐
所有评论(0)