summaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-11-09 16:12:37 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-11-26 19:38:02 -0200
commit64ff9ba5f1d771e8405ec766c31f6b32c9708285 (patch)
treecda19375ecf8e742b7aae674fd3692c09d6155a5 /drivers/media/video
parentf39c1ab3c3878f1a50ca129e55d17ae63215fcbe (diff)
V4L/DVB (13344): soc-camera: properly initialise the device object when reusing
Commit ef373189f62413803b7b816c972fc154c488cdc0 "fix use-after-free Oops, resulting from a driver-core API change" fixed the Oops, but didn't correct missing device object initialisation. This patch makes unloading and reloading of soc-camera host- and client-drivers possible again. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/soc_camera.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 36e617bd13c..95fdeb23c2c 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -1097,6 +1097,13 @@ static int default_s_crop(struct soc_camera_device *icd, struct v4l2_crop *a)
return v4l2_subdev_call(sd, video, s_crop, a);
}
+static void soc_camera_device_init(struct device *dev, void *pdata)
+{
+ dev->platform_data = pdata;
+ dev->bus = &soc_camera_bus_type;
+ dev->release = dummy_release;
+}
+
int soc_camera_host_register(struct soc_camera_host *ici)
{
struct soc_camera_host *ix;
@@ -1158,6 +1165,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
list_for_each_entry(icd, &devices, list) {
if (icd->iface == ici->nr) {
+ void *pdata = icd->dev.platform_data;
/* The bus->remove will be called */
device_unregister(&icd->dev);
/*
@@ -1169,6 +1177,7 @@ void soc_camera_host_unregister(struct soc_camera_host *ici)
* device private data.
*/
memset(&icd->dev, 0, sizeof(icd->dev));
+ soc_camera_device_init(&icd->dev, pdata);
}
}
@@ -1200,10 +1209,7 @@ static int soc_camera_device_register(struct soc_camera_device *icd)
* man, stay reasonable... */
return -ENOMEM;
- icd->devnum = num;
- icd->dev.bus = &soc_camera_bus_type;
-
- icd->dev.release = dummy_release;
+ icd->devnum = num;
icd->use_count = 0;
icd->host_priv = NULL;
mutex_init(&icd->video_lock);
@@ -1311,12 +1317,13 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev)
icd->iface = icl->bus_id;
icd->pdev = &pdev->dev;
platform_set_drvdata(pdev, icd);
- icd->dev.platform_data = icl;
ret = soc_camera_device_register(icd);
if (ret < 0)
goto escdevreg;
+ soc_camera_device_init(&icd->dev, icl);
+
icd->user_width = DEFAULT_WIDTH;
icd->user_height = DEFAULT_HEIGHT;