Hello all,
  I have attached sound driver locking patches for:
drivers/sound/cs4281/cs4281m.c
drivers/sound/i810_audio.c

The patches are against 2.4.5-ac13, and address the sound driver locking
issue mentioned in the -ac series.

Please review. Thanks.
Regards,
Frank
--- drivers/sound/cs4281/cs4281m.c.old  Mon Jun 11 00:23:02 2001

+++ drivers/sound/cs4281/cs4281m.c      Tue Jun 12 01:17:14 2001

@@ -293,6 +293,7 @@

 

        struct cs4281_pm pm;

        struct cs4281_pipeline pl[CS4281_NUMBER_OF_PIPELINES];

+       struct semaphore sem;

 };

 

 #include "cs4281pm-24.c"

@@ -2876,7 +2877,7 @@

 {

        struct cs4281_state *s =

            (struct cs4281_state *) file->private_data;

-       ssize_t ret;

+       ssize_t ret = 0;

        unsigned long flags;

        unsigned swptr;

        int cnt;

@@ -2890,11 +2891,12 @@

                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;

 //

 // "count" is the amount of bytes to read (from app), is decremented each loop

 //      by the amount of bytes that have been returned to the user buffer.

@@ -2950,10 +2952,23 @@

                        // the loop when wake up occurs.

                        start_adc(s);

                        if (file->f_flags & O_NONBLOCK)

-                               return ret ? ret : -EAGAIN;

+                       {

+                               if(!ret) ret = -EAGAIN;

+                               goto out;

+                       }

+                       up(&s->sem);

                        interruptible_sleep_on(&s->dma_adc.wait);

                        if (signal_pending(current))

-                               return ret ? ret : -ERESTARTSYS;

+                       {

+                               if(!ret) ret = -ERESTARTSYS;

+                               goto out;

+                       }

+                       down(&s->sem);

+                       if (s->dma_adc.mapped)

+                       {

+                               ret = -ENXIO;

+                               goto out;

+                       }

                        continue;

                }

                // there are bytes in the buffer to read.

@@ -2971,7 +2986,10 @@

 

                if (cs_copy_to_user

                    (s, buffer, s->dma_adc.rawbuf + swptr, cnt, &copied))

-                       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;

@@ -2984,6 +3002,8 @@

        }

        CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2,

                  printk(KERN_INFO "cs4281: cs4281_read()- %d\n", ret));

+out:

+       up(&s->sem);

        return ret;

 }

 

@@ -3007,10 +3027,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;

+

        ret = 0;

        while (count > 0) {

                spin_lock_irqsave(&s->lock, flags);

@@ -3035,14 +3057,30 @@

                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);

                        interruptible_sleep_on(&s->dma_dac.wait);

                        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 (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);

                s->dma_dac.swptr = swptr;

@@ -3056,6 +3094,8 @@

        }

        CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2,

                  printk(KERN_INFO "cs4281: cs4281_write()- %d\n", ret));

+out:

+       up(&s->sem);

        return ret;

 }

 

@@ -3132,35 +3172,49 @@

                  printk(KERN_INFO "cs4281: cs4281_mmap()+\n"));

 

        VALIDATE_STATE(s);

+       down(&s->sem);

        if (vma->vm_flags & VM_WRITE) {

                if ((ret = prog_dmabuf_dac(s)) != 0)

-                       return ret;

+                       goto out;

                db = &s->dma_dac;

        } else if (vma->vm_flags & VM_READ) {

                if ((ret = prog_dmabuf_adc(s)) != 0)

-                       return ret;

+                       goto out;

                db = &s->dma_adc;

-       } else

-               return -EINVAL;

+       } else {

+               ret = -EINVAL;

+               goto out;

+       }

 //

 // only support PLAYBACK for now

 //

        db = &s->dma_dac;

 

        if (cs4x_pgoff(vma) != 0)

-               return -EINVAL;

+       {

+               ret = -EINVAL;

+               goto out;

+       }

        size = vma->vm_end - vma->vm_start;

        if (size > (PAGE_SIZE << db->buforder))

-               return -EINVAL;

+       {

+               ret = -EINVAL;

+               goto out;

+       }

        if (remap_page_range

            (vma->vm_start, virt_to_phys(db->rawbuf), size,

-            vma->vm_page_prot)) return -EAGAIN;

+            vma->vm_page_prot)) 

+               { 

+               ret = -EAGAIN;

+               goto out;

+               }

        db->mapped = 1;

 

        CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4,

                  printk(KERN_INFO "cs4281: cs4281_mmap()- 0 size=%d\n",

                         (unsigned) size));

-

+out:

+       up(&s->sem);

        return 0;

 }

 

@@ -4323,6 +4377,7 @@

        init_waitqueue_head(&s->midi.iwait);

        init_waitqueue_head(&s->midi.owait);

        init_MUTEX(&s->open_sem);

+       init_MUTEX(&s->sem);

        init_MUTEX(&s->open_sem_adc);

        init_MUTEX(&s->open_sem_dac);

        spin_lock_init(&s->lock);

