diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2014-07-23 04:34:52 -0400 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2014-08-05 10:08:17 -0400 |
commit | f1b8596283f681b82546d6302bc7c372fdb2d422 (patch) | |
tree | 8f9a45047873ca59f5875d6e42562121659e24b7 | |
parent | ec8f112db2ee0032f2b047109fdbd87f1c264ad8 (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.c | 84 |
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, | |||
256 | static int drm_minor_alloc(struct drm_device *dev, unsigned int type) | 256 | static 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 | |||
287 | err_free: | ||
288 | kfree(minor); | ||
289 | return r; | ||
269 | } | 290 | } |
270 | 291 | ||
271 | static void drm_minor_free(struct drm_device *dev, unsigned int type) | 292 | static 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 | ||
283 | static int drm_minor_register(struct drm_device *dev, unsigned int type) | 312 | static 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 | ||
331 | err_debugfs: | 344 | err_debugfs: |
332 | drm_debugfs_cleanup(new_minor); | 345 | drm_debugfs_cleanup(minor); |
333 | err_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); |