accel: Use XArray instead of IDR for minors
authorjsg <jsg@openbsd.org>
Tue, 1 Oct 2024 06:36:45 +0000 (06:36 +0000)
committerjsg <jsg@openbsd.org>
Tue, 1 Oct 2024 06:36:45 +0000 (06:36 +0000)
From Michal Winiarski
f6b589e361538285fdad8cf62143e3cf3b2c8b2a in linux-6.6.y/6.6.53
45c4d994b82b08f0ce5eb50f8da29379c92a391e in mainline linux

sys/dev/pci/drm/drm_drv.c
sys/dev/pci/drm/drm_file.c
sys/dev/pci/drm/drm_internal.h
sys/dev/pci/drm/include/drm/drm_file.h

index 7dbc555..06f6e78 100644 (file)
@@ -71,7 +71,7 @@ MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl");
 MODULE_DESCRIPTION("DRM shared core routines");
 MODULE_LICENSE("GPL and additional rights");
 
-static DEFINE_XARRAY_ALLOC(drm_minors_xa);
+DEFINE_XARRAY_ALLOC(drm_minors_xa);
 
 /*
  * If the drm core fails to init for whatever reason,
@@ -144,6 +144,18 @@ SPLAY_PROTOTYPE(drm_file_tree, drm_file, link, drm_file_cmp);
  * registered and unregistered dynamically according to device-state.
  */
 
+static struct xarray *drm_minor_get_xa(enum drm_minor_type type)
+{
+       if (type == DRM_MINOR_PRIMARY || type == DRM_MINOR_RENDER)
+               return &drm_minors_xa;
+#if IS_ENABLED(CONFIG_DRM_ACCEL)
+       else if (type == DRM_MINOR_ACCEL)
+               return &accel_minors_xa;
+#endif
+       else
+               return ERR_PTR(-EOPNOTSUPP);
+}
+
 static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
                                             enum drm_minor_type type)
 {
@@ -169,13 +181,13 @@ static void drm_minor_alloc_release(struct drm_device *dev, void *data)
        put_device(minor->kdev);
 #endif
 
-       if (minor->type == DRM_MINOR_ACCEL)
-               accel_minor_remove(minor->index);
-       else
-               xa_erase(&drm_minors_xa, minor->index);
+       xa_erase(drm_minor_get_xa(minor->type), minor->index);
 }
 
