diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-16 20:04:56 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-12-30 06:39:14 -0500 |
commit | efc52a94840198eb5ba68107812b879d34959dbb (patch) | |
tree | 24cfe20c1c2558e1c572a91718596f994a75b933 /drivers/media/video/em28xx | |
parent | cf8c91c3e77cc26c43cfe6fc47e649b685736259 (diff) |
V4L/DVB (9912): em28xx: fix/improve em28xx locking schema
Changes/fixes on em28xx dev->lock:
- em28xx_init_dev() were unlocking without a previous lock;
- some read ioctls need to lock after the removal of KBL, since a write
may be happening at the same time an ioctl is reading;
- keep the device locked during all device initialization;
- lock/unlock while reading/writing registers.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r-- | drivers/media/video/em28xx/em28xx-video.c | 55 |
1 files changed, 43 insertions, 12 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 1681af192b02..de2d2fdbe6a4 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -784,10 +784,10 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | |||
784 | if (rc < 0) | 784 | if (rc < 0) |
785 | return rc; | 785 | return rc; |
786 | 786 | ||
787 | vidioc_try_fmt_vid_cap(file, priv, f); | ||
788 | |||
789 | mutex_lock(&dev->lock); | 787 | mutex_lock(&dev->lock); |
790 | 788 | ||
789 | vidioc_try_fmt_vid_cap(file, priv, f); | ||
790 | |||
791 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { | 791 | if (videobuf_queue_is_busy(&fh->vb_vidq)) { |
792 | em28xx_errdev("%s queue busy\n", __func__); | 792 | em28xx_errdev("%s queue busy\n", __func__); |
793 | rc = -EBUSY; | 793 | rc = -EBUSY; |
@@ -828,15 +828,12 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm) | |||
828 | 828 | ||
829 | mutex_lock(&dev->lock); | 829 | mutex_lock(&dev->lock); |
830 | dev->norm = *norm; | 830 | dev->norm = *norm; |
831 | mutex_unlock(&dev->lock); | ||
832 | 831 | ||
833 | /* Adjusts width/height, if needed */ | 832 | /* Adjusts width/height, if needed */ |
834 | f.fmt.pix.width = dev->width; | 833 | f.fmt.pix.width = dev->width; |
835 | f.fmt.pix.height = dev->height; | 834 | f.fmt.pix.height = dev->height; |
836 | vidioc_try_fmt_vid_cap(file, priv, &f); | 835 | vidioc_try_fmt_vid_cap(file, priv, &f); |
837 | 836 | ||
838 | mutex_lock(&dev->lock); | ||
839 | |||
840 | /* set new image size */ | 837 | /* set new image size */ |
841 | dev->width = f.fmt.pix.width; | 838 | dev->width = f.fmt.pix.width; |
842 | dev->height = f.fmt.pix.height; | 839 | dev->height = f.fmt.pix.height; |
@@ -966,11 +963,15 @@ static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a) | |||
966 | struct em28xx_fh *fh = priv; | 963 | struct em28xx_fh *fh = priv; |
967 | struct em28xx *dev = fh->dev; | 964 | struct em28xx *dev = fh->dev; |
968 | 965 | ||
966 | mutex_lock(&dev->lock); | ||
967 | |||
969 | dev->ctl_ainput = INPUT(a->index)->amux; | 968 | dev->ctl_ainput = INPUT(a->index)->amux; |
970 | dev->ctl_aoutput = INPUT(a->index)->aout; | 969 | dev->ctl_aoutput = INPUT(a->index)->aout; |
971 | 970 | ||
972 | if (!dev->ctl_aoutput) | 971 | if (!dev->ctl_aoutput) |
973 | dev->ctl_aoutput = EM28XX_AOUT_MASTER; | 972 | dev->ctl_aoutput = EM28XX_AOUT_MASTER; |
973 | |||
974 | mutex_unlock(&dev->lock); | ||
974 | return 0; | 975 | return 0; |
975 | } | 976 | } |
976 | 977 | ||
@@ -1019,6 +1020,7 @@ static int vidioc_g_ctrl(struct file *file, void *priv, | |||
1019 | rc = check_dev(dev); | 1020 | rc = check_dev(dev); |
1020 | if (rc < 0) | 1021 | if (rc < 0) |
1021 | return rc; | 1022 | return rc; |
1023 | |||
1022 | mutex_lock(&dev->lock); | 1024 | mutex_lock(&dev->lock); |
1023 | 1025 | ||
1024 | if (!dev->board.has_msp34xx) | 1026 | if (!dev->board.has_msp34xx) |
@@ -1129,8 +1131,10 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
1129 | struct em28xx_fh *fh = priv; | 1131 | struct em28xx_fh *fh = priv; |
1130 | struct em28xx *dev = fh->dev; | 1132 | struct em28xx *dev = fh->dev; |
1131 | 1133 | ||
1134 | mutex_lock(&dev->lock); | ||
1132 | f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; | 1135 | f->type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; |
1133 | f->frequency = dev->ctl_freq; | 1136 | f->frequency = dev->ctl_freq; |
1137 | mutex_unlock(&dev->lock); | ||
1134 | 1138 | ||
1135 | return 0; | 1139 | return 0; |
1136 | } | 1140 | } |
@@ -1160,6 +1164,7 @@ static int vidioc_s_frequency(struct file *file, void *priv, | |||
1160 | em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); | 1164 | em28xx_i2c_call_clients(dev, VIDIOC_S_FREQUENCY, f); |
1161 | 1165 | ||
1162 | mutex_unlock(&dev->lock); | 1166 | mutex_unlock(&dev->lock); |
1167 | |||
1163 | return 0; | 1168 | return 0; |
1164 | } | 1169 | } |
1165 | 1170 | ||
@@ -1187,15 +1192,20 @@ static int vidioc_g_register(struct file *file, void *priv, | |||
1187 | return -EINVAL; | 1192 | return -EINVAL; |
1188 | 1193 | ||
1189 | if (em28xx_reg_len(reg->reg) == 1) { | 1194 | if (em28xx_reg_len(reg->reg) == 1) { |
1195 | mutex_lock(&dev->lock); | ||
1190 | ret = em28xx_read_reg(dev, reg->reg); | 1196 | ret = em28xx_read_reg(dev, reg->reg); |
1197 | mutex_unlock(&dev->lock); | ||
1198 | |||
1191 | if (ret < 0) | 1199 | if (ret < 0) |
1192 | return ret; | 1200 | return ret; |
1193 | 1201 | ||
1194 | reg->val = ret; | 1202 | reg->val = ret; |
1195 | } else { | 1203 | } else { |
1196 | __le64 val = 0; | 1204 | __le64 val = 0; |
1205 | mutex_lock(&dev->lock); | ||
1197 | ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, | 1206 | ret = em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS, |
1198 | reg->reg, (char *)&val, 2); | 1207 | reg->reg, (char *)&val, 2); |
1208 | mutex_unlock(&dev->lock); | ||
1199 | if (ret < 0) | 1209 | if (ret < 0) |
1200 | return ret; | 1210 | return ret; |
1201 | 1211 | ||
@@ -1211,11 +1221,16 @@ static int vidioc_s_register(struct file *file, void *priv, | |||
1211 | struct em28xx_fh *fh = priv; | 1221 | struct em28xx_fh *fh = priv; |
1212 | struct em28xx *dev = fh->dev; | 1222 | struct em28xx *dev = fh->dev; |
1213 | __le64 buf; | 1223 | __le64 buf; |
1224 | int rc; | ||
1214 | 1225 | ||
1215 | buf = cpu_to_le64(reg->val); | 1226 | buf = cpu_to_le64(reg->val); |
1216 | 1227 | ||
1217 | return em28xx_write_regs(dev, reg->reg, (char *)&buf, | 1228 | mutex_lock(&dev->lock); |
1218 | em28xx_reg_len(reg->reg)); | 1229 | rc = em28xx_write_regs(dev, reg->reg, (char *)&buf, |
1230 | em28xx_reg_len(reg->reg)); | ||
1231 | mutex_unlock(&dev->lock); | ||
1232 | |||
1233 | return rc; | ||
1219 | } | 1234 | } |
1220 | #endif | 1235 | #endif |
1221 | 1236 | ||
@@ -1254,12 +1269,15 @@ static int vidioc_streamon(struct file *file, void *priv, | |||
1254 | 1269 | ||
1255 | mutex_lock(&dev->lock); | 1270 | mutex_lock(&dev->lock); |
1256 | rc = res_get(fh); | 1271 | rc = res_get(fh); |
1257 | mutex_unlock(&dev->lock); | ||
1258 | 1272 | ||
1259 | if (unlikely(rc < 0)) | 1273 | if (unlikely(rc < 0)) |
1260 | return rc; | 1274 | return rc; |
1261 | 1275 | ||
1262 | return (videobuf_streamon(&fh->vb_vidq)); | 1276 | rc = videobuf_streamon(&fh->vb_vidq); |
1277 | |||
1278 | mutex_unlock(&dev->lock); | ||
1279 | |||
1280 | return rc; | ||
1263 | } | 1281 | } |
1264 | 1282 | ||
1265 | static int vidioc_streamoff(struct file *file, void *priv, | 1283 | static int vidioc_streamoff(struct file *file, void *priv, |
@@ -1278,9 +1296,11 @@ static int vidioc_streamoff(struct file *file, void *priv, | |||
1278 | if (type != fh->type) | 1296 | if (type != fh->type) |
1279 | return -EINVAL; | 1297 | return -EINVAL; |
1280 | 1298 | ||
1281 | videobuf_streamoff(&fh->vb_vidq); | ||
1282 | mutex_lock(&dev->lock); | 1299 | mutex_lock(&dev->lock); |
1300 | |||
1301 | videobuf_streamoff(&fh->vb_vidq); | ||
1283 | res_free(fh); | 1302 | res_free(fh); |
1303 | |||
1284 | mutex_unlock(&dev->lock); | 1304 | mutex_unlock(&dev->lock); |
1285 | 1305 | ||
1286 | return 0; | 1306 | return 0; |
@@ -1465,7 +1485,10 @@ static int radio_g_tuner(struct file *file, void *priv, | |||
1465 | strcpy(t->name, "Radio"); | 1485 | strcpy(t->name, "Radio"); |
1466 | t->type = V4L2_TUNER_RADIO; | 1486 | t->type = V4L2_TUNER_RADIO; |
1467 | 1487 | ||
1488 | mutex_lock(&dev->lock); | ||
1468 | em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t); | 1489 | em28xx_i2c_call_clients(dev, VIDIOC_G_TUNER, t); |
1490 | mutex_unlock(&dev->lock); | ||
1491 | |||
1469 | return 0; | 1492 | return 0; |
1470 | } | 1493 | } |
1471 | 1494 | ||
@@ -1497,7 +1520,9 @@ static int radio_s_tuner(struct file *file, void *priv, | |||
1497 | if (0 != t->index) | 1520 | if (0 != t->index) |
1498 | return -EINVAL; | 1521 | return -EINVAL; |
1499 | 1522 | ||
1523 | mutex_lock(&dev->lock); | ||
1500 | em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t); | 1524 | em28xx_i2c_call_clients(dev, VIDIOC_S_TUNER, t); |
1525 | mutex_unlock(&dev->lock); | ||
1501 | 1526 | ||
1502 | return 0; | 1527 | return 0; |
1503 | } | 1528 | } |
@@ -1561,6 +1586,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) | |||
1561 | } | 1586 | } |
1562 | } | 1587 | } |
1563 | mutex_unlock(&em28xx_devlist_mutex); | 1588 | mutex_unlock(&em28xx_devlist_mutex); |
1589 | |||
1564 | if (NULL == dev) | 1590 | if (NULL == dev) |
1565 | return -ENODEV; | 1591 | return -ENODEV; |
1566 | 1592 | ||
@@ -2036,7 +2062,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2036 | unsigned int maxh, maxw; | 2062 | unsigned int maxh, maxw; |
2037 | 2063 | ||
2038 | dev->udev = udev; | 2064 | dev->udev = udev; |
2039 | mutex_init(&dev->lock); | ||
2040 | mutex_init(&dev->ctrl_urb_lock); | 2065 | mutex_init(&dev->ctrl_urb_lock); |
2041 | spin_lock_init(&dev->slock); | 2066 | spin_lock_init(&dev->slock); |
2042 | init_waitqueue_head(&dev->open); | 2067 | init_waitqueue_head(&dev->open); |
@@ -2151,7 +2176,6 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2151 | return 0; | 2176 | return 0; |
2152 | 2177 | ||
2153 | fail_reg_devices: | 2178 | fail_reg_devices: |
2154 | mutex_unlock(&dev->lock); | ||
2155 | return retval; | 2179 | return retval; |
2156 | } | 2180 | } |
2157 | 2181 | ||
@@ -2343,6 +2367,8 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2343 | dev->model = card[nr]; | 2367 | dev->model = card[nr]; |
2344 | 2368 | ||
2345 | /* allocate device struct */ | 2369 | /* allocate device struct */ |
2370 | mutex_init(&dev->lock); | ||
2371 | mutex_lock(&dev->lock); | ||
2346 | retval = em28xx_init_dev(&dev, udev, nr); | 2372 | retval = em28xx_init_dev(&dev, udev, nr); |
2347 | if (retval) { | 2373 | if (retval) { |
2348 | em28xx_devused &= ~(1<<dev->devno); | 2374 | em28xx_devused &= ~(1<<dev->devno); |
@@ -2356,6 +2382,11 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
2356 | 2382 | ||
2357 | request_modules(dev); | 2383 | request_modules(dev); |
2358 | 2384 | ||
2385 | /* Should be the last thing to do, to avoid newer udev's to | ||
2386 | open the device before fully initializing it | ||
2387 | */ | ||
2388 | mutex_unlock(&dev->lock); | ||
2389 | |||
2359 | return 0; | 2390 | return 0; |
2360 | } | 2391 | } |
2361 | 2392 | ||