lkml.org 
[lkml]   [2001]   [Jun]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
Date
From
Subjectpatches sound driver locking issue
Hello all,
I have attached patches against the following sound drivers to fix the locking issues mentioned in Alan's release notes for 2.4.5-ac9 . Please CC me on your comments to the code (I can address the issues quicker). Thanks.
drivers/sound/esssolo1.c
drivers/sound/maestro.c
drivers/sound/maestro3.c
drivers/sound/cmpci.c

Regards,
Frank

--- 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);--- drivers/sound/maestro.c.old Tue Jun 5 21:21:43 2001
+++ drivers/sound/maestro.c Tue Jun 5 23:44:41 2001
@@ -431,6 +431,7 @@

/* pointer to each dsp?s piece of the apu->src buffer page */
void *mixbuf;
+ struct semaphore sem;

};

@@ -2258,7 +2259,7 @@
ess_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
struct ess_state *s = (struct ess_state *)file->private_data;
- ssize_t ret;
+ ssize_t ret = 0;
unsigned long flags;
unsigned swptr;
int cnt;
@@ -2269,13 +2270,13 @@
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;
if(!(combbuf = kmalloc(count,GFP_KERNEL)))
return -ENOMEM;
- ret = 0;
+ down(&s->sem);
+ if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
+ goto rec_return_free;

calc_bob_rate(s);

@@ -2298,9 +2299,10 @@
start_adc(s);
if (file->f_flags & O_NONBLOCK)
{
- ret = ret ? ret : -EAGAIN;
+ if(!ret) ret = -EAGAIN;
goto rec_return_free;
}
+ up(&s->sem);
if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {
if(! s->card->in_suspend) printk(KERN_DEBUG "maestro: 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,
@@ -2317,7 +2319,13 @@
}
if (signal_pending(current))
{
- ret = ret ? ret : -ERESTARTSYS;
+ if(!ret) ret = -ERESTARTSYS;
+ goto rec_return_free;
+ }
+ down(&s->sem);
+ if (s->dma_adc.mapped)
+ {
+ ret = -ENXIO;
goto rec_return_free;
}
continue;
@@ -2327,12 +2335,12 @@
/* swptr/2 so that we know the real offset in each apu's buffer */
comb_stereo(s->dma_adc.rawbuf,combbuf,swptr/2,cnt,s->dma_adc.dmasize);
if (copy_to_user(buffer, combbuf, cnt)) {
- ret = ret ? ret : -EFAULT;
+ if(!ret) ret = -EFAULT;
goto rec_return_free;
}
} else {
if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
- ret = ret ? ret : -EFAULT;
+ if(!ret) ret = -EFAULT;
goto rec_return_free;
}
}
@@ -2349,6 +2357,7 @@
}

rec_return_free:
+ up(&s->sem);
if(combbuf) kfree(combbuf);
return ret;
}
@@ -2367,10 +2376,11 @@
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;
+ down(&s->sem);
+ if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+ goto return_free;
ret = 0;

calc_bob_rate(s);
@@ -2400,6 +2410,7 @@
if(!ret) ret = -EAGAIN;
goto return_free;
}
+ up(&s->sem);
if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {
if(! s->card->in_suspend) printk(KERN_DEBUG "maestro: 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,
@@ -2418,6 +2429,12 @@
if (!ret) ret = -ERESTARTSYS;
goto return_free;
}
+ down(&s->sem);
+ if (s->dma_dac.mapped)
+ {
+ ret = -ENXIO;
+ goto return_free;
+ }
continue;
}
if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
@@ -2439,6 +2456,7 @@
start_dac(s);
}
return_free:
+ up(&s->sem);
return ret;
}

@@ -2493,11 +2511,12 @@

VALIDATE_STATE(s);
lock_kernel();
+ down(&s->sem);
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf(s, 1)) != 0)
goto out;
db = &s->dma_dac;
- } else
+ } else {
#if 0
/* if we can have the wp/wc do the combining
we can turn this back on. */
@@ -2507,19 +2526,23 @@
db = &s->dma_adc;
} else
#endif
+ 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 = -EAGAIN;
goto out;
- ret = -EAGAIN;
+ }
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;
}
@@ -3463,6 +3486,7 @@
init_waitqueue_head(&s->open_wait);
spin_lock_init(&s->lock);
init_MUTEX(&s->open_sem);
+ init_MUTEX(&s->sem);
s->magic = ESS_STATE_MAGIC;

