diff -Naur linux-2.4.0-test1-ac19-orig/Documentation/usb/ov511.txt linux-2.4.0-test1-ac19/Documentation/usb/ov511.txt
--- linux-2.4.0-test1-ac19-orig/Documentation/usb/ov511.txt	Fri Jun 16 01:44:58 2000
+++ linux-2.4.0-test1-ac19/Documentation/usb/ov511.txt	Fri Jun 16 17:21:59 2000
@@ -6,22 +6,16 @@
 Homepage: http://alpha.dyndns.org/ov511
 
 NEW IN THIS VERSION:
- o Greyscale mode and timestamps restored
- o Image quality improvements
- o Experimental GBR422 mode
+ o Race conditions and other bugs fixed
 
 INTRODUCTION:
 
-This is a preliminary version of my OV511 Linux device driver. Currently, it can
-grab a frame in color (YUV420) at 640x480 or 320x240 using either vidcat or
-xawtv. Other utilities may work but have not yet been tested.
-
-Any camera using the OV511/OV511+ and the OV7610/20/20AE CCD should work. The
-driver only detects known cameras though, based on their custom id number. If
-you have a currently unsupported camera, the ID number should be reported to you
-in the kernel logs. Please send me the model, manufacturer and ID number and I 
-will add it to the detection code. In the meantime, you can add to the code
-yourself in the function ov511_probe().
+This is a driver for the OV511, a USB-only chip used in many "webcam" devices.
+Any camera using the OV511/OV511+ and the OV7610/20/20AE CCD should work.It 
+supports streaming and capture of color or monochrome video via theVideo4Linux
+API. Most V4L apps are compatible with it, but a few videoconferenceing programs
+do not work yet. The following resolutions are supported: 640x480, 448x336,
+384x288, 352x288, and 320x240.
 
 WHAT YOU NEED:
 
@@ -94,7 +88,8 @@
    bit flaky right now. This message means that the I2C bus never got
    initialized properly, and the camera will most likely not work even if you
    disable this warning. Try unloading/reloading the driver or unplugging/re-
-   plugging the camera if this happens.
+   plugging the camera if this happens. Also try increasing the i2c_detect_tries
+   parameter (see below).
 
 Q: "Why do you bother with this phony camera detection crap? It doesn't do
     anything useful!"
@@ -201,9 +196,6 @@
    would like them to release their specifications to the Linux community.
  o Get 160x120 working
  o YUV422 (and other color modes)
- o Fix read(). It only works right now if you run an mmap() based app like xawtv
-   or vidcat after loading the module and before using read(). Apparently there
-   are some initialization issues.
  o Get snapshot mode working with mmap().
  o Fix fixFrameRGBoffset(). It is not stable yet with streaming video.
  o Get hue (red/blue channel balance) adjustment working (in ov511_get_picture()
diff -Naur linux-2.4.0-test1-ac19-orig/drivers/usb/ov511.c linux-2.4.0-test1-ac19/drivers/usb/ov511.c
--- linux-2.4.0-test1-ac19-orig/drivers/usb/ov511.c	Fri Jun 16 01:45:34 2000
+++ linux-2.4.0-test1-ac19/drivers/usb/ov511.c	Fri Jun 16 17:21:49 2000
@@ -30,7 +30,7 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-static const char version[] = "1.16";
+static const char version[] = "1.17";
 
 #define __NO_VERSION__
 
@@ -1683,25 +1683,23 @@
 
 static int ov511_open(struct video_device *dev, int flags)
 {
-	int err = -EBUSY;
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
-	int i;
+	int i, err = 0;
 
+	MOD_INC_USE_COUNT;
 	PDEBUG(4, "opening");
-
 	down(&ov511->lock);
 
-	if (ov511->user) {
-		up(&ov511->lock);
-		return -EBUSY;
-	}
+	err = -EBUSY;
+	if (ov511->user) 
+		goto out;
 
 	err = -ENOMEM;
 
 	/* Allocate memory for the frame buffers */
 	ov511->fbuf = rvmalloc(OV511_NUMFRAMES * MAX_DATA_SIZE);
 	if (!ov511->fbuf)
-		return err;
+		goto out;
 
 	ov511->sub_flag = 0;
 
@@ -1716,7 +1714,7 @@
 open_free_ret:
 			while (--i) kfree(ov511->sbuf[i].data);
 			rvfree(ov511->fbuf, 2 * MAX_DATA_SIZE);
-			return err;
+			goto out;
 		}	
 		PDEBUG(4, "sbuf[%d] @ %p", i, ov511->sbuf[i].data);
 	}
