Commit 2f9a0c88 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Mauro Carvalho Chehab

[media] V4L: soc-camera: protect hosts during probing from overzealous user-space

If multiple clients are registered on a single camera host interface,
the user-space hot-plug software can try to access the one, that probed
first, before probing of the second one has completed. This can be
handled by individual host drivers, but it is even better to hold back
the user-space until all the probing on this host has completed. This
fixes a race on ecovec with two clients registered on the CEU1 host, which
otherwise triggers a BUG() in sh_mobile_ceu_remove_device().
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent e631f578
...@@ -530,7 +530,10 @@ static int soc_camera_open(struct file *file) ...@@ -530,7 +530,10 @@ static int soc_camera_open(struct file *file)
if (icl->reset) if (icl->reset)
icl->reset(icd->pdev); icl->reset(icd->pdev);
/* Don't mess with the host during probe */
mutex_lock(&ici->host_lock);
ret = ici->ops->add(icd); ret = ici->ops->add(icd);
mutex_unlock(&ici->host_lock);
if (ret < 0) { if (ret < 0) {
dev_err(icd->pdev, "Couldn't activate the camera: %d\n", ret); dev_err(icd->pdev, "Couldn't activate the camera: %d\n", ret);
goto eiciadd; goto eiciadd;
...@@ -956,7 +959,7 @@ static void scan_add_host(struct soc_camera_host *ici) ...@@ -956,7 +959,7 @@ static void scan_add_host(struct soc_camera_host *ici)
{ {
struct soc_camera_device *icd; struct soc_camera_device *icd;
mutex_lock(&list_lock); mutex_lock(&ici->host_lock);
list_for_each_entry(icd, &devices, list) { list_for_each_entry(icd, &devices, list) {
if (icd->iface == ici->nr) { if (icd->iface == ici->nr) {
...@@ -967,7 +970,7 @@ static void scan_add_host(struct soc_camera_host *ici) ...@@ -967,7 +970,7 @@ static void scan_add_host(struct soc_camera_host *ici)
} }
} }
mutex_unlock(&list_lock); mutex_unlock(&ici->host_lock);
} }
#ifdef CONFIG_I2C_BOARDINFO #ifdef CONFIG_I2C_BOARDINFO
...@@ -1313,6 +1316,7 @@ int soc_camera_host_register(struct soc_camera_host *ici) ...@@ -1313,6 +1316,7 @@ int soc_camera_host_register(struct soc_camera_host *ici)
list_add_tail(&ici->list, &hosts); list_add_tail(&ici->list, &hosts);
mutex_unlock(&list_lock); mutex_unlock(&list_lock);
mutex_init(&ici->host_lock);
scan_add_host(ici); scan_add_host(ici);
return 0; return 0;
......
...@@ -59,6 +59,7 @@ struct soc_camera_device { ...@@ -59,6 +59,7 @@ struct soc_camera_device {
struct soc_camera_host { struct soc_camera_host {
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
struct list_head list; struct list_head list;
struct mutex host_lock; /* Protect during probing */
unsigned char nr; /* Host number */ unsigned char nr; /* Host number */
void *priv; void *priv;
const char *drv_name; const char *drv_name;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment