enhancement to virt_to_bus/bus_to_virt (resent with spell-checked subject line)
PATCH 1/1 enhancement to virt_to_bus/bus_to_virt (resent with spell-checked subject line)
In 2.6.9 on non-APUS ppc32 platforms, virt_to_bus() will just subtract KERNELBASE from the the virtual address. bus_to_virt() will perform the reverse operation.
This patch will make virt_to_bus():
- perform the current operation if the virtual address is between KERNELBASE and ioremap_bot.
- use iopa() (as on APUS platform) otherwise.
The patch will make bus_to_virt():
- perform the current operation if the bus address is between PCI_DRAM_OFFSET and (ioremap_bot - KERNELBASE + PCI_DRAM_OFFSET).
- use mm_ptov() (as on APUS platform) otherwise.
The patch also changes virt_to_phys()/phys_to_virt() in a similar way.
Signature · 87 lines
Linh Dang
--- include/asm-ppc/io.h~2.6.9 2004-11-12 14:24:46.000000000 -0500
+++ include/asm-ppc/io.h 2004-12-02 09:42:32.000000000 -0500
@@ -6,10 +6,11 @@
#include <linux/types.h>
#include <asm/page.h>
#include <asm/byteorder.h>
#include <asm/mmu.h>
+#include <asm/pgtable.h>
#define SIO_CONFIG_RA 0x398
#define SIO_CONFIG_RD 0x399
#define SLOW_DOWN_IO
@@ -222,49 +223,60 @@ extern void io_block_mapping(unsigned lo
* have to be modified [mapped] appropriately.
*/
extern inline unsigned long virt_to_bus(volatile void * address)
{
#ifndef CONFIG_APUS
- if (address == (void *)0)
+ if (unlikely(address == (void *)0))
return 0;
+ if (likely((address >= (void*) KERNELBASE) &&
+ (address < ((void*) ioremap_bot))))
return (unsigned long)address - KERNELBASE + PCI_DRAM_OFFSET;
-#else
- return iopa ((unsigned long) address);
+ else
#endif
+ return iopa ((unsigned long) address);
}
extern inline void * bus_to_virt(unsigned long address)
{
#ifndef CONFIG_APUS
- if (address == 0)
+ if (unlikely (address == 0))
return NULL;
+ if (likely((address >= PCI_DRAM_OFFSET) &&
+ (address < (ioremap_bot - KERNELBASE + PCI_DRAM_OFFSET))))
return (void *)(address - PCI_DRAM_OFFSET + KERNELBASE);
-#else
- return (void*) mm_ptov (address);
+ else
#endif
+ return (void*) mm_ptov (address);
}
/*
* Change virtual addresses to physical addresses and vv, for
* addresses in the area where the kernel has the RAM mapped.
*/
extern inline unsigned long virt_to_phys(volatile void * address)
{
#ifndef CONFIG_APUS
+ if (unlikely(address == (void *)0))
+ return 0;
+ if (likely((address >= (void*) KERNELBASE) &&
+ (address < ((void*) ioremap_bot))))
return (unsigned long) address - KERNELBASE;
-#else
- return iopa ((unsigned long) address);
+ else
#endif
+ return iopa ((unsigned long) address);
}
extern inline void * phys_to_virt(unsigned long address)
{
#ifndef CONFIG_APUS
+ if (unlikely (address == 0))
+ return NULL;
+ if (likely(address < (ioremap_bot - KERNELBASE)))
return (void *) (address + KERNELBASE);
-#else
- return (void*) mm_ptov (address);
+ else
#endif
+ return (void*) mm_ptov (address);
}
/*
* Change "struct page" to physical address.
*/Re: [PATCH][PPC32[NEWBIE] enhancement to virt_to_bus/bus_to_virt (try 2)
In 2.6.9 on non-APUS ppc32 platforms, virt_to_bus() will just subtract KERNELBASE from the the virtual address. bus_to_virt() will perform the reverse operation.
This patch will make virt_to_bus():
- perform the current operation if the virtual address is between KERNELBASE and ioremap_bot.
- use iopa() (as on APUS platform) otherwise.
The patch will make bus_to_virt():
- perform the current operation if the bus address is between PCI_DRAM_OFFSET and (ioremap_bot - KERNELBASE + PCI_DRAM_OFFSET).
- use mm_ptov() (as on APUS platform) otherwise.
The patch also changes virt_to_phys()/phys_to_virt() in a similar way.
-- Linh Dang
asm-ppc/io.h renamed from asm-ppc/io.h~2.6.9 +18 -10
@@ -6,10 +6,11 @@#include <linux/types.h> #include <asm/page.h> #include <asm/byteorder.h> #include <asm/mmu.h> +#include <asm/pgtable.h> #define SIO_CONFIG_RA 0x398#define SIO_CONFIG_RD 0x399#define SLOW_DOWN_IO
@@ -222,49 +223,56 @@ extern void io_block_mapping(unsigned lo* have to be modified [mapped] appropriately. */ extern inline unsigned long virt_to_bus (volatile void * address) {#ifndef CONFIG_APUS -if (address == (void *)0 ) +if (unlikely (address == (void *)0 ))return 0 ; +if (likely ((address >= (void *)KERNELBASE ) && + (address < ((void *) ioremap_bot))))return (unsigned long )address -KERNELBASE +PCI_DRAM_OFFSET ; -#else -return iopa ((unsigned long ) address); + else#endif +return iopa ((unsigned long ) address); }extern inline void *bus_to_virt (unsigned long address) {#ifndef CONFIG_APUS -if (address ==0 ) +if (unlikely (address ==0 ))return NULL ; +if (likely ((address >=PCI_DRAM_OFFSET ) && + (address < (ioremap_bot -KERNELBASE +PCI_DRAM_OFFSET ))))return (void *)(address -PCI_DRAM_OFFSET +KERNELBASE ); -#else -return (void *)mm_ptov (address); + else#endif +return (void *)mm_ptov (address); }/* * Change virtual addresses to physical addresses and vv, for * addresses in the area where the kernel has the RAM mapped. */ extern inline unsigned long virt_to_phys (volatile void * address) {#ifndef CONFIG_APUS +if (likely ((address >= (void *)KERNELBASE ) && + (address < ((void *) ioremap_bot))))return (unsigned long ) address -KERNELBASE ; -#else -return iopa ((unsigned long ) address); + else#endif +return iopa ((unsigned long ) address); }extern inline void *phys_to_virt (unsigned long address) {#ifndef CONFIG_APUS +if (likely (address < (ioremap_bot -KERNELBASE )))return (void *) (address +KERNELBASE ); -#else -return (void *)mm_ptov (address); + else#endif +return (void *)mm_ptov (address); }/* * Change "struct page" to physical address. */
Re: [PATCH][PPC32[NEWBIE] enhancement to virt_to_bus/bus_to_virt (try 2)
Quoted 8 lines · Linh Dang
In 2.6.9 on non-APUS ppc32 platforms,
virt_to_bus()will just subtract KERNELBASE from the the virtual address.bus_to_virt()will perform the reverse operation.This patch will make
virt_to_bus():- perform the current operation if the virtual address is between KERNELBASE and
ioremap_bot.
Why do you want to do this? The only code that should be using virt_to_bus or bus_to_virt is the DMA API code, and it's happy with them the way they are.
Quoted 1 line
The patch also changes virt_to_phys()/phys_to_virt() in a similar way.
What do you want to use them for? They are only for use in low-level memory management code.
Paul.
Re: [PATCH][PPC32[NEWBIE] enhancement to virt_to_bus/bus_to_virt (try 2)
Quoted 6 lines · Paul Mackerras
Quoted 4 lines · Linh Dang
In 2.6.9 on non-APUS ppc32 platforms,
virt_to_bus()will just subtract KERNELBASE from the the virtual address.bus_to_virt()will perform the reverse operation.
Quoted 8 lines
Quoted 4 lines
This patch will make
virt_to_bus():- perform the current operation if the virtual address is between KERNELBASE and
ioremap_bot.Why do you want to do this? The only code that should be using
virt_to_busorbus_to_virtis the DMA API code, and it's happy with them the way they are.
I wrote a DMA engine (to used by other drivers) that (would like to) accept all kind of buffers as input (vmalloced, dual-access shared RAM mapped by BATs, etc). The DMA engine has to decode the virtual address of the input buffer to (possibly multiple) physical address(es). virt_to_phys() has the right name for the job except it only works for the kernel virtual addresses initially mapped at KERNELBASE
Quoted 5 lines
Quoted 2 lines
The patch also changes virt_to_phys()/phys_to_virt() in a similar way.
What do you want to use them for? They are only for use in low-level memory management code.
Any driver for a DMA-capable device would use them and the way virt_to_phys/phys_to_virt is currently written, you can't used them with vmalloced buffers.
Quoted 3 lines
Paul.
Thanx for the feedback
Signature · 1 line
Linh Dang
Re: [PATCH][PPC32[NEWBIE] enhancement to virt_to_bus/bus_to_virt (try 2)
Quoted 16 lines · Linh Dang
Quoted 6 lines · Paul Mackerras
Quoted 4 lines · Linh Dang
In 2.6.9 on non-APUS ppc32 platforms,
virt_to_bus()will just subtract KERNELBASE from the the virtual address.bus_to_virt()will perform the reverse operation.Quoted 8 lines
Quoted 4 lines
This patch will make
virt_to_bus():- perform the current operation if the virtual address is between KERNELBASE and
ioremap_bot.Why do you want to do this? The only code that should be using
virt_to_busorbus_to_virtis the DMA API code, and it's happy with them the way they are.
Quoted 6 lines
I wrote a DMA engine (to used by other drivers) that (would like to) accept all kind of buffers as input (vmalloced, dual-access shared RAM mapped by BATs, etc). The DMA engine has to decode the virtual address of the input buffer to (possibly multiple) physical address(es).
virt_to_phys()has the right name for the job except it only works for the kernel virtual addresses initially mapped at KERNELBASE
Unfortunately your patch doesn't achieve your goals. vmalloc space on PPC32 will be between KERNEL_BASE and ioremap_bot anyway, so additional check is mostly useless anyway (it will only call iopa() for ioremaps done early during the boot).
Also, even assuming you got the range right and called iopa() for vmalloced space, tell me how are you gonna deal with non-physically continuous vmalloced buffers in your DMA library?
--
Eugene
Re: [PATCH][PPC32[NEWBIE] enhancement to virt_to_bus/bus_to_virt (try 2)
On Sun, 5 Dec 2004 02:11:10 -0800, Eugene Surovegin <[email protected]> wrote:
[...]
Quoted 5 lines
Unfortunately your patch doesn't achieve your goals. vmalloc space on PPC32 will be between
KERNEL_BASEandioremap_botanyway, so additional check is mostly useless anyway (it will only calliopa()for ioremaps done early during the boot).
Duh! how about using total_lowmem? i.e. use the current way for memory between KERNEL_BASE and (KERNEL_BASE+total_lowmem),
and iopa for other addresses?
Quoted 6 lines
Also, even assuming you got the range right and called
iopa()for vmalloced space, tell me how are you gonna deal with non-physically continuous vmalloced buffers in your DMA library?From a single virtual buffer, the DMA library will build a chained list of
physically contiguous buffers (it can be one or more physical buffers). All the DMA engines I'm familiar with (mpc8260, mpc8580, marvell, etc.) accept a list of physical buffers.
The decoding algorithm (from a single virtual buffer to a chained list of physical buffers) is dead simple.
Thanx for the reply
Signature · 1 line
Linh Dang
Re: [PATCH][PPC32[NEWBIE] enhancement to virt_to_bus/bus_to_virt (try 2)
Quoted 7 lines · Linh Dang
From a single virtual buffer, the DMA library will build a chained list of physically contiguous buffers (it can be one or more physical buffers). All the DMA engines I'm familiar with (mpc8260, mpc8580, marvell, etc.) accept a list of physical buffers.
The decoding algorithm (from a single virtual buffer to a chained list of physical buffers) is dead simple.
So you gonna call virt_to_bus several times (for each page) and see whether you get new phys page or not? This could work, but for the common case of phys-continuous buffer it'll be suboptimal, i.e. you waste time calling virt_to_bus when it's not needed. TO make it better you have to move that range check from virt_to_bus and friends to your DMA library, in this case we end up in the same situation we are already :) - no need to modify virt_to_bus....
--
Eugene
Re: [PATCH][PPC32[NEWBIE] enhancement to virt_to_bus/bus_to_virt (try 2)
In reply to Linh DangQuoted 6 lines · Linh Dang
I wrote a DMA engine (to used by other drivers) that (would like to) accept all kind of buffers as input (vmalloced, dual-access shared RAM mapped by BATs, etc). The DMA engine has to decode the virtual address of the input buffer to (possibly multiple) physical address(es).
virt_to_phys()has the right name for the job except it only works for the kernel virtual addresses initially mapped at KERNELBASE
Have you read Documentation/DMA-API.txt? It explains the official kernel API for DMA, and drivers should use it in order to be portable to more than just one architecture.
If you want to create a competing DMA API, you'll have to show us at least one driver that really needs your new API.
Also, please don't change the existing virt_to_*/*_to_virt functions. Instead define your own functions (with different names) in the same source file as your other new code.
Paul.
Re: [PATCH][PPC32[NEWBIE] enhancement to virt_to_bus/bus_to_virt (try 2)
Quoted 9 lines · Paul Mackerras
Quoted 6 lines · Linh Dang
I wrote a DMA engine (to used by other drivers) that (would like to) accept all kind of buffers as input (vmalloced, dual-access shared RAM mapped by BATs, etc). The DMA engine has to decode the virtual address of the input buffer to (possibly multiple) physical address(es).
virt_to_phys()has the right name for the job except it only works for the kernel virtual addresses initially mapped at KERNELBASE
Quoted 3 lines
Have you read
Documentation/DMA-API.txt? It explains the official kernel API for DMA, and drivers should use it in order to be portable to more than just one architecture.
Thanx for the pointer, I'll read that carefully
Quoted 4 lines
If you want to create a competing DMA API, you'll have to show us at least one driver that really needs your new API.
I think I'll implement the official DMA API for my card (the card uses the Marvell 64460 as bridge).
Quoted 3 lines
Also, please don't change the existing virt_to_*/*_to_virt functions. Instead define your own functions (with different names) in the same source file as your other new code.
Thanx for the answers.
Signature · 1 line
Linh Dang
Re: [PATCH][PPC32[NEWBIE] enhancement to virt_to_bus/bus_to_virt (try 2)
In reply to Paul MackerrasQuoted 9 lines · Paul Mackerras
Quoted 6 lines · Linh Dang
I wrote a DMA engine (to used by other drivers) that (would like to) accept all kind of buffers as input (vmalloced, dual-access shared RAM mapped by BATs, etc). The DMA engine has to decode the virtual address of the input buffer to (possibly multiple) physical address(es).
virt_to_phys()has the right name for the job except it only works for the kernel virtual addresses initially mapped at KERNELBASE
Quoted 5 lines
Have you read
Documentation/DMA-API.txt? It explains the official kernel API for DMA, and drivers should use it in order to be portable to more than just one architecture.From further reading of that text, I don't think it's what I'm looking for.
The DMA-API.txt file describes the official API for mapping an kernel virtual address to something usable by the DMA of the bus-master capable device.
On a many embedded ppc32 platforms, the bridge is capable of performing DMA (usually called IDMA) between RAM ram and NON-busmaster-devices. Examples of such platforms are the PowerQuiccII, PowerQuiccIII, the Marvell Discovery I,II,II, etc.
Such DMA operations are very useful because CPU cycles are precious on many embedded platforms.
What I'm looking for is the Linux way or the Linux equivalent of:
http://fxr.watson.org/fxr/source/dev/marvell/gtidma.c?v=NETBSD
Oh, a side question, in Linux/Unix world, is it acceptable to DMA data directly from/to the userspace buffer? Something like:
int fd = open("/dev/my_asic0", O_RDWR);
int buffer = calloc(40, 4096);
int n = pread64(fd, buffer, 40 * 4096, SOME_ADDR);and the IDMA engine would transfer 40 pages from my_asic0's shared-ram directly into `buffer'.
Thanx
Signature · 1 line
Linh Dang