aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-20 12:41:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-20 12:41:44 -0400
commit7f06a8b26aba1dc03b42272dc0089a800372c575 (patch)
tree7c67198f83d069eb13fd417e022d111b7e4c82a1 /sound/core
parentc3ad33c9bcb6616999953af76f16318120fe3691 (diff)
parentd71f4cece4bd97d05592836202fc04ff2e7817e3 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (250 commits) ALSA: hda: Storage class should be before const qualifier ASoC: tpa6130a2: Remove CPVSS and HPVdd supplies ASoC: tpa6130a2: Define output pins with SND_SOC_DAPM_OUTPUT ASoC: sdp4430 - add sdp4430 pcm ops to DAI. ASoC: TWL6040: Enable earphone path in codec ASoC: SDP4430: Add support for Earphone speaker ASoC: SDP4430: Add sdp4430 machine driver ASoC: tlv320dac33: Avoid powering off while in BIAS_OFF ASoC: tlv320dac33: Use dev_dbg in dac33_hard_power function ALSA: sound/pci/asihpi: Use kzalloc ALSA: hdmi - dont fail on extra nodes ALSA: intelhdmi - add id for the CougarPoint chipset ALSA: intelhdmi - user friendly codec name ALSA: intelhdmi - add dependency on SND_DYNAMIC_MINORS ALSA: asihpi: incorrect range check ALSA: asihpi: testing the wrong variable ALSA: es1688: add pedantic range checks ARM: McBSP: Add support for omap4 in McBSP driver ARM: McBSP: Fix request for irq in OMAP4 OMAP: McBSP: Add 32-bit mode support ...
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/control.c5
-rw-r--r--sound/core/info.c74
-rw-r--r--sound/core/jack.c71
-rw-r--r--sound/core/oss/mixer_oss.c5
-rw-r--r--sound/core/oss/pcm_oss.c5
-rw-r--r--sound/core/pcm_native.c49
-rw-r--r--sound/core/rawmidi.c5
-rw-r--r--sound/core/seq/seq_clientmgr.c6
-rw-r--r--sound/core/sound.c73
-rw-r--r--sound/core/timer.c6
10 files changed, 210 insertions, 89 deletions
diff --git a/sound/core/control.c b/sound/core/control.c
index 439ce64f9d82..070aab490191 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -50,6 +50,10 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
50 struct snd_ctl_file *ctl; 50 struct snd_ctl_file *ctl;
51 int err; 51 int err;
52 52
53 err = nonseekable_open(inode, file);
54 if (err < 0)
55 return err;
56
53 card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL); 57 card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
54 if (!card) { 58 if (!card) {
55 err = -ENODEV; 59 err = -ENODEV;
@@ -1388,6 +1392,7 @@ static const struct file_operations snd_ctl_f_ops =
1388 .read = snd_ctl_read, 1392 .read = snd_ctl_read,
1389 .open = snd_ctl_open, 1393 .open = snd_ctl_open,
1390 .release = snd_ctl_release, 1394 .release = snd_ctl_release,
1395 .llseek = no_llseek,
1391 .poll = snd_ctl_poll, 1396 .poll = snd_ctl_poll,
1392 .unlocked_ioctl = snd_ctl_ioctl, 1397 .unlocked_ioctl = snd_ctl_ioctl,
1393 .compat_ioctl = snd_ctl_ioctl_compat, 1398 .compat_ioctl = snd_ctl_ioctl_compat,
diff --git a/sound/core/info.c b/sound/core/info.c
index cc4a53d4b7f8..b70564ed8b37 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -164,40 +164,44 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
164{ 164{
165 struct snd_info_private_data *data; 165 struct snd_info_private_data *data;
166 struct snd_info_entry *entry; 166 struct snd_info_entry *entry;
167 loff_t ret; 167 loff_t ret = -EINVAL, size;
168 168
169 data = file->private_data; 169 data = file->private_data;
170 entry = data->entry; 170 entry = data->entry;
171 lock_kernel(); 171 mutex_lock(&entry->access);
172 switch (entry->content) { 172 if (entry->content == SNDRV_INFO_CONTENT_DATA &&
173 case SNDRV_INFO_CONTENT_TEXT: 173 entry->c.ops->llseek) {
174 switch (orig) { 174 offset = entry->c.ops->llseek(entry,
175 case SEEK_SET: 175 data->file_private_data,
176 file->f_pos = offset; 176 file, offset, orig);
177 ret = file->f_pos; 177 goto out;
178 goto out; 178 }
179 case SEEK_CUR: 179 if (entry->content == SNDRV_INFO_CONTENT_DATA)
180 file->f_pos += offset; 180 size = entry->size;
181 ret = file->f_pos; 181 else
182 goto out; 182 size = 0;
183 case SEEK_END: 183 switch (orig) {
184 default: 184 case SEEK_SET:
185 ret = -EINVAL;
186 goto out;
187 }
188 break; 185 break;
189 case SNDRV_INFO_CONTENT_DATA: 186 case SEEK_CUR:
190 if (entry->c.ops->llseek) { 187 offset += file->f_pos;
191 ret = entry->c.ops->llseek(entry, 188 break;
192 data->file_private_data, 189 case SEEK_END:
193 file, offset, orig); 190 if (!size)
194 goto out; 191 goto out;
195 } 192 offset += size;
196 break; 193 break;
197 } 194 default:
198 ret = -ENXIO; 195 goto out;
199out: 196 }
200 unlock_kernel(); 197 if (offset < 0)
198 goto out;
199 if (size && offset > size)
200 offset = size;
201 file->f_pos = offset;
202 ret = offset;
203 out:
204 mutex_unlock(&entry->access);
201 return ret; 205 return ret;
202} 206}
203 207
@@ -232,10 +236,15 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
232 return -EFAULT; 236 return -EFAULT;
233 break; 237 break;
234 case SNDRV_INFO_CONTENT_DATA: 238 case SNDRV_INFO_CONTENT_DATA:
235 if (entry->c.ops->read) 239 if (pos >= entry->size)
240 return 0;
241 if (entry->c.ops->read) {
242 size = entry->size - pos;
243 size = min(count, size);
236 size = entry->c.ops->read(entry, 244 size = entry->c.ops->read(entry,
237 data->file_private_data, 245 data->file_private_data,
238 file, buffer, count, pos); 246 file, buffer, size, pos);
247 }
239 break; 248 break;
240 } 249 }
241 if ((ssize_t) size > 0) 250 if ((ssize_t) size > 0)
@@ -282,10 +291,13 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer
282 size = count; 291 size = count;
283 break; 292 break;
284 case SNDRV_INFO_CONTENT_DATA: 293 case SNDRV_INFO_CONTENT_DATA:
285 if (entry->c.ops->write) 294 if (entry->c.ops->write && count > 0) {
295 size_t maxsize = entry->size - pos;
296 count = min(count, maxsize);
286 size = entry->c.ops->write(entry, 297 size = entry->c.ops->write(entry,
287 data->file_private_data, 298 data->file_private_data,
288 file, buffer, count, pos); 299 file, buffer, count, pos);
300 }
289 break; 301 break;
290 } 302 }
291 if ((ssize_t) size > 0) 303 if ((ssize_t) size > 0)
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 14b8a4ee690d..4902ae568730 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -24,7 +24,7 @@
24#include <sound/jack.h> 24#include <sound/jack.h>
25#include <sound/core.h> 25#include <sound/core.h>
26 26
27static int jack_types[] = { 27static int jack_switch_types[] = {
28 SW_HEADPHONE_INSERT, 28 SW_HEADPHONE_INSERT,
29 SW_MICROPHONE_INSERT, 29 SW_MICROPHONE_INSERT,
30 SW_LINEOUT_INSERT, 30 SW_LINEOUT_INSERT,
@@ -56,7 +56,7 @@ static int snd_jack_dev_register(struct snd_device *device)
56{ 56{
57 struct snd_jack *jack = device->device_data; 57 struct snd_jack *jack = device->device_data;
58 struct snd_card *card = device->card; 58 struct snd_card *card = device->card;
59 int err; 59 int err, i;
60 60
61 snprintf(jack->name, sizeof(jack->name), "%s %s", 61 snprintf(jack->name, sizeof(jack->name), "%s %s",
62 card->shortname, jack->id); 62 card->shortname, jack->id);
@@ -66,6 +66,19 @@ static int snd_jack_dev_register(struct snd_device *device)
66 if (!jack->input_dev->dev.parent) 66 if (!jack->input_dev->dev.parent)
67 jack->input_dev->dev.parent = snd_card_get_device_link(card); 67 jack->input_dev->dev.parent = snd_card_get_device_link(card);
68 68
69 /* Add capabilities for any keys that are enabled */
70 for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
71 int testbit = SND_JACK_BTN_0 >> i;
72
73 if (!(jack->type & testbit))
74 continue;
75
76 if (!jack->key[i])
77 jack->key[i] = BTN_0 + i;
78
79 input_set_capability(jack->input_dev, EV_KEY, jack->key[i]);
80 }
81
69 err = input_register_device(jack->input_dev); 82 err = input_register_device(jack->input_dev);
70 if (err == 0) 83 if (err == 0)
71 jack->registered = 1; 84 jack->registered = 1;
@@ -113,10 +126,10 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
113 126
114 jack->type = type; 127 jack->type = type;
115 128
116 for (i = 0; i < ARRAY_SIZE(jack_types); i++) 129 for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++)
117 if (type & (1 << i)) 130 if (type & (1 << i))
118 input_set_capability(jack->input_dev, EV_SW, 131 input_set_capability(jack->input_dev, EV_SW,
119 jack_types[i]); 132 jack_switch_types[i]);
120 133
121 err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops); 134 err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
122 if (err < 0) 135 if (err < 0)
@@ -152,6 +165,43 @@ void snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
152EXPORT_SYMBOL(snd_jack_set_parent); 165EXPORT_SYMBOL(snd_jack_set_parent);
153 166
154/** 167/**
168 * snd_jack_set_key - Set a key mapping on a jack
169 *
170 * @jack: The jack to configure
171 * @type: Jack report type for this key
172 * @keytype: Input layer key type to be reported
173 *
174 * Map a SND_JACK_BTN_ button type to an input layer key, allowing
175 * reporting of keys on accessories via the jack abstraction. If no
176 * mapping is provided but keys are enabled in the jack type then
177 * BTN_n numeric buttons will be reported.
178 *
179 * Note that this is intended to be use by simple devices with small
180 * numbers of keys that can be reported. It is also possible to
181 * access the input device directly - devices with complex input
182 * capabilities on accessories should consider doing this rather than
183 * using this abstraction.
184 *
185 * This function may only be called prior to registration of the jack.
186 */
187int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
188 int keytype)
189{
190 int key = fls(SND_JACK_BTN_0) - fls(type);
191
192 WARN_ON(jack->registered);
193
194 if (!keytype || key >= ARRAY_SIZE(jack->key))
195 return -EINVAL;
196
197 jack->type |= type;
198 jack->key[key] = keytype;
199
200 return 0;
201}
202EXPORT_SYMBOL(snd_jack_set_key);
203
204/**
155 * snd_jack_report - Report the current status of a jack 205 * snd_jack_report - Report the current status of a jack
156 * 206 *
157 * @jack: The jack to report status for 207 * @jack: The jack to report status for
@@ -164,10 +214,19 @@ void snd_jack_report(struct snd_jack *jack, int status)
164 if (!jack) 214 if (!jack)
165 return; 215 return;
166 216
167 for (i = 0; i < ARRAY_SIZE(jack_types); i++) { 217 for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
218 int testbit = SND_JACK_BTN_0 >> i;
219
220 if (jack->type & testbit)
221 input_report_key(jack->input_dev, jack->key[i],
222 status & testbit);
223 }
224
225 for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
168 int testbit = 1 << i; 226 int testbit = 1 << i;
169 if (jack->type & testbit) 227 if (jack->type & testbit)
170 input_report_switch(jack->input_dev, jack_types[i], 228 input_report_switch(jack->input_dev,
229 jack_switch_types[i],
171 status & testbit); 230 status & testbit);
172 } 231 }
173 232
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 54e2eb56e4c2..f50ebf20df96 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -43,6 +43,10 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
43 struct snd_mixer_oss_file *fmixer; 43 struct snd_mixer_oss_file *fmixer;
44 int err; 44 int err;
45 45
46 err = nonseekable_open(inode, file);
47 if (err < 0)
48 return err;
49
46 card = snd_lookup_oss_minor_data(iminor(inode), 50 card = snd_lookup_oss_minor_data(iminor(inode),
47 SNDRV_OSS_DEVICE_TYPE_MIXER); 51 SNDRV_OSS_DEVICE_TYPE_MIXER);
48 if (card == NULL) 52 if (card == NULL)
@@ -397,6 +401,7 @@ static const struct file_operations snd_mixer_oss_f_ops =
397 .owner = THIS_MODULE, 401 .owner = THIS_MODULE,
398 .open = snd_mixer_oss_open, 402 .open = snd_mixer_oss_open,
399 .release = snd_mixer_oss_release, 403 .release = snd_mixer_oss_release,
404 .llseek = no_llseek,
400 .unlocked_ioctl = snd_mixer_oss_ioctl, 405 .unlocked_ioctl = snd_mixer_oss_ioctl,
401 .compat_ioctl = snd_mixer_oss_ioctl_compat, 406 .compat_ioctl = snd_mixer_oss_ioctl_compat,
402}; 407};
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 82d4e3329b3d..5c8c7dff8ede 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2379,6 +2379,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
2379 int nonblock; 2379 int nonblock;
2380 wait_queue_t wait; 2380 wait_queue_t wait;
2381 2381
2382 err = nonseekable_open(inode, file);
2383 if (err < 0)
2384 return err;
2385
2382 pcm = snd_lookup_oss_minor_data(iminor(inode), 2386 pcm = snd_lookup_oss_minor_data(iminor(inode),
2383 SNDRV_OSS_DEVICE_TYPE_PCM); 2387 SNDRV_OSS_DEVICE_TYPE_PCM);
2384 if (pcm == NULL) { 2388 if (pcm == NULL) {
@@ -2977,6 +2981,7 @@ static const struct file_operations snd_pcm_oss_f_reg =
2977 .write = snd_pcm_oss_write, 2981 .write = snd_pcm_oss_write,
2978 .open = snd_pcm_oss_open, 2982 .open = snd_pcm_oss_open,
2979 .release = snd_pcm_oss_release, 2983 .release = snd_pcm_oss_release,
2984 .llseek = no_llseek,
2980 .poll = snd_pcm_oss_poll, 2985 .poll = snd_pcm_oss_poll,
2981 .unlocked_ioctl = snd_pcm_oss_ioctl, 2986 .unlocked_ioctl = snd_pcm_oss_ioctl,
2982 .compat_ioctl = snd_pcm_oss_ioctl_compat, 2987 .compat_ioctl = snd_pcm_oss_ioctl_compat,
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 192dd407512f..644c2bb17b86 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2112,7 +2112,9 @@ static int snd_pcm_open_file(struct file *file,
2112static int snd_pcm_playback_open(struct inode *inode, struct file *file) 2112static int snd_pcm_playback_open(struct inode *inode, struct file *file)
2113{ 2113{
2114 struct snd_pcm *pcm; 2114 struct snd_pcm *pcm;
2115 2115 int err = nonseekable_open(inode, file);
2116 if (err < 0)
2117 return err;
2116 pcm = snd_lookup_minor_data(iminor(inode), 2118 pcm = snd_lookup_minor_data(iminor(inode),
2117 SNDRV_DEVICE_TYPE_PCM_PLAYBACK); 2119 SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
2118 return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); 2120 return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
@@ -2121,7 +2123,9 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)
2121static int snd_pcm_capture_open(struct inode *inode, struct file *file) 2123static int snd_pcm_capture_open(struct inode *inode, struct file *file)
2122{ 2124{
2123 struct snd_pcm *pcm; 2125 struct snd_pcm *pcm;
2124 2126 int err = nonseekable_open(inode, file);
2127 if (err < 0)
2128 return err;
2125 pcm = snd_lookup_minor_data(iminor(inode), 2129 pcm = snd_lookup_minor_data(iminor(inode),
2126 SNDRV_DEVICE_TYPE_PCM_CAPTURE); 2130 SNDRV_DEVICE_TYPE_PCM_CAPTURE);
2127 return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); 2131 return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
@@ -3312,18 +3316,13 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
3312 struct snd_pcm_file * pcm_file; 3316 struct snd_pcm_file * pcm_file;
3313 struct snd_pcm_substream *substream; 3317 struct snd_pcm_substream *substream;
3314 struct snd_pcm_runtime *runtime; 3318 struct snd_pcm_runtime *runtime;
3315 int err = -ENXIO;
3316 3319
3317 lock_kernel();
3318 pcm_file = file->private_data; 3320 pcm_file = file->private_data;
3319 substream = pcm_file->substream; 3321 substream = pcm_file->substream;
3320 if (PCM_RUNTIME_CHECK(substream)) 3322 if (PCM_RUNTIME_CHECK(substream))
3321 goto out; 3323 return -ENXIO;
3322 runtime = substream->runtime; 3324 runtime = substream->runtime;
3323 err = fasync_helper(fd, file, on, &runtime->fasync); 3325 return fasync_helper(fd, file, on, &runtime->fasync);
3324out:
3325 unlock_kernel();
3326 return err;
3327} 3326}
3328 3327
3329/* 3328/*
@@ -3443,14 +3442,28 @@ out:
3443#endif /* CONFIG_SND_SUPPORT_OLD_API */ 3442#endif /* CONFIG_SND_SUPPORT_OLD_API */
3444 3443
3445#ifndef CONFIG_MMU 3444#ifndef CONFIG_MMU
3446unsigned long dummy_get_unmapped_area(struct file *file, unsigned long addr, 3445static unsigned long snd_pcm_get_unmapped_area(struct file *file,
3447 unsigned long len, unsigned long pgoff, 3446 unsigned long addr,
3448 unsigned long flags) 3447 unsigned long len,
3449{ 3448 unsigned long pgoff,
3450 return 0; 3449 unsigned long flags)
3450{
3451 struct snd_pcm_file *pcm_file = file->private_data;
3452 struct snd_pcm_substream *substream = pcm_file->substream;
3453 struct snd_pcm_runtime *runtime = substream->runtime;
3454 unsigned long offset = pgoff << PAGE_SHIFT;
3455
3456 switch (offset) {
3457 case SNDRV_PCM_MMAP_OFFSET_STATUS:
3458 return (unsigned long)runtime->status;
3459 case SNDRV_PCM_MMAP_OFFSET_CONTROL:
3460 return (unsigned long)runtime->control;
3461 default:
3462 return (unsigned long)runtime->dma_area + offset;
3463 }
3451} 3464}
3452#else 3465#else
3453# define dummy_get_unmapped_area NULL 3466# define snd_pcm_get_unmapped_area NULL
3454#endif 3467#endif
3455 3468
3456/* 3469/*
@@ -3464,12 +3477,13 @@ const struct file_operations snd_pcm_f_ops[2] = {
3464 .aio_write = snd_pcm_aio_write, 3477 .aio_write = snd_pcm_aio_write,
3465 .open = snd_pcm_playback_open, 3478 .open = snd_pcm_playback_open,
3466 .release = snd_pcm_release, 3479 .release = snd_pcm_release,
3480 .llseek = no_llseek,
3467 .poll = snd_pcm_playback_poll, 3481 .poll = snd_pcm_playback_poll,
3468 .unlocked_ioctl = snd_pcm_playback_ioctl, 3482 .unlocked_ioctl = snd_pcm_playback_ioctl,
3469 .compat_ioctl = snd_pcm_ioctl_compat, 3483 .compat_ioctl = snd_pcm_ioctl_compat,
3470 .mmap = snd_pcm_mmap, 3484 .mmap = snd_pcm_mmap,
3471 .fasync = snd_pcm_fasync, 3485 .fasync = snd_pcm_fasync,
3472 .get_unmapped_area = dummy_get_unmapped_area, 3486 .get_unmapped_area = snd_pcm_get_unmapped_area,
3473 }, 3487 },
3474 { 3488 {
3475 .owner = THIS_MODULE, 3489 .owner = THIS_MODULE,
@@ -3477,11 +3491,12 @@ const struct file_operations snd_pcm_f_ops[2] = {
3477 .aio_read = snd_pcm_aio_read, 3491 .aio_read = snd_pcm_aio_read,
3478 .open = snd_pcm_capture_open, 3492 .open = snd_pcm_capture_open,
3479 .release = snd_pcm_release, 3493 .release = snd_pcm_release,
3494 .llseek = no_llseek,
3480 .poll = snd_pcm_capture_poll, 3495 .poll = snd_pcm_capture_poll,
3481 .unlocked_ioctl = snd_pcm_capture_ioctl, 3496 .unlocked_ioctl = snd_pcm_capture_ioctl,
3482 .compat_ioctl = snd_pcm_ioctl_compat, 3497 .compat_ioctl = snd_pcm_ioctl_compat,
3483 .mmap = snd_pcm_mmap, 3498 .mmap = snd_pcm_mmap,
3484 .fasync = snd_pcm_fasync, 3499 .fasync = snd_pcm_fasync,
3485 .get_unmapped_area = dummy_get_unmapped_area, 3500 .get_unmapped_area = snd_pcm_get_unmapped_area,
3486 } 3501 }
3487}; 3502};
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 0f5a194695d9..eb68326c37d4 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -376,6 +376,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
376 if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) 376 if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
377 return -EINVAL; /* invalid combination */ 377 return -EINVAL; /* invalid combination */
378 378
379 err = nonseekable_open(inode, file);
380 if (err < 0)
381 return err;
382
379 if (maj == snd_major) { 383 if (maj == snd_major) {
380 rmidi = snd_lookup_minor_data(iminor(inode), 384 rmidi = snd_lookup_minor_data(iminor(inode),
381 SNDRV_DEVICE_TYPE_RAWMIDI); 385 SNDRV_DEVICE_TYPE_RAWMIDI);
@@ -1391,6 +1395,7 @@ static const struct file_operations snd_rawmidi_f_ops =
1391 .write = snd_rawmidi_write, 1395 .write = snd_rawmidi_write,
1392 .open = snd_rawmidi_open, 1396 .open = snd_rawmidi_open,
1393 .release = snd_rawmidi_release, 1397 .release = snd_rawmidi_release,
1398 .llseek = no_llseek,
1394 .poll = snd_rawmidi_poll, 1399 .poll = snd_rawmidi_poll,
1395 .unlocked_ioctl = snd_rawmidi_ioctl, 1400 .unlocked_ioctl = snd_rawmidi_ioctl,
1396 .compat_ioctl = snd_rawmidi_ioctl_compat, 1401 .compat_ioctl = snd_rawmidi_ioctl_compat,
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 48eca9ff9ee7..99a485f13648 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -318,6 +318,11 @@ static int snd_seq_open(struct inode *inode, struct file *file)
318 int c, mode; /* client id */ 318 int c, mode; /* client id */
319 struct snd_seq_client *client; 319 struct snd_seq_client *client;
320 struct snd_seq_user_client *user; 320 struct snd_seq_user_client *user;
321 int err;
322
323 err = nonseekable_open(inode, file);
324 if (err < 0)
325 return err;
321 326
322 if (mutex_lock_interruptible(&register_mutex)) 327 if (mutex_lock_interruptible(&register_mutex))
323 return -ERESTARTSYS; 328 return -ERESTARTSYS;
@@ -2550,6 +2555,7 @@ static const struct file_operations snd_seq_f_ops =
2550 .write = snd_seq_write, 2555 .write = snd_seq_write,
2551 .open = snd_seq_open, 2556 .open = snd_seq_open,
2552 .release = snd_seq_release, 2557 .release = snd_seq_release,
2558 .llseek = no_llseek,
2553 .poll = snd_seq_poll, 2559 .poll = snd_seq_poll,
2554 .unlocked_ioctl = snd_seq_ioctl, 2560 .unlocked_ioctl = snd_seq_ioctl,
2555 .compat_ioctl = snd_seq_ioctl_compat, 2561 .compat_ioctl = snd_seq_ioctl_compat,
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 563d1967a0ad..ac42af42b787 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -120,7 +120,29 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
120 120
121EXPORT_SYMBOL(snd_lookup_minor_data); 121EXPORT_SYMBOL(snd_lookup_minor_data);
122 122
123static int __snd_open(struct inode *inode, struct file *file) 123#ifdef CONFIG_MODULES
124static struct snd_minor *autoload_device(unsigned int minor)
125{
126 int dev;
127 mutex_unlock(&sound_mutex); /* release lock temporarily */
128 dev = SNDRV_MINOR_DEVICE(minor);
129 if (dev == SNDRV_MINOR_CONTROL) {
130 /* /dev/aloadC? */
131 int card = SNDRV_MINOR_CARD(minor);
132 if (snd_cards[card] == NULL)
133 snd_request_card(card);
134 } else if (dev == SNDRV_MINOR_GLOBAL) {
135 /* /dev/aloadSEQ */
136 snd_request_other(minor);
137 }
138 mutex_lock(&sound_mutex); /* reacuire lock */
139 return snd_minors[minor];
140}
141#else /* !CONFIG_MODULES */
142#define autoload_device(minor) NULL
143#endif /* CONFIG_MODULES */
144
145static int snd_open(struct inode *inode, struct file *file)
124{ 146{
125 unsigned int minor = iminor(inode); 147 unsigned int minor = iminor(inode);
126 struct snd_minor *mptr = NULL; 148 struct snd_minor *mptr = NULL;
@@ -129,55 +151,36 @@ static int __snd_open(struct inode *inode, struct file *file)
129 151
130 if (minor >= ARRAY_SIZE(snd_minors)) 152 if (minor >= ARRAY_SIZE(snd_minors))
131 return -ENODEV; 153 return -ENODEV;
154 mutex_lock(&sound_mutex);
132 mptr = snd_minors[minor]; 155 mptr = snd_minors[minor];
133 if (mptr == NULL) { 156 if (mptr == NULL) {
134#ifdef CONFIG_MODULES 157 mptr = autoload_device(minor);
135 int dev = SNDRV_MINOR_DEVICE(minor); 158 if (!mptr) {
136 if (dev == SNDRV_MINOR_CONTROL) { 159 mutex_unlock(&sound_mutex);
137 /* /dev/aloadC? */
138 int card = SNDRV_MINOR_CARD(minor);
139 if (snd_cards[card] == NULL)
140 snd_request_card(card);
141 } else if (dev == SNDRV_MINOR_GLOBAL) {
142 /* /dev/aloadSEQ */
143 snd_request_other(minor);
144 }
145#ifndef CONFIG_SND_DYNAMIC_MINORS
146 /* /dev/snd/{controlC?,seq} */
147 mptr = snd_minors[minor];
148 if (mptr == NULL)
149#endif
150#endif
151 return -ENODEV; 160 return -ENODEV;
161 }
152 } 162 }
153 old_fops = file->f_op; 163 old_fops = file->f_op;
154 file->f_op = fops_get(mptr->f_ops); 164 file->f_op = fops_get(mptr->f_ops);
155 if (file->f_op == NULL) { 165 if (file->f_op == NULL) {
156 file->f_op = old_fops; 166 file->f_op = old_fops;
157 return -ENODEV; 167 err = -ENODEV;
158 } 168 }
159 if (file->f_op->open) 169 mutex_unlock(&sound_mutex);
170 if (err < 0)
171 return err;
172
173 if (file->f_op->open) {
160 err = file->f_op->open(inode, file); 174 err = file->f_op->open(inode, file);
161 if (err) { 175 if (err) {
162 fops_put(file->f_op); 176 fops_put(file->f_op);
163 file->f_op = fops_get(old_fops); 177 file->f_op = fops_get(old_fops);
178 }
164 } 179 }
165 fops_put(old_fops); 180 fops_put(old_fops);
166 return err; 181 return err;
167} 182}
168 183
169
170/* BKL pushdown: nasty #ifdef avoidance wrapper */
171static int snd_open(struct inode *inode, struct file *file)
172{
173 int ret;
174
175 lock_kernel();
176 ret = __snd_open(inode, file);
177 unlock_kernel();
178 return ret;
179}
180
181static const struct file_operations snd_fops = 184static const struct file_operations snd_fops =
182{ 185{
183 .owner = THIS_MODULE, 186 .owner = THIS_MODULE,
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 5040c7b862fe..13afb60999b9 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -1238,6 +1238,11 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
1238static int snd_timer_user_open(struct inode *inode, struct file *file) 1238static int snd_timer_user_open(struct inode *inode, struct file *file)
1239{ 1239{
1240 struct snd_timer_user *tu; 1240 struct snd_timer_user *tu;
1241 int err;
1242
1243 err = nonseekable_open(inode, file);
1244 if (err < 0)
1245 return err;
1241 1246
1242 tu = kzalloc(sizeof(*tu), GFP_KERNEL); 1247 tu = kzalloc(sizeof(*tu), GFP_KERNEL);
1243 if (tu == NULL) 1248 if (tu == NULL)
@@ -1922,6 +1927,7 @@ static const struct file_operations snd_timer_f_ops =
1922 .read = snd_timer_user_read, 1927 .read = snd_timer_user_read,
1923 .open = snd_timer_user_open, 1928 .open = snd_timer_user_open,
1924 .release = snd_timer_user_release, 1929 .release = snd_timer_user_release,
1930 .llseek = no_llseek,
1925 .poll = snd_timer_user_poll, 1931 .poll = snd_timer_user_poll,
1926 .unlocked_ioctl = snd_timer_user_ioctl, 1932 .unlocked_ioctl = snd_timer_user_ioctl,
1927 .compat_ioctl = snd_timer_user_ioctl_compat, 1933 .compat_ioctl = snd_timer_user_ioctl_compat,