Comment 3 for bug 34543

Revision history for this message
vodunvibe (vodunvibe) wrote :

Subject: [PATCH] spca5xx patch for “No space left on device” error message

Related bugs:
https://launchpad.net/distros/ubuntu/+source/spca5xx/+bug/34543
https://launchpad.net/distros/ubuntu/+source/linux-source-2.6.15/+bug/42132
https://launchpad.net/distros/ubuntu/+source/linux-source-2.6.15/+bug/38906

Please take a look at the following for more details and fixes:
http://ubuntuforums.org/showthread.php?t=247646

Subject: [PATCH] spca5xx patch for “No space left on device” error message

This patch Fixes the bandwidth problem that occurs when other USB devices
are on the same host controller bus as the camera by gradually lowering the
bandwidth requirements of the driver.

When the patch is applied, spca5xx drivers works even when other USB devices
are present on the same host controller bus as the camera.

This patch is currently against the spca5xx-20060501 source.

To apply the patch from your current working directory, with a subdirectory
called spca5xx-20060501 use:
patch -p0 < spca5xx-20060501-vodunvibe-Nospaceleftondevice.patch

To apply the patch, in the spca5xx-20060501 directory use:
patch -p1 < spca5xx-20060501-vodunvibe-Nospaceleftondevice.patch

Bandwidth Problem details:
 When other USB devices are present on the same host controller
 bus as the camera, the bandwidth requirements of the spca5xx driver
 are not being met. The spca5xx driver is asking for more bandwidth
 than is available which results in the following error messages:

 No space left on device
 can't open /dev/video0: No space left on device.
 usb_submit_urb(0) ret -28

Thanks,
vodunvibe

diff -urN spca5xx-20060501.orig/drivers/usb/spca5xx.c spca5xx-20060501/drivers/usb/spca5xx.c
--- spca5xx-20060501.orig/drivers/usb/spca5xx.c 2006-04-29 11:38:07.000000000 -0400
+++ spca5xx-20060501/drivers/usb/spca5xx.c 2006-09-05 13:19:04.000000000 -0400
@@ -1574,6 +1574,66 @@
       spca50x->funct.stopN(spca50x);
 }

+
+/**********************************************************************
+* spcaReducePacketSize
+* Function Fixes the bandwidth problem that occurs
+* when other USB devices are on the same host controller bus as the
+* camera by gradually lowering the bandwidth requirements of the driver.
+* It works even when other USB devices are present on the same
+* host controller bus as the camera.
+*
+* Problem
+* When other USB devices are present on the same host controller
+* bus as the camera, the bandwidth requirements of the spca5xx driver
+* are not being met. The spca5xx driver is asking for more bandwidth
+* than is available which results in the following error messages:
+*
+* No space left on device
+* can't open /dev/video0: No space left on device.
+* usb_submit_urb(0) ret -28
+*
+*
+* Many thanks to all the wonderful people contributing to this project.
+*
+* Great work!
+* vodunvibe [AT] <email address hidden> yahoo DOT com
+* 2006-08-27
+*
+***********************************************************************/
+static int spcaReducePacketSize(struct usb_spca50x *spca50x, int n, int err)
+{
+ int size=896, fx, i;
+ err("spcaReducePacketSize: vodunvibe - The usb_submit_urb(%d) transfer request submission failed - You probably have another device sharing the same USB Host Controller Bus as your camera. Try using another USB port, on a different host controller bus.", n);
+ while (err == -ENOSPC && size >= 0) {
+ err("spcaReducePacketSize: vodunvibe - Lowering the bandwidth requirements - New packet size (%d) ", size);
+ spca50x_set_packet_size(spca50x, size);
+ spca50x->sbuf[n].urb->transfer_buffer_length = spca50x->packet_size * FRAMES_PER_DESC;
+ for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
+ spca50x->sbuf[n].urb->iso_frame_desc[fx].offset = spca50x->packet_size * fx;
+ spca50x->sbuf[n].urb->iso_frame_desc[fx].length = spca50x->packet_size;
+ }
+ size-=128;
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,41)
+ err = usb_submit_urb(spca50x->sbuf[n].urb, GFP_KERNEL);
+#else
+ err = usb_submit_urb(spca50x->sbuf[n].urb);
+#endif
+ }
+
+ if (!err) {
+ for (i = 0; i < SPCA50X_NUMSBUF; i++) {
+ spca50x->sbuf[i].urb->transfer_buffer_length = spca50x->packet_size * FRAMES_PER_DESC;
+ for (fx = 0; fx < FRAMES_PER_DESC; fx++) {
+ spca50x->sbuf[i].urb->iso_frame_desc[fx].offset = spca50x->packet_size * fx;
+ spca50x->sbuf[i].urb->iso_frame_desc[fx].length = spca50x->packet_size;
+ }
+ }
+ }
+ return err;
+}
+
+
 static int spca50x_init_isoc(struct usb_spca50x *spca50x)
 {

@@ -1649,7 +1709,15 @@
 #endif
  if (err) {
      err("init isoc: usb_submit_urb(%d) ret %d", n, err);
- return err;
+ if (err == -ENOSPC) {
+ err = spcaReducePacketSize(spca50x, n, err);
+ if (err) {
+ err("init isoc: After spcaReducePacketSize - usb_submit_urb(%d) ret %d", n, err);
+ return err;
+ }
+ }else{
+ return err;
+ }
  }
     }