Browse Source

Merge branch 'etnaviv/fixes' of https://git.pengutronix.de/git/lst/linux into drm-fixes

Lucas wrote:
"a couple of small fixes:
- 2 patches from Fabio to fix module reloading
- one patch to fix a userspace visible regression, where the job
timeout is a bit too eager and kills legitimate jobs"

Signed-off-by: Dave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1530868450.15725.8.camel@pengutronix.de
Dave Airlie 7 years ago
parent
commit
fcaca5d8d1

+ 20 - 4
drivers/gpu/drm/etnaviv/etnaviv_drv.c

@@ -631,8 +631,11 @@ static struct platform_driver etnaviv_platform_driver = {
 	},
 	},
 };
 };
 
 
+static struct platform_device *etnaviv_drm;
+
 static int __init etnaviv_init(void)
 static int __init etnaviv_init(void)
 {
 {
+	struct platform_device *pdev;
 	int ret;
 	int ret;
 	struct device_node *np;
 	struct device_node *np;
 
 
@@ -644,7 +647,7 @@ static int __init etnaviv_init(void)
 
 
 	ret = platform_driver_register(&etnaviv_platform_driver);
 	ret = platform_driver_register(&etnaviv_platform_driver);
 	if (ret != 0)
 	if (ret != 0)
-		platform_driver_unregister(&etnaviv_gpu_driver);
+		goto unregister_gpu_driver;
 
 
 	/*
 	/*
 	 * If the DT contains at least one available GPU device, instantiate
 	 * If the DT contains at least one available GPU device, instantiate
@@ -653,20 +656,33 @@ static int __init etnaviv_init(void)
 	for_each_compatible_node(np, NULL, "vivante,gc") {
 	for_each_compatible_node(np, NULL, "vivante,gc") {
 		if (!of_device_is_available(np))
 		if (!of_device_is_available(np))
 			continue;
 			continue;
-
-		platform_device_register_simple("etnaviv", -1, NULL, 0);
+		pdev = platform_device_register_simple("etnaviv", -1,
+						       NULL, 0);
+		if (IS_ERR(pdev)) {
+			ret = PTR_ERR(pdev);
+			of_node_put(np);
+			goto unregister_platform_driver;
+		}
+		etnaviv_drm = pdev;
 		of_node_put(np);
 		of_node_put(np);
 		break;
 		break;
 	}
 	}
 
 
+	return 0;
+
+unregister_platform_driver:
+	platform_driver_unregister(&etnaviv_platform_driver);
+unregister_gpu_driver:
+	platform_driver_unregister(&etnaviv_gpu_driver);
 	return ret;
 	return ret;
 }
 }
 module_init(etnaviv_init);
 module_init(etnaviv_init);
 
 
 static void __exit etnaviv_exit(void)
 static void __exit etnaviv_exit(void)
 {
 {
-	platform_driver_unregister(&etnaviv_gpu_driver);
+	platform_device_unregister(etnaviv_drm);
 	platform_driver_unregister(&etnaviv_platform_driver);
 	platform_driver_unregister(&etnaviv_platform_driver);
+	platform_driver_unregister(&etnaviv_gpu_driver);
 }
 }
 module_exit(etnaviv_exit);
 module_exit(etnaviv_exit);
 
 

+ 3 - 0
drivers/gpu/drm/etnaviv/etnaviv_gpu.h

@@ -131,6 +131,9 @@ struct etnaviv_gpu {
 	struct work_struct sync_point_work;
 	struct work_struct sync_point_work;
 	int sync_point_event;
 	int sync_point_event;
 
 
+	/* hang detection */
+	u32 hangcheck_dma_addr;
+
 	void __iomem *mmio;
 	void __iomem *mmio;
 	int irq;
 	int irq;
 
 

+ 24 - 0
drivers/gpu/drm/etnaviv/etnaviv_sched.c

@@ -10,6 +10,7 @@
 #include "etnaviv_gem.h"
 #include "etnaviv_gem.h"
 #include "etnaviv_gpu.h"
 #include "etnaviv_gpu.h"
 #include "etnaviv_sched.h"
 #include "etnaviv_sched.h"
+#include "state.xml.h"
 
 
 static int etnaviv_job_hang_limit = 0;
 static int etnaviv_job_hang_limit = 0;
 module_param_named(job_hang_limit, etnaviv_job_hang_limit, int , 0444);
 module_param_named(job_hang_limit, etnaviv_job_hang_limit, int , 0444);
@@ -85,6 +86,29 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job)
 {
 {
 	struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job);
 	struct etnaviv_gem_submit *submit = to_etnaviv_submit(sched_job);
 	struct etnaviv_gpu *gpu = submit->gpu;
 	struct etnaviv_gpu *gpu = submit->gpu;
+	u32 dma_addr;
+	int change;
+
+	/*
+	 * If the GPU managed to complete this jobs fence, the timout is
+	 * spurious. Bail out.
+	 */
+	if (fence_completed(gpu, submit->out_fence->seqno))
+		return;
+
+	/*
+	 * If the GPU is still making forward progress on the front-end (which
+	 * should never loop) we shift out the timeout to give it a chance to
+	 * finish the job.
+	 */
+	dma_addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS);
+	change = dma_addr - gpu->hangcheck_dma_addr;
+	if (change < 0 || change > 16) {
+		gpu->hangcheck_dma_addr = dma_addr;
+		schedule_delayed_work(&sched_job->work_tdr,
+				      sched_job->sched->timeout);
+		return;
+	}
 
 
 	/* block scheduler */
 	/* block scheduler */
 	kthread_park(gpu->sched.thread);
 	kthread_park(gpu->sched.thread);