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.

Linux/AM3358: MUSB driver and endpoint usage

Part Number: AM3358

Tool/software: Linux


We have a large number of serial over usb devices that our host software needs to actively communicate with. We are using an AM3358 and are on TISDK version 05.00.00.15.

The USB device tree is as follows:
/: Bus 01.Port 1: Dev 1, class="root_hub", Driver=musb-hdrc/1p, 480M
    |__ Port 1: Dev 2, If 0, class="Hub", Driver=hub/7p, 480M
        |__ Port 1: Dev 8, If 0, class="Hub", Driver=hub/2p, 12M
            |__ Port 2: Dev 10, If 1, class="CDC" Data, Driver=cdc_acm, 12M
            |__ Port 2: Dev 10, If 0, class="Communications", Driver=cdc_acm, 12M
            |__ Port 1: Dev 9, If 0, class="Communications", Driver=cdc_acm, 12M
            |__ Port 1: Dev 9, If 1, class="CDC" Data, Driver=cdc_acm, 12M
        |__ Port 2: Dev 5, If 0, class="Hub", Driver=hub/2p, 480M
            |__ Port 1: Dev 6, If 1, class="CDC" Data, Driver=cdc_ether, 480M
            |__ Port 1: Dev 6, If 0, class="Communications", Driver=cdc_ether, 480M
            |__ Port 2: Dev 11, If 0, class="Communications", Driver=cdc_acm, 12M
            |__ Port 2: Dev 11, If 1, class="CDC" Data, Driver=cdc_acm, 12M
        |__ Port 4: Dev 7, If 1, class="CDC" Data, Driver=cdc_acm, 480M
        |__ Port 4: Dev 7, If 0, class="Communications", Driver=cdc_acm, 480M
        |__ Port 5: Dev 13, If 0, class="Hub", Driver=hub/4p, 480M
            |__ Port 4: Dev 14, If 0, class="Communications", Driver=cdc_acm, 12M
            |__ Port 4: Dev 14, If 1, class="CDC" Data, Driver=cdc_acm, 12M
        |__ Port 6: Dev 12, If 0, class="Communications", Driver=cdc_acm, 12M
        |__ Port 6: Dev 12, If 1, class="CDC" Data, Driver=cdc_acm, 12M

From reading the USB descriptors, all these devices require 1 Interrupt EP IN, 1 Bulk EP IN, and 1 Bulk EP OUT.

When trying to open each ACM device one at a time, I hit a wall on the last device and the following error appears in dmesg.

    [ 815.079232] musb-hdrc musb-hdrc.1: int hwep alloc failed for 1x64
    [ 815.079232] musb-hdrc musb-hdrc.1: int[ 815.090737] cdc_acm 1-1.1.1:1.0: acm_port_activate - usb_submit_urb(ctrl irq) failed hwep alloc failed for 1x64

    [ 815.090737] cdc_acm 1-1.1.1:1.0: acm_port_activate - usb_submit_urb(ctrl irq) failed

I've read through some of the past forum posts about device quantity limits specific to interrupt endpoints. Since I need two EP IN per device, the endpoints into the host are my limiting factor.

Counting my EP INs, I see:
4 Hubs
1 ECM Device
6 ACM Devices

It looks like the EPs for the ACM devices are allocated when the device is opened from user space. The ECM device's EP is allocated when it connects (in my case during startup).

Reading throught the driver it seems to indicate that there will be multiplexing of bulk endpoints on EP1 once all other available endpoints are exhausted, so I don't quite understand why I hit the limit when I do.

Assuming EP0 is reserved for control, that leaves 3 potential EPs for dedicated bulk transfers plus EP1 for multiplexing the rest.

