diff mbox

[RFC,v2,08/17] media-device: Make devnode.dev->kobj parent of devnode.cdev

Message ID 1471602228-30722-9-git-send-email-sakari.ailus@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sakari Ailus Aug. 19, 2016, 10:23 a.m. UTC
The struct cdev embedded in struct media_devnode contains its own kobj.
Instead of trying to manage its lifetime separately from struct
media_devnode, make the cdev kobj a parent of the struct media_device.dev
kobj.

The cdev will thus be released during unregistering the media_devnode, not
in media_devnode.dev kobj's release callback.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
---
 drivers/media/media-devnode.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

Comments

Hans Verkuil Aug. 22, 2016, 12:17 p.m. UTC | #1
On 08/19/2016 12:23 PM, Sakari Ailus wrote:
> The struct cdev embedded in struct media_devnode contains its own kobj.
> Instead of trying to manage its lifetime separately from struct
> media_devnode, make the cdev kobj a parent of the struct media_device.dev
> kobj.
> 
> The cdev will thus be released during unregistering the media_devnode, not
> in media_devnode.dev kobj's release callback.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> ---
>  drivers/media/media-devnode.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
> index aa8030b..69f84a7 100644
> --- a/drivers/media/media-devnode.c
> +++ b/drivers/media/media-devnode.c
> @@ -63,9 +63,6 @@ static void media_devnode_release(struct device *cd)
>  
>  	mutex_lock(&media_devnode_lock);
>  
> -	/* Delete the cdev on this minor as well */
> -	cdev_del(&devnode->cdev);
> -
>  	/* Mark device node number as free */
>  	clear_bit(devnode->minor, media_devnode_nums);
>  
> @@ -246,6 +243,7 @@ int __must_check media_devnode_register(struct media_devnode *devnode,
>  
>  	/* Part 2: Initialize and register the character device */
>  	cdev_init(&devnode->cdev, &media_devnode_fops);
> +	devnode->cdev.kobj.parent = &devnode->dev.kobj;
>  	devnode->cdev.owner = owner;
>  
>  	ret = cdev_add(&devnode->cdev, MKDEV(MAJOR(media_dev_t), devnode->minor), 1);
> @@ -291,6 +289,7 @@ void media_devnode_unregister(struct media_devnode *devnode)
>  	clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
>  	mutex_unlock(&media_devnode_lock);
>  	device_unregister(&devnode->dev);
> +	cdev_del(&devnode->cdev);

Are you sure about this order? Shouldn't cdev_del be called first?

The register() calls cdev_add() before device_add(), so I would expect the
reverse order here. This is also what cec-core.c does.

Regards,

	Hans

>  }
>  
>  /*
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sakari Ailus Aug. 22, 2016, 1:52 p.m. UTC | #2
On Mon, Aug 22, 2016 at 02:17:28PM +0200, Hans Verkuil wrote:
> On 08/19/2016 12:23 PM, Sakari Ailus wrote:
> > The struct cdev embedded in struct media_devnode contains its own kobj.
> > Instead of trying to manage its lifetime separately from struct
> > media_devnode, make the cdev kobj a parent of the struct media_device.dev
> > kobj.
> > 
> > The cdev will thus be released during unregistering the media_devnode, not
> > in media_devnode.dev kobj's release callback.
> > 
> > Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
> > ---
> >  drivers/media/media-devnode.c | 5 ++---
> >  1 file changed, 2 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
> > index aa8030b..69f84a7 100644
> > --- a/drivers/media/media-devnode.c
> > +++ b/drivers/media/media-devnode.c
> > @@ -63,9 +63,6 @@ static void media_devnode_release(struct device *cd)
> >  
> >  	mutex_lock(&media_devnode_lock);
> >  
> > -	/* Delete the cdev on this minor as well */
> > -	cdev_del(&devnode->cdev);
> > -
> >  	/* Mark device node number as free */
> >  	clear_bit(devnode->minor, media_devnode_nums);
> >  
> > @@ -246,6 +243,7 @@ int __must_check media_devnode_register(struct media_devnode *devnode,
> >  
> >  	/* Part 2: Initialize and register the character device */
> >  	cdev_init(&devnode->cdev, &media_devnode_fops);
> > +	devnode->cdev.kobj.parent = &devnode->dev.kobj;
> >  	devnode->cdev.owner = owner;
> >  
> >  	ret = cdev_add(&devnode->cdev, MKDEV(MAJOR(media_dev_t), devnode->minor), 1);
> > @@ -291,6 +289,7 @@ void media_devnode_unregister(struct media_devnode *devnode)
> >  	clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
> >  	mutex_unlock(&media_devnode_lock);
> >  	device_unregister(&devnode->dev);
> > +	cdev_del(&devnode->cdev);
> 
> Are you sure about this order? Shouldn't cdev_del be called first?
> 
> The register() calls cdev_add() before device_add(), so I would expect the
> reverse order here. This is also what cec-core.c does.

Correct.

It's possible that device_unregister() releases the last reference to the
struct device, which in turn causes the memory to be released.

I'll fix that.
diff mbox

Patch

diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index aa8030b..69f84a7 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -63,9 +63,6 @@  static void media_devnode_release(struct device *cd)
 
 	mutex_lock(&media_devnode_lock);
 
-	/* Delete the cdev on this minor as well */
-	cdev_del(&devnode->cdev);
-
 	/* Mark device node number as free */
 	clear_bit(devnode->minor, media_devnode_nums);
 
@@ -246,6 +243,7 @@  int __must_check media_devnode_register(struct media_devnode *devnode,
 
 	/* Part 2: Initialize and register the character device */
 	cdev_init(&devnode->cdev, &media_devnode_fops);
+	devnode->cdev.kobj.parent = &devnode->dev.kobj;
 	devnode->cdev.owner = owner;
 
 	ret = cdev_add(&devnode->cdev, MKDEV(MAJOR(media_dev_t), devnode->minor), 1);
@@ -291,6 +289,7 @@  void media_devnode_unregister(struct media_devnode *devnode)
 	clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
 	mutex_unlock(&media_devnode_lock);
 	device_unregister(&devnode->dev);
+	cdev_del(&devnode->cdev);
 }
 
 /*