Merge tag 'pm-for-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 22 Jul 2012 20:36:52 +0000 (13:36 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 22 Jul 2012 20:36:52 +0000 (13:36 -0700)
Pull power management updates from Rafael Wysocki:

 - ACPI conversion to PM handling based on struct dev_pm_ops.
 - Conversion of a number of platform drivers to PM handling based on
   struct dev_pm_ops and removal of empty legacy PM callbacks from a
   couple of PCI drivers.
 - Suspend-to-both for in-kernel hibernation from Bojan Smojver.
 - cpuidle fixes and cleanups from ShuoX Liu, Daniel Lezcano and Preeti
   Murthy.
 - cpufreq bug fixes from Jonghwa Lee and Stephen Boyd.
 - Suspend and hibernate fixes from Srivatsa Bhat and Colin Cross.
 - Generic PM domains framework updates.
 - RTC CMOS wakeup signaling update from Paul Fox.
 - sparse warnings fixes from Sachin Kamat.
 - Build warnings fixes for the generic PM domains framework and PM
   sysfs code.
 - sysfs switch for printing device suspend times from Sameer Nanda.
 - Documentation fix from Oskar Schirmer.

* tag 'pm-for-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (70 commits)
  cpufreq: Fix sysfs deadlock with concurrent hotplug/frequency switch
  EXYNOS: bugfix on retrieving old_index from freqs.old
  PM / Sleep: call early resume handlers when suspend_noirq fails
  PM / QoS: Use NULL pointer instead of plain integer in qos.c
  PM / QoS: Use NULL pointer instead of plain integer in pm_qos.h
  PM / Sleep: Require CAP_BLOCK_SUSPEND to use wake_lock/wake_unlock
  PM / Sleep: Add missing static storage class specifiers in main.c
  cpuilde / ACPI: remove time from acpi_processor_cx structure
  cpuidle / ACPI: remove usage from acpi_processor_cx structure
  cpuidle / ACPI : remove latency_ticks from acpi_processor_cx structure
  rtc-cmos: report wakeups from interrupt handler
  PM / Sleep: Fix build warning in sysfs.c for CONFIG_PM_SLEEP unset
  PM / Domains: Fix build warning for CONFIG_PM_RUNTIME unset
  olpc-xo15-sci: Use struct dev_pm_ops for power management
  PM / Domains: Replace plain integer with NULL pointer in domain.c file
  PM / Domains: Add missing static storage class specifier in domain.c file
  PM / crypto / ux500: Use struct dev_pm_ops for power management
  PM / IPMI: Remove empty legacy PCI PM callbacks
  tpm_nsc: Use struct dev_pm_ops for power management
  tpm_tis: Use struct dev_pm_ops for power management
  ...

1  2 
drivers/platform/x86/intel_ips.c
drivers/platform/x86/sony-laptop.c
kernel/power/hibernate.c

index 9af4257d49018443b19e447455969787b480a944,bd89f3c8e76e70198bf3a161700054566ea51e30..5051aa970e0af3144c294516a92282ead76bb06b
@@@ -72,7 -72,6 +72,7 @@@
  #include <linux/string.h>
  #include <linux/tick.h>
  #include <linux/timer.h>
 +#include <linux/dmi.h>
  #include <drm/i915_drm.h>
  #include <asm/msr.h>
  #include <asm/processor.h>
