aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-04-28 09:13:41 -0400
committerJaroslav Kysela <perex@suse.cz>2006-06-22 15:33:14 -0400
commit9c323fcbc51493f79f9700cb20830d0857c72d99 (patch)
tree17e17046c0642f918b9516de8d9517914cabd0ad
parent0df63e44c3e315ec0fe427ae62558231864108bd (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.h6
-rw-r--r--sound/core/oss/pcm_oss.c27
-rw-r--r--sound/core/pcm.c2
-rw-r--r--sound/core/pcm_native.c10
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
972static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) 972static 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
978static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) 978static 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
2574static int snd_pcm_oss_playback_ready(struct snd_pcm_substream *substream) 2575static 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)
2583static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream) 2584static 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