]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'pm-fixes-next' into linux-next
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 21 Oct 2013 23:19:49 +0000 (01:19 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 21 Oct 2013 23:19:49 +0000 (01:19 +0200)
* pm-fixes-next: (98 commits)
  intel_pstate: Correct calculation of min pstate value
  intel_pstate: Improve accuracy by not truncating until final result
  Linux 3.12-rc6
  Btrfs: release path before starting transaction in can_nocow_extent
  usb: usb_phy_gen: refine conditional declaration of usb_nop_xceiv_register
  Revert "Drivers: hv: vmbus: Fix a bug in channel rescind code"
  mm: revert mremap pud_free anti-fix
  mm: fix BUG in __split_huge_page_pmd
  swap: fix set_blocksize race during swapon/swapoff
  procfs: call default get_unmapped_area on MMU-present architectures
  procfs: fix unintended truncation of returned mapped address
  writeback: fix negative bdi max pause
  percpu_refcount: export symbols
  fs: buffer: move allocation failure loop into the allocator
  mm: memcg: handle non-error OOM situations more gracefully
  tools/testing/selftests: fix uninitialized variable
  block/partitions/efi.c: treat size mismatch as a warning, not an error
  mm: hugetlb: initialize PG_reserved for tail pages of gigantic compound pages
  mm/zswap: bugfix: memory leak when re-swapon
  mm: /proc/pid/pagemap: inspect _PAGE_SOFT_DIRTY only on present pages
  ...

218 files changed:
Documentation/ABI/testing/sysfs-class-powercap [new file with mode: 0644]
Documentation/power/opp.txt
Documentation/power/powercap/powercap.txt [new file with mode: 0644]
Documentation/power/runtime_pm.txt
MAINTAINERS
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/setup.c
arch/arm/mach-davinci/Kconfig
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/cpuidle.c
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/omap-pm.h
arch/arm/mach-omap2/opp.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/generic.h
arch/arm/mach-ux500/Kconfig
arch/arm/mach-zynq/common.c
arch/blackfin/Kconfig
arch/cris/Kconfig
arch/ia64/kernel/acpi.c
arch/powerpc/kernel/smp.c
arch/powerpc/platforms/pseries/dlpar.c
arch/x86/Kconfig
arch/x86/include/asm/acpi.h
arch/x86/include/asm/mpspec.h
arch/x86/include/asm/msr.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/topology.c
arch/x86/lib/msr-smp.c
arch/x86/platform/olpc/olpc-xo15-sci.c
drivers/Kconfig
drivers/Makefile
drivers/acpi/Kconfig
drivers/acpi/Makefile
drivers/acpi/ac.c
drivers/acpi/acpi_ipmi.c
drivers/acpi/acpi_lpss.c
drivers/acpi/acpi_memhotplug.c
drivers/acpi/acpi_platform.c
drivers/acpi/acpi_processor.c
drivers/acpi/acpica/acdebug.h
drivers/acpi/acpica/acevents.h
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acnamesp.h
drivers/acpi/acpica/evgpeutil.c
drivers/acpi/acpica/evmisc.c
drivers/acpi/acpica/evregion.c
drivers/acpi/acpica/evsci.c
drivers/acpi/acpica/evxface.c
drivers/acpi/acpica/hwxface.c
drivers/acpi/acpica/nsaccess.c
drivers/acpi/acpica/nsdump.c
drivers/acpi/acpica/nsxfeval.c
drivers/acpi/acpica/tbinstal.c
drivers/acpi/acpica/tbprint.c
drivers/acpi/acpica/tbxfroot.c
drivers/acpi/acpica/utdebug.c
drivers/acpi/acpica/utglobal.c
drivers/acpi/battery.c
drivers/acpi/blacklist.c
drivers/acpi/button.c
drivers/acpi/cm_sbs.c [deleted file]
drivers/acpi/device_pm.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/fan.c
drivers/acpi/internal.h
drivers/acpi/numa.c
drivers/acpi/osl.c
drivers/acpi/proc.c
drivers/acpi/processor_core.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_idle.c
drivers/acpi/sbs.c
drivers/acpi/sysfs.c
drivers/acpi/thermal.c
drivers/acpi/utils.c
drivers/acpi/video.c
drivers/acpi/video_detect.c
drivers/base/cpu.c
drivers/base/power/main.c
drivers/base/power/opp.c
drivers/base/power/runtime.c
drivers/cpufreq/Kconfig
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/Kconfig.powerpc
drivers/cpufreq/Kconfig.x86
drivers/cpufreq/Makefile
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/arm_big_little.c
drivers/cpufreq/arm_big_little_dt.c
drivers/cpufreq/at32ap-cpufreq.c
drivers/cpufreq/blackfin-cpufreq.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq-nforce2.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/cris-artpec3-cpufreq.c
drivers/cpufreq/cris-etraxfs-cpufreq.c
drivers/cpufreq/davinci-cpufreq.c
drivers/cpufreq/dbx500-cpufreq.c
drivers/cpufreq/e_powersaver.c
drivers/cpufreq/elanfreq.c
drivers/cpufreq/exynos-cpufreq.c
drivers/cpufreq/exynos4210-cpufreq.c
drivers/cpufreq/exynos4x12-cpufreq.c
drivers/cpufreq/exynos5440-cpufreq.c
drivers/cpufreq/freq_table.c
drivers/cpufreq/gx-suspmod.c
drivers/cpufreq/highbank-cpufreq.c
drivers/cpufreq/ia64-acpi-cpufreq.c
drivers/cpufreq/imx6q-cpufreq.c
drivers/cpufreq/integrator-cpufreq.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/kirkwood-cpufreq.c
drivers/cpufreq/longhaul.c
drivers/cpufreq/longrun.c
drivers/cpufreq/loongson2_cpufreq.c
drivers/cpufreq/maple-cpufreq.c
drivers/cpufreq/omap-cpufreq.c
drivers/cpufreq/p4-clockmod.c
drivers/cpufreq/pasemi-cpufreq.c
drivers/cpufreq/pcc-cpufreq.c
drivers/cpufreq/pmac32-cpufreq.c
drivers/cpufreq/pmac64-cpufreq.c
drivers/cpufreq/powernow-k6.c
drivers/cpufreq/powernow-k7.c
drivers/cpufreq/powernow-k8.c
drivers/cpufreq/ppc-corenet-cpufreq.c
drivers/cpufreq/ppc_cbe_cpufreq.c
drivers/cpufreq/pxa2xx-cpufreq.c
drivers/cpufreq/pxa3xx-cpufreq.c
drivers/cpufreq/s3c2416-cpufreq.c
drivers/cpufreq/s3c24xx-cpufreq.c
drivers/cpufreq/s3c64xx-cpufreq.c
drivers/cpufreq/s5pv210-cpufreq.c
drivers/cpufreq/sa1100-cpufreq.c
drivers/cpufreq/sa1110-cpufreq.c
drivers/cpufreq/sc520_freq.c
drivers/cpufreq/sh-cpufreq.c
drivers/cpufreq/sparc-us2e-cpufreq.c
drivers/cpufreq/sparc-us3-cpufreq.c
drivers/cpufreq/spear-cpufreq.c
drivers/cpufreq/speedstep-centrino.c
drivers/cpufreq/speedstep-ich.c
drivers/cpufreq/speedstep-smi.c
drivers/cpufreq/tegra-cpufreq.c
drivers/cpufreq/unicore2-cpufreq.c
drivers/cpuidle/Kconfig.arm
drivers/cpuidle/Makefile
drivers/cpuidle/cpuidle-at91.c [moved from arch/arm/mach-at91/cpuidle.c with 79% similarity]
drivers/cpuidle/cpuidle-ux500.c
drivers/cpuidle/cpuidle-zynq.c
drivers/devfreq/devfreq.c
drivers/devfreq/exynos/exynos4_bus.c
drivers/devfreq/exynos/exynos5_bus.c
drivers/gpio/gpiolib-acpi.c
drivers/gpu/drm/i915/intel_acpi.c
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/hid/i2c-hid/i2c-hid.c
drivers/i2c/i2c-core.c
drivers/idle/intel_idle.c
drivers/pci/hotplug/acpi_pcihp.c
drivers/pci/pci-acpi.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/fujitsu-laptop.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel-rst.c
drivers/platform/x86/intel-smartconnect.c
drivers/platform/x86/intel_menlow.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/topstar-laptop.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/wmi.c
drivers/pnp/pnpacpi/core.c
drivers/powercap/Kconfig [new file with mode: 0644]
drivers/powercap/Makefile [new file with mode: 0644]
drivers/powercap/intel_rapl.c [new file with mode: 0644]
drivers/powercap/powercap_sys.c [new file with mode: 0644]
drivers/spi/spi.c
drivers/thermal/Kconfig
drivers/video/backlight/backlight.c
include/acpi/acexcep.h
include/acpi/acpi_bus.h
include/acpi/acpixf.h
include/acpi/actypes.h
include/acpi/platform/aclinux.h
include/acpi/processor.h
include/linux/acpi.h
include/linux/backlight.h
include/linux/bitops.h
include/linux/cpu.h
include/linux/cpufreq.h
include/linux/devfreq.h
include/linux/opp.h [deleted file]
include/linux/pm_opp.h [new file with mode: 0644]
include/linux/powercap.h [new file with mode: 0644]
kernel/power/Kconfig
kernel/power/qos.c
kernel/power/user.c

diff --git a/Documentation/ABI/testing/sysfs-class-powercap b/Documentation/ABI/testing/sysfs-class-powercap
new file mode 100644 (file)
index 0000000..db3b3ff
--- /dev/null
@@ -0,0 +1,152 @@
+What:          /sys/class/powercap/
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               The powercap/ class sub directory belongs to the power cap
+               subsystem. Refer to
+               Documentation/power/powercap/powercap.txt for details.
+
+What:          /sys/class/powercap/<control type>
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               A <control type> is a unique name under /sys/class/powercap.
+               Here <control type> determines how the power is going to be
+               controlled. A <control type> can contain multiple power zones.
+
+What:          /sys/class/powercap/<control type>/enabled
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               This allows to enable/disable power capping for a "control type".
+               This status affects every power zone using this "control_type.
+
+What:          /sys/class/powercap/<control type>/<power zone>
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               A power zone is a single or a collection of devices, which can
+               be independently monitored and controlled. A power zone sysfs
+               entry is qualified with the name of the <control type>.
+               E.g. intel-rapl:0:1:1.
+
+What:          /sys/class/powercap/<control type>/<power zone>/<child power zone>
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Power zones may be organized in a hierarchy in which child
+               power zones provide monitoring and control for a subset of
+               devices under the parent. For example, if there is a parent
+               power zone for a whole CPU package, each CPU core in it can
+               be a child power zone.
+
+What:          /sys/class/powercap/.../<power zone>/name
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Specifies the name of this power zone.
+
+What:          /sys/class/powercap/.../<power zone>/energy_uj
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Current energy counter in micro-joules. Write "0" to reset.
+               If the counter can not be reset, then this attribute is
+               read-only.
+
+What:          /sys/class/powercap/.../<power zone>/max_energy_range_uj
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Range of the above energy counter in micro-joules.
+
+
+What:          /sys/class/powercap/.../<power zone>/power_uw
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Current power in micro-watts.
+
+What:          /sys/class/powercap/.../<power zone>/max_power_range_uw
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Range of the above power value in micro-watts.
+
+What:          /sys/class/powercap/.../<power zone>/constraint_X_name
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Each power zone can define one or more constraints. Each
+               constraint can have an optional name. Here "X" can have values
+               from 0 to max integer.
+
+What:          /sys/class/powercap/.../<power zone>/constraint_X_power_limit_uw
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Power limit in micro-watts should be applicable for
+               the time window specified by "constraint_X_time_window_us".
+               Here "X" can have values from 0 to max integer.
+
+What:          /sys/class/powercap/.../<power zone>/constraint_X_time_window_us
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Time window in micro seconds. This is used along with
+               constraint_X_power_limit_uw to define a power constraint.
+               Here "X" can have values from 0 to max integer.
+
+
+What:          /sys/class/powercap/<control type>/.../constraint_X_max_power_uw
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Maximum allowed power in micro watts for this constraint.
+               Here "X" can have values from 0 to max integer.
+
+What:          /sys/class/powercap/<control type>/.../constraint_X_min_power_uw
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Minimum allowed power in micro watts for this constraint.
+               Here "X" can have values from 0 to max integer.
+
+What:          /sys/class/powercap/.../<power zone>/constraint_X_max_time_window_us
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Maximum allowed time window in micro seconds for this
+               constraint. Here "X" can have values from 0 to max integer.
+
+What:          /sys/class/powercap/.../<power zone>/constraint_X_min_time_window_us
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description:
+               Minimum allowed time window in micro seconds for this
+               constraint. Here "X" can have values from 0 to max integer.
+
+What:          /sys/class/powercap/.../<power zone>/enabled
+Date:          September 2013
+KernelVersion: 3.13
+Contact:       linux-pm@vger.kernel.org
+Description
+               This allows to enable/disable power capping at power zone level.
+               This applies to current power zone and its children.
index 425c51d56aefb8b991b3d97b5d3f01564f9baaf6..b8a907dc01697890747ead021b836b4c60c24ae0 100644 (file)
@@ -42,7 +42,7 @@ We can represent these as three OPPs as the following {Hz, uV} tuples:
 
 OPP library provides a set of helper functions to organize and query the OPP
 information. The library is located in drivers/base/power/opp.c and the header
-is located in include/linux/opp.h. OPP library can be enabled by enabling
+is located in include/linux/pm_opp.h. OPP library can be enabled by enabling
 CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on
 CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to
 optionally boot at a certain OPP without needing cpufreq.
@@ -71,14 +71,14 @@ operations until that OPP could be re-enabled if possible.
 
 OPP library facilitates this concept in it's implementation. The following
 operational functions operate only on available opps:
-opp_find_freq_{ceil, floor}, opp_get_voltage, opp_get_freq, opp_get_opp_count
-and opp_init_cpufreq_table
+opp_find_freq_{ceil, floor}, dev_pm_opp_get_voltage, dev_pm_opp_get_freq, dev_pm_opp_get_opp_count
+and dev_pm_opp_init_cpufreq_table
 
-opp_find_freq_exact is meant to be used to find the opp pointer which can then
-be used for opp_enable/disable functions to make an opp available as required.
+dev_pm_opp_find_freq_exact is meant to be used to find the opp pointer which can then
+be used for dev_pm_opp_enable/disable functions to make an opp available as required.
 
 WARNING: Users of OPP library should refresh their availability count using
-get_opp_count if opp_enable/disable functions are invoked for a device, the
+get_opp_count if dev_pm_opp_enable/disable functions are invoked for a device, the
 exact mechanism to trigger these or the notification mechanism to other
 dependent subsystems such as cpufreq are left to the discretion of the SoC
 specific framework which uses the OPP library. Similar care needs to be taken
@@ -96,24 +96,24 @@ using RCU read locks. The opp_find_freq_{exact,ceil,floor},
 opp_get_{voltage, freq, opp_count} fall into this category.
 
 opp_{add,enable,disable} are updaters which use mutex and implement it's own
-RCU locking mechanisms. opp_init_cpufreq_table acts as an updater and uses
+RCU locking mechanisms. dev_pm_opp_init_cpufreq_table acts as an updater and uses
 mutex to implment RCU updater strategy. These functions should *NOT* be called
 under RCU locks and other contexts that prevent blocking functions in RCU or
 mutex operations from working.
 
 2. Initial OPP List Registration
 ================================
-The SoC implementation calls opp_add function iteratively to add OPPs per
+The SoC implementation calls dev_pm_opp_add function iteratively to add OPPs per
 device. It is expected that the SoC framework will register the OPP entries
 optimally- typical numbers range to be less than 5. The list generated by
 registering the OPPs is maintained by OPP library throughout the device
 operation. The SoC framework can subsequently control the availability of the
-OPPs dynamically using the opp_enable / disable functions.
+OPPs dynamically using the dev_pm_opp_enable / disable functions.
 
-opp_add - Add a new OPP for a specific domain represented by the device pointer.
+dev_pm_opp_add - Add a new OPP for a specific domain represented by the device pointer.
        The OPP is defined using the frequency and voltage. Once added, the OPP
        is assumed to be available and control of it's availability can be done
-       with the opp_enable/disable functions. OPP library internally stores
+       with the dev_pm_opp_enable/disable functions. OPP library internally stores
        and manages this information in the opp struct. This function may be
        used by SoC framework to define a optimal list as per the demands of
        SoC usage environment.
@@ -124,7 +124,7 @@ opp_add - Add a new OPP for a specific domain represented by the device pointer.
         soc_pm_init()
         {
                /* Do things */
-               r = opp_add(mpu_dev, 1000000, 900000);
+               r = dev_pm_opp_add(mpu_dev, 1000000, 900000);
                if (!r) {
                        pr_err("%s: unable to register mpu opp(%d)\n", r);
                        goto no_cpufreq;
@@ -143,44 +143,44 @@ functions return the matching pointer representing the opp if a match is
 found, else returns error. These errors are expected to be handled by standard
 error checks such as IS_ERR() and appropriate actions taken by the caller.
 
-opp_find_freq_exact - Search for an OPP based on an *exact* frequency and
+dev_pm_opp_find_freq_exact - Search for an OPP based on an *exact* frequency and
        availability. This function is especially useful to enable an OPP which
        is not available by default.
        Example: In a case when SoC framework detects a situation where a
        higher frequency could be made available, it can use this function to
-       find the OPP prior to call the opp_enable to actually make it available.
+       find the OPP prior to call the dev_pm_opp_enable to actually make it available.
         rcu_read_lock();
-        opp = opp_find_freq_exact(dev, 1000000000, false);
+        opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false);
         rcu_read_unlock();
         /* dont operate on the pointer.. just do a sanity check.. */
         if (IS_ERR(opp)) {
                pr_err("frequency not disabled!\n");
                /* trigger appropriate actions.. */
         } else {
-               opp_enable(dev,1000000000);
+               dev_pm_opp_enable(dev,1000000000);
         }
 
        NOTE: This is the only search function that operates on OPPs which are
        not available.
 
-opp_find_freq_floor - Search for an available OPP which is *at most* the
+dev_pm_opp_find_freq_floor - Search for an available OPP which is *at most* the
        provided frequency. This function is useful while searching for a lesser
        match OR operating on OPP information in the order of decreasing
        frequency.
        Example: To find the highest opp for a device:
         freq = ULONG_MAX;
         rcu_read_lock();
-        opp_find_freq_floor(dev, &freq);
+        dev_pm_opp_find_freq_floor(dev, &freq);
         rcu_read_unlock();
 
-opp_find_freq_ceil - Search for an available OPP which is *at least* the
+dev_pm_opp_find_freq_ceil - Search for an available OPP which is *at least* the
        provided frequency. This function is useful while searching for a
        higher match OR operating on OPP information in the order of increasing
        frequency.
        Example 1: To find the lowest opp for a device:
         freq = 0;
         rcu_read_lock();
-        opp_find_freq_ceil(dev, &freq);
+        dev_pm_opp_find_freq_ceil(dev, &freq);
         rcu_read_unlock();
        Example 2: A simplified implementation of a SoC cpufreq_driver->target:
         soc_cpufreq_target(..)
@@ -188,7 +188,7 @@ opp_find_freq_ceil - Search for an available OPP which is *at least* the
                /* Do stuff like policy checks etc. */
                /* Find the best frequency match for the req */
                rcu_read_lock();
-               opp = opp_find_freq_ceil(dev, &freq);
+               opp = dev_pm_opp_find_freq_ceil(dev, &freq);
                rcu_read_unlock();
                if (!IS_ERR(opp))
                        soc_switch_to_freq_voltage(freq);
@@ -208,34 +208,34 @@ as thermal considerations (e.g. don't use OPPx until the temperature drops).
 
 WARNING: Do not use these functions in interrupt context.
 
-opp_enable - Make a OPP available for operation.
+dev_pm_opp_enable - Make a OPP available for operation.
        Example: Lets say that 1GHz OPP is to be made available only if the
        SoC temperature is lower than a certain threshold. The SoC framework
        implementation might choose to do something as follows:
         if (cur_temp < temp_low_thresh) {
                /* Enable 1GHz if it was disabled */
                rcu_read_lock();
-               opp = opp_find_freq_exact(dev, 1000000000, false);
+               opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false);
                rcu_read_unlock();
                /* just error check */
                if (!IS_ERR(opp))
-                       ret = opp_enable(dev, 1000000000);
+                       ret = dev_pm_opp_enable(dev, 1000000000);
                else
                        goto try_something_else;
         }
 
-opp_disable - Make an OPP to be not available for operation
+dev_pm_opp_disable - Make an OPP to be not available for operation
        Example: Lets say that 1GHz OPP is to be disabled if the temperature
        exceeds a threshold value. The SoC framework implementation might
        choose to do something as follows:
         if (cur_temp > temp_high_thresh) {
                /* Disable 1GHz if it was enabled */
                rcu_read_lock();
-               opp = opp_find_freq_exact(dev, 1000000000, true);
+               opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true);
                rcu_read_unlock();
                /* just error check */
                if (!IS_ERR(opp))
-                       ret = opp_disable(dev, 1000000000);
+                       ret = dev_pm_opp_disable(dev, 1000000000);
                else
                        goto try_something_else;
         }
@@ -247,7 +247,7 @@ information from the OPP structure is necessary. Once an OPP pointer is
 retrieved using the search functions, the following functions can be used by SoC
 framework to retrieve the information represented inside the OPP layer.
 
-opp_get_voltage - Retrieve the voltage represented by the opp pointer.
+dev_pm_opp_get_voltage - Retrieve the voltage represented by the opp pointer.
        Example: At a cpufreq transition to a different frequency, SoC
        framework requires to set the voltage represented by the OPP using
        the regulator framework to the Power Management chip providing the
@@ -256,15 +256,15 @@ opp_get_voltage - Retrieve the voltage represented by the opp pointer.
         {
                /* do things */
                rcu_read_lock();
-               opp = opp_find_freq_ceil(dev, &freq);
-               v = opp_get_voltage(opp);
+               opp = dev_pm_opp_find_freq_ceil(dev, &freq);
+               v = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
                if (v)
                        regulator_set_voltage(.., v);
                /* do other things */
         }
 
-opp_get_freq - Retrieve the freq represented by the opp pointer.
+dev_pm_opp_get_freq - Retrieve the freq represented by the opp pointer.
        Example: Lets say the SoC framework uses a couple of helper functions
        we could pass opp pointers instead of doing additional parameters to
        handle quiet a bit of data parameters.
@@ -273,8 +273,8 @@ opp_get_freq - Retrieve the freq represented by the opp pointer.
                /* do things.. */
                 max_freq = ULONG_MAX;
                 rcu_read_lock();
-                max_opp = opp_find_freq_floor(dev,&max_freq);
-                requested_opp = opp_find_freq_ceil(dev,&freq);
+                max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq);
+                requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq);
                 if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
                        r = soc_test_validity(max_opp, requested_opp);
                 rcu_read_unlock();
@@ -282,25 +282,25 @@ opp_get_freq - Retrieve the freq represented by the opp pointer.
         }
         soc_test_validity(..)
         {
-                if(opp_get_voltage(max_opp) < opp_get_voltage(requested_opp))
+                if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp))
                         return -EINVAL;
-                if(opp_get_freq(max_opp) < opp_get_freq(requested_opp))
+                if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp))
                         return -EINVAL;
                /* do things.. */
         }
 
-opp_get_opp_count - Retrieve the number of available opps for a device
+dev_pm_opp_get_opp_count - Retrieve the number of available opps for a device
        Example: Lets say a co-processor in the SoC needs to know the available
        frequencies in a table, the main processor can notify as following:
         soc_notify_coproc_available_frequencies()
         {
                /* Do things */
                rcu_read_lock();
-               num_available = opp_get_opp_count(dev);
+               num_available = dev_pm_opp_get_opp_count(dev);
                speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL);
                /* populate the table in increasing order */
                freq = 0;
-               while (!IS_ERR(opp = opp_find_freq_ceil(dev, &freq))) {
+               while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq))) {
                        speeds[i] = freq;
                        freq++;
                        i++;
@@ -313,7 +313,7 @@ opp_get_opp_count - Retrieve the number of available opps for a device
 
 6. Cpufreq Table Generation
 ===========================
-opp_init_cpufreq_table - cpufreq framework typically is initialized with
+dev_pm_opp_init_cpufreq_table - cpufreq framework typically is initialized with
        cpufreq_frequency_table_cpuinfo which is provided with the list of
        frequencies that are available for operation. This function provides
        a ready to use conversion routine to translate the OPP layer's internal
@@ -326,7 +326,7 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with
         soc_pm_init()
         {
                /* Do things */
-               r = opp_init_cpufreq_table(dev, &freq_table);
+               r = dev_pm_opp_init_cpufreq_table(dev, &freq_table);
                if (!r)
                        cpufreq_frequency_table_cpuinfo(policy, freq_table);
                /* Do other things */
@@ -336,7 +336,7 @@ opp_init_cpufreq_table - cpufreq framework typically is initialized with
        addition to CONFIG_PM as power management feature is required to
        dynamically scale voltage and frequency in a system.
 
-opp_free_cpufreq_table - Free up the table allocated by opp_init_cpufreq_table
+dev_pm_opp_free_cpufreq_table - Free up the table allocated by dev_pm_opp_init_cpufreq_table
 
 7. Data Structures
 ==================
@@ -358,16 +358,16 @@ accessed by various functions as described above. However, the structures
 representing the actual OPPs and domains are internal to the OPP library itself
 to allow for suitable abstraction reusable across systems.
 
-struct opp - The internal data structure of OPP library which is used to
+struct dev_pm_opp - The internal data structure of OPP library which is used to
        represent an OPP. In addition to the freq, voltage, availability
        information, it also contains internal book keeping information required
        for the OPP library to operate on.  Pointer to this structure is
        provided back to the users such as SoC framework to be used as a
        identifier for OPP in the interactions with OPP layer.
 
-       WARNING: The struct opp pointer should not be parsed or modified by the
-       users. The defaults of for an instance is populated by opp_add, but the
-       availability of the OPP can be modified by opp_enable/disable functions.
+       WARNING: The struct dev_pm_opp pointer should not be parsed or modified by the
+       users. The defaults of for an instance is populated by dev_pm_opp_add, but the
+       availability of the OPP can be modified by dev_pm_opp_enable/disable functions.
 
 struct device - This is used to identify a domain to the OPP layer. The
        nature of the device and it's implementation is left to the user of
@@ -377,19 +377,19 @@ Overall, in a simplistic view, the data structure operations is represented as
 following:
 
 Initialization / modification:
-            +-----+        /- opp_enable
-opp_add --> | opp | <-------
-  |         +-----+        \- opp_disable
+            +-----+        /- dev_pm_opp_enable
+dev_pm_opp_add --> | opp | <-------
+  |         +-----+        \- dev_pm_opp_disable
   \-------> domain_info(device)
 
 Search functions:
-             /-- opp_find_freq_ceil  ---\   +-----+
-domain_info<---- opp_find_freq_exact -----> | opp |
-             \-- opp_find_freq_floor ---/   +-----+
+             /-- dev_pm_opp_find_freq_ceil  ---\   +-----+
+domain_info<---- dev_pm_opp_find_freq_exact -----> | opp |
+             \-- dev_pm_opp_find_freq_floor ---/   +-----+
 
 Retrieval functions:
-+-----+     /- opp_get_voltage
++-----+     /- dev_pm_opp_get_voltage
 | opp | <---
-+-----+     \- opp_get_freq
++-----+     \- dev_pm_opp_get_freq
 
-domain_info <- opp_get_opp_count
+domain_info <- dev_pm_opp_get_opp_count
diff --git a/Documentation/power/powercap/powercap.txt b/Documentation/power/powercap/powercap.txt
new file mode 100644 (file)
index 0000000..1e6ef16
--- /dev/null
@@ -0,0 +1,236 @@
+Power Capping Framework
+==================================
+
+The power capping framework provides a consistent interface between the kernel
+and the user space that allows power capping drivers to expose the settings to
+user space in a uniform way.
+
+Terminology
+=========================
+The framework exposes power capping devices to user space via sysfs in the
+form of a tree of objects. The objects at the root level of the tree represent
+'control types', which correspond to different methods of power capping.  For
+example, the intel-rapl control type represents the Intel "Running Average
+Power Limit" (RAPL) technology, whereas the 'idle-injection' control type
+corresponds to the use of idle injection for controlling power.
+
+Power zones represent different parts of the system, which can be controlled and
+monitored using the power capping method determined by the control type the
+given zone belongs to. They each contain attributes for monitoring power, as
+well as controls represented in the form of power constraints.  If the parts of
+the system represented by different power zones are hierarchical (that is, one
+bigger part consists of multiple smaller parts that each have their own power
+controls), those power zones may also be organized in a hierarchy with one
+parent power zone containing multiple subzones and so on to reflect the power
+control topology of the system.  In that case, it is possible to apply power
+capping to a set of devices together using the parent power zone and if more
+fine grained control is required, it can be applied through the subzones.
+
+
+Example sysfs interface tree:
+
+/sys/devices/virtual/powercap
+??? intel-rapl
+    ??? intel-rapl:0
+    ?Ā Ā  ??? constraint_0_name
+    ?Ā Ā  ??? constraint_0_power_limit_uw
+    ?Ā Ā  ??? constraint_0_time_window_us
+    ?Ā Ā  ??? constraint_1_name
+    ?Ā Ā  ??? constraint_1_power_limit_uw
+    ?Ā Ā  ??? constraint_1_time_window_us
+    ?Ā Ā  ??? device -> ../../intel-rapl
+    ?Ā Ā  ??? energy_uj
+    ?Ā Ā  ??? intel-rapl:0:0
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_name
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_power_limit_uw
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_time_window_us
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_name
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_power_limit_uw
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_time_window_us
+    ?Ā Ā  ?Ā Ā  ??? device -> ../../intel-rapl:0
+    ?Ā Ā  ?Ā Ā  ??? energy_uj
+    ?Ā Ā  ?Ā Ā  ??? max_energy_range_uj
+    ?Ā Ā  ?Ā Ā  ??? name
+    ?Ā Ā  ?Ā Ā  ??? enabled
+    ?Ā Ā  ?Ā Ā  ??? power
+    ?Ā Ā  ?Ā Ā  ?Ā Ā  ??? async
+    ?Ā Ā  ?Ā Ā  ?Ā Ā  []
+    ?Ā Ā  ?Ā Ā  ??? subsystem -> ../../../../../../class/power_cap
+    ?Ā Ā  ?Ā Ā  ??? uevent
+    ?Ā Ā  ??? intel-rapl:0:1
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_name
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_power_limit_uw
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_time_window_us
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_name
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_power_limit_uw
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_time_window_us
+    ?Ā Ā  ?Ā Ā  ??? device -> ../../intel-rapl:0
+    ?Ā Ā  ?Ā Ā  ??? energy_uj
+    ?Ā Ā  ?Ā Ā  ??? max_energy_range_uj
+    ?Ā Ā  ?Ā Ā  ??? name
+    ?Ā Ā  ?Ā Ā  ??? enabled
+    ?Ā Ā  ?Ā Ā  ??? power
+    ?Ā Ā  ?Ā Ā  ?Ā Ā  ??? async
+    ?Ā Ā  ?Ā Ā  ?Ā Ā  []
+    ?Ā Ā  ?Ā Ā  ??? subsystem -> ../../../../../../class/power_cap
+    ?Ā Ā  ?Ā Ā  ??? uevent
+    ?Ā Ā  ??? max_energy_range_uj
+    ?Ā Ā  ??? max_power_range_uw
+    ?Ā Ā  ??? name
+    ?Ā Ā  ??? enabled
+    ?Ā Ā  ??? power
+    ?Ā Ā  ?Ā Ā  ??? async
+    ?Ā Ā  ?Ā Ā  []
+    ?Ā Ā  ??? subsystem -> ../../../../../class/power_cap
+    ?Ā Ā  ??? enabled
+    ?Ā Ā  ??? uevent
+    ??? intel-rapl:1
+    ?Ā Ā  ??? constraint_0_name
+    ?Ā Ā  ??? constraint_0_power_limit_uw
+    ?Ā Ā  ??? constraint_0_time_window_us
+    ?Ā Ā  ??? constraint_1_name
+    ?Ā Ā  ??? constraint_1_power_limit_uw
+    ?Ā Ā  ??? constraint_1_time_window_us
+    ?Ā Ā  ??? device -> ../../intel-rapl
+    ?Ā Ā  ??? energy_uj
+    ?Ā Ā  ??? intel-rapl:1:0
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_name
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_power_limit_uw
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_time_window_us
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_name
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_power_limit_uw
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_time_window_us
+    ?Ā Ā  ?Ā Ā  ??? device -> ../../intel-rapl:1
+    ?Ā Ā  ?Ā Ā  ??? energy_uj
+    ?Ā Ā  ?Ā Ā  ??? max_energy_range_uj
+    ?Ā Ā  ?Ā Ā  ??? name
+    ?Ā Ā  ?Ā Ā  ??? enabled
+    ?Ā Ā  ?Ā Ā  ??? power
+    ?Ā Ā  ?Ā Ā  ?Ā Ā  ??? async
+    ?Ā Ā  ?Ā Ā  ?Ā Ā  []
+    ?Ā Ā  ?Ā Ā  ??? subsystem -> ../../../../../../class/power_cap
+    ?Ā Ā  ?Ā Ā  ??? uevent
+    ?Ā Ā  ??? intel-rapl:1:1
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_name
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_power_limit_uw
+    ?Ā Ā  ?Ā Ā  ??? constraint_0_time_window_us
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_name
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_power_limit_uw
+    ?Ā Ā  ?Ā Ā  ??? constraint_1_time_window_us
+    ?Ā Ā  ?Ā Ā  ??? device -> ../../intel-rapl:1
+    ?Ā Ā  ?Ā Ā  ??? energy_uj
+    ?Ā Ā  ?Ā Ā  ??? max_energy_range_uj
+    ?Ā Ā  ?Ā Ā  ??? name
+    ?Ā Ā  ?Ā Ā  ??? enabled
+    ?Ā Ā  ?Ā Ā  ??? power
+    ?Ā Ā  ?Ā Ā  ?Ā Ā  ??? async
+    ?Ā Ā  ?Ā Ā  ?Ā Ā  []
+    ?Ā Ā  ?Ā Ā  ??? subsystem -> ../../../../../../class/power_cap
+    ?Ā Ā  ?Ā Ā  ??? uevent
+    ?Ā Ā  ??? max_energy_range_uj
+    ?Ā Ā  ??? max_power_range_uw
+    ?Ā Ā  ??? name
+    ?Ā Ā  ??? enabled
+    ?Ā Ā  ??? power
+    ?Ā Ā  ?Ā Ā  ??? async
+    ?Ā Ā  ?Ā Ā  []
+    ?Ā Ā  ??? subsystem -> ../../../../../class/power_cap
+    ?Ā Ā  ??? uevent
+    ??? power
+    ?Ā Ā  ??? async
+    ?Ā Ā  []
+    ??? subsystem -> ../../../../class/power_cap
+    ??? enabled
+    ??? uevent
+
+The above example illustrates a case in which the Intel RAPL technology,
+available in IntelĀ® IA-64 and IA-32 Processor Architectures, is used. There is one
+control type called intel-rapl which contains two power zones, intel-rapl:0 and
+intel-rapl:1, representing CPU packages.  Each of these power zones contains
+two subzones, intel-rapl:j:0 and intel-rapl:j:1 (j = 0, 1), representing the
+"core" and the "uncore" parts of the given CPU package, respectively.  All of
+the zones and subzones contain energy monitoring attributes (energy_uj,
+max_energy_range_uj) and constraint attributes (constraint_*) allowing controls
+to be applied (the constraints in the 'package' power zones apply to the whole
+CPU packages and the subzone constraints only apply to the respective parts of
+the given package individually). Since Intel RAPL doesn't provide instantaneous
+power value, there is no power_uw attribute.
+
+In addition to that, each power zone contains a name attribute, allowing the
+part of the system represented by that zone to be identified.
+For example:
+
+cat /sys/class/power_cap/intel-rapl/intel-rapl:0/name
+package-0
+
+The Intel RAPL technology allows two constraints, short term and long term,
+with two different time windows to be applied to each power zone.  Thus for
+each zone there are 2 attributes representing the constraint names, 2 power
+limits and 2 attributes representing the sizes of the time windows. Such that,
+constraint_j_* attributes correspond to the jth constraint (j = 0,1).
+
+For example:
+       constraint_0_name
+       constraint_0_power_limit_uw
+       constraint_0_time_window_us
+       constraint_1_name
+       constraint_1_power_limit_uw
+       constraint_1_time_window_us
+
+Power Zone Attributes
+=================================
+Monitoring attributes
+----------------------
+
+energy_uj (rw): Current energy counter in micro joules. Write "0" to reset.
+If the counter can not be reset, then this attribute is read only.
+
+max_energy_range_uj (ro): Range of the above energy counter in micro-joules.
+
+power_uw (ro): Current power in micro watts.
+
+max_power_range_uw (ro): Range of the above power value in micro-watts.
+
+name (ro): Name of this power zone.
+
+It is possible that some domains have both power ranges and energy counter ranges;
+however, only one is mandatory.
+
+Constraints
+----------------
+constraint_X_power_limit_uw (rw): Power limit in micro watts, which should be
+applicable for the time window specified by "constraint_X_time_window_us".
+
+constraint_X_time_window_us (rw): Time window in micro seconds.
+
+constraint_X_name (ro): An optional name of the constraint
+
+constraint_X_max_power_uw(ro): Maximum allowed power in micro watts.
+
+constraint_X_min_power_uw(ro): Minimum allowed power in micro watts.
+
+constraint_X_max_time_window_us(ro): Maximum allowed time window in micro seconds.
+
+constraint_X_min_time_window_us(ro): Minimum allowed time window in micro seconds.
+
+Except power_limit_uw and time_window_us other fields are optional.
+
+Common zone and control type attributes
+----------------------------------------
+enabled (rw): Enable/Disable controls at zone level or for all zones using
+a control type.
+
+Power Cap Client Driver Interface
+==================================
+The API summary:
+
+Call powercap_register_control_type() to register control type object.
+Call powercap_register_zone() to register a power zone (under a given
+control type), either as a top-level power zone or as a subzone of another
+power zone registered earlier.
+The number of constraints in a power zone and the corresponding callbacks have
+to be defined prior to calling powercap_register_zone() to register that zone.
+
+To Free a power zone call powercap_unregister_zone().
+To free a control type object call powercap_unregister_control_type().
+Detailed API can be generated using kernel-doc on include/linux/powercap.h.
index 71d8fe4e75d3e5301e25037a28d91600d633dba7..0f54333b0ff2990ce090f88087e17417a894b46c 100644 (file)
@@ -145,11 +145,13 @@ The action performed by the idle callback is totally dependent on the subsystem
 if the device can be suspended (i.e. if all of the conditions necessary for
 suspending the device are satisfied) and to queue up a suspend request for the
 device in that case.  If there is no idle callback, or if the callback returns
-0, then the PM core will attempt to carry out a runtime suspend of the device;
-in essence, it will call pm_runtime_suspend() directly.  To prevent this (for
-example, if the callback routine has started a delayed suspend), the routine
-should return a non-zero value.  Negative error return codes are ignored by the
-PM core.
+0, then the PM core will attempt to carry out a runtime suspend of the device,
+also respecting devices configured for autosuspend.  In essence this means a
+call to pm_runtime_autosuspend() (do note that drivers needs to update the
+device last busy mark, pm_runtime_mark_last_busy(), to control the delay under
+this circumstance).  To prevent this (for example, if the callback routine has
+started a delayed suspend), the routine must return a non-zero value.  Negative
+error return codes are ignored by the PM core.
 
 The helper functions provided by the PM core, described in Section 4, guarantee
 that the following constraints are met with respect to runtime PM callbacks for
@@ -308,7 +310,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
     - execute the subsystem-level idle callback for the device; returns an
       error code on failure, where -EINPROGRESS means that ->runtime_idle() is
       already being executed; if there is no callback or the callback returns 0
-      then run pm_runtime_suspend(dev) and return its result
+      then run pm_runtime_autosuspend(dev) and return its result
 
   int pm_runtime_suspend(struct device *dev);
     - execute the subsystem-level suspend callback for the device; returns 0 on
index a7c34ef3509d5f199511e0547ddba1e88b9a3be9..dcf2f661a727022508e5ada921e3917b7347a125 100644 (file)
@@ -253,6 +253,20 @@ F: drivers/pci/*acpi*
 F:     drivers/pci/*/*acpi*
 F:     drivers/pci/*/*/*acpi*
 
+ACPI COMPONENT ARCHITECTURE (ACPICA)
+M:     Robert Moore <robert.moore@intel.com>
+M:     Lv Zheng <lv.zheng@intel.com>
+M:     Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+L:     linux-acpi@vger.kernel.org
+L:     devel@acpica.org
+W:     https://acpica.org/
+W:     https://github.com/acpica/acpica/
+Q:     https://patchwork.kernel.org/project/linux-acpi/list/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
+S:     Supported
+F:     drivers/acpi/acpica/
+F:     include/acpi/
+
 ACPI FAN DRIVER
 M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
index 3b0a9538093c168cb4cd80f4ff559b0458d0dfb3..c1b737097c9543faf67c4ed78f2617e3add0606f 100644 (file)
@@ -98,7 +98,6 @@ obj-y                         += leds.o
 # Power Management
 obj-$(CONFIG_PM)               += pm.o
 obj-$(CONFIG_AT91_SLOW_CLOCK)  += pm_slowclock.o
-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
 
 ifeq ($(CONFIG_PM_DEBUG),y)
 CFLAGS_pm.o += -DDEBUG
index 4aad93d54d6f059cc275ac819d7c55df196df4b1..25805f2f6010f3d7b98035f9c8e3b1e09524a4e3 100644 (file)
@@ -27,6 +27,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -327,6 +328,7 @@ static void __init at91rm9200_ioremap_registers(void)
 {
        at91rm9200_ioremap_st(AT91RM9200_BASE_ST);
        at91_ioremap_ramc(0, AT91RM9200_BASE_MC, 256);
+       at91_pm_set_standby(at91rm9200_standby);
 }
 
 static void __init at91rm9200_initialize(void)
index 5de6074b4f4f3681d308cfb34a8554a05550b2f2..f8629a3fa2452791b6215c19f77124813e1d3f5f 100644 (file)
@@ -28,6 +28,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -342,6 +343,7 @@ static void __init at91sam9260_ioremap_registers(void)
        at91sam926x_ioremap_pit(AT91SAM9260_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9260_BASE_SMC);
        at91_ioremap_matrix(AT91SAM9260_BASE_MATRIX);
+       at91_pm_set_standby(at91sam9_sdram_standby);
 }
 
 static void __init at91sam9260_initialize(void)
index 0e0793241ab7e1938dc4ec3fd961557344342369..1f3867a17a289beee4bb1a44ae64ca3bc96b044d 100644 (file)
@@ -27,6 +27,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -284,6 +285,7 @@ static void __init at91sam9261_ioremap_registers(void)
        at91sam926x_ioremap_pit(AT91SAM9261_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9261_BASE_SMC);
        at91_ioremap_matrix(AT91SAM9261_BASE_MATRIX);
+       at91_pm_set_standby(at91sam9_sdram_standby);
 }
 
 static void __init at91sam9261_initialize(void)
index 6ce7d18508934a428ea2ac94ab51162b683b43d1..90d455d294a1814e7e72722b5614b4d15548c298 100644 (file)
@@ -26,6 +26,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -321,6 +322,7 @@ static void __init at91sam9263_ioremap_registers(void)
        at91sam9_ioremap_smc(0, AT91SAM9263_BASE_SMC0);
        at91sam9_ioremap_smc(1, AT91SAM9263_BASE_SMC1);
        at91_ioremap_matrix(AT91SAM9263_BASE_MATRIX);
+       at91_pm_set_standby(at91sam9_sdram_standby);
 }
 
 static void __init at91sam9263_initialize(void)
index 474ee04d24b93729bdf32e2e4d64a7db0ea9bed8..e9bf0b8f40eb745d317e2d1d50c500eea1491aa4 100644 (file)
@@ -26,6 +26,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -370,6 +371,7 @@ static void __init at91sam9g45_ioremap_registers(void)
        at91sam926x_ioremap_pit(AT91SAM9G45_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9G45_BASE_SMC);
        at91_ioremap_matrix(AT91SAM9G45_BASE_MATRIX);
+       at91_pm_set_standby(at91_ddr_standby);
 }
 
 static void __init at91sam9g45_initialize(void)
index d4ec0d9a9872660e22f2e3c95fc2e8c154cf38e6..88995af09c043abf6198124d1c651d60ac03b0ff 100644 (file)
@@ -27,6 +27,7 @@
 #include "generic.h"
 #include "clock.h"
 #include "sam9_smc.h"
+#include "pm.h"
 
 /* --------------------------------------------------------------------
  *  Clocks
@@ -287,6 +288,7 @@ static void __init at91sam9rl_ioremap_registers(void)
        at91sam926x_ioremap_pit(AT91SAM9RL_BASE_PIT);
        at91sam9_ioremap_smc(0, AT91SAM9RL_BASE_SMC);
        at91_ioremap_matrix(AT91SAM9RL_BASE_MATRIX);
+       at91_pm_set_standby(at91sam9_sdram_standby);
 }
 
 static void __init at91sam9rl_initialize(void)
index 15afb5d9271f2237e3c61acd920b2f9c6d6e0a78..9986542e8060119fcad4eee37564fdf3d8d164a6 100644 (file)
@@ -39,6 +39,8 @@
 #include "at91_rstc.h"
 #include "at91_shdwc.h"
 
+static void (*at91_pm_standby)(void);
+
 static void __init show_reset_status(void)
 {
        static char reset[] __initdata = "reset";
@@ -266,14 +268,8 @@ static int at91_pm_enter(suspend_state_t state)
                         * For ARM 926 based chips, this requirement is weaker
                         * as at91sam9 can access a RAM in self-refresh mode.
                         */
-                       if (cpu_is_at91rm9200())
-                               at91rm9200_standby();
-                       else if (cpu_is_at91sam9g45())
-                               at91sam9g45_standby();
-                       else if (cpu_is_at91sam9263())
-                               at91sam9263_standby();
-                       else
-                               at91sam9_standby();
+                       if (at91_pm_standby)
+                               at91_pm_standby();
                        break;
 
                case PM_SUSPEND_ON:
@@ -314,6 +310,18 @@ static const struct platform_suspend_ops at91_pm_ops = {
        .end    = at91_pm_end,
 };
 
+static struct platform_device at91_cpuidle_device = {
+       .name = "cpuidle-at91",
+};
+
+void at91_pm_set_standby(void (*at91_standby)(void))
+{
+       if (at91_standby) {
+               at91_cpuidle_device.dev.platform_data = at91_standby;
+               at91_pm_standby = at91_standby;
+       }
+}
+
 static int __init at91_pm_init(void)
 {
 #ifdef CONFIG_AT91_SLOW_CLOCK
@@ -325,6 +333,9 @@ static int __init at91_pm_init(void)
        /* AT91RM9200 SDRAM low-power mode cannot be used with self-refresh. */
        if (cpu_is_at91rm9200())
                at91_ramc_write(0, AT91RM9200_SDRAMC_LPR, 0);
+       
+       if (at91_cpuidle_device.dev.platform_data)
+               platform_device_register(&at91_cpuidle_device);
 
        suspend_set_ops(&at91_pm_ops);
 
index 2f5908f0b8c5ec6dc9481f85bcba758d98f00d88..3ed190ce062bd5add5a426e07b1cf6c5d1e5b89a 100644 (file)
 #ifndef __ARCH_ARM_MACH_AT91_PM
 #define __ARCH_ARM_MACH_AT91_PM
 
+#include <asm/proc-fns.h>
+
 #include <mach/at91_ramc.h>
 #include <mach/at91rm9200_sdramc.h>
 
+extern void at91_pm_set_standby(void (*at91_standby)(void));
+
 /*
  * The AT91RM9200 goes into self-refresh mode with this command, and will
  * terminate self-refresh automatically on the next SDRAM access.
@@ -45,16 +49,18 @@ static inline void at91rm9200_standby(void)
 /* We manage both DDRAM/SDRAM controllers, we need more than one value to
  * remember.
  */
-static inline void at91sam9g45_standby(void)
+static inline void at91_ddr_standby(void)
 {
        /* Those two values allow us to delay self-refresh activation
         * to the maximum. */
-       u32 lpr0, lpr1;
-       u32 saved_lpr0, saved_lpr1;
+       u32 lpr0, lpr1 = 0;
+       u32 saved_lpr0, saved_lpr1 = 0;
 
-       saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
-       lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
-       lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
+       if (at91_ramc_base[1]) {
+               saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
+               lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
+               lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
+       }
 
        saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
        lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
@@ -62,25 +68,29 @@ static inline void at91sam9g45_standby(void)
 
        /* self-refresh mode now */
        at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
-       at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
 
        cpu_do_idle();
 
        at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
-       at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
 }
 
 /* We manage both DDRAM/SDRAM controllers, we need more than one value to
  * remember.
  */
-static inline void at91sam9263_standby(void)
+static inline void at91sam9_sdram_standby(void)
 {
-       u32 lpr0, lpr1;
-       u32 saved_lpr0, saved_lpr1;
+       u32 lpr0, lpr1 = 0;
+       u32 saved_lpr0, saved_lpr1 = 0;
 
-       saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
-       lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
-       lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
+       if (at91_ramc_base[1]) {
+               saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
+               lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
+               lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
+       }
 
        saved_lpr0 = at91_ramc_read(0, AT91_SDRAMC_LPR);
        lpr0 = saved_lpr0 & ~AT91_SDRAMC_LPCB;
@@ -88,27 +98,14 @@ static inline void at91sam9263_standby(void)
 
        /* self-refresh mode now */
        at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0);
-       at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
 
        cpu_do_idle();
 
        at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0);
-       at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
-}
-
-static inline void at91sam9_standby(void)
-{
-       u32 saved_lpr, lpr;
-
-       saved_lpr = at91_ramc_read(0, AT91_SDRAMC_LPR);
-
-       lpr = saved_lpr & ~AT91_SDRAMC_LPCB;
-       at91_ramc_write(0, AT91_SDRAMC_LPR, lpr |
-                       AT91_SDRAMC_LPCB_SELF_REFRESH);
-
-       cpu_do_idle();
-
-       at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr);
+       if (at91_ramc_base[1])
+               at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
 }
 
 #endif
index b17fbcf4d9e8f34dbd876ea96af334dae4780efc..094b3459c288e37700c42ea85a57ced905323eda 100644 (file)
@@ -23,6 +23,7 @@
 #include "at91_shdwc.h"
 #include "soc.h"
 #include "generic.h"
+#include "pm.h"
 
 struct at91_init_soc __initdata at91_boot_soc;
 
@@ -376,15 +377,16 @@ static void at91_dt_rstc(void)
 }
 
 static struct of_device_id ramc_ids[] = {
-       { .compatible = "atmel,at91rm9200-sdramc" },
-       { .compatible = "atmel,at91sam9260-sdramc" },
-       { .compatible = "atmel,at91sam9g45-ddramc" },
+       { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
+       { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
+       { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby },
        { /*sentinel*/ }
 };
 
 static void at91_dt_ramc(void)
 {
        struct device_node *np;
+       const struct of_device_id *of_id;
 
        np = of_find_matching_node(NULL, ramc_ids);
        if (!np)
@@ -396,6 +398,12 @@ static void at91_dt_ramc(void)
        /* the controller may have 2 banks */
        at91_ramc_base[1] = of_iomap(np, 1);
 
+       of_id = of_match_node(ramc_ids, np);
+       if (!of_id)
+               pr_warn("AT91: ramc no standby function available\n");
+       else
+               at91_pm_set_standby(of_id->data);
+
        of_node_put(np);
 }
 
index e026b19b23eaf1d8546f4996a387c13e1b8ed670..a075b3e0c5c7a5229aa87163e732d9c6b49a7a50 100644 (file)
@@ -40,7 +40,6 @@ config ARCH_DAVINCI_DA850
        bool "DA850/OMAP-L138/AM18x based system"
        select ARCH_DAVINCI_DA8XX
        select ARCH_HAS_CPUFREQ
-       select CPU_FREQ_TABLE
        select CP_INTC
 
 config ARCH_DAVINCI_DA8XX
index ba95e5db25011a0801c2ef1f7c27270b713280ee..c17407b16d7c687292fa6e064978d9ca1699ea0a 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/clk-provider.h>
 #include <linux/irqchip/arm-gic.h>
 #include <linux/irqchip/chained_irq.h>
+#include <linux/platform_device.h>
 
 #include <asm/proc-fns.h>
 #include <asm/exception.h>
@@ -294,6 +295,16 @@ void exynos5_restart(enum reboot_mode mode, const char *cmd)
        __raw_writel(val, addr);
 }
 
+static struct platform_device exynos_cpuidle = {
+       .name           = "exynos_cpuidle",
+       .id             = -1,
+};
+
+void __init exynos_cpuidle_init(void)
+{
+       platform_device_register(&exynos_cpuidle);
+}
+
 void __init exynos_init_late(void)
 {
        if (of_machine_is_compatible("samsung,exynos5440"))
index 8646a141ae467b8175aed00d0acf39ae73f02097..b2ac1885d381d6581717a111a92f6cec25723abe 100644 (file)
@@ -22,6 +22,7 @@ struct map_desc;
 void exynos_init_io(void);
 void exynos4_restart(enum reboot_mode mode, const char *cmd);
 void exynos5_restart(enum reboot_mode mode, const char *cmd);
+void exynos_cpuidle_init(void);
 void exynos_init_late(void);
 
 void exynos_firmware_init(void);
index ac139226d63c1d1aefe86a7e25087ad7e6da36da..1bde6ad07d93e5a0fe6ed69d7ecc840268be2586 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/export.h>
 #include <linux/time.h>
+#include <linux/platform_device.h>
 
 #include <asm/proc-fns.h>
 #include <asm/smp_scu.h>
@@ -192,7 +193,7 @@ static void __init exynos5_core_down_clk(void)
        __raw_writel(tmp, EXYNOS5_PWR_CTRL2);
 }
 
-static int __init exynos4_init_cpuidle(void)
+static int __init exynos_cpuidle_probe(struct platform_device *pdev)
 {
        int cpu_id, ret;
        struct cpuidle_device *device;
@@ -226,4 +227,13 @@ static int __init exynos4_init_cpuidle(void)
 
        return 0;
 }
-device_initcall(exynos4_init_cpuidle);
+
+static struct platform_driver exynos_cpuidle_driver = {
+       .probe  = exynos_cpuidle_probe,
+       .driver = {
+               .name = "exynos_cpuidle",
+               .owner = THIS_MODULE,
+       },
+};
+
+module_platform_driver(exynos_cpuidle_driver);
index 0099c6c13bbaa9504dccd6fa760c21273de41d3f..53a3dc37a7303b0a5bbdbdc202fbe211e6b0dd9e 100644 (file)
@@ -25,6 +25,8 @@
 
 static void __init exynos4_dt_machine_init(void)
 {
+       exynos_cpuidle_init();
+
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
index f874b773ca134e231df3e21d3c5c5f65caac33a9..c9f7dd1cdc8f9fd0f7a9c75fd4bb625ad42366f7 100644 (file)
@@ -47,6 +47,8 @@ static void __init exynos5_dt_machine_init(void)
                }
        }
 
+       exynos_cpuidle_init();
+
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
index 90372a21087f9ef38535479ccc35aac9e37977dc..699aabe296e1e62b91f7ca1b0a65c5e635ed8515 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/phy.h>
 #include <linux/reboot.h>
 #include <linux/regmap.h>
@@ -226,7 +226,7 @@ static void __init imx6q_opp_check_1p2ghz(struct device *cpu_dev)
        val = readl_relaxed(base + OCOTP_CFG3);
        val >>= OCOTP_CFG3_SPEED_SHIFT;
        if ((val & 0x3) != OCOTP_CFG3_SPEED_1P2GHZ)
-               if (opp_disable(cpu_dev, 1200000000))
+               if (dev_pm_opp_disable(cpu_dev, 1200000000))
                        pr_warn("failed to disable 1.2 GHz OPP\n");
 
 put_node:
index f26918467efcf42cc13639317965ebdb6d34bf14..6432ab8d92078ac4779627d9ae143761bd78ebef 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/cpu.h>
 
 #include <linux/mtd/mtd.h>
@@ -522,11 +522,11 @@ static int __init beagle_opp_init(void)
                        return -ENODEV;
                }
                /* Enable MPU 1GHz and lower opps */
-               r = opp_enable(mpu_dev, 800000000);
+               r = dev_pm_opp_enable(mpu_dev, 800000000);
                /* TODO: MPU 1GHz needs SR and ABB */
 
                /* Enable IVA 800MHz and lower opps */
-               r |= opp_enable(iva_dev, 660000000);
+               r |= dev_pm_opp_enable(iva_dev, 660000000);
                /* TODO: DSP 800MHz needs SR and ABB */
                if (r) {
                        pr_err("%s: failed to enable higher opp %d\n",
@@ -535,8 +535,8 @@ static int __init beagle_opp_init(void)
                         * Cleanup - disable the higher freqs - we dont care
                         * about the results
                         */
-                       opp_disable(mpu_dev, 800000000);
-                       opp_disable(iva_dev, 660000000);
+                       dev_pm_opp_disable(mpu_dev, 800000000);
+                       dev_pm_opp_disable(iva_dev, 660000000);
                }
        }
        return 0;
index 67faa7b8fe92fd932889b65d55adbe0c5a97e5de..1d777e63e05c94ccf754bab89a65ca681638c67f 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/device.h>
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 
 /*
  * agent_id values for use with omap_pm_set_min_bus_tput():
index bd41d59a7cab08ecbca342a665f5f944aa67b6bc..ec21e6eb03e133be1c8b1ff2a4733d0f34052abc 100644 (file)
@@ -17,7 +17,7 @@
  * GNU General Public License for more details.
  */
 #include <linux/module.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/cpu.h>
 
 #include "omap_device.h"
@@ -81,14 +81,14 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
                        dev = &oh->od->pdev->dev;
                }
 
-               r = opp_add(dev, opp_def->freq, opp_def->u_volt);
+               r = dev_pm_opp_add(dev, opp_def->freq, opp_def->u_volt);
                if (r) {
                        dev_err(dev, "%s: add OPP %ld failed for %s [%d] result=%d\n",
                                __func__, opp_def->freq,
                                opp_def->hwmod_name, i, r);
                } else {
                        if (!opp_def->default_available)
-                               r = opp_disable(dev, opp_def->freq);
+                               r = dev_pm_opp_disable(dev, opp_def->freq);
                        if (r)
                                dev_err(dev, "%s: disable %ld failed for %s [%d] result=%d\n",
                                        __func__, opp_def->freq,
index e742118fcfd2b69adc367057e6f17670a5136903..2f569b3c3092dbdaf4d3bbc2ec6a85253402db74 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/err.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/export.h>
 #include <linux/suspend.h>
 #include <linux/cpu.h>
@@ -131,7 +131,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
 {
        struct voltagedomain *voltdm;
        struct clk *clk;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long freq, bootup_volt;
        struct device *dev;
 
@@ -172,7 +172,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
        clk_put(clk);
 
        rcu_read_lock();
-       opp = opp_find_freq_ceil(dev, &freq);
+       opp = dev_pm_opp_find_freq_ceil(dev, &freq);
        if (IS_ERR(opp)) {
                rcu_read_unlock();
                pr_err("%s: unable to find boot up OPP for vdd_%s\n",
@@ -180,7 +180,7 @@ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name,
                goto exit;
        }
 
-       bootup_volt = opp_get_voltage(opp);
+       bootup_volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
        if (!bootup_volt) {
                pr_err("%s: unable to find voltage corresponding to the bootup OPP for vdd_%s\n",
index a8427115ee07b9a986d62dceac6006f8c9cecafd..96100dbf5a2e8353e9fad34ded41ec5e83dda7ad 100644 (file)
@@ -615,14 +615,12 @@ endmenu
 config PXA25x
        bool
        select CPU_XSCALE
-       select CPU_FREQ_TABLE if CPU_FREQ
        help
          Select code specific to PXA21x/25x/26x variants
 
 config PXA27x
        bool
        select CPU_XSCALE
-       select CPU_FREQ_TABLE if CPU_FREQ
        help
          Select code specific to PXA27x variants
 
@@ -635,7 +633,6 @@ config CPU_PXA26x
 config PXA3xx
        bool
        select CPU_XSC3
-       select CPU_FREQ_TABLE if CPU_FREQ
        help
          Select code specific to PXA3xx variants
 
index f25b6119e028cc42ee564712fb3ef746961e0574..cb4b2ca3cf6b9e3f4238b13b0aa678c8f8fed7b5 100644 (file)
@@ -42,23 +42,24 @@ EXPORT_SYMBOL(reset_status);
 /*
  * This table is setup for a 3.6864MHz Crystal.
  */
-static const unsigned short cclk_frequency_100khz[NR_FREQS] = {
-        590,   /*  59.0 MHz */
-        737,   /*  73.7 MHz */
-        885,   /*  88.5 MHz */
-       1032,   /* 103.2 MHz */
-       1180,   /* 118.0 MHz */
-       1327,   /* 132.7 MHz */
-       1475,   /* 147.5 MHz */
-       1622,   /* 162.2 MHz */
-       1769,   /* 176.9 MHz */
-       1917,   /* 191.7 MHz */
-       2064,   /* 206.4 MHz */
-       2212,   /* 221.2 MHz */
-       2359,   /* 235.9 MHz */
-       2507,   /* 250.7 MHz */
-       2654,   /* 265.4 MHz */
-       2802    /* 280.2 MHz */
+struct cpufreq_frequency_table sa11x0_freq_table[NR_FREQS+1] = {
+       { .frequency = 59000,   /*  59.0 MHz */},
+       { .frequency = 73700,   /*  73.7 MHz */},
+       { .frequency = 88500,   /*  88.5 MHz */},
+       { .frequency = 103200,  /* 103.2 MHz */},
+       { .frequency = 118000,  /* 118.0 MHz */},
+       { .frequency = 132700,  /* 132.7 MHz */},
+       { .frequency = 147500,  /* 147.5 MHz */},
+       { .frequency = 162200,  /* 162.2 MHz */},
+       { .frequency = 176900,  /* 176.9 MHz */},
+       { .frequency = 191700,  /* 191.7 MHz */},
+       { .frequency = 206400,  /* 206.4 MHz */},
+       { .frequency = 221200,  /* 221.2 MHz */},
+       { .frequency = 235900,  /* 235.9 MHz */},
+       { .frequency = 250700,  /* 250.7 MHz */},
+       { .frequency = 265400,  /* 265.4 MHz */},
+       { .frequency = 280200,  /* 280.2 MHz */},
+       { .frequency = CPUFREQ_TABLE_END, },
 };
 
 /* rounds up(!)  */
@@ -66,10 +67,8 @@ unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
 {
        int i;
 
-       khz /= 100;
-
        for (i = 0; i < NR_FREQS; i++)
-               if (cclk_frequency_100khz[i] >= khz)
+               if (sa11x0_freq_table[i].frequency >= khz)
                        break;
 
        return i;
@@ -79,37 +78,15 @@ unsigned int sa11x0_ppcr_to_freq(unsigned int idx)
 {
        unsigned int freq = 0;
        if (idx < NR_FREQS)
-               freq = cclk_frequency_100khz[idx] * 100;
+               freq = sa11x0_freq_table[idx].frequency;
        return freq;
 }
 
-
-/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on
- * this platform, anyway.
- */
-int sa11x0_verify_speed(struct cpufreq_policy *policy)
-{
-       unsigned int tmp;
-       if (policy->cpu)
-               return -EINVAL;
-
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
-
-       /* make sure that at least one frequency is within the policy */
-       tmp = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->min)] * 100;
-       if (tmp > policy->max)
-               policy->max = tmp;
-
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
-
-       return 0;
-}
-
 unsigned int sa11x0_getspeed(unsigned int cpu)
 {
        if (cpu)
                return 0;
-       return cclk_frequency_100khz[PPCR & 0xf] * 100;
+       return sa11x0_freq_table[PPCR & 0xf].frequency;
 }
 
 /*
index 9a33695c9492d238879a43dd64002a88d878df23..cbdfae744dc522183fb3b45918e5461a04aeab67 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Author: Nicolas Pitre
  */
+#include <linux/cpufreq.h>
 #include <linux/reboot.h>
 
 extern void sa1100_timer_init(void);
@@ -19,10 +20,8 @@ extern void sa11x0_init_late(void);
 extern void sa1110_mb_enable(void);
 extern void sa1110_mb_disable(void);
 
-struct cpufreq_policy;
-
+extern struct cpufreq_frequency_table sa11x0_freq_table[];
 extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
-extern int sa11x0_verify_speed(struct cpufreq_policy *policy);
 extern unsigned int sa11x0_getspeed(unsigned int cpu);
 extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx);
 
index 99a28d62829742d9103764c47abcb5ff24894fbf..7a3fc1af6944b2cd9175a46f7c1749c83a090220 100644 (file)
@@ -34,7 +34,6 @@ config UX500_SOC_COMMON
 
 config UX500_SOC_DB8500
        bool
-       select CPU_FREQ_TABLE if CPU_FREQ
        select MFD_DB8500_PRCMU
        select PINCTRL_DB8500
        select PINCTRL_DB8540
index 5f252569c68987d908546b55bb921d5f7693c7af..9a7bd137c8fd27d60f42a6b78c6dbf3cc234d348 100644 (file)
@@ -44,6 +44,10 @@ static struct of_device_id zynq_of_bus_ids[] __initdata = {
        {}
 };
 
+static struct platform_device zynq_cpuidle_device = {
+       .name = "cpuidle-zynq",
+};
+
 /**
  * zynq_init_machine - System specific initialization, intended to be
  *                    called from board specific initialization.
@@ -56,6 +60,8 @@ static void __init zynq_init_machine(void)
        l2x0_of_init(0x02060000, 0xF0F0FFFF);
 
        of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
+
+       platform_device_register(&zynq_cpuidle_device);
 }
 
 static void __init zynq_timer_init(void)
index f78c9a2c7e281f2d441a40719e6735226231ceaa..eb382aedd9a232c9d85173356bf4ed44d33fb6b5 100644 (file)
@@ -1429,7 +1429,6 @@ source "drivers/cpufreq/Kconfig"
 config BFIN_CPU_FREQ
        bool
        depends on CPU_FREQ
-       select CPU_FREQ_TABLE
        default y
 
 config CPU_VOLTAGE
index 02380bed189c6fda4920412a18f1baab6203d1c1..9c957c81c6885acd595c42d1c470a1390cef6feb 100644 (file)
@@ -130,13 +130,11 @@ config SVINTO_SIM
 
 config ETRAXFS
        bool "ETRAX-FS-V32"
-       select CPU_FREQ_TABLE if CPU_FREQ
        help
          Support CRIS V32.
 
 config CRIS_MACH_ARTPEC3
         bool "ARTPEC-3"
-       select CPU_FREQ_TABLE if CPU_FREQ
         help
           Support Axis ARTPEC-3.
 
index 5eb71d22c3d5901030eec5c9ead78dc1279d815e..59d52e3aef125b79b67afdaf1fcffd2b892367ff 100644 (file)
@@ -882,40 +882,10 @@ __init void prefill_possible_map(void)
                set_cpu_possible(i, true);
 }
 
-static int _acpi_map_lsapic(acpi_handle handle, int *pcpu)
+static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
 {
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *obj;
-       struct acpi_madt_local_sapic *lsapic;
        cpumask_t tmp_map;
-       int cpu, physid;
-
-       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
-               return -EINVAL;
-
-       if (!buffer.length || !buffer.pointer)
-               return -EINVAL;
-
-       obj = buffer.pointer;
-       if (obj->type != ACPI_TYPE_BUFFER)
-       {
-               kfree(buffer.pointer);
-               return -EINVAL;
-       }
-
-       lsapic = (struct acpi_madt_local_sapic *)obj->buffer.pointer;
-
-       if ((lsapic->header.type != ACPI_MADT_TYPE_LOCAL_SAPIC) ||
-           (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))) {
-               kfree(buffer.pointer);
-               return -EINVAL;
-       }
-
-       physid = ((lsapic->id << 8) | (lsapic->eid));
-
-       kfree(buffer.pointer);
-       buffer.length = ACPI_ALLOCATE_BUFFER;
-       buffer.pointer = NULL;
+       int cpu;
 
        cpumask_complement(&tmp_map, cpu_present_mask);
        cpu = cpumask_first(&tmp_map);
@@ -934,9 +904,9 @@ static int _acpi_map_lsapic(acpi_handle handle, int *pcpu)
 }
 
 /* wrapper to silence section mismatch warning */
-int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
+int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
 {
-       return _acpi_map_lsapic(handle, pcpu);
+       return _acpi_map_lsapic(handle, physid, pcpu);
 }
 EXPORT_SYMBOL(acpi_map_lsapic);
 
index 8e59abc237d7f17c96effa20583206e75b2e4b7a..930cd8af35035441031e1abecbdde3472ab48808 100644 (file)
@@ -844,18 +844,6 @@ void __cpu_die(unsigned int cpu)
                smp_ops->cpu_die(cpu);
 }
 
-static DEFINE_MUTEX(powerpc_cpu_hotplug_driver_mutex);
-
-void cpu_hotplug_driver_lock()
-{
-       mutex_lock(&powerpc_cpu_hotplug_driver_mutex);
-}
-
-void cpu_hotplug_driver_unlock()
-{
-       mutex_unlock(&powerpc_cpu_hotplug_driver_mutex);
-}
-
 void cpu_die(void)
 {
        if (ppc_md.cpu_die)
index 7cfdaae1721a925c1d7370515917e7d9af5cc553..a8fe5aa3d34fd545f87a31995153effd8a63521b 100644 (file)
@@ -404,46 +404,38 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
        unsigned long drc_index;
        int rc;
 
-       cpu_hotplug_driver_lock();
        rc = strict_strtoul(buf, 0, &drc_index);
-       if (rc) {
-               rc = -EINVAL;
-               goto out;
-       }
+       if (rc)
+               return -EINVAL;
 
        parent = of_find_node_by_path("/cpus");
-       if (!parent) {
-               rc = -ENODEV;
-               goto out;
-       }
+       if (!parent)
+               return -ENODEV;
 
        dn = dlpar_configure_connector(drc_index, parent);
-       if (!dn) {
-               rc = -EINVAL;
-               goto out;
-       }
+       if (!dn)
+               return -EINVAL;
 
        of_node_put(parent);
 
        rc = dlpar_acquire_drc(drc_index);
        if (rc) {
                dlpar_free_cc_nodes(dn);
-               rc = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
        rc = dlpar_attach_node(dn);
        if (rc) {
                dlpar_release_drc(drc_index);
                dlpar_free_cc_nodes(dn);
-               goto out;
+               return rc;
        }
 
        rc = dlpar_online_cpu(dn);
-out:
-       cpu_hotplug_driver_unlock();
+       if (rc)
+               return rc;
 
-       return rc ? rc : count;
+       return count;
 }
 
 static int dlpar_offline_cpu(struct device_node *dn)
@@ -516,30 +508,27 @@ static ssize_t dlpar_cpu_release(const char *buf, size_t count)
                return -EINVAL;
        }
 
-       cpu_hotplug_driver_lock();
        rc = dlpar_offline_cpu(dn);
        if (rc) {
                of_node_put(dn);
-               rc = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
        rc = dlpar_release_drc(*drc_index);
        if (rc) {
                of_node_put(dn);
-               goto out;
+               return rc;
        }
 
        rc = dlpar_detach_node(dn);
        if (rc) {
                dlpar_acquire_drc(*drc_index);
-               goto out;
+               return rc;
        }
 
        of_node_put(dn);
-out:
-       cpu_hotplug_driver_unlock();
-       return rc ? rc : count;
+
+       return count;
 }
 
 static int __init pseries_dlpar_init(void)
index f67e839f06c845e406d81c8b2be285ced8b57448..0c11032e2e913e4cf050f635cc2bd41bc71e7111 100644 (file)
@@ -254,10 +254,6 @@ config ARCH_HWEIGHT_CFLAGS
        default "-fcall-saved-ecx -fcall-saved-edx" if X86_32
        default "-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" if X86_64
 
-config ARCH_CPU_PROBE_RELEASE
-       def_bool y
-       depends on HOTPLUG_CPU
-
 config ARCH_SUPPORTS_UPROBES
        def_bool y
 
index b1977bad5435e5342af7e548700f08c1a04ff580..c8c1e700c26ed3426f0086c594a645bcc49261d9 100644 (file)
@@ -26,6 +26,7 @@
 #include <acpi/pdc_intel.h>
 
 #include <asm/numa.h>
+#include <asm/fixmap.h>
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/mpspec.h>
index 626cf70082d7c8229b14a529625652f5646fcf09..3142a94c7b4bf90314838fa8beb67c4e7ed0b363 100644 (file)
@@ -94,7 +94,7 @@ static inline void early_reserve_e820_mpc_new(void) { }
 #define default_get_smp_config x86_init_uint_noop
 #endif
 
-void generic_processor_info(int apicid, int version);
+int generic_processor_info(int apicid, int version);
 #ifdef CONFIG_ACPI
 extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
 extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
index cb7502852acb0921e4e0c7132962c681f43b51ec..e139b13f2a33a3572d91e4f7297952e1bf8a1ffc 100644 (file)
@@ -218,10 +218,14 @@ void msrs_free(struct msr *msrs);
 #ifdef CONFIG_SMP
 int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q);
+int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q);
 void rdmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
 void wrmsr_on_cpus(const struct cpumask *mask, u32 msr_no, struct msr *msrs);
 int rdmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
 int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
+int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q);
+int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q);
 int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
 int wrmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8]);
 #else  /*  CONFIG_SMP  */
@@ -235,6 +239,16 @@ static inline int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
        wrmsr(msr_no, l, h);
        return 0;
 }
+static inline int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
+{
+       rdmsrl(msr_no, *q);
+       return 0;
+}
+static inline int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
+{
+       wrmsrl(msr_no, q);
+       return 0;
+}
 static inline void rdmsr_on_cpus(const struct cpumask *m, u32 msr_no,
                                struct msr *msrs)
 {
@@ -254,6 +268,14 @@ static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 {
        return wrmsr_safe(msr_no, l, h);
 }
+static inline int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
+{
+       return rdmsrl_safe(msr_no, q);
+}
+static inline int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
+{
+       return wrmsrl_safe(msr_no, q);
+}
 static inline int rdmsr_safe_regs_on_cpu(unsigned int cpu, u32 regs[8])
 {
        return rdmsr_safe_regs(regs);
index 40c76604199f76e9263f94c10c249f2eee8e40dc..6c0b43bd024bb5890230ca45c61b3de082b611ef 100644 (file)
@@ -189,24 +189,31 @@ static int __init acpi_parse_madt(struct acpi_table_header *table)
        return 0;
 }
 
-static void acpi_register_lapic(int id, u8 enabled)
+/**
+ * acpi_register_lapic - register a local apic and generates a logic cpu number
+ * @id: local apic id to register
+ * @enabled: this cpu is enabled or not
+ *
+ * Returns the logic cpu number which maps to the local apic
+ */
+static int acpi_register_lapic(int id, u8 enabled)
 {
        unsigned int ver = 0;
 
        if (id >= MAX_LOCAL_APIC) {
                printk(KERN_INFO PREFIX "skipped apicid that is too big\n");
-               return;
+               return -EINVAL;
        }
 
        if (!enabled) {
                ++disabled_cpus;
-               return;
+               return -EINVAL;
        }
 
        if (boot_cpu_physical_apicid != -1U)
                ver = apic_version[boot_cpu_physical_apicid];
 
-       generic_processor_info(id, ver);
+       return generic_processor_info(id, ver);
 }
 
 static int __init
@@ -614,84 +621,27 @@ static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 #endif
 }
 
-static int _acpi_map_lsapic(acpi_handle handle, int *pcpu)
+static int _acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
 {
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *obj;
-       struct acpi_madt_local_apic *lapic;
-       cpumask_var_t tmp_map, new_map;
-       u8 physid;
        int cpu;
-       int retval = -ENOMEM;
-
-       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer)))
-               return -EINVAL;
-
-       if (!buffer.length || !buffer.pointer)
-               return -EINVAL;
-
-       obj = buffer.pointer;
-       if (obj->type != ACPI_TYPE_BUFFER ||
-           obj->buffer.length < sizeof(*lapic)) {
-               kfree(buffer.pointer);
-               return -EINVAL;
-       }
 
-       lapic = (struct acpi_madt_local_apic *)obj->buffer.pointer;
-
-       if (lapic->header.type != ACPI_MADT_TYPE_LOCAL_APIC ||
-           !(lapic->lapic_flags & ACPI_MADT_ENABLED)) {
-               kfree(buffer.pointer);
-               return -EINVAL;
-       }
-
-       physid = lapic->id;
-
-       kfree(buffer.pointer);
-       buffer.length = ACPI_ALLOCATE_BUFFER;
-       buffer.pointer = NULL;
-       lapic = NULL;
-
-       if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL))
-               goto out;
-
-       if (!alloc_cpumask_var(&new_map, GFP_KERNEL))
-               goto free_tmp_map;
-
-       cpumask_copy(tmp_map, cpu_present_mask);
-       acpi_register_lapic(physid, ACPI_MADT_ENABLED);
-
-       /*
-        * If acpi_register_lapic successfully generates a new logical cpu
-        * number, then the following will get us exactly what was mapped
-        */
-       cpumask_andnot(new_map, cpu_present_mask, tmp_map);
-       if (cpumask_empty(new_map)) {
-               printk ("Unable to map lapic to logical cpu number\n");
-               retval = -EINVAL;
-               goto free_new_map;
+       cpu = acpi_register_lapic(physid, ACPI_MADT_ENABLED);
+       if (cpu < 0) {
+               pr_info(PREFIX "Unable to map lapic to logical cpu number\n");
+               return cpu;
        }
 
        acpi_processor_set_pdc(handle);
-
-       cpu = cpumask_first(new_map);
        acpi_map_cpu2node(handle, cpu, physid);
 
        *pcpu = cpu;
-       retval = 0;
-
-free_new_map:
-       free_cpumask_var(new_map);
-free_tmp_map:
-       free_cpumask_var(tmp_map);
-out:
-       return retval;
+       return 0;
 }
 
 /* wrapper to silence section mismatch warning */
-int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
+int __ref acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu)
 {
-       return _acpi_map_lsapic(handle, pcpu);
+       return _acpi_map_lsapic(handle, physid, pcpu);
 }
 EXPORT_SYMBOL(acpi_map_lsapic);
 
@@ -745,7 +695,7 @@ static int __init acpi_parse_sbf(struct acpi_table_header *table)
 #ifdef CONFIG_HPET_TIMER
 #include <asm/hpet.h>
 
-static struct __initdata resource *hpet_res;
+static struct resource *hpet_res __initdata;
 
 static int __init acpi_parse_hpet(struct acpi_table_header *table)
 {
index a7eb82d9b0120d02147d8eb1620a7da1d708c282..ed165d657380062387d08da7bf2f607fff192490 100644 (file)
@@ -2107,7 +2107,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
        apic_write(APIC_LVT1, value);
 }
 
-void generic_processor_info(int apicid, int version)
+int generic_processor_info(int apicid, int version)
 {
        int cpu, max = nr_cpu_ids;
        bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid,
@@ -2127,7 +2127,7 @@ void generic_processor_info(int apicid, int version)
                        "  Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
 
                disabled_cpus++;
-               return;
+               return -ENODEV;
        }
 
        if (num_processors >= nr_cpu_ids) {
@@ -2138,7 +2138,7 @@ void generic_processor_info(int apicid, int version)
                        "  Processor %d/0x%x ignored.\n", max, thiscpu, apicid);
 
                disabled_cpus++;
-               return;
+               return -EINVAL;
        }
 
        num_processors++;
@@ -2183,6 +2183,8 @@ void generic_processor_info(int apicid, int version)
 #endif
        set_cpu_possible(cpu, true);
        set_cpu_present(cpu, true);
+
+       return cpu;
 }
 
 int hard_smp_processor_id(void)
index 6cacab671f9b76a35aaf49d41431b12e788e5bbe..e73b3f53310c7663b2c37a3cffd57c0cad974a3c 100644 (file)
 /* State of each CPU */
 DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * We need this for trampoline_base protection from concurrent accesses when
- * off- and onlining cores wildly.
- */
-static DEFINE_MUTEX(x86_cpu_hotplug_driver_mutex);
-
-void cpu_hotplug_driver_lock(void)
-{
-       mutex_lock(&x86_cpu_hotplug_driver_mutex);
-}
-
-void cpu_hotplug_driver_unlock(void)
-{
-       mutex_unlock(&x86_cpu_hotplug_driver_mutex);
-}
-
-ssize_t arch_cpu_probe(const char *buf, size_t count) { return -1; }
-ssize_t arch_cpu_release(const char *buf, size_t count) { return -1; }
-#endif
-
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
 EXPORT_SYMBOL(smp_num_siblings);
index 6e60b5fe224481d01ca8662c6edd01432da08518..649b010da00ba5a0c191a4144f2458c08f0500ab 100644 (file)
@@ -65,29 +65,32 @@ int __ref _debug_hotplug_cpu(int cpu, int action)
        if (!cpu_is_hotpluggable(cpu))
                return -EINVAL;
 
-       cpu_hotplug_driver_lock();
+       lock_device_hotplug();
 
        switch (action) {
        case 0:
                ret = cpu_down(cpu);
                if (!ret) {
                        pr_info("CPU %u is now offline\n", cpu);
+                       dev->offline = true;
                        kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
                } else
                        pr_debug("Can't offline CPU%d.\n", cpu);
                break;
        case 1:
                ret = cpu_up(cpu);
-               if (!ret)
+               if (!ret) {
+                       dev->offline = false;
                        kobject_uevent(&dev->kobj, KOBJ_ONLINE);
-               else
+               } else {
                        pr_debug("Can't online CPU%d.\n", cpu);
+               }
                break;
        default:
                ret = -EINVAL;
        }
 
-       cpu_hotplug_driver_unlock();
+       unlock_device_hotplug();
 
        return ret;
 }
index a6b1b86d225358f05e58a649fdadedc4eafdb87e..518532e6a3faa213eb0833c6781c9ceba34dea86 100644 (file)
@@ -47,6 +47,21 @@ int rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h)
 }
 EXPORT_SYMBOL(rdmsr_on_cpu);
 
+int rdmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       err = smp_call_function_single(cpu, __rdmsr_on_cpu, &rv, 1);
+       *q = rv.reg.q;
+
+       return err;
+}
+EXPORT_SYMBOL(rdmsrl_on_cpu);
+
 int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 {
        int err;
@@ -63,6 +78,22 @@ int wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 }
 EXPORT_SYMBOL(wrmsr_on_cpu);
 
+int wrmsrl_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       rv.reg.q = q;
+
+       err = smp_call_function_single(cpu, __wrmsr_on_cpu, &rv, 1);
+
+       return err;
+}
+EXPORT_SYMBOL(wrmsrl_on_cpu);
+
 static void __rwmsr_on_cpus(const struct cpumask *mask, u32 msr_no,
                            struct msr *msrs,
                            void (*msr_func) (void *info))
@@ -159,6 +190,37 @@ int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
 }
 EXPORT_SYMBOL(wrmsr_safe_on_cpu);
 
+int wrmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 q)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       rv.reg.q = q;
+
+       err = smp_call_function_single(cpu, __wrmsr_safe_on_cpu, &rv, 1);
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(wrmsrl_safe_on_cpu);
+
+int rdmsrl_safe_on_cpu(unsigned int cpu, u32 msr_no, u64 *q)
+{
+       int err;
+       struct msr_info rv;
+
+       memset(&rv, 0, sizeof(rv));
+
+       rv.msr_no = msr_no;
+       err = smp_call_function_single(cpu, __rdmsr_safe_on_cpu, &rv, 1);
+       *q = rv.reg.q;
+
+       return err ? err : rv.err;
+}
+EXPORT_SYMBOL(rdmsrl_safe_on_cpu);
+
 /*
  * These variants are significantly slower, but allows control over
  * the entire 32-bit GPR set.
index fef7d0ba7e3a93d8e44ed09cec92db708759cbcf..649a12befba92f399895b947cc779e0269ac750d 100644 (file)
@@ -40,16 +40,9 @@ static bool                          lid_wake_on_close;
  */
 static int set_lid_wake_behavior(bool wake_on_close)
 {
-       struct acpi_object_list arg_list;
-       union acpi_object arg;
        acpi_status status;
 
-       arg_list.count          = 1;
-       arg_list.pointer        = &arg;
-       arg.type                = ACPI_TYPE_INTEGER;
-       arg.integer.value       = wake_on_close;
-
-       status = acpi_evaluate_object(NULL, "\\_SB.PCI0.LID.LIDW", &arg_list, NULL);
+       status = acpi_execute_simple_method(NULL, "\\_SB.PCI0.LID.LIDW", wake_on_close);
        if (ACPI_FAILURE(status)) {
                pr_warning(PFX "failed to set lid behavior\n");
                return 1;
index aa43b911ccef582c78e70a914106ba454de2c05b..969e9871785ca5ae47e0153ef96c15c460daca18 100644 (file)
@@ -166,4 +166,6 @@ source "drivers/reset/Kconfig"
 
 source "drivers/fmc/Kconfig"
 
+source "drivers/powercap/Kconfig"
+
 endmenu
index ab93de8297f1338fc2440967ce8934a7ff6bc043..34c1d554f69b489fc523a811e9f1fc76b5a5cd4e 100644 (file)
@@ -152,3 +152,4 @@ obj-$(CONFIG_VME_BUS)               += vme/
 obj-$(CONFIG_IPACK_BUS)                += ipack/
 obj-$(CONFIG_NTB)              += ntb/
 obj-$(CONFIG_FMC)              += fmc/
+obj-$(CONFIG_POWERCAP)         += powercap/
index 6efe2ac6902fa635bf90a2d3e3d14728949aad5c..589da059ce3939c9a2139907daefbf00a5a9b0e2 100644 (file)
@@ -56,23 +56,6 @@ config ACPI_PROCFS
 
          Say N to delete /proc/acpi/ files that have moved to /sys/
 
-config ACPI_PROCFS_POWER
-       bool "Deprecated power /proc/acpi directories"
-       depends on PROC_FS
-       help
-         For backwards compatibility, this option allows
-          deprecated power /proc/acpi/ directories to exist, even when
-          they have been replaced by functions in /sys.
-          The deprecated directories (and their replacements) include:
-         /proc/acpi/battery/* (/sys/class/power_supply/*)
-         /proc/acpi/ac_adapter/* (sys/class/power_supply/*)
-         This option has no effect on /proc/acpi/ directories
-         and functions, which do not yet exist in /sys
-         This option, together with the proc directories, will be
-         deleted in 2.6.39.
-
-         Say N to delete power /proc/acpi/ directories that have moved to /sys/
-
 config ACPI_EC_DEBUGFS
        tristate "EC read/write access through /sys/kernel/debug/ec"
        default n
@@ -175,9 +158,10 @@ config ACPI_PROCESSOR
 
          To compile this driver as a module, choose M here:
          the module will be called processor.
+
 config ACPI_IPMI
        tristate "IPMI"
-       depends on IPMI_SI && IPMI_HANDLER
+       depends on IPMI_SI
        default n
        help
          This driver enables the ACPI to access the BMC controller. And it
index cdaf68b58b006fb833f104f2d5e28baa4ecaf991..a55fc06db4ae705b47aa8ca9f2b33d456057c536 100644 (file)
@@ -47,7 +47,6 @@ acpi-y                                += sysfs.o
 acpi-$(CONFIG_X86)             += acpi_cmos_rtc.o
 acpi-$(CONFIG_DEBUG_FS)                += debugfs.o
 acpi-$(CONFIG_ACPI_NUMA)       += numa.o
-acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
 ifdef CONFIG_ACPI_VIDEO
 acpi-y                         += video_detect.o
 endif
index f37beaa32750106dffdf9fd7aeac764f1f0094f2..b9f0d5f4bba51cecb6ffe8fda126762850818263 100644 (file)
 #include <linux/types.h>
 #include <linux/dmi.h>
 #include <linux/delay.h>
-#ifdef CONFIG_ACPI_PROCFS_POWER
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#endif
+#include <linux/platform_device.h>
 #include <linux/power_supply.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
@@ -55,75 +52,30 @@ MODULE_AUTHOR("Paul Diefenbaugh");
 MODULE_DESCRIPTION("ACPI AC Adapter Driver");
 MODULE_LICENSE("GPL");
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-extern struct proc_dir_entry *acpi_lock_ac_dir(void);
-extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
-static int acpi_ac_open_fs(struct inode *inode, struct file *file);
-#endif
-
-static int acpi_ac_add(struct acpi_device *device);
-static int acpi_ac_remove(struct acpi_device *device);
-static void acpi_ac_notify(struct acpi_device *device, u32 event);
-
-static const struct acpi_device_id ac_device_ids[] = {
-       {"ACPI0003", 0},
-       {"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, ac_device_ids);
-
-#ifdef CONFIG_PM_SLEEP
-static int acpi_ac_resume(struct device *dev);
-#endif
-static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
-
 static int ac_sleep_before_get_state_ms;
 
-static struct acpi_driver acpi_ac_driver = {
-       .name = "ac",
-       .class = ACPI_AC_CLASS,
-       .ids = ac_device_ids,
-       .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
-       .ops = {
-               .add = acpi_ac_add,
-               .remove = acpi_ac_remove,
-               .notify = acpi_ac_notify,
-               },
-       .drv.pm = &acpi_ac_pm,
-};
-
 struct acpi_ac {
        struct power_supply charger;
-       struct acpi_device * device;
+       struct acpi_device *adev;
+       struct platform_device *pdev;
        unsigned long long state;
 };
 
 #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger)
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-static const struct file_operations acpi_ac_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_ac_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-#endif
-
 /* --------------------------------------------------------------------------
                                AC Adapter Management
    -------------------------------------------------------------------------- */
 
 static int acpi_ac_get_state(struct acpi_ac *ac)
 {
-       acpi_status status = AE_OK;
-
-
-       if (!ac)
-               return -EINVAL;
+       acpi_status status;
 
-       status = acpi_evaluate_integer(ac->device->handle, "_PSR", NULL, &ac->state);
+       status = acpi_evaluate_integer(ac->adev->handle, "_PSR", NULL,
+                                      &ac->state);
        if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Error reading AC Adapter state"));
+               ACPI_EXCEPTION((AE_INFO, status,
+                               "Error reading AC Adapter state"));
                ac->state = ACPI_AC_STATUS_UNKNOWN;
                return -ENODEV;
        }
@@ -160,91 +112,13 @@ static enum power_supply_property ac_props[] = {
        POWER_SUPPLY_PROP_ONLINE,
 };
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-/* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-
-static struct proc_dir_entry *acpi_ac_dir;
-
-static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_ac *ac = seq->private;
-
-
-       if (!ac)
-               return 0;
-
-       if (acpi_ac_get_state(ac)) {
-               seq_puts(seq, "ERROR: Unable to read AC Adapter state\n");
-               return 0;
-       }
-
-       seq_puts(seq, "state:                   ");
-       switch (ac->state) {
-       case ACPI_AC_STATUS_OFFLINE:
-               seq_puts(seq, "off-line\n");
-               break;
-       case ACPI_AC_STATUS_ONLINE:
-               seq_puts(seq, "on-line\n");
-               break;
-       default:
-               seq_puts(seq, "unknown\n");
-               break;
-       }
-
-       return 0;
-}
-
-static int acpi_ac_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_ac_seq_show, PDE_DATA(inode));
-}
-
-static int acpi_ac_add_fs(struct acpi_device *device)
-{
-       struct proc_dir_entry *entry = NULL;
-
-       printk(KERN_WARNING PREFIX "Deprecated procfs I/F for AC is loaded,"
-                       " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
-       if (!acpi_device_dir(device)) {
-               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-                                                    acpi_ac_dir);
-               if (!acpi_device_dir(device))
-                       return -ENODEV;
-       }
-
-       /* 'state' [R] */
-       entry = proc_create_data(ACPI_AC_FILE_STATE,
-                                S_IRUGO, acpi_device_dir(device),
-                                &acpi_ac_fops, acpi_driver_data(device));
-       if (!entry)
-               return -ENODEV;
-       return 0;
-}
-
-static int acpi_ac_remove_fs(struct acpi_device *device)
-{
-
-       if (acpi_device_dir(device)) {
-               remove_proc_entry(ACPI_AC_FILE_STATE, acpi_device_dir(device));
-
-               remove_proc_entry(acpi_device_bid(device), acpi_ac_dir);
-               acpi_device_dir(device) = NULL;
-       }
-
-       return 0;
-}
-#endif
-
 /* --------------------------------------------------------------------------
                                    Driver Model
    -------------------------------------------------------------------------- */
 
-static void acpi_ac_notify(struct acpi_device *device, u32 event)
+static void acpi_ac_notify_handler(acpi_handle handle, u32 event, void *data)
 {
-       struct acpi_ac *ac = acpi_driver_data(device);
-
+       struct acpi_ac *ac = data;
 
        if (!ac)
                return;
@@ -267,10 +141,10 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
                        msleep(ac_sleep_before_get_state_ms);
 
                acpi_ac_get_state(ac);
-               acpi_bus_generate_netlink_event(device->pnp.device_class,
-                                                 dev_name(&device->dev), event,
-                                                 (u32) ac->state);
-               acpi_notifier_call_chain(device, event, (u32) ac->state);
+               acpi_bus_generate_netlink_event(ac->adev->pnp.device_class,
+                                               dev_name(&ac->pdev->dev),
+                                               event, (u32) ac->state);
+               acpi_notifier_call_chain(ac->adev, event, (u32) ac->state);
                kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
        }
 
@@ -295,53 +169,55 @@ static struct dmi_system_id ac_dmi_table[] = {
        {},
 };
 
-static int acpi_ac_add(struct acpi_device *device)
+static int acpi_ac_probe(struct platform_device *pdev)
 {
        int result = 0;
        struct acpi_ac *ac = NULL;
+       struct acpi_device *adev;
 
-
-       if (!device)
+       if (!pdev)
                return -EINVAL;
 
+       result = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
+       if (result)
+               return -ENODEV;
+
        ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
        if (!ac)
                return -ENOMEM;
 
-       ac->device = device;
-       strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
-       strcpy(acpi_device_class(device), ACPI_AC_CLASS);
-       device->driver_data = ac;
+       strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME);
+       strcpy(acpi_device_class(adev), ACPI_AC_CLASS);
+       ac->adev = adev;
+       ac->pdev = pdev;
+       platform_set_drvdata(pdev, ac);
 
        result = acpi_ac_get_state(ac);
        if (result)
                goto end;
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       result = acpi_ac_add_fs(device);
-#endif
-       if (result)
-               goto end;
-       ac->charger.name = acpi_device_bid(device);
+       ac->charger.name = acpi_device_bid(adev);
        ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
        ac->charger.properties = ac_props;
        ac->charger.num_properties = ARRAY_SIZE(ac_props);
        ac->charger.get_property = get_ac_property;
-       result = power_supply_register(&ac->device->dev, &ac->charger);
+       result = power_supply_register(&pdev->dev, &ac->charger);
        if (result)
                goto end;
 
+       result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev),
+                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler, ac);
+       if (result) {
+               power_supply_unregister(&ac->charger);
+               goto end;
+       }
        printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
-              acpi_device_name(device), acpi_device_bid(device),
+              acpi_device_name(adev), acpi_device_bid(adev),
               ac->state ? "on-line" : "off-line");
 
-      end:
-       if (result) {
-#ifdef CONFIG_ACPI_PROCFS_POWER
-               acpi_ac_remove_fs(device);
-#endif
+end:
+       if (result)
                kfree(ac);
-       }
 
        dmi_check_system(ac_dmi_table);
        return result;
@@ -356,7 +232,7 @@ static int acpi_ac_resume(struct device *dev)
        if (!dev)
                return -EINVAL;
 
-       ac = acpi_driver_data(to_acpi_device(dev));
+       ac = platform_get_drvdata(to_platform_device(dev));
        if (!ac)
                return -EINVAL;
 
@@ -368,28 +244,44 @@ static int acpi_ac_resume(struct device *dev)
        return 0;
 }
 #endif
+static SIMPLE_DEV_PM_OPS(acpi_ac_pm_ops, NULL, acpi_ac_resume);
 
-static int acpi_ac_remove(struct acpi_device *device)
+static int acpi_ac_remove(struct platform_device *pdev)
 {
-       struct acpi_ac *ac = NULL;
-
+       struct acpi_ac *ac;
 
-       if (!device || !acpi_driver_data(device))
+       if (!pdev)
                return -EINVAL;
 
-       ac = acpi_driver_data(device);
+       acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
+                       ACPI_DEVICE_NOTIFY, acpi_ac_notify_handler);
 
+       ac = platform_get_drvdata(pdev);
        if (ac->charger.dev)
                power_supply_unregister(&ac->charger);
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_ac_remove_fs(device);
-#endif
 
        kfree(ac);
 
        return 0;
 }
 
+static const struct acpi_device_id acpi_ac_match[] = {
+       { "ACPI0003", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, acpi_ac_match);
+
+static struct platform_driver acpi_ac_driver = {
+       .probe          = acpi_ac_probe,
+       .remove         = acpi_ac_remove,
+       .driver         = {
+               .name   = "acpi-ac",
+               .owner  = THIS_MODULE,
+               .pm     = &acpi_ac_pm_ops,
+               .acpi_match_table = ACPI_PTR(acpi_ac_match),
+       },
+};
+
 static int __init acpi_ac_init(void)
 {
        int result;
@@ -397,34 +289,16 @@ static int __init acpi_ac_init(void)
        if (acpi_disabled)
                return -ENODEV;
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_ac_dir = acpi_lock_ac_dir();
-       if (!acpi_ac_dir)
+       result = platform_driver_register(&acpi_ac_driver);
+       if (result < 0)
                return -ENODEV;
-#endif
-
-       result = acpi_bus_register_driver(&acpi_ac_driver);
-       if (result < 0) {
-#ifdef CONFIG_ACPI_PROCFS_POWER
-               acpi_unlock_ac_dir(acpi_ac_dir);
-#endif
-               return -ENODEV;
-       }
 
        return 0;
 }
 
 static void __exit acpi_ac_exit(void)
 {
-
-       acpi_bus_unregister_driver(&acpi_ac_driver);
-
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_unlock_ac_dir(acpi_ac_dir);
-#endif
-
-       return;
+       platform_driver_unregister(&acpi_ac_driver);
 }
-
 module_init(acpi_ac_init);
 module_exit(acpi_ac_exit);
index a6977e12d5745ab5f2015e2f2879174bddd64bc0..ac0f52f6df2b862052a3de423ac039a6bd2eefe8 100644 (file)
@@ -1,8 +1,9 @@
 /*
  *  acpi_ipmi.c - ACPI IPMI opregion
  *
- *  Copyright (C) 2010 Intel Corporation
- *  Copyright (C) 2010 Zhao Yakui <yakui.zhao@intel.com>
+ *  Copyright (C) 2010, 2013 Intel Corporation
+ *    Author: Zhao Yakui <yakui.zhao@intel.com>
+ *            Lv Zheng <lv.zheng@intel.com>
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  *
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
-#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/interrupt.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
 #include <linux/ipmi.h>
-#include <linux/device.h>
-#include <linux/pnp.h>
 #include <linux/spinlock.h>
 
 MODULE_AUTHOR("Zhao Yakui");
 MODULE_DESCRIPTION("ACPI IPMI Opregion driver");
 MODULE_LICENSE("GPL");
 
-#define IPMI_FLAGS_HANDLER_INSTALL     0
-
 #define ACPI_IPMI_OK                   0
 #define ACPI_IPMI_TIMEOUT              0x10
 #define ACPI_IPMI_UNKNOWN              0x07
 /* the IPMI timeout is 5s */
-#define IPMI_TIMEOUT                   (5 * HZ)
+#define IPMI_TIMEOUT                   (5000)
+#define ACPI_IPMI_MAX_MSG_LENGTH       64
 
 struct acpi_ipmi_device {
        /* the device list attached to driver_data.ipmi_devices */
        struct list_head head;
+
        /* the IPMI request message list */
        struct list_head tx_msg_list;
-       spinlock_t      tx_msg_lock;
+
+       spinlock_t tx_msg_lock;
        acpi_handle handle;
-       struct pnp_dev *pnp_dev;
-       ipmi_user_t     user_interface;
+       struct device *dev;
+       ipmi_user_t user_interface;
        int ipmi_ifnum; /* IPMI interface number */
        long curr_msgid;
-       unsigned long flags;
-       struct ipmi_smi_info smi_data;
+       bool dead;
+       struct kref kref;
 };
 
 struct ipmi_driver_data {
-       struct list_head        ipmi_devices;
-       struct ipmi_smi_watcher bmc_events;
-       struct ipmi_user_hndl   ipmi_hndlrs;
-       struct mutex            ipmi_lock;
+       struct list_head ipmi_devices;
+       struct ipmi_smi_watcher bmc_events;
+       struct ipmi_user_hndl ipmi_hndlrs;
+       struct mutex ipmi_lock;
+
+       /*
+        * NOTE: IPMI System Interface Selection
+        * There is no system interface specified by the IPMI operation
+        * region access.  We try to select one system interface with ACPI
+        * handle set.  IPMI messages passed from the ACPI codes are sent
+        * to this selected global IPMI system interface.
+        */
+       struct acpi_ipmi_device *selected_smi;
 };
 
 struct acpi_ipmi_msg {
        struct list_head head;
+
        /*
         * General speaking the addr type should be SI_ADDR_TYPE. And
         * the addr channel should be BMC.
@@ -86,30 +85,31 @@ struct acpi_ipmi_msg {
         */
        struct ipmi_addr addr;
        long tx_msgid;
+
        /* it is used to track whether the IPMI message is finished */
        struct completion tx_complete;
+
        struct kernel_ipmi_msg tx_message;
-       int     msg_done;
-       /* tx data . And copy it from ACPI object buffer */
-       u8      tx_data[64];
-       int     tx_len;
-       u8      rx_data[64];
-       int     rx_len;
+       int msg_done;
+
+       /* tx/rx data . And copy it from/to ACPI object buffer */
+       u8 data[ACPI_IPMI_MAX_MSG_LENGTH];
+       u8 rx_len;
+
        struct acpi_ipmi_device *device;
+       struct kref kref;
 };
 
 /* IPMI request/response buffer per ACPI 4.0, sec 5.5.2.4.3.2 */
 struct acpi_ipmi_buffer {
        u8 status;
        u8 length;
-       u8 data[64];
+       u8 data[ACPI_IPMI_MAX_MSG_LENGTH];
 };
 
 static void ipmi_register_bmc(int iface, struct device *dev);
 static void ipmi_bmc_gone(int iface);
 static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
-static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device);
-static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device);
 
 static struct ipmi_driver_data driver_data = {
        .ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices),
@@ -121,29 +121,142 @@ static struct ipmi_driver_data driver_data = {
        .ipmi_hndlrs = {
                .ipmi_recv_hndl = ipmi_msg_handler,
        },
+       .ipmi_lock = __MUTEX_INITIALIZER(driver_data.ipmi_lock)
 };
 
-static struct acpi_ipmi_msg *acpi_alloc_ipmi_msg(struct acpi_ipmi_device *ipmi)
+static struct acpi_ipmi_device *
+ipmi_dev_alloc(int iface, struct device *dev, acpi_handle handle)
+{
+       struct acpi_ipmi_device *ipmi_device;
+       int err;
+       ipmi_user_t user;
+
+       ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL);
+       if (!ipmi_device)
+               return NULL;
+
+       kref_init(&ipmi_device->kref);
+       INIT_LIST_HEAD(&ipmi_device->head);
+       INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
+       spin_lock_init(&ipmi_device->tx_msg_lock);
+       ipmi_device->handle = handle;
+       ipmi_device->dev = get_device(dev);
+       ipmi_device->ipmi_ifnum = iface;
+
+       err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs,
+                              ipmi_device, &user);
+       if (err) {
+               put_device(dev);
+               kfree(ipmi_device);
+               return NULL;
+       }
+       ipmi_device->user_interface = user;
+
+       return ipmi_device;
+}
+
+static void ipmi_dev_release(struct acpi_ipmi_device *ipmi_device)
+{
+       ipmi_destroy_user(ipmi_device->user_interface);
+       put_device(ipmi_device->dev);
+       kfree(ipmi_device);
+}
+
+static void ipmi_dev_release_kref(struct kref *kref)
+{
+       struct acpi_ipmi_device *ipmi =
+               container_of(kref, struct acpi_ipmi_device, kref);
+
+       ipmi_dev_release(ipmi);
+}
+
+static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device)
+{
+       list_del(&ipmi_device->head);
+       if (driver_data.selected_smi == ipmi_device)
+               driver_data.selected_smi = NULL;
+
+       /*
+        * Always setting dead flag after deleting from the list or
+        * list_for_each_entry() codes must get changed.
+        */
+       ipmi_device->dead = true;
+}
+
+static struct acpi_ipmi_device *acpi_ipmi_dev_get(void)
+{
+       struct acpi_ipmi_device *ipmi_device = NULL;
+
+       mutex_lock(&driver_data.ipmi_lock);
+       if (driver_data.selected_smi) {
+               ipmi_device = driver_data.selected_smi;
+               kref_get(&ipmi_device->kref);
+       }
+       mutex_unlock(&driver_data.ipmi_lock);
+
+       return ipmi_device;
+}
+
+static void acpi_ipmi_dev_put(struct acpi_ipmi_device *ipmi_device)
+{
+       kref_put(&ipmi_device->kref, ipmi_dev_release_kref);
+}
+
+static struct acpi_ipmi_msg *ipmi_msg_alloc(void)
 {
+       struct acpi_ipmi_device *ipmi;
        struct acpi_ipmi_msg *ipmi_msg;
-       struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+
+       ipmi = acpi_ipmi_dev_get();
+       if (!ipmi)
+               return NULL;
 
        ipmi_msg = kzalloc(sizeof(struct acpi_ipmi_msg), GFP_KERNEL);
-       if (!ipmi_msg)  {
-               dev_warn(&pnp_dev->dev, "Can't allocate memory for ipmi_msg\n");
+       if (!ipmi_msg) {
+               acpi_ipmi_dev_put(ipmi);
                return NULL;
        }
+
+       kref_init(&ipmi_msg->kref);
        init_completion(&ipmi_msg->tx_complete);
        INIT_LIST_HEAD(&ipmi_msg->head);
        ipmi_msg->device = ipmi;
+       ipmi_msg->msg_done = ACPI_IPMI_UNKNOWN;
+
        return ipmi_msg;
 }
 
-#define                IPMI_OP_RGN_NETFN(offset)       ((offset >> 8) & 0xff)
-#define                IPMI_OP_RGN_CMD(offset)         (offset & 0xff)
-static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
-                               acpi_physical_address address,
-                               acpi_integer *value)
+static void ipmi_msg_release(struct acpi_ipmi_msg *tx_msg)
+{
+       acpi_ipmi_dev_put(tx_msg->device);
+       kfree(tx_msg);
+}
+
+static void ipmi_msg_release_kref(struct kref *kref)
+{
+       struct acpi_ipmi_msg *tx_msg =
+               container_of(kref, struct acpi_ipmi_msg, kref);
+
+       ipmi_msg_release(tx_msg);
+}
+
+static struct acpi_ipmi_msg *acpi_ipmi_msg_get(struct acpi_ipmi_msg *tx_msg)
+{
+       kref_get(&tx_msg->kref);
+
+       return tx_msg;
+}
+
+static void acpi_ipmi_msg_put(struct acpi_ipmi_msg *tx_msg)
+{
+       kref_put(&tx_msg->kref, ipmi_msg_release_kref);
+}
+
+#define IPMI_OP_RGN_NETFN(offset)      ((offset >> 8) & 0xff)
+#define IPMI_OP_RGN_CMD(offset)                (offset & 0xff)
+static int acpi_format_ipmi_request(struct acpi_ipmi_msg *tx_msg,
+                                   acpi_physical_address address,
+                                   acpi_integer *value)
 {
        struct kernel_ipmi_msg *msg;
        struct acpi_ipmi_buffer *buffer;
@@ -151,21 +264,31 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
        unsigned long flags;
 
        msg = &tx_msg->tx_message;
+
        /*
         * IPMI network function and command are encoded in the address
         * within the IPMI OpRegion; see ACPI 4.0, sec 5.5.2.4.3.
         */
        msg->netfn = IPMI_OP_RGN_NETFN(address);
        msg->cmd = IPMI_OP_RGN_CMD(address);
-       msg->data = tx_msg->tx_data;
+       msg->data = tx_msg->data;
+
        /*
         * value is the parameter passed by the IPMI opregion space handler.
         * It points to the IPMI request message buffer
         */
        buffer = (struct acpi_ipmi_buffer *)value;
+
        /* copy the tx message data */
+       if (buffer->length > ACPI_IPMI_MAX_MSG_LENGTH) {
+               dev_WARN_ONCE(tx_msg->device->dev, true,
+                             "Unexpected request (msg len %d).\n",
+                             buffer->length);
+               return -EINVAL;
+       }
        msg->data_len = buffer->length;
-       memcpy(tx_msg->tx_data, buffer->data, msg->data_len);
+       memcpy(tx_msg->data, buffer->data, msg->data_len);
+
        /*
         * now the default type is SYSTEM_INTERFACE and channel type is BMC.
         * If the netfn is APP_REQUEST and the cmd is SEND_MESSAGE,
@@ -179,14 +302,17 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg,
 
        /* Get the msgid */
        device = tx_msg->device;
+
        spin_lock_irqsave(&device->tx_msg_lock, flags);
        device->curr_msgid++;
        tx_msg->tx_msgid = device->curr_msgid;
        spin_unlock_irqrestore(&device->tx_msg_lock, flags);
+
+       return 0;
 }
 
 static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
-               acpi_integer *value, int rem_time)
+                                     acpi_integer *value)
 {
        struct acpi_ipmi_buffer *buffer;
 
@@ -195,110 +321,158 @@ static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg,
         * IPMI message returned by IPMI command.
         */
        buffer = (struct acpi_ipmi_buffer *)value;
-       if (!rem_time && !msg->msg_done) {
-               buffer->status = ACPI_IPMI_TIMEOUT;
-               return;
-       }
+
        /*
-        * If the flag of msg_done is not set or the recv length is zero, it
-        * means that the IPMI command is not executed correctly.
-        * The status code will be ACPI_IPMI_UNKNOWN.
+        * If the flag of msg_done is not set, it means that the IPMI command is
+        * not executed correctly.
         */
-       if (!msg->msg_done || !msg->rx_len) {
-               buffer->status = ACPI_IPMI_UNKNOWN;
+       buffer->status = msg->msg_done;
+       if (msg->msg_done != ACPI_IPMI_OK)
                return;
-       }
+
        /*
         * If the IPMI response message is obtained correctly, the status code
         * will be ACPI_IPMI_OK
         */
-       buffer->status = ACPI_IPMI_OK;
        buffer->length = msg->rx_len;
-       memcpy(buffer->data, msg->rx_data, msg->rx_len);
+       memcpy(buffer->data, msg->data, msg->rx_len);
 }
 
 static void ipmi_flush_tx_msg(struct acpi_ipmi_device *ipmi)
 {
-       struct acpi_ipmi_msg *tx_msg, *temp;
-       int count = HZ / 10;
-       struct pnp_dev *pnp_dev = ipmi->pnp_dev;
+       struct acpi_ipmi_msg *tx_msg;
+       unsigned long flags;
+
+       /*
+        * NOTE: On-going ipmi_recv_msg
+        * ipmi_msg_handler() may still be invoked by ipmi_si after
+        * flushing.  But it is safe to do a fast flushing on module_exit()
+        * without waiting for all ipmi_recv_msg(s) to complete from
+        * ipmi_msg_handler() as it is ensured by ipmi_si that all
+        * ipmi_recv_msg(s) are freed after invoking ipmi_destroy_user().
+        */
+       spin_lock_irqsave(&ipmi->tx_msg_lock, flags);
+       while (!list_empty(&ipmi->tx_msg_list)) {
+               tx_msg = list_first_entry(&ipmi->tx_msg_list,
+                                         struct acpi_ipmi_msg,
+                                         head);
+               list_del(&tx_msg->head);
+               spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags);
 
-       list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) {
                /* wake up the sleep thread on the Tx msg */
                complete(&tx_msg->tx_complete);
+               acpi_ipmi_msg_put(tx_msg);
+               spin_lock_irqsave(&ipmi->tx_msg_lock, flags);
        }
+       spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags);
+}
+
+static void ipmi_cancel_tx_msg(struct acpi_ipmi_device *ipmi,
+                              struct acpi_ipmi_msg *msg)
+{
+       struct acpi_ipmi_msg *tx_msg, *temp;
+       bool msg_found = false;
+       unsigned long flags;
 
-       /* wait for about 100ms to flush the tx message list */
-       while (count--) {
-               if (list_empty(&ipmi->tx_msg_list))
+       spin_lock_irqsave(&ipmi->tx_msg_lock, flags);
+       list_for_each_entry_safe(tx_msg, temp, &ipmi->tx_msg_list, head) {
+               if (msg == tx_msg) {
+                       msg_found = true;
+                       list_del(&tx_msg->head);
                        break;
-               schedule_timeout(1);
+               }
        }
-       if (!list_empty(&ipmi->tx_msg_list))
-               dev_warn(&pnp_dev->dev, "tx msg list is not NULL\n");
+       spin_unlock_irqrestore(&ipmi->tx_msg_lock, flags);
+
+       if (msg_found)
+               acpi_ipmi_msg_put(tx_msg);
 }
 
 static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data)
 {
        struct acpi_ipmi_device *ipmi_device = user_msg_data;
-       int msg_found = 0;
-       struct acpi_ipmi_msg *tx_msg;
-       struct pnp_dev *pnp_dev = ipmi_device->pnp_dev;
+       bool msg_found = false;
+       struct acpi_ipmi_msg *tx_msg, *temp;
+       struct device *dev = ipmi_device->dev;
        unsigned long flags;
 
        if (msg->user != ipmi_device->user_interface) {
-               dev_warn(&pnp_dev->dev, "Unexpected response is returned. "
-                       "returned user %p, expected user %p\n",
-                       msg->user, ipmi_device->user_interface);
-               ipmi_free_recv_msg(msg);
-               return;
+               dev_warn(dev,
+                        "Unexpected response is returned. returned user %p, expected user %p\n",
+                        msg->user, ipmi_device->user_interface);
+               goto out_msg;
        }
+
        spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
-       list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) {
+       list_for_each_entry_safe(tx_msg, temp, &ipmi_device->tx_msg_list, head) {
                if (msg->msgid == tx_msg->tx_msgid) {
-                       msg_found = 1;
+                       msg_found = true;
+                       list_del(&tx_msg->head);
                        break;
                }
        }
-
        spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
+
        if (!msg_found) {
-               dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is "
-                       "returned.\n", msg->msgid);
-               ipmi_free_recv_msg(msg);
-               return;
+               dev_warn(dev,
+                        "Unexpected response (msg id %ld) is returned.\n",
+                        msg->msgid);
+               goto out_msg;
        }
 
-       if (msg->msg.data_len) {
-               /* copy the response data to Rx_data buffer */
-               memcpy(tx_msg->rx_data, msg->msg_data, msg->msg.data_len);
-               tx_msg->rx_len = msg->msg.data_len;
-               tx_msg->msg_done = 1;
+       /* copy the response data to Rx_data buffer */
+       if (msg->msg.data_len > ACPI_IPMI_MAX_MSG_LENGTH) {
+               dev_WARN_ONCE(dev, true,
+                             "Unexpected response (msg len %d).\n",
+                             msg->msg.data_len);
+               goto out_comp;
        }
+
+       /* response msg is an error msg */
+       msg->recv_type = IPMI_RESPONSE_RECV_TYPE;
+       if (msg->recv_type == IPMI_RESPONSE_RECV_TYPE &&
+           msg->msg.data_len == 1) {
+               if (msg->msg.data[0] == IPMI_TIMEOUT_COMPLETION_CODE) {
+                       dev_WARN_ONCE(dev, true,
+                                     "Unexpected response (timeout).\n");
+                       tx_msg->msg_done = ACPI_IPMI_TIMEOUT;
+               }
+               goto out_comp;
+       }
+
+       tx_msg->rx_len = msg->msg.data_len;
+       memcpy(tx_msg->data, msg->msg.data, tx_msg->rx_len);
+       tx_msg->msg_done = ACPI_IPMI_OK;
+
+out_comp:
        complete(&tx_msg->tx_complete);
+       acpi_ipmi_msg_put(tx_msg);
+out_msg:
        ipmi_free_recv_msg(msg);
-};
+}
 
 static void ipmi_register_bmc(int iface, struct device *dev)
 {
        struct acpi_ipmi_device *ipmi_device, *temp;
-       struct pnp_dev *pnp_dev;
-       ipmi_user_t             user;
        int err;
        struct ipmi_smi_info smi_data;
        acpi_handle handle;
 
        err = ipmi_get_smi_info(iface, &smi_data);
-
        if (err)
                return;
 
-       if (smi_data.addr_src != SI_ACPI) {
-               put_device(smi_data.dev);
-               return;
-       }
-
+       if (smi_data.addr_src != SI_ACPI)
+               goto err_ref;
        handle = smi_data.addr_info.acpi_info.acpi_handle;
+       if (!handle)
+               goto err_ref;
+
+       ipmi_device = ipmi_dev_alloc(iface, smi_data.dev, handle);
+       if (!ipmi_device) {
+               dev_warn(smi_data.dev, "Can't create IPMI user interface\n");
+               goto err_ref;
+       }
 
        mutex_lock(&driver_data.ipmi_lock);
        list_for_each_entry(temp, &driver_data.ipmi_devices, head) {
@@ -307,34 +481,20 @@ static void ipmi_register_bmc(int iface, struct device *dev)
                 * to the device list, don't add it again.
                 */
                if (temp->handle == handle)
-                       goto out;
+                       goto err_lock;
        }
-
-       ipmi_device = kzalloc(sizeof(*ipmi_device), GFP_KERNEL);
-
-       if (!ipmi_device)
-               goto out;
-
-       pnp_dev = to_pnp_dev(smi_data.dev);
-       ipmi_device->handle = handle;
-       ipmi_device->pnp_dev = pnp_dev;
-
-       err = ipmi_create_user(iface, &driver_data.ipmi_hndlrs,
-                                       ipmi_device, &user);
-       if (err) {
-               dev_warn(&pnp_dev->dev, "Can't create IPMI user interface\n");
-               kfree(ipmi_device);
-               goto out;
-       }
-       acpi_add_ipmi_device(ipmi_device);
-       ipmi_device->user_interface = user;
-       ipmi_device->ipmi_ifnum = iface;
+       if (!driver_data.selected_smi)
+               driver_data.selected_smi = ipmi_device;
+       list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices);
        mutex_unlock(&driver_data.ipmi_lock);
-       memcpy(&ipmi_device->smi_data, &smi_data, sizeof(struct ipmi_smi_info));
+
+       put_device(smi_data.dev);
        return;
 
-out:
+err_lock:
        mutex_unlock(&driver_data.ipmi_lock);
+       ipmi_dev_release(ipmi_device);
+err_ref:
        put_device(smi_data.dev);
        return;
 }
@@ -342,23 +502,29 @@ out:
 static void ipmi_bmc_gone(int iface)
 {
        struct acpi_ipmi_device *ipmi_device, *temp;
+       bool dev_found = false;
 
        mutex_lock(&driver_data.ipmi_lock);
        list_for_each_entry_safe(ipmi_device, temp,
-                               &driver_data.ipmi_devices, head) {
-               if (ipmi_device->ipmi_ifnum != iface)
-                       continue;
-
-               acpi_remove_ipmi_device(ipmi_device);
-               put_device(ipmi_device->smi_data.dev);
-               kfree(ipmi_device);
-               break;
+                                &driver_data.ipmi_devices, head) {
+               if (ipmi_device->ipmi_ifnum != iface) {
+                       dev_found = true;
+                       __ipmi_dev_kill(ipmi_device);
+                       break;
+               }
        }
+       if (!driver_data.selected_smi)
+               driver_data.selected_smi = list_first_entry_or_null(
+                                       &driver_data.ipmi_devices,
+                                       struct acpi_ipmi_device, head);
        mutex_unlock(&driver_data.ipmi_lock);
+
+       if (dev_found) {
+               ipmi_flush_tx_msg(ipmi_device);
+               acpi_ipmi_dev_put(ipmi_device);
+       }
 }
-/* --------------------------------------------------------------------------
- *                     Address Space Management
- * -------------------------------------------------------------------------- */
+
 /*
  * This is the IPMI opregion space handler.
  * @function: indicates the read/write. In fact as the IPMI message is driven
@@ -371,17 +537,17 @@ static void ipmi_bmc_gone(int iface)
  *          the response IPMI message returned by IPMI command.
  * @handler_context: IPMI device context.
  */
-
 static acpi_status
 acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
-                     u32 bits, acpi_integer *value,
-                     void *handler_context, void *region_context)
+                       u32 bits, acpi_integer *value,
+                       void *handler_context, void *region_context)
 {
        struct acpi_ipmi_msg *tx_msg;
-       struct acpi_ipmi_device *ipmi_device = handler_context;
-       int err, rem_time;
+       struct acpi_ipmi_device *ipmi_device;
+       int err;
        acpi_status status;
        unsigned long flags;
+
        /*
         * IPMI opregion message.
         * IPMI message is firstly written to the BMC and system software
@@ -391,118 +557,75 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
        if ((function & ACPI_IO_MASK) == ACPI_READ)
                return AE_TYPE;
 
-       if (!ipmi_device->user_interface)
+       tx_msg = ipmi_msg_alloc();
+       if (!tx_msg)
                return AE_NOT_EXIST;
+       ipmi_device = tx_msg->device;
 
-       tx_msg = acpi_alloc_ipmi_msg(ipmi_device);
-       if (!tx_msg)
-               return AE_NO_MEMORY;
+       if (acpi_format_ipmi_request(tx_msg, address, value) != 0) {
+               ipmi_msg_release(tx_msg);
+               return AE_TYPE;
+       }
 
-       acpi_format_ipmi_msg(tx_msg, address, value);
+       acpi_ipmi_msg_get(tx_msg);
+       mutex_lock(&driver_data.ipmi_lock);
+       /* Do not add a tx_msg that can not be flushed. */
+       if (ipmi_device->dead) {
+               mutex_unlock(&driver_data.ipmi_lock);
+               ipmi_msg_release(tx_msg);
+               return AE_NOT_EXIST;
+       }
        spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
        list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list);
        spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
+       mutex_unlock(&driver_data.ipmi_lock);
+
        err = ipmi_request_settime(ipmi_device->user_interface,
-                                       &tx_msg->addr,
-                                       tx_msg->tx_msgid,
-                                       &tx_msg->tx_message,
-                                       NULL, 0, 0, 0);
+                                  &tx_msg->addr,
+                                  tx_msg->tx_msgid,
+                                  &tx_msg->tx_message,
+                                  NULL, 0, 0, IPMI_TIMEOUT);
        if (err) {
                status = AE_ERROR;
-               goto end_label;
+               goto out_msg;
        }
-       rem_time = wait_for_completion_timeout(&tx_msg->tx_complete,
-                                       IPMI_TIMEOUT);
-       acpi_format_ipmi_response(tx_msg, value, rem_time);
+       wait_for_completion(&tx_msg->tx_complete);
+
+       acpi_format_ipmi_response(tx_msg, value);
        status = AE_OK;
 
-end_label:
-       spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags);
-       list_del(&tx_msg->head);
-       spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags);
-       kfree(tx_msg);
+out_msg:
+       ipmi_cancel_tx_msg(ipmi_device, tx_msg);
+       acpi_ipmi_msg_put(tx_msg);
        return status;
 }
 
-static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi)
-{
-       if (!test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
-               return;
-
-       acpi_remove_address_space_handler(ipmi->handle,
-                               ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler);
-
-       clear_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
-}
-
-static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi)
+static int __init acpi_ipmi_init(void)
 {
+       int result;
        acpi_status status;
 
-       if (test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
+       if (acpi_disabled)
                return 0;
 
-       status = acpi_install_address_space_handler(ipmi->handle,
+       status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
                                                    ACPI_ADR_SPACE_IPMI,
                                                    &acpi_ipmi_space_handler,
-                                                   NULL, ipmi);
+                                                   NULL, NULL);
        if (ACPI_FAILURE(status)) {
-               struct pnp_dev *pnp_dev = ipmi->pnp_dev;
-               dev_warn(&pnp_dev->dev, "Can't register IPMI opregion space "
-                       "handle\n");
+               pr_warn("Can't register IPMI opregion space handle\n");
                return -EINVAL;
        }
-       set_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
-       return 0;
-}
-
-static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device)
-{
-
-       INIT_LIST_HEAD(&ipmi_device->head);
-
-       spin_lock_init(&ipmi_device->tx_msg_lock);
-       INIT_LIST_HEAD(&ipmi_device->tx_msg_list);
-       ipmi_install_space_handler(ipmi_device);
-
-       list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices);
-}
-
-static void acpi_remove_ipmi_device(struct acpi_ipmi_device *ipmi_device)
-{
-       /*
-        * If the IPMI user interface is created, it should be
-        * destroyed.
-        */
-       if (ipmi_device->user_interface) {
-               ipmi_destroy_user(ipmi_device->user_interface);
-               ipmi_device->user_interface = NULL;
-       }
-       /* flush the Tx_msg list */
-       if (!list_empty(&ipmi_device->tx_msg_list))
-               ipmi_flush_tx_msg(ipmi_device);
-
-       list_del(&ipmi_device->head);
-       ipmi_remove_space_handler(ipmi_device);
-}
-
-static int __init acpi_ipmi_init(void)
-{
-       int result = 0;
-
-       if (acpi_disabled)
-               return result;
-
-       mutex_init(&driver_data.ipmi_lock);
-
        result = ipmi_smi_watcher_register(&driver_data.bmc_events);
+       if (result)
+               pr_err("Can't register IPMI system interface watcher\n");
 
        return result;
 }
 
 static void __exit acpi_ipmi_exit(void)
 {
-       struct acpi_ipmi_device *ipmi_device, *temp;
+       struct acpi_ipmi_device *ipmi_device;
 
        if (acpi_disabled)
                return;
@@ -516,13 +639,22 @@ static void __exit acpi_ipmi_exit(void)
         * handler and free it.
         */
        mutex_lock(&driver_data.ipmi_lock);
-       list_for_each_entry_safe(ipmi_device, temp,
-                               &driver_data.ipmi_devices, head) {
-               acpi_remove_ipmi_device(ipmi_device);
-               put_device(ipmi_device->smi_data.dev);
-               kfree(ipmi_device);
+       while (!list_empty(&driver_data.ipmi_devices)) {
+               ipmi_device = list_first_entry(&driver_data.ipmi_devices,
+                                              struct acpi_ipmi_device,
+                                              head);
+               __ipmi_dev_kill(ipmi_device);
+               mutex_unlock(&driver_data.ipmi_lock);
+
+               ipmi_flush_tx_msg(ipmi_device);
+               acpi_ipmi_dev_put(ipmi_device);
+
+               mutex_lock(&driver_data.ipmi_lock);
        }
        mutex_unlock(&driver_data.ipmi_lock);
+       acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
+                                         ACPI_ADR_SPACE_IPMI,
+                                         &acpi_ipmi_space_handler);
 }
 
 module_init(acpi_ipmi_init);
index fb78bb9ad8f65888817fc6f7a3ecb2563b975134..d3961014aad7ff9d77bcb296ec2f851f96d64b5b 100644 (file)
@@ -30,6 +30,7 @@ ACPI_MODULE_NAME("acpi_lpss");
 /* Offsets relative to LPSS_PRIVATE_OFFSET */
 #define LPSS_GENERAL                   0x08
 #define LPSS_GENERAL_LTR_MODE_SW       BIT(2)
+#define LPSS_GENERAL_UART_RTS_OVRD     BIT(3)
 #define LPSS_SW_LTR                    0x10
 #define LPSS_AUTO_LTR                  0x14
 #define LPSS_TX_INT                    0x20
@@ -68,11 +69,16 @@ struct lpss_private_data {
 
 static void lpss_uart_setup(struct lpss_private_data *pdata)
 {
-       unsigned int tx_int_offset = pdata->dev_desc->prv_offset + LPSS_TX_INT;
+       unsigned int offset;
        u32 reg;
 
-       reg = readl(pdata->mmio_base + tx_int_offset);
-       writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + tx_int_offset);
+       offset = pdata->dev_desc->prv_offset + LPSS_TX_INT;
+       reg = readl(pdata->mmio_base + offset);
+       writel(reg | LPSS_TX_INT_MASK, pdata->mmio_base + offset);
+
+       offset = pdata->dev_desc->prv_offset + LPSS_GENERAL;
+       reg = readl(pdata->mmio_base + offset);
+       writel(reg | LPSS_GENERAL_UART_RTS_OVRD, pdata->mmio_base + offset);
 }
 
 static struct lpss_device_desc lpt_dev_desc = {
index 999adb5499c7270626466a7d74870531c3e3ae28..551dad712ffec451364a08c01487a1987c10d7db 100644 (file)
@@ -152,8 +152,9 @@ static int acpi_memory_check_device(struct acpi_memory_device *mem_device)
        unsigned long long current_status;
 
        /* Get device present/absent information from the _STA */
-       if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle, "_STA",
-                                              NULL, &current_status)))
+       if (ACPI_FAILURE(acpi_evaluate_integer(mem_device->device->handle,
+                                              METHOD_NAME__STA, NULL,
+                                              &current_status)))
                return -ENODEV;
        /*
         * Check for device status. Device should be
@@ -281,7 +282,7 @@ static void acpi_memory_remove_memory(struct acpi_memory_device *mem_device)
                if (!info->enabled)
                        continue;
 
-               if (nid < 0)
+               if (nid == NUMA_NO_NODE)
                        nid = memory_add_physaddr_to_nid(info->start_addr);
 
                acpi_unbind_memory_blocks(info, handle);
index 1bde12708f9e112c708bb71ae8d6162af5e367a9..8a4cfc7e71f0f83cc7a8644e75eab627c8e3c52d 100644 (file)
@@ -29,6 +29,13 @@ ACPI_MODULE_NAME("platform");
 static const struct acpi_device_id acpi_platform_device_ids[] = {
 
        { "PNP0D40" },
+       { "ACPI0003" },
+       { "VPC2004" },
+       { "BCM4752" },
+
+       /* Intel Smart Sound Technology */
+       { "INT33C8" },
+       { "80860F28" },
 
        { }
 };
index f29e06efa47976eba16e3b4e449a8b5a9235909f..3c1d6b0c09a4b7d1eeeb9347a7c743d1c7487988 100644 (file)
@@ -140,15 +140,11 @@ static int acpi_processor_errata_piix4(struct pci_dev *dev)
        return 0;
 }
 
-static int acpi_processor_errata(struct acpi_processor *pr)
+static int acpi_processor_errata(void)
 {
        int result = 0;
        struct pci_dev *dev = NULL;
 
-
-       if (!pr)
-               return -EINVAL;
-
        /*
         * PIIX4
         */
@@ -181,7 +177,7 @@ static int acpi_processor_hotadd_init(struct acpi_processor *pr)
        cpu_maps_update_begin();
        cpu_hotplug_begin();
 
-       ret = acpi_map_lsapic(pr->handle, &pr->id);
+       ret = acpi_map_lsapic(pr->handle, pr->apic_id, &pr->id);
        if (ret)
                goto out;
 
@@ -219,11 +215,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
        int cpu_index, device_declaration = 0;
        acpi_status status = AE_OK;
        static int cpu0_initialized;
+       unsigned long long value;
 
-       if (num_online_cpus() > 1)
-               errata.smp = TRUE;
-
-       acpi_processor_errata(pr);
+       acpi_processor_errata();
 
        /*
         * Check to see if we have bus mastering arbitration control.  This
@@ -247,18 +241,12 @@ static int acpi_processor_get_info(struct acpi_device *device)
                        return -ENODEV;
                }
 
-               /*
-                * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP.
-                *      >>> 'acpi_get_processor_id(acpi_id, &id)' in
-                *      arch/xxx/acpi.c
-                */
                pr->acpi_id = object.processor.proc_id;
        } else {
                /*
                 * Declared with "Device" statement; match _UID.
                 * Note that we don't handle string _UIDs yet.
                 */
-               unsigned long long value;
                status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID,
                                                NULL, &value);
                if (ACPI_FAILURE(status)) {
@@ -270,7 +258,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
                device_declaration = 1;
                pr->acpi_id = value;
        }
-       cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id);
+       pr->apic_id = acpi_get_apicid(pr->handle, device_declaration,
+                                       pr->acpi_id);
+       cpu_index = acpi_map_cpuid(pr->apic_id, pr->acpi_id);
 
        /* Handle UP system running SMP kernel, with no LAPIC in MADT */
        if (!cpu0_initialized && (cpu_index == -1) &&
@@ -332,9 +322,9 @@ static int acpi_processor_get_info(struct acpi_device *device)
         * ensure we get the right value in the "physical id" field
         * of /proc/cpuinfo
         */
-       status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer);
+       status = acpi_evaluate_integer(pr->handle, "_SUN", NULL, &value);
        if (ACPI_SUCCESS(status))
-               arch_fix_phys_package_id(pr->id, object.integer.value);
+               arch_fix_phys_package_id(pr->id, value);
 
        return 0;
 }
index 9feba08c29fe08b772e976fdefc7531300eb4d2d..27c36a5251b56dd560b04333a773ddd875360fd3 100644 (file)
@@ -113,11 +113,12 @@ void acpi_db_display_handlers(void);
 ACPI_HW_DEPENDENT_RETURN_VOID(void
                              acpi_db_generate_gpe(char *gpe_arg,
                                                   char *block_arg))
+ ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_db_generate_sci(void))
 
 /*
  * dbconvert - miscellaneous conversion routines
  */
- acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value);
+acpi_status acpi_db_hex_char_to_value(int hex_char, u8 *return_value);
 
 acpi_status acpi_db_convert_to_package(char *string, union acpi_object *object);
 
@@ -154,6 +155,8 @@ void acpi_db_set_scope(char *name);
 
 void acpi_db_dump_namespace(char *start_arg, char *depth_arg);
 
+void acpi_db_dump_namespace_paths(void);
+
 void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg);
 
 acpi_status acpi_db_find_name_in_namespace(char *name_arg);
index ab0e9771038127c83365fc3b1d72de841612fb99..3ae5fd02ae649f46677b362af9aa4cd39c4e6e3b 100644 (file)
@@ -242,11 +242,11 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
  */
 u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context);
 
-u32 acpi_ev_install_sci_handler(void);
+u32 acpi_ev_sci_dispatch(void);
 
-acpi_status acpi_ev_remove_sci_handler(void);
+u32 acpi_ev_install_sci_handler(void);
 
-u32 acpi_ev_initialize_SCI(u32 program_SCI);
+acpi_status acpi_ev_remove_all_sci_handlers(void);
 
 ACPI_HW_DEPENDENT_RETURN_VOID(void acpi_ev_terminate(void))
 #endif                         /* __ACEVENTS_H__  */
index 90e846f985fa30caa109c8de336ac8e677a29bee..0fba431f4fcb90fd1bad8ec85b870486a33b70d6 100644 (file)
@@ -269,6 +269,7 @@ ACPI_EXTERN acpi_table_handler acpi_gbl_table_handler;
 ACPI_EXTERN void *acpi_gbl_table_handler_context;
 ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
 ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler;
+ACPI_EXTERN struct acpi_sci_handler_info *acpi_gbl_sci_handler_list;
 
 /* Owner ID support */
 
@@ -445,13 +446,6 @@ ACPI_EXTERN u8 acpi_gbl_db_opt_tables;
 ACPI_EXTERN u8 acpi_gbl_db_opt_stats;
 ACPI_EXTERN u8 acpi_gbl_db_opt_ini_methods;
 ACPI_EXTERN u8 acpi_gbl_db_opt_no_region_support;
-
-ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS];
-ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS];
-ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE];
-ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE];
-ACPI_EXTERN char acpi_gbl_db_scope_buf[80];
-ACPI_EXTERN char acpi_gbl_db_debug_filename[80];
 ACPI_EXTERN u8 acpi_gbl_db_output_to_file;
 ACPI_EXTERN char *acpi_gbl_db_buffer;
 ACPI_EXTERN char *acpi_gbl_db_filename;
@@ -459,6 +453,16 @@ ACPI_EXTERN u32 acpi_gbl_db_debug_level;
 ACPI_EXTERN u32 acpi_gbl_db_console_debug_level;
 ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_db_scope_node;
 
+ACPI_EXTERN char *acpi_gbl_db_args[ACPI_DEBUGGER_MAX_ARGS];
+ACPI_EXTERN acpi_object_type acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS];
+
+/* These buffers should all be the same size */
+
+ACPI_EXTERN char acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_scope_buf[ACPI_DB_LINE_BUFFER_SIZE];
+ACPI_EXTERN char acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE];
+
 /*
  * Statistic globals
  */
index 0ed00669cd217a0754087ed61bc89465e31804f3..be9e30ee60488b7de09a61ea1dd198fe84ebf43b 100644 (file)
@@ -398,6 +398,14 @@ struct acpi_simple_repair_info {
  *
  ****************************************************************************/
 
+/* Dispatch info for each host-installed SCI handler */
+
+struct acpi_sci_handler_info {
+       struct acpi_sci_handler_info *next;
+       acpi_sci_handler address;       /* Address of handler */
+       void *context;          /* Context to be passed to handler */
+};
+
 /* Dispatch info for each GPE -- either a method or handler, cannot be both */
 
 struct acpi_gpe_handler_info {
index 40b04bd5579e36abec92165270c44f576e8fddc4..e6138ac4a16054038275fc81f2f616cd70c26d5d 100644 (file)
@@ -213,6 +213,12 @@ acpi_ns_dump_objects(acpi_object_type type,
                     u8 display_type,
                     u32 max_depth,
                     acpi_owner_id owner_id, acpi_handle start_handle);
+
+void
+acpi_ns_dump_object_paths(acpi_object_type type,
+                         u8 display_type,
+                         u32 max_depth,
+                         acpi_owner_id owner_id, acpi_handle start_handle);
 #endif                         /* ACPI_FUTURE_USAGE */
 
 /*
index b24dbb80fab8f681dc3089cd8a29c700f5cb57c7..d52339090b604ba1569f599a03a45e6712e54ee9 100644 (file)
@@ -196,7 +196,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  *
  * FUNCTION:    acpi_ev_get_gpe_xrupt_block
  *
- * PARAMETERS:  interrupt_number     - Interrupt for a GPE block
+ * PARAMETERS:  interrupt_number            - Interrupt for a GPE block
  *
  * RETURN:      A GPE interrupt block
  *
index 1b111ef74903771f8f9a8f690aef85b752f65c61..a5687540e9a66e5ba20bfeb9772ad5351b20bc61 100644 (file)
@@ -264,13 +264,6 @@ void acpi_ev_terminate(void)
 
                status = acpi_ev_walk_gpe_list(acpi_hw_disable_gpe_block, NULL);
 
-               /* Remove SCI handler */
-
-               status = acpi_ev_remove_sci_handler();
-               if (ACPI_FAILURE(status)) {
-                       ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
-               }
-
                status = acpi_ev_remove_global_lock_handler();
                if (ACPI_FAILURE(status)) {
                        ACPI_ERROR((AE_INFO,
@@ -280,6 +273,13 @@ void acpi_ev_terminate(void)
                acpi_gbl_events_initialized = FALSE;
        }
 
+       /* Remove SCI handlers */
+
+       status = acpi_ev_remove_all_sci_handlers();
+       if (ACPI_FAILURE(status)) {
+               ACPI_ERROR((AE_INFO, "Could not remove SCI handler"));
+       }
+
        /* Deallocate all handler objects installed within GPE info structs */
 
        status = acpi_ev_walk_gpe_list(acpi_ev_delete_gpe_handlers, NULL);
index cea14d6fc76c976db580144f93d28d890ff3938f..6293d6bb6fe1e2a0348f90505ebbaa36f2f3f3b2 100644 (file)
@@ -217,16 +217,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
                if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {
                        region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;
 
-                       if (region_obj2->extra.region_context) {
-
-                               /* The handler for this region was already installed */
-
-                               ACPI_FREE(region_context);
-                       } else {
-                               /*
-                                * Save the returned context for use in all accesses to
-                                * this particular region
-                                */
+                       /*
+                        * Save the returned context for use in all accesses to
+                        * the handler for this particular region
+                        */
+                       if (!(region_obj2->extra.region_context)) {
                                region_obj2->extra.region_context =
                                    region_context;
                        }
@@ -402,6 +397,14 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
                                                 handler_obj->address_space.
                                                 context, region_context);
 
+                               /*
+                                * region_context should have been released by the deactivate
+                                * operation. We don't need access to it anymore here.
+                                */
+                               if (region_context) {
+                                       *region_context = NULL;
+                               }
+
                                /* Init routine may fail, Just ignore errors */
 
                                if (ACPI_FAILURE(status)) {
index b905acf7aacdc1d90f9189b9660df28eb6777f08..94d9ebddf5755031a34b654664b0be6471330662 100644 (file)
@@ -52,6 +52,50 @@ ACPI_MODULE_NAME("evsci")
 /* Local prototypes */
 static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context);
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ev_sci_dispatch
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status code indicates whether interrupt was handled.
+ *
+ * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers.
+ *
+ ******************************************************************************/
+
+u32 acpi_ev_sci_dispatch(void)
+{
+       struct acpi_sci_handler_info *sci_handler;
+       acpi_cpu_flags flags;
+       u32 int_status = ACPI_INTERRUPT_NOT_HANDLED;
+
+       ACPI_FUNCTION_NAME(ev_sci_dispatch);
+
+       /* Are there any host-installed SCI handlers? */
+
+       if (!acpi_gbl_sci_handler_list) {
+               return (int_status);
+       }
+
+       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+       /* Invoke all host-installed SCI handlers */
+
+       sci_handler = acpi_gbl_sci_handler_list;
+       while (sci_handler) {
+
+               /* Invoke the installed handler (at interrupt level) */
+
+               int_status |= sci_handler->address(sci_handler->context);
+
+               sci_handler = sci_handler->next;
+       }
+
+       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+       return (int_status);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ev_sci_xrupt_handler
@@ -89,6 +133,10 @@ static u32 ACPI_SYSTEM_XFACE acpi_ev_sci_xrupt_handler(void *context)
         */
        interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
 
+       /* Invoke all host-installed SCI handlers */
+
+       interrupt_handled |= acpi_ev_sci_dispatch();
+
        return_UINT32(interrupt_handled);
 }
 
@@ -112,14 +160,13 @@ u32 ACPI_SYSTEM_XFACE acpi_ev_gpe_xrupt_handler(void *context)
        ACPI_FUNCTION_TRACE(ev_gpe_xrupt_handler);
 
        /*
-        * We are guaranteed by the ACPI CA initialization/shutdown code that
+        * We are guaranteed by the ACPICA initialization/shutdown code that
         * if this interrupt handler is installed, ACPI is enabled.
         */
 
        /* GPEs: Check for and dispatch any GPEs that have occurred */
 
        interrupt_handled |= acpi_ev_gpe_detect(gpe_xrupt_list);
-
        return_UINT32(interrupt_handled);
 }
 
@@ -150,15 +197,15 @@ u32 acpi_ev_install_sci_handler(void)
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_ev_remove_sci_handler
+ * FUNCTION:    acpi_ev_remove_all_sci_handlers
  *
  * PARAMETERS:  none
  *
- * RETURN:      E_OK if handler uninstalled OK, E_ERROR if handler was not
+ * RETURN:      AE_OK if handler uninstalled, AE_ERROR if handler was not
  *              installed to begin with
  *
  * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be
- *              taken.
+ *              taken. Remove all host-installed SCI handlers.
  *
  * Note:  It doesn't seem important to disable all events or set the event
  *        enable registers to their original values. The OS should disable
@@ -167,11 +214,13 @@ u32 acpi_ev_install_sci_handler(void)
  *
  ******************************************************************************/
 
-acpi_status acpi_ev_remove_sci_handler(void)
+acpi_status acpi_ev_remove_all_sci_handlers(void)
 {
+       struct acpi_sci_handler_info *sci_handler;
+       acpi_cpu_flags flags;
        acpi_status status;
 
-       ACPI_FUNCTION_TRACE(ev_remove_sci_handler);
+       ACPI_FUNCTION_TRACE(ev_remove_all_sci_handlers);
 
        /* Just let the OS remove the handler and disable the level */
 
@@ -179,6 +228,21 @@ acpi_status acpi_ev_remove_sci_handler(void)
            acpi_os_remove_interrupt_handler((u32) acpi_gbl_FADT.sci_interrupt,
                                             acpi_ev_sci_xrupt_handler);
 
+       if (!acpi_gbl_sci_handler_list) {
+               return (status);
+       }
+
+       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+       /* Free all host-installed SCI handlers */
+
+       while (acpi_gbl_sci_handler_list) {
+               sci_handler = acpi_gbl_sci_handler_list;
+               acpi_gbl_sci_handler_list = sci_handler->next;
+               ACPI_FREE(sci_handler);
+       }
+
+       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        return_ACPI_STATUS(status);
 }
 
index ca5fba99c33bc82a302f8eb246ca41224a2cbada..6f56146a6f88a55a7d0ebebaa4be0bbd84126bd0 100644 (file)
@@ -383,6 +383,144 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
 #endif                         /*  ACPI_FUTURE_USAGE  */
 
 #if (!ACPI_REDUCED_HARDWARE)
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_install_sci_handler
+ *
+ * PARAMETERS:  address             - Address of the handler
+ *              context             - Value passed to the handler on each SCI
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install a handler for a System Control Interrupt.
+ *
+ ******************************************************************************/
+acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)
+{
+       struct acpi_sci_handler_info *new_sci_handler;
+       struct acpi_sci_handler_info *sci_handler;
+       acpi_cpu_flags flags;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(acpi_install_sci_handler);
+
+       if (!address) {
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
+       }
+
+       /* Allocate and init a handler object */
+
+       new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info));
+       if (!new_sci_handler) {
+               return_ACPI_STATUS(AE_NO_MEMORY);
+       }
+
+       new_sci_handler->address = address;
+       new_sci_handler->context = context;
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+       if (ACPI_FAILURE(status)) {
+               goto exit;
+       }
+
+       /* Lock list during installation */
+
+       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+       sci_handler = acpi_gbl_sci_handler_list;
+
+       /* Ensure handler does not already exist */
+
+       while (sci_handler) {
+               if (address == sci_handler->address) {
+                       status = AE_ALREADY_EXISTS;
+                       goto unlock_and_exit;
+               }
+
+               sci_handler = sci_handler->next;
+       }
+
+       /* Install the new handler into the global list (at head) */
+
+       new_sci_handler->next = acpi_gbl_sci_handler_list;
+       acpi_gbl_sci_handler_list = new_sci_handler;
+
+      unlock_and_exit:
+
+       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+       (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+      exit:
+       if (ACPI_FAILURE(status)) {
+               ACPI_FREE(new_sci_handler);
+       }
+       return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_remove_sci_handler
+ *
+ * PARAMETERS:  address             - Address of the handler
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Remove a handler for a System Control Interrupt.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
+{
+       struct acpi_sci_handler_info *prev_sci_handler;
+       struct acpi_sci_handler_info *next_sci_handler;
+       acpi_cpu_flags flags;
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(acpi_remove_sci_handler);
+
+       if (!address) {
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
+       }
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
+       /* Remove the SCI handler with lock */
+
+       flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
+
+       prev_sci_handler = NULL;
+       next_sci_handler = acpi_gbl_sci_handler_list;
+       while (next_sci_handler) {
+               if (next_sci_handler->address == address) {
+
+                       /* Unlink and free the SCI handler info block */
+
+                       if (prev_sci_handler) {
+                               prev_sci_handler->next = next_sci_handler->next;
+                       } else {
+                               acpi_gbl_sci_handler_list =
+                                   next_sci_handler->next;
+                       }
+
+                       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+                       ACPI_FREE(next_sci_handler);
+                       goto unlock_and_exit;
+               }
+
+               prev_sci_handler = next_sci_handler;
+               next_sci_handler = next_sci_handler->next;
+       }
+
+       acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
+       status = AE_NOT_EXIST;
+
+      unlock_and_exit:
+       (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+       return_ACPI_STATUS(status);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_install_global_event_handler
@@ -398,6 +536,7 @@ ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
  *              Can be used to update event counters, etc.
  *
  ******************************************************************************/
+
 acpi_status
 acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
 {
index 5ee7a814cd9207db34d42b8945867e415ab733bb..f81fb068d20ed34613615d76217841e2c7297ad4 100644 (file)
@@ -119,7 +119,8 @@ ACPI_EXPORT_SYMBOL(acpi_reset)
  ******************************************************************************/
 acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
 {
-       u32 value;
+       u32 value_lo;
+       u32 value_hi;
        u32 width;
        u64 address;
        acpi_status status;
@@ -137,13 +138,8 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
                return (status);
        }
 
-       /* Initialize entire 64-bit return value to zero */
-
-       *return_value = 0;
-       value = 0;
-
        /*
-        * Two address spaces supported: Memory or IO. PCI_Config is
+        * Two address spaces supported: Memory or I/O. PCI_Config is
         * not supported here because the GAS structure is insufficient
         */
        if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
@@ -155,29 +151,35 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
                }
        } else {                /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
 
+               value_lo = 0;
+               value_hi = 0;
+
                width = reg->bit_width;
                if (width == 64) {
                        width = 32;     /* Break into two 32-bit transfers */
                }
 
                status = acpi_hw_read_port((acpi_io_address)
-                                          address, &value, width);
+                                          address, &value_lo, width);
                if (ACPI_FAILURE(status)) {
                        return (status);
                }
-               *return_value = value;
 
                if (reg->bit_width == 64) {
 
                        /* Read the top 32 bits */
 
                        status = acpi_hw_read_port((acpi_io_address)
-                                                  (address + 4), &value, 32);
+                                                  (address + 4), &value_hi,
+                                                  32);
                        if (ACPI_FAILURE(status)) {
                                return (status);
                        }
-                       *return_value |= ((u64)value << 32);
                }
+
+               /* Set the return value only if status is AE_OK */
+
+               *return_value = (value_lo | ((u64)value_hi << 32));
        }
 
        ACPI_DEBUG_PRINT((ACPI_DB_IO,
@@ -186,7 +188,7 @@ acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
                          ACPI_FORMAT_UINT64(address),
                          acpi_ut_get_region_name(reg->space_id)));
 
-       return (status);
+       return (AE_OK);
 }
 
 ACPI_EXPORT_SYMBOL(acpi_read)
index c5316e5bd4abf2efce5aad7d4968708d3bccdb3d..aff79c7392ff3ff20e19e0a8f43a82709b0053ef 100644 (file)
@@ -424,8 +424,9 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
                                        /* Current scope has no parent scope */
 
                                        ACPI_ERROR((AE_INFO,
-                                                   "ACPI path has too many parent prefixes (^) "
-                                                   "- reached beyond root node"));
+                                                   "%s: Path has too many parent prefixes (^) "
+                                                   "- reached beyond root node",
+                                                   pathname));
                                        return_ACPI_STATUS(AE_NOT_FOUND);
                                }
                        }
index 7418c77fde8c70db88d0d0af9c0c6a8fcad6cad5..80633851cb2fd00e7886bdc4deacf0929726818a 100644 (file)
@@ -59,6 +59,17 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
 #endif
 
 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+
+#ifdef ACPI_FUTURE_USAGE
+static acpi_status
+acpi_ns_dump_one_object_path(acpi_handle obj_handle,
+                            u32 level, void *context, void **return_value);
+
+static acpi_status
+acpi_ns_get_max_depth(acpi_handle obj_handle,
+                     u32 level, void *context, void **return_value);
+#endif                         /* ACPI_FUTURE_USAGE */
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_print_pathname
@@ -671,6 +682,129 @@ acpi_ns_dump_objects(acpi_object_type type,
 }
 #endif                         /* ACPI_FUTURE_USAGE */
 
+#ifdef ACPI_FUTURE_USAGE
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_dump_one_object_path, acpi_ns_get_max_depth
+ *
+ * PARAMETERS:  obj_handle          - Node to be dumped
+ *              level               - Nesting level of the handle
+ *              context             - Passed into walk_namespace
+ *              return_value        - Not used
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Dump the full pathname to a namespace object. acp_ns_get_max_depth
+ *              computes the maximum nesting depth in the namespace tree, in
+ *              order to simplify formatting in acpi_ns_dump_one_object_path.
+ *              These procedures are user_functions called by acpi_ns_walk_namespace.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ns_dump_one_object_path(acpi_handle obj_handle,
+                            u32 level, void *context, void **return_value)
+{
+       u32 max_level = *((u32 *)context);
+       char *pathname;
+       struct acpi_namespace_node *node;
+       int path_indent;
+
+       if (!obj_handle) {
+               return (AE_OK);
+       }
+
+       node = acpi_ns_validate_handle(obj_handle);
+       pathname = acpi_ns_get_external_pathname(node);
+
+       path_indent = 1;
+       if (level <= max_level) {
+               path_indent = max_level - level + 1;
+       }
+
+       acpi_os_printf("%2d%*s%-12s%*s",
+                      level, level, " ", acpi_ut_get_type_name(node->type),
+                      path_indent, " ");
+
+       acpi_os_printf("%s\n", &pathname[1]);
+       ACPI_FREE(pathname);
+       return (AE_OK);
+}
+
+static acpi_status
+acpi_ns_get_max_depth(acpi_handle obj_handle,
+                     u32 level, void *context, void **return_value)
+{
+       u32 *max_level = (u32 *)context;
+
+       if (level > *max_level) {
+               *max_level = level;
+       }
+       return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_dump_object_paths
+ *
+ * PARAMETERS:  type                - Object type to be dumped
+ *              display_type        - 0 or ACPI_DISPLAY_SUMMARY
+ *              max_depth           - Maximum depth of dump. Use ACPI_UINT32_MAX
+ *                                    for an effectively unlimited depth.
+ *              owner_id            - Dump only objects owned by this ID. Use
+ *                                    ACPI_UINT32_MAX to match all owners.
+ *              start_handle        - Where in namespace to start/end search
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Dump full object pathnames within the loaded namespace. Uses
+ *              acpi_ns_walk_namespace in conjunction with acpi_ns_dump_one_object_path.
+ *
+ ******************************************************************************/
+
+void
+acpi_ns_dump_object_paths(acpi_object_type type,
+                         u8 display_type,
+                         u32 max_depth,
+                         acpi_owner_id owner_id, acpi_handle start_handle)
+{
+       acpi_status status;
+       u32 max_level = 0;
+
+       ACPI_FUNCTION_ENTRY();
+
+       /*
+        * Just lock the entire namespace for the duration of the dump.
+        * We don't want any changes to the namespace during this time,
+        * especially the temporary nodes since we are going to display
+        * them also.
+        */
+       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+       if (ACPI_FAILURE(status)) {
+               acpi_os_printf("Could not acquire namespace mutex\n");
+               return;
+       }
+
+       /* Get the max depth of the namespace tree, for formatting later */
+
+       (void)acpi_ns_walk_namespace(type, start_handle, max_depth,
+                                    ACPI_NS_WALK_NO_UNLOCK |
+                                    ACPI_NS_WALK_TEMP_NODES,
+                                    acpi_ns_get_max_depth, NULL,
+                                    (void *)&max_level, NULL);
+
+       /* Now dump the entire namespace */
+
+       (void)acpi_ns_walk_namespace(type, start_handle, max_depth,
+                                    ACPI_NS_WALK_NO_UNLOCK |
+                                    ACPI_NS_WALK_TEMP_NODES,
+                                    acpi_ns_dump_one_object_path, NULL,
+                                    (void *)&max_level, NULL);
+
+       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+}
+#endif                         /* ACPI_FUTURE_USAGE */
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_dump_entry
index b38b4b07f86e31d8920a7b1467ba4fb6604fc6eb..481a6b4a9b2ffbeb64418abd6b458697faa74eb5 100644 (file)
@@ -605,11 +605,19 @@ acpi_walk_namespace(acpi_object_type type,
                goto unlock_and_exit;
        }
 
+       /* Now we can validate the starting node */
+
+       if (!acpi_ns_validate_handle(start_object)) {
+               status = AE_BAD_PARAMETER;
+               goto unlock_and_exit2;
+       }
+
        status = acpi_ns_walk_namespace(type, start_object, max_depth,
                                        ACPI_NS_WALK_UNLOCK,
                                        descending_callback, ascending_callback,
                                        context, return_value);
 
+      unlock_and_exit2:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 
       unlock_and_exit:
index 42a13c0d7015360ab44c684ab9645500fc63f1d8..9e6788f9ba0ff5865bd2caeac1d05918c407fa11 100644 (file)
@@ -80,16 +80,10 @@ acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
                }
        }
 
-       /* FACS is the odd table, has no standard ACPI header and no checksum */
+       /* Always calculate checksum, ignore bad checksum if requested */
 
-       if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) {
-
-               /* Always calculate checksum, ignore bad checksum if requested */
-
-               status =
-                   acpi_tb_verify_checksum(table_desc->pointer,
-                                           table_desc->length);
-       }
+       status =
+           acpi_tb_verify_checksum(table_desc->pointer, table_desc->length);
 
        return_ACPI_STATUS(status);
 }
index dc963f823d2c094bb204b7baf6734fb6d340c007..9a47715af1f37893e2985b370b7b63e9f57a01bf 100644 (file)
@@ -138,7 +138,7 @@ acpi_tb_print_table_header(acpi_physical_address address,
                ACPI_INFO((AE_INFO, "%4.4s %p %05X",
                           header->signature, ACPI_CAST_PTR(void, address),
                           header->length));
-       } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) {
+       } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) {
 
                /* RSDP has no common fields */
 
@@ -190,6 +190,16 @@ acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
 {
        u8 checksum;
 
+       /*
+        * FACS/S3PT:
+        * They are the odd tables, have no standard ACPI header and no checksum
+        */
+
+       if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_S3PT) ||
+           ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FACS)) {
+               return (AE_OK);
+       }
+
        /* Compute the checksum on the table */
 
        checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
index 948c95e80d44765f41e82bb62c92bb4c3405bb01..1c95fabbe6a42171b868ea85e6825a3363dc31d5 100644 (file)
@@ -68,8 +68,7 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
         * Note: Sometimes there exists more than one RSDP in memory; the valid
         * RSDP has a valid checksum, all others have an invalid checksum.
         */
-       if (ACPI_STRNCMP((char *)rsdp->signature, ACPI_SIG_RSDP,
-                        sizeof(ACPI_SIG_RSDP) - 1) != 0) {
+       if (!ACPI_VALIDATE_RSDP_SIG(rsdp->signature)) {
 
                /* Nope, BAD Signature */
 
index 5796e11a0671d32fad4329262e05b51d038cd38e..ffd0db509d347d00ba6da16f6c8c03e047d323f2 100644 (file)
@@ -190,7 +190,7 @@ acpi_debug_print(u32 requested_debug_level,
         * Display the module name, current line number, thread ID (if requested),
         * current procedure nesting level, and the current procedure name
         */
-       acpi_os_printf("%8s-%04ld ", module_name, line_number);
+       acpi_os_printf("%9s-%04ld ", module_name, line_number);
 
        if (ACPI_LV_THREADS & acpi_dbg_level) {
                acpi_os_printf("[%u] ", (u32)thread_id);
index d6f26bf8a0626d0d7497baeaf1ce931d3a76c9ba..046d5b059c07f3ce56b6f35d2c2aac3ea9d59f0d 100644 (file)
@@ -291,7 +291,7 @@ acpi_status acpi_ut_init_globals(void)
 
 #if (!ACPI_REDUCED_HARDWARE)
 
-       /* GPE support */
+       /* GPE/SCI support */
 
        acpi_gbl_all_gpes_initialized = FALSE;
        acpi_gbl_gpe_xrupt_list_head = NULL;
@@ -300,6 +300,7 @@ acpi_status acpi_ut_init_globals(void)
        acpi_current_gpe_count = 0;
 
        acpi_gbl_global_event_handler = NULL;
+       acpi_gbl_sci_handler_list = NULL;
 
 #endif                         /* !ACPI_REDUCED_HARDWARE */
 
index 2c9958cd7a4350ae675b76ad338904999ae149c1..fbf1aceda8b8ab915a7d2476d78db2b6e2b94e68 100644 (file)
 #include <linux/suspend.h>
 #include <asm/unaligned.h>
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <asm/uaccess.h>
-#endif
-
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 #include <linux/power_supply.h>
@@ -72,19 +66,6 @@ static unsigned int cache_time = 1000;
 module_param(cache_time, uint, 0644);
 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-extern struct proc_dir_entry *acpi_lock_battery_dir(void);
-extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
-
-enum acpi_battery_files {
-       info_tag = 0,
-       state_tag,
-       alarm_tag,
-       ACPI_BATTERY_NUMFILES,
-};
-
-#endif
-
 static const struct acpi_device_id battery_device_ids[] = {
        {"PNP0C0A", 0},
        {"", 0},
@@ -320,14 +301,6 @@ static enum power_supply_property energy_battery_props[] = {
        POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-inline char *acpi_battery_units(struct acpi_battery *battery)
-{
-       return (battery->power_unit == ACPI_BATTERY_POWER_UNIT_MA) ?
-               "mA" : "mW";
-}
-#endif
-
 /* --------------------------------------------------------------------------
                                Battery Management
    -------------------------------------------------------------------------- */
@@ -740,279 +713,6 @@ static void acpi_battery_refresh(struct acpi_battery *battery)
        sysfs_add_battery(battery);
 }
 
-/* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-
-#ifdef CONFIG_ACPI_PROCFS_POWER
-static struct proc_dir_entry *acpi_battery_dir;
-
-static int acpi_battery_print_info(struct seq_file *seq, int result)
-{
-       struct acpi_battery *battery = seq->private;
-
-       if (result)
-               goto end;
-
-       seq_printf(seq, "present:                 %s\n",
-                  acpi_battery_present(battery) ? "yes" : "no");
-       if (!acpi_battery_present(battery))
-               goto end;
-       if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "design capacity:         unknown\n");
-       else
-               seq_printf(seq, "design capacity:         %d %sh\n",
-                          battery->design_capacity,
-                          acpi_battery_units(battery));
-
-       if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "last full capacity:      unknown\n");
-       else
-               seq_printf(seq, "last full capacity:      %d %sh\n",
-                          battery->full_charge_capacity,
-                          acpi_battery_units(battery));
-
-       seq_printf(seq, "battery technology:      %srechargeable\n",
-                  (!battery->technology)?"non-":"");
-
-       if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "design voltage:          unknown\n");
-       else
-               seq_printf(seq, "design voltage:          %d mV\n",
-                          battery->design_voltage);
-       seq_printf(seq, "design capacity warning: %d %sh\n",
-                  battery->design_capacity_warning,
-                  acpi_battery_units(battery));
-       seq_printf(seq, "design capacity low:     %d %sh\n",
-                  battery->design_capacity_low,
-                  acpi_battery_units(battery));
-       seq_printf(seq, "cycle count:             %i\n", battery->cycle_count);
-       seq_printf(seq, "capacity granularity 1:  %d %sh\n",
-                  battery->capacity_granularity_1,
-                  acpi_battery_units(battery));
-       seq_printf(seq, "capacity granularity 2:  %d %sh\n",
-                  battery->capacity_granularity_2,
-                  acpi_battery_units(battery));
-       seq_printf(seq, "model number:            %s\n", battery->model_number);
-       seq_printf(seq, "serial number:           %s\n", battery->serial_number);
-       seq_printf(seq, "battery type:            %s\n", battery->type);
-       seq_printf(seq, "OEM info:                %s\n", battery->oem_info);
-      end:
-       if (result)
-               seq_printf(seq, "ERROR: Unable to read battery info\n");
-       return result;
-}
-
-static int acpi_battery_print_state(struct seq_file *seq, int result)
-{
-       struct acpi_battery *battery = seq->private;
-
-       if (result)
-               goto end;
-
-       seq_printf(seq, "present:                 %s\n",
-                  acpi_battery_present(battery) ? "yes" : "no");
-       if (!acpi_battery_present(battery))
-               goto end;
-
-       seq_printf(seq, "capacity state:          %s\n",
-                       (battery->state & 0x04) ? "critical" : "ok");
-       if ((battery->state & 0x01) && (battery->state & 0x02))
-               seq_printf(seq,
-                          "charging state:          charging/discharging\n");
-       else if (battery->state & 0x01)
-               seq_printf(seq, "charging state:          discharging\n");
-       else if (battery->state & 0x02)
-               seq_printf(seq, "charging state:          charging\n");
-       else
-               seq_printf(seq, "charging state:          charged\n");
-
-       if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "present rate:            unknown\n");
-       else
-               seq_printf(seq, "present rate:            %d %s\n",
-                          battery->rate_now, acpi_battery_units(battery));
-
-       if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "remaining capacity:      unknown\n");
-       else
-               seq_printf(seq, "remaining capacity:      %d %sh\n",
-                          battery->capacity_now, acpi_battery_units(battery));
-       if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
-               seq_printf(seq, "present voltage:         unknown\n");
-       else
-               seq_printf(seq, "present voltage:         %d mV\n",
-                          battery->voltage_now);
-      end:
-       if (result)
-               seq_printf(seq, "ERROR: Unable to read battery state\n");
-
-       return result;
-}
-
-static int acpi_battery_print_alarm(struct seq_file *seq, int result)
-{
-       struct acpi_battery *battery = seq->private;
-
-       if (result)
-               goto end;
-
-       if (!acpi_battery_present(battery)) {
-               seq_printf(seq, "present:                 no\n");
-               goto end;
-       }
-       seq_printf(seq, "alarm:                   ");
-       if (!battery->alarm)
-               seq_printf(seq, "unsupported\n");
-       else
-               seq_printf(seq, "%u %sh\n", battery->alarm,
-                               acpi_battery_units(battery));
-      end:
-       if (result)
-               seq_printf(seq, "ERROR: Unable to read battery alarm\n");
-       return result;
-}
-
-static ssize_t acpi_battery_write_alarm(struct file *file,
-                                       const char __user * buffer,
-                                       size_t count, loff_t * ppos)
-{
-       int result = 0;
-       char alarm_string[12] = { '\0' };
-       struct seq_file *m = file->private_data;
-       struct acpi_battery *battery = m->private;
-
-       if (!battery || (count > sizeof(alarm_string) - 1))
-               return -EINVAL;
-       if (!acpi_battery_present(battery)) {
-               result = -ENODEV;
-               goto end;
-       }
-       if (copy_from_user(alarm_string, buffer, count)) {
-               result = -EFAULT;
-               goto end;
-       }
-       alarm_string[count] = '\0';
-       battery->alarm = simple_strtol(alarm_string, NULL, 0);
-       result = acpi_battery_set_alarm(battery);
-      end:
-       if (!result)
-               return count;
-       return result;
-}
-
-typedef int(*print_func)(struct seq_file *seq, int result);
-
-static print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = {
-       acpi_battery_print_info,
-       acpi_battery_print_state,
-       acpi_battery_print_alarm,
-};
-
-static int acpi_battery_read(int fid, struct seq_file *seq)
-{
-       struct acpi_battery *battery = seq->private;
-       int result = acpi_battery_update(battery);
-       return acpi_print_funcs[fid](seq, result);
-}
-
-#define DECLARE_FILE_FUNCTIONS(_name) \
-static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \
-{ \
-       return acpi_battery_read(_name##_tag, seq); \
-} \
-static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \
-{ \
-       return single_open(file, acpi_battery_read_##_name, PDE_DATA(inode)); \
-}
-
-DECLARE_FILE_FUNCTIONS(info);
-DECLARE_FILE_FUNCTIONS(state);
-DECLARE_FILE_FUNCTIONS(alarm);
-
-#undef DECLARE_FILE_FUNCTIONS
-
-#define FILE_DESCRIPTION_RO(_name) \
-       { \
-       .name = __stringify(_name), \
-       .mode = S_IRUGO, \
-       .ops = { \
-               .open = acpi_battery_##_name##_open_fs, \
-               .read = seq_read, \
-               .llseek = seq_lseek, \
-               .release = single_release, \
-               .owner = THIS_MODULE, \
-               }, \
-       }
-
-#define FILE_DESCRIPTION_RW(_name) \
-       { \
-       .name = __stringify(_name), \
-       .mode = S_IFREG | S_IRUGO | S_IWUSR, \
-       .ops = { \
-               .open = acpi_battery_##_name##_open_fs, \
-               .read = seq_read, \
-               .llseek = seq_lseek, \
-               .write = acpi_battery_write_##_name, \
-               .release = single_release, \
-               .owner = THIS_MODULE, \
-               }, \
-       }
-
-static const struct battery_file {
-       struct file_operations ops;
-       umode_t mode;
-       const char *name;
-} acpi_battery_file[] = {
-       FILE_DESCRIPTION_RO(info),
-       FILE_DESCRIPTION_RO(state),
-       FILE_DESCRIPTION_RW(alarm),
-};
-
-#undef FILE_DESCRIPTION_RO
-#undef FILE_DESCRIPTION_RW
-
-static int acpi_battery_add_fs(struct acpi_device *device)
-{
-       struct proc_dir_entry *entry = NULL;
-       int i;
-
-       printk(KERN_WARNING PREFIX "Deprecated procfs I/F for battery is loaded,"
-                       " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
-       if (!acpi_device_dir(device)) {
-               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-                                                    acpi_battery_dir);
-               if (!acpi_device_dir(device))
-                       return -ENODEV;
-       }
-
-       for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
-               entry = proc_create_data(acpi_battery_file[i].name,
-                                        acpi_battery_file[i].mode,
-                                        acpi_device_dir(device),
-                                        &acpi_battery_file[i].ops,
-                                        acpi_driver_data(device));
-               if (!entry)
-                       return -ENODEV;
-       }
-       return 0;
-}
-
-static void acpi_battery_remove_fs(struct acpi_device *device)
-{
-       int i;
-       if (!acpi_device_dir(device))
-               return;
-       for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i)
-               remove_proc_entry(acpi_battery_file[i].name,
-                                 acpi_device_dir(device));
-
-       remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
-       acpi_device_dir(device) = NULL;
-}
-
-#endif
-
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -1075,15 +775,6 @@ static int acpi_battery_add(struct acpi_device *device)
        result = acpi_battery_update(battery);
        if (result)
                goto fail;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       result = acpi_battery_add_fs(device);
-#endif
-       if (result) {
-#ifdef CONFIG_ACPI_PROCFS_POWER
-               acpi_battery_remove_fs(device);
-#endif
-               goto fail;
-       }
 
        printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
                ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
@@ -1110,9 +801,6 @@ static int acpi_battery_remove(struct acpi_device *device)
                return -EINVAL;
        battery = acpi_driver_data(device);
        unregister_pm_notifier(&battery->pm_nb);
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_battery_remove_fs(device);
-#endif
        sysfs_remove_battery(battery);
        mutex_destroy(&battery->lock);
        mutex_destroy(&battery->sysfs_lock);
@@ -1158,18 +846,7 @@ static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
 {
        if (acpi_disabled)
                return;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_battery_dir = acpi_lock_battery_dir();
-       if (!acpi_battery_dir)
-               return;
-#endif
-       if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
-#ifdef CONFIG_ACPI_PROCFS_POWER
-               acpi_unlock_battery_dir(acpi_battery_dir);
-#endif
-               return;
-       }
-       return;
+       acpi_bus_register_driver(&acpi_battery_driver);
 }
 
 static int __init acpi_battery_init(void)
@@ -1181,9 +858,6 @@ static int __init acpi_battery_init(void)
 static void __exit acpi_battery_exit(void)
 {
        acpi_bus_unregister_driver(&acpi_battery_driver);
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_unlock_battery_dir(acpi_battery_dir);
-#endif
 }
 
 module_init(acpi_battery_init);
index 9515f18898b2b578053c58309185daa7934cfdda..aa4d874a96fdda83dd548ba30563133e2019f04b 100644 (file)
@@ -273,6 +273,11 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                     DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P305D"),
                },
        },
+
+       /*
+        * The following machines have broken backlight support when reporting
+        * the Windows 2012 OSI, so disable it until their support is fixed.
+        */
        {
        .callback = dmi_disable_osi_win8,
        .ident = "ASUS Zenbook Prime UX31A",
@@ -297,6 +302,54 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = {
                     DMI_MATCH(DMI_PRODUCT_VERSION, "3259A2G"),
                },
        },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "ThinkPad Edge E530",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "3259CTO"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "ThinkPad Edge E530",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "3259HJG"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "Acer Aspire V5-573G",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "V5-573G/Dazzle_HW"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "Acer Aspire V5-572G",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "Acer Aspire"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "V5-572G/Dazzle_CX"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "ThinkPad T431s",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "20AACTO1WW"),
+               },
+       },
+       {
+       .callback = dmi_disable_osi_win8,
+       .ident = "ThinkPad T430",
+       .matches = {
+                    DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                    DMI_MATCH(DMI_PRODUCT_VERSION, "2349D15"),
+               },
+       },
 
        /*
         * BIOS invocation of _OSI(Linux) is almost always a BIOS bug.
index a55773801c5f1fb739df9597dbbde86d272b092c..c971929d75c20090b69afda2ab65b073bc95b140 100644 (file)
@@ -383,18 +383,15 @@ static int acpi_button_add(struct acpi_device *device)
 
        switch (button->type) {
        case ACPI_BUTTON_TYPE_POWER:
-               input->evbit[0] = BIT_MASK(EV_KEY);
-               set_bit(KEY_POWER, input->keybit);
+               input_set_capability(input, EV_KEY, KEY_POWER);
                break;
 
        case ACPI_BUTTON_TYPE_SLEEP:
-               input->evbit[0] = BIT_MASK(EV_KEY);
-               set_bit(KEY_SLEEP, input->keybit);
+               input_set_capability(input, EV_KEY, KEY_SLEEP);
                break;
 
        case ACPI_BUTTON_TYPE_LID:
-               input->evbit[0] = BIT_MASK(EV_SW);
-               set_bit(SW_LID, input->swbit);
+               input_set_capability(input, EV_SW, SW_LID);
                break;
        }
 
diff --git a/drivers/acpi/cm_sbs.c b/drivers/acpi/cm_sbs.c
deleted file mode 100644 (file)
index 6c9ee68..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or (at
- *  your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful, but
- *  WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-
-#define PREFIX "ACPI: "
-
-ACPI_MODULE_NAME("cm_sbs");
-#define ACPI_AC_CLASS          "ac_adapter"
-#define ACPI_BATTERY_CLASS     "battery"
-#define _COMPONENT             ACPI_SBS_COMPONENT
-static struct proc_dir_entry *acpi_ac_dir;
-static struct proc_dir_entry *acpi_battery_dir;
-
-static DEFINE_MUTEX(cm_sbs_mutex);
-
-static int lock_ac_dir_cnt;
-static int lock_battery_dir_cnt;
-
-struct proc_dir_entry *acpi_lock_ac_dir(void)
-{
-       mutex_lock(&cm_sbs_mutex);
-       if (!acpi_ac_dir)
-               acpi_ac_dir = proc_mkdir(ACPI_AC_CLASS, acpi_root_dir);
-       if (acpi_ac_dir) {
-               lock_ac_dir_cnt++;
-       } else {
-               printk(KERN_ERR PREFIX
-                                 "Cannot create %s\n", ACPI_AC_CLASS);
-       }
-       mutex_unlock(&cm_sbs_mutex);
-       return acpi_ac_dir;
-}
-EXPORT_SYMBOL(acpi_lock_ac_dir);
-
-void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir_param)
-{
-       mutex_lock(&cm_sbs_mutex);
-       if (acpi_ac_dir_param)
-               lock_ac_dir_cnt--;
-       if (lock_ac_dir_cnt == 0 && acpi_ac_dir_param && acpi_ac_dir) {
-               remove_proc_entry(ACPI_AC_CLASS, acpi_root_dir);
-               acpi_ac_dir = NULL;
-       }
-       mutex_unlock(&cm_sbs_mutex);
-}
-EXPORT_SYMBOL(acpi_unlock_ac_dir);
-
-struct proc_dir_entry *acpi_lock_battery_dir(void)
-{
-       mutex_lock(&cm_sbs_mutex);
-       if (!acpi_battery_dir) {
-               acpi_battery_dir =
-                   proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
-       }
-       if (acpi_battery_dir) {
-               lock_battery_dir_cnt++;
-       } else {
-               printk(KERN_ERR PREFIX
-                                 "Cannot create %s\n", ACPI_BATTERY_CLASS);
-       }
-       mutex_unlock(&cm_sbs_mutex);
-       return acpi_battery_dir;
-}
-EXPORT_SYMBOL(acpi_lock_battery_dir);
-
-void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir_param)
-{
-       mutex_lock(&cm_sbs_mutex);
-       if (acpi_battery_dir_param)
-               lock_battery_dir_cnt--;
-       if (lock_battery_dir_cnt == 0 && acpi_battery_dir_param
-           && acpi_battery_dir) {
-               remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
-               acpi_battery_dir = NULL;
-       }
-       mutex_unlock(&cm_sbs_mutex);
-       return;
-}
-EXPORT_SYMBOL(acpi_unlock_battery_dir);
index a94383d1f3502ae35138e7e677df02c1d8df3d72..d42b2fb5a7e94131ce2633ef95f4d7631729325f 100644 (file)
@@ -118,9 +118,10 @@ int acpi_device_get_power(struct acpi_device *device, int *state)
        /*
         * If we were unsure about the device parent's power state up to this
         * point, the fact that the device is in D0 implies that the parent has
-        * to be in D0 too.
+        * to be in D0 too, except if ignore_parent is set.
         */
-       if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN
+       if (!device->power.flags.ignore_parent && device->parent
+           && device->parent->power.state == ACPI_STATE_UNKNOWN
            && result == ACPI_STATE_D0)
                device->parent->power.state = ACPI_STATE_D0;
 
@@ -177,7 +178,8 @@ int acpi_device_set_power(struct acpi_device *device, int state)
                         acpi_power_state_string(state));
                return -ENODEV;
        }
-       if (device->parent && (state < device->parent->power.state)) {
+       if (!device->power.flags.ignore_parent &&
+           device->parent && (state < device->parent->power.state)) {
                dev_warn(&device->dev,
                         "Cannot transition to power state %s for parent in %s\n",
                         acpi_power_state_string(state),
index 05ea4be01a832ccb3d8b38e4318c66fee0f83a89..ca86c1ce7c8a1b5d06713e6a5264e25bd05e99e5 100644 (file)
@@ -441,7 +441,7 @@ static void handle_dock(struct dock_station *ds, int dock)
        acpi_status status;
        struct acpi_object_list arg_list;
        union acpi_object arg;
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       unsigned long long value;
 
        acpi_handle_info(ds->handle, "%s\n", dock ? "docking" : "undocking");
 
@@ -450,12 +450,10 @@ static void handle_dock(struct dock_station *ds, int dock)
        arg_list.pointer = &arg;
        arg.type = ACPI_TYPE_INTEGER;
        arg.integer.value = dock;
-       status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer);
+       status = acpi_evaluate_integer(ds->handle, "_DCK", &arg_list, &value);
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
                acpi_handle_err(ds->handle, "Failed to execute _DCK (0x%x)\n",
                                status);
-
-       kfree(buffer.pointer);
 }
 
 static inline void dock(struct dock_station *ds)
index a06d9837470585aaf0298b3f3f96f7e94bd64724..d5309fd494589b4d1596cb1c03576ed1e7ef252e 100644 (file)
@@ -28,6 +28,7 @@
 
 /* Uncomment next line to get verbose printout */
 /* #define DEBUG */
+#define pr_fmt(fmt) "ACPI : EC: " fmt
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -49,9 +50,6 @@
 #define ACPI_EC_DEVICE_NAME            "Embedded Controller"
 #define ACPI_EC_FILE_INFO              "info"
 
-#undef PREFIX
-#define PREFIX                         "ACPI: EC: "
-
 /* EC status register */
 #define ACPI_EC_FLAG_OBF       0x01    /* Output buffer full */
 #define ACPI_EC_FLAG_IBF       0x02    /* Input buffer full */
@@ -131,26 +129,26 @@ static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */
 static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
 {
        u8 x = inb(ec->command_addr);
-       pr_debug(PREFIX "---> status = 0x%2.2x\n", x);
+       pr_debug("---> status = 0x%2.2x\n", x);
        return x;
 }
 
 static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
 {
        u8 x = inb(ec->data_addr);
-       pr_debug(PREFIX "---> data = 0x%2.2x\n", x);
+       pr_debug("---> data = 0x%2.2x\n", x);
        return x;
 }
 
 static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
 {
-       pr_debug(PREFIX "<--- command = 0x%2.2x\n", command);
+       pr_debug("<--- command = 0x%2.2x\n", command);
        outb(command, ec->command_addr);
 }
 
 static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
 {
-       pr_debug(PREFIX "<--- data = 0x%2.2x\n", data);
+       pr_debug("<--- data = 0x%2.2x\n", data);
        outb(data, ec->data_addr);
 }
 
@@ -241,7 +239,7 @@ static int ec_poll(struct acpi_ec *ec)
                        }
                        advance_transaction(ec, acpi_ec_read_status(ec));
                } while (time_before(jiffies, delay));
-               pr_debug(PREFIX "controller reset, restart transaction\n");
+               pr_debug("controller reset, restart transaction\n");
                spin_lock_irqsave(&ec->lock, flags);
                start_transaction(ec);
                spin_unlock_irqrestore(&ec->lock, flags);
@@ -309,12 +307,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
                }
        }
        if (ec_wait_ibf0(ec)) {
-               pr_err(PREFIX "input buffer is not empty, "
+               pr_err("input buffer is not empty, "
                                "aborting transaction\n");
                status = -ETIME;
                goto end;
        }
-       pr_debug(PREFIX "transaction start (cmd=0x%02x, addr=0x%02x)\n",
+       pr_debug("transaction start (cmd=0x%02x, addr=0x%02x)\n",
                        t->command, t->wdata ? t->wdata[0] : 0);
        /* disable GPE during transaction if storm is detected */
        if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) {
@@ -331,12 +329,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t)
                /* It is safe to enable the GPE outside of the transaction. */
                acpi_enable_gpe(NULL, ec->gpe);
        } else if (t->irq_count > ec_storm_threshold) {
-               pr_info(PREFIX "GPE storm detected(%d GPEs), "
+               pr_info("GPE storm detected(%d GPEs), "
                        "transactions will use polling mode\n",
                        t->irq_count);
                set_bit(EC_FLAGS_GPE_STORM, &ec->flags);
        }
-       pr_debug(PREFIX "transaction end\n");
+       pr_debug("transaction end\n");
 end:
        if (ec->global_lock)
                acpi_release_global_lock(glk);
@@ -570,12 +568,12 @@ static void acpi_ec_run(void *cxt)
        struct acpi_ec_query_handler *handler = cxt;
        if (!handler)
                return;
-       pr_debug(PREFIX "start query execution\n");
+       pr_debug("start query execution\n");
        if (handler->func)
                handler->func(handler->data);
        else if (handler->handle)
                acpi_evaluate_object(handler->handle, NULL, NULL, NULL);
-       pr_debug(PREFIX "stop query execution\n");
+       pr_debug("stop query execution\n");
        kfree(handler);
 }
 
@@ -593,7 +591,8 @@ static int acpi_ec_sync_query(struct acpi_ec *ec)
                        if (!copy)
                                return -ENOMEM;
                        memcpy(copy, handler, sizeof(*copy));
-                       pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value);
+                       pr_debug("push query execution (0x%2x) on queue\n",
+                               value);
                        return acpi_os_execute((copy->func) ?
                                OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER,
                                acpi_ec_run, copy);
@@ -616,7 +615,7 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
 {
        if (state & ACPI_EC_FLAG_SCI) {
                if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) {
-                       pr_debug(PREFIX "push gpe query to the queue\n");
+                       pr_debug("push gpe query to the queue\n");
                        return acpi_os_execute(OSL_NOTIFY_HANDLER,
                                acpi_ec_gpe_query, ec);
                }
@@ -630,7 +629,7 @@ static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
        struct acpi_ec *ec = data;
        u8 status = acpi_ec_read_status(ec);
 
-       pr_debug(PREFIX "~~~> interrupt, status:0x%02x\n", status);
+       pr_debug("~~~> interrupt, status:0x%02x\n", status);
 
        advance_transaction(ec, status);
        if (ec_transaction_done(ec) &&
@@ -776,7 +775,7 @@ static int ec_install_handlers(struct acpi_ec *ec)
                         * The AE_NOT_FOUND error will be ignored and OS
                         * continue to initialize EC.
                         */
-                       printk(KERN_ERR "Fail in evaluating the _REG object"
+                       pr_err("Fail in evaluating the _REG object"
                                " of EC device. Broken bios is suspected.\n");
                } else {
                        acpi_remove_gpe_handler(NULL, ec->gpe,
@@ -795,10 +794,10 @@ static void ec_remove_handlers(struct acpi_ec *ec)
        acpi_disable_gpe(NULL, ec->gpe);
        if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
                                ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
-               pr_err(PREFIX "failed to remove space handler\n");
+               pr_err("failed to remove space handler\n");
        if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
                                &acpi_ec_gpe_handler)))
-               pr_err(PREFIX "failed to remove gpe handler\n");
+               pr_err("failed to remove gpe handler\n");
        clear_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags);
 }
 
@@ -840,7 +839,7 @@ static int acpi_ec_add(struct acpi_device *device)
        ret = !!request_region(ec->command_addr, 1, "EC cmd");
        WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr);
 
-       pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
+       pr_info("GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
                          ec->gpe, ec->command_addr, ec->data_addr);
 
        ret = ec_install_handlers(ec);
@@ -931,7 +930,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id)
 /* MSI EC needs special treatment, enable it */
 static int ec_flag_msi(const struct dmi_system_id *id)
 {
-       printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n");
+       pr_debug("Detected MSI hardware, enabling workarounds.\n");
        EC_FLAGS_MSI = 1;
        EC_FLAGS_VALIDATE_ECDT = 1;
        return 0;
@@ -1010,7 +1009,7 @@ int __init acpi_ec_ecdt_probe(void)
        status = acpi_get_table(ACPI_SIG_ECDT, 1,
                                (struct acpi_table_header **)&ecdt_ptr);
        if (ACPI_SUCCESS(status)) {
-               pr_info(PREFIX "EC description table is found, configuring boot EC\n");
+               pr_info("EC description table is found, configuring boot EC\n");
                boot_ec->command_addr = ecdt_ptr->control.address;
                boot_ec->data_addr = ecdt_ptr->data.address;
                boot_ec->gpe = ecdt_ptr->gpe;
@@ -1030,7 +1029,7 @@ int __init acpi_ec_ecdt_probe(void)
 
        /* This workaround is needed only on some broken machines,
         * which require early EC, but fail to provide ECDT */
-       printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
+       pr_debug("Look up EC in DSDT\n");
        status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
                                        boot_ec, NULL);
        /* Check that acpi_get_devices actually find something */
@@ -1042,7 +1041,7 @@ int __init acpi_ec_ecdt_probe(void)
                    saved_ec->data_addr != boot_ec->data_addr ||
                    saved_ec->gpe != boot_ec->gpe ||
                    saved_ec->handle != boot_ec->handle)
-                       pr_info(PREFIX "ASUSTek keeps feeding us with broken "
+                       pr_info("ASUSTek keeps feeding us with broken "
                        "ECDT tables, which are very hard to workaround. "
                        "Trying to use DSDT EC info instead. Please send "
                        "output of acpidump to linux-acpi@vger.kernel.org\n");
index 41ade6570bc07c22c3c40445d696aea26e4e4c41..ba3da88cee45a20479df62023ee560aa422dff22 100644 (file)
@@ -168,7 +168,7 @@ static int acpi_fan_add(struct acpi_device *device)
               acpi_device_name(device), acpi_device_bid(device),
               !device->power.state ? "on" : "off");
 
-      end:
+end:
        return result;
 }
 
index 20f423337e1fb73c66379a3771954741860c6d7d..e9304dc7ebfa0dc40c37dcc3be270cc299b94170 100644 (file)
@@ -169,9 +169,7 @@ int acpi_create_platform_device(struct acpi_device *adev,
                                        Video
   -------------------------------------------------------------------------- */
 #if defined(CONFIG_ACPI_VIDEO) || defined(CONFIG_ACPI_VIDEO_MODULE)
-bool acpi_video_backlight_quirks(void);
-#else
-static inline bool acpi_video_backlight_quirks(void) { return false; }
+bool acpi_osi_is_win8(void);
 #endif
 
 #endif /* _ACPI_INTERNAL_H_ */
index 2e82e5d7693016676ad6afdf69ce3b553e968d44..a2343a1d9e0b1a0e77f3b7a7caf6676499c5f989 100644 (file)
@@ -73,7 +73,7 @@ int acpi_map_pxm_to_node(int pxm)
 {
        int node = pxm_to_node_map[pxm];
 
-       if (node < 0) {
+       if (node == NUMA_NO_NODE) {
                if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
                        return NUMA_NO_NODE;
                node = first_unset_node(nodes_found_map);
@@ -334,7 +334,7 @@ int acpi_get_pxm(acpi_handle h)
 
 int acpi_get_node(acpi_handle *handle)
 {
-       int pxm, node = -1;
+       int pxm, node = NUMA_NO_NODE;
 
        pxm = acpi_get_pxm(handle);
        if (pxm >= 0 && pxm < MAX_PXM_DOMAINS)
index e5f416c7f66e9e92e1ed988c3a709bc2820d56f4..a0c09adf7e7d2043587dad0384ba1374353989c7 100644 (file)
@@ -569,8 +569,10 @@ static const char * const table_sigs[] = {
 
 #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
 
-/* Must not increase 10 or needs code modification below */
-#define ACPI_OVERRIDE_TABLES 10
+#define ACPI_OVERRIDE_TABLES 64
+static struct cpio_data __initdata acpi_initrd_files[ACPI_OVERRIDE_TABLES];
+
+#define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)
 
 void __init acpi_initrd_override(void *data, size_t size)
 {
@@ -579,8 +581,6 @@ void __init acpi_initrd_override(void *data, size_t size)
        struct acpi_table_header *table;
        char cpio_path[32] = "kernel/firmware/acpi/";
        struct cpio_data file;
-       struct cpio_data early_initrd_files[ACPI_OVERRIDE_TABLES];
-       char *p;
 
        if (data == NULL || size == 0)
                return;
@@ -625,8 +625,8 @@ void __init acpi_initrd_override(void *data, size_t size)
                        table->signature, cpio_path, file.name, table->length);
 
                all_tables_size += table->length;
-               early_initrd_files[table_nr].data = file.data;
-               early_initrd_files[table_nr].size = file.size;
+               acpi_initrd_files[table_nr].data = file.data;
+               acpi_initrd_files[table_nr].size = file.size;
                table_nr++;
        }
        if (table_nr == 0)
@@ -652,14 +652,34 @@ void __init acpi_initrd_override(void *data, size_t size)
        memblock_reserve(acpi_tables_addr, all_tables_size);
        arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
 
-       p = early_ioremap(acpi_tables_addr, all_tables_size);
-
+       /*
+        * early_ioremap only can remap 256k one time. If we map all
+        * tables one time, we will hit the limit. Need to map chunks
+        * one by one during copying the same as that in relocate_initrd().
+        */
        for (no = 0; no < table_nr; no++) {
-               memcpy(p + total_offset, early_initrd_files[no].data,
-                      early_initrd_files[no].size);
-               total_offset += early_initrd_files[no].size;
+               unsigned char *src_p = acpi_initrd_files[no].data;
+               phys_addr_t size = acpi_initrd_files[no].size;
+               phys_addr_t dest_addr = acpi_tables_addr + total_offset;
+               phys_addr_t slop, clen;
+               char *dest_p;
+
+               total_offset += size;
+
+               while (size) {
+                       slop = dest_addr & ~PAGE_MASK;
+                       clen = size;
+                       if (clen > MAP_CHUNK_SIZE - slop)
+                               clen = MAP_CHUNK_SIZE - slop;
+                       dest_p = early_ioremap(dest_addr & PAGE_MASK,
+                                                clen + slop);
+                       memcpy(dest_p + slop, src_p, clen);
+                       early_iounmap(dest_p, clen + slop);
+                       src_p += clen;
+                       dest_addr += clen;
+                       size -= clen;
+               }
        }
-       early_iounmap(p, all_tables_size);
 }
 #endif /* CONFIG_ACPI_INITRD_TABLE_OVERRIDE */
 
@@ -820,7 +840,7 @@ acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
 
 void acpi_os_sleep(u64 ms)
 {
-       schedule_timeout_interruptible(msecs_to_jiffies(ms));
+       msleep(ms);
 }
 
 void acpi_os_stall(u32 us)
@@ -1335,7 +1355,7 @@ static int __init acpi_os_name_setup(char *str)
        if (!str || !*str)
                return 0;
 
-       for (; count-- && str && *str; str++) {
+       for (; count-- && *str; str++) {
                if (isalnum(*str) || *str == ' ' || *str == ':')
                        *p++ = *str;
                else if (*str == '\'' || *str == '"')
index 04a13784dd20a4a7e42b15b98eedcff90cb67299..6a5b152ad4d070511d08d74439155fa17a83ed8a 100644 (file)
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
-#ifdef CONFIG_X86
-#include <linux/mc146818rtc.h>
-#endif
-
 #include "sleep.h"
 
 #define _COMPONENT             ACPI_SYSTEM_COMPONENT
 
 /*
  * this file provides support for:
- * /proc/acpi/alarm
  * /proc/acpi/wakeup
  */
 
 ACPI_MODULE_NAME("sleep")
 
-#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || !defined(CONFIG_X86)
-/* use /sys/class/rtc/rtcX/wakealarm instead; it's not ACPI-specific */
-#else
-#define        HAVE_ACPI_LEGACY_ALARM
-#endif
-
-#ifdef HAVE_ACPI_LEGACY_ALARM
-
-static u32 cmos_bcd_read(int offset, int rtc_control);
-
-static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
-{
-       u32 sec, min, hr;
-       u32 day, mo, yr, cent = 0;
-       u32 today = 0;
-       unsigned char rtc_control = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&rtc_lock, flags);
-
-       rtc_control = CMOS_READ(RTC_CONTROL);
-       sec = cmos_bcd_read(RTC_SECONDS_ALARM, rtc_control);
-       min = cmos_bcd_read(RTC_MINUTES_ALARM, rtc_control);
-       hr = cmos_bcd_read(RTC_HOURS_ALARM, rtc_control);
-
-       /* If we ever get an FACP with proper values... */
-       if (acpi_gbl_FADT.day_alarm) {
-               /* ACPI spec: only low 6 its should be cared */
-               day = CMOS_READ(acpi_gbl_FADT.day_alarm) & 0x3F;
-               if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-                       day = bcd2bin(day);
-       } else
-               day = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
-       if (acpi_gbl_FADT.month_alarm)
-               mo = cmos_bcd_read(acpi_gbl_FADT.month_alarm, rtc_control);
-       else {
-               mo = cmos_bcd_read(RTC_MONTH, rtc_control);
-               today = cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
-       }
-       if (acpi_gbl_FADT.century)
-               cent = cmos_bcd_read(acpi_gbl_FADT.century, rtc_control);
-
-       yr = cmos_bcd_read(RTC_YEAR, rtc_control);
-
-       spin_unlock_irqrestore(&rtc_lock, flags);
-
-       /* we're trusting the FADT (see above) */
-       if (!acpi_gbl_FADT.century)
-               /* If we're not trusting the FADT, we should at least make it
-                * right for _this_ century... ehm, what is _this_ century?
-                *
-                * TBD:
-                *  ASAP: find piece of code in the kernel, e.g. star tracker driver,
-                *        which we can trust to determine the century correctly. Atom
-                *        watch driver would be nice, too...
-                *
-                *  if that has not happened, change for first release in 2050:
-                *        if (yr<50)
-                *                yr += 2100;
-                *        else
-                *                yr += 2000;   // current line of code
-                *
-                *  if that has not happened either, please do on 2099/12/31:23:59:59
-                *        s/2000/2100
-                *
-                */
-               yr += 2000;
-       else
-               yr += cent * 100;
-
-       /*
-        * Show correct dates for alarms up to a month into the future.
-        * This solves issues for nearly all situations with the common
-        * 30-day alarm clocks in PC hardware.
-        */
-       if (day < today) {
-               if (mo < 12) {
-                       mo += 1;
-               } else {
-                       mo = 1;
-                       yr += 1;
-               }
-       }
-
-       seq_printf(seq, "%4.4u-", yr);
-       (mo > 12) ? seq_puts(seq, "**-") : seq_printf(seq, "%2.2u-", mo);
-       (day > 31) ? seq_puts(seq, "** ") : seq_printf(seq, "%2.2u ", day);
-       (hr > 23) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", hr);
-       (min > 59) ? seq_puts(seq, "**:") : seq_printf(seq, "%2.2u:", min);
-       (sec > 59) ? seq_puts(seq, "**\n") : seq_printf(seq, "%2.2u\n", sec);
-
-       return 0;
-}
-
-static int acpi_system_alarm_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_system_alarm_seq_show, PDE_DATA(inode));
-}
-
-static int get_date_field(char **p, u32 * value)
-{
-       char *next = NULL;
-       char *string_end = NULL;
-       int result = -EINVAL;
-
-       /*
-        * Try to find delimeter, only to insert null.  The end of the
-        * string won't have one, but is still valid.
-        */
-       if (*p == NULL)
-               return result;
-
-       next = strpbrk(*p, "- :");
-       if (next)
-               *next++ = '\0';
-
-       *value = simple_strtoul(*p, &string_end, 10);
-
-       /* Signal success if we got a good digit */
-       if (string_end != *p)
-               result = 0;
-
-       if (next)
-               *p = next;
-       else
-               *p = NULL;
-
-       return result;
-}
-
-/* Read a possibly BCD register, always return binary */
-static u32 cmos_bcd_read(int offset, int rtc_control)
-{
-       u32 val = CMOS_READ(offset);
-       if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               val = bcd2bin(val);
-       return val;
-}
-
-/* Write binary value into possibly BCD register */
-static void cmos_bcd_write(u32 val, int offset, int rtc_control)
-{
-       if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               val = bin2bcd(val);
-       CMOS_WRITE(val, offset);
-}
-
-static ssize_t
-acpi_system_write_alarm(struct file *file,
-                       const char __user * buffer, size_t count, loff_t * ppos)
-{
-       int result = 0;
-       char alarm_string[30] = { '\0' };
-       char *p = alarm_string;
-       u32 sec, min, hr, day, mo, yr;
-       int adjust = 0;
-       unsigned char rtc_control = 0;
-
-       if (count > sizeof(alarm_string) - 1)
-               return -EINVAL;
-
-       if (copy_from_user(alarm_string, buffer, count))
-               return -EFAULT;
-
-       alarm_string[count] = '\0';
-
-       /* check for time adjustment */
-       if (alarm_string[0] == '+') {
-               p++;
-               adjust = 1;
-       }
-
-       if ((result = get_date_field(&p, &yr)))
-               goto end;
-       if ((result = get_date_field(&p, &mo)))
-               goto end;
-       if ((result = get_date_field(&p, &day)))
-               goto end;
-       if ((result = get_date_field(&p, &hr)))
-               goto end;
-       if ((result = get_date_field(&p, &min)))
-               goto end;
-       if ((result = get_date_field(&p, &sec)))
-               goto end;
-
-       spin_lock_irq(&rtc_lock);
-
-       rtc_control = CMOS_READ(RTC_CONTROL);
-
-       if (adjust) {
-               yr += cmos_bcd_read(RTC_YEAR, rtc_control);
-               mo += cmos_bcd_read(RTC_MONTH, rtc_control);
-               day += cmos_bcd_read(RTC_DAY_OF_MONTH, rtc_control);
-               hr += cmos_bcd_read(RTC_HOURS, rtc_control);
-               min += cmos_bcd_read(RTC_MINUTES, rtc_control);
-               sec += cmos_bcd_read(RTC_SECONDS, rtc_control);
-       }
-
-       spin_unlock_irq(&rtc_lock);
-
-       if (sec > 59) {
-               min += sec/60;
-               sec = sec%60;
-       }
-       if (min > 59) {
-               hr += min/60;
-               min = min%60;
-       }
-       if (hr > 23) {
-               day += hr/24;
-               hr = hr%24;
-       }
-       if (day > 31) {
-               mo += day/32;
-               day = day%32;
-       }
-       if (mo > 12) {
-               yr += mo/13;
-               mo = mo%13;
-       }
-
-       spin_lock_irq(&rtc_lock);
-       /*
-        * Disable alarm interrupt before setting alarm timer or else
-        * when ACPI_EVENT_RTC is enabled, a spurious ACPI interrupt occurs
-        */
-       rtc_control &= ~RTC_AIE;
-       CMOS_WRITE(rtc_control, RTC_CONTROL);
-       CMOS_READ(RTC_INTR_FLAGS);
-
-       /* write the fields the rtc knows about */
-       cmos_bcd_write(hr, RTC_HOURS_ALARM, rtc_control);
-       cmos_bcd_write(min, RTC_MINUTES_ALARM, rtc_control);
-       cmos_bcd_write(sec, RTC_SECONDS_ALARM, rtc_control);
-
-       /*
-        * If the system supports an enhanced alarm it will have non-zero
-        * offsets into the CMOS RAM here -- which for some reason are pointing
-        * to the RTC area of memory.
-        */
-       if (acpi_gbl_FADT.day_alarm)
-               cmos_bcd_write(day, acpi_gbl_FADT.day_alarm, rtc_control);
-       if (acpi_gbl_FADT.month_alarm)
-               cmos_bcd_write(mo, acpi_gbl_FADT.month_alarm, rtc_control);
-       if (acpi_gbl_FADT.century) {
-               if (adjust)
-                       yr += cmos_bcd_read(acpi_gbl_FADT.century, rtc_control) * 100;
-               cmos_bcd_write(yr / 100, acpi_gbl_FADT.century, rtc_control);
-       }
-       /* enable the rtc alarm interrupt */
-       rtc_control |= RTC_AIE;
-       CMOS_WRITE(rtc_control, RTC_CONTROL);
-       CMOS_READ(RTC_INTR_FLAGS);
-
-       spin_unlock_irq(&rtc_lock);
-
-       acpi_clear_event(ACPI_EVENT_RTC);
-       acpi_enable_event(ACPI_EVENT_RTC, 0);
-
-       *ppos += count;
-
-       result = 0;
-      end:
-       return result ? result : count;
-}
-#endif                         /* HAVE_ACPI_LEGACY_ALARM */
-
 static int
 acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
 {
@@ -417,41 +145,8 @@ static const struct file_operations acpi_system_wakeup_device_fops = {
        .release = single_release,
 };
 
-#ifdef HAVE_ACPI_LEGACY_ALARM
-static const struct file_operations acpi_system_alarm_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_system_alarm_open_fs,
-       .read = seq_read,
-       .write = acpi_system_write_alarm,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static u32 rtc_handler(void *context)
-{
-       acpi_clear_event(ACPI_EVENT_RTC);
-       acpi_disable_event(ACPI_EVENT_RTC, 0);
-
-       return ACPI_INTERRUPT_HANDLED;
-}
-#endif                         /* HAVE_ACPI_LEGACY_ALARM */
-
 int __init acpi_sleep_proc_init(void)
 {
-#ifdef HAVE_ACPI_LEGACY_ALARM
-       /* 'alarm' [R/W] */
-       proc_create("alarm", S_IFREG | S_IRUGO | S_IWUSR,
-                   acpi_root_dir, &acpi_system_alarm_fops);
-
-       acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
-       /*
-        * Disable the RTC event after installing RTC handler.
-        * Only when RTC alarm is set will it be enabled.
-        */
-       acpi_clear_event(ACPI_EVENT_RTC);
-       acpi_disable_event(ACPI_EVENT_RTC, 0);
-#endif                         /* HAVE_ACPI_LEGACY_ALARM */
-
        /* 'wakeup device' [R/W] */
        proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
                    acpi_root_dir, &acpi_system_wakeup_device_fops);
index cf34d903f4fb4a45b7975fc5fce60d141de2b7a9..b3171f30b319c1244007e686a0b516833443191d 100644 (file)
@@ -162,16 +162,23 @@ exit:
        return apic_id;
 }
 
-int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
+int acpi_get_apicid(acpi_handle handle, int type, u32 acpi_id)
 {
-#ifdef CONFIG_SMP
-       int i;
-#endif
-       int apic_id = -1;
+       int apic_id;
 
        apic_id = map_mat_entry(handle, type, acpi_id);
        if (apic_id == -1)
                apic_id = map_madt_entry(type, acpi_id);
+
+       return apic_id;
+}
+
+int acpi_map_cpuid(int apic_id, u32 acpi_id)
+{
+#ifdef CONFIG_SMP
+       int i;
+#endif
+
        if (apic_id == -1) {
                /*
                 * On UP processor, there is no _MAT or MADT table.
@@ -211,6 +218,15 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
 #endif
        return -1;
 }
+
+int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
+{
+       int apic_id;
+
+       apic_id = acpi_get_apicid(handle, type, acpi_id);
+
+       return acpi_map_cpuid(apic_id, acpi_id);
+}
 EXPORT_SYMBOL_GPL(acpi_get_cpuid);
 
 static bool __init processor_physically_present(acpi_handle handle)
index e534ba66d5b80861849ae705bf941ac570720607..40fc773ab6e078a0f9d06e7d9b3faf497ec49169 100644 (file)
@@ -153,8 +153,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
        return NOTIFY_OK;
 }
 
-static struct notifier_block __refdata acpi_cpu_notifier =
-{
+static struct notifier_block __refdata acpi_cpu_notifier = {
            .notifier_call = acpi_cpu_soft_notify,
 };
 
index f98dd00b51a94b2d7e2d7dc9cd15f3e941e81bff..35c8f2bbcc40b45510ea7d1b67ee294efc33471b 100644 (file)
@@ -272,9 +272,6 @@ static void tsc_check_state(int state) { return; }
 static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr)
 {
 
-       if (!pr)
-               return -EINVAL;
-
        if (!pr->pblk)
                return -ENODEV;
 
@@ -1076,12 +1073,8 @@ int acpi_processor_hotplug(struct acpi_processor *pr)
        if (disabled_by_idle_boot_param())
                return 0;
 
-       if (!pr)
-               return -EINVAL;
-
-       if (nocst) {
+       if (nocst)
                return -ENODEV;
-       }
 
        if (!pr->flags.power_setup_done)
                return -ENODEV;
@@ -1108,9 +1101,6 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
        if (disabled_by_idle_boot_param())
                return 0;
 
-       if (!pr)
-               return -EINVAL;
-
        if (nocst)
                return -ENODEV;
 
@@ -1183,9 +1173,6 @@ int acpi_processor_power_init(struct acpi_processor *pr)
                first_run++;
        }
 
-       if (!pr)
-               return -EINVAL;
-
        if (acpi_gbl_FADT.cst_control && !nocst) {
                status =
                    acpi_os_write_port(acpi_gbl_FADT.smi_command, acpi_gbl_FADT.cst_control, 8);
index aef7e1cd1e5d62f95512484935e4fea9b11af961..d465ae6cdd004b9813cc333529c54ef29abcb16f 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 
-#ifdef CONFIG_ACPI_PROCFS_POWER
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <asm/uaccess.h>
-#endif
-
 #include <linux/acpi.h>
 #include <linux/timer.h>
 #include <linux/jiffies.h>
@@ -67,11 +61,6 @@ static unsigned int cache_time = 1000;
 module_param(cache_time, uint, 0644);
 MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
 
-extern struct proc_dir_entry *acpi_lock_ac_dir(void);
-extern struct proc_dir_entry *acpi_lock_battery_dir(void);
-extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
-extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
-
 #define MAX_SBS_BAT                    4
 #define ACPI_SBS_BLOCK_MAX             32
 
@@ -84,9 +73,6 @@ MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
 struct acpi_battery {
        struct power_supply bat;
        struct acpi_sbs *sbs;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       struct proc_dir_entry *proc_entry;
-#endif
        unsigned long update_time;
        char name[8];
        char manufacturer_name[ACPI_SBS_BLOCK_MAX];
@@ -119,9 +105,6 @@ struct acpi_sbs {
        struct acpi_device *device;
        struct acpi_smb_hc *hc;
        struct mutex lock;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       struct proc_dir_entry *charger_entry;
-#endif
        struct acpi_battery battery[MAX_SBS_BAT];
        u8 batteries_supported:4;
        u8 manager_present:1;
@@ -481,261 +464,6 @@ static struct device_attribute alarm_attr = {
        .store = acpi_battery_alarm_store,
 };
 
-/* --------------------------------------------------------------------------
-                              FS Interface (/proc/acpi)
-   -------------------------------------------------------------------------- */
-
-#ifdef CONFIG_ACPI_PROCFS_POWER
-/* Generic Routines */
-static int
-acpi_sbs_add_fs(struct proc_dir_entry **dir,
-               struct proc_dir_entry *parent_dir,
-               char *dir_name,
-               const struct file_operations *info_fops,
-               const struct file_operations *state_fops,
-               const struct file_operations *alarm_fops, void *data)
-{
-       printk(KERN_WARNING PREFIX "Deprecated procfs I/F for SBS is loaded,"
-                       " please retry with CONFIG_ACPI_PROCFS_POWER cleared\n");
-       if (!*dir) {
-               *dir = proc_mkdir(dir_name, parent_dir);
-               if (!*dir) {
-                       return -ENODEV;
-               }
-       }
-
-       /* 'info' [R] */
-       if (info_fops)
-               proc_create_data(ACPI_SBS_FILE_INFO, S_IRUGO, *dir,
-                                info_fops, data);
-
-       /* 'state' [R] */
-       if (state_fops)
-               proc_create_data(ACPI_SBS_FILE_STATE, S_IRUGO, *dir,
-                                state_fops, data);
-
-       /* 'alarm' [R/W] */
-       if (alarm_fops)
-               proc_create_data(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir,
-                                alarm_fops, data);
-       return 0;
-}
-
-/* Smart Battery Interface */
-static struct proc_dir_entry *acpi_battery_dir = NULL;
-
-static inline char *acpi_battery_units(struct acpi_battery *battery)
-{
-       return acpi_battery_mode(battery) ? " mW" : " mA";
-}
-
-
-static int acpi_battery_read_info(struct seq_file *seq, void *offset)
-{
-       struct acpi_battery *battery = seq->private;
-       struct acpi_sbs *sbs = battery->sbs;
-       int result = 0;
-
-       mutex_lock(&sbs->lock);
-
-       seq_printf(seq, "present:                 %s\n",
-                  (battery->present) ? "yes" : "no");
-       if (!battery->present)
-               goto end;
-
-       seq_printf(seq, "design capacity:         %i%sh\n",
-                  battery->design_capacity * acpi_battery_scale(battery),
-                  acpi_battery_units(battery));
-       seq_printf(seq, "last full capacity:      %i%sh\n",
-                  battery->full_charge_capacity * acpi_battery_scale(battery),
-                  acpi_battery_units(battery));
-       seq_printf(seq, "battery technology:      rechargeable\n");
-       seq_printf(seq, "design voltage:          %i mV\n",
-                  battery->design_voltage * acpi_battery_vscale(battery));
-       seq_printf(seq, "design capacity warning: unknown\n");
-       seq_printf(seq, "design capacity low:     unknown\n");
-       seq_printf(seq, "cycle count:             %i\n", battery->cycle_count);
-       seq_printf(seq, "capacity granularity 1:  unknown\n");
-       seq_printf(seq, "capacity granularity 2:  unknown\n");
-       seq_printf(seq, "model number:            %s\n", battery->device_name);
-       seq_printf(seq, "serial number:           %i\n",
-                  battery->serial_number);
-       seq_printf(seq, "battery type:            %s\n",
-                  battery->device_chemistry);
-       seq_printf(seq, "OEM info:                %s\n",
-                  battery->manufacturer_name);
-      end:
-       mutex_unlock(&sbs->lock);
-       return result;
-}
-
-static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_battery_read_info, PDE_DATA(inode));
-}
-
-static int acpi_battery_read_state(struct seq_file *seq, void *offset)
-{
-       struct acpi_battery *battery = seq->private;
-       struct acpi_sbs *sbs = battery->sbs;
-       int rate;
-
-       mutex_lock(&sbs->lock);
-       seq_printf(seq, "present:                 %s\n",
-                  (battery->present) ? "yes" : "no");
-       if (!battery->present)
-               goto end;
-
-       acpi_battery_get_state(battery);
-       seq_printf(seq, "capacity state:          %s\n",
-                  (battery->state & 0x0010) ? "critical" : "ok");
-       seq_printf(seq, "charging state:          %s\n",
-                  (battery->rate_now < 0) ? "discharging" :
-                  ((battery->rate_now > 0) ? "charging" : "charged"));
-       rate = abs(battery->rate_now) * acpi_battery_ipscale(battery);
-       rate *= (acpi_battery_mode(battery))?(battery->voltage_now *
-                       acpi_battery_vscale(battery)/1000):1;
-       seq_printf(seq, "present rate:            %d%s\n", rate,
-                  acpi_battery_units(battery));
-       seq_printf(seq, "remaining capacity:      %i%sh\n",
-                  battery->capacity_now * acpi_battery_scale(battery),
-                  acpi_battery_units(battery));
-       seq_printf(seq, "present voltage:         %i mV\n",
-                  battery->voltage_now * acpi_battery_vscale(battery));
-
-      end:
-       mutex_unlock(&sbs->lock);
-       return 0;
-}
-
-static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_battery_read_state, PDE_DATA(inode));
-}
-
-static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
-{
-       struct acpi_battery *battery = seq->private;
-       struct acpi_sbs *sbs = battery->sbs;
-       int result = 0;
-
-       mutex_lock(&sbs->lock);
-
-       if (!battery->present) {
-               seq_printf(seq, "present:                 no\n");
-               goto end;
-       }
-
-       acpi_battery_get_alarm(battery);
-       seq_printf(seq, "alarm:                   ");
-       if (battery->alarm_capacity)
-               seq_printf(seq, "%i%sh\n",
-                          battery->alarm_capacity *
-                          acpi_battery_scale(battery),
-                          acpi_battery_units(battery));
-       else
-               seq_printf(seq, "disabled\n");
-      end:
-       mutex_unlock(&sbs->lock);
-       return result;
-}
-
-static ssize_t
-acpi_battery_write_alarm(struct file *file, const char __user * buffer,
-                        size_t count, loff_t * ppos)
-{
-       struct seq_file *seq = file->private_data;
-       struct acpi_battery *battery = seq->private;
-       struct acpi_sbs *sbs = battery->sbs;
-       char alarm_string[12] = { '\0' };
-       int result = 0;
-       mutex_lock(&sbs->lock);
-       if (!battery->present) {
-               result = -ENODEV;
-               goto end;
-       }
-       if (count > sizeof(alarm_string) - 1) {
-               result = -EINVAL;
-               goto end;
-       }
-       if (copy_from_user(alarm_string, buffer, count)) {
-               result = -EFAULT;
-               goto end;
-       }
-       alarm_string[count] = 0;
-       battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) /
-                                       acpi_battery_scale(battery);
-       acpi_battery_set_alarm(battery);
-      end:
-       mutex_unlock(&sbs->lock);
-       if (result)
-               return result;
-       return count;
-}
-
-static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_battery_read_alarm, PDE_DATA(inode));
-}
-
-static const struct file_operations acpi_battery_info_fops = {
-       .open = acpi_battery_info_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-static const struct file_operations acpi_battery_state_fops = {
-       .open = acpi_battery_state_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-static const struct file_operations acpi_battery_alarm_fops = {
-       .open = acpi_battery_alarm_open_fs,
-       .read = seq_read,
-       .write = acpi_battery_write_alarm,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-/* Legacy AC Adapter Interface */
-
-static struct proc_dir_entry *acpi_ac_dir = NULL;
-
-static int acpi_ac_read_state(struct seq_file *seq, void *offset)
-{
-
-       struct acpi_sbs *sbs = seq->private;
-
-       mutex_lock(&sbs->lock);
-
-       seq_printf(seq, "state:                   %s\n",
-                  sbs->charger_present ? "on-line" : "off-line");
-
-       mutex_unlock(&sbs->lock);
-       return 0;
-}
-
-static int acpi_ac_state_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_ac_read_state, PDE_DATA(inode));
-}
-
-static const struct file_operations acpi_ac_state_fops = {
-       .open = acpi_ac_state_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-#endif
-
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -781,12 +509,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
                return result;
 
        sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,
-                       battery->name, &acpi_battery_info_fops,
-                       &acpi_battery_state_fops, &acpi_battery_alarm_fops,
-                       battery);
-#endif
        battery->bat.name = battery->name;
        battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
        if (!acpi_battery_mode(battery)) {
@@ -822,10 +544,6 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
                        device_remove_file(battery->bat.dev, &alarm_attr);
                power_supply_unregister(&battery->bat);
        }
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       proc_remove(battery->proc_entry);
-       battery->proc_entry = NULL;
-#endif
 }
 
 static int acpi_charger_add(struct acpi_sbs *sbs)
@@ -835,13 +553,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
        result = acpi_ac_get_present(sbs);
        if (result)
                goto end;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,
-                                ACPI_AC_DIR_NAME, NULL,
-                                &acpi_ac_state_fops, NULL, sbs);
-       if (result)
-               goto end;
-#endif
+
        sbs->charger.name = "sbs-charger";
        sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
        sbs->charger.properties = sbs_ac_props;
@@ -859,10 +571,6 @@ static void acpi_charger_remove(struct acpi_sbs *sbs)
 {
        if (sbs->charger.dev)
                power_supply_unregister(&sbs->charger);
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       proc_remove(sbs->charger_entry);
-       sbs->charger_entry = NULL;
-#endif
 }
 
 static void acpi_sbs_callback(void *context)
@@ -950,20 +658,6 @@ static int acpi_sbs_remove(struct acpi_device *device)
        return 0;
 }
 
-static void acpi_sbs_rmdirs(void)
-{
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       if (acpi_ac_dir) {
-               acpi_unlock_ac_dir(acpi_ac_dir);
-               acpi_ac_dir = NULL;
-       }
-       if (acpi_battery_dir) {
-               acpi_unlock_battery_dir(acpi_battery_dir);
-               acpi_battery_dir = NULL;
-       }
-#endif
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int acpi_sbs_resume(struct device *dev)
 {
@@ -995,28 +689,17 @@ static int __init acpi_sbs_init(void)
 
        if (acpi_disabled)
                return -ENODEV;
-#ifdef CONFIG_ACPI_PROCFS_POWER
-       acpi_ac_dir = acpi_lock_ac_dir();
-       if (!acpi_ac_dir)
-               return -ENODEV;
-       acpi_battery_dir = acpi_lock_battery_dir();
-       if (!acpi_battery_dir) {
-               acpi_sbs_rmdirs();
-               return -ENODEV;
-       }
-#endif
+
        result = acpi_bus_register_driver(&acpi_sbs_driver);
-       if (result < 0) {
-               acpi_sbs_rmdirs();
+       if (result < 0)
                return -ENODEV;
-       }
+
        return 0;
 }
 
 static void __exit acpi_sbs_exit(void)
 {
        acpi_bus_unregister_driver(&acpi_sbs_driver);
-       acpi_sbs_rmdirs();
        return;
 }
 
index 05306a59aedc18b45dd89f636d907def41d67d11..db5293650f622108e80a09124097f469c727547f 100644 (file)
@@ -564,6 +564,7 @@ static ssize_t counter_set(struct kobject *kobj,
        acpi_event_status status;
        acpi_handle handle;
        int result = 0;
+       unsigned long tmp;
 
        if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) {
                int i;
@@ -596,8 +597,10 @@ static ssize_t counter_set(struct kobject *kobj,
                else if (!strcmp(buf, "clear\n") &&
                         (status & ACPI_EVENT_FLAG_SET))
                        result = acpi_clear_gpe(handle, index);
+               else if (!kstrtoul(buf, 0, &tmp))
+                       all_counters[index].count = tmp;
                else
-                       all_counters[index].count = strtoul(buf, NULL, 0);
+                       result = -EINVAL;
        } else if (index < num_gpes + ACPI_NUM_FIXED_EVENTS) {
                int event = index - num_gpes;
                if (!strcmp(buf, "disable\n") &&
@@ -609,8 +612,10 @@ static ssize_t counter_set(struct kobject *kobj,
                else if (!strcmp(buf, "clear\n") &&
                         (status & ACPI_EVENT_FLAG_SET))
                        result = acpi_clear_event(event);
+               else if (!kstrtoul(buf, 0, &tmp))
+                       all_counters[index].count = tmp;
                else
-                       all_counters[index].count = strtoul(buf, NULL, 0);
+                       result = -EINVAL;
        } else
                all_counters[index].count = strtoul(buf, NULL, 0);
 
@@ -762,13 +767,8 @@ void acpi_sysfs_add_hotplug_profile(struct acpi_hotplug_profile *hotplug,
        if (!hotplug_kobj)
                goto err_out;
 
-       kobject_init(&hotplug->kobj, &acpi_hotplug_profile_ktype);
-       error = kobject_set_name(&hotplug->kobj, "%s", name);
-       if (error)
-               goto err_out;
-
-       hotplug->kobj.parent = hotplug_kobj;
-       error = kobject_add(&hotplug->kobj, hotplug_kobj, NULL);
+       error = kobject_init_and_add(&hotplug->kobj,
+               &acpi_hotplug_profile_ktype, hotplug_kobj, "%s", name);
        if (error)
                goto err_out;
 
index 6a0329340b42ad188add760db66ebcc17ba9ab22..e600b5dbfcb6028e7aa49953d53d60e14b167043 100644 (file)
@@ -299,8 +299,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                        ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                          "No critical threshold\n"));
                } else if (tmp <= 2732) {
-                       printk(KERN_WARNING FW_BUG "Invalid critical threshold "
-                              "(%llu)\n", tmp);
+                       pr_warn(FW_BUG "Invalid critical threshold (%llu)\n",
+                               tmp);
                        tz->trips.critical.flags.valid = 0;
                } else {
                        tz->trips.critical.flags.valid = 1;
@@ -317,8 +317,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                                 * Allow override critical threshold
                                 */
                                if (crt_k > tz->trips.critical.temperature)
-                                       printk(KERN_WARNING PREFIX
-                                               "Critical threshold %d C\n", crt);
+                                       pr_warn(PREFIX "Critical threshold %d C\n",
+                                               crt);
                                tz->trips.critical.temperature = crt_k;
                        }
                }
@@ -390,8 +390,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                status = acpi_evaluate_reference(tz->device->handle, "_PSL",
                                                        NULL, &devices);
                if (ACPI_FAILURE(status)) {
-                       printk(KERN_WARNING PREFIX
-                               "Invalid passive threshold\n");
+                       pr_warn(PREFIX "Invalid passive threshold\n");
                        tz->trips.passive.flags.valid = 0;
                }
                else
@@ -453,8 +452,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
                        status = acpi_evaluate_reference(tz->device->handle,
                                                name, NULL, &devices);
                        if (ACPI_FAILURE(status)) {
-                               printk(KERN_WARNING PREFIX
-                                       "Invalid active%d threshold\n", i);
+                               pr_warn(PREFIX "Invalid active%d threshold\n",
+                                       i);
                                tz->trips.active[i].flags.valid = 0;
                        }
                        else
@@ -505,7 +504,7 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
                valid |= tz->trips.active[i].flags.valid;
 
        if (!valid) {
-               printk(KERN_WARNING FW_BUG "No valid trip found\n");
+               pr_warn(FW_BUG "No valid trip found\n");
                return -ENODEV;
        }
        return 0;
@@ -923,8 +922,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
                                  acpi_bus_private_data_handler,
                                  tz->thermal_zone);
        if (ACPI_FAILURE(status)) {
-               printk(KERN_ERR PREFIX
-                               "Error attaching device data\n");
+               pr_err(PREFIX "Error attaching device data\n");
                return -ENODEV;
        }
 
@@ -1094,9 +1092,8 @@ static int acpi_thermal_add(struct acpi_device *device)
        if (result)
                goto free_memory;
 
-       printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
-              acpi_device_name(device), acpi_device_bid(device),
-              KELVIN_TO_CELSIUS(tz->temperature));
+       pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
+               acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature));
        goto end;
 
 free_memory:
@@ -1159,24 +1156,24 @@ static int acpi_thermal_resume(struct device *dev)
 static int thermal_act(const struct dmi_system_id *d) {
 
        if (act == 0) {
-               printk(KERN_NOTICE "ACPI: %s detected: "
-                       "disabling all active thermal trip points\n", d->ident);
+               pr_notice(PREFIX "%s detected: "
+                         "disabling all active thermal trip points\n", d->ident);
                act = -1;
        }
        return 0;
 }
 static int thermal_nocrt(const struct dmi_system_id *d) {
 
-       printk(KERN_NOTICE "ACPI: %s detected: "
-               "disabling all critical thermal trip point actions.\n", d->ident);
+       pr_notice(PREFIX "%s detected: "
+                 "disabling all critical thermal trip point actions.\n", d->ident);
        nocrt = 1;
        return 0;
 }
 static int thermal_tzp(const struct dmi_system_id *d) {
 
        if (tzp == 0) {
-               printk(KERN_NOTICE "ACPI: %s detected: "
-                       "enabling thermal zone polling\n", d->ident);
+               pr_notice(PREFIX "%s detected: "
+                         "enabling thermal zone polling\n", d->ident);
                tzp = 300;      /* 300 dS = 30 Seconds */
        }
        return 0;
@@ -1184,8 +1181,8 @@ static int thermal_tzp(const struct dmi_system_id *d) {
 static int thermal_psv(const struct dmi_system_id *d) {
 
        if (psv == 0) {
-               printk(KERN_NOTICE "ACPI: %s detected: "
-                       "disabling all passive thermal trip points\n", d->ident);
+               pr_notice(PREFIX "%s detected: "
+                         "disabling all passive thermal trip points\n", d->ident);
                psv = -1;
        }
        return 0;
@@ -1238,7 +1235,7 @@ static int __init acpi_thermal_init(void)
        dmi_check_system(thermal_dmi_table);
 
        if (off) {
-               printk(KERN_NOTICE "ACPI: thermal control disabled\n");
+               pr_notice(PREFIX "thermal control disabled\n");
                return -ENODEV;
        }
 
index 552248b0005b01a241ab511e52eef08a1c15d244..fc2cd328408053dfaa37eceb227de974b2796bf6 100644 (file)
@@ -169,11 +169,20 @@ acpi_extract_package(union acpi_object *package,
        /*
         * Validate output buffer.
         */
-       if (buffer->length < size_required) {
+       if (buffer->length == ACPI_ALLOCATE_BUFFER) {
+               buffer->pointer = ACPI_ALLOCATE(size_required);
+               if (!buffer->pointer)
+                       return AE_NO_MEMORY;
                buffer->length = size_required;
-               return AE_BUFFER_OVERFLOW;
-       } else if (buffer->length != size_required || !buffer->pointer) {
-               return AE_BAD_PARAMETER;
+               memset(buffer->pointer, 0, size_required);
+       } else {
+               if (buffer->length < size_required) {
+                       buffer->length = size_required;
+                       return AE_BUFFER_OVERFLOW;
+               } else if (buffer->length != size_required ||
+                          !buffer->pointer) {
+                       return AE_BAD_PARAMETER;
+               }
        }
 
        head = buffer->pointer;
index aebcf6355df467e3c394c00fa5c48731e42cc18d..d020df5a732ab1109d9fd3ddcaa9c7ff871b192b 100644 (file)
@@ -88,7 +88,16 @@ module_param(allow_duplicates, bool, 0644);
 static bool use_bios_initial_backlight = 1;
 module_param(use_bios_initial_backlight, bool, 0644);
 
+/*
+ * For Windows 8 systems: if set ture and the GPU driver has
+ * registered a backlight interface, skip registering ACPI video's.
+ */
+static bool use_native_backlight = false;
+module_param(use_native_backlight, bool, 0644);
+
 static int register_count;
+static struct mutex video_list_lock;
+static struct list_head video_bus_head;
 static int acpi_video_bus_add(struct acpi_device *device);
 static int acpi_video_bus_remove(struct acpi_device *device);
 static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
@@ -157,6 +166,7 @@ struct acpi_video_bus {
        struct acpi_video_bus_flags flags;
        struct list_head video_device_list;
        struct mutex device_list_lock;  /* protects video_device_list */
+       struct list_head entry;
        struct input_dev *input;
        char phys[32];  /* for input device */
        struct notifier_block pm_nb;
@@ -229,6 +239,14 @@ static int acpi_video_get_next_level(struct acpi_video_device *device,
 static int acpi_video_switch_brightness(struct acpi_video_device *device,
                                         int event);
 
+static bool acpi_video_verify_backlight_support(void)
+{
+       if (acpi_osi_is_win8() && use_native_backlight &&
+           backlight_device_registered(BACKLIGHT_RAW))
+               return false;
+       return acpi_video_backlight_support();
+}
+
 /* backlight device sysfs support */
 static int acpi_video_get_brightness(struct backlight_device *bd)
 {
@@ -884,79 +902,6 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
 
        if (acpi_has_method(device->dev->handle, "_DDC"))
                device->cap._DDC = 1;
-
-       if (acpi_video_backlight_support()) {
-               struct backlight_properties props;
-               struct pci_dev *pdev;
-               acpi_handle acpi_parent;
-               struct device *parent = NULL;
-               int result;
-               static int count;
-               char *name;
-
-               result = acpi_video_init_brightness(device);
-               if (result)
-                       return;
-               name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
-               if (!name)
-                       return;
-               count++;
-
-               acpi_get_parent(device->dev->handle, &acpi_parent);
-
-               pdev = acpi_get_pci_dev(acpi_parent);
-               if (pdev) {
-                       parent = &pdev->dev;
-                       pci_dev_put(pdev);
-               }
-
-               memset(&props, 0, sizeof(struct backlight_properties));
-               props.type = BACKLIGHT_FIRMWARE;
-               props.max_brightness = device->brightness->count - 3;
-               device->backlight = backlight_device_register(name,
-                                                             parent,
-                                                             device,
-                                                             &acpi_backlight_ops,
-                                                             &props);
-               kfree(name);
-               if (IS_ERR(device->backlight))
-                       return;
-
-               /*
-                * Save current brightness level in case we have to restore it
-                * before acpi_video_device_lcd_set_level() is called next time.
-                */
-               device->backlight->props.brightness =
-                               acpi_video_get_brightness(device->backlight);
-
-               device->cooling_dev = thermal_cooling_device_register("LCD",
-                                       device->dev, &video_cooling_ops);
-               if (IS_ERR(device->cooling_dev)) {
-                       /*
-                        * Set cooling_dev to NULL so we don't crash trying to
-                        * free it.
-                        * Also, why the hell we are returning early and
-                        * not attempt to register video output if cooling
-                        * device registration failed?
-                        * -- dtor
-                        */
-                       device->cooling_dev = NULL;
-                       return;
-               }
-
-               dev_info(&device->dev->dev, "registered as cooling_device%d\n",
-                        device->cooling_dev->id);
-               result = sysfs_create_link(&device->dev->dev.kobj,
-                               &device->cooling_dev->device.kobj,
-                               "thermal_cooling");
-               if (result)
-                       printk(KERN_ERR PREFIX "Create sysfs link\n");
-               result = sysfs_create_link(&device->cooling_dev->device.kobj,
-                               &device->dev->dev.kobj, "device");
-               if (result)
-                       printk(KERN_ERR PREFIX "Create sysfs link\n");
-
-       }
 }
 
 /*
@@ -1143,13 +1088,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
        acpi_video_device_bind(video, data);
        acpi_video_device_find_cap(data);
 
-       status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
-                                            acpi_video_device_notify, data);
-       if (ACPI_FAILURE(status))
-               dev_err(&device->dev, "Error installing notify handler\n");
-       else
-               data->flags.notify = 1;
-
        mutex_lock(&video->device_list_lock);
        list_add_tail(&data->entry, &video->video_device_list);
        mutex_unlock(&video->device_list_lock);
@@ -1333,8 +1271,8 @@ acpi_video_switch_brightness(struct acpi_video_device *device, int event)
        unsigned long long level_current, level_next;
        int result = -EINVAL;
 
-       /* no warning message if acpi_backlight=vendor is used */
-       if (!acpi_video_backlight_support())
+       /* no warning message if acpi_backlight=vendor or a quirk is used */
+       if (!acpi_video_verify_backlight_support())
                return 0;
 
        if (!device->brightness)
@@ -1454,64 +1392,6 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
        return status;
 }
 
-static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
-{
-       acpi_status status;
-
-       if (!device || !device->video)
-               return -ENOENT;
-
-       if (device->flags.notify) {
-               status = acpi_remove_notify_handler(device->dev->handle,
-                               ACPI_DEVICE_NOTIFY, acpi_video_device_notify);
-               if (ACPI_FAILURE(status))
-                       dev_err(&device->dev->dev,
-                                       "Can't remove video notify handler\n");
-       }
-
-       if (device->backlight) {
-               backlight_device_unregister(device->backlight);
-               device->backlight = NULL;
-       }
-       if (device->cooling_dev) {
-               sysfs_remove_link(&device->dev->dev.kobj,
-                                 "thermal_cooling");
-               sysfs_remove_link(&device->cooling_dev->device.kobj,
-                                 "device");
-               thermal_cooling_device_unregister(device->cooling_dev);
-               device->cooling_dev = NULL;
-       }
-
-       return 0;
-}
-
-static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
-{
-       int status;
-       struct acpi_video_device *dev, *next;
-
-       mutex_lock(&video->device_list_lock);
-
-       list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
-
-               status = acpi_video_bus_put_one_device(dev);
-               if (ACPI_FAILURE(status))
-                       printk(KERN_WARNING PREFIX
-                              "hhuuhhuu bug in acpi video driver.\n");
-
-               if (dev->brightness) {
-                       kfree(dev->brightness->levels);
-                       kfree(dev->brightness);
-               }
-               list_del(&dev->entry);
-               kfree(dev);
-       }
-
-       mutex_unlock(&video->device_list_lock);
-
-       return 0;
-}
-
 /* acpi_video interface */
 
 /*
@@ -1521,13 +1401,13 @@ static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
 static int acpi_video_bus_start_devices(struct acpi_video_bus *video)
 {
        return acpi_video_bus_DOS(video, 0,
-                                 acpi_video_backlight_quirks() ? 1 : 0);
+                                 acpi_osi_is_win8() ? 1 : 0);
 }
 
 static int acpi_video_bus_stop_devices(struct acpi_video_bus *video)
 {
        return acpi_video_bus_DOS(video, 0,
-                                 acpi_video_backlight_quirks() ? 0 : 1);
+                                 acpi_osi_is_win8() ? 0 : 1);
 }
 
 static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
@@ -1536,7 +1416,7 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
        struct input_dev *input;
        int keycode = 0;
 
-       if (!video)
+       if (!video || !video->input)
                return;
 
        input = video->input;
@@ -1691,12 +1571,236 @@ acpi_video_bus_match(acpi_handle handle, u32 level, void *context,
        return AE_OK;
 }
 
+static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
+{
+       if (acpi_video_verify_backlight_support()) {
+               struct backlight_properties props;
+               struct pci_dev *pdev;
+               acpi_handle acpi_parent;
+               struct device *parent = NULL;
+               int result;
+               static int count;
+               char *name;
+
+               result = acpi_video_init_brightness(device);
+               if (result)
+                       return;
+               name = kasprintf(GFP_KERNEL, "acpi_video%d", count);
+               if (!name)
+                       return;
+               count++;
+
+               acpi_get_parent(device->dev->handle, &acpi_parent);
+
+               pdev = acpi_get_pci_dev(acpi_parent);
+               if (pdev) {
+                       parent = &pdev->dev;
+                       pci_dev_put(pdev);
+               }
+
+               memset(&props, 0, sizeof(struct backlight_properties));
+               props.type = BACKLIGHT_FIRMWARE;
+               props.max_brightness = device->brightness->count - 3;
+               device->backlight = backlight_device_register(name,
+                                                             parent,
+                                                             device,
+                                                             &acpi_backlight_ops,
+                                                             &props);
+               kfree(name);
+               if (IS_ERR(device->backlight))
+                       return;
+
+               /*
+                * Save current brightness level in case we have to restore it
+                * before acpi_video_device_lcd_set_level() is called next time.
+                */
+               device->backlight->props.brightness =
+                               acpi_video_get_brightness(device->backlight);
+
+               device->cooling_dev = thermal_cooling_device_register("LCD",
+                                       device->dev, &video_cooling_ops);
+               if (IS_ERR(device->cooling_dev)) {
+                       /*
+                        * Set cooling_dev to NULL so we don't crash trying to
+                        * free it.
+                        * Also, why the hell we are returning early and
+                        * not attempt to register video output if cooling
+                        * device registration failed?
+                        * -- dtor
+                        */
+                       device->cooling_dev = NULL;
+                       return;
+               }
+
+               dev_info(&device->dev->dev, "registered as cooling_device%d\n",
+                        device->cooling_dev->id);
+               result = sysfs_create_link(&device->dev->dev.kobj,
+                               &device->cooling_dev->device.kobj,
+                               "thermal_cooling");
+               if (result)
+                       printk(KERN_ERR PREFIX "Create sysfs link\n");
+               result = sysfs_create_link(&device->cooling_dev->device.kobj,
+                               &device->dev->dev.kobj, "device");
+               if (result)
+                       printk(KERN_ERR PREFIX "Create sysfs link\n");
+       }
+}
+
+static int acpi_video_bus_register_backlight(struct acpi_video_bus *video)
+{
+       struct acpi_video_device *dev;
+
+       mutex_lock(&video->device_list_lock);
+       list_for_each_entry(dev, &video->video_device_list, entry)
+               acpi_video_dev_register_backlight(dev);
+       mutex_unlock(&video->device_list_lock);
+
+       video->pm_nb.notifier_call = acpi_video_resume;
+       video->pm_nb.priority = 0;
+       return register_pm_notifier(&video->pm_nb);
+}
+
+static void acpi_video_dev_unregister_backlight(struct acpi_video_device *device)
+{
+       if (device->backlight) {
+               backlight_device_unregister(device->backlight);
+               device->backlight = NULL;
+       }
+       if (device->brightness) {
+               kfree(device->brightness->levels);
+               kfree(device->brightness);
+               device->brightness = NULL;
+       }
+       if (device->cooling_dev) {
+               sysfs_remove_link(&device->dev->dev.kobj, "thermal_cooling");
+               sysfs_remove_link(&device->cooling_dev->device.kobj, "device");
+               thermal_cooling_device_unregister(device->cooling_dev);
+               device->cooling_dev = NULL;
+       }
+}
+
+static int acpi_video_bus_unregister_backlight(struct acpi_video_bus *video)
+{
+       struct acpi_video_device *dev;
+       int error = unregister_pm_notifier(&video->pm_nb);
+
+       mutex_lock(&video->device_list_lock);
+       list_for_each_entry(dev, &video->video_device_list, entry)
+               acpi_video_dev_unregister_backlight(dev);
+       mutex_unlock(&video->device_list_lock);
+
+       return error;
+}
+
+static void acpi_video_dev_add_notify_handler(struct acpi_video_device *device)
+{
+       acpi_status status;
+       struct acpi_device *adev = device->dev;
+
+       status = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY,
+                                            acpi_video_device_notify, device);
+       if (ACPI_FAILURE(status))
+               dev_err(&adev->dev, "Error installing notify handler\n");
+       else
+               device->flags.notify = 1;
+}
+
+static int acpi_video_bus_add_notify_handler(struct acpi_video_bus *video)
+{
+       struct input_dev *input;
+       struct acpi_video_device *dev;
+       int error;
+
+       video->input = input = input_allocate_device();
+       if (!input) {
+               error = -ENOMEM;
+               goto out;
+       }
+
+       error = acpi_video_bus_start_devices(video);
+       if (error)
+               goto err_free_input;
+
+       snprintf(video->phys, sizeof(video->phys),
+                       "%s/video/input0", acpi_device_hid(video->device));
+
+       input->name = acpi_device_name(video->device);
+       input->phys = video->phys;
+       input->id.bustype = BUS_HOST;
+       input->id.product = 0x06;
+       input->dev.parent = &video->device->dev;
+       input->evbit[0] = BIT(EV_KEY);
+       set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
+       set_bit(KEY_VIDEO_NEXT, input->keybit);
+       set_bit(KEY_VIDEO_PREV, input->keybit);
+       set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit);
+       set_bit(KEY_BRIGHTNESSUP, input->keybit);
+       set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
+       set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
+       set_bit(KEY_DISPLAY_OFF, input->keybit);
+
+       error = input_register_device(input);
+       if (error)
+               goto err_stop_dev;
+
+       mutex_lock(&video->device_list_lock);
+       list_for_each_entry(dev, &video->video_device_list, entry)
+               acpi_video_dev_add_notify_handler(dev);
+       mutex_unlock(&video->device_list_lock);
+
+       return 0;
+
+err_stop_dev:
+       acpi_video_bus_stop_devices(video);
+err_free_input:
+       input_free_device(input);
+       video->input = NULL;
+out:
+       return error;
+}
+
+static void acpi_video_dev_remove_notify_handler(struct acpi_video_device *dev)
+{
+       if (dev->flags.notify) {
+               acpi_remove_notify_handler(dev->dev->handle, ACPI_DEVICE_NOTIFY,
+                                          acpi_video_device_notify);
+               dev->flags.notify = 0;
+       }
+}
+
+static void acpi_video_bus_remove_notify_handler(struct acpi_video_bus *video)
+{
+       struct acpi_video_device *dev;
+
+       mutex_lock(&video->device_list_lock);
+       list_for_each_entry(dev, &video->video_device_list, entry)
+               acpi_video_dev_remove_notify_handler(dev);
+       mutex_unlock(&video->device_list_lock);
+
+       acpi_video_bus_stop_devices(video);
+       input_unregister_device(video->input);
+       video->input = NULL;
+}
+
+static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
+{
+       struct acpi_video_device *dev, *next;
+
+       mutex_lock(&video->device_list_lock);
+       list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
+               list_del(&dev->entry);
+               kfree(dev);
+       }
+       mutex_unlock(&video->device_list_lock);
+
+       return 0;
+}
+
 static int instance;
 
 static int acpi_video_bus_add(struct acpi_device *device)
 {
        struct acpi_video_bus *video;
-       struct input_dev *input;
        int error;
        acpi_status status;
 
@@ -1748,62 +1852,24 @@ static int acpi_video_bus_add(struct acpi_device *device)
        if (error)
                goto err_put_video;
 
-       video->input = input = input_allocate_device();
-       if (!input) {
-               error = -ENOMEM;
-               goto err_put_video;
-       }
-
-       error = acpi_video_bus_start_devices(video);
-       if (error)
-               goto err_free_input_dev;
-
-       snprintf(video->phys, sizeof(video->phys),
-               "%s/video/input0", acpi_device_hid(video->device));
-
-       input->name = acpi_device_name(video->device);
-       input->phys = video->phys;
-       input->id.bustype = BUS_HOST;
-       input->id.product = 0x06;
-       input->dev.parent = &device->dev;
-       input->evbit[0] = BIT(EV_KEY);
-       set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
-       set_bit(KEY_VIDEO_NEXT, input->keybit);
-       set_bit(KEY_VIDEO_PREV, input->keybit);
-       set_bit(KEY_BRIGHTNESS_CYCLE, input->keybit);
-       set_bit(KEY_BRIGHTNESSUP, input->keybit);
-       set_bit(KEY_BRIGHTNESSDOWN, input->keybit);
-       set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
-       set_bit(KEY_DISPLAY_OFF, input->keybit);
-
        printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s  rom: %s  post: %s)\n",
               ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
               video->flags.multihead ? "yes" : "no",
               video->flags.rom ? "yes" : "no",
               video->flags.post ? "yes" : "no");
+       mutex_lock(&video_list_lock);
+       list_add_tail(&video->entry, &video_bus_head);
+       mutex_unlock(&video_list_lock);
 
-       video->pm_nb.notifier_call = acpi_video_resume;
-       video->pm_nb.priority = 0;
-       error = register_pm_notifier(&video->pm_nb);
-       if (error)
-               goto err_stop_video;
-
-       error = input_register_device(input);
-       if (error)
-               goto err_unregister_pm_notifier;
+       acpi_video_bus_register_backlight(video);
+       acpi_video_bus_add_notify_handler(video);
 
        return 0;
 
- err_unregister_pm_notifier:
-       unregister_pm_notifier(&video->pm_nb);
- err_stop_video:
-       acpi_video_bus_stop_devices(video);
- err_free_input_dev:
-       input_free_device(input);
- err_put_video:
+err_put_video:
        acpi_video_bus_put_devices(video);
        kfree(video->attached_array);
- err_free_video:
+err_free_video:
        kfree(video);
        device->driver_data = NULL;
 
@@ -1820,12 +1886,14 @@ static int acpi_video_bus_remove(struct acpi_device *device)
 
        video = acpi_driver_data(device);
 
-       unregister_pm_notifier(&video->pm_nb);
-
-       acpi_video_bus_stop_devices(video);
+       acpi_video_bus_remove_notify_handler(video);
+       acpi_video_bus_unregister_backlight(video);
        acpi_video_bus_put_devices(video);
 
-       input_unregister_device(video->input);
+       mutex_lock(&video_list_lock);
+       list_del(&video->entry);
+       mutex_unlock(&video_list_lock);
+
        kfree(video->attached_array);
        kfree(video);
 
@@ -1874,6 +1942,9 @@ int acpi_video_register(void)
                return 0;
        }
 
+       mutex_init(&video_list_lock);
+       INIT_LIST_HEAD(&video_bus_head);
+
        result = acpi_bus_register_driver(&acpi_video_bus);
        if (result < 0)
                return -ENODEV;
index 940edbf2fe8f4460b27fceb1e7fe5fdb7cbacfc3..84875fd4c74f9fbd100106ea3615ffcde2daf6cf 100644 (file)
@@ -168,6 +168,14 @@ static struct dmi_system_id video_detect_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
                },
        },
+       {
+       .callback = video_detect_force_vendor,
+       .ident = "Lenovo Yoga 13",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga 13"),
+               },
+       },
        { },
 };
 
@@ -233,11 +241,11 @@ static void acpi_video_caps_check(void)
                acpi_video_get_capabilities(NULL);
 }
 
-bool acpi_video_backlight_quirks(void)
+bool acpi_osi_is_win8(void)
 {
        return acpi_gbl_osi_data >= ACPI_OSI_WIN_8;
 }
-EXPORT_SYMBOL(acpi_video_backlight_quirks);
+EXPORT_SYMBOL(acpi_osi_is_win8);
 
 /* Promote the vendor interface instead of the generic video module.
  * This function allow DMI blacklists to be implemented by externals
index 848ebbd25717269fa0ef34e1632e502eb29f4aeb..f48370dfc908e19a73a86cf817ad05128c0ed034 100644 (file)
@@ -44,13 +44,11 @@ static int __ref cpu_subsys_online(struct device *dev)
        struct cpu *cpu = container_of(dev, struct cpu, dev);
        int cpuid = dev->id;
        int from_nid, to_nid;
-       int ret = -ENODEV;
-
-       cpu_hotplug_driver_lock();
+       int ret;
 
        from_nid = cpu_to_node(cpuid);
        if (from_nid == NUMA_NO_NODE)
-               goto out;
+               return -ENODEV;
 
        ret = cpu_up(cpuid);
        /*
@@ -61,19 +59,12 @@ static int __ref cpu_subsys_online(struct device *dev)
        if (from_nid != to_nid)
                change_cpu_under_node(cpu, from_nid, to_nid);
 
- out:
-       cpu_hotplug_driver_unlock();
        return ret;
 }
 
 static int cpu_subsys_offline(struct device *dev)
 {
-       int ret;
-
-       cpu_hotplug_driver_lock();
-       ret = cpu_down(dev->id);
-       cpu_hotplug_driver_unlock();
-       return ret;
+       return cpu_down(dev->id);
 }
 
 void unregister_cpu(struct cpu *cpu)
@@ -93,7 +84,17 @@ static ssize_t cpu_probe_store(struct device *dev,
                               const char *buf,
                               size_t count)
 {
-       return arch_cpu_probe(buf, count);
+       ssize_t cnt;
+       int ret;
+
+       ret = lock_device_hotplug_sysfs();
+       if (ret)
+               return ret;
+
+       cnt = arch_cpu_probe(buf, count);
+
+       unlock_device_hotplug();
+       return cnt;
 }
 
 static ssize_t cpu_release_store(struct device *dev,
@@ -101,7 +102,17 @@ static ssize_t cpu_release_store(struct device *dev,
                                 const char *buf,
                                 size_t count)
 {
-       return arch_cpu_release(buf, count);
+       ssize_t cnt;
+       int ret;
+
+       ret = lock_device_hotplug_sysfs();
+       if (ret)
+               return ret;
+
+       cnt = arch_cpu_release(buf, count);
+
+       unlock_device_hotplug();
+       return cnt;
 }
 
 static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
index 9f098a82cf04b061edb203fff718ef0ca70e6328..ee039afe90786510eb19e0a536beb30413b27a38 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/suspend.h>
 #include <trace/events/power.h>
 #include <linux/cpuidle.h>
+#include <linux/timer.h>
+
 #include "../base.h"
 #include "power.h"
 
@@ -390,6 +392,71 @@ static int dpm_run_callback(pm_callback_t cb, struct device *dev,
        return error;
 }
 
+#ifdef CONFIG_DPM_WATCHDOG
+struct dpm_watchdog {
+       struct device           *dev;
+       struct task_struct      *tsk;
+       struct timer_list       timer;
+};
+
+#define DECLARE_DPM_WATCHDOG_ON_STACK(wd) \
+       struct dpm_watchdog wd
+
+/**
+ * dpm_watchdog_handler - Driver suspend / resume watchdog handler.
+ * @data: Watchdog object address.
+ *
+ * Called when a driver has timed out suspending or resuming.
+ * There's not much we can do here to recover so panic() to
+ * capture a crash-dump in pstore.
+ */
+static void dpm_watchdog_handler(unsigned long data)
+{
+       struct dpm_watchdog *wd = (void *)data;
+
+       dev_emerg(wd->dev, "**** DPM device timeout ****\n");
+       show_stack(wd->tsk, NULL);
+       panic("%s %s: unrecoverable failure\n",
+               dev_driver_string(wd->dev), dev_name(wd->dev));
+}
+
+/**
+ * dpm_watchdog_set - Enable pm watchdog for given device.
+ * @wd: Watchdog. Must be allocated on the stack.
+ * @dev: Device to handle.
+ */
+static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
+{
+       struct timer_list *timer = &wd->timer;
+
+       wd->dev = dev;
+       wd->tsk = current;
+
+       init_timer_on_stack(timer);
+       /* use same timeout value for both suspend and resume */
+       timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_TIMEOUT;
+       timer->function = dpm_watchdog_handler;
+       timer->data = (unsigned long)wd;
+       add_timer(timer);
+}
+
+/**
+ * dpm_watchdog_clear - Disable suspend/resume watchdog.
+ * @wd: Watchdog to disable.
+ */
+static void dpm_watchdog_clear(struct dpm_watchdog *wd)
+{
+       struct timer_list *timer = &wd->timer;
+
+       del_timer_sync(timer);
+       destroy_timer_on_stack(timer);
+}
+#else
+#define DECLARE_DPM_WATCHDOG_ON_STACK(wd)
+#define dpm_watchdog_set(x, y)
+#define dpm_watchdog_clear(x)
+#endif
+
 /*------------------------- Resume routines -------------------------*/
 
 /**
@@ -576,6 +643,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
        pm_callback_t callback = NULL;
        char *info = NULL;
        int error = 0;
+       DECLARE_DPM_WATCHDOG_ON_STACK(wd);
 
        TRACE_DEVICE(dev);
        TRACE_RESUME(0);
@@ -584,6 +652,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
                goto Complete;
 
        dpm_wait(dev->parent, async);
+       dpm_watchdog_set(&wd, dev);
        device_lock(dev);
 
        /*
@@ -642,6 +711,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
 
  Unlock:
        device_unlock(dev);
+       dpm_watchdog_clear(&wd);
 
  Complete:
        complete_all(&dev->power.completion);
@@ -1060,6 +1130,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
        pm_callback_t callback = NULL;
        char *info = NULL;
        int error = 0;
+       DECLARE_DPM_WATCHDOG_ON_STACK(wd);
 
        dpm_wait_for_children(dev, async);
 
@@ -1083,6 +1154,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
        if (dev->power.syscore)
                goto Complete;
 
+       dpm_watchdog_set(&wd, dev);
        device_lock(dev);
 
        if (dev->pm_domain) {
@@ -1139,6 +1211,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
        }
 
        device_unlock(dev);
+       dpm_watchdog_clear(&wd);
 
  Complete:
        complete_all(&dev->power.completion);
index ef89897c6043eec57ed2d8d1f4c6db464cfd92d1..fa41874184401cd46c155526102fb72aed99e329 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/list.h>
 #include <linux/rculist.h>
 #include <linux/rcupdate.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/of.h>
 #include <linux/export.h>
 
@@ -42,7 +42,7 @@
  */
 
 /**
- * struct opp - Generic OPP description structure
+ * struct dev_pm_opp - Generic OPP description structure
  * @node:      opp list node. The nodes are maintained throughout the lifetime
  *             of boot. It is expected only an optimal set of OPPs are
  *             added to the library by the SoC framework.
@@ -59,7 +59,7 @@
  *
  * This structure stores the OPP information for a given device.
  */
-struct opp {
+struct dev_pm_opp {
        struct list_head node;
 
        bool available;
@@ -136,7 +136,7 @@ static struct device_opp *find_device_opp(struct device *dev)
 }
 
 /**
- * opp_get_voltage() - Gets the voltage corresponding to an available opp
+ * dev_pm_opp_get_voltage() - Gets the voltage corresponding to an available opp
  * @opp:       opp for which voltage has to be returned for
  *
  * Return voltage in micro volt corresponding to the opp, else
@@ -150,9 +150,9 @@ static struct device_opp *find_device_opp(struct device *dev)
  * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
  * pointer.
  */
-unsigned long opp_get_voltage(struct opp *opp)
+unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
 {
-       struct opp *tmp_opp;
+       struct dev_pm_opp *tmp_opp;
        unsigned long v = 0;
 
        tmp_opp = rcu_dereference(opp);
@@ -163,10 +163,10 @@ unsigned long opp_get_voltage(struct opp *opp)
 
        return v;
 }
-EXPORT_SYMBOL_GPL(opp_get_voltage);
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_voltage);
 
 /**
- * opp_get_freq() - Gets the frequency corresponding to an available opp
+ * dev_pm_opp_get_freq() - Gets the frequency corresponding to an available opp
  * @opp:       opp for which frequency has to be returned for
  *
  * Return frequency in hertz corresponding to the opp, else
@@ -180,9 +180,9 @@ EXPORT_SYMBOL_GPL(opp_get_voltage);
  * prior to unlocking with rcu_read_unlock() to maintain the integrity of the
  * pointer.
  */
-unsigned long opp_get_freq(struct opp *opp)
+unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
 {
-       struct opp *tmp_opp;
+       struct dev_pm_opp *tmp_opp;
        unsigned long f = 0;
 
        tmp_opp = rcu_dereference(opp);
@@ -193,10 +193,10 @@ unsigned long opp_get_freq(struct opp *opp)
 
        return f;
 }
-EXPORT_SYMBOL_GPL(opp_get_freq);
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_freq);
 
 /**
- * opp_get_opp_count() - Get number of opps available in the opp list
+ * dev_pm_opp_get_opp_count() - Get number of opps available in the opp list
  * @dev:       device for which we do this operation
  *
  * This function returns the number of available opps if there are any,
@@ -206,10 +206,10 @@ EXPORT_SYMBOL_GPL(opp_get_freq);
  * internally references two RCU protected structures: device_opp and opp which
  * are safe as long as we are under a common RCU locked section.
  */
-int opp_get_opp_count(struct device *dev)
+int dev_pm_opp_get_opp_count(struct device *dev)
 {
        struct device_opp *dev_opp;
-       struct opp *temp_opp;
+       struct dev_pm_opp *temp_opp;
        int count = 0;
 
        dev_opp = find_device_opp(dev);
@@ -226,10 +226,10 @@ int opp_get_opp_count(struct device *dev)
 
        return count;
 }
-EXPORT_SYMBOL_GPL(opp_get_opp_count);
+EXPORT_SYMBOL_GPL(dev_pm_opp_get_opp_count);
 
 /**
- * opp_find_freq_exact() - search for an exact frequency
+ * dev_pm_opp_find_freq_exact() - search for an exact frequency
  * @dev:               device for which we do this operation
  * @freq:              frequency to search for
  * @available:         true/false - match for available opp
@@ -254,11 +254,12 @@ EXPORT_SYMBOL_GPL(opp_get_opp_count);
  * under the locked area. The pointer returned must be used prior to unlocking
  * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
-struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
-                               bool available)
+struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
+                                             unsigned long freq,
+                                             bool available)
 {
        struct device_opp *dev_opp;
-       struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
+       struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        dev_opp = find_device_opp(dev);
        if (IS_ERR(dev_opp)) {
@@ -277,10 +278,10 @@ struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
 
        return opp;
 }
-EXPORT_SYMBOL_GPL(opp_find_freq_exact);
+EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_exact);
 
 /**
- * opp_find_freq_ceil() - Search for an rounded ceil freq
+ * dev_pm_opp_find_freq_ceil() - Search for an rounded ceil freq
  * @dev:       device for which we do this operation
  * @freq:      Start frequency
  *
@@ -300,10 +301,11 @@ EXPORT_SYMBOL_GPL(opp_find_freq_exact);
  * under the locked area. The pointer returned must be used prior to unlocking
  * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
-struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
+struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
+                                            unsigned long *freq)
 {
        struct device_opp *dev_opp;
-       struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
+       struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        if (!dev || !freq) {
                dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -324,10 +326,10 @@ struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq)
 
        return opp;
 }
-EXPORT_SYMBOL_GPL(opp_find_freq_ceil);
+EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_ceil);
 
 /**
- * opp_find_freq_floor() - Search for a rounded floor freq
+ * dev_pm_opp_find_freq_floor() - Search for a rounded floor freq
  * @dev:       device for which we do this operation
  * @freq:      Start frequency
  *
@@ -347,10 +349,11 @@ EXPORT_SYMBOL_GPL(opp_find_freq_ceil);
  * under the locked area. The pointer returned must be used prior to unlocking
  * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
-struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
+struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
+                                             unsigned long *freq)
 {
        struct device_opp *dev_opp;
-       struct opp *temp_opp, *opp = ERR_PTR(-ERANGE);
+       struct dev_pm_opp *temp_opp, *opp = ERR_PTR(-ERANGE);
 
        if (!dev || !freq) {
                dev_err(dev, "%s: Invalid argument freq=%p\n", __func__, freq);
@@ -375,17 +378,17 @@ struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq)
 
        return opp;
 }
-EXPORT_SYMBOL_GPL(opp_find_freq_floor);
+EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
 
 /**
- * opp_add()  - Add an OPP table from a table definitions
+ * dev_pm_opp_add()  - Add an OPP table from a table definitions
  * @dev:       device for which we do this operation
  * @freq:      Frequency in Hz for this OPP
  * @u_volt:    Voltage in uVolts for this OPP
  *
  * This function adds an opp definition to the opp list and returns status.
  * The opp is made available by default and it can be controlled using
- * opp_enable/disable functions.
+ * dev_pm_opp_enable/disable functions.
  *
  * Locking: The internal device_opp and opp structures are RCU protected.
  * Hence this function internally uses RCU updater strategy with mutex locks
@@ -393,14 +396,14 @@ EXPORT_SYMBOL_GPL(opp_find_freq_floor);
  * that this function is *NOT* called under RCU protection or in contexts where
  * mutex cannot be locked.
  */
-int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
+int dev_pm_opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
 {
        struct device_opp *dev_opp = NULL;
-       struct opp *opp, *new_opp;
+       struct dev_pm_opp *opp, *new_opp;
        struct list_head *head;
 
        /* allocate new OPP node */
-       new_opp = kzalloc(sizeof(struct opp), GFP_KERNEL);
+       new_opp = kzalloc(sizeof(*new_opp), GFP_KERNEL);
        if (!new_opp) {
                dev_warn(dev, "%s: Unable to create new OPP node\n", __func__);
                return -ENOMEM;
@@ -460,7 +463,7 @@ int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt)
        srcu_notifier_call_chain(&dev_opp->head, OPP_EVENT_ADD, new_opp);
        return 0;
 }
-EXPORT_SYMBOL_GPL(opp_add);
+EXPORT_SYMBOL_GPL(dev_pm_opp_add);
 
 /**
  * opp_set_availability() - helper to set the availability of an opp
@@ -485,11 +488,11 @@ static int opp_set_availability(struct device *dev, unsigned long freq,
                bool availability_req)
 {
        struct device_opp *tmp_dev_opp, *dev_opp = ERR_PTR(-ENODEV);
-       struct opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
+       struct dev_pm_opp *new_opp, *tmp_opp, *opp = ERR_PTR(-ENODEV);
        int r = 0;
 
        /* keep the node allocated */
-       new_opp = kmalloc(sizeof(struct opp), GFP_KERNEL);
+       new_opp = kmalloc(sizeof(*new_opp), GFP_KERNEL);
        if (!new_opp) {
                dev_warn(dev, "%s: Unable to create OPP\n", __func__);
                return -ENOMEM;
@@ -552,13 +555,13 @@ unlock:
 }
 
 /**
- * opp_enable() - Enable a specific OPP
+ * dev_pm_opp_enable() - Enable a specific OPP
  * @dev:       device for which we do this operation
  * @freq:      OPP frequency to enable
  *
  * Enables a provided opp. If the operation is valid, this returns 0, else the
  * corresponding error value. It is meant to be used for users an OPP available
- * after being temporarily made unavailable with opp_disable.
+ * after being temporarily made unavailable with dev_pm_opp_disable.
  *
  * Locking: The internal device_opp and opp structures are RCU protected.
  * Hence this function indirectly uses RCU and mutex locks to keep the
@@ -566,21 +569,21 @@ unlock:
  * this function is *NOT* called under RCU protection or in contexts where
  * mutex locking or synchronize_rcu() blocking calls cannot be used.
  */
-int opp_enable(struct device *dev, unsigned long freq)
+int dev_pm_opp_enable(struct device *dev, unsigned long freq)
 {
        return opp_set_availability(dev, freq, true);
 }
-EXPORT_SYMBOL_GPL(opp_enable);
+EXPORT_SYMBOL_GPL(dev_pm_opp_enable);
 
 /**
- * opp_disable() - Disable a specific OPP
+ * dev_pm_opp_disable() - Disable a specific OPP
  * @dev:       device for which we do this operation
  * @freq:      OPP frequency to disable
  *
  * Disables a provided opp. If the operation is valid, this returns
  * 0, else the corresponding error value. It is meant to be a temporary
  * control by users to make this OPP not available until the circumstances are
- * right to make it available again (with a call to opp_enable).
+ * right to make it available again (with a call to dev_pm_opp_enable).
  *
  * Locking: The internal device_opp and opp structures are RCU protected.
  * Hence this function indirectly uses RCU and mutex locks to keep the
@@ -588,15 +591,15 @@ EXPORT_SYMBOL_GPL(opp_enable);
  * this function is *NOT* called under RCU protection or in contexts where
  * mutex locking or synchronize_rcu() blocking calls cannot be used.
  */
-int opp_disable(struct device *dev, unsigned long freq)
+int dev_pm_opp_disable(struct device *dev, unsigned long freq)
 {
        return opp_set_availability(dev, freq, false);
 }
-EXPORT_SYMBOL_GPL(opp_disable);
+EXPORT_SYMBOL_GPL(dev_pm_opp_disable);
 
 #ifdef CONFIG_CPU_FREQ
 /**
- * opp_init_cpufreq_table() - create a cpufreq table for a device
+ * dev_pm_opp_init_cpufreq_table() - create a cpufreq table for a device
  * @dev:       device for which we do this operation
  * @table:     Cpufreq table returned back to caller
  *
@@ -619,11 +622,11 @@ EXPORT_SYMBOL_GPL(opp_disable);
  * Callers should ensure that this function is *NOT* called under RCU protection
  * or in contexts where mutex locking cannot be used.
  */
-int opp_init_cpufreq_table(struct device *dev,
+int dev_pm_opp_init_cpufreq_table(struct device *dev,
                            struct cpufreq_frequency_table **table)
 {
        struct device_opp *dev_opp;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        struct cpufreq_frequency_table *freq_table;
        int i = 0;
 
@@ -639,7 +642,7 @@ int opp_init_cpufreq_table(struct device *dev,
        }
 
        freq_table = kzalloc(sizeof(struct cpufreq_frequency_table) *
-                            (opp_get_opp_count(dev) + 1), GFP_KERNEL);
+                            (dev_pm_opp_get_opp_count(dev) + 1), GFP_KERNEL);
        if (!freq_table) {
                mutex_unlock(&dev_opp_list_lock);
                dev_warn(dev, "%s: Unable to allocate frequency table\n",
@@ -663,16 +666,16 @@ int opp_init_cpufreq_table(struct device *dev,
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(opp_init_cpufreq_table);
+EXPORT_SYMBOL_GPL(dev_pm_opp_init_cpufreq_table);
 
 /**
- * opp_free_cpufreq_table() - free the cpufreq table
+ * dev_pm_opp_free_cpufreq_table() - free the cpufreq table
  * @dev:       device for which we do this operation
  * @table:     table to free
  *
- * Free up the table allocated by opp_init_cpufreq_table
+ * Free up the table allocated by dev_pm_opp_init_cpufreq_table
  */
-void opp_free_cpufreq_table(struct device *dev,
+void dev_pm_opp_free_cpufreq_table(struct device *dev,
                                struct cpufreq_frequency_table **table)
 {
        if (!table)
@@ -681,14 +684,14 @@ void opp_free_cpufreq_table(struct device *dev,
        kfree(*table);
        *table = NULL;
 }
-EXPORT_SYMBOL_GPL(opp_free_cpufreq_table);
+EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
 #endif         /* CONFIG_CPU_FREQ */
 
 /**
- * opp_get_notifier() - find notifier_head of the device with opp
+ * dev_pm_opp_get_notifier() - find notifier_head of the device with opp
  * @dev:       device pointer used to lookup device OPPs.
  */
-struct srcu_notifier_head *opp_get_notifier(struct device *dev)
+struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev)
 {
        struct device_opp *dev_opp = find_device_opp(dev);
 
@@ -732,7 +735,7 @@ int of_init_opp_table(struct device *dev)
                unsigned long freq = be32_to_cpup(val++) * 1000;
                unsigned long volt = be32_to_cpup(val++);
 
-               if (opp_add(dev, freq, volt)) {
+               if (dev_pm_opp_add(dev, freq, volt)) {
                        dev_warn(dev, "%s: Failed to add OPP %ld\n",
                                 __func__, freq);
                        continue;
index 268a35097578d94f78f4baef4d9cc8b3fa1c31cd..72e00e66ecc5d3f84c6d2cce5f6d387c3d4ee260 100644 (file)
@@ -258,7 +258,8 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
  * Check if the device's runtime PM status allows it to be suspended.  If
  * another idle notification has been started earlier, return immediately.  If
  * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise
- * run the ->runtime_idle() callback directly.
+ * run the ->runtime_idle() callback directly. If the ->runtime_idle callback
+ * doesn't exist or if it returns 0, call rpm_suspend with the RPM_AUTO flag.
  *
  * This function must be called under dev->power.lock with interrupts disabled.
  */
@@ -331,7 +332,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
 
  out:
        trace_rpm_return_int(dev, _THIS_IP_, retval);
-       return retval ? retval : rpm_suspend(dev, rpmflags);
+       return retval ? retval : rpm_suspend(dev, rpmflags | RPM_AUTO);
 }
 
 /**
index 534fcb8251538a31d2695313b1d565990f8d51d4..38093e272377b2729939400c581aeb9706424011 100644 (file)
@@ -17,15 +17,11 @@ config CPU_FREQ
 
 if CPU_FREQ
 
-config CPU_FREQ_TABLE
-       tristate
-
 config CPU_FREQ_GOV_COMMON
        bool
 
 config CPU_FREQ_STAT
        tristate "CPU frequency translation statistics"
-       select CPU_FREQ_TABLE
        default y
        help
          This driver exports CPU frequency statistics information through sysfs
@@ -143,7 +139,6 @@ config CPU_FREQ_GOV_USERSPACE
 
 config CPU_FREQ_GOV_ONDEMAND
        tristate "'ondemand' cpufreq policy governor"
-       select CPU_FREQ_TABLE
        select CPU_FREQ_GOV_COMMON
        help
          'ondemand' - This driver adds a dynamic cpufreq policy governor.
@@ -187,7 +182,6 @@ config CPU_FREQ_GOV_CONSERVATIVE
 config GENERIC_CPUFREQ_CPU0
        tristate "Generic CPU0 cpufreq driver"
        depends on HAVE_CLK && REGULATOR && PM_OPP && OF
-       select CPU_FREQ_TABLE
        help
          This adds a generic cpufreq driver for CPU0 frequency management.
          It supports both uniprocessor (UP) and symmetric multiprocessor (SMP)
@@ -223,7 +217,6 @@ depends on IA64
 
 config IA64_ACPI_CPUFREQ
        tristate "ACPI Processor P-States driver"
-       select CPU_FREQ_TABLE
        depends on ACPI_PROCESSOR
        help
        This driver adds a CPUFreq driver which utilizes the ACPI
@@ -240,7 +233,6 @@ depends on MIPS
 
 config LOONGSON2_CPUFREQ
        tristate "Loongson2 CPUFreq Driver"
-       select CPU_FREQ_TABLE
        help
          This option adds a CPUFreq driver for loongson processors which
          support software configurable cpu frequency.
@@ -262,7 +254,6 @@ menu "SPARC CPU frequency scaling drivers"
 depends on SPARC64
 config SPARC_US3_CPUFREQ
        tristate "UltraSPARC-III CPU Frequency driver"
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for UltraSPARC-III processors.
 
@@ -272,7 +263,6 @@ config SPARC_US3_CPUFREQ
 
 config SPARC_US2E_CPUFREQ
        tristate "UltraSPARC-IIe CPU Frequency driver"
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for UltraSPARC-IIe processors.
 
@@ -285,7 +275,6 @@ menu "SH CPU Frequency scaling"
 depends on SUPERH
 config SH_CPU_FREQ
        tristate "SuperH CPU Frequency driver"
-       select CPU_FREQ_TABLE
        help
          This adds the cpufreq driver for SuperH. Any CPU that supports
          clock rate rounding through the clock framework can use this
index 0fa204b244bd2df52974a50fc4290e9fa77d287c..701ec95ce95487cb29dbb9a1ba45012984085299 100644 (file)
@@ -5,7 +5,6 @@
 config ARM_BIG_LITTLE_CPUFREQ
        tristate "Generic ARM big LITTLE CPUfreq driver"
        depends on ARM_CPU_TOPOLOGY && PM_OPP && HAVE_CLK
-       select CPU_FREQ_TABLE
        help
          This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
 
@@ -18,7 +17,6 @@ config ARM_DT_BL_CPUFREQ
 
 config ARM_EXYNOS_CPUFREQ
        bool
-       select CPU_FREQ_TABLE
 
 config ARM_EXYNOS4210_CPUFREQ
        bool "SAMSUNG EXYNOS4210"
@@ -58,7 +56,6 @@ config ARM_EXYNOS5440_CPUFREQ
        depends on SOC_EXYNOS5440
        depends on HAVE_CLK && PM_OPP && OF
        default y
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for Samsung EXYNOS5440
          SoC. The nature of exynos5440 clock controller is
@@ -85,7 +82,6 @@ config ARM_IMX6Q_CPUFREQ
        tristate "Freescale i.MX6Q cpufreq support"
        depends on SOC_IMX6Q
        depends on REGULATOR_ANATOP
-       select CPU_FREQ_TABLE
        help
          This adds cpufreq driver support for Freescale i.MX6Q SOC.
 
@@ -101,7 +97,6 @@ config ARM_INTEGRATOR
 
 config ARM_KIRKWOOD_CPUFREQ
        def_bool ARCH_KIRKWOOD && OF
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for Marvell Kirkwood
          SoCs.
@@ -110,7 +105,6 @@ config ARM_OMAP2PLUS_CPUFREQ
        bool "TI OMAP2+"
        depends on ARCH_OMAP2PLUS
        default ARCH_OMAP2PLUS
-       select CPU_FREQ_TABLE
 
 config ARM_S3C_CPUFREQ
        bool
@@ -165,7 +159,6 @@ config ARM_S3C2412_CPUFREQ
 config ARM_S3C2416_CPUFREQ
        bool "S3C2416 CPU Frequency scaling support"
        depends on CPU_S3C2416
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for the Samsung S3C2416 and
          S3C2450 SoC. The S3C2416 supports changing the rate of the
@@ -196,7 +189,6 @@ config ARM_S3C2440_CPUFREQ
 config ARM_S3C64XX_CPUFREQ
        bool "Samsung S3C64XX"
        depends on CPU_S3C6410
-       select CPU_FREQ_TABLE
        default y
        help
          This adds the CPUFreq driver for Samsung S3C6410 SoC.
@@ -206,7 +198,6 @@ config ARM_S3C64XX_CPUFREQ
 config ARM_S5PV210_CPUFREQ
        bool "Samsung S5PV210 and S5PC110"
        depends on CPU_S5PV210
-       select CPU_FREQ_TABLE
        default y
        help
          This adds the CPUFreq driver for Samsung S5PV210 and
@@ -223,7 +214,6 @@ config ARM_SA1110_CPUFREQ
 config ARM_SPEAR_CPUFREQ
        bool "SPEAr CPUFreq support"
        depends on PLAT_SPEAR
-       select CPU_FREQ_TABLE
        default y
        help
          This adds the CPUFreq driver support for SPEAr SOCs.
@@ -231,7 +221,6 @@ config ARM_SPEAR_CPUFREQ
 config ARM_TEGRA_CPUFREQ
        bool "TEGRA CPUFreq support"
        depends on ARCH_TEGRA
-       select CPU_FREQ_TABLE
        default y
        help
          This adds the CPUFreq driver support for TEGRA SOCs.
index 25ca9db62e090d6b49e20d6744c3cd4027a16bfb..ca0021a96e19738abefa9538bcb590e3e2c3faa7 100644 (file)
@@ -1,7 +1,6 @@
 config CPU_FREQ_CBE
        tristate "CBE frequency scaling"
        depends on CBE_RAS && PPC_CELL
-       select CPU_FREQ_TABLE
        default m
        help
          This adds the cpufreq driver for Cell BE processors.
@@ -20,7 +19,6 @@ config CPU_FREQ_CBE_PMI
 config CPU_FREQ_MAPLE
        bool "Support for Maple 970FX Evaluation Board"
        depends on PPC_MAPLE
-       select CPU_FREQ_TABLE
        help
          This adds support for frequency switching on Maple 970FX
          Evaluation Board and compatible boards (IBM JS2x blades).
@@ -28,7 +26,6 @@ config CPU_FREQ_MAPLE
 config PPC_CORENET_CPUFREQ
        tristate "CPU frequency scaling driver for Freescale E500MC SoCs"
        depends on PPC_E500MC && OF && COMMON_CLK
-       select CPU_FREQ_TABLE
        select CLK_PPC_CORENET
        help
          This adds the CPUFreq driver support for Freescale e500mc,
@@ -38,7 +35,6 @@ config PPC_CORENET_CPUFREQ
 config CPU_FREQ_PMAC
        bool "Support for Apple PowerBooks"
        depends on ADB_PMU && PPC32
-       select CPU_FREQ_TABLE
        help
          This adds support for frequency switching on Apple PowerBooks,
          this currently includes some models of iBook & Titanium
@@ -47,7 +43,6 @@ config CPU_FREQ_PMAC
 config CPU_FREQ_PMAC64
        bool "Support for some Apple G5s"
        depends on PPC_PMAC && PPC64
-       select CPU_FREQ_TABLE
        help
          This adds support for frequency switching on Apple iMac G5,
          and some of the more recent desktop G5 machines as well.
@@ -55,7 +50,6 @@ config CPU_FREQ_PMAC64
 config PPC_PASEMI_CPUFREQ
        bool "Support for PA Semi PWRficient"
        depends on PPC_PASEMI
-       select CPU_FREQ_TABLE
        default y
        help
          This adds the support for frequency switching on PA Semi
index e2b6eabef2218d4e1e392ed523b3451553e196cb..6897ad85b0467a8200c3a529e5dee14344c2afbf 100644 (file)
@@ -31,7 +31,6 @@ config X86_PCC_CPUFREQ
 
 config X86_ACPI_CPUFREQ
        tristate "ACPI Processor P-States driver"
-       select CPU_FREQ_TABLE
        depends on ACPI_PROCESSOR
        help
          This driver adds a CPUFreq driver which utilizes the ACPI
@@ -60,7 +59,6 @@ config X86_ACPI_CPUFREQ_CPB
 
 config ELAN_CPUFREQ
        tristate "AMD Elan SC400 and SC410"
-       select CPU_FREQ_TABLE
        depends on MELAN
        ---help---
          This adds the CPUFreq driver for AMD Elan SC400 and SC410
@@ -76,7 +74,6 @@ config ELAN_CPUFREQ
 
 config SC520_CPUFREQ
        tristate "AMD Elan SC520"
-       select CPU_FREQ_TABLE
        depends on MELAN
        ---help---
          This adds the CPUFreq driver for AMD Elan SC520 processor.
@@ -88,7 +85,6 @@ config SC520_CPUFREQ
 
 config X86_POWERNOW_K6
        tristate "AMD Mobile K6-2/K6-3 PowerNow!"
-       select CPU_FREQ_TABLE
        depends on X86_32
        help
          This adds the CPUFreq driver for mobile AMD K6-2+ and mobile
@@ -100,7 +96,6 @@ config X86_POWERNOW_K6
 
 config X86_POWERNOW_K7
        tristate "AMD Mobile Athlon/Duron PowerNow!"
-       select CPU_FREQ_TABLE
        depends on X86_32
        help
          This adds the CPUFreq driver for mobile AMD K7 mobile processors.
@@ -118,7 +113,6 @@ config X86_POWERNOW_K7_ACPI
 
 config X86_POWERNOW_K8
        tristate "AMD Opteron/Athlon64 PowerNow!"
-       select CPU_FREQ_TABLE
        depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ
        help
          This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors.
@@ -132,7 +126,6 @@ config X86_POWERNOW_K8
 config X86_AMD_FREQ_SENSITIVITY
        tristate "AMD frequency sensitivity feedback powersave bias"
        depends on CPU_FREQ_GOV_ONDEMAND && X86_ACPI_CPUFREQ && CPU_SUP_AMD
-       select CPU_FREQ_TABLE
        help
          This adds AMD-specific powersave bias function to the ondemand
          governor, which allows it to make more power-conscious frequency
@@ -160,7 +153,6 @@ config X86_GX_SUSPMOD
 
 config X86_SPEEDSTEP_CENTRINO
        tristate "Intel Enhanced SpeedStep (deprecated)"
-       select CPU_FREQ_TABLE
        select X86_SPEEDSTEP_CENTRINO_TABLE if X86_32
        depends on X86_32 || (X86_64 && ACPI_PROCESSOR)
        help
@@ -190,7 +182,6 @@ config X86_SPEEDSTEP_CENTRINO_TABLE
 
 config X86_SPEEDSTEP_ICH
        tristate "Intel Speedstep on ICH-M chipsets (ioport interface)"
-       select CPU_FREQ_TABLE
        depends on X86_32
        help
          This adds the CPUFreq driver for certain mobile Intel Pentium III
@@ -204,7 +195,6 @@ config X86_SPEEDSTEP_ICH
 
 config X86_SPEEDSTEP_SMI
        tristate "Intel SpeedStep on 440BX/ZX/MX chipsets (SMI interface)"
-       select CPU_FREQ_TABLE
        depends on X86_32
        help
          This adds the CPUFreq driver for certain mobile Intel Pentium III
@@ -217,7 +207,6 @@ config X86_SPEEDSTEP_SMI
 
 config X86_P4_CLOCKMOD
        tristate "Intel Pentium 4 clock modulation"
-       select CPU_FREQ_TABLE
        help
          This adds the CPUFreq driver for Intel Pentium 4 / XEON
          processors.  When enabled it will lower CPU temperature by skipping
@@ -259,7 +248,6 @@ config X86_LONGRUN
 
 config X86_LONGHAUL
        tristate "VIA Cyrix III Longhaul"
-       select CPU_FREQ_TABLE
        depends on X86_32 && ACPI_PROCESSOR
        help
          This adds the CPUFreq driver for VIA Samuel/CyrixIII,
@@ -272,7 +260,6 @@ config X86_LONGHAUL
 
 config X86_E_POWERSAVER
        tristate "VIA C7 Enhanced PowerSaver (DANGEROUS)"
-       select CPU_FREQ_TABLE
        depends on X86_32 && ACPI_PROCESSOR
        help
          This adds the CPUFreq driver for VIA C7 processors.  However, this driver
index ad5866c2ada0a5bd219305954682dbc7aae4f5a2..b7948bbbbf1fe7346590e79e3e6cbd9655272000 100644 (file)
@@ -1,5 +1,5 @@
 # CPUfreq core
-obj-$(CONFIG_CPU_FREQ)                 += cpufreq.o
+obj-$(CONFIG_CPU_FREQ)                 += cpufreq.o freq_table.o
 # CPUfreq stats
 obj-$(CONFIG_CPU_FREQ_STAT)             += cpufreq_stats.o
 
@@ -11,9 +11,6 @@ obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)   += cpufreq_ondemand.o
 obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)        += cpufreq_conservative.o
 obj-$(CONFIG_CPU_FREQ_GOV_COMMON)              += cpufreq_governor.o
 
-# CPUfreq cross-arch helpers
-obj-$(CONFIG_CPU_FREQ_TABLE)           += freq_table.o
-
 obj-$(CONFIG_GENERIC_CPUFREQ_CPU0)     += cpufreq-cpu0.o
 
 ##################################################################################
index d2c3253e015ee23f107d2d34333c6afa533ab7cf..a1717d7367c1ad0bd29a3dd54de644791d648cc7 100644 (file)
@@ -516,15 +516,6 @@ out:
        return result;
 }
 
-static int acpi_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
-
-       pr_debug("acpi_cpufreq_verify\n");
-
-       return cpufreq_frequency_table_verify(policy, data->freq_table);
-}
-
 static unsigned long
 acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu)
 {
@@ -837,7 +828,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
        data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
        perf->state = 0;
 
-       result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
+       result = cpufreq_table_validate_and_show(policy, data->freq_table);
        if (result)
                goto err_freqfree;
 
@@ -846,12 +837,16 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
 
        switch (perf->control_register.space_id) {
        case ACPI_ADR_SPACE_SYSTEM_IO:
-               /* Current speed is unknown and not detectable by IO port */
+               /*
+                * The core will not set policy->cur, because
+                * cpufreq_driver->get is NULL, so we need to set it here.
+                * However, we have to guess it, because the current speed is
+                * unknown and not detectable via IO ports.
+                */
                policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu);
                break;
        case ACPI_ADR_SPACE_FIXED_HARDWARE:
                acpi_cpufreq_driver.get = get_cur_freq_on_cpu;
-               policy->cur = get_cur_freq_on_cpu(cpu);
                break;
        default:
                break;
@@ -868,8 +863,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
                        (u32) perf->states[i].power,
                        (u32) perf->states[i].transition_latency);
 
-       cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
-
        /*
         * the first call to ->target() should result in us actually
         * writing something to the appropriate registers.
@@ -929,7 +922,7 @@ static struct freq_attr *acpi_cpufreq_attr[] = {
 };
 
 static struct cpufreq_driver acpi_cpufreq_driver = {
-       .verify         = acpi_cpufreq_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = acpi_cpufreq_target,
        .bios_limit     = acpi_processor_get_bios_limit,
        .init           = acpi_cpufreq_cpu_init,
index 3549f0784af176d07ee17dd60d02ec85859d6bd1..086f7c17ff5816001ab9be359741b9292539cf47 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/cpumask.h>
 #include <linux/export.h>
 #include <linux/of_platform.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/slab.h>
 #include <linux/topology.h>
 #include <linux/types.h>
@@ -47,14 +47,6 @@ static unsigned int bL_cpufreq_get(unsigned int cpu)
        return clk_get_rate(clk[cur_cluster]) / 1000;
 }
 
-/* Validate policy frequency range */
-static int bL_cpufreq_verify_policy(struct cpufreq_policy *policy)
-{
-       u32 cur_cluster = cpu_to_cluster(policy->cpu);
-
-       return cpufreq_frequency_table_verify(policy, freq_table[cur_cluster]);
-}
-
 /* Set clock frequency */
 static int bL_cpufreq_set_target(struct cpufreq_policy *policy,
                unsigned int target_freq, unsigned int relation)
@@ -98,7 +90,7 @@ static void put_cluster_clk_and_freq_table(struct device *cpu_dev)
 
        if (!atomic_dec_return(&cluster_usage[cluster])) {
                clk_put(clk[cluster]);
-               opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
+               dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
                dev_dbg(cpu_dev, "%s: cluster: %d\n", __func__, cluster);
        }
 }
@@ -119,7 +111,7 @@ static int get_cluster_clk_and_freq_table(struct device *cpu_dev)
                goto atomic_dec;
        }
 
-       ret = opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]);
+       ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table[cluster]);
        if (ret) {
                dev_err(cpu_dev, "%s: failed to init cpufreq table, cpu: %d, err: %d\n",
                                __func__, cpu_dev->id, ret);
@@ -127,7 +119,7 @@ static int get_cluster_clk_and_freq_table(struct device *cpu_dev)
        }
 
        name[12] = cluster + '0';
-       clk[cluster] = clk_get_sys(name, NULL);
+       clk[cluster] = clk_get(cpu_dev, name);
        if (!IS_ERR(clk[cluster])) {
                dev_dbg(cpu_dev, "%s: clk: %p & freq table: %p, cluster: %d\n",
                                __func__, clk[cluster], freq_table[cluster],
@@ -138,7 +130,7 @@ static int get_cluster_clk_and_freq_table(struct device *cpu_dev)
        dev_err(cpu_dev, "%s: Failed to get clk for cpu: %d, cluster: %d\n",
                        __func__, cpu_dev->id, cluster);
        ret = PTR_ERR(clk[cluster]);
-       opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
+       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table[cluster]);
 
 atomic_dec:
        atomic_dec(&cluster_usage[cluster]);
@@ -165,7 +157,7 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
        if (ret)
                return ret;
 
-       ret = cpufreq_frequency_table_cpuinfo(policy, freq_table[cur_cluster]);
+       ret = cpufreq_table_validate_and_show(policy, freq_table[cur_cluster]);
        if (ret) {
                dev_err(cpu_dev, "CPU %d, cluster: %d invalid freq table\n",
                                policy->cpu, cur_cluster);
@@ -173,16 +165,12 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
                return ret;
        }
 
-       cpufreq_frequency_table_get_attr(freq_table[cur_cluster], policy->cpu);
-
        if (arm_bL_ops->get_transition_latency)
                policy->cpuinfo.transition_latency =
                        arm_bL_ops->get_transition_latency(cpu_dev);
        else
                policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
 
-       policy->cur = bL_cpufreq_get(policy->cpu);
-
        cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
 
        dev_info(cpu_dev, "%s: CPU %d initialized\n", __func__, policy->cpu);
@@ -200,28 +188,23 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy)
                return -ENODEV;
        }
 
+       cpufreq_frequency_table_put_attr(policy->cpu);
        put_cluster_clk_and_freq_table(cpu_dev);
        dev_dbg(cpu_dev, "%s: Exited, cpu: %d\n", __func__, policy->cpu);
 
        return 0;
 }
 
-/* Export freq_table to sysfs */
-static struct freq_attr *bL_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver bL_cpufreq_driver = {
        .name                   = "arm-big-little",
-       .flags                  = CPUFREQ_STICKY,
-       .verify                 = bL_cpufreq_verify_policy,
+       .flags                  = CPUFREQ_STICKY |
+                                       CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
+       .verify                 = cpufreq_generic_frequency_table_verify,
        .target                 = bL_cpufreq_set_target,
        .get                    = bL_cpufreq_get,
        .init                   = bL_cpufreq_init,
        .exit                   = bL_cpufreq_exit,
-       .have_governor_per_policy = true,
-       .attr                   = bL_cpufreq_attr,
+       .attr                   = cpufreq_generic_attr,
 };
 
 int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops)
index 480c0bd0468d7c0fbbed9e0872cd9adb4fb77244..8d9d5910890689e58d5994d6aeebfccf03215c59 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/export.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/types.h>
index e0c38d9389979b2f1b9a503d36c8e12364ecc188..7439deddd5cf72794f8580712f11ca7b6388e6f6 100644 (file)
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/export.h>
+#include <linux/slab.h>
 
 static struct clk *cpuclk;
-
-static int at32_verify_speed(struct cpufreq_policy *policy)
-{
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                       policy->cpuinfo.max_freq);
-       return 0;
-}
+static struct cpufreq_frequency_table *freq_table;
 
 static unsigned int at32_get_speed(unsigned int cpu)
 {
@@ -85,31 +77,68 @@ static int at32_set_target(struct cpufreq_policy *policy,
 
 static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy)
 {
+       unsigned int frequency, rate, min_freq;
+       int retval, steps, i;
+
        if (policy->cpu != 0)
                return -EINVAL;
 
        cpuclk = clk_get(NULL, "cpu");
        if (IS_ERR(cpuclk)) {
                pr_debug("cpufreq: could not get CPU clk\n");
-               return PTR_ERR(cpuclk);
+               retval = PTR_ERR(cpuclk);
+               goto out_err;
        }
 
-       policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000;
-       policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
+       min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000;
+       frequency = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
        policy->cpuinfo.transition_latency = 0;
-       policy->cur = at32_get_speed(0);
-       policy->min = policy->cpuinfo.min_freq;
-       policy->max = policy->cpuinfo.max_freq;
 
-       printk("cpufreq: AT32AP CPU frequency driver\n");
+       /*
+        * AVR32 CPU frequency rate scales in power of two between maximum and
+        * minimum, also add space for the table end marker.
+        *
+        * Further validate that the frequency is usable, and append it to the
+        * frequency table.
+        */
+       steps = fls(frequency / min_freq) + 1;
+       freq_table = kzalloc(steps * sizeof(struct cpufreq_frequency_table),
+                       GFP_KERNEL);
+       if (!freq_table) {
+               retval = -ENOMEM;
+               goto out_err_put_clk;
+       }
+
+       for (i = 0; i < (steps - 1); i++) {
+               rate = clk_round_rate(cpuclk, frequency * 1000) / 1000;
 
-       return 0;
+               if (rate != frequency)
+                       freq_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+               else
+                       freq_table[i].frequency = frequency;
+
+               frequency /= 2;
+       }
+
+       freq_table[steps - 1].frequency = CPUFREQ_TABLE_END;
+
+       retval = cpufreq_table_validate_and_show(policy, freq_table);
+       if (!retval) {
+               printk("cpufreq: AT32AP CPU frequency driver\n");
+               return 0;
+       }
+
+       kfree(freq_table);
+out_err_put_clk:
+       clk_put(cpuclk);
+out_err:
+       return retval;
 }
 
 static struct cpufreq_driver at32_driver = {
        .name           = "at32ap",
        .init           = at32_cpufreq_driver_init,
-       .verify         = at32_verify_speed,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = at32_set_target,
        .get            = at32_get_speed,
        .flags          = CPUFREQ_STICKY,
index ef05978a723702de29da757eda20edec7d21c3d6..0bc9e8c2c79bb1404a8539f6ff8760c5ab966727 100644 (file)
@@ -191,11 +191,6 @@ static int bfin_target(struct cpufreq_policy *policy,
        return ret;
 }
 
-static int bfin_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, bfin_freq_table);
-}
-
 static int __bfin_cpu_init(struct cpufreq_policy *policy)
 {
 
@@ -209,23 +204,17 @@ static int __bfin_cpu_init(struct cpufreq_policy *policy)
 
        policy->cpuinfo.transition_latency = 50000; /* 50us assumed */
 
-       policy->cur = cclk;
-       cpufreq_frequency_table_get_attr(bfin_freq_table, policy->cpu);
-       return cpufreq_frequency_table_cpuinfo(policy, bfin_freq_table);
+       return cpufreq_table_validate_and_show(policy, bfin_freq_table);
 }
 
-static struct freq_attr *bfin_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver bfin_driver = {
-       .verify = bfin_verify_speed,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = bfin_target,
        .get = bfin_getfreq_khz,
        .init = __bfin_cpu_init,
+       .exit = cpufreq_generic_exit,
        .name = "bfin cpufreq",
-       .attr = bfin_freq_attr,
+       .attr = cpufreq_generic_attr,
 };
 
 static int __init bfin_cpu_init(void)
index c522a95c0e168ae30e4a347f189f89c27173c427..33ab6504c4478ae344395a746cddde0341ca2c52 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
@@ -30,11 +30,6 @@ static struct clk *cpu_clk;
 static struct regulator *cpu_reg;
 static struct cpufreq_frequency_table *freq_table;
 
-static int cpu0_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
 static unsigned int cpu0_get_speed(unsigned int cpu)
 {
        return clk_get_rate(cpu_clk) / 1000;
@@ -44,7 +39,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
                           unsigned int target_freq, unsigned int relation)
 {
        struct cpufreq_freqs freqs;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long volt = 0, volt_old = 0, tol = 0;
        long freq_Hz, freq_exact;
        unsigned int index;
@@ -72,7 +67,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
 
        if (!IS_ERR(cpu_reg)) {
                rcu_read_lock();
-               opp = opp_find_freq_ceil(cpu_dev, &freq_Hz);
+               opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
                if (IS_ERR(opp)) {
                        rcu_read_unlock();
                        pr_err("failed to find OPP for %ld\n", freq_Hz);
@@ -80,7 +75,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy,
                        ret = PTR_ERR(opp);
                        goto post_notify;
                }
-               volt = opp_get_voltage(opp);
+               volt = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
                tol = volt * voltage_tolerance / 100;
                volt_old = regulator_get_voltage(cpu_reg);
@@ -127,50 +122,18 @@ post_notify:
 
 static int cpu0_cpufreq_init(struct cpufreq_policy *policy)
 {
-       int ret;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       if (ret) {
-               pr_err("invalid frequency table: %d\n", ret);
-               return ret;
-       }
-
-       policy->cpuinfo.transition_latency = transition_latency;
-       policy->cur = clk_get_rate(cpu_clk) / 1000;
-
-       /*
-        * The driver only supports the SMP configuartion where all processors
-        * share the clock and voltage and clock.  Use cpufreq affected_cpus
-        * interface to have all CPUs scaled together.
-        */
-       cpumask_setall(policy->cpus);
-
-       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-
-       return 0;
-}
-
-static int cpu0_cpufreq_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-
-       return 0;
+       return cpufreq_generic_init(policy, freq_table, transition_latency);
 }
 
-static struct freq_attr *cpu0_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver cpu0_cpufreq_driver = {
        .flags = CPUFREQ_STICKY,
-       .verify = cpu0_verify_speed,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = cpu0_set_target,
        .get = cpu0_get_speed,
        .init = cpu0_cpufreq_init,
-       .exit = cpu0_cpufreq_exit,
+       .exit = cpufreq_generic_exit,
        .name = "generic_cpu0",
-       .attr = cpu0_cpufreq_attr,
+       .attr = cpufreq_generic_attr,
 };
 
 static int cpu0_cpufreq_probe(struct platform_device *pdev)
@@ -218,7 +181,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
                goto out_put_node;
        }
 
-       ret = opp_init_cpufreq_table(cpu_dev, &freq_table);
+       ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
        if (ret) {
                pr_err("failed to init cpufreq table: %d\n", ret);
                goto out_put_node;
@@ -230,7 +193,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
                transition_latency = CPUFREQ_ETERNAL;
 
        if (!IS_ERR(cpu_reg)) {
-               struct opp *opp;
+               struct dev_pm_opp *opp;
                unsigned long min_uV, max_uV;
                int i;
 
@@ -242,12 +205,12 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
                for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
                        ;
                rcu_read_lock();
-               opp = opp_find_freq_exact(cpu_dev,
+               opp = dev_pm_opp_find_freq_exact(cpu_dev,
                                freq_table[0].frequency * 1000, true);
-               min_uV = opp_get_voltage(opp);
-               opp = opp_find_freq_exact(cpu_dev,
+               min_uV = dev_pm_opp_get_voltage(opp);
+               opp = dev_pm_opp_find_freq_exact(cpu_dev,
                                freq_table[i-1].frequency * 1000, true);
-               max_uV = opp_get_voltage(opp);
+               max_uV = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
                ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
                if (ret > 0)
@@ -264,7 +227,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev)
        return 0;
 
 out_free_table:
-       opp_free_cpufreq_table(cpu_dev, &freq_table);
+       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
 out_put_node:
        of_node_put(np);
        return ret;
@@ -273,7 +236,7 @@ out_put_node:
 static int cpu0_cpufreq_remove(struct platform_device *pdev)
 {
        cpufreq_unregister_driver(&cpu0_cpufreq_driver);
-       opp_free_cpufreq_table(cpu_dev, &freq_table);
+       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
 
        return 0;
 }
index b83d45f6857495083163e13336027ef4449b5da2..a05b876f375e5672c00b05412782c23ead83a773 100644 (file)
@@ -303,9 +303,7 @@ static int nforce2_verify(struct cpufreq_policy *policy)
        if (policy->min < (fsb_pol_max * fid * 100))
                policy->max = (fsb_pol_max + 1) * fid * 100;
 
-       cpufreq_verify_within_limits(policy,
-                                    policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
        return 0;
 }
 
@@ -362,7 +360,6 @@ static int nforce2_cpu_init(struct cpufreq_policy *policy)
        policy->min = policy->cpuinfo.min_freq = min_fsb * fid * 100;
        policy->max = policy->cpuinfo.max_freq = max_fsb * fid * 100;
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       policy->cur = nforce2_get(policy->cpu);
 
        return 0;
 }
index 04548f7023af68dee6b36fc590ec59f02c0216f7..ec391d7f010b531a2fe378df96a88780b5c5faf2 100644 (file)
@@ -67,13 +67,11 @@ static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
 static DEFINE_PER_CPU(struct rw_semaphore, cpu_policy_rwsem);
 
 #define lock_policy_rwsem(mode, cpu)                                   \
-static int lock_policy_rwsem_##mode(int cpu)                           \
+static void lock_policy_rwsem_##mode(int cpu)                          \
 {                                                                      \
        struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu); \
        BUG_ON(!policy);                                                \
        down_##mode(&per_cpu(cpu_policy_rwsem, policy->cpu));           \
-                                                                       \
-       return 0;                                                       \
 }
 
 lock_policy_rwsem(read, cpu);
@@ -135,7 +133,7 @@ static DEFINE_MUTEX(cpufreq_governor_mutex);
 
 bool have_governor_per_policy(void)
 {
-       return cpufreq_driver->have_governor_per_policy;
+       return !!(cpufreq_driver->flags & CPUFREQ_HAVE_GOVERNOR_PER_POLICY);
 }
 EXPORT_SYMBOL_GPL(have_governor_per_policy);
 
@@ -183,6 +181,37 @@ u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy)
 }
 EXPORT_SYMBOL_GPL(get_cpu_idle_time);
 
+/*
+ * This is a generic cpufreq init() routine which can be used by cpufreq
+ * drivers of SMP systems. It will do following:
+ * - validate & show freq table passed
+ * - set policies transition latency
+ * - policy->cpus with all possible CPUs
+ */
+int cpufreq_generic_init(struct cpufreq_policy *policy,
+               struct cpufreq_frequency_table *table,
+               unsigned int transition_latency)
+{
+       int ret;
+
+       ret = cpufreq_table_validate_and_show(policy, table);
+       if (ret) {
+               pr_err("%s: invalid frequency table: %d\n", __func__, ret);
+               return ret;
+       }
+
+       policy->cpuinfo.transition_latency = transition_latency;
+
+       /*
+        * The driver only supports the SMP configuartion where all processors
+        * share the clock and voltage and clock.
+        */
+       cpumask_setall(policy->cpus);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_generic_init);
+
 struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
 {
        struct cpufreq_policy *policy = NULL;
@@ -414,7 +443,7 @@ show_one(scaling_min_freq, min);
 show_one(scaling_max_freq, max);
 show_one(scaling_cur_freq, cur);
 
-static int __cpufreq_set_policy(struct cpufreq_policy *policy,
+static int cpufreq_set_policy(struct cpufreq_policy *policy,
                                struct cpufreq_policy *new_policy);
 
 /**
@@ -435,7 +464,7 @@ static ssize_t store_##file_name                                    \
        if (ret != 1)                                                   \
                return -EINVAL;                                         \
                                                                        \
-       ret = __cpufreq_set_policy(policy, &new_policy);                \
+       ret = cpufreq_set_policy(policy, &new_policy);          \
        policy->user_policy.object = policy->object;                    \
                                                                        \
        return ret ? ret : count;                                       \
@@ -493,11 +522,7 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy,
                                                &new_policy.governor))
                return -EINVAL;
 
-       /*
-        * Do not use cpufreq_set_policy here or the user_policy.max
-        * will be wrongly overridden
-        */
-       ret = __cpufreq_set_policy(policy, &new_policy);
+       ret = cpufreq_set_policy(policy, &new_policy);
 
        policy->user_policy.policy = policy->policy;
        policy->user_policy.governor = policy->governor;
@@ -653,13 +678,12 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
 {
        struct cpufreq_policy *policy = to_policy(kobj);
        struct freq_attr *fattr = to_attr(attr);
-       ssize_t ret = -EINVAL;
+       ssize_t ret;
 
        if (!down_read_trylock(&cpufreq_rwsem))
-               goto exit;
+               return -EINVAL;
 
-       if (lock_policy_rwsem_read(policy->cpu) < 0)
-               goto up_read;
+       lock_policy_rwsem_read(policy->cpu);
 
        if (fattr->show)
                ret = fattr->show(policy, buf);
@@ -667,10 +691,8 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
                ret = -EIO;
 
        unlock_policy_rwsem_read(policy->cpu);
-
-up_read:
        up_read(&cpufreq_rwsem);
-exit:
+
        return ret;
 }
 
@@ -689,8 +711,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
        if (!down_read_trylock(&cpufreq_rwsem))
                goto unlock;
 
-       if (lock_policy_rwsem_write(policy->cpu) < 0)
-               goto up_read;
+       lock_policy_rwsem_write(policy->cpu);
 
        if (fattr->store)
                ret = fattr->store(policy, buf, count);
@@ -699,7 +720,6 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
 
        unlock_policy_rwsem_write(policy->cpu);
 
-up_read:
        up_read(&cpufreq_rwsem);
 unlock:
        put_online_cpus();
@@ -844,11 +864,11 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy)
        int ret = 0;
 
        memcpy(&new_policy, policy, sizeof(*policy));
-       /* assure that the starting sequence is run in __cpufreq_set_policy */
+       /* assure that the starting sequence is run in cpufreq_set_policy */
        policy->governor = NULL;
 
        /* set default policy */
-       ret = __cpufreq_set_policy(policy, &new_policy);
+       ret = cpufreq_set_policy(policy, &new_policy);
        policy->user_policy.policy = policy->policy;
        policy->user_policy.governor = policy->governor;
 
@@ -949,7 +969,7 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
 
 static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
 {
-       if (cpu == policy->cpu)
+       if (WARN_ON(cpu == policy->cpu))
                return;
 
        /*
@@ -966,9 +986,7 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu)
 
        up_write(&per_cpu(cpu_policy_rwsem, policy->last_cpu));
 
-#ifdef CONFIG_CPU_FREQ_TABLE
        cpufreq_frequency_table_update_policy_cpu(policy);
-#endif
        blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
                        CPUFREQ_UPDATE_POLICY_CPU, policy);
 }
@@ -1053,6 +1071,14 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
                goto err_set_policy_cpu;
        }
 
+       if (cpufreq_driver->get) {
+               policy->cur = cpufreq_driver->get(policy->cpu);
+               if (!policy->cur) {
+                       pr_err("%s: ->get() failed\n", __func__);
+                       goto err_get_freq;
+               }
+       }
+
        /* related cpus should atleast have policy->cpus */
        cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
 
@@ -1107,6 +1133,9 @@ err_out_unregister:
                per_cpu(cpufreq_cpu_data, j) = NULL;
        write_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
+err_get_freq:
+       if (cpufreq_driver->exit)
+               cpufreq_driver->exit(policy);
 err_set_policy_cpu:
        cpufreq_policy_free(policy);
 nomem_out:
@@ -1147,7 +1176,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy,
        if (ret) {
                pr_err("%s: Failed to move kobj: %d", __func__, ret);
 
-               WARN_ON(lock_policy_rwsem_write(old_cpu));
+               lock_policy_rwsem_write(old_cpu);
                cpumask_set_cpu(old_cpu, policy->cpus);
                unlock_policy_rwsem_write(old_cpu);
 
@@ -1208,14 +1237,13 @@ static int __cpufreq_remove_dev_prepare(struct device *dev,
                if (!frozen)
                        sysfs_remove_link(&dev->kobj, "cpufreq");
        } else if (cpus > 1) {
-
                new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen);
                if (new_cpu >= 0) {
                        update_policy_cpu(policy, new_cpu);
 
                        if (!frozen) {
-                               pr_debug("%s: policy Kobject moved to cpu: %d "
-                                        "from: %d\n",__func__, new_cpu, cpu);
+                               pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n",
+                                               __func__, new_cpu, cpu);
                        }
                }
        }
@@ -1243,7 +1271,7 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
                return -EINVAL;
        }
 
-       WARN_ON(lock_policy_rwsem_write(cpu));
+       lock_policy_rwsem_write(cpu);
        cpus = cpumask_weight(policy->cpus);
 
        if (cpus > 1)
@@ -1310,36 +1338,24 @@ static int __cpufreq_remove_dev_finish(struct device *dev,
 }
 
 /**
- * __cpufreq_remove_dev - remove a CPU device
+ * cpufreq_remove_dev - remove a CPU device
  *
  * Removes the cpufreq interface for a CPU device.
- * Caller should already have policy_rwsem in write mode for this CPU.
- * This routine frees the rwsem before returning.
  */
-static inline int __cpufreq_remove_dev(struct device *dev,
-                                      struct subsys_interface *sif,
-                                      bool frozen)
-{
-       int ret;
-
-       ret = __cpufreq_remove_dev_prepare(dev, sif, frozen);
-
-       if (!ret)
-               ret = __cpufreq_remove_dev_finish(dev, sif, frozen);
-
-       return ret;
-}
-
 static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
 {
        unsigned int cpu = dev->id;
-       int retval;
+       int ret;
 
        if (cpu_is_offline(cpu))
                return 0;
 
-       retval = __cpufreq_remove_dev(dev, sif, false);
-       return retval;
+       ret = __cpufreq_remove_dev_prepare(dev, sif, false);
+
+       if (!ret)
+               ret = __cpufreq_remove_dev_finish(dev, sif, false);
+
+       return ret;
 }
 
 static void handle_update(struct work_struct *work)
@@ -1466,14 +1482,11 @@ unsigned int cpufreq_get(unsigned int cpu)
        if (!down_read_trylock(&cpufreq_rwsem))
                return 0;
 
-       if (unlikely(lock_policy_rwsem_read(cpu)))
-               goto out_policy;
+       lock_policy_rwsem_read(cpu);
 
        ret_freq = __cpufreq_get(cpu);
 
        unlock_policy_rwsem_read(cpu);
-
-out_policy:
        up_read(&cpufreq_rwsem);
 
        return ret_freq;
@@ -1697,14 +1710,12 @@ int cpufreq_driver_target(struct cpufreq_policy *policy,
 {
        int ret = -EINVAL;
 
-       if (unlikely(lock_policy_rwsem_write(policy->cpu)))
-               goto fail;
+       lock_policy_rwsem_write(policy->cpu);
 
        ret = __cpufreq_driver_target(policy, target_freq, relation);
 
        unlock_policy_rwsem_write(policy->cpu);
 
-fail:
        return ret;
 }
 EXPORT_SYMBOL_GPL(cpufreq_driver_target);
@@ -1871,10 +1882,10 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu)
 EXPORT_SYMBOL(cpufreq_get_policy);
 
 /*
- * data   : current policy.
- * policy : policy to be set.
+ * policy : current policy.
+ * new_policy: policy to be set.
  */
-static int __cpufreq_set_policy(struct cpufreq_policy *policy,
+static int cpufreq_set_policy(struct cpufreq_policy *policy,
                                struct cpufreq_policy *new_policy)
 {
        int ret = 0, failed = 1;
@@ -1995,10 +2006,7 @@ int cpufreq_update_policy(unsigned int cpu)
                goto no_policy;
        }
 
-       if (unlikely(lock_policy_rwsem_write(cpu))) {
-               ret = -EINVAL;
-               goto fail;
-       }
+       lock_policy_rwsem_write(cpu);
 
        pr_debug("updating policy for CPU %u\n", cpu);
        memcpy(&new_policy, policy, sizeof(*policy));
@@ -2023,11 +2031,10 @@ int cpufreq_update_policy(unsigned int cpu)
                }
        }
 
-       ret = __cpufreq_set_policy(policy, &new_policy);
+       ret = cpufreq_set_policy(policy, &new_policy);
 
        unlock_policy_rwsem_write(cpu);
 
-fail:
        cpufreq_cpu_put(policy);
 no_policy:
        return ret;
index 88cd39f7b0e9573b4fc7e5ca13ac0126cf6ede9d..b5f2b8618949dc75d55202d7b76e56e1e0c52a5f 100644 (file)
@@ -191,7 +191,10 @@ struct common_dbs_data {
        struct attribute_group *attr_group_gov_sys; /* one governor - system */
        struct attribute_group *attr_group_gov_pol; /* one governor - policy */
 
-       /* Common data for platforms that don't set have_governor_per_policy */
+       /*
+        * Common data for platforms that don't set
+        * CPUFREQ_HAVE_GOVERNOR_PER_POLICY
+        */
        struct dbs_data *gdbs_data;
 
        struct cpu_dbs_common_info *(*get_cpu_cdbs)(int cpu);
index cb8276dd19caee0a5e2756883148a2d70a7132f2..05fdc7e40257f96a83940d3fbd601d45f4e8e77a 100644 (file)
@@ -54,11 +54,6 @@ static void cris_freq_set_cpu_state(struct cpufreq_policy *policy,
        cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 };
 
-static int cris_freq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]);
-}
-
 static int cris_freq_target(struct cpufreq_policy *policy,
                            unsigned int target_freq,
                            unsigned int relation)
@@ -76,42 +71,17 @@ static int cris_freq_target(struct cpufreq_policy *policy,
 
 static int cris_freq_cpu_init(struct cpufreq_policy *policy)
 {
-       int result;
-
-       /* cpuinfo and default policy values */
-       policy->cpuinfo.transition_latency = 1000000; /* 1ms */
-       policy->cur = cris_freq_get_cpu_frequency(0);
-
-       result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table);
-       if (result)
-               return (result);
-
-       cpufreq_frequency_table_get_attr(cris_freq_table, policy->cpu);
-
-       return 0;
-}
-
-
-static int cris_freq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_generic_init(policy, cris_freq_table, 1000000);
 }
 
-
-static struct freq_attr *cris_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver cris_freq_driver = {
        .get    = cris_freq_get_cpu_frequency,
-       .verify = cris_freq_verify,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = cris_freq_target,
        .init   = cris_freq_cpu_init,
-       .exit   = cris_freq_cpu_exit,
+       .exit   = cpufreq_generic_exit,
        .name   = "cris_freq",
-       .attr   = cris_freq_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static int __init cris_freq_init(void)
index 72328f77dc53bdef993173a1832d3159ac3fd03c..fac2b26932dd7fc4ff121e6bc6edd98ed65b0c47 100644 (file)
@@ -54,11 +54,6 @@ static void cris_freq_set_cpu_state(struct cpufreq_policy *policy,
        cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 };
 
-static int cris_freq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]);
-}
-
 static int cris_freq_target(struct cpufreq_policy *policy,
                            unsigned int target_freq, unsigned int relation)
 {
@@ -75,40 +70,17 @@ static int cris_freq_target(struct cpufreq_policy *policy,
 
 static int cris_freq_cpu_init(struct cpufreq_policy *policy)
 {
-       int result;
-
-       /* cpuinfo and default policy values */
-       policy->cpuinfo.transition_latency = 1000000;   /* 1ms */
-       policy->cur = cris_freq_get_cpu_frequency(0);
-
-       result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table);
-       if (result)
-               return (result);
-
-       cpufreq_frequency_table_get_attr(cris_freq_table, policy->cpu);
-
-       return 0;
-}
-
-static int cris_freq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_generic_init(policy, cris_freq_table, 1000000);
 }
 
-static struct freq_attr *cris_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver cris_freq_driver = {
        .get = cris_freq_get_cpu_frequency,
-       .verify = cris_freq_verify,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = cris_freq_target,
        .init = cris_freq_cpu_init,
-       .exit = cris_freq_cpu_exit,
+       .exit = cpufreq_generic_exit,
        .name = "cris_freq",
-       .attr = cris_freq_attr,
+       .attr = cpufreq_generic_attr,
 };
 
 static int __init cris_freq_init(void)
index 551dd655c6f2ac1d49fb1238ee20f38c213e3f36..972583baf9e8d605b14b830b40b2c459ae1414b5 100644 (file)
@@ -50,9 +50,7 @@ static int davinci_verify_speed(struct cpufreq_policy *policy)
        if (policy->cpu)
                return -EINVAL;
 
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
-
+       cpufreq_verify_within_cpu_limits(policy);
        policy->min = clk_round_rate(armclk, policy->min * 1000) / 1000;
        policy->max = clk_round_rate(armclk, policy->max * 1000) / 1000;
        cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
@@ -138,47 +136,24 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
                        return result;
        }
 
-       policy->cur = davinci_getspeed(0);
-
-       result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       if (result) {
-               pr_err("%s: cpufreq_frequency_table_cpuinfo() failed",
-                               __func__);
-               return result;
-       }
-
-       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-
        /*
         * Time measurement across the target() function yields ~1500-1800us
         * time taken with no drivers on notification list.
         * Setting the latency to 2000 us to accommodate addition of drivers
         * to pre/post change notification list.
         */
-       policy->cpuinfo.transition_latency = 2000 * 1000;
-       return 0;
+       return cpufreq_generic_init(policy, freq_table, 2000 * 1000);
 }
 
-static int davinci_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
-}
-
-static struct freq_attr *davinci_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver davinci_driver = {
        .flags          = CPUFREQ_STICKY,
        .verify         = davinci_verify_speed,
        .target         = davinci_target,
        .get            = davinci_getspeed,
        .init           = davinci_cpu_init,
-       .exit           = davinci_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .name           = "davinci",
-       .attr           = davinci_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init davinci_cpufreq_probe(struct platform_device *pdev)
index 26321cdc19464f1cd3b23f7bf6575d5d97fa6ffc..a60f7693c18e1b93809d53c5835c89583a8af379 100644 (file)
 static struct cpufreq_frequency_table *freq_table;
 static struct clk *armss_clk;
 
-static struct freq_attr *dbx500_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-static int dbx500_cpufreq_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
 static int dbx500_cpufreq_target(struct cpufreq_policy *policy,
                                unsigned int target_freq,
                                unsigned int relation)
@@ -84,43 +74,17 @@ static unsigned int dbx500_cpufreq_getspeed(unsigned int cpu)
 
 static int dbx500_cpufreq_init(struct cpufreq_policy *policy)
 {
-       int res;
-
-       /* get policy fields based on the table */
-       res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       if (!res)
-               cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-       else {
-               pr_err("dbx500-cpufreq: Failed to read policy table\n");
-               return res;
-       }
-
-       policy->min = policy->cpuinfo.min_freq;
-       policy->max = policy->cpuinfo.max_freq;
-       policy->cur = dbx500_cpufreq_getspeed(policy->cpu);
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-
-       /*
-        * FIXME : Need to take time measurement across the target()
-        *         function with no/some/all drivers in the notification
-        *         list.
-        */
-       policy->cpuinfo.transition_latency = 20 * 1000; /* in ns */
-
-       /* policy sharing between dual CPUs */
-       cpumask_setall(policy->cpus);
-
-       return 0;
+       return cpufreq_generic_init(policy, freq_table, 20 * 1000);
 }
 
 static struct cpufreq_driver dbx500_cpufreq_driver = {
        .flags  = CPUFREQ_STICKY | CPUFREQ_CONST_LOOPS,
-       .verify = dbx500_cpufreq_verify_speed,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = dbx500_cpufreq_target,
        .get    = dbx500_cpufreq_getspeed,
        .init   = dbx500_cpufreq_init,
        .name   = "DBX500",
-       .attr   = dbx500_cpufreq_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static int dbx500_cpufreq_probe(struct platform_device *pdev)
index 09f64cc830197fc1f80f605e41d73be6b0441435..2c11ce3c67bde69a9e199135349becdd065fa283 100644 (file)
@@ -198,12 +198,6 @@ static int eps_target(struct cpufreq_policy *policy,
        return ret;
 }
 
-static int eps_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                       &eps_cpu[policy->cpu]->freq_table[0]);
-}
-
 static int eps_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int i;
@@ -401,15 +395,13 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
        }
 
        policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */
-       policy->cur = fsb * current_multiplier;
 
-       ret = cpufreq_frequency_table_cpuinfo(policy, &centaur->freq_table[0]);
+       ret = cpufreq_table_validate_and_show(policy, &centaur->freq_table[0]);
        if (ret) {
                kfree(centaur);
                return ret;
        }
 
-       cpufreq_frequency_table_get_attr(&centaur->freq_table[0], policy->cpu);
        return 0;
 }
 
@@ -424,19 +416,14 @@ static int eps_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-static struct freq_attr *eps_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver eps_driver = {
-       .verify         = eps_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = eps_target,
        .init           = eps_cpu_init,
        .exit           = eps_cpu_exit,
        .get            = eps_get,
        .name           = "e_powersaver",
-       .attr           = eps_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 
index 823a400d98fd6bc5f8c627db8151df572ffc68b9..d91a645a27aea800062dde1358fa02f5155137d0 100644 (file)
@@ -165,19 +165,6 @@ static void elanfreq_set_cpu_state(struct cpufreq_policy *policy,
 };
 
 
-/**
- *     elanfreq_validatespeed: test if frequency range is valid
- *     @policy: the policy to validate
- *
- *     This function checks if a given frequency range in kHz is valid
- *     for the hardware supported by the driver.
- */
-
-static int elanfreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &elanfreq_table[0]);
-}
-
 static int elanfreq_target(struct cpufreq_policy *policy,
                            unsigned int target_freq,
                            unsigned int relation)
@@ -202,7 +189,6 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
 {
        struct cpuinfo_x86 *c = &cpu_data(0);
        unsigned int i;
-       int result;
 
        /* capability check */
        if ((c->x86_vendor != X86_VENDOR_AMD) ||
@@ -221,21 +207,8 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
 
        /* cpuinfo and default policy values */
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       policy->cur = elanfreq_get_cpu_frequency(0);
 
-       result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table);
-       if (result)
-               return result;
-
-       cpufreq_frequency_table_get_attr(elanfreq_table, policy->cpu);
-       return 0;
-}
-
-
-static int elanfreq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_table_validate_and_show(policy, elanfreq_table);
 }
 
 
@@ -261,20 +234,14 @@ __setup("elanfreq=", elanfreq_setup);
 #endif
 
 
-static struct freq_attr *elanfreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-
 static struct cpufreq_driver elanfreq_driver = {
        .get            = elanfreq_get_cpu_frequency,
-       .verify         = elanfreq_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = elanfreq_target,
        .init           = elanfreq_cpu_init,
-       .exit           = elanfreq_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .name           = "elanfreq",
-       .attr           = elanfreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id elan_id[] = {
index 0fac34439e3171dbc97b8f717a935b691657cba9..3e4af676f43d79fba9c704049858e5c7026f5dac 100644 (file)
@@ -31,12 +31,6 @@ static unsigned int locking_frequency;
 static bool frequency_locked;
 static DEFINE_MUTEX(cpufreq_lock);
 
-static int exynos_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                                             exynos_info->freq_table);
-}
-
 static unsigned int exynos_getspeed(unsigned int cpu)
 {
        return clk_get_rate(exynos_info->cpu_clk) / 1000;
@@ -141,7 +135,7 @@ post_notify:
        if ((freqs.new < freqs.old) ||
           ((freqs.new > freqs.old) && safe_arm_volt)) {
                /* down the voltage after frequency change */
-               regulator_set_voltage(arm_regulator, arm_volt,
+               ret = regulator_set_voltage(arm_regulator, arm_volt,
                                arm_volt);
                if (ret) {
                        pr_err("%s: failed to set cpu voltage to %d\n",
@@ -247,38 +241,18 @@ static struct notifier_block exynos_cpufreq_nb = {
 
 static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       policy->cur = policy->min = policy->max = exynos_getspeed(policy->cpu);
-
-       cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
-
-       /* set the transition latency value */
-       policy->cpuinfo.transition_latency = 100000;
-
-       cpumask_setall(policy->cpus);
-
-       return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+       return cpufreq_generic_init(policy, exynos_info->freq_table, 100000);
 }
 
-static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
-}
-
-static struct freq_attr *exynos_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver exynos_driver = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = exynos_verify_speed,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = exynos_target,
        .get            = exynos_getspeed,
        .init           = exynos_cpufreq_cpu_init,
-       .exit           = exynos_cpufreq_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .name           = "exynos_cpufreq",
-       .attr           = exynos_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 #ifdef CONFIG_PM
        .suspend        = exynos_cpufreq_suspend,
        .resume         = exynos_cpufreq_resume,
index add7fbec4fc9af5ca3060e925cfe662a25d21eb4..f2c75065ce198694428d631baef388ad8e9aa6c6 100644 (file)
@@ -81,9 +81,9 @@ static void exynos4210_set_clkdiv(unsigned int div_index)
 
 static void exynos4210_set_apll(unsigned int index)
 {
-       unsigned int tmp;
+       unsigned int tmp, freq = apll_freq_4210[index].freq;
 
-       /* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
+       /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
        clk_set_parent(moutcore, mout_mpll);
 
        do {
@@ -92,21 +92,9 @@ static void exynos4210_set_apll(unsigned int index)
                tmp &= 0x7;
        } while (tmp != 0x2);
 
-       /* 2. Set APLL Lock time */
-       __raw_writel(EXYNOS4_APLL_LOCKTIME, EXYNOS4_APLL_LOCK);
-
-       /* 3. Change PLL PMS values */
-       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-       tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
-       tmp |= apll_freq_4210[index].mps;
-       __raw_writel(tmp, EXYNOS4_APLL_CON0);
+       clk_set_rate(mout_apll, freq * 1000);
 
-       /* 4. wait_lock_time */
-       do {
-               tmp = __raw_readl(EXYNOS4_APLL_CON0);
-       } while (!(tmp & (0x1 << EXYNOS4_APLLCON0_LOCKED_SHIFT)));
-
-       /* 5. MUX_CORE_SEL = APLL */
+       /* MUX_CORE_SEL = APLL */
        clk_set_parent(moutcore, mout_apll);
 
        do {
@@ -115,53 +103,15 @@ static void exynos4210_set_apll(unsigned int index)
        } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
 }
 
-static bool exynos4210_pms_change(unsigned int old_index, unsigned int new_index)
-{
-       unsigned int old_pm = apll_freq_4210[old_index].mps >> 8;
-       unsigned int new_pm = apll_freq_4210[new_index].mps >> 8;
-
-       return (old_pm == new_pm) ? 0 : 1;
-}
-
 static void exynos4210_set_frequency(unsigned int old_index,
                                     unsigned int new_index)
 {
-       unsigned int tmp;
-
        if (old_index > new_index) {
-               if (!exynos4210_pms_change(old_index, new_index)) {
-                       /* 1. Change the system clock divider values */
-                       exynos4210_set_clkdiv(new_index);
-
-                       /* 2. Change just s value in apll m,p,s value */
-                       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-                       tmp &= ~(0x7 << 0);
-                       tmp |= apll_freq_4210[new_index].mps & 0x7;
-                       __raw_writel(tmp, EXYNOS4_APLL_CON0);
-               } else {
-                       /* Clock Configuration Procedure */
-                       /* 1. Change the system clock divider values */
-                       exynos4210_set_clkdiv(new_index);
-                       /* 2. Change the apll m,p,s value */
-                       exynos4210_set_apll(new_index);
-               }
+               exynos4210_set_clkdiv(new_index);
+               exynos4210_set_apll(new_index);
        } else if (old_index < new_index) {
-               if (!exynos4210_pms_change(old_index, new_index)) {
-                       /* 1. Change just s value in apll m,p,s value */
-                       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-                       tmp &= ~(0x7 << 0);
-                       tmp |= apll_freq_4210[new_index].mps & 0x7;
-                       __raw_writel(tmp, EXYNOS4_APLL_CON0);
-
-                       /* 2. Change the system clock divider values */
-                       exynos4210_set_clkdiv(new_index);
-               } else {
-                       /* Clock Configuration Procedure */
-                       /* 1. Change the apll m,p,s value */
-                       exynos4210_set_apll(new_index);
-                       /* 2. Change the system clock divider values */
-                       exynos4210_set_clkdiv(new_index);
-               }
+               exynos4210_set_apll(new_index);
+               exynos4210_set_clkdiv(new_index);
        }
 }
 
@@ -194,7 +144,6 @@ int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
        info->volt_table = exynos4210_volt_table;
        info->freq_table = exynos4210_freq_table;
        info->set_freq = exynos4210_set_frequency;
-       info->need_apll_change = exynos4210_pms_change;
 
        return 0;
 
index 08b7477b0aa23ea139faa00aef4d6eca601d173c..8683304ce62cc4dba0c947e2be6049e1b94ffcaf 100644 (file)
@@ -128,9 +128,9 @@ static void exynos4x12_set_clkdiv(unsigned int div_index)
 
 static void exynos4x12_set_apll(unsigned int index)
 {
-       unsigned int tmp, pdiv;
+       unsigned int tmp, freq = apll_freq_4x12[index].freq;
 
-       /* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
+       /* MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
        clk_set_parent(moutcore, mout_mpll);
 
        do {
@@ -140,24 +140,9 @@ static void exynos4x12_set_apll(unsigned int index)
                tmp &= 0x7;
        } while (tmp != 0x2);
 
-       /* 2. Set APLL Lock time */
-       pdiv = ((apll_freq_4x12[index].mps >> 8) & 0x3f);
+       clk_set_rate(mout_apll, freq * 1000);
 
-       __raw_writel((pdiv * 250), EXYNOS4_APLL_LOCK);
-
-       /* 3. Change PLL PMS values */
-       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-       tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
-       tmp |= apll_freq_4x12[index].mps;
-       __raw_writel(tmp, EXYNOS4_APLL_CON0);
-
-       /* 4. wait_lock_time */
-       do {
-               cpu_relax();
-               tmp = __raw_readl(EXYNOS4_APLL_CON0);
-       } while (!(tmp & (0x1 << EXYNOS4_APLLCON0_LOCKED_SHIFT)));
-
-       /* 5. MUX_CORE_SEL = APLL */
+       /* MUX_CORE_SEL = APLL */
        clk_set_parent(moutcore, mout_apll);
 
        do {
@@ -167,52 +152,15 @@ static void exynos4x12_set_apll(unsigned int index)
        } while (tmp != (0x1 << EXYNOS4_CLKSRC_CPU_MUXCORE_SHIFT));
 }
 
-static bool exynos4x12_pms_change(unsigned int old_index, unsigned int new_index)
-{
-       unsigned int old_pm = apll_freq_4x12[old_index].mps >> 8;
-       unsigned int new_pm = apll_freq_4x12[new_index].mps >> 8;
-
-       return (old_pm == new_pm) ? 0 : 1;
-}
-
 static void exynos4x12_set_frequency(unsigned int old_index,
                                  unsigned int new_index)
 {
-       unsigned int tmp;
-
        if (old_index > new_index) {
-               if (!exynos4x12_pms_change(old_index, new_index)) {
-                       /* 1. Change the system clock divider values */
-                       exynos4x12_set_clkdiv(new_index);
-                       /* 2. Change just s value in apll m,p,s value */
-                       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-                       tmp &= ~(0x7 << 0);
-                       tmp |= apll_freq_4x12[new_index].mps & 0x7;
-                       __raw_writel(tmp, EXYNOS4_APLL_CON0);
-
-               } else {
-                       /* Clock Configuration Procedure */
-                       /* 1. Change the system clock divider values */
-                       exynos4x12_set_clkdiv(new_index);
-                       /* 2. Change the apll m,p,s value */
-                       exynos4x12_set_apll(new_index);
-               }
+               exynos4x12_set_clkdiv(new_index);
+               exynos4x12_set_apll(new_index);
        } else if (old_index < new_index) {
-               if (!exynos4x12_pms_change(old_index, new_index)) {
-                       /* 1. Change just s value in apll m,p,s value */
-                       tmp = __raw_readl(EXYNOS4_APLL_CON0);
-                       tmp &= ~(0x7 << 0);
-                       tmp |= apll_freq_4x12[new_index].mps & 0x7;
-                       __raw_writel(tmp, EXYNOS4_APLL_CON0);
-                       /* 2. Change the system clock divider values */
-                       exynos4x12_set_clkdiv(new_index);
-               } else {
-                       /* Clock Configuration Procedure */
-                       /* 1. Change the apll m,p,s value */
-                       exynos4x12_set_apll(new_index);
-                       /* 2. Change the system clock divider values */
-                       exynos4x12_set_clkdiv(new_index);
-               }
+               exynos4x12_set_apll(new_index);
+               exynos4x12_set_clkdiv(new_index);
        }
 }
 
@@ -250,7 +198,6 @@ int exynos4x12_cpufreq_init(struct exynos_dvfs_info *info)
        info->volt_table = exynos4x12_volt_table;
        info->freq_table = exynos4x12_freq_table;
        info->set_freq = exynos4x12_set_frequency;
-       info->need_apll_change = exynos4x12_pms_change;
 
        return 0;
 
index be5380ecdcd43f95c4aa88a62389c184597f3971..8ae5e2925bf1e2e446bdb952a68f925d46da732e 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
@@ -118,12 +118,12 @@ static int init_div_table(void)
        struct cpufreq_frequency_table *freq_tbl = dvfs_info->freq_table;
        unsigned int tmp, clk_div, ema_div, freq, volt_id;
        int i = 0;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
 
        rcu_read_lock();
        for (i = 0; freq_tbl[i].frequency != CPUFREQ_TABLE_END; i++) {
 
-               opp = opp_find_freq_exact(dvfs_info->dev,
+               opp = dev_pm_opp_find_freq_exact(dvfs_info->dev,
                                        freq_tbl[i].frequency * 1000, true);
                if (IS_ERR(opp)) {
                        rcu_read_unlock();
@@ -142,7 +142,7 @@ static int init_div_table(void)
                                        << P0_7_CSCLKDEV_SHIFT;
 
                /* Calculate EMA */
-               volt_id = opp_get_voltage(opp);
+               volt_id = dev_pm_opp_get_voltage(opp);
                volt_id = (MAX_VOLTAGE - volt_id) / VOLTAGE_STEP;
                if (volt_id < PMIC_HIGH_VOLT) {
                        ema_div = (CPUEMA_HIGH << P0_7_CPUEMA_SHIFT) |
@@ -209,12 +209,6 @@ static void exynos_enable_dvfs(void)
                                dvfs_info->base + XMU_DVFS_CTRL);
 }
 
-static int exynos_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                                             dvfs_info->freq_table);
-}
-
 static unsigned int exynos_getspeed(unsigned int cpu)
 {
        return dvfs_info->cur_frequency;
@@ -324,30 +318,19 @@ static void exynos_sort_descend_freq_table(void)
 
 static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       int ret;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, dvfs_info->freq_table);
-       if (ret) {
-               dev_err(dvfs_info->dev, "Invalid frequency table: %d\n", ret);
-               return ret;
-       }
-
-       policy->cur = dvfs_info->cur_frequency;
-       policy->cpuinfo.transition_latency = dvfs_info->latency;
-       cpumask_setall(policy->cpus);
-
-       cpufreq_frequency_table_get_attr(dvfs_info->freq_table, policy->cpu);
-
-       return 0;
+       return cpufreq_generic_init(policy, dvfs_info->freq_table,
+                       dvfs_info->latency);
 }
 
 static struct cpufreq_driver exynos_driver = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = exynos_verify_speed,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = exynos_target,
        .get            = exynos_getspeed,
        .init           = exynos_cpufreq_cpu_init,
+       .exit           = cpufreq_generic_exit,
        .name           = CPUFREQ_NAME,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct of_device_id exynos_cpufreq_match[] = {
@@ -399,13 +382,14 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
                goto err_put_node;
        }
 
-       ret = opp_init_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
+       ret = dev_pm_opp_init_cpufreq_table(dvfs_info->dev,
+                                           &dvfs_info->freq_table);
        if (ret) {
                dev_err(dvfs_info->dev,
                        "failed to init cpufreq table: %d\n", ret);
                goto err_put_node;
        }
-       dvfs_info->freq_count = opp_get_opp_count(dvfs_info->dev);
+       dvfs_info->freq_count = dev_pm_opp_get_opp_count(dvfs_info->dev);
        exynos_sort_descend_freq_table();
 
        if (of_property_read_u32(np, "clock-latency", &dvfs_info->latency))
@@ -454,7 +438,7 @@ static int exynos_cpufreq_probe(struct platform_device *pdev)
        return 0;
 
 err_free_table:
-       opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
+       dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
 err_put_node:
        of_node_put(np);
        dev_err(&pdev->dev, "%s: failed initialization\n", __func__);
@@ -464,7 +448,7 @@ err_put_node:
 static int exynos_cpufreq_remove(struct platform_device *pdev)
 {
        cpufreq_unregister_driver(&exynos_driver);
-       opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
+       dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
        return 0;
 }
 
index f111454a7aeace94454e3c8eff6e7e45360380d7..3458d27f63b409e03b866e6b20e541a7de8cc769 100644 (file)
@@ -54,31 +54,30 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);
 int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table)
 {
-       unsigned int next_larger = ~0;
-       unsigned int i;
-       unsigned int count = 0;
+       unsigned int next_larger = ~0, freq, i = 0;
+       bool found = false;
 
        pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n",
                                        policy->min, policy->max, policy->cpu);
 
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
 
-       for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
-               unsigned int freq = table[i].frequency;
+       for (; freq = table[i].frequency, freq != CPUFREQ_TABLE_END; i++) {
                if (freq == CPUFREQ_ENTRY_INVALID)
                        continue;
-               if ((freq >= policy->min) && (freq <= policy->max))
-                       count++;
-               else if ((next_larger > freq) && (freq > policy->max))
+               if ((freq >= policy->min) && (freq <= policy->max)) {
+                       found = true;
+                       break;
+               }
+
+               if ((next_larger > freq) && (freq > policy->max))
                        next_larger = freq;
        }
 
-       if (!count)
+       if (!found) {
                policy->max = next_larger;
-
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
+               cpufreq_verify_within_cpu_limits(policy);
+       }
 
        pr_debug("verification lead to (%u - %u kHz) for cpu %u\n",
                                policy->min, policy->max, policy->cpu);
@@ -87,6 +86,20 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);
 
+/*
+ * Generic routine to verify policy & frequency table, requires driver to call
+ * cpufreq_frequency_table_get_attr() prior to it.
+ */
+int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy)
+{
+       struct cpufreq_frequency_table *table =
+               cpufreq_frequency_get_table(policy->cpu);
+       if (!table)
+               return -ENODEV;
+
+       return cpufreq_frequency_table_verify(policy, table);
+}
+EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify);
 
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table,
@@ -200,6 +213,12 @@ struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
 };
 EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
 
+struct freq_attr *cpufreq_generic_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+EXPORT_SYMBOL_GPL(cpufreq_generic_attr);
+
 /*
  * if you use these, you must assure that the frequency table is valid
  * all the time between get_attr and put_attr!
@@ -219,6 +238,18 @@ void cpufreq_frequency_table_put_attr(unsigned int cpu)
 }
 EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);
 
+int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
+                                     struct cpufreq_frequency_table *table)
+{
+       int ret = cpufreq_frequency_table_cpuinfo(policy, table);
+
+       if (!ret)
+               cpufreq_frequency_table_get_attr(table, policy->cpu);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
+
 void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy)
 {
        pr_debug("Updating show_table for new_cpu %u from last_cpu %u\n",
index 70442c7b5e71aed7e57ce61b20893e42dc36a215..d83e8266a58e2eddf824696c80240ced024bab57 100644 (file)
@@ -401,7 +401,7 @@ static int cpufreq_gx_target(struct cpufreq_policy *policy,
 
 static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
 {
-       unsigned int maxfreq, curfreq;
+       unsigned int maxfreq;
 
        if (!policy || policy->cpu != 0)
                return -ENODEV;
@@ -415,10 +415,8 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
                maxfreq = 30000 * gx_freq_mult[getCx86(CX86_DIR1) & 0x0f];
 
        stock_freq = maxfreq;
-       curfreq = gx_get_cpuspeed(0);
 
        pr_debug("cpu max frequency is %d.\n", maxfreq);
-       pr_debug("cpu current frequency is %dkHz.\n", curfreq);
 
        /* setup basic struct for cpufreq API */
        policy->cpu = 0;
@@ -428,7 +426,6 @@ static int cpufreq_gx_cpu_init(struct cpufreq_policy *policy)
        else
                policy->min = maxfreq / POLICY_MIN_DIV;
        policy->max = maxfreq;
-       policy->cur = curfreq;
        policy->cpuinfo.min_freq = maxfreq / max_duration;
        policy->cpuinfo.max_freq = maxfreq;
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
index 794123fcf3e3ebce87cdbcbf0a66b60f4b70db2c..bf8902a0866dd4d767cdab4ba45d84ca397033fe 100644 (file)
@@ -66,7 +66,8 @@ static int hb_cpufreq_driver_init(void)
        struct device_node *np;
        int ret;
 
-       if (!of_machine_is_compatible("calxeda,highbank"))
+       if ((!of_machine_is_compatible("calxeda,highbank")) &&
+               (!of_machine_is_compatible("calxeda,ecx-2000")))
                return -ENODEV;
 
        cpu_dev = get_cpu_device(0);
index 3e14f03171759bcdbd8a0501bc1ff38fee86d4c0..90c6598415fd39687aa874a85d52730452f26c3d 100644 (file)
@@ -247,22 +247,6 @@ acpi_cpufreq_target (
 }
 
 
-static int
-acpi_cpufreq_verify (
-       struct cpufreq_policy   *policy)
-{
-       unsigned int result = 0;
-       struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu];
-
-       pr_debug("acpi_cpufreq_verify\n");
-
-       result = cpufreq_frequency_table_verify(policy,
-                       data->freq_table);
-
-       return (result);
-}
-
-
 static int
 acpi_cpufreq_cpu_init (
        struct cpufreq_policy   *policy)
@@ -321,7 +305,6 @@ acpi_cpufreq_cpu_init (
                            data->acpi_data.states[i].transition_latency * 1000;
                }
        }
-       policy->cur = processor_get_freq(data, policy->cpu);
 
        /* table init */
        for (i = 0; i <= data->acpi_data.state_count; i++)
@@ -335,7 +318,7 @@ acpi_cpufreq_cpu_init (
                }
        }
 
-       result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
+       result = cpufreq_table_validate_and_show(policy, data->freq_table);
        if (result) {
                goto err_freqfree;
        }
@@ -356,8 +339,6 @@ acpi_cpufreq_cpu_init (
                        (u32) data->acpi_data.states[i].status,
                        (u32) data->acpi_data.states[i].control);
 
-       cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu);
-
        /* the first call to ->target() should result in us actually
         * writing something to the appropriate registers. */
        data->resume = 1;
@@ -396,20 +377,14 @@ acpi_cpufreq_cpu_exit (
 }
 
 
-static struct freq_attr* acpi_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-
 static struct cpufreq_driver acpi_cpufreq_driver = {
-       .verify         = acpi_cpufreq_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = acpi_cpufreq_target,
        .get            = acpi_cpufreq_get,
        .init           = acpi_cpufreq_cpu_init,
        .exit           = acpi_cpufreq_cpu_exit,
        .name           = "acpi-cpufreq",
-       .attr           = acpi_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 
index c3fd2a101ca02852c677d021c567b27ee74b075a..be23892282e3462947e7df176113070a2b1d8ca7 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/err.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
 
@@ -35,11 +35,6 @@ static struct device *cpu_dev;
 static struct cpufreq_frequency_table *freq_table;
 static unsigned int transition_latency;
 
-static int imx6q_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
 static unsigned int imx6q_get_speed(unsigned int cpu)
 {
        return clk_get_rate(arm_clk) / 1000;
@@ -49,7 +44,7 @@ static int imx6q_set_target(struct cpufreq_policy *policy,
                            unsigned int target_freq, unsigned int relation)
 {
        struct cpufreq_freqs freqs;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long freq_hz, volt, volt_old;
        unsigned int index;
        int ret;
@@ -70,14 +65,14 @@ static int imx6q_set_target(struct cpufreq_policy *policy,
                return 0;
 
        rcu_read_lock();
-       opp = opp_find_freq_ceil(cpu_dev, &freq_hz);
+       opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_hz);
        if (IS_ERR(opp)) {
                rcu_read_unlock();
                dev_err(cpu_dev, "failed to find OPP for %ld\n", freq_hz);
                return PTR_ERR(opp);
        }
 
-       volt = opp_get_voltage(opp);
+       volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
        volt_old = regulator_get_voltage(arm_reg);
 
@@ -159,47 +154,23 @@ post_notify:
 
 static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
 {
-       int ret;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       if (ret) {
-               dev_err(cpu_dev, "invalid frequency table: %d\n", ret);
-               return ret;
-       }
-
-       policy->cpuinfo.transition_latency = transition_latency;
-       policy->cur = clk_get_rate(arm_clk) / 1000;
-       cpumask_setall(policy->cpus);
-       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-
-       return 0;
-}
-
-static int imx6q_cpufreq_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_generic_init(policy, freq_table, transition_latency);
 }
 
-static struct freq_attr *imx6q_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver imx6q_cpufreq_driver = {
-       .verify = imx6q_verify_speed,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = imx6q_set_target,
        .get = imx6q_get_speed,
        .init = imx6q_cpufreq_init,
-       .exit = imx6q_cpufreq_exit,
+       .exit = cpufreq_generic_exit,
        .name = "imx6q-cpufreq",
-       .attr = imx6q_cpufreq_attr,
+       .attr = cpufreq_generic_attr,
 };
 
 static int imx6q_cpufreq_probe(struct platform_device *pdev)
 {
        struct device_node *np;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long min_volt, max_volt;
        int num, ret;
 
@@ -237,14 +208,14 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
        }
 
        /* We expect an OPP table supplied by platform */
-       num = opp_get_opp_count(cpu_dev);
+       num = dev_pm_opp_get_opp_count(cpu_dev);
        if (num < 0) {
                ret = num;
                dev_err(cpu_dev, "no OPP table is found: %d\n", ret);
                goto put_node;
        }
 
-       ret = opp_init_cpufreq_table(cpu_dev, &freq_table);
+       ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
        if (ret) {
                dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
                goto put_node;
@@ -259,12 +230,12 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
         * same order.
         */
        rcu_read_lock();
-       opp = opp_find_freq_exact(cpu_dev,
+       opp = dev_pm_opp_find_freq_exact(cpu_dev,
                                  freq_table[0].frequency * 1000, true);
-       min_volt = opp_get_voltage(opp);
-       opp = opp_find_freq_exact(cpu_dev,
+       min_volt = dev_pm_opp_get_voltage(opp);
+       opp = dev_pm_opp_find_freq_exact(cpu_dev,
                                  freq_table[--num].frequency * 1000, true);
-       max_volt = opp_get_voltage(opp);
+       max_volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
        ret = regulator_set_voltage_time(arm_reg, min_volt, max_volt);
        if (ret > 0)
@@ -292,7 +263,7 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
        return 0;
 
 free_freq_table:
-       opp_free_cpufreq_table(cpu_dev, &freq_table);
+       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
 put_node:
        of_node_put(np);
        return ret;
@@ -301,7 +272,7 @@ put_node:
 static int imx6q_cpufreq_remove(struct platform_device *pdev)
 {
        cpufreq_unregister_driver(&imx6q_cpufreq_driver);
-       opp_free_cpufreq_table(cpu_dev, &freq_table);
+       dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
 
        return 0;
 }
index f7c99df0880b4d396fee72860b904b5764f943f3..babf3e40e9fa5030be4420f7038681954ebc5bb8 100644 (file)
@@ -59,9 +59,7 @@ static int integrator_verify_policy(struct cpufreq_policy *policy)
 {
        struct icst_vco vco;
 
-       cpufreq_verify_within_limits(policy, 
-                                    policy->cpuinfo.min_freq, 
-                                    policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
 
        vco = icst_hz_to_vco(&cclk_params, policy->max * 1000);
        policy->max = icst_hz(&cclk_params, vco) / 1000;
@@ -69,10 +67,7 @@ static int integrator_verify_policy(struct cpufreq_policy *policy)
        vco = icst_hz_to_vco(&cclk_params, policy->min * 1000);
        policy->min = icst_hz(&cclk_params, vco) / 1000;
 
-       cpufreq_verify_within_limits(policy, 
-                                    policy->cpuinfo.min_freq, 
-                                    policy->cpuinfo.max_freq);
-
+       cpufreq_verify_within_cpu_limits(policy);
        return 0;
 }
 
@@ -186,10 +181,9 @@ static int integrator_cpufreq_init(struct cpufreq_policy *policy)
 {
 
        /* set default policy and cpuinfo */
-       policy->cpuinfo.max_freq = 160000;
-       policy->cpuinfo.min_freq = 12000;
+       policy->max = policy->cpuinfo.max_freq = 160000;
+       policy->min = policy->cpuinfo.min_freq = 12000;
        policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */
-       policy->cur = policy->min = policy->max = integrator_get(policy->cpu);
 
        return 0;
 }
index eb3fdc755000e0005f43474bb5ae967dd6ab8aa8..67a87e01c1d96f6709de25dff2b9cbb590d70b36 100644 (file)
@@ -613,9 +613,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 
 static int intel_pstate_verify_policy(struct cpufreq_policy *policy)
 {
-       cpufreq_verify_within_limits(policy,
-                               policy->cpuinfo.min_freq,
-                               policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
 
        if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
                (policy->policy != CPUFREQ_POLICY_PERFORMANCE))
index ba10658a93949fe9adca0863c7c8926a11fe1676..fff8653c8e9b7087a71a0a885853d7c4cdfd30c0 100644 (file)
@@ -102,11 +102,6 @@ static void kirkwood_cpufreq_set_cpu_state(struct cpufreq_policy *policy,
        cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 };
 
-static int kirkwood_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, kirkwood_freq_table);
-}
-
 static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
                            unsigned int target_freq,
                            unsigned int relation)
@@ -125,40 +120,17 @@ static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
 /* Module init and exit code */
 static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       int result;
-
-       /* cpuinfo and default policy values */
-       policy->cpuinfo.transition_latency = 5000; /* 5uS */
-       policy->cur = kirkwood_cpufreq_get_cpu_frequency(0);
-
-       result = cpufreq_frequency_table_cpuinfo(policy, kirkwood_freq_table);
-       if (result)
-               return result;
-
-       cpufreq_frequency_table_get_attr(kirkwood_freq_table, policy->cpu);
-
-       return 0;
-}
-
-static int kirkwood_cpufreq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_generic_init(policy, kirkwood_freq_table, 5000);
 }
 
-static struct freq_attr *kirkwood_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver kirkwood_cpufreq_driver = {
        .get    = kirkwood_cpufreq_get_cpu_frequency,
-       .verify = kirkwood_cpufreq_verify,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = kirkwood_cpufreq_target,
        .init   = kirkwood_cpufreq_cpu_init,
-       .exit   = kirkwood_cpufreq_cpu_exit,
+       .exit   = cpufreq_generic_exit,
        .name   = "kirkwood-cpufreq",
-       .attr   = kirkwood_cpufreq_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static int kirkwood_cpufreq_probe(struct platform_device *pdev)
index 4ada1cccb0523632e72c016e9a511dd38b08d33d..14df4974fb458a165b3dacaaeb15e843d1af6c82 100644 (file)
@@ -625,12 +625,6 @@ static void longhaul_setup_voltagescaling(void)
 }
 
 
-static int longhaul_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, longhaul_table);
-}
-
-
 static int longhaul_target(struct cpufreq_policy *policy,
                            unsigned int target_freq, unsigned int relation)
 {
@@ -919,36 +913,18 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy)
                longhaul_setup_voltagescaling();
 
        policy->cpuinfo.transition_latency = 200000;    /* nsec */
-       policy->cur = calc_speed(longhaul_get_cpu_mult());
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
-       if (ret)
-               return ret;
-
-       cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu);
 
-       return 0;
+       return cpufreq_table_validate_and_show(policy, longhaul_table);
 }
 
-static int longhaul_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
-}
-
-static struct freq_attr *longhaul_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver longhaul_driver = {
-       .verify = longhaul_verify,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = longhaul_target,
        .get    = longhaul_get,
        .init   = longhaul_cpu_init,
-       .exit   = longhaul_cpu_exit,
+       .exit   = cpufreq_generic_exit,
        .name   = "longhaul",
-       .attr   = longhaul_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id longhaul_id[] = {
index 5aa031612d5393ff08d196f83b8701ac8c8f5e12..074971b12635af04b7214f510c70e7e8c37ebcbf 100644 (file)
@@ -129,9 +129,7 @@ static int longrun_verify_policy(struct cpufreq_policy *policy)
                return -EINVAL;
 
        policy->cpu = 0;
-       cpufreq_verify_within_limits(policy,
-               policy->cpuinfo.min_freq,
-               policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
 
        if ((policy->policy != CPUFREQ_POLICY_POWERSAVE) &&
            (policy->policy != CPUFREQ_POLICY_PERFORMANCE))
index 7bc3c44d34e2f0ec5493ad9fdf0c8467ccd8a037..2c8ec8e064490be7d56b4e591960b2e11a4bf813 100644 (file)
@@ -131,40 +131,24 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
                return ret;
        }
 
-       policy->cur = loongson2_cpufreq_get(policy->cpu);
-
-       cpufreq_frequency_table_get_attr(&loongson2_clockmod_table[0],
-                                        policy->cpu);
-
-       return cpufreq_frequency_table_cpuinfo(policy,
-                                           &loongson2_clockmod_table[0]);
-}
-
-static int loongson2_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                                             &loongson2_clockmod_table[0]);
+       return cpufreq_generic_init(policy, &loongson2_clockmod_table[0], 0);
 }
 
 static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
 {
+       cpufreq_frequency_table_put_attr(policy->cpu);
        clk_put(cpuclk);
        return 0;
 }
 
-static struct freq_attr *loongson2_table_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver loongson2_cpufreq_driver = {
        .name = "loongson2",
        .init = loongson2_cpufreq_cpu_init,
-       .verify = loongson2_cpufreq_verify,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = loongson2_cpufreq_target,
        .get = loongson2_cpufreq_get,
        .exit = loongson2_cpufreq_exit,
-       .attr = loongson2_table_attr,
+       .attr = cpufreq_generic_attr,
 };
 
 static struct platform_device_id platform_device_ids[] = {
index 6168d77b296d78b7d1a452bae6f3ae34c7e036c3..eb1e1766baede24438b948a6f9974d5f6e0877be 100644 (file)
@@ -64,11 +64,6 @@ static struct cpufreq_frequency_table maple_cpu_freqs[] = {
        {0,                     CPUFREQ_TABLE_END},
 };
 
-static struct freq_attr *maple_cpu_freqs_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 /* Power mode data is an array of the 32 bits PCR values to use for
  * the various frequencies, retrieved from the device-tree
  */
@@ -135,11 +130,6 @@ static int maple_scom_query_freq(void)
  * Common interface to the cpufreq core
  */
 
-static int maple_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, maple_cpu_freqs);
-}
-
 static int maple_cpufreq_target(struct cpufreq_policy *policy,
        unsigned int target_freq, unsigned int relation)
 {
@@ -175,27 +165,17 @@ static unsigned int maple_cpufreq_get_speed(unsigned int cpu)
 
 static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       policy->cpuinfo.transition_latency = 12000;
-       policy->cur = maple_cpu_freqs[maple_scom_query_freq()].frequency;
-       /* secondary CPUs are tied to the primary one by the
-        * cpufreq core if in the secondary policy we tell it that
-        * it actually must be one policy together with all others. */
-       cpumask_setall(policy->cpus);
-       cpufreq_frequency_table_get_attr(maple_cpu_freqs, policy->cpu);
-
-       return cpufreq_frequency_table_cpuinfo(policy,
-               maple_cpu_freqs);
+       return cpufreq_generic_init(policy, maple_cpu_freqs, 12000);
 }
 
-
 static struct cpufreq_driver maple_cpufreq_driver = {
        .name           = "maple",
        .flags          = CPUFREQ_CONST_LOOPS,
        .init           = maple_cpufreq_cpu_init,
-       .verify         = maple_cpufreq_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = maple_cpufreq_target,
        .get            = maple_cpufreq_get_speed,
-       .attr           = maple_cpu_freqs_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init maple_cpufreq_init(void)
index f31fcfcad514330ca856bcfd015aba3927de8241..ac552d090463d729d4ef0b98aebe893c554ae02c 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -40,13 +40,6 @@ static struct clk *mpu_clk;
 static struct device *mpu_dev;
 static struct regulator *mpu_reg;
 
-static int omap_verify_speed(struct cpufreq_policy *policy)
-{
-       if (!freq_table)
-               return -EINVAL;
-       return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
 static unsigned int omap_getspeed(unsigned int cpu)
 {
        unsigned long rate;
@@ -65,7 +58,7 @@ static int omap_target(struct cpufreq_policy *policy,
        unsigned int i;
        int r, ret = 0;
        struct cpufreq_freqs freqs;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long freq, volt = 0, volt_old = 0, tol = 0;
 
        if (!freq_table) {
@@ -105,14 +98,14 @@ static int omap_target(struct cpufreq_policy *policy,
 
        if (mpu_reg) {
                rcu_read_lock();
-               opp = opp_find_freq_ceil(mpu_dev, &freq);
+               opp = dev_pm_opp_find_freq_ceil(mpu_dev, &freq);
                if (IS_ERR(opp)) {
                        rcu_read_unlock();
                        dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n",
                                __func__, freqs.new);
                        return -EINVAL;
                }
-               volt = opp_get_voltage(opp);
+               volt = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
                tol = volt * OPP_TOLERANCE / 100;
                volt_old = regulator_get_voltage(mpu_reg);
@@ -162,86 +155,57 @@ done:
 static inline void freq_table_free(void)
 {
        if (atomic_dec_and_test(&freq_table_users))
-               opp_free_cpufreq_table(mpu_dev, &freq_table);
+               dev_pm_opp_free_cpufreq_table(mpu_dev, &freq_table);
 }
 
 static int omap_cpu_init(struct cpufreq_policy *policy)
 {
-       int result = 0;
+       int result;
 
        mpu_clk = clk_get(NULL, "cpufreq_ck");
        if (IS_ERR(mpu_clk))
                return PTR_ERR(mpu_clk);
 
-       if (policy->cpu >= NR_CPUS) {
-               result = -EINVAL;
-               goto fail_ck;
-       }
-
-       policy->cur = omap_getspeed(policy->cpu);
-
-       if (!freq_table)
-               result = opp_init_cpufreq_table(mpu_dev, &freq_table);
-
-       if (result) {
-               dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
+       if (!freq_table) {
+               result = dev_pm_opp_init_cpufreq_table(mpu_dev, &freq_table);
+               if (result) {
+                       dev_err(mpu_dev,
+                               "%s: cpu%d: failed creating freq table[%d]\n",
                                __func__, policy->cpu, result);
-               goto fail_ck;
+                       goto fail;
+               }
        }
 
        atomic_inc_return(&freq_table_users);
 
-       result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       if (result)
-               goto fail_table;
-
-       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-
-       policy->cur = omap_getspeed(policy->cpu);
-
-       /*
-        * On OMAP SMP configuartion, both processors share the voltage
-        * and clock. So both CPUs needs to be scaled together and hence
-        * needs software co-ordination. Use cpufreq affected_cpus
-        * interface to handle this scenario. Additional is_smp() check
-        * is to keep SMP_ON_UP build working.
-        */
-       if (is_smp())
-               cpumask_setall(policy->cpus);
-
        /* FIXME: what's the actual transition time? */
-       policy->cpuinfo.transition_latency = 300 * 1000;
-
-       return 0;
+       result = cpufreq_generic_init(policy, freq_table, 300 * 1000);
+       if (!result)
+               return 0;
 
-fail_table:
        freq_table_free();
-fail_ck:
+fail:
        clk_put(mpu_clk);
        return result;
 }
 
 static int omap_cpu_exit(struct cpufreq_policy *policy)
 {
+       cpufreq_frequency_table_put_attr(policy->cpu);
        freq_table_free();
        clk_put(mpu_clk);
        return 0;
 }
 
-static struct freq_attr *omap_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver omap_driver = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = omap_verify_speed,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = omap_target,
        .get            = omap_getspeed,
        .init           = omap_cpu_init,
        .exit           = omap_cpu_exit,
        .name           = "omap",
-       .attr           = omap_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int omap_cpufreq_probe(struct platform_device *pdev)
index 2f0a2a65c37f67eeae9789ed12afa20627fd3503..6164c1cca504881d80ecb64d3bfb10e756a17349 100644 (file)
@@ -140,12 +140,6 @@ static int cpufreq_p4_target(struct cpufreq_policy *policy,
 }
 
 
-static int cpufreq_p4_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &p4clockmod_table[0]);
-}
-
-
 static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c)
 {
        if (c->x86 == 0x06) {
@@ -230,25 +224,17 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
                else
                        p4clockmod_table[i].frequency = (stock_freq * i)/8;
        }
-       cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu);
 
        /* cpuinfo and default policy values */
 
        /* the transition latency is set to be 1 higher than the maximum
         * transition latency of the ondemand governor */
        policy->cpuinfo.transition_latency = 10000001;
-       policy->cur = stock_freq;
 
-       return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0]);
+       return cpufreq_table_validate_and_show(policy, &p4clockmod_table[0]);
 }
 
 
-static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
-}
-
 static unsigned int cpufreq_p4_get(unsigned int cpu)
 {
        u32 l, h;
@@ -267,19 +253,14 @@ static unsigned int cpufreq_p4_get(unsigned int cpu)
        return stock_freq;
 }
 
-static struct freq_attr *p4clockmod_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver p4clockmod_driver = {
-       .verify         = cpufreq_p4_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = cpufreq_p4_target,
        .init           = cpufreq_p4_cpu_init,
-       .exit           = cpufreq_p4_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .get            = cpufreq_p4_get,
        .name           = "p4-clockmod",
-       .attr           = p4clockmod_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id cpufreq_p4_id[] = {
index 534e43a60d1f9a80b2a952abe254fb01e06c0f12..1cca332728c3c36e2a40a5bc248f1cb39651c741 100644 (file)
@@ -69,11 +69,6 @@ static struct cpufreq_frequency_table pas_freqs[] = {
        {0,     CPUFREQ_TABLE_END},
 };
 
-static struct freq_attr *pas_cpu_freqs_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 /*
  * hardware specific functions
  */
@@ -209,22 +204,13 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
                pr_debug("%d: %d\n", i, pas_freqs[i].frequency);
        }
 
-       policy->cpuinfo.transition_latency = get_gizmo_latency();
-
        cur_astate = get_cur_astate(policy->cpu);
        pr_debug("current astate is at %d\n",cur_astate);
 
        policy->cur = pas_freqs[cur_astate].frequency;
-       cpumask_copy(policy->cpus, cpu_online_mask);
-
        ppc_proc_freq = policy->cur * 1000ul;
 
-       cpufreq_frequency_table_get_attr(pas_freqs, policy->cpu);
-
-       /* this ensures that policy->cpuinfo_min and policy->cpuinfo_max
-        * are set correctly
-        */
-       return cpufreq_frequency_table_cpuinfo(policy, pas_freqs);
+       return cpufreq_generic_init(policy, pas_freqs, get_gizmo_latency());
 
 out_unmap_sdcpwr:
        iounmap(sdcpwr_mapbase);
@@ -253,11 +239,6 @@ static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-static int pas_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, pas_freqs);
-}
-
 static int pas_cpufreq_target(struct cpufreq_policy *policy,
                              unsigned int target_freq,
                              unsigned int relation)
@@ -300,9 +281,9 @@ static struct cpufreq_driver pas_cpufreq_driver = {
        .flags          = CPUFREQ_CONST_LOOPS,
        .init           = pas_cpufreq_cpu_init,
        .exit           = pas_cpufreq_cpu_exit,
-       .verify         = pas_cpufreq_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = pas_cpufreq_target,
-       .attr           = pas_cpu_freqs_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 /*
index d81c4e5ea0ada8c49afac790f1107bc5ce8f11e6..e2b4f40ff69acaaff51f6461caafd4c8a23bdd16 100644 (file)
@@ -111,8 +111,7 @@ static struct pcc_cpu __percpu *pcc_cpu_info;
 
 static int pcc_cpufreq_verify(struct cpufreq_policy *policy)
 {
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
        return 0;
 }
 
@@ -396,15 +395,14 @@ static int __init pcc_cpufreq_probe(void)
        struct pcc_memory_resource *mem_resource;
        struct pcc_register_resource *reg_resource;
        union acpi_object *out_obj, *member;
-       acpi_handle handle, osc_handle, pcch_handle;
+       acpi_handle handle, osc_handle;
        int ret = 0;
 
        status = acpi_get_handle(NULL, "\\_SB", &handle);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
-       status = acpi_get_handle(handle, "PCCH", &pcch_handle);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(handle, "PCCH"))
                return -ENODEV;
 
        status = acpi_get_handle(handle, "_OSC", &osc_handle);
@@ -560,13 +558,6 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
                ioread32(&pcch_hdr->nominal) * 1000;
        policy->min = policy->cpuinfo.min_freq =
                ioread32(&pcch_hdr->minimum_frequency) * 1000;
-       policy->cur = pcc_get_freq(cpu);
-
-       if (!policy->cur) {
-               pr_debug("init: Unable to get current CPU frequency\n");
-               result = -EINVAL;
-               goto out;
-       }
 
        pr_debug("init: policy->max is %d, policy->min is %d\n",
                policy->max, policy->min);
index a096cd3fa23d1aaef19b3ae27ecd87037f01ba6f..6eac1e2300785ed4c3a9dc1d00ea362014061c50 100644 (file)
@@ -86,11 +86,6 @@ static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
        {0,                     CPUFREQ_TABLE_END},
 };
 
-static struct freq_attr* pmac_cpu_freqs_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static inline void local_delay(unsigned long ms)
 {
        if (no_schedule)
@@ -378,11 +373,6 @@ static unsigned int pmac_cpufreq_get_speed(unsigned int cpu)
        return cur_freq;
 }
 
-static int pmac_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, pmac_cpu_freqs);
-}
-
 static int pmac_cpufreq_target(        struct cpufreq_policy *policy,
                                        unsigned int target_freq,
                                        unsigned int relation)
@@ -402,14 +392,7 @@ static int pmac_cpufreq_target(    struct cpufreq_policy *policy,
 
 static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       if (policy->cpu != 0)
-               return -ENODEV;
-
-       policy->cpuinfo.transition_latency      = transition_latency;
-       policy->cur = cur_freq;
-
-       cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
-       return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
+       return cpufreq_generic_init(policy, pmac_cpu_freqs, transition_latency);
 }
 
 static u32 read_gpio(struct device_node *np)
@@ -469,14 +452,14 @@ static int pmac_cpufreq_resume(struct cpufreq_policy *policy)
 }
 
 static struct cpufreq_driver pmac_cpufreq_driver = {
-       .verify         = pmac_cpufreq_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = pmac_cpufreq_target,
        .get            = pmac_cpufreq_get_speed,
        .init           = pmac_cpufreq_cpu_init,
        .suspend        = pmac_cpufreq_suspend,
        .resume         = pmac_cpufreq_resume,
        .flags          = CPUFREQ_PM_NO_WARN,
-       .attr           = pmac_cpu_freqs_attr,
+       .attr           = cpufreq_generic_attr,
        .name           = "powermac",
 };
 
index 3a51ad7e47c8c67c95da5f3691d7f89e397c34a6..5261b92d768bb31fa89d60bb2692768d412882d8 100644 (file)
@@ -70,11 +70,6 @@ static struct cpufreq_frequency_table g5_cpu_freqs[] = {
        {0,                     CPUFREQ_TABLE_END},
 };
 
-static struct freq_attr* g5_cpu_freqs_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 /* Power mode data is an array of the 32 bits PCR values to use for
  * the various frequencies, retrieved from the device-tree
  */
@@ -142,7 +137,7 @@ static void g5_vdnap_switch_volt(int speed_mode)
                pmf_call_one(pfunc_vdnap0_complete, &args);
                if (done)
                        break;
-               msleep(1);
+               usleep_range(1000, 1000);
        }
        if (done == 0)
                printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n");
@@ -241,7 +236,7 @@ static void g5_pfunc_switch_volt(int speed_mode)
                if (pfunc_cpu1_volt_low)
                        pmf_call_one(pfunc_cpu1_volt_low, NULL);
        }
-       msleep(10); /* should be faster , to fix */
+       usleep_range(10000, 10000); /* should be faster , to fix */
 }
 
 /*
@@ -286,7 +281,7 @@ static int g5_pfunc_switch_freq(int speed_mode)
                pmf_call_one(pfunc_slewing_done, &args);
                if (done)
                        break;
-               msleep(1);
+               usleep_range(500, 500);
        }
        if (done == 0)
                printk(KERN_WARNING "cpufreq: Timeout in clock slewing !\n");
@@ -317,11 +312,6 @@ static int g5_pfunc_query_freq(void)
  * Common interface to the cpufreq core
  */
 
-static int g5_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, g5_cpu_freqs);
-}
-
 static int g5_cpufreq_target(struct cpufreq_policy *policy,
        unsigned int target_freq, unsigned int relation)
 {
@@ -357,27 +347,17 @@ static unsigned int g5_cpufreq_get_speed(unsigned int cpu)
 
 static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
 {
-       policy->cpuinfo.transition_latency = transition_latency;
-       policy->cur = g5_cpu_freqs[g5_query_freq()].frequency;
-       /* secondary CPUs are tied to the primary one by the
-        * cpufreq core if in the secondary policy we tell it that
-        * it actually must be one policy together with all others. */
-       cpumask_copy(policy->cpus, cpu_online_mask);
-       cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu);
-
-       return cpufreq_frequency_table_cpuinfo(policy,
-               g5_cpu_freqs);
+       return cpufreq_generic_init(policy, g5_cpu_freqs, transition_latency);
 }
 
-
 static struct cpufreq_driver g5_cpufreq_driver = {
        .name           = "powermac",
        .flags          = CPUFREQ_CONST_LOOPS,
        .init           = g5_cpufreq_cpu_init,
-       .verify         = g5_cpufreq_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = g5_cpufreq_target,
        .get            = g5_cpufreq_get_speed,
-       .attr           = g5_cpu_freqs_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 
@@ -397,7 +377,8 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpunode)
        /* Check supported platforms */
        if (of_machine_is_compatible("PowerMac8,1") ||
            of_machine_is_compatible("PowerMac8,2") ||
-           of_machine_is_compatible("PowerMac9,1"))
+           of_machine_is_compatible("PowerMac9,1") ||
+           of_machine_is_compatible("PowerMac12,1"))
                use_volts_smu = 1;
        else if (of_machine_is_compatible("PowerMac11,2"))
                use_volts_vdnap = 1;
@@ -647,8 +628,10 @@ static int __init g5_pm72_cpufreq_init(struct device_node *cpunode)
        g5_cpu_freqs[0].frequency = max_freq;
        g5_cpu_freqs[1].frequency = min_freq;
 
+       /* Based on a measurement on Xserve G5, rounded up. */
+       transition_latency = 10 * NSEC_PER_MSEC;
+
        /* Set callbacks */
-       transition_latency = CPUFREQ_ETERNAL;
        g5_switch_volt = g5_pfunc_switch_volt;
        g5_switch_freq = g5_pfunc_switch_freq;
        g5_query_freq = g5_pfunc_query_freq;
index 85f1c8c25ddc5d20a361e219d023548b356b835b..eda17024a34adb0e11cd9cb4553d4d0ca7d18164 100644 (file)
@@ -104,19 +104,6 @@ static void powernow_k6_set_state(struct cpufreq_policy *policy,
 }
 
 
-/**
- * powernow_k6_verify - verifies a new CPUfreq policy
- * @policy: new policy
- *
- * Policy must be within lowest and highest possible CPU Frequency,
- * and at least one possible state must be within min and max.
- */
-static int powernow_k6_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &clock_ratio[0]);
-}
-
-
 /**
  * powernow_k6_setpolicy - sets a new CPUFreq policy
  * @policy: new policy
@@ -145,7 +132,6 @@ static int powernow_k6_target(struct cpufreq_policy *policy,
 static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int i, f;
-       int result;
 
        if (policy->cpu != 0)
                return -ENODEV;
@@ -165,15 +151,8 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
 
        /* cpuinfo and default policy values */
        policy->cpuinfo.transition_latency = 200000;
-       policy->cur = busfreq * max_multiplier;
-
-       result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio);
-       if (result)
-               return result;
-
-       cpufreq_frequency_table_get_attr(clock_ratio, policy->cpu);
 
-       return 0;
+       return cpufreq_table_validate_and_show(policy, clock_ratio);
 }
 
 
@@ -195,19 +174,14 @@ static unsigned int powernow_k6_get(unsigned int cpu)
        return ret;
 }
 
-static struct freq_attr *powernow_k6_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver powernow_k6_driver = {
-       .verify         = powernow_k6_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = powernow_k6_target,
        .init           = powernow_k6_cpu_init,
        .exit           = powernow_k6_cpu_exit,
        .get            = powernow_k6_get,
        .name           = "powernow-k6",
-       .attr           = powernow_k6_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id powernow_k6_ids[] = {
index 14ce480be8ab2503515cb1d61b8f30b5892d85d2..44d345bad6fb1d9b93345ea5b80e24c7cfc0b281 100644 (file)
@@ -549,11 +549,6 @@ static int powernow_target(struct cpufreq_policy *policy,
 }
 
 
-static int powernow_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, powernow_table);
-}
-
 /*
  * We use the fact that the bus frequency is somehow
  * a multiple of 100000/3 khz, then we compute sgtc according
@@ -678,11 +673,7 @@ static int powernow_cpu_init(struct cpufreq_policy *policy)
        policy->cpuinfo.transition_latency =
                cpufreq_scale(2000000UL, fsb, latency);
 
-       policy->cur = powernow_get(0);
-
-       cpufreq_frequency_table_get_attr(powernow_table, policy->cpu);
-
-       return cpufreq_frequency_table_cpuinfo(policy, powernow_table);
+       return cpufreq_table_validate_and_show(policy, powernow_table);
 }
 
 static int powernow_cpu_exit(struct cpufreq_policy *policy)
@@ -701,13 +692,8 @@ static int powernow_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-static struct freq_attr *powernow_table_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver powernow_driver = {
-       .verify         = powernow_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = powernow_target,
        .get            = powernow_get,
 #ifdef CONFIG_X86_POWERNOW_K7_ACPI
@@ -716,7 +702,7 @@ static struct cpufreq_driver powernow_driver = {
        .init           = powernow_cpu_init,
        .exit           = powernow_cpu_exit,
        .name           = "powernow-k7",
-       .attr           = powernow_table_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init powernow_init(void)
index 2344a9ed17f3c38017701e075c945df8ae0f4bdf..298beb742ebb1e62ef743c7e3392bd0f980bc3ba 100644 (file)
@@ -1053,17 +1053,6 @@ static int powernowk8_target(struct cpufreq_policy *pol,
        return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
 }
 
-/* Driver entry point to verify the policy and range of frequencies */
-static int powernowk8_verify(struct cpufreq_policy *pol)
-{
-       struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
-
-       if (!data)
-               return -EINVAL;
-
-       return cpufreq_frequency_table_verify(pol, data->powernow_table);
-}
-
 struct init_on_cpu {
        struct powernow_k8_data *data;
        int rc;
@@ -1152,11 +1141,8 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
        cpumask_copy(pol->cpus, cpu_core_mask(pol->cpu));
        data->available_cores = pol->cpus;
 
-       pol->cur = find_khz_freq_from_fid(data->currfid);
-       pr_debug("policy current frequency %d kHz\n", pol->cur);
-
        /* min/max the cpu is capable of */
-       if (cpufreq_frequency_table_cpuinfo(pol, data->powernow_table)) {
+       if (cpufreq_table_validate_and_show(pol, data->powernow_table)) {
                printk(KERN_ERR FW_BUG PFX "invalid powernow_table\n");
                powernow_k8_cpu_exit_acpi(data);
                kfree(data->powernow_table);
@@ -1164,8 +1150,6 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
                return -EINVAL;
        }
 
-       cpufreq_frequency_table_get_attr(data->powernow_table, pol->cpu);
-
        pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
                 data->currfid, data->currvid);
 
@@ -1227,20 +1211,15 @@ out:
        return khz;
 }
 
-static struct freq_attr *powernow_k8_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver cpufreq_amd64_driver = {
-       .verify         = powernowk8_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = powernowk8_target,
        .bios_limit     = acpi_processor_get_bios_limit,
        .init           = powernowk8_cpu_init,
        .exit           = powernowk8_cpu_exit,
        .get            = powernowk8_get,
        .name           = "powernow-k8",
-       .attr           = powernow_k8_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static void __request_acpi_cpufreq(void)
index 60e81d524ea8231666210ecca2c97407c0a5a279..a0f562ca292dd6124226329a1202ba00435c5a6a 100644 (file)
@@ -202,7 +202,7 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
        table[i].frequency = CPUFREQ_TABLE_END;
 
        /* set the min and max frequency properly */
-       ret = cpufreq_frequency_table_cpuinfo(policy, table);
+       ret = cpufreq_table_validate_and_show(policy, table);
        if (ret) {
                pr_err("invalid frequency table: %d\n", ret);
                goto err_nomem1;
@@ -217,9 +217,6 @@ static int corenet_cpufreq_cpu_init(struct cpufreq_policy *policy)
                per_cpu(cpu_data, i) = data;
 
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       policy->cur = corenet_cpufreq_get_speed(policy->cpu);
-
-       cpufreq_frequency_table_get_attr(table, cpu);
        of_node_put(np);
 
        return 0;
@@ -253,14 +250,6 @@ static int __exit corenet_cpufreq_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-static int corenet_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       struct cpufreq_frequency_table *table =
-               per_cpu(cpu_data, policy->cpu)->table;
-
-       return cpufreq_frequency_table_verify(policy, table);
-}
-
 static int corenet_cpufreq_target(struct cpufreq_policy *policy,
                unsigned int target_freq, unsigned int relation)
 {
@@ -293,20 +282,15 @@ static int corenet_cpufreq_target(struct cpufreq_policy *policy,
        return ret;
 }
 
-static struct freq_attr *corenet_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver ppc_corenet_cpufreq_driver = {
        .name           = "ppc_cpufreq",
        .flags          = CPUFREQ_CONST_LOOPS,
        .init           = corenet_cpufreq_cpu_init,
        .exit           = __exit_p(corenet_cpufreq_cpu_exit),
-       .verify         = corenet_cpufreq_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = corenet_cpufreq_target,
        .get            = corenet_cpufreq_get_speed,
-       .attr           = corenet_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct of_device_id node_matches[] __initdata = {
index 2e448f0bbdc583465672e7ec40804f1d01467224..38540d1f59390b1306b286bcb36fb34a3980bbcb 100644 (file)
@@ -123,22 +123,9 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
        cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu));
 #endif
 
-       cpufreq_frequency_table_get_attr(cbe_freqs, policy->cpu);
-
        /* this ensures that policy->cpuinfo_min
         * and policy->cpuinfo_max are set correctly */
-       return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs);
-}
-
-static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
-}
-
-static int cbe_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, cbe_freqs);
+       return cpufreq_table_validate_and_show(policy, cbe_freqs);
 }
 
 static int cbe_cpufreq_target(struct cpufreq_policy *policy,
@@ -176,10 +163,10 @@ static int cbe_cpufreq_target(struct cpufreq_policy *policy,
 }
 
 static struct cpufreq_driver cbe_cpufreq_driver = {
-       .verify         = cbe_cpufreq_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = cbe_cpufreq_target,
        .init           = cbe_cpufreq_cpu_init,
-       .exit           = cbe_cpufreq_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .name           = "cbe-cpufreq",
        .flags          = CPUFREQ_CONST_LOOPS,
 };
index 8749eaf1879338ad331f587c9a716a501ab0c701..29aca574317bd02bb3932bb890da9726ccd8268d 100644 (file)
@@ -262,23 +262,6 @@ static u32 mdrefr_dri(unsigned int freq)
        return (interval - (cpu_is_pxa27x() ? 31 : 0)) / 32;
 }
 
-/* find a valid frequency point */
-static int pxa_verify_policy(struct cpufreq_policy *policy)
-{
-       struct cpufreq_frequency_table *pxa_freqs_table;
-       pxa_freqs_t *pxa_freqs;
-       int ret;
-
-       find_freq_tables(&pxa_freqs_table, &pxa_freqs);
-       ret = cpufreq_frequency_table_verify(policy, pxa_freqs_table);
-
-       if (freq_debug)
-               pr_debug("Verified CPU policy: %dKhz min to %dKhz max\n",
-                        policy->min, policy->max);
-
-       return ret;
-}
-
 static unsigned int pxa_cpufreq_get(unsigned int cpu)
 {
        return get_clk_frequency_khz(0);
@@ -414,8 +397,6 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
 
        /* set default policy and cpuinfo */
        policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
-       policy->cur = get_clk_frequency_khz(0);    /* current freq */
-       policy->min = policy->max = policy->cur;
 
        /* Generate pxa25x the run cpufreq_frequency_table struct */
        for (i = 0; i < NUM_PXA25x_RUN_FREQS; i++) {
@@ -453,10 +434,12 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
                find_freq_tables(&pxa255_freq_table, &pxa255_freqs);
                pr_info("PXA255 cpufreq using %s frequency table\n",
                        pxa255_turbo_table ? "turbo" : "run");
-               cpufreq_frequency_table_cpuinfo(policy, pxa255_freq_table);
+
+               cpufreq_table_validate_and_show(policy, pxa255_freq_table);
+       }
+       else if (cpu_is_pxa27x()) {
+               cpufreq_table_validate_and_show(policy, pxa27x_freq_table);
        }
-       else if (cpu_is_pxa27x())
-               cpufreq_frequency_table_cpuinfo(policy, pxa27x_freq_table);
 
        printk(KERN_INFO "PXA CPU frequency change support initialized\n");
 
@@ -464,9 +447,10 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
 }
 
 static struct cpufreq_driver pxa_cpufreq_driver = {
-       .verify = pxa_verify_policy,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = pxa_set_target,
        .init   = pxa_cpufreq_init,
+       .exit   = cpufreq_generic_exit,
        .get    = pxa_cpufreq_get,
        .name   = "PXA2xx",
 };
index d26306fb00d2e8a749ed044c816533f101defd11..47fbee49d6e594f2dfd6ca1e55ddebbe0b3a2f90 100644 (file)
@@ -108,7 +108,7 @@ static int setup_freqs_table(struct cpufreq_policy *policy,
        pxa3xx_freqs_num = num;
        pxa3xx_freqs_table = table;
 
-       return cpufreq_frequency_table_cpuinfo(policy, table);
+       return cpufreq_table_validate_and_show(policy, table);
 }
 
 static void __update_core_freq(struct pxa3xx_freq_info *info)
@@ -150,11 +150,6 @@ static void __update_bus_freq(struct pxa3xx_freq_info *info)
                cpu_relax();
 }
 
-static int pxa3xx_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, pxa3xx_freqs_table);
-}
-
 static unsigned int pxa3xx_cpufreq_get(unsigned int cpu)
 {
        return pxa3xx_get_clk_frequency_khz(0);
@@ -206,11 +201,10 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
        int ret = -EINVAL;
 
        /* set default policy and cpuinfo */
-       policy->cpuinfo.min_freq = 104000;
-       policy->cpuinfo.max_freq = (cpu_is_pxa320()) ? 806000 : 624000;
+       policy->min = policy->cpuinfo.min_freq = 104000;
+       policy->max = policy->cpuinfo.max_freq =
+               (cpu_is_pxa320()) ? 806000 : 624000;
        policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
-       policy->max = pxa3xx_get_clk_frequency_khz(0);
-       policy->cur = policy->min = policy->max;
 
        if (cpu_is_pxa300() || cpu_is_pxa310())
                ret = setup_freqs_table(policy, pxa300_freqs,
@@ -230,9 +224,10 @@ static int pxa3xx_cpufreq_init(struct cpufreq_policy *policy)
 }
 
 static struct cpufreq_driver pxa3xx_cpufreq_driver = {
-       .verify         = pxa3xx_cpufreq_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = pxa3xx_cpufreq_set,
        .init           = pxa3xx_cpufreq_init,
+       .exit           = cpufreq_generic_exit,
        .get            = pxa3xx_cpufreq_get,
        .name           = "pxa3xx-cpufreq",
 };
index 22dcb81ef9d0e9069b8fc4d49249713d59d41dd9..26a35d1371574f2e4abef7dd05beea6becb8f2a2 100644 (file)
@@ -87,16 +87,6 @@ static struct cpufreq_frequency_table s3c2450_freq_table[] = {
        { 0, CPUFREQ_TABLE_END },
 };
 
-static int s3c2416_cpufreq_verify_speed(struct cpufreq_policy *policy)
-{
-       struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
-
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       return cpufreq_frequency_table_verify(policy, s3c_freq->freq_table);
-}
-
 static unsigned int s3c2416_cpufreq_get_speed(unsigned int cpu)
 {
        struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
@@ -486,20 +476,14 @@ static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy)
                freq++;
        }
 
-       policy->cur = clk_get_rate(s3c_freq->armclk) / 1000;
-
        /* Datasheet says PLL stabalisation time must be at least 300us,
         * so but add some fudge. (reference in LOCKCON0 register description)
         */
-       policy->cpuinfo.transition_latency = (500 * 1000) +
-                                            s3c_freq->regulator_latency;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, s3c_freq->freq_table);
+       ret = cpufreq_generic_init(policy, s3c_freq->freq_table,
+                       (500 * 1000) + s3c_freq->regulator_latency);
        if (ret)
                goto err_freq_table;
 
-       cpufreq_frequency_table_get_attr(s3c_freq->freq_table, 0);
-
        register_reboot_notifier(&s3c2416_cpufreq_reboot_notifier);
 
        return 0;
@@ -518,19 +502,14 @@ err_hclk:
        return ret;
 }
 
-static struct freq_attr *s3c2416_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver s3c2416_cpufreq_driver = {
        .flags          = 0,
-       .verify         = s3c2416_cpufreq_verify_speed,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = s3c2416_cpufreq_set_target,
        .get            = s3c2416_cpufreq_get_speed,
        .init           = s3c2416_cpufreq_driver_init,
        .name           = "s3c2416",
-       .attr           = s3c2416_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init s3c2416_cpufreq_init(void)
index b0f343fcb7eefdfe40b942b202398372a618df44..485088253358d1a5712c9f73cfea9036f65aa156 100644 (file)
@@ -373,23 +373,7 @@ struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name)
 
 static int s3c_cpufreq_init(struct cpufreq_policy *policy)
 {
-       printk(KERN_INFO "%s: initialising policy %p\n", __func__, policy);
-
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       policy->cur = s3c_cpufreq_get(0);
-       policy->min = policy->cpuinfo.min_freq = 0;
-       policy->max = policy->cpuinfo.max_freq = cpu_cur.info->max.fclk / 1000;
-       policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
-
-       /* feed the latency information from the cpu driver */
-       policy->cpuinfo.transition_latency = cpu_cur.info->latency;
-
-       if (ftab)
-               cpufreq_frequency_table_cpuinfo(policy, ftab);
-
-       return 0;
+       return cpufreq_generic_init(policy, ftab, cpu_cur.info->latency);
 }
 
 static int __init s3c_cpufreq_initclks(void)
@@ -416,14 +400,6 @@ static int __init s3c_cpufreq_initclks(void)
        return 0;
 }
 
-static int s3c_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       return 0;
-}
-
 #ifdef CONFIG_PM
 static struct cpufreq_frequency_table suspend_pll;
 static unsigned int suspend_freq;
@@ -473,7 +449,6 @@ static int s3c_cpufreq_resume(struct cpufreq_policy *policy)
 
 static struct cpufreq_driver s3c24xx_driver = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = s3c_cpufreq_verify,
        .target         = s3c_cpufreq_target,
        .get            = s3c_cpufreq_get,
        .init           = s3c_cpufreq_init,
index 15631f92ab7d78cceec876e319c85092c921b8bc..461617332033de80fb7c1ff774bfd15106670830 100644 (file)
@@ -54,14 +54,6 @@ static struct cpufreq_frequency_table s3c64xx_freq_table[] = {
 };
 #endif
 
-static int s3c64xx_cpufreq_verify_speed(struct cpufreq_policy *policy)
-{
-       if (policy->cpu != 0)
-               return -EINVAL;
-
-       return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table);
-}
-
 static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu)
 {
        if (cpu != 0)
@@ -243,15 +235,12 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
                freq++;
        }
 
-       policy->cur = clk_get_rate(armclk) / 1000;
-
        /* Datasheet says PLL stabalisation time (if we were to use
         * the PLLs, which we don't currently) is ~300us worst case,
         * but add some fudge.
         */
-       policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table);
+       ret = cpufreq_generic_init(policy, s3c64xx_freq_table,
+                       (500 * 1000) + regulator_latency);
        if (ret != 0) {
                pr_err("Failed to configure frequency table: %d\n",
                       ret);
@@ -264,7 +253,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
 
 static struct cpufreq_driver s3c64xx_cpufreq_driver = {
        .flags          = 0,
-       .verify         = s3c64xx_cpufreq_verify_speed,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = s3c64xx_cpufreq_set_target,
        .get            = s3c64xx_cpufreq_get_speed,
        .init           = s3c64xx_cpufreq_driver_init,
index 5c77570737937c298577303904baa60823fdce60..600b4f472e28432ad9ac6b0bab2b1a3d5091104f 100644 (file)
@@ -174,14 +174,6 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
        __raw_writel(tmp1, reg);
 }
 
-static int s5pv210_verify_speed(struct cpufreq_policy *policy)
-{
-       if (policy->cpu)
-               return -EINVAL;
-
-       return cpufreq_frequency_table_verify(policy, s5pv210_freq_table);
-}
-
 static unsigned int s5pv210_getspeed(unsigned int cpu)
 {
        if (cpu)
@@ -551,13 +543,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
        s5pv210_dram_conf[1].refresh = (__raw_readl(S5P_VA_DMC1 + 0x30) * 1000);
        s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
 
-       policy->cur = policy->min = policy->max = s5pv210_getspeed(0);
-
-       cpufreq_frequency_table_get_attr(s5pv210_freq_table, policy->cpu);
-
-       policy->cpuinfo.transition_latency = 40000;
-
-       return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
+       return cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
 
 out_dmc1:
        clk_put(dmc0_clk);
@@ -605,7 +591,7 @@ static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this,
 
 static struct cpufreq_driver s5pv210_driver = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = s5pv210_verify_speed,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = s5pv210_target,
        .get            = s5pv210_getspeed,
        .init           = s5pv210_cpu_init,
index cff18e87ca58721cc9ae13e432816d712d7d0c2d..b282cea47e628d67551c2366b0d494dda781cff7 100644 (file)
@@ -218,18 +218,12 @@ static int sa1100_target(struct cpufreq_policy *policy,
 
 static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
 {
-       if (policy->cpu != 0)
-               return -EINVAL;
-       policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
-       policy->cpuinfo.min_freq = 59000;
-       policy->cpuinfo.max_freq = 287000;
-       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       return 0;
+       return cpufreq_generic_init(policy, sa11x0_freq_table, CPUFREQ_ETERNAL);
 }
 
 static struct cpufreq_driver sa1100_driver __refdata = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = sa11x0_verify_speed,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = sa1100_target,
        .get            = sa11x0_getspeed,
        .init           = sa1100_cpu_init,
index 39c90b6f42865eb8f8950ce0f7d7ce84d463a9ee..bca04c0b4a734369ef5281a6acebb575a2940da1 100644 (file)
@@ -332,20 +332,14 @@ static int sa1110_target(struct cpufreq_policy *policy,
 
 static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
 {
-       if (policy->cpu != 0)
-               return -EINVAL;
-       policy->cur = policy->min = policy->max = sa11x0_getspeed(0);
-       policy->cpuinfo.min_freq = 59000;
-       policy->cpuinfo.max_freq = 287000;
-       policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       return 0;
+       return cpufreq_generic_init(policy, sa11x0_freq_table, CPUFREQ_ETERNAL);
 }
 
 /* sa1110_driver needs __refdata because it must remain after init registers
  * it with cpufreq_register_driver() */
 static struct cpufreq_driver sa1110_driver __refdata = {
        .flags          = CPUFREQ_STICKY,
-       .verify         = sa11x0_verify_speed,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = sa1110_target,
        .get            = sa11x0_getspeed,
        .init           = sa1110_cpu_init,
index d6f6c6f4efa76ac6f82a97ddeff3292a06cfd18c..9047ab1ca014b9e4b735abc60f244a54d1a74733 100644 (file)
@@ -78,11 +78,6 @@ static void sc520_freq_set_cpu_state(struct cpufreq_policy *policy,
        cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
 };
 
-static int sc520_freq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &sc520_freq_table[0]);
-}
-
 static int sc520_freq_target(struct cpufreq_policy *policy,
                            unsigned int target_freq,
                            unsigned int relation)
@@ -106,7 +101,6 @@ static int sc520_freq_target(struct cpufreq_policy *policy,
 static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
 {
        struct cpuinfo_x86 *c = &cpu_data(0);
-       int result;
 
        /* capability check */
        if (c->x86_vendor != X86_VENDOR_AMD ||
@@ -115,39 +109,19 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
 
        /* cpuinfo and default policy values */
        policy->cpuinfo.transition_latency = 1000000; /* 1ms */
-       policy->cur = sc520_freq_get_cpu_frequency(0);
-
-       result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table);
-       if (result)
-               return result;
-
-       cpufreq_frequency_table_get_attr(sc520_freq_table, policy->cpu);
-
-       return 0;
-}
-
 
-static int sc520_freq_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_table_validate_and_show(policy, sc520_freq_table);
 }
 
 
-static struct freq_attr *sc520_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
-
 static struct cpufreq_driver sc520_freq_driver = {
        .get    = sc520_freq_get_cpu_frequency,
-       .verify = sc520_freq_verify,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = sc520_freq_target,
        .init   = sc520_freq_cpu_init,
-       .exit   = sc520_freq_cpu_exit,
+       .exit   = cpufreq_generic_exit,
        .name   = "sc520_freq",
-       .attr   = sc520_freq_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id sc520_ids[] = {
index ffc6d24b0cfbed764db6b6c8e2015330e6fb9fbd..387af12503a64e43f15d8fd0fa1d6e108a741f62 100644 (file)
@@ -87,15 +87,12 @@ static int sh_cpufreq_verify(struct cpufreq_policy *policy)
        if (freq_table)
                return cpufreq_frequency_table_verify(policy, freq_table);
 
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
+       cpufreq_verify_within_cpu_limits(policy);
 
        policy->min = (clk_round_rate(cpuclk, 1) + 500) / 1000;
        policy->max = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
 
-       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
-                                    policy->cpuinfo.max_freq);
-
+       cpufreq_verify_within_cpu_limits(policy);
        return 0;
 }
 
@@ -114,15 +111,13 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
                return PTR_ERR(cpuclk);
        }
 
-       policy->cur = sh_cpufreq_get(cpu);
-
        freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL;
        if (freq_table) {
                int result;
 
-               result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
-               if (!result)
-                       cpufreq_frequency_table_get_attr(freq_table, cpu);
+               result = cpufreq_table_validate_and_show(policy, freq_table);
+               if (result)
+                       return result;
        } else {
                dev_notice(dev, "no frequency table found, falling back "
                           "to rate rounding.\n");
@@ -154,11 +149,6 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-static struct freq_attr *sh_freq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver sh_cpufreq_driver = {
        .name           = "sh",
        .get            = sh_cpufreq_get,
@@ -166,7 +156,7 @@ static struct cpufreq_driver sh_cpufreq_driver = {
        .verify         = sh_cpufreq_verify,
        .init           = sh_cpufreq_cpu_init,
        .exit           = sh_cpufreq_cpu_exit,
-       .attr           = sh_freq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init sh_cpufreq_module_init(void)
index cf5bc2ca16fa11f4155d757c6d5219b6691a6b81..291688c1da9acb5883fe3c2339ebbdf216a81696 100644 (file)
@@ -295,12 +295,6 @@ static int us2e_freq_target(struct cpufreq_policy *policy,
        return 0;
 }
 
-static int us2e_freq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                                             &us2e_freq_table[policy->cpu].table[0]);
-}
-
 static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int cpu = policy->cpu;
@@ -324,13 +318,15 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
        policy->cpuinfo.transition_latency = 0;
        policy->cur = clock_tick;
 
-       return cpufreq_frequency_table_cpuinfo(policy, table);
+       return cpufreq_table_validate_and_show(policy, table);
 }
 
 static int us2e_freq_cpu_exit(struct cpufreq_policy *policy)
 {
-       if (cpufreq_us2e_driver)
+       if (cpufreq_us2e_driver) {
+               cpufreq_frequency_table_put_attr(policy->cpu);
                us2e_set_cpu_divider_index(policy, 0);
+       }
 
        return 0;
 }
@@ -361,7 +357,7 @@ static int __init us2e_freq_init(void)
                        goto err_out;
 
                driver->init = us2e_freq_cpu_init;
-               driver->verify = us2e_freq_verify;
+               driver->verify = cpufreq_generic_frequency_table_verify;
                driver->target = us2e_freq_target;
                driver->get = us2e_freq_get;
                driver->exit = us2e_freq_cpu_exit;
index ac76b489979d48cac1278525ab861f46b69f8c86..9b3dbd31362efaa3f5b3a1dcffe5a34c16f42f49 100644 (file)
@@ -156,12 +156,6 @@ static int us3_freq_target(struct cpufreq_policy *policy,
        return 0;
 }
 
-static int us3_freq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                                             &us3_freq_table[policy->cpu].table[0]);
-}
-
 static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int cpu = policy->cpu;
@@ -181,13 +175,15 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
        policy->cpuinfo.transition_latency = 0;
        policy->cur = clock_tick;
 
-       return cpufreq_frequency_table_cpuinfo(policy, table);
+       return cpufreq_table_validate_and_show(policy, table);
 }
 
 static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
 {
-       if (cpufreq_us3_driver)
+       if (cpufreq_us3_driver) {
+               cpufreq_frequency_table_put_attr(policy->cpu);
                us3_set_cpu_divider_index(policy, 0);
+       }
 
        return 0;
 }
@@ -222,7 +218,7 @@ static int __init us3_freq_init(void)
                        goto err_out;
 
                driver->init = us3_freq_cpu_init;
-               driver->verify = us3_freq_verify;
+               driver->verify = cpufreq_generic_frequency_table_verify;
                driver->target = us3_freq_target;
                driver->get = us3_freq_get;
                driver->exit = us3_freq_cpu_exit;
index 3f418166ce02b8fc57a664f3d870bfb8508f3018..8841366a2068e2c41898daf982997820a10ed725 100644 (file)
@@ -30,11 +30,6 @@ static struct {
        u32 cnt;
 } spear_cpufreq;
 
-static int spear_cpufreq_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, spear_cpufreq.freq_tbl);
-}
-
 static unsigned int spear_cpufreq_get(unsigned int cpu)
 {
        return clk_get_rate(spear_cpufreq.clk) / 1000;
@@ -176,43 +171,19 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
 
 static int spear_cpufreq_init(struct cpufreq_policy *policy)
 {
-       int ret;
-
-       ret = cpufreq_frequency_table_cpuinfo(policy, spear_cpufreq.freq_tbl);
-       if (ret) {
-               pr_err("cpufreq_frequency_table_cpuinfo() failed");
-               return ret;
-       }
-
-       cpufreq_frequency_table_get_attr(spear_cpufreq.freq_tbl, policy->cpu);
-       policy->cpuinfo.transition_latency = spear_cpufreq.transition_latency;
-       policy->cur = spear_cpufreq_get(0);
-
-       cpumask_setall(policy->cpus);
-
-       return 0;
-}
-
-static int spear_cpufreq_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_generic_init(policy, spear_cpufreq.freq_tbl,
+                       spear_cpufreq.transition_latency);
 }
 
-static struct freq_attr *spear_cpufreq_attr[] = {
-        &cpufreq_freq_attr_scaling_available_freqs,
-        NULL,
-};
-
 static struct cpufreq_driver spear_cpufreq_driver = {
        .name           = "cpufreq-spear",
        .flags          = CPUFREQ_STICKY,
-       .verify         = spear_cpufreq_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = spear_cpufreq_target,
        .get            = spear_cpufreq_get,
        .init           = spear_cpufreq_init,
-       .exit           = spear_cpufreq_exit,
-       .attr           = spear_cpufreq_attr,
+       .exit           = cpufreq_generic_exit,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int spear_cpufreq_driver_init(void)
index f897d510584285bea376474ca6a3198eeef7d74f..25e45f89acac1b550c227c969e9fe9ebf659b077 100644 (file)
@@ -343,9 +343,7 @@ static unsigned int get_cur_freq(unsigned int cpu)
 static int centrino_cpu_init(struct cpufreq_policy *policy)
 {
        struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu);
-       unsigned freq;
        unsigned l, h;
-       int ret;
        int i;
 
        /* Only Intel makes Enhanced Speedstep-capable CPUs */
@@ -373,9 +371,8 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
                return -ENODEV;
        }
 
-       if (centrino_cpu_init_table(policy)) {
+       if (centrino_cpu_init_table(policy))
                return -ENODEV;
-       }
 
        /* Check to see if Enhanced SpeedStep is enabled, and try to
           enable it if not. */
@@ -395,22 +392,11 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
                }
        }
 
-       freq = get_cur_freq(policy->cpu);
        policy->cpuinfo.transition_latency = 10000;
                                                /* 10uS transition latency */
-       policy->cur = freq;
-
-       pr_debug("centrino_cpu_init: cur=%dkHz\n", policy->cur);
 
-       ret = cpufreq_frequency_table_cpuinfo(policy,
+       return cpufreq_table_validate_and_show(policy,
                per_cpu(centrino_model, policy->cpu)->op_points);
-       if (ret)
-               return (ret);
-
-       cpufreq_frequency_table_get_attr(
-               per_cpu(centrino_model, policy->cpu)->op_points, policy->cpu);
-
-       return 0;
 }
 
 static int centrino_cpu_exit(struct cpufreq_policy *policy)
@@ -427,19 +413,6 @@ static int centrino_cpu_exit(struct cpufreq_policy *policy)
        return 0;
 }
 
-/**
- * centrino_verify - verifies a new CPUFreq policy
- * @policy: new policy
- *
- * Limit must be within this model's frequency range at least one
- * border included.
- */
-static int centrino_verify (struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy,
-                       per_cpu(centrino_model, policy->cpu)->op_points);
-}
-
 /**
  * centrino_setpolicy - set a new CPUFreq policy
  * @policy: new policy
@@ -561,20 +534,15 @@ out:
        return retval;
 }
 
-static struct freq_attr* centrino_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver centrino_driver = {
        .name           = "centrino", /* should be speedstep-centrino,
                                         but there's a 16 char limit */
        .init           = centrino_cpu_init,
        .exit           = centrino_cpu_exit,
-       .verify         = centrino_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = centrino_target,
        .get            = get_cur_freq,
-       .attr           = centrino_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 /*
index 5355abb69afc972d88c9f509924d3e779fa0cdac..1a8b01bd0feca15998092d539a274cce543216ad 100644 (file)
@@ -289,18 +289,6 @@ static int speedstep_target(struct cpufreq_policy *policy,
 }
 
 
-/**
- * speedstep_verify - verifies a new CPUFreq policy
- * @policy: new policy
- *
- * Limit must be within speedstep_low_freq and speedstep_high_freq, with
- * at least one border included.
- */
-static int speedstep_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
-}
-
 struct get_freqs {
        struct cpufreq_policy *policy;
        int ret;
@@ -320,8 +308,7 @@ static void get_freqs_on_cpu(void *_get_freqs)
 
 static int speedstep_cpu_init(struct cpufreq_policy *policy)
 {
-       int result;
-       unsigned int policy_cpu, speed;
+       unsigned int policy_cpu;
        struct get_freqs gf;
 
        /* only run on CPU to be set, or on its sibling */
@@ -336,49 +323,18 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
        if (gf.ret)
                return gf.ret;
 
-       /* get current speed setting */
-       speed = speedstep_get(policy_cpu);
-       if (!speed)
-               return -EIO;
-
-       pr_debug("currently at %s speed setting - %i MHz\n",
-               (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency)
-               ? "low" : "high",
-               (speed / 1000));
-
-       /* cpuinfo and default policy values */
-       policy->cur = speed;
-
-       result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
-       if (result)
-               return result;
-
-       cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu);
-
-       return 0;
-}
-
-
-static int speedstep_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_table_validate_and_show(policy, speedstep_freqs);
 }
 
-static struct freq_attr *speedstep_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 
 static struct cpufreq_driver speedstep_driver = {
        .name   = "speedstep-ich",
-       .verify = speedstep_verify,
+       .verify = cpufreq_generic_frequency_table_verify,
        .target = speedstep_target,
        .init   = speedstep_cpu_init,
-       .exit   = speedstep_cpu_exit,
+       .exit   = cpufreq_generic_exit,
        .get    = speedstep_get,
-       .attr   = speedstep_attr,
+       .attr   = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id ss_smi_ids[] = {
index abfba4f731ebdc4212696732a765b56083bc8252..a02b649c9647ef04432a811abb0ade749eb1a823 100644 (file)
@@ -264,23 +264,9 @@ static int speedstep_target(struct cpufreq_policy *policy,
 }
 
 
-/**
- * speedstep_verify - verifies a new CPUFreq policy
- * @policy: new policy
- *
- * Limit must be within speedstep_low_freq and speedstep_high_freq, with
- * at least one border included.
- */
-static int speedstep_verify(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]);
-}
-
-
 static int speedstep_cpu_init(struct cpufreq_policy *policy)
 {
        int result;
-       unsigned int speed, state;
        unsigned int *low, *high;
 
        /* capability check */
@@ -316,32 +302,8 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
                        pr_debug("workaround worked.\n");
        }
 
-       /* get current speed setting */
-       state = speedstep_get_state();
-       speed = speedstep_freqs[state].frequency;
-
-       pr_debug("currently at %s speed setting - %i MHz\n",
-               (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency)
-               ? "low" : "high",
-               (speed / 1000));
-
-       /* cpuinfo and default policy values */
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
-       policy->cur = speed;
-
-       result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
-       if (result)
-               return result;
-
-       cpufreq_frequency_table_get_attr(speedstep_freqs, policy->cpu);
-
-       return 0;
-}
-
-static int speedstep_cpu_exit(struct cpufreq_policy *policy)
-{
-       cpufreq_frequency_table_put_attr(policy->cpu);
-       return 0;
+       return cpufreq_table_validate_and_show(policy, speedstep_freqs);
 }
 
 static unsigned int speedstep_get(unsigned int cpu)
@@ -362,20 +324,15 @@ static int speedstep_resume(struct cpufreq_policy *policy)
        return result;
 }
 
-static struct freq_attr *speedstep_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver speedstep_driver = {
        .name           = "speedstep-smi",
-       .verify         = speedstep_verify,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = speedstep_target,
        .init           = speedstep_cpu_init,
-       .exit           = speedstep_cpu_exit,
+       .exit           = cpufreq_generic_exit,
        .get            = speedstep_get,
        .resume         = speedstep_resume,
-       .attr           = speedstep_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static const struct x86_cpu_id ss_smi_ids[] = {
index a7b876fdc1d8a5b672346233d7f7b7ce0a7c962f..32483ef63d5305c064a97ff5aa1280ed1203ff87 100644 (file)
@@ -51,11 +51,6 @@ static unsigned long target_cpu_speed[NUM_CPUS];
 static DEFINE_MUTEX(tegra_cpu_lock);
 static bool is_suspended;
 
-static int tegra_verify_speed(struct cpufreq_policy *policy)
-{
-       return cpufreq_frequency_table_verify(policy, freq_table);
-}
-
 static unsigned int tegra_getspeed(unsigned int cpu)
 {
        unsigned long rate;
@@ -209,21 +204,23 @@ static struct notifier_block tegra_cpu_pm_notifier = {
 
 static int tegra_cpu_init(struct cpufreq_policy *policy)
 {
+       int ret;
+
        if (policy->cpu >= NUM_CPUS)
                return -EINVAL;
 
        clk_prepare_enable(emc_clk);
        clk_prepare_enable(cpu_clk);
 
-       cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
-       policy->cur = tegra_getspeed(policy->cpu);
-       target_cpu_speed[policy->cpu] = policy->cur;
+       target_cpu_speed[policy->cpu] = tegra_getspeed(policy->cpu);
 
        /* FIXME: what's the actual transition time? */
-       policy->cpuinfo.transition_latency = 300 * 1000;
-
-       cpumask_copy(policy->cpus, cpu_possible_mask);
+       ret = cpufreq_generic_init(policy, freq_table, 300 * 1000);
+       if (ret) {
+               clk_disable_unprepare(cpu_clk);
+               clk_disable_unprepare(emc_clk);
+               return ret;
+       }
 
        if (policy->cpu == 0)
                register_pm_notifier(&tegra_cpu_pm_notifier);
@@ -233,24 +230,20 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
 
 static int tegra_cpu_exit(struct cpufreq_policy *policy)
 {
-       cpufreq_frequency_table_cpuinfo(policy, freq_table);
+       cpufreq_frequency_table_put_attr(policy->cpu);
+       clk_disable_unprepare(cpu_clk);
        clk_disable_unprepare(emc_clk);
        return 0;
 }
 
-static struct freq_attr *tegra_cpufreq_attr[] = {
-       &cpufreq_freq_attr_scaling_available_freqs,
-       NULL,
-};
-
 static struct cpufreq_driver tegra_cpufreq_driver = {
-       .verify         = tegra_verify_speed,
+       .verify         = cpufreq_generic_frequency_table_verify,
        .target         = tegra_target,
        .get            = tegra_getspeed,
        .init           = tegra_cpu_init,
        .exit           = tegra_cpu_exit,
        .name           = "tegra",
-       .attr           = tegra_cpufreq_attr,
+       .attr           = cpufreq_generic_attr,
 };
 
 static int __init tegra_cpufreq_init(void)
index b225f04d8ae5c55bcfee26f644812d3d1100cc04..653ae2955b555ad63607d84a4ebeb27be205e644 100644 (file)
@@ -29,9 +29,7 @@ static int ucv2_verify_speed(struct cpufreq_policy *policy)
        if (policy->cpu)
                return -EINVAL;
 
-       cpufreq_verify_within_limits(policy,
-                       policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
-
+       cpufreq_verify_within_cpu_limits(policy);
        return 0;
 }
 
@@ -68,7 +66,6 @@ static int __init ucv2_cpu_init(struct cpufreq_policy *policy)
 {
        if (policy->cpu != 0)
                return -EINVAL;
-       policy->cur = ucv2_getspeed(0);
        policy->min = policy->cpuinfo.min_freq = 250000;
        policy->max = policy->cpuinfo.max_freq = 1000000;
        policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
index 8e366032230893dc35c0d03f55138a20e0a33f07..f23bd75426cdfcac5da246ef6f23adef0a15b0da 100644 (file)
@@ -2,6 +2,17 @@
 # ARM CPU Idle drivers
 #
 
+config ARM_BIG_LITTLE_CPUIDLE
+       bool "Support for ARM big.LITTLE processors"
+       depends on ARCH_VEXPRESS_TC2_PM
+       select ARM_CPU_SUSPEND
+       select CPU_IDLE_MULTIPLE_DRIVERS
+       help
+         Select this option to enable CPU idle driver for big.LITTLE based
+         ARM systems. Driver manages CPUs coordination through MCPM and
+         define different C-states for little and big cores through the
+         multiple CPU idle drivers infrastructure.
+
 config ARM_HIGHBANK_CPUIDLE
        bool "CPU Idle Driver for Calxeda processors"
        depends on ARCH_HIGHBANK
@@ -27,13 +38,9 @@ config ARM_U8500_CPUIDLE
        help
          Select this to enable cpuidle for ST-E u8500 processors
 
-config CPU_IDLE_BIG_LITTLE
-       bool "Support for ARM big.LITTLE processors"
-       depends on ARCH_VEXPRESS_TC2_PM
-       select ARM_CPU_SUSPEND
-       select CPU_IDLE_MULTIPLE_DRIVERS
+config ARM_AT91_CPUIDLE
+       bool "Cpu Idle Driver for the AT91 processors"
+       default y
+       depends on ARCH_AT91
        help
-         Select this option to enable CPU idle driver for big.LITTLE based
-         ARM systems. Driver manages CPUs coordination through MCPM and
-         define different C-states for little and big cores through the
-         multiple CPU idle drivers infrastructure.
+         Select this to enable cpuidle for AT91 processors
index cea5ef58876d8202521545008afb9026565fbe7e..527be28e5c1e4e785032a83027899fdf47103b21 100644 (file)
@@ -7,8 +7,9 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
 
 ##################################################################################
 # ARM SoC drivers
+obj-$(CONFIG_ARM_BIG_LITTLE_CPUIDLE)   += cpuidle-big_little.o
 obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE)     += cpuidle-calxeda.o
 obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE)     += cpuidle-kirkwood.o
 obj-$(CONFIG_ARM_ZYNQ_CPUIDLE)         += cpuidle-zynq.o
 obj-$(CONFIG_ARM_U8500_CPUIDLE)         += cpuidle-ux500.o
-obj-$(CONFIG_CPU_IDLE_BIG_LITTLE)      += cpuidle-big_little.o
+obj-$(CONFIG_ARM_AT91_CPUIDLE)          += cpuidle-at91.o
similarity index 79%
rename from arch/arm/mach-at91/cpuidle.c
rename to drivers/cpuidle/cpuidle-at91.c
index 4ec6a6d9b9be7e7e0e853ad17a57f2ae2d7b986b..a0774370c6bc41acd38c410beedd55e4592558d0 100644 (file)
 #include <linux/export.h>
 #include <asm/proc-fns.h>
 #include <asm/cpuidle.h>
-#include <mach/cpu.h>
-
-#include "pm.h"
 
 #define AT91_MAX_STATES        2
 
+static void (*at91_standby)(void);
+
 /* Actual code that puts the SoC in different idle states */
 static int at91_enter_idle(struct cpuidle_device *dev,
                        struct cpuidle_driver *drv,
                               int index)
 {
-       if (cpu_is_at91rm9200())
-               at91rm9200_standby();
-       else if (cpu_is_at91sam9g45())
-               at91sam9g45_standby();
-       else if (cpu_is_at91sam9263())
-               at91sam9263_standby();
-       else
-               at91sam9_standby();
-
+       at91_standby();
        return index;
 }
 
@@ -60,9 +51,19 @@ static struct cpuidle_driver at91_idle_driver = {
 };
 
 /* Initialize CPU idle by registering the idle states */
-static int __init at91_init_cpuidle(void)
+static int at91_cpuidle_probe(struct platform_device *dev)
 {
+       at91_standby = (void *)(dev->dev.platform_data);
+       
        return cpuidle_register(&at91_idle_driver, NULL);
 }
 
-device_initcall(at91_init_cpuidle);
+static struct platform_driver at91_cpuidle_driver = {
+       .driver = {
+               .name = "cpuidle-at91",
+               .owner = THIS_MODULE,
+       },
+       .probe = at91_cpuidle_probe,
+};
+
+module_platform_driver(at91_cpuidle_driver);
index e0564652af35114f2d73227b68bf781758975629..5e35804b1a952393dd84b20aacaf96442eac4d62 100644 (file)
@@ -111,7 +111,7 @@ static struct cpuidle_driver ux500_idle_driver = {
        .state_count = 2,
 };
 
-static int __init dbx500_cpuidle_probe(struct platform_device *pdev)
+static int dbx500_cpuidle_probe(struct platform_device *pdev)
 {
        /* Configure wake up reasons */
        prcmu_enable_wakeups(PRCMU_WAKEUP(ARM) | PRCMU_WAKEUP(RTC) |
index 38e03a18359156077e17d8f5b35671de47bf6d8e..aded759280282b08e7fb3e9025f130240b9f6074 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/init.h>
 #include <linux/cpu_pm.h>
 #include <linux/cpuidle.h>
-#include <linux/of.h>
+#include <linux/platform_device.h>
 #include <asm/proc-fns.h>
 #include <asm/cpuidle.h>
 
@@ -70,14 +70,19 @@ static struct cpuidle_driver zynq_idle_driver = {
 };
 
 /* Initialize CPU idle by registering the idle states */
-static int __init zynq_cpuidle_init(void)
+static int zynq_cpuidle_probe(struct platform_device *pdev)
 {
-       if (!of_machine_is_compatible("xlnx,zynq-7000"))
-               return -ENODEV;
-
        pr_info("Xilinx Zynq CpuIdle Driver started\n");
 
        return cpuidle_register(&zynq_idle_driver, NULL);
 }
 
-device_initcall(zynq_cpuidle_init);
+static struct platform_driver zynq_cpuidle_driver = {
+       .driver = {
+               .name = "cpuidle-zynq",
+               .owner = THIS_MODULE,
+       },
+       .probe = zynq_cpuidle_probe,
+};
+
+module_platform_driver(zynq_cpuidle_driver);
index c99c00d35d34f73d7ceca6cbf1e68b163fcc502a..2e23b12c350b8759c71ae1d5a438c9aaf2089166 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/devfreq.h>
 #include <linux/workqueue.h>
 #include <linux/platform_device.h>
@@ -902,13 +902,13 @@ static ssize_t available_frequencies_show(struct device *d,
 {
        struct devfreq *df = to_devfreq(d);
        struct device *dev = df->dev.parent;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        ssize_t count = 0;
        unsigned long freq = 0;
 
        rcu_read_lock();
        do {
-               opp = opp_find_freq_ceil(dev, &freq);
+               opp = dev_pm_opp_find_freq_ceil(dev, &freq);
                if (IS_ERR(opp))
                        break;
 
@@ -1029,25 +1029,26 @@ module_exit(devfreq_exit);
  * under the locked area. The pointer returned must be used prior to unlocking
  * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
-struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
-                                   u32 flags)
+struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
+                                          unsigned long *freq,
+                                          u32 flags)
 {
-       struct opp *opp;
+       struct dev_pm_opp *opp;
 
        if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) {
                /* The freq is an upper bound. opp should be lower */
-               opp = opp_find_freq_floor(dev, freq);
+               opp = dev_pm_opp_find_freq_floor(dev, freq);
 
                /* If not available, use the closest opp */
                if (opp == ERR_PTR(-ERANGE))
-                       opp = opp_find_freq_ceil(dev, freq);
+                       opp = dev_pm_opp_find_freq_ceil(dev, freq);
        } else {
                /* The freq is an lower bound. opp should be higher */
-               opp = opp_find_freq_ceil(dev, freq);
+               opp = dev_pm_opp_find_freq_ceil(dev, freq);
 
                /* If not available, use the closest opp */
                if (opp == ERR_PTR(-ERANGE))
-                       opp = opp_find_freq_floor(dev, freq);
+                       opp = dev_pm_opp_find_freq_floor(dev, freq);
        }
 
        return opp;
@@ -1066,7 +1067,7 @@ int devfreq_register_opp_notifier(struct device *dev, struct devfreq *devfreq)
        int ret = 0;
 
        rcu_read_lock();
-       nh = opp_get_notifier(dev);
+       nh = dev_pm_opp_get_notifier(dev);
        if (IS_ERR(nh))
                ret = PTR_ERR(nh);
        rcu_read_unlock();
@@ -1092,7 +1093,7 @@ int devfreq_unregister_opp_notifier(struct device *dev, struct devfreq *devfreq)
        int ret = 0;
 
        rcu_read_lock();
-       nh = opp_get_notifier(dev);
+       nh = dev_pm_opp_get_notifier(dev);
        if (IS_ERR(nh))
                ret = PTR_ERR(nh);
        rcu_read_unlock();
index c5f86d8caca34c6a7a3ea2341da5c242ddf41c83..cede6f71cd63feb5afebde508199b9be9a507778 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/suspend.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 #include <linux/devfreq.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
@@ -639,7 +639,7 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
        struct platform_device *pdev = container_of(dev, struct platform_device,
                                                    dev);
        struct busfreq_data *data = platform_get_drvdata(pdev);
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long freq;
        unsigned long old_freq = data->curr_oppinfo.rate;
        struct busfreq_opp_info new_oppinfo;
@@ -650,8 +650,8 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq,
                rcu_read_unlock();
                return PTR_ERR(opp);
        }
-       new_oppinfo.rate = opp_get_freq(opp);
-       new_oppinfo.volt = opp_get_voltage(opp);
+       new_oppinfo.rate = dev_pm_opp_get_freq(opp);
+       new_oppinfo.volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
        freq = new_oppinfo.rate;
 
@@ -873,7 +873,7 @@ static int exynos4210_init_tables(struct busfreq_data *data)
                exynos4210_busclk_table[i].volt = exynos4210_asv_volt[mgrp][i];
 
        for (i = LV_0; i < EX4210_LV_NUM; i++) {
-               err = opp_add(data->dev, exynos4210_busclk_table[i].clk,
+               err = dev_pm_opp_add(data->dev, exynos4210_busclk_table[i].clk,
                              exynos4210_busclk_table[i].volt);
                if (err) {
                        dev_err(data->dev, "Cannot add opp entries.\n");
@@ -940,7 +940,7 @@ static int exynos4x12_init_tables(struct busfreq_data *data)
        }
 
        for (i = 0; i < EX4x12_LV_NUM; i++) {
-               ret = opp_add(data->dev, exynos4x12_mifclk_table[i].clk,
+               ret = dev_pm_opp_add(data->dev, exynos4x12_mifclk_table[i].clk,
                              exynos4x12_mifclk_table[i].volt);
                if (ret) {
                        dev_err(data->dev, "Fail to add opp entries.\n");
@@ -956,7 +956,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
 {
        struct busfreq_data *data = container_of(this, struct busfreq_data,
                                                 pm_notifier);
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        struct busfreq_opp_info new_oppinfo;
        unsigned long maxfreq = ULONG_MAX;
        int err = 0;
@@ -969,7 +969,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
                data->disabled = true;
 
                rcu_read_lock();
-               opp = opp_find_freq_floor(data->dev, &maxfreq);
+               opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
                if (IS_ERR(opp)) {
                        rcu_read_unlock();
                        dev_err(data->dev, "%s: unable to find a min freq\n",
@@ -977,8 +977,8 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this,
                        mutex_unlock(&data->lock);
                        return PTR_ERR(opp);
                }
-               new_oppinfo.rate = opp_get_freq(opp);
-               new_oppinfo.volt = opp_get_voltage(opp);
+               new_oppinfo.rate = dev_pm_opp_get_freq(opp);
+               new_oppinfo.volt = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
 
                err = exynos4_bus_setvolt(data, &new_oppinfo,
@@ -1020,7 +1020,7 @@ unlock:
 static int exynos4_busfreq_probe(struct platform_device *pdev)
 {
        struct busfreq_data *data;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        struct device *dev = &pdev->dev;
        int err = 0;
 
@@ -1065,15 +1065,16 @@ static int exynos4_busfreq_probe(struct platform_device *pdev)
        }
 
        rcu_read_lock();
-       opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq);
+       opp = dev_pm_opp_find_freq_floor(dev,
+                                        &exynos4_devfreq_profile.initial_freq);
        if (IS_ERR(opp)) {
                rcu_read_unlock();
                dev_err(dev, "Invalid initial frequency %lu kHz.\n",
                        exynos4_devfreq_profile.initial_freq);
                return PTR_ERR(opp);
        }
-       data->curr_oppinfo.rate = opp_get_freq(opp);
-       data->curr_oppinfo.volt = opp_get_voltage(opp);
+       data->curr_oppinfo.rate = dev_pm_opp_get_freq(opp);
+       data->curr_oppinfo.volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
 
        platform_set_drvdata(pdev, data);
index 574b16b59be5df13352ebee4f952e592b9a6f52f..9e3752dac99e5115bbe2df05694c06e8ca7fe2a8 100644 (file)
 #include <linux/module.h>
 #include <linux/devfreq.h>
 #include <linux/io.h>
-#include <linux/opp.h>
 #include <linux/slab.h>
 #include <linux/suspend.h>
-#include <linux/opp.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
+#include <linux/pm_opp.h>
 #include <linux/pm_qos.h>
 #include <linux/regulator/consumer.h>
 #include <linux/of_address.h>
@@ -132,7 +131,7 @@ static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
        struct platform_device *pdev = container_of(dev, struct platform_device,
                                                    dev);
        struct busfreq_data_int *data = platform_get_drvdata(pdev);
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long old_freq, freq;
        unsigned long volt;
 
@@ -144,8 +143,8 @@ static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
                return PTR_ERR(opp);
        }
 
-       freq = opp_get_freq(opp);
-       volt = opp_get_voltage(opp);
+       freq = dev_pm_opp_get_freq(opp);
+       volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
 
        old_freq = data->curr_freq;
@@ -246,7 +245,7 @@ static int exynos5250_init_int_tables(struct busfreq_data_int *data)
        int i, err = 0;
 
        for (i = LV_0; i < _LV_END; i++) {
-               err = opp_add(data->dev, exynos5_int_opp_table[i].clk,
+               err = dev_pm_opp_add(data->dev, exynos5_int_opp_table[i].clk,
                                exynos5_int_opp_table[i].volt);
                if (err) {
                        dev_err(data->dev, "Cannot add opp entries.\n");
@@ -262,7 +261,7 @@ static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
 {
        struct busfreq_data_int *data = container_of(this,
                                        struct busfreq_data_int, pm_notifier);
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        unsigned long maxfreq = ULONG_MAX;
        unsigned long freq;
        unsigned long volt;
@@ -276,14 +275,14 @@ static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
                data->disabled = true;
 
                rcu_read_lock();
-               opp = opp_find_freq_floor(data->dev, &maxfreq);
+               opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
                if (IS_ERR(opp)) {
                        rcu_read_unlock();
                        err = PTR_ERR(opp);
                        goto unlock;
                }
-               freq = opp_get_freq(opp);
-               volt = opp_get_voltage(opp);
+               freq = dev_pm_opp_get_freq(opp);
+               volt = dev_pm_opp_get_voltage(opp);
                rcu_read_unlock();
 
                err = exynos5_int_setvolt(data, volt);
@@ -316,7 +315,7 @@ unlock:
 static int exynos5_busfreq_int_probe(struct platform_device *pdev)
 {
        struct busfreq_data_int *data;
-       struct opp *opp;
+       struct dev_pm_opp *opp;
        struct device *dev = &pdev->dev;
        struct device_node *np;
        unsigned long initial_freq;
@@ -368,7 +367,7 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
        }
 
        rcu_read_lock();
-       opp = opp_find_freq_floor(dev,
+       opp = dev_pm_opp_find_freq_floor(dev,
                        &exynos5_devfreq_int_profile.initial_freq);
        if (IS_ERR(opp)) {
                rcu_read_unlock();
@@ -377,8 +376,8 @@ static int exynos5_busfreq_int_probe(struct platform_device *pdev)
                err = PTR_ERR(opp);
                goto err_opp_add;
        }
-       initial_freq = opp_get_freq(opp);
-       initial_volt = opp_get_voltage(opp);
+       initial_freq = dev_pm_opp_get_freq(opp);
+       initial_volt = dev_pm_opp_get_voltage(opp);
        rcu_read_unlock();
        data->curr_freq = initial_freq;
 
index 5c1ef2b3ef188253e0031b0ceec2e65239220df5..f2beb728ed8f32cf8eeb1b6135fcf652796ab294 100644 (file)
@@ -73,15 +73,8 @@ static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
 static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data)
 {
        struct acpi_gpio_evt_pin *evt_pin = data;
-       struct acpi_object_list args;
-       union acpi_object arg;
 
-       arg.type = ACPI_TYPE_INTEGER;
-       arg.integer.value = evt_pin->pin;
-       args.count = 1;
-       args.pointer = &arg;
-
-       acpi_evaluate_object(evt_pin->evt_handle, NULL, &args, NULL);
+       acpi_execute_simple_method(evt_pin->evt_handle, NULL, evt_pin->pin);
 
        return IRQ_HANDLED;
 }
index 57fe1ae32a0d69d767eb7d698cfeab2ead4231e2..43959edd4291193a538449c1d4f75bba8d30ea8a 100644 (file)
@@ -193,16 +193,14 @@ out:
 
 static bool intel_dsm_pci_probe(struct pci_dev *pdev)
 {
-       acpi_handle dhandle, intel_handle;
-       acpi_status status;
+       acpi_handle dhandle;
        int ret;
 
        dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
        if (!dhandle)
                return false;
 
-       status = acpi_get_handle(dhandle, "_DSM", &intel_handle);
-       if (ACPI_FAILURE(status)) {
+       if (!acpi_has_method(dhandle, "_DSM")) {
                DRM_DEBUG_KMS("no _DSM method for intel device\n");
                return false;
        }
index dd7d2e18271940ea3e9f6d9a90b09140c767e73e..cfbeee607b3ace2eb0c602919033b570580f2625 100644 (file)
@@ -253,18 +253,15 @@ static struct vga_switcheroo_handler nouveau_dsm_handler = {
 
 static int nouveau_dsm_pci_probe(struct pci_dev *pdev)
 {
-       acpi_handle dhandle, nvidia_handle;
-       acpi_status status;
+       acpi_handle dhandle;
        int retval = 0;
 
        dhandle = DEVICE_ACPI_HANDLE(&pdev->dev);
        if (!dhandle)
                return false;
 
-       status = acpi_get_handle(dhandle, "_DSM", &nvidia_handle);
-       if (ACPI_FAILURE(status)) {
+       if (!acpi_has_method(dhandle, "_DSM"))
                return false;
-       }
 
        if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER))
                retval |= NOUVEAU_DSM_HAS_MUX;
index c1336193b04ba3deb92c3edf2468551f3f6933a9..fd7ce374f812ead7960b72a5d00ac3b5908ab221 100644 (file)
@@ -854,10 +854,10 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
                0xF7, 0xF6, 0xDF, 0x3C, 0x67, 0x42, 0x55, 0x45,
                0xAD, 0x05, 0xB3, 0x0A, 0x3D, 0x89, 0x38, 0xDE,
        };
-       struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object params[4], *obj;
+       union acpi_object params[4];
        struct acpi_object_list input;
        struct acpi_device *adev;
+       unsigned long long value;
        acpi_handle handle;
 
        handle = ACPI_HANDLE(&client->dev);
@@ -878,22 +878,14 @@ static int i2c_hid_acpi_pdata(struct i2c_client *client,
        params[3].package.count = 0;
        params[3].package.elements = NULL;
 
-       if (ACPI_FAILURE(acpi_evaluate_object(handle, "_DSM", &input, &buf))) {
+       if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_DSM", &input,
+                                                               &value))) {
                dev_err(&client->dev, "device _DSM execution failed\n");
                return -ENODEV;
        }
 
-       obj = (union acpi_object *)buf.pointer;
-       if (obj->type != ACPI_TYPE_INTEGER) {
-               dev_err(&client->dev, "device _DSM returned invalid type: %d\n",
-                       obj->type);
-               kfree(buf.pointer);
-               return -EINVAL;
-       }
-
-       pdata->hid_descriptor_address = obj->integer.value;
+       pdata->hid_descriptor_address = value;
 
-       kfree(buf.pointer);
        return 0;
 }
 
index 3be58f89ac774962db749fcdea5c032e28edce0d..75ba8608383e4b1d26e65a389f099f7028e7b733 100644 (file)
@@ -254,10 +254,12 @@ static int i2c_device_probe(struct device *dev)
                                        client->flags & I2C_CLIENT_WAKE);
        dev_dbg(dev, "probe\n");
 
+       acpi_dev_pm_attach(&client->dev, true);
        status = driver->probe(client, i2c_match_id(driver->id_table, client));
        if (status) {
                client->driver = NULL;
                i2c_set_clientdata(client, NULL);
+               acpi_dev_pm_detach(&client->dev, true);
        }
        return status;
 }
@@ -283,6 +285,7 @@ static int i2c_device_remove(struct device *dev)
                client->driver = NULL;
                i2c_set_clientdata(client, NULL);
        }
+       acpi_dev_pm_detach(&client->dev, true);
        return status;
 }
 
@@ -1111,8 +1114,10 @@ static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
        if (ret < 0 || !info.addr)
                return AE_OK;
 
+       adev->power.flags.ignore_parent = true;
        strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
        if (!i2c_new_device(adapter, &info)) {
+               adev->power.flags.ignore_parent = false;
                dev_err(&adapter->dev,
                        "failed to add I2C device %s from ACPI\n",
                        dev_name(&adev->dev));
index fa6964d8681a0d126fcf7c4845896b3f06298f8f..33e599ebbe96ccb024239964b5938f1bad5aff15 100644 (file)
@@ -123,7 +123,7 @@ static struct cpuidle_state *cpuidle_state_table;
  * which is also the index into the MWAIT hint array.
  * Thus C0 is a dummy.
  */
-static struct cpuidle_state nehalem_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state nehalem_cstates[] __initdata = {
        {
                .name = "C1-NHM",
                .desc = "MWAIT 0x00",
@@ -156,7 +156,7 @@ static struct cpuidle_state nehalem_cstates[CPUIDLE_STATE_MAX] = {
                .enter = NULL }
 };
 
-static struct cpuidle_state snb_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state snb_cstates[] __initdata = {
        {
                .name = "C1-SNB",
                .desc = "MWAIT 0x00",
@@ -196,7 +196,7 @@ static struct cpuidle_state snb_cstates[CPUIDLE_STATE_MAX] = {
                .enter = NULL }
 };
 
-static struct cpuidle_state ivb_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state ivb_cstates[] __initdata = {
        {
                .name = "C1-IVB",
                .desc = "MWAIT 0x00",
@@ -236,7 +236,7 @@ static struct cpuidle_state ivb_cstates[CPUIDLE_STATE_MAX] = {
                .enter = NULL }
 };
 
-static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state hsw_cstates[] __initdata = {
        {
                .name = "C1-HSW",
                .desc = "MWAIT 0x00",
@@ -297,7 +297,7 @@ static struct cpuidle_state hsw_cstates[CPUIDLE_STATE_MAX] = {
                .enter = NULL }
 };
 
-static struct cpuidle_state atom_cstates[CPUIDLE_STATE_MAX] = {
+static struct cpuidle_state atom_cstates[] __initdata = {
        {
                .name = "C1E-ATM",
                .desc = "MWAIT 0x00",
@@ -490,7 +490,7 @@ MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids);
 /*
  * intel_idle_probe()
  */
-static int intel_idle_probe(void)
+static int __init intel_idle_probe(void)
 {
        unsigned int eax, ebx, ecx;
        const struct x86_cpu_id *id;
@@ -558,7 +558,7 @@ static void intel_idle_cpuidle_devices_uninit(void)
  * intel_idle_cpuidle_driver_init()
  * allocate, initialize cpuidle_states
  */
-static int intel_idle_cpuidle_driver_init(void)
+static int __init intel_idle_cpuidle_driver_init(void)
 {
        int cstate;
        struct cpuidle_driver *drv = &intel_idle_driver;
@@ -628,7 +628,7 @@ static int intel_idle_cpu_init(int cpu)
                int num_substates, mwait_hint, mwait_cstate, mwait_substate;
 
                if (cpuidle_state_table[cstate].enter == NULL)
-                       continue;
+                       break;
 
                if (cstate + 1 > max_cstate) {
                        printk(PREFIX "max_cstate %d reached\n", max_cstate);
index 2a47e82821dacff72dd227950a6c3de828755053..5440131cd4eecff5fb74a3d9bbcd63d00f4d1ad1 100644 (file)
@@ -411,13 +411,10 @@ EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);
 static int pcihp_is_ejectable(acpi_handle handle)
 {
        acpi_status status;
-       acpi_handle tmp;
        unsigned long long removable;
-       status = acpi_get_handle(handle, "_ADR", &tmp);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(handle, "_ADR"))
                return 0;
-       status = acpi_get_handle(handle, "_EJ0", &tmp);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(handle, "_EJ0"))
                return 1;
        status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable);
        if (ACPI_SUCCESS(status) && removable)
index b0299e6d9a3f2d1359f78454eb67e399ea6d3eb1..dfd1f59de729c6293416d789fb6f665dc09bf701 100644 (file)
@@ -181,7 +181,6 @@ static bool acpi_pci_power_manageable(struct pci_dev *dev)
 static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
 {
        acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
-       acpi_handle tmp;
        static const u8 state_conv[] = {
                [PCI_D0] = ACPI_STATE_D0,
                [PCI_D1] = ACPI_STATE_D1,
@@ -192,7 +191,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
        int error = -EINVAL;
 
        /* If the ACPI device has _EJ0, ignore the device */
-       if (!handle || ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
+       if (!handle || acpi_has_method(handle, "_EJ0"))
                return -ENODEV;
 
        switch (state) {
index a6afd4108beb0592c15604efa9f779180d5349ef..aefcc32e563479d2b22404fdd75ceb7072423d16 100644 (file)
@@ -190,16 +190,10 @@ struct eeepc_laptop {
  */
 static int write_acpi_int(acpi_handle handle, const char *method, int val)
 {
-       struct acpi_object_list params;
-       union acpi_object in_obj;
        acpi_status status;
 
-       params.count = 1;
-       params.pointer = &in_obj;
-       in_obj.type = ACPI_TYPE_INTEGER;
-       in_obj.integer.value = val;
+       status = acpi_execute_simple_method(handle, (char *)method, val);
 
-       status = acpi_evaluate_object(handle, (char *)method, &params, NULL);
        return (status == AE_OK ? 0 : -1);
 }
 
index 52b8a97efde150f52d393b4e7a6c0be9360bc9ef..9d30d69aa78f24a3bbb1caa71f797f9c520bbc5c 100644 (file)
@@ -219,8 +219,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
        { .type = ACPI_TYPE_INTEGER }
        };
        struct acpi_object_list arg_list = { 4, &params[0] };
-       struct acpi_buffer output;
-       union acpi_object out_obj;
+       unsigned long long value;
        acpi_handle handle = NULL;
 
        status = acpi_get_handle(fujitsu_hotkey->acpi_handle, "FUNC", &handle);
@@ -235,10 +234,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
        params[2].integer.value = arg1;
        params[3].integer.value = arg2;
 
-       output.length = sizeof(out_obj);
-       output.pointer = &out_obj;
-
-       status = acpi_evaluate_object(handle, NULL, &arg_list, &output);
+       status = acpi_evaluate_integer(handle, NULL, &arg_list, &value);
        if (ACPI_FAILURE(status)) {
                vdbg_printk(FUJLAPTOP_DBG_WARN,
                        "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) call failed\n",
@@ -246,18 +242,10 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2)
                return -ENODEV;
        }
 
-       if (out_obj.type != ACPI_TYPE_INTEGER) {
-               vdbg_printk(FUJLAPTOP_DBG_WARN,
-                       "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) did not "
-                       "return an integer\n",
-                       cmd, arg0, arg1, arg2);
-               return -ENODEV;
-       }
-
        vdbg_printk(FUJLAPTOP_DBG_TRACE,
                "FUNC 0x%x (args 0x%x, 0x%x, 0x%x) returned 0x%x\n",
-                       cmd, arg0, arg1, arg2, (int)out_obj.integer.value);
-       return out_obj.integer.value;
+                       cmd, arg0, arg1, arg2, (int)value);
+       return value;
 }
 
 #if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
@@ -317,8 +305,6 @@ static enum led_brightness kblamps_get(struct led_classdev *cdev)
 static int set_lcd_level(int level)
 {
        acpi_status status = AE_OK;
-       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list arg_list = { 1, &arg0 };
        acpi_handle handle = NULL;
 
        vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBLL [%d]\n",
@@ -333,9 +319,8 @@ static int set_lcd_level(int level)
                return -ENODEV;
        }
 
-       arg0.integer.value = level;
 
-       status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+       status = acpi_execute_simple_method(handle, NULL, level);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -345,8 +330,6 @@ static int set_lcd_level(int level)
 static int set_lcd_level_alt(int level)
 {
        acpi_status status = AE_OK;
-       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list arg_list = { 1, &arg0 };
        acpi_handle handle = NULL;
 
        vdbg_printk(FUJLAPTOP_DBG_TRACE, "set lcd level via SBL2 [%d]\n",
@@ -361,9 +344,7 @@ static int set_lcd_level_alt(int level)
                return -ENODEV;
        }
 
-       arg0.integer.value = level;
-
-       status = acpi_evaluate_object(handle, NULL, &arg_list, NULL);
+       status = acpi_execute_simple_method(handle, NULL, level);
        if (ACPI_FAILURE(status))
                return -ENODEV;
 
@@ -586,11 +567,10 @@ static struct platform_driver fujitsupf_driver = {
 
 static void dmi_check_cb_common(const struct dmi_system_id *id)
 {
-       acpi_handle handle;
        pr_info("Identified laptop model '%s'\n", id->ident);
        if (use_alt_lcd_levels == -1) {
-               if (ACPI_SUCCESS(acpi_get_handle(NULL,
-                               "\\_SB.PCI0.LPCB.FJEX.SBL2", &handle)))
+               if (acpi_has_method(NULL,
+                               "\\_SB.PCI0.LPCB.FJEX.SBL2"))
                        use_alt_lcd_levels = 1;
                else
                        use_alt_lcd_levels = 0;
@@ -653,7 +633,6 @@ static struct dmi_system_id fujitsu_dmi_table[] = {
 
 static int acpi_fujitsu_add(struct acpi_device *device)
 {
-       acpi_handle handle;
        int result = 0;
        int state = 0;
        struct input_dev *input;
@@ -702,8 +681,7 @@ static int acpi_fujitsu_add(struct acpi_device *device)
 
        fujitsu->dev = device;
 
-       if (ACPI_SUCCESS
-           (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) {
+       if (acpi_has_method(device->handle, METHOD_NAME__INI)) {
                vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
                if (ACPI_FAILURE
                    (acpi_evaluate_object
@@ -803,7 +781,6 @@ static void acpi_fujitsu_notify(struct acpi_device *device, u32 event)
 
 static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
 {
-       acpi_handle handle;
        int result = 0;
        int state = 0;
        struct input_dev *input;
@@ -866,8 +843,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
 
        fujitsu_hotkey->dev = device;
 
-       if (ACPI_SUCCESS
-           (acpi_get_handle(device->handle, METHOD_NAME__INI, &handle))) {
+       if (acpi_has_method(device->handle, METHOD_NAME__INI)) {
                vdbg_printk(FUJLAPTOP_DBG_INFO, "Invoking _INI\n");
                if (ACPI_FAILURE
                    (acpi_evaluate_object
index 89c4519d48ac80d2a54f42ceabf7a48b792e871c..6788acc22ab97f01b410240eef0a5b2082c98550 100644 (file)
@@ -72,8 +72,15 @@ enum {
        VPCCMD_W_BL_POWER = 0x33,
 };
 
+struct ideapad_rfk_priv {
+       int dev;
+       struct ideapad_private *priv;
+};
+
 struct ideapad_private {
+       struct acpi_device *adev;
        struct rfkill *rfk[IDEAPAD_RFKILL_DEV_NUM];
+       struct ideapad_rfk_priv rfk_priv[IDEAPAD_RFKILL_DEV_NUM];
        struct platform_device *platform_device;
        struct input_dev *inputdev;
        struct backlight_device *blightdev;
@@ -81,8 +88,6 @@ struct ideapad_private {
        unsigned long cfg;
 };
 
-static acpi_handle ideapad_handle;
-static struct ideapad_private *ideapad_priv;
 static bool no_bt_rfkill;
 module_param(no_bt_rfkill, bool, 0444);
 MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
@@ -200,34 +205,38 @@ static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
  */
 static int debugfs_status_show(struct seq_file *s, void *data)
 {
+       struct ideapad_private *priv = s->private;
        unsigned long value;
 
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &value))
+       if (!priv)
+               return -EINVAL;
+
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &value))
                seq_printf(s, "Backlight max:\t%lu\n", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_BL, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL, &value))
                seq_printf(s, "Backlight now:\t%lu\n", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &value))
                seq_printf(s, "BL power value:\t%s\n", value ? "On" : "Off");
        seq_printf(s, "=====================\n");
 
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_RF, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_RF, &value))
                seq_printf(s, "Radio status:\t%s(%lu)\n",
                           value ? "On" : "Off", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_WIFI, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_WIFI, &value))
                seq_printf(s, "Wifi status:\t%s(%lu)\n",
                           value ? "On" : "Off", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_BT, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_BT, &value))
                seq_printf(s, "BT status:\t%s(%lu)\n",
                           value ? "On" : "Off", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_3G, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_3G, &value))
                seq_printf(s, "3G status:\t%s(%lu)\n",
                           value ? "On" : "Off", value);
        seq_printf(s, "=====================\n");
 
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_TOUCHPAD, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value))
                seq_printf(s, "Touchpad status:%s(%lu)\n",
                           value ? "On" : "Off", value);
-       if (!read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &value))
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value))
                seq_printf(s, "Camera status:\t%s(%lu)\n",
                           value ? "On" : "Off", value);
 
@@ -236,7 +245,7 @@ static int debugfs_status_show(struct seq_file *s, void *data)
 
 static int debugfs_status_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, debugfs_status_show, NULL);
+       return single_open(file, debugfs_status_show, inode->i_private);
 }
 
 static const struct file_operations debugfs_status_fops = {
@@ -249,21 +258,23 @@ static const struct file_operations debugfs_status_fops = {
 
 static int debugfs_cfg_show(struct seq_file *s, void *data)
 {
-       if (!ideapad_priv) {
+       struct ideapad_private *priv = s->private;
+
+       if (!priv) {
                seq_printf(s, "cfg: N/A\n");
        } else {
                seq_printf(s, "cfg: 0x%.8lX\n\nCapability: ",
-                          ideapad_priv->cfg);
-               if (test_bit(CFG_BT_BIT, &ideapad_priv->cfg))
+                          priv->cfg);
+               if (test_bit(CFG_BT_BIT, &priv->cfg))
                        seq_printf(s, "Bluetooth ");
-               if (test_bit(CFG_3G_BIT, &ideapad_priv->cfg))
+               if (test_bit(CFG_3G_BIT, &priv->cfg))
                        seq_printf(s, "3G ");
-               if (test_bit(CFG_WIFI_BIT, &ideapad_priv->cfg))
+               if (test_bit(CFG_WIFI_BIT, &priv->cfg))
                        seq_printf(s, "Wireless ");
-               if (test_bit(CFG_CAMERA_BIT, &ideapad_priv->cfg))
+               if (test_bit(CFG_CAMERA_BIT, &priv->cfg))
                        seq_printf(s, "Camera ");
                seq_printf(s, "\nGraphic: ");
-               switch ((ideapad_priv->cfg)&0x700) {
+               switch ((priv->cfg)&0x700) {
                case 0x100:
                        seq_printf(s, "Intel");
                        break;
@@ -287,7 +298,7 @@ static int debugfs_cfg_show(struct seq_file *s, void *data)
 
 static int debugfs_cfg_open(struct inode *inode, struct file *file)
 {
-       return single_open(file, debugfs_cfg_show, NULL);
+       return single_open(file, debugfs_cfg_show, inode->i_private);
 }
 
 static const struct file_operations debugfs_cfg_fops = {
@@ -308,14 +319,14 @@ static int ideapad_debugfs_init(struct ideapad_private *priv)
                goto errout;
        }
 
-       node = debugfs_create_file("cfg", S_IRUGO, priv->debug, NULL,
+       node = debugfs_create_file("cfg", S_IRUGO, priv->debug, priv,
                                   &debugfs_cfg_fops);
        if (!node) {
                pr_err("failed to create cfg in debugfs");
                goto errout;
        }
 
-       node = debugfs_create_file("status", S_IRUGO, priv->debug, NULL,
+       node = debugfs_create_file("status", S_IRUGO, priv->debug, priv,
                                   &debugfs_status_fops);
        if (!node) {
                pr_err("failed to create status in debugfs");
@@ -342,8 +353,9 @@ static ssize_t show_ideapad_cam(struct device *dev,
                                char *buf)
 {
        unsigned long result;
+       struct ideapad_private *priv = dev_get_drvdata(dev);
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_CAMERA, &result))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &result))
                return sprintf(buf, "-1\n");
        return sprintf(buf, "%lu\n", result);
 }
@@ -353,12 +365,13 @@ static ssize_t store_ideapad_cam(struct device *dev,
                                 const char *buf, size_t count)
 {
        int ret, state;
+       struct ideapad_private *priv = dev_get_drvdata(dev);
 
        if (!count)
                return 0;
        if (sscanf(buf, "%i", &state) != 1)
                return -EINVAL;
-       ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state);
+       ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_CAMERA, state);
        if (ret < 0)
                return -EIO;
        return count;
@@ -371,8 +384,9 @@ static ssize_t show_ideapad_fan(struct device *dev,
                                char *buf)
 {
        unsigned long result;
+       struct ideapad_private *priv = dev_get_drvdata(dev);
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_FAN, &result))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &result))
                return sprintf(buf, "-1\n");
        return sprintf(buf, "%lu\n", result);
 }
@@ -382,6 +396,7 @@ static ssize_t store_ideapad_fan(struct device *dev,
                                 const char *buf, size_t count)
 {
        int ret, state;
+       struct ideapad_private *priv = dev_get_drvdata(dev);
 
        if (!count)
                return 0;
@@ -389,7 +404,7 @@ static ssize_t store_ideapad_fan(struct device *dev,
                return -EINVAL;
        if (state < 0 || state > 4 || state == 3)
                return -EINVAL;
-       ret = write_ec_cmd(ideapad_handle, VPCCMD_W_FAN, state);
+       ret = write_ec_cmd(priv->adev->handle, VPCCMD_W_FAN, state);
        if (ret < 0)
                return -EIO;
        return count;
@@ -415,7 +430,8 @@ static umode_t ideapad_is_visible(struct kobject *kobj,
                supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
        else if (attr == &dev_attr_fan_mode.attr) {
                unsigned long value;
-               supported = !read_ec_data(ideapad_handle, VPCCMD_R_FAN, &value);
+               supported = !read_ec_data(priv->adev->handle, VPCCMD_R_FAN,
+                                         &value);
        } else
                supported = true;
 
@@ -445,9 +461,9 @@ const struct ideapad_rfk_data ideapad_rfk_data[] = {
 
 static int ideapad_rfk_set(void *data, bool blocked)
 {
-       unsigned long opcode = (unsigned long)data;
+       struct ideapad_rfk_priv *priv = data;
 
-       return write_ec_cmd(ideapad_handle, opcode, !blocked);
+       return write_ec_cmd(priv->priv->adev->handle, priv->dev, !blocked);
 }
 
 static struct rfkill_ops ideapad_rfk_ops = {
@@ -459,7 +475,7 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv)
        unsigned long hw_blocked;
        int i;
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_RF, &hw_blocked))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_RF, &hw_blocked))
                return;
        hw_blocked = !hw_blocked;
 
@@ -468,27 +484,30 @@ static void ideapad_sync_rfk_state(struct ideapad_private *priv)
                        rfkill_set_hw_state(priv->rfk[i], hw_blocked);
 }
 
-static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
+static int ideapad_register_rfkill(struct ideapad_private *priv, int dev)
 {
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
        int ret;
        unsigned long sw_blocked;
 
        if (no_bt_rfkill &&
            (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
                /* Force to enable bluetooth when no_bt_rfkill=1 */
-               write_ec_cmd(ideapad_handle,
+               write_ec_cmd(priv->adev->handle,
                             ideapad_rfk_data[dev].opcode, 1);
                return 0;
        }
-
-       priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adevice->dev,
-                                     ideapad_rfk_data[dev].type, &ideapad_rfk_ops,
-                                     (void *)(long)dev);
+       priv->rfk_priv[dev].dev = dev;
+       priv->rfk_priv[dev].priv = priv;
+
+       priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name,
+                                     &priv->platform_device->dev,
+                                     ideapad_rfk_data[dev].type,
+                                     &ideapad_rfk_ops,
+                                     &priv->rfk_priv[dev]);
        if (!priv->rfk[dev])
                return -ENOMEM;
 
-       if (read_ec_data(ideapad_handle, ideapad_rfk_data[dev].opcode-1,
+       if (read_ec_data(priv->adev->handle, ideapad_rfk_data[dev].opcode-1,
                         &sw_blocked)) {
                rfkill_init_sw_state(priv->rfk[dev], 0);
        } else {
@@ -504,10 +523,8 @@ static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
        return 0;
 }
 
-static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
+static void ideapad_unregister_rfkill(struct ideapad_private *priv, int dev)
 {
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
-
        if (!priv->rfk[dev])
                return;
 
@@ -518,37 +535,16 @@ static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
 /*
  * Platform device
  */
-static int ideapad_platform_init(struct ideapad_private *priv)
+static int ideapad_sysfs_init(struct ideapad_private *priv)
 {
-       int result;
-
-       priv->platform_device = platform_device_alloc("ideapad", -1);
-       if (!priv->platform_device)
-               return -ENOMEM;
-       platform_set_drvdata(priv->platform_device, priv);
-
-       result = platform_device_add(priv->platform_device);
-       if (result)
-               goto fail_platform_device;
-
-       result = sysfs_create_group(&priv->platform_device->dev.kobj,
+       return sysfs_create_group(&priv->platform_device->dev.kobj,
                                    &ideapad_attribute_group);
-       if (result)
-               goto fail_sysfs;
-       return 0;
-
-fail_sysfs:
-       platform_device_del(priv->platform_device);
-fail_platform_device:
-       platform_device_put(priv->platform_device);
-       return result;
 }
 
-static void ideapad_platform_exit(struct ideapad_private *priv)
+static void ideapad_sysfs_exit(struct ideapad_private *priv)
 {
        sysfs_remove_group(&priv->platform_device->dev.kobj,
                           &ideapad_attribute_group);
-       platform_device_unregister(priv->platform_device);
 }
 
 /*
@@ -623,7 +619,7 @@ static void ideapad_input_novokey(struct ideapad_private *priv)
 {
        unsigned long long_pressed;
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_NOVO, &long_pressed))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_NOVO, &long_pressed))
                return;
        if (long_pressed)
                ideapad_input_report(priv, 17);
@@ -635,7 +631,7 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv)
 {
        unsigned long bit, value;
 
-       read_ec_data(ideapad_handle, VPCCMD_R_SPECIAL_BUTTONS, &value);
+       read_ec_data(priv->adev->handle, VPCCMD_R_SPECIAL_BUTTONS, &value);
 
        for (bit = 0; bit < 16; bit++) {
                if (test_bit(bit, &value)) {
@@ -662,19 +658,28 @@ static void ideapad_check_special_buttons(struct ideapad_private *priv)
  */
 static int ideapad_backlight_get_brightness(struct backlight_device *blightdev)
 {
+       struct ideapad_private *priv = bl_get_data(blightdev);
        unsigned long now;
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
+       if (!priv)
+               return -EINVAL;
+
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
                return -EIO;
        return now;
 }
 
 static int ideapad_backlight_update_status(struct backlight_device *blightdev)
 {
-       if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL,
+       struct ideapad_private *priv = bl_get_data(blightdev);
+
+       if (!priv)
+               return -EINVAL;
+
+       if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL,
                         blightdev->props.brightness))
                return -EIO;
-       if (write_ec_cmd(ideapad_handle, VPCCMD_W_BL_POWER,
+       if (write_ec_cmd(priv->adev->handle, VPCCMD_W_BL_POWER,
                         blightdev->props.power == FB_BLANK_POWERDOWN ? 0 : 1))
                return -EIO;
 
@@ -692,11 +697,11 @@ static int ideapad_backlight_init(struct ideapad_private *priv)
        struct backlight_properties props;
        unsigned long max, now, power;
 
-       if (read_ec_data(ideapad_handle, VPCCMD_R_BL_MAX, &max))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_MAX, &max))
                return -EIO;
-       if (read_ec_data(ideapad_handle, VPCCMD_R_BL, &now))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now))
                return -EIO;
-       if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
                return -EIO;
 
        memset(&props, 0, sizeof(struct backlight_properties));
@@ -734,7 +739,7 @@ static void ideapad_backlight_notify_power(struct ideapad_private *priv)
 
        if (!blightdev)
                return;
-       if (read_ec_data(ideapad_handle, VPCCMD_R_BL_POWER, &power))
+       if (read_ec_data(priv->adev->handle, VPCCMD_R_BL_POWER, &power))
                return;
        blightdev->props.power = power ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
 }
@@ -745,7 +750,7 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
 
        /* if we control brightness via acpi video driver */
        if (priv->blightdev == NULL) {
-               read_ec_data(ideapad_handle, VPCCMD_R_BL, &now);
+               read_ec_data(priv->adev->handle, VPCCMD_R_BL, &now);
                return;
        }
 
@@ -755,19 +760,12 @@ static void ideapad_backlight_notify_brightness(struct ideapad_private *priv)
 /*
  * module init/exit
  */
-static const struct acpi_device_id ideapad_device_ids[] = {
-       { "VPC2004", 0},
-       { "", 0},
-};
-MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
-
-static void ideapad_sync_touchpad_state(struct acpi_device *adevice)
+static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
 {
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
        unsigned long value;
 
        /* Without reading from EC touchpad LED doesn't switch state */
-       if (!read_ec_data(adevice->handle, VPCCMD_R_TOUCHPAD, &value)) {
+       if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
                /* Some IdeaPads don't really turn off touchpad - they only
                 * switch the LED state. We (de)activate KBC AUX port to turn
                 * touchpad off and on. We send KEY_TOUCHPAD_OFF and
@@ -779,26 +777,77 @@ static void ideapad_sync_touchpad_state(struct acpi_device *adevice)
        }
 }
 
-static int ideapad_acpi_add(struct acpi_device *adevice)
+static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
+{
+       struct ideapad_private *priv = data;
+       unsigned long vpc1, vpc2, vpc_bit;
+
+       if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
+               return;
+       if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
+               return;
+
+       vpc1 = (vpc2 << 8) | vpc1;
+       for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
+               if (test_bit(vpc_bit, &vpc1)) {
+                       switch (vpc_bit) {
+                       case 9:
+                               ideapad_sync_rfk_state(priv);
+                               break;
+                       case 13:
+                       case 11:
+                       case 7:
+                       case 6:
+                               ideapad_input_report(priv, vpc_bit);
+                               break;
+                       case 5:
+                               ideapad_sync_touchpad_state(priv);
+                               break;
+                       case 4:
+                               ideapad_backlight_notify_brightness(priv);
+                               break;
+                       case 3:
+                               ideapad_input_novokey(priv);
+                               break;
+                       case 2:
+                               ideapad_backlight_notify_power(priv);
+                               break;
+                       case 0:
+                               ideapad_check_special_buttons(priv);
+                               break;
+                       default:
+                               pr_info("Unknown event: %lu\n", vpc_bit);
+                       }
+               }
+       }
+}
+
+static int ideapad_acpi_add(struct platform_device *pdev)
 {
        int ret, i;
        int cfg;
        struct ideapad_private *priv;
+       struct acpi_device *adev;
+
+       ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
+       if (ret)
+               return -ENODEV;
 
-       if (read_method_int(adevice->handle, "_CFG", &cfg))
+       if (read_method_int(adev->handle, "_CFG", &cfg))
                return -ENODEV;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
-       dev_set_drvdata(&adevice->dev, priv);
-       ideapad_priv = priv;
-       ideapad_handle = adevice->handle;
+
+       dev_set_drvdata(&pdev->dev, priv);
        priv->cfg = cfg;
+       priv->adev = adev;
+       priv->platform_device = pdev;
 
-       ret = ideapad_platform_init(priv);
+       ret = ideapad_sysfs_init(priv);
        if (ret)
-               goto platform_failed;
+               goto sysfs_failed;
 
        ret = ideapad_debugfs_init(priv);
        if (ret)
@@ -810,117 +859,92 @@ static int ideapad_acpi_add(struct acpi_device *adevice)
 
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++) {
                if (test_bit(ideapad_rfk_data[i].cfgbit, &priv->cfg))
-                       ideapad_register_rfkill(adevice, i);
+                       ideapad_register_rfkill(priv, i);
                else
                        priv->rfk[i] = NULL;
        }
        ideapad_sync_rfk_state(priv);
-       ideapad_sync_touchpad_state(adevice);
+       ideapad_sync_touchpad_state(priv);
 
        if (!acpi_video_backlight_support()) {
                ret = ideapad_backlight_init(priv);
                if (ret && ret != -ENODEV)
                        goto backlight_failed;
        }
+       ret = acpi_install_notify_handler(adev->handle,
+               ACPI_DEVICE_NOTIFY, ideapad_acpi_notify, priv);
+       if (ret)
+               goto notification_failed;
 
        return 0;
-
+notification_failed:
+       ideapad_backlight_exit(priv);
 backlight_failed:
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
-               ideapad_unregister_rfkill(adevice, i);
+               ideapad_unregister_rfkill(priv, i);
        ideapad_input_exit(priv);
 input_failed:
        ideapad_debugfs_exit(priv);
 debugfs_failed:
-       ideapad_platform_exit(priv);
-platform_failed:
+       ideapad_sysfs_exit(priv);
+sysfs_failed:
        kfree(priv);
        return ret;
 }
 
-static int ideapad_acpi_remove(struct acpi_device *adevice)
+static int ideapad_acpi_remove(struct platform_device *pdev)
 {
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
+       struct ideapad_private *priv = dev_get_drvdata(&pdev->dev);
        int i;
 
+       acpi_remove_notify_handler(priv->adev->handle,
+               ACPI_DEVICE_NOTIFY, ideapad_acpi_notify);
        ideapad_backlight_exit(priv);
        for (i = 0; i < IDEAPAD_RFKILL_DEV_NUM; i++)
-               ideapad_unregister_rfkill(adevice, i);
+               ideapad_unregister_rfkill(priv, i);
        ideapad_input_exit(priv);
        ideapad_debugfs_exit(priv);
-       ideapad_platform_exit(priv);
-       dev_set_drvdata(&adevice->dev, NULL);
+       ideapad_sysfs_exit(priv);
+       dev_set_drvdata(&pdev->dev, NULL);
        kfree(priv);
 
        return 0;
 }
 
-static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
+#ifdef CONFIG_PM_SLEEP
+static int ideapad_acpi_resume(struct device *device)
 {
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
-       acpi_handle handle = adevice->handle;
-       unsigned long vpc1, vpc2, vpc_bit;
-
-       if (read_ec_data(handle, VPCCMD_R_VPC1, &vpc1))
-               return;
-       if (read_ec_data(handle, VPCCMD_R_VPC2, &vpc2))
-               return;
+       struct ideapad_private *priv;
 
-       vpc1 = (vpc2 << 8) | vpc1;
-       for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
-               if (test_bit(vpc_bit, &vpc1)) {
-                       switch (vpc_bit) {
-                       case 9:
-                               ideapad_sync_rfk_state(priv);
-                               break;
-                       case 13:
-                       case 11:
-                       case 7:
-                       case 6:
-                               ideapad_input_report(priv, vpc_bit);
-                               break;
-                       case 5:
-                               ideapad_sync_touchpad_state(adevice);
-                               break;
-                       case 4:
-                               ideapad_backlight_notify_brightness(priv);
-                               break;
-                       case 3:
-                               ideapad_input_novokey(priv);
-                               break;
-                       case 2:
-                               ideapad_backlight_notify_power(priv);
-                               break;
-                       case 0:
-                               ideapad_check_special_buttons(priv);
-                               break;
-                       default:
-                               pr_info("Unknown event: %lu\n", vpc_bit);
-                       }
-               }
-       }
-}
+       if (!device)
+               return -EINVAL;
+       priv = dev_get_drvdata(device);
 
-static int ideapad_acpi_resume(struct device *device)
-{
-       ideapad_sync_rfk_state(ideapad_priv);
-       ideapad_sync_touchpad_state(to_acpi_device(device));
+       ideapad_sync_rfk_state(priv);
+       ideapad_sync_touchpad_state(priv);
        return 0;
 }
-
+#endif
 static SIMPLE_DEV_PM_OPS(ideapad_pm, NULL, ideapad_acpi_resume);
 
-static struct acpi_driver ideapad_acpi_driver = {
-       .name = "ideapad_acpi",
-       .class = "IdeaPad",
-       .ids = ideapad_device_ids,
-       .ops.add = ideapad_acpi_add,
-       .ops.remove = ideapad_acpi_remove,
-       .ops.notify = ideapad_acpi_notify,
-       .drv.pm = &ideapad_pm,
-       .owner = THIS_MODULE,
+static const struct acpi_device_id ideapad_device_ids[] = {
+       { "VPC2004", 0},
+       { "", 0},
 };
-module_acpi_driver(ideapad_acpi_driver);
+MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
+
+static struct platform_driver ideapad_acpi_driver = {
+       .probe = ideapad_acpi_add,
+       .remove = ideapad_acpi_remove,
+       .driver = {
+               .name   = "ideapad_acpi",
+               .owner  = THIS_MODULE,
+               .pm     = &ideapad_pm,
+               .acpi_match_table = ACPI_PTR(ideapad_device_ids),
+       },
+};
+
+module_platform_driver(ideapad_acpi_driver);
 
 MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
 MODULE_DESCRIPTION("IdeaPad ACPI Extras");
index 41b740cb28bca8743ea282bbf2fb5639a2f4266c..a2083a9e5662d660fd95cbb297815aa0570c8268 100644 (file)
@@ -29,24 +29,16 @@ static ssize_t irst_show_wakeup_events(struct device *dev,
                                       char *buf)
 {
        struct acpi_device *acpi;
-       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *result;
+       unsigned long long value;
        acpi_status status;
 
        acpi = to_acpi_device(dev);
 
-       status = acpi_evaluate_object(acpi->handle, "GFFS", NULL, &output);
+       status = acpi_evaluate_integer(acpi->handle, "GFFS", NULL, &value);
        if (!ACPI_SUCCESS(status))
                return -EINVAL;
 
-       result = output.pointer;
-
-       if (result->type != ACPI_TYPE_INTEGER) {
-               kfree(result);
-               return -EINVAL;
-       }
-
-       return sprintf(buf, "%lld\n", result->integer.value);
+       return sprintf(buf, "%lld\n", value);
 }
 
 static ssize_t irst_store_wakeup_events(struct device *dev,
@@ -54,8 +46,6 @@ static ssize_t irst_store_wakeup_events(struct device *dev,
                                        const char *buf, size_t count)
 {
        struct acpi_device *acpi;
-       struct acpi_object_list input;
-       union acpi_object param;
        acpi_status status;
        unsigned long value;
        int error;
@@ -67,13 +57,7 @@ static ssize_t irst_store_wakeup_events(struct device *dev,
        if (error)
                return error;
 
-       param.type = ACPI_TYPE_INTEGER;
-       param.integer.value = value;
-
-       input.count = 1;
-       input.pointer = &param;
-
-       status = acpi_evaluate_object(acpi->handle, "SFFS", &input, NULL);
+       status = acpi_execute_simple_method(acpi->handle, "SFFS", value);
 
        if (!ACPI_SUCCESS(status))
                return -EINVAL;
@@ -91,24 +75,16 @@ static ssize_t irst_show_wakeup_time(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
        struct acpi_device *acpi;
-       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *result;
+       unsigned long long value;
        acpi_status status;
 
        acpi = to_acpi_device(dev);
 
-       status = acpi_evaluate_object(acpi->handle, "GFTV", NULL, &output);
+       status = acpi_evaluate_integer(acpi->handle, "GFTV", NULL, &value);
        if (!ACPI_SUCCESS(status))
                return -EINVAL;
 
-       result = output.pointer;
-
-       if (result->type != ACPI_TYPE_INTEGER) {
-               kfree(result);
-               return -EINVAL;
-       }
-
-       return sprintf(buf, "%lld\n", result->integer.value);
+       return sprintf(buf, "%lld\n", value);
 }
 
 static ssize_t irst_store_wakeup_time(struct device *dev,
@@ -116,8 +92,6 @@ static ssize_t irst_store_wakeup_time(struct device *dev,
                                      const char *buf, size_t count)
 {
        struct acpi_device *acpi;
-       struct acpi_object_list input;
-       union acpi_object param;
        acpi_status status;
        unsigned long value;
        int error;
@@ -129,13 +103,7 @@ static ssize_t irst_store_wakeup_time(struct device *dev,
        if (error)
                return error;
 
-       param.type = ACPI_TYPE_INTEGER;
-       param.integer.value = value;
-
-       input.count = 1;
-       input.pointer = &param;
-
-       status = acpi_evaluate_object(acpi->handle, "SFTV", &input, NULL);
+       status = acpi_execute_simple_method(acpi->handle, "SFTV", value);
 
        if (!ACPI_SUCCESS(status))
                return -EINVAL;
index 52259dcabecb8251edad2a0e0dc7eccb9b174500..1838400dc0360615f799fac64a82b51f7efb9c17 100644 (file)
@@ -25,37 +25,18 @@ MODULE_LICENSE("GPL");
 
 static int smartconnect_acpi_init(struct acpi_device *acpi)
 {
-       struct acpi_object_list input;
-       struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *result;
-       union acpi_object param;
+       unsigned long long value;
        acpi_status status;
 
-       status = acpi_evaluate_object(acpi->handle, "GAOS", NULL, &output);
+       status = acpi_evaluate_integer(acpi->handle, "GAOS", NULL, &value);
        if (!ACPI_SUCCESS(status))
                return -EINVAL;
 
-       result = output.pointer;
-
-       if (result->type != ACPI_TYPE_INTEGER) {
-               kfree(result);
-               return -EINVAL;
-       }
-
-       if (result->integer.value & 0x1) {
-               param.type = ACPI_TYPE_INTEGER;
-               param.integer.value = 0;
-
-               input.count = 1;
-               input.pointer = &param;
-
+       if (value & 0x1) {
                dev_info(&acpi->dev, "Disabling Intel Smart Connect\n");
-               status = acpi_evaluate_object(acpi->handle, "SAOS", &input,
-                                             NULL);
+               status = acpi_execute_simple_method(acpi->handle, "SAOS", 0);
        }
 
-       kfree(result);
-
        return 0;
 }
 
index d6cfc1558c2f1e067d8fd72edb1dc7ce3ecd00e3..11244f8703c402c876fb34b0e107383781661416 100644 (file)
@@ -156,19 +156,15 @@ static struct thermal_cooling_device_ops memory_cooling_ops = {
 static int intel_menlow_memory_add(struct acpi_device *device)
 {
        int result = -ENODEV;
-       acpi_status status = AE_OK;
-       acpi_handle dummy;
        struct thermal_cooling_device *cdev;
 
        if (!device)
                return -EINVAL;
 
-       status = acpi_get_handle(device->handle, MEMORY_GET_BANDWIDTH, &dummy);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(device->handle, MEMORY_GET_BANDWIDTH))
                goto end;
 
-       status = acpi_get_handle(device->handle, MEMORY_SET_BANDWIDTH, &dummy);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(device->handle, MEMORY_SET_BANDWIDTH))
                goto end;
 
        cdev = thermal_cooling_device_register("Memory controller", device,
index d3fd52036fd6e041592c7060c987ed5508684a0e..3b32852d6d2d0582642a7140d305566e5149a552 100644 (file)
@@ -1509,7 +1509,6 @@ static void sony_nc_function_resume(void)
 static int sony_nc_resume(struct device *dev)
 {
        struct sony_nc_value *item;
-       acpi_handle handle;
 
        for (item = sony_nc_values; item->name; item++) {
                int ret;
@@ -1524,15 +1523,13 @@ static int sony_nc_resume(struct device *dev)
                }
        }
 
-       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
-                                        &handle))) {
+       if (acpi_has_method(sony_nc_acpi_handle, "ECON")) {
                int arg = 1;
                if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL))
                        dprintk("ECON Method failed\n");
        }
 
-       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
-                                        &handle)))
+       if (acpi_has_method(sony_nc_acpi_handle, "SN00"))
                sony_nc_function_resume();
 
        return 0;
@@ -2690,7 +2687,6 @@ static void sony_nc_backlight_ng_read_limits(int handle,
 
 static void sony_nc_backlight_setup(void)
 {
-       acpi_handle unused;
        int max_brightness = 0;
        const struct backlight_ops *ops = NULL;
        struct backlight_properties props;
@@ -2725,8 +2721,7 @@ static void sony_nc_backlight_setup(void)
                sony_nc_backlight_ng_read_limits(0x14c, &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))) {
+       } else if (acpi_has_method(sony_nc_acpi_handle, "GBRT")) {
                ops = &sony_backlight_ops;
                max_brightness = SONY_MAX_BRIGHTNESS - 1;
 
@@ -2758,7 +2753,6 @@ static int sony_nc_add(struct acpi_device *device)
 {
        acpi_status status;
        int result = 0;
-       acpi_handle handle;
        struct sony_nc_value *item;
 
        pr_info("%s v%s\n", SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
@@ -2798,15 +2792,13 @@ static int sony_nc_add(struct acpi_device *device)
                goto outplatform;
        }
 
-       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
-                                        &handle))) {
+       if (acpi_has_method(sony_nc_acpi_handle, "ECON")) {
                int arg = 1;
                if (sony_nc_int_call(sony_nc_acpi_handle, "ECON", &arg, NULL))
                        dprintk("ECON Method failed\n");
        }
 
-       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
-                                        &handle))) {
+       if (acpi_has_method(sony_nc_acpi_handle, "SN00")) {
                dprintk("Doing SNC setup\n");
                /* retrieve the available handles */
                result = sony_nc_handles_setup(sony_pf_device);
@@ -2829,9 +2821,8 @@ static int sony_nc_add(struct acpi_device *device)
 
                /* find the available acpiget as described in the DSDT */
                for (; item->acpiget && *item->acpiget; ++item->acpiget) {
-                       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
-                                                        *item->acpiget,
-                                                        &handle))) {
+                       if (acpi_has_method(sony_nc_acpi_handle,
+                                                       *item->acpiget)) {
                                dprintk("Found %s getter: %s\n",
                                                item->name, *item->acpiget);
                                item->devattr.attr.mode |= S_IRUGO;
@@ -2841,9 +2832,8 @@ static int sony_nc_add(struct acpi_device *device)
 
                /* find the available acpiset as described in the DSDT */
                for (; item->acpiset && *item->acpiset; ++item->acpiset) {
-                       if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle,
-                                                        *item->acpiset,
-                                                        &handle))) {
+                       if (acpi_has_method(sony_nc_acpi_handle,
+                                                       *item->acpiset)) {
                                dprintk("Found %s setter: %s\n",
                                                item->name, *item->acpiset);
                                item->devattr.attr.mode |= S_IWUSR;
index 03ca6c139f1a5c9dd0cc821045bad7b5cb409d51..170f2788ee671491725fe6403b96a4b5d6cca9bc 100644 (file)
@@ -700,6 +700,14 @@ static void __init drv_acpi_handle_init(const char *name,
 static acpi_status __init tpacpi_acpi_handle_locate_callback(acpi_handle handle,
                        u32 level, void *context, void **return_value)
 {
+       struct acpi_device *dev;
+       if (!strcmp(context, "video")) {
+               if (acpi_bus_get_device(handle, &dev))
+                       return AE_OK;
+               if (strcmp(ACPI_VIDEO_HID, acpi_device_hid(dev)))
+                       return AE_OK;
+       }
+
        *(acpi_handle *)return_value = handle;
 
        return AE_CTRL_TERMINATE;
@@ -712,10 +720,10 @@ static void __init tpacpi_acpi_handle_locate(const char *name,
        acpi_status status;
        acpi_handle device_found;
 
-       BUG_ON(!name || !hid || !handle);
+       BUG_ON(!name || !handle);
        vdbg_printk(TPACPI_DBG_INIT,
                        "trying to locate ACPI handle for %s, using HID %s\n",
-                       name, hid);
+                       name, hid ? hid : "NULL");
 
        memset(&device_found, 0, sizeof(device_found));
        status = acpi_get_devices(hid, tpacpi_acpi_handle_locate_callback,
@@ -6090,19 +6098,28 @@ static int __init tpacpi_query_bcl_levels(acpi_handle handle)
 {
        struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *obj;
+       struct acpi_device *device, *child;
        int rc;
 
-       if (ACPI_SUCCESS(acpi_evaluate_object(handle, "_BCL", NULL, &buffer))) {
+       if (acpi_bus_get_device(handle, &device))
+               return 0;
+
+       rc = 0;
+       list_for_each_entry(child, &device->children, node) {
+               acpi_status status = acpi_evaluate_object(child->handle, "_BCL",
+                                                         NULL, &buffer);
+               if (ACPI_FAILURE(status))
+                       continue;
+
                obj = (union acpi_object *)buffer.pointer;
                if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) {
                        pr_err("Unknown _BCL data, please report this to %s\n",
-                              TPACPI_MAIL);
+                               TPACPI_MAIL);
                        rc = 0;
                } else {
                        rc = obj->package.count;
                }
-       } else {
-               return 0;
+               break;
        }
 
        kfree(buffer.pointer);
@@ -6118,7 +6135,7 @@ static unsigned int __init tpacpi_check_std_acpi_brightness_support(void)
        acpi_handle video_device;
        int bcl_levels = 0;
 
-       tpacpi_acpi_handle_locate("video", ACPI_VIDEO_HID, &video_device);
+       tpacpi_acpi_handle_locate("video", NULL, &video_device);
        if (video_device)
                bcl_levels = tpacpi_query_bcl_levels(video_device);
 
index 4ab618c63b457e0bbf5a613274ab10a3e76f26cc..67897c8740ba58ea3c93cf54b0a2a3e74a1e3a84 100644 (file)
@@ -80,13 +80,9 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event)
 static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
 {
        acpi_status status;
-       union acpi_object fncx_params[1] = {
-               { .type = ACPI_TYPE_INTEGER }
-       };
-       struct acpi_object_list fncx_arg_list = { 1, &fncx_params[0] };
 
-       fncx_params[0].integer.value = state ? 0x86 : 0x87;
-       status = acpi_evaluate_object(device->handle, "FNCX", &fncx_arg_list, NULL);
+       status = acpi_execute_simple_method(device->handle, "FNCX",
+                                               state ? 0x86 : 0x87);
        if (ACPI_FAILURE(status)) {
                pr_err("Unable to switch FNCX notifications\n");
                return -ENODEV;
index eb3467ea6d860e6c6961f3294922804e0e5776a2..0cfadb65f7c639597abce1d1bcb81ba3a04ff1d3 100644 (file)
@@ -191,16 +191,9 @@ static __inline__ void _set_bit(u32 * word, u32 mask, int value)
 
 static int write_acpi_int(const char *methodName, int val)
 {
-       struct acpi_object_list params;
-       union acpi_object in_objs[1];
        acpi_status status;
 
-       params.count = ARRAY_SIZE(in_objs);
-       params.pointer = in_objs;
-       in_objs[0].type = ACPI_TYPE_INTEGER;
-       in_objs[0].integer.value = val;
-
-       status = acpi_evaluate_object(NULL, (char *)methodName, &params, NULL);
+       status = acpi_execute_simple_method(NULL, (char *)methodName, val);
        return (status == AE_OK) ? 0 : -EIO;
 }
 
@@ -947,21 +940,17 @@ static void toshiba_acpi_hotkey_work(struct work_struct *work)
  */
 static int toshiba_acpi_query_hotkey(struct toshiba_acpi_dev *dev)
 {
-       struct acpi_buffer buf;
-       union acpi_object out_obj;
+       unsigned long long value;
        acpi_status status;
 
-       buf.pointer = &out_obj;
-       buf.length = sizeof(out_obj);
-
-       status = acpi_evaluate_object(dev->acpi_dev->handle, "INFO",
-                                     NULL, &buf);
-       if (ACPI_FAILURE(status) || out_obj.type != ACPI_TYPE_INTEGER) {
+       status = acpi_evaluate_integer(dev->acpi_dev->handle, "INFO",
+                                     NULL, &value);
+       if (ACPI_FAILURE(status)) {
                pr_err("ACPI INFO method execution failed\n");
                return -EIO;
        }
 
-       return out_obj.integer.value;
+       return value;
 }
 
 static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
@@ -981,7 +970,7 @@ static void toshiba_acpi_report_hotkey(struct toshiba_acpi_dev *dev,
 static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
 {
        acpi_status status;
-       acpi_handle ec_handle, handle;
+       acpi_handle ec_handle;
        int error;
        u32 hci_result;
 
@@ -1008,10 +997,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
         */
        status = AE_ERROR;
        ec_handle = ec_get_handle();
-       if (ec_handle)
-               status = acpi_get_handle(ec_handle, "NTFY", &handle);
-
-       if (ACPI_SUCCESS(status)) {
+       if (ec_handle && acpi_has_method(ec_handle, "NTFY")) {
                INIT_WORK(&dev->hotkey_work, toshiba_acpi_hotkey_work);
 
                error = i8042_install_filter(toshiba_acpi_i8042_filter);
@@ -1027,10 +1013,9 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev)
         * Determine hotkey query interface. Prefer using the INFO
         * method when it is available.
         */
-       status = acpi_get_handle(dev->acpi_dev->handle, "INFO", &handle);
-       if (ACPI_SUCCESS(status)) {
+       if (acpi_has_method(dev->acpi_dev->handle, "INFO"))
                dev->info_supported = 1;
-       else {
+       else {
                hci_write1(dev, HCI_SYSTEM_EVENT, 1, &hci_result);
                if (hci_result == HCI_SUCCESS)
                        dev->system_event_supported = 1;
@@ -1155,15 +1140,10 @@ static int toshiba_acpi_remove(struct acpi_device *acpi_dev)
 
 static const char *find_hci_method(acpi_handle handle)
 {
-       acpi_status status;
-       acpi_handle hci_handle;
-
-       status = acpi_get_handle(handle, "GHCI", &hci_handle);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(handle, "GHCI"))
                return "GHCI";
 
-       status = acpi_get_handle(handle, "SPFC", &hci_handle);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(handle, "SPFC"))
                return "SPFC";
 
        return NULL;
index 601ea951224201a87719f0acc7de5ee7e4635649..62e8c221d01ea10a5f105a0a44b2d2d8277d7878 100644 (file)
@@ -252,8 +252,6 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
 {
        struct guid_block *block = NULL;
        char method[5];
-       struct acpi_object_list input;
-       union acpi_object params[1];
        acpi_status status;
        acpi_handle handle;
 
@@ -263,13 +261,9 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
        if (!block)
                return AE_NOT_EXIST;
 
-       input.count = 1;
-       input.pointer = params;
-       params[0].type = ACPI_TYPE_INTEGER;
-       params[0].integer.value = enable;
 
        snprintf(method, 5, "WE%02X", block->notify_id);
-       status = acpi_evaluate_object(handle, method, &input, NULL);
+       status = acpi_execute_simple_method(handle, method, enable);
 
        if (status != AE_OK && status != AE_NOT_FOUND)
                return status;
@@ -353,10 +347,10 @@ struct acpi_buffer *out)
 {
        struct guid_block *block = NULL;
        struct wmi_block *wblock = NULL;
-       acpi_handle handle, wc_handle;
+       acpi_handle handle;
        acpi_status status, wc_status = AE_ERROR;
-       struct acpi_object_list input, wc_input;
-       union acpi_object wc_params[1], wq_params[1];
+       struct acpi_object_list input;
+       union acpi_object wq_params[1];
        char method[5];
        char wc_method[5] = "WC";
 
@@ -386,11 +380,6 @@ struct acpi_buffer *out)
         * enable collection.
         */
        if (block->flags & ACPI_WMI_EXPENSIVE) {
-               wc_input.count = 1;
-               wc_input.pointer = wc_params;
-               wc_params[0].type = ACPI_TYPE_INTEGER;
-               wc_params[0].integer.value = 1;
-
                strncat(wc_method, block->object_id, 2);
 
                /*
@@ -398,10 +387,9 @@ struct acpi_buffer *out)
                 * expensive, but have no corresponding WCxx method. So we
                 * should not fail if this happens.
                 */
-               wc_status = acpi_get_handle(handle, wc_method, &wc_handle);
-               if (ACPI_SUCCESS(wc_status))
-                       wc_status = acpi_evaluate_object(handle, wc_method,
-                               &wc_input, NULL);
+               if (acpi_has_method(handle, wc_method))
+                       wc_status = acpi_execute_simple_method(handle,
+                                                               wc_method, 1);
        }
 
        strcpy(method, "WQ");
@@ -414,9 +402,7 @@ struct acpi_buffer *out)
         * the WQxx method failed - we should disable collection anyway.
         */
        if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {
-               wc_params[0].integer.value = 0;
-               status = acpi_evaluate_object(handle,
-               wc_method, &wc_input, NULL);
+               status = acpi_execute_simple_method(handle, wc_method, 0);
        }
 
        return status;
index 34049b0b4c731e352ae48f62c7fd3edcfc71b517..747826d99059955f8941d592ef2f7734cd38fd08 100644 (file)
@@ -239,8 +239,6 @@ static char *__init pnpacpi_get_id(struct acpi_device *device)
 
 static int __init pnpacpi_add_device(struct acpi_device *device)
 {
-       acpi_handle temp = NULL;
-       acpi_status status;
        struct pnp_dev *dev;
        char *pnpid;
        struct acpi_hardware_id *id;
@@ -253,8 +251,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
         * If a PnPacpi device is not present , the device
         * driver should not be loaded.
         */
-       status = acpi_get_handle(device->handle, "_CRS", &temp);
-       if (ACPI_FAILURE(status))
+       if (!acpi_has_method(device->handle, "_CRS"))
                return 0;
 
        pnpid = pnpacpi_get_id(device);
@@ -271,16 +268,14 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
        dev->data = device;
        /* .enabled means the device can decode the resources */
        dev->active = device->status.enabled;
-       status = acpi_get_handle(device->handle, "_SRS", &temp);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(device->handle, "_SRS"))
                dev->capabilities |= PNP_CONFIGURABLE;
        dev->capabilities |= PNP_READ;
        if (device->flags.dynamic_status && (dev->capabilities & PNP_CONFIGURABLE))
                dev->capabilities |= PNP_WRITE;
        if (device->flags.removable)
                dev->capabilities |= PNP_REMOVABLE;
-       status = acpi_get_handle(device->handle, "_DIS", &temp);
-       if (ACPI_SUCCESS(status))
+       if (acpi_has_method(device->handle, "_DIS"))
                dev->capabilities |= PNP_DISABLE;
 
        if (strlen(acpi_device_name(device)))
diff --git a/drivers/powercap/Kconfig b/drivers/powercap/Kconfig
new file mode 100644 (file)
index 0000000..a7c81b5
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# Generic power capping sysfs interface configuration
+#
+
+menuconfig POWERCAP
+       bool "Generic powercap sysfs driver"
+       help
+         The power capping sysfs interface allows kernel subsystems to expose power
+         capping settings to user space in a consistent way.  Usually, it consists
+         of multiple control types that determine which settings may be exposed and
+         power zones representing parts of the system that can be subject to power
+         capping.
+
+         If you want this code to be compiled in, say Y here.
+
+if POWERCAP
+# Client driver configurations go here.
+config INTEL_RAPL
+       tristate "Intel RAPL Support"
+       depends on X86
+       default n
+       ---help---
+         This enables support for the Intel Running Average Power Limit (RAPL)
+         technology which allows power limits to be enforced and monitored on
+         modern Intel processors (Sandy Bridge and later).
+
+         In RAPL, the platform level settings are divided into domains for
+         fine grained control. These domains include processor package, DRAM
+         controller, CPU core (Power Plance 0), graphics uncore (Power Plane
+         1), etc.
+
+endif
diff --git a/drivers/powercap/Makefile b/drivers/powercap/Makefile
new file mode 100644 (file)
index 0000000..0a21ef3
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_POWERCAP) += powercap_sys.o
+obj-$(CONFIG_INTEL_RAPL) += intel_rapl.o
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
new file mode 100644 (file)
index 0000000..2a786c5
--- /dev/null
@@ -0,0 +1,1395 @@
+/*
+ * Intel Running Average Power Limit (RAPL) Driver
+ * Copyright (c) 2013, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/log2.h>
+#include <linux/bitmap.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/cpu.h>
+#include <linux/powercap.h>
+
+#include <asm/processor.h>
+#include <asm/cpu_device_id.h>
+
+/* bitmasks for RAPL MSRs, used by primitive access functions */
+#define ENERGY_STATUS_MASK      0xffffffff
+
+#define POWER_LIMIT1_MASK       0x7FFF
+#define POWER_LIMIT1_ENABLE     BIT(15)
+#define POWER_LIMIT1_CLAMP      BIT(16)
+
+#define POWER_LIMIT2_MASK       (0x7FFFULL<<32)
+#define POWER_LIMIT2_ENABLE     BIT_ULL(47)
+#define POWER_LIMIT2_CLAMP      BIT_ULL(48)
+#define POWER_PACKAGE_LOCK      BIT_ULL(63)
+#define POWER_PP_LOCK           BIT(31)
+
+#define TIME_WINDOW1_MASK       (0x7FULL<<17)
+#define TIME_WINDOW2_MASK       (0x7FULL<<49)
+
+#define POWER_UNIT_OFFSET      0
+#define POWER_UNIT_MASK                0x0F
+
+#define ENERGY_UNIT_OFFSET     0x08
+#define ENERGY_UNIT_MASK       0x1F00
+
+#define TIME_UNIT_OFFSET       0x10
+#define TIME_UNIT_MASK         0xF0000
+
+#define POWER_INFO_MAX_MASK     (0x7fffULL<<32)
+#define POWER_INFO_MIN_MASK     (0x7fffULL<<16)
+#define POWER_INFO_MAX_TIME_WIN_MASK     (0x3fULL<<48)
+#define POWER_INFO_THERMAL_SPEC_MASK     0x7fff
+
+#define PERF_STATUS_THROTTLE_TIME_MASK 0xffffffff
+#define PP_POLICY_MASK         0x1F
+
+/* Non HW constants */
+#define RAPL_PRIMITIVE_DERIVED       BIT(1) /* not from raw data */
+#define RAPL_PRIMITIVE_DUMMY         BIT(2)
+
+/* scale RAPL units to avoid floating point math inside kernel */
+#define POWER_UNIT_SCALE     (1000000)
+#define ENERGY_UNIT_SCALE    (1000000)
+#define TIME_UNIT_SCALE      (1000000)
+
+#define TIME_WINDOW_MAX_MSEC 40000
+#define TIME_WINDOW_MIN_MSEC 250
+
+enum unit_type {
+       ARBITRARY_UNIT, /* no translation */
+       POWER_UNIT,
+       ENERGY_UNIT,
+       TIME_UNIT,
+};
+
+enum rapl_domain_type {
+       RAPL_DOMAIN_PACKAGE, /* entire package/socket */
+       RAPL_DOMAIN_PP0, /* core power plane */
+       RAPL_DOMAIN_PP1, /* graphics uncore */
+       RAPL_DOMAIN_DRAM,/* DRAM control_type */
+       RAPL_DOMAIN_MAX,
+};
+
+enum rapl_domain_msr_id {
+       RAPL_DOMAIN_MSR_LIMIT,
+       RAPL_DOMAIN_MSR_STATUS,
+       RAPL_DOMAIN_MSR_PERF,
+       RAPL_DOMAIN_MSR_POLICY,
+       RAPL_DOMAIN_MSR_INFO,
+       RAPL_DOMAIN_MSR_MAX,
+};
+
+/* per domain data, some are optional */
+enum rapl_primitives {
+       ENERGY_COUNTER,
+       POWER_LIMIT1,
+       POWER_LIMIT2,
+       FW_LOCK,
+
+       PL1_ENABLE,  /* power limit 1, aka long term */
+       PL1_CLAMP,   /* allow frequency to go below OS request */
+       PL2_ENABLE,  /* power limit 2, aka short term, instantaneous */
+       PL2_CLAMP,
+
+       TIME_WINDOW1, /* long term */
+       TIME_WINDOW2, /* short term */
+       THERMAL_SPEC_POWER,
+       MAX_POWER,
+
+       MIN_POWER,
+       MAX_TIME_WINDOW,
+       THROTTLED_TIME,
+       PRIORITY_LEVEL,
+
+       /* below are not raw primitive data */
+       AVERAGE_POWER,
+       NR_RAPL_PRIMITIVES,
+};
+
+#define NR_RAW_PRIMITIVES (NR_RAPL_PRIMITIVES - 2)
+
+/* Can be expanded to include events, etc.*/
+struct rapl_domain_data {
+       u64 primitives[NR_RAPL_PRIMITIVES];
+       unsigned long timestamp;
+};
+
+
+#define        DOMAIN_STATE_INACTIVE           BIT(0)
+#define        DOMAIN_STATE_POWER_LIMIT_SET    BIT(1)
+#define DOMAIN_STATE_BIOS_LOCKED        BIT(2)
+
+#define NR_POWER_LIMITS (2)
+struct rapl_power_limit {
+       struct powercap_zone_constraint *constraint;
+       int prim_id; /* primitive ID used to enable */
+       struct rapl_domain *domain;
+       const char *name;
+};
+
+static const char pl1_name[] = "long_term";
+static const char pl2_name[] = "short_term";
+
+struct rapl_domain {
+       const char *name;
+       enum rapl_domain_type id;
+       int msrs[RAPL_DOMAIN_MSR_MAX];
+       struct powercap_zone power_zone;
+       struct rapl_domain_data rdd;
+       struct rapl_power_limit rpl[NR_POWER_LIMITS];
+       u64 attr_map; /* track capabilities */
+       unsigned int state;
+       int package_id;
+};
+#define power_zone_to_rapl_domain(_zone) \
+       container_of(_zone, struct rapl_domain, power_zone)
+
+
+/* Each physical package contains multiple domains, these are the common
+ * data across RAPL domains within a package.
+ */
+struct rapl_package {
+       unsigned int id; /* physical package/socket id */
+       unsigned int nr_domains;
+       unsigned long domain_map; /* bit map of active domains */
+       unsigned int power_unit_divisor;
+       unsigned int energy_unit_divisor;
+       unsigned int time_unit_divisor;
+       struct rapl_domain *domains; /* array of domains, sized at runtime */
+       struct powercap_zone *power_zone; /* keep track of parent zone */
+       int nr_cpus; /* active cpus on the package, topology info is lost during
+                     * cpu hotplug. so we have to track ourselves.
+                     */
+       unsigned long power_limit_irq; /* keep track of package power limit
+                                       * notify interrupt enable status.
+                                       */
+       struct list_head plist;
+};
+#define PACKAGE_PLN_INT_SAVED   BIT(0)
+#define MAX_PRIM_NAME (32)
+
+/* per domain data. used to describe individual knobs such that access function
+ * can be consolidated into one instead of many inline functions.
+ */
+struct rapl_primitive_info {
+       const char *name;
+       u64 mask;
+       int shift;
+       enum rapl_domain_msr_id id;
+       enum unit_type unit;
+       u32 flag;
+};
+
+#define PRIMITIVE_INFO_INIT(p, m, s, i, u, f) {        \
+               .name = #p,                     \
+               .mask = m,                      \
+               .shift = s,                     \
+               .id = i,                        \
+               .unit = u,                      \
+               .flag = f                       \
+       }
+
+static void rapl_init_domains(struct rapl_package *rp);
+static int rapl_read_data_raw(struct rapl_domain *rd,
+                       enum rapl_primitives prim,
+                       bool xlate, u64 *data);
+static int rapl_write_data_raw(struct rapl_domain *rd,
+                       enum rapl_primitives prim,
+                       unsigned long long value);
+static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
+                       int to_raw);
+static void package_power_limit_irq_save(int package_id);
+
+static LIST_HEAD(rapl_packages); /* guarded by CPU hotplug lock */
+
+static const char * const rapl_domain_names[] = {
+       "package",
+       "core",
+       "uncore",
+       "dram",
+};
+
+static struct powercap_control_type *control_type; /* PowerCap Controller */
+
+/* caller to ensure CPU hotplug lock is held */
+static struct rapl_package *find_package_by_id(int id)
+{
+       struct rapl_package *rp;
+
+       list_for_each_entry(rp, &rapl_packages, plist) {
+               if (rp->id == id)
+                       return rp;
+       }
+
+       return NULL;
+}
+
+/* caller to ensure CPU hotplug lock is held */
+static int find_active_cpu_on_package(int package_id)
+{
+       int i;
+
+       for_each_online_cpu(i) {
+               if (topology_physical_package_id(i) == package_id)
+                       return i;
+       }
+       /* all CPUs on this package are offline */
+
+       return -ENODEV;
+}
+
+/* caller must hold cpu hotplug lock */
+static void rapl_cleanup_data(void)
+{
+       struct rapl_package *p, *tmp;
+
+       list_for_each_entry_safe(p, tmp, &rapl_packages, plist) {
+               kfree(p->domains);
+               list_del(&p->plist);
+               kfree(p);
+       }
+}
+
+static int get_energy_counter(struct powercap_zone *power_zone, u64 *energy_raw)
+{
+       struct rapl_domain *rd;
+       u64 energy_now;
+
+       /* prevent CPU hotplug, make sure the RAPL domain does not go
+        * away while reading the counter.
+        */
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+
+       if (!rapl_read_data_raw(rd, ENERGY_COUNTER, true, &energy_now)) {
+               *energy_raw = energy_now;
+               put_online_cpus();
+
+               return 0;
+       }
+       put_online_cpus();
+
+       return -EIO;
+}
+
+static int get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy)
+{
+       *energy = rapl_unit_xlate(0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
+       return 0;
+}
+
+static int release_zone(struct powercap_zone *power_zone)
+{
+       struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
+       struct rapl_package *rp;
+
+       /* package zone is the last zone of a package, we can free
+        * memory here since all children has been unregistered.
+        */
+       if (rd->id == RAPL_DOMAIN_PACKAGE) {
+               rp = find_package_by_id(rd->package_id);
+               if (!rp) {
+                       dev_warn(&power_zone->dev, "no package id %s\n",
+                               rd->name);
+                       return -ENODEV;
+               }
+               kfree(rd);
+               rp->domains = NULL;
+       }
+
+       return 0;
+
+}
+
+static int find_nr_power_limit(struct rapl_domain *rd)
+{
+       int i;
+
+       for (i = 0; i < NR_POWER_LIMITS; i++) {
+               if (rd->rpl[i].name == NULL)
+                       break;
+       }
+
+       return i;
+}
+
+static int set_domain_enable(struct powercap_zone *power_zone, bool mode)
+{
+       struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
+       int nr_powerlimit;
+
+       if (rd->state & DOMAIN_STATE_BIOS_LOCKED)
+               return -EACCES;
+       get_online_cpus();
+       nr_powerlimit = find_nr_power_limit(rd);
+       /* here we activate/deactivate the hardware for power limiting */
+       rapl_write_data_raw(rd, PL1_ENABLE, mode);
+       /* always enable clamp such that p-state can go below OS requested
+        * range. power capping priority over guranteed frequency.
+        */
+       rapl_write_data_raw(rd, PL1_CLAMP, mode);
+       /* some domains have pl2 */
+       if (nr_powerlimit > 1) {
+               rapl_write_data_raw(rd, PL2_ENABLE, mode);
+               rapl_write_data_raw(rd, PL2_CLAMP, mode);
+       }
+       put_online_cpus();
+
+       return 0;
+}
+
+static int get_domain_enable(struct powercap_zone *power_zone, bool *mode)
+{
+       struct rapl_domain *rd = power_zone_to_rapl_domain(power_zone);
+       u64 val;
+
+       if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
+               *mode = false;
+               return 0;
+       }
+       get_online_cpus();
+       if (rapl_read_data_raw(rd, PL1_ENABLE, true, &val)) {
+               put_online_cpus();
+               return -EIO;
+       }
+       *mode = val;
+       put_online_cpus();
+
+       return 0;
+}
+
+/* per RAPL domain ops, in the order of rapl_domain_type */
+static struct powercap_zone_ops zone_ops[] = {
+       /* RAPL_DOMAIN_PACKAGE */
+       {
+               .get_energy_uj = get_energy_counter,
+               .get_max_energy_range_uj = get_max_energy_counter,
+               .release = release_zone,
+               .set_enable = set_domain_enable,
+               .get_enable = get_domain_enable,
+       },
+       /* RAPL_DOMAIN_PP0 */
+       {
+               .get_energy_uj = get_energy_counter,
+               .get_max_energy_range_uj = get_max_energy_counter,
+               .release = release_zone,
+               .set_enable = set_domain_enable,
+               .get_enable = get_domain_enable,
+       },
+       /* RAPL_DOMAIN_PP1 */
+       {
+               .get_energy_uj = get_energy_counter,
+               .get_max_energy_range_uj = get_max_energy_counter,
+               .release = release_zone,
+               .set_enable = set_domain_enable,
+               .get_enable = get_domain_enable,
+       },
+       /* RAPL_DOMAIN_DRAM */
+       {
+               .get_energy_uj = get_energy_counter,
+               .get_max_energy_range_uj = get_max_energy_counter,
+               .release = release_zone,
+               .set_enable = set_domain_enable,
+               .get_enable = get_domain_enable,
+       },
+};
+
+static int set_power_limit(struct powercap_zone *power_zone, int id,
+                       u64 power_limit)
+{
+       struct rapl_domain *rd;
+       struct rapl_package *rp;
+       int ret = 0;
+
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+       rp = find_package_by_id(rd->package_id);
+       if (!rp) {
+               ret = -ENODEV;
+               goto set_exit;
+       }
+
+       if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
+               dev_warn(&power_zone->dev, "%s locked by BIOS, monitoring only\n",
+                       rd->name);
+               ret = -EACCES;
+               goto set_exit;
+       }
+
+       switch (rd->rpl[id].prim_id) {
+       case PL1_ENABLE:
+               rapl_write_data_raw(rd, POWER_LIMIT1, power_limit);
+               break;
+       case PL2_ENABLE:
+               rapl_write_data_raw(rd, POWER_LIMIT2, power_limit);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       if (!ret)
+               package_power_limit_irq_save(rd->package_id);
+set_exit:
+       put_online_cpus();
+       return ret;
+}
+
+static int get_current_power_limit(struct powercap_zone *power_zone, int id,
+                                       u64 *data)
+{
+       struct rapl_domain *rd;
+       u64 val;
+       int prim;
+       int ret = 0;
+
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+       switch (rd->rpl[id].prim_id) {
+       case PL1_ENABLE:
+               prim = POWER_LIMIT1;
+               break;
+       case PL2_ENABLE:
+               prim = POWER_LIMIT2;
+               break;
+       default:
+               put_online_cpus();
+               return -EINVAL;
+       }
+       if (rapl_read_data_raw(rd, prim, true, &val))
+               ret = -EIO;
+       else
+               *data = val;
+
+       put_online_cpus();
+
+       return ret;
+}
+
+static int set_time_window(struct powercap_zone *power_zone, int id,
+                                                               u64 window)
+{
+       struct rapl_domain *rd;
+       int ret = 0;
+
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+       switch (rd->rpl[id].prim_id) {
+       case PL1_ENABLE:
+               rapl_write_data_raw(rd, TIME_WINDOW1, window);
+               break;
+       case PL2_ENABLE:
+               rapl_write_data_raw(rd, TIME_WINDOW2, window);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       put_online_cpus();
+       return ret;
+}
+
+static int get_time_window(struct powercap_zone *power_zone, int id, u64 *data)
+{
+       struct rapl_domain *rd;
+       u64 val;
+       int ret = 0;
+
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+       switch (rd->rpl[id].prim_id) {
+       case PL1_ENABLE:
+               ret = rapl_read_data_raw(rd, TIME_WINDOW1, true, &val);
+               break;
+       case PL2_ENABLE:
+               ret = rapl_read_data_raw(rd, TIME_WINDOW2, true, &val);
+               break;
+       default:
+               put_online_cpus();
+               return -EINVAL;
+       }
+       if (!ret)
+               *data = val;
+       put_online_cpus();
+
+       return ret;
+}
+
+static const char *get_constraint_name(struct powercap_zone *power_zone, int id)
+{
+       struct rapl_power_limit *rpl;
+       struct rapl_domain *rd;
+
+       rd = power_zone_to_rapl_domain(power_zone);
+       rpl = (struct rapl_power_limit *) &rd->rpl[id];
+
+       return rpl->name;
+}
+
+
+static int get_max_power(struct powercap_zone *power_zone, int id,
+                                       u64 *data)
+{
+       struct rapl_domain *rd;
+       u64 val;
+       int prim;
+       int ret = 0;
+
+       get_online_cpus();
+       rd = power_zone_to_rapl_domain(power_zone);
+       switch (rd->rpl[id].prim_id) {
+       case PL1_ENABLE:
+               prim = THERMAL_SPEC_POWER;
+               break;
+       case PL2_ENABLE:
+               prim = MAX_POWER;
+               break;
+       default:
+               put_online_cpus();
+               return -EINVAL;
+       }
+       if (rapl_read_data_raw(rd, prim, true, &val))
+               ret = -EIO;
+       else
+               *data = val;
+
+       put_online_cpus();
+
+       return ret;
+}
+
+static struct powercap_zone_constraint_ops constraint_ops = {
+       .set_power_limit_uw = set_power_limit,
+       .get_power_limit_uw = get_current_power_limit,
+       .set_time_window_us = set_time_window,
+       .get_time_window_us = get_time_window,
+       .get_max_power_uw = get_max_power,
+       .get_name = get_constraint_name,
+};
+
+/* called after domain detection and package level data are set */
+static void rapl_init_domains(struct rapl_package *rp)
+{
+       int i;
+       struct rapl_domain *rd = rp->domains;
+
+       for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
+               unsigned int mask = rp->domain_map & (1 << i);
+               switch (mask) {
+               case BIT(RAPL_DOMAIN_PACKAGE):
+                       rd->name = rapl_domain_names[RAPL_DOMAIN_PACKAGE];
+                       rd->id = RAPL_DOMAIN_PACKAGE;
+                       rd->msrs[0] = MSR_PKG_POWER_LIMIT;
+                       rd->msrs[1] = MSR_PKG_ENERGY_STATUS;
+                       rd->msrs[2] = MSR_PKG_PERF_STATUS;
+                       rd->msrs[3] = 0;
+                       rd->msrs[4] = MSR_PKG_POWER_INFO;
+                       rd->rpl[0].prim_id = PL1_ENABLE;
+                       rd->rpl[0].name = pl1_name;
+                       rd->rpl[1].prim_id = PL2_ENABLE;
+                       rd->rpl[1].name = pl2_name;
+                       break;
+               case BIT(RAPL_DOMAIN_PP0):
+                       rd->name = rapl_domain_names[RAPL_DOMAIN_PP0];
+                       rd->id = RAPL_DOMAIN_PP0;
+                       rd->msrs[0] = MSR_PP0_POWER_LIMIT;
+                       rd->msrs[1] = MSR_PP0_ENERGY_STATUS;
+                       rd->msrs[2] = 0;
+                       rd->msrs[3] = MSR_PP0_POLICY;
+                       rd->msrs[4] = 0;
+                       rd->rpl[0].prim_id = PL1_ENABLE;
+                       rd->rpl[0].name = pl1_name;
+                       break;
+               case BIT(RAPL_DOMAIN_PP1):
+                       rd->name = rapl_domain_names[RAPL_DOMAIN_PP1];
+                       rd->id = RAPL_DOMAIN_PP1;
+                       rd->msrs[0] = MSR_PP1_POWER_LIMIT;
+                       rd->msrs[1] = MSR_PP1_ENERGY_STATUS;
+                       rd->msrs[2] = 0;
+                       rd->msrs[3] = MSR_PP1_POLICY;
+                       rd->msrs[4] = 0;
+                       rd->rpl[0].prim_id = PL1_ENABLE;
+                       rd->rpl[0].name = pl1_name;
+                       break;
+               case BIT(RAPL_DOMAIN_DRAM):
+                       rd->name = rapl_domain_names[RAPL_DOMAIN_DRAM];
+                       rd->id = RAPL_DOMAIN_DRAM;
+                       rd->msrs[0] = MSR_DRAM_POWER_LIMIT;
+                       rd->msrs[1] = MSR_DRAM_ENERGY_STATUS;
+                       rd->msrs[2] = MSR_DRAM_PERF_STATUS;
+                       rd->msrs[3] = 0;
+                       rd->msrs[4] = MSR_DRAM_POWER_INFO;
+                       rd->rpl[0].prim_id = PL1_ENABLE;
+                       rd->rpl[0].name = pl1_name;
+                       break;
+               }
+               if (mask) {
+                       rd->package_id = rp->id;
+                       rd++;
+               }
+       }
+}
+
+static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
+                       int to_raw)
+{
+       u64 divisor = 1;
+       int scale = 1; /* scale to user friendly data without floating point */
+       u64 f, y; /* fraction and exp. used for time unit */
+       struct rapl_package *rp;
+
+       rp = find_package_by_id(package);
+       if (!rp)
+               return value;
+
+       switch (type) {
+       case POWER_UNIT:
+               divisor = rp->power_unit_divisor;
+               scale = POWER_UNIT_SCALE;
+               break;
+       case ENERGY_UNIT:
+               scale = ENERGY_UNIT_SCALE;
+               divisor = rp->energy_unit_divisor;
+               break;
+       case TIME_UNIT:
+               divisor = rp->time_unit_divisor;
+               scale = TIME_UNIT_SCALE;
+               /* special processing based on 2^Y*(1+F)/4 = val/divisor, refer
+                * to Intel Software Developer's manual Vol. 3a, CH 14.7.4.
+                */
+               if (!to_raw) {
+                       f = (value & 0x60) >> 5;
+                       y = value & 0x1f;
+                       value = (1 << y) * (4 + f) * scale / 4;
+                       return div64_u64(value, divisor);
+               } else {
+                       do_div(value, scale);
+                       value *= divisor;
+                       y = ilog2(value);
+                       f = div64_u64(4 * (value - (1 << y)), 1 << y);
+                       value = (y & 0x1f) | ((f & 0x3) << 5);
+                       return value;
+               }
+               break;
+       case ARBITRARY_UNIT:
+       default:
+               return value;
+       };
+
+       if (to_raw)
+               return div64_u64(value * divisor, scale);
+       else
+               return div64_u64(value * scale, divisor);
+}
+
+/* in the order of enum rapl_primitives */
+static struct rapl_primitive_info rpi[] = {
+       /* name, mask, shift, msr index, unit divisor */
+       PRIMITIVE_INFO_INIT(ENERGY_COUNTER, ENERGY_STATUS_MASK, 0,
+                               RAPL_DOMAIN_MSR_STATUS, ENERGY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(POWER_LIMIT1, POWER_LIMIT1_MASK, 0,
+                               RAPL_DOMAIN_MSR_LIMIT, POWER_UNIT, 0),
+       PRIMITIVE_INFO_INIT(POWER_LIMIT2, POWER_LIMIT2_MASK, 32,
+                               RAPL_DOMAIN_MSR_LIMIT, POWER_UNIT, 0),
+       PRIMITIVE_INFO_INIT(FW_LOCK, POWER_PP_LOCK, 31,
+                               RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(PL1_ENABLE, POWER_LIMIT1_ENABLE, 15,
+                               RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(PL1_CLAMP, POWER_LIMIT1_CLAMP, 16,
+                               RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(PL2_ENABLE, POWER_LIMIT2_ENABLE, 47,
+                               RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(PL2_CLAMP, POWER_LIMIT2_CLAMP, 48,
+                               RAPL_DOMAIN_MSR_LIMIT, ARBITRARY_UNIT, 0),
+       PRIMITIVE_INFO_INIT(TIME_WINDOW1, TIME_WINDOW1_MASK, 17,
+                               RAPL_DOMAIN_MSR_LIMIT, TIME_UNIT, 0),
+       PRIMITIVE_INFO_INIT(TIME_WINDOW2, TIME_WINDOW2_MASK, 49,
+                               RAPL_DOMAIN_MSR_LIMIT, TIME_UNIT, 0),
+       PRIMITIVE_INFO_INIT(THERMAL_SPEC_POWER, POWER_INFO_THERMAL_SPEC_MASK,
+                               0, RAPL_DOMAIN_MSR_INFO, POWER_UNIT, 0),
+       PRIMITIVE_INFO_INIT(MAX_POWER, POWER_INFO_MAX_MASK, 32,
+                               RAPL_DOMAIN_MSR_INFO, POWER_UNIT, 0),
+       PRIMITIVE_INFO_INIT(MIN_POWER, POWER_INFO_MIN_MASK, 16,
+                               RAPL_DOMAIN_MSR_INFO, POWER_UNIT, 0),
+       PRIMITIVE_INFO_INIT(MAX_TIME_WINDOW, POWER_INFO_MAX_TIME_WIN_MASK, 48,
+                               RAPL_DOMAIN_MSR_INFO, TIME_UNIT, 0),
+       PRIMITIVE_INFO_INIT(THROTTLED_TIME, PERF_STATUS_THROTTLE_TIME_MASK, 0,
+                               RAPL_DOMAIN_MSR_PERF, TIME_UNIT, 0),
+       PRIMITIVE_INFO_INIT(PRIORITY_LEVEL, PP_POLICY_MASK, 0,
+                               RAPL_DOMAIN_MSR_POLICY, ARBITRARY_UNIT, 0),
+       /* non-hardware */
+       PRIMITIVE_INFO_INIT(AVERAGE_POWER, 0, 0, 0, POWER_UNIT,
+                               RAPL_PRIMITIVE_DERIVED),
+       {NULL, 0, 0, 0},
+};
+
+/* Read primitive data based on its related struct rapl_primitive_info.
+ * if xlate flag is set, return translated data based on data units, i.e.
+ * time, energy, and power.
+ * RAPL MSRs are non-architectual and are laid out not consistently across
+ * domains. Here we use primitive info to allow writing consolidated access
+ * functions.
+ * For a given primitive, it is processed by MSR mask and shift. Unit conversion
+ * is pre-assigned based on RAPL unit MSRs read at init time.
+ * 63-------------------------- 31--------------------------- 0
+ * |                           xxxxx (mask)                   |
+ * |                                |<- shift ----------------|
+ * 63-------------------------- 31--------------------------- 0
+ */
+static int rapl_read_data_raw(struct rapl_domain *rd,
+                       enum rapl_primitives prim,
+                       bool xlate, u64 *data)
+{
+       u64 value, final;
+       u32 msr;
+       struct rapl_primitive_info *rp = &rpi[prim];
+       int cpu;
+
+       if (!rp->name || rp->flag & RAPL_PRIMITIVE_DUMMY)
+               return -EINVAL;
+
+       msr = rd->msrs[rp->id];
+       if (!msr)
+               return -EINVAL;
+       /* use physical package id to look up active cpus */
+       cpu = find_active_cpu_on_package(rd->package_id);
+       if (cpu < 0)
+               return cpu;
+
+       /* special-case package domain, which uses a different bit*/
+       if (prim == FW_LOCK && rd->id == RAPL_DOMAIN_PACKAGE) {
+               rp->mask = POWER_PACKAGE_LOCK;
+               rp->shift = 63;
+       }
+       /* non-hardware data are collected by the polling thread */
+       if (rp->flag & RAPL_PRIMITIVE_DERIVED) {
+               *data = rd->rdd.primitives[prim];
+               return 0;
+       }
+
+       if (rdmsrl_safe_on_cpu(cpu, msr, &value)) {
+               pr_debug("failed to read msr 0x%x on cpu %d\n", msr, cpu);
+               return -EIO;
+       }
+
+       final = value & rp->mask;
+       final = final >> rp->shift;
+       if (xlate)
+               *data = rapl_unit_xlate(rd->package_id, rp->unit, final, 0);
+       else
+               *data = final;
+
+       return 0;
+}
+
+/* Similar use of primitive info in the read counterpart */
+static int rapl_write_data_raw(struct rapl_domain *rd,
+                       enum rapl_primitives prim,
+                       unsigned long long value)
+{
+       u64 msr_val;
+       u32 msr;
+       struct rapl_primitive_info *rp = &rpi[prim];
+       int cpu;
+
+       cpu = find_active_cpu_on_package(rd->package_id);
+       if (cpu < 0)
+               return cpu;
+       msr = rd->msrs[rp->id];
+       if (rdmsrl_safe_on_cpu(cpu, msr, &msr_val)) {
+               dev_dbg(&rd->power_zone.dev,
+                       "failed to read msr 0x%x on cpu %d\n", msr, cpu);
+               return -EIO;
+       }
+       value = rapl_unit_xlate(rd->package_id, rp->unit, value, 1);
+       msr_val &= ~rp->mask;
+       msr_val |= value << rp->shift;
+       if (wrmsrl_safe_on_cpu(cpu, msr, msr_val)) {
+               dev_dbg(&rd->power_zone.dev,
+                       "failed to write msr 0x%x on cpu %d\n", msr, cpu);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int rapl_check_unit(struct rapl_package *rp, int cpu)
+{
+       u64 msr_val;
+       u32 value;
+
+       if (rdmsrl_safe_on_cpu(cpu, MSR_RAPL_POWER_UNIT, &msr_val)) {
+               pr_err("Failed to read power unit MSR 0x%x on CPU %d, exit.\n",
+                       MSR_RAPL_POWER_UNIT, cpu);
+               return -ENODEV;
+       }
+
+       /* Raw RAPL data stored in MSRs are in certain scales. We need to
+        * convert them into standard units based on the divisors reported in
+        * the RAPL unit MSRs.
+        * i.e.
+        * energy unit: 1/enery_unit_divisor Joules
+        * power unit: 1/power_unit_divisor Watts
+        * time unit: 1/time_unit_divisor Seconds
+        */
+       value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
+       rp->energy_unit_divisor = 1 << value;
+
+
+       value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
+       rp->power_unit_divisor = 1 << value;
+
+       value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
+       rp->time_unit_divisor = 1 << value;
+
+       pr_debug("Physical package %d units: energy=%d, time=%d, power=%d\n",
+               rp->id,
+               rp->energy_unit_divisor,
+               rp->time_unit_divisor,
+               rp->power_unit_divisor);
+
+       return 0;
+}
+
+/* REVISIT:
+ * When package power limit is set artificially low by RAPL, LVT
+ * thermal interrupt for package power limit should be ignored
+ * since we are not really exceeding the real limit. The intention
+ * is to avoid excessive interrupts while we are trying to save power.
+ * A useful feature might be routing the package_power_limit interrupt
+ * to userspace via eventfd. once we have a usecase, this is simple
+ * to do by adding an atomic notifier.
+ */
+
+static void package_power_limit_irq_save(int package_id)
+{
+       u32 l, h = 0;
+       int cpu;
+       struct rapl_package *rp;
+
+       rp = find_package_by_id(package_id);
+       if (!rp)
+               return;
+
+       if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
+               return;
+
+       cpu = find_active_cpu_on_package(package_id);
+       if (cpu < 0)
+               return;
+       /* save the state of PLN irq mask bit before disabling it */
+       rdmsr_safe_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
+       if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED)) {
+               rp->power_limit_irq = l & PACKAGE_THERM_INT_PLN_ENABLE;
+               rp->power_limit_irq |= PACKAGE_PLN_INT_SAVED;
+       }
+       l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
+       wrmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+}
+
+/* restore per package power limit interrupt enable state */
+static void package_power_limit_irq_restore(int package_id)
+{
+       u32 l, h;
+       int cpu;
+       struct rapl_package *rp;
+
+       rp = find_package_by_id(package_id);
+       if (!rp)
+               return;
+
+       if (!boot_cpu_has(X86_FEATURE_PTS) || !boot_cpu_has(X86_FEATURE_PLN))
+               return;
+
+       cpu = find_active_cpu_on_package(package_id);
+       if (cpu < 0)
+               return;
+
+       /* irq enable state not saved, nothing to restore */
+       if (!(rp->power_limit_irq & PACKAGE_PLN_INT_SAVED))
+               return;
+       rdmsr_safe_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &l, &h);
+
+       if (rp->power_limit_irq & PACKAGE_THERM_INT_PLN_ENABLE)
+               l |= PACKAGE_THERM_INT_PLN_ENABLE;
+       else
+               l &= ~PACKAGE_THERM_INT_PLN_ENABLE;
+
+       wrmsr_on_cpu(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, l, h);
+}
+
+static const struct x86_cpu_id rapl_ids[] = {
+       { X86_VENDOR_INTEL, 6, 0x2a},/* SNB */
+       { X86_VENDOR_INTEL, 6, 0x2d},/* SNB EP */
+       { X86_VENDOR_INTEL, 6, 0x3a},/* IVB */
+       { X86_VENDOR_INTEL, 6, 0x45},/* HSW */
+       /* TODO: Add more CPU IDs after testing */
+       {}
+};
+MODULE_DEVICE_TABLE(x86cpu, rapl_ids);
+
+/* read once for all raw primitive data for all packages, domains */
+static void rapl_update_domain_data(void)
+{
+       int dmn, prim;
+       u64 val;
+       struct rapl_package *rp;
+
+       list_for_each_entry(rp, &rapl_packages, plist) {
+               for (dmn = 0; dmn < rp->nr_domains; dmn++) {
+                       pr_debug("update package %d domain %s data\n", rp->id,
+                               rp->domains[dmn].name);
+                       /* exclude non-raw primitives */
+                       for (prim = 0; prim < NR_RAW_PRIMITIVES; prim++)
+                               if (!rapl_read_data_raw(&rp->domains[dmn], prim,
+                                                               rpi[prim].unit,
+                                                               &val))
+                                       rp->domains[dmn].rdd.primitives[prim] =
+                                                                       val;
+               }
+       }
+
+}
+
+static int rapl_unregister_powercap(void)
+{
+       struct rapl_package *rp;
+       struct rapl_domain *rd, *rd_package = NULL;
+
+       /* unregister all active rapl packages from the powercap layer,
+        * hotplug lock held
+        */
+       list_for_each_entry(rp, &rapl_packages, plist) {
+               package_power_limit_irq_restore(rp->id);
+
+               for (rd = rp->domains; rd < rp->domains + rp->nr_domains;
+                    rd++) {
+                       pr_debug("remove package, undo power limit on %d: %s\n",
+                               rp->id, rd->name);
+                       rapl_write_data_raw(rd, PL1_ENABLE, 0);
+                       rapl_write_data_raw(rd, PL2_ENABLE, 0);
+                       rapl_write_data_raw(rd, PL1_CLAMP, 0);
+                       rapl_write_data_raw(rd, PL2_CLAMP, 0);
+                       if (rd->id == RAPL_DOMAIN_PACKAGE) {
+                               rd_package = rd;
+                               continue;
+                       }
+                       powercap_unregister_zone(control_type, &rd->power_zone);
+               }
+               /* do the package zone last */
+               if (rd_package)
+                       powercap_unregister_zone(control_type,
+                                               &rd_package->power_zone);
+       }
+       powercap_unregister_control_type(control_type);
+
+       return 0;
+}
+
+static int rapl_package_register_powercap(struct rapl_package *rp)
+{
+       struct rapl_domain *rd;
+       int ret = 0;
+       char dev_name[17]; /* max domain name = 7 + 1 + 8 for int + 1 for null*/
+       struct powercap_zone *power_zone = NULL;
+       int nr_pl;
+
+       /* first we register package domain as the parent zone*/
+       for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
+               if (rd->id == RAPL_DOMAIN_PACKAGE) {
+                       nr_pl = find_nr_power_limit(rd);
+                       pr_debug("register socket %d package domain %s\n",
+                               rp->id, rd->name);
+                       memset(dev_name, 0, sizeof(dev_name));
+                       snprintf(dev_name, sizeof(dev_name), "%s-%d",
+                               rd->name, rp->id);
+                       power_zone = powercap_register_zone(&rd->power_zone,
+                                                       control_type,
+                                                       dev_name, NULL,
+                                                       &zone_ops[rd->id],
+                                                       nr_pl,
+                                                       &constraint_ops);
+                       if (IS_ERR(power_zone)) {
+                               pr_debug("failed to register package, %d\n",
+                                       rp->id);
+                               ret = PTR_ERR(power_zone);
+                               goto exit_package;
+                       }
+                       /* track parent zone in per package/socket data */
+                       rp->power_zone = power_zone;
+                       /* done, only one package domain per socket */
+                       break;
+               }
+       }
+       if (!power_zone) {
+               pr_err("no package domain found, unknown topology!\n");
+               ret = -ENODEV;
+               goto exit_package;
+       }
+       /* now register domains as children of the socket/package*/
+       for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
+               if (rd->id == RAPL_DOMAIN_PACKAGE)
+                       continue;
+               /* number of power limits per domain varies */
+               nr_pl = find_nr_power_limit(rd);
+               power_zone = powercap_register_zone(&rd->power_zone,
+                                               control_type, rd->name,
+                                               rp->power_zone,
+                                               &zone_ops[rd->id], nr_pl,
+                                               &constraint_ops);
+
+               if (IS_ERR(power_zone)) {
+                       pr_debug("failed to register power_zone, %d:%s:%s\n",
+                               rp->id, rd->name, dev_name);
+                       ret = PTR_ERR(power_zone);
+                       goto err_cleanup;
+               }
+       }
+
+exit_package:
+       return ret;
+err_cleanup:
+       /* clean up previously initialized domains within the package if we
+        * failed after the first domain setup.
+        */
+       while (--rd >= rp->domains) {
+               pr_debug("unregister package %d domain %s\n", rp->id, rd->name);
+               powercap_unregister_zone(control_type, &rd->power_zone);
+       }
+
+       return ret;
+}
+
+static int rapl_register_powercap(void)
+{
+       struct rapl_domain *rd;
+       struct rapl_package *rp;
+       int ret = 0;
+
+       control_type = powercap_register_control_type(NULL, "intel-rapl", NULL);
+       if (IS_ERR(control_type)) {
+               pr_debug("failed to register powercap control_type.\n");
+               return PTR_ERR(control_type);
+       }
+       /* read the initial data */
+       rapl_update_domain_data();
+       list_for_each_entry(rp, &rapl_packages, plist)
+               if (rapl_package_register_powercap(rp))
+                       goto err_cleanup_package;
+       return ret;
+
+err_cleanup_package:
+       /* clean up previously initialized packages */
+       list_for_each_entry_continue_reverse(rp, &rapl_packages, plist) {
+               for (rd = rp->domains; rd < rp->domains + rp->nr_domains;
+                    rd++) {
+                       pr_debug("unregister zone/package %d, %s domain\n",
+                               rp->id, rd->name);
+                       powercap_unregister_zone(control_type, &rd->power_zone);
+               }
+       }
+
+       return ret;
+}
+
+static int rapl_check_domain(int cpu, int domain)
+{
+       unsigned msr;
+       u64 val1, val2 = 0;
+       int retry = 0;
+
+       switch (domain) {
+       case RAPL_DOMAIN_PACKAGE:
+               msr = MSR_PKG_ENERGY_STATUS;
+               break;
+       case RAPL_DOMAIN_PP0:
+               msr = MSR_PP0_ENERGY_STATUS;
+               break;
+       case RAPL_DOMAIN_PP1:
+               msr = MSR_PP1_ENERGY_STATUS;
+               break;
+       case RAPL_DOMAIN_DRAM:
+               msr = MSR_DRAM_ENERGY_STATUS;
+               break;
+       default:
+               pr_err("invalid domain id %d\n", domain);
+               return -EINVAL;
+       }
+       if (rdmsrl_safe_on_cpu(cpu, msr, &val1))
+               return -ENODEV;
+
+       /* energy counters roll slowly on some domains */
+       while (++retry < 10) {
+               usleep_range(10000, 15000);
+               rdmsrl_safe_on_cpu(cpu, msr, &val2);
+               if ((val1 & ENERGY_STATUS_MASK) != (val2 & ENERGY_STATUS_MASK))
+                       return 0;
+       }
+       /* if energy counter does not change, report as bad domain */
+       pr_info("domain %s energy ctr %llu:%llu not working, skip\n",
+               rapl_domain_names[domain], val1, val2);
+
+       return -ENODEV;
+}
+
+/* Detect active and valid domains for the given CPU, caller must
+ * ensure the CPU belongs to the targeted package and CPU hotlug is disabled.
+ */
+static int rapl_detect_domains(struct rapl_package *rp, int cpu)
+{
+       int i;
+       int ret = 0;
+       struct rapl_domain *rd;
+       u64 locked;
+
+       for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
+               /* use physical package id to read counters */
+               if (!rapl_check_domain(cpu, i))
+                       rp->domain_map |= 1 << i;
+       }
+       rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX);
+       if (!rp->nr_domains) {
+               pr_err("no valid rapl domains found in package %d\n", rp->id);
+               ret = -ENODEV;
+               goto done;
+       }
+       pr_debug("found %d domains on package %d\n", rp->nr_domains, rp->id);
+
+       rp->domains = kcalloc(rp->nr_domains + 1, sizeof(struct rapl_domain),
+                       GFP_KERNEL);
+       if (!rp->domains) {
+               ret = -ENOMEM;
+               goto done;
+       }
+       rapl_init_domains(rp);
+
+       for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
+               /* check if the domain is locked by BIOS */
+               if (rapl_read_data_raw(rd, FW_LOCK, false, &locked)) {
+                       pr_info("RAPL package %d domain %s locked by BIOS\n",
+                               rp->id, rd->name);
+                               rd->state |= DOMAIN_STATE_BIOS_LOCKED;
+               }
+       }
+
+
+done:
+       return ret;
+}
+
+static bool is_package_new(int package)
+{
+       struct rapl_package *rp;
+
+       /* caller prevents cpu hotplug, there will be no new packages added
+        * or deleted while traversing the package list, no need for locking.
+        */
+       list_for_each_entry(rp, &rapl_packages, plist)
+               if (package == rp->id)
+                       return false;
+
+       return true;
+}
+
+/* RAPL interface can be made of a two-level hierarchy: package level and domain
+ * level. We first detect the number of packages then domains of each package.
+ * We have to consider the possiblity of CPU online/offline due to hotplug and
+ * other scenarios.
+ */
+static int rapl_detect_topology(void)
+{
+       int i;
+       int phy_package_id;
+       struct rapl_package *new_package, *rp;
+
+       for_each_online_cpu(i) {
+               phy_package_id = topology_physical_package_id(i);
+               if (is_package_new(phy_package_id)) {
+                       new_package = kzalloc(sizeof(*rp), GFP_KERNEL);
+                       if (!new_package) {
+                               rapl_cleanup_data();
+                               return -ENOMEM;
+                       }
+                       /* add the new package to the list */
+                       new_package->id = phy_package_id;
+                       new_package->nr_cpus = 1;
+
+                       /* check if the package contains valid domains */
+                       if (rapl_detect_domains(new_package, i) ||
+                               rapl_check_unit(new_package, i)) {
+                               kfree(new_package->domains);
+                               kfree(new_package);
+                               /* free up the packages already initialized */
+                               rapl_cleanup_data();
+                               return -ENODEV;
+                       }
+                       INIT_LIST_HEAD(&new_package->plist);
+                       list_add(&new_package->plist, &rapl_packages);
+               } else {
+                       rp = find_package_by_id(phy_package_id);
+                       if (rp)
+                               ++rp->nr_cpus;
+               }
+       }
+
+       return 0;
+}
+
+/* called from CPU hotplug notifier, hotplug lock held */
+static void rapl_remove_package(struct rapl_package *rp)
+{
+       struct rapl_domain *rd, *rd_package = NULL;
+
+       for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
+               if (rd->id == RAPL_DOMAIN_PACKAGE) {
+                       rd_package = rd;
+                       continue;
+               }
+               pr_debug("remove package %d, %s domain\n", rp->id, rd->name);
+               powercap_unregister_zone(control_type, &rd->power_zone);
+       }
+       /* do parent zone last */
+       powercap_unregister_zone(control_type, &rd_package->power_zone);
+       list_del(&rp->plist);
+       kfree(rp);
+}
+
+/* called from CPU hotplug notifier, hotplug lock held */
+static int rapl_add_package(int cpu)
+{
+       int ret = 0;
+       int phy_package_id;
+       struct rapl_package *rp;
+
+       phy_package_id = topology_physical_package_id(cpu);
+       rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
+       if (!rp)
+               return -ENOMEM;
+
+       /* add the new package to the list */
+       rp->id = phy_package_id;
+       rp->nr_cpus = 1;
+       /* check if the package contains valid domains */
+       if (rapl_detect_domains(rp, cpu) ||
+               rapl_check_unit(rp, cpu)) {
+               ret = -ENODEV;
+               goto err_free_package;
+       }
+       if (!rapl_package_register_powercap(rp)) {
+               INIT_LIST_HEAD(&rp->plist);
+               list_add(&rp->plist, &rapl_packages);
+               return ret;
+       }
+
+err_free_package:
+       kfree(rp->domains);
+       kfree(rp);
+
+       return ret;
+}
+
+/* Handles CPU hotplug on multi-socket systems.
+ * If a CPU goes online as the first CPU of the physical package
+ * we add the RAPL package to the system. Similarly, when the last
+ * CPU of the package is removed, we remove the RAPL package and its
+ * associated domains. Cooling devices are handled accordingly at
+ * per-domain level.
+ */
+static int rapl_cpu_callback(struct notifier_block *nfb,
+                               unsigned long action, void *hcpu)
+{
+       unsigned long cpu = (unsigned long)hcpu;
+       int phy_package_id;
+       struct rapl_package *rp;
+
+       phy_package_id = topology_physical_package_id(cpu);
+       switch (action) {
+       case CPU_ONLINE:
+       case CPU_ONLINE_FROZEN:
+       case CPU_DOWN_FAILED:
+       case CPU_DOWN_FAILED_FROZEN:
+               rp = find_package_by_id(phy_package_id);
+               if (rp)
+                       ++rp->nr_cpus;
+               else
+                       rapl_add_package(cpu);
+               break;
+       case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
+               rp = find_package_by_id(phy_package_id);
+               if (!rp)
+                       break;
+               if (--rp->nr_cpus == 0)
+                       rapl_remove_package(rp);
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block rapl_cpu_notifier = {
+       .notifier_call = rapl_cpu_callback,
+};
+
+static int __init rapl_init(void)
+{
+       int ret = 0;
+
+       if (!x86_match_cpu(rapl_ids)) {
+               pr_err("driver does not support CPU family %d model %d\n",
+                       boot_cpu_data.x86, boot_cpu_data.x86_model);
+
+               return -ENODEV;
+       }
+       /* prevent CPU hotplug during detection */
+       get_online_cpus();
+       ret = rapl_detect_topology();
+       if (ret)
+               goto done;
+
+       if (rapl_register_powercap()) {
+               rapl_cleanup_data();
+               ret = -ENODEV;
+               goto done;
+       }
+       register_hotcpu_notifier(&rapl_cpu_notifier);
+done:
+       put_online_cpus();
+
+       return ret;
+}
+
+static void __exit rapl_exit(void)
+{
+       get_online_cpus();
+       unregister_hotcpu_notifier(&rapl_cpu_notifier);
+       rapl_unregister_powercap();
+       rapl_cleanup_data();
+       put_online_cpus();
+}
+
+module_init(rapl_init);
+module_exit(rapl_exit);
+
+MODULE_DESCRIPTION("Driver for Intel RAPL (Running Average Power Limit)");
+MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c
new file mode 100644 (file)
index 0000000..c22fa4c
--- /dev/null
@@ -0,0 +1,683 @@
+/*
+ * Power capping class
+ * Copyright (c) 2013, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/powercap.h>
+
+#define to_powercap_zone(n) container_of(n, struct powercap_zone, dev)
+#define to_powercap_control_type(n) \
+                       container_of(n, struct powercap_control_type, dev)
+
+/* Power zone show function */
+#define define_power_zone_show(_attr)          \
+static ssize_t _attr##_show(struct device *dev, \
+                                       struct device_attribute *dev_attr,\
+                                       char *buf) \
+{ \
+       u64 value; \
+       ssize_t len = -EINVAL; \
+       struct powercap_zone *power_zone = to_powercap_zone(dev); \
+       \
+       if (power_zone->ops->get_##_attr) { \
+               if (!power_zone->ops->get_##_attr(power_zone, &value)) \
+                       len = sprintf(buf, "%lld\n", value); \
+       } \
+       \
+       return len; \
+}
+
+/* The only meaningful input is 0 (reset), others are silently ignored */
+#define define_power_zone_store(_attr)         \
+static ssize_t _attr##_store(struct device *dev,\
+                               struct device_attribute *dev_attr, \
+                               const char *buf, size_t count) \
+{ \
+       int err; \
+       struct powercap_zone *power_zone = to_powercap_zone(dev); \
+       u64 value; \
+       \
+       err = kstrtoull(buf, 10, &value); \
+       if (err) \
+               return -EINVAL; \
+       if (value) \
+               return count; \
+       if (power_zone->ops->reset_##_attr) { \
+               if (!power_zone->ops->reset_##_attr(power_zone)) \
+                       return count; \
+       } \
+       \
+       return -EINVAL; \
+}
+
+/* Power zone constraint show function */
+#define define_power_zone_constraint_show(_attr) \
+static ssize_t show_constraint_##_attr(struct device *dev, \
+                               struct device_attribute *dev_attr,\
+                               char *buf) \
+{ \
+       u64 value; \
+       ssize_t len = -ENODATA; \
+       struct powercap_zone *power_zone = to_powercap_zone(dev); \
+       int id; \
+       struct powercap_zone_constraint *pconst;\
+       \
+       if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
+               return -EINVAL; \
+       if (id >= power_zone->const_id_cnt)     \
+               return -EINVAL; \
+       pconst = &power_zone->constraints[id]; \
+       if (pconst && pconst->ops && pconst->ops->get_##_attr) { \
+               if (!pconst->ops->get_##_attr(power_zone, id, &value)) \
+                       len = sprintf(buf, "%lld\n", value); \
+       } \
+       \
+       return len; \
+}
+
+/* Power zone constraint store function */
+#define define_power_zone_constraint_store(_attr) \
+static ssize_t store_constraint_##_attr(struct device *dev,\
+                               struct device_attribute *dev_attr, \
+                               const char *buf, size_t count) \
+{ \
+       int err; \
+       u64 value; \
+       struct powercap_zone *power_zone = to_powercap_zone(dev); \
+       int id; \
+       struct powercap_zone_constraint *pconst;\
+       \
+       if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id)) \
+               return -EINVAL; \
+       if (id >= power_zone->const_id_cnt)     \
+               return -EINVAL; \
+       pconst = &power_zone->constraints[id]; \
+       err = kstrtoull(buf, 10, &value); \
+       if (err) \
+               return -EINVAL; \
+       if (pconst && pconst->ops && pconst->ops->set_##_attr) { \
+               if (!pconst->ops->set_##_attr(power_zone, id, value)) \
+                       return count; \
+       } \
+       \
+       return -ENODATA; \
+}
+
+/* Power zone information callbacks */
+define_power_zone_show(power_uw);
+define_power_zone_show(max_power_range_uw);
+define_power_zone_show(energy_uj);
+define_power_zone_store(energy_uj);
+define_power_zone_show(max_energy_range_uj);
+
+/* Power zone attributes */
+static DEVICE_ATTR_RO(max_power_range_uw);
+static DEVICE_ATTR_RO(power_uw);
+static DEVICE_ATTR_RO(max_energy_range_uj);
+static DEVICE_ATTR_RW(energy_uj);
+
+/* Power zone constraint attributes callbacks */
+define_power_zone_constraint_show(power_limit_uw);
+define_power_zone_constraint_store(power_limit_uw);
+define_power_zone_constraint_show(time_window_us);
+define_power_zone_constraint_store(time_window_us);
+define_power_zone_constraint_show(max_power_uw);
+define_power_zone_constraint_show(min_power_uw);
+define_power_zone_constraint_show(max_time_window_us);
+define_power_zone_constraint_show(min_time_window_us);
+
+/* For one time seeding of constraint device attributes */
+struct powercap_constraint_attr {
+       struct device_attribute power_limit_attr;
+       struct device_attribute time_window_attr;
+       struct device_attribute max_power_attr;
+       struct device_attribute min_power_attr;
+       struct device_attribute max_time_window_attr;
+       struct device_attribute min_time_window_attr;
+       struct device_attribute name_attr;
+};
+
+static struct powercap_constraint_attr
+                               constraint_attrs[MAX_CONSTRAINTS_PER_ZONE];
+
+/* A list of powercap control_types */
+static LIST_HEAD(powercap_cntrl_list);
+/* Mutex to protect list of powercap control_types */
+static DEFINE_MUTEX(powercap_cntrl_list_lock);
+
+#define POWERCAP_CONSTRAINT_NAME_LEN   30 /* Some limit to avoid overflow */
+static ssize_t show_constraint_name(struct device *dev,
+                               struct device_attribute *dev_attr,
+                               char *buf)
+{
+       const char *name;
+       struct powercap_zone *power_zone = to_powercap_zone(dev);
+       int id;
+       ssize_t len = -ENODATA;
+       struct powercap_zone_constraint *pconst;
+
+       if (!sscanf(dev_attr->attr.name, "constraint_%d_", &id))
+               return -EINVAL;
+       if (id >= power_zone->const_id_cnt)
+               return -EINVAL;
+       pconst = &power_zone->constraints[id];
+
+       if (pconst && pconst->ops && pconst->ops->get_name) {
+               name = pconst->ops->get_name(power_zone, id);
+               if (name) {
+                       snprintf(buf, POWERCAP_CONSTRAINT_NAME_LEN,
+                                                               "%s\n", name);
+                       buf[POWERCAP_CONSTRAINT_NAME_LEN] = '\0';
+                       len = strlen(buf);
+               }
+       }
+
+       return len;
+}
+
+static int create_constraint_attribute(int id, const char *name,
+                               int mode,
+                               struct device_attribute *dev_attr,
+                               ssize_t (*show)(struct device *,
+                                       struct device_attribute *, char *),
+                               ssize_t (*store)(struct device *,
+                                       struct device_attribute *,
+                               const char *, size_t)
+                               )
+{
+
+       dev_attr->attr.name = kasprintf(GFP_KERNEL, "constraint_%d_%s",
+                                                               id, name);
+       if (!dev_attr->attr.name)
+               return -ENOMEM;
+       dev_attr->attr.mode = mode;
+       dev_attr->show = show;
+       dev_attr->store = store;
+
+       return 0;
+}
+
+static void free_constraint_attributes(void)
+{
+       int i;
+
+       for (i = 0; i < MAX_CONSTRAINTS_PER_ZONE; ++i) {
+               kfree(constraint_attrs[i].power_limit_attr.attr.name);
+               kfree(constraint_attrs[i].time_window_attr.attr.name);
+               kfree(constraint_attrs[i].name_attr.attr.name);
+               kfree(constraint_attrs[i].max_power_attr.attr.name);
+               kfree(constraint_attrs[i].min_power_attr.attr.name);
+               kfree(constraint_attrs[i].max_time_window_attr.attr.name);
+               kfree(constraint_attrs[i].min_time_window_attr.attr.name);
+       }
+}
+
+static int seed_constraint_attributes(void)
+{
+       int i;
+       int ret;
+
+       for (i = 0; i < MAX_CONSTRAINTS_PER_ZONE; ++i) {
+               ret = create_constraint_attribute(i, "power_limit_uw",
+                                       S_IWUSR | S_IRUGO,
+                                       &constraint_attrs[i].power_limit_attr,
+                                       show_constraint_power_limit_uw,
+                                       store_constraint_power_limit_uw);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "time_window_us",
+                                       S_IWUSR | S_IRUGO,
+                                       &constraint_attrs[i].time_window_attr,
+                                       show_constraint_time_window_us,
+                                       store_constraint_time_window_us);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "name", S_IRUGO,
+                               &constraint_attrs[i].name_attr,
+                               show_constraint_name,
+                               NULL);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "max_power_uw", S_IRUGO,
+                               &constraint_attrs[i].max_power_attr,
+                               show_constraint_max_power_uw,
+                               NULL);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "min_power_uw", S_IRUGO,
+                               &constraint_attrs[i].min_power_attr,
+                               show_constraint_min_power_uw,
+                               NULL);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "max_time_window_us",
+                               S_IRUGO,
+                               &constraint_attrs[i].max_time_window_attr,
+                               show_constraint_max_time_window_us,
+                               NULL);
+               if (ret)
+                       goto err_alloc;
+               ret = create_constraint_attribute(i, "min_time_window_us",
+                               S_IRUGO,
+                               &constraint_attrs[i].min_time_window_attr,
+                               show_constraint_min_time_window_us,
+                               NULL);
+               if (ret)
+                       goto err_alloc;
+
+       }
+
+       return 0;
+
+err_alloc:
+       free_constraint_attributes();
+
+       return ret;
+}
+
+static int create_constraints(struct powercap_zone *power_zone,
+                               int nr_constraints,
+                               struct powercap_zone_constraint_ops *const_ops)
+{
+       int i;
+       int ret = 0;
+       int count;
+       struct powercap_zone_constraint *pconst;
+
+       if (!power_zone || !const_ops || !const_ops->get_power_limit_uw ||
+                                       !const_ops->set_power_limit_uw ||
+                                       !const_ops->get_time_window_us ||
+                                       !const_ops->set_time_window_us)
+               return -EINVAL;
+
+       count = power_zone->zone_attr_count;
+       for (i = 0; i < nr_constraints; ++i) {
+               pconst = &power_zone->constraints[i];
+               pconst->ops = const_ops;
+               pconst->id = power_zone->const_id_cnt;
+               power_zone->const_id_cnt++;
+               power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].power_limit_attr.attr;
+               power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].time_window_attr.attr;
+               if (pconst->ops->get_name)
+                       power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].name_attr.attr;
+               if (pconst->ops->get_max_power_uw)
+                       power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].max_power_attr.attr;
+               if (pconst->ops->get_min_power_uw)
+                       power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].min_power_attr.attr;
+               if (pconst->ops->get_max_time_window_us)
+                       power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].max_time_window_attr.attr;
+               if (pconst->ops->get_min_time_window_us)
+                       power_zone->zone_dev_attrs[count++] =
+                               &constraint_attrs[i].min_time_window_attr.attr;
+       }
+       power_zone->zone_attr_count = count;
+
+       return ret;
+}
+
+static bool control_type_valid(void *control_type)
+{
+       struct powercap_control_type *pos = NULL;
+       bool found = false;
+
+       mutex_lock(&powercap_cntrl_list_lock);
+
+       list_for_each_entry(pos, &powercap_cntrl_list, node) {
+               if (pos == control_type) {
+                       found = true;
+                       break;
+               }
+       }
+       mutex_unlock(&powercap_cntrl_list_lock);
+
+       return found;
+}
+
+static ssize_t name_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct powercap_zone *power_zone = to_powercap_zone(dev);
+
+       return sprintf(buf, "%s\n", power_zone->name);
+}
+
+static DEVICE_ATTR_RO(name);
+
+/* Create zone and attributes in sysfs */
+static void create_power_zone_common_attributes(
+                                       struct powercap_zone *power_zone)
+{
+       int count = 0;
+
+       power_zone->zone_dev_attrs[count++] = &dev_attr_name.attr;
+       if (power_zone->ops->get_max_energy_range_uj)
+               power_zone->zone_dev_attrs[count++] =
+                                       &dev_attr_max_energy_range_uj.attr;
+       if (power_zone->ops->get_energy_uj)
+               power_zone->zone_dev_attrs[count++] =
+                                       &dev_attr_energy_uj.attr;
+       if (power_zone->ops->get_power_uw)
+               power_zone->zone_dev_attrs[count++] =
+                                       &dev_attr_power_uw.attr;
+       if (power_zone->ops->get_max_power_range_uw)
+               power_zone->zone_dev_attrs[count++] =
+                                       &dev_attr_max_power_range_uw.attr;
+       power_zone->zone_dev_attrs[count] = NULL;
+       power_zone->zone_attr_count = count;
+}
+
+static void powercap_release(struct device *dev)
+{
+       bool allocated;
+
+       if (dev->parent) {
+               struct powercap_zone *power_zone = to_powercap_zone(dev);
+
+               /* Store flag as the release() may free memory */
+               allocated = power_zone->allocated;
+               /* Remove id from parent idr struct */
+               idr_remove(power_zone->parent_idr, power_zone->id);
+               /* Destroy idrs allocated for this zone */
+               idr_destroy(&power_zone->idr);
+               kfree(power_zone->name);
+               kfree(power_zone->zone_dev_attrs);
+               kfree(power_zone->constraints);
+               if (power_zone->ops->release)
+                       power_zone->ops->release(power_zone);
+               if (allocated)
+                       kfree(power_zone);
+       } else {
+               struct powercap_control_type *control_type =
+                                               to_powercap_control_type(dev);
+
+               /* Store flag as the release() may free memory */
+               allocated = control_type->allocated;
+               idr_destroy(&control_type->idr);
+               mutex_destroy(&control_type->lock);
+               if (control_type->ops && control_type->ops->release)
+                       control_type->ops->release(control_type);
+               if (allocated)
+                       kfree(control_type);
+       }
+}
+
+static ssize_t enabled_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       bool mode = true;
+
+       /* Default is enabled */
+       if (dev->parent) {
+               struct powercap_zone *power_zone = to_powercap_zone(dev);
+               if (power_zone->ops->get_enable)
+                       if (power_zone->ops->get_enable(power_zone, &mode))
+                               mode = false;
+       } else {
+               struct powercap_control_type *control_type =
+                                               to_powercap_control_type(dev);
+               if (control_type->ops && control_type->ops->get_enable)
+                       if (control_type->ops->get_enable(control_type, &mode))
+                               mode = false;
+       }
+
+       return sprintf(buf, "%d\n", mode);
+}
+
+static ssize_t enabled_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf,  size_t len)
+{
+       bool mode;
+
+       if (strtobool(buf, &mode))
+               return -EINVAL;
+       if (dev->parent) {
+               struct powercap_zone *power_zone = to_powercap_zone(dev);
+               if (power_zone->ops->set_enable)
+                       if (!power_zone->ops->set_enable(power_zone, mode))
+                               return len;
+       } else {
+               struct powercap_control_type *control_type =
+                                               to_powercap_control_type(dev);
+               if (control_type->ops && control_type->ops->set_enable)
+                       if (!control_type->ops->set_enable(control_type, mode))
+                               return len;
+       }
+
+       return -ENOSYS;
+}
+
+static struct device_attribute powercap_def_attrs[] = {
+               __ATTR(enabled, S_IWUSR | S_IRUGO, enabled_show,
+                                                       enabled_store),
+               __ATTR_NULL
+};
+
+static struct class powercap_class = {
+       .name = "powercap",
+       .dev_release = powercap_release,
+       .dev_attrs = powercap_def_attrs,
+};
+
+struct powercap_zone *powercap_register_zone(
+                               struct powercap_zone *power_zone,
+                               struct powercap_control_type *control_type,
+                               const char *name,
+                               struct powercap_zone *parent,
+                               const struct powercap_zone_ops *ops,
+                               int nr_constraints,
+                               struct powercap_zone_constraint_ops *const_ops)
+{
+       int result;
+       int nr_attrs;
+
+       if (!name || !control_type || !ops ||
+                       nr_constraints > MAX_CONSTRAINTS_PER_ZONE ||
+                       (!ops->get_energy_uj && !ops->get_power_uw) ||
+                       !control_type_valid(control_type))
+               return ERR_PTR(-EINVAL);
+
+       if (power_zone) {
+               if (!ops->release)
+                       return ERR_PTR(-EINVAL);
+               memset(power_zone, 0, sizeof(*power_zone));
+       } else {
+               power_zone = kzalloc(sizeof(*power_zone), GFP_KERNEL);
+               if (!power_zone)
+                       return ERR_PTR(-ENOMEM);
+               power_zone->allocated = true;
+       }
+       power_zone->ops = ops;
+       power_zone->control_type_inst = control_type;
+       if (!parent) {
+               power_zone->dev.parent = &control_type->dev;
+               power_zone->parent_idr = &control_type->idr;
+       } else {
+               power_zone->dev.parent = &parent->dev;
+               power_zone->parent_idr = &parent->idr;
+       }
+       power_zone->dev.class = &powercap_class;
+
+       mutex_lock(&control_type->lock);
+       /* Using idr to get the unique id */
+       result = idr_alloc(power_zone->parent_idr, NULL, 0, 0, GFP_KERNEL);
+       if (result < 0)
+               goto err_idr_alloc;
+
+       power_zone->id = result;
+       idr_init(&power_zone->idr);
+       power_zone->name = kstrdup(name, GFP_KERNEL);
+       if (!power_zone->name)
+               goto err_name_alloc;
+       dev_set_name(&power_zone->dev, "%s:%x",
+                                       dev_name(power_zone->dev.parent),
+                                       power_zone->id);
+       power_zone->constraints = kzalloc(sizeof(*power_zone->constraints) *
+                                        nr_constraints, GFP_KERNEL);
+       if (!power_zone->constraints)
+               goto err_const_alloc;
+
+       nr_attrs = nr_constraints * POWERCAP_CONSTRAINTS_ATTRS +
+                                               POWERCAP_ZONE_MAX_ATTRS + 1;
+       power_zone->zone_dev_attrs = kzalloc(sizeof(void *) *
+                                               nr_attrs, GFP_KERNEL);
+       if (!power_zone->zone_dev_attrs)
+               goto err_attr_alloc;
+       create_power_zone_common_attributes(power_zone);
+       result = create_constraints(power_zone, nr_constraints, const_ops);
+       if (result)
+               goto err_dev_ret;
+
+       power_zone->zone_dev_attrs[power_zone->zone_attr_count] = NULL;
+       power_zone->dev_zone_attr_group.attrs = power_zone->zone_dev_attrs;
+       power_zone->dev_attr_groups[0] = &power_zone->dev_zone_attr_group;
+       power_zone->dev_attr_groups[1] = NULL;
+       power_zone->dev.groups = power_zone->dev_attr_groups;
+       result = device_register(&power_zone->dev);
+       if (result)
+               goto err_dev_ret;
+
+       control_type->nr_zones++;
+       mutex_unlock(&control_type->lock);
+
+       return power_zone;
+
+err_dev_ret:
+       kfree(power_zone->zone_dev_attrs);
+err_attr_alloc:
+       kfree(power_zone->constraints);
+err_const_alloc:
+       kfree(power_zone->name);
+err_name_alloc:
+       idr_remove(power_zone->parent_idr, power_zone->id);
+err_idr_alloc:
+       if (power_zone->allocated)
+               kfree(power_zone);
+       mutex_unlock(&control_type->lock);
+
+       return ERR_PTR(result);
+}
+EXPORT_SYMBOL_GPL(powercap_register_zone);
+
+int powercap_unregister_zone(struct powercap_control_type *control_type,
+                               struct powercap_zone *power_zone)
+{
+       if (!power_zone || !control_type)
+               return -EINVAL;
+
+       mutex_lock(&control_type->lock);
+       control_type->nr_zones--;
+       mutex_unlock(&control_type->lock);
+
+       device_unregister(&power_zone->dev);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(powercap_unregister_zone);
+
+struct powercap_control_type *powercap_register_control_type(
+                               struct powercap_control_type *control_type,
+                               const char *name,
+                               const struct powercap_control_type_ops *ops)
+{
+       int result;
+
+       if (!name)
+               return ERR_PTR(-EINVAL);
+       if (control_type) {
+               if (!ops || !ops->release)
+                       return ERR_PTR(-EINVAL);
+               memset(control_type, 0, sizeof(*control_type));
+       } else {
+               control_type = kzalloc(sizeof(*control_type), GFP_KERNEL);
+               if (!control_type)
+                       return ERR_PTR(-ENOMEM);
+               control_type->allocated = true;
+       }
+       mutex_init(&control_type->lock);
+       control_type->ops = ops;
+       INIT_LIST_HEAD(&control_type->node);
+       control_type->dev.class = &powercap_class;
+       dev_set_name(&control_type->dev, name);
+       result = device_register(&control_type->dev);
+       if (result) {
+               if (control_type->allocated)
+                       kfree(control_type);
+               return ERR_PTR(result);
+       }
+       idr_init(&control_type->idr);
+
+       mutex_lock(&powercap_cntrl_list_lock);
+       list_add_tail(&control_type->node, &powercap_cntrl_list);
+       mutex_unlock(&powercap_cntrl_list_lock);
+
+       return control_type;
+}
+EXPORT_SYMBOL_GPL(powercap_register_control_type);
+
+int powercap_unregister_control_type(struct powercap_control_type *control_type)
+{
+       struct powercap_control_type *pos = NULL;
+
+       if (control_type->nr_zones) {
+               dev_err(&control_type->dev, "Zones of this type still not freed\n");
+               return -EINVAL;
+       }
+       mutex_lock(&powercap_cntrl_list_lock);
+       list_for_each_entry(pos, &powercap_cntrl_list, node) {
+               if (pos == control_type) {
+                       list_del(&control_type->node);
+                       mutex_unlock(&powercap_cntrl_list_lock);
+                       device_unregister(&control_type->dev);
+                       return 0;
+               }
+       }
+       mutex_unlock(&powercap_cntrl_list_lock);
+
+       return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(powercap_unregister_control_type);
+
+static int __init powercap_init(void)
+{
+       int result = 0;
+
+       result = seed_constraint_attributes();
+       if (result)
+               return result;
+
+       result = class_register(&powercap_class);
+
+       return result;
+}
+
+device_initcall(powercap_init);
+
+MODULE_DESCRIPTION("PowerCap sysfs Driver");
+MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
index 9e039c60c0680ae761e2be41f0de0a171368f3c6..740f9ddda227d55f15042e1e7a8d2cadb58aae71 100644 (file)
@@ -240,15 +240,27 @@ EXPORT_SYMBOL_GPL(spi_bus_type);
 static int spi_drv_probe(struct device *dev)
 {
        const struct spi_driver         *sdrv = to_spi_driver(dev->driver);
+       struct spi_device               *spi = to_spi_device(dev);
+       int ret;
+
+       acpi_dev_pm_attach(&spi->dev, true);
+       ret = sdrv->probe(spi);
+       if (ret)
+               acpi_dev_pm_detach(&spi->dev, true);
 
-       return sdrv->probe(to_spi_device(dev));
+       return ret;
 }
 
 static int spi_drv_remove(struct device *dev)
 {
        const struct spi_driver         *sdrv = to_spi_driver(dev->driver);
+       struct spi_device               *spi = to_spi_device(dev);
+       int ret;
+
+       ret = sdrv->remove(spi);
+       acpi_dev_pm_detach(&spi->dev, true);
 
-       return sdrv->remove(to_spi_device(dev));
+       return ret;
 }
 
 static void spi_drv_shutdown(struct device *dev)
@@ -1025,8 +1037,10 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
                return AE_OK;
        }
 
+       adev->power.flags.ignore_parent = true;
        strlcpy(spi->modalias, dev_name(&adev->dev), sizeof(spi->modalias));
        if (spi_add_device(spi)) {
+               adev->power.flags.ignore_parent = false;
                dev_err(&master->dev, "failed to add SPI device %s from ACPI\n",
                        dev_name(&adev->dev));
                spi_dev_put(spi);
index dbfc390330acf2ee8bc6af339ff22f3b6fc3ec77..5ef596765060ac605013e41a45ced379132e8853 100644 (file)
@@ -78,7 +78,6 @@ config THERMAL_GOV_USER_SPACE
 config CPU_THERMAL
        bool "generic cpu cooling support"
        depends on CPU_FREQ
-       select CPU_FREQ_TABLE
        help
          This implements the generic cpu cooling mechanism through frequency
          reduction. An ACPI version of this already exists
index 94a403a9717ae9f84c941e334098bbc0c0713bbb..5d05555fe841d2a4eaac7d230e498e0c51f5d841 100644 (file)
@@ -21,6 +21,9 @@
 #include <asm/backlight.h>
 #endif
 
+static struct list_head backlight_dev_list;
+static struct mutex backlight_dev_list_mutex;
+
 static const char *const backlight_types[] = {
        [BACKLIGHT_RAW] = "raw",
        [BACKLIGHT_PLATFORM] = "platform",
@@ -349,10 +352,32 @@ struct backlight_device *backlight_device_register(const char *name,
        mutex_unlock(&pmac_backlight_mutex);
 #endif
 
+       mutex_lock(&backlight_dev_list_mutex);
+       list_add(&new_bd->entry, &backlight_dev_list);
+       mutex_unlock(&backlight_dev_list_mutex);
+
        return new_bd;
 }
 EXPORT_SYMBOL(backlight_device_register);
 
+bool backlight_device_registered(enum backlight_type type)
+{
+       bool found = false;
+       struct backlight_device *bd;
+
+       mutex_lock(&backlight_dev_list_mutex);
+       list_for_each_entry(bd, &backlight_dev_list, entry) {
+               if (bd->props.type == type) {
+                       found = true;
+                       break;
+               }
+       }
+       mutex_unlock(&backlight_dev_list_mutex);
+
+       return found;
+}
+EXPORT_SYMBOL(backlight_device_registered);
+
 /**
  * backlight_device_unregister - unregisters a backlight device object.
  * @bd: the backlight device object to be unregistered and freed.
@@ -364,6 +389,10 @@ void backlight_device_unregister(struct backlight_device *bd)
        if (!bd)
                return;
 
+       mutex_lock(&backlight_dev_list_mutex);
+       list_del(&bd->entry);
+       mutex_unlock(&backlight_dev_list_mutex);
+
 #ifdef CONFIG_PMAC_BACKLIGHT
        mutex_lock(&pmac_backlight_mutex);
        if (pmac_backlight == bd)
@@ -499,6 +528,8 @@ static int __init backlight_class_init(void)
 
        backlight_class->dev_groups = bl_device_groups;
        backlight_class->pm = &backlight_class_dev_pm_ops;
+       INIT_LIST_HEAD(&backlight_dev_list);
+       mutex_init(&backlight_dev_list_mutex);
        return 0;
 }
 
index cf051e05a8fe682894251ec5944299a8ead8277f..4e280bd226ddaa107a3d19f08b07389279b53922 100644 (file)
@@ -125,8 +125,9 @@ struct acpi_exception_info {
 #define AE_NO_HANDLER                   EXCEP_ENV (0x001A)
 #define AE_OWNER_ID_LIMIT               EXCEP_ENV (0x001B)
 #define AE_NOT_CONFIGURED               EXCEP_ENV (0x001C)
+#define AE_ACCESS                       EXCEP_ENV (0x001D)
 
-#define AE_CODE_ENV_MAX                 0x001C
+#define AE_CODE_ENV_MAX                 0x001D
 
 /*
  * Programmer exceptions
@@ -227,7 +228,7 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = {
        EXCEP_TXT("AE_NO_ACPI_TABLES", "ACPI tables could not be found"),
        EXCEP_TXT("AE_NO_NAMESPACE", "A namespace has not been loaded"),
        EXCEP_TXT("AE_NO_MEMORY", "Insufficient dynamic memory"),
-       EXCEP_TXT("AE_NOT_FOUND", "The name was not found in the namespace"),
+       EXCEP_TXT("AE_NOT_FOUND", "A requested entity is not found"),
        EXCEP_TXT("AE_NOT_EXIST", "A required entity does not exist"),
        EXCEP_TXT("AE_ALREADY_EXISTS", "An entity already exists"),
        EXCEP_TXT("AE_TYPE", "The object type is incorrect"),
@@ -259,7 +260,8 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = {
        EXCEP_TXT("AE_OWNER_ID_LIMIT",
                  "There are no more Owner IDs available for ACPI tables or control methods"),
        EXCEP_TXT("AE_NOT_CONFIGURED",
-                 "The interface is not part of the current subsystem configuration")
+                 "The interface is not part of the current subsystem configuration"),
+       EXCEP_TXT("AE_ACCESS", "Permission denied for the requested operation")
 };
 
 static const struct acpi_exception_info acpi_gbl_exception_names_pgm[] = {
index d9019821aa6020e1c6d974856edfb404cb81d8c8..15100f625e6550a94bc2afe721ccf3804a2360d5 100644 (file)
@@ -222,7 +222,8 @@ struct acpi_device_power_flags {
        u32 power_resources:1;  /* Power resources */
        u32 inrush_current:1;   /* Serialize Dx->D0 */
        u32 power_removed:1;    /* Optimize Dx->D0 */
-       u32 reserved:28;
+       u32 ignore_parent:1;    /* Power is independent of parent power state */
+       u32 reserved:27;
 };
 
 struct acpi_device_power_state {
index 85bfdbe178052bd2231dce137b1463d174b2bffe..c7b1475422b3f3ed140e852f9a3407719c8f68b2 100644 (file)
@@ -46,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20130725
+#define ACPI_CA_VERSION                 0x20130823
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
@@ -280,9 +280,16 @@ acpi_status
 acpi_install_initialization_handler(acpi_init_handler handler, u32 function);
 
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
-                               acpi_install_global_event_handler
-                               (acpi_gbl_event_handler handler, void *context))
-
+                               acpi_install_sci_handler(acpi_sci_handler
+                                                        address,
+                                                        void *context))
+ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+                                acpi_remove_sci_handler(acpi_sci_handler
+                                                        address))
+ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
+                                acpi_install_global_event_handler
+                                (acpi_gbl_event_handler handler,
+                                 void *context))
 ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
                                 acpi_install_fixed_event_handler(u32
                                                                  acpi_event,
index b748aefce929983cf94d3729db782e62c2843768..f6abf23ad0a71d51df5c86806c1b504b678a4bc1 100644 (file)
@@ -474,6 +474,11 @@ typedef u64 acpi_integer;
 #define ACPI_MOVE_NAME(dest,src)        (ACPI_STRNCPY (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAME_SIZE))
 #endif
 
+/* Support for the special RSDP signature (8 characters) */
+
+#define ACPI_VALIDATE_RSDP_SIG(a)       (!ACPI_STRNCMP (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, 8))
+#define ACPI_MAKE_RSDP_SIG(dest)        (ACPI_MEMCPY (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8))
+
 /*******************************************************************************
  *
  * Miscellaneous constants
@@ -945,6 +950,9 @@ typedef void
 /*
  * Various handlers and callback procedures
  */
+typedef
+u32 (*acpi_sci_handler) (void *context);
+
 typedef
 void (*acpi_gbl_event_handler) (u32 event_type,
                               acpi_handle device,
index 68534ef86ec81a903e09ccd93169baf69b4bb73e..fda0f3e35c03fc40043cbfdba951cbe1852d9ca6 100644 (file)
@@ -87,7 +87,7 @@
 #define ACPI_FLUSH_CPU_CACHE()
 #define ACPI_CAST_PTHREAD_T(pthread) ((acpi_thread_id) (pthread))
 
-#if defined(__ia64__) || defined(__x86_64__)
+#if defined(__ia64__) || defined(__x86_64__) || defined(__aarch64__)
 #define ACPI_MACHINE_WIDTH          64
 #define COMPILER_DEPENDENT_INT64    long
 #define COMPILER_DEPENDENT_UINT64   unsigned long
index 66096d06925e417d70d6b8974a00a035d05ef1d8..7816e45f5d5a0177b7aac0b4b40fdd9e125a97bb 100644 (file)
@@ -199,6 +199,7 @@ struct acpi_processor_flags {
 struct acpi_processor {
        acpi_handle handle;
        u32 acpi_id;
+       u32 apic_id;
        u32 id;
        u32 pblk;
        int performance_platform_limit;
@@ -314,6 +315,8 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
 
 /* in processor_core.c */
 void acpi_processor_set_pdc(acpi_handle handle);
+int acpi_get_apicid(acpi_handle, int type, u32 acpi_id);
+int acpi_map_cpuid(int apic_id, u32 acpi_id);
 int acpi_get_cpuid(acpi_handle, int type, u32 acpi_id);
 
 /* in processor_throttling.c */
index a5db4aeefa3642107e28b431c21a89c195569993..3bc74141453f85b93400536f0bcb61f1354b8bf5 100644 (file)
@@ -116,7 +116,7 @@ void acpi_numa_arch_fixup(void);
 
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
 /* Arch dependent functions for cpu hotplug support */
-int acpi_map_lsapic(acpi_handle handle, int *pcpu);
+int acpi_map_lsapic(acpi_handle handle, int physid, int *pcpu);
 int acpi_unmap_lsapic(int cpu);
 #endif /* CONFIG_ACPI_HOTPLUG_CPU */
 
index 53b77949c79d4c84b6595614206857e2b6796b1f..5f9cd963213dd3a3150abd3e34f62a6925096053 100644 (file)
@@ -100,6 +100,9 @@ struct backlight_device {
        /* The framebuffer notifier block */
        struct notifier_block fb_notif;
 
+       /* list entry of all registered backlight devices */
+       struct list_head entry;
+
        struct device dev;
 };
 
@@ -123,6 +126,7 @@ extern void devm_backlight_device_unregister(struct device *dev,
                                        struct backlight_device *bd);
 extern void backlight_force_update(struct backlight_device *bd,
                                   enum backlight_update_reason reason);
+extern bool backlight_device_registered(enum backlight_type type);
 
 #define to_backlight_device(obj) container_of(obj, struct backlight_device, dev)
 
index a3b6b82108b9ad239dd1dda1abe6c8e3f585d3b3..5a1c8b71ccd84616b0471b833ee909c9d794be5f 100644 (file)
@@ -4,8 +4,11 @@
 
 #ifdef __KERNEL__
 #define BIT(nr)                        (1UL << (nr))
+#define BIT_ULL(nr)            (1ULL << (nr))
 #define BIT_MASK(nr)           (1UL << ((nr) % BITS_PER_LONG))
 #define BIT_WORD(nr)           ((nr) / BITS_PER_LONG)
+#define BIT_ULL_MASK(nr)       (1ULL << ((nr) % BITS_PER_LONG_LONG))
+#define BIT_ULL_WORD(nr)       ((nr) / BITS_PER_LONG_LONG)
 #define BITS_PER_BYTE          8
 #define BITS_TO_LONGS(nr)      DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
 #endif
index 801ff9e73679a00d7f945d82253454a236319966..3434ef7de017de0d5a33e7dd5dbfb173678c58c0 100644 (file)
@@ -185,19 +185,6 @@ extern void cpu_hotplug_enable(void);
 void clear_tasks_mm_cpumask(int cpu);
 int cpu_down(unsigned int cpu);
 
-#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
-extern void cpu_hotplug_driver_lock(void);
-extern void cpu_hotplug_driver_unlock(void);
-#else
-static inline void cpu_hotplug_driver_lock(void)
-{
-}
-
-static inline void cpu_hotplug_driver_unlock(void)
-{
-}
-#endif
-
 #else          /* CONFIG_HOTPLUG_CPU */
 
 static inline void cpu_hotplug_begin(void) {}
index fcabc42d66ab413a38730cb78d8eedc9bda91084..0aba2a6cadafcb9e73a42dd04b74a5c1d433ad36 100644 (file)
@@ -180,13 +180,6 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
 struct cpufreq_driver {
        char                    name[CPUFREQ_NAME_LEN];
        u8                      flags;
-       /*
-        * This should be set by platforms having multiple clock-domains, i.e.
-        * supporting multiple policies. With this sysfs directories of governor
-        * would be created in cpu/cpu<num>/cpufreq/ directory and so they can
-        * use the same governor with different tunables for different clusters.
-        */
-       bool                    have_governor_per_policy;
 
        /* needed by all drivers */
        int     (*init)         (struct cpufreq_policy *policy);
@@ -211,13 +204,22 @@ struct cpufreq_driver {
 };
 
 /* flags */
-#define CPUFREQ_STICKY         0x01    /* the driver isn't removed even if
-                                        * all ->init() calls failed */
-#define CPUFREQ_CONST_LOOPS    0x02    /* loops_per_jiffy or other kernel
-                                        * "constants" aren't affected by
-                                        * frequency transitions */
-#define CPUFREQ_PM_NO_WARN     0x04    /* don't warn on suspend/resume speed
-                                        * mismatches */
+#define CPUFREQ_STICKY         (1 << 0)        /* driver isn't removed even if
+                                                  all ->init() calls failed */
+#define CPUFREQ_CONST_LOOPS    (1 << 1)        /* loops_per_jiffy or other
+                                                  kernel "constants" aren't
+                                                  affected by frequency
+                                                  transitions */
+#define CPUFREQ_PM_NO_WARN     (1 << 2)        /* don't warn on suspend/resume
+                                                  speed mismatches */
+
+/*
+ * This should be set by platforms having multiple clock-domains, i.e.
+ * supporting multiple policies. With this sysfs directories of governor would
+ * be created in cpu/cpu<num>/cpufreq/ directory and so they can use the same
+ * governor with different tunables for different clusters.
+ */
+#define CPUFREQ_HAVE_GOVERNOR_PER_POLICY (1 << 3)
 
 int cpufreq_register_driver(struct cpufreq_driver *driver_data);
 int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
@@ -240,6 +242,13 @@ static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,
        return;
 }
 
+static inline void
+cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy)
+{
+       cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+                       policy->cpuinfo.max_freq);
+}
+
 /*********************************************************************
  *                     CPUFREQ NOTIFIER INTERFACE                    *
  *********************************************************************/
@@ -392,6 +401,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
 
 int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table);
+int cpufreq_generic_frequency_table_verify(struct cpufreq_policy *policy);
 
 int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
                                   struct cpufreq_frequency_table *table,
@@ -407,8 +417,20 @@ struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
 
 /* the following are really really optional */
 extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
+extern struct freq_attr *cpufreq_generic_attr[];
 void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
                                      unsigned int cpu);
 void cpufreq_frequency_table_put_attr(unsigned int cpu);
+int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
+                                     struct cpufreq_frequency_table *table);
+
+int cpufreq_generic_init(struct cpufreq_policy *policy,
+               struct cpufreq_frequency_table *table,
+               unsigned int transition_latency);
+static inline int cpufreq_generic_exit(struct cpufreq_policy *policy)
+{
+       cpufreq_frequency_table_put_attr(policy->cpu);
+       return 0;
+}
 
 #endif /* _LINUX_CPUFREQ_H */
index 5f1ab92107e63b1889da7e544189f8b73cc740fb..7a7cc74d7f27e9901e59d2a61b850c0ec6acbe9e 100644 (file)
@@ -15,7 +15,7 @@
 
 #include <linux/device.h>
 #include <linux/notifier.h>
-#include <linux/opp.h>
+#include <linux/pm_opp.h>
 
 #define DEVFREQ_NAME_LEN 16
 
@@ -187,7 +187,7 @@ extern int devfreq_suspend_device(struct devfreq *devfreq);
 extern int devfreq_resume_device(struct devfreq *devfreq);
 
 /* Helper functions for devfreq user device driver with OPP. */
-extern struct opp *devfreq_recommended_opp(struct device *dev,
+extern struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
                                           unsigned long *freq, u32 flags);
 extern int devfreq_register_opp_notifier(struct device *dev,
                                         struct devfreq *devfreq);
@@ -238,7 +238,7 @@ static inline int devfreq_resume_device(struct devfreq *devfreq)
        return 0;
 }
 
-static inline struct opp *devfreq_recommended_opp(struct device *dev,
+static inline struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
                                           unsigned long *freq, u32 flags)
 {
        return ERR_PTR(-EINVAL);
diff --git a/include/linux/opp.h b/include/linux/opp.h
deleted file mode 100644 (file)
index 3aca2b8..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Generic OPP Interface
- *
- * Copyright (C) 2009-2010 Texas Instruments Incorporated.
- *     Nishanth Menon
- *     Romit Dasgupta
- *     Kevin Hilman
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __LINUX_OPP_H__
-#define __LINUX_OPP_H__
-
-#include <linux/err.h>
-#include <linux/cpufreq.h>
-#include <linux/notifier.h>
-
-struct opp;
-struct device;
-
-enum opp_event {
-       OPP_EVENT_ADD, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE,
-};
-
-#if defined(CONFIG_PM_OPP)
-
-unsigned long opp_get_voltage(struct opp *opp);
-
-unsigned long opp_get_freq(struct opp *opp);
-
-int opp_get_opp_count(struct device *dev);
-
-struct opp *opp_find_freq_exact(struct device *dev, unsigned long freq,
-                               bool available);
-
-struct opp *opp_find_freq_floor(struct device *dev, unsigned long *freq);
-
-struct opp *opp_find_freq_ceil(struct device *dev, unsigned long *freq);
-
-int opp_add(struct device *dev, unsigned long freq, unsigned long u_volt);
-
-int opp_enable(struct device *dev, unsigned long freq);
-
-int opp_disable(struct device *dev, unsigned long freq);
-
-struct srcu_notifier_head *opp_get_notifier(struct device *dev);
-#else
-static inline unsigned long opp_get_voltage(struct opp *opp)
-{
-       return 0;
-}
-
-static inline unsigned long opp_get_freq(struct opp *opp)
-{
-       return 0;
-}
-
-static inline int opp_get_opp_count(struct device *dev)
-{
-       return 0;
-}
-
-static inline struct opp *opp_find_freq_exact(struct device *dev,
-                                       unsigned long freq, bool available)
-{
-       return ERR_PTR(-EINVAL);
-}
-
-static inline struct opp *opp_find_freq_floor(struct device *dev,
-                                       unsigned long *freq)
-{
-       return ERR_PTR(-EINVAL);
-}
-
-static inline struct opp *opp_find_freq_ceil(struct device *dev,
-                                       unsigned long *freq)
-{
-       return ERR_PTR(-EINVAL);
-}
-
-static inline int opp_add(struct device *dev, unsigned long freq,
-                                       unsigned long u_volt)
-{
-       return -EINVAL;
-}
-
-static inline int opp_enable(struct device *dev, unsigned long freq)
-{
-       return 0;
-}
-
-static inline int opp_disable(struct device *dev, unsigned long freq)
-{
-       return 0;
-}
-
-static inline struct srcu_notifier_head *opp_get_notifier(struct device *dev)
-{
-       return ERR_PTR(-EINVAL);
-}
-#endif         /* CONFIG_PM_OPP */
-
-#if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
-int of_init_opp_table(struct device *dev);
-#else
-static inline int of_init_opp_table(struct device *dev)
-{
-       return -EINVAL;
-}
-#endif
-
-#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
-int opp_init_cpufreq_table(struct device *dev,
-                           struct cpufreq_frequency_table **table);
-void opp_free_cpufreq_table(struct device *dev,
-                               struct cpufreq_frequency_table **table);
-#else
-static inline int opp_init_cpufreq_table(struct device *dev,
-                           struct cpufreq_frequency_table **table)
-{
-       return -EINVAL;
-}
-
-static inline
-void opp_free_cpufreq_table(struct device *dev,
-                               struct cpufreq_frequency_table **table)
-{
-}
-#endif         /* CONFIG_CPU_FREQ */
-
-#endif         /* __LINUX_OPP_H__ */
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h
new file mode 100644 (file)
index 0000000..5151b00
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Generic OPP Interface
+ *
+ * Copyright (C) 2009-2010 Texas Instruments Incorporated.
+ *     Nishanth Menon
+ *     Romit Dasgupta
+ *     Kevin Hilman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_OPP_H__
+#define __LINUX_OPP_H__
+
+#include <linux/err.h>
+#include <linux/cpufreq.h>
+#include <linux/notifier.h>
+
+struct dev_pm_opp;
+struct device;
+
+enum dev_pm_opp_event {
+       OPP_EVENT_ADD, OPP_EVENT_ENABLE, OPP_EVENT_DISABLE,
+};
+
+#if defined(CONFIG_PM_OPP)
+
+unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp);
+
+unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp);
+
+int dev_pm_opp_get_opp_count(struct device *dev);
+
+struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
+                                             unsigned long freq,
+                                             bool available);
+
+struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
+                                             unsigned long *freq);
+
+struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
+                                            unsigned long *freq);
+
+int dev_pm_opp_add(struct device *dev, unsigned long freq,
+                  unsigned long u_volt);
+
+int dev_pm_opp_enable(struct device *dev, unsigned long freq);
+
+int dev_pm_opp_disable(struct device *dev, unsigned long freq);
+
+struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev);
+#else
+static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
+{
+       return 0;
+}
+
+static inline unsigned long dev_pm_opp_get_freq(struct dev_pm_opp *opp)
+{
+       return 0;
+}
+
+static inline int dev_pm_opp_get_opp_count(struct device *dev)
+{
+       return 0;
+}
+
+static inline struct dev_pm_opp *dev_pm_opp_find_freq_exact(struct device *dev,
+                                       unsigned long freq, bool available)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
+                                       unsigned long *freq)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline struct dev_pm_opp *dev_pm_opp_find_freq_ceil(struct device *dev,
+                                       unsigned long *freq)
+{
+       return ERR_PTR(-EINVAL);
+}
+
+static inline int dev_pm_opp_add(struct device *dev, unsigned long freq,
+                                       unsigned long u_volt)
+{
+       return -EINVAL;
+}
+
+static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq)
+{
+       return 0;
+}
+
+static inline int dev_pm_opp_disable(struct device *dev, unsigned long freq)
+{
+       return 0;
+}
+
+static inline struct srcu_notifier_head *dev_pm_opp_get_notifier(
+                                                       struct device *dev)
+{
+       return ERR_PTR(-EINVAL);
+}
+#endif         /* CONFIG_PM_OPP */
+
+#if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
+int of_init_opp_table(struct device *dev);
+#else
+static inline int of_init_opp_table(struct device *dev)
+{
+       return -EINVAL;
+}
+#endif
+
+#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_PM_OPP)
+int dev_pm_opp_init_cpufreq_table(struct device *dev,
+                           struct cpufreq_frequency_table **table);
+void dev_pm_opp_free_cpufreq_table(struct device *dev,
+                               struct cpufreq_frequency_table **table);
+#else
+static inline int dev_pm_opp_init_cpufreq_table(struct device *dev,
+                           struct cpufreq_frequency_table **table)
+{
+       return -EINVAL;
+}
+
+static inline
+void dev_pm_opp_free_cpufreq_table(struct device *dev,
+                               struct cpufreq_frequency_table **table)
+{
+}
+#endif         /* CONFIG_CPU_FREQ */
+
+#endif         /* __LINUX_OPP_H__ */
diff --git a/include/linux/powercap.h b/include/linux/powercap.h
new file mode 100644 (file)
index 0000000..4e25041
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+ * powercap.h: Data types and headers for sysfs power capping interface
+ * Copyright (c) 2013, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.
+ *
+ */
+
+#ifndef __POWERCAP_H__
+#define __POWERCAP_H__
+
+#include <linux/device.h>
+#include <linux/idr.h>
+
+/*
+ * A power cap class device can contain multiple powercap control_types.
+ * Each control_type can have multiple power zones, which can be independently
+ * controlled. Each power zone can have one or more constraints.
+ */
+
+struct powercap_control_type;
+struct powercap_zone;
+struct powercap_zone_constraint;
+
+/**
+ * struct powercap_control_type_ops - Define control type callbacks
+ * @set_enable:                Enable/Disable whole control type.
+ *                     Default is enabled. But this callback allows all zones
+ *                     to be in disable state and remove any applied power
+ *                     limits. If disabled power zone can only be monitored
+ *                     not controlled.
+ * @get_enable:                get Enable/Disable status.
+ * @release:           Callback to inform that last reference to this
+ *                     control type is closed. So it is safe to free data
+ *                     structure associated with this control type.
+ *                     This callback is mandatory if the client own memory
+ *                     for the control type.
+ *
+ * This structure defines control type callbacks to be implemented by client
+ * drivers
+ */
+struct powercap_control_type_ops {
+       int (*set_enable) (struct powercap_control_type *, bool mode);
+       int (*get_enable) (struct powercap_control_type *, bool *mode);
+       int (*release) (struct powercap_control_type *);
+};
+
+/**
+ * struct powercap_control_type- Defines a powercap control_type
+ * @name:              name of control_type
+ * @dev:               device for this control_type
+ * @idr:               idr to have unique id for its child
+ * @root_node:         Root holding power zones for this control_type
+ * @ops:               Pointer to callback struct
+ * @node_lock:         mutex for control type
+ * @allocated:         This is possible that client owns the memory
+ *                     used by this structure. In this case
+ *                     this flag is set to false by framework to
+ *                     prevent deallocation during release process.
+ *                     Otherwise this flag is set to true.
+ * @ctrl_inst:         link to the control_type list
+ *
+ * Defines powercap control_type. This acts as a container for power
+ * zones, which use same method to control power. E.g. RAPL, RAPL-PCI etc.
+ * All fields are private and should not be used by client drivers.
+ */
+struct powercap_control_type {
+       struct device dev;
+       struct idr idr;
+       int nr_zones;
+       const struct powercap_control_type_ops *ops;
+       struct mutex lock;
+       bool allocated;
+       struct list_head node;
+};
+
+/**
+ * struct powercap_zone_ops - Define power zone callbacks
+ * @get_max_energy_range_uj:   Get maximum range of energy counter in
+ *                             micro-joules.
+ * @get_energy_uj:             Get current energy counter in micro-joules.
+ * @reset_energy_uj:           Reset micro-joules energy counter.
+ * @get_max_power_range_uw:    Get maximum range of power counter in
+ *                             micro-watts.
+ * @get_power_uw:              Get current power counter in micro-watts.
+ * @set_enable:                        Enable/Disable power zone controls.
+ *                             Default is enabled.
+ * @get_enable:                        get Enable/Disable status.
+ * @release:                   Callback to inform that last reference to this
+ *                             control type is closed. So it is safe to free
+ *                             data structure associated with this
+ *                             control type. Mandatory, if client driver owns
+ *                             the power_zone memory.
+ *
+ * This structure defines zone callbacks to be implemented by client drivers.
+ * Client drives can define both energy and power related callbacks. But at
+ * the least one type (either power or energy) is mandatory. Client drivers
+ * should handle mutual exclusion, if required in callbacks.
+ */
+struct powercap_zone_ops {
+       int (*get_max_energy_range_uj) (struct powercap_zone *, u64 *);
+       int (*get_energy_uj) (struct powercap_zone *, u64 *);
+       int (*reset_energy_uj) (struct powercap_zone *);
+       int (*get_max_power_range_uw) (struct powercap_zone *, u64 *);
+       int (*get_power_uw) (struct powercap_zone *, u64 *);
+       int (*set_enable) (struct powercap_zone *, bool mode);
+       int (*get_enable) (struct powercap_zone *, bool *mode);
+       int (*release) (struct powercap_zone *);
+};
+
+#define        POWERCAP_ZONE_MAX_ATTRS         6
+#define        POWERCAP_CONSTRAINTS_ATTRS      8
+#define MAX_CONSTRAINTS_PER_ZONE       10
+/**
+ * struct powercap_zone- Defines instance of a power cap zone
+ * @id:                        Unique id
+ * @name:              Power zone name.
+ * @control_type_inst: Control type instance for this zone.
+ * @ops:               Pointer to the zone operation structure.
+ * @dev:               Instance of a device.
+ * @const_id_cnt:      Number of constraint defined.
+ * @idr:               Instance to an idr entry for children zones.
+ * @parent_idr:                To remove reference from the parent idr.
+ * @private_data:      Private data pointer if any for this zone.
+ * @zone_dev_attrs:    Attributes associated with this device.
+ * @zone_attr_count:   Attribute count.
+ * @dev_zone_attr_group: Attribute group for attributes.
+ * @dev_attr_groups:   Attribute group store to register with device.
+ * @allocated:         This is possible that client owns the memory
+ *                     used by this structure. In this case
+ *                     this flag is set to false by framework to
+ *                     prevent deallocation during release process.
+ *                     Otherwise this flag is set to true.
+ * @constraint_ptr:    List of constraints for this zone.
+ *
+ * This defines a power zone instance. The fields of this structure are
+ * private, and should not be used by client drivers.
+ */
+struct powercap_zone {
+       int id;
+       char *name;
+       void *control_type_inst;
+       const struct powercap_zone_ops *ops;
+       struct device dev;
+       int const_id_cnt;
+       struct idr idr;
+       struct idr *parent_idr;
+       void *private_data;
+       struct attribute **zone_dev_attrs;
+       int zone_attr_count;
+       struct attribute_group dev_zone_attr_group;
+       const struct attribute_group *dev_attr_groups[2]; /* 1 group + NULL */
+       bool allocated;
+       struct powercap_zone_constraint *constraints;
+};
+
+/**
+ * struct powercap_zone_constraint_ops - Define constraint callbacks
+ * @set_power_limit_uw:                Set power limit in micro-watts.
+ * @get_power_limit_uw:                Get power limit in micro-watts.
+ * @set_time_window_us:                Set time window in micro-seconds.
+ * @get_time_window_us:                Get time window in micro-seconds.
+ * @get_max_power_uw:          Get max power allowed in micro-watts.
+ * @get_min_power_uw:          Get min power allowed in micro-watts.
+ * @get_max_time_window_us:    Get max time window allowed in micro-seconds.
+ * @get_min_time_window_us:    Get min time window allowed in micro-seconds.
+ * @get_name:                  Get the name of constraint
+ *
+ * This structure is used to define the constraint callbacks for the client
+ * drivers. The following callbacks are mandatory and can't be NULL:
+ *  set_power_limit_uw
+ *  get_power_limit_uw
+ *  set_time_window_us
+ *  get_time_window_us
+ *  get_name
+ *  Client drivers should handle mutual exclusion, if required in callbacks.
+ */
+struct powercap_zone_constraint_ops {
+       int (*set_power_limit_uw) (struct powercap_zone *, int, u64);
+       int (*get_power_limit_uw) (struct powercap_zone *, int, u64 *);
+       int (*set_time_window_us) (struct powercap_zone *, int, u64);
+       int (*get_time_window_us) (struct powercap_zone *, int, u64 *);
+       int (*get_max_power_uw) (struct powercap_zone *, int, u64 *);
+       int (*get_min_power_uw) (struct powercap_zone *, int, u64 *);
+       int (*get_max_time_window_us) (struct powercap_zone *, int, u64 *);
+       int (*get_min_time_window_us) (struct powercap_zone *, int, u64 *);
+       const char *(*get_name) (struct powercap_zone *, int);
+};
+
+/**
+ * struct powercap_zone_constraint- Defines instance of a constraint
+ * @id:                        Instance Id of this constraint.
+ * @power_zone:                Pointer to the power zone for this constraint.
+ * @ops:               Pointer to the constraint callbacks.
+ *
+ * This defines a constraint instance.
+ */
+struct powercap_zone_constraint {
+       int id;
+       struct powercap_zone *power_zone;
+       struct powercap_zone_constraint_ops *ops;
+};
+
+
+/* For clients to get their device pointer, may be used for dev_dbgs */
+#define POWERCAP_GET_DEV(power_zone)   (&power_zone->dev)
+
+/**
+* powercap_set_zone_data() - Set private data for a zone
+* @power_zone: A pointer to the valid zone instance.
+* @pdata:      A pointer to the user private data.
+*
+* Allows client drivers to associate some private data to zone instance.
+*/
+static inline void powercap_set_zone_data(struct powercap_zone *power_zone,
+                                               void *pdata)
+{
+       if (power_zone)
+               power_zone->private_data = pdata;
+}
+
+/**
+* powercap_get_zone_data() - Get private data for a zone
+* @power_zone: A pointer to the valid zone instance.
+*
+* Allows client drivers to get private data associate with a zone,
+* using call to powercap_set_zone_data.
+*/
+static inline void *powercap_get_zone_data(struct powercap_zone *power_zone)
+{
+       if (power_zone)
+               return power_zone->private_data;
+       return NULL;
+}
+
+/**
+* powercap_register_control_type() - Register a control_type with framework
+* @control_type:       Pointer to client allocated memory for the control type
+*                      structure storage. If this is NULL, powercap framework
+*                      will allocate memory and own it.
+*                      Advantage of this parameter is that client can embed
+*                      this data in its data structures and allocate in a
+*                      single call, preventing multiple allocations.
+* @control_type_name:  The Name of this control_type, which will be shown
+*                      in the sysfs Interface.
+* @ops:                        Callbacks for control type. This parameter is optional.
+*
+* Used to create a control_type with the power capping class. Here control_type
+* can represent a type of technology, which can control a range of power zones.
+* For example a control_type can be RAPL (Running Average Power Limit)
+* IntelĀ® 64 and IA-32 Processor Architectures. The name can be any string
+* which must be unique, otherwise this function returns NULL.
+* A pointer to the control_type instance is returned on success.
+*/
+struct powercap_control_type *powercap_register_control_type(
+                               struct powercap_control_type *control_type,
+                               const char *name,
+                               const struct powercap_control_type_ops *ops);
+
+/**
+* powercap_unregister_control_type() - Unregister a control_type from framework
+* @instance:   A pointer to the valid control_type instance.
+*
+* Used to unregister a control_type with the power capping class.
+* All power zones registered under this control type have to be unregistered
+* before calling this function, or it will fail with an error code.
+*/
+int powercap_unregister_control_type(struct powercap_control_type *instance);
+
+/* Zone register/unregister API */
+
+/**
+* powercap_register_zone() - Register a power zone
+* @power_zone: Pointer to client allocated memory for the power zone structure
+*              storage. If this is NULL, powercap framework will allocate
+*              memory and own it. Advantage of this parameter is that client
+*              can embed this data in its data structures and allocate in a
+*              single call, preventing multiple allocations.
+* @control_type: A control_type instance under which this zone operates.
+* @name:       A name for this zone.
+* @parent:     A pointer to the parent power zone instance if any or NULL
+* @ops:                Pointer to zone operation callback structure.
+* @no_constraints: Number of constraints for this zone
+* @const_ops:  Pointer to constraint callback structure
+*
+* Register a power zone under a given control type. A power zone must register
+* a pointer to a structure representing zone callbacks.
+* A power zone can be located under a parent power zone, in which case @parent
+* should point to it.  Otherwise, if @parent is NULL, the new power zone will
+* be located directly under the given control type
+* For each power zone there may be a number of constraints that appear in the
+* sysfs under that zone as attributes with unique numeric IDs.
+* Returns pointer to the power_zone on success.
+*/
+struct powercap_zone *powercap_register_zone(
+                       struct powercap_zone *power_zone,
+                       struct powercap_control_type *control_type,
+                       const char *name,
+                       struct powercap_zone *parent,
+                       const struct powercap_zone_ops *ops,
+                       int nr_constraints,
+                       struct powercap_zone_constraint_ops *const_ops);
+
+/**
+* powercap_unregister_zone() - Unregister a zone device
+* @control_type:       A pointer to the valid instance of a control_type.
+* @power_zone: A pointer to the valid zone instance for a control_type
+*
+* Used to unregister a zone device for a control_type.  Caller should
+* make sure that children for this zone are unregistered first.
+*/
+int powercap_unregister_zone(struct powercap_control_type *control_type,
+                               struct powercap_zone *power_zone);
+
+#endif
index d444c4e834f4526ec318f71b1076a02c909e34a8..2fac9cc79b3da6183dd56f5e3469a7de54d4167e 100644 (file)
@@ -178,6 +178,22 @@ config PM_SLEEP_DEBUG
        def_bool y
        depends on PM_DEBUG && PM_SLEEP
 
+config DPM_WATCHDOG
+       bool "Device suspend/resume watchdog"
+       depends on PM_DEBUG && PSTORE
+       ---help---
+         Sets up a watchdog timer to capture drivers that are
+         locked up attempting to suspend/resume a device.
+         A detected lockup causes system panic with message
+         captured in pstore device for inspection in subsequent
+         boot session.
+
+config DPM_WATCHDOG_TIMEOUT
+       int "Watchdog timeout in seconds"
+       range 1 120
+       default 12
+       depends on DPM_WATCHDOG
+
 config PM_TRACE
        bool
        help
index a394297f8b2f94ea806a545c6e92e4b7221d2f7e..8dff9b48075af3f61eeab3531b3ad706b88718e4 100644 (file)
@@ -558,30 +558,12 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
        if (count == sizeof(s32)) {
                if (copy_from_user(&value, buf, sizeof(s32)))
                        return -EFAULT;
-       } else if (count <= 11) { /* ASCII perhaps? */
-               char ascii_value[11];
-               unsigned long int ulval;
+       } else {
                int ret;
 
-               if (copy_from_user(ascii_value, buf, count))
-                       return -EFAULT;
-
-               if (count > 10) {
-                       if (ascii_value[10] == '\n')
-                               ascii_value[10] = '\0';
-                       else
-                               return -EINVAL;
-               } else {
-                       ascii_value[count] = '\0';
-               }
-               ret = kstrtoul(ascii_value, 16, &ulval);
-               if (ret) {
-                       pr_debug("%s, 0x%lx, 0x%x\n", ascii_value, ulval, ret);
-                       return -EINVAL;
-               }
-               value = (s32)lower_32_bits(ulval);
-       } else {
-               return -EINVAL;
+               ret = kstrtos32_from_user(buf, count, 16, &value);
+               if (ret)
+                       return ret;
        }
 
        req = filp->private_data;
index 957f06164ad1004b0050dbdcb7563c91c3755e55..24850270c8024948d60c0f827457b18d2de2d9a7 100644 (file)
@@ -36,9 +36,9 @@ static struct snapshot_data {
        struct snapshot_handle handle;
        int swap;
        int mode;
-       char frozen;
-       char ready;
-       char platform_support;
+       bool frozen;
+       bool ready;
+       bool platform_support;
        bool free_bitmaps;
 } snapshot_state;
 
@@ -93,9 +93,9 @@ static int snapshot_open(struct inode *inode, struct file *filp)
        if (error)
                atomic_inc(&snapshot_device_available);
 
-       data->frozen = 0;
-       data->ready = 0;
-       data->platform_support = 0;
+       data->frozen = false;
+       data->ready = false;
+       data->platform_support = false;
 
  Unlock:
        unlock_system_sleep();
@@ -229,7 +229,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                if (error)
                        thaw_processes();
                else
-                       data->frozen = 1;
+                       data->frozen = true;
 
                break;
 
@@ -240,7 +240,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                free_basic_memory_bitmaps();
                data->free_bitmaps = false;
                thaw_processes();
-               data->frozen = 0;
+               data->frozen = false;
                break;
 
        case SNAPSHOT_CREATE_IMAGE:
@@ -270,7 +270,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
        case SNAPSHOT_FREE:
                swsusp_free();
                memset(&data->handle, 0, sizeof(struct snapshot_handle));
-               data->ready = 0;
+               data->ready = false;
                /*
                 * It is necessary to thaw kernel threads here, because
                 * SNAPSHOT_CREATE_IMAGE may be invoked directly after
@@ -334,7 +334,7 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,
                 * PM_HIBERNATION_PREPARE
                 */
                error = suspend_devices_and_enter(PM_SUSPEND_MEM);
-               data->ready = 0;
+               data->ready = false;
                break;
 
        case SNAPSHOT_PLATFORM_SUPPORT: