From 85f7ff9702bcc5e899bd0bf6b6e383ecb2ac436a Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Fri, 2 Jun 2017 05:30:02 -0400 Subject: media: v4l2-flash: Use led_classdev instead of led_classdev_flash for indicator The V4L2 flash class initialisation expects struct led_classdev_flash that describes an indicator but only uses struct led_classdev which is a field iled_cdev in the struct. Use struct iled_cdev only. Signed-off-by: Sakari Ailus Reviewed-by: Jacek Anaszewski Reviewed-by: Sebastian Reichel Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/greybus/light.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/greybus') diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 861a249e6ef1..129ceed39829 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -536,7 +536,7 @@ static int gb_lights_light_v4l2_register(struct gb_light *light) struct device *dev = &connection->bundle->dev; struct v4l2_flash_config *sd_cfg; struct led_classdev_flash *fled; - struct led_classdev_flash *iled = NULL; + struct led_classdev *iled = NULL; struct gb_channel *channel_torch, *channel_ind, *channel_flash; int ret = 0; @@ -553,7 +553,7 @@ static int gb_lights_light_v4l2_register(struct gb_light *light) if (channel_ind) { __gb_lights_channel_v4l2_config(&channel_ind->intensity_uA, &sd_cfg->indicator_intensity); - iled = &channel_ind->fled; + iled = &channel_ind->fled.led_cdev; } channel_flash = get_channel_from_mode(light, GB_CHANNEL_MODE_FLASH); -- cgit From 428359cbfe086f43cb84b7ab7b48e7e7862700e2 Mon Sep 17 00:00:00 2001 From: Rui Miguel Silva Date: Wed, 2 Aug 2017 12:52:57 -0400 Subject: media: staging: greybus: light: fix memory leak in v4l2 register We are allocating memory for the v4l2 flash configuration structure and leak it in the normal path. Just use the stack for this as we do not use it outside of this function. Also use IS_ERR() instead of IS_ERR_OR_NULL() to check return value from v4l2_flash_init() for it never returns NULL. Fixes: 2870b52bae4c ("greybus: lights: add lights implementation") Reported-by: Sakari Ailus Signed-off-by: Rui Miguel Silva Reviewed-by: Viresh Kumar Signed-off-by: Sakari Ailus Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/greybus/light.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'drivers/staging/greybus') diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 129ceed39829..81469d087e74 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -534,25 +534,20 @@ static int gb_lights_light_v4l2_register(struct gb_light *light) { struct gb_connection *connection = get_conn_from_light(light); struct device *dev = &connection->bundle->dev; - struct v4l2_flash_config *sd_cfg; + struct v4l2_flash_config sd_cfg = { {0} }; struct led_classdev_flash *fled; struct led_classdev *iled = NULL; struct gb_channel *channel_torch, *channel_ind, *channel_flash; - int ret = 0; - - sd_cfg = kcalloc(1, sizeof(*sd_cfg), GFP_KERNEL); - if (!sd_cfg) - return -ENOMEM; channel_torch = get_channel_from_mode(light, GB_CHANNEL_MODE_TORCH); if (channel_torch) __gb_lights_channel_v4l2_config(&channel_torch->intensity_uA, - &sd_cfg->torch_intensity); + &sd_cfg.torch_intensity); channel_ind = get_channel_from_mode(light, GB_CHANNEL_MODE_INDICATOR); if (channel_ind) { __gb_lights_channel_v4l2_config(&channel_ind->intensity_uA, - &sd_cfg->indicator_intensity); + &sd_cfg.indicator_intensity); iled = &channel_ind->fled.led_cdev; } @@ -561,27 +556,21 @@ static int gb_lights_light_v4l2_register(struct gb_light *light) fled = &channel_flash->fled; - snprintf(sd_cfg->dev_name, sizeof(sd_cfg->dev_name), "%s", light->name); + snprintf(sd_cfg.dev_name, sizeof(sd_cfg.dev_name), "%s", light->name); /* Set the possible values to faults, in our case all faults */ - sd_cfg->flash_faults = LED_FAULT_OVER_VOLTAGE | LED_FAULT_TIMEOUT | + sd_cfg.flash_faults = LED_FAULT_OVER_VOLTAGE | LED_FAULT_TIMEOUT | LED_FAULT_OVER_TEMPERATURE | LED_FAULT_SHORT_CIRCUIT | LED_FAULT_OVER_CURRENT | LED_FAULT_INDICATOR | LED_FAULT_UNDER_VOLTAGE | LED_FAULT_INPUT_VOLTAGE | LED_FAULT_LED_OVER_TEMPERATURE; light->v4l2_flash = v4l2_flash_init(dev, NULL, fled, iled, - &v4l2_flash_ops, sd_cfg); - if (IS_ERR_OR_NULL(light->v4l2_flash)) { - ret = PTR_ERR(light->v4l2_flash); - goto out_free; - } + &v4l2_flash_ops, &sd_cfg); + if (IS_ERR(light->v4l2_flash)) + return PTR_ERR(light->v4l2_flash); - return ret; - -out_free: - kfree(sd_cfg); - return ret; + return 0; } static void gb_lights_light_v4l2_unregister(struct gb_light *light) -- cgit From 503dd28af108888c505e8d6a86f4acf5eb20f3b7 Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Tue, 18 Jul 2017 09:26:59 -0400 Subject: media: v4l2-flash-led-class: Create separate sub-devices for indicators The V4L2 flash interface allows controlling multiple LEDs through a single sub-devices if, and only if, these LEDs are of different types. This approach scales badly for flash controllers that drive multiple flash LEDs or for LED specific associations. Essentially, the original assumption of a LED driver chip that drives a single flash LED and an indicator LED is no longer valid. Address the matter by registering one sub-device per LED. Signed-off-by: Sakari Ailus Reviewed-by: Jacek Anaszewski Acked-by: Pavel Machek Reviewed-by: Rui Miguel Silva (for greybus/light) Acked-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/greybus/light.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'drivers/staging/greybus') diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c index 81469d087e74..3f4148c92308 100644 --- a/drivers/staging/greybus/light.c +++ b/drivers/staging/greybus/light.c @@ -58,6 +58,7 @@ struct gb_light { bool ready; #if IS_REACHABLE(CONFIG_V4L2_FLASH_LED_CLASS) struct v4l2_flash *v4l2_flash; + struct v4l2_flash *v4l2_flash_ind; #endif }; @@ -534,7 +535,7 @@ static int gb_lights_light_v4l2_register(struct gb_light *light) { struct gb_connection *connection = get_conn_from_light(light); struct device *dev = &connection->bundle->dev; - struct v4l2_flash_config sd_cfg = { {0} }; + struct v4l2_flash_config sd_cfg = { {0} }, sd_cfg_ind = { {0} }; struct led_classdev_flash *fled; struct led_classdev *iled = NULL; struct gb_channel *channel_torch, *channel_ind, *channel_flash; @@ -542,12 +543,12 @@ static int gb_lights_light_v4l2_register(struct gb_light *light) channel_torch = get_channel_from_mode(light, GB_CHANNEL_MODE_TORCH); if (channel_torch) __gb_lights_channel_v4l2_config(&channel_torch->intensity_uA, - &sd_cfg.torch_intensity); + &sd_cfg.intensity); channel_ind = get_channel_from_mode(light, GB_CHANNEL_MODE_INDICATOR); if (channel_ind) { __gb_lights_channel_v4l2_config(&channel_ind->intensity_uA, - &sd_cfg.indicator_intensity); + &sd_cfg_ind.intensity); iled = &channel_ind->fled.led_cdev; } @@ -557,6 +558,8 @@ static int gb_lights_light_v4l2_register(struct gb_light *light) fled = &channel_flash->fled; snprintf(sd_cfg.dev_name, sizeof(sd_cfg.dev_name), "%s", light->name); + snprintf(sd_cfg_ind.dev_name, sizeof(sd_cfg_ind.dev_name), + "%s indicator", light->name); /* Set the possible values to faults, in our case all faults */ sd_cfg.flash_faults = LED_FAULT_OVER_VOLTAGE | LED_FAULT_TIMEOUT | @@ -565,16 +568,26 @@ static int gb_lights_light_v4l2_register(struct gb_light *light) LED_FAULT_UNDER_VOLTAGE | LED_FAULT_INPUT_VOLTAGE | LED_FAULT_LED_OVER_TEMPERATURE; - light->v4l2_flash = v4l2_flash_init(dev, NULL, fled, iled, - &v4l2_flash_ops, &sd_cfg); + light->v4l2_flash = v4l2_flash_init(dev, NULL, fled, &v4l2_flash_ops, + &sd_cfg); if (IS_ERR(light->v4l2_flash)) return PTR_ERR(light->v4l2_flash); + if (channel_ind) { + light->v4l2_flash_ind = + v4l2_flash_indicator_init(dev, NULL, iled, &sd_cfg_ind); + if (IS_ERR(light->v4l2_flash_ind)) { + v4l2_flash_release(light->v4l2_flash); + return PTR_ERR(light->v4l2_flash_ind); + } + } + return 0; } static void gb_lights_light_v4l2_unregister(struct gb_light *light) { + v4l2_flash_release(light->v4l2_flash_ind); v4l2_flash_release(light->v4l2_flash); } #else -- cgit