Hi,

mdc800 used sleep_on and slept with io_lock held.
I converted sleep_on to waitqueues with schedule_timeout and made io_lock
a semaphore from a spinlock.

Somebody with the hardware please test.

        Regards
                Oliver

--- mdc800.c.alt        Sun Dec  2 02:42:01 2001
+++ mdc800.c    Sun Dec  2 02:46:06 2001
@@ -136,6 +136,7 @@

        purb_t                  irq_urb;
        wait_queue_head_t       irq_wait;
+       int                     irq_woken;
        char*                   irq_urb_buffer;

        int                     camera_busy;          // is camera busy ?
@@ -145,11 +146,13 @@
        purb_t                  write_urb;
        char*                   write_urb_buffer;
        wait_queue_head_t       write_wait;
+       int                     written;


        purb_t                  download_urb;
        char*                   download_urb_buffer;
        wait_queue_head_t       download_wait;
+       int                     downloaded;
        int                     download_left;          // Bytes left to download ?


@@ -159,7 +162,7 @@
        int                     out_count;      // Bytes in the buffer

        int                     open;           // Camera device open ?
-       spinlock_t              io_lock;        // IO -lock
+       struct semaphore                io_lock;        // IO -lock

        char                    in [8];         // Command Input Buffer
        int                     in_count;
@@ -284,6 +287,7 @@
        if (wake_up)
        {
                mdc800->camera_request_ready=0;
+               mdc800->irq_woken=1;
                wake_up_interruptible (&mdc800->irq_wait);
        }
 }
@@ -300,9 +304,17 @@
  */
 static int mdc800_usb_waitForIRQ (int mode, int msec)
 {
+        DECLARE_WAITQUEUE(wait, current);
+
        mdc800->camera_request_ready=1+mode;

-       interruptible_sleep_on_timeout (&mdc800->irq_wait, msec*HZ/1000);
+       add_wait_queue(&mdc800->irq_wait, &wait);
+       set_current_state(TASK_INTERRUPTIBLE);
+       if (!mdc800->irq_woken)
+               schedule_timeout (msec*HZ/1000);
+        remove_wait_queue(&mdc800->irq_wait, &wait);
+       set_current_state(TASK_RUNNING);
+       mdc800->irq_woken = 0;

        if (mdc800->camera_request_ready>0)
        {
@@ -310,14 +322,14 @@
                err ("timeout waiting for camera.");
                return -1;
        }
-
+
        if (mdc800->state == NOT_CONNECTED)
        {
                warn ("Camera gets disconnected during waiting for irq.");
                mdc800->camera_request_ready=0;
                return -2;
        }
-
+
        return 0;
 }

@@ -334,9 +346,10 @@
                err ("writing command fails (status=%i)", urb->status);
        }
        else
-       {
+       {
                mdc800->state=READY;
        }
+       mdc800->written = 1;
        wake_up_interruptible (&mdc800->write_wait);
 }

@@ -364,6 +377,7 @@
        {
                err ("request bytes fails (status:%i)", urb->status);
        }
+       mdc800->downloaded = 1;
        wake_up_interruptible (&mdc800->download_wait);
 }

@@ -445,7 +459,7 @@

        info ("Found Mustek MDC800 on USB.");

-       spin_lock (&mdc800->io_lock);
+       down (&mdc800->io_lock);

        mdc800->dev=dev;
        mdc800->open=0;
@@ -484,7 +498,7 @@

        mdc800->state=READY;

-       spin_unlock (&mdc800->io_lock);
+       up (&mdc800->io_lock);

        return mdc800;
 }
@@ -558,7 +572,7 @@
        int retval=0;
        int errn=0;

-       spin_lock (&mdc800->io_lock);
+       down (&mdc800->io_lock);

        if (mdc800->state == NOT_CONNECTED)
        {
@@ -594,7 +608,7 @@
        dbg ("Mustek MDC800 device opened.");

 error_out:
-       spin_unlock (&mdc800->io_lock);
+       up (&mdc800->io_lock);
        return errn;
 }

@@ -607,10 +621,9 @@
        int retval=0;
        dbg ("Mustek MDC800 device closed.");

-       spin_lock (&mdc800->io_lock);
+       down (&mdc800->io_lock);
        if (mdc800->open && (mdc800->state != NOT_CONNECTED))
        {
-               spin_unlock(&mdc800->io_lock);
                usb_unlink_urb (mdc800->irq_urb);
                usb_unlink_urb (mdc800->write_urb);
                usb_unlink_urb (mdc800->download_urb);
@@ -618,11 +631,10 @@
        }
        else
        {
-               spin_unlock (&mdc800->io_lock);
                retval=-EIO;
        }

-
+        up(&mdc800->io_lock);
        return retval;
 }