--- drivers/sound/i810_audio.c.old      Mon Jun 11 00:23:05 2001
+++ drivers/sound/i810_audio.c  Tue Jun 12 19:03:50 2001
@@ -298,6 +298,7 @@
                unsigned ossmaxfrags;
                unsigned subdivision;
        } dmabuf;
+       struct semaphore sem;
 };
 
 
@@ -1066,7 +1067,7 @@
 {
        struct i810_state *state = (struct i810_state *)file->private_data;
        struct dmabuf *dmabuf = &state->dmabuf;
-       ssize_t ret;
+       ssize_t ret = 0;
        unsigned long flags;
        unsigned int swptr;
        int cnt;
@@ -1088,13 +1089,14 @@
                        return -EBUSY;
                }
        }
-       if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
-               return ret;
        if (!access_ok(VERIFY_WRITE, buffer, count))
                return -EFAULT;
        dmabuf->trigger &= ~PCM_ENABLE_OUTPUT;
-       ret = 0;
 
+       down(&state->sem);
+       if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
+               goto out;
+       
        while (count > 0) {
                spin_lock_irqsave(&state->card->lock, flags);
                swptr = dmabuf->swptr;
@@ -1119,8 +1121,9 @@
                        }
                        if (file->f_flags & O_NONBLOCK) {
                                if (!ret) ret = -EAGAIN;
-                               return ret;
+                               goto out;
                        }
+                       up(&state->sem);
                        /* This isnt strictly right for the 810  but it'll do */
                        tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
                        tmo >>= 1;
@@ -1142,15 +1145,21 @@
                                   while loop begin and we REALLY have space to record 
*/
                        }
                        if (signal_pending(current)) {
-                               ret = ret ? ret : -ERESTARTSYS;
-                               return ret;
+                               if(!ret) ret = -ERESTARTSYS;
+                               goto out;
+                       }
+                       down(&state->sem);
+                       if (dmabuf->mapped)
+                       {
+                               ret = -ENXIO;
+                               goto out;
                        }
                        continue;
                }
 
                if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) {
                        if (!ret) ret = -EFAULT;
-                       return ret;
+                       goto out;
                }
 
                swptr = (swptr + cnt) % dmabuf->dmasize;
@@ -1164,6 +1173,8 @@
                buffer += cnt;
                ret += cnt;
        }
+out:
+       up(&state->sem);
        i810_update_lvi(state,1);
        start_adc(state);
        return ret;
@@ -1196,11 +1207,12 @@
                if(!dmabuf->write_channel)
                        return -EBUSY;
        }
-       if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
-               return ret;
        if (!access_ok(VERIFY_READ, buffer, count))
                return -EFAULT;
        dmabuf->trigger &= ~PCM_ENABLE_INPUT;
+       down(&state->sem);
+       if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
+               goto out;
        ret = 0;
 
        while (count > 0) {
@@ -1228,8 +1240,9 @@
                        }
                        if (file->f_flags & O_NONBLOCK) {
                                if (!ret) ret = -EAGAIN;
-                               return ret;
+                               goto out;
                        }
+                       up(&state->sem);
                        /* Not strictly correct but works */
                        tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 4);
                        /* There are two situations when sleep_on_timeout returns, one 
is when
@@ -1252,13 +1265,19 @@
                        }
                        if (signal_pending(current)) {
                                if (!ret) ret = -ERESTARTSYS;
-                               return ret;
+                               goto out;
                        }
                        continue;
                }
+               down(&state->sem);
+               if (dmabuf->mapped)
+               {
+                       ret = -ENXIO;
+                       goto out;
+               }
                if (copy_from_user(dmabuf->rawbuf+swptr,buffer,cnt)) {
                        if (!ret) ret = -EFAULT;
-                       return ret;
+                       goto out;
                }
 
                swptr = (swptr + cnt) % dmabuf->dmasize;
@@ -1277,6 +1296,8 @@
                if((x + dmabuf->count) < dmabuf->dmasize)
                        memset(dmabuf->rawbuf + swptr, '\0', x);
        }
+out:
+       up(&state->sem);
        i810_update_lvi(state,0);
        if (!dmabuf->enable && dmabuf->count >= dmabuf->userfragsize)
                start_dac(state);
@@ -1323,6 +1344,7 @@
        unsigned long size;
 
        lock_kernel();
+       down(&state->sem);
        if (vma->vm_flags & VM_WRITE) {
                if (!dmabuf->write_channel &&
                    (dmabuf->write_channel =
@@ -1362,6 +1384,7 @@
        printk("i810_audio: mmap'ed %ld bytes of data space\n", size);
 #endif
 out:
+       up(&state->sem);
        unlock_kernel();
        return ret;
 }
@@ -1784,6 +1807,7 @@
        state->magic = I810_STATE_MAGIC;
        init_waitqueue_head(&dmabuf->wait);
        init_MUTEX(&state->open_sem);
+       init_MUTEX(&state->sem);
        file->private_data = state;
        dmabuf->trigger = 0;
 

Reply via email to