Skip to content

Commit c4c03bb

Browse files
mwiniarsgregkh
authored andcommitted
drm: Use XArray instead of IDR for minors
[ Upstream commit 5fbca8b ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 98f7e32 commit c4c03bb

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);
@@ -1071,7 +1059,7 @@ static void drm_core_exit(void)
10711059
unregister_chrdev(DRM_MAJOR, "drm");
10721060
debugfs_remove(drm_debugfs_root);
10731061
drm_sysfs_destroy();
1074-
idr_destroy(&drm_minors_idr);
1062+
WARN_ON(!xa_empty(&drm_minors_xa));
10751063
drm_connector_ida_destroy();
10761064
}
10771065

@@ -1080,7 +1068,6 @@ static int __init drm_core_init(void)
10801068
int ret;
10811069

10821070
drm_connector_ida_init();
1083-
idr_init(&drm_minors_idr);
10841071
drm_memcpy_init_early();
10851072

10861073
ret = drm_sysfs_init();

0 commit comments

Comments
 (0)