diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c
index 34c3bccc621a52f805b95b8ef6af6dc638f2e29f..d85528d000bf0db91d25b0889c7f4cb8cc02b175 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.c
+++ b/drivers/gpu/drm/panfrost/panfrost_device.c
@@ -69,6 +69,7 @@ int panfrost_device_init(struct panfrost_device *pfdev)
 	struct resource *res;
 
 	mutex_init(&pfdev->sched_lock);
+	INIT_LIST_HEAD(&pfdev->scheduled_jobs);
 
 	err = panfrost_clk_init(pfdev);
 	if (err) {
diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h
index 3aca60fa60a8c29d4e64099bad924ae6a0d5664e..a2887b36d68b6089472dd2b0f308c1446b5c8ae3 100644
--- a/drivers/gpu/drm/panfrost/panfrost_device.h
+++ b/drivers/gpu/drm/panfrost/panfrost_device.h
@@ -66,6 +66,7 @@ struct panfrost_device {
 	struct panfrost_job_slot *js;
 
 	struct panfrost_job *jobs[3];
+	struct list_head scheduled_jobs;
 
 	struct mutex sched_lock;
 };
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 3791c06a894bcae1e192e3dfacda88d858e4a7fa..2749bfb80ecd35d720b2e3d8ced3547623f7bfa6 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -244,6 +244,10 @@ static int panfrost_ioctl_gem_submit(struct drm_device *dev, void *data,
 		job->atom_nr = atoms[i].atom_nr;
 		job->requirements = atoms[i].requirements;
 		job->flush_id = latest_flush_id;
+		job->deps[0].atom_nr = atoms[i].deps[0].atom_nr;
+		job->deps[0].type = atoms[i].deps[0].type;
+		job->deps[1].atom_nr = atoms[i].deps[1].atom_nr;
+		job->deps[1].type = atoms[i].deps[1].type;
 
 		ret = panfrost_lookup_bos(dev, file, &atoms[i], job);
 		if (ret)
diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
index fb098f1947a1f3aac19c2300b5de5958555df431..a8b56616f806652dcab2de15724ebd7e659b6aa1 100644
--- a/drivers/gpu/drm/panfrost/panfrost_job.c
+++ b/drivers/gpu/drm/panfrost/panfrost_job.c
@@ -379,12 +379,16 @@ int panfrost_job_push(struct panfrost_job *job)
 
 	ret = panfrost_lock_bo_reservations(job->bos, job->bo_count,
 					    &acquire_ctx);
-	if (ret)
+	if (ret) {
+		mutex_unlock(&pfdev->sched_lock);
 		return ret;
+	}
 
 	ret = drm_sched_job_init(&job->base, entity, NULL);
-	if (ret)
+	if (ret) {
+		mutex_unlock(&pfdev->sched_lock);
 		goto unlock;
+	}
 
 	job->render_done_fence = dma_fence_get(&job->base.s_fence->finished);
 
@@ -392,6 +396,8 @@ int panfrost_job_push(struct panfrost_job *job)
 
 	drm_sched_entity_push_job(&job->base, entity);
 
+	list_add(&job->head, &pfdev->scheduled_jobs);
+
 	mutex_unlock(&pfdev->sched_lock);
 
 	panfrost_attach_object_fences(job->bos, job->bo_count,
@@ -408,23 +414,54 @@ int panfrost_job_push(struct panfrost_job *job)
 static void
 panfrost_job_free(struct drm_sched_job *sched_job)
 {
+	struct panfrost_job *job = to_panfrost_job(sched_job);
+	struct panfrost_device *pfdev = job->pfdev;
+
+	mutex_lock(&pfdev->sched_lock);
+	list_del(&job->head);
+	mutex_unlock(&pfdev->sched_lock);
+
 	drm_sched_job_cleanup(sched_job);
 }
 
-/**
- * Returns the fences that the bin or render job depends on, one by one.
- * panfrost_job_run() won't be called until all of them have been signaled.
- */
+struct panfrost_job *panfrost_job_lookup(struct panfrost_device *pfdev, int atom_nr)
+{
+	struct panfrost_job *job;
+
+	list_for_each_entry(job, &pfdev->scheduled_jobs, head) {
+		if (job->atom_nr == atom_nr)
+			return job;
+	}
+
+	return NULL;
+}
+
 static struct dma_fence *
 panfrost_job_dependency(struct drm_sched_job *sched_job,
 		   struct drm_sched_entity *s_entity)
 {
+	struct panfrost_job *job = to_panfrost_job(sched_job);
+	struct panfrost_device *pfdev = job->pfdev;
+	struct panfrost_job *dep;
 	struct dma_fence *fence = NULL;
+	int i;
+
+	mutex_lock(&pfdev->sched_lock);
+	for (i = 0; i < 2 && !fence; i++) {
+		if (!job->deps[i].atom_nr)
+			continue;
+		dep = panfrost_job_lookup(pfdev, job->deps[i].atom_nr);
+		if (!dep)
+			continue; /* Dep might have finished already */
+		/* TODO: Handle job->deps[i].type */
+		if (!dma_fence_is_signaled(dep->render_done_fence))
+			fence = dep->render_done_fence;
+	}
+	mutex_unlock(&pfdev->sched_lock);
 
 	return fence;
 }
 
-
 static struct dma_fence *panfrost_job_run(struct drm_sched_job *sched_job)
 {
 	struct panfrost_job *job = to_panfrost_job(sched_job);
@@ -432,6 +469,9 @@ static struct dma_fence *panfrost_job_run(struct drm_sched_job *sched_job)
 	int slot = panfrost_job_get_slot(job);
 	struct dma_fence *fence = NULL;
 
+	if (unlikely(job->base.s_fence->finished.error))
+		return NULL;
+
 	pfdev->jobs[slot] = job;
 
 	fence = panfrost_fence_create(pfdev, slot);
diff --git a/drivers/gpu/drm/panfrost/panfrost_job.h b/drivers/gpu/drm/panfrost/panfrost_job.h
index 4a80fb11c09a7aa90a2bfe4f121f1878ac204a11..b7d5f312acd7ad801f6ad27caaec0818e7bc1dec 100644
--- a/drivers/gpu/drm/panfrost/panfrost_job.h
+++ b/drivers/gpu/drm/panfrost/panfrost_job.h
@@ -4,6 +4,7 @@
 #ifndef __PANFROST_JOB_H__
 #define __PANFROST_JOB_H__
 
+#include <uapi/drm/panfrost_drm.h>
 #include <drm/gpu_scheduler.h>
 
 #define NUM_JOB_SLOTS	2	/* Don't need 3rd one until we have compute support */
@@ -31,6 +32,10 @@ struct panfrost_job {
 	u32 bo_count;
 
 	struct dma_fence *render_done_fence;
+
+	struct drm_panfrost_gem_submit_atom_dep deps[2];
+
+	struct list_head head;
 };
 
 int panfrost_job_init(struct panfrost_device *pfdev);
diff --git a/include/uapi/drm/panfrost_drm.h b/include/uapi/drm/panfrost_drm.h
index bb4c83b1065b1bf182b31956dcc5d0cbf1088590..d4d271e3720668c7d7ad954fd43e9b87c3555ec4 100644
--- a/include/uapi/drm/panfrost_drm.h
+++ b/include/uapi/drm/panfrost_drm.h
@@ -80,12 +80,21 @@ struct drm_panfrost_gem_cpu_fini {
 
 #define PANFROST_JD_REQ_FS (1 << 0)
 
+#define PANFROST_DEP_TYPE_ORDER	0x01
+#define PANFROST_DEP_TYPE_DATA	0x02
+
+struct drm_panfrost_gem_submit_atom_dep {
+	__u32 atom_nr;	/* job ID of dependency */
+	__u32 type;	/* one of PANFROST_DEP_TYPE_* */
+};
+
 struct drm_panfrost_gem_submit_atom {
 	__u64 jc;           /* in, address to GPU mapping of job descriptor */
 	__u32 atom_nr;      /* in, job ID */
 	__u32 requirements; /* in, a combination of PANFROST_JD_REQ_* */
 	__u64 bo_handles;
 	__u32 bo_handle_count;
+	struct drm_panfrost_gem_submit_atom_dep deps[2];
 };
 
 struct drm_panfrost_gem_submit {