Commit f2a2e491 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

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: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent c4a98793
...@@ -76,18 +76,22 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg, ...@@ -76,18 +76,22 @@ int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
em28xx_regdbg("req=%02x, reg=%02x ", req, reg); em28xx_regdbg("req=%02x, reg=%02x ", req, reg);
mutex_lock(&dev->ctrl_urb_lock);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, reg, dev->urb_buf, len, HZ); 0x0000, reg, dev->urb_buf, len, HZ);
if (ret < 0) { if (ret < 0) {
if (reg_debug) if (reg_debug)
printk(" failed!\n"); printk(" failed!\n");
mutex_unlock(&dev->ctrl_urb_lock);
return ret; return ret;
} }
if (len) if (len)
memcpy(buf, dev->urb_buf, len); memcpy(buf, dev->urb_buf, len);
mutex_unlock(&dev->ctrl_urb_lock);
if (reg_debug) { if (reg_debug) {
printk("%02x values: ", ret); printk("%02x values: ", ret);
for (byte = 0; byte < len; byte++) for (byte = 0; byte < len; byte++)
...@@ -112,16 +116,18 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg) ...@@ -112,16 +116,18 @@ int em28xx_read_reg_req(struct em28xx *dev, u8 req, u16 reg)
em28xx_regdbg("req=%02x, reg=%02x:", req, reg); em28xx_regdbg("req=%02x, reg=%02x:", req, reg);
mutex_lock(&dev->ctrl_urb_lock);
ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req, ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), req,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, reg, dev->urb_buf, 1, HZ); 0x0000, reg, dev->urb_buf, 1, HZ);
val = dev->urb_buf[0];
mutex_unlock(&dev->ctrl_urb_lock);
if (ret < 0) { if (ret < 0) {
printk(" failed!\n"); printk(" failed!\n");
return ret; return ret;
} }
val = dev->urb_buf[0];
if (reg_debug) if (reg_debug)
printk("%02x\n", (unsigned char) val); printk("%02x\n", (unsigned char) val);
...@@ -156,10 +162,12 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf, ...@@ -156,10 +162,12 @@ int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
printk("\n"); printk("\n");
} }
mutex_lock(&dev->ctrl_urb_lock);
memcpy(dev->urb_buf, buf, len); memcpy(dev->urb_buf, buf, len);
ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req, ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), req,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0x0000, reg, dev->urb_buf, len, HZ); 0x0000, reg, dev->urb_buf, len, HZ);
mutex_unlock(&dev->ctrl_urb_lock);
if (dev->wait_after_write) if (dev->wait_after_write)
msleep(dev->wait_after_write); msleep(dev->wait_after_write);
......
...@@ -1936,6 +1936,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, ...@@ -1936,6 +1936,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev,
dev->udev = udev; dev->udev = udev;
mutex_init(&dev->lock); mutex_init(&dev->lock);
mutex_init(&dev->ctrl_urb_lock);
spin_lock_init(&dev->slock); spin_lock_init(&dev->slock);
init_waitqueue_head(&dev->open); init_waitqueue_head(&dev->open);
init_waitqueue_head(&dev->wait_frame); init_waitqueue_head(&dev->wait_frame);
......
...@@ -433,6 +433,7 @@ struct em28xx { ...@@ -433,6 +433,7 @@ struct em28xx {
/* locks */ /* locks */
struct mutex lock; struct mutex lock;
struct mutex ctrl_urb_lock; /* protects urb_buf */
/* spinlock_t queue_lock; */ /* spinlock_t queue_lock; */
struct list_head inqueue, outqueue; struct list_head inqueue, outqueue;
wait_queue_head_t open, wait_frame, wait_stream; wait_queue_head_t open, wait_frame, wait_stream;
......
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