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 Wed, Jul 13, 2011 at 01:38:26PM -0400, Alan Stern wrote:
> 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.

Yes, that's true.

> 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!

Fair enough. :)  I guess you could say it's the worst case for the
behavior we expect from this particular xHCI scheduler.

> 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.

Ah, you're right.  If we've wrapped around the list, smaller_ep will
point to the last endpoint in the list, and list_add_tail will add the
new endpoint in the second-to-last position.  Nice catch!

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

Really?  I always feel a bit clumsy with the list structures, so I may
be wrong, but it seems like we would potentially be dereferencing memory
we don't own.

If the list is empty, interval_bw->endpoints->next will point to the
struct list_head in struct xhci_interval_bw.  But we would pass
containerof the type struct xhci_virt_ep, so we'd have a pointer to an
xhci_virt_ep that would be somewhere far away from the struct
xhci_interval_bw, since the xhci_virt_ep structure is much bigger.  Then
the conditional part of the for loop in list_for_each_entry would
calculate &smaller_ep->bw_endpoint_list.  Won't the kernel complain when
the bogus address is dereferenced?  Or is it just pointer math, so the
bogus smaller_ep address won't actually be dereferenced?

Sarah
--
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