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