Skip to content

Commit 5fbca8b

Browse files
mwiniarsChristianKoenigAMD
authored andcommitted
drm: Use XArray instead of IDR for minors
IDR is deprecated, and since XArray manages its own state with internal locking, it simplifies the locking on DRM side. Additionally, don't use the IRQ-safe variant, since operating on drm minor is not done in IRQ context. Suggested-by: Matthew Wilcox <willy@infradead.org> Signed-off-by: Michał Winiarski <michal.winiarski@intel.com> Acked-by: James Zhu <James.Zhu@amd.com> Acked-by: Christian König <christian.koenig@amd.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240823163048.2676257-2-michal.winiarski@intel.com Signed-off-by: Christian König <christian.koenig@amd.com>
1 parent 22bc22c commit 5fbca8b

1 file changed

Lines changed: 25 additions & 38 deletions

File tree

drivers/gpu/drm/drm_drv.c

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/pseudo_fs.h>
3535
#include <linux/slab.h>
3636
#include <linux/srcu.h>
37+
#include <linux/xarray.h>
3738

3839
#include <drm/drm_accel.h>
3940
#include <drm/drm_cache.h>
@@ -54,8 +55,7 @@ MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl");
5455
MODULE_DESCRIPTION("DRM shared core routines");
5556
MODULE_LICENSE("GPL and additional rights");
5657

57-
static DEFINE_SPINLOCK(drm_minor_lock);
58-
static struct idr drm_minors_idr;
58+
static DEFINE_XARRAY_ALLOC(drm_minors_xa);
5959

6060
/*
6161
* If the drm core fails to init for whatever reason,
@@ -101,26 +101,23 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
101101
static void drm_minor_alloc_release(struct drm_device *dev, void *data)
102102
{
103103
struct drm_minor *minor = data;
104-
unsigned long flags;
105104

106105
WARN_ON(dev != minor->dev);
107106

108107
put_device(minor->kdev);
109108

110-
if (minor->type == DRM_MINOR_ACCEL) {
109+
if (minor->type == DRM_MINOR_ACCEL)
111110
accel_minor_remove(minor->index);
112-
} else {
113-
spin_lock_irqsave(&drm_minor_lock, flags);
114-
idr_remove(&drm_minors_idr, minor->index);
115-
spin_unlock_irqrestore(&drm_minor_lock, flags);
116-
}
111+
else
112+
xa_erase(&drm_minors_xa, minor->index);
117113
}
118114

115+
#define DRM_MINOR_LIMIT(t) ({ typeof(t) _t = (t); XA_LIMIT(64 * _t, 64 * _t + 63); })
116+
119117
static int drm_minor_alloc(struct drm_device *dev, enum drm_minor_type type)
120118
{
121119
struct drm_minor *minor;
122-
unsigned long flags;
123-
int r;
120+
int index, r;
124121

125122
minor = drmm_kzalloc(dev, sizeof(*minor), GFP_KERNEL);
126123
if (!minor)
@@ -129,24 +126,17 @@ static int drm_minor_alloc(struct drm_device *dev, enum drm_minor_type type)
129126
minor->type = type;
130127
minor->dev = dev;
131128

132-
idr_preload(GFP_KERNEL);
133129
if (type == DRM_MINOR_ACCEL) {
134130
r = accel_minor_alloc();
131+
index = r;
135132
} else {
136-
spin_lock_irqsave(&drm_minor_lock, flags);
137-
r = idr_alloc(&drm_minors_idr,
138-
NULL,
139-
64 * type,
140-
64 * (type + 1),
141-
GFP_NOWAIT);
142-
spin_unlock_irqrestore(&drm_minor_lock, flags);
133+
r = xa_alloc(&drm_minors_xa, &index, NULL, DRM_MINOR_LIMIT(type), GFP_KERNEL);
143134
}
144-
idr_preload_end();
145135

146136
if (r < 0)
147137
return r;
148138

149-
minor->index = r;
139+
minor->index = index;
150140

151141
r = drmm_add_action_or_reset(dev, drm_minor_alloc_release, minor);
152142
if (r)
@@ -163,7 +153,7 @@ static int drm_minor_alloc(struct drm_device *dev, enum drm_minor_type type)
163153
static int drm_minor_register(struct drm_device *dev, enum drm_minor_type type)
164154
{
165155
struct drm_minor *minor;
166-
unsigned long flags;
156+
void *entry;
167157
int ret;
168158

169159
DRM_DEBUG("\n");
@@ -189,9 +179,12 @@ static int drm_minor_register(struct drm_device *dev, enum drm_minor_type type)
189179
if (minor->type == DRM_MINOR_ACCEL) {
190180
accel_minor_replace(minor, minor->index);
191181
} else {
192-
spin_lock_irqsave(&drm_minor_lock, flags);
193-
idr_replace(&drm_minors_idr, minor, minor->index);
194-
spin_unlock_irqrestore(&drm_minor_lock, flags);
182+
entry = xa_store(&drm_minors_xa, minor->index, minor, GFP_KERNEL);
183+
if (xa_is_err(entry)) {
184+
ret = xa_err(entry);
185+
goto err_debugfs;
186+
}
187+
WARN_ON(entry);
195188
}
196189

197190
DRM_DEBUG("new minor registered %d\n", minor->index);
@@ -205,20 +198,16 @@ static int drm_minor_register(struct drm_device *dev, enum drm_minor_type type)
205198
static void drm_minor_unregister(struct drm_device *dev, enum drm_minor_type type)
206199
{
207200
struct drm_minor *minor;
208-
unsigned long flags;
209201

210202
minor = *drm_minor_get_slot(dev, type);
211203
if (!minor || !device_is_registered(minor->kdev))
212204
return;
213205

214206
/* replace @minor with NULL so lookups will fail from now on */
215-
if (minor->type == DRM_MINOR_ACCEL) {
207+
if (minor->type == DRM_MINOR_ACCEL)
216208
accel_minor_replace(NULL, minor->index);
217-
} else {
218-
spin_lock_irqsave(&drm_minor_lock, flags);
219-
idr_replace(&drm_minors_idr, NULL, minor->index);
220-
spin_unlock_irqrestore(&drm_minor_lock, flags);
221-
}
209+
else
210+
xa_store(&drm_minors_xa, minor->index, NULL, GFP_KERNEL);
222211

