From f9e9c0669f15919a0e5e2908369eb6406af95ca0 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Mon, 26 Dec 2016 15:14:33 -0200 Subject: [media] v4l2-async: Use kmalloc_array() in v4l2_async_notifier_unregister() A multiplication for the size determination of a memory allocation indicated that an array data structure should be processed. Thus use the corresponding function "kmalloc_array". This issue was detected by using the Coccinelle software. Signed-off-by: Markus Elfring Acked-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-async.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/media/v4l2-core/v4l2-async.c') diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 5bada202b2d3..277183f2d514 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -202,7 +202,7 @@ void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier) if (!notifier->v4l2_dev) return; - dev = kmalloc(n_subdev * sizeof(*dev), GFP_KERNEL); + dev = kmalloc_array(n_subdev, sizeof(*dev), GFP_KERNEL); if (!dev) { dev_err(notifier->v4l2_dev->dev, "Failed to allocate device cache!\n"); -- cgit v1.2.3 From d2180e0cf77dc7a7049671d5d57dfa0a228f83c1 Mon Sep 17 00:00:00 2001 From: Javi Merino Date: Mon, 5 Dec 2016 08:09:56 -0200 Subject: [media] v4l: async: make v4l2 coexist with devicetree nodes in a dt overlay In asds configured with V4L2_ASYNC_MATCH_OF, the v4l2 subdev can be part of a devicetree overlay, for example: &media_bridge { ... my_port: port@0 { #address-cells = <1>; #size-cells = <0>; reg = <0>; ep: endpoint@0 { remote-endpoint = <&camera0>; }; }; }; / { fragment@0 { target = <&i2c0>; __overlay__ { my_cam { compatible = "foo,bar"; port { camera0: endpoint { remote-endpoint = <&my_port>; ... }; }; }; }; }; }; Each time the overlay is applied, its of_node pointer will be different. We are not interested in matching the pointer, what we want to match is that the path is the one we are expecting. Change to use of_node_cmp() so that we continue matching after the overlay has been removed and reapplied. Cc: Mauro Carvalho Chehab Cc: Sakari Ailus Signed-off-by: Javi Merino Reviewed-by: Javier Martinez Canillas Reviewed-by: Sylwester Nawrocki Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-async.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/media/v4l2-core/v4l2-async.c') diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 277183f2d514..618135089548 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -42,7 +42,8 @@ static bool match_devname(struct v4l2_subdev *sd, static bool match_of(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) { - return sd->of_node == asd->match.of.node; + return !of_node_cmp(of_node_full_name(sd->of_node), + of_node_full_name(asd->match.of.node)); } static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd) -- cgit v1.2.3 From 47b037a0512d9f8675ec2693bed46c8ea6a884ab Mon Sep 17 00:00:00 2001 From: Tuukka Toivonen Date: Fri, 27 Jan 2017 08:32:56 -0200 Subject: [media] v4l2-async: failing functions shouldn't have side effects v4l2-async had several functions doing some operations and then not undoing the operations in a failure situation. For example, v4l2_async_test_notify() moved a subdev into notifier's done list even if registering the subdev (v4l2_device_register_subdev) failed. If the subdev was allocated and v4l2_async_register_subdev() called from the driver's probe() function, as usually, the probe() function freed the allocated subdev and returned a failure. Nevertheless, the subdev was still left into the notifier's done list, causing an access to already freed memory when the notifier was later unregistered. A hand-edited call trace leaving freed subdevs into the notifier: v4l2_async_register_notifier(notifier, asd) cameradrv_probe sd = devm_kzalloc() v4l2_async_register_subdev(sd) v4l2_async_test_notify(notifier, sd, asd) list_move(sd, ¬ifier->done) v4l2_device_register_subdev(notifier->v4l2_dev, sd) cameradrv_registered(sd) -> fails ->v4l2_async_register_subdev returns failure ->cameradrv_probe returns failure ->devres frees the allocated sd ->sd was freed but it still remains in the notifier's list. This patch fixes this and several other cases where a failing function could leave nodes into a linked list while the caller might free the node due to a failure. Signed-off-by: Tuukka Toivonen Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-async.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/media/v4l2-core/v4l2-async.c') diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 618135089548..96cc733f35ef 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -100,18 +100,11 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, { int ret; - /* Remove from the waiting list */ - list_del(&asd->list); - sd->asd = asd; - sd->notifier = notifier; - if (notifier->bound) { ret = notifier->bound(notifier, sd, asd); if (ret < 0) return ret; } - /* Move from the global subdevice list to notifier's done */ - list_move(&sd->async_list, ¬ifier->done); ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd); if (ret < 0) { @@ -120,6 +113,14 @@ static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier, return ret; } + /* Remove from the waiting list */ + list_del(&asd->list); + sd->asd = asd; + sd->notifier = notifier; + + /* Move from the global subdevice list to notifier's done */ + list_move(&sd->async_list, ¬ifier->done); + if (list_empty(¬ifier->waiting) && notifier->complete) return notifier->complete(notifier); @@ -169,9 +170,6 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, mutex_lock(&list_lock); - /* Keep also completed notifiers on the list */ - list_add(¬ifier->list, ¬ifier_list); - list_for_each_entry_safe(sd, tmp, &subdev_list, async_list) { int ret; @@ -186,6 +184,9 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev, } } + /* Keep also completed notifiers on the list */ + list_add(¬ifier->list, ¬ifier_list); + mutex_unlock(&list_lock); return 0; -- cgit v1.2.3