patch-2.3.25 linux/drivers/sound/es1370.c
Next file: linux/drivers/sound/es1371.c
Previous file: linux/drivers/sound/cmpci.c
Back to the patch index
Back to the overall index
- Lines: 391
- Date:
Sat Oct 30 09:45:36 1999
- Orig file:
v2.3.24/linux/drivers/sound/es1370.c
- Orig date:
Fri Sep 10 23:57:35 1999
diff -u --recursive --new-file v2.3.24/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
@@ -113,6 +113,7 @@
* replaced current->state = x with set_current_state(x)
* 03.09.99 0.30 change read semantics for MIDI to match
* OSS more closely; remove possible wakeup race
+ * 28.10.99 0.31 More waitqueue races fixed
*
* some important things missing in Ensoniq documentation:
*
@@ -1064,9 +1065,9 @@
if (s->dma_dac1.mapped || !s->dma_dac1.ready)
return 0;
- __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->dma_dac1.wait, &wait);
for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&s->lock, flags);
count = s->dma_dac1.count;
spin_unlock_irqrestore(&s->lock, flags);
@@ -1100,9 +1101,9 @@
if (s->dma_dac2.mapped || !s->dma_dac2.ready)
return 0;
- __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->dma_dac2.wait, &wait);
for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&s->lock, flags);
count = s->dma_dac2.count;
spin_unlock_irqrestore(&s->lock, flags);
@@ -1133,6 +1134,7 @@
static ssize_t es1370_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
struct es1370_state *s = (struct es1370_state *)file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned swptr;
@@ -1148,26 +1150,38 @@
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
ret = 0;
+ add_wait_queue(&s->dma_adc.wait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
swptr = s->dma_adc.swptr;
cnt = s->dma_adc.dmasize-swptr;
if (s->dma_adc.count < cnt)
cnt = s->dma_adc.count;
+ if (cnt <= 0)
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
if (cnt <= 0) {
start_adc(s);
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->dma_adc.wait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
swptr = (swptr + cnt) % s->dma_adc.dmasize;
spin_lock_irqsave(&s->lock, flags);
s->dma_adc.swptr = swptr;
@@ -1178,12 +1192,15 @@
ret += cnt;
start_adc(s);
}
+ remove_wait_queue(&s->dma_adc.wait, &wait);
+ set_current_state(TASK_RUNNING);
return ret;
}
static ssize_t es1370_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
struct es1370_state *s = (struct es1370_state *)file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned swptr;
@@ -1199,6 +1216,7 @@
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
ret = 0;
+ add_wait_queue(&s->dma_dac2.wait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
if (s->dma_dac2.count < 0) {
@@ -1209,20 +1227,31 @@
cnt = s->dma_dac2.dmasize-swptr;
if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize)
cnt = s->dma_dac2.dmasize - s->dma_dac2.count;
+ if (cnt <= 0)
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
if (cnt <= 0) {
start_dac2(s);
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->dma_dac2.wait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
swptr = (swptr + cnt) % s->dma_dac2.dmasize;
spin_lock_irqsave(&s->lock, flags);
s->dma_dac2.swptr = swptr;
@@ -1234,6 +1263,8 @@
ret += cnt;
start_dac2(s);
}
+ remove_wait_queue(&s->dma_dac2.wait, &wait);
+ set_current_state(TASK_RUNNING);
return ret;
}
@@ -1285,7 +1316,7 @@
db = &s->dma_adc;
} else
return -EINVAL;
- if (vma->vm_offset != 0)
+ if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << db->buforder))
@@ -1608,6 +1639,7 @@
static int es1370_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
+ DECLARE_WAITQUEUE(wait, current);
struct es1370_state *s = devs;
unsigned long flags;
@@ -1624,8 +1656,12 @@
up(&s->open_sem);
return -EBUSY;
}
+ add_wait_queue(&s->open_wait, &wait);
+ __set_current_state(TASK_INTERRUPTIBLE);
up(&s->open_sem);
- interruptible_sleep_on(&s->open_wait);
+ schedule();
+ remove_wait_queue(&s->open_wait, &wait);
+ set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
down(&s->open_sem);
@@ -1676,8 +1712,8 @@
dealloc_dmabuf(&s->dma_adc);
}
s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
- up(&s->open_sem);
wake_up(&s->open_wait);
+ up(&s->open_sem);
MOD_DEC_USE_COUNT;
return 0;
}
@@ -1705,6 +1741,7 @@
static ssize_t es1370_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
struct es1370_state *s = (struct es1370_state *)file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret = 0;
unsigned long flags;
unsigned swptr;
@@ -1719,6 +1756,7 @@
return ret;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
+ add_wait_queue(&s->dma_dac1.wait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
if (s->dma_dac1.count < 0) {
@@ -1729,20 +1767,31 @@
cnt = s->dma_dac1.dmasize-swptr;
if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize)
cnt = s->dma_dac1.dmasize - s->dma_dac1.count;
+ if (cnt <= 0)
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
if (cnt <= 0) {
start_dac1(s);
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->dma_dac1.wait);
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ schedule();
+ if (signal_pending(current)) {
+ if (!ret)
+ ret = -ERESTARTSYS;
+ break;
+ }
continue;
}
- if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
swptr = (swptr + cnt) % s->dma_dac1.dmasize;
spin_lock_irqsave(&s->lock, flags);
s->dma_dac1.swptr = swptr;
@@ -1754,6 +1803,8 @@
ret += cnt;
start_dac1(s);
}
+ remove_wait_queue(&s->dma_dac1.wait, &wait);
+ set_current_state(TASK_RUNNING);
return ret;
}
@@ -1789,7 +1840,7 @@
return -EINVAL;
if ((ret = prog_dmabuf_dac1(s)) != 0)
return ret;
- if (vma->vm_offset != 0)
+ if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
if (size > (PAGE_SIZE << s->dma_dac1.buforder))
@@ -1991,6 +2042,7 @@
static int es1370_open_dac(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
+ DECLARE_WAITQUEUE(wait, current);
struct es1370_state *s = devs;
unsigned long flags;
@@ -2014,8 +2066,12 @@
up(&s->open_sem);
return -EBUSY;
}
+ add_wait_queue(&s->open_wait, &wait);
+ __set_current_state(TASK_INTERRUPTIBLE);
up(&s->open_sem);
- interruptible_sleep_on(&s->open_wait);
+ schedule();
+ remove_wait_queue(&s->open_wait, &wait);
+ set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
down(&s->open_sem);
@@ -2047,8 +2103,8 @@
stop_dac1(s);
dealloc_dmabuf(&s->dma_dac1);
s->open_mode &= ~FMODE_DAC;
- up(&s->open_sem);
wake_up(&s->open_wait);
+ up(&s->open_sem);
MOD_DEC_USE_COUNT;
return 0;
}
@@ -2097,6 +2153,8 @@
cnt = MIDIINBUF - ptr;
if (s->midi.icnt < cnt)
cnt = s->midi.icnt;
+ if (cnt <= 0)
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
@@ -2106,7 +2164,6 @@
ret = -EAGAIN;
break;
}
- __set_current_state(TASK_INTERRUPTIBLE);
schedule();
if (signal_pending(current)) {
if (!ret)
@@ -2159,8 +2216,10 @@
cnt = MIDIOUTBUF - ptr;
if (s->midi.ocnt + cnt > MIDIOUTBUF)
cnt = MIDIOUTBUF - s->midi.ocnt;
- if (cnt <= 0)
+ if (cnt <= 0) {
+ __set_current_state(TASK_INTERRUPTIBLE);
es1370_handle_midi(s);
+ }
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
@@ -2170,7 +2229,6 @@
ret = -EAGAIN;
break;
}
- __set_current_state(TASK_INTERRUPTIBLE);
schedule();
if (signal_pending(current)) {
if (!ret)
@@ -2228,6 +2286,7 @@
static int es1370_midi_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
+ DECLARE_WAITQUEUE(wait, current);
struct es1370_state *s = devs;
unsigned long flags;
@@ -2244,8 +2303,12 @@
up(&s->open_sem);
return -EBUSY;
}
+ add_wait_queue(&s->open_wait, &wait);
+ __set_current_state(TASK_INTERRUPTIBLE);
up(&s->open_sem);
- interruptible_sleep_on(&s->open_wait);
+ schedule();
+ remove_wait_queue(&s->open_wait, &wait);
+ set_current_state(TASK_RUNNING);
if (signal_pending(current))
return -ERESTARTSYS;
down(&s->open_sem);
@@ -2284,9 +2347,9 @@
VALIDATE_STATE(s);
if (file->f_mode & FMODE_WRITE) {
- __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->midi.owait, &wait);
for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&s->lock, flags);
count = s->midi.ocnt;
spin_unlock_irqrestore(&s->lock, flags);
@@ -2314,8 +2377,8 @@
outl(s->ctrl, s->io+ES1370_REG_CONTROL);
}
spin_unlock_irqrestore(&s->lock, flags);
- up(&s->open_sem);
wake_up(&s->open_wait);
+ up(&s->open_sem);
MOD_DEC_USE_COUNT;
return 0;
}
@@ -2389,7 +2452,7 @@
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1370: version v0.29 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1370: version v0.31 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
if (!RSRCISIOREGION(pcidev, 0))
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)