drm/xe: Avoid any races around ccs_mode update

Ensure that there are no drm clients when changing CCS mode.
Allow exec_queue creation only with enabled CCS engines.

v2: Rebase

Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
Signed-off-by: Niranjana Vishwanathapura <niranjana.vishwanathapura@intel.com>
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
This commit is contained in:
Niranjana Vishwanathapura 2023-11-01 19:02:53 +00:00 committed by Rodrigo Vivi
parent f3bc5bb4d5
commit 78e2701a26
3 changed files with 28 additions and 0 deletions

View File

@ -73,6 +73,10 @@ static int xe_file_open(struct drm_device *dev, struct drm_file *file)
mutex_init(&xef->exec_queue.lock);
xa_init_flags(&xef->exec_queue.xa, XA_FLAGS_ALLOC1);
spin_lock(&xe->clients.lock);
xe->clients.count++;
spin_unlock(&xe->clients.lock);
file->driver_priv = xef;
return 0;
}
@ -105,6 +109,10 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file)
xa_destroy(&xef->vm.xa);
mutex_destroy(&xef->vm.lock);
spin_lock(&xe->clients.lock);
xe->clients.count--;
spin_unlock(&xe->clients.lock);
xe_drm_client_put(xef->client);
kfree(xef);
}
@ -225,6 +233,7 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
xe->info.force_execlist = xe_modparam.force_execlist;
spin_lock_init(&xe->irq.lock);
spin_lock_init(&xe->clients.lock);
init_waitqueue_head(&xe->ufence_wq);

View File

@ -310,6 +310,15 @@ struct xe_device {
enum xe_sriov_mode __mode;
} sriov;
/** @clients: drm clients info */
struct {
/** @lock: Protects drm clients info */
spinlock_t lock;
/** @count: number of drm clients */
u64 count;
} clients;
/** @usm: unified memory state */
struct {
/** @asid: convert a ASID to VM */

View File

@ -105,6 +105,7 @@ ccs_mode_store(struct device *kdev, struct device_attribute *attr,
const char *buff, size_t count)
{
struct xe_gt *gt = kobj_to_gt(&kdev->kobj);
struct xe_device *xe = gt_to_xe(gt);
u32 num_engines, num_slices;
int ret;
@ -123,12 +124,21 @@ ccs_mode_store(struct device *kdev, struct device_attribute *attr,
return -EINVAL;
}
/* CCS mode can only be updated when there are no drm clients */
spin_lock(&xe->clients.lock);
if (xe->clients.count) {
spin_unlock(&xe->clients.lock);
return -EBUSY;
}
if (gt->ccs_mode != num_engines) {
xe_gt_info(gt, "Setting compute mode to %d\n", num_engines);
gt->ccs_mode = num_engines;
xe_gt_reset_async(gt);
}
spin_unlock(&xe->clients.lock);
return count;
}