2008-10-01 12:08:17

by Christoph Lameter

[permalink] [raw]
Subject: Re: wrong usage of MAX_DMA_ADDRESS in bootmem.h

Russell King - ARM Linux wrote:

> Not correct. MAX_DMA_ADDRESS is a virtual address. ISA_DMA_THRESHOLD
> is the last byte of _physical_ memory which ISA DMA can transfer:

> include/asm-x86/scatterlist.h:#define ISA_DMA_THRESHOLD (0x00ffffff)
>
> So what you've just suggested is completely insane.

Someone screwed around with the basics here. MAX_DMA_ADDRESS is no longer
related to MAX_DMA_PFN for the x86_32 case. What is the point of relating
MAX_DMA_ADDRESS to PAGE_OFFSET? Looks like we are creating more confusion
about the strange DMA zone.

The best would be to rename these variables to make the semantics clearer

ZONE_DMA related variables:

MAX_DMA_PFN -> MAX_ZONE_DMA_PFN
MAX_DMA_ADDRESS -> MAX_ZONE_DMA_ADDRESS

MAX_DMA32_PFN -> MAX_ZONE_DMA32_PFN
MAX_DMA32_ADDRESS -> MAX_ZONE_DMA32_ADDRESS

Then the general DMAability

MAX_DMA_ADDRESS -> DMA_LIMIT


> Incorrect. MAX_DMA_ADDRESS is the highest possible virtual DMA address:

MAX_DMA_ADDRESS is the highest possible address for the DMA zone. Not the
highest possible address that any DMA controller can use. And now we have
special casing that makes the semantics different between 32 bit and 64 bit
x86? Insane! Please clean up the fuzzy semantics.

> include/asm-x86/dma.h:#define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x1000000)
>
> Think about what that means on an x86 machine with less than 16MB of RAM.

> As we have already covered in the past, CONFIG_ZONE_DMA has to always
> be enabled on ARM because ARM always puts all memory in the first zone.
> To do otherwise introduces lots of special cases, and I steadfastly
> refuse to make the memory initialisation any more complicated than it
> already is.

I believe we have been over this. If you just have one zone then the core code
would expect you to disable CONFIG_ZONE_DMA and have all memory treated equal
in ZONE_NORMAL.

The naming seems to be the problem here. Maybe renaming ZONE_DMA to
ZONE_RESTRICTED_DMA or something would help. We are currently creating two
different paradigms of using these constants.



2008-10-01 14:07:09

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: wrong usage of MAX_DMA_ADDRESS in bootmem.h

On Wed, Oct 01, 2008 at 07:07:42AM -0500, Christoph Lameter wrote:
> Russell King - ARM Linux wrote:
>
> > Not correct. MAX_DMA_ADDRESS is a virtual address. ISA_DMA_THRESHOLD
> > is the last byte of _physical_ memory which ISA DMA can transfer:
>
> > include/asm-x86/scatterlist.h:#define ISA_DMA_THRESHOLD (0x00ffffff)
> >
> > So what you've just suggested is completely insane.
>
> Someone screwed around with the basics here. MAX_DMA_ADDRESS is no longer
> related to MAX_DMA_PFN for the x86_32 case. What is the point of relating
> MAX_DMA_ADDRESS to PAGE_OFFSET? Looks like we are creating more confusion
> about the strange DMA zone.

Because it is a virtual address. It has to be. You're using __pa() on it,
and __pa() ONLY takes a virtual address.

> The best would be to rename these variables to make the semantics clearer
>
> ZONE_DMA related variables:
>
> MAX_DMA_PFN -> MAX_ZONE_DMA_PFN
> MAX_DMA_ADDRESS -> MAX_ZONE_DMA_ADDRESS
>
> MAX_DMA32_PFN -> MAX_ZONE_DMA32_PFN
> MAX_DMA32_ADDRESS -> MAX_ZONE_DMA32_ADDRESS
>
> Then the general DMAability
>
> MAX_DMA_ADDRESS -> DMA_LIMIT

That's no clearer. Are they physical addresses? Or are they virtual
addresses? Can't guess that from the names.

