Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 24e9a47e authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

[media] v4l2-async: Don't use dynamic static allocation



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: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
Reviewed-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent 278ba83a
Loading
Loading
Loading
Loading
+27 −3
Original line number Diff line number Diff line
@@ -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];

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

	notifier->v4l2_dev = NULL;