From fc7367debb7f01c82a6c4c67f86b7a405dbefb75 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 27 Sep 2023 13:53:08 +0100 Subject: [PATCH] drm/tegra: Fix crash when engine probe fails If probing of the VIC engine fails then the following crash is observed ... tegra-vic 15340000.vic: devfreq_add_device: Unable to find governor for the device tegra-vic 15340000.vic: failed to init devfreq: -22 tegra-vic: probe of 15340000.vic failed with error -22 tegra-nvdec 15480000.nvdec: Adding to iommu group 45 list_add corruption. prev->next should be next (ffff000094505f80), but was 0000000000000000. (prev=ffff000095245cf0). ------------[ cut here ]------------ kernel BUG at lib/list_debug.c:26! Internal error: Oops - BUG: 00000000f2000800 [#1] SMP ... pc : __list_add_valid+0x80/0x84 lr : __list_add_valid+0x80/0x84 ... Call trace: __list_add_valid+0x80/0x84 host1x_subdev_register+0x80/0x170 [host1x_next] __host1x_client_register+0xac/0x160 [host1x_next] nvdec_probe+0x1c8/0x58c [tegra_drm_next] platform_probe+0x6c/0xe0 really_probe+0xc4/0x3dc __driver_probe_device+0x114/0x190 driver_probe_device+0x44/0x114 __driver_attach+0xcc/0x1f0 bus_for_each_dev+0x78/0xd0 driver_attach+0x28/0x30 bus_add_driver+0xbc/0x220 driver_register+0x70/0x120 __platform_register_drivers+0x70/0x140 host1x_drm_init+0x58/0x1000 [tegra_drm_next] do_one_initcall+0x48/0x2d0 do_init_module+0x5c/0x270 load_module+0xb08/0xc70 __do_sys_init_module+0x1dc/0x214 __arm64_sys_init_module+0x20/0x2c invoke_syscall.constprop.0+0x7c/0xd0 el0_svc_common.constprop.0+0x140/0x150 do_el0_svc+0x38/0xa0 el0_svc+0x38/0x18c el0t_64_sync_handler+0xb4/0x130 el0t_64_sync+0x17c/0x180 Code: aa0103e2 910fa000 aa0403e1 941b9509 (d4210000) ---[ end trace f8f20f933fe03c7e ]--- The problem is that some of the engines are not cleaning up correctly on probe failure and so fix this by adding the necessary calls clean up if probe fails. Bug 4303860 Change-Id: Ife1e0ce7429458d187422162a298cc140f0e3bc4 Signed-off-by: Jon Hunter Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2986790 Reviewed-by: Mikko Perttunen GVS: Gerrit_Virtual_Submit --- drivers/gpu/drm/tegra/nvdec.c | 7 +++++-- drivers/gpu/drm/tegra/nvenc.c | 7 +++++-- drivers/gpu/drm/tegra/nvjpg.c | 7 +++++-- drivers/gpu/drm/tegra/vic.c | 8 ++++++-- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/tegra/nvdec.c b/drivers/gpu/drm/tegra/nvdec.c index 6bd7c57a..18a017d3 100644 --- a/drivers/gpu/drm/tegra/nvdec.c +++ b/drivers/gpu/drm/tegra/nvdec.c @@ -835,13 +835,13 @@ static int nvdec_probe(struct platform_device *pdev) err = clk_set_rate(nvdec->clks[0].clk, ULONG_MAX); if (err < 0) { dev_err(&pdev->dev, "failed to set clock rate: %d\n", err); - goto exit_falcon; + goto exit_actmon; } err = nvdec_devfreq_init(nvdec); if (err < 0) { dev_err(&pdev->dev, "failed to init devfreq: %d\n", err); - goto exit_falcon; + goto exit_actmon; } pm_runtime_enable(dev); @@ -850,6 +850,9 @@ static int nvdec_probe(struct platform_device *pdev) return 0; +exit_actmon: + host1x_actmon_unregister(&nvdec->client.base); + host1x_client_unregister(&nvdec->client.base); exit_falcon: falcon_exit(&nvdec->falcon); diff --git a/drivers/gpu/drm/tegra/nvenc.c b/drivers/gpu/drm/tegra/nvenc.c index f19f02ed..e7c1c13f 100644 --- a/drivers/gpu/drm/tegra/nvenc.c +++ b/drivers/gpu/drm/tegra/nvenc.c @@ -701,13 +701,13 @@ static int nvenc_probe(struct platform_device *pdev) err = clk_set_rate(nvenc->clk, ULONG_MAX); if (err < 0) { dev_err(&pdev->dev, "failed to set clock rate\n"); - goto exit_falcon; + goto exit_actmon; } err = nvenc_devfreq_init(nvenc); if (err < 0) { dev_err(&pdev->dev, "failed to init devfreq: %d\n", err); - goto exit_falcon; + goto exit_actmon; } pm_runtime_enable(dev); @@ -716,6 +716,9 @@ static int nvenc_probe(struct platform_device *pdev) return 0; +exit_actmon: + host1x_actmon_unregister(&nvenc->client.base); + host1x_client_unregister(&nvenc->client.base); exit_falcon: falcon_exit(&nvenc->falcon); diff --git a/drivers/gpu/drm/tegra/nvjpg.c b/drivers/gpu/drm/tegra/nvjpg.c index cd40b3fe..3d2d636e 100644 --- a/drivers/gpu/drm/tegra/nvjpg.c +++ b/drivers/gpu/drm/tegra/nvjpg.c @@ -688,13 +688,13 @@ static int nvjpg_probe(struct platform_device *pdev) err = clk_set_rate(nvjpg->clk, ULONG_MAX); if (err < 0) { dev_err(&pdev->dev, "failed to set clock rate\n"); - goto exit_falcon; + goto exit_actmon; } err = nvjpg_devfreq_init(nvjpg); if (err < 0) { dev_err(&pdev->dev, "failed to init devfreq: %d\n", err); - goto exit_falcon; + goto exit_actmon; } pm_runtime_enable(dev); @@ -703,6 +703,9 @@ static int nvjpg_probe(struct platform_device *pdev) return 0; +exit_actmon: + host1x_actmon_unregister(&nvjpg->client.base); + host1x_client_unregister(&nvjpg->client.base); exit_falcon: falcon_exit(&nvjpg->falcon); diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c index e8251088..79f02bd1 100644 --- a/drivers/gpu/drm/tegra/vic.c +++ b/drivers/gpu/drm/tegra/vic.c @@ -769,13 +769,13 @@ static int vic_probe(struct platform_device *pdev) err = clk_set_rate(vic->clk, ULONG_MAX); if (err < 0) { dev_err(&pdev->dev, "failed to set clock rate: %d\n", err); - goto exit_falcon; + goto exit_actmon; } err = vic_devfreq_init(vic); if (err < 0) { dev_err(&pdev->dev, "failed to init devfreq: %d\n", err); - goto exit_falcon; + goto exit_actmon; } pm_runtime_enable(dev); @@ -784,6 +784,10 @@ static int vic_probe(struct platform_device *pdev) return 0; +exit_actmon: + host1x_actmon_unregister(&vic->client.base); + host1x_client_unregister(&vic->client.base); + exit_falcon: falcon_exit(&vic->falcon);