|
@@ -153,9 +153,11 @@ static int stop_urb_transfer(struct au0828_dev *dev)
|
|
|
|
|
|
dev->urb_streaming = 0;
|
|
|
for (i = 0; i < URB_COUNT; i++) {
|
|
|
- usb_kill_urb(dev->urbs[i]);
|
|
|
- kfree(dev->urbs[i]->transfer_buffer);
|
|
|
- usb_free_urb(dev->urbs[i]);
|
|
|
+ if (dev->urbs[i]) {
|
|
|
+ usb_kill_urb(dev->urbs[i]);
|
|
|
+ kfree(dev->urbs[i]->transfer_buffer);
|
|
|
+ usb_free_urb(dev->urbs[i]);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -185,6 +187,9 @@ static int start_urb_transfer(struct au0828_dev *dev)
|
|
|
if (!purb->transfer_buffer) {
|
|
|
usb_free_urb(purb);
|
|
|
dev->urbs[i] = NULL;
|
|
|
+ printk(KERN_ERR
|
|
|
+ "%s: failed big buffer allocation, err = %d\n",
|
|
|
+ __func__, ret);
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
@@ -217,6 +222,27 @@ err:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static void au0828_start_transport(struct au0828_dev *dev)
|
|
|
+{
|
|
|
+ au0828_write(dev, 0x608, 0x90);
|
|
|
+ au0828_write(dev, 0x609, 0x72);
|
|
|
+ au0828_write(dev, 0x60a, 0x71);
|
|
|
+ au0828_write(dev, 0x60b, 0x01);
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static void au0828_stop_transport(struct au0828_dev *dev, int full_stop)
|
|
|
+{
|
|
|
+ if (full_stop) {
|
|
|
+ au0828_write(dev, 0x608, 0x00);
|
|
|
+ au0828_write(dev, 0x609, 0x00);
|
|
|
+ au0828_write(dev, 0x60a, 0x00);
|
|
|
+ }
|
|
|
+ au0828_write(dev, 0x60b, 0x00);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
|
|
|
{
|
|
|
struct dvb_demux *demux = feed->demux;
|
|
@@ -231,13 +257,17 @@ static int au0828_dvb_start_feed(struct dvb_demux_feed *feed)
|
|
|
|
|
|
if (dvb) {
|
|
|
mutex_lock(&dvb->lock);
|
|
|
+ dvb->start_count++;
|
|
|
+ dprintk(1, "%s(), start_count: %d, stop_count: %d\n", __func__,
|
|
|
+ dvb->start_count, dvb->stop_count);
|
|
|
if (dvb->feeding++ == 0) {
|
|
|
/* Start transport */
|
|
|
- au0828_write(dev, 0x608, 0x90);
|
|
|
- au0828_write(dev, 0x609, 0x72);
|
|
|
- au0828_write(dev, 0x60a, 0x71);
|
|
|
- au0828_write(dev, 0x60b, 0x01);
|
|
|
+ au0828_start_transport(dev);
|
|
|
ret = start_urb_transfer(dev);
|
|
|
+ if (ret < 0) {
|
|
|
+ au0828_stop_transport(dev, 0);
|
|
|
+ dvb->feeding--; /* We ran out of memory... */
|
|
|
+ }
|
|
|
}
|
|
|
mutex_unlock(&dvb->lock);
|
|
|
}
|
|
@@ -256,10 +286,16 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
|
|
|
|
|
|
if (dvb) {
|
|
|
mutex_lock(&dvb->lock);
|
|
|
- if (--dvb->feeding == 0) {
|
|
|
- /* Stop transport */
|
|
|
- ret = stop_urb_transfer(dev);
|
|
|
- au0828_write(dev, 0x60b, 0x00);
|
|
|
+ dvb->stop_count++;
|
|
|
+ dprintk(1, "%s(), start_count: %d, stop_count: %d\n", __func__,
|
|
|
+ dvb->start_count, dvb->stop_count);
|
|
|
+ if (dvb->feeding > 0) {
|
|
|
+ dvb->feeding--;
|
|
|
+ if (dvb->feeding == 0) {
|
|
|
+ /* Stop transport */
|
|
|
+ ret = stop_urb_transfer(dev);
|
|
|
+ au0828_stop_transport(dev, 0);
|
|
|
+ }
|
|
|
}
|
|
|
mutex_unlock(&dvb->lock);
|
|
|
}
|
|
@@ -282,16 +318,10 @@ static void au0828_restart_dvb_streaming(struct work_struct *work)
|
|
|
|
|
|
/* Stop transport */
|
|
|
stop_urb_transfer(dev);
|
|
|
- au0828_write(dev, 0x608, 0x00);
|
|
|
- au0828_write(dev, 0x609, 0x00);
|
|
|
- au0828_write(dev, 0x60a, 0x00);
|
|
|
- au0828_write(dev, 0x60b, 0x00);
|
|
|
+ au0828_stop_transport(dev, 1);
|
|
|
|
|
|
/* Start transport */
|
|
|
- au0828_write(dev, 0x608, 0x90);
|
|
|
- au0828_write(dev, 0x609, 0x72);
|
|
|
- au0828_write(dev, 0x60a, 0x71);
|
|
|
- au0828_write(dev, 0x60b, 0x01);
|
|
|
+ au0828_start_transport(dev);
|
|
|
start_urb_transfer(dev);
|
|
|
|
|
|
mutex_unlock(&dvb->lock);
|
|
@@ -375,6 +405,9 @@ static int dvb_register(struct au0828_dev *dev)
|
|
|
|
|
|
/* register network adapter */
|
|
|
dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
|
|
|
+
|
|
|
+ dvb->start_count = 0;
|
|
|
+ dvb->stop_count = 0;
|
|
|
return 0;
|
|
|
|
|
|
fail_fe_conn:
|