Am I missing something fundamental here?

  • Hi,

    EP1 multiplexing is only used when no endpoint available, otherwise a free endpoint will be allocated for bulk transfers. Please check if the following assumption explains the problem:

    - Before any usb device is attached, EP2~EP15 IN endpoints available;

    - Attached 4 hubs, each one takes one interrupt endpoint, assuming EP2~EP5, now EP6~EP15 are available;

    - Attach and open 1 ECM, takine two endpoints, assuming EP6 & 7, now EP8~EP15 are available, total are 8 endpoints left;

    - Now if attach and open 4 more ACM, which will take 8 endpoints, then there no more IN endpoints available, but you still have two more ACM devices to attach.

  • Apologies. Your assumptions above are correct. I hit the error when attempting to open the 5th ACM, not the 6th.
  • Hi,

    No worries. Glad the issue is clear now.
  • I still have questions, though. There is logic in the driver to use that free endpoint (EP1) to multiplex bulk transfers when we have exhausted available endpoints, correct? Does that logic function?

    If there was an available EP IN for the Interrupt when opening the 5th ACM would that then allow data transfers from the device?

    Is it feasible to modify the driver to reserve enough endpoints for my configuration and multiplex the bulk transfers on EP1?

    Is that type of scheduling possible?
  • Hi,

    Yes, the EP1 multiplexing logic works. If endpoints run out, new bulk endpoint request will be assigned to EP1.

    Please test the kernel patch below, it changes the endpoint scheduling and assigns all bulk transfers to EP1, so you will have enough endpoints for you interrupt endpoint use case. Please note that the bulk transfer performance might not be good due to the multiplexing, I didn't test this case before.

    diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
    index b59ce9ad14ce..8a01ed5cae44 100644
    --- a/drivers/usb/musb/musb_host.c
    +++ b/drivers/usb/musb/musb_host.c
    @@ -2050,6 +2050,27 @@ static int musb_schedule(
     	best_diff = 4096;
     	best_end = -1;
     
    +	/* use bulk reserved ep1 */
    +	if (qh->type == USB_ENDPOINT_XFER_BULK) {
    +		hw_ep = musb->bulk_ep;
    +		if (is_in)
    +			head = &musb->in_bulk;
    +		else
    +			head = &musb->out_bulk;
    +
    +		/* Enable bulk RX/TX NAK timeout scheme when bulk requests are
    +		 * multiplexed. This scheme does not work in high speed to full
    +		 * speed scenario as NAK interrupts are not coming from a
    +		 * full speed device connected to a high speed device.
    +		 * NAK timeout interval is 8 (128 uframe or 16ms) for HS and
    +		 * 4 (8 frame or 8ms) for FS device.
    +		 */
    +		if (qh->dev)
    +			qh->intv_reg =
    +				(USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4;
    +		goto success;
    +	}
    +
     	for (epnum = 1, hw_ep = musb->endpoints + 1;
     			epnum < musb->nr_endpoints;
     			epnum++, hw_ep++) {
    @@ -2093,26 +2114,8 @@ static int musb_schedule(
     			best_end = epnum;
     		}
     	}
    -	/* use bulk reserved ep1 if no other ep is free */
    -	if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) {
    -		hw_ep = musb->bulk_ep;
    -		if (is_in)
    -			head = &musb->in_bulk;
    -		else
    -			head = &musb->out_bulk;
     
    -		/* Enable bulk RX/TX NAK timeout scheme when bulk requests are
    -		 * multiplexed. This scheme does not work in high speed to full
    -		 * speed scenario as NAK interrupts are not coming from a
    -		 * full speed device connected to a high speed device.
    -		 * NAK timeout interval is 8 (128 uframe or 16ms) for HS and
    -		 * 4 (8 frame or 8ms) for FS device.
    -		 */
    -		if (qh->dev)
    -			qh->intv_reg =
    -				(USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4;
    -		goto success;
    -	} else if (best_end < 0) {
    +	if (best_end < 0) {
     		dev_err(musb->controller,
     				"%s hwep alloc failed for %dx%d\n",
     				musb_ep_xfertype_string(qh->type),
    

  • I tested your patch and this gets me a lot closer.

    I did notice, however, that if the EP_OUT endpoints are multiplexed I run into problems.  When I start reading data off the ACM device, the ECM device appears to be starved.  I modified your patch to only apply to BULK EP_IN and then things begin to function.  I do see the performance hit you mention.  I see latency spikes in the 15-20ms range.

    When I attempt to include a Full Speed ACM device, though, things break down.  It appears the NAK timeout logic no longer fires and that devices holds on to EP 1 until I stop my reader.

    I see in the comments the following.

    /* Enable bulk RX/TX NAK timeout scheme when bulk requests are
    * multiplexed. This scheme does not work in high speed to full
    * speed scenario as NAK interrupts are not coming from a
    * full speed device connected to a high speed device.
    * NAK timeout interval is 8 (128 uframe or 16ms) for HS and
    * 4 (8 frame or 8ms) for FS device.
    */

    Is my suspicion correct that this limitation is what is causing my issue with Full Speed?

    Any chance there is another way to trigger a timeout so the other devices get a chance to transfer data?

  • Hi Frank,

    It does sound you run into that NAK timeout limitation. But I am not aware of any other workaround for it.

    The Bulk EP1 multiplexing logic implemented in the driver has not been validated at all by TI, so I don't recommend to use it at all. It seems the issue in your use case is only short for a few endpoints, I recommend you use both USB controllers on AM335x and spread all your usb devices evenly on both controllers to avoid this endpoint limitation. Trying to modify the kernel driver for a invalidated function is not a good idea I think.