diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-15 01:55:58 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-15 01:55:58 +0000 |
commit | 53b3988d474435254a3b053a68bb24ce9e439295 (patch) | |
tree | f8da8e40f01f4ad02bbd76b8c9920749b118235f /drivers/sound/trident.c | |
parent | b0cb48abe83d1a4389ea938bf624f8baa82c5047 (diff) |
Merge with 2.3.99-pre9.
Diffstat (limited to 'drivers/sound/trident.c')
-rw-r--r-- | drivers/sound/trident.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c index a1f462f3b..6a3b8b4d6 100644 --- a/drivers/sound/trident.c +++ b/drivers/sound/trident.c @@ -29,6 +29,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History + * v0.14.3 May 20 2000 Aaron Holtzman + * Fix kfree'd memory access in release + * Fix race in open while looking for a free virtual channel slot + * remove open_wait wq (which appears to be unused) * v0.14.2 Mar 29 2000 Ching Ling Lee * Add clear to silence advance in trident_update_ptr * fix invalid data of the end of the sound @@ -166,10 +170,6 @@ struct trident_state { unsigned int magic; struct trident_card *card; /* Card info */ - /* single open lock mechanism, only used for recording */ - struct semaphore open_sem; - wait_queue_head_t open_wait; - /* file mode */ mode_t open_mode; @@ -261,6 +261,9 @@ struct trident_card { /* We keep trident cards in a linked list */ struct trident_card *next; + /* single open lock mechanism, only used for recording */ + struct semaphore open_sem; + /* The trident has a certain amount of cross channel interaction so we use a single per card lock */ spinlock_t lock; @@ -1904,6 +1907,7 @@ static int trident_open(struct inode *inode, struct file *file) /* find an avaiable virtual channel (instance of /dev/dsp) */ while (card != NULL) { + down(&card->open_sem); for (i = 0; i < NR_HW_CH; i++) { if (card->states[i] == NULL) { state = card->states[i] = (struct trident_state *) @@ -1915,6 +1919,7 @@ static int trident_open(struct inode *inode, struct file *file) goto found_virt; } } + up(&card->open_sem); card = card->next; } /* no more virtual channel avaiable */ @@ -1939,10 +1944,8 @@ static int trident_open(struct inode *inode, struct file *file) state->card = card; state->magic = TRIDENT_STATE_MAGIC; init_waitqueue_head(&dmabuf->wait); - init_MUTEX(&state->open_sem); file->private_data = state; - down(&state->open_sem); /* set default sample format. According to OSS Programmer's Guide /dev/dsp should be default to unsigned 8-bits, mono, with sample rate 8kHz and @@ -1985,7 +1988,7 @@ static int trident_open(struct inode *inode, struct file *file) } state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - up(&state->open_sem); + up(&card->open_sem); #ifdef DEBUG printk(KERN_ERR "trident: open virtual channel %d, hard channel %d\n", @@ -1999,6 +2002,7 @@ static int trident_open(struct inode *inode, struct file *file) static int trident_release(struct inode *inode, struct file *file) { struct trident_state *state = (struct trident_state *)file->private_data; + struct trident_card *card = state->card; struct dmabuf *dmabuf = &state->dmabuf; VALIDATE_STATE(state); @@ -2009,25 +2013,25 @@ static int trident_release(struct inode *inode, struct file *file) } /* stop DMA state machine and free DMA buffers/channels */ - down(&state->open_sem); + down(&card->open_sem); if (file->f_mode & FMODE_WRITE) { stop_dac(state); dealloc_dmabuf(state); state->card->free_pcm_channel(state->card, dmabuf->channel->num); } + if (file->f_mode & FMODE_READ) { stop_adc(state); dealloc_dmabuf(state); state->card->free_pcm_channel(state->card, dmabuf->channel->num); } - kfree(state->card->states[state->virt]); - state->card->states[state->virt] = NULL; - state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); + card->states[state->virt] = NULL; + kfree(state); /* we're covered by the open_sem */ - up(&state->open_sem); + up(&card->open_sem); MOD_DEC_USE_COUNT; return 0; @@ -2408,6 +2412,7 @@ static int __init trident_probe(struct pci_dev *pci_dev, const struct pci_device card->banks[BANK_A].bitmap = 0UL; card->banks[BANK_B].addresses = &bank_b_addrs; card->banks[BANK_B].bitmap = 0UL; + init_MUTEX(&card->open_sem); spin_lock_init(&card->lock); devs = card; |