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 | ||