-#define DRM_MINOR_LIMIT(t) ({ typeof(t) _t = (t); XA_LIMIT(64 * _t, 64 * _t + 63); })
+#define DRM_MINOR_LIMIT(t) ({ \
+       typeof(t) _t = (t); \
+       _t == DRM_MINOR_ACCEL ? XA_LIMIT(0, ACCEL_MAX_MINORS) : XA_LIMIT(64 * _t, 64 * _t + 63); \
+})
 
 static int drm_minor_alloc(struct drm_device *dev, enum drm_minor_type type)
 {
@@ -189,18 +201,11 @@ static int drm_minor_alloc(struct drm_device *dev, enum drm_minor_type type)
        minor->type = type;
        minor->dev = dev;
 
-       if (type == DRM_MINOR_ACCEL) {
-               r = accel_minor_alloc();
-               index = r;
-       } else {
-               r = xa_alloc(&drm_minors_xa, &index, NULL, DRM_MINOR_LIMIT(type), GFP_KERNEL);
-       }
-
+       r = xa_alloc(drm_minor_get_xa(type), &minor->index,
+                    NULL, DRM_MINOR_LIMIT(type), GFP_KERNEL);
        if (r < 0)
                return r;
 
-       minor->index = index;
-
        r = drmm_add_action_or_reset(dev, drm_minor_alloc_release, minor);
        if (r)
                return r;
@@ -246,16 +251,12 @@ static int drm_minor_register(struct drm_device *dev, enum drm_minor_type type)
 #endif
 
        /* replace NULL with @minor so lookups will succeed from now on */
-       if (minor->type == DRM_MINOR_ACCEL) {
-               accel_minor_replace(minor, minor->index);
-       } else {
-               entry = xa_store(&drm_minors_xa, minor->index, minor, GFP_KERNEL);
-               if (xa_is_err(entry)) {
-                       ret = xa_err(entry);
-                       goto err_debugfs;
-               }
-               WARN_ON(entry);
+       entry = xa_store(drm_minor_get_xa(type), minor->index, minor, GFP_KERNEL);
+       if (xa_is_err(entry)) {
+               ret = xa_err(entry);
+               goto err_debugfs;
        }
+       WARN_ON(entry);
 
        DRM_DEBUG("new minor registered %d\n", minor->index);
        return 0;
@@ -280,10 +281,7 @@ static void drm_minor_unregister(struct drm_device *dev, enum drm_minor_type typ
                return;
 
        /* replace @minor with NULL so lookups will fail from now on */
-       if (minor->type == DRM_MINOR_ACCEL)
-               accel_minor_replace(NULL, minor->index);
-       else
-               xa_store(&drm_minors_xa, minor->index, NULL, GFP_KERNEL);
+       xa_store(drm_minor_get_xa(type), minor->index, NULL, GFP_KERNEL);
 
 #ifdef __linux__
        device_del(minor->kdev);
@@ -301,15 +299,15 @@ static void drm_minor_unregister(struct drm_device *dev, enum drm_minor_type typ
  * minor->dev pointer will stay valid! However, the device may get unplugged and
  * unregistered while you hold the minor.
  */
-struct drm_minor *drm_minor_acquire(unsigned int minor_id)
+struct drm_minor *drm_minor_acquire(struct xarray *minor_xa, unsigned int minor_id)
 {
        struct drm_minor *minor;
 
-       xa_lock(&drm_minors_xa);
-       minor = xa_load(&drm_minors_xa, minor_id);
+       xa_lock(minor_xa);
+       minor = xa_load(minor_xa, minor_id);
        if (minor)
                drm_dev_get(minor->dev);
-       xa_unlock(&drm_minors_xa);
+       xa_unlock(minor_xa);
 
        if (!minor) {
                return ERR_PTR(-ENODEV);
@@ -1128,7 +1126,7 @@ static int drm_stub_open(struct inode *inode, struct file *filp)
 
        DRM_DEBUG("\n");
 
-       minor = drm_minor_acquire(iminor(inode));
+       minor = drm_minor_acquire(&drm_minors_xa, iminor(inode));
        if (IS_ERR(minor))
                return PTR_ERR(minor);
 
index a4f3e5c..d160a12 100644 (file)
@@ -426,7 +426,7 @@ int drm_open(struct inode *inode, struct file *filp)
        int retcode;
        int need_setup = 0;
 
-       minor = drm_minor_acquire(iminor(inode));
+       minor = drm_minor_acquire(&drm_minors_xa, iminor(inode));
        if (IS_ERR(minor))
                return PTR_ERR(minor);
 
index 584cc7f..e0db753 100644 (file)
@@ -77,10 +77,6 @@ void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
 void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
                                 uint32_t handle);
 
-/* drm_drv.c */
-struct drm_minor *drm_minor_acquire(unsigned int minor_id);
-void drm_minor_release(struct drm_minor *minor);
-
 /* drm_managed.c */
 void drm_managed_release(struct drm_device *dev);
 void drmm_add_final_kfree(struct drm_device *dev, void *container);
index 6e966a8..50ed4cf 100644 (file)
@@ -48,6 +48,8 @@ struct device;
 struct file;
 struct seq_file;
 
+extern struct xarray drm_minors_xa;
+
 /*
  * FIXME: Not sure we want to have drm_minor here in the end, but to avoid
  * header include loops we need it here for now.
@@ -449,6 +451,9 @@ static inline bool drm_is_accel_client(const struct drm_file *file_priv)
 
 void drm_file_update_pid(struct drm_file *);
 
+struct drm_minor *drm_minor_acquire(struct xarray *minors_xa, unsigned int minor_id);
+void drm_minor_release(struct drm_minor *minor);
+
 #ifdef __linux__
 int drm_open(struct inode *inode, struct file *filp);
 int drm_open_helper(struct file *filp, struct drm_minor *minor);