223212
device_del(minor->kdev);
224213
dev_set_drvdata(minor->kdev, NULL); /* safety belt */
@@ -237,13 +226,12 @@ static void drm_minor_unregister(struct drm_device *dev, enum drm_minor_type typ
237226
struct drm_minor *drm_minor_acquire(unsigned int minor_id)
238227
{
239228
struct drm_minor *minor;
240-
unsigned long flags;
241229

242-
spin_lock_irqsave(&drm_minor_lock, flags);
243-
minor = idr_find(&drm_minors_idr, minor_id);
230+
xa_lock(&drm_minors_xa);
231+
minor = xa_load(&drm_minors_xa, minor_id);
244232
if (minor)
245233
drm_dev_get(minor->dev);
246-
spin_unlock_irqrestore(&drm_minor_lock, flags);
234+
xa_unlock(&drm_minors_xa);
247235

248236
if (!minor) {
249237
return ERR_PTR(-ENODEV);
@@ -1072,7 +1060,7 @@ static void drm_core_exit(void)
10721060
unregister_chrdev(DRM_MAJOR, "drm");
10731061
debugfs_remove(drm_debugfs_root);
10741062
drm_sysfs_destroy();
1075-
idr_destroy(&drm_minors_idr);
1063+
WARN_ON(!xa_empty(&drm_minors_xa));
10761064
drm_connector_ida_destroy();
10771065
}
10781066

@@ -1081,7 +1069,6 @@ static int __init drm_core_init(void)
10811069
int ret;
10821070

10831071
drm_connector_ida_init();
1084-
idr_init(&drm_minors_idr);
10851072
drm_memcpy_init_early();
10861073

10871074
ret = drm_sysfs_init();

0 commit comments

Comments
 (0)