Re: EHCI: Definitions of HC_LENGTH and HC_VERSION

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

 



On Fri, 22 Jan 2010, Jan Andersson wrote:

> > Why is this a problem?  With the exception of some old code in 
> > ehci-au1xxx.c, this register is always read via ehci_readl(), which 
> > automatically takes the endianness into account.
> > 
> 
> Yes, and EHCI readl() works for the other registers that are defined as 
> 32-bit and should be read with DWORD accesses only. However here we have 
> the case where CAPLENGTH is specified to be at byte offset 0 (as opposed 
> to a bit position within a 32-bit word). On a big endian system byte 0 
> is 31:24 in a 32-bit word and on a little endian system it is 7:0 (in a 
> 32-bit word).
> 
> For the big endian version of the host controller I need to set 
> ehci->big_endian_mmio to 1 so that the reads and writes to registers are 
> not byte swapped by software (I run on SPARC that is big endian). 
> ehci_readl will then call readl_be() that will return a 32 bit word 
> organized as CAPLENGTH : RESERVED : HCIVERSION.
> 
> Since CAPLENGTH is defined to be a 8-bit register at offset base + 0x0 
> this is the expected position of that register (on a big endian system) 
> when doing a 32-bit read access. But it does not match with the 
> definition of HC_LENGTH(p).
> 
> This issue would not have come up if CAPLENGTH and HCIVERSION were 
> specified as members of a 32-bit register (as most of the other 
> registers are). If you do not agree with me think of the case where 
> CAPLENGTH, as specified, is read out using a byte access. The 
> specification says that it is located at offset 0. Should a 32-bit read 
> on a big endian system return CAPLENGTH on any other position that 31:24 
> on a 32-bit read to offset 0 then that byte will not be located at the 
> specified address.

So change the places that compute HC_VERSION and HC_LENGTH.  Instead of 
doing

	HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase))

make them do

	HC_VERSION(le32_to_cpu(readl(&ehci->caps->hc_capbase)));

and similarly for HC_LENGTH.  That'll do what you want, won't it?  
Apart from bus glue, these things occur only once in ehci-dbg.c and 
ehci-hcd.c.

Include a comment explaining that ehci_readl() can't be used here 
because the register is defined in terms of byte offsets rather than as 
a 32-bit word.

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