@@@ -1486,24 -1485,6 +1486,24 @@@ static DEFINE_PCI_DEVICE_TABLE(ips_id_t
  
  MODULE_DEVICE_TABLE(pci, ips_id_table);
  
 +static int ips_blacklist_callback(const struct dmi_system_id *id)
 +{
 +      pr_info("Blacklisted intel_ips for %s\n", id->ident);
 +      return 1;
 +}
 +
 +static const struct dmi_system_id ips_blacklist[] = {
 +      {
 +              .callback = ips_blacklist_callback,
 +              .ident = "HP ProBook",
 +              .matches = {
 +                      DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 +                      DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook"),
 +              },
 +      },
 +      { }     /* terminating entry */
 +};
 +
  static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id)
  {
        u64 platform_info;
        u16 htshi, trc, trc_required_mask;
        u8 tse;
  
 +      if (dmi_check_system(ips_blacklist))
 +              return -ENODEV;
 +
        ips = kzalloc(sizeof(struct ips_driver), GFP_KERNEL);
        if (!ips)
                return -ENOMEM;
@@@ -1719,21 -1697,6 +1719,6 @@@ static void ips_remove(struct pci_dev *
        dev_dbg(&dev->dev, "IPS driver removed\n");
  }
  
- #ifdef CONFIG_PM
- static int ips_suspend(struct pci_dev *dev, pm_message_t state)
- {
-       return 0;
- }
- static int ips_resume(struct pci_dev *dev)
- {
-       return 0;
- }
- #else
- #define ips_suspend NULL
- #define ips_resume NULL
- #endif /* CONFIG_PM */
  static void ips_shutdown(struct pci_dev *dev)
  {
  }
@@@ -1743,8 -1706,6 +1728,6 @@@ static struct pci_driver ips_pci_drive
        .id_table = ips_id_table,
        .probe = ips_probe,
        .remove = ips_remove,
-       .suspend = ips_suspend,
-       .resume = ips_resume,
        .shutdown = ips_shutdown,
  };
  
index d456ff0c73b73614339d4109c1bc282037c64e08,c7a236240785352e1c537c25b49cd862112f2516..9363969ad07adf65cefe1a6aa918ca47363ca907
@@@ -973,7 -973,7 +973,7 @@@ static ssize_t sony_nc_sysfs_store(stru
                               struct device_attribute *attr,
                               const char *buffer, size_t count)
  {
 -      unsigned long value = 0;
 +      int value;
        int ret = 0;
        struct sony_nc_value *item =
            container_of(attr, struct sony_nc_value, devattr);
        if (count > 31)
                return -EINVAL;
  
 -      if (kstrtoul(buffer, 10, &value))
 +      if (kstrtoint(buffer, 10, &value))
                return -EINVAL;
  
        if (item->validate)
                return value;
  
        ret = sony_nc_int_call(sony_nc_acpi_handle, *item->acpiset,
 -                      (int *)&value, NULL);
 +                             &value, NULL);
        if (ret < 0)
                return -EIO;
  
  struct sony_backlight_props {
        struct backlight_device *dev;
        int                     handle;
 +      int                     cmd_base;
        u8                      offset;
        u8                      maxlvl;
  };
@@@ -1038,7 -1037,7 +1038,7 @@@ static int sony_nc_get_brightness_ng(st
        struct sony_backlight_props *sdev =
                (struct sony_backlight_props *)bl_get_data(bd);
  
 -      sony_call_snc_handle(sdev->handle, 0x0200, &result);
 +      sony_call_snc_handle(sdev->handle, sdev->cmd_base + 0x100, &result);
  
        return (result & 0xff) - sdev->offset;
  }
