aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c182
-rw-r--r--drivers/media/video/em28xx/em28xx.h10
2 files changed, 102 insertions, 90 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 55bc8ea56094..dda4a76dcaba 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -833,34 +833,63 @@ static void video_mux(struct em28xx *dev, int index)
833} 833}
834 834
835/* Usage lock check functions */ 835/* Usage lock check functions */
836static int res_get(struct em28xx_fh *fh) 836static int res_get(struct em28xx_fh *fh, unsigned int bit)
837{ 837{
838 struct em28xx *dev = fh->dev; 838 struct em28xx *dev = fh->dev;
839 int rc = 0;
840 839
841 /* This instance already has stream_on */ 840 if (fh->resources & bit)
842 if (fh->stream_on) 841 /* have it already allocated */
843 return rc; 842 return 1;
844 843
845 if (dev->stream_on) 844 /* is it free? */
846 return -EBUSY; 845 mutex_lock(&dev->lock);
846 if (dev->resources & bit) {
847 /* no, someone else uses it */
848 mutex_unlock(&dev->lock);
849 return 0;
850 }
851 /* it's free, grab it */
852 fh->resources |= bit;
853 dev->resources |= bit;
854 em28xx_videodbg("res: get %d\n", bit);
855 mutex_unlock(&dev->lock);
856 return 1;
857}
847 858
848 dev->stream_on = 1; 859static int res_check(struct em28xx_fh *fh, unsigned int bit)
849 fh->stream_on = 1; 860{
850 return rc; 861 return (fh->resources & bit);
851} 862}
852 863
853static int res_check(struct em28xx_fh *fh) 864static int res_locked(struct em28xx *dev, unsigned int bit)
854{ 865{
855 return fh->stream_on; 866 return (dev->resources & bit);
856} 867}
857 868
858static void res_free(struct em28xx_fh *fh) 869static void res_free(struct em28xx_fh *fh, unsigned int bits)
859{ 870{
860 struct em28xx *dev = fh->dev; 871 struct em28xx *dev = fh->dev;
861 872
862 fh->stream_on = 0; 873 BUG_ON((fh->resources & bits) != bits);
863 dev->stream_on = 0; 874
875 mutex_lock(&dev->lock);
876 fh->resources &= ~bits;
877 dev->resources &= ~bits;
878 em28xx_videodbg("res: put %d\n", bits);
879 mutex_unlock(&dev->lock);
880}
881
882static int get_ressource(struct em28xx_fh *fh)
883{
884 switch (fh->type) {
885 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
886 return EM28XX_RESOURCE_VIDEO;
887 case V4L2_BUF_TYPE_VBI_CAPTURE:
888 return EM28XX_RESOURCE_VBI;
889 default:
890 BUG();
891 return 0;
892 }
864} 893}
865 894
866/* 895/*
@@ -1103,12 +1132,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
1103 goto out; 1132 goto out;
1104 } 1133 }
1105 1134
1106 if (dev->stream_on && !fh->stream_on) {
1107 em28xx_errdev("%s device in use by another fh\n", __func__);
1108 rc = -EBUSY;
1109 goto out;
1110 }
1111
1112 rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat, 1135 rc = em28xx_set_video_format(dev, f->fmt.pix.pixelformat,
1113 f->fmt.pix.width, f->fmt.pix.height); 1136 f->fmt.pix.width, f->fmt.pix.height);
1114 1137
@@ -1668,24 +1691,25 @@ static int vidioc_streamon(struct file *file, void *priv,
1668{ 1691{
1669 struct em28xx_fh *fh = priv; 1692 struct em28xx_fh *fh = priv;
1670 struct em28xx *dev = fh->dev; 1693 struct em28xx *dev = fh->dev;
1671 int rc; 1694 int rc = -EINVAL;
1672 1695
1673 rc = check_dev(dev); 1696 rc = check_dev(dev);
1674 if (rc < 0) 1697 if (rc < 0)
1675 return rc; 1698 return rc;
1676 1699
1700 if (unlikely(type != fh->type))
1701 return -EINVAL;
1677 1702
1678 mutex_lock(&dev->lock); 1703 em28xx_videodbg("vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
1679 rc = res_get(fh); 1704 fh, type, fh->resources, dev->resources);
1680 1705
1681 if (likely(rc >= 0)) { 1706 if (unlikely(!res_get(fh,get_ressource(fh))))
1682 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1707 return -EBUSY;
1683 rc = videobuf_streamon(&fh->vb_vidq);
1684 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1685 rc = videobuf_streamon(&fh->vb_vbiq);
1686 }
1687 1708
1688 mutex_unlock(&dev->lock); 1709 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1710 rc = videobuf_streamon(&fh->vb_vidq);
1711 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1712 rc = videobuf_streamon(&fh->vb_vbiq);
1689 1713
1690 return rc; 1714 return rc;
1691} 1715}
@@ -1707,16 +1731,16 @@ static int vidioc_streamoff(struct file *file, void *priv,
1707 if (type != fh->type) 1731 if (type != fh->type)
1708 return -EINVAL; 1732 return -EINVAL;
1709 1733
1710 mutex_lock(&dev->lock); 1734 em28xx_videodbg("vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
1735 fh, type, fh->resources, dev->resources);
1711 1736
1712 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 1737 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
1713 videobuf_streamoff(&fh->vb_vidq); 1738 videobuf_streamoff(&fh->vb_vidq);
1714 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) 1739 res_free(fh, EM28XX_RESOURCE_VIDEO);
1740 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
1715 videobuf_streamoff(&fh->vb_vbiq); 1741 videobuf_streamoff(&fh->vb_vbiq);
1716 1742 res_free(fh, EM28XX_RESOURCE_VBI);
1717 res_free(fh); 1743 }
1718
1719 mutex_unlock(&dev->lock);
1720 1744
1721 return 0; 1745 return 0;
1722} 1746}
@@ -2095,17 +2119,16 @@ static int em28xx_v4l2_open(struct file *filp)
2095 else 2119 else
2096 field = V4L2_FIELD_INTERLACED; 2120 field = V4L2_FIELD_INTERLACED;
2097 2121
2098 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 2122 videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops,
2099 videobuf_queue_vmalloc_init(&fh->vb_vidq, &em28xx_video_qops, 2123 NULL, &dev->slock,
2100 NULL, &dev->slock, fh->type, field, 2124 V4L2_BUF_TYPE_VIDEO_CAPTURE, field,
2101 sizeof(struct em28xx_buffer), fh); 2125 sizeof(struct em28xx_buffer), fh);
2102 2126
2103 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) 2127 videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops,
2104 videobuf_queue_vmalloc_init(&fh->vb_vbiq, &em28xx_vbi_qops, 2128 NULL, &dev->slock,
2105 NULL, &dev->slock, 2129 V4L2_BUF_TYPE_VBI_CAPTURE,
2106 V4L2_BUF_TYPE_VBI_CAPTURE, 2130 V4L2_FIELD_SEQ_TB,
2107 V4L2_FIELD_SEQ_TB, 2131 sizeof(struct em28xx_buffer), fh);
2108 sizeof(struct em28xx_buffer), fh);
2109 2132
2110 mutex_unlock(&dev->lock); 2133 mutex_unlock(&dev->lock);
2111 2134
@@ -2162,20 +2185,21 @@ static int em28xx_v4l2_close(struct file *filp)
2162 2185
2163 em28xx_videodbg("users=%d\n", dev->users); 2186 em28xx_videodbg("users=%d\n", dev->users);
2164 2187
2165 2188 if (res_check(fh, EM28XX_RESOURCE_VIDEO)) {
2166 mutex_lock(&dev->lock);
2167 if (res_check(fh))
2168 res_free(fh);
2169
2170 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && dev->users == 1) {
2171 videobuf_stop(&fh->vb_vidq); 2189 videobuf_stop(&fh->vb_vidq);
2172 videobuf_mmap_free(&fh->vb_vidq); 2190 res_free(fh, EM28XX_RESOURCE_VIDEO);
2191 }
2173 2192
2193 if (res_check(fh, EM28XX_RESOURCE_VBI)) {
2194 videobuf_stop(&fh->vb_vbiq);
2195 res_free(fh, EM28XX_RESOURCE_VBI);
2196 }
2197
2198 if(dev->users == 1) {
2174 /* the device is already disconnect, 2199 /* the device is already disconnect,
2175 free the remaining resources */ 2200 free the remaining resources */
2176 if (dev->state & DEV_DISCONNECTED) { 2201 if (dev->state & DEV_DISCONNECTED) {
2177 em28xx_release_resources(dev); 2202 em28xx_release_resources(dev);
2178 mutex_unlock(&dev->lock);
2179 kfree(dev); 2203 kfree(dev);
2180 return 0; 2204 return 0;
2181 } 2205 }
@@ -2197,15 +2221,11 @@ static int em28xx_v4l2_close(struct file *filp)
2197 } 2221 }
2198 } 2222 }
2199 2223
2200 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { 2224 videobuf_mmap_free(&fh->vb_vidq);
2201 videobuf_stop(&fh->vb_vbiq); 2225 videobuf_mmap_free(&fh->vb_vbiq);
2202 videobuf_mmap_free(&fh->vb_vbiq);
2203 }
2204
2205 kfree(fh); 2226 kfree(fh);
2206 dev->users--; 2227 dev->users--;
2207 wake_up_interruptible_nr(&dev->open, 1); 2228 wake_up_interruptible_nr(&dev->open, 1);
2208 mutex_unlock(&dev->lock);
2209 return 0; 2229 return 0;
2210} 2230}
2211 2231
@@ -2230,12 +2250,8 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
2230 */ 2250 */
2231 2251
2232 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { 2252 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2233 mutex_lock(&dev->lock); 2253 if (res_locked(dev, EM28XX_RESOURCE_VIDEO))
2234 rc = res_get(fh); 2254 return -EBUSY;
2235 mutex_unlock(&dev->lock);
2236
2237 if (unlikely(rc < 0))
2238 return rc;
2239 2255
2240 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0, 2256 return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
2241 filp->f_flags & O_NONBLOCK); 2257 filp->f_flags & O_NONBLOCK);
@@ -2243,9 +2259,8 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
2243 2259
2244 2260
2245 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { 2261 if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
2246 mutex_lock(&dev->lock); 2262 if (!res_get(fh, EM28XX_RESOURCE_VBI))
2247 rc = res_get(fh); 2263 return -EBUSY;
2248 mutex_unlock(&dev->lock);
2249 2264
2250 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0, 2265 return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
2251 filp->f_flags & O_NONBLOCK); 2266 filp->f_flags & O_NONBLOCK);
@@ -2268,19 +2283,17 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait)
2268 if (rc < 0) 2283 if (rc < 0)
2269 return rc; 2284 return rc;
2270 2285
2271 mutex_lock(&dev->lock); 2286 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
2272 rc = res_get(fh); 2287 if (!res_get(fh, EM28XX_RESOURCE_VIDEO))
2273 mutex_unlock(&dev->lock); 2288 return POLLERR;
2274
2275 if (unlikely(rc < 0))
2276 return POLLERR;
2277
2278 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
2279 return videobuf_poll_stream(filp, &fh->vb_vidq, wait); 2289 return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
2280 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) 2290 } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
2291 if (!res_get(fh, EM28XX_RESOURCE_VBI))
2292 return POLLERR;
2281 return videobuf_poll_stream(filp, &fh->vb_vbiq, wait); 2293 return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
2282 else 2294 } else {
2283 return POLLERR; 2295 return POLLERR;
2296 }
2284} 2297}
2285 2298
2286/* 2299/*
@@ -2296,13 +2309,6 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
2296 if (rc < 0) 2309 if (rc < 0)
2297 return rc; 2310 return rc;
2298 2311
2299 mutex_lock(&dev->lock);
2300 rc = res_get(fh);
2301 mutex_unlock(&dev->lock);
2302
2303 if (unlikely(rc < 0))
2304 return rc;
2305
2306 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) 2312 if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
2307 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma); 2313 rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
2308 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) 2314 else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 8dac50b9c00b..b4a6e07236d3 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -444,6 +444,10 @@ enum em28xx_dev_state {
444#define EM28XX_AUDIO 0x10 444#define EM28XX_AUDIO 0x10
445#define EM28XX_DVB 0x20 445#define EM28XX_DVB 0x20
446 446
447/* em28xx resource types (used for res_get/res_lock etc */
448#define EM28XX_RESOURCE_VIDEO 0x01
449#define EM28XX_RESOURCE_VBI 0x02
450
447struct em28xx_audio { 451struct em28xx_audio {
448 char name[50]; 452 char name[50];
449 char *transfer_buffer[EM28XX_AUDIO_BUFS]; 453 char *transfer_buffer[EM28XX_AUDIO_BUFS];
@@ -464,8 +468,8 @@ struct em28xx;
464 468
465struct em28xx_fh { 469struct em28xx_fh {
466 struct em28xx *dev; 470 struct em28xx *dev;
467 unsigned int stream_on:1; /* Locks streams */
468 int radio; 471 int radio;
472 unsigned int resources;
469 473
470 struct videobuf_queue vb_vidq; 474 struct videobuf_queue vb_vidq;
471 struct videobuf_queue vb_vbiq; 475 struct videobuf_queue vb_vbiq;
@@ -495,7 +499,6 @@ struct em28xx {
495 /* Vinmode/Vinctl used at the driver */ 499 /* Vinmode/Vinctl used at the driver */
496 int vinmode, vinctl; 500 int vinmode, vinctl;
497 501
498 unsigned int stream_on:1; /* Locks streams */
499 unsigned int has_audio_class:1; 502 unsigned int has_audio_class:1;
500 unsigned int has_alsa_audio:1; 503 unsigned int has_alsa_audio:1;
501 504
@@ -563,6 +566,9 @@ struct em28xx {
563 struct video_device *vbi_dev; 566 struct video_device *vbi_dev;
564 struct video_device *radio_dev; 567 struct video_device *radio_dev;
565 568
569 /* resources in use */
570 unsigned int resources;
571
566 unsigned char eedata[256]; 572 unsigned char eedata[256];
567 573
568 /* Isoc control struct */ 574 /* Isoc control struct */