From: Takashi Iwai sound/core/pcm_native.c was assuming that all architectures implement io_remap_page_range() in the same way. They don't, so the sparc64 build broke. Signed-off-by: Andrew Morton --- 25-akpm/include/sound/asound.h | 1 25-akpm/include/sound/pcm.h | 23 +++++++++ 25-akpm/sound/core/pcm.c | 3 + 25-akpm/sound/core/pcm_native.c | 100 ++++++++++++++++++++++++++++++---------- 25-akpm/sound/pci/nm256/nm256.c | 8 +-- 25-akpm/sound/pci/rme32.c | 10 ++-- 25-akpm/sound/pci/rme96.c | 16 +++--- 7 files changed, 120 insertions(+), 41 deletions(-) diff -puN include/sound/asound.h~sparc-alsa-fix include/sound/asound.h --- 25/include/sound/asound.h~sparc-alsa-fix 2004-09-01 23:33:25.000000000 -0700 +++ 25-akpm/include/sound/asound.h 2004-09-01 23:33:25.000000000 -0700 @@ -275,7 +275,6 @@ enum sndrv_pcm_subformat { #define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000 /* only half duplex */ #define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000 /* playback and capture stream are somewhat correlated */ #define SNDRV_PCM_INFO_SYNC_START 0x00400000 /* pcm support some kind of sync go */ -#define SNDRV_PCM_INFO_MMAP_IOMEM 0x01000000 /* mmap on IO memory */ enum sndrv_pcm_state { SNDRV_PCM_STATE_OPEN = 0, /* stream is open */ diff -puN include/sound/pcm.h~sparc-alsa-fix include/sound/pcm.h --- 25/include/sound/pcm.h~sparc-alsa-fix 2004-09-01 23:33:25.000000000 -0700 +++ 25-akpm/include/sound/pcm.h 2004-09-01 23:33:25.000000000 -0700 @@ -97,6 +97,7 @@ typedef struct _snd_pcm_ops { int (*silence)(snd_pcm_substream_t *substream, int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count); struct page *(*page)(snd_pcm_substream_t *substream, unsigned long offset); + int (*mmap)(snd_pcm_substream_t *substream, struct vm_area_struct *vma); int (*ack)(snd_pcm_substream_t *substream); } snd_pcm_ops_t; @@ -938,6 +939,28 @@ int snd_pcm_lib_free_pages(snd_pcm_subst #define snd_pcm_sgbuf_get_addr(sgbuf,ofs) snd_sgbuf_get_addr(sgbuf,ofs) struct page *snd_pcm_sgbuf_ops_page(snd_pcm_substream_t *substream, unsigned long offset); +/* handle mmap counter - PCM mmap callback should handle this counter properly */ +static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) +{ + snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data; + atomic_inc(&substream->runtime->mmap_count); +} + +static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) +{ + snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data; + atomic_dec(&substream->runtime->mmap_count); +} + +/* mmap for io-memory area */ +#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA) +#define SNDRV_PCM_INFO_MMAP_IOMEM SNDRV_PCM_INFO_MMAP +int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct *area); +#else +#define SNDRV_PCM_INFO_MMAP_IOMEM 0 +#define snd_pcm_lib_mmap_iomem NULL +#endif + static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) { *max = dma < 4 ? 64 * 1024 : 128 * 1024; diff -puN sound/core/pcm.c~sparc-alsa-fix sound/core/pcm.c --- 25/sound/core/pcm.c~sparc-alsa-fix 2004-09-01 23:33:25.000000000 -0700 +++ 25-akpm/sound/core/pcm.c 2004-09-01 23:33:25.000000000 -0700 @@ -1050,6 +1050,9 @@ EXPORT_SYMBOL(snd_pcm_release); EXPORT_SYMBOL(snd_pcm_playback_poll); EXPORT_SYMBOL(snd_pcm_capture_poll); EXPORT_SYMBOL(snd_pcm_mmap_data); +#if SNDRV_PCM_INFO_MMAP_IOMEM +EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); +#endif /* pcm_misc.c */ EXPORT_SYMBOL(snd_pcm_format_signed); EXPORT_SYMBOL(snd_pcm_format_unsigned); diff -puN sound/core/pcm_native.c~sparc-alsa-fix sound/core/pcm_native.c --- 25/sound/core/pcm_native.c~sparc-alsa-fix 2004-09-01 23:33:25.000000000 -0700 +++ 25-akpm/sound/core/pcm_native.c 2004-09-01 23:33:25.000000000 -0700 @@ -2908,6 +2908,18 @@ unsigned int snd_pcm_capture_poll(struct return mask; } +/* + * mmap support + */ + +/* + * Only on coherent architectures, we can mmap the status and the control records + * for effcient data transfer. On others, we have to use HWSYNC ioctl... + */ +#if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA) +/* + * mmap status record + */ static struct page * snd_pcm_mmap_status_nopage(struct vm_area_struct *area, unsigned long address, int *type) { snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data; @@ -2930,8 +2942,8 @@ static struct vm_operations_struct snd_p .nopage = snd_pcm_mmap_status_nopage, }; -int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file, - struct vm_area_struct *area) +static int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file, + struct vm_area_struct *area) { snd_pcm_runtime_t *runtime; long size; @@ -2948,6 +2960,9 @@ int snd_pcm_mmap_status(snd_pcm_substrea return 0; } +/* + * mmap control record + */ static struct page * snd_pcm_mmap_control_nopage(struct vm_area_struct *area, unsigned long address, int *type) { snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data; @@ -2987,20 +3002,26 @@ static int snd_pcm_mmap_control(snd_pcm_ area->vm_flags |= VM_RESERVED; return 0; } - -static void snd_pcm_mmap_data_open(struct vm_area_struct *area) +#else /* ! coherent mmap */ +/* + * don't support mmap for status and control records. + */ +static int snd_pcm_mmap_status(snd_pcm_substream_t *substream, struct file *file, + struct vm_area_struct *area) { - snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data; - atomic_inc(&substream->runtime->mmap_count); + return -ENXIO; } - -static void snd_pcm_mmap_data_close(struct vm_area_struct *area) +static int snd_pcm_mmap_control(snd_pcm_substream_t *substream, struct file *file, + struct vm_area_struct *area) { - snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data; - atomic_dec(&substream->runtime->mmap_count); + return -ENXIO; } +#endif /* coherent mmap */ -static struct page * snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int *type) +/* + * nopage callback for mmapping a RAM page + */ +static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area, unsigned long address, int *type) { snd_pcm_substream_t *substream = (snd_pcm_substream_t *)area->vm_private_data; snd_pcm_runtime_t *runtime; @@ -3040,12 +3061,52 @@ static struct vm_operations_struct snd_p .nopage = snd_pcm_mmap_data_nopage, }; +/* + * mmap the DMA buffer on RAM + */ +static int snd_pcm_default_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *area) +{ + area->vm_ops = &snd_pcm_vm_ops_data; + area->vm_private_data = substream; + area->vm_flags |= VM_RESERVED; + atomic_inc(&substream->runtime->mmap_count); + return 0; +} + +/* + * mmap the DMA buffer on I/O memory area + */ +#if SNDRV_PCM_INFO_MMAP_IOMEM static struct vm_operations_struct snd_pcm_vm_ops_data_mmio = { .open = snd_pcm_mmap_data_open, .close = snd_pcm_mmap_data_close, }; +int snd_pcm_lib_mmap_iomem(snd_pcm_substream_t *substream, struct vm_area_struct *area) +{ + long size; + unsigned long offset; + +#ifdef pgprot_noncached + area->vm_page_prot = pgprot_noncached(area->vm_page_prot); +#endif + area->vm_ops = &snd_pcm_vm_ops_data_mmio; + area->vm_flags |= VM_IO; + size = area->vm_end - area->vm_start; + offset = area->vm_pgoff << PAGE_SHIFT; + if (io_remap_page_range(area, area->vm_start, + substream->runtime->dma_addr + offset, + size, area->vm_page_prot)) + return -EAGAIN; + atomic_inc(&substream->runtime->mmap_count); + return 0; +} +#endif /* SNDRV_PCM_INFO_MMAP */ + +/* + * mmap DMA buffer + */ int snd_pcm_mmap_data(snd_pcm_substream_t *substream, struct file *file, struct vm_area_struct *area) { @@ -3078,19 +3139,10 @@ int snd_pcm_mmap_data(snd_pcm_substream_ if (offset > dma_bytes - size) return -EINVAL; - area->vm_ops = &snd_pcm_vm_ops_data; - area->vm_private_data = substream; - area->vm_flags |= VM_RESERVED; - if (runtime->hw.info & SNDRV_PCM_INFO_MMAP_IOMEM) { - area->vm_ops = &snd_pcm_vm_ops_data_mmio; - area->vm_flags |= VM_IO; - if (io_remap_page_range(area, area->vm_start, - runtime->dma_addr + offset, - size, area->vm_page_prot)) - return -EAGAIN; - } - atomic_inc(&runtime->mmap_count); - return 0; + if (substream->ops->mmap) + return substream->ops->mmap(substream, area); + else + return snd_pcm_default_mmap(substream, area); } static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) diff -puN sound/pci/nm256/nm256.c~sparc-alsa-fix sound/pci/nm256/nm256.c --- 25/sound/pci/nm256/nm256.c~sparc-alsa-fix 2004-09-01 23:33:25.000000000 -0700 +++ 25-akpm/sound/pci/nm256/nm256.c 2004-09-01 23:33:25.000000000 -0700 @@ -742,8 +742,7 @@ snd_nm256_capture_update(nm256_t *chip) */ static snd_pcm_hardware_t snd_nm256_playback = { - .info = SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID| - SNDRV_PCM_INFO_MMAP_IOMEM| + .info = SNDRV_PCM_INFO_MMAP_IOMEM |SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | /*SNDRV_PCM_INFO_PAUSE |*/ SNDRV_PCM_INFO_RESUME, @@ -762,8 +761,7 @@ static snd_pcm_hardware_t snd_nm256_play static snd_pcm_hardware_t snd_nm256_capture = { - .info = SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID| - SNDRV_PCM_INFO_MMAP_IOMEM| + .info = SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | /*SNDRV_PCM_INFO_PAUSE |*/ SNDRV_PCM_INFO_RESUME, @@ -864,6 +862,7 @@ static snd_pcm_ops_t snd_nm256_playback_ .copy = snd_nm256_playback_copy, .silence = snd_nm256_playback_silence, #endif + .mmap = snd_pcm_lib_mmap_iomem, }; static snd_pcm_ops_t snd_nm256_capture_ops = { @@ -877,6 +876,7 @@ static snd_pcm_ops_t snd_nm256_capture_o #ifndef __i386__ .copy = snd_nm256_capture_copy, #endif + .mmap = snd_pcm_lib_mmap_iomem, }; static int __devinit diff -puN sound/pci/rme32.c~sparc-alsa-fix sound/pci/rme32.c --- 25/sound/pci/rme32.c~sparc-alsa-fix 2004-09-01 23:33:25.000000000 -0700 +++ 25-akpm/sound/pci/rme32.c 2004-09-01 23:33:25.000000000 -0700 @@ -331,9 +331,8 @@ static int snd_rme32_capture_copy(snd_pc * SPDIF I/O capabilites (half-duplex mode) */ static snd_pcm_hardware_t snd_rme32_spdif_info = { - .info = (SNDRV_PCM_INFO_MMAP | + .info = (SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START), @@ -359,9 +358,8 @@ static snd_pcm_hardware_t snd_rme32_spdi */ static snd_pcm_hardware_t snd_rme32_adat_info = { - .info = (SNDRV_PCM_INFO_MMAP | + .info = (SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_SYNC_START), @@ -1246,6 +1244,7 @@ static snd_pcm_ops_t snd_rme32_playback_ .pointer = snd_rme32_playback_pointer, .copy = snd_rme32_playback_copy, .silence = snd_rme32_playback_silence, + .mmap = snd_pcm_lib_mmap_iomem, }; static snd_pcm_ops_t snd_rme32_capture_spdif_ops = { @@ -1258,6 +1257,7 @@ static snd_pcm_ops_t snd_rme32_capture_s .trigger = snd_rme32_pcm_trigger, .pointer = snd_rme32_capture_pointer, .copy = snd_rme32_capture_copy, + .mmap = snd_pcm_lib_mmap_iomem, }; static snd_pcm_ops_t snd_rme32_playback_adat_ops = { @@ -1270,6 +1270,7 @@ static snd_pcm_ops_t snd_rme32_playback_ .pointer = snd_rme32_playback_pointer, .copy = snd_rme32_playback_copy, .silence = snd_rme32_playback_silence, + .mmap = snd_pcm_lib_mmap_iomem, }; static snd_pcm_ops_t snd_rme32_capture_adat_ops = { @@ -1281,6 +1282,7 @@ static snd_pcm_ops_t snd_rme32_capture_a .trigger = snd_rme32_pcm_trigger, .pointer = snd_rme32_capture_pointer, .copy = snd_rme32_capture_copy, + .mmap = snd_pcm_lib_mmap_iomem, }; /* for fullduplex mode */ diff -puN sound/pci/rme96.c~sparc-alsa-fix sound/pci/rme96.c --- 25/sound/pci/rme96.c~sparc-alsa-fix 2004-09-01 23:33:25.000000000 -0700 +++ 25-akpm/sound/pci/rme96.c 2004-09-01 23:33:25.000000000 -0700 @@ -383,9 +383,8 @@ snd_rme96_capture_copy(snd_pcm_substream */ static snd_pcm_hardware_t snd_rme96_playback_spdif_info = { - .info = (SNDRV_PCM_INFO_MMAP | + .info = (SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE), .formats = (SNDRV_PCM_FMTBIT_S16_LE | @@ -413,9 +412,8 @@ static snd_pcm_hardware_t snd_rme96_play */ static snd_pcm_hardware_t snd_rme96_capture_spdif_info = { - .info = (SNDRV_PCM_INFO_MMAP | + .info = (SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE), .formats = (SNDRV_PCM_FMTBIT_S16_LE | @@ -443,9 +441,8 @@ static snd_pcm_hardware_t snd_rme96_capt */ static snd_pcm_hardware_t snd_rme96_playback_adat_info = { - .info = (SNDRV_PCM_INFO_MMAP | + .info = (SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE), .formats = (SNDRV_PCM_FMTBIT_S16_LE | @@ -469,9 +466,8 @@ static snd_pcm_hardware_t snd_rme96_play */ static snd_pcm_hardware_t snd_rme96_capture_adat_info = { - .info = (SNDRV_PCM_INFO_MMAP | + .info = (SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE), .formats = (SNDRV_PCM_FMTBIT_S16_LE | @@ -1494,6 +1490,7 @@ static snd_pcm_ops_t snd_rme96_playback_ .pointer = snd_rme96_playback_pointer, .copy = snd_rme96_playback_copy, .silence = snd_rme96_playback_silence, + .mmap = snd_pcm_lib_mmap_iomem, }; static snd_pcm_ops_t snd_rme96_capture_spdif_ops = { @@ -1505,6 +1502,7 @@ static snd_pcm_ops_t snd_rme96_capture_s .trigger = snd_rme96_capture_trigger, .pointer = snd_rme96_capture_pointer, .copy = snd_rme96_capture_copy, + .mmap = snd_pcm_lib_mmap_iomem, }; static snd_pcm_ops_t snd_rme96_playback_adat_ops = { @@ -1517,6 +1515,7 @@ static snd_pcm_ops_t snd_rme96_playback_ .pointer = snd_rme96_playback_pointer, .copy = snd_rme96_playback_copy, .silence = snd_rme96_playback_silence, + .mmap = snd_pcm_lib_mmap_iomem, }; static snd_pcm_ops_t snd_rme96_capture_adat_ops = { @@ -1528,6 +1527,7 @@ static snd_pcm_ops_t snd_rme96_capture_a .trigger = snd_rme96_capture_trigger, .pointer = snd_rme96_capture_pointer, .copy = snd_rme96_capture_copy, + .mmap = snd_pcm_lib_mmap_iomem, }; static void _