diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-04-28 09:13:41 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-06-22 15:33:14 -0400 |
commit | 9c323fcbc51493f79f9700cb20830d0857c72d99 (patch) | |
tree | 17e17046c0642f918b9516de8d9517914cabd0ad | |
parent | 0df63e44c3e315ec0fe427ae62558231864108bd (diff) |
[ALSA] Fix mmap_count with O_APPEND opened streams
Move mmap_count to snd_pcm_substream instead of runtime struct
so that multiplly opened substreams via O_APPEND can be handled
correctly.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | include/sound/pcm.h | 6 | ||||
-rw-r--r-- | sound/core/oss/pcm_oss.c | 27 | ||||
-rw-r--r-- | sound/core/pcm.c | 2 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 10 |
4 files changed, 23 insertions, 22 deletions
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index cebf0310a8dc..f84d84993a31 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -300,7 +300,6 @@ struct snd_pcm_runtime { | |||
300 | /* -- mmap -- */ | 300 | /* -- mmap -- */ |
301 | volatile struct snd_pcm_mmap_status *status; | 301 | volatile struct snd_pcm_mmap_status *status; |
302 | volatile struct snd_pcm_mmap_control *control; | 302 | volatile struct snd_pcm_mmap_control *control; |
303 | atomic_t mmap_count; | ||
304 | 303 | ||
305 | /* -- locking / scheduling -- */ | 304 | /* -- locking / scheduling -- */ |
306 | wait_queue_head_t sleep; | 305 | wait_queue_head_t sleep; |
@@ -369,6 +368,7 @@ struct snd_pcm_substream { | |||
369 | /* -- assigned files -- */ | 368 | /* -- assigned files -- */ |
370 | void *file; | 369 | void *file; |
371 | int ref_count; | 370 | int ref_count; |
371 | atomic_t mmap_count; | ||
372 | unsigned int f_flags; | 372 | unsigned int f_flags; |
373 | void (*pcm_release)(struct snd_pcm_substream *); | 373 | void (*pcm_release)(struct snd_pcm_substream *); |
374 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 374 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
@@ -972,13 +972,13 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne | |||
972 | static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) | 972 | static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) |
973 | { | 973 | { |
974 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; | 974 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; |
975 | atomic_inc(&substream->runtime->mmap_count); | 975 | atomic_inc(&substream->mmap_count); |
976 | } | 976 | } |
977 | 977 | ||
978 | static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) | 978 | static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) |
979 | { | 979 | { |
980 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; | 980 | struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; |
981 | atomic_dec(&substream->runtime->mmap_count); | 981 | atomic_dec(&substream->mmap_count); |
982 | } | 982 | } |
983 | 983 | ||
984 | /* mmap for io-memory area */ | 984 | /* mmap for io-memory area */ |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 9803a6ce3d46..4395285aa6a3 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -684,7 +684,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, | |||
684 | oss_buffer_size = snd_pcm_plug_client_size(substream, | 684 | oss_buffer_size = snd_pcm_plug_client_size(substream, |
685 | snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; | 685 | snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; |
686 | oss_buffer_size = 1 << ld2(oss_buffer_size); | 686 | oss_buffer_size = 1 << ld2(oss_buffer_size); |
687 | if (atomic_read(&runtime->mmap_count)) { | 687 | if (atomic_read(&substream->mmap_count)) { |
688 | if (oss_buffer_size > runtime->oss.mmap_bytes) | 688 | if (oss_buffer_size > runtime->oss.mmap_bytes) |
689 | oss_buffer_size = runtime->oss.mmap_bytes; | 689 | oss_buffer_size = runtime->oss.mmap_bytes; |
690 | } | 690 | } |
@@ -819,7 +819,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
819 | goto failure; | 819 | goto failure; |
820 | } | 820 | } |
821 | 821 | ||
822 | if (atomic_read(&runtime->mmap_count)) | 822 | if (atomic_read(&substream->mmap_count)) |
823 | direct = 1; | 823 | direct = 1; |
824 | else | 824 | else |
825 | direct = substream->oss.setup.direct; | 825 | direct = substream->oss.setup.direct; |
@@ -828,7 +828,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
828 | _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); | 828 | _snd_pcm_hw_param_setinteger(sparams, SNDRV_PCM_HW_PARAM_PERIODS); |
829 | _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); | 829 | _snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0); |
830 | snd_mask_none(&mask); | 830 | snd_mask_none(&mask); |
831 | if (atomic_read(&runtime->mmap_count)) | 831 | if (atomic_read(&substream->mmap_count)) |
832 | snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); | 832 | snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED); |
833 | else { | 833 | else { |
834 | snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED); | 834 | snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED); |
@@ -947,7 +947,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
947 | } else { | 947 | } else { |
948 | sw_params->start_threshold = runtime->boundary; | 948 | sw_params->start_threshold = runtime->boundary; |
949 | } | 949 | } |
950 | if (atomic_read(&runtime->mmap_count) || substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 950 | if (atomic_read(&substream->mmap_count) || |
951 | substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
951 | sw_params->stop_threshold = runtime->boundary; | 952 | sw_params->stop_threshold = runtime->boundary; |
952 | else | 953 | else |
953 | sw_params->stop_threshold = runtime->buffer_size; | 954 | sw_params->stop_threshold = runtime->buffer_size; |
@@ -957,7 +958,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) | |||
957 | sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | 958 | sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? |
958 | 1 : runtime->period_size; | 959 | 1 : runtime->period_size; |
959 | sw_params->xfer_align = 1; | 960 | sw_params->xfer_align = 1; |
960 | if (atomic_read(&runtime->mmap_count) || | 961 | if (atomic_read(&substream->mmap_count) || |
961 | substream->oss.setup.nosilence) { | 962 | substream->oss.setup.nosilence) { |
962 | sw_params->silence_threshold = 0; | 963 | sw_params->silence_threshold = 0; |
963 | sw_params->silence_size = 0; | 964 | sw_params->silence_size = 0; |
@@ -1301,7 +1302,7 @@ static ssize_t snd_pcm_oss_write1(struct snd_pcm_substream *substream, const cha | |||
1301 | ssize_t tmp; | 1302 | ssize_t tmp; |
1302 | struct snd_pcm_runtime *runtime = substream->runtime; | 1303 | struct snd_pcm_runtime *runtime = substream->runtime; |
1303 | 1304 | ||
1304 | if (atomic_read(&runtime->mmap_count)) | 1305 | if (atomic_read(&substream->mmap_count)) |
1305 | return -ENXIO; | 1306 | return -ENXIO; |
1306 | 1307 | ||
1307 | if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) | 1308 | if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) |
@@ -1391,7 +1392,7 @@ static ssize_t snd_pcm_oss_read1(struct snd_pcm_substream *substream, char __use | |||
1391 | ssize_t tmp; | 1392 | ssize_t tmp; |
1392 | struct snd_pcm_runtime *runtime = substream->runtime; | 1393 | struct snd_pcm_runtime *runtime = substream->runtime; |
1393 | 1394 | ||
1394 | if (atomic_read(&runtime->mmap_count)) | 1395 | if (atomic_read(&substream->mmap_count)) |
1395 | return -ENXIO; | 1396 | return -ENXIO; |
1396 | 1397 | ||
1397 | if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) | 1398 | if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) |
@@ -1521,7 +1522,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file) | |||
1521 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; | 1522 | substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK]; |
1522 | if (substream != NULL) { | 1523 | if (substream != NULL) { |
1523 | runtime = substream->runtime; | 1524 | runtime = substream->runtime; |
1524 | if (atomic_read(&runtime->mmap_count)) | 1525 | if (atomic_read(&substream->mmap_count)) |
1525 | goto __direct; | 1526 | goto __direct; |
1526 | if ((err = snd_pcm_oss_make_ready(substream)) < 0) | 1527 | if ((err = snd_pcm_oss_make_ready(substream)) < 0) |
1527 | return err; | 1528 | return err; |
@@ -1690,7 +1691,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file) | |||
1690 | 1691 | ||
1691 | if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) | 1692 | if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0) |
1692 | return err; | 1693 | return err; |
1693 | if (atomic_read(&substream->runtime->mmap_count)) | 1694 | if (atomic_read(&substream->mmap_count)) |
1694 | direct = 1; | 1695 | direct = 1; |
1695 | else | 1696 | else |
1696 | direct = substream->oss.setup.direct; | 1697 | direct = substream->oss.setup.direct; |
@@ -1900,7 +1901,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr | |||
1900 | if (trigger & PCM_ENABLE_OUTPUT) { | 1901 | if (trigger & PCM_ENABLE_OUTPUT) { |
1901 | if (runtime->oss.trigger) | 1902 | if (runtime->oss.trigger) |
1902 | goto _skip1; | 1903 | goto _skip1; |
1903 | if (atomic_read(&psubstream->runtime->mmap_count)) | 1904 | if (atomic_read(&psubstream->mmap_count)) |
1904 | snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt); | 1905 | snd_pcm_oss_simulate_fill(psubstream, runtime->hw_ptr_interrupt); |
1905 | runtime->oss.trigger = 1; | 1906 | runtime->oss.trigger = 1; |
1906 | runtime->start_threshold = 1; | 1907 | runtime->start_threshold = 1; |
@@ -2018,7 +2019,7 @@ static int snd_pcm_oss_get_ptr(struct snd_pcm_oss_file *pcm_oss_file, int stream | |||
2018 | if (err < 0) | 2019 | if (err < 0) |
2019 | return err; | 2020 | return err; |
2020 | info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); | 2021 | info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size); |
2021 | if (atomic_read(&runtime->mmap_count)) { | 2022 | if (atomic_read(&substream->mmap_count)) { |
2022 | snd_pcm_sframes_t n; | 2023 | snd_pcm_sframes_t n; |
2023 | n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt; | 2024 | n = (delay = runtime->hw_ptr_interrupt) - runtime->oss.prev_hw_ptr_interrupt; |
2024 | if (n < 0) | 2025 | if (n < 0) |
@@ -2574,7 +2575,7 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size | |||
2574 | static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) | 2575 | static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) |
2575 | { | 2576 | { |
2576 | struct snd_pcm_runtime *runtime = substream->runtime; | 2577 | struct snd_pcm_runtime *runtime = substream->runtime; |
2577 | if (atomic_read(&runtime->mmap_count)) | 2578 | if (atomic_read(&substream->mmap_count)) |
2578 | return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; | 2579 | return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; |
2579 | else | 2580 | else |
2580 | return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames; | 2581 | return snd_pcm_playback_avail(runtime) >= runtime->oss.period_frames; |
@@ -2583,7 +2584,7 @@ static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) | |||
2583 | static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) | 2584 | static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) |
2584 | { | 2585 | { |
2585 | struct snd_pcm_runtime *runtime = substream->runtime; | 2586 | struct snd_pcm_runtime *runtime = substream->runtime; |
2586 | if (atomic_read(&runtime->mmap_count)) | 2587 | if (atomic_read(&substream->mmap_count)) |
2587 | return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; | 2588 | return runtime->oss.prev_hw_ptr_interrupt != runtime->hw_ptr_interrupt; |
2588 | else | 2589 | else |
2589 | return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames; | 2590 | return snd_pcm_capture_avail(runtime) >= runtime->oss.period_frames; |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 8136be2e6066..bc00f9b00cbd 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -662,6 +662,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count) | |||
662 | INIT_LIST_HEAD(&substream->self_group.substreams); | 662 | INIT_LIST_HEAD(&substream->self_group.substreams); |
663 | list_add_tail(&substream->link_list, &substream->self_group.substreams); | 663 | list_add_tail(&substream->link_list, &substream->self_group.substreams); |
664 | spin_lock_init(&substream->timer_lock); | 664 | spin_lock_init(&substream->timer_lock); |
665 | atomic_set(&substream->mmap_count, 0); | ||
665 | prev = substream; | 666 | prev = substream; |
666 | } | 667 | } |
667 | return 0; | 668 | return 0; |
@@ -884,7 +885,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, | |||
884 | memset((void*)runtime->control, 0, size); | 885 | memset((void*)runtime->control, 0, size); |
885 | 886 | ||
886 | init_waitqueue_head(&runtime->sleep); | 887 | init_waitqueue_head(&runtime->sleep); |
887 | atomic_set(&runtime->mmap_count, 0); | ||
888 | init_timer(&runtime->tick_timer); | 888 | init_timer(&runtime->tick_timer); |
889 | runtime->tick_timer.function = snd_pcm_tick_timer_func; | 889 | runtime->tick_timer.function = snd_pcm_tick_timer_func; |
890 | runtime->tick_timer.data = (unsigned long) substream; | 890 | runtime->tick_timer.data = (unsigned long) substream; |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 36d6765618a4..a998f88e3f30 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -372,7 +372,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, | |||
372 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) | 372 | #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) |
373 | if (!substream->oss.oss) | 373 | if (!substream->oss.oss) |
374 | #endif | 374 | #endif |
375 | if (atomic_read(&runtime->mmap_count)) | 375 | if (atomic_read(&substream->mmap_count)) |
376 | return -EBADFD; | 376 | return -EBADFD; |
377 | 377 | ||
378 | params->rmask = ~0U; | 378 | params->rmask = ~0U; |
@@ -485,7 +485,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) | |||
485 | return -EBADFD; | 485 | return -EBADFD; |
486 | } | 486 | } |
487 | snd_pcm_stream_unlock_irq(substream); | 487 | snd_pcm_stream_unlock_irq(substream); |
488 | if (atomic_read(&runtime->mmap_count)) | 488 | if (atomic_read(&substream->mmap_count)) |
489 | return -EBADFD; | 489 | return -EBADFD; |
490 | if (substream->ops->hw_free) | 490 | if (substream->ops->hw_free) |
491 | result = substream->ops->hw_free(substream); | 491 | result = substream->ops->hw_free(substream); |
@@ -2207,7 +2207,7 @@ static int snd_pcm_release(struct inode *inode, struct file *file) | |||
2207 | pcm_file = file->private_data; | 2207 | pcm_file = file->private_data; |
2208 | substream = pcm_file->substream; | 2208 | substream = pcm_file->substream; |
2209 | snd_assert(substream != NULL, return -ENXIO); | 2209 | snd_assert(substream != NULL, return -ENXIO); |
2210 | snd_assert(!atomic_read(&substream->runtime->mmap_count), ); | 2210 | snd_assert(!atomic_read(&substream->mmap_count), ); |
2211 | pcm = substream->pcm; | 2211 | pcm = substream->pcm; |
2212 | fasync_helper(-1, file, 0, &substream->runtime->fasync); | 2212 | fasync_helper(-1, file, 0, &substream->runtime->fasync); |
2213 | mutex_lock(&pcm->open_mutex); | 2213 | mutex_lock(&pcm->open_mutex); |
@@ -3178,7 +3178,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream, | |||
3178 | area->vm_ops = &snd_pcm_vm_ops_data; | 3178 | area->vm_ops = &snd_pcm_vm_ops_data; |
3179 | area->vm_private_data = substream; | 3179 | area->vm_private_data = substream; |
3180 | area->vm_flags |= VM_RESERVED; | 3180 | area->vm_flags |= VM_RESERVED; |
3181 | atomic_inc(&substream->runtime->mmap_count); | 3181 | atomic_inc(&substream->mmap_count); |
3182 | return 0; | 3182 | return 0; |
3183 | } | 3183 | } |
3184 | 3184 | ||
@@ -3210,7 +3210,7 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, | |||
3210 | (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, | 3210 | (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, |
3211 | size, area->vm_page_prot)) | 3211 | size, area->vm_page_prot)) |
3212 | return -EAGAIN; | 3212 | return -EAGAIN; |
3213 | atomic_inc(&substream->runtime->mmap_count); | 3213 | atomic_inc(&substream->mmap_count); |
3214 | return 0; | 3214 | return 0; |
3215 | } | 3215 | } |
3216 | 3216 | ||