s->apu[0] = 6*i;--- drivers/sound/maestro3.c.old Tue May 8 22:24:57 2001
+++ drivers/sound/maestro3.c Wed Jun 6 00:00:06 2001
@@ -242,6 +242,7 @@
dma_addr_t handle;

} dma_dac, dma_adc;
+ struct semaphore sem;
};

struct m3_card {
@@ -1328,7 +1329,7 @@
static ssize_t m3_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
struct m3_state *s = (struct m3_state *)file->private_data;
- ssize_t ret;
+ ssize_t ret = 0;
unsigned long flags;
unsigned swptr;
int cnt;
@@ -1338,12 +1339,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;
spin_lock_irqsave(&s->lock, flags);

while (count > 0) {
@@ -1361,10 +1361,10 @@
start_adc(s);
if (file->f_flags & O_NONBLOCK)
{
- ret = ret ? ret : -EAGAIN;
+ if(!ret) ret = -EAGAIN;
goto out;
}
-
+ up(&s->sem);
spin_unlock_irqrestore(&s->lock, flags);
timed_out = interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ) == 0;
spin_lock_irqsave(&s->lock, flags);
@@ -1379,16 +1379,22 @@
}
if (signal_pending(current))
{
- ret = ret ? ret : -ERESTARTSYS;
+ if(!ret) ret = -ERESTARTSYS;
goto out;
}
+ down(&s->sem);
+ if (s->dma_adc.mapped)
+ {
+ ret = -ENXIO;
+ goto out;
+ }
continue;
}

spin_unlock_irqrestore(&s->lock, flags);
if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
- ret = ret ? ret : -EFAULT;
- return ret;
+ if(!ret) ret = -EFAULT;
+ goto out;
}
spin_lock_irqsave(&s->lock, flags);

@@ -1402,6 +1408,7 @@
}

out:
+ up(&s->sem);
spin_unlock_irqrestore(&s->lock, flags);
return ret;
}
@@ -1419,10 +1426,11 @@
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;
+ down(&s->sem);
+ if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+ goto out;
ret = 0;

spin_lock_irqsave(&s->lock, flags);
@@ -1451,6 +1459,7 @@
if(!ret) ret = -EAGAIN;
goto out;
}
+ up(&s->sem);
spin_unlock_irqrestore(&s->lock, flags);
timed_out = interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ) == 0;
spin_lock_irqsave(&s->lock, flags);
@@ -1466,12 +1475,18 @@
if (!ret) ret = -ERESTARTSYS;
goto out;
}
+ down(&s->sem);
+ if (s->dma_dac.mapped)
+ {
+ ret = -ENXIO;
+ goto out;
+ }
continue;
}
spin_unlock_irqrestore(&s->lock, flags);
if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
if (!ret) ret = -EFAULT;
- return ret;
+ goto out;
}
spin_lock_irqsave(&s->lock, flags);

@@ -1489,6 +1504,7 @@
start_dac(s);
}
out:
+ up(&s->sem);
spin_unlock_irqrestore(&s->lock, flags);
return ret;
}
@@ -1534,17 +1550,20 @@
int ret = -EINVAL;

VALIDATE_STATE(s);
+ down(&s->sem);
if (vma->vm_flags & VM_WRITE) {
if ((ret = prog_dmabuf(s, 0)) != 0)
- return ret;
+ goto out;
db = &s->dma_dac;
} else
if (vma->vm_flags & VM_READ) {
if ((ret = prog_dmabuf(s, 1)) != 0)
- return ret;
+ goto out;
db = &s->dma_adc;
- } else
- return -EINVAL;
+ } else {
+ ret = -EINVAL;
+ goto out;
+ }

max_size = db->dmasize;

@@ -1554,14 +1573,17 @@

if(size > max_size)
goto out;
+
if(offset > max_size - size)
+ {
+ ret = -EAGAIN;
goto out;
+ }

/*
* this will be ->nopage() once I can
* ask Jeff what the hell I'm doing wrong.
*/
- ret = -EAGAIN;
if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
goto out;

