Skip to content

Commit

Permalink
[media] v4l2-async: Don't use dynamic static allocation
Browse files Browse the repository at this point in the history
Dynamic static allocation is evil, as Kernel stack is too low, and
compilation complains about it on some archs:
	drivers/media/v4l2-core/v4l2-async.c:238:1: warning: 'v4l2_async_notifier_unregister' uses dynamic stack allocation [enabled by default]
Instead, let's enforce a limit for the buffer.
In this specific case, there's a hard limit imposed by V4L2_MAX_SUBDEVS,
with is currently 128. That means that the buffer size can be up to
128x8 = 1024 bytes (on a 64bits kernel), with is too big for stack.
Worse than that, someone could increase it and cause real troubles.
So, let's use dynamically allocated data, instead.

Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
  • Loading branch information
Mauro Carvalho Chehab committed Nov 8, 2013
1 parent 278ba83 commit 24e9a47
Showing 1 changed file with 27 additions and 3 deletions.
30 changes: 27 additions & 3 deletions drivers/media/v4l2-core/v4l2-async.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,30 +189,53 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
struct v4l2_subdev *sd, *tmp;
unsigned int notif_n_subdev = notifier->num_subdevs;
unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS);
struct device *dev[n_subdev];
struct device **dev;
int i = 0;

if (!notifier->v4l2_dev)
return;

dev = kmalloc(n_subdev * sizeof(*dev), GFP_KERNEL);
if (!dev) {
dev_err(notifier->v4l2_dev->dev,
"Failed to allocate device cache!\n");
}

mutex_lock(&list_lock);

list_del(&notifier->list);

list_for_each_entry_safe(sd, tmp, &notifier->done, async_list) {
dev[i] = get_device(sd->dev);
struct device *d;

d = get_device(sd->dev);

v4l2_async_cleanup(sd);

/* If we handled USB devices, we'd have to lock the parent too */
device_release_driver(dev[i++]);
device_release_driver(d);

if (notifier->unbind)
notifier->unbind(notifier, sd, sd->asd);

/*
* Store device at the device cache, in order to call
* put_device() on the final step
*/
if (dev)
dev[i++] = d;
else
put_device(d);
}

mutex_unlock(&list_lock);

/*
* Call device_attach() to reprobe devices
*
* NOTE: If dev allocation fails, i is 0, and the whole loop won't be
* executed.
*/
while (i--) {
struct device *d = dev[i];

Expand All @@ -228,6 +251,7 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
}
put_device(d);
}
kfree(dev);

notifier->v4l2_dev = NULL;

Expand Down

0 comments on commit 24e9a47

Please sign in to comment.