@@ -634,22 +646,23 @@
 {
        int   left=len, sts=len; /* single transfer size */
        char* ptr=buf;
+       DECLARE_WAITQUEUE(wait, current);

-       spin_lock (&mdc800->io_lock);
+       down (&mdc800->io_lock);
        if (mdc800->state == NOT_CONNECTED)
        {
-               spin_unlock (&mdc800->io_lock);
+               up (&mdc800->io_lock);
                return -EBUSY;
        }
        if (mdc800->state == WORKING)
        {
                warn ("Illegal State \"working\" reached during read ?!");
-               spin_unlock (&mdc800->io_lock);
+               up (&mdc800->io_lock);
                return -EBUSY;
        }
        if (!mdc800->open)
        {
-               spin_unlock (&mdc800->io_lock);
+               up (&mdc800->io_lock);
                return -EBUSY;
        }

@@ -657,7 +670,7 @@
        {
                if (signal_pending (current))
                {
-                       spin_unlock (&mdc800->io_lock);
+                       up (&mdc800->io_lock);
                        return -EINTR;
                }

@@ -676,21 +689,27 @@
                                if (usb_submit_urb (mdc800->download_urb))
                                {
                                        err ("Can't submit download urb 
(status=%i)",mdc800->download_urb->status);
-                                       spin_unlock (&mdc800->io_lock);
+                                       up (&mdc800->io_lock);
                                        return len-left;
                                }
-                               interruptible_sleep_on_timeout 
(&mdc800->download_wait, TO_DOWNLOAD_GET_READY*HZ/1000);
+                               add_wait_queue(&mdc800->download_wait, &wait);
+                               set_current_state(TASK_INTERRUPTIBLE);
+                               if (!mdc800->downloaded)
+                                       schedule_timeout 
+(TO_DOWNLOAD_GET_READY*HZ/1000);
+                                set_current_state(TASK_RUNNING);
+                               remove_wait_queue(&mdc800->download_wait, &wait);
+                               mdc800->downloaded = 0;
                                if (mdc800->download_urb->status != 0)
                                {
                                        err ("request download-bytes fails 
(status=%i)",mdc800->download_urb->status);
-                                       spin_unlock (&mdc800->io_lock);
+                                       up (&mdc800->io_lock);
                                        return len-left;
                                }
                        }
                        else
                        {
                                /* No more bytes -> that's an error*/
-                               spin_unlock (&mdc800->io_lock);
+                               up (&mdc800->io_lock);
                                return -EIO;
                        }
                }
@@ -704,7 +723,7 @@
                }
        }

-       spin_unlock (&mdc800->io_lock);
+       up (&mdc800->io_lock);
        return len-left;
 }

@@ -718,16 +737,17 @@
 static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, 
loff_t *pos)
 {
        int i=0;
+       DECLARE_WAITQUEUE(wait, current);

-       spin_lock (&mdc800->io_lock);
+       down (&mdc800->io_lock);
        if (mdc800->state != READY)
        {
-               spin_unlock (&mdc800->io_lock);
+               up (&mdc800->io_lock);
                return -EBUSY;
        }
        if (!mdc800->open )
        {
-               spin_unlock (&mdc800->io_lock);
+               up (&mdc800->io_lock);
                return -EBUSY;
        }

@@ -735,7 +755,7 @@
        {
                if (signal_pending (current))
                {
-                       spin_unlock (&mdc800->io_lock);
+                       up (&mdc800->io_lock);
                        return -EINTR;
                }

@@ -757,7 +777,7 @@
                else
                {
                        err ("Command is to long !\n");
-                       spin_unlock (&mdc800->io_lock);
+                       up (&mdc800->io_lock);
                        return -EIO;
                }

@@ -769,7 +789,7 @@
                        if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
                        {
                                err ("Camera didn't get ready.\n");
-                               spin_unlock (&mdc800->io_lock);
+                               up (&mdc800->io_lock);
                                return -EIO;
                        }

@@ -781,14 +801,20 @@
                        if (usb_submit_urb (mdc800->write_urb))
                        {
                                err ("submitting write urb fails (status=%i)", 
mdc800->write_urb->status);
-                               spin_unlock (&mdc800->io_lock);
+                               up (&mdc800->io_lock);
                                return -EIO;
                        }
-                       interruptible_sleep_on_timeout (&mdc800->write_wait, 
TO_WRITE_GET_READY*HZ/1000);
+                       add_wait_queue(&mdc800->write_wait, &wait);
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       if (!mdc800->written)
+                               schedule_timeout (TO_WRITE_GET_READY*HZ/1000);
+                        set_current_state(TASK_RUNNING);
+                       remove_wait_queue(&mdc800->write_wait, &wait);
+                       mdc800->written = 0;
                        if (mdc800->state == WORKING)
                        {
                                usb_unlink_urb (mdc800->write_urb);
-                               spin_unlock (&mdc800->io_lock);
+                               up (&mdc800->io_lock);
                                return -EIO;
                        }

@@ -800,7 +826,7 @@
                                        {
                                                err ("call 0x07 before 0x05,0x3e");
                                                mdc800->state=READY;
-                                               spin_unlock (&mdc800->io_lock);
+                                               up (&mdc800->io_lock);
                                                return -EIO;
                                        }
                                        mdc800->pic_len=-1;
@@ -819,7 +845,7 @@
                                                if (mdc800_usb_waitForIRQ 
(1,TO_READ_FROM_IRQ))
                                                {
                                                        err ("requesting answer from 
irq fails");
-                                                       spin_unlock (&mdc800->io_lock);
+                                                       up (&mdc800->io_lock);
                                                        return -EIO;
                                                }

@@ -847,7 +873,7 @@
                                                if (mdc800_usb_waitForIRQ 
(0,TO_DEFAULT_COMMAND))
                                                {
                                                        err ("Command Timeout.");
-                                                       spin_unlock (&mdc800->io_lock);
+                                                       up (&mdc800->io_lock);
                                                        return -EIO;
                                                }
                                        }
@@ -857,7 +883,7 @@
                }
                i++;
        }
-       spin_unlock (&mdc800->io_lock);
+       up (&mdc800->io_lock);
        return i;
 }

@@ -916,11 +942,15 @@
        mdc800->dev=0;
        mdc800->open=0;
        mdc800->state=NOT_CONNECTED;
-       spin_lock_init (&mdc800->io_lock);
+       init_MUTEX (&mdc800->io_lock);

        init_waitqueue_head (&mdc800->irq_wait);
        init_waitqueue_head (&mdc800->write_wait);
        init_waitqueue_head (&mdc800->download_wait);
+
+       mdc800->irq_woken = 0;
+       mdc800->downloaded = 0;
+       mdc800->written = 0;

        try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
        try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));


_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to