diff options
| author | David Herrmann <dh.herrmann@gmail.com> | 2013-11-21 20:50:50 +1000 | 
|---|---|---|
| committer | Dave Airlie <airlied@gmail.com> | 2013-11-21 21:10:00 +1000 | 
| commit | 760c960bd6880cf22a57c0af9ff60c96250aad39 (patch) | |
| tree | fc301356c571ad9175c09b6c5bf35c31bfa58dac /drivers/gpu | |
| parent | c3bddbda36a74225ad3d04aaa9600a25aff6b98b (diff) | |
| download | linux-760c960bd6880cf22a57c0af9ff60c96250aad39.tar.bz2 | |
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>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/drm/drm_sysfs.c | 40 | 
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)  }  EXPORT_SYMBOL(drm_sysfs_hotplug_event); +static void drm_sysfs_release(struct device *dev) +{ +	kfree(dev); +} +  /**   * drm_sysfs_device_add - adds a class device to sysfs for a character driver   * @dev: DRM device to be added @@ -501,6 +506,7 @@ EXPORT_SYMBOL(drm_sysfs_hotplug_event);  int drm_sysfs_device_add(struct drm_minor *minor)  {  	char *minor_str; +	int r;  	if (minor->type == DRM_MINOR_CONTROL)  		minor_str = "controlD%d"; @@ -509,14 +515,34 @@ int drm_sysfs_device_add(struct drm_minor *minor)          else                  minor_str = "card%d"; -	minor->kdev = device_create(drm_class, minor->dev->dev, -				    MKDEV(DRM_MAJOR, minor->index), -				    minor, minor_str, minor->index); -	if (IS_ERR(minor->kdev)) { -		DRM_ERROR("device create failed %ld\n", PTR_ERR(minor->kdev)); -		return PTR_ERR(minor->kdev); +	minor->kdev = kzalloc(sizeof(*minor->kdev), GFP_KERNEL); +	if (!minor->dev) { +		r = -ENOMEM; +		goto error;  	} + +	device_initialize(minor->kdev); +	minor->kdev->devt = MKDEV(DRM_MAJOR, minor->index); +	minor->kdev->class = drm_class; +	minor->kdev->type = &drm_sysfs_device_minor; +	minor->kdev->parent = minor->dev->dev; +	minor->kdev->release = drm_sysfs_release; +	dev_set_drvdata(minor->kdev, minor); + +	r = dev_set_name(minor->kdev, minor_str, minor->index); +	if (r < 0) +		goto error; + +	r = device_add(minor->kdev); +	if (r < 0) +		goto error; +  	return 0; + +error: +	DRM_ERROR("device create failed %d\n", r); +	put_device(minor->kdev); +	return r;  }  /** @@ -529,7 +555,7 @@ int drm_sysfs_device_add(struct drm_minor *minor)  void drm_sysfs_device_remove(struct drm_minor *minor)  {  	if (minor->kdev) -		device_destroy(drm_class, MKDEV(DRM_MAJOR, minor->index)); +		device_unregister(minor->kdev);  	minor->kdev = NULL;  }  |