diff options
author | David Pu <dpu@nvidia.com> | 2013-07-17 10:03:07 +0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2013-09-14 13:41:45 -0700 |
commit | 2d087319ffd8140c2ad11128078fe1c9f81b2332 (patch) | |
tree | 55603f54b3640ba2b11182010066507c1994924a /drivers/media | |
parent | 0589a9d84451224e665398a668fa54a004c0393d (diff) |
media: video: fix deadlock in edp client driver
don't call edp api in throttle callback or deadlock will happen since
the edp lock is held from caller.
Bug 1327193
Change-Id: I6b90630d0a37d53521c1db4e95f5945f184a70f5
Signed-off-by: David Pu <dpu@nvidia.com>
Reviewed-on: http://git-master/r/247173
(cherry picked from commit 48dbf16c280f7846c3360c50a4f4cfc824d0f5fc)
Reviewed-on: http://git-master/r/263684
GVS: Gerrit_Virtual_Submit
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/tegra/max77387.c | 37 | ||||
-rw-r--r-- | drivers/media/video/tegra/max77665-flash.c | 37 |
2 files changed, 54 insertions, 20 deletions
diff --git a/drivers/media/video/tegra/max77387.c b/drivers/media/video/tegra/max77387.c index 901d796d639c..40e9a68d9a8f 100644 --- a/drivers/media/video/tegra/max77387.c +++ b/drivers/media/video/tegra/max77387.c @@ -507,6 +507,7 @@ static int max77387_edp_req(struct max77387_info *info, return 0; } + static int max77387_set_leds(struct max77387_info *info, u8 mask, u8 curr1, u8 curr2) { @@ -527,15 +528,10 @@ static int max77387_set_leds(struct max77387_info *info, info->regs.led2_tcurr = 0; info->regs.leds_en = 0; info->regs.regs_stale = false; - max77387_edp_lowest(info); } goto set_leds_end; } - err = max77387_edp_req(info, mask, &curr1, &curr2); - if (err) - goto set_leds_end; - if (mask & 1) { if (info->op_mode == MAXFLASH_MODE_FLASH) { if (curr1 > info->max_flash[0]) @@ -614,6 +610,25 @@ set_leds_end: return err; } +static int max77387_edp_set_leds(struct max77387_info *info, + u8 mask, u8 curr1, u8 curr2) +{ + int err; + + err = max77387_edp_req(info, mask, &curr1, &curr2); + if (err) + goto edp_set_leds_end; + + err = max77387_set_leds(info, mask, curr1, curr2); + if (!err && info->op_mode == MAXFLASH_MODE_NONE) + max77387_edp_lowest(info); + +edp_set_leds_end: + if (err) + dev_err(info->dev, "%s ERROR: %d\n", __func__, err); + return err; +} + static void max77387_update_config(struct max77387_info *info) { struct max77387_settings *pst = &info->settings; @@ -882,10 +897,10 @@ static int max77387_update_settings(struct max77387_info *info) err = max77387_reg_raw_wr(info, MAX77387_RW_NTC, regs, 5); if (info->op_mode == MAXFLASH_MODE_FLASH) - err |= max77387_set_leds(info, info->config.led_mask, + err |= max77387_edp_set_leds(info, info->config.led_mask, info->regs.led1_fcurr, info->regs.led2_fcurr); else - err |= max77387_set_leds(info, info->config.led_mask, + err |= max77387_edp_set_leds(info, info->config.led_mask, info->regs.led1_tcurr, info->regs.led2_tcurr); info->regs.regs_stale = false; @@ -1137,6 +1152,7 @@ static void max77387_shutdown(struct i2c_client *client) dev_info(info->dev, "Shutting down\n"); max77387_enter_offmode(info, true); + max77387_edp_lowest(info); info->regs.regs_stale = true; } #endif @@ -1246,6 +1262,7 @@ static int max77387_power_set(struct max77387_info *info, int pwr) switch (pwr) { case NVC_PWR_OFF: max77387_enter_offmode(info, true); + max77387_edp_lowest(info); if ((info->pdata->cfg & NVC_CFG_OFF2STDBY) || (info->pdata->cfg & NVC_CFG_BOOT_INIT)) pwr = NVC_PWR_STDBY; @@ -1518,7 +1535,7 @@ static int max77387_set_param(struct max77387_info *info, long arg) info->new_timer = led_levels.timeout; curr1 = led_levels.levels[0]; curr2 = led_levels.levels[1]; - err = max77387_set_leds(info, + err = max77387_edp_set_leds(info, led_levels.ledmask, curr1, curr2); break; case NVC_PARAM_TORCH_LEVEL: @@ -1526,7 +1543,7 @@ static int max77387_set_param(struct max77387_info *info, long arg) info->new_timer = led_levels.timeout; curr1 = led_levels.levels[0]; curr2 = led_levels.levels[1]; - err = max77387_set_leds(info, + err = max77387_edp_set_leds(info, led_levels.ledmask, curr1, curr2); break; case NVC_PARAM_FLASH_PIN_STATE: @@ -1883,7 +1900,7 @@ set_attr: break; /* change led 1/2 current settings */ case 'c': - max77387_set_leds(info, info->config.led_mask, + max77387_edp_set_leds(info, info->config.led_mask, val & 0xff, (val >> 8) & 0xff); break; /* modify flash timeout reg */ diff --git a/drivers/media/video/tegra/max77665-flash.c b/drivers/media/video/tegra/max77665-flash.c index 419dceb31add..895a901d4963 100644 --- a/drivers/media/video/tegra/max77665-flash.c +++ b/drivers/media/video/tegra/max77665-flash.c @@ -503,15 +503,10 @@ static int max77665_f_set_leds(struct max77665_f_info *info, info, MAX77665_F_RW_FLED_ENABLE, 0, true); if (!err) { info->regs.leds_en = 0; - max77665_f_edp_lowest(info); } goto set_leds_end; } - err = max77665_f_edp_req(info, mask, &curr1, &curr2); - if (err) - goto set_leds_end; - if (mask & 1) { if (info->op_mode == MAXFLASH_MODE_FLASH) { if (curr1 > info->max_flash[0]) @@ -587,6 +582,26 @@ set_leds_end: return err; } +static int max77665_f_edp_set_leds(struct max77665_f_info *info, + u8 mask, u8 curr1, u8 curr2) +{ + int err; + + err = max77665_f_edp_req(info, mask, &curr1, &curr2); + if (err) + goto edp_set_leds_end; + + err = max77665_f_set_leds(info, mask, curr1, curr2); + if (!err && info->op_mode == MAXFLASH_MODE_NONE) + max77665_f_edp_lowest(info); + + +edp_set_leds_end: + if (err) + dev_err(info->dev, "%s ERROR: %d\n", __func__, err); + return err; +} + static inline int max77665_f_get_boost_volt(u16 mV) { if (mV <= BOOST_VOLT_FLOOR) @@ -792,7 +807,7 @@ static int max77665_f_update_settings(struct max77665_f_info *info) err |= max77665_f_reg_wr(info, MAX77665_F_RW_MAXFLASH_TIMER, info->regs.m_timing, false); - err |= max77665_f_set_leds(info, info->config.led_mask, + err |= max77665_f_edp_set_leds(info, info->config.led_mask, info->regs.led1_curr, info->regs.led2_curr); info->regs.regs_stale = false; @@ -995,6 +1010,7 @@ static void max77665_f_shutdown(struct platform_device *pdev) dev_info(&pdev->dev, "Shutting down\n"); max77665_f_enter_offmode(info, true); + max77665_f_edp_lowest(info); info->regs.regs_stale = true; } #endif @@ -1112,6 +1128,7 @@ static int max77665_f_power_set(struct max77665_f_info *info, int pwr) switch (pwr) { case NVC_PWR_OFF: max77665_f_enter_offmode(info, true); + max77665_f_edp_lowest(info); if ((info->pdata->cfg & NVC_CFG_OFF2STDBY) || (info->pdata->cfg & NVC_CFG_BOOT_INIT)) pwr = NVC_PWR_STDBY; @@ -1354,7 +1371,7 @@ static int max77665_f_set_param(struct max77665_f_info *info, long arg) info->new_ftimer = led_levels.timeout & 0X0F; curr1 = led_levels.levels[0]; curr2 = led_levels.levels[1]; - err = max77665_f_set_leds(info, + err = max77665_f_edp_set_leds(info, led_levels.ledmask, curr1, curr2); return err; case NVC_PARAM_TORCH_LEVEL: @@ -1362,7 +1379,7 @@ static int max77665_f_set_param(struct max77665_f_info *info, long arg) info->new_ftimer = led_levels.timeout & 0X0F; curr1 = led_levels.levels[0]; curr2 = led_levels.levels[1]; - err = max77665_f_set_leds(info, + err = max77665_f_edp_set_leds(info, led_levels.ledmask, curr1, curr2); return err; case NVC_PARAM_FLASH_PIN_STATE: @@ -1690,7 +1707,7 @@ set_attr: dev_info(info->dev, "new data = %x\n", val); switch (buf[0]) { case 'c': /* change led 1/2 current settings */ - max77665_f_set_leds(info, info->config.led_mask, + max77665_f_edp_set_leds(info, info->config.led_mask, val & 0xff, (val >> 8) & 0xff); break; case 'l': /* enable/disable led 1/2 */ @@ -1703,7 +1720,7 @@ set_attr: break; case 'f': /* modify flash timeout reg */ info->new_ftimer = val & 0X0F; - max77665_f_set_leds(info, info->config.led_mask, + max77665_f_edp_set_leds(info, info->config.led_mask, info->regs.led1_curr, info->regs.led2_curr); break; case 'p': |