Re: [RFC 8/9] xhci: Track interval bandwidth tables per port/TT.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 7 Jul 2011, Sarah Sharp wrote:

> In order to update the root port or TT's bandwidth interval table, we will
> need to keep track of a list of endpoints, per interval.  That way we can
> easily know the new largest max packet size when we have to remove an
> endpoint.

Okay.  I haven't read through these patches in exhaustive detail, but 
at least I now understand how the bandwidth-tracking algorithm works.  
As you say, it is rather pessimistic.  For example, it would fail when 
given:

	two endpoints of period 2, each requiring 35% of the available
	periodic bandwidth, and

	one endpoint of period 4, requiring 70% of the available
	bandwidth,

even though this could be handled easily enough by scheduling the first 
two endpoints in the same uframe.

However, I'm not sure that describing this as a "worst-case" algorithm 
is really correct.  If you want to be pedantic, worst-case scheduling 
means trying to cram every transaction into the same uframe!

Regardless, it seems basically okay.  I didn't spend much time looking 
for mistakes in the code, but one thing caught my eye:

> +static void xhci_add_ep_to_interval_table(struct xhci_hcd *xhci,
> +		struct xhci_bw_info *ep_bw,
> +		struct xhci_interval_bw_table *bw_table,
> +		struct usb_device *udev,
> +		struct xhci_virt_ep *virt_ep,
> +		struct xhci_tt_bw_info *tt_info)
> +{

...

> +	/* Insert the endpoint into the list, largest max packet size first. */
> +	if (list_empty(&interval_bw->endpoints))
> +		list_add(&virt_ep->bw_endpoint_list, &interval_bw->endpoints);
> +	else {
> +		struct xhci_virt_ep *smaller_ep;
> +
> +		list_for_each(ep_list_entry, &interval_bw->endpoints) {
> +			smaller_ep = list_entry(ep_list_entry,
> +					struct xhci_virt_ep, bw_endpoint_list);
> +			if (ep_bw->max_packet_size >=
> +					smaller_ep->bw_info.max_packet_size) {
> +				break;
> +			}
> +		}
> +		/* If we have looped through the list, ep_list_entry will point
> +		 * to the head of the list, and list_add_tail will put the new
> +		 * entry at the end of the list (before the head entry).
> +		 * Otherwise, we'll add this endpoint in the list before the
> +		 * endpoint with the smaller max packet size.
> +		 */
> +		list_add_tail(&virt_ep->bw_endpoint_list,
> +				&smaller_ep->bw_endpoint_list);
> +	}

Despite the lengthy comment, the logic is wrong.  I'll leave it as an 
exercise for you to figure out why.  Here are two hints:

	The comment talks about ep_list_entry, but the following line
	of code uses smaller_ep instead.

	If the loop used list_for_each_entry() then the initial "if"
	statement wouldn't be needed.

Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux