patch-2.3.25 linux/drivers/sound/esssolo1.c
Next file: linux/drivers/sound/maestro.c
Previous file: linux/drivers/sound/es1371.c
Back to the patch index
Back to the overall index
- Lines: 325
- Date:
Sat Oct 30 09:45:36 1999
- Orig file:
v2.3.24/linux/drivers/sound/esssolo1.c
- Orig date:
Sat Oct 9 11:47:50 1999
diff -u --recursive --new-file v2.3.24/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
@@ -60,6 +60,7 @@
* OSS more closely; remove possible wakeup race
* 07.10.99 0.9 Fix initialization; complain if sequencer writes time out
* Revised resource grabbing for the FM synthesizer
+ * 28.10.99 0.10 More waitqueue races fixed
*
*/
@@ -101,7 +102,7 @@
#define SOLO1_MAGIC ((PCI_VENDOR_ID_ESS<<16)|PCI_DEVICE_ID_ESS_SOLO1)
-#define DDMABASE_OFFSET 0x10 /* chip bug workaround kludge */
+#define DDMABASE_OFFSET 0 /* chip bug workaround kludge */
#define DDMABASE_EXTENT 16
#define IOBASE_EXTENT 16
@@ -939,9 +940,9 @@
if (s->dma_dac.mapped)
return 0;
- __set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&s->dma_dac.wait, &wait);
for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
spin_lock_irqsave(&s->lock, flags);
count = s->dma_dac.count;
spin_unlock_irqrestore(&s->lock, flags);
@@ -974,6 +975,7 @@
static ssize_t solo1_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
struct solo1_state *s = (struct solo1_state *)file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned swptr;
@@ -989,12 +991,15 @@
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;
@@ -1015,9 +1020,12 @@
#endif
if (inb(s->ddmabase+15) & 1)
printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n");
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->dma_adc.wait);
+ if (file->f_flags & O_NONBLOCK) {
+ if (!ret)
+ ret = -EAGAIN;
+ break;
+ }
+ schedule();
#ifdef DEBUGREC
printk(KERN_DEBUG "solo1_read: regs: A1: 0x%02x A2: 0x%02x A4: 0x%02x A5: 0x%02x A8: 0x%02x\n"
KERN_DEBUG "solo1_read: regs: B1: 0x%02x B2: 0x%02x B7: 0x%02x B8: 0x%02x B9: 0x%02x\n"
@@ -1027,12 +1035,18 @@
read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9),
inl(s->ddmabase), inw(s->ddmabase+4), inb(s->ddmabase+8), inb(s->ddmabase+15), inb(s->sbbase+0xc), cnt);
#endif
- if (signal_pending(current))
- return ret ? ret : -ERESTARTSYS;
+ 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;
@@ -1047,12 +1061,15 @@
read_ctrl(s, 0xb8), inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->sbbase+0xc));
#endif
}
+ remove_wait_queue(&s->dma_adc.wait, &wait);
+ set_current_state(TASK_RUNNING);
return ret;
}
static ssize_t solo1_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
struct solo1_state *s = (struct solo1_state *)file->private_data;
+ DECLARE_WAITQUEUE(wait, current);
ssize_t ret;
unsigned long flags;
unsigned swptr;
@@ -1076,6 +1093,7 @@
read_mixer(s, 0x78), read_mixer(s, 0x7a), inw(s->iobase+4), inb(s->iobase+6), inb(s->sbbase+0xc));
#endif
ret = 0;
+ add_wait_queue(&s->dma_dac.wait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
if (s->dma_dac.count < 0) {
@@ -1086,20 +1104,31 @@
cnt = s->dma_dac.dmasize-swptr;
if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
cnt = s->dma_dac.dmasize - s->dma_dac.count;
+ if (cnt <= 0)
+ __set_current_state(TASK_INTERRUPTIBLE);
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
if (cnt <= 0) {
start_dac(s);
- if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EAGAIN;
- interruptible_sleep_on(&s->dma_dac.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_dac.rawbuf + swptr, buffer, cnt))
- return ret ? ret : -EFAULT;
+ if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+ if (!ret)
+ ret = -EFAULT;
+ break;
+ }
swptr = (swptr + cnt) % s->dma_dac.dmasize;
spin_lock_irqsave(&s->lock, flags);
s->dma_dac.swptr = swptr;
@@ -1111,6 +1140,8 @@
ret += cnt;
start_dac(s);
}
+ remove_wait_queue(&s->dma_dac.wait, &wait);
+ set_current_state(TASK_RUNNING);
return ret;
}
@@ -1168,7 +1199,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))
@@ -1473,8 +1504,8 @@
dealloc_dmabuf(&s->dma_adc);
}
s->open_mode &= ~(FMODE_READ | FMODE_WRITE);
- up(&s->open_sem);
wake_up(&s->open_wait);
+ up(&s->open_sem);
MOD_DEC_USE_COUNT;
return 0;
}
@@ -1482,6 +1513,7 @@
static int solo1_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
+ DECLARE_WAITQUEUE(wait, current);
struct solo1_state *s = devs;
while (s && ((s->dev_audio ^ minor) & ~0xf))
@@ -1497,8 +1529,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);
@@ -1630,6 +1666,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;
@@ -1639,7 +1677,6 @@
ret = -EAGAIN;
break;
}
- __set_current_state(TASK_INTERRUPTIBLE);
schedule();
if (signal_pending(current)) {
if (!ret)
@@ -1692,8 +1729,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);
solo1_handle_midi(s);
+ }
spin_unlock_irqrestore(&s->lock, flags);
if (cnt > count)
cnt = count;
@@ -1703,7 +1742,6 @@
ret = -EAGAIN;
break;
}
- __set_current_state(TASK_INTERRUPTIBLE);
schedule();
if (signal_pending(current)) {
if (!ret)
@@ -1761,6 +1799,7 @@
static int solo1_midi_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
+ DECLARE_WAITQUEUE(wait, current);
struct solo1_state *s = devs;
unsigned long flags;
@@ -1777,8 +1816,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);
@@ -1822,9 +1865,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);
@@ -1852,8 +1895,8 @@
del_timer(&s->midi.timer);
}
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;
}
@@ -1978,6 +2021,7 @@
static int solo1_dmfm_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
+ DECLARE_WAITQUEUE(wait, current);
struct solo1_state *s = devs;
while (s && s->dev_dmfm != minor)
@@ -1993,8 +2037,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);
@@ -2033,8 +2081,8 @@
outb(0, s->sbbase+3);
}
release_region(s->sbbase, FMSYNTH_EXTENT);
- up(&s->open_sem);
wake_up(&s->open_wait);
+ up(&s->open_sem);
MOD_DEC_USE_COUNT;
return 0;
}
@@ -2094,7 +2142,7 @@
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "solo1: version v0.7 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "solo1: version v0.10 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, 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)