@@@ -1050,8 -1049,7 +1050,8 @@@ static int sony_nc_update_status_ng(str
                (struct sony_backlight_props *)bl_get_data(bd);
  
        value = bd->props.brightness + sdev->offset;
 -      if (sony_call_snc_handle(sdev->handle, 0x0100 | (value << 16), &result))
 +      if (sony_call_snc_handle(sdev->handle, sdev->cmd_base | (value << 0x10),
 +                              &result))
                return -EIO;
  
        return value;
@@@ -1174,11 -1172,6 +1174,11 @@@ static int sony_nc_hotkeys_decode(u32 e
  /*
   * ACPI callbacks
   */
 +enum event_types {
 +      HOTKEY = 1,
 +      KILLSWITCH,
 +      GFX_SWITCH
 +};
  static void sony_nc_notify(struct acpi_device *device, u32 event)
  {
        u32 real_ev = event;
                /* hotkey event */
                case 0x0100:
                case 0x0127:
 -                      ev_type = 1;
 +                      ev_type = HOTKEY;
                        real_ev = sony_nc_hotkeys_decode(event, handle);
  
                        if (real_ev > 0)
                         * update the rfkill device status when the
                         * switch is moved.
                         */
 -                      ev_type = 2;
 +                      ev_type = KILLSWITCH;
                        sony_call_snc_handle(handle, 0x0100, &result);
                        real_ev = result & 0x03;
  
  
                        break;
  
 +              case 0x0128:
 +              case 0x0146:
 +                      /* Hybrid GFX switching */
 +                      sony_call_snc_handle(handle, 0x0000, &result);
 +                      dprintk("GFX switch event received (reason: %s)\n",
 +                                      (result & 0x01) ?
 +                                      "switch change" : "unknown");
 +
 +                      /* verify the switch state
 +                       * 1: discrete GFX
 +                       * 0: integrated GFX
 +                       */
 +                      sony_call_snc_handle(handle, 0x0100, &result);
 +
 +                      ev_type = GFX_SWITCH;
 +                      real_ev = result & 0xff;
 +                      break;
 +
                default:
                        dprintk("Unknown event 0x%x for handle 0x%x\n",
                                        event, handle);
  
        } else {
                /* old style event */
 -              ev_type = 1;
 +              ev_type = HOTKEY;
                sony_laptop_report_input_event(real_ev);
        }
  
@@@ -1477,7 -1452,7 +1477,7 @@@ static void sony_nc_function_resume(voi
                                &result);
  }
  
- static int sony_nc_resume(struct acpi_device *device)
+ static int sony_nc_resume(struct device *dev)
  {
        struct sony_nc_value *item;
        acpi_handle handle;
        return 0;
  }
  
+ static SIMPLE_DEV_PM_OPS(sony_nc_pm, NULL, sony_nc_resume);
  static void sony_nc_rfkill_cleanup(void)
  {
        int i;
@@@ -1918,33 -1895,32 +1920,33 @@@ static ssize_t sony_nc_battery_care_lim
         *  bits 4,5: store the limit into the EC
         *  bits 6,7: store the limit into the battery
         */
 +      cmd = 0;
  
 -      /*
 -       * handle 0x0115 should allow storing on battery too;
 -       * handle 0x0136 same as 0x0115 + health status;
 -       * handle 0x013f, same as 0x0136 but no storing on the battery
 -       *
 -       * Store only inside the EC for now, regardless the handle number
 -       */
 -      if (value == 0)
 -              /* disable limits */
 -              cmd = 0x0;
 +      if (value > 0) {
 +              if (value <= 50)
 +                      cmd = 0x20;
  
 -      else if (value <= 50)
 -              cmd = 0x21;
 +              else if (value <= 80)
 +                      cmd = 0x10;
  
 -      else if (value <= 80)
 -              cmd = 0x11;
 +              else if (value <= 100)
 +                      cmd = 0x30;
  
 -      else if (value <= 100)
 -              cmd = 0x31;
 +              else
 +                      return -EINVAL;
  
 -      else
 -              return -EINVAL;
 +              /*
 +               * handle 0x0115 should allow storing on battery too;
 +               * handle 0x0136 same as 0x0115 + health status;
 +               * handle 0x013f, same as 0x0136 but no storing on the battery
 +               */
 +              if (bcare_ctl->handle != 0x013f)
 +                      cmd = cmd | (cmd << 2);
  
 -      if (sony_call_snc_handle(bcare_ctl->handle, (cmd << 0x10) | 0x0100,
 -                              &result))
 +              cmd = (cmd | 0x1) << 0x10;
 +      }
 +
 +      if (sony_call_snc_handle(bcare_ctl->handle, cmd | 0x0100, &result))
                return -EIO;
  
        return count;
@@@ -2139,7 -2115,7 +2141,7 @@@ static ssize_t sony_nc_thermal_mode_sho
                struct device_attribute *attr, char *buffer)
  {
        ssize_t count = 0;
 -      unsigned int mode = sony_nc_thermal_mode_get();
 +      int mode = sony_nc_thermal_mode_get();
  
        if (mode < 0)
                return mode;
@@@ -2498,7 -2474,6 +2500,7 @@@ static void sony_nc_backlight_ng_read_l
  {
        u64 offset;
        int i;
 +      int lvl_table_len = 0;
        u8 min = 0xff, max = 0x00;
        unsigned char buffer[32] = { 0 };
  
        props->maxlvl = 0xff;
  
        offset = sony_find_snc_handle(handle);
 -      if (offset < 0)
 -              return;
  
        /* try to read the boundaries from ACPI tables, if we fail the above
         * defaults should be reasonable
        if (i < 0)
                return;
  
 +      switch (handle) {
 +      case 0x012f:
 +      case 0x0137:
 +              lvl_table_len = 9;
 +              break;
 +      case 0x143:
 +              lvl_table_len = 16;
 +              break;
 +      }
 +
        /* the buffer lists brightness levels available, brightness levels are
         * from position 0 to 8 in the array, other values are used by ALS
         * control.
         */
 -      for (i = 0; i < 9 && i < ARRAY_SIZE(buffer); i++) {
 +      for (i = 0; i < lvl_table_len && i < ARRAY_SIZE(buffer); i++) {
  
                dprintk("Brightness level: %d\n", buffer[i]);
  
@@@ -2555,24 -2522,16 +2557,24 @@@ static void sony_nc_backlight_setup(voi
        const struct backlight_ops *ops = NULL;
        struct backlight_properties props;
  
 -      if (sony_find_snc_handle(0x12f) != -1) {
 +      if (sony_find_snc_handle(0x12f) >= 0) {
                ops = &sony_backlight_ng_ops;
 +              sony_bl_props.cmd_base = 0x0100;
                sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
                max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
  
 -      } else if (sony_find_snc_handle(0x137) != -1) {
 +      } else if (sony_find_snc_handle(0x137) >= 0) {
                ops = &sony_backlight_ng_ops;
 +              sony_bl_props.cmd_base = 0x0100;
                sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
                max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
  
 +      } else if (sony_find_snc_handle(0x143) >= 0) {
 +              ops = &sony_backlight_ng_ops;
 +              sony_bl_props.cmd_base = 0x3000;
 +              sony_nc_backlight_ng_read_limits(0x143, &sony_bl_props);
 +              max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
 +
        } else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
                                                &unused))) {
                ops = &sony_backlight_ops;
@@@ -2640,12 -2599,6 +2642,12 @@@ static int sony_nc_add(struct acpi_devi
                }
        }
  
 +      result = sony_laptop_setup_input(device);
 +      if (result) {
 +              pr_err("Unable to create input devices\n");
 +              goto outplatform;
 +      }
 +
        if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
                                         &handle))) {
                int arg = 1;
        }
  
        /* setup input devices and helper fifo */
 -      result = sony_laptop_setup_input(device);
 -      if (result) {
 -              pr_err("Unable to create input devices\n");
 -              goto outsnc;
 -      }
 -
        if (acpi_video_backlight_support()) {
                pr_info("brightness ignored, must be controlled by ACPI video driver\n");
        } else {
  
        return 0;
  
 -      out_sysfs:
 +out_sysfs:
        for (item = sony_nc_values; item->name; ++item) {
                device_remove_file(&sony_pf_device->dev, &item->devattr);
        }
        sony_nc_backlight_cleanup();
 -
 -      sony_laptop_remove_input();
 -
 -      outsnc:
        sony_nc_function_cleanup(sony_pf_device);
        sony_nc_handles_cleanup(sony_pf_device);
  
 -      outpresent:
 +outplatform:
 +      sony_laptop_remove_input();
 +
 +outpresent:
        sony_pf_remove();
  
 -      outwalk:
 +outwalk:
        sony_nc_rfkill_cleanup();
        return result;
  }
@@@ -2770,9 -2730,9 +2772,9 @@@ static struct acpi_driver sony_nc_drive
        .ops = {
                .add = sony_nc_add,
                .remove = sony_nc_remove,
-               .resume = sony_nc_resume,
                .notify = sony_nc_notify,
                },
+       .drv.pm = &sony_nc_pm,
  };
  
  /*********** SPIC (SNY6001) Device ***********/
