(patch 6 of 8)

Hi,

Here's a patch for the usb mdc800 driver against 2.2.20-pre2 that brings
it up to the same logic level that is in 2.4.5.

thanks,

greg k-h
diff -Nru a/drivers/usb/mdc800.c b/drivers/usb/mdc800.c
--- a/drivers/usb/mdc800.c      Tue Jun 12 22:34:40 2001
+++ b/drivers/usb/mdc800.c      Tue Jun 12 22:34:40 2001
@@ -22,13 +22,26 @@
  *     (c) 1999/2000 Henning Zabel <[EMAIL PROTECTED]>
  *
  *
- *     The driver brings the USB functions of the MDC800 to Linux.
+ * The driver brings the USB functions of the MDC800 to Linux.
  * To use the Camera you must support the USB Protocoll of the camera
  * to the Kernel Node.
  * The Driver uses a misc device Node. Create it with :
  * mknod /dev/mustek c 180 32
  *
  * The driver supports only one camera.
+ * 
+ * (08/04/2001) gb
+ * Identify version on module load.
+ *
+ * version 0.7.5
+ * Fixed potential SMP races with Spinlocks.
+ * Thanks to Oliver Neukum <[EMAIL PROTECTED]> who 
+ * noticed the race conditions.
+ * (30/10/2000)
+ *
+ * Fixed: Setting urb->dev before submitting urb.
+ * by Greg KH <[EMAIL PROTECTED]>
+ * (13/10/2000)
  *
  * version 0.7.3
  * bugfix : The mdc800->state field gets set to READY after the
@@ -61,7 +74,7 @@
  * (09/11/1999)
  *
  * version 0.5.0:
- *     first Version that gets a version number. Most of the needed
+ * first Version that gets a version number. Most of the needed
  * functions work.
  * (20/10/1999)
  */
@@ -80,8 +93,12 @@
 
 #include <linux/usb.h>
 
-#define VERSION        "0.7.3"
-#define RELEASE_DATE   "(24/04/2000)"
+/*
+ * Version Information
+ */
+#define DRIVER_VERSION "v0.7.5 (30/10/2000)"
+#define DRIVER_AUTHOR "Henning Zabel <[EMAIL PROTECTED]>"
+#define DRIVER_DESC "USB Driver for Mustek MDC800 Digital Camera"
 
 /* Vendor and Product Information */
 #define MDC800_VENDOR_ID       0x055f
@@ -123,7 +140,7 @@
 
        int                     camera_busy;          // is camera busy ?
        int                     camera_request_ready; // Status to synchronize with irq
-       char                    camera_response [8];     // last Bytes send after busy
+       char                    camera_response [8];  // last Bytes send after busy
 
        purb_t                  write_urb;
        char*                   write_urb_buffer;
@@ -138,16 +155,16 @@
 
        /* Device Data */
        char                    out [64];       // Answer Buffer
-       int                     out_ptr;                // Index to the first not 
readen byte
+       int                     out_ptr;        // Index to the first not readen byte
        int                     out_count;      // Bytes in the buffer
 
-       int                     open;                   // Camera device open ?
-       int                     rw_lock;                // Block read <-> write
+       int                     open;           // Camera device open ?
+       spinlock_t              io_lock;        // IO -lock     
 
-       char                    in [8];                 // Command Input Buffer
+       char                    in [8];         // Command Input Buffer
        int                     in_count;
 
-       int                     pic_index;              // Cache for the Imagesize (-1 
for nothing cached )
+       int                     pic_index;      // Cache for the Imagesize (-1 for 
+nothing cached )
        int                     pic_len;
 };
 
@@ -253,16 +270,16 @@
                }
        }
        wake_up= ( mdc800->camera_request_ready > 0 )
-                               &&
-                               (
-                                       ((mdc800->camera_request_ready == 1) && 
(!mdc800->camera_busy))
-                               ||
-                                       ((mdc800->camera_request_ready == 2) && 
data_received)
-                               ||
-                                       ((mdc800->camera_request_ready == 3) && 
(mdc800->camera_busy))
-                               ||
-                                       (urb->status < 0)
-                               );
+               &&
+               (
+                       ((mdc800->camera_request_ready == 1) && (!mdc800->camera_busy))
+               ||
+                       ((mdc800->camera_request_ready == 2) && data_received)
+               ||
+                       ((mdc800->camera_request_ready == 3) && (mdc800->camera_busy))
+               ||
+                       (urb->status < 0)
+               );
 
        if (wake_up)
        {
@@ -362,7 +379,7 @@
  */
 static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum )
 {
-       int                                                                            
 i,j;
+       int i,j;
        struct usb_interface_descriptor *intf_desc;
        int irq_interval=0;
 
@@ -432,10 +449,10 @@
 
        info ("Found Mustek MDC800 on USB.");
 
+       spin_lock (&mdc800->io_lock);
+
        mdc800->dev=dev;
-       mdc800->state=READY;
        mdc800->open=0;
-       mdc800->rw_lock=0;
 
        /* Setup URB Structs */
        FILL_INT_URB (
@@ -469,6 +486,10 @@
                mdc800
        );
 
+       mdc800->state=READY;
+
+       spin_unlock (&mdc800->io_lock);
+       
        return mdc800;
 }
 
