Commit 0bad9098 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm+acpi-4.2-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management and ACPI fixes from Rafael Wysocki:
 "These fix a recent regression in the ACPI backlight code and a memory
  leak in the Exynos cpufreq driver.

  Specifics:

   - Fix a recently introduced issue in the ACPI backlight code which
     causes lockdep to complain about a circular lock dependency during
     initialization (Hans de Goede).

   - Fix a possible memory during initialization in the Exynos cpufreq
     driver (Shailendra Verma)"

* tag 'pm+acpi-4.2-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpufreq: exynos: Fix for memory leak in case SoC name does not match
  ACPI / video: Fix circular lock dependency issue in the video-detect code
parents 28e55d07 b8a1171f
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/workqueue.h>
#include <acpi/video.h> #include <acpi/video.h>
ACPI_MODULE_NAME("video"); ACPI_MODULE_NAME("video");
...@@ -41,6 +42,7 @@ void acpi_video_unregister_backlight(void); ...@@ -41,6 +42,7 @@ void acpi_video_unregister_backlight(void);
static bool backlight_notifier_registered; static bool backlight_notifier_registered;
static struct notifier_block backlight_nb; static struct notifier_block backlight_nb;
static struct work_struct backlight_notify_work;
static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef; static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef;
static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef; static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef;
...@@ -262,6 +264,13 @@ static const struct dmi_system_id video_detect_dmi_table[] = { ...@@ -262,6 +264,13 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
{ }, { },
}; };
/* This uses a workqueue to avoid various locking ordering issues */
static void acpi_video_backlight_notify_work(struct work_struct *work)
{
if (acpi_video_get_backlight_type() != acpi_backlight_video)
acpi_video_unregister_backlight();
}
static int acpi_video_backlight_notify(struct notifier_block *nb, static int acpi_video_backlight_notify(struct notifier_block *nb,
unsigned long val, void *bd) unsigned long val, void *bd)
{ {
...@@ -269,9 +278,8 @@ static int acpi_video_backlight_notify(struct notifier_block *nb, ...@@ -269,9 +278,8 @@ static int acpi_video_backlight_notify(struct notifier_block *nb,
/* A raw bl registering may change video -> native */ /* A raw bl registering may change video -> native */
if (backlight->props.type == BACKLIGHT_RAW && if (backlight->props.type == BACKLIGHT_RAW &&
val == BACKLIGHT_REGISTERED && val == BACKLIGHT_REGISTERED)
acpi_video_get_backlight_type() != acpi_backlight_video) schedule_work(&backlight_notify_work);
acpi_video_unregister_backlight();
return NOTIFY_OK; return NOTIFY_OK;
} }
...@@ -304,6 +312,8 @@ enum acpi_backlight_type acpi_video_get_backlight_type(void) ...@@ -304,6 +312,8 @@ enum acpi_backlight_type acpi_video_get_backlight_type(void)
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, find_video, NULL, ACPI_UINT32_MAX, find_video, NULL,
&video_caps, NULL); &video_caps, NULL);
INIT_WORK(&backlight_notify_work,
acpi_video_backlight_notify_work);
backlight_nb.notifier_call = acpi_video_backlight_notify; backlight_nb.notifier_call = acpi_video_backlight_notify;
backlight_nb.priority = 0; backlight_nb.priority = 0;
if (backlight_register_notifier(&backlight_nb) == 0) if (backlight_register_notifier(&backlight_nb) == 0)
......
...@@ -180,7 +180,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) ...@@ -180,7 +180,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
ret = exynos5250_cpufreq_init(exynos_info); ret = exynos5250_cpufreq_init(exynos_info);
} else { } else {
pr_err("%s: Unknown SoC type\n", __func__); pr_err("%s: Unknown SoC type\n", __func__);
return -ENODEV; ret = -ENODEV;
} }
if (ret) if (ret)
...@@ -188,12 +188,14 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) ...@@ -188,12 +188,14 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
if (exynos_info->set_freq == NULL) { if (exynos_info->set_freq == NULL) {
dev_err(&pdev->dev, "No set_freq function (ERR)\n"); dev_err(&pdev->dev, "No set_freq function (ERR)\n");
ret = -EINVAL;
goto err_vdd_arm; goto err_vdd_arm;
} }
arm_regulator = regulator_get(NULL, "vdd_arm"); arm_regulator = regulator_get(NULL, "vdd_arm");
if (IS_ERR(arm_regulator)) { if (IS_ERR(arm_regulator)) {
dev_err(&pdev->dev, "failed to get resource vdd_arm\n"); dev_err(&pdev->dev, "failed to get resource vdd_arm\n");
ret = -EINVAL;
goto err_vdd_arm; goto err_vdd_arm;
} }
...@@ -225,7 +227,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev) ...@@ -225,7 +227,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
regulator_put(arm_regulator); regulator_put(arm_regulator);
err_vdd_arm: err_vdd_arm:
kfree(exynos_info); kfree(exynos_info);
return -EINVAL; return ret;
} }
static struct platform_driver exynos_cpufreq_platdrv = { static struct platform_driver exynos_cpufreq_platdrv = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment