--- drivers/sound/cmpci.c.old Tue Jun 5 21:21:39 2001 +++ drivers/sound/cmpci.c Tue Jun 5 23:20:41 2001 @@ -312,6 +312,7 @@ /* spdif frame counter */ int spdif_counter; + struct semaphore sem; }; /* flags used for capability */ @@ -1653,7 +1654,7 @@ static ssize_t cm_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { struct cm_state *s = (struct cm_state *)file->private_data; - ssize_t ret; + ssize_t ret = 0; unsigned long flags; unsigned swptr; int cnt; @@ -1663,11 +1664,11 @@ return -ESPIPE; if (s->dma_adc.mapped) return -ENXIO; - if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) - return ret; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; - ret = 0; + down(&s->sem); + if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) + goto out; #if 0 spin_lock_irqsave(&s->lock, flags); cm_update_ptr(s); @@ -1684,8 +1685,12 @@ cnt = count; if (cnt <= 0) { start_adc(s); - if (file->f_flags & O_NONBLOCK) - return ret ? ret : -EAGAIN; + if (file->f_flags & O_NONBLOCK)a + { + if(!ret) ret = -EAGAIN; + goto out; + } + up(&s->sem); if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) { printk(KERN_DEBUG "cm: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count, @@ -1698,12 +1703,24 @@ s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0; spin_unlock_irqrestore(&s->lock, flags); } - if (signal_pending(current)) - return ret ? ret : -ERESTARTSYS; + if (signal_pending(current)) + { + if(!ret) ret = -ERESTARTSYS; + goto out; + } + down(&s->sem); + if (s->dma_adc.mapped) + { + ret = -ENXIO; + goto out; + } continue; } if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) - return ret ? ret : -EFAULT; + { + if(!ret) ret = -EFAULT; + goto out; + } swptr = (swptr + cnt) % s->dma_adc.dmasize; spin_lock_irqsave(&s->lock, flags); s->dma_adc.swptr = swptr; @@ -1714,6 +1731,8 @@ start_adc_unlocked(s); spin_unlock_irqrestore(&s->lock, flags); } +out: + up(&s->sem); return ret; } @@ -1730,18 +1749,20 @@ return -ESPIPE; if (s->dma_dac.mapped) return -ENXIO; - if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) - return ret; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; if (s->status & DO_DUAL_DAC) { if (s->dma_adc.mapped) return -ENXIO; - if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) - return ret; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; + down(&s->sem); + if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) + goto out; } + down(&s->sem); + if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) + goto out; ret = 0; #if 0 spin_lock_irqsave(&s->lock, flags); @@ -1776,7 +1797,11 @@ if (cnt <= 0) { start_dac(s); if (file->f_flags & O_NONBLOCK) - return ret ? ret : -EAGAIN; + { + if(!ret) ret = -EAGAIN; + goto out; + } + up(&s->sem); if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) { printk(KERN_DEBUG "cm: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n", s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, @@ -1794,7 +1819,16 @@ spin_unlock_irqrestore(&s->lock, flags); } if (signal_pending(current)) - return ret ? ret : -ERESTARTSYS; + { + if(!ret) ret = -ERESTARTSYS; + goto out; + } + down(&s->sem); + if (s->dma_dac.mapped) + { + ret = -ENXIO; + goto out; + } continue; } if (s->status & DO_AC3_SW) { @@ -1818,7 +1852,10 @@ swptr = (swptr + cnt) % s->dma_dac.dmasize; } else { if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) - return ret ? ret : -EFAULT; + { + if(!ret) ret = -EFAULT; + goto out; + } swptr = (swptr + cnt) % s->dma_dac.dmasize; } spin_lock_irqsave(&s->lock, flags); @@ -1838,6 +1875,8 @@ } start_dac(s); } +out: + up(&s->sem); return ret; } @@ -1880,6 +1919,7 @@ VALIDATE_STATE(s); lock_kernel(); + down(&s->sem); if (vma->vm_flags & VM_WRITE) { if ((ret = prog_dmabuf(s, 0)) != 0) goto out; @@ -1888,20 +1928,24 @@ if ((ret = prog_dmabuf(s, 1)) != 0) goto out; db = &s->dma_adc; - } else + } else { + ret = -EINVAL; goto out; - ret = -EINVAL; + } if (vma->vm_pgoff != 0) goto out; size = vma->vm_end - vma->vm_start; if (size > (PAGE_SIZE << db->buforder)) + { + ret = -EINVAL; goto out; - ret = -EINVAL; + } if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) goto out; db->mapped = 1; ret = 0; out: + up(&s->sem); unlock_kernel(); return ret; } @@ -3047,6 +3091,7 @@ init_waitqueue_head(&s->midi.iwait); init_waitqueue_head(&s->midi.owait); init_MUTEX(&s->open_sem); + init_MUTEX(&s->sem); spin_lock_init(&s->lock); s->magic = CM_MAGIC; s->iobase = pci_resource_start(pcidev, 0);