> > Incorrect. MAX_DMA_ADDRESS is the highest possible virtual DMA address:
>
> MAX_DMA_ADDRESS is the highest possible address for the DMA zone. Not the
> highest possible address that any DMA controller can use.

Semantically disagree.

If you only have a controller which can address 1MB of memory (yes, they do
exist) then MAX_DMA_ADDRESS must be PAGE_OFFSET + 1MB, otherwise you have
precisely NO way to obtain memory from the kernel for this DMA controller
- and that means you want the DMA zone to be sized to 1MB. So _indirectly_
it's true that MAX_DMA_ADDRESS is the highest possible address for the DMA
zone.

2008-10-01 14:50:55

by Christoph Lameter

[permalink] [raw]
Subject: Re: wrong usage of MAX_DMA_ADDRESS in bootmem.h

Russell King - ARM Linux wrote:

>> Someone screwed around with the basics here. MAX_DMA_ADDRESS is no longer
>> related to MAX_DMA_PFN for the x86_32 case. What is the point of relating
>> MAX_DMA_ADDRESS to PAGE_OFFSET? Looks like we are creating more confusion
>> about the strange DMA zone.
>
> Because it is a virtual address. It has to be. You're using __pa() on it,
> and __pa() ONLY takes a virtual address.

Ok. I agree you need to add a __va to it in order to convert it back later.
That was not really the point. MAX_DMA_PFN can be used as a base to calculate
MAX_DMA_ADDRESS. Both are related and currently some arches go one way and
other do vice versa. Its particularly strange that x86_32 and x86_64 go
different ways. Can we unify that to one way only and put the definition of
MAX_DMA_ADDRESS in core code?

Also as a result of the long type used for a kernel "virtual" address we have
the strange situation that all uses of MAX_DMA_ADDRESS require a cast.

>> The best would be to rename these variables to make the semantics clearer
>>
>> ZONE_DMA related variables:
>>
>> MAX_DMA_PFN -> MAX_ZONE_DMA_PFN
>> MAX_DMA_ADDRESS -> MAX_ZONE_DMA_ADDRESS
>>
>> MAX_DMA32_PFN -> MAX_ZONE_DMA32_PFN
>> MAX_DMA32_ADDRESS -> MAX_ZONE_DMA32_ADDRESS
>>
>> Then the general DMAability
>>
>> MAX_DMA_ADDRESS -> DMA_LIMIT
>
> That's no clearer. Are they physical addresses? Or are they virtual
> addresses? Can't guess that from the names.

It is clearer because the association with ZONE_DMA is in the name now. One no
longer has the impression that MAX_DMA_ADDRESS is upper bound of any DMA
transfer in the system.

Maybe we should make these physical addresses to avoid the casts? That would
avoid casts in the bootmem allocator etc etc.

2008-10-01 15:03:24

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: wrong usage of MAX_DMA_ADDRESS in bootmem.h

On Wed, Oct 01, 2008 at 09:50:24AM -0500, Christoph Lameter wrote:
> Russell King - ARM Linux wrote:
> >> The best would be to rename these variables to make the semantics clearer
> >>
> >> ZONE_DMA related variables:
> >>
> >> MAX_DMA_PFN -> MAX_ZONE_DMA_PFN
> >> MAX_DMA_ADDRESS -> MAX_ZONE_DMA_ADDRESS
> >>
> >> MAX_DMA32_PFN -> MAX_ZONE_DMA32_PFN
> >> MAX_DMA32_ADDRESS -> MAX_ZONE_DMA32_ADDRESS
> >>
> >> Then the general DMAability
> >>
> >> MAX_DMA_ADDRESS -> DMA_LIMIT
> >
> > That's no clearer. Are they physical addresses? Or are they virtual
> > addresses? Can't guess that from the names.
>
> It is clearer because the association with ZONE_DMA is in the name now.
> One no longer has the impression that MAX_DMA_ADDRESS is upper bound of
> any DMA transfer in the system.

... so you didn't get my point.

> Maybe we should make these physical addresses to avoid the casts?

Finally, we agree on something. Yes, they should be phys addresses.
But not for the sake of getting rid of casts, but because that's what
the bootmem allocator _actually_ wants to have in the first place.

