diff options
Diffstat (limited to 'sound/oss/trident.c')
-rw-r--r-- | sound/oss/trident.c | 62 |
1 files changed, 32 insertions, 30 deletions
diff --git a/sound/oss/trident.c b/sound/oss/trident.c index a21c663e7e12..e61a454a8150 100644 --- a/sound/oss/trident.c +++ b/sound/oss/trident.c | |||
@@ -190,7 +190,7 @@ | |||
190 | * | 190 | * |
191 | * Lock order (high->low) | 191 | * Lock order (high->low) |
192 | * lock - hardware lock | 192 | * lock - hardware lock |
193 | * open_sem - guard opens | 193 | * open_mutex - guard opens |
194 | * sem - guard dmabuf, write re-entry etc | 194 | * sem - guard dmabuf, write re-entry etc |
195 | */ | 195 | */ |
196 | 196 | ||
@@ -216,6 +216,8 @@ | |||
216 | #include <linux/pm.h> | 216 | #include <linux/pm.h> |
217 | #include <linux/gameport.h> | 217 | #include <linux/gameport.h> |
218 | #include <linux/kernel.h> | 218 | #include <linux/kernel.h> |
219 | #include <linux/mutex.h> | ||
220 | |||
219 | #include <asm/uaccess.h> | 221 | #include <asm/uaccess.h> |
220 | #include <asm/io.h> | 222 | #include <asm/io.h> |
221 | #include <asm/dma.h> | 223 | #include <asm/dma.h> |
@@ -349,7 +351,7 @@ struct trident_state { | |||
349 | unsigned chans_num; | 351 | unsigned chans_num; |
350 | unsigned long fmt_flag; | 352 | unsigned long fmt_flag; |
351 | /* Guard against mmap/write/read races */ | 353 | /* Guard against mmap/write/read races */ |
352 | struct semaphore sem; | 354 | struct mutex sem; |
353 | 355 | ||
354 | }; | 356 | }; |
355 | 357 | ||
@@ -402,7 +404,7 @@ struct trident_card { | |||
402 | struct trident_card *next; | 404 | struct trident_card *next; |
403 | 405 | ||
404 | /* single open lock mechanism, only used for recording */ | 406 | /* single open lock mechanism, only used for recording */ |
405 | struct semaphore open_sem; | 407 | struct mutex open_mutex; |
406 | 408 | ||
407 | /* The trident has a certain amount of cross channel interaction | 409 | /* The trident has a certain amount of cross channel interaction |
408 | so we use a single per card lock */ | 410 | so we use a single per card lock */ |
@@ -1881,7 +1883,7 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos | |||
1881 | if (!access_ok(VERIFY_WRITE, buffer, count)) | 1883 | if (!access_ok(VERIFY_WRITE, buffer, count)) |
1882 | return -EFAULT; | 1884 | return -EFAULT; |
1883 | 1885 | ||
1884 | down(&state->sem); | 1886 | mutex_lock(&state->sem); |
1885 | if (!dmabuf->ready && (ret = prog_dmabuf_record(state))) | 1887 | if (!dmabuf->ready && (ret = prog_dmabuf_record(state))) |
1886 | goto out; | 1888 | goto out; |
1887 | 1889 | ||
@@ -1913,7 +1915,7 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos | |||
1913 | goto out; | 1915 | goto out; |
1914 | } | 1916 | } |
1915 | 1917 | ||
1916 | up(&state->sem); | 1918 | mutex_unlock(&state->sem); |
1917 | /* No matter how much space left in the buffer, */ | 1919 | /* No matter how much space left in the buffer, */ |
1918 | /* we have to wait until CSO == ESO/2 or CSO == ESO */ | 1920 | /* we have to wait until CSO == ESO/2 or CSO == ESO */ |
1919 | /* when address engine interrupts */ | 1921 | /* when address engine interrupts */ |
@@ -1940,7 +1942,7 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos | |||
1940 | ret = -ERESTARTSYS; | 1942 | ret = -ERESTARTSYS; |
1941 | goto out; | 1943 | goto out; |
1942 | } | 1944 | } |
1943 | down(&state->sem); | 1945 | mutex_lock(&state->sem); |
1944 | if (dmabuf->mapped) { | 1946 | if (dmabuf->mapped) { |
1945 | if (!ret) | 1947 | if (!ret) |
1946 | ret = -ENXIO; | 1948 | ret = -ENXIO; |
@@ -1968,7 +1970,7 @@ trident_read(struct file *file, char __user *buffer, size_t count, loff_t * ppos | |||
1968 | start_adc(state); | 1970 | start_adc(state); |
1969 | } | 1971 | } |
1970 | out: | 1972 | out: |
1971 | up(&state->sem); | 1973 | mutex_unlock(&state->sem); |
1972 | return ret; | 1974 | return ret; |
1973 | } | 1975 | } |
1974 | 1976 | ||
@@ -1996,7 +1998,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t | |||
1996 | * Guard against an mmap or ioctl while writing | 1998 | * Guard against an mmap or ioctl while writing |
1997 | */ | 1999 | */ |
1998 | 2000 | ||
1999 | down(&state->sem); | 2001 | mutex_lock(&state->sem); |
2000 | 2002 | ||
2001 | if (dmabuf->mapped) { | 2003 | if (dmabuf->mapped) { |
2002 | ret = -ENXIO; | 2004 | ret = -ENXIO; |
@@ -2045,7 +2047,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t | |||
2045 | tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); | 2047 | tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); |
2046 | tmo >>= sample_shift[dmabuf->fmt]; | 2048 | tmo >>= sample_shift[dmabuf->fmt]; |
2047 | unlock_set_fmt(state); | 2049 | unlock_set_fmt(state); |
2048 | up(&state->sem); | 2050 | mutex_unlock(&state->sem); |
2049 | 2051 | ||
2050 | /* There are two situations when sleep_on_timeout */ | 2052 | /* There are two situations when sleep_on_timeout */ |
2051 | /* returns, one is when the interrupt is serviced */ | 2053 | /* returns, one is when the interrupt is serviced */ |
@@ -2073,7 +2075,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t | |||
2073 | ret = -ERESTARTSYS; | 2075 | ret = -ERESTARTSYS; |
2074 | goto out_nolock; | 2076 | goto out_nolock; |
2075 | } | 2077 | } |
2076 | down(&state->sem); | 2078 | mutex_lock(&state->sem); |
2077 | if (dmabuf->mapped) { | 2079 | if (dmabuf->mapped) { |
2078 | if (!ret) | 2080 | if (!ret) |
2079 | ret = -ENXIO; | 2081 | ret = -ENXIO; |
@@ -2131,7 +2133,7 @@ trident_write(struct file *file, const char __user *buffer, size_t count, loff_t | |||
2131 | start_dac(state); | 2133 | start_dac(state); |
2132 | } | 2134 | } |
2133 | out: | 2135 | out: |
2134 | up(&state->sem); | 2136 | mutex_unlock(&state->sem); |
2135 | out_nolock: | 2137 | out_nolock: |
2136 | return ret; | 2138 | return ret; |
2137 | } | 2139 | } |
@@ -2152,24 +2154,24 @@ trident_poll(struct file *file, struct poll_table_struct *wait) | |||
2152 | * prog_dmabuf events | 2154 | * prog_dmabuf events |
2153 | */ | 2155 | */ |
2154 | 2156 | ||
2155 | down(&state->sem); | 2157 | mutex_lock(&state->sem); |
2156 | 2158 | ||
2157 | if (file->f_mode & FMODE_WRITE) { | 2159 | if (file->f_mode & FMODE_WRITE) { |
2158 | if (!dmabuf->ready && prog_dmabuf_playback(state)) { | 2160 | if (!dmabuf->ready && prog_dmabuf_playback(state)) { |
2159 | up(&state->sem); | 2161 | mutex_unlock(&state->sem); |
2160 | return 0; | 2162 | return 0; |
2161 | } | 2163 | } |
2162 | poll_wait(file, &dmabuf->wait, wait); | 2164 | poll_wait(file, &dmabuf->wait, wait); |
2163 | } | 2165 | } |
2164 | if (file->f_mode & FMODE_READ) { | 2166 | if (file->f_mode & FMODE_READ) { |
2165 | if (!dmabuf->ready && prog_dmabuf_record(state)) { | 2167 | if (!dmabuf->ready && prog_dmabuf_record(state)) { |
2166 | up(&state->sem); | 2168 | mutex_unlock(&state->sem); |
2167 | return 0; | 2169 | return 0; |
2168 | } | 2170 | } |
2169 | poll_wait(file, &dmabuf->wait, wait); | 2171 | poll_wait(file, &dmabuf->wait, wait); |
2170 | } | 2172 | } |
2171 | 2173 | ||
2172 | up(&state->sem); | 2174 | mutex_unlock(&state->sem); |
2173 | 2175 | ||
2174 | spin_lock_irqsave(&state->card->lock, flags); | 2176 | spin_lock_irqsave(&state->card->lock, flags); |
2175 | trident_update_ptr(state); | 2177 | trident_update_ptr(state); |
@@ -2207,7 +2209,7 @@ trident_mmap(struct file *file, struct vm_area_struct *vma) | |||
2207 | * a read or write against an mmap. | 2209 | * a read or write against an mmap. |
2208 | */ | 2210 | */ |
2209 | 2211 | ||
2210 | down(&state->sem); | 2212 | mutex_lock(&state->sem); |
2211 | 2213 | ||
2212 | if (vma->vm_flags & VM_WRITE) { | 2214 | if (vma->vm_flags & VM_WRITE) { |
2213 | if ((ret = prog_dmabuf_playback(state)) != 0) | 2215 | if ((ret = prog_dmabuf_playback(state)) != 0) |
@@ -2232,7 +2234,7 @@ trident_mmap(struct file *file, struct vm_area_struct *vma) | |||
2232 | dmabuf->mapped = 1; | 2234 | dmabuf->mapped = 1; |
2233 | ret = 0; | 2235 | ret = 0; |
2234 | out: | 2236 | out: |
2235 | up(&state->sem); | 2237 | mutex_unlock(&state->sem); |
2236 | return ret; | 2238 | return ret; |
2237 | } | 2239 | } |
2238 | 2240 | ||
@@ -2429,15 +2431,15 @@ trident_ioctl(struct inode *inode, struct file *file, | |||
2429 | unlock_set_fmt(state); | 2431 | unlock_set_fmt(state); |
2430 | break; | 2432 | break; |
2431 | } | 2433 | } |
2432 | down(&state->card->open_sem); | 2434 | mutex_lock(&state->card->open_mutex); |
2433 | ret = ali_allocate_other_states_resources(state, 6); | 2435 | ret = ali_allocate_other_states_resources(state, 6); |
2434 | if (ret < 0) { | 2436 | if (ret < 0) { |
2435 | up(&state->card->open_sem); | 2437 | mutex_unlock(&state->card->open_mutex); |
2436 | unlock_set_fmt(state); | 2438 | unlock_set_fmt(state); |
2437 | break; | 2439 | break; |
2438 | } | 2440 | } |
2439 | state->card->multi_channel_use_count++; | 2441 | state->card->multi_channel_use_count++; |
2440 | up(&state->card->open_sem); | 2442 | mutex_unlock(&state->card->open_mutex); |
2441 | } else | 2443 | } else |
2442 | val = 2; /*yield to 2-channels */ | 2444 | val = 2; /*yield to 2-channels */ |
2443 | } else | 2445 | } else |
@@ -2727,11 +2729,11 @@ trident_open(struct inode *inode, struct file *file) | |||
2727 | 2729 | ||
2728 | /* find an available virtual channel (instance of /dev/dsp) */ | 2730 | /* find an available virtual channel (instance of /dev/dsp) */ |
2729 | while (card != NULL) { | 2731 | while (card != NULL) { |
2730 | down(&card->open_sem); | 2732 | mutex_lock(&card->open_mutex); |
2731 | if (file->f_mode & FMODE_READ) { | 2733 | if (file->f_mode & FMODE_READ) { |
2732 | /* Skip opens on cards that are in 6 channel mode */ | 2734 | /* Skip opens on cards that are in 6 channel mode */ |
2733 | if (card->multi_channel_use_count > 0) { | 2735 | if (card->multi_channel_use_count > 0) { |
2734 | up(&card->open_sem); | 2736 | mutex_unlock(&card->open_mutex); |
2735 | card = card->next; | 2737 | card = card->next; |
2736 | continue; | 2738 | continue; |
2737 | } | 2739 | } |
@@ -2740,16 +2742,16 @@ trident_open(struct inode *inode, struct file *file) | |||
2740 | if (card->states[i] == NULL) { | 2742 | if (card->states[i] == NULL) { |
2741 | state = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL); | 2743 | state = card->states[i] = kmalloc(sizeof(*state), GFP_KERNEL); |
2742 | if (state == NULL) { | 2744 | if (state == NULL) { |
2743 | up(&card->open_sem); | 2745 | mutex_unlock(&card->open_mutex); |
2744 | return -ENOMEM; | 2746 | return -ENOMEM; |
2745 | } | 2747 | } |
2746 | memset(state, 0, sizeof(*state)); | 2748 | memset(state, 0, sizeof(*state)); |
2747 | init_MUTEX(&state->sem); | 2749 | mutex_init(&state->sem); |
2748 | dmabuf = &state->dmabuf; | 2750 | dmabuf = &state->dmabuf; |
2749 | goto found_virt; | 2751 | goto found_virt; |
2750 | } | 2752 | } |
2751 | } | 2753 | } |
2752 | up(&card->open_sem); | 2754 | mutex_unlock(&card->open_mutex); |
2753 | card = card->next; | 2755 | card = card->next; |
2754 | } | 2756 | } |
2755 | /* no more virtual channel avaiable */ | 2757 | /* no more virtual channel avaiable */ |
@@ -2816,7 +2818,7 @@ trident_open(struct inode *inode, struct file *file) | |||
2816 | } | 2818 | } |
2817 | 2819 | ||
2818 | state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); | 2820 | state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); |
2819 | up(&card->open_sem); | 2821 | mutex_unlock(&card->open_mutex); |
2820 | 2822 | ||
2821 | pr_debug("trident: open virtual channel %d, hard channel %d\n", | 2823 | pr_debug("trident: open virtual channel %d, hard channel %d\n", |
2822 | state->virt, dmabuf->channel->num); | 2824 | state->virt, dmabuf->channel->num); |
@@ -2845,7 +2847,7 @@ trident_release(struct inode *inode, struct file *file) | |||
2845 | state->virt, dmabuf->channel->num); | 2847 | state->virt, dmabuf->channel->num); |
2846 | 2848 | ||
2847 | /* stop DMA state machine and free DMA buffers/channels */ | 2849 | /* stop DMA state machine and free DMA buffers/channels */ |
2848 | down(&card->open_sem); | 2850 | mutex_lock(&card->open_mutex); |
2849 | 2851 | ||
2850 | if (file->f_mode & FMODE_WRITE) { | 2852 | if (file->f_mode & FMODE_WRITE) { |
2851 | stop_dac(state); | 2853 | stop_dac(state); |
@@ -2878,8 +2880,8 @@ trident_release(struct inode *inode, struct file *file) | |||
2878 | card->states[state->virt] = NULL; | 2880 | card->states[state->virt] = NULL; |
2879 | kfree(state); | 2881 | kfree(state); |
2880 | 2882 | ||
2881 | /* we're covered by the open_sem */ | 2883 | /* we're covered by the open_mutex */ |
2882 | up(&card->open_sem); | 2884 | mutex_unlock(&card->open_mutex); |
2883 | 2885 | ||
2884 | return 0; | 2886 | return 0; |
2885 | } | 2887 | } |
@@ -4405,7 +4407,7 @@ trident_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id) | |||
4405 | card->banks[BANK_B].addresses = &bank_b_addrs; | 4407 | card->banks[BANK_B].addresses = &bank_b_addrs; |
4406 | card->banks[BANK_B].bitmap = 0UL; | 4408 | card->banks[BANK_B].bitmap = 0UL; |
4407 | 4409 | ||
4408 | init_MUTEX(&card->open_sem); | 4410 | mutex_init(&card->open_mutex); |
4409 | spin_lock_init(&card->lock); | 4411 | spin_lock_init(&card->lock); |
4410 | init_timer(&card->timer); | 4412 | init_timer(&card->timer); |
4411 | 4413 | ||