diff options
-rw-r--r-- | drivers/media/platform/soc_camera/soc_camera.c | 22 | ||||
-rw-r--r-- | include/media/soc_camera.h | 2 |
2 files changed, 20 insertions, 4 deletions
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c index a8ca956e7a40..1070a0c496d8 100644 --- a/drivers/media/platform/soc_camera/soc_camera.c +++ b/drivers/media/platform/soc_camera/soc_camera.c | |||
@@ -517,7 +517,14 @@ static int soc_camera_open(struct file *file) | |||
517 | /* No device driver attached */ | 517 | /* No device driver attached */ |
518 | return -ENODEV; | 518 | return -ENODEV; |
519 | 519 | ||
520 | /* | ||
521 | * Don't mess with the host during probe: wait until the loop in | ||
522 | * scan_add_host() completes | ||
523 | */ | ||
524 | if (mutex_lock_interruptible(&list_lock)) | ||
525 | return -ERESTARTSYS; | ||
520 | ici = to_soc_camera_host(icd->parent); | 526 | ici = to_soc_camera_host(icd->parent); |
527 | mutex_unlock(&list_lock); | ||
521 | 528 | ||
522 | if (mutex_lock_interruptible(&icd->video_lock)) | 529 | if (mutex_lock_interruptible(&icd->video_lock)) |
523 | return -ERESTARTSYS; | 530 | return -ERESTARTSYS; |
@@ -548,7 +555,6 @@ static int soc_camera_open(struct file *file) | |||
548 | if (icl->reset) | 555 | if (icl->reset) |
549 | icl->reset(icd->pdev); | 556 | icl->reset(icd->pdev); |
550 | 557 | ||
551 | /* Don't mess with the host during probe */ | ||
552 | mutex_lock(&ici->host_lock); | 558 | mutex_lock(&ici->host_lock); |
553 | ret = ici->ops->add(icd); | 559 | ret = ici->ops->add(icd); |
554 | mutex_unlock(&ici->host_lock); | 560 | mutex_unlock(&ici->host_lock); |
@@ -602,7 +608,9 @@ esfmt: | |||
602 | eresume: | 608 | eresume: |
603 | __soc_camera_power_off(icd); | 609 | __soc_camera_power_off(icd); |
604 | epower: | 610 | epower: |
611 | mutex_lock(&ici->host_lock); | ||
605 | ici->ops->remove(icd); | 612 | ici->ops->remove(icd); |
613 | mutex_unlock(&ici->host_lock); | ||
606 | eiciadd: | 614 | eiciadd: |
607 | icd->use_count--; | 615 | icd->use_count--; |
608 | module_put(ici->ops->owner); | 616 | module_put(ici->ops->owner); |
@@ -625,7 +633,9 @@ static int soc_camera_close(struct file *file) | |||
625 | 633 | ||
626 | if (ici->ops->init_videobuf2) | 634 | if (ici->ops->init_videobuf2) |
627 | vb2_queue_release(&icd->vb2_vidq); | 635 | vb2_queue_release(&icd->vb2_vidq); |
636 | mutex_lock(&ici->host_lock); | ||
628 | ici->ops->remove(icd); | 637 | ici->ops->remove(icd); |
638 | mutex_unlock(&ici->host_lock); | ||
629 | 639 | ||
630 | __soc_camera_power_off(icd); | 640 | __soc_camera_power_off(icd); |
631 | } | 641 | } |
@@ -1052,7 +1062,7 @@ static void scan_add_host(struct soc_camera_host *ici) | |||
1052 | { | 1062 | { |
1053 | struct soc_camera_device *icd; | 1063 | struct soc_camera_device *icd; |
1054 | 1064 | ||
1055 | mutex_lock(&ici->host_lock); | 1065 | mutex_lock(&list_lock); |
1056 | 1066 | ||
1057 | list_for_each_entry(icd, &devices, list) { | 1067 | list_for_each_entry(icd, &devices, list) { |
1058 | if (icd->iface == ici->nr) { | 1068 | if (icd->iface == ici->nr) { |
@@ -1061,7 +1071,7 @@ static void scan_add_host(struct soc_camera_host *ici) | |||
1061 | } | 1071 | } |
1062 | } | 1072 | } |
1063 | 1073 | ||
1064 | mutex_unlock(&ici->host_lock); | 1074 | mutex_unlock(&list_lock); |
1065 | } | 1075 | } |
1066 | 1076 | ||
1067 | #ifdef CONFIG_I2C_BOARDINFO | 1077 | #ifdef CONFIG_I2C_BOARDINFO |
@@ -1148,7 +1158,9 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1148 | if (icl->reset) | 1158 | if (icl->reset) |
1149 | icl->reset(icd->pdev); | 1159 | icl->reset(icd->pdev); |
1150 | 1160 | ||
1161 | mutex_lock(&ici->host_lock); | ||
1151 | ret = ici->ops->add(icd); | 1162 | ret = ici->ops->add(icd); |
1163 | mutex_unlock(&ici->host_lock); | ||
1152 | if (ret < 0) | 1164 | if (ret < 0) |
1153 | goto eadd; | 1165 | goto eadd; |
1154 | 1166 | ||
@@ -1220,7 +1232,9 @@ static int soc_camera_probe(struct soc_camera_device *icd) | |||
1220 | icd->field = mf.field; | 1232 | icd->field = mf.field; |
1221 | } | 1233 | } |
1222 | 1234 | ||
1235 | mutex_lock(&ici->host_lock); | ||
1223 | ici->ops->remove(icd); | 1236 | ici->ops->remove(icd); |
1237 | mutex_unlock(&ici->host_lock); | ||
1224 | 1238 | ||
1225 | mutex_unlock(&icd->video_lock); | 1239 | mutex_unlock(&icd->video_lock); |
1226 | 1240 | ||
@@ -1242,7 +1256,9 @@ eadddev: | |||
1242 | video_device_release(icd->vdev); | 1256 | video_device_release(icd->vdev); |
1243 | icd->vdev = NULL; | 1257 | icd->vdev = NULL; |
1244 | evdc: | 1258 | evdc: |
1259 | mutex_lock(&ici->host_lock); | ||
1245 | ici->ops->remove(icd); | 1260 | ici->ops->remove(icd); |
1261 | mutex_unlock(&ici->host_lock); | ||
1246 | eadd: | 1262 | eadd: |
1247 | ereg: | 1263 | ereg: |
1248 | v4l2_ctrl_handler_free(&icd->ctrl_handler); | 1264 | v4l2_ctrl_handler_free(&icd->ctrl_handler); |
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 6442edc2a151..0370a9517282 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h | |||
@@ -62,7 +62,7 @@ struct soc_camera_device { | |||
62 | struct soc_camera_host { | 62 | struct soc_camera_host { |
63 | struct v4l2_device v4l2_dev; | 63 | struct v4l2_device v4l2_dev; |
64 | struct list_head list; | 64 | struct list_head list; |
65 | struct mutex host_lock; /* Protect during probing */ | 65 | struct mutex host_lock; /* Protect pipeline modifications */ |
66 | unsigned char nr; /* Host number */ | 66 | unsigned char nr; /* Host number */ |
67 | u32 capabilities; | 67 | u32 capabilities; |
68 | void *priv; | 68 | void *priv; |