And, to do this, the following are going to have to be changed:

drivers/block/floppy.c: } else if ((unsigned long)current_req->buffer < MAX_DMA_ADDRESS) {
drivers/block/floppy.c: * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide
drivers/block/floppy.c: (MAX_DMA_ADDRESS -
drivers/net/3c505.c: if ((unsigned long)(target + rlen) >= MAX_DMA_ADDRESS) {
drivers/net/3c505.c: if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS || nlen != skb->len) {
drivers/net/cs89x0.c: if ((unsigned long) lp->dma_buff >= MAX_DMA_ADDRESS ||
drivers/net/wan/cosa.c: if (b+len >= MAX_DMA_ADDRESS)
drivers/parport/parport_pc.c: if (end < MAX_DMA_ADDRESS) {
drivers/scsi/BusLogic.c: if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus && (void *) high_memory > (void *)
drivers/scsi/BusLogic.c: if (HostAdapter->BIOS_Address > 0 && strcmp(HostAdapter->ModelName, "BT-445S") == 0 && strc
sound/oss/dmabuf.c: || end_addr >= (char *) (MAX_DMA_ADDRESS)) {
sound/oss/sscape.c: || end_addr >= (char *) (MAX_DMA_ADDRESS)) {

which probably want to do the check in the phys address space anyway.

2008-10-02 16:49:44

by Christoph Lameter

[permalink] [raw]
Subject: Re: wrong usage of MAX_DMA_ADDRESS in bootmem.h

Russell King - ARM Linux wrote:

>> Maybe we should make these physical addresses to avoid the casts?
>
> Finally, we agree on something. Yes, they should be phys addresses.
> But not for the sake of getting rid of casts, but because that's what
> the bootmem allocator _actually_ wants to have in the first place.
>
> And, to do this, the following are going to have to be changed:
>
> drivers/block/floppy.c: } else if ((unsigned long)current_req->buffer < MAX_DMA_ADDRESS) {
> drivers/block/floppy.c: * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide
> drivers/block/floppy.c: (MAX_DMA_ADDRESS -
> drivers/net/3c505.c: if ((unsigned long)(target + rlen) >= MAX_DMA_ADDRESS) {
> drivers/net/3c505.c: if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS || nlen != skb->len) {
> drivers/net/cs89x0.c: if ((unsigned long) lp->dma_buff >= MAX_DMA_ADDRESS ||
> drivers/net/wan/cosa.c: if (b+len >= MAX_DMA_ADDRESS)
> drivers/parport/parport_pc.c: if (end < MAX_DMA_ADDRESS) {
> drivers/scsi/BusLogic.c: if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus && (void *) high_memory > (void *)
> drivers/scsi/BusLogic.c: if (HostAdapter->BIOS_Address > 0 && strcmp(HostAdapter->ModelName, "BT-445S") == 0 && strc
> sound/oss/dmabuf.c: || end_addr >= (char *) (MAX_DMA_ADDRESS)) {
> sound/oss/sscape.c: || end_addr >= (char *) (MAX_DMA_ADDRESS)) {
>
> which probably want to do the check in the phys address space anyway.

Right. Lets do it. MAX_DMA32 needs to be changed too.

While you are at it: Could you make the association with the zones clearer?

MAX_ZONE_DMA32_ADDRESS MAX_ZONE_DMA_ADDRESS, MAX_ZONE_DMA_PFN,
MAX_ZONE_DMA32_PFN ....

2008-10-02 19:07:30

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: wrong usage of MAX_DMA_ADDRESS in bootmem.h

On Thu, Oct 02, 2008 at 11:49:09AM -0500, Christoph Lameter wrote:
> Right. Lets do it. MAX_DMA32 needs to be changed too.
>
> While you are at it: Could you make the association with the zones clearer?
>
> MAX_ZONE_DMA32_ADDRESS MAX_ZONE_DMA_ADDRESS, MAX_ZONE_DMA_PFN,
> MAX_ZONE_DMA32_PFN ....

If you want me to do it, expect it in about 6 to 12 months time.