@@@ -4285,19 -4245,22 +4287,22 @@@ err_free_resources
        return result;
  }
  
- static int sony_pic_suspend(struct acpi_device *device, pm_message_t state)
+ static int sony_pic_suspend(struct device *dev)
  {
-       if (sony_pic_disable(device))
+       if (sony_pic_disable(to_acpi_device(dev)))
                return -ENXIO;
        return 0;
  }
  
- static int sony_pic_resume(struct acpi_device *device)
+ static int sony_pic_resume(struct device *dev)
  {
-       sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
+       sony_pic_enable(to_acpi_device(dev),
+                       spic_dev.cur_ioport, spic_dev.cur_irq);
        return 0;
  }
  
+ static SIMPLE_DEV_PM_OPS(sony_pic_pm, sony_pic_suspend, sony_pic_resume);
  static const struct acpi_device_id sony_pic_device_ids[] = {
        {SONY_PIC_HID, 0},
        {"", 0},
@@@ -4311,9 -4274,8 +4316,8 @@@ static struct acpi_driver sony_pic_driv
        .ops = {
                .add = sony_pic_add,
                .remove = sony_pic_remove,
-               .suspend = sony_pic_suspend,
-               .resume = sony_pic_resume,
                },
+       .drv.pm = &sony_pic_pm,
  };
  
  static struct dmi_system_id __initdata sonypi_dmi_table[] = {
diff --combined kernel/power/hibernate.c
index 238025f5472e42d745752f0c29d3534ab7b66285,0d4b354bc1beb9b22cd73f63978a91ce9ff2f890..b26f5f1e773e6b6aa3420ee1fb60c9b8fc6025cc
@@@ -5,6 -5,7 +5,7 @@@
   * Copyright (c) 2003 Open Source Development Lab
   * Copyright (c) 2004 Pavel Machek <pavel@ucw.cz>
   * Copyright (c) 2009 Rafael J. Wysocki, Novell Inc.
+  * Copyright (C) 2012 Bojan Smojver <bojan@rexursive.com>
   *
   * This file is released under the GPLv2.
   */
@@@ -27,6 -28,7 +28,6 @@@
  #include <linux/syscore_ops.h>
  #include <linux/ctype.h>
  #include <linux/genhd.h>
 -#include <scsi/scsi_scan.h>
  
  #include "power.h"
  
@@@ -45,6 -47,9 +46,9 @@@ enum 
        HIBERNATION_PLATFORM,
        HIBERNATION_SHUTDOWN,
        HIBERNATION_REBOOT,
+ #ifdef CONFIG_SUSPEND
+       HIBERNATION_SUSPEND,
+ #endif
        /* keep last */
        __HIBERNATION_AFTER_LAST
  };
