[alsa-devel] ALSA on MIPS platform
Hi, In http://www.linux-mips.org/archives/linux-mips/2007-04/msg00114.html, Atsushi Nemoto pointed out the problem is discussed before, the thread can be found at http://lkml.org/lkml/2006/1/25/117. Thanks Atsushi Nemoto:) The problem is clear: 1. dma_alloc_noncoherent() return a non-cached address, and virt_to_page() need a cached logical addr (Have I named it right?) 2. mmaped dam buffer should be non-cached.
We have a ugly patch, but we want to solve the problem cleanly, so can anyone show me the way?
Regards, Tian
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 59b29cd..fd0aa66 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3138,7 +3138,11 @@ static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area, return NOPAGE_OOM; /* XXX: is this really due to OOM? */ } else { vaddr = runtime->dma_area + offset; +#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT) + page = virt_to_page(CAC_ADDR(vaddr)); +#else page = virt_to_page(vaddr); +#endif } get_page(page); if (type) @@ -3254,6 +3258,11 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) substream = pcm_file->substream; snd_assert(substream != NULL, return -ENXIO);
+#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT) + /* all mmap using uncached mode */ + area->vm_page_prot = pgprot_noncached(area->vm_page_prot); +#endif + offset = area->vm_pgoff << PAGE_SHIFT; switch (offset) { case SNDRV_PCM_MMAP_OFFSET_STATUS: diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index cefd228..2251e70 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -91,12 +91,21 @@ void *snd_malloc_sgbuf_pages(struct device *device, } sgbuf->table[i].buf = tmpb.area; sgbuf->table[i].addr = tmpb.addr; +#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT) + sgbuf->page_table[i] = virt_to_page(CAC_ADDR(tmpb.area)); +#else sgbuf->page_table[i] = virt_to_page(tmpb.area); +#endif sgbuf->pages++; }
sgbuf->size = size; +#if defined(__mips__) && defined(CONFIG_DMA_NONCOHERENT) + /* maybe we should use uncached accelerated mode */ + dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, pgprot_noncached(PAGE_KERNEL)); +#else dmab->area = vmap(sgbuf->page_table, sgbuf->pages, VM_MAP, PAGE_KERNEL); +#endif if (! dmab->area) goto _failed; return dmab->area;
On Wed, 01 Aug 2007 15:56:48 +0800, Songmao Tian tiansm@lemote.com wrote:
The problem is clear:
- dma_alloc_noncoherent() return a non-cached address, and
virt_to_page() need a cached logical addr (Have I named it right?) 2. mmaped dam buffer should be non-cached.
We have a ugly patch, but we want to solve the problem cleanly, so can anyone show me the way?
virt_to_page() is used in many place in mm so making it robust might affect performance. IMHO virt_to_page() seems too low-level as DMA API.
If something like dma_virt_to_page(dev, cpu_addr) which can take a cpu address returned by dma_xxx APIs was defined, MIPS can implement it appropriately.
And then pgprot_noncached issues still exist...
--- Atsushi Nemoto
Atsushi Nemoto wrote:
On Wed, 01 Aug 2007 15:56:48 +0800, Songmao Tian tiansm@lemote.com wrote:
The problem is clear:
- dma_alloc_noncoherent() return a non-cached address, and
virt_to_page() need a cached logical addr (Have I named it right?) 2. mmaped dam buffer should be non-cached.
We have a ugly patch, but we want to solve the problem cleanly, so can anyone show me the way?
virt_to_page() is used in many place in mm so making it robust might affect performance. IMHO virt_to_page() seems too low-level as DMA API.
If something like dma_virt_to_page(dev, cpu_addr) which can take a cpu address returned by dma_xxx APIs was defined, MIPS can implement it appropriately.
And then pgprot_noncached issues still exist...
Atsushi Nemoto
I agree, and I am investigating to implement a dma_map_coherent, but It seems dma_map_coherent doesn't solve all the problem and will change a lot of code:(
dma_virt_to_page can be something like this.
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h index b92dd8c..d2ead8a 100644 --- a/include/asm-mips/page.h +++ b/include/asm-mips/page.h @@ -181,6 +181,8 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(virt_to_phys(kaddr))) #define virt_addr_valid(kaddr) pfn_valid(PFN_DOWN(virt_to_phys(kaddr)))
+#define dma_virt_to_page(dma_addr) pfn_to_page(PFN_DOWN(virt_to_phys(CAC_ADDR(kaddr)))) + #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
diff --git a/include/linux/mm.h b/include/linux/mm.h index 655094d..5e694dd 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -39,6 +39,10 @@ extern int sysctl_legacy_va_layout; #include <asm/pgtable.h> #include <asm/processor.h>
+#ifndef dma_virt_to_page +#define dma_virt_to_page virt_to_page +#endif + #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
/* diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index cefd228..8b29bfd 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -91,7 +91,7 @@ void *snd_malloc_sgbuf_pages(struct device *device, } sgbuf->table[i].buf = tmpb.area; sgbuf->table[i].addr = tmpb.addr; - sgbuf->page_table[i] = virt_to_page(tmpb.area); + sgbuf->page_table[i] = dma_virt_to_page(tmpb.area); sgbuf->pages++; }
At Fri, 03 Aug 2007 21:50:36 +0800, Songmao Tian wrote:
Atsushi Nemoto wrote:
On Wed, 01 Aug 2007 15:56:48 +0800, Songmao Tian tiansm@lemote.com wrote:
The problem is clear:
- dma_alloc_noncoherent() return a non-cached address, and
virt_to_page() need a cached logical addr (Have I named it right?) 2. mmaped dam buffer should be non-cached.
We have a ugly patch, but we want to solve the problem cleanly, so can anyone show me the way?
virt_to_page() is used in many place in mm so making it robust might affect performance. IMHO virt_to_page() seems too low-level as DMA API.
If something like dma_virt_to_page(dev, cpu_addr) which can take a cpu address returned by dma_xxx APIs was defined, MIPS can implement it appropriately.
And then pgprot_noncached issues still exist...
Atsushi Nemoto
I agree, and I am investigating to implement a dma_map_coherent, but It seems dma_map_coherent doesn't solve all the problem and will change a lot of code:(
It won't be that much. You'll need to change snd_pcm_default_mmap() in sound/core/pcm_native.c to call dma_mmap_coherent() directly instead of nopage ops. But, this won't work with SG-buffers, which requires some more additional works.
Takashi
Takashi Iwai wrote:
At Fri, 03 Aug 2007 21:50:36 +0800, Songmao Tian wrote:
Atsushi Nemoto wrote:
On Wed, 01 Aug 2007 15:56:48 +0800, Songmao Tian tiansm@lemote.com wrote:
The problem is clear:
- dma_alloc_noncoherent() return a non-cached address, and
virt_to_page() need a cached logical addr (Have I named it right?) 2. mmaped dam buffer should be non-cached.
We have a ugly patch, but we want to solve the problem cleanly, so can anyone show me the way?
virt_to_page() is used in many place in mm so making it robust might affect performance. IMHO virt_to_page() seems too low-level as DMA API.
If something like dma_virt_to_page(dev, cpu_addr) which can take a cpu address returned by dma_xxx APIs was defined, MIPS can implement it appropriately.
And then pgprot_noncached issues still exist...
Atsushi Nemoto
I agree, and I am investigating to implement a dma_map_coherent, but It seems dma_map_coherent doesn't solve all the problem and will change a lot of code:(
It won't be that much. You'll need to change snd_pcm_default_mmap() in sound/core/pcm_native.c to call dma_mmap_coherent() directly instead of nopage ops. But, this won't work with SG-buffers, which requires some more additional works.
Takashi _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
I have no idea if the patch can work, the idea is not very clear now. And I use vt686b ac97 sound driver, the driver use sgbuf, so I will write a test program tomorrow. Good sleep...:)
And if any of you can take some time look into the patch, and give some review will be appreciated:)
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 76903c7..f088a6b 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -369,3 +369,23 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size, }
EXPORT_SYMBOL(dma_cache_sync); + +static int dma_mmap(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t dma_addr, size_t size) +{ + if (remap_pfn_range(vma, vma->vm_start, + PFN_DOWN(virt_to_phys(CAC_ADDR(cpu_addr))) + vma->vm_pgoff, + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) + return -EAGAIN; + return 0; +} + +int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t dma_addr, size_t size) +{ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + return dma_mmap(dev, vma, cpu_addr, dma_addr, size); +} +EXPORT_SYMBOL(dma_mmap_coherent); + diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 59b29cd..af82a3b 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3152,6 +3152,8 @@ static struct vm_operations_struct snd_pcm_vm_ops_data = .close = snd_pcm_mmap_data_close, .nopage = snd_pcm_mmap_data_nopage, }; +int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma, + void *cpu_addr, dma_addr_t dma_addr, size_t size);
/* * mmap the DMA buffer on RAM @@ -3159,9 +3161,10 @@ static struct vm_operations_struct snd_pcm_vm_ops_data = static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *area) { - area->vm_ops = &snd_pcm_vm_ops_data; + struct snd_pcm_runtime *runtime = substream->runtime; area->vm_private_data = substream; - area->vm_flags |= VM_RESERVED; + dma_mmap_coherent(NULL, area, runtime->dma_area, + runtime->dma_addr, runtime->dma_bytes); atomic_inc(&substream->mmap_count); return 0; }
At Fri, 03 Aug 2007 23:57:07 +0800, Songmao Tian wrote:
Takashi Iwai wrote:
At Fri, 03 Aug 2007 21:50:36 +0800, Songmao Tian wrote:
Atsushi Nemoto wrote:
On Wed, 01 Aug 2007 15:56:48 +0800, Songmao Tian tiansm@lemote.com wrote:
The problem is clear:
- dma_alloc_noncoherent() return a non-cached address, and
virt_to_page() need a cached logical addr (Have I named it right?) 2. mmaped dam buffer should be non-cached.
We have a ugly patch, but we want to solve the problem cleanly, so can anyone show me the way?
virt_to_page() is used in many place in mm so making it robust might affect performance. IMHO virt_to_page() seems too low-level as DMA API.
If something like dma_virt_to_page(dev, cpu_addr) which can take a cpu address returned by dma_xxx APIs was defined, MIPS can implement it appropriately.
And then pgprot_noncached issues still exist...
Atsushi Nemoto
I agree, and I am investigating to implement a dma_map_coherent, but It seems dma_map_coherent doesn't solve all the problem and will change a lot of code:(
It won't be that much. You'll need to change snd_pcm_default_mmap() in sound/core/pcm_native.c to call dma_mmap_coherent() directly instead of nopage ops. But, this won't work with SG-buffers, which requires some more additional works.
Takashi _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
I have no idea if the patch can work, the idea is not very clear now. And I use vt686b ac97 sound driver, the driver use sgbuf, so I will write a test program tomorrow. Good sleep...:)
Ah, that's a bad luck. Then your patch won't work as it is. We'll need another function for SG-buffer, that calls dma_mmap_coherent() for each page found in the given buffer.
Takashi
And if any of you can take some time look into the patch, and give some review will be appreciated:)
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 76903c7..f088a6b 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -369,3 +369,23 @@ void dma_cache_sync(struct device *dev, void *vaddr, size_t size, }
EXPORT_SYMBOL(dma_cache_sync);
+static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size)
+{
- if (remap_pfn_range(vma, vma->vm_start,
PFN_DOWN(virt_to_phys(CAC_ADDR(cpu_addr))) +
vma->vm_pgoff,
vma->vm_end - vma->vm_start,
vma->vm_page_prot))
return -EAGAIN;
- return 0;
+}
+int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size)
+{
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
+} +EXPORT_SYMBOL(dma_mmap_coherent);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 59b29cd..af82a3b 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3152,6 +3152,8 @@ static struct vm_operations_struct snd_pcm_vm_ops_data = .close = snd_pcm_mmap_data_close, .nopage = snd_pcm_mmap_data_nopage, }; +int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size);
/*
- mmap the DMA buffer on RAM
@@ -3159,9 +3161,10 @@ static struct vm_operations_struct snd_pcm_vm_ops_data = static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *area) {
- area->vm_ops = &snd_pcm_vm_ops_data;
- struct snd_pcm_runtime *runtime = substream->runtime; area->vm_private_data = substream;
- area->vm_flags |= VM_RESERVED;
- dma_mmap_coherent(NULL, area, runtime->dma_area,
atomic_inc(&substream->mmap_count); return 0;runtime->dma_addr, runtime->dma_bytes);
} _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
I think this problem can be solved by revising the __pa macro like this:
--- a/include/asm-mips/page.h 2007-08-07 09:45:00.000000000 +0800 +++ b/include/asm-mips/page.h 2007-08-07 09:46:59.000000000 +0800 @@ -150,7 +150,7 @@ }) #else #define __pa(x) \ - ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET) + (((unsigned long)(x) & 0x1fffffff) + PHYS_OFFSET) #endif
So, the virt_to_page can accept all cached or uncached address.
Tan
2007/8/3, Songmao Tian tiansm@lemote.com:
Atsushi Nemoto wrote:
On Wed, 01 Aug 2007 15:56:48 +0800, Songmao Tian tiansm@lemote.com wrote:
The problem is clear:
- dma_alloc_noncoherent() return a non-cached address, and
virt_to_page() need a cached logical addr (Have I named it right?) 2. mmaped dam buffer should be non-cached.
We have a ugly patch, but we want to solve the problem cleanly, so can anyone show me the way?
virt_to_page() is used in many place in mm so making it robust might affect performance. IMHO virt_to_page() seems too low-level as DMA API.
If something like dma_virt_to_page(dev, cpu_addr) which can take a cpu address returned by dma_xxx APIs was defined, MIPS can implement it appropriately.
And then pgprot_noncached issues still exist...
Atsushi Nemoto
I agree, and I am investigating to implement a dma_map_coherent, but It seems dma_map_coherent doesn't solve all the problem and will change a lot of code:(
dma_virt_to_page can be something like this.
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h index b92dd8c..d2ead8a 100644 --- a/include/asm-mips/page.h +++ b/include/asm-mips/page.h @@ -181,6 +181,8 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(virt_to_phys(kaddr))) #define virt_addr_valid(kaddr) pfn_valid(PFN_DOWN(virt_to_phys(kaddr)))
+#define dma_virt_to_page(dma_addr) pfn_to_page(PFN_DOWN(virt_to_phys(CAC_ADDR(kaddr))))
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
diff --git a/include/linux/mm.h b/include/linux/mm.h index 655094d..5e694dd 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -39,6 +39,10 @@ extern int sysctl_legacy_va_layout; #include <asm/pgtable.h> #include <asm/processor.h>
+#ifndef dma_virt_to_page +#define dma_virt_to_page virt_to_page +#endif
#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
/* diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index cefd228..8b29bfd 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -91,7 +91,7 @@ void *snd_malloc_sgbuf_pages(struct device *device, } sgbuf->table[i].buf = tmpb.area; sgbuf->table[i].addr = tmpb.addr;
sgbuf->page_table[i] = virt_to_page(tmpb.area);
}sgbuf->page_table[i] = dma_virt_to_page(tmpb.area); sgbuf->pages++;
Sorry, that aim at 2.6.18.
In the latest kernel:
--- a/include/asm-mips/io.h 2007-08-07 10:18:03.000000000 +0800 +++ b/include/asm-mips/io.h 2007-08-07 10:18:56.000000000 +0800 @@ -116,7 +116,7 @@ */ static inline unsigned long virt_to_phys(volatile const void *address) { - return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET; + return ((unsigned long)address & 0x1fffffff) + PHYS_OFFSET; }
I think virt_to_phys or __pa should accept kseg1 address.
Tan
2007/8/7, Dajie Tan jiankemeng@gmail.com:
I think this problem can be solved by revising the __pa macro like this:
--- a/include/asm-mips/page.h 2007-08-07 09:45:00.000000000 +0800 +++ b/include/asm-mips/page.h 2007-08-07 09:46:59.000000000 +0800 @@ -150,7 +150,7 @@ }) #else #define __pa(x) \
- ((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
- (((unsigned long)(x) & 0x1fffffff) + PHYS_OFFSET)
#endif
So, the virt_to_page can accept all cached or uncached address.
Tan
2007/8/3, Songmao Tian tiansm@lemote.com:
Atsushi Nemoto wrote:
On Wed, 01 Aug 2007 15:56:48 +0800, Songmao Tian tiansm@lemote.com wrote:
The problem is clear:
- dma_alloc_noncoherent() return a non-cached address, and
virt_to_page() need a cached logical addr (Have I named it right?) 2. mmaped dam buffer should be non-cached.
We have a ugly patch, but we want to solve the problem cleanly, so can anyone show me the way?
virt_to_page() is used in many place in mm so making it robust might affect performance. IMHO virt_to_page() seems too low-level as DMA API.
If something like dma_virt_to_page(dev, cpu_addr) which can take a cpu address returned by dma_xxx APIs was defined, MIPS can implement it appropriately.
And then pgprot_noncached issues still exist...
Atsushi Nemoto
I agree, and I am investigating to implement a dma_map_coherent, but It seems dma_map_coherent doesn't solve all the problem and will change a lot of code:(
dma_virt_to_page can be something like this.
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h index b92dd8c..d2ead8a 100644 --- a/include/asm-mips/page.h +++ b/include/asm-mips/page.h @@ -181,6 +181,8 @@ typedef struct { unsigned long pgprot; } pgprot_t; #define virt_to_page(kaddr) pfn_to_page(PFN_DOWN(virt_to_phys(kaddr))) #define virt_addr_valid(kaddr) pfn_valid(PFN_DOWN(virt_to_phys(kaddr)))
+#define dma_virt_to_page(dma_addr) pfn_to_page(PFN_DOWN(virt_to_phys(CAC_ADDR(kaddr))))
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
diff --git a/include/linux/mm.h b/include/linux/mm.h index 655094d..5e694dd 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -39,6 +39,10 @@ extern int sysctl_legacy_va_layout; #include <asm/pgtable.h> #include <asm/processor.h>
+#ifndef dma_virt_to_page +#define dma_virt_to_page virt_to_page +#endif
#define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
/* diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index cefd228..8b29bfd 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c @@ -91,7 +91,7 @@ void *snd_malloc_sgbuf_pages(struct device *device, } sgbuf->table[i].buf = tmpb.area; sgbuf->table[i].addr = tmpb.addr;
sgbuf->page_table[i] = virt_to_page(tmpb.area);
}sgbuf->page_table[i] = dma_virt_to_page(tmpb.area); sgbuf->pages++;
On Tue, 7 Aug 2007 10:18:04 +0400, "Dajie Tan" jiankemeng@gmail.com wrote:
static inline unsigned long virt_to_phys(volatile const void *address) {
return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET;
return ((unsigned long)address & 0x1fffffff) + PHYS_OFFSET;
}
This makes virt_to_phys() a bit slower, and more importantly, breaks 64-bit kernel.
--- Atsushi Nemoto
On Tue, Aug 07, 2007 at 11:01:57PM +0900, Atsushi Nemoto wrote:
On Tue, 7 Aug 2007 10:18:04 +0400, "Dajie Tan" jiankemeng@gmail.com wrote:
static inline unsigned long virt_to_phys(volatile const void *address) {
return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET;
return ((unsigned long)address & 0x1fffffff) + PHYS_OFFSET;
}
This makes virt_to_phys() a bit slower, and more importantly, breaks 64-bit kernel.
It's ALSA that is doing funny things here so there is no point in fixing the arch code to work for ALSA.
Ralf
At Tue, 7 Aug 2007 18:54:02 +0100, Ralf Baechle wrote:
On Tue, Aug 07, 2007 at 11:01:57PM +0900, Atsushi Nemoto wrote:
On Tue, 7 Aug 2007 10:18:04 +0400, "Dajie Tan" jiankemeng@gmail.com wrote:
static inline unsigned long virt_to_phys(volatile const void *address) {
return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET;
return ((unsigned long)address & 0x1fffffff) + PHYS_OFFSET;
}
This makes virt_to_phys() a bit slower, and more importantly, breaks 64-bit kernel.
It's ALSA that is doing funny things here so there is no point in fixing the arch code to work for ALSA.
Yep, but OTOH, the arch code doesn't provide a proper standard way to mmap the pages allocated via dma_alloc_coherent(). That's the missing piece, especially on mips and sparc. ARM has already one.
My wish is implementing dma_mmap_coherent() on all architectures, so that the driver can use it safely without messy ifdefs.
Takashi
On Tue, Aug 07, 2007 at 08:41:10PM +0200, Takashi Iwai wrote:
It's ALSA that is doing funny things here so there is no point in fixing the arch code to work for ALSA.
Yep, but OTOH, the arch code doesn't provide a proper standard way to mmap the pages allocated via dma_alloc_coherent(). That's the missing piece, especially on mips and sparc. ARM has already one.
My wish is implementing dma_mmap_coherent() on all architectures, so that the driver can use it safely without messy ifdefs.
Adding dma_mmap_coherent has been proposed in 2004 but the discussion for some reason went nowhere because it apparently isn't implementable on PARISC due to cache synonyms - on MIPS we'd solve those issues where they exist by using uncached or writethrough mappings, as apropriate.
Ralf
On Wed, 8 Aug 2007, Ralf Baechle wrote:
Yep, but OTOH, the arch code doesn't provide a proper standard way to mmap the pages allocated via dma_alloc_coherent(). That's the missing piece, especially on mips and sparc. ARM has already one.
My wish is implementing dma_mmap_coherent() on all architectures, so that the driver can use it safely without messy ifdefs.
Adding dma_mmap_coherent has been proposed in 2004 but the discussion for some reason went nowhere because it apparently isn't implementable on PARISC due to cache synonyms - on MIPS we'd solve those issues where they exist by using uncached or writethrough mappings, as apropriate.
Hmm, why should everybody suffer from some limitation of some peculiar architecture? I would suggest to let them find an architecture-specific way of addressing the problem -- they surely have a good control over their own code and can implement a workaround that would not impede all the others.
Ralf, do you have an idea about what their issue exactly is?
Maciej
At Wed, 8 Aug 2007 12:58:52 +0100, Ralf Baechle wrote:
On Tue, Aug 07, 2007 at 08:41:10PM +0200, Takashi Iwai wrote:
It's ALSA that is doing funny things here so there is no point in fixing the arch code to work for ALSA.
Yep, but OTOH, the arch code doesn't provide a proper standard way to mmap the pages allocated via dma_alloc_coherent(). That's the missing piece, especially on mips and sparc. ARM has already one.
My wish is implementing dma_mmap_coherent() on all architectures, so that the driver can use it safely without messy ifdefs.
Adding dma_mmap_coherent has been proposed in 2004 but the discussion for some reason went nowhere because it apparently isn't implementable on PARISC due to cache synonyms - on MIPS we'd solve those issues where they exist by using uncached or writethrough mappings, as apropriate.
Actually, if it cannot be implemented (or not yet implemented properly) on some architectures, it's fine. Then we can simply drop the mmap support just for such an architecture. I suppose an inlined dma_mmap_coherent() that always returns an error, just like the earlier version of asm-generic/dma-mapping-broken.h, would work well.
But, currently, the driver has no idea which architecture is OK and which not, and which method to choose. That is where we got stuck.
Takashi
Ralf Baechle wrote:
On Tue, Aug 07, 2007 at 11:01:57PM +0900, Atsushi Nemoto wrote:
On Tue, 7 Aug 2007 10:18:04 +0400, "Dajie Tan" jiankemeng@gmail.com wrote:
static inline unsigned long virt_to_phys(volatile const void *address) {
return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET;
return ((unsigned long)address & 0x1fffffff) + PHYS_OFFSET;
}
This makes virt_to_phys() a bit slower, and more importantly, breaks 64-bit kernel.
It's ALSA that is doing funny things here so there is no point in fixing the arch code to work for ALSA.
Ralf
arm has made a dma_mmap_coherent, but I don't quite understand the code and I am not sure the situation is the same.
Tian
Atsushi Nemoto wrote:
On Tue, 7 Aug 2007 10:18:04 +0400, "Dajie Tan" jiankemeng@gmail.com wrote:
static inline unsigned long virt_to_phys(volatile const void *address) {
return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET;
return ((unsigned long)address & 0x1fffffff) + PHYS_OFFSET;
}
This makes virt_to_phys() a bit slower, and more importantly, breaks 64-bit kernel.
I have tried this way, and disassemble result show 32-bit kernel add only one instruction. But I don't really insist on this patch, for it doesn't resolve some driver code requirement.
Atsushi Nemoto _______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
participants (6)
-
Atsushi Nemoto
-
Dajie Tan
-
Maciej W. Rozycki
-
Ralf Baechle
-
Songmao Tian
-
Takashi Iwai