[PATCH] fix for race problem in DVB USB drivers (dibusb)

Fixed race between submitting streaming URBs in the driver and starting
the actual transfer in hardware (demodulator and USB controller) which
sometimes lead to garbled data transfers. URBs are now submitted first,
then the transfer is enabled. Dibusb devices and clones are now fully
functional again.

Signed-off-by: Patrick Boettcher <pb@linuxtv.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
index 63b626f..9b9d6f8 100644
--- a/drivers/media/dvb/dvb-usb/dibusb-common.c
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -70,13 +70,22 @@
 
 int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff)
 {
-	u8 b[2];
+	u8 b[3] = { 0 };
+	int ret;
+
+	if ((ret = dibusb_streaming_ctrl(d,onoff)) < 0)
+		return ret;
+
+	if (onoff) {
+		b[0] = DIBUSB_REQ_SET_STREAMING_MODE;
+		b[1] = 0x00;
+		if ((ret = dvb_usb_generic_write(d,b,2)) < 0)
+			return ret;
+	}
+
 	b[0] = DIBUSB_REQ_SET_IOCTL;
 	b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
-
-	dvb_usb_generic_write(d,b,3);
-
-	return dibusb_streaming_ctrl(d,onoff);
+	return dvb_usb_generic_write(d,b,3);
 }
 EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
 
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
index 3491ff4..6fa9210 100644
--- a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -23,12 +23,12 @@
 	 */
 	if (newfeedcount == 0) {
 		deb_ts("stop feeding\n");
+		dvb_usb_urb_kill(d);
 
 		if (d->props.streaming_ctrl != NULL)
 			if ((ret = d->props.streaming_ctrl(d,0)))
 				err("error while stopping stream.");
 
-		dvb_usb_urb_kill(d);
 	}
 
 	d->feedcount = newfeedcount;
@@ -44,6 +44,8 @@
 	 * for reception.
 	 */
 	if (d->feedcount == onoff && d->feedcount > 0) {
+		deb_ts("submitting all URBs\n");
+		dvb_usb_urb_submit(d);
 
 		deb_ts("controlling pid parser\n");
 		if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
@@ -59,7 +61,6 @@
 				return -ENODEV;
 			}
 
-		dvb_usb_urb_submit(d);
 	}
 	return 0;
 }