@@ -539,18 +560,21 @@
 static int mdc800_device_open (struct inode* inode, struct file *file)
 {
        int retval=0;
+       int errn=0;
+
+       spin_lock (&mdc800->io_lock);
        
        if (mdc800->state == NOT_CONNECTED)
        {
-               return -EBUSY;
+               errn=-EBUSY;
+               goto error_out;
        }
-
        if (mdc800->open)
        {
-               return -EBUSY;
+               errn=-EBUSY;
+               goto error_out;
        }
 
-       mdc800->rw_lock=0;
        mdc800->in_count=0;
        mdc800->out_count=0;
        mdc800->out_ptr=0;
@@ -562,16 +586,20 @@
        mdc800->camera_request_ready=0;
 
        retval=0;
+       mdc800->irq_urb->dev = mdc800->dev;
        if (usb_submit_urb (mdc800->irq_urb))
        {
                err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, 
mdc800->irq_urb->status);
-               return -EIO;
+               errn = -EIO;
+               goto error_out;
        }
 
        mdc800->open=1;
-
        dbg ("Mustek MDC800 device opened.");
-       return 0;
+
+error_out:
+       spin_unlock (&mdc800->io_lock);
+       return errn;
 }
 
 
@@ -583,7 +611,7 @@
        int retval=0;
        dbg ("Mustek MDC800 device closed.");
 
-       lock_kernel();
+       spin_lock (&mdc800->io_lock);
        if (mdc800->open && (mdc800->state != NOT_CONNECTED))
        {
                mdc800->open=0;
@@ -595,7 +623,7 @@
        {
                retval=-EIO;
        }
-       unlock_kernel();
+       spin_unlock (&mdc800->io_lock);
 
        return retval;
 }
@@ -609,23 +637,29 @@
        int   left=len, sts=len; /* single transfer size */
        char* ptr=buf;
 
+       spin_lock (&mdc800->io_lock);
        if (mdc800->state == NOT_CONNECTED)
+       {
+               spin_unlock (&mdc800->io_lock);
                return -EBUSY;
-
+       }
        if (mdc800->state == WORKING)
        {
                warn ("Illegal State \"working\" reached during read ?!");
+               spin_unlock (&mdc800->io_lock);
                return -EBUSY;
        }
-
-       if (!mdc800->open || mdc800->rw_lock)
+       if (!mdc800->open)
+       {
+               spin_unlock (&mdc800->io_lock);
                return -EBUSY;
-       mdc800->rw_lock=1;
+       }
 
        while (left)
        {
-               if (signal_pending (current)) {
-                       mdc800->rw_lock=0;
+               if (signal_pending (current)) 
+               {
+                       spin_unlock (&mdc800->io_lock);
                        return -EINTR;
                }
 
@@ -640,24 +674,25 @@
                                mdc800->out_ptr=0;
 
                                /* Download -> Request new bytes */
+                               mdc800->download_urb->dev = mdc800->dev;
                                if (usb_submit_urb (mdc800->download_urb))
                                {
                                        err ("Can't submit download urb 
(status=%i)",mdc800->download_urb->status);
-                                       mdc800->rw_lock=0;
+                                       spin_unlock (&mdc800->io_lock);
                                        return len-left;
                                }
                                interruptible_sleep_on_timeout 
(&mdc800->download_wait, TO_DOWNLOAD_GET_READY*HZ/1000);
                                if (mdc800->download_urb->status != 0)
                                {
                                        err ("request download-bytes fails 
(status=%i)",mdc800->download_urb->status);
-                                       mdc800->rw_lock=0;
+                                       spin_unlock (&mdc800->io_lock);
                                        return len-left;
                                }
                        }
                        else
                        {
                                /* No more bytes -> that's an error*/
-                               mdc800->rw_lock=0;
+                               spin_unlock (&mdc800->io_lock);
                                return -EIO;
                        }
                }
@@ -671,7 +706,7 @@
                }
        }
 
-       mdc800->rw_lock=0;
+       spin_unlock (&mdc800->io_lock);
        return len-left;
 }
 
