diff options
Diffstat (limited to 'drivers/media/video/soc_camera.c')
-rw-r--r-- | drivers/media/video/soc_camera.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 59aa7a3694c2..95fdeb23c2c1 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) | |||
1097 | return v4l2_subdev_call(sd, video, s_crop, a); | 1097 | return v4l2_subdev_call(sd, video, s_crop, a); |
1098 | } | 1098 | } |
1099 | 1099 | ||
1100 | static void soc_camera_device_init(struct device *dev, void *pdata) | ||
1101 | { | ||
1102 | dev->platform_data = pdata; | ||
1103 | dev->bus = &soc_camera_bus_type; | ||
1104 | dev->release = dummy_release; | ||
1105 | } | ||
1106 | |||
1100 | int soc_camera_host_register(struct soc_camera_host *ici) | 1107 | int soc_camera_host_register(struct soc_camera_host *ici) |
1101 | { | 1108 | { |
1102 | struct soc_camera_host *ix; | 1109 | struct soc_camera_host *ix; |
@@ -1158,15 +1165,19 @@ void soc_camera_host_unregister(struct soc_camera_host *ici) | |||
1158 | 1165 | ||
1159 | list_for_each_entry(icd, &devices, list) { | 1166 | list_for_each_entry(icd, &devices, list) { |
1160 | if (icd->iface == ici->nr) { | 1167 | if (icd->iface == ici->nr) { |
1168 | void *pdata = icd->dev.platform_data; | ||
1161 | /* The bus->remove will be called */ | 1169 | /* The bus->remove will be called */ |
1162 | device_unregister(&icd->dev); | 1170 | device_unregister(&icd->dev); |
1163 | /* Not before device_unregister(), .remove | 1171 | /* |
1164 | * needs parent to call ici->ops->remove() */ | 1172 | * Not before device_unregister(), .remove |
1165 | icd->dev.parent = NULL; | 1173 | * needs parent to call ici->ops->remove(). |
1166 | 1174 | * If the host module is loaded again, device_register() | |
1167 | /* If the host module is loaded again, device_register() | 1175 | * would complain "already initialised," since 2.6.32 |
1168 | * would complain "already initialised" */ | 1176 | * this is also needed to prevent use-after-free of the |
1169 | memset(&icd->dev.kobj, 0, sizeof(icd->dev.kobj)); | 1177 | * device private data. |
1178 | */ | ||
1179 | memset(&icd->dev, 0, sizeof(icd->dev)); | ||
1180 | soc_camera_device_init(&icd->dev, pdata); | ||
1170 | } | 1181 | } |
1171 | } | 1182 | } |
1172 | 1183 | ||
@@ -1198,10 +1209,7 @@ static int soc_camera_device_register(struct soc_camera_device *icd) | |||
1198 | * man, stay reasonable... */ | 1209 | * man, stay reasonable... */ |
1199 | return -ENOMEM; | 1210 | return -ENOMEM; |
1200 | 1211 | ||
1201 | icd->devnum = num; | 1212 | icd->devnum = num; |
1202 | icd->dev.bus = &soc_camera_bus_type; | ||
1203 | |||
1204 | icd->dev.release = dummy_release; | ||
1205 | icd->use_count = 0; | 1213 | icd->use_count = 0; |
1206 | icd->host_priv = NULL; | 1214 | icd->host_priv = NULL; |
1207 | mutex_init(&icd->video_lock); | 1215 | mutex_init(&icd->video_lock); |
@@ -1309,12 +1317,13 @@ static int __devinit soc_camera_pdrv_probe(struct platform_device *pdev) | |||
1309 | icd->iface = icl->bus_id; | 1317 | icd->iface = icl->bus_id; |
1310 | icd->pdev = &pdev->dev; | 1318 | icd->pdev = &pdev->dev; |
1311 | platform_set_drvdata(pdev, icd); | 1319 | platform_set_drvdata(pdev, icd); |
1312 | icd->dev.platform_data = icl; | ||
1313 | 1320 | ||
1314 | ret = soc_camera_device_register(icd); | 1321 | ret = soc_camera_device_register(icd); |
1315 | if (ret < 0) | 1322 | if (ret < 0) |
1316 | goto escdevreg; | 1323 | goto escdevreg; |
1317 | 1324 | ||
1325 | soc_camera_device_init(&icd->dev, icl); | ||
1326 | |||
1318 | icd->user_width = DEFAULT_WIDTH; | 1327 | icd->user_width = DEFAULT_WIDTH; |
1319 | icd->user_height = DEFAULT_HEIGHT; | 1328 | icd->user_height = DEFAULT_HEIGHT; |
1320 | 1329 | ||