From: Christoph Hellwig <hch@lst.de>

Take a reference before calling into the module and release it after we're
done.  Also remove the useless (and wrong) refcounting in videocodec -
symbols from this module are used by other modules if we call into those
functions so it can't be unloaded anyway.

We really need to add a debug check to tip all those
try_module_get(THIS_MODULE) callers..



---

 25-akpm/drivers/media/video/videocodec.c |   55 +++++++------------------------
 25-akpm/drivers/media/video/videocodec.h |    1 
 25-akpm/drivers/media/video/zr36016.c    |   20 -----------
 25-akpm/drivers/media/video/zr36050.c    |   20 -----------
 25-akpm/drivers/media/video/zr36060.c    |   20 -----------
 5 files changed, 17 insertions(+), 99 deletions(-)

diff -puN drivers/media/video/videocodec.c~zoran-refcounting-fixes drivers/media/video/videocodec.c
--- 25/drivers/media/video/videocodec.c~zoran-refcounting-fixes	Thu Feb 19 15:20:03 2004
+++ 25-akpm/drivers/media/video/videocodec.c	Thu Feb 19 15:20:03 2004
@@ -108,13 +108,17 @@ videocodec_attach (struct videocodec_mas
 		if ((master->flags & h->codec->flags) == master->flags) {
 			dprintk(4, "videocodec_attach: try '%s'\n",
 				h->codec->name);
+
+			if (!try_module_get(h->codec->owner))
+				return NULL;
+
 			codec =
 			    kmalloc(sizeof(struct videocodec), GFP_KERNEL);
 			if (!codec) {
 				dprintk(1,
 					KERN_ERR
 					"videocodec_attach: no mem\n");
-				return NULL;
+				goto out_module_put;
 			}
 			memcpy(codec, h->codec, sizeof(struct videocodec));
 
@@ -132,26 +136,12 @@ videocodec_attach (struct videocodec_mas
 					dprintk(1,
 						KERN_ERR
 						"videocodec_attach: no memory\n");
-					kfree(codec);
-					return NULL;
+					goto out_kfree;
 				}
 				memset(ptr, 0,
 				       sizeof(struct attached_list));
 				ptr->codec = codec;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-				MOD_INC_USE_COUNT;
-#else
-				if (!try_module_get(THIS_MODULE)) {
-					dprintk(1,
-						KERN_ERR
-						"videocodec: failed to increment usecount\n");
-					kfree(codec);
-					kfree(ptr);
-					return NULL;
-				}
-#endif
-
 				a = h->list;
 				if (!a) {
 					h->list = ptr;
@@ -177,6 +167,12 @@ videocodec_attach (struct videocodec_mas
 
 	dprintk(1, KERN_ERR "videocodec_attach: no codec found!\n");
 	return NULL;
+
+ out_module_put:
+	module_put(h->codec->owner);
+ out_kfree:
+	kfree(codec);
+	return NULL;
 }
 
 int
@@ -228,16 +224,10 @@ videocodec_detach (struct videocodec *co
 					dprintk(4,
 						"videocodec: delete middle\n");
 				}
+				module_put(a->codec->owner);
 				kfree(a->codec);
 				kfree(a);
 				h->attached -= 1;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-				MOD_DEC_USE_COUNT;
-#else
-				module_put(THIS_MODULE);
-#endif
-
 				return 0;
 			}
 			prev = a;
@@ -274,18 +264,6 @@ videocodec_register (const struct videoc
 	memset(ptr, 0, sizeof(struct codec_list));
 	ptr->codec = codec;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	MOD_INC_USE_COUNT;
-#else
-	if (!try_module_get(THIS_MODULE)) {
-		dprintk(1,
-			KERN_ERR
-			"videocodec: failed to increment module count\n");
-		kfree(ptr);
-		return -ENODEV;
-	}
-#endif
-
 	if (!h) {
 		codeclist_top = ptr;
 		dprintk(4, "videocodec: hooked in as first element\n");
@@ -342,13 +320,6 @@ videocodec_unregister (const struct vide
 					"videocodec: delete middle element\n");
 			}
 			kfree(h);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-			MOD_DEC_USE_COUNT;
-#else
-			module_put(THIS_MODULE);
-#endif
-
 			return 0;
 		}
 		prev = h;
diff -puN drivers/media/video/videocodec.h~zoran-refcounting-fixes drivers/media/video/videocodec.h
--- 25/drivers/media/video/videocodec.h~zoran-refcounting-fixes	Thu Feb 19 15:20:03 2004
+++ 25-akpm/drivers/media/video/videocodec.h	Thu Feb 19 15:20:03 2004
@@ -249,6 +249,7 @@ struct tvnorm {
 };
 
 struct videocodec {
+	struct module *owner;
 	/* -- filled in by slave device during register -- */
 	char name[32];
 	unsigned long magic;	/* may be used for client<->master attaching */
diff -puN drivers/media/video/zr36016.c~zoran-refcounting-fixes drivers/media/video/zr36016.c
--- 25/drivers/media/video/zr36016.c~zoran-refcounting-fixes	Thu Feb 19 15:20:03 2004
+++ 25-akpm/drivers/media/video/zr36016.c	Thu Feb 19 15:20:03 2004
@@ -422,12 +422,6 @@ zr36016_unset (struct videocodec *codec)
 		codec->data = NULL;
 
 		zr36016_codecs--;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		MOD_DEC_USE_COUNT;
-#else
-		module_put(THIS_MODULE);
-#endif
-
 		return 0;
 	}
 
@@ -470,19 +464,6 @@ zr36016_setup (struct videocodec *codec)
 	ptr->num = zr36016_codecs++;
 	ptr->codec = codec;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	MOD_INC_USE_COUNT;
-#else
-	if (!try_module_get(THIS_MODULE)) {
-		dprintk(1,
-			KERN_ERR
-			"zr36016: failed to increase module use count\n");
-		kfree(ptr);
-		zr36016_codecs--;
-		return -ENODEV;
-	}
-#endif
-
 	//testing
 	res = zr36016_basic_test(ptr);
 	if (res < 0) {
@@ -504,6 +485,7 @@ zr36016_setup (struct videocodec *codec)
 }
 
 static const struct videocodec zr36016_codec = {
+	.owner = THIS_MODULE,
 	.name = "zr36016",
 	.magic = 0L,		// magic not used
 	.flags =
diff -puN drivers/media/video/zr36050.c~zoran-refcounting-fixes drivers/media/video/zr36050.c
--- 25/drivers/media/video/zr36050.c~zoran-refcounting-fixes	Thu Feb 19 15:20:03 2004
+++ 25-akpm/drivers/media/video/zr36050.c	Thu Feb 19 15:20:03 2004
@@ -737,12 +737,6 @@ zr36050_unset (struct videocodec *codec)
 		codec->data = NULL;
 
 		zr36050_codecs--;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		MOD_DEC_USE_COUNT;
-#else
-		module_put(THIS_MODULE);
-#endif
-
 		return 0;
 	}
 
@@ -785,19 +779,6 @@ zr36050_setup (struct videocodec *codec)
 	ptr->num = zr36050_codecs++;
 	ptr->codec = codec;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	MOD_INC_USE_COUNT;
-#else
-	if (!try_module_get(THIS_MODULE)) {
-		dprintk(1,
-			KERN_ERR
-			"zr36050: failed to increase module use count\n");
-		kfree(ptr);
-		zr36050_codecs--;
-		return -ENODEV;
-	}
-#endif
-
 	//testing
 	res = zr36050_basic_test(ptr);
 	if (res < 0) {
@@ -826,6 +807,7 @@ zr36050_setup (struct videocodec *codec)
 }
 
 static const struct videocodec zr36050_codec = {
+	.owner = THIS_MODULE,
 	.name = "zr36050",
 	.magic = 0L,		// magic not used
 	.flags =
diff -puN drivers/media/video/zr36060.c~zoran-refcounting-fixes drivers/media/video/zr36060.c
--- 25/drivers/media/video/zr36060.c~zoran-refcounting-fixes	Thu Feb 19 15:20:03 2004
+++ 25-akpm/drivers/media/video/zr36060.c	Thu Feb 19 15:20:03 2004
@@ -868,12 +868,6 @@ zr36060_unset (struct videocodec *codec)
 		codec->data = NULL;
 
 		zr36060_codecs--;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-		MOD_DEC_USE_COUNT;
-#else
-		module_put(THIS_MODULE);
-#endif
-
 		return 0;
 	}
 
@@ -916,19 +910,6 @@ zr36060_setup (struct videocodec *codec)
 	ptr->num = zr36060_codecs++;
 	ptr->codec = codec;
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-	MOD_INC_USE_COUNT;
-#else
-	if (!try_module_get(THIS_MODULE)) {
-		dprintk(1,
-			KERN_ERR
-			"zr36060: failed to increase module use count\n");
-		kfree(ptr);
-		zr36060_codecs--;
-		return -ENODEV;
-	}
-#endif
-
 	//testing
 	res = zr36060_basic_test(ptr);
 	if (res < 0) {
@@ -958,6 +939,7 @@ zr36060_setup (struct videocodec *codec)
 }
 
 static const struct videocodec zr36060_codec = {
+	.owner = THIS_MODULE,
 	.name = "zr36060",
 	.magic = 0L,		// magic not used
 	.flags =

_