[RFC] dove: fix __io() definition to use bus based offset
Russell King - ARM Linux
linux at arm.linux.org.uk
Sat Jul 31 16:47:27 EDT 2010
On Sat, Jul 31, 2010 at 09:21:40PM +0200, Arnd Bergmann wrote:
> On Saturday 31 July 2010 13:08:02 Russell King - ARM Linux wrote:
> > On Thu, Jul 29, 2010 at 01:45:35PM +0800, Eric Miao wrote:
> > > diff --git a/arch/arm/mach-dove/include/mach/io.h
> > > b/arch/arm/mach-dove/include/mach/io.h
> > > index 3b3e472..067435e 100644
> > > --- a/arch/arm/mach-dove/include/mach/io.h
> > > +++ b/arch/arm/mach-dove/include/mach/io.h
> > > @@ -11,10 +11,9 @@
> > >
> > > #include "dove.h"
> > >
> > > -#define IO_SPACE_LIMIT 0xffffffff
> > > -
> > > -#define __io(a) ((void __iomem *)(((a) - DOVE_PCIE0_IO_PHYS_BASE) +\
> > > - DOVE_PCIE0_IO_VIRT_BASE))
> > > -#define __mem_pci(a) (a)
> > > +#define IO_SPACE_LIMIT 0xffffffff
> > > +#define __io(a) __typesafe_io((a) - DOVE_PCIE0_IO_BUS_BASE + \
> > > + DOVE_PCIE0_IO_VIRT_BASE)
> >
> > I recommend against this use of __typesafe_io():
> >
> > http://lists.arm.linux.org.uk/lurker/message/20090214.154245.6325bc9d.en.html
> >
>
> On a related note, is there a particular reason why most of the
> *_*_VIRT_BASE macros are just numbers instead of void __iomem
> pointers?
Let me expand a little, and then I'll answer your question.
As already covered, __io() is the macro to enable the PC-like IO port
macros, and if there's a simple 1:1 mapping, defining it to be the
__typesafe_io() function is what's required. __typesafe_io() should
not appear anywhere else, and as I've said in the URL above, it
shouldn't be aliased to __io() with offsets. So I wouldn't want to
see stuff using __io() nor __typesafe_io() for other stuff (such as
_VIRT_BASE macros.)
Now, when it comes to _VIRT_BASE macros, they tend to end up being
used not only in C code, but also assembly. In C, it's useful to
have virtual addresses typed correctly - which as you say are void
__iomem pointers. When it comes to assembly, to avoid defining a
set of additional pointers, I've suggested in the past to do this:
#ifndef __ASSEMBLY__
#define IOMEM(x) ((void __iomem __force *)(x))
#else
#define IOMEM(x) (x)
#endif
#define FOO_VIRT_BASE IOMEM(0xfeedface)
which gives us the behaviour we desire. I'd ideally like IOMEM() to
be in some generic header, but I don't think asm/io.h makes much sense
for that - neither does creating a new header just for it. What do
other architectures do for accessing system device registers (excluding
x86 which of course uses ISA IO macros)? I wonder if somewhere under
linux/ would be appropriate for it.
There is one place in our architecture code where this goes wrong, and
that's the static map structures (struct map_desc) where the virtual
address is an unsigned long - this is because the underlying code really
wants it as a number and not a pointer (it wants to do stuff with page
tables.) Converting this to a pointer results in casts-to-pointers
appearing elsewhere in the code, so you can't win on that.
However, for the vast majority of definitions (being registers) then
defining them to be void __iomem pointer like is definitely the right
thing.
I've toyed in the past with making the IO macros have tigher type-
checking, but I've found each time I've tried it that it causes gcc
to become less efficient with code generation, resulting in larger
kernels.
If someone can come up with a script or put the work into fixing the
integer-likeness of some of the _VIRT_BASE stuff and create a set of
reasonable patches, I'm personally all for it.
More information about the linux-arm-kernel
mailing list