aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2008-11-19 04:17:44 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-11-20 14:20:14 -0500
commitf2a2e4910502e866833732f31ee697d15b3e56fd (patch)
tree0679969d675d9e785c6c92a3625ce8df759e0cc3
parentc4a98793a63c423c9e1af51822325969e23c16d4 (diff)
V4L/DVB (9647): em28xx: void having two concurrent control URB's
Now that we have a polling task for IR, there's a race condition, since IR can be polling while other operations are being doing. Also, we are now sharing the same urb_buf for both read and write control urb operations. So, we need a mutex. Thanks to Davin Heitmueller <devin.heitmueller@gmail.com> for warning me. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/em28xx/em28xx-core.c12
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c1
-rw-r--r--drivers/media/video/em28xx/em28xx.h1
3 files changed, 12 insertions, 2 deletions
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c
index 9551b8ab8c44..15e2b525310d 100644
--- a/drivers/media/video/em28xx/em28xx-core.c
+++ b/drivers/media/video/em28xx/em28xx-core.c
@@ -76,18 +76,22 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
76 76
77 em28xx_regdbg("req=%02x, reg=%02x ", req, reg); 77 em28xx_regdbg("req=%02x, reg=%02x ", req, reg);
78 78
79 mutex_lock(&dev->ctrl_urb_lock);
79 ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, 80 ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
80 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 81 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
81 0x0000, reg, dev->urb_buf, len, HZ); 82 0x0000, reg, dev->urb_buf, len, HZ);
82 if (ret < 0) { 83 if (ret < 0) {
83 if (reg_debug) 84 if (reg_debug)
84 printk(" failed!\n"); 85 printk(" failed!\n");
86 mutex_unlock(&dev->ctrl_urb_lock);
85 return ret; 87 return ret;
86 } 88 }
87 89
88 if (len) 90 if (len)
89 memcpy(buf, dev->urb_buf, len); 91 memcpy(buf, dev->urb_buf, len);
90 92
93 mutex_unlock(&dev->ctrl_urb_lock);
94
91 if (reg_debug) { 95 if (reg_debug) {
92 printk("%02x values: ", ret); 96 printk("%02x values: ", ret);
93 for (byte = 0; byte < len; byte++) 97 for (byte = 0; byte < len; byte++)
@@ -112,16 +116,18 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
112 116
113 em28xx_regdbg("req=%02x, reg=%02x:", req, reg); 117 em28xx_regdbg("req=%02x, reg=%02x:", req, reg);
114 118
119 mutex_lock(&dev->ctrl_urb_lock);
115 ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, 120 ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
116 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 121 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
117 0x0000, reg, dev->urb_buf, 1, HZ); 122 0x0000, reg, dev->urb_buf, 1, HZ);
123 val = dev->urb_buf[0];
124 mutex_unlock(&dev->ctrl_urb_lock);
125
118 if (ret < 0) { 126 if (ret < 0) {
119 printk(" failed!\n"); 127 printk(" failed!\n");
120 return ret; 128 return ret;
121 } 129 }
122 130
123 val = dev->urb_buf[0];
124
125 if (reg_debug) 131 if (reg_debug)
126 printk("%02x\n", (unsigned char) val); 132 printk("%02x\n", (unsigned char) val);
127 133
@@ -156,10 +162,12 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
156 printk("\n"); 162 printk("\n");
157 } 163 }
158 164
165 mutex_lock(&dev->ctrl_urb_lock);
159 memcpy(dev->urb_buf, buf, len); 166 memcpy(dev->urb_buf, buf, len);
160 ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, 167 ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
161 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 168 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
162 0x0000, reg, dev->urb_buf, len, HZ); 169 0x0000, reg, dev->urb_buf, len, HZ);
170 mutex_unlock(&dev->ctrl_urb_lock);
163 171
164 if (dev->wait_after_write) 172 if (dev->wait_after_write)
165 msleep(dev->wait_after_write); 173 msleep(dev->wait_after_write);
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index bca5955339b8..c32fc7d24a42 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1936,6 +1936,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
1936 1936
1937 dev->udev = udev; 1937 dev->udev = udev;
1938 mutex_init(&dev->lock); 1938 mutex_init(&dev->lock);
1939 mutex_init(&dev->ctrl_urb_lock);
1939 spin_lock_init(&dev->slock); 1940 spin_lock_init(&dev->slock);
1940 init_waitqueue_head(&dev->open); 1941 init_waitqueue_head(&dev->open);
1941 init_waitqueue_head(&dev->wait_frame); 1942 init_waitqueue_head(&dev->wait_frame);
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index 1adf3d9d9bff..5956e9b3062f 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -433,6 +433,7 @@ struct em28xx {
433 433
434 /* locks */ 434 /* locks */
435 struct mutex lock; 435 struct mutex lock;
436 struct mutex ctrl_urb_lock; /* protects urb_buf */
436 /* spinlock_t queue_lock; */ 437 /* spinlock_t queue_lock; */
437 struct list_head inqueue, outqueue; 438 struct list_head inqueue, outqueue;
438 wait_queue_head_t open, wait_frame, wait_stream; 439 wait_queue_head_t open, wait_frame, wait_stream;