Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] V4L2: soc-camera: fix requesting regulators in synchronous case

With synchronous subdevice probing regulators should be requested by the
soc-camera core in soc_camera_pdrv_probe(). Subdevice drivers, supporting
asynchronous probing, call soc_camera_power_init() to request regulators.
Erroneously, the same regulator array is used in the latter case as in
the former, which leads to a failure. This patch fixes it by preventing
the second regulator request from being executed.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>

authored by

Guennadi Liakhovetski and committed by
Mauro Carvalho Chehab
23272427 85e86c6e

+27 -6
+27 -6
drivers/media/platform/soc_camera/soc_camera.c
··· 136 136 137 137 int soc_camera_power_init(struct device *dev, struct soc_camera_subdev_desc *ssdd) 138 138 { 139 - 139 + /* Should not have any effect in synchronous case */ 140 140 return devm_regulator_bulk_get(dev, ssdd->num_regulators, 141 141 ssdd->regulators); 142 142 } ··· 1311 1311 static int soc_camera_i2c_init(struct soc_camera_device *icd, 1312 1312 struct soc_camera_desc *sdesc) 1313 1313 { 1314 + struct soc_camera_subdev_desc *ssdd; 1314 1315 struct i2c_client *client; 1315 1316 struct soc_camera_host *ici; 1316 1317 struct soc_camera_host_desc *shd = &sdesc->host_desc; ··· 1334 1333 return -ENODEV; 1335 1334 } 1336 1335 1337 - shd->board_info->platform_data = &sdesc->subdev_desc; 1336 + ssdd = kzalloc(sizeof(*ssdd), GFP_KERNEL); 1337 + if (!ssdd) { 1338 + ret = -ENOMEM; 1339 + goto ealloc; 1340 + } 1341 + 1342 + memcpy(ssdd, &sdesc->subdev_desc, sizeof(*ssdd)); 1343 + /* 1344 + * In synchronous case we request regulators ourselves in 1345 + * soc_camera_pdrv_probe(), make sure the subdevice driver doesn't try 1346 + * to allocate them again. 1347 + */ 1348 + ssdd->num_regulators = 0; 1349 + ssdd->regulators = NULL; 1350 + shd->board_info->platform_data = ssdd; 1338 1351 1339 1352 snprintf(clk_name, sizeof(clk_name), "%d-%04x", 1340 1353 shd->i2c_adapter_id, shd->board_info->addr); ··· 1374 1359 return 0; 1375 1360 ei2cnd: 1376 1361 v4l2_clk_unregister(icd->clk); 1377 - eclkreg: 1378 1362 icd->clk = NULL; 1363 + eclkreg: 1364 + kfree(ssdd); 1365 + ealloc: 1379 1366 i2c_put_adapter(adap); 1380 1367 return ret; 1381 1368 } ··· 1387 1370 struct i2c_client *client = 1388 1371 to_i2c_client(to_soc_camera_control(icd)); 1389 1372 struct i2c_adapter *adap; 1373 + struct soc_camera_subdev_desc *ssdd; 1390 1374 1391 1375 icd->control = NULL; 1392 1376 if (icd->sasc) 1393 1377 return; 1394 1378 1395 1379 adap = client->adapter; 1380 + ssdd = client->dev.platform_data; 1396 1381 v4l2_device_unregister_subdev(i2c_get_clientdata(client)); 1397 1382 i2c_unregister_device(client); 1398 1383 i2c_put_adapter(adap); 1384 + kfree(ssdd); 1399 1385 v4l2_clk_unregister(icd->clk); 1400 1386 icd->clk = NULL; 1401 1387 } ··· 2015 1995 2016 1996 /* 2017 1997 * In the asynchronous case ssdd->num_regulators == 0 yet, so, the below 2018 - * regulator allocation is a dummy. They will be really requested later 2019 - * in soc_camera_async_bind(). Also note, that in that case regulators 2020 - * are attached to the I2C device and not to the camera platform device. 1998 + * regulator allocation is a dummy. They are actually requested by the 1999 + * subdevice driver, using soc_camera_power_init(). Also note, that in 2000 + * that case regulators are attached to the I2C device and not to the 2001 + * camera platform device. 2021 2002 */ 2022 2003 ret = devm_regulator_bulk_get(&pdev->dev, ssdd->num_regulators, 2023 2004 ssdd->regulators);