From: Christoph Hellwig 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 = _