diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-07-31 10:51:51 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-09-23 04:39:50 -0400 |
commit | 548a648b98318e4b843b636dd2c7f42377e19a00 (patch) | |
tree | af08ffaaabd478080656a7fb8df149d37f66cdb8 | |
parent | 1c3985580445ef9225c1ea7714d6d963f7626eeb (diff) |
[ALSA] Fix control/status mmap with shared PCM substream
The flag to avoid 32bit-incompatible mmap for control/status records
should be outside the pcm substream instance since a substream can be
shared among multiple opens. Now it's flagged in pcm_file list that
is directly assigned to file->private_data.
Also, removed snd_pcm_add_file() and remove_file() functions and
substream.files field that are not really used in the code.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
-rw-r--r-- | include/sound/pcm.h | 4 | ||||
-rw-r--r-- | sound/core/pcm_compat.c | 2 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 49 |
3 files changed, 12 insertions, 43 deletions
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index f84d84993a31..60d40b34efc0 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
@@ -190,7 +190,7 @@ struct snd_pcm_ops { | |||
190 | 190 | ||
191 | struct snd_pcm_file { | 191 | struct snd_pcm_file { |
192 | struct snd_pcm_substream *substream; | 192 | struct snd_pcm_substream *substream; |
193 | struct snd_pcm_file *next; | 193 | int no_compat_mmap; |
194 | }; | 194 | }; |
195 | 195 | ||
196 | struct snd_pcm_hw_rule; | 196 | struct snd_pcm_hw_rule; |
@@ -384,7 +384,6 @@ struct snd_pcm_substream { | |||
384 | struct snd_info_entry *proc_prealloc_entry; | 384 | struct snd_info_entry *proc_prealloc_entry; |
385 | #endif | 385 | #endif |
386 | /* misc flags */ | 386 | /* misc flags */ |
387 | unsigned int no_mmap_ctrl: 1; | ||
388 | unsigned int hw_opened: 1; | 387 | unsigned int hw_opened: 1; |
389 | }; | 388 | }; |
390 | 389 | ||
@@ -402,7 +401,6 @@ struct snd_pcm_str { | |||
402 | /* -- OSS things -- */ | 401 | /* -- OSS things -- */ |
403 | struct snd_pcm_oss_stream oss; | 402 | struct snd_pcm_oss_stream oss; |
404 | #endif | 403 | #endif |
405 | struct snd_pcm_file *files; | ||
406 | #ifdef CONFIG_SND_VERBOSE_PROCFS | 404 | #ifdef CONFIG_SND_VERBOSE_PROCFS |
407 | struct snd_info_entry *proc_root; | 405 | struct snd_info_entry *proc_root; |
408 | struct snd_info_entry *proc_info_entry; | 406 | struct snd_info_entry *proc_info_entry; |
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 2b8aab6fd6cd..2b539799d23b 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c | |||
@@ -478,7 +478,7 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l | |||
478 | * mmap of PCM status/control records because of the size | 478 | * mmap of PCM status/control records because of the size |
479 | * incompatibility. | 479 | * incompatibility. |
480 | */ | 480 | */ |
481 | substream->no_mmap_ctrl = 1; | 481 | pcm_file->no_compat_mmap = 1; |
482 | 482 | ||
483 | switch (cmd) { | 483 | switch (cmd) { |
484 | case SNDRV_PCM_IOCTL_PVERSION: | 484 | case SNDRV_PCM_IOCTL_PVERSION: |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 439f047929e1..0224c70414f5 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -1992,35 +1992,9 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) | |||
1992 | return 0; | 1992 | return 0; |
1993 | } | 1993 | } |
1994 | 1994 | ||
1995 | static void snd_pcm_add_file(struct snd_pcm_str *str, | ||
1996 | struct snd_pcm_file *pcm_file) | ||
1997 | { | ||
1998 | pcm_file->next = str->files; | ||
1999 | str->files = pcm_file; | ||
2000 | } | ||
2001 | |||
2002 | static void snd_pcm_remove_file(struct snd_pcm_str *str, | ||
2003 | struct snd_pcm_file *pcm_file) | ||
2004 | { | ||
2005 | struct snd_pcm_file * pcm_file1; | ||
2006 | if (str->files == pcm_file) { | ||
2007 | str->files = pcm_file->next; | ||
2008 | } else { | ||
2009 | pcm_file1 = str->files; | ||
2010 | while (pcm_file1 && pcm_file1->next != pcm_file) | ||
2011 | pcm_file1 = pcm_file1->next; | ||
2012 | if (pcm_file1 != NULL) | ||
2013 | pcm_file1->next = pcm_file->next; | ||
2014 | } | ||
2015 | } | ||
2016 | |||
2017 | static void pcm_release_private(struct snd_pcm_substream *substream) | 1995 | static void pcm_release_private(struct snd_pcm_substream *substream) |
2018 | { | 1996 | { |
2019 | struct snd_pcm_file *pcm_file = substream->file; | ||
2020 | |||
2021 | snd_pcm_unlink(substream); | 1997 | snd_pcm_unlink(substream); |
2022 | snd_pcm_remove_file(substream->pstr, pcm_file); | ||
2023 | kfree(pcm_file); | ||
2024 | } | 1998 | } |
2025 | 1999 | ||
2026 | void snd_pcm_release_substream(struct snd_pcm_substream *substream) | 2000 | void snd_pcm_release_substream(struct snd_pcm_substream *substream) |
@@ -2060,7 +2034,6 @@ int snd_pcm_open_substream(struct snd_pcm *pcm, int stream, | |||
2060 | return 0; | 2034 | return 0; |
2061 | } | 2035 | } |
2062 | 2036 | ||
2063 | substream->no_mmap_ctrl = 0; | ||
2064 | err = snd_pcm_hw_constraints_init(substream); | 2037 | err = snd_pcm_hw_constraints_init(substream); |
2065 | if (err < 0) { | 2038 | if (err < 0) { |
2066 | snd_printd("snd_pcm_hw_constraints_init failed\n"); | 2039 | snd_printd("snd_pcm_hw_constraints_init failed\n"); |
@@ -2105,19 +2078,16 @@ static int snd_pcm_open_file(struct file *file, | |||
2105 | if (err < 0) | 2078 | if (err < 0) |
2106 | return err; | 2079 | return err; |
2107 | 2080 | ||
2108 | if (substream->ref_count > 1) | 2081 | pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); |
2109 | pcm_file = substream->file; | 2082 | if (pcm_file == NULL) { |
2110 | else { | 2083 | snd_pcm_release_substream(substream); |
2111 | pcm_file = kzalloc(sizeof(*pcm_file), GFP_KERNEL); | 2084 | return -ENOMEM; |
2112 | if (pcm_file == NULL) { | 2085 | } |
2113 | snd_pcm_release_substream(substream); | 2086 | pcm_file->substream = substream; |
2114 | return -ENOMEM; | 2087 | if (substream->ref_count == 1) { |
2115 | } | ||
2116 | str = substream->pstr; | 2088 | str = substream->pstr; |
2117 | substream->file = pcm_file; | 2089 | substream->file = pcm_file; |
2118 | substream->pcm_release = pcm_release_private; | 2090 | substream->pcm_release = pcm_release_private; |
2119 | pcm_file->substream = substream; | ||
2120 | snd_pcm_add_file(str, pcm_file); | ||
2121 | } | 2091 | } |
2122 | file->private_data = pcm_file; | 2092 | file->private_data = pcm_file; |
2123 | *rpcm_file = pcm_file; | 2093 | *rpcm_file = pcm_file; |
@@ -2209,6 +2179,7 @@ static int snd_pcm_release(struct inode *inode, struct file *file) | |||
2209 | fasync_helper(-1, file, 0, &substream->runtime->fasync); | 2179 | fasync_helper(-1, file, 0, &substream->runtime->fasync); |
2210 | mutex_lock(&pcm->open_mutex); | 2180 | mutex_lock(&pcm->open_mutex); |
2211 | snd_pcm_release_substream(substream); | 2181 | snd_pcm_release_substream(substream); |
2182 | kfree(pcm_file); | ||
2212 | mutex_unlock(&pcm->open_mutex); | 2183 | mutex_unlock(&pcm->open_mutex); |
2213 | wake_up(&pcm->open_wait); | 2184 | wake_up(&pcm->open_wait); |
2214 | module_put(pcm->card->module); | 2185 | module_put(pcm->card->module); |
@@ -3270,11 +3241,11 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) | |||
3270 | offset = area->vm_pgoff << PAGE_SHIFT; | 3241 | offset = area->vm_pgoff << PAGE_SHIFT; |
3271 | switch (offset) { | 3242 | switch (offset) { |
3272 | case SNDRV_PCM_MMAP_OFFSET_STATUS: | 3243 | case SNDRV_PCM_MMAP_OFFSET_STATUS: |
3273 | if (substream->no_mmap_ctrl) | 3244 | if (pcm_file->no_compat_mmap) |
3274 | return -ENXIO; | 3245 | return -ENXIO; |
3275 | return snd_pcm_mmap_status(substream, file, area); | 3246 | return snd_pcm_mmap_status(substream, file, area); |
3276 | case SNDRV_PCM_MMAP_OFFSET_CONTROL: | 3247 | case SNDRV_PCM_MMAP_OFFSET_CONTROL: |
3277 | if (substream->no_mmap_ctrl) | 3248 | if (pcm_file->no_compat_mmap) |
3278 | return -ENXIO; | 3249 | return -ENXIO; |
3279 | return snd_pcm_mmap_control(substream, file, area); | 3250 | return snd_pcm_mmap_control(substream, file, area); |
3280 | default: | 3251 | default: |