[PATCH 26/83] hsa/radeon: Make binding of process to device permanent

Oded Gabbay oded.gabbay at gmail.com
Thu Jul 10 14:50:26 PDT 2014


From: Andrew Lewycky <Andrew.Lewycky at amd.com>

Permanently bind the process to the device.
The binding survives even when all queues are destroyed.
Process exit and device removal terminate the binding.

Signed-off-by: Andrew Lewycky <Andrew.Lewycky at amd.com>
Signed-off-by: Oded Gabbay <oded.gabbay at amd.com>
---
 drivers/gpu/hsa/radeon/kfd_chardev.c | 27 +++------------------------
 drivers/gpu/hsa/radeon/kfd_priv.h    |  3 ---
 drivers/gpu/hsa/radeon/kfd_process.c | 21 ++++++++++-----------
 3 files changed, 13 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/hsa/radeon/kfd_chardev.c b/drivers/gpu/hsa/radeon/kfd_chardev.c
index 4e7d5d0..e0b276d 100644
--- a/drivers/gpu/hsa/radeon/kfd_chardev.c
+++ b/drivers/gpu/hsa/radeon/kfd_chardev.c
@@ -141,20 +141,13 @@ kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, void __user *a
 	pdd = radeon_kfd_bind_process_to_device(dev, p);
 	if (IS_ERR(pdd) < 0) {
 		err = PTR_ERR(pdd);
-		goto err_bind_pasid;
+		goto err_bind_process;
 	}
 
-	pr_debug("kfd: creating queue number %d for PASID %d on GPU 0x%x\n",
-			pdd->queue_count,
+	pr_debug("kfd: creating queue for PASID %d on GPU 0x%x\n",
 			p->pasid,
 			dev->id);
 
-	if (pdd->queue_count++ == 0) {
-		err = dev->device_info->scheduler_class->register_process(dev->scheduler, p, &pdd->scheduler_process);
-		if (err < 0)
-			goto err_register_process;
-	}
-
 	if (!radeon_kfd_allocate_queue_id(p, &queue_id))
 		goto err_allocate_queue_id;
 
@@ -198,12 +191,7 @@ err_copy_args_out:
 err_create_queue:
 	radeon_kfd_remove_queue(p, queue_id);
 err_allocate_queue_id:
-	if (--pdd->queue_count == 0) {
-		dev->device_info->scheduler_class->deregister_process(dev->scheduler, pdd->scheduler_process);
-		pdd->scheduler_process = NULL;
-	}
-err_register_process:
-err_bind_pasid:
+err_bind_process:
 	kfree(queue);
 	mutex_unlock(&p->mutex);
 	return err;
@@ -215,7 +203,6 @@ kfd_ioctl_destroy_queue(struct file *filp, struct kfd_process *p, void __user *a
 	struct kfd_ioctl_destroy_queue_args args;
 	struct kfd_queue *queue;
 	struct kfd_dev *dev;
-	struct kfd_process_device *pdd;
 
 	if (copy_from_user(&args, arg, sizeof(args)))
 		return -EFAULT;
@@ -239,14 +226,6 @@ kfd_ioctl_destroy_queue(struct file *filp, struct kfd_process *p, void __user *a
 
 	kfree(queue);
 
-	pdd = radeon_kfd_get_process_device_data(dev, p);
-	BUG_ON(pdd == NULL); /* Because a queue exists. */
-
-	if (--pdd->queue_count == 0) {
-		dev->device_info->scheduler_class->deregister_process(dev->scheduler, pdd->scheduler_process);
-		pdd->scheduler_process = NULL;
-	}
-
 	mutex_unlock(&p->mutex);
 	return 0;
 }
diff --git a/drivers/gpu/hsa/radeon/kfd_priv.h b/drivers/gpu/hsa/radeon/kfd_priv.h
index 630d690..bca9cce 100644
--- a/drivers/gpu/hsa/radeon/kfd_priv.h
+++ b/drivers/gpu/hsa/radeon/kfd_priv.h
@@ -166,9 +166,6 @@ struct kfd_process_device {
 	/* The user-mode address of the doorbell mapping for this device. */
 	doorbell_t __user *doorbell_mapping;
 
-	/* The number of queues created by this process for this device. */
-	uint32_t queue_count;
-
 	/* Scheduler process data for this device. */
 	struct kfd_scheduler_process *scheduler_process;
 
diff --git a/drivers/gpu/hsa/radeon/kfd_process.c b/drivers/gpu/hsa/radeon/kfd_process.c
index 145ee38..f89f855 100644
--- a/drivers/gpu/hsa/radeon/kfd_process.c
+++ b/drivers/gpu/hsa/radeon/kfd_process.c
@@ -120,15 +120,6 @@ destroy_queues(struct kfd_process *p, struct kfd_dev *dev_filter)
 			dev->device_info->scheduler_class->destroy_queue(dev->scheduler, &queue->scheduler_queue);
 
 			kfree(queue);
-
-			BUG_ON(pdd->queue_count == 0);
-			BUG_ON(pdd->scheduler_process == NULL);
-
-			if (--pdd->queue_count == 0) {
-				dev->device_info->scheduler_class->deregister_process(dev->scheduler,
-							pdd->scheduler_process);
-				pdd->scheduler_process = NULL;
-			}
 		}
 	}
 }
@@ -144,6 +135,8 @@ static void free_process(struct kfd_process *p)
 	/* doorbell mappings: automatic */
 
 	list_for_each_entry_safe(pdd, temp, &p->per_device_data, per_device_list) {
+		pdd->dev->device_info->scheduler_class->deregister_process(pdd->dev->scheduler, pdd->scheduler_process);
+		pdd->scheduler_process = NULL;
 		amd_iommu_unbind_pasid(pdd->dev->pdev, p->pasid);
 		list_del(&pdd->per_device_list);
 		kfree(pdd);
@@ -255,6 +248,12 @@ struct kfd_process_device *radeon_kfd_bind_process_to_device(struct kfd_dev *dev
 	if (err < 0)
 		return ERR_PTR(err);
 
+	err = dev->device_info->scheduler_class->register_process(dev->scheduler, p, &pdd->scheduler_process);
+	if (err < 0) {
+		amd_iommu_unbind_pasid(dev->pdev, p->pasid);
+		return ERR_PTR(err);
+	}
+
 	pdd->bound = true;
 
 	return pdd;
@@ -285,8 +284,8 @@ void radeon_kfd_unbind_process_from_device(struct kfd_dev *dev, pasid_t pasid)
 
 	destroy_queues(p, dev);
 
-	/* All queues just got destroyed so this should be gone. */
-	BUG_ON(pdd->scheduler_process != NULL);
+	dev->device_info->scheduler_class->deregister_process(dev->scheduler, pdd->scheduler_process);
+	pdd->scheduler_process = NULL;
 
 	/*
 	 * Just mark pdd as unbound, because we still need it to call
-- 
1.9.1



More information about the dri-devel mailing list