diff options
Diffstat (limited to 'sound/oss/soundcard.c')
-rw-r--r-- | sound/oss/soundcard.c | 103 |
1 files changed, 44 insertions, 59 deletions
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c index 07f803e6d203..7c7793a0eb25 100644 --- a/sound/oss/soundcard.c +++ b/sound/oss/soundcard.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <linux/major.h> | 40 | #include <linux/major.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/proc_fs.h> | 42 | #include <linux/proc_fs.h> |
43 | #include <linux/smp_lock.h> | 43 | #include <linux/mutex.h> |
44 | #include <linux/module.h> | 44 | #include <linux/module.h> |
45 | #include <linux/mm.h> | 45 | #include <linux/mm.h> |
46 | #include <linux/device.h> | 46 | #include <linux/device.h> |
@@ -56,6 +56,7 @@ | |||
56 | * Table for permanently allocated memory (used when unloading the module) | 56 | * Table for permanently allocated memory (used when unloading the module) |
57 | */ | 57 | */ |
58 | void * sound_mem_blocks[MAX_MEM_BLOCKS]; | 58 | void * sound_mem_blocks[MAX_MEM_BLOCKS]; |
59 | static DEFINE_MUTEX(soundcard_mutex); | ||
59 | int sound_nblocks = 0; | 60 | int sound_nblocks = 0; |
60 | 61 | ||
61 | /* Persistent DMA buffers */ | 62 | /* Persistent DMA buffers */ |
@@ -86,7 +87,7 @@ int *load_mixer_volumes(char *name, int *levels, int present) | |||
86 | int i, n; | 87 | int i, n; |
87 | 88 | ||
88 | for (i = 0; i < num_mixer_volumes; i++) { | 89 | for (i = 0; i < num_mixer_volumes; i++) { |
89 | if (strcmp(name, mixer_vols[i].name) == 0) { | 90 | if (strncmp(name, mixer_vols[i].name, 32) == 0) { |
90 | if (present) | 91 | if (present) |
91 | mixer_vols[i].num = i; | 92 | mixer_vols[i].num = i; |
92 | return mixer_vols[i].levels; | 93 | return mixer_vols[i].levels; |
@@ -98,7 +99,7 @@ int *load_mixer_volumes(char *name, int *levels, int present) | |||
98 | } | 99 | } |
99 | n = num_mixer_volumes++; | 100 | n = num_mixer_volumes++; |
100 | 101 | ||
101 | strcpy(mixer_vols[n].name, name); | 102 | strncpy(mixer_vols[n].name, name, 32); |
102 | 103 | ||
103 | if (present) | 104 | if (present) |
104 | mixer_vols[n].num = n; | 105 | mixer_vols[n].num = n; |
@@ -151,7 +152,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof | |||
151 | * big one anyway, we might as well bandage here.. | 152 | * big one anyway, we might as well bandage here.. |
152 | */ | 153 | */ |
153 | 154 | ||
154 | lock_kernel(); | 155 | mutex_lock(&soundcard_mutex); |
155 | 156 | ||
156 | DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count)); | 157 | DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count)); |
157 | switch (dev & 0x0f) { | 158 | switch (dev & 0x0f) { |
@@ -169,7 +170,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof | |||
169 | case SND_DEV_MIDIN: | 170 | case SND_DEV_MIDIN: |
170 | ret = MIDIbuf_read(dev, file, buf, count); | 171 | ret = MIDIbuf_read(dev, file, buf, count); |
171 | } | 172 | } |
172 | unlock_kernel(); | 173 | mutex_unlock(&soundcard_mutex); |
173 | return ret; | 174 | return ret; |
174 | } | 175 | } |
175 | 176 | ||
@@ -178,7 +179,7 @@ static ssize_t sound_write(struct file *file, const char __user *buf, size_t cou | |||
178 | int dev = iminor(file->f_path.dentry->d_inode); | 179 | int dev = iminor(file->f_path.dentry->d_inode); |
179 | int ret = -EINVAL; | 180 | int ret = -EINVAL; |
180 | 181 | ||
181 | lock_kernel(); | 182 | mutex_lock(&soundcard_mutex); |
182 | DEB(printk("sound_write(dev=%d, count=%d)\n", dev, count)); | 183 | DEB(printk("sound_write(dev=%d, count=%d)\n", dev, count)); |
183 | switch (dev & 0x0f) { | 184 | switch (dev & 0x0f) { |
184 | case SND_DEV_SEQ: | 185 | case SND_DEV_SEQ: |
@@ -196,7 +197,7 @@ static ssize_t sound_write(struct file *file, const char __user *buf, size_t cou | |||
196 | ret = MIDIbuf_write(dev, file, buf, count); | 197 | ret = MIDIbuf_write(dev, file, buf, count); |
197 | break; | 198 | break; |
198 | } | 199 | } |
199 | unlock_kernel(); | 200 | mutex_unlock(&soundcard_mutex); |
200 | return ret; | 201 | return ret; |
201 | } | 202 | } |
202 | 203 | ||
@@ -210,7 +211,7 @@ static int sound_open(struct inode *inode, struct file *file) | |||
210 | printk(KERN_ERR "Invalid minor device %d\n", dev); | 211 | printk(KERN_ERR "Invalid minor device %d\n", dev); |
211 | return -ENXIO; | 212 | return -ENXIO; |
212 | } | 213 | } |
213 | lock_kernel(); | 214 | mutex_lock(&soundcard_mutex); |
214 | switch (dev & 0x0f) { | 215 | switch (dev & 0x0f) { |
215 | case SND_DEV_CTL: | 216 | case SND_DEV_CTL: |
216 | dev >>= 4; | 217 | dev >>= 4; |
@@ -247,15 +248,15 @@ static int sound_open(struct inode *inode, struct file *file) | |||
247 | retval = -ENXIO; | 248 | retval = -ENXIO; |
248 | } | 249 | } |
249 | 250 | ||
250 | unlock_kernel(); | 251 | mutex_unlock(&soundcard_mutex); |
251 | return 0; | 252 | return retval; |
252 | } | 253 | } |
253 | 254 | ||
254 | static int sound_release(struct inode *inode, struct file *file) | 255 | static int sound_release(struct inode *inode, struct file *file) |
255 | { | 256 | { |
256 | int dev = iminor(inode); | 257 | int dev = iminor(inode); |
257 | 258 | ||
258 | lock_kernel(); | 259 | mutex_lock(&soundcard_mutex); |
259 | DEB(printk("sound_release(dev=%d)\n", dev)); | 260 | DEB(printk("sound_release(dev=%d)\n", dev)); |
260 | switch (dev & 0x0f) { | 261 | switch (dev & 0x0f) { |
261 | case SND_DEV_CTL: | 262 | case SND_DEV_CTL: |
@@ -280,7 +281,7 @@ static int sound_release(struct inode *inode, struct file *file) | |||
280 | default: | 281 | default: |
281 | printk(KERN_ERR "Sound error: Releasing unknown device 0x%02x\n", dev); | 282 | printk(KERN_ERR "Sound error: Releasing unknown device 0x%02x\n", dev); |
282 | } | 283 | } |
283 | unlock_kernel(); | 284 | mutex_unlock(&soundcard_mutex); |
284 | 285 | ||
285 | return 0; | 286 | return 0; |
286 | } | 287 | } |
@@ -354,7 +355,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
354 | if (cmd == OSS_GETVERSION) | 355 | if (cmd == OSS_GETVERSION) |
355 | return __put_user(SOUND_VERSION, (int __user *)p); | 356 | return __put_user(SOUND_VERSION, (int __user *)p); |
356 | 357 | ||
357 | lock_kernel(); | 358 | mutex_lock(&soundcard_mutex); |
358 | if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 && /* Mixer ioctl */ | 359 | if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 && /* Mixer ioctl */ |
359 | (dev & 0x0f) != SND_DEV_CTL) { | 360 | (dev & 0x0f) != SND_DEV_CTL) { |
360 | dtype = dev & 0x0f; | 361 | dtype = dev & 0x0f; |
@@ -369,7 +370,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
369 | ret = sound_mixer_ioctl(dev >> 4, cmd, p); | 370 | ret = sound_mixer_ioctl(dev >> 4, cmd, p); |
370 | break; | 371 | break; |
371 | } | 372 | } |
372 | unlock_kernel(); | 373 | mutex_unlock(&soundcard_mutex); |
373 | return ret; | 374 | return ret; |
374 | } | 375 | } |
375 | 376 | ||
@@ -399,7 +400,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
399 | break; | 400 | break; |
400 | 401 | ||
401 | } | 402 | } |
402 | unlock_kernel(); | 403 | mutex_unlock(&soundcard_mutex); |
403 | return ret; | 404 | return ret; |
404 | } | 405 | } |
405 | 406 | ||
@@ -439,35 +440,35 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma) | |||
439 | printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n"); | 440 | printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n"); |
440 | return -EINVAL; | 441 | return -EINVAL; |
441 | } | 442 | } |
442 | lock_kernel(); | 443 | mutex_lock(&soundcard_mutex); |
443 | if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */ | 444 | if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */ |
444 | dmap = audio_devs[dev]->dmap_out; | 445 | dmap = audio_devs[dev]->dmap_out; |
445 | else if (vma->vm_flags & VM_READ) | 446 | else if (vma->vm_flags & VM_READ) |
446 | dmap = audio_devs[dev]->dmap_in; | 447 | dmap = audio_devs[dev]->dmap_in; |
447 | else { | 448 | else { |
448 | printk(KERN_ERR "Sound: Undefined mmap() access\n"); | 449 | printk(KERN_ERR "Sound: Undefined mmap() access\n"); |
449 | unlock_kernel(); | 450 | mutex_unlock(&soundcard_mutex); |
450 | return -EINVAL; | 451 | return -EINVAL; |
451 | } | 452 | } |
452 | 453 | ||
453 | if (dmap == NULL) { | 454 | if (dmap == NULL) { |
454 | printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n"); | 455 | printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n"); |
455 | unlock_kernel(); | 456 | mutex_unlock(&soundcard_mutex); |
456 | return -EIO; | 457 | return -EIO; |
457 | } | 458 | } |
458 | if (dmap->raw_buf == NULL) { | 459 | if (dmap->raw_buf == NULL) { |
459 | printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n"); | 460 | printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n"); |
460 | unlock_kernel(); | 461 | mutex_unlock(&soundcard_mutex); |
461 | return -EIO; | 462 | return -EIO; |
462 | } | 463 | } |
463 | if (dmap->mapping_flags) { | 464 | if (dmap->mapping_flags) { |
464 | printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n"); | 465 | printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n"); |
465 | unlock_kernel(); | 466 | mutex_unlock(&soundcard_mutex); |
466 | return -EIO; | 467 | return -EIO; |
467 | } | 468 | } |
468 | if (vma->vm_pgoff != 0) { | 469 | if (vma->vm_pgoff != 0) { |
469 | printk(KERN_ERR "Sound: mmap() offset must be 0.\n"); | 470 | printk(KERN_ERR "Sound: mmap() offset must be 0.\n"); |
470 | unlock_kernel(); | 471 | mutex_unlock(&soundcard_mutex); |
471 | return -EINVAL; | 472 | return -EINVAL; |
472 | } | 473 | } |
473 | size = vma->vm_end - vma->vm_start; | 474 | size = vma->vm_end - vma->vm_start; |
@@ -478,7 +479,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma) | |||
478 | if (remap_pfn_range(vma, vma->vm_start, | 479 | if (remap_pfn_range(vma, vma->vm_start, |
479 | virt_to_phys(dmap->raw_buf) >> PAGE_SHIFT, | 480 | virt_to_phys(dmap->raw_buf) >> PAGE_SHIFT, |
480 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) { | 481 | vma->vm_end - vma->vm_start, vma->vm_page_prot)) { |
481 | unlock_kernel(); | 482 | mutex_unlock(&soundcard_mutex); |
482 | return -EAGAIN; | 483 | return -EAGAIN; |
483 | } | 484 | } |
484 | 485 | ||
@@ -490,7 +491,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma) | |||
490 | memset(dmap->raw_buf, | 491 | memset(dmap->raw_buf, |
491 | dmap->neutral_byte, | 492 | dmap->neutral_byte, |
492 | dmap->bytes_in_use); | 493 | dmap->bytes_in_use); |
493 | unlock_kernel(); | 494 | mutex_unlock(&soundcard_mutex); |
494 | return 0; | 495 | return 0; |
495 | } | 496 | } |
496 | 497 | ||
@@ -525,31 +526,21 @@ bad: | |||
525 | } | 526 | } |
526 | 527 | ||
527 | 528 | ||
528 | /* These device names follow the official Linux device list, | ||
529 | * Documentation/devices.txt. Let us know if there are other | ||
530 | * common names we should support for compatibility. | ||
531 | * Only those devices not created by the generic code in sound_core.c are | ||
532 | * registered here. | ||
533 | */ | ||
534 | static const struct { | ||
535 | unsigned short minor; | ||
536 | char *name; | ||
537 | umode_t mode; | ||
538 | int *num; | ||
539 | } dev_list[] = { /* list of minor devices */ | ||
540 | /* seems to be some confusion here -- this device is not in the device list */ | ||
541 | {SND_DEV_DSP16, "dspW", S_IWUGO | S_IRUSR | S_IRGRP, | ||
542 | &num_audiodevs}, | ||
543 | {SND_DEV_AUDIO, "audio", S_IWUGO | S_IRUSR | S_IRGRP, | ||
544 | &num_audiodevs}, | ||
545 | }; | ||
546 | |||
547 | static int dmabuf; | 529 | static int dmabuf; |
548 | static int dmabug; | 530 | static int dmabug; |
549 | 531 | ||
550 | module_param(dmabuf, int, 0444); | 532 | module_param(dmabuf, int, 0444); |
551 | module_param(dmabug, int, 0444); | 533 | module_param(dmabug, int, 0444); |
552 | 534 | ||
535 | /* additional minors for compatibility */ | ||
536 | struct oss_minor_dev { | ||
537 | unsigned short minor; | ||
538 | unsigned int enabled; | ||
539 | } dev_list[] = { | ||
540 | { SND_DEV_DSP16 }, | ||
541 | { SND_DEV_AUDIO }, | ||
542 | }; | ||
543 | |||
553 | static int __init oss_init(void) | 544 | static int __init oss_init(void) |
554 | { | 545 | { |
555 | int err; | 546 | int err; |
@@ -570,18 +561,12 @@ static int __init oss_init(void) | |||
570 | sound_dmap_flag = (dmabuf > 0 ? 1 : 0); | 561 | sound_dmap_flag = (dmabuf > 0 ? 1 : 0); |
571 | 562 | ||
572 | for (i = 0; i < ARRAY_SIZE(dev_list); i++) { | 563 | for (i = 0; i < ARRAY_SIZE(dev_list); i++) { |
573 | device_create(sound_class, NULL, | 564 | j = 0; |
574 | MKDEV(SOUND_MAJOR, dev_list[i].minor), NULL, | 565 | do { |
575 | "%s", dev_list[i].name); | 566 | unsigned short minor = dev_list[i].minor + j * 0x10; |
576 | 567 | if (!register_sound_special(&oss_sound_fops, minor)) | |
577 | if (!dev_list[i].num) | 568 | dev_list[i].enabled = (1 << j); |
578 | continue; | 569 | } while (++j < num_audiodevs); |
579 | |||
580 | for (j = 1; j < *dev_list[i].num; j++) | ||
581 | device_create(sound_class, NULL, | ||
582 | MKDEV(SOUND_MAJOR, | ||
583 | dev_list[i].minor + (j*0x10)), | ||
584 | NULL, "%s%d", dev_list[i].name, j); | ||
585 | } | 570 | } |
586 | 571 | ||
587 | if (sound_nblocks >= MAX_MEM_BLOCKS - 1) | 572 | if (sound_nblocks >= MAX_MEM_BLOCKS - 1) |
@@ -595,11 +580,11 @@ static void __exit oss_cleanup(void) | |||
595 | int i, j; | 580 | int i, j; |
596 | 581 | ||
597 | for (i = 0; i < ARRAY_SIZE(dev_list); i++) { | 582 | for (i = 0; i < ARRAY_SIZE(dev_list); i++) { |
598 | device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor)); | 583 | j = 0; |
599 | if (!dev_list[i].num) | 584 | do { |
600 | continue; | 585 | if (dev_list[i].enabled & (1 << j)) |
601 | for (j = 1; j < *dev_list[i].num; j++) | 586 | unregister_sound_special(dev_list[i].minor); |
602 | device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10))); | 587 | } while (++j < num_audiodevs); |
603 | } | 588 | } |
604 | 589 | ||
605 | unregister_sound_special(1); | 590 | unregister_sound_special(1); |