This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

USB DMA issue: bulk_read return more than requested bytes (PG2.0 too)

Expert 2280 points

Hi

On a AM335x-based custom board, I have a linux application using libusb to talk with a custom USB device through USB1 host interface.

If kernel MUSB driver is built without DMA support, there is no issue. But with DMA support, sometimes it happens that usb_bulk_read returns a number of read bytes greater than the buffer size as specified in function arguments. In the specific case, buffer size is 15872, and usb_bulk_read return 16384, i.e. 512 more. Thus memory allocator asserts detecting corruption, causing the application to exit, of course.

I do not think it is due to libusb, because without DMA everything works fine.

Moreover I've verified this behaviour both on new silicon revison PG2.0, and old one too.

So I suspect is something in kernel MUSB driver.

Best regards,
Max

  • Max,


    The DMA has been used widely across many usb classes and we have not seen such issue. There are a couple things could you please check?

    • Please briefly describe the usb device? what class? what kind of EPs in use?
    • Ensure it is not the USB device sending the extra 512 bytes. do you have access to an USB protocol analyzer or the firmware source code of the USB device to log the usb bus traffic?
    • If it is not the USB device causing the issue, could you increase the buffer size in the application to capture the extra data, and look at if there is any kind of pattern in it? repeat packet of any 512 bytes of the 15872 byte data? or just random garbage?
    • what version of libusb do you use? I don't see usb_bulk_read() in its latest version.

    Regards,

    -Bin.

    -

  • Hi Bin, thanks for your support.

    • It's a custom USB device, no standard class, with just two bulk EPs, one IN and one OUT.
    • I do no think it is the device to send extra bytes  (in PIO mode everything works fine) but cannot be 100% sure because I do not have a USB bus/protocol analyzer. We have device firmware source code, but not easily to debug.
    • I've done it capturing extra data: it's almost all zeros in the last 512-bytes chunk, but I've also verified that data in some of the previous 31 chunks is corrupted. Starting with approx the 23th chunk, data is filled with zeros and others recurring patterns. This happens at least in the wrong-sized received buffer; as now I'm not sure data in previously received buffers is correct.
    • We are using libusb 0.1: it's not the latest but still supported and provided within SDK rootfs.

    I've notice one interesting thing running further tests: adding some logs/printk in MUSB driver in kernel space, the behaviour changes. In some cases the wrong-sized buffer is 24576 bytes long. In another case, logging on DMA channel allocation, it happens that things worked fine. But it is not easily reproducible. My suspect is that logs slow down processing, so issue seems related to speed/time. Of course slow-down affects USB device side too.

    Regards,

    Max

  • Max,

    At this point I don't have a clear idea how to debug this issue. But I just noticed a DMA issue while debug a USB problem. could you please try the following change to see if yours is the same? If you see the printk message when the extra packet happens, it is the same issue.

    diff --git a/drivers/usb/musb/cppi41_dma.c b/drivers/usb/musb/cppi41_dma.c
    @@ -1447,7 +1447,8 @@ void cppi41_handle_txfifo_intr(struct musb *musb, u16 usbintr)
                                    dev_dbg(musb->controller,
                                            "txc: givback ep%d\n", index+1);
                                    musb_dma_completion(musb, index+1, 1);
    -                       }       
    +                       } else          
    +                               printk("**** TIFIFO Emtry INT, but not complete yet\n");
                    }       
                    usbintr = usbintr >> 1;
            }

    For the printk slowing down affect, you could use trace_printk(), which has very minimum side affect. [Documentation/trace/ftrace.txt]

  • Bin,

    I've added the suggested printk but I do not see it.

    Regarding the libusb version, I had a quick look at the filesystem and it seems libusb 0.1 is just a wrapper to libusb 1.0 to provide 0.1 API interface. So I do not think it's an issue.

    As now I'm running some tests splitting the usb_bulk_read of 15872 bytes into multiple usb_bulk_read calls (each one of 512 bytes or less): looking at first results, things seem working in this way, even if I cannot understand the reason (is it just a matter of timing or something else?). I will confirm after running further tests.

    Regards

    Max

  • Max,


    Could you please check if the IRQ load goes higher when the app splits the transfer to 512-byte?

    What kernel version do you use right now? (Sorry, I lost tracking of your project.) I have a few USB DMA patches from PSP team (not been fully tested yet) and I'd like to check if they are applicable on your kernel then you can test those patches.

    Regards,

    -Bin.

  • Hi Bin,

    Splitting to 512-bytes chunks seems finally working: I run several tests, but I do not like this solution too much. It is not really clear, and I worry it could be the cause of new problems in the future. How can I check IRQ load?

    I'm using kernel based on PSP 04.06.00.08. In the meantime I've seen a new 04.06.00.09 has been released: does it include USB DMA enhancements? Or are there any other unreleased patches that can help?

    By the way, do new kernel releases support both PG2.0 and older one too? How silicon revision is handled: at kernel compile time or at run time? Is there any patch to optimize PG2.0-only usage?

    Thanks. Regards,

    Max

  • Max,


    I don't think the application splitting the USB request to 512-byte chunks should cause any issue other than probably higher IRQ load. One quick way to check the IRQ load is using 'top' command, it is listed on the top of the output.

    The latest PSP release .09-rc2 (integrated in SDK 5.6.0.0) does have some DMA patches to workaround h/w issues. But I cannot think of any related to this issue.

    As I requested via another channel, if you could create a test case on AM335x EVM to replicate the issue, we will investigate it.

    Yes, the PSP .09-rc2 supports both PG2.0 and 1.0 at run time by checking the silicon revision register. But I am not aware of any patch to optimize for PG2.0 only.

    Regards,

    -Bin.