@@ -1726,11 +1724,14 @@
 		goto open_free_ret;
 
 	ov511->user++;
+
+out:
 	up(&ov511->lock);
 
-	MOD_INC_USE_COUNT;
+	if (err)
+		MOD_DEC_USE_COUNT;
 
-	return 0;
+	return err;
 }
 
 static void ov511_close(struct video_device *dev)
@@ -1743,8 +1744,6 @@
 	down(&ov511->lock);	
 	ov511->user--;
 
-	MOD_DEC_USE_COUNT;
-
 	ov511_stop_isoc(ov511);
 
 	rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE);
@@ -1757,6 +1756,9 @@
 		video_unregister_device(&ov511->vdev);
 		kfree(ov511);
 	}
+
+	MOD_DEC_USE_COUNT;
+
 }
 
 static int ov511_init_done(struct video_device *dev)
@@ -1988,6 +1990,7 @@
 	case VIDIOCMCAPTURE:
 	{
 		struct video_mmap vm;
+		int ret;
 
 		if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))
 			return -EFAULT;
@@ -2016,8 +2019,12 @@
 			   before changing modes */
 			interruptible_sleep_on(&ov511->wq);
 			if (signal_pending(current)) return -EINTR;
-			ov511_mode_init_regs(ov511, vm.width, vm.height,
+			ret = ov511_mode_init_regs(ov511, vm.width, vm.height,
 				vm.format, ov511->sub_flag);
+#if 0
+			if (ret < 0)
+				return ret;
+#endif
 		}
 
 		ov511->frame[vm.frame].width = vm.width;
@@ -2540,9 +2547,6 @@
 	usb_driver_release_interface(&ov511_driver,
 		&dev->actconfig->interface[ov511->iface]);
 
-	kfree(ov511);
-	ov511 = NULL;
-
 	return -EBUSY;	
 }
 
@@ -2580,9 +2584,12 @@
 	if (interface->bInterfaceSubClass != 0x00)
 		return NULL;
 
+	/* Since code below may sleep, we use this as a lock */
+	MOD_INC_USE_COUNT;
+
 	if ((ov511 = kmalloc(sizeof(*ov511), GFP_KERNEL)) == NULL) {
 		err("couldn't kmalloc ov511 struct");
-		return NULL;
+		goto error;
 	}
 
 	memset(ov511, 0, sizeof(*ov511));
@@ -2620,7 +2627,7 @@
 	/* Lifeview USB Life TV not supported */
 	if (clist[i].id == 38) {
 		err("This device is not supported yet.");
-		return NULL;
+		goto error;
 	}
 
 	if (clist[i].id == -1) {
@@ -2637,12 +2644,12 @@
 	if (!ov511_configure(ov511)) {
 		ov511->user = 0;
 		init_MUTEX(&ov511->lock);	/* to 1 == available */
-		return ov511;
 	} else {
 		err("Failed to configure camera");
 		goto error;
 	}
 
+	MOD_DEC_USE_COUNT;
      	return ov511;
 
 error:
@@ -2651,6 +2658,7 @@
 		ov511 = NULL;
 	}
 
+	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
@@ -2659,7 +2667,7 @@
 {
 	struct usb_ov511 *ov511 = (struct usb_ov511 *) ptr;
 
-//	video_unregister_device(&ov511->vdev);
+	MOD_INC_USE_COUNT;
 
 	/* We don't want people trying to open up the device */
 	if (!ov511->user)
@@ -2702,10 +2710,12 @@
 #endif
 
 	/* Free the memory */
-	if (!ov511->user) {
+	if (ov511 && !ov511->user) {
 		kfree(ov511);
 		ov511 = NULL;
 	}
+
+	MOD_DEC_USE_COUNT;
 }
 
 static struct usb_driver ov511_driver = {
