Re: New resources - pls, explain :-(

Linus Torvalds (torvalds@transmeta.com)
Thu, 12 Aug 1999 14:18:31 -0700 (PDT)


On 12 Aug 1999, Jes Sorensen wrote:
>
> Having a readl_na() would make sense on big endian machines with PCI
> busses since since some PCI cards (some gfx and network cards) will do
> the translation for you in hardware making it look like the card is
> native byte order. For 16 and 24 bit graphics for instance it is
> absolutely not fun doing the byte swapping in software.

But the point is _still_ that the driver needs to know. The driver needs
to know which area to select, and in some cases the driver needs to put
the card in the right endianness mode.

In short, I have not heard a SINGLE argument for this being a generic
feature. I _have_ heard tons of valid argument for fixing on a known
byte-order, and I agree with them. And it's very obvious that little-
endian is THE byteorder, nobody really even argues about that.

In short, I still don't see why not just have a "bigendian_writel()" is so
hard to accept for people. The the drivers that know about the issue might
do something like this:

/*
* On big-endian machines we map the byte-swapped data
* area in order to use native byte order for performance
*/
#ifdef BIG_ENDIAN
#define gfx_readl(x) bigendian_readl(x)
#define gfx_writel(x,y) bigendian_writel(x,y)
#else
#define gfx_readl(x) readl(x)
#define gfx_writel(x,y) writel(x,y)
#endif

...

init_card(...)
{

/* memory map 3 is BE, memory map 2 is LE */
#ifdef BIG_ENDIAN
base = dev->resource[3].start;
size = dev->resource[3].size;
#else
base = dev->resource[2].start;
size = dev->resource[2].size;
#endif
baseptr = ioremap(base, size);
...

But note how it would NOT really have made any sense to have a "generic"
don't-swap, because that is not a generic problem.

> I do not disagree with your vme_readl() proposal. Well it would be
> nice if one could have a readl() that works for everybody but if one
> wants to support 256 PCI busses in a box it might be a little
> problematic.

Well, if it were just a case of the same type of bus, it probably wouldn't
be too bad. They'd be mapped at different offsets, but that can be handled
by ioremap() and friends. The trouble really starts when you have
different kinds of buses that have different rules for how they can be
accessed because of different coherency issues or similar (or different
ways to handle non-existent addresses - you may end up having to use
different address spaces for different buses).

That's why it is so much easier if the programmer explicitly states some
extra information - on some hardware the things may end up being collapsed
to the same case, but on other hardware there may be special rules for one
of them.

For example, I've considered maybe having two kinds of "writel()" - one
that does a synchronous write and does an implied write barrier, and one
that says "I don't care if this write gets re-ordered with respect to
other writes". On x86, the two are one and the same thing, because the
MTRR's (or the page table bits) handle the difference in hardware. On
other architectures they can end up being quite different, and have quite
different performance characteristics. And it would be bad if "writel()"
had to try to figure out the information by hand, when a programmer could
just tell it what kind of access he was thinking of..

The same is true of other differences between accesses - it doesn't make
sense to try to have _one_ function that magically does the right thing
for all different buses, when the programmer is basically guaranteed to
trivially know which kind of bus he's accessing (and I'd like to make
clear that I consider PCI/ISA/MCA/HPPCI etc to be basically the same bus).

Linus

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/