diff options
author | David Pu <dpu@nvidia.com> | 2013-07-17 10:03:07 +0800 |
---|---|---|
committer | Harshada Kale <hkale@nvidia.com> | 2013-07-30 04:48:23 -0700 |
commit | 48dbf16c280f7846c3360c50a4f4cfc824d0f5fc (patch) | |
tree | 9733c99975968031e3603dae3b412f9043d5fff4 /drivers/media | |
parent | 33cf78ad018222f764a536f8e668053626d5c857 (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
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Rick Song <ricks@nvidia.com>
Reviewed-by: Charlie Huang <chahuang@nvidia.com>
Reviewed-by: Sivaram Nair <sivaramn@nvidia.com>
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Reviewed-by: Sachin Nikam <snikam@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 5f871a3a5b92..1ec138f30f68 100644 --- a/drivers/media/video/tegra/max77387.c +++ b/drivers/media/video/tegra/max77387.c @@ -509,6 +509,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) { @@ -533,15 +534,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 > f_levels1) @@ -620,6 +616,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; @@ -888,10 +903,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; @@ -1133,6 +1148,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 @@ -1242,6 +1258,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; @@ -1514,7 +1531,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: @@ -1522,7 +1539,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 2feee300eb42..2d41f2ab787f 100644 --- a/drivers/media/video/tegra/max77665-flash.c +++ b/drivers/media/video/tegra/max77665-flash.c @@ -506,15 +506,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 > f_levels1) @@ -590,6 +585,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) @@ -795,7 +810,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; @@ -988,6 +1003,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 @@ -1105,6 +1121,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; @@ -1347,7 +1364,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: @@ -1355,7 +1372,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: @@ -1683,7 +1700,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 */ @@ -1696,7 +1713,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': |