@@ -686,17 +721,23 @@
 {
        int i=0;
 
+       spin_lock (&mdc800->io_lock);
        if (mdc800->state != READY)
+       {
+               spin_unlock (&mdc800->io_lock);
                return -EBUSY;
-
-       if (!mdc800->open || mdc800->rw_lock)
+       }
+       if (!mdc800->open )
+       {
+               spin_unlock (&mdc800->io_lock);
                return -EBUSY;
-       mdc800->rw_lock=1;
+       }
 
        while (i<len)
        {
-               if (signal_pending (current)) {
-                       mdc800->rw_lock=0;
+               if (signal_pending (current)) 
+               {
+                       spin_unlock (&mdc800->io_lock);
                        return -EINTR;
                }
 
@@ -718,7 +759,7 @@
                else
                {
                        err ("Command is to long !\n");
-                       mdc800->rw_lock=0;
+                       spin_unlock (&mdc800->io_lock);
                        return -EIO;
                }
 
@@ -730,7 +771,7 @@
                        if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
                        {
                                err ("Camera didn't get ready.\n");
-                               mdc800->rw_lock=0;
+                               spin_unlock (&mdc800->io_lock);
                                return -EIO;
                        }
 
@@ -738,17 +779,18 @@
 
                        mdc800->state=WORKING;
                        memcpy (mdc800->write_urb->transfer_buffer, mdc800->in,8);
+                       mdc800->write_urb->dev = mdc800->dev;
                        if (usb_submit_urb (mdc800->write_urb))
                        {
                                err ("submitting write urb fails (status=%i)", 
mdc800->write_urb->status);
-                               mdc800->rw_lock=0;
+                               spin_unlock (&mdc800->io_lock);
                                return -EIO;
                        }
                        interruptible_sleep_on_timeout (&mdc800->write_wait, 
TO_WRITE_GET_READY*HZ/1000);
                        if (mdc800->state == WORKING)
                        {
                                usb_unlink_urb (mdc800->write_urb);
-                               mdc800->rw_lock=0;
+                               spin_unlock (&mdc800->io_lock);
                                return -EIO;
                        }
 
@@ -760,7 +802,7 @@
                                        {
                                                err ("call 0x07 before 0x05,0x3e");
                                                mdc800->state=READY;
-                                               mdc800->rw_lock=0;
+                                               spin_unlock (&mdc800->io_lock);
                                                return -EIO;
                                        }
                                        mdc800->pic_len=-1;
@@ -779,7 +821,7 @@
                                                if (mdc800_usb_waitForIRQ 
(1,TO_READ_FROM_IRQ))
                                                {
                                                        err ("requesting answer from 
irq fails");
-                                                       mdc800->rw_lock=0;
+                                                       spin_unlock (&mdc800->io_lock);
                                                        return -EIO;
                                                }
 
@@ -807,7 +849,7 @@
                                                if (mdc800_usb_waitForIRQ 
(0,TO_DEFAULT_COMMAND))
                                                {
                                                        err ("Command Timeout.");
-                                                       mdc800->rw_lock=0;
+                                                       spin_unlock (&mdc800->io_lock);
                                                        return -EIO;
                                                }
                                        }
@@ -817,7 +859,7 @@
                }
                i++;
        }
-       mdc800->rw_lock=0;
+       spin_unlock (&mdc800->io_lock);
        return i;
 }
 
@@ -842,12 +884,11 @@
  */
 static struct usb_driver mdc800_usb_driver =
 {
-       "mdc800",
-       mdc800_usb_probe,
-       mdc800_usb_disconnect,
-       { 0,0 },
-       &mdc800_device_ops,
-       MDC800_DEVICE_MINOR_BASE
+       name:           "mdc800",
+       probe:          mdc800_usb_probe,
+       disconnect:     mdc800_usb_disconnect,
+       fops:           &mdc800_device_ops,
+       minor:          MDC800_DEVICE_MINOR_BASE,
 };
 
 
@@ -865,10 +906,11 @@
        /* Allocate Memory */
        try (mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL));
 
+       memset(mdc800, 0, sizeof(struct mdc800_data));
        mdc800->dev=0;
        mdc800->open=0;
        mdc800->state=NOT_CONNECTED;
-       memset(mdc800, 0, sizeof(struct mdc800_data));
+       spin_lock_init (&mdc800->io_lock);
 
        init_waitqueue_head (&mdc800->irq_wait);
        init_waitqueue_head (&mdc800->write_wait);
@@ -886,8 +928,8 @@
        if (usb_register (&mdc800_usb_driver) < 0)
                goto cleanup_on_fail;
 
-       info ("Mustek Digital Camera Driver " VERSION " (MDC800)");
-       info (RELEASE_DATE " Henning Zabel <[EMAIL PROTECTED]>");
+       info (DRIVER_VERSION " " DRIVER_AUTHOR);
+       info (DRIVER_DESC);
 
        return 0;
 
@@ -930,9 +972,9 @@
        mdc800=0;
 }
 
-
-MODULE_AUTHOR ("Henning Zabel <[EMAIL PROTECTED]>");
-MODULE_DESCRIPTION ("USB Driver for Mustek MDC800 Digital Camera");
-
 module_init (usb_mdc800_init);
 module_exit (usb_mdc800_cleanup);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+

Reply via email to