@@@ -353,6 -358,7 +357,7 @@@ int hibernation_snapshot(int platform_m
        }
  
        suspend_console();
+       ftrace_stop();
        pm_restrict_gfp_mask();
  
        error = dpm_suspend(PMSG_FREEZE);
        if (error || !in_suspend)
                pm_restore_gfp_mask();
  
+       ftrace_start();
        resume_console();
        dpm_complete(msg);
  
@@@ -480,6 -487,7 +486,7 @@@ int hibernation_restore(int platform_mo
  
        pm_prepare_console();
        suspend_console();
+       ftrace_stop();
        pm_restrict_gfp_mask();
        error = dpm_suspend_start(PMSG_QUIESCE);
        if (!error) {
                dpm_resume_end(PMSG_RECOVER);
        }
        pm_restore_gfp_mask();
+       ftrace_start();
        resume_console();
        pm_restore_console();
        return error;
@@@ -513,6 -522,7 +521,7 @@@ int hibernation_platform_enter(void
  
        entering_platform_hibernation = true;
        suspend_console();
+       ftrace_stop();
        error = dpm_suspend_start(PMSG_HIBERNATE);
        if (error) {
                if (hibernation_ops->recover)
   Resume_devices:
        entering_platform_hibernation = false;
        dpm_resume_end(PMSG_RESTORE);
+       ftrace_start();
        resume_console();
  
   Close:
   */
  static void power_down(void)
  {
+ #ifdef CONFIG_SUSPEND
+       int error;
+ #endif
        switch (hibernation_mode) {
        case HIBERNATION_REBOOT:
                kernel_restart(NULL);
        case HIBERNATION_SHUTDOWN:
                kernel_power_off();
                break;
+ #ifdef CONFIG_SUSPEND
+       case HIBERNATION_SUSPEND:
+               error = suspend_devices_and_enter(PM_SUSPEND_MEM);
+               if (error) {
+                       if (hibernation_ops)
+                               hibernation_mode = HIBERNATION_PLATFORM;
+                       else
+                               hibernation_mode = HIBERNATION_SHUTDOWN;
+                       power_down();
+               }
+               /*
+                * Restore swap signature.
+                */
+               error = swsusp_unmark();
+               if (error)
+                       printk(KERN_ERR "PM: Swap will be unusable! "
+                                       "Try swapon -a.\n");
+               return;
+ #endif
        }
        kernel_halt();
        /*
@@@ -747,6 -781,13 +780,6 @@@ static int software_resume(void
                        async_synchronize_full();
                }
  
 -              /*
 -               * We can't depend on SCSI devices being available after loading
 -               * one of their modules until scsi_complete_async_scans() is
 -               * called and the resume device usually is a SCSI one.
 -               */
 -              scsi_complete_async_scans();
 -
                swsusp_resume_device = name_to_dev_t(resume_file);
                if (!swsusp_resume_device) {
                        error = -ENODEV;
@@@ -819,6 -860,9 +852,9 @@@ static const char * const hibernation_m
        [HIBERNATION_PLATFORM]  = "platform",
        [HIBERNATION_SHUTDOWN]  = "shutdown",
        [HIBERNATION_REBOOT]    = "reboot",
+ #ifdef CONFIG_SUSPEND
+       [HIBERNATION_SUSPEND]   = "suspend",
+ #endif
  };
  
  /*
@@@ -859,6 -903,9 +895,9 @@@ static ssize_t disk_show(struct kobjec
                switch (i) {
                case HIBERNATION_SHUTDOWN:
                case HIBERNATION_REBOOT:
+ #ifdef CONFIG_SUSPEND
+               case HIBERNATION_SUSPEND:
+ #endif
                        break;
                case HIBERNATION_PLATFORM:
                        if (hibernation_ops)
@@@ -899,6 -946,9 +938,9 @@@ static ssize_t disk_store(struct kobjec
                switch (mode) {
                case HIBERNATION_SHUTDOWN:
                case HIBERNATION_REBOOT:
+ #ifdef CONFIG_SUSPEND
+               case HIBERNATION_SUSPEND:
+ #endif
                        hibernation_mode = mode;
                        break;
                case HIBERNATION_PLATFORM:
This page took 0.054206 seconds and 5 git commands to generate.