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

[PATCH] zoran: add release callback

From: Ronald Bultje <rbultje@ronald.bitfreak.net>

This patch adds a release callback which frees the video_device struct.
This is needed to prevent freeing memory before it's not in use anymore,
as described in http://lwn.net/Articles/36850/. Without this, the driver
will give a warning when loaded. It might crash when unloading (see
article), too. The video4linux patch (by Gerd Knorr) was accepted a week
(or 2?) ago, but I forgot to adapt my driver to it.
parent ef392885
...@@ -383,7 +383,7 @@ struct card_info { ...@@ -383,7 +383,7 @@ struct card_info {
}; };
struct zoran { struct zoran {
struct video_device video_dev; struct video_device *video_dev;
struct i2c_adapter i2c_adapter; /* */ struct i2c_adapter i2c_adapter; /* */
struct i2c_algo_bit_data i2c_algo; /* */ struct i2c_algo_bit_data i2c_algo; /* */
......
...@@ -987,6 +987,7 @@ static int __devinit ...@@ -987,6 +987,7 @@ static int __devinit
zr36057_init (struct zoran *zr) zr36057_init (struct zoran *zr)
{ {
unsigned long mem; unsigned long mem;
void *vdev;
unsigned mem_needed; unsigned mem_needed;
int j; int j;
int two = 2; int two = 2;
...@@ -1041,11 +1042,16 @@ zr36057_init (struct zoran *zr) ...@@ -1041,11 +1042,16 @@ zr36057_init (struct zoran *zr)
* in case allocation fails */ * in case allocation fails */
mem_needed = BUZ_NUM_STAT_COM * 4; mem_needed = BUZ_NUM_STAT_COM * 4;
mem = (unsigned long) kmalloc(mem_needed, GFP_KERNEL); mem = (unsigned long) kmalloc(mem_needed, GFP_KERNEL);
if (!mem) { vdev = (void *) kmalloc(sizeof(struct video_device), GFP_KERNEL);
if (!mem || !vdev) {
dprintk(1, dprintk(1,
KERN_ERR KERN_ERR
"%s: zr36057_init() - kmalloc (STAT_COM) failed\n", "%s: zr36057_init() - kmalloc (STAT_COM) failed\n",
ZR_DEVNAME(zr)); ZR_DEVNAME(zr));
if (vdev)
kfree(vdev);
if (mem)
kfree((void *)mem);
return -ENOMEM; return -ENOMEM;
} }
memset((void *) mem, 0, mem_needed); memset((void *) mem, 0, mem_needed);
...@@ -1057,12 +1063,14 @@ zr36057_init (struct zoran *zr) ...@@ -1057,12 +1063,14 @@ zr36057_init (struct zoran *zr)
/* /*
* Now add the template and register the device unit. * Now add the template and register the device unit.
*/ */
memcpy(&zr->video_dev, &zoran_template, sizeof(zoran_template)); zr->video_dev = vdev;
strcpy(zr->video_dev.name, ZR_DEVNAME(zr)); memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template));
if (video_register_device strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
(&zr->video_dev, VFL_TYPE_GRABBER, video_nr) < 0) { if (video_register_device(zr->video_dev, VFL_TYPE_GRABBER,
video_nr) < 0) {
zoran_unregister_i2c(zr); zoran_unregister_i2c(zr);
kfree((void *) zr->stat_com); kfree((void *) zr->stat_com);
kfree(vdev);
return -1; return -1;
} }
...@@ -1110,7 +1118,13 @@ zoran_release (struct zoran *zr) ...@@ -1110,7 +1118,13 @@ zoran_release (struct zoran *zr)
kfree((void *) zr->stat_com); kfree((void *) zr->stat_com);
zoran_proc_cleanup(zr); zoran_proc_cleanup(zr);
iounmap(zr->zr36057_mem); iounmap(zr->zr36057_mem);
video_unregister_device(&zr->video_dev); video_unregister_device(zr->video_dev);
}
void
zoran_vdev_release (struct video_device *vdev)
{
kfree(vdev);
} }
static struct videocodec_master * __devinit static struct videocodec_master * __devinit
......
...@@ -40,5 +40,6 @@ extern struct video_device zoran_template; ...@@ -40,5 +40,6 @@ extern struct video_device zoran_template;
extern int zoran_check_jpg_settings(struct zoran *zr, extern int zoran_check_jpg_settings(struct zoran *zr,
struct zoran_jpg_settings *settings); struct zoran_jpg_settings *settings);
extern void zoran_open_init_params(struct zoran *zr); extern void zoran_open_init_params(struct zoran *zr);
extern void zoran_vdev_release(struct video_device *vdev);
#endif /* __ZORAN_CARD_H__ */ #endif /* __ZORAN_CARD_H__ */
...@@ -1268,7 +1268,7 @@ zoran_open (struct inode *inode, ...@@ -1268,7 +1268,7 @@ zoran_open (struct inode *inode,
/* find the device */ /* find the device */
for (i = 0; i < zoran_num; i++) { for (i = 0; i < zoran_num; i++) {
if (zoran[i].video_dev.minor == minor) { if (zoran[i].video_dev->minor == minor) {
zr = &zoran[i]; zr = &zoran[i];
break; break;
} }
...@@ -2358,7 +2358,7 @@ zoran_do_ioctl (struct inode *inode, ...@@ -2358,7 +2358,7 @@ zoran_do_ioctl (struct inode *inode,
struct video_unit *vunit = arg; struct video_unit *vunit = arg;
dprintk(3, KERN_DEBUG "%s: VIDIOCGUNIT\n", ZR_DEVNAME(zr)); dprintk(3, KERN_DEBUG "%s: VIDIOCGUNIT\n", ZR_DEVNAME(zr));
vunit->video = zr->video_dev.minor; vunit->video = zr->video_dev->minor;
vunit->vbi = VIDEO_NO_UNIT; vunit->vbi = VIDEO_NO_UNIT;
vunit->radio = VIDEO_NO_UNIT; vunit->radio = VIDEO_NO_UNIT;
vunit->audio = VIDEO_NO_UNIT; vunit->audio = VIDEO_NO_UNIT;
...@@ -4665,5 +4665,6 @@ struct video_device zoran_template __devinitdata = { ...@@ -4665,5 +4665,6 @@ struct video_device zoran_template __devinitdata = {
#endif #endif
.hardware = ZORAN_HARDWARE, .hardware = ZORAN_HARDWARE,
.fops = &zoran_fops, .fops = &zoran_fops,
.release = &zoran_vdev_release,
.minor = -1 .minor = -1
}; };
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