[linux-dvb] [Patch] kernel crash when using a dvb usb stick on a mips platform

Michele Scorcia scorcia at usa.net
Sun Jan 20 13:02:40 CET 2008

I post this patch that fixes a kernel crash that happens when using a dvb
usb stick on a mips platform and I think even on other platforms on which
the dma access in not cache-coherent.

The problem's origin is that, inside the method usb_bulk_urb_init of file
drivers/media/dvb/dvb-usb/usb-urb.c, stream->urb_list[i]->transfer_buffer
points to a memory area that has been allocated to be dma-coherent but
stream->urb_list[i]->transfer_flags doesn't include the
URB_NO_TRANSFER_DMA_MAP flag and stream->urb_list[i]->transfer_dma is not
When later on the stream->urb_list[i]->transfer_buffer pointer is used
inside function usb_hcd_submit_urb of file drivers/usb/core/hcd.c since the
flag URB_NO_TRANSFER_DMA_MAP is not set the urb->transfer_buffer pointer is
passed to the dma_map_single function that since the address is dma-coherent
returns a wrong tranfer_dma address that later on leads to the kernel crash.

The problem is solved by setting the URB_NO_TRANSFER_DMA_MAP flag and the
stream->urb_list[i]->transfer_dma address.

Perhaps to be more safe the URB_NO_TRANSFER_DMA_MAP flag can be set only
if stream->urb_list[i]->transfer_dma != 0.

I don't know if half of the fault can be of the dma_map_single function that
should anyway returns a valid address both for a not dma-coherent and a
dma-coherent address.

Just to be clear:
I've done this patch to solve my problem and I tested it only on a mips 
but I think it should not cause any problems on other platforms.
I posted it here to help someone else that can have my same problem and to 
point it out
to the mantainer of this part of code.
You can use it at your own risk and I'm not resposible in any way for any 
problem or
damage that it can cause.
I'm available to discuss about it


Michele Scorcia


--- linux- 2007-03-23
20:52:51.000000000 +0100
+++ linux- 2007-10-25
12:19:50.000000000 +0200
@@ -152,7 +152,8 @@
     usb_urb_complete, stream);

-  stream->urb_list[i]->transfer_flags = 0;
+  stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+  stream->urb_list[i]->transfer_dma = stream->dma_addr[i];
  return 0;

More information about the linux-dvb mailing list