aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorDean Anderson <dean@sensoray.com>2008-07-22 13:43:27 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-26 12:18:14 -0400
commitf78d92c9ffcda7451b5943ab491c087f1ec7e08d (patch)
treec9cf013cc73d875fd45160af11b2256ae87741fc /drivers/media
parent655b8408557d586212d0797d423babdc464c587f (diff)
V4L/DVB (8490): s2255drv Sensoray 2255 driver fixes
This patch fixes timer issues in driver disconnect. It also removes the restriction of one user per channel at a time. Thanks to Oliver Neukum and Mauro Chehab for finding these issues. Locking of video stream partly based on saa7134 driver. Signed-off-by: Dean Anderson <dean@sensoray.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/s2255drv.c111
1 files changed, 65 insertions, 46 deletions
diff --git a/drivers/media/video/s2255drv.c b/drivers/media/video/s2255drv.c
index 2428d441fe15..9ff5403483e5 100644
--- a/drivers/media/video/s2255drv.c
+++ b/drivers/media/video/s2255drv.c
@@ -185,6 +185,7 @@ struct s2255_dmaqueue {
185#define S2255_FW_LOADED_DSPWAIT 1 185#define S2255_FW_LOADED_DSPWAIT 1
186#define S2255_FW_SUCCESS 2 186#define S2255_FW_SUCCESS 2
187#define S2255_FW_FAILED 3 187#define S2255_FW_FAILED 3
188#define S2255_FW_DISCONNECTING 4
188 189
189struct s2255_fw { 190struct s2255_fw {
190 int fw_loaded; 191 int fw_loaded;
@@ -264,7 +265,6 @@ struct s2255_buffer {
264 265
265struct s2255_fh { 266struct s2255_fh {
266 struct s2255_dev *dev; 267 struct s2255_dev *dev;
267 unsigned int resources;
268 const struct s2255_fmt *fmt; 268 const struct s2255_fmt *fmt;
269 unsigned int width; 269 unsigned int width;
270 unsigned int height; 270 unsigned int height;
@@ -274,14 +274,9 @@ struct s2255_fh {
274 /* mode below is the desired mode. 274 /* mode below is the desired mode.
275 mode in s2255_dev is the current mode that was last set */ 275 mode in s2255_dev is the current mode that was last set */
276 struct s2255_mode mode; 276 struct s2255_mode mode;
277 int resources[MAX_CHANNELS];
277}; 278};
278 279
279/*
280 * TODO: fixme S2255_MAX_USERS. Do not limit open driver handles.
281 * Limit V4L to one stream at a time.
282 */
283#define S2255_MAX_USERS 1
284
285#define CUR_USB_FWVER 774 /* current cypress EEPROM firmware version */ 280#define CUR_USB_FWVER 774 /* current cypress EEPROM firmware version */
286#define S2255_MAJOR_VERSION 1 281#define S2255_MAJOR_VERSION 1
287#define S2255_MINOR_VERSION 13 282#define S2255_MINOR_VERSION 13
@@ -477,10 +472,9 @@ static void s2255_timer(unsigned long user_data)
477 dprintk(100, "s2255 timer\n"); 472 dprintk(100, "s2255 timer\n");
478 if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) { 473 if (usb_submit_urb(data->fw_urb, GFP_ATOMIC) < 0) {
479 printk(KERN_ERR "s2255: can't submit urb\n"); 474 printk(KERN_ERR "s2255: can't submit urb\n");
480 if (data->fw) { 475 atomic_set(&data->fw_state, S2255_FW_FAILED);
481 release_firmware(data->fw); 476 /* wake up anything waiting for the firmware */
482 data->fw = NULL; 477 wake_up(&data->wait_fw);
483 }
484 return; 478 return;
485 } 479 }
486} 480}
@@ -510,13 +504,18 @@ static void s2255_fwchunk_complete(struct urb *urb)
510 struct usb_device *udev = urb->dev; 504 struct usb_device *udev = urb->dev;
511 int len; 505 int len;
512 dprintk(100, "udev %p urb %p", udev, urb); 506 dprintk(100, "udev %p urb %p", udev, urb);
513 /* TODO: fixme. reflect change in status */
514 if (urb->status) { 507 if (urb->status) {
515 dev_err(&udev->dev, "URB failed with status %d", urb->status); 508 dev_err(&udev->dev, "URB failed with status %d", urb->status);
509 atomic_set(&data->fw_state, S2255_FW_FAILED);
510 /* wake up anything waiting for the firmware */
511 wake_up(&data->wait_fw);
516 return; 512 return;
517 } 513 }
518 if (data->fw_urb == NULL) { 514 if (data->fw_urb == NULL) {
519 dev_err(&udev->dev, "early disconncect\n"); 515 dev_err(&udev->dev, "s2255 disconnected\n");
516 atomic_set(&data->fw_state, S2255_FW_FAILED);
517 /* wake up anything waiting for the firmware */
518 wake_up(&data->wait_fw);
520 return; 519 return;
521 } 520 }
522#define CHUNK_SIZE 512 521#define CHUNK_SIZE 512
@@ -790,7 +789,8 @@ static int res_get(struct s2255_dev *dev, struct s2255_fh *fh)
790 } 789 }
791 /* it's free, grab it */ 790 /* it's free, grab it */
792 dev->resources[fh->channel] = 1; 791 dev->resources[fh->channel] = 1;
793 dprintk(1, "res: get\n"); 792 fh->resources[fh->channel] = 1;
793 dprintk(1, "s2255: res: get\n");
794 mutex_unlock(&dev->lock); 794 mutex_unlock(&dev->lock);
795 return 1; 795 return 1;
796} 796}
@@ -800,9 +800,18 @@ static int res_locked(struct s2255_dev *dev, struct s2255_fh *fh)
800 return dev->resources[fh->channel]; 800 return dev->resources[fh->channel];
801} 801}
802 802
803static int res_check(struct s2255_fh *fh)
804{
805 return fh->resources[fh->channel];
806}
807
808
803static void res_free(struct s2255_dev *dev, struct s2255_fh *fh) 809static void res_free(struct s2255_dev *dev, struct s2255_fh *fh)
804{ 810{
811 mutex_lock(&dev->lock);
805 dev->resources[fh->channel] = 0; 812 dev->resources[fh->channel] = 0;
813 fh->resources[fh->channel] = 0;
814 mutex_unlock(&dev->lock);
806 dprintk(1, "res: put\n"); 815 dprintk(1, "res: put\n");
807} 816}
808 817
@@ -1233,7 +1242,7 @@ static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
1233 } 1242 }
1234 1243
1235 if (!res_get(dev, fh)) { 1244 if (!res_get(dev, fh)) {
1236 dev_err(&dev->udev->dev, "res get busy\n"); 1245 dev_err(&dev->udev->dev, "s2255: stream busy\n");
1237 return -EBUSY; 1246 return -EBUSY;
1238 } 1247 }
1239 1248
@@ -1289,8 +1298,10 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
1289 } 1298 }
1290 s2255_stop_acquire(dev, fh->channel); 1299 s2255_stop_acquire(dev, fh->channel);
1291 res = videobuf_streamoff(&fh->vb_vidq); 1300 res = videobuf_streamoff(&fh->vb_vidq);
1301 if (res < 0)
1302 return res;
1292 res_free(dev, fh); 1303 res_free(dev, fh);
1293 return res; 1304 return 0;
1294} 1305}
1295 1306
1296static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i) 1307static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
@@ -1463,12 +1474,7 @@ static int s2255_open(struct inode *inode, struct file *file)
1463 mutex_lock(&dev->open_lock); 1474 mutex_lock(&dev->open_lock);
1464 1475
1465 dev->users[cur_channel]++; 1476 dev->users[cur_channel]++;
1466 if (dev->users[cur_channel] > S2255_MAX_USERS) { 1477 dprintk(4, "s2255: open_handles %d\n", dev->users[cur_channel]);
1467 dev->users[cur_channel]--;
1468 mutex_unlock(&dev->open_lock);
1469 printk(KERN_INFO "s2255drv: too many open handles!\n");
1470 return -EBUSY;
1471 }
1472 1478
1473 if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) { 1479 if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_FAILED) {
1474 err("2255 firmware load failed. retrying.\n"); 1480 err("2255 firmware load failed. retrying.\n");
@@ -1479,7 +1485,8 @@ static int s2255_open(struct inode *inode, struct file *file)
1479 msecs_to_jiffies(S2255_LOAD_TIMEOUT)); 1485 msecs_to_jiffies(S2255_LOAD_TIMEOUT));
1480 if (atomic_read(&dev->fw_data->fw_state) 1486 if (atomic_read(&dev->fw_data->fw_state)
1481 != S2255_FW_SUCCESS) { 1487 != S2255_FW_SUCCESS) {
1482 printk(KERN_INFO "2255 FW load failed after 2 tries\n"); 1488 printk(KERN_INFO "2255 FW load failed.\n");
1489 dev->users[cur_channel]--;
1483 mutex_unlock(&dev->open_lock); 1490 mutex_unlock(&dev->open_lock);
1484 return -EFAULT; 1491 return -EFAULT;
1485 } 1492 }
@@ -1495,6 +1502,7 @@ static int s2255_open(struct inode *inode, struct file *file)
1495 != S2255_FW_SUCCESS) { 1502 != S2255_FW_SUCCESS) {
1496 printk(KERN_INFO "2255 firmware not loaded" 1503 printk(KERN_INFO "2255 firmware not loaded"
1497 "try again\n"); 1504 "try again\n");
1505 dev->users[cur_channel]--;
1498 mutex_unlock(&dev->open_lock); 1506 mutex_unlock(&dev->open_lock);
1499 return -EBUSY; 1507 return -EBUSY;
1500 } 1508 }
@@ -1503,6 +1511,7 @@ static int s2255_open(struct inode *inode, struct file *file)
1503 /* allocate + initialize per filehandle data */ 1511 /* allocate + initialize per filehandle data */
1504 fh = kzalloc(sizeof(*fh), GFP_KERNEL); 1512 fh = kzalloc(sizeof(*fh), GFP_KERNEL);
1505 if (NULL == fh) { 1513 if (NULL == fh) {
1514 dev->users[cur_channel]--;
1506 mutex_unlock(&dev->open_lock); 1515 mutex_unlock(&dev->open_lock);
1507 return -ENOMEM; 1516 return -ENOMEM;
1508 } 1517 }
@@ -1562,44 +1571,48 @@ static void s2255_destroy(struct kref *kref)
1562 printk(KERN_ERR "s2255drv: kref problem\n"); 1571 printk(KERN_ERR "s2255drv: kref problem\n");
1563 return; 1572 return;
1564 } 1573 }
1574
1575 /*
1576 * Wake up any firmware load waiting (only done in .open,
1577 * which holds the open_lock mutex)
1578 */
1579 atomic_set(&dev->fw_data->fw_state, S2255_FW_DISCONNECTING);
1580 wake_up(&dev->fw_data->wait_fw);
1581
1565 /* prevent s2255_disconnect from racing s2255_open */ 1582 /* prevent s2255_disconnect from racing s2255_open */
1566 mutex_lock(&dev->open_lock); 1583 mutex_lock(&dev->open_lock);
1567 s2255_exit_v4l(dev); 1584 s2255_exit_v4l(dev);
1568 /* device unregistered so no longer possible to open. open_mutex 1585 /*
1569 can be unlocked */ 1586 * device unregistered so no longer possible to open. open_mutex
1587 * can be unlocked and timers deleted afterwards.
1588 */
1570 mutex_unlock(&dev->open_lock); 1589 mutex_unlock(&dev->open_lock);
1571 1590
1572 /* board shutdown stops the read pipe if it is running */ 1591 /* board shutdown stops the read pipe if it is running */
1573 s2255_board_shutdown(dev); 1592 s2255_board_shutdown(dev);
1574 1593
1575 /* make sure firmware still not trying to load */ 1594 /* make sure firmware still not trying to load */
1595 del_timer(&dev->timer); /* only started in .probe and .open */
1596
1576 if (dev->fw_data->fw_urb) { 1597 if (dev->fw_data->fw_urb) {
1577 dprintk(2, "kill fw_urb\n"); 1598 dprintk(2, "kill fw_urb\n");
1578 usb_kill_urb(dev->fw_data->fw_urb); 1599 usb_kill_urb(dev->fw_data->fw_urb);
1579 usb_free_urb(dev->fw_data->fw_urb); 1600 usb_free_urb(dev->fw_data->fw_urb);
1580 dev->fw_data->fw_urb = NULL; 1601 dev->fw_data->fw_urb = NULL;
1581 } 1602 }
1603
1582 /* 1604 /*
1583 * TODO: fixme(above, below): potentially leaving timers alive. 1605 * delete the dsp_wait timer, which sets the firmware
1584 * do not ignore timeout below if 1606 * state on completion. This is done before fw_data
1585 * it occurs. 1607 * is freed below.
1586 */ 1608 */
1587 1609
1588 /* make sure we aren't waiting for the DSP */ 1610 del_timer(&dev->fw_data->dsp_wait); /* only started in .open */
1589 if (atomic_read(&dev->fw_data->fw_state) == S2255_FW_LOADED_DSPWAIT) {
1590 /* if we are, wait for the wakeup for fw_success or timeout */
1591 wait_event_timeout(dev->fw_data->wait_fw,
1592 (atomic_read(&dev->fw_data->fw_state)
1593 == S2255_FW_SUCCESS),
1594 msecs_to_jiffies(S2255_LOAD_TIMEOUT));
1595 }
1596 1611
1597 if (dev->fw_data) { 1612 if (dev->fw_data->fw)
1598 if (dev->fw_data->fw) 1613 release_firmware(dev->fw_data->fw);
1599 release_firmware(dev->fw_data->fw); 1614 kfree(dev->fw_data->pfw_data);
1600 kfree(dev->fw_data->pfw_data); 1615 kfree(dev->fw_data);
1601 kfree(dev->fw_data);
1602 }
1603 1616
1604 usb_put_dev(dev->udev); 1617 usb_put_dev(dev->udev);
1605 dprintk(1, "%s", __func__); 1618 dprintk(1, "%s", __func__);
@@ -1616,17 +1629,23 @@ static int s2255_close(struct inode *inode, struct file *file)
1616 1629
1617 mutex_lock(&dev->open_lock); 1630 mutex_lock(&dev->open_lock);
1618 1631
1619 if (dev->b_acquire[fh->channel]) 1632 /* turn off stream */
1620 s2255_stop_acquire(dev, fh->channel); 1633 if (res_check(fh)) {
1621 res_free(dev, fh); 1634 if (dev->b_acquire[fh->channel])
1635 s2255_stop_acquire(dev, fh->channel);
1636 videobuf_streamoff(&fh->vb_vidq);
1637 res_free(dev, fh);
1638 }
1639
1622 videobuf_mmap_free(&fh->vb_vidq); 1640 videobuf_mmap_free(&fh->vb_vidq);
1623 kfree(fh);
1624 dev->users[fh->channel]--; 1641 dev->users[fh->channel]--;
1642
1625 mutex_unlock(&dev->open_lock); 1643 mutex_unlock(&dev->open_lock);
1626 1644
1627 kref_put(&dev->kref, s2255_destroy); 1645 kref_put(&dev->kref, s2255_destroy);
1628 dprintk(1, "s2255: close called (minor=%d, users=%d)\n", 1646 dprintk(1, "s2255: close called (minor=%d, users=%d)\n",
1629 minor, dev->users[fh->channel]); 1647 minor, dev->users[fh->channel]);
1648 kfree(fh);
1630 return 0; 1649 return 0;
1631} 1650}
1632 1651