aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/core.h9
-rw-r--r--include/sound/hwdep.h1
-rw-r--r--include/sound/pcm.h2
-rw-r--r--include/sound/rawmidi.h6
-rw-r--r--sound/core/control.c7
-rw-r--r--sound/core/hwdep.c91
-rw-r--r--sound/core/oss/mixer_oss.c7
-rw-r--r--sound/core/oss/pcm_oss.c14
-rw-r--r--sound/core/pcm.c118
-rw-r--r--sound/core/pcm_native.c40
-rw-r--r--sound/core/rawmidi.c87
-rw-r--r--sound/core/seq/oss/seq_oss.c4
-rw-r--r--sound/core/seq/seq_clientmgr.c2
-rw-r--r--sound/core/seq/seq_midi.c10
-rw-r--r--sound/core/sound.c46
-rw-r--r--sound/core/sound_oss.c27
-rw-r--r--sound/core/timer.c4
17 files changed, 278 insertions, 197 deletions
diff --git a/include/sound/core.h b/include/sound/core.h
index 67b0a7e764e7..90ac6132ea3b 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -187,6 +187,7 @@ struct snd_minor {
187 int card; /* card number */ 187 int card; /* card number */
188 int device; /* device number */ 188 int device; /* device number */
189 struct file_operations *f_ops; /* file operations */ 189 struct file_operations *f_ops; /* file operations */
190 void *private_data; /* private data for f_ops->open */
190 char name[0]; /* device name (keep at the end of 191 char name[0]; /* device name (keep at the end of
191 structure) */ 192 structure) */
192}; 193};
@@ -199,13 +200,17 @@ extern int snd_ecards_limit;
199void snd_request_card(int card); 200void snd_request_card(int card);
200 201
201int snd_register_device(int type, struct snd_card *card, int dev, 202int snd_register_device(int type, struct snd_card *card, int dev,
202 struct file_operations *f_ops, const char *name); 203 struct file_operations *f_ops, void *private_data,
204 const char *name);
203int snd_unregister_device(int type, struct snd_card *card, int dev); 205int snd_unregister_device(int type, struct snd_card *card, int dev);
206void *snd_lookup_minor_data(unsigned int minor, int type);
204 207
205#ifdef CONFIG_SND_OSSEMUL 208#ifdef CONFIG_SND_OSSEMUL
206int snd_register_oss_device(int type, struct snd_card *card, int dev, 209int snd_register_oss_device(int type, struct snd_card *card, int dev,
207 struct file_operations *f_ops, const char *name); 210 struct file_operations *f_ops, void *private_data,
211 const char *name);
208int snd_unregister_oss_device(int type, struct snd_card *card, int dev); 212int snd_unregister_oss_device(int type, struct snd_card *card, int dev);
213void *snd_lookup_oss_minor_data(unsigned int minor, int type);
209#endif 214#endif
210 215
211int snd_minor_info_init(void); 216int snd_minor_info_init(void);
diff --git a/include/sound/hwdep.h b/include/sound/hwdep.h
index 04b20bc4f144..c679e5b31111 100644
--- a/include/sound/hwdep.h
+++ b/include/sound/hwdep.h
@@ -43,6 +43,7 @@ struct snd_hwdep_ops {
43 43
44struct snd_hwdep { 44struct snd_hwdep {
45 struct snd_card *card; 45 struct snd_card *card;
46 struct list_head list;
46 int device; 47 int device;
47 char id[32]; 48 char id[32];
48 char name[80]; 49 char name[80];
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 5e29b0e0f214..314268a11048 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -412,6 +412,7 @@ struct snd_pcm_str {
412 412
413struct snd_pcm { 413struct snd_pcm {
414 struct snd_card *card; 414 struct snd_card *card;
415 struct list_head list;
415 unsigned int device; /* device number */ 416 unsigned int device; /* device number */
416 unsigned int info_flags; 417 unsigned int info_flags;
417 unsigned short dev_class; 418 unsigned short dev_class;
@@ -439,7 +440,6 @@ struct snd_pcm_notify {
439 * Registering 440 * Registering
440 */ 441 */
441 442
442extern struct snd_pcm *snd_pcm_devices[];
443extern struct file_operations snd_pcm_f_ops[2]; 443extern struct file_operations snd_pcm_f_ops[2];
444 444
445int snd_pcm_new(struct snd_card *card, char *id, int device, 445int snd_pcm_new(struct snd_card *card, char *id, int device,
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 9492a32c1026..d19bddfbf995 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -113,7 +113,7 @@ struct snd_rawmidi_str {
113 113
114struct snd_rawmidi { 114struct snd_rawmidi {
115 struct snd_card *card; 115 struct snd_card *card;
116 116 struct list_head list;
117 unsigned int device; /* device number */ 117 unsigned int device; /* device number */
118 unsigned int info_flags; /* SNDRV_RAWMIDI_INFO_XXXX */ 118 unsigned int info_flags; /* SNDRV_RAWMIDI_INFO_XXXX */
119 char id[64]; 119 char id[64];
@@ -165,8 +165,8 @@ int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
165/* main midi functions */ 165/* main midi functions */
166 166
167int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info); 167int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info);
168int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, int mode, 168int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
169 struct snd_rawmidi_file *rfile); 169 int mode, struct snd_rawmidi_file *rfile);
170int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile); 170int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile);
171int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream, 171int snd_rawmidi_output_params(struct snd_rawmidi_substream *substream,
172 struct snd_rawmidi_params *params); 172 struct snd_rawmidi_params *params);
diff --git a/sound/core/control.c b/sound/core/control.c
index 23561e74712b..abd62f943726 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -47,13 +47,12 @@ static LIST_HEAD(snd_control_compat_ioctls);
47 47
48static int snd_ctl_open(struct inode *inode, struct file *file) 48static int snd_ctl_open(struct inode *inode, struct file *file)
49{ 49{
50 int cardnum = SNDRV_MINOR_CARD(iminor(inode));
51 unsigned long flags; 50 unsigned long flags;
52 struct snd_card *card; 51 struct snd_card *card;
53 struct snd_ctl_file *ctl; 52 struct snd_ctl_file *ctl;
54 int err; 53 int err;
55 54
56 card = snd_cards[cardnum]; 55 card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
57 if (!card) { 56 if (!card) {
58 err = -ENODEV; 57 err = -ENODEV;
59 goto __error1; 58 goto __error1;
@@ -1277,8 +1276,8 @@ static int snd_ctl_dev_register(struct snd_device *device)
1277 cardnum = card->number; 1276 cardnum = card->number;
1278 snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); 1277 snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
1279 sprintf(name, "controlC%i", cardnum); 1278 sprintf(name, "controlC%i", cardnum);
1280 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, 1279 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_CONTROL, card, -1,
1281 card, -1, &snd_ctl_f_ops, name)) < 0) 1280 &snd_ctl_f_ops, card, name)) < 0)
1282 return err; 1281 return err;
1283 return 0; 1282 return 0;
1284} 1283}
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 27d5bf7266f0..b8c0c8c4d126 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -35,8 +35,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
35MODULE_DESCRIPTION("Hardware dependent layer"); 35MODULE_DESCRIPTION("Hardware dependent layer");
36MODULE_LICENSE("GPL"); 36MODULE_LICENSE("GPL");
37 37
38static struct snd_hwdep *snd_hwdep_devices[SNDRV_CARDS * SNDRV_MINOR_HWDEPS]; 38static LIST_HEAD(snd_hwdep_devices);
39
40static DECLARE_MUTEX(register_mutex); 39static DECLARE_MUTEX(register_mutex);
41 40
42static int snd_hwdep_free(struct snd_hwdep *hwdep); 41static int snd_hwdep_free(struct snd_hwdep *hwdep);
@@ -44,9 +43,19 @@ static int snd_hwdep_dev_free(struct snd_device *device);
44static int snd_hwdep_dev_register(struct snd_device *device); 43static int snd_hwdep_dev_register(struct snd_device *device);
45static int snd_hwdep_dev_unregister(struct snd_device *device); 44static int snd_hwdep_dev_unregister(struct snd_device *device);
46 45
47/*
48 46
49 */ 47static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device)
48{
49 struct list_head *p;
50 struct snd_hwdep *hwdep;
51
52 list_for_each(p, &snd_hwdep_devices) {
53 hwdep = list_entry(p, struct snd_hwdep, list);
54 if (hwdep->card == card && hwdep->device == device)
55 return hwdep;
56 }
57 return NULL;
58}
50 59
51static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig) 60static loff_t snd_hwdep_llseek(struct file * file, loff_t offset, int orig)
52{ 61{
@@ -77,34 +86,25 @@ static ssize_t snd_hwdep_write(struct file * file, const char __user *buf,
77static int snd_hwdep_open(struct inode *inode, struct file * file) 86static int snd_hwdep_open(struct inode *inode, struct file * file)
78{ 87{
79 int major = imajor(inode); 88 int major = imajor(inode);
80 int cardnum;
81 int device;
82 struct snd_hwdep *hw; 89 struct snd_hwdep *hw;
83 int err; 90 int err;
84 wait_queue_t wait; 91 wait_queue_t wait;
85 92
86 if (major == snd_major) { 93 if (major == snd_major) {
87 cardnum = SNDRV_MINOR_CARD(iminor(inode)); 94 hw = snd_lookup_minor_data(iminor(inode),
88 device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_HWDEP; 95 SNDRV_DEVICE_TYPE_HWDEP);
89#ifdef CONFIG_SND_OSSEMUL 96#ifdef CONFIG_SND_OSSEMUL
90 } else if (major == SOUND_MAJOR) { 97 } else if (major == SOUND_MAJOR) {
91 cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); 98 hw = snd_lookup_oss_minor_data(iminor(inode),
92 device = 0; 99 SNDRV_OSS_DEVICE_TYPE_DMFM);
93#endif 100#endif
94 } else 101 } else
95 return -ENXIO; 102 return -ENXIO;
96 cardnum %= SNDRV_CARDS;
97 device %= SNDRV_MINOR_HWDEPS;
98 hw = snd_hwdep_devices[(cardnum * SNDRV_MINOR_HWDEPS) + device];
99 if (hw == NULL) 103 if (hw == NULL)
100 return -ENODEV; 104 return -ENODEV;
101 105
102 if (!hw->ops.open) 106 if (!hw->ops.open)
103 return -ENXIO; 107 return -ENXIO;
104#ifdef CONFIG_SND_OSSEMUL
105 if (major == SOUND_MAJOR && hw->oss_type < 0)
106 return -ENXIO;
107#endif
108 108
109 if (!try_module_get(hw->card->module)) 109 if (!try_module_get(hw->card->module))
110 return -EFAULT; 110 return -EFAULT;
@@ -265,9 +265,6 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
265 struct snd_ctl_file * control, 265 struct snd_ctl_file * control,
266 unsigned int cmd, unsigned long arg) 266 unsigned int cmd, unsigned long arg)
267{ 267{
268 unsigned int tmp;
269
270 tmp = card->number * SNDRV_MINOR_HWDEPS;
271 switch (cmd) { 268 switch (cmd) {
272 case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE: 269 case SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE:
273 { 270 {
@@ -275,14 +272,16 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
275 272
276 if (get_user(device, (int __user *)arg)) 273 if (get_user(device, (int __user *)arg))
277 return -EFAULT; 274 return -EFAULT;
275 down(&register_mutex);
278 device = device < 0 ? 0 : device + 1; 276 device = device < 0 ? 0 : device + 1;
279 while (device < SNDRV_MINOR_HWDEPS) { 277 while (device < SNDRV_MINOR_HWDEPS) {
280 if (snd_hwdep_devices[tmp + device]) 278 if (snd_hwdep_search(card, device))
281 break; 279 break;
282 device++; 280 device++;
283 } 281 }
284 if (device >= SNDRV_MINOR_HWDEPS) 282 if (device >= SNDRV_MINOR_HWDEPS)
285 device = -1; 283 device = -1;
284 up(&register_mutex);
286 if (put_user(device, (int __user *)arg)) 285 if (put_user(device, (int __user *)arg))
287 return -EFAULT; 286 return -EFAULT;
288 return 0; 287 return 0;
@@ -290,17 +289,19 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
290 case SNDRV_CTL_IOCTL_HWDEP_INFO: 289 case SNDRV_CTL_IOCTL_HWDEP_INFO:
291 { 290 {
292 struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg; 291 struct snd_hwdep_info __user *info = (struct snd_hwdep_info __user *)arg;
293 int device; 292 int device, err;
294 struct snd_hwdep *hwdep; 293 struct snd_hwdep *hwdep;
295 294
296 if (get_user(device, &info->device)) 295 if (get_user(device, &info->device))
297 return -EFAULT; 296 return -EFAULT;
298 if (device < 0 || device >= SNDRV_MINOR_HWDEPS) 297 down(&register_mutex);
299 return -ENXIO; 298 hwdep = snd_hwdep_search(card, device);
300 hwdep = snd_hwdep_devices[tmp + device]; 299 if (hwdep)
301 if (hwdep == NULL) 300 err = snd_hwdep_info(hwdep, info);
302 return -ENXIO; 301 else
303 return snd_hwdep_info(hwdep, info); 302 err = -ENXIO;
303 up(&register_mutex);
304 return err;
304 } 305 }
305 } 306 }
306 return -ENOIOCTLCMD; 307 return -ENOIOCTLCMD;
@@ -397,23 +398,22 @@ static int snd_hwdep_dev_free(struct snd_device *device)
397static int snd_hwdep_dev_register(struct snd_device *device) 398static int snd_hwdep_dev_register(struct snd_device *device)
398{ 399{
399 struct snd_hwdep *hwdep = device->device_data; 400 struct snd_hwdep *hwdep = device->device_data;
400 int idx, err; 401 int err;
401 char name[32]; 402 char name[32];
402 403
403 down(&register_mutex); 404 down(&register_mutex);
404 idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device; 405 if (snd_hwdep_search(hwdep->card, hwdep->device)) {
405 if (snd_hwdep_devices[idx]) {
406 up(&register_mutex); 406 up(&register_mutex);
407 return -EBUSY; 407 return -EBUSY;
408 } 408 }
409 snd_hwdep_devices[idx] = hwdep; 409 list_add_tail(&hwdep->list, &snd_hwdep_devices);
410 sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device); 410 sprintf(name, "hwC%iD%i", hwdep->card->number, hwdep->device);
411 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP, 411 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_HWDEP,
412 hwdep->card, hwdep->device, 412 hwdep->card, hwdep->device,
413 &snd_hwdep_f_ops, name)) < 0) { 413 &snd_hwdep_f_ops, hwdep, name)) < 0) {
414 snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n", 414 snd_printk(KERN_ERR "unable to register hardware dependent device %i:%i\n",
415 hwdep->card->number, hwdep->device); 415 hwdep->card->number, hwdep->device);
416 snd_hwdep_devices[idx] = NULL; 416 list_del(&hwdep->list);
417 up(&register_mutex); 417 up(&register_mutex);
418 return err; 418 return err;
419 } 419 }
@@ -425,7 +425,7 @@ static int snd_hwdep_dev_register(struct snd_device *device)
425 } else { 425 } else {
426 if (snd_register_oss_device(hwdep->oss_type, 426 if (snd_register_oss_device(hwdep->oss_type,
427 hwdep->card, hwdep->device, 427 hwdep->card, hwdep->device,
428 &snd_hwdep_f_ops, 428 &snd_hwdep_f_ops, hwdep,
429 hwdep->oss_dev) < 0) { 429 hwdep->oss_dev) < 0) {
430 snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n", 430 snd_printk(KERN_ERR "unable to register OSS compatibility device %i:%i\n",
431 hwdep->card->number, hwdep->device); 431 hwdep->card->number, hwdep->device);
@@ -441,12 +441,10 @@ static int snd_hwdep_dev_register(struct snd_device *device)
441static int snd_hwdep_dev_unregister(struct snd_device *device) 441static int snd_hwdep_dev_unregister(struct snd_device *device)
442{ 442{
443 struct snd_hwdep *hwdep = device->device_data; 443 struct snd_hwdep *hwdep = device->device_data;
444 int idx;
445 444
446 snd_assert(hwdep != NULL, return -ENXIO); 445 snd_assert(hwdep != NULL, return -ENXIO);
447 down(&register_mutex); 446 down(&register_mutex);
448 idx = (hwdep->card->number * SNDRV_MINOR_HWDEPS) + hwdep->device; 447 if (snd_hwdep_search(hwdep->card, hwdep->device) != hwdep) {
449 if (snd_hwdep_devices[idx] != hwdep) {
450 up(&register_mutex); 448 up(&register_mutex);
451 return -EINVAL; 449 return -EINVAL;
452 } 450 }
@@ -455,7 +453,7 @@ static int snd_hwdep_dev_unregister(struct snd_device *device)
455 snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); 453 snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
456#endif 454#endif
457 snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); 455 snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
458 snd_hwdep_devices[idx] = NULL; 456 list_del(&hwdep->list);
459 up(&register_mutex); 457 up(&register_mutex);
460 return snd_hwdep_free(hwdep); 458 return snd_hwdep_free(hwdep);
461} 459}
@@ -467,18 +465,14 @@ static int snd_hwdep_dev_unregister(struct snd_device *device)
467static void snd_hwdep_proc_read(struct snd_info_entry *entry, 465static void snd_hwdep_proc_read(struct snd_info_entry *entry,
468 struct snd_info_buffer *buffer) 466 struct snd_info_buffer *buffer)
469{ 467{
470 int idx; 468 struct list_head *p;
471 struct snd_hwdep *hwdep; 469 struct snd_hwdep *hwdep;
472 470
473 down(&register_mutex); 471 down(&register_mutex);
474 for (idx = 0; idx < SNDRV_CARDS * SNDRV_MINOR_HWDEPS; idx++) { 472 list_for_each(p, &snd_hwdep_devices) {
475 hwdep = snd_hwdep_devices[idx]; 473 hwdep = list_entry(p, struct snd_hwdep, list);
476 if (hwdep == NULL)
477 continue;
478 snd_iprintf(buffer, "%02i-%02i: %s\n", 474 snd_iprintf(buffer, "%02i-%02i: %s\n",
479 idx / SNDRV_MINOR_HWDEPS, 475 hwdep->card->number, hwdep->device, hwdep->name);
480 idx % SNDRV_MINOR_HWDEPS,
481 hwdep->name);
482 } 476 }
483 up(&register_mutex); 477 up(&register_mutex);
484} 478}
@@ -493,9 +487,8 @@ static int __init alsa_hwdep_init(void)
493{ 487{
494 struct snd_info_entry *entry; 488 struct snd_info_entry *entry;
495 489
496 memset(snd_hwdep_devices, 0, sizeof(snd_hwdep_devices));
497 if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) { 490 if ((entry = snd_info_create_module_entry(THIS_MODULE, "hwdep", NULL)) != NULL) {
498 entry->c.text.read_size = 512; 491 entry->c.text.read_size = PAGE_SIZE;
499 entry->c.text.read = snd_hwdep_proc_read; 492 entry->c.text.read = snd_hwdep_proc_read;
500 if (snd_info_register(entry) < 0) { 493 if (snd_info_register(entry) < 0) {
501 snd_info_free_entry(entry); 494 snd_info_free_entry(entry);
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 2dd6bf9b49ed..2d7a42014f51 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -41,12 +41,13 @@ MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_MIXER);
41 41
42static int snd_mixer_oss_open(struct inode *inode, struct file *file) 42static int snd_mixer_oss_open(struct inode *inode, struct file *file)
43{ 43{
44 int cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode));
45 struct snd_card *card; 44 struct snd_card *card;
46 struct snd_mixer_oss_file *fmixer; 45 struct snd_mixer_oss_file *fmixer;
47 int err; 46 int err;
48 47
49 if ((card = snd_cards[cardnum]) == NULL) 48 card = snd_lookup_oss_minor_data(iminor(inode),
49 SNDRV_OSS_DEVICE_TYPE_MIXER);
50 if (card == NULL)
50 return -ENODEV; 51 return -ENODEV;
51 if (card->mixer_oss == NULL) 52 if (card->mixer_oss == NULL)
52 return -ENODEV; 53 return -ENODEV;
@@ -1286,7 +1287,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
1286 sprintf(name, "mixer%i%i", card->number, 0); 1287 sprintf(name, "mixer%i%i", card->number, 0);
1287 if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, 1288 if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER,
1288 card, 0, 1289 card, 0,
1289 &snd_mixer_oss_f_ops, 1290 &snd_mixer_oss_f_ops, card,
1290 name)) < 0) { 1291 name)) < 0) {
1291 snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n", 1292 snd_printk(KERN_ERR "unable to register OSS mixer device %i:%i\n",
1292 card->number, 0); 1293 card->number, 0);
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 947bf08df42a..2ae283c7b28a 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1834,9 +1834,6 @@ static int snd_task_name(struct task_struct *task, char *name, size_t size)
1834 1834
1835static int snd_pcm_oss_open(struct inode *inode, struct file *file) 1835static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1836{ 1836{
1837 int minor = iminor(inode);
1838 int cardnum = SNDRV_MINOR_OSS_CARD(minor);
1839 int device;
1840 int err; 1837 int err;
1841 char task_name[32]; 1838 char task_name[32];
1842 struct snd_pcm *pcm; 1839 struct snd_pcm *pcm;
@@ -1845,11 +1842,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1845 int nonblock; 1842 int nonblock;
1846 wait_queue_t wait; 1843 wait_queue_t wait;
1847 1844
1848 snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); 1845 pcm = snd_lookup_oss_minor_data(iminor(inode),
1849 device = SNDRV_MINOR_OSS_DEVICE(minor) == SNDRV_MINOR_OSS_PCM1 ? 1846 SNDRV_OSS_DEVICE_TYPE_PCM);
1850 adsp_map[cardnum] : dsp_map[cardnum];
1851
1852 pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + device];
1853 if (pcm == NULL) { 1847 if (pcm == NULL) {
1854 err = -ENODEV; 1848 err = -ENODEV;
1855 goto __error1; 1849 goto __error1;
@@ -1890,7 +1884,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
1890 down(&pcm->open_mutex); 1884 down(&pcm->open_mutex);
1891 while (1) { 1885 while (1) {
1892 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file, 1886 err = snd_pcm_oss_open_file(file, pcm, &pcm_oss_file,
1893 minor, psetup, csetup); 1887 iminor(inode), psetup, csetup);
1894 if (err >= 0) 1888 if (err >= 0)
1895 break; 1889 break;
1896 if (err == -EAGAIN) { 1890 if (err == -EAGAIN) {
@@ -2450,7 +2444,7 @@ static void register_oss_dsp(struct snd_pcm *pcm, int index)
2450 sprintf(name, "dsp%i%i", pcm->card->number, pcm->device); 2444 sprintf(name, "dsp%i%i", pcm->card->number, pcm->device);
2451 if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, 2445 if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM,
2452 pcm->card, index, &snd_pcm_oss_f_reg, 2446 pcm->card, index, &snd_pcm_oss_f_reg,
2453 name) < 0) { 2447 pcm, name) < 0) {
2454 snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n", 2448 snd_printk(KERN_ERR "unable to register OSS PCM device %i:%i\n",
2455 pcm->card->number, pcm->device); 2449 pcm->card->number, pcm->device);
2456 } 2450 }
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 2bc5f69ec2a8..95036c83de43 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -33,7 +33,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Abramo Bagnara <abramo@alsa-proj
33MODULE_DESCRIPTION("Midlevel PCM code for ALSA."); 33MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
34MODULE_LICENSE("GPL"); 34MODULE_LICENSE("GPL");
35 35
36struct snd_pcm *snd_pcm_devices[SNDRV_CARDS * SNDRV_PCM_DEVICES]; 36static LIST_HEAD(snd_pcm_devices);
37static LIST_HEAD(snd_pcm_notify_list); 37static LIST_HEAD(snd_pcm_notify_list);
38static DECLARE_MUTEX(register_mutex); 38static DECLARE_MUTEX(register_mutex);
39 39
@@ -43,13 +43,23 @@ static int snd_pcm_dev_register(struct snd_device *device);
43static int snd_pcm_dev_disconnect(struct snd_device *device); 43static int snd_pcm_dev_disconnect(struct snd_device *device);
44static int snd_pcm_dev_unregister(struct snd_device *device); 44static int snd_pcm_dev_unregister(struct snd_device *device);
45 45
46static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
47{
48 struct list_head *p;
49 struct snd_pcm *pcm;
50
51 list_for_each(p, &snd_pcm_devices) {
52 pcm = list_entry(p, struct snd_pcm, list);
53 if (pcm->card == card && pcm->device == device)
54 return pcm;
55 }
56 return NULL;
57}
58
46static int snd_pcm_control_ioctl(struct snd_card *card, 59static int snd_pcm_control_ioctl(struct snd_card *card,
47 struct snd_ctl_file *control, 60 struct snd_ctl_file *control,
48 unsigned int cmd, unsigned long arg) 61 unsigned int cmd, unsigned long arg)
49{ 62{
50 unsigned int tmp;
51
52 tmp = card->number * SNDRV_PCM_DEVICES;
53 switch (cmd) { 63 switch (cmd) {
54 case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE: 64 case SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE:
55 { 65 {
@@ -57,14 +67,16 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
57 67
58 if (get_user(device, (int __user *)arg)) 68 if (get_user(device, (int __user *)arg))
59 return -EFAULT; 69 return -EFAULT;
70 down(&register_mutex);
60 device = device < 0 ? 0 : device + 1; 71 device = device < 0 ? 0 : device + 1;
61 while (device < SNDRV_PCM_DEVICES) { 72 while (device < SNDRV_PCM_DEVICES) {
62 if (snd_pcm_devices[tmp + device]) 73 if (snd_pcm_search(card, device))
63 break; 74 break;
64 device++; 75 device++;
65 } 76 }
66 if (device == SNDRV_PCM_DEVICES) 77 if (device == SNDRV_PCM_DEVICES)
67 device = -1; 78 device = -1;
79 up(&register_mutex);
68 if (put_user(device, (int __user *)arg)) 80 if (put_user(device, (int __user *)arg))
69 return -EFAULT; 81 return -EFAULT;
70 return 0; 82 return 0;
@@ -77,31 +89,44 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
77 struct snd_pcm *pcm; 89 struct snd_pcm *pcm;
78 struct snd_pcm_str *pstr; 90 struct snd_pcm_str *pstr;
79 struct snd_pcm_substream *substream; 91 struct snd_pcm_substream *substream;
92 int err;
93
80 info = (struct snd_pcm_info __user *)arg; 94 info = (struct snd_pcm_info __user *)arg;
81 if (get_user(device, &info->device)) 95 if (get_user(device, &info->device))
82 return -EFAULT; 96 return -EFAULT;
83 if (device >= SNDRV_PCM_DEVICES)
84 return -ENXIO;
85 pcm = snd_pcm_devices[tmp + device];
86 if (pcm == NULL)
87 return -ENXIO;
88 if (get_user(stream, &info->stream)) 97 if (get_user(stream, &info->stream))
89 return -EFAULT; 98 return -EFAULT;
90 if (stream < 0 || stream > 1) 99 if (stream < 0 || stream > 1)
91 return -EINVAL; 100 return -EINVAL;
92 pstr = &pcm->streams[stream];
93 if (pstr->substream_count == 0)
94 return -ENOENT;
95 if (get_user(subdevice, &info->subdevice)) 101 if (get_user(subdevice, &info->subdevice))
96 return -EFAULT; 102 return -EFAULT;
97 if (subdevice >= pstr->substream_count) 103 down(&register_mutex);
98 return -ENXIO; 104 pcm = snd_pcm_search(card, device);
99 for (substream = pstr->substream; substream; substream = substream->next) 105 if (pcm == NULL) {
106 err = -ENXIO;
107 goto _error;
108 }
109 pstr = &pcm->streams[stream];
110 if (pstr->substream_count == 0) {
111 err = -ENOENT;
112 goto _error;
113 }
114 if (subdevice >= pstr->substream_count) {
115 err = -ENXIO;
116 goto _error;
117 }
118 for (substream = pstr->substream; substream;
119 substream = substream->next)
100 if (substream->number == (int)subdevice) 120 if (substream->number == (int)subdevice)
101 break; 121 break;
102 if (substream == NULL) 122 if (substream == NULL) {
103 return -ENXIO; 123 err = -ENXIO;
104 return snd_pcm_info_user(substream, info); 124 goto _error;
125 }
126 err = snd_pcm_info_user(substream, info);
127 _error:
128 up(&register_mutex);
129 return err;
105 } 130 }
106 case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE: 131 case SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE:
107 { 132 {
@@ -865,8 +890,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
865 890
866static int snd_pcm_dev_register(struct snd_device *device) 891static int snd_pcm_dev_register(struct snd_device *device)
867{ 892{
868 int idx, cidx, err; 893 int cidx, err;
869 unsigned short minor;
870 struct snd_pcm_substream *substream; 894 struct snd_pcm_substream *substream;
871 struct list_head *list; 895 struct list_head *list;
872 char str[16]; 896 char str[16];
@@ -874,12 +898,11 @@ static int snd_pcm_dev_register(struct snd_device *device)
874 898
875 snd_assert(pcm != NULL && device != NULL, return -ENXIO); 899 snd_assert(pcm != NULL && device != NULL, return -ENXIO);
876 down(&register_mutex); 900 down(&register_mutex);
877 idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device; 901 if (snd_pcm_search(pcm->card, pcm->device)) {
878 if (snd_pcm_devices[idx]) {
879 up(&register_mutex); 902 up(&register_mutex);
880 return -EBUSY; 903 return -EBUSY;
881 } 904 }
882 snd_pcm_devices[idx] = pcm; 905 list_add_tail(&pcm->list, &snd_pcm_devices);
883 for (cidx = 0; cidx < 2; cidx++) { 906 for (cidx = 0; cidx < 2; cidx++) {
884 int devtype = -1; 907 int devtype = -1;
885 if (pcm->streams[cidx].substream == NULL) 908 if (pcm->streams[cidx].substream == NULL)
@@ -887,20 +910,19 @@ static int snd_pcm_dev_register(struct snd_device *device)
887 switch (cidx) { 910 switch (cidx) {
888 case SNDRV_PCM_STREAM_PLAYBACK: 911 case SNDRV_PCM_STREAM_PLAYBACK:
889 sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device); 912 sprintf(str, "pcmC%iD%ip", pcm->card->number, pcm->device);
890 minor = SNDRV_MINOR_PCM_PLAYBACK + idx;
891 devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK; 913 devtype = SNDRV_DEVICE_TYPE_PCM_PLAYBACK;
892 break; 914 break;
893 case SNDRV_PCM_STREAM_CAPTURE: 915 case SNDRV_PCM_STREAM_CAPTURE:
894 sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device); 916 sprintf(str, "pcmC%iD%ic", pcm->card->number, pcm->device);
895 minor = SNDRV_MINOR_PCM_CAPTURE + idx;
896 devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE; 917 devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
897 break; 918 break;
898 } 919 }
899 if ((err = snd_register_device(devtype, pcm->card, 920 if ((err = snd_register_device(devtype, pcm->card,
900 pcm->device, 921 pcm->device,
901 &snd_pcm_f_ops[cidx], str)) < 0) 922 &snd_pcm_f_ops[cidx],
923 pcm, str)) < 0)
902 { 924 {
903 snd_pcm_devices[idx] = NULL; 925 list_del(&pcm->list);
904 up(&register_mutex); 926 up(&register_mutex);
905 return err; 927 return err;
906 } 928 }
@@ -921,11 +943,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
921 struct snd_pcm *pcm = device->device_data; 943 struct snd_pcm *pcm = device->device_data;
922 struct list_head *list; 944 struct list_head *list;
923 struct snd_pcm_substream *substream; 945 struct snd_pcm_substream *substream;
924 int idx, cidx; 946 int cidx;
925 947
926 down(&register_mutex); 948 down(&register_mutex);
927 idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device; 949 list_del_init(&pcm->list);
928 snd_pcm_devices[idx] = NULL;
929 for (cidx = 0; cidx < 2; cidx++) 950 for (cidx = 0; cidx < 2; cidx++)
930 for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) 951 for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
931 if (substream->runtime) 952 if (substream->runtime)
@@ -941,15 +962,14 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
941 962
942static int snd_pcm_dev_unregister(struct snd_device *device) 963static int snd_pcm_dev_unregister(struct snd_device *device)
943{ 964{
944 int idx, cidx, devtype; 965 int cidx, devtype;
945 struct snd_pcm_substream *substream; 966 struct snd_pcm_substream *substream;
946 struct list_head *list; 967 struct list_head *list;
947 struct snd_pcm *pcm = device->device_data; 968 struct snd_pcm *pcm = device->device_data;
948 969
949 snd_assert(pcm != NULL, return -ENXIO); 970 snd_assert(pcm != NULL, return -ENXIO);
950 down(&register_mutex); 971 down(&register_mutex);
951 idx = (pcm->card->number * SNDRV_PCM_DEVICES) + pcm->device; 972 list_del(&pcm->list);
952 snd_pcm_devices[idx] = NULL;
953 for (cidx = 0; cidx < 2; cidx++) { 973 for (cidx = 0; cidx < 2; cidx++) {
954 devtype = -1; 974 devtype = -1;
955 switch (cidx) { 975 switch (cidx) {
@@ -975,24 +995,19 @@ static int snd_pcm_dev_unregister(struct snd_device *device)
975 995
976int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) 996int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
977{ 997{
978 int idx; 998 struct list_head *p;
979 999
980 snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL); 1000 snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL);
981 down(&register_mutex); 1001 down(&register_mutex);
982 if (nfree) { 1002 if (nfree) {
983 list_del(&notify->list); 1003 list_del(&notify->list);
984 for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) { 1004 list_for_each(p, &snd_pcm_devices)
985 if (snd_pcm_devices[idx] == NULL) 1005 notify->n_unregister(list_entry(p,
986 continue; 1006 struct snd_pcm, list));
987 notify->n_unregister(snd_pcm_devices[idx]);
988 }
989 } else { 1007 } else {
990 list_add_tail(&notify->list, &snd_pcm_notify_list); 1008 list_add_tail(&notify->list, &snd_pcm_notify_list);
991 for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) { 1009 list_for_each(p, &snd_pcm_devices)
992 if (snd_pcm_devices[idx] == NULL) 1010 notify->n_register(list_entry(p, struct snd_pcm, list));
993 continue;
994 notify->n_register(snd_pcm_devices[idx]);
995 }
996 } 1011 }
997 up(&register_mutex); 1012 up(&register_mutex);
998 return 0; 1013 return 0;
@@ -1005,16 +1020,14 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
1005static void snd_pcm_proc_read(struct snd_info_entry *entry, 1020static void snd_pcm_proc_read(struct snd_info_entry *entry,
1006 struct snd_info_buffer *buffer) 1021 struct snd_info_buffer *buffer)
1007{ 1022{
1008 int idx; 1023 struct list_head *p;
1009 struct snd_pcm *pcm; 1024 struct snd_pcm *pcm;
1010 1025
1011 down(&register_mutex); 1026 down(&register_mutex);
1012 for (idx = 0; idx < SNDRV_CARDS * SNDRV_PCM_DEVICES; idx++) { 1027 list_for_each(p, &snd_pcm_devices) {
1013 pcm = snd_pcm_devices[idx]; 1028 pcm = list_entry(p, struct snd_pcm, list);
1014 if (pcm == NULL) 1029 snd_iprintf(buffer, "%02i-%02i: %s : %s",
1015 continue; 1030 pcm->card->number, pcm->device, pcm->id, pcm->name);
1016 snd_iprintf(buffer, "%02i-%02i: %s : %s", idx / SNDRV_PCM_DEVICES,
1017 idx % SNDRV_PCM_DEVICES, pcm->id, pcm->name);
1018 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) 1031 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
1019 snd_iprintf(buffer, " : playback %i", 1032 snd_iprintf(buffer, " : playback %i",
1020 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count); 1033 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count);
@@ -1063,7 +1076,6 @@ static void __exit alsa_pcm_exit(void)
1063module_init(alsa_pcm_init) 1076module_init(alsa_pcm_init)
1064module_exit(alsa_pcm_exit) 1077module_exit(alsa_pcm_exit)
1065 1078
1066EXPORT_SYMBOL(snd_pcm_devices);
1067EXPORT_SYMBOL(snd_pcm_new); 1079EXPORT_SYMBOL(snd_pcm_new);
1068EXPORT_SYMBOL(snd_pcm_new_stream); 1080EXPORT_SYMBOL(snd_pcm_new_stream);
1069EXPORT_SYMBOL(snd_pcm_notify); 1081EXPORT_SYMBOL(snd_pcm_notify);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index bb40c016135e..9010306bcead 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -62,6 +62,7 @@ static int snd_pcm_hw_refine_old_user(struct snd_pcm_substream *substream,
62 struct snd_pcm_hw_params_old __user * _oparams); 62 struct snd_pcm_hw_params_old __user * _oparams);
63static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream, 63static int snd_pcm_hw_params_old_user(struct snd_pcm_substream *substream,
64 struct snd_pcm_hw_params_old __user * _oparams); 64 struct snd_pcm_hw_params_old __user * _oparams);
65static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream);
65 66
66/* 67/*
67 * 68 *
@@ -1554,7 +1555,8 @@ static struct file *snd_pcm_file_fd(int fd)
1554{ 1555{
1555 struct file *file; 1556 struct file *file;
1556 struct inode *inode; 1557 struct inode *inode;
1557 unsigned short minor; 1558 unsigned int minor;
1559
1558 file = fget(fd); 1560 file = fget(fd);
1559 if (!file) 1561 if (!file)
1560 return NULL; 1562 return NULL;
@@ -1565,8 +1567,8 @@ static struct file *snd_pcm_file_fd(int fd)
1565 return NULL; 1567 return NULL;
1566 } 1568 }
1567 minor = iminor(inode); 1569 minor = iminor(inode);
1568 if (minor >= 256 || 1570 if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) &&
1569 minor % SNDRV_MINOR_DEVICES < SNDRV_MINOR_PCM_PLAYBACK) { 1571 !snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE)) {
1570 fput(file); 1572 fput(file);
1571 return NULL; 1573 return NULL;
1572 } 1574 }
@@ -2071,18 +2073,30 @@ static int snd_pcm_open_file(struct file *file,
2071 return 0; 2073 return 0;
2072} 2074}
2073 2075
2074static int snd_pcm_open(struct inode *inode, struct file *file) 2076static int snd_pcm_playback_open(struct inode *inode, struct file *file)
2077{
2078 struct snd_pcm *pcm;
2079
2080 pcm = snd_lookup_minor_data(iminor(inode),
2081 SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
2082 return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
2083}
2084
2085static int snd_pcm_capture_open(struct inode *inode, struct file *file)
2075{ 2086{
2076 int cardnum = SNDRV_MINOR_CARD(iminor(inode));
2077 int device = SNDRV_MINOR_DEVICE(iminor(inode));
2078 int err;
2079 struct snd_pcm *pcm; 2087 struct snd_pcm *pcm;
2088
2089 pcm = snd_lookup_minor_data(iminor(inode),
2090 SNDRV_DEVICE_TYPE_PCM_CAPTURE);
2091 return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
2092}
2093
2094static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
2095{
2096 int err;
2080 struct snd_pcm_file *pcm_file; 2097 struct snd_pcm_file *pcm_file;
2081 wait_queue_t wait; 2098 wait_queue_t wait;
2082 2099
2083 if (device < SNDRV_MINOR_PCM_PLAYBACK || device >= SNDRV_MINOR_DEVICES)
2084 return -ENXIO;
2085 pcm = snd_pcm_devices[(cardnum * SNDRV_PCM_DEVICES) + (device % SNDRV_MINOR_PCMS)];
2086 if (pcm == NULL) { 2100 if (pcm == NULL) {
2087 err = -ENODEV; 2101 err = -ENODEV;
2088 goto __error1; 2102 goto __error1;
@@ -2098,7 +2112,7 @@ static int snd_pcm_open(struct inode *inode, struct file *file)
2098 add_wait_queue(&pcm->open_wait, &wait); 2112 add_wait_queue(&pcm->open_wait, &wait);
2099 down(&pcm->open_mutex); 2113 down(&pcm->open_mutex);
2100 while (1) { 2114 while (1) {
2101 err = snd_pcm_open_file(file, pcm, device >= SNDRV_MINOR_PCM_CAPTURE ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK, &pcm_file); 2115 err = snd_pcm_open_file(file, pcm, stream, &pcm_file);
2102 if (err >= 0) 2116 if (err >= 0)
2103 break; 2117 break;
2104 if (err == -EAGAIN) { 2118 if (err == -EAGAIN) {
@@ -3375,7 +3389,7 @@ struct file_operations snd_pcm_f_ops[2] = {
3375 .owner = THIS_MODULE, 3389 .owner = THIS_MODULE,
3376 .write = snd_pcm_write, 3390 .write = snd_pcm_write,
3377 .writev = snd_pcm_writev, 3391 .writev = snd_pcm_writev,
3378 .open = snd_pcm_open, 3392 .open = snd_pcm_playback_open,
3379 .release = snd_pcm_release, 3393 .release = snd_pcm_release,
3380 .poll = snd_pcm_playback_poll, 3394 .poll = snd_pcm_playback_poll,
3381 .unlocked_ioctl = snd_pcm_playback_ioctl, 3395 .unlocked_ioctl = snd_pcm_playback_ioctl,
@@ -3387,7 +3401,7 @@ struct file_operations snd_pcm_f_ops[2] = {
3387 .owner = THIS_MODULE, 3401 .owner = THIS_MODULE,
3388 .read = snd_pcm_read, 3402 .read = snd_pcm_read,
3389 .readv = snd_pcm_readv, 3403 .readv = snd_pcm_readv,
3390 .open = snd_pcm_open, 3404 .open = snd_pcm_capture_open,
3391 .release = snd_pcm_release, 3405 .release = snd_pcm_release,
3392 .poll = snd_pcm_capture_poll, 3406 .poll = snd_pcm_capture_poll,
3393 .unlocked_ioctl = snd_pcm_capture_ioctl, 3407 .unlocked_ioctl = snd_pcm_capture_ioctl,
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 7ac77e5ddcb1..e6ee0d813783 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -56,10 +56,22 @@ static int snd_rawmidi_dev_register(struct snd_device *device);
56static int snd_rawmidi_dev_disconnect(struct snd_device *device); 56static int snd_rawmidi_dev_disconnect(struct snd_device *device);
57static int snd_rawmidi_dev_unregister(struct snd_device *device); 57static int snd_rawmidi_dev_unregister(struct snd_device *device);
58 58
59static struct snd_rawmidi *snd_rawmidi_devices[SNDRV_CARDS * SNDRV_RAWMIDI_DEVICES]; 59static LIST_HEAD(snd_rawmidi_devices);
60
61static DECLARE_MUTEX(register_mutex); 60static DECLARE_MUTEX(register_mutex);
62 61
62static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)
63{
64 struct list_head *p;
65 struct snd_rawmidi *rawmidi;
66
67 list_for_each(p, &snd_rawmidi_devices) {
68 rawmidi = list_entry(p, struct snd_rawmidi, list);
69 if (rawmidi->card == card && rawmidi->device == device)
70 return rawmidi;
71 }
72 return NULL;
73}
74
63static inline unsigned short snd_rawmidi_file_flags(struct file *file) 75static inline unsigned short snd_rawmidi_file_flags(struct file *file)
64{ 76{
65 switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) { 77 switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
@@ -214,7 +226,7 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)
214 return 0; 226 return 0;
215} 227}
216 228
217int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice, 229int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
218 int mode, struct snd_rawmidi_file * rfile) 230 int mode, struct snd_rawmidi_file * rfile)
219{ 231{
220 struct snd_rawmidi *rmidi; 232 struct snd_rawmidi *rmidi;
@@ -225,7 +237,9 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
225 237
226 if (rfile) 238 if (rfile)
227 rfile->input = rfile->output = NULL; 239 rfile->input = rfile->output = NULL;
228 rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device]; 240 down(&register_mutex);
241 rmidi = snd_rawmidi_search(card, device);
242 up(&register_mutex);
229 if (rmidi == NULL) { 243 if (rmidi == NULL) {
230 err = -ENODEV; 244 err = -ENODEV;
231 goto __error1; 245 goto __error1;
@@ -368,9 +382,8 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
368static int snd_rawmidi_open(struct inode *inode, struct file *file) 382static int snd_rawmidi_open(struct inode *inode, struct file *file)
369{ 383{
370 int maj = imajor(inode); 384 int maj = imajor(inode);
371 int cardnum;
372 struct snd_card *card; 385 struct snd_card *card;
373 int device, subdevice; 386 int subdevice;
374 unsigned short fflags; 387 unsigned short fflags;
375 int err; 388 int err;
376 struct snd_rawmidi *rmidi; 389 struct snd_rawmidi *rmidi;
@@ -380,27 +393,18 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
380 struct snd_ctl_file *kctl; 393 struct snd_ctl_file *kctl;
381 394
382 if (maj == snd_major) { 395 if (maj == snd_major) {
383 cardnum = SNDRV_MINOR_CARD(iminor(inode)); 396 rmidi = snd_lookup_minor_data(iminor(inode),
384 cardnum %= SNDRV_CARDS; 397 SNDRV_DEVICE_TYPE_RAWMIDI);
385 device = SNDRV_MINOR_DEVICE(iminor(inode)) - SNDRV_MINOR_RAWMIDI;
386 device %= SNDRV_MINOR_RAWMIDIS;
387#ifdef CONFIG_SND_OSSEMUL 398#ifdef CONFIG_SND_OSSEMUL
388 } else if (maj == SOUND_MAJOR) { 399 } else if (maj == SOUND_MAJOR) {
389 cardnum = SNDRV_MINOR_OSS_CARD(iminor(inode)); 400 rmidi = snd_lookup_oss_minor_data(iminor(inode),
390 cardnum %= SNDRV_CARDS; 401 SNDRV_OSS_DEVICE_TYPE_MIDI);
391 device = SNDRV_MINOR_OSS_DEVICE(iminor(inode)) == SNDRV_MINOR_OSS_MIDI ?
392 midi_map[cardnum] : amidi_map[cardnum];
393#endif 402#endif
394 } else 403 } else
395 return -ENXIO; 404 return -ENXIO;
396 405
397 rmidi = snd_rawmidi_devices[(cardnum * SNDRV_RAWMIDI_DEVICES) + device];
398 if (rmidi == NULL) 406 if (rmidi == NULL)
399 return -ENODEV; 407 return -ENODEV;
400#ifdef CONFIG_SND_OSSEMUL
401 if (maj == SOUND_MAJOR && !rmidi->ossreg)
402 return -ENXIO;
403#endif
404 if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) 408 if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
405 return -EINVAL; /* invalid combination */ 409 return -EINVAL; /* invalid combination */
406 card = rmidi->card; 410 card = rmidi->card;
@@ -430,7 +434,8 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
430 } 434 }
431 } 435 }
432 up_read(&card->controls_rwsem); 436 up_read(&card->controls_rwsem);
433 err = snd_rawmidi_kernel_open(cardnum, device, subdevice, fflags, rawmidi_file); 437 err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device,
438 subdevice, fflags, rawmidi_file);
434 if (err >= 0) 439 if (err >= 0)
435 break; 440 break;
436 if (err == -EAGAIN) { 441 if (err == -EAGAIN) {
@@ -570,9 +575,10 @@ int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info
570 struct snd_rawmidi_str *pstr; 575 struct snd_rawmidi_str *pstr;
571 struct snd_rawmidi_substream *substream; 576 struct snd_rawmidi_substream *substream;
572 struct list_head *list; 577 struct list_head *list;
573 if (info->device >= SNDRV_RAWMIDI_DEVICES) 578
574 return -ENXIO; 579 down(&register_mutex);
575 rmidi = snd_rawmidi_devices[card->number * SNDRV_RAWMIDI_DEVICES + info->device]; 580 rmidi = snd_rawmidi_search(card, info->device);
581 up(&register_mutex);
576 if (!rmidi) 582 if (!rmidi)
577 return -ENXIO; 583 return -ENXIO;
578 if (info->stream < 0 || info->stream > 1) 584 if (info->stream < 0 || info->stream > 1)
@@ -803,9 +809,7 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
803 unsigned long arg) 809 unsigned long arg)
804{ 810{
805 void __user *argp = (void __user *)arg; 811 void __user *argp = (void __user *)arg;
806 unsigned int tmp;
807 812
808 tmp = card->number * SNDRV_RAWMIDI_DEVICES;
809 switch (cmd) { 813 switch (cmd) {
810 case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE: 814 case SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE:
811 { 815 {
@@ -813,14 +817,16 @@ static int snd_rawmidi_control_ioctl(struct snd_card *card,
813 817
814 if (get_user(device, (int __user *)argp)) 818 if (get_user(device, (int __user *)argp))
815 return -EFAULT; 819 return -EFAULT;
820 down(&register_mutex);
816 device = device < 0 ? 0 : device + 1; 821 device = device < 0 ? 0 : device + 1;
817 while (device < SNDRV_RAWMIDI_DEVICES) { 822 while (device < SNDRV_RAWMIDI_DEVICES) {
818 if (snd_rawmidi_devices[tmp + device]) 823 if (snd_rawmidi_search(card, device))
819 break; 824 break;
820 device++; 825 device++;
821 } 826 }
822 if (device == SNDRV_RAWMIDI_DEVICES) 827 if (device == SNDRV_RAWMIDI_DEVICES)
823 device = -1; 828 device = -1;
829 up(&register_mutex);
824 if (put_user(device, (int __user *)argp)) 830 if (put_user(device, (int __user *)argp))
825 return -EFAULT; 831 return -EFAULT;
826 return 0; 832 return 0;
@@ -1493,7 +1499,7 @@ static void snd_rawmidi_dev_seq_free(struct snd_seq_device *device)
1493 1499
1494static int snd_rawmidi_dev_register(struct snd_device *device) 1500static int snd_rawmidi_dev_register(struct snd_device *device)
1495{ 1501{
1496 int idx, err; 1502 int err;
1497 struct snd_info_entry *entry; 1503 struct snd_info_entry *entry;
1498 char name[16]; 1504 char name[16];
1499 struct snd_rawmidi *rmidi = device->device_data; 1505 struct snd_rawmidi *rmidi = device->device_data;
@@ -1501,25 +1507,24 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
1501 if (rmidi->device >= SNDRV_RAWMIDI_DEVICES) 1507 if (rmidi->device >= SNDRV_RAWMIDI_DEVICES)
1502 return -ENOMEM; 1508 return -ENOMEM;
1503 down(&register_mutex); 1509 down(&register_mutex);
1504 idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device; 1510 if (snd_rawmidi_search(rmidi->card, rmidi->device)) {
1505 if (snd_rawmidi_devices[idx] != NULL) {
1506 up(&register_mutex); 1511 up(&register_mutex);
1507 return -EBUSY; 1512 return -EBUSY;
1508 } 1513 }
1509 snd_rawmidi_devices[idx] = rmidi; 1514 list_add_tail(&rmidi->list, &snd_rawmidi_devices);
1510 sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device); 1515 sprintf(name, "midiC%iD%i", rmidi->card->number, rmidi->device);
1511 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI, 1516 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_RAWMIDI,
1512 rmidi->card, rmidi->device, 1517 rmidi->card, rmidi->device,
1513 &snd_rawmidi_f_ops, name)) < 0) { 1518 &snd_rawmidi_f_ops, rmidi, name)) < 0) {
1514 snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device); 1519 snd_printk(KERN_ERR "unable to register rawmidi device %i:%i\n", rmidi->card->number, rmidi->device);
1515 snd_rawmidi_devices[idx] = NULL; 1520 list_del(&rmidi->list);
1516 up(&register_mutex); 1521 up(&register_mutex);
1517 return err; 1522 return err;
1518 } 1523 }
1519 if (rmidi->ops && rmidi->ops->dev_register && 1524 if (rmidi->ops && rmidi->ops->dev_register &&
1520 (err = rmidi->ops->dev_register(rmidi)) < 0) { 1525 (err = rmidi->ops->dev_register(rmidi)) < 0) {
1521 snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); 1526 snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
1522 snd_rawmidi_devices[idx] = NULL; 1527 list_del(&rmidi->list);
1523 up(&register_mutex); 1528 up(&register_mutex);
1524 return err; 1529 return err;
1525 } 1530 }
@@ -1527,8 +1532,8 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
1527 rmidi->ossreg = 0; 1532 rmidi->ossreg = 0;
1528 if ((int)rmidi->device == midi_map[rmidi->card->number]) { 1533 if ((int)rmidi->device == midi_map[rmidi->card->number]) {
1529 if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, 1534 if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
1530 rmidi->card, 0, 1535 rmidi->card, 0, &snd_rawmidi_f_ops,
1531 &snd_rawmidi_f_ops, name) < 0) { 1536 rmidi, name) < 0) {
1532 snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0); 1537 snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 0);
1533 } else { 1538 } else {
1534 rmidi->ossreg++; 1539 rmidi->ossreg++;
@@ -1539,8 +1544,8 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
1539 } 1544 }
1540 if ((int)rmidi->device == amidi_map[rmidi->card->number]) { 1545 if ((int)rmidi->device == amidi_map[rmidi->card->number]) {
1541 if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI, 1546 if (snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIDI,
1542 rmidi->card, 1, 1547 rmidi->card, 1, &snd_rawmidi_f_ops,
1543 &snd_rawmidi_f_ops, name) < 0) { 1548 rmidi, name) < 0) {
1544 snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1); 1549 snd_printk(KERN_ERR "unable to register OSS rawmidi device %i:%i\n", rmidi->card->number, 1);
1545 } else { 1550 } else {
1546 rmidi->ossreg++; 1551 rmidi->ossreg++;
@@ -1576,24 +1581,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
1576static int snd_rawmidi_dev_disconnect(struct snd_device *device) 1581static int snd_rawmidi_dev_disconnect(struct snd_device *device)
1577{ 1582{
1578 struct snd_rawmidi *rmidi = device->device_data; 1583 struct snd_rawmidi *rmidi = device->device_data;
1579 int idx;
1580 1584
1581 down(&register_mutex); 1585 down(&register_mutex);
1582 idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device; 1586 list_del_init(&rmidi->list);
1583 snd_rawmidi_devices[idx] = NULL;
1584 up(&register_mutex); 1587 up(&register_mutex);
1585 return 0; 1588 return 0;
1586} 1589}
1587 1590
1588static int snd_rawmidi_dev_unregister(struct snd_device *device) 1591static int snd_rawmidi_dev_unregister(struct snd_device *device)
1589{ 1592{
1590 int idx;
1591 struct snd_rawmidi *rmidi = device->device_data; 1593 struct snd_rawmidi *rmidi = device->device_data;
1592 1594
1593 snd_assert(rmidi != NULL, return -ENXIO); 1595 snd_assert(rmidi != NULL, return -ENXIO);
1594 down(&register_mutex); 1596 down(&register_mutex);
1595 idx = (rmidi->card->number * SNDRV_RAWMIDI_DEVICES) + rmidi->device; 1597 list_del(&rmidi->list);
1596 snd_rawmidi_devices[idx] = NULL;
1597 if (rmidi->proc_entry) { 1598 if (rmidi->proc_entry) {
1598 snd_info_unregister(rmidi->proc_entry); 1599 snd_info_unregister(rmidi->proc_entry);
1599 rmidi->proc_entry = NULL; 1600 rmidi->proc_entry = NULL;
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index 61c0a41376fd..4b51ab56507b 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -225,7 +225,7 @@ register_device(void)
225 down(&register_mutex); 225 down(&register_mutex);
226 if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, 226 if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER,
227 NULL, 0, 227 NULL, 0,
228 &seq_oss_f_ops, 228 &seq_oss_f_ops, NULL,
229 SNDRV_SEQ_OSS_DEVNAME)) < 0) { 229 SNDRV_SEQ_OSS_DEVNAME)) < 0) {
230 snd_printk(KERN_ERR "can't register device seq\n"); 230 snd_printk(KERN_ERR "can't register device seq\n");
231 up(&register_mutex); 231 up(&register_mutex);
@@ -233,7 +233,7 @@ register_device(void)
233 } 233 }
234 if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC, 234 if ((rc = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MUSIC,
235 NULL, 0, 235 NULL, 0,
236 &seq_oss_f_ops, 236 &seq_oss_f_ops, NULL,
237 SNDRV_SEQ_OSS_DEVNAME)) < 0) { 237 SNDRV_SEQ_OSS_DEVNAME)) < 0) {
238 snd_printk(KERN_ERR "can't register device music\n"); 238 snd_printk(KERN_ERR "can't register device music\n");
239 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0); 239 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_SEQUENCER, NULL, 0);
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 087fdf32732b..c8bd37ee8375 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -2531,7 +2531,7 @@ int __init snd_sequencer_device_init(void)
2531 return -ERESTARTSYS; 2531 return -ERESTARTSYS;
2532 2532
2533 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0, 2533 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_SEQUENCER, NULL, 0,
2534 &snd_seq_f_ops, "seq")) < 0) { 2534 &snd_seq_f_ops, NULL, "seq")) < 0) {
2535 up(&register_mutex); 2535 up(&register_mutex);
2536 return err; 2536 return err;
2537 } 2537 }
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index f88d2e3ee66e..0a65eb2f976b 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -183,7 +183,10 @@ static int midisynth_subscribe(void *private_data, struct snd_seq_port_subscribe
183 struct snd_rawmidi_params params; 183 struct snd_rawmidi_params params;
184 184
185 /* open midi port */ 185 /* open midi port */
186 if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_INPUT, &msynth->input_rfile)) < 0) { 186 if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
187 msynth->subdevice,
188 SNDRV_RAWMIDI_LFLG_INPUT,
189 &msynth->input_rfile)) < 0) {
187 snd_printd("midi input open failed!!!\n"); 190 snd_printd("midi input open failed!!!\n");
188 return err; 191 return err;
189 } 192 }
@@ -221,7 +224,10 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
221 struct snd_rawmidi_params params; 224 struct snd_rawmidi_params params;
222 225
223 /* open midi port */ 226 /* open midi port */
224 if ((err = snd_rawmidi_kernel_open(msynth->card->number, msynth->device, msynth->subdevice, SNDRV_RAWMIDI_LFLG_OUTPUT, &msynth->output_rfile)) < 0) { 227 if ((err = snd_rawmidi_kernel_open(msynth->card, msynth->device,
228 msynth->subdevice,
229 SNDRV_RAWMIDI_LFLG_OUTPUT,
230 &msynth->output_rfile)) < 0) {
225 snd_printd("midi output open failed!!!\n"); 231 snd_printd("midi output open failed!!!\n");
226 return err; 232 return err;
227 } 233 }
diff --git a/sound/core/sound.c b/sound/core/sound.c
index a509f49fa0b4..1e5eca546925 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -60,7 +60,6 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
60int snd_ecards_limit; 60int snd_ecards_limit;
61 61
62static struct snd_minor *snd_minors[SNDRV_OS_MINORS]; 62static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
63
64static DECLARE_MUTEX(sound_mutex); 63static DECLARE_MUTEX(sound_mutex);
65 64
66extern struct class *sound_class; 65extern struct class *sound_class;
@@ -107,6 +106,31 @@ static void snd_request_other(int minor)
107 106
108#endif /* request_module support */ 107#endif /* request_module support */
109 108
109/**
110 * snd_lookup_minor_data - get user data of a registered device
111 * @minor: the minor number
112 * @type: device type (SNDRV_DEVICE_TYPE_XXX)
113 *
114 * Checks that a minor device with the specified type is registered, and returns
115 * its user data pointer.
116 */
117void *snd_lookup_minor_data(unsigned int minor, int type)
118{
119 struct snd_minor *mreg;
120 void *private_data;
121
122 if (minor > ARRAY_SIZE(snd_minors))
123 return NULL;
124 down(&sound_mutex);
125 mreg = snd_minors[minor];
126 if (mreg && mreg->type == type)
127 private_data = mreg->private_data;
128 else
129 private_data = NULL;
130 up(&sound_mutex);
131 return private_data;
132}
133
110static int snd_open(struct inode *inode, struct file *file) 134static int snd_open(struct inode *inode, struct file *file)
111{ 135{
112 int minor = iminor(inode); 136 int minor = iminor(inode);
@@ -183,6 +207,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
183 * @card: the card instance 207 * @card: the card instance
184 * @dev: the device index 208 * @dev: the device index
185 * @f_ops: the file operations 209 * @f_ops: the file operations
210 * @private_data: user pointer for f_ops->open()
186 * @name: the device file name 211 * @name: the device file name
187 * 212 *
188 * Registers an ALSA device file for the given card. 213 * Registers an ALSA device file for the given card.
@@ -191,7 +216,8 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
191 * Retrurns zero if successful, or a negative error code on failure. 216 * Retrurns zero if successful, or a negative error code on failure.
192 */ 217 */
193int snd_register_device(int type, struct snd_card *card, int dev, 218int snd_register_device(int type, struct snd_card *card, int dev,
194 struct file_operations *f_ops, const char *name) 219 struct file_operations *f_ops, void *private_data,
220 const char *name)
195{ 221{
196 int minor = snd_kernel_minor(type, card, dev); 222 int minor = snd_kernel_minor(type, card, dev);
197 struct snd_minor *preg; 223 struct snd_minor *preg;
@@ -207,6 +233,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
207 preg->card = card ? card->number : -1; 233 preg->card = card ? card->number : -1;
208 preg->device = dev; 234 preg->device = dev;
209 preg->f_ops = f_ops; 235 preg->f_ops = f_ops;
236 preg->private_data = private_data;
210 strcpy(preg->name, name); 237 strcpy(preg->name, name);
211 down(&sound_mutex); 238 down(&sound_mutex);
212 if (snd_minors[minor]) { 239 if (snd_minors[minor]) {
@@ -238,13 +265,18 @@ int snd_register_device(int type, struct snd_card *card, int dev,
238 */ 265 */
239int snd_unregister_device(int type, struct snd_card *card, int dev) 266int snd_unregister_device(int type, struct snd_card *card, int dev)
240{ 267{
241 int minor = snd_kernel_minor(type, card, dev); 268 int cardnum, minor;
242 struct snd_minor *mptr; 269 struct snd_minor *mptr;
243 270
244 if (minor < 0) 271 cardnum = card ? card->number : -1;
245 return minor;
246 down(&sound_mutex); 272 down(&sound_mutex);
247 if ((mptr = snd_minors[minor]) == NULL) { 273 for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor)
274 if ((mptr = snd_minors[minor]) != NULL &&
275 mptr->type == type &&
276 mptr->card == cardnum &&
277 mptr->device == dev)
278 break;
279 if (minor == ARRAY_SIZE(snd_minors)) {
248 up(&sound_mutex); 280 up(&sound_mutex);
249 return -EINVAL; 281 return -EINVAL;
250 } 282 }
@@ -392,9 +424,11 @@ EXPORT_SYMBOL(snd_request_card);
392#endif 424#endif
393EXPORT_SYMBOL(snd_register_device); 425EXPORT_SYMBOL(snd_register_device);
394EXPORT_SYMBOL(snd_unregister_device); 426EXPORT_SYMBOL(snd_unregister_device);
427EXPORT_SYMBOL(snd_lookup_minor_data);
395#if defined(CONFIG_SND_OSSEMUL) 428#if defined(CONFIG_SND_OSSEMUL)
396EXPORT_SYMBOL(snd_register_oss_device); 429EXPORT_SYMBOL(snd_register_oss_device);
397EXPORT_SYMBOL(snd_unregister_oss_device); 430EXPORT_SYMBOL(snd_unregister_oss_device);
431EXPORT_SYMBOL(snd_lookup_oss_minor_data);
398#endif 432#endif
399 /* memory.c */ 433 /* memory.c */
400EXPORT_SYMBOL(copy_to_user_fromio); 434EXPORT_SYMBOL(copy_to_user_fromio);
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index afbfd8df1298..b9e89cac4c5d 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -38,9 +38,25 @@
38#define SNDRV_OSS_MINORS 128 38#define SNDRV_OSS_MINORS 128
39 39
40static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; 40static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
41
42static DECLARE_MUTEX(sound_oss_mutex); 41static DECLARE_MUTEX(sound_oss_mutex);
43 42
43void *snd_lookup_oss_minor_data(unsigned int minor, int type)
44{
45 struct snd_minor *mreg;
46 void *private_data;
47
48 if (minor > ARRAY_SIZE(snd_oss_minors))
49 return NULL;
50 down(&sound_oss_mutex);
51 mreg = snd_oss_minors[minor];
52 if (mreg && mreg->type == type)
53 private_data = mreg->private_data;
54 else
55 private_data = NULL;
56 up(&sound_oss_mutex);
57 return private_data;
58}
59
44static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev) 60static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
45{ 61{
46 int minor; 62 int minor;
@@ -78,7 +94,8 @@ static int snd_oss_kernel_minor(int type, struct snd_card *card, int dev)
78} 94}
79 95
80int snd_register_oss_device(int type, struct snd_card *card, int dev, 96int snd_register_oss_device(int type, struct snd_card *card, int dev,
81 struct file_operations *f_ops, const char *name) 97 struct file_operations *f_ops, void *private_data,
98 const char *name)
82{ 99{
83 int minor = snd_oss_kernel_minor(type, card, dev); 100 int minor = snd_oss_kernel_minor(type, card, dev);
84 int minor_unit; 101 int minor_unit;
@@ -97,6 +114,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
97 preg->card = card ? card->number : -1; 114 preg->card = card ? card->number : -1;
98 preg->device = dev; 115 preg->device = dev;
99 preg->f_ops = f_ops; 116 preg->f_ops = f_ops;
117 preg->private_data = private_data;
100 down(&sound_oss_mutex); 118 down(&sound_oss_mutex);
101 snd_oss_minors[minor] = preg; 119 snd_oss_minors[minor] = preg;
102 minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); 120 minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
@@ -121,6 +139,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
121 carddev); 139 carddev);
122 if (register2 != track2) 140 if (register2 != track2)
123 goto __end; 141 goto __end;
142 snd_oss_minors[track2] = preg;
124 } 143 }
125 up(&sound_oss_mutex); 144 up(&sound_oss_mutex);
126 return 0; 145 return 0;
@@ -163,8 +182,10 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev)
163 track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1); 182 track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1);
164 break; 183 break;
165 } 184 }
166 if (track2 >= 0) 185 if (track2 >= 0) {
167 unregister_sound_special(track2); 186 unregister_sound_special(track2);
187 snd_oss_minors[track2] = NULL;
188 }
168 snd_oss_minors[minor] = NULL; 189 snd_oss_minors[minor] = NULL;
169 up(&sound_oss_mutex); 190 up(&sound_oss_mutex);
170 kfree(mptr); 191 kfree(mptr);
diff --git a/sound/core/timer.c b/sound/core/timer.c
index a7bcb04263cb..c62dbacdca13 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -1952,8 +1952,8 @@ static int __init alsa_timer_init(void)
1952 if ((err = snd_timer_register_system()) < 0) 1952 if ((err = snd_timer_register_system()) < 0)
1953 snd_printk(KERN_ERR "unable to register system timer (%i)\n", 1953 snd_printk(KERN_ERR "unable to register system timer (%i)\n",
1954 err); 1954 err);
1955 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, 1955 if ((err = snd_register_device(SNDRV_DEVICE_TYPE_TIMER, NULL, 0,
1956 NULL, 0, &snd_timer_f_ops, "timer")) < 0) 1956 &snd_timer_f_ops, NULL, "timer")) < 0)
1957 snd_printk(KERN_ERR "unable to register timer device (%i)\n", 1957 snd_printk(KERN_ERR "unable to register timer device (%i)\n",
1958 err); 1958 err);
1959 return 0; 1959 return 0;