On Friday 17 June 2011, Michael Hope wrote:
Hi Paolo. I've had a look into this and updated the ticket. The problem is due to a change in behaviour between 4.5 and 4.6 when accessing strcuts marked with __attribute__((packed)). 4.5 would do a word-wise access where 4.6 assumes the worst and does a byte-by-byte access.
There was a discussion on the GCC list: http://gcc.gnu.org/ml/gcc/2011-02/msg00035.html
which petered out unfortunately. IMO the compiler is working correctly and the problem should be fixed in the kernel initially and then a long term plan worked out between the kernel and compiler.
Arnd, do you want to pick up that thread? Both Ubuntu and Debian are now 4.6 based so this problem will come up more often. I think Patrik said there's a fix for this specific problem pending.
I fear Russell will not like this too much, but I guess it has to be done. It will also come back to the toolchain team as a request to make the inline assembly syntax more helpful. When we last talked about it on the mailing list, the reason that was given for having writel() not do an inline assembly to access I/O memory was that we cannot express all possible addressing modes well.
The function in question is
#define __raw_writel(v,a) (*(volatile unsigned int __force *)(a) = (v))
AFAICT, this should really be written as
static inline void __raw_writel(unsigned int v, volatile __iomem unsigned int *a) { asm volatile("str %0, %1" : "=o" (*a) : "r" (v) : "memory"); }
What I don't know is whether this form is ideal in all cases (or even correct), and what the constraints should be. If I understood Uli correctly, it should be possible to express this with gcc syntax, but of course there may be a catch somewhere.
We need all six forms of this function, for read/write and 8/16/32 bit accesses.
Arnd