Skip to content

Commit

Permalink
[media] V4L: dynamically allocate video_device nodes in subdevices
Browse files Browse the repository at this point in the history
Currently only very few drivers actually use video_device nodes, embedded
in struct v4l2_subdev. Allocate these nodes dynamically for those drivers
to save memory for the rest.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Tested-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Guennadi Liakhovetski authored and Mauro Carvalho Chehab committed Nov 3, 2011
1 parent 2fbdc9b commit 3e0ec41
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
36 changes: 31 additions & 5 deletions drivers/media/video/v4l2-device.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#if defined(CONFIG_SPI)
#include <linux/spi/spi.h>
#endif
Expand Down Expand Up @@ -193,6 +194,13 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
}
EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);

static void v4l2_device_release_subdev_node(struct video_device *vdev)
{
struct v4l2_subdev *sd = video_get_drvdata(vdev);
sd->devnode = NULL;
kfree(vdev);
}

int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
{
struct video_device *vdev;
Expand All @@ -206,22 +214,40 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
continue;

vdev = &sd->devnode;
vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
if (!vdev) {
err = -ENOMEM;
goto clean_up;
}

video_set_drvdata(vdev, sd);
strlcpy(vdev->name, sd->name, sizeof(vdev->name));
vdev->v4l2_dev = v4l2_dev;
vdev->fops = &v4l2_subdev_fops;
vdev->release = video_device_release_empty;
vdev->release = v4l2_device_release_subdev_node;
vdev->ctrl_handler = sd->ctrl_handler;
err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
sd->owner);
if (err < 0)
return err;
if (err < 0) {
kfree(vdev);
goto clean_up;
}
#if defined(CONFIG_MEDIA_CONTROLLER)
sd->entity.v4l.major = VIDEO_MAJOR;
sd->entity.v4l.minor = vdev->minor;
#endif
sd->devnode = vdev;
}
return 0;

clean_up:
list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
if (!sd->devnode)
break;
video_unregister_device(sd->devnode);
}

return err;
}
EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes);

Expand All @@ -247,7 +273,7 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
if (v4l2_dev->mdev)
media_device_unregister_entity(&sd->entity);
#endif
video_unregister_device(&sd->devnode);
video_unregister_device(sd->devnode);
module_put(sd->owner);
}
EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
4 changes: 2 additions & 2 deletions include/media/v4l2-subdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -534,13 +534,13 @@ struct v4l2_subdev {
void *dev_priv;
void *host_priv;
/* subdev device node */
struct video_device devnode;
struct video_device *devnode;
};

#define media_entity_to_v4l2_subdev(ent) \
container_of(ent, struct v4l2_subdev, entity)
#define vdev_to_v4l2_subdev(vdev) \
container_of(vdev, struct v4l2_subdev, devnode)
video_get_drvdata(vdev)

/*
* Used for storing subdev information per file handle
Expand Down

0 comments on commit 3e0ec41

Please sign in to comment.