diff --git a/drivers/media/platform/nxp/imx-mipi-csis.c b/drivers/media/platform/nxp/imx-mipi-csis.c index 905072871ed2..eb35657bb7a2 100644 --- a/drivers/media/platform/nxp/imx-mipi-csis.c +++ b/drivers/media/platform/nxp/imx-mipi-csis.c @@ -1275,6 +1275,8 @@ static int mipi_csis_notify_bound(struct v4l2_async_notifier *notifier, struct mipi_csis_device *csis = mipi_notifier_to_csis_state(notifier); struct media_pad *sink = &csis->sd.entity.pads[CSIS_PAD_SINK]; + printk("%s:%d\n", __func__, __LINE__); + return v4l2_create_fwnode_links_to_pad(sd, sink, 0); } diff --git a/drivers/media/platform/nxp/imx7-media-csi.c b/drivers/media/platform/nxp/imx7-media-csi.c index 886374d3a6ff..6fc7bafdd436 100644 --- a/drivers/media/platform/nxp/imx7-media-csi.c +++ b/drivers/media/platform/nxp/imx7-media-csi.c @@ -2165,6 +2165,8 @@ static int imx7_csi_notify_bound(struct v4l2_async_notifier *notifier, csi->src_sd = sd; + printk("%s:%d\n", __func__, __LINE__); + return v4l2_create_fwnode_links_to_pad(sd, sink, MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE); } @@ -2173,6 +2175,8 @@ static int imx7_csi_notify_complete(struct v4l2_async_notifier *notifier) { struct imx7_csi *csi = imx7_csi_notifier_to_dev(notifier); + printk("%s:%d\n", __func__, __LINE__); + return v4l2_device_register_subdev_nodes(&csi->v4l2_dev); } diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index 2f1b718a9189..820abb5ce77c 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -86,6 +86,8 @@ match_fwnode_one(struct v4l2_async_notifier *notifier, bool sd_fwnode_is_ep; struct device *dev; + printk("%s:%d\n", __func__, __LINE__); + /* * Both the subdev and the async subdev can provide either an endpoint * fwnode or a device fwnode. Start with the simple case of direct @@ -94,6 +96,8 @@ match_fwnode_one(struct v4l2_async_notifier *notifier, if (sd_fwnode == asd->match.fwnode) return true; + printk("%s:%d\n", __func__, __LINE__); + /* * Otherwise, check if the sd fwnode and the asd fwnode refer to an * endpoint or a device. If they're of the same type, there's no match. @@ -108,6 +112,8 @@ match_fwnode_one(struct v4l2_async_notifier *notifier, if (sd_fwnode_is_ep == asd_fwnode_is_ep) return false; + printk("%s:%d\n", __func__, __LINE__); + /* * The sd and asd fwnodes are of different types. Get the device fwnode * parent of the endpoint fwnode, and compare it with the other fwnode. @@ -125,6 +131,8 @@ match_fwnode_one(struct v4l2_async_notifier *notifier, if (dev_fwnode != other_fwnode) return false; + printk("%s:%d\n", __func__, __LINE__); + /* * We have a heterogeneous match. Retrieve the struct device of the side * that matched on a device fwnode to print its driver name. @@ -163,6 +171,55 @@ static LIST_HEAD(subdev_list); static LIST_HEAD(notifier_list); static DEFINE_MUTEX(list_lock); +static const char * +v4l2_async_nf_name(struct v4l2_async_notifier *notifier) +{ + if (notifier->v4l2_dev) + return notifier->v4l2_dev->name; + else if (notifier->sd) + return notifier->sd->name; + else + return "nil"; +} + +static void print_subdev(struct v4l2_async_subdev *asd) +{ + switch (asd->match_type) { + case V4L2_ASYNC_MATCH_I2C: + printk(" [i2c] dev=%d-%04x\n", asd->match.i2c.adapter_id, + asd->match.i2c.address); + break; + case V4L2_ASYNC_MATCH_FWNODE: { + struct fwnode_handle *devnode, *fwnode = asd->match.fwnode; + + devnode = fwnode_graph_is_endpoint(fwnode) ? + fwnode_graph_get_port_parent(fwnode) : + fwnode_handle_get(fwnode); + + printk(" [fwnode] dev=%s, node=%pfw\n", + devnode->dev ? dev_name(devnode->dev) : "nil", + fwnode); + + fwnode_handle_put(devnode); + break; + } + } +} + +static int print_notifiers_subdevs(void) +{ + struct v4l2_async_notifier *notif; + struct v4l2_async_subdev *asd; + + list_for_each_entry(notif, ¬ifier_list, list) { + printk(" %s:\n", v4l2_async_nf_name(notif)); + list_for_each_entry(asd, ¬if->waiting, list) + print_subdev(asd); + } + + return 0; +} + static struct v4l2_async_subdev * v4l2_async_find_match(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd) @@ -171,7 +228,11 @@ v4l2_async_find_match(struct v4l2_async_notifier *notifier, struct v4l2_subdev *sd, struct v4l2_async_subdev *asd); struct v4l2_async_subdev *asd; + printk("%s:%d\n", __func__, __LINE__); + list_for_each_entry(asd, ¬ifier->waiting, list) { + printk("%s:%d\n", __func__, __LINE__); + print_subdev(asd); /* bus_type has been verified valid before */ switch (asd->match_type) { case V4L2_ASYNC_MATCH_I2C: @@ -317,16 +378,22 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, struct v4l2_async_notifier *subdev_notifier; int ret; + printk("%s:%d\n", __func__, __LINE__); + ret = v4l2_device_register_subdev(v4l2_dev, sd); if (ret < 0) return ret; + printk("%s:%d\n", __func__, __LINE__); + ret = v4l2_async_nf_call_bound(notifier, sd, asd); if (ret < 0) { v4l2_device_unregister_subdev(sd); return ret; } + printk("%s:%d\n", __func__, __LINE__); + /* * Depending of the function of the entities involved, we may want to * create links between them (for example between a sensor and its lens @@ -340,6 +407,8 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, return ret; } + printk("%s:%d\n", __func__, __LINE__); + /* Remove from the waiting list */ list_del(&asd->list); sd->asd = asd; @@ -355,6 +424,8 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier, if (!subdev_notifier || subdev_notifier->parent) return 0; + printk("%s:%d\n", __func__, __LINE__); + /* * Proceed with checking for the sub-device notifier's async * sub-devices, and return the result. The error will be handled by the @@ -373,18 +444,29 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier) v4l2_async_nf_find_v4l2_dev(notifier); struct v4l2_subdev *sd; + printk("%s:%d\n", __func__, __LINE__); + printk(" %s:\n", v4l2_async_nf_name(notifier)); + print_notifiers_subdevs(); + if (!v4l2_dev) return 0; + printk("%s:%d\n", __func__, __LINE__); + again: list_for_each_entry(sd, &subdev_list, async_list) { struct v4l2_async_subdev *asd; int ret; + printk("%s:%d\n", __func__, __LINE__); + asd = v4l2_async_find_match(notifier, sd); if (!asd) continue; + printk("%s:%d\n", __func__, __LINE__); + print_subdev(asd); + ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd); if (ret < 0) return ret; @@ -525,16 +607,22 @@ static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier) struct v4l2_async_subdev *asd; int ret, i = 0; + printk("%s:%d\n", __func__, __LINE__); + printk(" %s:\n", v4l2_async_nf_name(notifier)); + INIT_LIST_HEAD(¬ifier->waiting); INIT_LIST_HEAD(¬ifier->done); mutex_lock(&list_lock); list_for_each_entry(asd, ¬ifier->asd_list, asd_list) { + printk("%s:%d\n", __func__, __LINE__); + print_subdev(asd); ret = v4l2_async_nf_asd_valid(notifier, asd, i++); if (ret) goto err_unlock; + printk("%s:%d\n", __func__, __LINE__); list_add_tail(&asd->list, ¬ifier->waiting); } @@ -767,18 +855,29 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd) INIT_LIST_HEAD(&sd->async_list); + printk("%s:%d\n", __func__, __LINE__); + print_notifiers_subdevs(); + list_for_each_entry(notifier, ¬ifier_list, list) { struct v4l2_device *v4l2_dev = v4l2_async_nf_find_v4l2_dev(notifier); struct v4l2_async_subdev *asd; + printk("%s:%d\n", __func__, __LINE__); + printk(" %s:\n", v4l2_async_nf_name(notifier)); + if (!v4l2_dev) continue; + printk("%s:%d\n", __func__, __LINE__); + asd = v4l2_async_find_match(notifier, sd); if (!asd) continue; + printk("%s:%d\n", __func__, __LINE__); + print_subdev(asd); + ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd); if (ret) goto err_unbind; @@ -868,17 +967,6 @@ static void print_waiting_subdev(struct seq_file *s, } } -static const char * -v4l2_async_nf_name(struct v4l2_async_notifier *notifier) -{ - if (notifier->v4l2_dev) - return notifier->v4l2_dev->name; - else if (notifier->sd) - return notifier->sd->name; - else - return "nil"; -} - static int pending_subdevs_show(struct seq_file *s, void *data) { struct v4l2_async_notifier *notif; diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 3d9533c1b202..45ed62b16327 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -1293,6 +1293,8 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd) struct v4l2_async_notifier *notifier; int ret; + printk("%s:%d\n", __func__, __LINE__); + if (WARN_ON(!sd->dev)) return -ENODEV; @@ -1306,14 +1308,20 @@ int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd) if (ret < 0) goto out_cleanup; + printk("%s:%d\n", __func__, __LINE__); + ret = v4l2_async_subdev_nf_register(sd, notifier); if (ret < 0) goto out_cleanup; + printk("%s:%d\n", __func__, __LINE__); + ret = v4l2_async_register_subdev(sd); if (ret < 0) goto out_unregister; + printk("%s:%d\n", __func__, __LINE__); + sd->subdev_notifier = notifier; return 0;