@@ -1569,6 +1591,7 @@
ret = 0;

out:
+ up(&s->sem);
return ret;
}

@@ -2674,6 +2697,7 @@
init_waitqueue_head(&s->open_wait);
spin_lock_init(&s->lock);
init_MUTEX(&(s->open_sem));
+ init_MUTEX(&s->sem);
s->magic = M3_STATE_MAGIC;

m3_assp_client_init(s);--- drivers/sound/esssolo1.c.old Tue Jun 5 01:34:16 2001
+++ drivers/sound/esssolo1.c Tue Jun 5 01:48:00 2001
@@ -226,6 +226,7 @@
} midi;

struct gameport gameport;
+ struct semaphore sem;
};

/* --------------------------------------------------------------------- */
@@ -1010,7 +1011,7 @@
{
struct solo1_state *s = (struct solo1_state *)file->private_data;
DECLARE_WAITQUEUE(wait, current);
- ssize_t ret;
+ ssize_t ret = 0;
unsigned long flags;
unsigned swptr;
int cnt;
@@ -1020,11 +1021,13 @@
return -ESPIPE;
if (s->dma_adc.mapped)
return -ENXIO;
- if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
- return ret;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
- ret = 0;
+
+ down(&s->sem);
+ if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+ goto out;
+
add_wait_queue(&s->dma_adc.wait, &wait);
while (count > 0) {
spin_lock_irqsave(&s->lock, flags);
@@ -1058,8 +1061,9 @@
if (file->f_flags & O_NONBLOCK) {
if (!ret)
ret = -EAGAIN;
- break;
+ goto out;
}
+ up(&s->sem);
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"
@@ -1073,14 +1077,20 @@
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
- break;
+ 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)) {
if (!ret)
ret = -EFAULT;
- break;
+ goto out;
}
swptr = (swptr + cnt) % s->dma_adc.dmasize;
spin_lock_irqsave(&s->lock, flags);
@@ -1097,6 +1107,8 @@
read_ctrl(s, 0xb8), inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->sbbase+0xc));
#endif
}
+out:
+ up(&s->sem);
remove_wait_queue(&s->dma_adc.wait, &wait);
set_current_state(TASK_RUNNING);
return ret;
@@ -1116,10 +1128,12 @@
return -ESPIPE;
if (s->dma_dac.mapped)
return -ENXIO;
- if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
- return ret;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
+ down(&s->sem);
+ if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
+ goto out;
+
#if 0
printk(KERN_DEBUG "solo1_write: reg 70: 0x%02x 71: 0x%02x 72: 0x%02x 74: 0x%02x 76: 0x%02x 78: 0x%02x 7A: 0x%02x\n"
KERN_DEBUG "solo1_write: DMA: addr: 0x%08x cnt: 0x%04x stat: 0x%02x SBstat: 0x%02x\n",
@@ -1151,20 +1165,27 @@
if (file->f_flags & O_NONBLOCK) {
if (!ret)
ret = -EAGAIN;
- break;
+ goto out;
}
+ up(&s->sem);
schedule();
if (signal_pending(current)) {
if (!ret)
ret = -ERESTARTSYS;
- break;
+ goto out;
+ }
+ down(&s->sem);
+ if (s->dma_dac.mapped)
+ {
+ ret = -ENXIO;
+ goto out;
}
continue;
}
if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
if (!ret)
ret = -EFAULT;
- break;
+ goto out;
}
swptr = (swptr + cnt) % s->dma_dac.dmasize;
spin_lock_irqsave(&s->lock, flags);
@@ -1178,6 +1199,8 @@
if (s->dma_dac.enabled)
start_dac(s);
}
+out:
+ up(&s->sem);
remove_wait_queue(&s->dma_dac.wait, &wait);
set_current_state(TASK_RUNNING);
return ret;
@@ -1243,15 +1266,18 @@
if ((ret = prog_dmabuf_adc(s)) != 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 = -EAGAIN;
goto out;
- ret = -EAGAIN;
+ }
if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
goto out;
db->mapped = 1;
@@ -2322,6 +2348,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 = SOLO1_MAGIC;
s->dev = pcidev;
\
 
 \ /
  Last update: 2005-03-22 12:54    [W:0.038 / U:0.052 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site