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