Re: [RFC 06/15] xhci: Setup array of USB 2.0 and USB 3.0 ports.

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

 



On Mon, Dec 13, 2010 at 04:23:39PM +0800, Xu, Andiry wrote:
> > + * Scan the Extended Capabilities for the "Supported Protocol
> > Capabilities" that
> > + * specify what speeds each port is supposed to be.  We can't count
> on
> > the port
> > + * speed bits in the PORTSC register being correct until a device is
> > connected,
> > + * but we need to set up the two fake roothubs with the correct
> number of
> > USB
> > + * 3.0 and USB 2.0 ports at host controller initialization time.
> > + */
> > +static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
> > +{
> > +	u32 __iomem *addr;
> > +	u32 offset;
> > +	unsigned int num_ports;
> > +	int i, port_index;
> > +
> > +	addr = &xhci->cap_regs->hcc_params;
> > +	offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr));
> 
> From xHCI spec, the offset read here should be multiple by 4 and add to
> the address base.
> 
> > +	if (offset == 0) {
> > +		xhci_err(xhci, "No Extended Capability registers, "
> > +				"unable to set up roothub.\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
> > +	xhci->port_array = kzalloc(sizeof(*xhci->port_array)*num_ports,
> > flags);
> > +	if (!xhci->port_array)
> > +		return -ENOMEM;
> > +
> > +	/*
> > +	 * For whatever reason, the first capability offset is from the
> > +	 * capability register base, not from the HCCPARAMS register.
> > +	 * See section 5.3.6 for offset calculation.
> > +	 */
> > +	addr = &xhci->cap_regs->hc_capbase + offset;
> 
> So maybe here should be offset << 2?

I believe the pointer math is correct.  Section 5.3.6 of the xHCI 0.96
spec says:

"The value of this field indicates a relative offset, in 32-bit words,
from Base to the beginning of the first extended capability."

We extract that value and add it to the base register offset.  The spec
does have a math example, where the offset is multiplied by four.
However, addr is a pointer to a u32.  Adding 1 to that pointer will move
the pointer to point to one u32 ahead of the current pointer.  So the
multiply by 4 is implied because the compiler automatically multiplies
the offset by the size of what the pointer points to.  If addr were a
pointer to a byte (u8) instead of a pointer to a 4-byte word (u32),
then, yes, we would need to multiply by 4.

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