aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-11-21 05:50:50 -0500
committerDave Airlie <airlied@gmail.com>2013-11-21 06:10:00 -0500
commit760c960bd6880cf22a57c0af9ff60c96250aad39 (patch)
treefc301356c571ad9175c09b6c5bf35c31bfa58dac
parentc3bddbda36a74225ad3d04aaa9600a25aff6b98b (diff)
drm/sysfs: fix hotplug regression since lifetime changes
airlied: The lifetime changes introduced in 5bdebb183c9702a8c57a01dff09337be3de337a6 tried to use device_create, however that led to the regression where dev->type wasn't getting set correctly. First attempt at fixing it would have led to a race, so this undoes the device_createa work and does it all manually making sure the dev->type is setup before we register the device. Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_sysfs.c40
1 files changed, 33 insertions, 7 deletions
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 1a35ea53106b..bd2bca395792 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -489,6 +489,11 @@ void drm_sysfs_hotplug_event(struct drm_device *dev)
489} 489}
490EXPORT_SYMBOL(drm_sysfs_hotplug_event); 490EXPORT_SYMBOL(drm_sysfs_hotplug_event);
491 491
492static void drm_sysfs_release(struct device *dev)
493{
494 kfree(dev);
495}
496
492/** 497/**
493 * drm_sysfs_device_add - adds a class device to sysfs for a character driver 498 * drm_sysfs_device_add - adds a class device to sysfs for a character driver
494 * @dev: DRM device to be added 499 * @dev: DRM device to be added
@@ -501,6 +506,7 @@ EXPORT_SYMBOL(drm_sysfs_hotplug_event);
501int drm_sysfs_device_add(struct drm_minor *minor) 506int drm_sysfs_device_add(struct drm_minor *minor)
502{ 507{
503 char *minor_str; 508 char *minor_str;
509 int r;
504 510
505 if (minor->type == DRM_MINOR_CONTROL) 511 if (minor->type == DRM_MINOR_CONTROL)
506 minor_str = "controlD%d"; 512 minor_str = "controlD%d";
@@ -509,14 +515,34 @@ int drm_sysfs_device_add(struct drm_minor *minor)
509 else 515 else
510 minor_str = "card%d"; 516 minor_str = "card%d";
511 517
512 minor->kdev = device_create(drm_class, minor->dev->dev, 518 minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL);
513 MKDEV(DRM_MAJOR, minor->index), 519 if (!minor->dev) {
514 minor, minor_str, minor->index); 520 r = -ENOMEM;
515 if (IS_ERR(minor->kdev)) { 521 goto error;
516 DRM_ERROR("device create failed %ld\n", PTR_ERR(minor->kdev));
517 return PTR_ERR(minor->kdev);
518 } 522 }
523
524 device_initialize(minor->kdev);
525 minor->kdev->devt = MKDEV(DRM_MAJOR, minor->index);
526 minor->kdev->class = drm_class;
527 minor->kdev->type = &drm_sysfs_device_minor;
528 minor->kdev->parent = minor->dev->dev;
529 minor->kdev->release = drm_sysfs_release;
530 dev_set_drvdata(minor->kdev, minor);
531
532 r = dev_set_name(minor->kdev, minor_str, minor->index);
533 if (r < 0)
534 goto error;
535
536 r = device_add(minor->kdev);
537 if (r < 0)
538 goto error;
539
519 return 0; 540 return 0;
541
542error:
543 DRM_ERROR("device create failed %d\n", r);
544 put_device(minor->kdev);
545 return r;
520} 546}
521 547
522/** 548/**
@@ -529,7 +555,7 @@ int drm_sysfs_device_add(struct drm_minor *minor)
529void drm_sysfs_device_remove(struct drm_minor *minor) 555void drm_sysfs_device_remove(struct drm_minor *minor)
530{ 556{
531 if (minor->kdev) 557 if (minor->kdev)
532 device_destroy(drm_class, MKDEV(DRM_MAJOR, minor->index)); 558 device_unregister(minor->kdev);
533 minor->kdev = NULL; 559 minor->kdev = NULL;
534} 560}
535 561