aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2014-07-23 04:34:52 -0400
committerDavid Herrmann <dh.herrmann@gmail.com>2014-08-05 10:08:17 -0400
commitf1b8596283f681b82546d6302bc7c372fdb2d422 (patch)
tree8f9a45047873ca59f5875d6e42562121659e24b7
parentec8f112db2ee0032f2b047109fdbd87f1c264ad8 (diff)
drm: make minor->index available early
Instead of allocating the minor-index during registration, we now do this during allocation. This way, debug-messages between minor-allocation and minor-registration will now use the correct minor instead of 0. Same is done for unregistration vs. free, so debug-messages between device-shutdown and device-destruction show proper indices. Even though minor-indices are allocated early, we don't enable minor lookup early. Instead, we keep the entry set to NULL and replace it during registration / unregistration. This way, the index is allocated but lookup only works if registered. Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
-rw-r--r--drivers/gpu/drm/drm_stub.c84
1 files changed, 46 insertions, 38 deletions
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index b249f14f66a9..8b24db51116e 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -256,6 +256,8 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
256static int drm_minor_alloc(struct drm_device *dev, unsigned int type) 256static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
257{ 257{
258 struct drm_minor *minor; 258 struct drm_minor *minor;
259 unsigned long flags;
260 int r;
259 261
260 minor = kzalloc(sizeof(*minor), GFP_KERNEL); 262 minor = kzalloc(sizeof(*minor), GFP_KERNEL);
261 if (!minor) 263 if (!minor)
@@ -264,57 +266,68 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
264 minor->type = type; 266 minor->type = type;
265 minor->dev = dev; 267 minor->dev = dev;
266 268
269 idr_preload(GFP_KERNEL);
270 spin_lock_irqsave(&drm_minor_lock, flags);
271 r = idr_alloc(&drm_minors_idr,
272 NULL,
273 64 * type,
274 64 * (type + 1),
275 GFP_NOWAIT);
276 spin_unlock_irqrestore(&drm_minor_lock, flags);
277 idr_preload_end();
278
279 if (r < 0)
280 goto err_free;
281
282 minor->index = r;
283
267 *drm_minor_get_slot(dev, type) = minor; 284 *drm_minor_get_slot(dev, type) = minor;
268 return 0; 285 return 0;
286
287err_free:
288 kfree(minor);
289 return r;
269} 290}
270 291
271static void drm_minor_free(struct drm_device *dev, unsigned int type) 292static void drm_minor_free(struct drm_device *dev, unsigned int type)
272{ 293{
273 struct drm_minor **slot; 294 struct drm_minor **slot, *minor;
295 unsigned long flags;
274 296
275 slot = drm_minor_get_slot(dev, type); 297 slot = drm_minor_get_slot(dev, type);
276 if (*slot) { 298 minor = *slot;
277 drm_mode_group_destroy(&(*slot)->mode_group); 299 if (!minor)
278 kfree(*slot); 300 return;
279 *slot = NULL; 301
280 } 302 drm_mode_group_destroy(&minor->mode_group);
303
304 spin_lock_irqsave(&drm_minor_lock, flags);
305 idr_remove(&drm_minors_idr, minor->index);
306 spin_unlock_irqrestore(&drm_minor_lock, flags);
307
308 kfree(minor);
309 *slot = NULL;
281} 310}
282 311
283static int drm_minor_register(struct drm_device *dev, unsigned int type) 312static int drm_minor_register(struct drm_device *dev, unsigned int type)
284{ 313{
285 struct drm_minor *new_minor; 314 struct drm_minor *minor;
286 unsigned long flags; 315 unsigned long flags;
287 int ret; 316 int ret;
288 int minor_id;
289 317
290 DRM_DEBUG("\n"); 318 DRM_DEBUG("\n");
291 319
292 new_minor = *drm_minor_get_slot(dev, type); 320 minor = *drm_minor_get_slot(dev, type);
293 if (!new_minor) 321 if (!minor)
294 return 0; 322 return 0;
295 323
296 idr_preload(GFP_KERNEL); 324 ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
297 spin_lock_irqsave(&drm_minor_lock, flags);
298 minor_id = idr_alloc(&drm_minors_idr,
299 NULL,
300 64 * type,
301 64 * (type + 1),
302 GFP_NOWAIT);
303 spin_unlock_irqrestore(&drm_minor_lock, flags);
304 idr_preload_end();
305
306 if (minor_id < 0)
307 return minor_id;
308
309 new_minor->index = minor_id;
310
311 ret = drm_debugfs_init(new_minor, minor_id, drm_debugfs_root);
312 if (ret) { 325 if (ret) {
313 DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n"); 326 DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
314 goto err_id; 327 return ret;
315 } 328 }
316 329
317 ret = drm_sysfs_device_add(new_minor); 330 ret = drm_sysfs_device_add(minor);
318 if (ret) { 331 if (ret) {
319 DRM_ERROR("DRM: Error sysfs_device_add.\n"); 332 DRM_ERROR("DRM: Error sysfs_device_add.\n");
320 goto err_debugfs; 333 goto err_debugfs;
@@ -322,19 +335,14 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)
322 335
323 /* replace NULL with @minor so lookups will succeed from now on */ 336 /* replace NULL with @minor so lookups will succeed from now on */
324 spin_lock_irqsave(&drm_minor_lock, flags); 337 spin_lock_irqsave(&drm_minor_lock, flags);
325 idr_replace(&drm_minors_idr, new_minor, new_minor->index); 338 idr_replace(&drm_minors_idr, minor, minor->index);
326 spin_unlock_irqrestore(&drm_minor_lock, flags); 339 spin_unlock_irqrestore(&drm_minor_lock, flags);
327 340
328 DRM_DEBUG("new minor assigned %d\n", minor_id); 341 DRM_DEBUG("new minor registered %d\n", minor->index);
329 return 0; 342 return 0;
330 343
331err_debugfs: 344err_debugfs:
332 drm_debugfs_cleanup(new_minor); 345 drm_debugfs_cleanup(minor);
333err_id:
334 spin_lock_irqsave(&drm_minor_lock, flags);
335 idr_remove(&drm_minors_idr, minor_id);
336 spin_unlock_irqrestore(&drm_minor_lock, flags);
337 new_minor->index = 0;
338 return ret; 346 return ret;
339} 347}
340 348
@@ -347,10 +355,10 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
347 if (!minor || !minor->kdev) 355 if (!minor || !minor->kdev)
348 return; 356 return;
349 357
358 /* replace @minor with NULL so lookups will fail from now on */
350 spin_lock_irqsave(&drm_minor_lock, flags); 359 spin_lock_irqsave(&drm_minor_lock, flags);
351 idr_remove(&drm_minors_idr, minor->index); 360 idr_replace(&drm_minors_idr, NULL, minor->index);
352 spin_unlock_irqrestore(&drm_minor_lock, flags); 361 spin_unlock_irqrestore(&drm_minor_lock, flags);
353 minor->index = 0;
354 362
355 drm_debugfs_cleanup(minor); 363 drm_debugfs_cleanup(minor);
356 drm_sysfs_device_remove(minor); 364 drm_sysfs_device_remove(minor);