Commit cb57118e authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] fix module reference counting in zoran driver

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..
parent e32c0212
......@@ -108,13 +108,17 @@ videocodec_attach (struct videocodec_master *master)
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_master *master)
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_master *master)
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 *codec)
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 videocodec *codec)
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 videocodec *codec)
"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;
......
......@@ -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 */
......
......@@ -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 =
......
......@@ -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 =
......
......@@ -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 =
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment